begin process at 2010 02 10 00:27:00
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Chaîne de caractères

 > TABLEAUX DE CHAINES DE CARACTÈRE: FONCTIONS IMPLODE, EXPLODE ET COUNT

TABLEAUX DE CHAINES DE CARACTÈRE: FONCTIONS IMPLODE, EXPLODE ET COUNT


 Information sur la source

Note :
9 / 10 - par 2 personnes
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Chaîne de caractères Classé sous :implode, explode, chaines, tableaux, count Niveau :Débutant Date de création :09/08/2007 Date de mise à jour :14/08/2007 02:54:29 Vu :10 383

Auteur : guill76

Ecrire un message privé
Commentaire sur cette source (12)
Ajouter un commentaire et/ou une note

 Description

Voici quelques fonctions utiles pour la gestion des tableaux de chaines de caractères (comme les fonctions de PHP).

explode :
        scinde une chaine à partir de son délimiteur et retourne 1 tableau de chaines découpées.version php
        
implode :
        fait l'inverse d'explode et fusionne les chaines d'un tableau en une seule chaine.
        =>le paramétre optionnel n permet la fusion des n 1ers elts du tableau.

count :
        retourne le nombre d'élements d'un tableau de chaines.

int countfields(char delim,char token,char* src):
retour du nombre de champs avec token d'une chaine à spliter

***AUTRE VERSION d'Explode que j'ai un peu plus optimisée:***

int fieldsExplode(char delim,char token,char * src, char** dest)
=>Fonction ajoutée : Gére les champs entourés par guillemets , quotes ou caractere au choix)

Source

  • #include <iostream>
  • using namespace std;
  • int count(char** tabsrc)
  • {
  • int i=0;
  • while (tabsrc[i]!=NULL){i++;}
  • return i;
  • }
  • char** explode( const char delim, char* src)
  • {
  • char* start = src;
  • char* ptr = src;
  • char** tab;
  • int i = 0, pos = 0, len = 0;
  • int items = 0;
  • //items :calcul nombre d'elements du tableau (nb delimiteurs)
  • while ( *src ) { if ( *src == delim ){ items++; } src++; }
  • //si aucun déilimiteurs pas la peine de se fatiguer
  • if ( !items ) return NULL;
  • //nombre element= nombre de caractere delim + 1
  • items++;
  • //réinit du pointeur src
  • src = start;
  • //allocation memoire du tableau
  • tab = new char* [items] ;
  • //parcours de la chaine à spliter
  • while ( *ptr && i < items )
  • {
  • if ( *src == delim || *src == 0 )
  • {
  • len = 0;
  • ptr = start;
  • while ( ptr < src ){ len++; ptr++; }
  • tab[i] = new char [len+1];
  • pos = 0;
  • while ( start < ptr ){ tab[i][pos] = *start; start++; pos++; }
  • tab[i][pos] = 0;
  • start = ptr + 1;
  • i++;
  • }
  • src++;
  • }
  • //fin du tableau
  • tab[i]=NULL;
  • return tab;
  • }
  • char * implode(const char delim, char** tabstring, int n=0)
  • {
  • int i = 0,size = 0, max = count(tabstring);
  • char * tmp,*ptr,*start;
  • if (n <= 0 || n > max)
  • n = max;
  • // calcul de la taille de la chaine (size) à allouer
  • while (i < n)
  • {
  • ptr = tabstring[i];
  • while (*ptr)
  • {
  • ptr++;
  • size++;
  • }
  • i++;
  • }
  • // Allocation de la mémoire nécessaire à la chaine à fusionner
  • tmp = new char[size+1];
  • start = tmp;
  • i = 0;
  • //fusion
  • while (i < n)
  • {
  • ptr=tabstring[i];
  • while (*ptr)
  • {
  • *tmp = *ptr;
  • ptr++;
  • tmp++;
  • }
  • if (i < n-1)
  • *tmp = delim;
  • else *tmp = 0;
  • tmp++;
  • i++;
  • }
  • //retour de la chaine fusionnée
  • return start;
  • }
  • int countfields(char delim,char token,char* src)
  • {
  • int i=0,cntL=0;
  • while (*src)
  • {
  • if (*src==delim)
  • {
  • if ( cntL%2!=1 )
  • {
  • i++;
  • }
  • }
  • if (*src==token)
  • cntL++;
  • src++;
  • }
  • return i+1;
  • }
  • int maxFieldSize(char delim,char token,char* src)
  • {
  • int i=0,a=0,max=0,cntL=0;
  • while (*src)
  • {
  • if (*src==delim)
  • {
  • if ( cntL%2!=1 )
  • {
  • i++;
  • if (a>max)
  • max=a;
  • a=0;
  • }
  • }
  • if (*src==token)
  • cntL++;
  • src++;
  • a++;
  • }
  • return max;
  • }
  • //la meilleure version d'explode
  • int fieldsExplode(char delim,char token,char * src, char** dest)
  • {
  • char* ptr;
  • int i=0,cntL=0;//,cntR;
  • ptr=dest[0];
  • while (*src)
  • {
  • if (*src!=delim)
  • {
  • if (*src==token) cntL++;
  • *ptr=*src;
  • ptr++; src++;
  • if (!*src) *ptr=0;
  • }
  • else
  • {
  • //si impaire à gauche on continue
  • if ( cntL%2==1 )
  • {
  • *ptr=*src;
  • ptr++;
  • }
  • else
  • {
  • *ptr=0;
  • i++;
  • ptr=dest[i];
  • }
  • src++;
  • }
  • }
  • dest[i+1]=NULL;
  • return i+1;
  • }
  • // pour tester
  • int main ()
  • {
  • int items=0;
  • char** explodeTest=explode(';',"voici;;un;test;d;explode");
  • items=count(explodeTest);
  • for (int i=0;i<items;i++)
  • cout<<"Item "<<i<<": "<<explodeTest[i]<<endl;
  • cout <<"Count():"<<items<<endl;
  • char* implodeTest=implode(';',explodeTest);
  • cout<<"IMPLODE: "<<implodeTest<<endl;
  • return 0;
  • }
  • //exemple avec le nouvel explode
  • int main ()
  • {
  • char** tableau;
  • char chaine[200];
  • int len;
  • strcpy(chaine,"test;'1;2;3';;explode;;'token';2;test");
  • tableau=new char* [countfields(';','\'',chaine)];
  • for(int i=0 ; i<10;i++)
  • tableau[i]=new char[maxFieldSize(';','\'',chaine)+1];
  • len=fieldsExplode(';','\'',chaine,tableau);
  • for(int i=0 ; i<len;i++)
  • cout<<tableau[i]<<endl;
  • }
#include <iostream>
using namespace std;

int count(char** tabsrc)
{
    int i=0;
    while (tabsrc[i]!=NULL){i++;}
    return i;
}

char** explode( const char delim, char* src)
{
    char* start = src;
    char* ptr = src;
    char** tab;
    int i = 0, pos = 0, len = 0;
    int items = 0;
    
    //items :calcul nombre d'elements du tableau (nb delimiteurs)
    while ( *src ) { if ( *src == delim ){ items++; } src++; }
    
    //si aucun déilimiteurs pas la peine de se fatiguer
    if ( !items ) return NULL;

    //nombre element= nombre de caractere delim + 1
    items++;

    //réinit du pointeur src
    src = start;

    //allocation memoire du tableau
    tab = new char* [items] ;

    //parcours de la chaine à spliter
    while ( *ptr && i < items )
    {
        if ( *src == delim || *src == 0 )
        {
            len = 0;
            ptr = start;
            while ( ptr < src ){ len++; ptr++; }
            tab[i] = new char [len+1];
            pos = 0;
            while ( start < ptr ){ tab[i][pos] = *start; start++; pos++; }
            tab[i][pos] = 0;
            start = ptr + 1;
            i++;
        }
        src++;
    }
    //fin du tableau
    tab[i]=NULL;
    return tab;
}

char * implode(const char delim, char** tabstring, int n=0)
{
    int i = 0,size = 0, max = count(tabstring);

    char * tmp,*ptr,*start;

    if (n <= 0 || n > max)
        n = max;
    
    // calcul de la taille de la chaine (size) à allouer
    while (i < n)
    {
        ptr = tabstring[i];
        while (*ptr)
        {
            ptr++;
            size++;
        }
        i++;
    }

    // Allocation de la mémoire nécessaire à la chaine à fusionner
    tmp = new char[size+1];
    start = tmp;
    i = 0;

    //fusion
    while (i < n)
    {
       ptr=tabstring[i];
        while (*ptr)
        {
            *tmp = *ptr;
            ptr++;
            tmp++;
        }
        if (i < n-1)
            *tmp = delim;
        else *tmp = 0;
        tmp++;
        i++;
    }
    //retour de la chaine fusionnée
    return start;
}

int countfields(char delim,char token,char* src)
{
    int i=0,cntL=0;
    while (*src)
    {
        if (*src==delim)
        { 
            if ( cntL%2!=1 )
            {
                i++;
            }
        }
        if (*src==token)
            cntL++;
        src++;
    }
    return i+1;
}

int maxFieldSize(char delim,char token,char* src)
{
    int i=0,a=0,max=0,cntL=0;
    while (*src)
    {
        if (*src==delim)
        { 
            if ( cntL%2!=1 )
            {
                i++;
                if (a>max)
                    max=a;
                a=0;
            }
        }
        if (*src==token)
            cntL++;
        src++;
        a++;
    }
    return max;
}

//la meilleure version d'explode

int fieldsExplode(char delim,char token,char * src, char** dest)
{
    char* ptr;
    int i=0,cntL=0;//,cntR;
    ptr=dest[0];

    while (*src)
    {
        if (*src!=delim)
        {
            if (*src==token) cntL++;
            *ptr=*src;
            ptr++; src++;
            if (!*src) *ptr=0;
        }
        else
        {
            //si impaire à gauche on continue
            if ( cntL%2==1 )
            {
                *ptr=*src;
                ptr++;
            }
            else
            {
                *ptr=0;
                i++;
                ptr=dest[i];
            }
            src++;
        }
    }
    dest[i+1]=NULL;
    return i+1;
}
// pour tester

int main ()
{
    int items=0;
    char** explodeTest=explode(';',"voici;;un;test;d;explode");

    items=count(explodeTest);
    for (int i=0;i<items;i++)
    cout<<"Item "<<i<<": "<<explodeTest[i]<<endl;

    cout <<"Count():"<<items<<endl;

    char* implodeTest=implode(';',explodeTest);
    cout<<"IMPLODE: "<<implodeTest<<endl;
    
    return 0;
}
//exemple avec le nouvel explode
int main ()
{
    char** tableau;
    char chaine[200];
    int len;
    
    strcpy(chaine,"test;'1;2;3';;explode;;'token';2;test");
    tableau=new char* [countfields(';','\'',chaine)];
    
    for(int i=0 ; i<10;i++)
    tableau[i]=new char[maxFieldSize(';','\'',chaine)+1];
    
    len=fieldsExplode(';','\'',chaine,tableau);
    
    for(int i=0 ; i<len;i++)
    cout<<tableau[i]<<endl;

}

 Conclusion

Voilà j'ai vu plusieurs fonctions dans ce style pour le split/explode sur ce site,
celle là est un peu différente. Mais sauf erreur de ma part, je n'ai rien vu sur implode ou join.
  


 Historique

10 août 2007 00:11:41 :
bug corrigé
14 août 2007 02:11:05 :
nouvel explode beaucoup plus optimisé encore, je laisse quand même l'ancien pour comparer.
14 août 2007 02:54:30 :
'"' par '\'' dans appel à countfields(';','\'',chaine)

 Sources du même auteur

Source avec une capture MAP STL ET ARBRES ROUGES ET NOIRS

 Sources de la même categorie

Source avec Zip RECHERCHE D'ANNAGRAMMES par Torin
GESTION DE CHAINE DE CARACTÉRE EN C++ AVEC NSTRING par xmustapha
Source avec Zip COMMENTER CODE C <=> ASM (WIN64) par BruNews
Source avec Zip GSTRING - GESTION DES CHAINES DE CARACTÈRES par Neokript
Source avec Zip ANALYSEUR SYNTAXIQUEV(0.1) par kohan95

 Sources en rapport avec celle ci

SIMPLE FONCTION TOKENIZE par spidermario
Source avec Zip PARSEUR GÉNÉRAL par mehdicherti
Source avec Zip Source avec une capture OPÉRATIONS SUR LES MATRICES (TABLEAU À DEUX DIMENSIONS) par shnaykhs
Source avec Zip TOTAL MEMO C++ VERTION 1.06 par FeelCode
Source avec Zip SPLIT/EXPLODE D'UNE CHAINE DE CARACTERE EN C par goth

Commentaires et avis

Commentaire de BruNews le 09/08/2007 23:06:41 administrateur CS

Je n'ai jamais eu l'emploi de explode() ou implode().
A quoi peuvent-elles te servir ?

Commentaire de guill76 le 09/08/2007 23:28:11

L'utilité me parait réélle quand on les a utilisées dans d'autres languages comme php. Implode peut-être utilisée pour formater un fichier de sortie comme un .ini ou un .csv par exemple, et explode pour le lire, mais pour pas mal d'autre choses.

Commentaire de BruNews le 09/08/2007 23:37:03 administrateur CS

Ben non, c'est bien là que je veux en venir. En natif, il faut se laver le cerveau du fatras qu'apporte l'usage des interprétés. Quand on les a utilisées, on se dépêche de les oublier.
Je t'assure que jamais employé de bidules de ce genre et je ne suis malheureusement plus en début de carrière.

Commentaire de RaphAstronome le 13/08/2007 00:52:19

Même si on n'en met pas dans tout les programmes je trouve que "explode" est très pratique (par contre implode nettement moins).

Commentaire de Lucky92 le 13/08/2007 04:03:34

Salut,

J'ai une question.
C'est le deuxième sujet sur les chaînes de caractères en c/c++, qui tombe en 15 jours - l'autre sujet traitait des fonctions de type trim() ; et dans les deux cas, on a l'impression que les strings de la librairie standard du c++ ont mauvaise haleine !
D'où ma question, écris-tu des routines en C presque pur :
a - pour optimiser la vitesse et/ou la mémoire de tes applications ?
b - pour des raisons scolaires ( exercices, devoirs à la maison, ... ) ?
c - parce que tu n'aimes pas le c++ et ce qu'il est devenu avec l'avènement de la STL ?

PS : Ces deux fonctions existent également dans le langage perl sous les doux noms de join() et split(). Si elles existent, c'est qu'elles doivent bien servir à quelque chose ! Mais, même si elles ne servent à rien ni à personne, j'aime bien les sources un peu académiques...

Commentaire de BruNews le 13/08/2007 09:42:34 administrateur CS

Lucky92, sors le listing asm du compilo d'un exemple avec std:string et compare avec 2 pointeurs sur un buffer, tu auras la réponse.

Commentaire de RaphAstronome le 13/08/2007 12:01:33

La classe string est plus lente mais est plus pratique car tu as pas à te soucier de la gestion de la mémoire, ce qui veux dire aussi que tu est en partie protégé des dépassements de buffer.

Commentaire de guill76 le 14/08/2007 02:33:19

je viens de metre à jour et d'optimiser un nouvel explode qui je pense est plus rapide que le précédent, je me suis un peu inspiré d'un autre code de brunews et j'ai rajouté la vraie gestion des champs csv avec la gestion des token.
l'allocation se fait dans le main: ce qui est + "conventionnel"

Commentaire de Lucky92 le 14/08/2007 10:36:57

Le délimiteur de ta fonction explode se limite à un seul caractère. Que penses-tu d'étendre celui-ci à une chaîne de caractères, voire à une expression régulière comme en perl ?

Commentaire de jacqhal le 23/02/2008 07:35:52

par contre quelques traitements d'erreur serait certanement bien venu en cas de dépassement de memoire ..

par ex : voici ce que j'ai fait en reprenant une partie de ce que tu avais fait..

int Explode(char* Txt, char**& return_value, char Separator /*= ';'*/)
{
if (Separator == '\0')
throw "Delimiter null";

int NumRows = 0;
char *Car = Txt;

// Calcul de la taille
while (Car != NULL) {
Car = strchr(++Car, Separator);
if (Car != NULL) { NumRows++; }
}

if (!NumRows) return 0; // Si pas de chaine a scindé , on sort.

NumRows++; //pour avoir le dernier "Mot" qui n'as pas de ';' en fin (en theorie)

Car = Txt; //Reinitialisation du pointeur

int lenWord = 0;
char *CarPtr = &(Txt[0]);
int i = 0;
int NumCar = 0;
  int lenChar = strlen(&Separator); // toujours 1 mais au cas ou Separator != > char.

try {
return_value = new char * [NumRows];   //Allocation

// parcours a la recherche des chaines
while(i<NumRows) {
lenWord++;
if ((*Car == Separator) || (*Car==0)) {
return_value[i] = new char[lenWord];
strncpy(return_value[i], CarPtr, lenWord-lenChar);
CarPtr = &Txt[NumCar+lenChar];
lenWord = 0; //reinitialisation de la longueur de chaine
i++; //Element suivant dans le tableau
}
Car++; NumCar++;
};

} catch (...) {
delete [] return_value;
return 0;
}
return NumRows; // Renvoie du nombre de ligne;
}

Commentaire de ranzia le 19/12/2008 10:57:34 8/10

Merci pour ce source très utile.
Voici une autre version de la fonction implode() où le délimiteur est une chaine au lieu d'un char.

/**
* Rassemble les elements d'un tableau en une chaine en les concatenant avec le separateur
* @param strarr tableau de chaine
* @param separator separateur (peut etre une chaine vide)
* @return chaine concatenee ou NULL en cas d'erreur
*/

char * implode(const char **strarr, const char *separator)
{
    char *res;
    int taille_strarr,taille_sep;
    int i;
    const char *sep;
    
    if(strarr!=NULL && strarr[0]!=NULL)
    {
        taille_strarr = sizeof(strarr);
        res = (char *)malloc((strlen(strarr[0])+1)*sizeof(char));
        sprintf(res,"%s",strarr[0]);
        if(separator==NULL)
            sep = "";
        else
            sep = separator;
        taille_sep = strlen(sep);
        for(i=1;i<taille_strarr;i++)
        {
            res = (char *)realloc(res,(strlen(res)+taille_sep+strlen(strarr[i])+1)*sizeof(char));
            sprintf(res,"%s%s%s",res,separator,strarr[i]);
        }
        return res;
    }
    return NULL;
}

Commentaire de BruNews le 19/12/2008 11:29:43 administrateur CS

if(strarr!=NULL && strarr[0]!=NULL)
Si strarr vaut 0, c'est badaboum garanti d'essayer de lire strarr[0].

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Comment faire des tableaux de chaines de caractères ? [ par ProGamer ] Je veux faire des tableaux de chaines de caractères I want to make arrays of strings, mais en utilisant seulement le type de base, char.J'ai essayé ce Comment faire des tableaux de chaines de caractères ? [ par ProGamer ] Je veux faire des tableaux de chaines de caractères I want to make arrays of strings, mais en utilisant seulement le type de base, char.J'ai essayé ce Pointeurs sur des tableaux de plusieurs dimensions [ par ProGamer ] J'ai besoin de faire des pointeurs sur ce genre de tableaux. Voici comment je m'y prends (et surtout, voici comment ça ne marche pas...):unsigned char je suis perdu avec les tableaux !! [ par djamine ] bonjour les programmeurs je suis débutant en C j'aimerais saisir les ages de 40 éleves d'un classe du mon lycée ( ils ont au moins 14 ans et au plus 2 transfer de valeur de tableaux à tableaux [ par cabarrus ] soient 2 tbleaux t1 et t2 déclaré ainsi:float t1[10],t2[10];mon prog doit écrire les instructions permettant de recopier ds t1 tous les éléments posit LES TABLEAUX UNIDIMENSIONNELS. [ par SniPi ] Voilà tout d'abord bonjour à tous, je viens de m'inscrire sur ce site et c'est ma première apparition ( mais pas la dernère).En fait j'ai un problème Pb tableaux langage C (Borland) [ par SniPi ] Comment on fait pr faire un tableau avec 10 valeurs, mais que les 10 valeurs ce soit l'utilisateur qui les rentre...??Amicalement...SniPi De gros Tableaux [ par Malkavien ] Voila, j'ai besoin de créer un tableau de 640*480 éléments (un écran koi)mais voila, il me dit ke l'array est trop grand...alors comment faire pour dé AIDEZZZZZZ MOIIIII SVP SUR TABELAU JAI UN GROS PB!!! [ par retaks666 ] alors jiamerais faire une fonction ki decale les éléments d'u ntableau de une case, je suis en vcpp++6 et sous windows, voici la source: void CMultiGa Pb de tri et taille de tableaux [ par daarkon666 ] Salut !!Je viens de terminer le tri/fusion itératif (et d'autres algos de tri, pr un projet info de fac) en C, et je suis soumis à un pb auss ibien so


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,655 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales