Split/explode d'une chaine de caractere en c

Description

Suite à la question que j'ai posé sur le forum, j'ai fait une petite
fonction qui découpe une chaine suivant un délimiteur.
La fonction permet de choisir si on accpete ou non les mots vides.
Elle retourne un tableau de chaines de caractères, terminé par NULL.

Le code est compilé sous windows avec gcc donc la fonction doit être portable sous linux/unix.
(quoique que j'ai des doutes sur system("pause") )

Source / Exemple :


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

// Retour tableau des chaines recupérer. Terminé par NULL.
// chaine : chaine à splitter
// delim : delimiteur qui sert à la decoupe
// vide : 0 : on n'accepte pas les chaines vides
//        1 : on accepte les chaines vides
char** split(char* chaine,const char* delim,int vide){
    
    char** tab=NULL;                    //tableau de chaine, tableau resultat
    char *ptr;                     //pointeur sur une partie de
    int sizeStr;                   //taille de la chaine à recupérer
    int sizeTab=0;                 //taille du tableau de chaine
    char* largestring;             //chaine à traiter
    
    int sizeDelim=strlen(delim);   //taille du delimiteur

    largestring = chaine;          //comme ca on ne modifie pas le pointeur d'origine
                                   //(faut ke je verifie si c bien nécessaire)
    

    while( (ptr=strstr(largestring, delim))!=NULL ){
           sizeStr=ptr-largestring;
     
           //si la chaine trouvé n'est pas vide ou si on accepte les chaine vide                   
           if(vide==1 || sizeStr!=0){
               //on alloue une case en plus au tableau de chaines
               sizeTab++;
               tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
                              
               //on alloue la chaine du tableau
               tab[sizeTab-1]=(char*) malloc( sizeof(char)*(sizeStr+1) );
               strncpy(tab[sizeTab-1],largestring,sizeStr);
               tab[sizeTab-1][sizeStr]='\0';
           }
           
           //on decale le pointeur largestring  pour continuer la boucle apres le premier elément traiter
           ptr=ptr+sizeDelim;
           largestring=ptr;
    }
    
    //si la chaine n'est pas vide, on recupere le dernier "morceau"
    if(strlen(largestring)!=0){
           sizeStr=strlen(largestring);
           sizeTab++;
           tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
           tab[sizeTab-1]=(char*) malloc( sizeof(char)*(sizeStr+1) );
           strncpy(tab[sizeTab-1],largestring,sizeStr);
           tab[sizeTab-1][sizeStr]='\0';
    }
    else if(vide==1){ //si on fini sur un delimiteur et si on accepte les mots vides,on ajoute un mot vide
           sizeTab++;
           tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
           tab[sizeTab-1]=(char*) malloc( sizeof(char)*1 );
           tab[sizeTab-1][0]='\0';
           
    }
    
    //on ajoute une case à null pour finir le tableau
    sizeTab++;
    tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
    tab[sizeTab-1]=NULL;

    return tab;
}

int main(){
    int i;
    int ret;
    char* str="foo|bar||baz|bar|";
    char** tab;
    
    printf("Chaine initiale : %s \n",str);
    
    tab=split(str,"|",0);
    //affichage du resultat
    for(i=0;tab[i]!=NULL;i++) {
       printf("%d : %s\n",i,tab[i]);
       //au passge je désalloue les chaines
       free(tab[i]);
    }
    free(tab);
    
    printf("\n");
    
    tab=split(str,"|",1);
    //affichage du resultat
    for(i=0;tab[i]!=NULL;i++) {
       printf("%d : %s\n",i,tab[i]);
       //au passge je désalloue les chaines
       free(tab[i]);
    }
    free(tab);
    
    system("pause");

}

Conclusion :


Le tableau est alloué dynamiquement => n'oubliez pas de désallouer.

Merci à buno et steve_clamage pour leur info sur le forum.

Puis si vous trouver des bug ou si vous voulez noter, un chtit commentaire.

Voila a quoi ressemble la sortie :
chaine init : foo|bar||baz|bar|
0 : foo
1 : bar
2 : baz
3 : bar

0 : foo
1 : bar
2 :
3 : baz
4 : bar
5 :
Appuyez sur une touche pour continuer...

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.