string vers char*

string vers char* - C++ - Programmation

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)
 
 

Reply

Marsh Posté le 04-02-2009 à 18:20:51   

Reply

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

Message cité 1 fois
Message édité par Joel F le 04-02-2009 à 18:58:07
Reply

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 [:pingouino]


Message édité par erulio le 04-02-2009 à 19:00:47
Reply

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.

Reply

Marsh Posté le 04-02-2009 à 20:05:01    

xphanoo a écrit :


j'ai bien essayé de faire strtok(chaine.c_str()," " ), mais là le compilateur de dit : cannot convert from 'const char *' to 'char *'

 

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. :o

 

Du coup, si comme chez moi tu n'as pas accès à boost ([:zytrasnif]), 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 [:dawa]

 

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. [:implosion du tibia]

Message cité 1 fois
Message édité par Elmoricq le 04-02-2009 à 20:05:57
Reply

Marsh Posté le 04-02-2009 à 20:11:41    

en plus elle est pas reentrante :o
donc strtok_r dans du vrai code :o

Reply

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 :
char * buffer = new char[chaine.length() + 1];
strcpy(buffer, chaine.c_str());
 
<ton code avec strtok()>
 
delete[] buffer;


 

Code :
  1. std::vector<char> copie(chaine.begin(), chaine.end());
  2. copie.push_back('\0');
  3. ...  &copie[0] ...


 

Citation :

Mais bon. Faut vraiment aimer strtok(), là. J'ai toujours trouvé que c'était la plus laide des fonctions C disponibles. [:implosion du tibia]


 
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é.

Reply

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!!


Message édité par xphanoo le 04-02-2009 à 21:44:52
Reply

Marsh Posté le 04-02-2009 à 21:51:45    

Reply

Marsh Posté le 04-02-2009 à 22:05:23    

Reply

Marsh Posté le 04-02-2009 à 22:05:23   

Reply

Marsh Posté le 04-02-2009 à 22:08:37    

Un Programmeur a écrit :


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!


 
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. [:chapi-chapo]

Reply

Marsh Posté le 04-02-2009 à 22:12:24    


 


 
mais pourquoi les fonctions que j'utilise sont toujours les plus détestées  :cry:  
 
pourtant y'a pas plus simple  [:face_de_pomme]

Message cité 1 fois
Message édité par xphanoo le 04-02-2009 à 22:13:03
Reply

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  :cry:

 

pourtant y'a pas plus simple  [:face_de_pomme]

 

Tu sembles avoir un souci avec la documentation on dirait. [:dawak]

 
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
     used in new code.

 


Message cité 1 fois
Message édité par Elmoricq le 04-02-2009 à 22:18:22
Reply

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. [:chapi-chapo]


 
Il y a aussi gets()...

Reply

Marsh Posté le 05-02-2009 à 09:12:40    

Moi ce qui m'embete c'est :

Citation :


The atoi() function is not thread-safe and also not async-cancel safe.

Reply

Marsh Posté le 05-02-2009 à 09:53:42    

Un Programmeur a écrit :


 
Il y a aussi gets()...


 
gets() n'existe pas, c'est une illusion d'optique :o

Reply

Marsh Posté le 05-02-2009 à 11:28:40    

Elmoricq a écrit :


 
Tu sembles avoir un souci avec la documentation on dirait. [:dawak]
 

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
     used in new code.
 



 
hm certes mais vu que je suis sur des données que je lui envoie, pas de raison qu'il y ait d'erreur  [:dobeliou2]  
 
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...

Reply

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.

Reply

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. [:chapi-chapo]


 
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).

Reply

Marsh Posté le 08-02-2009 à 17:20:08    

xphanoo a écrit :


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...


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.


Message édité par el muchacho le 08-02-2009 à 17:45:42

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

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.

Reply

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 :
  1. /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
  2. /*
  3. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/types.h>
  18. #include <string.h>
  19. /*
  20. * Copy src to string dst of size siz.  At most siz-1 characters
  21. * will be copied.  Always NUL terminates (unless siz == 0).
  22. * Returns strlen(src); if retval >= siz, truncation occurred.
  23. */
  24. size_t
  25. strlcpy(char *dst, const char *src, size_t siz)
  26. {
  27. char *d = dst;
  28. const char *s = src;
  29. size_t n = siz;
  30. /* Copy as many bytes as will fit */
  31. if (n != 0) {
  32.  while (--n != 0) {
  33.   if ((*d++ = *s++) == '\0')
  34.    break;
  35.  }
  36. }
  37. /* Not enough room in dst, add NUL and traverse rest of src */
  38. if (n == 0) {
  39.  if (siz != 0)
  40.   *d = '\0';  /* NUL-terminate dst */
  41.  while (*s++)
  42.   ;
  43. }
  44. return(s - src - 1); /* count does not include NUL */
  45. }
  46. /*
  47. * Appends src to string dst of size siz (unlike strncat, siz is the
  48. * full size of dst, not space left).  At most siz-1 characters
  49. * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
  50. * Returns strlen(src) + MIN(siz, strlen(initial dst)).
  51. * If retval >= siz, truncation occurred.
  52. */
  53. size_t
  54. strlcat(char *dst, const char *src, size_t siz)
  55. {
  56. char *d = dst;
  57. const char *s = src;
  58. size_t n = siz;
  59. size_t dlen;
  60. /* Find the end of dst and adjust bytes left but don't go past end */
  61. while (n-- != 0 && *d != '\0')
  62.  d++;
  63. dlen = d - dst;
  64. n = siz - dlen;
  65. if (n == 0)
  66.  return(dlen + strlen(s));
  67. while (*s != '\0') {
  68.  if (n != 1) {
  69.   *d++ = *s;
  70.   n--;
  71.  }
  72.  s++;
  73. }
  74. *d = '\0';
  75. return(dlen + (s - src)); /* count does not include NUL */
  76. }


Message édité par el muchacho le 08-02-2009 à 17:46:23

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 08-02-2009 à 18:38:51    

Ou alors on peut utiliser snprintf() :o

Message cité 2 fois
Message édité par Elmoricq le 08-02-2009 à 18:42:57
Reply

Marsh Posté le 08-02-2009 à 18:43:00    

Elmoricq a écrit :

Pas portable. :o


C'est quoi la partie pas portable, si tu les embarques avec toi plutôt que d'espérer une libc qui les contient?


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 08-02-2009 à 18:43:40    

Modifié mon post 3s avant ta réponse. [:klem3i1]

 

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 :o

Message cité 1 fois
Message édité par Elmoricq le 08-02-2009 à 18:45:06
Reply

Marsh Posté le 08-02-2009 à 19:01:37    

Elmoricq a écrit :

Modifié mon post 3s avant ta réponse. [:klem3i1]


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é [:pingouino]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 08-02-2009 à 19:03:15    

Quand tu te balades pas avec ta bibliothèque d'outils, ça dépanne bien. :o

Reply

Marsh Posté le 08-02-2009 à 19:06:29    

masklinn a écrit :


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é [:pingouino]


 
 [:sadnoir]  


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 08-02-2009 à 19:13:29    


?


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

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).


Message édité par 0x90 le 08-02-2009 à 19:36:25

---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

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.


Message édité par el muchacho le 09-02-2009 à 21:57:20

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 09-02-2009 à 16:40:01    

ici ? 0 :o :p


Message édité par Joel F le 09-02-2009 à 16:40:11
Reply

Marsh Posté le 09-02-2009 à 17:09:23    

el muchacho a écrit :

Plus dur:  
l'usage "sûr" de strncat (à supposer que strlen retourne qq chose de correct...):
strncat(dst, src , sizeof(dst) - strlen(dst) - 1);
 
Combien de fois vous utilisez cet idiome ?  
Ici, j'ai pas besoin de compter pour savoir que c'est zéro. :o
 
(
Rappel du seul usage sûr de strncpy:
strncpy(dst, src, sizeof(dst) - 1);
dst[sizeof(dst)-1] = '\0';
)


En même temps, les deux formes sont dans les man respectifs de strncat et strncpy :o
 
En tout cas elles le sont sur mon mac :o


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 09-02-2009 à 17:10:17    

masklinn a écrit :


En même temps, les deux formes sont dans les man respectifs de strncat et strncpy :o
 
En tout cas elles le sont sur mon mac :o


Elles le sont que sur Mac. Parce que dans la plupart des manpages, elles n'y sont pas.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 09-02-2009 à 17:12:10    

el muchacho a écrit :


Elles le sont que sur Mac. Parce que dans la plupart des manpages, elles n'y sont pas.


Elles sont aussi (et mieux formattées) dans le man de ma passerelle, OpenBSD 4.4 :o

STRCAT(3)                 OpenBSD Programmer's Manual                STRCAT(3)
 
NAME
     strcat, strncat - concatenate strings
 
SYNOPSIS
     #include <string.h>
 
     char *
     strcat(char *s, const char *append);
 
     char *
     strncat(char *s, const char *append, size_t count);
 
DESCRIPTION
     The strcat() and strncat() functions append a copy of the NUL-terminated
     string append to the end of the NUL-terminated string s, then add a ter-
     minating `\0'.  The string s must have sufficient space to hold the re-
     sult.
 
     The strncat() function appends not more than count characters where space
     for the terminating `\0' should not be included in count.
 
RETURN VALUES
     The strcat() and strncat() functions return the pointer s.
 
EXAMPLES
     The following appends ``abc'' to chararray:
 
           char *letters = "abcdefghi";
 
           (void)strncat(chararray, letters, 3);
 
     The following example shows how to use strncat() safely in conjunction
     with strncpy(3).
 
           char buf[BUFSIZ];
           char *input, *suffix;
 
           (void)strncpy(buf, input, sizeof(buf) - 1);
           buf[sizeof(buf) - 1] = '\0';
           (void)strncat(buf, suffix, sizeof(buf) - 1 - strlen(buf));
 
     The above will copy as many characters from input to buf as will fit.  It
     then appends as many characters from suffix as will fit (or none if there
     is no space).  For operations like this, the strlcpy(3) and strlcat(3)
     functions are a better choice, as shown below.
 
           (void)strlcpy(buf, input, sizeof(buf));
           (void)strlcat(buf, suffix, sizeof(buf));
SEE ALSO
     bcopy(3), memccpy(3), memcpy(3), memmove(3), strcpy(3), strlcat(3),
     strlcpy(3)
 
STANDARDS
     The strcat() and strncat() functions conform to ANSI X3.159-1989 (``ANSI
     C'').
 
OpenBSD 4.4                    February 4, 2009                              1


 
Sounds like you need a man's OS, girly boy :o


Message édité par masklinn le 09-02-2009 à 17:13:30

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

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.

Message cité 1 fois
Message édité par el muchacho le 09-02-2009 à 17:13:41

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 09-02-2009 à 17:16:55    

ouasi ben on est sur la cat. C++ : boost::tokenizer :o

Reply

Marsh 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)


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 09-02-2009 à 17:44:09    

Joel F a écrit :

ouasi ben on est sur la cat. C++ : boost::tokenizer :o


ouais, on a considérablement dérivé, cette discussion serait plus à sa place en cat C, mais bon c'est tjrs utile.  :o

masklinn a écrit :


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)


ouais, bref OSEF, c'est juste sur les man de BSD qu'il y a ces exemples d'usage. :o


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 09-02-2009 à 18:12:16    

el muchacho a écrit :


ouais, on a considérablement dérivé, cette discussion serait plus à sa place en cat C, mais bon c'est tjrs utile.  :o


Oui :)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed