Tout programme lancé depuis un terminal peut recevoir des arguments : gcc -Wall hello.c -o hello en passe quatre. Vos propres programmes C lisent les leurs via deux paramètres de main, et c'est tout le mécanisme - aucun appel de bibliothèque, aucune configuration.
La signature
Jusqu'ici, tous les exemples de ces docs ont utilisé int main(void). L'autre forme standard prend la ligne de commande :
int main(int argc, char *argv[]) {
/* ... */
}
argc(« argument count ») est le nombre d'arguments, y compris le nom du programme.argv(« argument vector ») est un tableau de chaînes.char *argv[]signifie « tableau de pointeurs sur char », c'est-à-dire un tableau de chaînes C.
char **argv est une écriture équivalente que vous verrez tout aussi souvent ; les paramètres tableau se dégradent en pointeurs, donc les deux déclarent la même chose.
Utilisez le panneau Args de l'éditeur pour fournir des arguments (chaque champ est un argument), puis lancez. Essayez trois champs : hello, world, 42.
L'anatomie
Exécuter ./greet Ada Lovelace produit :
| Indice | Valeur | |
|---|---|---|
argv[0] | "./greet" | le nom du programme tel qu'invoqué |
argv[1] | "Ada" | premier vrai argument |
argv[2] | "Lovelace" | deuxième vrai argument |
argv[3] | NULL | le terminateur |
argc | 3 | compte incluant argv[0] |
Quatre faits à retenir :
argcvaut au moins 1 en pratique, carargv[0]est le nom du programme. Les vrais arguments commencent à l'indice 1, c'est pourquoi les boucles sur eux démarrent ài = 1.- Tout est une chaîne.
./prog 42vous donne"42", les deux caractères, jamais le nombre 42. La conversion est votre travail. argv[argc]vautNULL. Garanti par la norme, vous pouvez donc parcourir le tableau sansargcsi vous préférez :for (char **p = argv + 1; *p != NULL; p++).- C'est le shell qui découpe les mots, pas votre programme.
./prog "Ada Lovelace"est un seul argument ; les guillemets sont consommés par le shell et n'atteignent jamaisargv.
Vérifier avant de lire
Un argument qui n'a pas été passé n'est pas une chaîne vide - c'est de la mémoire que vous n'avez pas le droit de toucher. Validez toujours argc d'abord :
Deux conventions dans ce minuscule programme, toutes deux standard dans les outils Unix :
- Le message d'usage va vers
stderr, passtdout, pour ne pas polluer une sortie redirigée ailleurs. - Un retour non nul de
mainsignale un échec à ce qui a lancé le programme.0signifie succès ; tout le reste veut dire que quelque chose a mal tourné. Les scripts shell le vérifient.
Afficher argv[0] plutôt qu'un nom écrit en dur fait que le message correspond à la façon dont l'utilisateur a invoqué le programme, même s'il a été renommé ou atteint par un autre chemin.
Convertir des arguments numériques
argv[1] est du texte. Pour faire de l'arithmétique, vous devez le convertir, et la fonction à utiliser est strtol de <stdlib.h> :
Ajoutez 10, 20, 30 comme trois champs Args, puis remplacez-en un par banane pour voir le chemin d'erreur.
Le troisième paramètre de strtol est la base : 10 pour décimal, 16 pour hexadécimal, ou 0 pour détecter automatiquement d'après un préfixe 0x ou un zéro initial. Le second indique où stocker un pointeur sur le premier caractère qu'il n'a pas consommé, et c'est ce qui rend la vérification d'erreur possible :
end == textsignifie que rien n'a été analysé - l'argument ne commençait pas par un nombre.*end != '\0'signifie qu'il restait du texte après le nombre, donc"12abc"est rejeté au lieu de devenir silencieusement 12.errno == ERANGEsignifie que la valeur a débordé unlong.
Comparez avec atoi, plus court et incapable de signaler quoi que ce soit de tout cela :
int n = atoi(argv[1]); /* "banane" -> 0, "0" -> 0, debordement -> indefini */
atoi renvoie 0 pour une entrée invalide, ce qui est indiscernable d'un vrai zéro. Utilisez strtol (et strtod pour le flottant) dès que l'entrée vient de l'extérieur de votre programme. Plus de détails dans conversion de chaînes.
Une petite calculatrice
Tout mis ensemble - un programme prenant un nombre, un opérateur et un nombre :
Essayez 12 + 30, puis 7 x 6, puis 5 / 0.
Notez strcmp(op, "+") == 0 plutôt que op == "+". Comparer des valeurs char * avec == compare des adresses, pas des contenus, et serait faux même pour un texte identique. Voir fonctions de chaînes.
Le x au lieu de * est un détail du monde réel : la plupart des shells remplacent un * isolé par la liste des fichiers du répertoire courant avant même que votre programme ne démarre. Le protéger par des quotes ('*') fonctionne aussi, mais choisir un caractère que le shell ignore est plus aimable.
Analyser des options
Les options commencent conventionnellement par -. Une simple boucle écrite à la main gère les cas courants :
Essayez-le avec quatre champs Args : -v, -n, 3, hello.
La vérification i + 1 >= argc avant argv[++i] est la ligne importante : une option attendant une valeur doit confirmer que la valeur est bien là, sinon -n en dernier argument lit au-delà de la fin du tableau. Sur les vrais systèmes Unix, getopt de <unistd.h> fait tout cela pour vous, y compris les options courtes groupées comme -vn3 ; cela vaut le coup dès qu'un programme a plus de deux ou trois options.
Les arguments dans l'éditeur du navigateur
Les blocs d'éditeur de cette page sont compilés et exécutés pour vous, et le panneau Args est l'endroit où vous tapez ce qui suivrait le nom du programme dans un terminal. Chaque champ que vous ajoutez avec Add arg devient exactement une entrée de argv - il n'y a aucun shell entre les deux, donc rien n'est découpé sur les espaces et aucune mise entre guillemets n'est nécessaire : un champ contenant hello world arrive comme l'unique argument hello world. Pour passer -n 3 hello, ajoutez trois champs. Laisser le panneau vide donne argc == 1 - c'est pourquoi la garde argc < 2 se déclenche au premier lancement, et pourquoi elle mérite d'être écrite.
Erreurs courantes
- Lire
argv[1]sans vérifierargc. Comportement indéfini quand aucun argument n'a été passé - et le plantage le plus courant dans ce domaine. - Commencer la boucle à
i = 0. Cela traite le nom du programme comme une donnée. - Traiter
argv[1]comme un nombre. C'est du texte tant que vous ne l'avez pas converti. - Utiliser
atoisur une entrée utilisateur. Aucun moyen de distinguer un mauvais argument d'un zéro. - Comparer des chaînes avec
==. Utilisezstrcmp. - Écrire dans les chaînes de
argv. Les modifier est autorisé par la norme, mais l'espace est limité et dépend de la plateforme ; copiez dans votre propre tampon si vous devez changer quelque chose.
Questions fréquentes
Que sont argc et argv en C ?
Ce sont les deux paramètres de int main(int argc, char *argv[]). argc est le nombre d'arguments de ligne de commande, nom du programme inclus ; argv est un tableau de ces arguments sous forme de chaînes. argv[0] est le nom du programme, argv[1] le premier vrai argument, et argv[argc] vaut toujours NULL.
Comment passer des arguments à un programme C ?
Tapez-les après le nom de l'exécutable dans le terminal : ./program hello 42. Cela donne argc == 3, avec argv[1] la chaîne "hello" et argv[2] la chaîne "42". Dans l'éditeur de cette page, les arguments se saisissent dans le panneau Args plutôt que dans un terminal.
Comment convertir un argument de ligne de commande en int en C ?
Utilisez strtol : char *end; long n = strtol(argv[1], &end, 10); puis vérifiez que end ne pointe pas encore au début (rien n'a été analysé) et que *end vaut '\0' (pas de résidu). atoi est plus court mais renvoie 0 aussi bien pour "0" que pour "banane", il ne peut donc pas signaler d'erreur.
Qu'est-ce que argv[0] en C ?
Le nom avec lequel le programme a été invoqué - typiquement ./program ou le chemin complet. Il est utile dans les messages d'usage (fprintf(stderr, "usage : %s FICHIER\n", argv[0])) pour que le message corresponde à la façon dont l'utilisateur a réellement appelé le programme. Il peut être une chaîne vide dans des cas inhabituels, ne supposez donc pas qu'il est présent.