Scinde une chaîne avec des séparateurs en C
Comment puis-je écrire une fonction pour séparer et de retourner un tableau pour une chaîne de caractères avec des séparateurs dans le langage de programmation C?
char* str = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC";
str_split(str,',');
- Vous pouvez utiliser le
strtok
fonction de la bibliothèque standard pour obtenir la même chose. - stackoverflow.com/questions/8461170/...
- Un commentaire...le point clé pour une
strtok()
fonction de la famille est de comprendrestatic variables
en C. c'est à dire comment ils se comportent entre chaque appel de la fonction dans laquelle elles sont utilisées. Voir mon code ci-dessous
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser le
strtok()
fonction pour séparer une chaîne de caractères (spécifier le délimiteur à utiliser). Notez questrtok()
va modifier la chaîne de caractères passée en elle. Si la chaîne d'origine est requis ailleurs en faire une copie et de transmettre la copie destrtok()
.EDIT:
Exemple (notez qu'il ne traite pas des séparateurs identiques consécutifs, "JAN,,,FÉV,MAR", par exemple):
De sortie:
strtok
est marqué comme obsolète parstrsep(3)
dans la page de man.strsep
est un remplacement pourstrtok
, maisstrtok
est préféré pour des raisons de portabilité. Donc, sauf si vous avez besoin d'aide pour les champs vides ou de fractionnement de multiples cordes à la fois,strtok
est un meilleur choix.strtok_s()
(Microsoft, C11 Annexe K, en option) oustrtok_r()
(POSIX) que la plainestrtok()
. Plainestrtok()
est mal dans une fonction de la bibliothèque. Pas d'appel de fonction une fonction de la bibliothèque peut être à l'aide destrtok()
à l'époque, et pas de la fonction appelée par une fonction de la bibliothèque peut appelerstrtok()
.strsep
etstrtok
des pages de man. Et commeman strsep
dit, il n'est pas POSIX.strtok()
n'est pas thread-safe (pour les raisons @JonathanLeffler mentionné) et, par conséquent, l'ensemble de cette fonction n'est pas thread-safe. Si vous essayez de l'utiliser dans un filetée de l'environnement, vous aurez l'irrégularité et l'imprévisibilité des résultats. Remplacement destrtok()
pourstrtok_r()
résout ce problème.strsep()
fonction est conçu comme un remplacement pour lestrtok()
fonction. Alors que lestrtok()
fonction doit être préféré pour des raisons de portabilité (il est conforme à la norme ISO/IEC 9899:1990) il est incapable de gérer des champs vides, c'est à dire, de détecter les champs sont délimités par deux adjacentes séparateur de caractères, ou d'être utilisé pour plus qu'une seule chaîne à la fois. Lestrsep()
fonction première apparition en 4.4 BSD.Je pense que
strsep
est toujours le meilleur outil pour cela:Qui est littéralement une ligne qui divise une chaîne de caractères.
L'extra parenthèses sont un élément stylistique pour indiquer que nous sommes intentionnellement tester le résultat d'une affectation, pas un opérateur d'égalité
==
.Pour que le modèle fonctionne,
token
etstr
à la fois de typechar *
. Si vous avez commencé avec une chaîne littérale, alors vous voulez faire une copie de celui-ci d'abord:Si deux délimiteurs apparaissent ensemble dans
str
, vous obtiendrez untoken
valeur est la chaîne vide. La valeur destr
est modifié en ce sens que chaque séparateur rencontré est remplacé par un zéro octet - une autre bonne raison pour copier la chaîne pour être analysée en premier.Dans un commentaire, quelqu'un a suggéré que
strtok
est mieux questrsep
parce questrtok
est plus portable. Ubuntu et Mac OS X ont desstrsep
; il est sûr de deviner que d'autres unixy systèmes de faire aussi bien. Windows manque destrsep
, mais il astrbrk
qui permet de court et douxstrsep
de remplacement:Ici est une bonne explication de
strsep
vsstrtok
. Les avantages et les inconvénients peuvent être jugés subjectivement; cependant, je pense que c'est un signe révélateur questrsep
a été conçu comme un remplacement pourstrtok
.tofree
est le un gratuit d et ne passtr
?str
parce que sa valeur peut être modifiée par des appels àstrsep()
. La valeur detofree
constante de points au début de la mémoire que vous voulez gratuitement.Chaîne tokenizer ce code devrait vous mettre dans la bonne direction.
Méthode ci-dessous va faire tout le travail (allocation de mémoire, en comptant la longueur) pour vous. Plus d'informations et une description peut être trouvée ici - La mise en œuvre de Java Chaîne.méthode split() pour diviser chaîne C
Comment l'utiliser:
found 10 tokens. string #0: Hello, string #1: this string #2: is string #3: a string #4: test string #5: module string #6: for string #7: the string #8: string string #9: splitting.¢
Voici mes deux cents:
Utilisation:
Dans l'exemple ci-dessus, il y aurait un moyen de retourner un tableau de valeur null cordes (comme vous voulez) en place dans la chaîne. Cela ne ferait-il possible de passer une chaîne littérale même si, comme il aurait à être modifié par la fonction:
Il y a probablement un plus propre façon de le faire, mais vous obtenez l'idée.
Cette fonction prend un char* string et le divise par le séparateur. Il peut y avoir plusieurs deliminators dans une rangée. Notez que cette fonction modifie l'original de la chaîne. Vous devez faire une copie de l'original de la chaîne si vous avez besoin de l'original pour rester inchangée. Cette fonction ne pas utiliser toute la cstring appels de fonction de sorte qu'il pourrait être un peu plus vite que d'autres. Si vous n'avez pas de soins sur l'allocation de la mémoire, vous pouvez allouer sub_strings en haut de la fonction avec la taille strlen(src_str)/2 et (comme le c++ "version" mentionné), passez la moitié inférieure de la fonction. Si vous faites cela, la fonction est réduite à O(N), mais la mémoire optimisée de la manière indiquée ci-dessous est O(2N).
La fonction:
Comment l'utiliser:
Ci-dessous est mon
strtok()
mise en œuvre de la bibliothèque zString..zstring_strtok()
se distingue de la norme de la bibliothèquestrtok()
dans la façon dont elle traite des séparateurs identiques consécutifs.Il suffit de regarder le code ci-dessous,assurez-vous que vous aurez une idée de la façon dont il fonctionne (j'ai essayé d'utiliser autant de commentaires que j'ai pu)
Ci-dessous est un exemple d'utilisation...
La bibliothèque peut être téléchargé à partir de Github
https://github.com/fnoyanisi/zString
Essayer de l'utiliser.
Cette méthode optimisée de créer (ou de mise à jour de l'existant) tableau de pointeurs *résultat et renvoie le nombre d'éléments dans le *comte.
Utiliser "max" pour indiquer le nombre maximal de chaînes que vous attendez (lorsque vous spécifiez un groupe existant ou de tout autre reaseon), d'autre mis à 0
À comparer à une liste de séparateurs, de définir delim comme un char* et remplacer la ligne:
avec les deux lignes suivantes:
Profiter de
Exemple d'utilisation:
Je pense que la solution suivante est l'idéal:
Explication du code:
token
pour stocker l'adresse et les longueurs des jetonsstr
est entièrement composée de séparateurs il y a doncstrlen(str) + 1
jetons, toutes les cordes à vide
str
l'enregistrement de l'adresse et la longueur de chaque jetonNULL
sentinelle valeurde l'information - utiliser
memcpy
comme il est plus rapide questrcpy
et nous savonsles longueurs
Note
malloc
vérification omis par souci de concision.En général, je ne voudrais pas retourner un tableau de
char *
pointeurs à partir d'une fonction de répartition comme ça car il donne beaucoup de responsabilités sur les appelant à libérer correctement. Une interface que je préfère est de permettre à l'appelant de passer d'une fonction de rappel et d'appel pour chaque jeton, comme je l'ai décrit ici: Découper une Chaîne en C.token
.Ma version:
C'est une chaîne de fractionnement fonction qui permet de gérer le multi-caractères délimiteurs. Notez que si le délimiteur est plus longue que la chaîne est de split, puis
buffer
etstringLengths
sera mis à(void *) 0
, etnumStrings
sera mis à0
.Cet algorithme a été testé et fonctionne. (Avertissement: Il n'a pas été testé pour les non-ASCII cordes, et il suppose que l'appelant a donné des paramètres valides)
Exemple de code:
Bibliothèques:
buffer
et de laisser l'allocation de l'appelant, processus de max taille des éléments.Mon approche consiste à analyser la chaîne et de laisser les pointeurs point pour chaque personnage après la deliminators(et le premier caractère), dans le même temps, affecter les apparences de séparateur de chaîne '\0'.
Faites d'abord une copie de la chaîne d'origine(puisque c'est une constante), puis obtenir le nombre de divisions par le scanner, passer à de pointeur de paramètre len. Après cela, point de le premier pointeur de résultat de la copie pointeur de la chaîne, puis analyser la copie de la chaîne: une fois la rencontre d'un séparateur, l'affecter à '\0' donc le résultat précédent de la chaîne est terminée, et le point le résultat suivant pointeur de la chaîne à la prochaine pointeur de caractère.
Mon code (testé):
Résultat:
Exploser & imploser - chaîne initiale reste intacte, allocation dynamique de la mémoire
Utilisation:
Si vous êtes prêt à utiliser une bibliothèque externe, je ne peux pas le recommander
bstrlib
assez. Il prend un peu plus de l'installation, mais est plus facile à utiliser sur le long terme.Par exemple, diviser la chaîne ci-dessous, on crée d'abord un
bstring
avec lebfromcstr()
appel. (Unbstring
est un wrapper autour d'un char buffer).Ensuite, diviser la chaîne sur des virgules, et sauvegarde le résultat dans un
struct bstrList
, qui a des champsqty
et un tableauentry
, qui est un tableau debstring
s.bstrlib
a de nombreuses autres fonctions pour fonctionner surbstring
sSimple comme bonjour...
Encore une autre réponse (ce qui a été déplacé ici de ici):
Essayez d'utiliser la fonction strtok:
voir détails à ce sujet, ici ou ici
Le problème ici est que vous avez à traiter de la
words
immédiatement. Si vous souhaitez le stocker dans un tableau, vous devez allouer de lacorrect size
pour ce qui est inconnu.Ainsi, par exemple:
Note:
Nous utilisons la même boucle et la fonction pour calculer le nombre de pass) et pour faire des copies (pass deux), afin d'éviter les problèmes d'allocation.
Note 2:
Vous pouvez aussi utiliser un autre de mise en œuvre de la strtok les raisons de le mentionner dans certains postes.
Vous pouvez l'utiliser comme:
(Je n'ai pas tester, donc s'il vous plaît laissez-moi savoir si cela ne fonctionne pas!)
Deux questions autour de cette question sont la gestion de la mémoire et de la sécurité des threads. Comme vous pouvez le voir sur de nombreux postes,
ce n'est pas une tâche facile à accomplir de façon transparente en C. j'ai souhaité une solution qui est:
La solution je suis venu répond à tous ces critères. C'est probablement un peu plus de travail pour le programme d'installation
que certains autres solutions posté ici, mais je pense que, dans la pratique, le travail supplémentaire en vaut la peine
afin d'éviter les pièges courants d'autres solutions.
Ci-dessous est un exemple de compilation et de sortie. Notez que dans mon exemple, j'ai volontairement énoncé "AVRIL", de sorte que vous pouvez voir comment le soft erreur œuvres.
Profitez-en!