Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercices pour débutants en C (suite)

Venez vous entrainer!

    1 avril 2010 à 20:51:27

    Bonjour a tous,

    Je me permets de creer un nouveau topic concernant les exercices pour s'entrainer en C suite a quelques "desagrements" (notamment concernant la mise a jour des liens des exercices et de leur correction) voici le lien de l'ancien topic : http://www.siteduzero.com/forum-83-329 [...] nts-en-c.html.

    Voici donc un rappel de l'utilite de ce topic :

    Citation : shareman


    Vous apprenez le langage C ? Parfait, c'est ici qu'on s'entraîne ! Sur ce topic, vous aurez la possibilité de vous entraîner à la programmation en langage C grâce aux exercices que je vais vous proposer. Tout le monde vous le dira, l'entraînement, c'est la clef de la réussite, surtout en programmation. Pour bien progresser, il faut donc s'exercer. Vous avez à présent à disposition des exercices adaptés à votre niveau, chose que l'on trouve assez rarement sur le net. ;)

    Si vous n'êtes plus débutants et désirez des exercices un peu plus poussés et en langage C++, il existe un topic géré par Nanoc qui sera l'idéal pour vous. Il fonctionne un peu sous le même principe. Ici, c'est pour les vrais débutants.

    But du topic et petits détails



    principe et but


    Voilà comment nous allons fonctionner : Chaque mois, à partir de celui-ci, je vais vous proposer un ou plusieurs exercice(s) sur un thème particulier dans le but d'approfondir vos connaissances (résultat garanti) ! Je pourrais par exemple vous donner comme thème "les listes chaînées" ce qui vous permettra d'approfondir votre expérience et vos connaissances à ce sujet. C'est le principe des exercices en réalité. Ces exercices seront spécialement destinés aux débutants qui souhaitent s'améliorer. Débutants, je vous conseil vivement d'y participer ! Les exercices seront toujours adaptés à votre niveau et pour y répondre, aucune installation d'une bibliothèque non-standard ne sera nécessaire. Que vous suiviez le cours de m@teo21 sur le langage C ou que vous souhaitiez juste vous entraîner pour le plaisir, ces exercices sont pour vous ! :)

    L'envoi des réponses


    Vous avez la possibilité, mais ce n'est pas une obligation (quoique je vous le conseille), de soumettre vos codes (avec explications si nécessaire) à réponse. Je pourrais ainsi vous donner de bons conseils qui vous permettrons de progresser d'avantage. Le titre du MP devra porter le nom de l'exercice par exemple "zReader - ma solution". Par contre, pour m'envoyer une réponse, il faut au minimum que le code compile et qu'il ne bug pas en cours de route. :p Si vraiment vous bloquez sur une erreur, le forum sera toujours là pour vous aider !


    Citation : Eusebus

    Dernier point : l'envoi des réponses à "réponse" n'est désormais plus d'actualité - système de gestion un peu trop lourd, pas de possibilités d'avoir des commentaires d'autres codeurs... Vous êtes donc tous invités à poster votre code directement sur le topic, avec des balises secret. Toutefois "réponse" reste en fonction pour ceux qui auraient peur de poster en public. Je les y invite cependant car c'est toujours plus constructif d'avoir divers avis. J'en profite pour demander aux participants de faire un effort sur la lisibilité et la clarté de leur code, afin que nous n'ayions pas à décrypter ce que vous avez posté. C'est un effort salutaire autant pour les lecteurs que pour les posteurs.



    La correction


    Les exercices seront corrigés. Lors de cette correction, que je vais poster ici avant la sortie de l'énoncé d'un prochain exercice, je vous donnerais une manière de procéder, vous aurez peut-être d'autres méthodes qui seront toutes aussi bonnes. Par ailleurs, il est possible que je retienne l'un des codes qu'un zér0 aura envoyé à réponse et que je vous le présente.

    Venez vous entraîner pour progresser !

    Exercices proposés



    Ici, vous pouvez accéder rapidement à tous les exercices qui ont déjà été proposés ainsi qu'à leur correction.



    Date Titre Auteur Thème Correction Auteur du code proposé
    octobre 2008 zReader shareman Manipulation des fichiers (ouverture, écriture) shareman
    octobre 2008 zBinary shareman Base binaire, algorithmique shareman
    novembre 2008 zTri shareman Tri, comparatif, secondes système shareman / yoch
    novembre 2008 zStrcapitalize Invading Chaine de caractères shareman
    novembre 2008 zAddition shareman Matrice, pure algorithmique Eusebus
    décembre 2008 zMath shareman Algorithmique, pile shareman
    janvier 2009 zGame shareman Révisions du cours sur le C shareman
    mars 2009 zStrstat Eusebus Chaînes de caractères Eusebus/bluestorm
    mai 2009 zStrSearch Eusebus Chaînes de caractères Eusebus
    juin 2009 zBrace shareman Algorithmique, expressions parenthésées shareman
    juillet - août 2009 zGrep Arthurus argc/argv, chaînes, fichier, algo
    /
    /
    Janvier 2010 z0zéro GurneyH algo, écrire un nombre en toute lettre GurneyH
    Janvier 2010 zSommeChiffre GurneyH Calculer la somme des chiffres d'un nombre donné GurneyH
    février 2010 zArray1D GurneyH Pratique des tableaux à une dimension. GurneyH
    février 2010 zBigInt GurneyH Opérations surs les grands entiers. GurneyH
    Mars 2010 zLCD GurneyH Simulation d'un afficheur 7 segments. GurneyH
    Mars 2010 zCoupure Lithrein Jouer au banquier. Lithrein
    Avril 2010 zWordCount Lithrein Manipulation de fichiers Lithrein
    Avril 2010 zJustificator Lithrein / Candide Justification de texte Lithrein
    Mai 2010 zTransforme Lithrein Manipulations basiques de tableaux Lithrein
    Juin 2010 zPointers Lithrein Manipulations de pointeurs Lithrein
    Juin 2010 zIdentificator candide Algorithmique
    /
    /
    Juin 2010 zChance Lithrein Manipulation du temps et/ou pratique algorithmique Lithrein
    Juillet 2010 zConvert Pouet_forever Conversion chiffre -> chaine de caracteres Pouet_forever
    Septembre 2010 zCalc Lithrein Creer une calculatrice Lithrein
    Octobre 2010 zCrypt Tosh Initiation au cryptage Tosh
    Décembre 2010 zMorp Pouet_forever Boucles, manipulation de tableaux et pointeurs Pouet_forever
    Décembre 2010 zMorp 2 Pouet_forever Approfondissement Pouet_forever
    Décembre 2010 zMorp SDL GurneyH Extension de l'exercice de Pouet_forever a une version graphique
    /
    /
    Février 2011 getline (3) Lithrein Recoder une fonction standard de saisie Lithrein
    Mars 2011 zConjug paraze manipuler les chaines de caracteres paraze

    Et bien sur bonne chance a tous!
    J'editerais au fur et a mesure des exercices proposes.
    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      1 avril 2010 à 21:02:18

      Intéressant.
      • Partager sur Facebook
      • Partager sur Twitter
        1 avril 2010 à 21:09:43

        Moui :) , je pense faire un sujet annexe de proposition d'exercices. Ou bien preferez vous en discuter sur ce meme topic?

        Pour que tout le monde puisse proposer des exercices (bien sur, quand je dis tout le monde, je veux dire : tous ceux qui ont un exercice potable) pour qu'on puisse les aiguiller leur dire que tel ou tel exercice n'est pas adapte, ou qu'il devrait le remanier de telle ou telle facon, ou encore dire que son exo est tres bien et qu'il peut le poster.
        • Partager sur Facebook
        • Partager sur Twitter
          1 avril 2010 à 21:20:45

          Je trouve que c'est une bonne idée de repartir sur un topic tout neuf (Au moins le premier message ne sera plus geler).
          Autrement pour les propositions d'exercices je pense que l'on pourrait les faire directement ici puisque chaque exercice à un sujet dédié sur le forum.
          En clair, je vois bien ce sujet regrouper les propositions d'exercices, les exercices retenus ainsi que leurs corrections.
          • Partager sur Facebook
          • Partager sur Twitter
            1 avril 2010 à 21:25:06

            +1 pour moi. Si les autres ont pas d'objections, on va faire comme ca..

            Je rappelle le lien du topic de l'exo en cours : zWordCount.

            Si vous avez des suggestions, remarques (vis a vis de ce topic et de son contenu...) n'hesitez pas.
            • Partager sur Facebook
            • Partager sur Twitter
              2 avril 2010 à 20:19:46

              zWordCount (Du 1er au 15 Avril)


              Connaissances requises :

              I) Mise au point d'un programme basique pour compter les mots


              Premièrement, définissons clairement ce qu'est un mot : Un mot est défini comme étant la plus longue séquence contiguë (sans espaces) de caractères alphanumériques pouvant contenir des caractères de ponctuation. Les caractères considérés comme séparateur de mots sont : l'espace ( ' ' ) la tablulation horizontale ( '\t' ), le retour à la ligne ( '\n' ) et le retour chariot ( '\r' )

              1) Créez un programme qui récupère sur l'entrée standard (stdin) un flot de caractères tant que la constante EOF (End Of File) n'a pas été envoyée (Pour envoyer EOF : Au commencement d'une ligne Ctrl+Z pour Windows et Ctrl+D pour les unixoïdes). Votre programme affichera le nombre de lignes, de mots, puis de caractères (espaces compris) du texte récupéré.

              $ wc 
              Salut les Zer0s.
                   1 ligne(s), 3 mot(s), 17 caractere(s)


              2) Pour cette question, vous devrez créer un programme similaire qui, cette fois ci, récupère le texte à partir d'un fichier passé en argument ($ wc fichier.txt). Si ce fichier n'existe pas le programme affiche une erreur puis se termine normalement. Si aucun fichier n'est passé en argument vous récupérerez le texte sur l'entrée standard comme pour la première question.

              Citation : Entree.txt

              Salut les Zer0s.

              $ wc Entree.txt
                   1 ligne(s) 3 mot(s) 17 caractere(s)

              $ wc fichier_inconnu.txt 
              Erreur : Aucun fichier trouvé


              II) Amélioration du programme précédent grâce à un système d'options



              L'usage de la fonction getopt est interdite, vous pouvez néanmoins l'utilisez si vous choisissez de gérer les options longues (--line par exemple)


              1) Vous devez créer un programme qui affiche les options passées au programme. Les options que pourra recevoir le programme seront : `-a`, `-b`, `-c`, `-d`, il est possible de les raccourcir en `-abcd` Exemples :

              $ options 
              a : inactive. 
              b : inactive. 
              c : inactive. 
              d : inactive.

              $ options -a -c 
              a : active. 
              b : inactive. 
              c : active. 
              d : inactive.

              $ options -bcd 
              a : inactive. 
              b : active. 
              c : active. 
              d : active.


              2) Grâce à l'activité préparatoire de la question 1. Vous pouvez maintenant créer un système d'options pour le programme word count (wc) réalisé lors de la deuxième question de la première partie. Les options possible seront `-c` (afficher le nombre de caractères), `-l` (afficher le nombre de lignes), `-w` (afficher le nombre de mots). Par défaut les trois options sont actives. (wc = wc -l -c -w = wc -lcw). Une dernière option est possible : `-h` (elle permet d'afficher la manière d'utiliser le programme). Indiquer un fichier et facultatif (se référer à la question 2 de la première partie pour plus de détails). Votre programme doit d'abord afficher le nombre de lignes, puis de mots et ensuite de caractères.

              $ wc -lwc fichier_inconnu.txt 
              Erreur : Aucun fichier trouve. 
              
              $ wc -h 
              Usage : wc [-l] [-w] [-c] [FICHIER] 
              
              $ wc -l 
              Salut les Zer0s.
                   1 ligne(s) 
              
              $ wc -lm 
              Salut les Zer0s.
                   1 ligne(s) 3 mot(s) 
              
              $ wc -l -c 
              Salut les Zer0s.
                   1 ligne(s) 17 caractere(s)


              Le but n'est pas de soumettre le plus rapidement une solution ce n'est pas un concours, prenez donc le temps de peaufiner votre solution. Et n'hésitez pas à poser des questions si vous êtes bloqués ou si vous avez besoin de conseils.
              Un topic a été créé pour cet exercice.

              Bonne chance.
              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                2 avril 2010 à 21:57:18

                Je vais y participer ce week-end (pas bac blanc mais presque ^^)
                • Partager sur Facebook
                • Partager sur Twitter
                  3 avril 2010 à 1:57:35

                  Une erreur dans l'énoncé (à moins que ce ne soit volontaire) : d'après l'énoncé, on doit gérer -w, -l et -c. Ok.
                  Or elles sont actives par défaut. Ok toujours.
                  Maintenant comment on les désactive ? Le sujet ne précise pas ce point. Tel quel, ça signifie qu'il suffit de TOUJOURS afficher les trois données, puisqu'elles seront toujours actives.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 avril 2010 à 9:06:10

                    Citation : Arcanis

                    Une erreur dans l'énoncé (à moins que ce ne soit volontaire) : d'après l'énoncé, on doit gérer -w, -l et -c. Ok.
                    Or elles sont actives par défaut. Ok toujours.
                    Maintenant comment on les désactive ? Le sujet ne précise pas ce point. Tel quel, ça signifie qu'il suffit de TOUJOURS afficher les trois données, puisqu'elles seront toujours actives.



                    Par défaut les 3 options sont activées...
                    Pas d'arguments = -wlc.
                    Par contre dès que tu passes une option -l par exemple, les options par défauts sont désactivées, et ici seul le nombre de lignes sera affiché.
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Zeste de Savoir, le site qui en a dans le citron !
                    Anonyme
                      12 avril 2010 à 7:33:28

                      Salut, moi j'ai une question concernant le zWc.. En fait, j'ai du mal à comprendre ceci :

                      Citation : Lithrein

                      Si aucun fichier n'est passé en argument vous récupérerez le texte sur l'entrée standard comme pour la première question.


                      Si quelqu'un pourrait m'expliquer, j'en serais ravis!
                      À+
                      • Partager sur Facebook
                      • Partager sur Twitter
                        12 avril 2010 à 12:20:54

                        Citation : 1vrai0

                        Salut, moi j'ai une question concernant le zWc.. En fait, j'ai du mal à comprendre ceci :

                        Citation : Lithrein

                        Si aucun fichier n'est passé en argument vous récupérerez le texte sur l'entrée standard comme pour la première question.


                        Si quelqu'un pourrait m'expliquer, j'en serais ravis!
                        À+



                        Bah en gros, si on te spécifie pas de fichier, tu fais comme dans la première question:

                        $ zWc fichier
                        
                            X ligne(s) X mot(s) X caractere(s) 
                        
                        $ zWc
                        blabla
                            1 ligne(s) 1 mot(s) 6 caractere(s)
                        • Partager sur Facebook
                        • Partager sur Twitter
                          18 avril 2010 à 18:36:43

                          zWordCount : Correction



                          I) Mise au point d'un programme basique pour compter les mots



                          1) Ici, on doit seulement compter le nombre de lignes, mots et caractères reçu par le biais de l'endrée standard soit stdin.

                          Je rappelle que les caractères définis comme caractères d'espacement sont : ' ', '\t', '\n', '\r'.

                          Pour l'instant notre code se résume à :
                          #include <stdlib.h> /* Pour EXIT_SUCCESS */
                          
                          int
                          main (void) {
                          
                              return EXIT_SUCCESS;
                          }
                          


                          Ensuite, on a besoin d'appeler la fonction qui va compter les mots, lignes, caractères. Je propose qu'on l'appelle wc. Cette fonction aura besoin d'utiliser les fonctions d'entrées/sorties standards.

                          #include <stdio.h>  /* Pour les fonctions d'entrées/sorties */
                          #include <stdlib.h> /* Pour EXIT_SUCCESS */
                          
                          int
                          main (void) {
                              wc();
                          
                              return EXIT_SUCCESS;
                          }
                          


                          Occupons nous maintenant de la fonction `wc'.

                          On a besoin de compter les caractères tant qu'on a pas rencontré la constante de fin de fichier <acronym title="End Of File">EOF</acronym>.

                          void
                          wc (void) {
                              int c; /* Caractère actuel */
                              int nc; /* Compteur de caractères */
                          
                              int c = nc = 0; /* On met les compteurs à 0 */
                          
                              while ((c = getchar()) != EOF) { /* On lit 1 à 1 les caractères sur stdin */
                                  ++nc;
                              }
                          
                          }
                          


                          On a aussi besoin de compter les mots. Pour cela, on a besoin de savoir si on est dans un mot ou non de manière à savoir si on doit ajouter un mot au compteur ou non.
                          Pour savoir cela je vous propose de définir deux états pour la position du curseur : dans un mot `in' ou hors d'un mot `out'. On peut définir ces états à l'aide d'une énumération1.
                          Au début de la lecture on est hors d'un mot.

                          void
                          wc (void) {
                              int c;        /* Caractère actuel */
                              int state;    /* État de la position du curseur */
                              int nc;       /* Compteur de caractères */
                              int nw;       /* Compteur de mots */
                          
                              enum {out, in};
                          
                              c = nc = nw;    /* On met les compteurs à 0 */
                              state = out;    /* Au début on est hors d'un mot */
                          
                              /* On lit 1 à 1 les caractères sur stdin */
                              while ((c = getchar()) != EOF) {
                                  ++nc;
                           
                                  /* On sort d'un mot */
                                  if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                                      state = out;
                                  } else if (state == out) {
                                      ++nw;
                                      state = in;
                                  }
                              }
                          
                          }
                          


                          Il ne nous reste plus qu'à compter les lignes et afficher le résultat :
                          void
                          wc (void) {
                              int c;        /* Caractère actuel */
                              int state;    /* État de la position du curseur */
                              int nc;       /* Compteur de caractères */
                              int nw;       /* Compteur de mots */
                              int nl;       /* Compteur de lignes */
                          
                              enum {out, in};
                          
                              c = nc = nw = nl = 0;    /* On met les compteurs à 0 */
                              state = out;             /* Au début on est hors d'un mot */
                          
                              /* On lit 1 à 1 les caractères sur stdin */
                              while ((c = getchar()) != EOF) {
                                  ++nc;
                          
                                  /* On sort d'un mot */
                                  if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                                      state = out;
                                      
                                      /* On est revenu à la ligne */
                                      if (c == '\n') {
                                          ++nl;
                                      }
                                  } else if (state == out) { /* On rentre dans un mot */
                                      ++nw;
                                      state = in;
                                  }
                              }
                          
                              printf("\t%d ligne(s),\t%d mot(s)\t%d caractere(s)", nl, nw, nc);
                          
                          }
                          


                          Solution complète de la question 1 :
                          #include <stdio.h>
                          #include <stdlib.h>
                          
                          enum {out, in};
                          
                          void
                          wc (void) {
                              int c, nc, nw, nl, state;
                          
                              c = nc = nw = nl = 0; /* Initialisation des compteurs à  0 */
                              state = out; /* Au début on n'est pas dans un  mot */
                          
                              while ((c = getchar()) != EOF) { /* On lit les caractères 1 à  1 sur stdin */
                                  ++nc;
                          
                          	if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                                      state = out; /* On n'est pas dans un mot */
                          
                                      if (c == '\n') { /* On revient à  la ligne  */
                          	    	    ++nl;
                                      }
                                  } else if (state == out) { /* On rentre dans un mot */
                                      state = in;
                                      ++nw;
                                  }
                              }
                          
                              printf("\t%d ligne(s)\t%d mot(s)\t%d caractere(s)\n", nl, nw ,nc);
                          }
                          
                          int
                          main (void) {
                              wc();
                          
                              return EXIT_SUCCESS;
                          }
                          


                          2) Cette fois-ci, on doit pouvoir passer un fichier en argument.

                          Il y a très peu de choses à changer :

                          #include <stdio.h>
                          #include <stdlib.h>
                          
                          enum {in, out};
                          
                          void wc (FILE * stream) {
                              int c, nc, nw, nl, state;
                          
                              c = nc = nw = nl = 0;    /* Initialisation des compteurs à 0 */
                              state = out;             /* Au début on n'est pas dans un mot  */
                          
                              while ((c = fgetc(stream)) != EOF) {
                                  ++nc;
                          
                                  /* On sort d'un mot */
                                  if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                                      state = out;
                          
                                      /* On revient à la ligne */
                                      if (c == '\n') {
                                          ++nl;
                                      }
                                  } else if (state == out) { /* On rentre dans un mot  */ 
                                      state = in;
                                      ++nw;
                                  }
                              }
                              printf("\t%d ligne(s)\t%d mot(s)\t%d caractere(s)\n", nl, nw ,nc);
                          }
                          
                          FILE *
                          open_file (char * path, char * mode) {
                              FILE * stream;
                              
                              stream = fopen(path, mode);
                              if (stream == NULL) {
                                  perror(path);
                              }
                              return stream;
                          }
                          
                          int
                          main (int argc, char *argv[]) {
                              
                              if (argc < 1) {
                                  wc(stdin);
                              } else {
                                  FILE * stream = NULL;
                                  if ((stream = open_file(argv[1], "r")) == NULL) {
                                      return EXIT_FAILURE;
                                  }
                                  wc(stream);
                                  fclose(stream), stream = NULL;
                              }
                          
                              return EXIT_SUCCESS;
                          }
                          


                          Cette fois ci, la fonction `wc' prend en argument le fichier à lire (l. 6), de ce fait, on utilise `fgetc' à la place de `getchar'2.

                          La fonction `open_file' se contente d'ouvrir le fichier ou d'afficher une erreur.

                          La partie la plus intéressante est bien ce qui se passe dans la fonction `main'.
                          On commence par regarder s'il y a un fichier en argument. S'il n'y en a pas on dit à la fonction wc de lire l'entrée standard. Par contre s'il y a un fichier, on vérifie qu'il existe, puis on l'ouvre, ensuite on dit à la fonction `wc' de lire ce fichier. Une fois cela fait, il ne reste plus qu'à fermer le fichier.

                          II) Amélioration du programme précédent grâce à un système d'options



                          1) On doit faire un programme qui prend 4 options (a, b, c, d) et qui affiche si l'option est active ou non.

                          Solution complète de la question 1 :

                          Au début, on a un code dans le style suivant :
                          #include <stdio.h>
                          #include <stdlib.h>
                          
                          #define NB_OPTIONS 256 /* Nombre de caractères de la table ascii */
                          
                          int
                          main (int argc, char ** argv) {
                              char options[NB_OPTIONS] = {0};
                          
                              parseArg(argc, argv, options);
                              printArg(options, NB_OPTIONS);
                          
                              return EXIT_SUCCESS;
                          }
                          


                          Voyons d'abord comment récupérer les arguments de la ligne de commande.

                          Si, il y a moins de 2 arguments, il n'y a pas d'options. Il en découle :
                          void
                          parseArg (int ac, char ** av, char * options) {
                          
                              if (ac < 2)
                                  return;
                          }
                          


                          Tant qu'il y des arguments, on les parcourent à l'envers (ac--) mais l'option commence au second caractère (i=1) car le premier est le tiret.
                          Pour être sur que c'est une option courte, elle doit commencer par un tiret et un seul. Tant qu'il y des options, on les active.

                          void
                          parseArg (int ac, char ** av, char * options) {
                              size_t i;
                          
                              if (ac < 2)
                                  return;
                          
                              while(i = 1, ac-- > 1)
                                  if (av[ac][0] == '-' && av[ac][1] != '-') /* Un tiret et un seul */
                                      while (av[ac][i]) /* Tant qu'on est pas à la fin de l'argument */
                                          options[(size_t)(unsigned char)av[ac][i++]] = 1;
                          }
                          


                          Pourquoi un double cast ?
                          Pour éviter un overflow par Dieu ! `av' est tableau de char signé or les indices d'un tableau se doivent d'être positif donc non signé (size_t). De ce fait on converti en d'abord en char non signé (sans bit de signe) puis en size_t entier non signé).

                          Exemple de catastrophe :
                          taille du tableau : 256
                          (unsigned int)(-128) =>
                          -128 = 10000000 => 00000000 00000000 00000000 10000000 ==(complément à 1)=> 11111111 11111111 11111111 01111111 ==(complément à 2)=> 11111111 11111111 11111111 10000000 (soit 4294967168 en unsigned int)


                          Il ne reste plus qu'à s'occuper de l'affichage. Il suffit de parcourir le tableau et de voir si les options qui nous intéressent sont actives.

                          void
                          printArg (char * options, size_t len) {
                              size_t i = 0;
                          
                              while (i++ < len)
                              if ('a' <=  i && i <= 'd') {
                                  if (options[i]) {
                                      printf("%c : active.\n", i);
                                  } else {
                                      printf("%c : inactive.\n", i);
                                  }
                              }
                          }
                          


                          #include <stdio.h>
                          #include <stdlib.h>
                          
                          #define NB_OPTIONS 256
                          
                          void
                          parseArg (int ac, char ** av, char * options) {
                              size_t i;
                          
                              if (ac < 2)
                                  return;
                          
                              while (i = 1, ac-- > 1)
                                  if (av[ac][0] == '-' && av[ac][1] != '-')
                                      while (av[ac][i])
                                          options[(size_t)(unsigned char)av[ac][i++]] = 1;
                          }
                          
                          void
                          printArg (char * options, size_t len) {
                              size_t i = 0;
                          
                              while (i++ < len)
                              if ('a' <=  i && i <= 'd') {
                                  if (options[i]) {
                                      printf("%c : active.\n", i);
                                  } else {
                                      printf("%c : inactive.\n", i);
                                  }
                              }
                          }
                          
                          int
                          main (int argc, char ** argv) {
                              char options[NB_OPTIONS] = {0};
                          
                              parseArg(argc, argv, options);
                              printArg(options, NB_OPTIONS);
                          
                              return EXIT_SUCCESS;
                          }
                          


                          Version cryptique (c'est beau hein ? :-° ) :
                          #include <stdio.h>
                          
                          void parseArg(int,char**,char*);
                          void printArg(char*,size_t);
                          
                          void parseArg(int ac,char **av,char * opt){
                              size_t i;
                              if(ac<2)return;
                              while(i=1,ac-->1)
                                  if(av[ac][0]=='-'&&av[ac][1]!='-')
                                      while(opt[(size_t)(unsigned char)av[ac][i++]]=1,av[ac][i]);
                          }
                          
                          void printArg(char *opt,size_t n){
                              while(n--)if(opt[n])printf("Option %c active.\n",n);
                          }
                          
                          int main(int ac,char **av){
                              char opt[256]={0};
                              return 1?parseArg(ac,av,opt),printArg(opt,256),1:0;
                          }
                          



                          2) On doit refaire le même programme que pour la question 2 de la partie 1 si ce n'est que l'on a besoin de gérer 3 options (c, w, l).
                          La solution est assez facile à comprendre, tous les points difficiles ont été éclaircis juste avant.

                          Solution complète de la question 2 :
                          #include <stdio.h>
                          #include <stdlib.h>
                          
                          #define NB_OPTIONS 256
                          
                          typedef enum bool_e {false, true} bool_t;
                          enum {in, out};
                          
                          void
                          wc (FILE * stream, bool_t car, bool_t line, bool_t word) {
                              int c, nc, nw, nl, state;
                          
                              c = nc = nw = nl = 0;
                              state = out;
                          
                              while ((c = fgetc(stream)) != EOF) {
                                  ++nc;
                          
                                  if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                                      state = out;
                          
                                      if (c == '\n') {
                                          ++nl;
                                      }
                                  } else if (state == out) {
                                      state = in;
                                      ++nw;
                                  }
                              }
                              if (line)
                                  printf("\t%d ligne(s)", nl);
                              if (word)
                                  printf("\t%d mot(s)", nw);
                              if (car)
                                  printf("\t%d caractere(s)", nc);
                              putchar('\n');
                          }
                          
                          int
                          parseArg (int ac, char ** av, bool_t * options) {
                              size_t i;
                              int nb_opt;
                          
                              nb_opt = 0;
                          
                              if (ac < 2)
                                  return nb_opt; /* 0 */
                          
                              while (i = 1, ac-- > 1) {
                                  if (av[ac][0] == '-' && av[ac][1] != '-') {
                                      ++nb_opt;
                                      while (av[ac][i]) {
                                          if (av[ac][i] == 'c' || av[ac][i] == 'l' || av[ac][i] == 'w' || av[ac][i] == 'h') {
                                              options[(size_t)(unsigned char)av[ac][i++]] = 1;
                                          } else {
                                              return -1; /* Erreur */
                                          }
                                      }
                                  }
                              }
                              
                              return nb_opt;
                          }
                          
                          FILE *
                          open_file (char * path, const char * mode) {
                              FILE * stream;
                          
                              stream = fopen(path, mode);
                              if (stream == NULL) {
                                  perror(path);
                              }
                              return stream;
                          }
                          
                          int
                          main (int argc, char ** argv) {
                              bool_t options[NB_OPTIONS] = {0};
                              int nb_opt;
                          
                              if ((nb_opt = parseArg(argc, argv, options)) == 0) { /* On active les options */
                                  options[(size_t)(unsigned char)'c'] = options[(size_t)(unsigned char)'l'] = options[(size_t)(unsigned char)'w'] = 1;
                              }
                              if (nb_opt == -1 || options[(size_t)(unsigned char)'h']) {
                                  puts("usage : wc [-l | -w | -c | -h] [file]");
                                  return EXIT_SUCCESS;
                              }
                          
                              if (argc-1 > nb_opt) { /* Un fichier est passé en argument */
                                  FILE * stream;
                                  
                                  if ((stream = open_file(argv[argc-1], "r")) == NULL) {
                                      return EXIT_FAILURE;
                                  }
                                  
                                  wc(stream, options[(size_t)(unsigned char)'c'], options[(size_t)(unsigned char)'l'], options[(size_t)(unsigned char)'w']);
                                  fclose(stream), stream = NULL;
                              } else {
                                  wc(stdin, options[(size_t)(unsigned char)'c'], options[(size_t)(unsigned char)'l'], options[(size_t)(unsigned char)'w']);
                              }
                              
                              return EXIT_SUCCESS;
                          }
                          

                          ___________________________________________________

                          Notes :

                          1 : Il est aussi possible de les définir à l'aide de constantes de préprocesseur.
                          2 : Généralement `getchar' est une macro définie comme suit :
                          #define getchar() getc(stdin)
                          


                          Enjoy, et à bientôt pour le prochain exercice.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            18 avril 2010 à 20:04:09

                            Belle correction, j'aime bien :) . Sinon, je posterai pas mon exercice, pas accessible aux Zer0s . Donc je discute ave cdes Zer0s a propos d'un autre eventuel exercice.. Si l'un d'entre vous a une idee n'hesitez pas...
                            • Partager sur Facebook
                            • Partager sur Twitter
                            Anonyme
                              18 avril 2010 à 20:36:39

                              Et si tu corrigeais les fautes d'orthographe ?
                              • Partager sur Facebook
                              • Partager sur Twitter
                                18 avril 2010 à 20:42:10

                                Le double cast est totalement inutile. :-°
                                Comment tu peux affirmer que av est signé ? ça dépend de ton compilateur (et en général c'est signé). Avec gcc tu peux faire un -funsigned-char pour dire que ton char est non signé par défaut. :)
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  18 avril 2010 à 21:08:24

                                  Citation : Pouet_forever

                                  Le double cast est totalement inutile. :-°
                                  Comment tu peux affirmer que av est signé ? ça dépend de ton compilateur (et en général c'est signé). Avec gcc tu peux faire un -funsigned-char pour dire que ton char est non signé par défaut. :)



                                  Le double cast est une précaution car de manière générale argv est un char signé. (Pour l'option de gcc, je n'était pas au courant, en même temps vu le nombre d'options de gcc ...)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    18 avril 2010 à 21:12:07

                                    Où est-ce que tu as vu ça ? :o
                                    Et de toutes façons ton cast en size_t ne sert absolument à rien.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      18 avril 2010 à 21:21:40

                                      Je ne dit pas que c'est vrai sur tout les systèmes mais souvent char équivaut à un signed char tout comme int équivaut à un signed int.
                                      En effet, le cast en size_t n'est pas forcément utile.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        18 avril 2010 à 21:33:25

                                        Oui effectivement, Pouet a raison, pourquoi forcement? un unsigned char est forcement entier positif...
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          18 avril 2010 à 21:39:20

                                          Citation : Adroneus

                                          Oui effectivement, Pouet a raison, pourquoi forcement? un unsigned char est forcement entier positif...



                                          L'indice d'un tableau doit être non signé mais argv contient des char signés il faut pour cela en char non signé (ensuite le cast en size_t n'est pas obligatoire, je peux l'enlever s'il vous dérange).
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            19 avril 2010 à 14:14:05

                                            Bonjour,


                                            je viens de tomber sur ce topique, et surtout sur le topique qui le précédait.

                                            Je viens d'arriver sur ce site, je le trouve formidable.

                                            Je débute réellement de zéro :euh:

                                            Bref, je vous encourage à persévérer dans la proposition d'exercices, sachez d'ores et déjà que je viens de finir de digérer la seconde partie du Tutoriel de Mateo21 et je suis demandeur.

                                            Je suis venu au C, simplement parce que j'ai envie de CODER :p

                                            En fait ce qui m'interresse, c'est :

                                            Expression d'un besoin ==> définitions de réponses (algorithmes) ==> codage.

                                            Il est clair que ces topiques d'exercices, même si le niveau est quelquefois difficilement appréhendable est une bonne base pour moi de répondre aux problématiques du C.
                                            Une fois l'algorithme et sa réponse mathématique défini, ce n'est qu'une histoire d'un langage.

                                            bref il y a matière a travailler et a optimiser son langage et sa réflexion ici et avec vous.

                                            C'est en forgeant que l'on devient forgeron, et j'espère que je pourrai suivre les prochains exercices...
                                            Dans tous les cas j'essaierai d'y participer de mon mieux. (déjà le compteur de mots a fourni énormément de réponses qui m'ont permis de coder la partie 2 du Pendu :p )


                                            Cdt,

                                            Olivier.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              19 avril 2010 à 14:15:25

                                              Citation : Lithrein


                                              L'indice d'un tableau doit être non signé



                                              Je me disais bien que c'est pour cette raison que tu avais converti en size_t. Et tu tiens d'où que les indice doivent être non signés ? T'as jamais utilisé un indice négatif ?
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                19 avril 2010 à 14:34:28

                                                Oui c'est une discussion qu'on avait eu avec Pouet_FOrever et GurneyH je crois... ainsi que Fvirtman, c'etait sur la FAQ C je pense... Mesage supprime, bref, les indices ne doivent pas obligatoirement etres positifs
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  19 avril 2010 à 14:50:01

                                                  @Adroneus : Je suis au courant. Je souhaitais réglé ça par Mp avec Candide mais puisque tu le précise, je le fait aussi ici.


                                                  Ce code fonctionne très bien mais son utilité réelle est quasi nulle.
                                                  [...]
                                                  {
                                                      int tab[4] = {0};
                                                      int *p_t = tab+2;
                                                  
                                                      printf("Somme = %d", p_t[-2] + p_t[-1] + p_t[0] + p_t[1]);
                                                  [...]
                                                  }
                                                  


                                                  Le prochain exercice arrivera en fin de semaine, le temps que je le conçoive et que je fasse la correction.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    19 avril 2010 à 15:37:07

                                                    J'ai une question, avec le code pour la correction n°1 (celui du K&R quoi) quand je tape ma saisie par exemple :
                                                    bonjour

                                                    Pour envoyer EOF je dois d'abord effectuer un saut de ligne, il n'y a pas un moyen de corriger ça ?
                                                    Ça me compte donc un caractère de plus.
                                                    C'est pas très important mais je suis curieux.
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      21 avril 2010 à 18:08:35

                                                      MAGNIFIQUES !!! Je suis aux anges, vraiment!
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        21 avril 2010 à 18:48:16

                                                        Citation : honolyani

                                                        MAGNIFIQUES !!! Je suis aux anges, vraiment!


                                                        Citation : SofEvans

                                                        Apres l'etude de la SDL, voici l'etude du LSD!!

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          24 avril 2010 à 0:57:59

                                                          - citation d'un message supprimé coupée -

                                                          Tiens, une idée d'exo qui me vient à l'esprit : écrire le code d'un zJustificator.

                                                          En gros, un zJustificator va transformer le texte de gauche en le texte de droite :

                                                          Image utilisateur






                                                          Un "Justificator" est un programme qui transforme un texte donné en le même texte mais présenté en sorte qu'il soit affiché sur un nombre de colonnes donné et que le texte soit justifié, c'est à dire que les débuts de chaque ligne et les fins de chaque ligne soient verticalement alignés (sauf la dernière ligne) et non terminées par un espace. Le principe est d'ajouter dans le texte initial des "blancs" pour réaliser les alignements verticaux.

                                                          Après avoir avoir un peu cherché, j'ai pas pu mettre la main sur un outil Unix en ligne de commande et qui fasse ça mais je suis convaincu que ça doit se trouver. (*)

                                                          Voilà, je suggère cet exo mais je ne le prends pas en charge, ni énoncé rigoureux ni suivi de posts ni correction, je lance juste l'idée.

                                                          EDIT (*): après recherches laborieuses, il existe l'outil reformat mais la sortie proposée est assez peu élaborée :

                                                          $ reformat -j -w 27 < a.txt 
                                                          Candide, en retournant dans
                                                          sa   métairie,   fit    de
                                                          profondes  réflexions  sur
                                                          le discours du Turc. Il dit
                                                          à Pangloss et  à Martin :
                                                          « Ce  bon   vieillard   me
                                                          paraît   s'être  fait  un
                                                          sort bien  préférable  à
                                                          celui des six rois avec qui
                                                          nous avons eu  l'honneur de
                                                          souper.  -- Les  grandeurs,
                                                          dit  Pangloss,   sont  fort
                                                          dangereuses,     selon   le
                                                          rapport    de  tous     les
                                                          philosophes   :  car  enfin
                                                          Églon,  roi des  Moabites,
                                                          fut  assassiné  par  Aod ;
                                                          Absalon  fut pendu  par les
                                                          cheveux et  percé de trois
                                                          dards ; le roi  Nadab, fils
                                                          de Jéroboam,  fut tué par
                                                          Baaza  ; le roi  Éla,  par
                                                          Zambri  ;   Ochosias,   par
                                                          Jéhu   ;  Athalia,     par
                                                          Joïada ; les rois Joachim,
                                                          Jéchonias, Sédécias,
                                                          furent esclaves. Vous savez
                                                          comment périrent  Crésus,
                                                          Astyage,  Darius,  Denys de
                                                          Syracuse, Pyrrhus, Persée,
                                                          Annibal,          Jugurtha,
                                                          Arioviste, César, Pompée,
                                                          Néron,  Othon,  Vitellius,
                                                          Domitien,     Richard    II
                                                          d'Angleterre,  Édouard II,
                                                          Henri  VI,   Richard   III,
                                                          Marie Stuart,  Charles Ier,
                                                          les trois Henri  de France,
                                                          l'empereur  Henri IV ? Vous
                                                          savez... -- Je  sais aussi,
                                                          dit  Candide,   qu'il  faut
                                                          cultiver  notre  jardin. --
                                                          Vous  avez   raison,    dit
                                                          Pangloss   :  car,    quand
                                                          l'homme  fut  mis  dans  le
                                                          jardin  d'Éden,  il  y fut
                                                          mis ut operaretur eum, pour
                                                          qu'il  travaillât,  ce qui
                                                          prouve  que  l'homme  n'est
                                                          pas né  pour le  repos. --
                                                          Travaillons sans raisonner,
                                                          dit Martin ;  c'est le seul
                                                          moyen  de  rendre  la   vie
                                                          supportable. »


                                                          comme quoi, ça doit pas être si facile à réussir.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          Exercices pour débutants en C (suite)

                                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                          • Editeur
                                                          • Markdown