Annonce

Réduire
Aucune annonce.

Cours langage C n°11 - Manipulation des chaînes de caractères avec string.h

Réduire
Ceci est une discussion importante.
X
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Cours langage C n°11 - Manipulation des chaînes de caractères avec string.h

    Manipulation des chaînes de caractères


    Remplacer des lettres, inverser une chaîne de caractères, concaténer deux chaînes, ... On peut le faire nous même, mais pourquoi réinventer la roue, tout cela existe déjà dans la bibliothèque string.h

    Nous allons donc en voir les plus importantes:
    • strcpy Copie d'une chaîne dans une autre
    • strcat Concaténation de deux chaînes de caractères (lier les deux chaînes ensemble)
    • strchr Cherche la 1ère occurence d'une lettre dans une chaîne
    • strlen Retourne la longueur d'une chaîne


    STRCPY

    Pour copier une chaîne dans une autre variable, on pouvait faire ceci

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        const char source[] = "hello world !";
        char destination[50];
    
        int i;
        for (i=0; source[i]!='\0'; i++)
        {
            destination[i] = source[i];
        }
    
        destination[i] = '\0';
    
        printf("%s\n", destination);
    
        return 0;
    }
    Assez lourd non ?

    Avec strcpy, on va pouvoir faire cela

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        const char source[] = "hello world !";
        char destination[50]; /* Attention d'avoir assez de place pour placer tous les caractères + '\0' */
    
        strcpy(destination, source); /* copie de la variable source dans variable destination */
    
        printf("%s\n", destination); /* affichage du contenu de la variable destination */
    
        return 0;
    }
    Beaucoup plus simple non ?

    Remarques:
    1. On inclut la bibliothèque string.h
    2. On utilise strcpy
    3. Pas d'ajout de caractère de fin de chaîne '\0', cette fonction le fait pour nous


    STRCAT

    Concaténer est le fait de lier deux chaînes ensemble, exemple "hello" et " world !", fera ce résultat "hello world !"

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char word_1[80] = "hello"; /* Attention de garder suffisamment de place pour placer word_2 */
        char word_2[] = " world !";
    
        strcat(word_1, word_2);
    
        printf("%s\n", word_1); /* affichage de word_1: "hello world !" */
    
        return 0;
    }
    On pourrait créer le mot secret du pendu avec cette fonction

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char secret[80] = "\0"; /* déclaration du mot secret avec 80 caractère maxi et initialisé */
        const char word[] = "secret";
    
        int i;
        for (i=0; word[i]!='\0'; i++)
        {
            strcat(secret, "*"); /* ajout de "*" en fin de chaîne */
        }
    
        printf("%s\n", secret); /* affichage de "******" */
    
        return 0;
    }
    Remarques:
    1. inclusion de la bibliothèque string.h
    2. Déclaration d'une chaîne avec suffisamment de place mémoire pour recevoir au moins l'équivalent de la taille de la variable word
    3. On ajoute des chaînes et non un caractère, donc pas '*' mais "*"


    STRCHR

    Cette fonction permet de retrouver l'occurrence d'un caractère, et par exemple de remplacer ce caractère par un autre

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char word[] = "hello world!\n"; /* le '\n' nous embête */
        char *p = word; /* p contient l'adresse du 1er élément du tableau word */
    
        p = strchr(word, '\n'); /* p contiendra l'adresse du caractère '\n' */
        if (p != NULL) /* si caractère '\n' trouvé dans word */
        {
            *p = '\0'; /* on remplace '\n' par '\0' */
        }
    
        printf("%s\n", word); /* affichage de word: "hello world !" sans '\n' */
    
        return 0;
    }
    Si on veut remplacer dans notre pendu des '*' par un autre caractère exemple "*******" en "*o**o**"

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char secret[] = "bonjour";
        char word[] = "*******";
        char *p = secret; /* p contient l'adresse du 1er élément du tableau secret */
        int index;
    
        p = strchr(secret, 'o');
        while (p != NULL)
        {
            index = p - secret;
            word[index] = *p;
            p = strchr(p+1, 'o');
        }
    
        printf("%s\n", word); /* affichage de word: "*o**o**" sans '\n' */
    
        return 0;
    }
    what ? p - secret donne un entier ? Eh bien oui, se sont des adresses, imaginez que vous cherchiez un objet, comme une pelle de jardin par exemple, dans l'ordre vous cherchez

    chez vous, adresse 0x7fff36b12621
    chez le voisin adresse 0x7fff36b12622
    chez l'autre adresse 0x7fff36b12623
    ...

    Vous avez trouvé à l'adresse 2, donc 0x7fff36b12623 - 0x7fff36b12621 = 2, l'indice sera 2

    Bon le plus courant et même je dirais le plus simple, serait

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        char secret[] = "bonjour";
        char word[] = "*******";
        int index;
    
        for (index=0; secret[index]!='\0'; index++)
        {
            if (secret[index] == 'o')
            {
                word[index] = 'o';
            }
        }
    
        printf("%s\n", word); /* affichage de word: "*o**o**" sans '\n' */
    
        return 0;
    }
    Voilà il est vrai qu'il faut adapter l'utilisation des fonctions présentées ici à son problème, pour le cas du pendu, le dernier code me semble plus adapté au besoin.

    strchr est très souvent utilisé pour le 1er cas lorsqu'on veut virer un '\n' gênant...

    STRLEN

    Cette fonction permet d'avoir la longueur d'une chaîne, elle permet entre autres de faire de l'allocation dynamique, qu'on verra plus tard

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char secret[] = "bonjour";
    
        int length = strlen(secret);
    
        printf("%d\n", length); /* affichage de la longueur de "bonjour", c'est à dire 7 */
    
        return 0;
    }
    CONSEILS

    Entraînez-vous à les utiliser
    Revoir les chaînes de caractères
    Revoir les pointeurs
    Revoir les fonctions et prototypes

    EXERCICES

    Créer un jeu du pendu, on ne vous impose rien à part l'utilisation de strcmp qui permettra de comparer le mot secret à votre mot composé d'*

    Merci de m'avoir lu et à bientôt pour le prochain cours
    Dernière modification par fred, 06 novembre 2016, 11h18.

  • #2
    Salut,

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
    
        char motUilisateur[100] = {'\0'};
        char motSecret[100] = {'\0'};
        char lettre;
        int i;
        int j;
    
        printf("================================================================================\n");
        printf("\t\t\t\t=== PENDU ===\n\n");
        printf("================================================================================\n\n");
    
    
        printf("\t\t\tBienvenue dans le jeu du pendu !\n\n\n");
        printf("Entrez le mot secret :");
        scanf("%s", motSecret);
        printf("\n\n");
    
        for(i=0; motSecret[i] != '\0'; i++)
        {
            motUilisateur[i] = '*';
        }
    
        printf("Le mot a trouve se compose de %d caracteres\n\n", i);
    
        while(strcmp(motUilisateur,motSecret) != 0)
        {
            printf("Entrez une lettre..");
            scanf("%c", &lettre);
    
    
            for(j=0; motUilisateur[j] != '\0'; j++)
            {
                if(lettre == motSecret[j])
                {
                    motUilisateur[j] = lettre;
                }
            }
    
            printf("Votre recherche : %s\n\n", motUilisateur);
        }
    
        printf("Bravo, vous avez trouve le nombre mystere !");
    
        return 0;
    
    }
    Juste un p'tit problème d'affichage quand vous allez exécuter le code, si quelqu'un pourrait me dire d'où sa vient ?
    deux et deux font cinq

    Commentaire


    • #3
      Ok, bon eh bien tout cela semble pas mal du tout...

      Quand tu parles de problème d'affichage, tu parles dans le cas des accents ?

      Si oui il me semble que c'est dû à l'encodage de ton fichier créé, qu'il faut soit utiliser avec l'encodage utf8, iso8859 voir latin1, en fait faut tester, mais comme dans mes programmes je n'utilise jamais les accents, je peux guère t'aider sur ce plan là...

      Commentaire


      • #4
        Salut fred', et merci pour ta réponse ^_^

        J'ai effectivement des problèmes d'accents, le problème vient de la console Windows, elle utilise une vieille norme qui n'inclut pas les accents.

        Sinon, quand je disais problème d'affichage, j'ai un soucis au niveau de ma boucle "while" elle boucle toujours une fois sans demandé le "scanf"

        et je comprend pas pourquoi :s
        deux et deux font cinq

        Commentaire


        • #5
          Sans doute une merde liée à Windows encore, car chez moi je n'ai pas de soucis lors des tests... (sous Unix)

          Commentaire


          • #6
            Malheureusement, je suis obligé de resté sur Windows, mes cours et exercices sont essentiellement dessus.

            Sinon je passerais bien sur un système Unix ! J'aimerais beaucoup essayé Kali'

            Heureusement qu'il y a les VM !
            deux et deux font cinq

            Commentaire


            • #7
              En fait j'ai été un peu vite dans mon test, en effet il y a un bug, il faut dans ton cas nettoyer le buffer à l'aide de cette ligne

              Code:
              while(getchar() != '\n');
              Que tu places entre ton printf et scanf

              Commentaire


              • #8
                Envoyé par fred Voir le message
                En fait j'ai été un peu vite dans mon test, en effet il y a un bug, il faut dans ton cas nettoyer le buffer à l'aide de cette ligne

                Code:
                while(getchar() != '\n');
                Que tu places entre ton printf et scanf
                En effet, ça fonctionne correctement maintenant !

                C'est quoi le "buffer" ? et pourquoi doit-on le nettoyer ?

                J'ai entendu parlé de cette notion en ADA mais sinon ? :s

                EDIT : Aussi, dans mon code j'ai oublié le caractère de fin de chaine de la chaine "motUtilisateur" mais

                apparemment le code fonctionne quand même ? Je boucle dessus pour y mettre les étoiles mais lorsque je sors de

                la boucle je ne précise pas que c'est la fin de la chaine.
                Dernière modification par shirocen, 16 janvier 2015, 15h47.
                deux et deux font cinq

                Commentaire


                • #9
                  C'est quoi le "buffer" ? et pourquoi doit-on le nettoyer ?
                  Se sont des résidus (lorsque scanf se passe mal, dont le format attendu n'est pas correct) se trouvant sur l'entrée standard, des caractères qui ne sont pas réellement nettoyé en zone mémoire (buffer). c'est pourquoi on utilise une petite boucle pour faire ce nettoyage jusqu'à rencontré le caractère '\n' de fin de ligne. La ligne doit être un peu plus précisé, mais n'est pas utile à spécifier dans ton cas.

                  Aussi, dans mon code j'ai oublié le caractère de fin de chaine de la chaine "motUtilisateur" mais

                  apparemment le code fonctionne quand même ?
                  Non non, tu l'as bien fais lors de l'initialisation, automatiquement le caractère '\0' est implanté en fin de chaîne (en fait pour être sûr faut que je regarde la norme).

                  Mais ne rien indiquer comme

                  Code:
                  char s[100];
                  suffirait... ainsi il ne faudra pas oublier le '\0' à la fin.

                  Après recherche, oui c'est bien cela, tu auras 100 fois le caractère '\0'.

                  Voilà pourquoi tu n'as pas besoin de le spécifier.
                  Dernière modification par fred, 16 janvier 2015, 17h19.

                  Commentaire


                  • #10
                    Ok donc lorsqu'on créé un tableau de char et qu'on l'initialise :

                    char tableau[100] = {'a'} - char tableau[100] = {'\0'}

                    Toutes les valeurs qui suivent sont automatiquement misent à '\0'.

                    Par contre, si on ne l'initialise pas, il faudra écrire le caractère de fin de chaine manuellement dans le code.

                    Pour un tableau d'int, toutes les valeurs qui suivent l'initialisation seront mise à "0"
                    Dernière modification par shirocen, 17 janvier 2015, 17h34.
                    deux et deux font cinq

                    Commentaire


                    • #11
                      char tableau[100] = {'a'}
                      Là non, en fait se sera {'a', '\0', '\0', ...}

                      Enfin je sais pas si c'est ce que tu voulais dire pour ce cas. Si oui dans ce cas tu avais raison, je préférais préciser.

                      Pour le reste tout est ok.

                      Commentaire


                      • #12
                        En effet fred', je voulais dire ça !

                        Je vais donc continuer tes cours !!!
                        deux et deux font cinq

                        Commentaire


                        • #13
                          Un petit test de pendu, j'ai essayé de réutiliser un peu tout ^^

                          Code:
                          #include <stdio.h>
                          #include <string.h>
                          
                          void DisplayMenu(void);
                          int TestWord(void);
                          void TestLetter(void);
                          
                          int lives = 10; /* Nombre de vies */
                          char secret[80] = "\0"; /* déclaration du mot secret avec 80 caractère maxi et initialisé */
                          char word[] = "secret";
                          
                          int main(void)
                          {
                          
                          
                              int i;
                              int choice;
                          
                          
                              for (i=0; word[i]!='\0'; i++)
                              {
                                  strcat(secret, "*"); /* ajout de "*" en fin de chaîne */
                              }
                              printf("Vous avez %d vies. \n", lives);
                              puts("Mot à deviner \n");
                              printf("%s\n", secret); /* affichage de "******" */
                              DisplayMenu();
                          
                              while(scanf("%d", &choice) != 0)
                              {
                                  putchar('\n');
                                  switch (choice)
                                  {
                                      case 1:
                                          TestLetter();
                                          break;
                                      case 2:
                                          if (TestWord() == 1)
                                              return 0;
                                          else
                                              break;
                                      case 3:
                                          puts("Vous quittez le pendu...");
                                          return 0;
                                      default:
                                          puts("Invalid choice. Try again. \n");
                                          break;
                                  }
                                  if (lives > 0)
                                      DisplayMenu();
                                  else
                                  {
                                      puts("\n Vous n'avez plus de vies, vous avez perdu... \n \n");
                                      break;
                                  }
                              }
                              return 0;
                          }
                          
                          void DisplayMenu(void)
                          {
                              puts("\n 1 - Dire une lettre \n 2 - Tenter un mot \n 3 - Quitter le pendu \n \n Entrez votre choix : \n");
                          }
                          
                          void TestLetter(void)
                          {
                              char *p = word; /* p contient l'adresse du 1er élément du tableau secret */
                              int index;
                              char test;
                          
                              char oldWord[100];
                              strcpy(oldWord, secret); /* On copie l'état actuel du mot caché, avant modification */
                          
                              puts("Essayez une lettre : \n");
                          
                              int result;
                              result = scanf(" %c", &test); /* Avec un espace pour passer outre les espaces précédents */
                          
                              if (result != 0)
                              {
                                  p = strchr(word, test);
                                  while (p != NULL) /* On remplace les occurences de la lettre */
                                  {
                                      index = p - word;
                                      secret[index] = *p;
                                      p = strchr(p+1, test);
                                  }
                                  if (strcmp(oldWord, secret) != 0) /* Si les deux mots sont différents, la lettre était présente */
                                      printf("\n Nouveau mot : %s \n", secret);
                                  else
                                  {
                                      /* Sinon ça veut dire que la lettre n'y était pas */
                                      lives--;
                                      printf("\n La lettre n'est pas présente. Il vous reste %d vies. \n \n" , lives);
                                  }
                              }
                              else
                                  puts("Une erreur est survenue.");
                          }
                          
                          int TestWord(void)
                          {
                              char test[100];
                              puts("Essayez un mot : \n");
                              scanf("%99s", test);
                              if (strcmp(word,test) != 0)
                              {
                                  lives--;
                                  printf("\n Mauvais mot ! Il vous reste %d vies \n", lives);
                                  return 0;
                              }
                              else
                              {
                                  printf("\n Bravo tu as deviné le bon mot avec %d vies ! Le mot secret était bien %s \n \n", lives, test);
                                  return 1;
                              }
                          
                          }
                          Mon blog : http://rootsheep.info

                          Commentaire


                          • #14
                            Bonjour,

                            Petite erreur au début de la leçon, il manque une fermeture de commentaire */ après la zone en gras.

                            Code:
                            #include <stdio.h> #include <string.h> int main(void) { const char source[] = "hello world !"; char destination[50]; /* Attention d'avoir assez de place pour placer tous les caractères + '\0' strcpy(destination, source); /* copie de la variable source dans variable destination */ printf("%s\n", destination); /* affichage du contenu de la variable destination */ return 0; }
                            Après correction :

                            Code:
                             #include <stdio.h> #include <string.h>  int main(void) {     const char source[] = "hello world !";     char destination[50]; /* Attention d'avoir assez de place pour placer tous les caractères + '\0' */      strcpy(destination, source); /* copie de la variable source dans variable destination */      printf("%s\n", destination); /* affichage du contenu de la variable destination */      return 0; }
                            Ps: En mettant en gras et modifiant la taille de certains caractère, on perd la mise en page du code...
                            Dernière modification par Ephemeral25, 05 novembre 2016, 23h38.
                            "la Connaissance pour un éveil de la Conscience"

                            Commentaire


                            • #15
                              Merci c'est modifié !

                              Commentaire

                              Chargement...
                              X