On Mon, 20 Jun 2005 14:29:24 +0200 nico [nico] wrote:
[...] nico> Quelle est la meilleure méthode (si toutefois la première marchait) ?
ni l'une ni l'autre, tu ne devrais pas toucher au contenu de argv, mais plutot t'allouer un buffer et travailler dedans.
ici tu écrases le contenu de argv avec son propre contenu, ce qui n'est pas, je pense, ce que tu veux vraiment faire.
-- Alain
Antoine Leca
[ISO/CÉI 8859-1]
En <news:42b6b6a4$0$32719$, nico va escriure:
str = argv[1];
strcat(str, " "); strcat(str, argv[i]);
Rapelle-moi, tu as alloué la mémoire pour pouvoir ajouter tes chaînes de caractères ?
pourquoi si j'apelle mon prog par :
./prog salut ceci est un test
ca m'affiche "salut est un test" ?
Parce que le premier strcat() (avec " ") a écrit un ' ' à la place du 'c' de ceci; le second a trouvé cette fin de chaîne, donc n'a rien ajouté; le reste a copié sans recouvrement (enfin, en recouvrant successivement argv[2] puis argv[3] etc.) donc le résultat paraît être correct.
j'ai trouvé une autre méthode qui consiste a remplacer les deux strcat par :
sprintf(str, "%s %s", str, argv[i]);
et là ca fonctionne.
Non, cela semble fonctionner (chez toi). Ici, le sprintf n'écrit pas le ' ' après l'espace, donc le problème ci-dessus ne se produit plus. le sprintf ne fait rien d'autre que de faire l'inverse de ce qu'a fait le shell auparavant, c'est-à-dire mettre des ' ' là où il y a des ' ' qui indique la fin des chaînes-arguments quand tu entres dans le programme.
Quelle est la meilleure méthode (si toutefois la première marchait) ?
Lire strcpy() et malloc()/ARG_MAX. Si tu as un programme qui utilise strcat() sans utiliser strcpy(), en général il y a un bogue.
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas arriver » (je mettais souvent '¤' avant les euros, comme il était au clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du programme on vérifie que le '¤' n'a pas été écrasé, et sinon on signale un problème (assert par exemple). Ensuite on passe des GROS arguments au programme, miam miam. Dans ton cas, cette méthose permet de détecter tout de suite le problème: il n'y a pas d'endroit pour mettre le '¤'...
Antoine
[ISO/CÉI 8859-1]
En <news:42b6b6a4$0$32719$636a15ce@news.free.fr>, nico va escriure:
str = argv[1];
strcat(str, " ");
strcat(str, argv[i]);
Rapelle-moi, tu as alloué la mémoire pour pouvoir ajouter tes chaînes de
caractères ?
pourquoi si j'apelle mon prog par :
./prog salut ceci est un test
ca m'affiche "salut est un test" ?
Parce que le premier strcat() (avec " ") a écrit un ' ' à la place du 'c'
de ceci; le second a trouvé cette fin de chaîne, donc n'a rien ajouté; le
reste a copié sans recouvrement (enfin, en recouvrant successivement argv[2]
puis argv[3] etc.) donc le résultat paraît être correct.
j'ai trouvé une autre méthode qui consiste a remplacer les deux
strcat par :
sprintf(str, "%s %s", str, argv[i]);
et là ca fonctionne.
Non, cela semble fonctionner (chez toi).
Ici, le sprintf n'écrit pas le ' ' après l'espace, donc le problème
ci-dessus ne se produit plus. le sprintf ne fait rien d'autre que de faire
l'inverse de ce qu'a fait le shell auparavant, c'est-à-dire mettre des ' '
là où il y a des ' ' qui indique la fin des chaînes-arguments quand tu
entres dans le programme.
Quelle est la meilleure méthode (si toutefois la première marchait) ?
Lire strcpy() et malloc()/ARG_MAX.
Si tu as un programme qui utilise strcat() sans utiliser strcpy(), en
général il y a un bogue.
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas
arriver » (je mettais souvent '¤' avant les euros, comme il était au
clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du
programme on vérifie que le '¤' n'a pas été écrasé, et sinon on signale un
problème (assert par exemple). Ensuite on passe des GROS arguments au
programme, miam miam.
Dans ton cas, cette méthose permet de détecter tout de suite le problème: il
n'y a pas d'endroit pour mettre le '¤'...
Rapelle-moi, tu as alloué la mémoire pour pouvoir ajouter tes chaînes de caractères ?
pourquoi si j'apelle mon prog par :
./prog salut ceci est un test
ca m'affiche "salut est un test" ?
Parce que le premier strcat() (avec " ") a écrit un ' ' à la place du 'c' de ceci; le second a trouvé cette fin de chaîne, donc n'a rien ajouté; le reste a copié sans recouvrement (enfin, en recouvrant successivement argv[2] puis argv[3] etc.) donc le résultat paraît être correct.
j'ai trouvé une autre méthode qui consiste a remplacer les deux strcat par :
sprintf(str, "%s %s", str, argv[i]);
et là ca fonctionne.
Non, cela semble fonctionner (chez toi). Ici, le sprintf n'écrit pas le ' ' après l'espace, donc le problème ci-dessus ne se produit plus. le sprintf ne fait rien d'autre que de faire l'inverse de ce qu'a fait le shell auparavant, c'est-à-dire mettre des ' ' là où il y a des ' ' qui indique la fin des chaînes-arguments quand tu entres dans le programme.
Quelle est la meilleure méthode (si toutefois la première marchait) ?
Lire strcpy() et malloc()/ARG_MAX. Si tu as un programme qui utilise strcat() sans utiliser strcpy(), en général il y a un bogue.
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas arriver » (je mettais souvent '¤' avant les euros, comme il était au clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du programme on vérifie que le '¤' n'a pas été écrasé, et sinon on signale un problème (assert par exemple). Ensuite on passe des GROS arguments au programme, miam miam. Dans ton cas, cette méthose permet de détecter tout de suite le problème: il n'y a pas d'endroit pour mettre le '¤'...
Antoine
Yves ROMAN
"nico" a écrit dans le message de news: 42b6b6a4$0$32719$
Tu ne devrait pas toucher la zone pointée par argv[i] car tu ne connais pas sa taille disponible
Si tu affiches les adresses contenues dans argv[i], tu verras qu'il y a une zone contigue qui contient: salut ceci est un test argv[1] pointe vers le s de salut argv[2] pointe vers le c de ceci ...
Le 1er strcat(str," ") transforme la zone en salut eci est un test argv[2] pointe maintenant vers le derrière l'espace, et le strcat() ne fait rien Pour les autres ca fonctionne car il a un décalage du au fait que "ceci" n'a pas été copié.
Par contre, maintenant argv[i] pointent vers un peu n'importe quoi...
j'ai trouvé une autre méthode qui consiste a remplacer les deux strcat par :
sprintf(str, "%s %s", str, argv[i]);
et là ca fonctionne.
coup de bol ! le sprintf ne met pas le après le " ", donc argv[2] pointe toujours vers "ceci "
Par contre, après ton traitement, argv[2] pointe vers "ceci est un test "
Tu as de la chance que les arguments du programme soient gérés comme ca. Si argv[1] pointait vers une zone de 6 caractères, avec une zone inaccesible derrière, ton programme aurait planté.
Il vaudrait mieux - calculer la taille finale de la chaine avec une boucle de strlen() - allouer str avec malloc(somme(strlen())+(argc-2)+1) - puis faire la boucle des strcat() - liberer str quand il est devenu inutile
Nota: J'ai toujours des scrupules à utiliser sprintf(str, "%s....", str,...); (en supposant que str soit assez grand)
"nico" <nospam@spam.fr> a écrit dans le message de news:
42b6b6a4$0$32719$636a15ce@news.free.fr...
Tu ne devrait pas toucher la zone pointée par argv[i] car tu ne connais pas
sa taille disponible
Si tu affiches les adresses contenues dans argv[i], tu verras qu'il y a une
zone contigue qui contient:
salut ceci est un test
argv[1] pointe vers le s de salut
argv[2] pointe vers le c de ceci
...
Le 1er strcat(str," ")
transforme la zone en
salut eci est un test
argv[2] pointe maintenant vers le derrière l'espace, et le strcat() ne
fait rien
Pour les autres ca fonctionne car il a un décalage du au fait que "ceci" n'a
pas été copié.
Par contre, maintenant argv[i] pointent vers un peu n'importe quoi...
j'ai trouvé une autre méthode qui consiste a remplacer les deux strcat par
:
sprintf(str, "%s %s", str, argv[i]);
et là ca fonctionne.
coup de bol !
le sprintf ne met pas le après le " ", donc argv[2] pointe toujours vers
"ceci "
Par contre, après ton traitement, argv[2] pointe vers "ceci est un test "
Tu as de la chance que les arguments du programme soient gérés comme ca.
Si argv[1] pointait vers une zone de 6 caractères, avec une zone inaccesible
derrière, ton programme aurait planté.
Il vaudrait mieux
- calculer la taille finale de la chaine avec une boucle de strlen()
- allouer str avec malloc(somme(strlen())+(argc-2)+1)
- puis faire la boucle des strcat()
- liberer str quand il est devenu inutile
Nota:
J'ai toujours des scrupules à utiliser
sprintf(str, "%s....", str,...);
(en supposant que str soit assez grand)
Tu ne devrait pas toucher la zone pointée par argv[i] car tu ne connais pas sa taille disponible
Si tu affiches les adresses contenues dans argv[i], tu verras qu'il y a une zone contigue qui contient: salut ceci est un test argv[1] pointe vers le s de salut argv[2] pointe vers le c de ceci ...
Le 1er strcat(str," ") transforme la zone en salut eci est un test argv[2] pointe maintenant vers le derrière l'espace, et le strcat() ne fait rien Pour les autres ca fonctionne car il a un décalage du au fait que "ceci" n'a pas été copié.
Par contre, maintenant argv[i] pointent vers un peu n'importe quoi...
j'ai trouvé une autre méthode qui consiste a remplacer les deux strcat par :
sprintf(str, "%s %s", str, argv[i]);
et là ca fonctionne.
coup de bol ! le sprintf ne met pas le après le " ", donc argv[2] pointe toujours vers "ceci "
Par contre, après ton traitement, argv[2] pointe vers "ceci est un test "
Tu as de la chance que les arguments du programme soient gérés comme ca. Si argv[1] pointait vers une zone de 6 caractères, avec une zone inaccesible derrière, ton programme aurait planté.
Il vaudrait mieux - calculer la taille finale de la chaine avec une boucle de strlen() - allouer str avec malloc(somme(strlen())+(argc-2)+1) - puis faire la boucle des strcat() - liberer str quand il est devenu inutile
Nota: J'ai toujours des scrupules à utiliser sprintf(str, "%s....", str,...); (en supposant que str soit assez grand)
nico
Salut,
D'abord merci pour la réponse.
Il vaudrait mieux - calculer la taille finale de la chaine avec une boucle de strlen() - allouer str avec malloc(somme(strlen())+(argc-2)+1) - puis faire la boucle des strcat() - liberer str quand il est devenu inutile
Je veux bien mais je le connais pas quand le lis de stdin, voici mon code complet :
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou de reallouer dans mon cas) donc forcément je suppose que le code qui suit est horrible)
j'aimerai savoir coment m'en sortir pour la lecture de stdin (pour la lecture de argv j'ai compris, je vais claculer la taille à l'avance).
void show_usage(char* prg) { printf("Usage: %s [--help] [string [string2 [string3 ...]]]n", prg); printf("tstringtString to encode/decoden"); printf("t--helptShow helpn"); printf("If string argument is not provided, read string from standard inputn"); }
/* fin main.c */
PS: je viens de C++ (que je pratique depuis un moment) donc pour les chaines j'avais l'habitude de ne pas m'embeter beaucoup (un coup de std::string et de std::string::c_str quand je voulais un char* pour les APIs et c'était fini !) -- nico
Salut,
D'abord merci pour la réponse.
Il vaudrait mieux
- calculer la taille finale de la chaine avec une boucle de strlen()
- allouer str avec malloc(somme(strlen())+(argc-2)+1)
- puis faire la boucle des strcat()
- liberer str quand il est devenu inutile
Je veux bien mais je le connais pas quand le lis de stdin, voici mon code
complet :
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou
de reallouer dans mon cas) donc forcément je suppose que le code qui suit
est horrible)
j'aimerai savoir coment m'en sortir pour la lecture de stdin (pour la
lecture de argv j'ai compris, je vais claculer la taille à l'avance).
void show_usage(char* prg)
{
printf("Usage: %s [--help] [string [string2 [string3 ...]]]n", prg);
printf("tstringtString to encode/decoden");
printf("t--helptShow helpn");
printf("If string argument is not provided, read string from standard
inputn");
}
/* fin main.c */
PS: je viens de C++ (que je pratique depuis un moment) donc pour les chaines
j'avais l'habitude de ne pas m'embeter beaucoup (un coup de std::string et
de std::string::c_str quand je voulais un char* pour les APIs et c'était
fini !)
--
nico
Il vaudrait mieux - calculer la taille finale de la chaine avec une boucle de strlen() - allouer str avec malloc(somme(strlen())+(argc-2)+1) - puis faire la boucle des strcat() - liberer str quand il est devenu inutile
Je veux bien mais je le connais pas quand le lis de stdin, voici mon code complet :
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou de reallouer dans mon cas) donc forcément je suppose que le code qui suit est horrible)
j'aimerai savoir coment m'en sortir pour la lecture de stdin (pour la lecture de argv j'ai compris, je vais claculer la taille à l'avance).
void show_usage(char* prg) { printf("Usage: %s [--help] [string [string2 [string3 ...]]]n", prg); printf("tstringtString to encode/decoden"); printf("t--helptShow helpn"); printf("If string argument is not provided, read string from standard inputn"); }
/* fin main.c */
PS: je viens de C++ (que je pratique depuis un moment) donc pour les chaines j'avais l'habitude de ne pas m'embeter beaucoup (un coup de std::string et de std::string::c_str quand je voulais un char* pour les APIs et c'était fini !) -- nico
Jean-Claude Arbaut
On 20/06/2005 16:17, nico wrote:
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou de reallouer dans mon cas) donc forcément je suppose que le code qui suit est horrible)
Aïeoupsssss. Horrible est le mot juste ;-)
On 20/06/2005 16:17, nico wrote:
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou
de reallouer dans mon cas) donc forcément je suppose que le code qui suit
est horrible)
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou de reallouer dans mon cas) donc forcément je suppose que le code qui suit est horrible)
Aïeoupsssss. Horrible est le mot juste ;-)
nico
Jean-Claude Arbaut wrote:
On 20/06/2005 16:17, nico wrote:
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou de reallouer dans mon cas) donc forcément je suppose que le code qui suit est horrible)
void show_usage(char* prg) { printf("Usage: %s [--help] [string [string2 [string3 ...]]]n", prg); printf("tstringtString to encode/decoden"); printf("t--helptShow helpn"); printf("If string argument is not provided, read string from standard inputn"); }
-- nico
Jean-Claude Arbaut wrote:
On 20/06/2005 16:17, nico wrote:
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/
(ou de reallouer dans mon cas) donc forcément je suppose que le code qui
suit est horrible)
(je pensais que sprintf() s'occupait d'allouer la mémoire qui va bien :/ (ou de reallouer dans mon cas) donc forcément je suppose que le code qui suit est horrible)
Comportement indéfini. Tu ne sais pas si l'argument est modifible, ni si il peut être agrandi.
-- Emmanuel The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html The C-library: http://www.dinkumware.com/refxc.html
"Mal nommer les choses c'est ajouter du malheur au monde." -- Albert Camus.
Emmanuel Delahaye
Antoine Leca wrote on 20/06/05 :
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas arriver » (je mettais souvent '¤' avant les euros, comme il était au clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du programme on vérifie que le '¤' n'a pas été écrasé, et sinon on signale un problème (assert par exemple). Ensuite on passe des GROS arguments au programme, miam miam. Dans ton cas, cette méthose permet de détecter tout de suite le problème: il n'y a pas d'endroit pour mettre le '¤'...
Je faisais ça aussi avec -1 ou je ne sais quel caractère bizarre jusqu'à ce qu'un 'smart guy' de c.l.c me fasse remarqué que 0 était la bonne valeur.
Depuis :
/* controles */ #define LIM_STR(s) (s)[sizeof (s) - 1]=0 #define CHK_STR(s) ASSERT((s)[sizeof (s) - 1]==0)
-- Emmanuel The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html The C-library: http://www.dinkumware.com/refxc.html
"There are 10 types of people in the world today; those that understand binary, and those that dont."
Antoine Leca wrote on 20/06/05 :
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas
arriver » (je mettais souvent '¤' avant les euros, comme il était au
clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du
programme on vérifie que le '¤' n'a pas été écrasé, et sinon on signale un
problème (assert par exemple). Ensuite on passe des GROS arguments au
programme, miam miam.
Dans ton cas, cette méthose permet de détecter tout de suite le problème: il
n'y a pas d'endroit pour mettre le '¤'...
Je faisais ça aussi avec -1 ou je ne sais quel caractère bizarre
jusqu'à ce qu'un 'smart guy' de c.l.c me fasse remarqué que 0 était la
bonne valeur.
Depuis :
/* controles */
#define LIM_STR(s) (s)[sizeof (s) - 1]=0
#define CHK_STR(s) ASSERT((s)[sizeof (s) - 1]==0)
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas arriver » (je mettais souvent '¤' avant les euros, comme il était au clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du programme on vérifie que le '¤' n'a pas été écrasé, et sinon on signale un problème (assert par exemple). Ensuite on passe des GROS arguments au programme, miam miam. Dans ton cas, cette méthose permet de détecter tout de suite le problème: il n'y a pas d'endroit pour mettre le '¤'...
Je faisais ça aussi avec -1 ou je ne sais quel caractère bizarre jusqu'à ce qu'un 'smart guy' de c.l.c me fasse remarqué que 0 était la bonne valeur.
Depuis :
/* controles */ #define LIM_STR(s) (s)[sizeof (s) - 1]=0 #define CHK_STR(s) ASSERT((s)[sizeof (s) - 1]==0)
-- Emmanuel The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html The C-library: http://www.dinkumware.com/refxc.html
"There are 10 types of people in the world today; those that understand binary, and those that dont."
nico
Antoine Leca wrote:
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas arriver » (je mettais souvent '?' avant les euros, comme il était au clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du programme on vérifie que le '?' n'a pas été écrasé, et sinon on signale un problème (assert par exemple). Ensuite on passe des GROS arguments au programme, miam miam. Dans ton cas, cette méthose permet de détecter tout de suite le problème: il n'y a pas d'endroit pour mettre le '?'...
ok. à la fin de la zona allouée tu veux dire ?
par exemple :
char * str = malloc(nb); str[nb - 1] = '?';
-- nico
Antoine Leca wrote:
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas
arriver » (je mettais souvent '?' avant les euros, comme il était au
clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du
programme on vérifie que le '?' n'a pas été écrasé, et sinon on signale un
problème (assert par exemple). Ensuite on passe des GROS arguments au
programme, miam miam.
Dans ton cas, cette méthose permet de détecter tout de suite le problème:
il n'y a pas d'endroit pour mettre le '?'...
Sinon, une bonne méthode consiste à mettre un caractère « qui ne peut pas arriver » (je mettais souvent '?' avant les euros, comme il était au clavier) tout à la fin de la zone où tu fais les strcat(); et à la fin du programme on vérifie que le '?' n'a pas été écrasé, et sinon on signale un problème (assert par exemple). Ensuite on passe des GROS arguments au programme, miam miam. Dans ton cas, cette méthose permet de détecter tout de suite le problème: il n'y a pas d'endroit pour mettre le '?'...