Split/explode d'une chaine de caractere en c

Soyez le premier à donner votre avis sur cette source.

Vue 39 856 fois - Téléchargée 493 fois

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

Ajouter un commentaire

Commentaires

Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
Il manque une mise à 0 avant le return final

while( *pos++ );
pos += sizeSeparator - 1;
}
currentSplit[sizeSplit] = 0; // Affectation manquante
return currentSplit;
}
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2
du code d'il y a 7 ans ? en C ? j'étais un aventurier.

Non testé ? je ne pense pas. Peut être pas tous les cas mais bon.

Quelles sont les données en entrées qui font planter ?
Messages postés
5
Date d'inscription
mercredi 18 juillet 2007
Statut
Membre
Dernière intervention
9 mars 2012

Bonjour,

Alors quand on met du code source on balance pas du code sans l'avoir testé avant "Hylvenir" >:-(

Au final ton code marche pas des segfault à la volé j'ai pas envie de debuguer

Le mec a peux être fait du code pas propre à cause de la dé-allocation abusive mais sa marche!
Messages postés
82
Date d'inscription
lundi 23 décembre 2002
Statut
Membre
Dernière intervention
23 août 2005

lol,ca t'a dit quelque les fonction pour manipuler les chaines en C?
Essaie man 3 strcmp dans google
Messages postés
102
Date d'inscription
dimanche 3 octobre 2004
Statut
Membre
Dernière intervention
8 septembre 2006

slt
J'essay d'utiliser ton code mais j'ai un petit souci.
Mon code :

char** tableau;
tableau = split("TESTE;rien",";",0);
if (tableau[0] == "TESTE")
{
printf("%s",tableau[0]);
} else {
printf("1er tableau n'est pas teste0");
}

Mon probleme est qu'il fait toujours le else, pourquoi ?
Afficher les 17 commentaires

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.