Besoin de savoir quand aucune donnée n’apparaît entre deux séparateurs de jetons à l’aide de strtok ()

J’essaie de marquer une chaîne mais j’ai besoin de savoir exactement quand aucune donnée n’est vue entre deux jetons. par exemple, lors de la création de la chaîne suivante ” a,b,c,,,d,e “, il me faut connaître les deux emplacements vides entre ” d ” et ” e ” … que je ne parviens pas à trouver simplement en utilisant strtok() . Ma tentative est montrée ci-dessous:

 char arr_fields[num_of_fields]; char delim[]=",\n"; char *tok; tok=strtok(line,delim);//line contains the data for(i=0;i<num_of_fields;i++,tok=strtok(NULL,delim)) { if(tok) sprintf(arr_fields[i], "%s", tok); else sprintf(arr_fields[i], "%s", "-"); } 

L’exécution du code ci-dessus avec les exemples susmentionnés place les caractères a, b, c, d, e dans les cinq premiers éléments de arr_fields ce qui n’est pas souhaitable. J’ai besoin que la position de chaque caractère entre dans des index spécifiques du tableau: c’est-à-dire que s’il manque un caractère entre deux caractères, il doit être enregistré tel quel.

7.21.5.8 la fonction strtok

La norme dit ce qui suit concernant strtok :

[# 3] Le premier appel de la séquence recherche dans la chaîne pointée par s1 le premier caractère non contenu dans la chaîne de séparation actuelle pointée par s2 . Si aucun caractère de ce type n’est trouvé, la chaîne pointée par s1 ne contient aucun jeton et la fonction strtok renvoie un pointeur nul. Si un tel caractère est trouvé, c’est le début du premier jeton.

Dans la citation ci-dessus, nous pouvons lire que vous ne pouvez pas utiliser strtok comme solution à votre problème spécifique, car tous les caractères séquentiels trouvés dans delims comme un seul jeton.


Suis-je condamné à pleurer en silence ou quelqu’un peut-il m’aider?

Vous pouvez facilement implémenter votre propre version de strtok qui fait ce que vous voulez, voir les extraits à la fin de ce post.

strtok_single utilise strpbrk (char const* src, const char* delims) qui renverra un pointeur sur la première occurrence de tout caractère dans delims qui se trouve dans la chaîne src terminée par un zéro .

Si aucun caractère correspondant n’est trouvé, la fonction retournera NULL.


strtok_single

 char * strtok_single (char * str, char const * delims) { static char * src = NULL; char * p, * ret = 0; if (str != NULL) src = str; if (src == NULL) return NULL; if ((p = strpbrk (src, delims)) != NULL) { *p = 0; ret = src; src = ++p; } else if (*src) { ret = src; src = NULL; } return ret; } 

exemple d’utilisation

  char delims[] = ","; char data [] = "foo,bar,,baz,biz"; char * p = strtok_single (data, delims); while (p) { printf ("%s\n", *p ? p : ""); p = strtok_single (NULL, delims); } 

sortie

 foo bar  baz biz 

Vous ne pouvez pas utiliser strtok() si c’est ce que vous voulez. De la page de manuel:

Une séquence de deux ou plusieurs caractères de délimitation contigus dans la chaîne analysée est considérée comme un simple délimiteur. Les délimiteurs au début ou à la fin de la chaîne sont ignorés. En d’autres termes: les jetons renvoyés par strtok () sont toujours des chaînes non vides.

Par conséquent, il va simplement passer de c à d dans votre exemple.

Vous devrez parsingr la chaîne manuellement ou peut-être rechercher une bibliothèque d’parsing CSV qui vous faciliterait la vie.

Dernièrement, je cherchais une solution au même problème et trouvais ce fil.

Vous pouvez utiliser strsep() . Du manuel:

La fonction strsep () a été introduite pour remplacer strtok (3), cette dernière ne pouvant pas gérer les champs vides.

Comme mentionné dans cette réponse , vous souhaiterez implémenter vous-même quelque chose comme strtok . Je préfère utiliser strcspn (par opposition à strpbrk ), car cela permet d’avoir moins d’instructions if :

 char arr_fields[num_of_fields]; char delim[]=",\n"; char *tok; int current_token= 0; int token_length; for (i = 0; i < num_of_fields; i++, token_length = strcspn(line + current_token,delim)) { if(token_length) sprintf(arr_fields[i], "%.*s", token_length, line + current_token); else sprintf(arr_fields[i], "%s", "-"); current_token += token_length; } 
  1. Parse (par exemple, strtok)
  2. Trier
  3. Insérer
  4. Rincer et répéter au besoin 🙂

Vous pouvez essayer d’utiliser strchr pour trouver l’emplacement des symboles. Tokenize manuellement votre chaîne jusqu’au jeton que vous avez trouvé (en utilisant memcpy ou strncpy ), puis utilisez à nouveau strchr. Vous pourrez ainsi voir si deux ou plusieurs virgules sont côte à côte de cette façon (strchr renverra des nombres dont la soustraction sera égale à 1) et vous pourrez écrire une instruction if pour gérer ce cas.