J'ai écrit un petit programme qui prend des paramètres d'entrée à partir de *argv[]
et les imprime. Dans presque tous les cas d'utilisation, mon code fonctionne parfaitement bien. Le problème ne survient que lorsque j'utilise plus d'un point d'exclamation à la fin de la chaîne de caractères que je veux passer comme argument ...
Ça marche :
./program -m "Hello, world!"
Cela ne fonctionne pas :
./program -m "Hello, world!!!!"
^^ Si je fais cela, la sortie du programme est soit deux fois cette chaîne, soit la commande que j'ai entrée avant ./programme.
Cependant, ce que je ne comprends absolument pas : Ce qui suit, bizarrement, fonctionne :
./program -m 'Hello, world!!!!'
^^ La sortie est exactement ...
Hello, world!!!!
... comme souhaité.
Donc, mes questions sont :
- Pourquoi ce comportement étrange se produit-il lorsque l'on utilise plusieurs points d'exclamation dans une chaîne de caractères ?
- Pour autant que je sache, en C, on utilise
""
pour cordes et''
pour les caractères uniques. Alors pourquoi est-ce que j'obtiens le résultat souhaité en utilisant''
mais pas en utilisant""
comme je le devrais (selon ma compréhension) ? - Y a-t-il une erreur dans mon code ou que dois-je changer pour pouvoir entrer n'importe quelle chaîne de caractères (peu importe si, quoi et combien de signes de ponctuation sont utilisés) et obtenir exactement cette chaîne de caractères imprimée ?
Les parties pertinentes de mon code :
// this is a simplified example that, in essence, does the same
// as my (significantly longer) code
int main(int argc, char* argv[]) {
char *msg = (char *)calloc(1024, sizeof(char));
printf("%s", strcat(msg, argv[2])); // argv[1] is "-m"
free(msg);
}
J'ai déjà essayé de copier le contenu de argv[2]
en un char*
d'abord et ajouter un '\0'
ce qui n'a rien changé.
2 votes
Pourquoi
printf("%s", strcat(msg, argv[2]))
au lieu deprintf("%s", argv[2]))
? ?2 votes
L'espace, vous devez y échapper. Aussi,
calloc()
ça n'a pas beaucoup de sens. Justechar msg[1024]
est très bon. Lorsque vous utilisez les qoutes simples, la chaîne est transmise telle quelle. Cela n'a rien à voir avecargv
ou le c le langage de programmation, mais avec le shell1 votes
@Michael Walz : Parce que je crée une chaîne beaucoup plus longue dans msg. L'ajout du contenu de argv à celui-ci n'est que la première des nombreuses étapes de mon code complet. Désolé de ne pas avoir clarifié cela plus tôt.
6 votes
Le point d'exclamation est un caractère spécial pour votre shell (probablement
bash
). S'il n'est pas placé entre guillemets simples, l'interpréteur de commandes interprète!!
et la remplace par quelque chose d'autre (la commande précédente dans l'historique). Votre programme fonctionne correctement, il imprime ce qu'il reçoit du shell dans la ligne de commande.0 votes
@Iharob Al Asimi : Je pensais qu'en utilisant calloc (au lieu de malloc), je remettais à zéro toute la zone mémoire, et que je n'avais donc pas besoin d'utiliser '. \0 à la fin de la chaîne.
0 votes
@ci7i2en4 OK ; mais la prochaine fois, merci de réduire le problème autant que possible. Mais, de toute façon, ici le problème n'était pas dans votre code mais c'est à cause du shell (voir les réponses ci-dessous)
0 votes
Je suppose que ceux d'entre vous qui font allusion à la coquille ont raison. Je viens d'essayer "Hello, world ?????" en entrée de programme et j'obtiens exactement ça en sortie.
0 votes
Cela me laisse avec une autre question : Existe-t-il un moyen de garantir que les utilisateurs de mon programme puissent toujours utiliser "Something !!!!" comme paramètre d'entrée sans subir ce comportement ? (quel que soit le shell qu'ils utilisent)
0 votes
@ci7i2en4 : c'est la façon dont Bash fonctionne -- et si vos utilisateurs veulent pour développer la commande précédente en tant que paramètre de votre programme ?
0 votes
@Groo : Le problème est que mon programme n'est pas capable de gérer ce comportement (et je ne sais pas comment changer cela). Si un utilisateur utilise "hallo !!" en entrée, le programme se termine avec l'erreur suivante : -bash : syntax error near unexpected token `)'.
2 votes
@ci7i2en4 : 1) l'erreur de syntaxe est une erreur de syntaxe de bash créée pendant l'expansion, votre programme n'est même pas lancé dans ce cas, 2) votre programme devrait être responsable de la validation des valeurs d'entrée, mais vous ne pouvez pas "annuler" l'expansion faite par bash. Les choses que vous devrait est de vérifier si
argc
a une longueur valide et en vérifiant si les paramètres ont un sens, puis en affichant probablement un message d'erreur avec des informations d'utilisation.0 votes
^^ D'une certaine manière, entrer "hello !!!! :-)" conduit à cette erreur de bash et le jeton inattendu doit être le ) de :-). Je ne comprends pas pourquoi c'est un problème pour bash. Et je ne sais pas comment je dois valider cette chaîne de caractères alors que l'utilisateur devrait être autorisé à saisir n'importe quelle chaîne de caractères. Je ne peux pas attendre des utilisateurs du programme qu'ils sachent comment fonctionne bash et ce qu'ils ne doivent pas saisir ...
0 votes
Je viens de tester "(Hello, world !!!! :-))))". Dans ce cas, je n'obtiens pas l'erreur "unexpected token". Je vais continuer à chercher des solutions... Merci à tous !
0 votes
Ça ne fait pas ça pour moi.
0 votes
@DonaldDuck Vous ne semblez pas être dans Bash, ce qui est l'objet de la question.
0 votes
Vote pour la réouverture. Les réponses dans le dup donné contiennent moins d'informations que ceux de cette question, ce qui est plus largement perçu. J'ai voté pour fermer l'autre en raison de cela.