string vers char* - C++ - Programmation
Marsh Posté le 04-02-2009 à 18:58:00
pr le premier, t'as le droit d'utiliser boost::tokenizer au lieu de cet antediluvien strtok.
Pour le deuxieme, std::ostringstream/istringstream
Marsh Posté le 04-02-2009 à 19:00:35
Joel F a écrit : Pour le deuxieme, std::ostringstream/istringstream |
Tant qu'à faire, boost::lexical_cast
Marsh Posté le 04-02-2009 à 19:15:46
il parle de lire un fichier donc je suppose que celui ci est +/- formaté.
Mais sinon oui lexical_cast, son defaut etant une propension à lancer des exceptions pas forcement triviales en terme de sens.
Marsh Posté le 04-02-2009 à 20:05:01
xphanoo a écrit :
|
c_str() retourne un const char*. Et il est bien indiqué dans la documentation que la chaîne retournée utilise un espace alloué en interne et qu'elle ne devrait pas être modifiée.
Or, la documentation de strtok() indique que la chaîne passée en paramètre va être modifiée par strtok() (il est d'ailleurs conseillé de travailler avec une copie de la chaîne justement à cause de ça).
Bref, tes questions sont répondues par la documentation adéquate sur ces deux fonctions, il suffisait de les lire.
Du coup, si comme chez moi tu n'as pas accès à boost (), le plus simple est de créer ton propre "tokenizer", ce n'est pas très compliqué à faire, et tu n'as qu'à retourner le résultat dans un list<string>.
Et l'avantage c'est que tu pourras dégager ce #include <string.h> de ton code
Et si vraiment vraiment tu veux utiliser strtok() (là, t'insistes vraiment beaucoup vu la kyrielle de meilleures solutions proposées jusqu'ici), tu peux écrire :
char * buffer = new char[chaine.length() + 1];
strcpy(buffer, chaine.c_str());
<ton code avec strtok()>
delete[] buffer;
Mais bon. Faut vraiment aimer strtok(), là. J'ai toujours trouvé que c'était la plus laide des fonctions C disponibles.
Marsh Posté le 04-02-2009 à 20:11:41
en plus elle est pas reentrante
donc strtok_r dans du vrai code
Marsh Posté le 04-02-2009 à 21:01:56
Elmoricq a écrit : Et si vraiment vraiment tu veux utiliser strtok() (là, t'insistes vraiment beaucoup vu la kyrielle de meilleures solutions proposées jusqu'ici), tu peux écrire : |
Code :
|
Citation : Mais bon. Faut vraiment aimer strtok(), là. J'ai toujours trouvé que c'était la plus laide des fonctions C disponibles. |
C'est peut-être la plus laide, mais c'est pas la plus piègeuse; personne ne s'imagine pouvoir l'utiliser sans relire la doc!
Dans le genre piègeux, les isXXX auxquelles on ne peut pas passer un char, c'est pas mal; et le couple strncat/strncpy aux paramètres inconstistants et inintuitifs est aussi bien placé.
Marsh Posté le 04-02-2009 à 21:34:56
wow merci pour vos réponses !!
j'ai pas utilisé boost car flemme d'installer la lib, mais bon si c'est vraiment mieux je prendrais un peu de temps pour le faire.
pour la conversion char=> int j'ai trouvé sur le net la fonction atoi(). je connaissais pas mais ça marche!!
Marsh Posté le 04-02-2009 à 22:08:37
Un Programmeur a écrit : |
Très laide mais clairement pas la plus piégeuse, je suis d'accord.
Pour moi, strncpy() tient effectivement le haut du pavé avec son absence de '\0' en cas de chaîne tronquée.
Marsh Posté le 04-02-2009 à 22:12:24
Joel F a écrit : atoi |
mais pourquoi les fonctions que j'utilise sont toujours les plus détestées
pourtant y'a pas plus simple
Marsh Posté le 04-02-2009 à 22:17:01
xphanoo a écrit : mais pourquoi les fonctions que j'utilise sont toujours les plus détestées pourtant y'a pas plus simple |
Tu sembles avoir un souci avec la documentation on dirait.
Citation : The atoi() function converts the initial portion of the string pointed to by nptr to int. The behaviour is the same as strtol(nptr, (char **)NULL, 10); except that atoi() does not detect errors. IMPLEMENTATION NOTES The atoi() function is not thread-safe and also not async-cancel safe. The atoi() function has been deprecated by strtol() and should not be |
Marsh Posté le 05-02-2009 à 08:24:57
Elmoricq a écrit : Pour moi, strncpy() tient effectivement le haut du pavé avec son absence de '\0' en cas de chaîne tronquée. |
Il y a aussi gets()...
Marsh Posté le 05-02-2009 à 09:12:40
Moi ce qui m'embete c'est :
Citation : |
Marsh Posté le 05-02-2009 à 09:53:42
ReplyMarsh Posté le 05-02-2009 à 11:28:40
Elmoricq a écrit :
|
hm certes mais vu que je suis sur des données que je lui envoie, pas de raison qu'il y ait d'erreur
enfin je sais qu'en cours on mets partout des systèmes pour détecter les erreurs, ça prend facilement la moitié du code, mais il me semble que là où la détection d'erreur est importante c'est sur les actions/saisies de l'utilisateur...
Marsh Posté le 05-02-2009 à 14:00:49
la gestion d'erreur est necessaire là ou le recouvrement d'un etat correct est complexe.
Marsh Posté le 07-02-2009 à 22:03:11
Elmoricq a écrit : Pour moi, strncpy() tient effectivement le haut du pavé avec son absence de '\0' en cas de chaîne tronquée. |
je vote aussi strtok, même si gets a la particularité de ne pas pouvoir être sûre quelque soit son contexte d'utilisation. strtok on peut toujours l'utiliser sur une copie de la chaine.
strncpy elle fonctionne bien, c'est juste qu'elle ne sert pas à copier une chaine vers une autre, mais une chaine vers un buffer de taille fixe (du moins connu à l'avance).
Dans un contexte old-school, on est en 1983, tu veux remplir un nom de client dans le buffer de taille fixe de ton super soft de compta sur VAX, ton buffer il fait 16 caractères, et bien un strncpy( buffer, src, 16) ça fait exactement ce que tu veux. Cette fonction a un sens, elle est juste mal nommée.
Maintenant pour copier de chaine à chaine, en effet cette fonction est mauvaise. Elle n'est ni sûre (pas de '\0') ni performante (remplissage de 0 à la fin s'il reste de la place, utile pour un buffer mais pas pour une chaine).
Marsh Posté le 08-02-2009 à 17:20:08
xphanoo a écrit :
|
Si tu penses comme ça, t'es mal barré, ou plutôt tes futurs employeurs...
Les sources d'erreurs possibles:
- erreurs d'actions/saisies humaines ou actions malveillantes
- défaillances matérielles
- codage incorrect (écrasements mémoires, division par zéro, etc, calculs erronnés, etc)
- ressources à bout (espace disque, RAM,handlers, connexions, etc)
- erreurs de communication avec d'autres systèmes (identification, protocole incorrect, timeouts)
- droits d'accès à des ressources (fichiers par ex) non obtenus
Et j'en oublie sûrement. Tout ça doit faire partie des préoccupations de l'ingénieur logiciel.
Marsh Posté le 08-02-2009 à 17:25:39
+1
Une bonne gestion d'erreur, c'est un gain de temps considérable lorsqu'un problème survient en environnement de production.
Testé et approuvé lors d'astreintes de nuit. Tu préfères un programme qui ferme en sachant exactement pourquoi dans un fichier d'erreur, qu'un plantage avec, pour seule information, un "Segmentation fault", ce qui promet des heures de joie et d'amusement pour trouver le problème.
Marsh Posté le 08-02-2009 à 17:40:47
Et comme remplacement de strncpy() et strncat()
strlcpy and strlcat - consistent, safe, string copy and concatenation.
Man page: http://www.openbsd.org/cgi-bin/man.cgi?query=strlcat
Source code
Code :
|
Marsh Posté le 08-02-2009 à 18:38:51
Ou alors on peut utiliser snprintf()
Marsh Posté le 08-02-2009 à 18:43:00
Elmoricq a écrit : Pas portable. |
C'est quoi la partie pas portable, si tu les embarques avec toi plutôt que d'espérer une libc qui les contient?
Marsh Posté le 08-02-2009 à 18:43:40
Modifié mon post 3s avant ta réponse.
J'ai comme qui dirait relu le post de much, je pensais que son code était des exemples d'utilisations d'utilisations de fonctions présentes sur un OS particulier, pas fait gaffe
Marsh Posté le 08-02-2009 à 19:01:37
Elmoricq a écrit : Modifié mon post 3s avant ta réponse. |
Utiliser snprintf comme un strlcpy, c'est quand même pas l'option la plus efficace du monde, tant sur la vitesse du code que sur sa clarté
Marsh Posté le 08-02-2009 à 19:03:15
Quand tu te balades pas avec ta bibliothèque d'outils, ça dépanne bien.
Marsh Posté le 08-02-2009 à 19:06:29
masklinn a écrit : |
Marsh Posté le 08-02-2009 à 19:13:29
?
Marsh Posté le 08-02-2009 à 19:36:12
Je pense qu'il faut se lever tôt pour sentir la différence (et en fait entre un strlcpy codé simplement comme ci-dessus et un strlcpy qui utilise le snprintf aux petits oignons du compilo je suis pas sûr que le premier gagne).
Marsh Posté le 09-02-2009 à 16:20:37
Petit test: combien de fois avez-vous, dans votre codebase:
memcpy(dst, src, sizeof(src); //correct, si sizeof(src) <= sizeof(dst)
strncpy(dst, src, sizeof(src)); // incorrect
?
Là, comme ça, j'en compte 25 dans notre codebase rien que pour les strncpy.
Je crois que c'est l'une des erreurs de codage les plus courantes.
Marsh Posté le 09-02-2009 à 16:40:01
ici ? 0
Marsh Posté le 09-02-2009 à 17:09:23
el muchacho a écrit : Plus dur: |
En même temps, les deux formes sont dans les man respectifs de strncat et strncpy
En tout cas elles le sont sur mon mac
Marsh Posté le 09-02-2009 à 17:10:17
masklinn a écrit : |
Elles le sont que sur Mac. Parce que dans la plupart des manpages, elles n'y sont pas.
Marsh Posté le 09-02-2009 à 17:12:10
el muchacho a écrit : |
Elles sont aussi (et mieux formattées) dans le man de ma passerelle, OpenBSD 4.4
STRCAT(3) OpenBSD Programmer's Manual STRCAT(3) |
Sounds like you need a man's OS, girly boy
Marsh Posté le 09-02-2009 à 17:13:22
En fait, ces considérations d'usage de ces fonctions n'existent que sur le man d'OpenBSD, duquel dérive MacOS X, je le rappelle.
Marsh Posté le 09-02-2009 à 17:16:55
ReplyMarsh Posté le 09-02-2009 à 17:18:35
el muchacho a écrit : En fait, ces considérations d'usage sûr n'existent que sur le man d'OpenBSD, duquel dérive MacOS X, je le rappelle. |
Say ratal, OSX dérive de FreeBSD (c'est un kernel mach, un userland BSD 4.3, et des récupérations supplémentaires de FreeBSD et NetBSD post-split)
Marsh Posté le 09-02-2009 à 17:44:09
Joel F a écrit : ouasi ben on est sur la cat. C++ : boost::tokenizer |
ouais, on a considérablement dérivé, cette discussion serait plus à sa place en cat C, mais bon c'est tjrs utile.
masklinn a écrit : |
ouais, bref OSEF, c'est juste sur les man de BSD qu'il y a ces exemples d'usage.
Marsh Posté le 09-02-2009 à 18:12:16
el muchacho a écrit : |
Oui
Marsh Posté le 04-02-2009 à 18:20:51
bonjour
je voudrais parser avec un strtok une chaine de type string, mais le compilateur refuse de convertir un string en char* (le type que demande strtok apparemment).
j'ai bien essayé de faire strtok(chaine.c_str()," " ), mais là le compilateur de dit : cannot convert from 'const char *' to 'char *'
tant que j'y suis, j'aurais aussi besoin de convertir un char* en int... (en fait je dois lire un fichier texte pour le charger dans une structure, qui comporte des variables de types string et int... d'où les conversions que j'essaie de faire)