Manipulation de chaînes de caractères




        



Le langage C n'est certes pas un langage récent, mais il propose au programmeur au travers de la bibliothèque standard un grand nombre de routines dédiées à la manipulation de chaînes de caractères.
Rappelons qu'en C une chaîne de caractères ou 'string', est un tableau de type char dont la dernière case contient le caractère nul '\0' indiquant la fin de la string.
Pour utiliser les fonctions que nous allons aborder dans ce cours il est nécessaire d'inclure dans vos programmes les header files stdlib.h et string.h


Sommaire

1. Les types utilisés par les fonctions de manipulation de strings
2. strlen : Connaître la longueur d'une chaîne de caractères
3. Copie de chaînes de caractères
4. strcpy
5. strncpy
6. La concatenation de chaînes de caractères
7. strcat
8. strncat
9. La comparaison de chaînes de caractères
10. strcmp
11. strncmp
12. strchr et strrchr : Recherche d'un caractère
13. strspn, strcspn, strpbrk : recherche par rapport à plusieurs caractères
14. strtok : Découper une chaîne de caractères en lexèmes


Les types utilisés par les fonctions de manipulation de strings

        Lorsqu'on utilise les fonction de manipulation de chaînes, on est amené a utilisé divers types que nous allons tout de suite présenter.
  • Lorsque dans le prototype d'une fonction de manipulatuion de chaîne on rencontre :


const char *

        il s'agit d'un argument de type chaîne de caractère se terminant par un '\0' qui ne sera pas modifié par la fonction.

  • Lorsqu'on rencontre un argument de type


char *

        il s'agit généralement d'une string devant être modifié par la fonction.

  • Enfin le type size_t


typedef unsigned long size_t

        représente une valeur de type unsigned long (type souvent utilisé pour le renvoie de valeur par les fonctions).


strlen : Connaître la longueur d'une chaîne de caractères

        La fonction strlen


size_t strlen(const char * s);

        renvoie la longueur de la chapîne qu'on lui passe en argument.

  • s

    chaîne de caractère pointée par s dont on veut la taille. Cette chaîne doit bien avoir été initialisée en mémoire.


  • valeur retournée

    La fonction retourne la longueur de la chaîne de caractère sans compter le '\0' final.




En fait il serait très simple de programmer nous même cette méthode ainsi :



size_t PWGStrlen(const char * s)
{
  size_t increment;
  char c;

  //incrementer 'increment' tant qu'on a 
  //pas le caractere nul
  while(  (c = *(s + increment)) != '\0')
  {
    increment++;
  }

  //renvoyer la taille
  return increment;
}

        Voyons un exemple


#include <string.h>
#include <stdlib.h>
#include stdio.h>



int main(int argc, char * argv)
{
  //valeur qui va contenir la taille des arguments passé au programme
  size_t tailleArgument;

  //increment standard
  int i;

  //passer le nom du programme
  argc--; argv++;

  if (!argc)
  {
    fprintf(stderr, "vous devez au moins passer un argument au programme !\n");
    exit(0);
  }
  
  while(i < argc)
  {
    //prendre la taille de l'argument
    tailleArgument = strlen(argv[i]);

    //afficher infos
    printf("l'argument %d a pour libellé :%s et pour taille %d\n",
                  i, argv[i], tailleArgument);

  }

  return 0;
}


Copie de chaînes de caractères

        Les fonctions strcpy et strncpy permettent de recopier une chaîne de caractère passé en paramètre vers un espace alloué de la mémoire.


char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t nb);


        voyons ces fonctions plus en détails.


  Danger
Attention a veiller à ce que l'espace mémoire de destination soit assez grand pour contenir la chaîne à recopier !!


strcpy

        La fonction strcpy


char *strcpy(char *dest, const char *src);

        

recopie le contenu de la chaîne de caractère pointée par src vers l'adresse contenue dans dest. Elle retourne en outre la chaîne obtenue.

  • src

    src est un pointeur sur la chaîne de caractère a recopier.



  • dest

    dest est un pointeur sur un espace mémoire dans lequel va être recopié la chaîne de caractères pointée par src.
    L'initialisation de dest est souvent la cause principale d'erreur dans un programme (voir le dernier point de ce chapitre).




  • Valeur retournée

    La fonction strcpy renvoie le contenu de dest.



Un petit exemple :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    char buffer[80];

    strcpy( buffer, "Hello world" );
    printf( "%s\n", buffer );

    return 0;
}


        donne la sortie :


Hello world


strncpy

        La fonction strncpy



char *strncpy(char *dest, const char *src, size_t nb);

        

fonctionne sur le même principe que strcpy mais on lui passe un argument suplémentaire :nb.
Elle copie en effet le nombre de caractère contenu dans nb à l'adresse de dest.


  • nb

    L'argument nb contient le nombre de caractères à recopier de src vers dest. Si nb est supérieur à la longueur de la chaîne source alors la chaîne recopiée est complété par des caractères nul.



  • src

    src est un pointeur sur la chaîne de caractère a recopier




  • dest

    dest est un pointeur sur un espace mémoire dans lequel va être recopié la chaîne de caractères pointée par src.
    L'initialisation de dest est souvent la cause principale d'erreur dans un programme (voir le dernier point de ce chapitre).




  • Valeur retournée

    La fonction strcpy renvoie le contenu de dest.




Un petit exemple :


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void )
{
    char buffer[15];

    printf( "%s\n", strncpy( buffer, "abcdefg", 10 ) );
    printf( "%s\n", strncpy( buffer, "1234567",  6 ) );
    printf( "%s\n", strncpy( buffer, "abcdefg",  3 ) );
    printf( "%s\n", strncpy( buffer, "*******",  0 ) );

    return 0;
}




        produit la sortie :


abcdefg
123456g
abc456g
abc456g

        dans l'exemple ci-dessus nous l'affichons pas le contenu pointé par la variable buffer mais la valeur renvoyée par strncpy, ce qui revient au même.


La concatenation de chaînes de caractères

        Les fonctions strcat et strncat concatènent deux chaînes de caractères ensemble.


char *strcat(char *dest, const char *src):
char *strncat(char *dest, const char *src, size_t nb):


  Danger
Attention a veiller à ce que l'espace mémoire de destination soit assez grand pour contenir la chaîne à rajouter !!


strcat

        La fonction strcat


char *strcat(char *dest, const char *src):

        La fonction strcat ajoute la chaîne pointée par src à la chaine pointée par dest. Le caractère nul '\0' de fin de chaine de dest est alors remplacé par le premier caractère de la string pointée par src.



  • src

    src est un pointeur sur la chaîne de caractère qui doit être ajoutée à dest.




  • dest

    dest est un pointeur sur un espace mémoire dans lequel va être ajouté la chaîne de caractères pointée par src.

L'initialisation de dest est souvent la cause principale d'erreur dans un programme (voir le dernier point de ce chapitre).



  • Valeur retournée

    La fonction strcpy renvoie le contenu de dest final.






Il est important que la zone mémoire pointée par dest soit assez grand pour contenir la chaine src dans son ensemble.
De même on déconseillera aux apprentis magicien de faire se chevaucher les chaînes dest et src : les résultats sont completement imprévisibles.

Exemple :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    //bugger d'une taille supérieure a ce qu'on veut y placer
    char buffer[80];

    // copier hello dans la chaine (qui est vide pour l'instant)
    strcpy( buffer, "Hello " );

    //concatener la chaine world
    strcat( buffer, "world" );

    //afficher le resultat
    printf( "%s\n", buffer );

    return 0;
}


        donne la sortie


Hello world

        De même en second exemple nous pourrions créer une fonction qui ajoute une extension à un nom de fichier


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/**
 * fonction qui accepte une chaine en entrée
 * qui ajoute à cette chaine la string ".cpp" et qui la
 * renvoie
 */
char* extensionCPP(char *nomFichier)
{
    //buffer qui va contenir la chaine en entier
    char buffer;

   //allouer un espace mémoire suffisant pour accepter la chaine 
   //+ l'extension .cpp
   buffer = (char *)malloc(strlen(nomFichier)+4+1);

   //copier le nom de fichier
   strcpy(buffer, nomFichier);

   //ajouter l'extension
   strcat(buffer, ".cpp");

    //renvoyer la nouvelle chaine
    return buffer;
}


        La valeur "4+1" dans la ligne :


  buffer = (char *)malloc(strlen(nomFichier)+4+1);

        le nombre 4 représentant le nomber de caractère dans l'extension ".cpp" et le 1 est ajouté pour permettre l'ajout du caractère final nul '\0' à la fin de la chaine.

Nous pouvons facilement reprogrammer la fonction strcat par l'intermédiaire de la fonction strcpy :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/**
 * notre strcat a nous
 */
char* PWGStrcat(char *dest, const char * src)
{
    //buffer qui va contenir la chaine en entier
    char buffer;

   //faire pointer buffer sur dest
  buffer = dest

   //se placer à la fin de la chaine
   buffer = buffer + strlen(dest);

   //maintenant qu'on est à la fin
   //copier la chaine src
   strcpy(buffer, src);

    //renvoyer la nouvelle chaine
    return buffer;
}


        Comme on le voit il s'agit d'une fonction relativement simple.


strncat

        La fonction strncat


char *strncat(char *dest, const char *src, size_t n):

        fonctionne sur le même principe que strcat mais accepte un argument de plus : nb. La valeur entière contenue dans nb indique les nb premier caractères de src à ajouter à dest.





  • nb

    La fonction ajoute au plus les nb premiers caractères de la chaîne de caractère pointée par src à la chaine pointée par dest.





  • src

    src est un pointeur sur la chaîne de caractère qui doit être ajoutée à dest.




  • dest
    dest est un pointeur sur un espace mémoire dans lequel va être ajouté la chaîne de caractères pointée par src.
    L'initialisation de dest est souvent la cause principale d'erreur dans un programme (voir le dernier point de ce chapitre).




  • Valeur retournée
    La fonction strcpy renvoie le contenu de dest final.






Il est important que la zone mémoire pointée par dest soit assez grand pour contenir la chaine src dans son ensemble.
De même on déconseillera aux apprentis magicien de faire se chevaucher les chaînes dest et src : les résultats sont completement imprévisibles.

Exemple :


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char buffer[80];

int main( void )
{
    strcpy( buffer, "Hello " );
    strncat( buffer, "world", 8 );
    printf( "%s\n", buffer );
    strncat( buffer, "*************", 4 );
    printf( "%s\n", buffer );
    return 0;
}


        produit la sortie


Hello world
Hello world****


La comparaison de chaînes de caractères

        La comparaison de chaînes de caractères s'effectue au travers de deux fonctions :


int strcmp(const char *s1, const char *s2);
inr strncmp(const char *s1, const char *s2, size_t nb);

        La compariaon s'effectue entre deux chaînes de caractères (s1 et s2) suivant le système lexicogaraphique (celui de tout doictionnaire).
Les deux fonctions retournent une valeur négative si s1 est avant s2, positive si s1 est après s2 et égale à 0 si s1 est égale à s2.


  Réponse
Il est à remarquer que les minuscules sont considérées comme étant avant les majuscules


strcmp

        La fonction strcmp


int strcmp(const char *s1, const char *s2);

        compare les deux chaînes de caractères s1 et s2 qu'on lui passe en argument.



  • s1

    s1 est un pointeur sur la première chaîne de caractère de la comparaison.




  • s2

    s2 est un pointeur sur la seconde chaîne de caractère de la comparaison.



  • Valeur retournée

    La fonction strcmp renvoie :

    • -1 si s1 < s2
    • 0  si s1 == s2
    • 1 si  s1 > s2



Exemple :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    printf( "%d\n", strcmp( "abcdef", "abcdef" ) );
    printf( "%d\n", strcmp( "abcdef", "abc" ) );
    printf( "%d\n", strcmp( "abc", "abcdef" ) );
    printf( "%d\n", strcmp( "abcdef", "mnopqr" ) );
    printf( "%d\n", strcmp( "mnopqr", "abcdef" ) );
    printf( "%d\n", strcmp( "chien", "chiens" ) );
    printf( "%d\n", strcmp( "chien", "Chiens" ) );

    return 0;
}


        donne la sortie :


0
1
-1
-1
1
-1
1


strncmp

        La fonction strncmp


inr strncmp(const char *s1, const char *s2, size_t nb);

        compare les deux chaînes de caractères s1 et s2 qu'on lui passe en argument. Elle fonctionne sur le même principe que la fonction strcmp en comparant les nb premiers caractères de chaque chaîne.



  • nb

    nb indique le nombre de caractères a partir du début sur lesquels doit se porter la comparaison des chaînes s1 et s2.




  • s1

    s1 est un pointeur sur la première chaîne de caractère de la comparaison.




  • s2

    s2 est un pointeur sur la seconde chaîne de caractère de la comparaison.


  • Valeur retournée

    La fonction strcmp renvoie :

    • -1 si s1 < s2
    • 0  si s1 == s2
    • 1 si  s1 > s2



Exemple :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
   
    printf( "%d\n", strncmp( "abcdef", "abcDEF", 10 ) );
    printf( "%d\n", strncmp( "abcdef", "abcDEF",  6 ) );
    printf( "%d\n", strncmp( "abcdef", "abcDEF",  3 ) );
    printf( "%d\n", strncmp( "abcdef", "abcDEF",  0 ) );

    return 0;

}


        affiche :


1
1
0
0


strchr et strrchr : Recherche d'un caractère

        Les fonctions strchr et strrchr


char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);

        recherchent si un caractère est présent dans une chaîne de caracteres.
La fonction strchr recherche le caractère c qu'on lui transmet en paramètre est présent dans la châine s donnée en argument. Si c'est le cas, elle retourne alors un pointeur sur la première occurence de ce caractère dans la chaîne.


  • c

    Le caractère qui doit être cherché à l'intérieur de s.



  • s

    la string à l'intérieur de laquelle on cherche le caractère.





Il est à noter qu'on peut donner la valeur du caractère nul '\0' à c. Dans ce cas strchr retourne un pointeur sur le dernier caractère de la chaine.
La fonction strlen pourrait être programmée ainsi




#define strlen(n) strchr(n, '\0')-n

        C'est à dire chercher la fin de la string puis soustraire cette adresse finale à l'adresse de début pour obtenir par différence la taille de la chaîne.


La fonction strrchr est identique à la fonction strchr mais elle renvoie un pointeur sur la dernière occurence du caractère c de la chaîne s.


Exemple :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    char chaine[50] = "bonjour a tous et a toutes";
    char *p;
    char *p2;

    p = strchr( 't', chaine);

    p2 = strrchr( 't', chaine);

    printf( "%s\n", p );

    printf( "%s\n", p2 );

    return 0;
}


        donne la sortie :


tous et à toutes
toutes

        L'exemple suivant :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    char chaine[50] = "bonjour a tous et a toutes";
    char *p;
    char *p2;
    char *p3;

    p = strchr( 't', chaine);
    p2 = strrchr( 't', p);
    p3 = strrchr( 't', p2);

    printf( "%s\n", p );
    printf( "%s\n", p2 );
    printf( "%s\n", p3 );

    return 0;
}


        donnerait la sortie :


tous et a toutes
t a toutes
toutes

        Ce dernier exemple aurait pu être simplifié ainsi :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    char chaine[50] = "bonjour a tous et a toutes";
    char *p;
    char *p2;

    //p2 pointe sur le premier caractère de la chaîne
    p2 = chaine;

    //tant qu'il y'a une occurence du caractère...
    while ( (p = strchr( 't', p2)) != NULL)
    {
        printf( "%s\n", p );

        //sauvegarder le bout de string restant
        p2 = p;      
    }   
    return 0;
}



  Remarque
Comme on le voit dans ce dernier exemple, les fonctions strchr et strrchr renvoie la valeur NULL si aucune occurence du caractère n'est trouvée dans la chaîne de caractères.


strspn, strcspn, strpbrk : recherche par rapport à plusieurs caractères

        Les fonctions strspn, strcspn, strpbrk


size_t strspn(const char *suite, const char *chaine);
size_t strcspn(const char *suite, const char *chaine);
char * strpbrk(const char *suite, const char *chaine);


        recherchent les caractères contenu dans la string suite à l'intérieur de la string chaine.

La fonction strspn recherche la chaîne suite à l'intérieur de la chaîne chaine. Elle renvoie le nombre le plus grand de caractères trouvés se suivant qui correspondent à suite. Par exemple, l'instruction :


strspn("jouer", "bonjour");

        renverra la valeur 2 car deux lettres se suivent et correspondent dans les deux strings : "jo".
Autre exemple :


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void )
{
    printf( "%d\n", strspn( "out to lunch", "aeiou" ) );
    printf( "%d\n", strspn( "out to lunch", "xyz" ) );
    return 0;
}


        produit la sortie :


2
0


        car deux lettres de "aeiou" ont été trouvées dans "out to lunch" : "ou".
La seconde instruction renvoie 0 car aucune suite de lettre correspondante n'a été trouvée.

La fonction strcspn renvoie la longueur du du préfixe le plus long n'appartenant pas à la string suite.
L'exemple précédent avec cette fonction :


strcspn("jouer", "bonjour");

        renverrait la valeur 3. Car trois lettres se suivent et ne correspondent pas à la chaîne suite : "bon".
Autre exemple :


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( void )
{
    printf( "%d\n", strcspn( "abcbcadef", "cba" ) );
    printf( "%d\n", strcspn( "xxxbcadef", "cba" ) );
    printf( "%d\n", strcspn( "123456789", "cba" ) );
    
    return 0;
}



        produit la sortie :


0
3
9


        
Enfin, la fonction strpbrk est identique à la fonction strcspn mais elle renvoie un pointeur sur le premier caractère de la chaîne suite qui appartient aussi à la chaîne chaine.

Par exemple :


printf("%s\n", strpbrk("abcdefghijklm", "neon"));

        va renvoyer


efghijklm

        car le premier caractère de la chaîne "neon" se trouvant aussi dans la chaîne "abcdefghiklm" est le caractères 'e'.
Autre exemple :




#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
 * ce programme va chercher les voyelles
 * dans la phrases anglaise
 * "Find all vowels"
 */
int main( void )
{
    char* p = "Find all vowels";

    while( p != NULL ) {
      printf( "%s\n", p );
      p = strpbrk( p+1, "aeiouAEIOU" );
    }
    return 0;
}


        donne la sortie :


Find all vowels
ind all vowels
all vowels
owels
els


strtok : Découper une chaîne de caractères en lexèmes

        La fonction strtok


char * strtok(char *source, const char *s);

        permet de découper une chaîne en token ou élements, c'est à dire en sous-mots séparés par des caractères spéicfiés par le programmeur.



  • s

    s va contenir les caractères qui vont délimités tous les sous-mots de la chaîne source.




  • source

    source est la chaîne a diviser en lexèmes.





Les caractères de la chaine s sont considérés comme des séparateurs.

Pour bien comprendre le fonctionnement de strtok, il faut comprendre étape par étape ce qu'elle fait.

Au premier appel de strtok, les caractères de source se trouvant dans la chaîne de spéarateurs s sont ignorés (il s'agit là de séparateurs et non de lexèmes). Si tous les caractères de source sont des séparateurs, alors strtok renvoie un poniteur NULL.

Si plusieurs caractères de source se suivent et n'appartiennent pas à s alors cette suite de caractères est considérée comme un lexem. La fonction strtok lis alors ce lexem jusqu'à rencontrer un séparateur ou bien la fin de la chaîne. Dans ces deux cas le séparateur dans source est replacé par le le caractères de fin de string '\0 et '\0' est aussi ajouté à la fin du lexème. Ce dernier est alors renvoyé par la fonction.


Les appels suivants de la fonction strtok de la forme


strtok(NULL, s);

        continuerons la rehcerche là ou elle s'était arrétée dans la chaîne source au précédent appel à strtok.

Exemple :


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/**
 * programme qui va découper notre chaîne
 * en lexèmes
 */
int main( void )
{
    char* p;
    char* buffer;
    char* separateurs = { " .,!" };

    buffer = strdup( Trouve les mots... Tous les mots!" );

    //afficher la chaîne entière
    printf( "%s\n", buffer );

    //premier appel, renvoie le premier mot
    p = strtok( buffer, separateurs  );

    //pour tous les mots suivants :
    while( p != NULL ) 
    {
      //afficher le lexème
      printf( "lexeme : %s\n", p );
      //chercher le mot suivant
      p = strtok( NULL, separateurs  );
    }

    
    printf( "%s\n", buffer );
    return 0;
}





        produit la sortie :


Trouve les mots... Tous les mots!
lexeme:Trouve
lexeme:les
lexeme:mots
lexeme:Tous
lexeme:les
lexeme:mots
Trouve


[ Précédent | Index | Suivant ]



par Valentin BILLOTTE
vbillotte@programmationworld.com
http://www.programmationworld.com
Dernière mise à jour: