Lis ce que l'utilisateur te donne.
argc et argv sont les deux paramètres que le système d'exploitation passe à main() quand tu lances un programme depuis le terminal. Ils permettent à ton programme de recevoir des arguments en ligne de commande.
int main(int argc, char **argv)
{
/* argc = argument count — nombre d'arguments (toujours >= 1)
argv = argument vector — tableau de chaînes de caractères */
return (0);
}
Imagine que tu lances un jeu depuis un launcher en ligne de commande : ./game --level 5 --player "Link". Le launcher compte les mots que tu as tapés (argc) et te les passe dans un tableau de chaînes (argv). Ton programme peut alors lire chaque argument comme s'il ouvrait les cases d'un inventaire.
int argc — argument count
Nombre total d'arguments, incluant le nom du programme. Toujours ≥ 1.
char **argv — argument vector
Tableau de pointeurs vers des chaînes. argv[0] = nom du programme. Toujours terminé par NULL.
./prog hello 42Commande tapée : ./prog hello 42
argv[2] vaut "42" — c'est une chaîne de caractères, PAS un entier. Pour l'utiliser comme nombre : atoi(argv[2]) ou strtol(argv[2], NULL, 10)./* Quand tu n'as pas besoin des args */
int main(void)
{
printf("Hello World\n");
return (0);
}
Utilise cette forme quand ton programme ne lit aucun argument — Betty approuve !
/* Quand tu lis des arguments */
int main(int argc, char **argv)
{
/* ou : char *argv[] — équivalent */
return (0);
}
char **argv et char *argv[] sont strictement équivalents en paramètre de fonction.
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
/* Afficher argc */
printf("Nombre d'arguments : %d\n", argc);
/* Méthode 1 — boucle avec index (plus lisible) */
i = 0;
while (i < argc)
{
printf("argv[%d] = \"%s\"\n", i, argv[i]);
i++;
}
/* Méthode 2 — boucle sur pointeur (sentinelle NULL) */
char **ptr = argv;
while (*ptr != NULL)
{
printf("%s\n", *ptr);
ptr++;
}
/* Accès direct */
printf("Programme : %s\n", argv[0]); /* toujours safe */
if (argc > 1)
printf("1er arg : %s\n", argv[1]); /* vérifier avant ! */
return (0);
}
argc > N avant d'accéder à argv[N]. Accéder à argv[1] sans vérifier quand l'utilisateur n'a donné aucun argument → undefined behavior.#include <stdlib.h> /* atoi, atof, strtol, strtod */
#include <stdio.h>
int main(int argc, char **argv)
{
int n;
double f;
long l;
if (argc < 2)
{
fprintf(stderr, "Usage: %s <nombre>\n", argv[0]);
return (1);
}
n = atoi(argv[1]); /* string → int (simple, pas de gestion d'erreur) */
f = atof(argv[1]); /* string → double */
l = strtol(argv[1], NULL, 10); /* string → long (gestion d'erreur possible) */
printf("int : %d\n", n);
printf("double : %f\n", f);
printf("long : %ld\n", l);
return (0);
}
| Fonction | Retourne | Gestion erreur | Usage |
|---|---|---|---|
| atoi(str) | int | ❌ aucune | Conversion simple, Holberton OK |
| atof(str) | double | ❌ aucune | Flottants |
| atol(str) | long | ❌ aucune | Grands entiers |
| strtol(str, end, base) | long | ✅ via errno | Robuste, base configurable |
| strtod(str, end) | double | ✅ via errno | Flottants robustes |
atoi("abc") retourne 0 sans signaler d'erreur. En production utilise strtol. À Holberton, atoi est généralement accepté.#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
/* ── Vérifier le nombre d'arguments ─────────────── */
if (argc != 3)
{
fprintf(stderr, "Usage: %s <nom> <age>\n", argv[0]);
return (1);
}
/* ── Utiliser les arguments validés ──────────────── */
char *name = argv[1];
int age = atoi(argv[2]);
printf("Nom : %s\n", name);
printf("Age : %d\n", age);
return (0);
}
/*
* $ ./prog Alice 25
* Nom : Alice
* Age : 25
*
* $ ./prog
* Usage: ./prog <nom> <age>
*/
stderr avec fprintf(stderr, ...), et retourner 1 (ou EXIT_FAILURE) en cas d'erreur. C'est la convention Unix.#include <stdio.h>
int main(int argc, char **argv)
{
int i = 1; /* on commence à 1 pour sauter argv[0] */
while (i < argc)
{
printf("%s\n", argv[i]);
i++;
}
return (0);
}
/*
* $ ./prog un deux trois
* un
* deux
* trois
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int sum = 0;
int i = 1;
if (argc < 2)
{
fprintf(stderr, "Usage: %s <n1> [n2 ...]\n", argv[0]);
return (1);
}
while (i < argc)
{
sum += atoi(argv[i]);
i++;
}
printf("Somme : %d\n", sum);
return (0);
}
/*
* $ ./sum 10 20 30 5
* Somme : 65
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
int a;
int b;
if (argc != 4)
{
fprintf(stderr, "Usage: %s <n1> <op> <n2>\n", argv[0]);
fprintf(stderr, " op: + - * /\n");
return (1);
}
a = atoi(argv[1]);
b = atoi(argv[3]);
if (strcmp(argv[2], "+") == 0)
printf("%d\n", a + b);
else if (strcmp(argv[2], "-") == 0)
printf("%d\n", a - b);
else if (strcmp(argv[2], "*") == 0)
printf("%d\n", a * b);
else if (strcmp(argv[2], "/") == 0)
{
if (b == 0)
{
fprintf(stderr, "Error: division by zero\n");
return (1);
}
printf("%d\n", a / b);
}
else
{
fprintf(stderr, "Error: unknown operator '%s'\n", argv[2]);
return (1);
}
return (0);
}
/*
* $ ./calc 10 + 5 → 15
* $ ./calc 10 / 0 → Error: division by zero
* $ ./calc 7 "*" 6 → 42 (guillemets pour le shell)
*/
* est un caractère spécial (glob). Passe-le entre guillemets : ./calc 7 "*" 6 ou échappe-le : ./calc 7 \* 6./* Accéder sans vérifier */
int main(int argc, char **argv)
{
printf("%s\n", argv[1]);
/* ❌ si pas d'arg → segfault */
}
/* Utiliser argv[1] comme int direct */
int n = argv[1]; /* ❌ c'est un char* ! */
/* Modifier argv[0] */
argv[0][0] = 'X';
/* ❌ comportement indéfini */
/* Oublier argc dans la signature */
int main(char **argv)
/* ❌ signature invalide */
/* Toujours vérifier argc */
int main(int argc, char **argv)
{
if (argc < 2)
return (1);
printf("%s\n", argv[1]); /* ✅ */
}
/* Convertir avec atoi */
int n = atoi(argv[1]); /* ✅ */
/* Lire argv[0], pas le modifier */
printf("%s\n", argv[0]); /* ✅ */
/* Signatures valides */
int main(int argc, char **argv)
int main(int argc, char *argv[])
/* ✅ les deux sont équivalents */
argv[0] = nom du programme — toujours présent
Même si tu lances ./prog sans rien d'autre, argc = 1 et argv[0] = "./prog". Le compteur part de 1, pas de 0.
argv[argc] vaut toujours NULL
C'est garanti par la norme C. Tu peux itérer avec while (*argv) ou while (argv[i]) comme alternative à compter avec argc.
char * (strings)
Même "42" ou "3.14" sont des chaînes. Convertis toujours avec atoi, atof ou strtol avant d'utiliser comme nombre.
stderr, retour 1
Convention Unix : les erreurs vont sur stderr avec fprintf(stderr, ...). Retourne 1 ou EXIT_FAILURE en cas d'erreur, 0 ou EXIT_SUCCESS si tout va bien.
Un argument avec un espace doit être entre guillemets : ./prog "Hello World" → argv[1] = "Hello World" (1 seul argument). Sans guillemets → 2 arguments séparés.
$ ./prog "Hello World" → argc=2, argv[1]="Hello World"
$ ./prog Hello World → argc=3, argv[1]="Hello", argv[2]="World"
Les chaînes dans argv pointent vers la mémoire gérée par le système. Copie dans un buffer local si tu dois modifier : char buf[256]; strcpy(buf, argv[1]);
/*
* SIGNATURES VALIDES
* ───────────────────────────────────────────────────────────
* int main(void) ← pas d'args
* int main(int argc, char **argv) ← standard
* int main(int argc, char *argv[]) ← équivalent
*
* CE QUE CONTIENT ARGV
* ───────────────────────────────────────────────────────────
* argv[0] = nom/chemin du programme (toujours présent)
* argv[1] = 1er argument utilisateur
* argv[argc-1] = dernier argument
* argv[argc] = NULL (sentinelle)
*
* RÈGLES D'OR
* ───────────────────────────────────────────────────────────
* 1. argc >= 1 TOUJOURS (argv[0] compte)
* 2. Vérifier argc avant d'accéder à argv[N]
* 3. argv[i] est toujours un char* — convertir avec atoi/strtol
* 4. Erreurs → fprintf(stderr) + return (1)
* 5. Succès → return (0)
* 6. Espaces dans un arg → guillemets dans le shell
*
* PATTERN HOLBERTON STANDARD
* ───────────────────────────────────────────────────────────
* int main(int argc, char **argv)
* {
* if (argc != N)
* {
* fprintf(stderr, "Usage: %s \n", argv[0]);
* return (1);
* }
* [... utiliser argv[1] à argv[N-1] ...]
* return (0);
* }
*/