• 2. Définition d'une chaine de caractères

      Une chaine de caractères est un tableau de caractères particulier puisqu’en plus d’intégrer le code ASCII de chaque caractère, le tableau se termine par la valeur 0. Ainsi un tableau de 10 caractères initialisé avec la chaine de caractère "ABC" aura 4 cases initialisées : les 3 cases ayant les codes 65('A'),66('B') et 67('C') et la quatrième case avec la valeur 0 (fin de la chaine). Par défaut la valeur 0 est codé sur 32 bits (c’est un int) alors que '\0' est codé sur 8 bits, c’est donc cette dernière que l’on utilisera pour tester la fin de la chaine de caractères. 

      Comme tout tableau, il est possible de créer une chaine de caractères non initialisée.

      char sz[10];

      Il existe 2 solutions permettant d'initialiser une chaine de caractères : avec les " " ou bien caractère par caractère.

      Solution 1 : création d'une chaine de caractères et initialisation en utilisant " " 
      Solution 2 : création d'une chaine de caractères et initialisation caractères par caractères
      char sz[10] = "ABC"; char sz[10] = { 'A', 'B', 'C', '\0' };

      Comme tout tableau, il est possible de modifier une case du tableau. Dans l’exemple ci-dessous, on place 'B' dans la case 0.

      sz[0] = 'B';

      Quizz
    • 3. Lire et afficher une chaine de caractères

      Il est possible de lire une chaine de caractères notée mot avec la fonction gets(mot) ou scanf("%s", mot). Pour afficher sur l’écran une chaine de caractère, on utilisera les fonction puts(mot) ou printf("%s\n", mot). La fonction puts (put string) en plus d'afficher la chaine de caractères fait un saut de ligne.

      Nous avons vu jusqu’ici la lecture d’une variable entière (%d), réelle (%lf) et de type caractère (%c). Il existe un dernier type de lecture : la lecture de chaine de caractères %s.

      Lecture d'une chaine de caractères saisie par l'utilisateur
      Affichage à l'écran d'une chaine de caractères
      char mot[10];
gets(mot); char mot[10]="test';
puts(mot);

      Quizz

      A la différence avec la lecture caractère par caractère de la fonction getchar(), la lecture du buffer de caractère se fait en une seule fois avec la fonction gets. Tous les caractères saisis se trouvent dans le tableau passé en argument et le code ASCII de la touche « Entrée (ou retour charriot) » est remplacée par la valeur '\0'. Il ne reste donc plus qu’à utiliser une boucle pour lire les caractères du tableau jusqu’à trouver le '\0' terminal.

      Afin de mieux comprendre comment travailler avec une chaine de caractères, prenons un exemple utilisant les fonction gets, puts, printf et la lecture des caractères de la chaine de caractères au travers une boucle for.

      Exemple de code utilisant les chaines de caractères
      Résultat

          char chaine[80] = "Bonjour";

          puts(chaine);

          chaine[0] = 'b';

          puts(chaine);

          printf("entrer une phrase :");

          gets(chaine);

          printf("chaine=%s\n", chaine);

          for (int i = 0; chaine[i] != '\0'; i++)

              printf("chaine[%d]=%c\n",i, chaine[i]);

      Bonjour

      bonjour

      entrer une phrase :roger

      chaine=roger

      chaine[0]=r

      chaine[1]=o

      chaine[2]=g

      chaine[3]=e

      chaine[4]=r

      Les fonctions d'affichage printf %s ou puts utilisent le '\0' terminal pour stopper l'affichage de la chaine de caractère. Dans le programme ci-dessous, le fait de modifier la position du '\0' terminal coupe l'affichage de la chaine "bonjour" qui a été au préalable modifié en "abnjour" par la boucle for.

      Exemple de code modifiant l '\0' terminal
      Résultat

          char mot[80] = "Bonjour";

          int i;

          for (i = 0; i < 2; i++)

              mot[i] = 'a' + i;

          mot[4] = '\0';

          puts(mot);

      abnj

      Quizz
    • 4. La bibliothèque string.h

      Il existe de nombreuses fonctions définies dans la bibliothèque string.h et notamment les fonction strcmp, strcpy, strlen. Pour plus de détail on pourra consulter https://www.tutorialspoint.com/c_standard_library/string_h.htm

      Programme de test des fonctions strlen, strcmp et strcpy
      résultat

      #include <stdio.h>

      #include <string.h>

      int main(){

          char szSrc[80] = "Bonjour";

          char szDest[80] = "Bonjour a tous";

          printf("longueur de szSrc : %d\n", strlen(szSrc));

          printf("longueur de szDest : %d\n", strlen(szDest));

          if (strcmp(szSrc, szDest) == 0)

              printf("chaines identiques\n");

          else

              printf("chaines differentes\n");

          strcpy(szDest, szSrc);

          printf("apres copie de szSrc vers szDest\n");

          printf("longueur de szSrc : %d\n", strlen(szSrc));

          printf("longueur de szDest : %d\n", strlen(szDest));

          if (strcmp(szSrc, szDest) == 0)

              printf("chaines identiques\n");

          else

              printf("chaines différentes\n");

          return 0;

      }

      longueur de szSrc : 7

      longueur de szDest : 14

      chaines differentes

      apres copie de szSrc vers szDest

      longueur de szSrc : 7

      longueur de szDest : 7

      chaines identiques

      Quizz

    • 5. Comparaison entre gets et getchar

      La lecture d'une chaine de caractère peut être faite de 2 façons :

      • en utilisant la fonction gets et en travaillant avec les chaines de caractères, il est alors possible de lire la chaine jusqu'au caractère '\0'
      • en utilisant la fonction getchar (ou scanf %c) et au travers d'une lecture caractère par caractère jusqu'au caractère '\n'

      Dans l'exemple ci-dessous, nous utilisons la boucle en do while pour parcourir la chaine de caractères, mais en général on utilisera la boucle répétitive for plus compacte.

      travail avec gets lecture de la chaine de caractère
      Travail avec la fonction scanf %c ou getchar (lecture caractère par caractère)

      #define _CRT_SECURE_NO_WARNINGS

      #include <stdio.h>

      int main() {

          char buffer[30],c; 

          int cpt = 0,i=0;

          printf("entrer des caracteres:");

          gets(buffer);

          do {

              c = buffer[i];

              if (c == 'a' || c == 'A')

                  cpt++;

              i++;

          } while (c != '\0');

          printf("nombre de lettre A ou a : %d\n", cpt);

          return 0;

      }

      #define _CRT_SECURE_NO_WARNINGS

      #include <stdio.h>

      int main() {

          char c;

          int cpt = 0;

          printf("entrer des caracteres:");

          do {

              scanf("%c", &c);

              if (c == 'a' || c == 'A')

                  cpt++;

          } while (c != '\n');

          printf("nombre de lettre A ou a : %d\n", cpt);

          return 0;

      }

    • 6. Ecrire des fonctions de gestion de caractères

      Nous avons vu que la différence entre une chaine de caractères et un tableau d’entier ou de réels est liée au '\0' terminal que l’on trouve en fin de chaine de caractères et qui permet de connaitre la taille de la chaine. Ainsi les fonctions associées aux chaines de caractères n’ont pas besoin de 2 arguments (le tableau et la taille du tableau) mais seulement de la chaine de caractères.

      Voici 3 codes de fonctions :

      • strLen (qui implémente le code de la fonction strlen définie dans string.h) qui compte le nombre de caractères jusqu'au '\0' terminal
      • strCmp (qui implémente le code de la fonction strcmp définie dans string.h) qui compare 2 chaines de caractères et renvoie 0 si les 2 chaines sont identiques
      • strChr (qui implémente le code de la fonction strchr définie dans string.h) qui cherche le caractère passé en argument et compte le nombre d'occurrence 

      Pour ces 3 fonctions, on passe la chaine de caractères et la fonction va lire la chaine caractère par caractère jusqu'au '\0' terminal. 

      Code des fonctions
      Appel de ces fonctions
      résultat

      int strLen(char chaine[]) {

          int i;

          for (i = 0; chaine[i] != '\0'; i++);

          return i;

      }

      int main(){

          char mot[80] = "Boom";

          printf("%s:%d\n", mot,strLen(mot));

          printf("%s:%d", "bon", strLen("bon"));

      }

      Boom:4

      bon:3

      int strCmp(char chaine1[], char chaine2[]) {

          int i,cpt=0;

          int n1 = strLen(chaine1);

          int n2 = strLen(chaine2);

          if (n1 != n2)

              return (n1-n2);

          for (int i = 0; i < n1; i++)

              cpt += chaine1[i] - chaine2[i];

          return cpt;

      }

      int main(){

        char mot[80] = "Boom";

          printf("%d\n",strCmp(mot,"BOOm"));

          printf("%d", strCmp("Bon", "Bon"));

      }

      64

      0

       

      int strChr(char chaine[], char c) {

          int cpt = 0;

          for (int i = 0; chaine[i] != '\0'; i++)

              if (chaine[i] == c)

                  cpt++;

          return cpt;

      }

       

       char mot[80] = "Boom";

       printf(" %d %c dans %s\n", strChr(mot, 'o'), 'o', mot );

       printf(" %d %c dans %s", strChr("bonjour", 'o'),'o', "bonjour");

      2 o dans Boom

      2 o dans bonjour

    • 7. problème de sécurité gets

      La fonction gets en C est notoirement dangereuse car elle ne vérifie pas la taille de la chaîne dans laquelle elle lit, ce qui peut conduire à des dépassements de tampon et des failles de sécurité. En raison de ces problèmes, elle a été retirée de la norme C11 (version 2011 du langage C)

      Sous Visual Studio, on peut continuer d'utiliser gets (même si c'est déconseillé) à condition d'ajouter la macro _CRT_SECURE_NO_WARNINGS

      Programme avec gets (Visual Studio)
      Résultat

      #define _CRT_SECURE_NO_WARNINGS

      #include <stdio.h>

      #include <stdint.h>

      #include <stdlib.h> 

      int main() {

          system("CHCP 1252 > nul");

          int8_t chaine[30];

          printf("entrer une chaine de caractère:");

          gets(chaine);

          printf("n=%d\n", strlen(chaine));

      }

      entrer une chaine de caractère:Bonjour

      n=7

      Il est fortement recommandé d'utiliser fgets à la place de gets car elle permet de spécifier la taille maximale du tampon et donc de prévenir les dépassements de tampon.

      Programme avec fgets (tout type de compilateur Windows Linux)
      Résultat

      #include <stdio.h>

      #include <stdint.h>

      #include <stdlib.h> 

      int main() {

          system("CHCP 1252 > nul");

          int8_t chaine[30];

          printf("entrer une chaine de caractère:");

          fgets(chaine,30,stdin);

          printf("n=%d\n", strlen(chaine));

      }

      entrer une chaine de caractère:Bonjour

      n=7

    • 8. Test de fin de chapitre