C course menu
Command-Line Arguments in C: argc and argv
Learn to read command-line arguments in C with argc and argv: what argv[0] holds, looping over arguments, converting arguments to numbers safely with strtol, handling options and flags, printing usage messages, and returning exit codes.
On this page
Command-line tools such as gcc, git and ls take their input from the words typed after the program name. A C program receives those words through two parameters of main.
argc and argv#
int main(int argc, char *argv[])argc(argument count) is the number of words, including the program name.argv(argument vector) is an array of strings:argv[0]is usually the program's name,argv[1]toargv[argc - 1]are the arguments, andargv[argc]isNULL.
char *argv[] and char **argv mean the same thing.
Printing the arguments#
Running ./args report.txt -v 42:
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("argc = %d\n", argc);
for (int i = 1; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}argc = 4
argv[1] = report.txt
argv[2] = -v
argv[3] = 42The loop starts at 1 to skip the program name, whose exact form depends on how the program was started. The shell splits arguments at spaces; quote an argument to keep spaces in it: ./args "my file.txt".
Converting arguments to numbers#
Arguments are always strings. Convert them with strtol or strtod and check that the whole argument was a valid number:
Running ./sum 10 20 abc 5:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
long total = 0;
int skipped = 0;
for (int i = 1; i < argc; i++) {
char *end;
long value = strtol(argv[i], &end, 10);
if (end == argv[i] || *end != '\0') {
skipped++; /* not a whole number */
continue;
}
total += value;
}
printf("total = %ld\n", total);
if (skipped > 0) fprintf(stderr, "warning: skipped %d invalid argument(s)\n", skipped);
return 0;
}total = 35
warning: skipped 1 invalid argument(s)Error messages go to stderr, so they stay separate from the program's normal output when it is redirected to a file.
Options, usage messages and exit codes#
A good command-line program checks its arguments, prints a usage message when they are wrong, and returns an exit code: 0 (EXIT_SUCCESS) for success and non-zero (EXIT_FAILURE) for failure. Scripts and other programs check this code.
Running ./greet -u --times 2 Asha:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void usage(const char *prog) {
fprintf(stderr, "usage: %s [-u] [--times N] NAME\n", prog);
}
int main(int argc, char *argv[]) {
int upper = 0;
long times = 1;
const char *name = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-u") == 0) {
upper = 1;
} else if (strcmp(argv[i], "--times") == 0 && i + 1 < argc) {
times = strtol(argv[++i], NULL, 10);
} else if (argv[i][0] == '-') {
usage(argv[0]);
return EXIT_FAILURE;
} else {
name = argv[i];
}
}
if (name == NULL || times < 1) {
usage(argv[0]);
return EXIT_FAILURE;
}
for (long t = 0; t < times; t++) {
printf("Hello, ");
for (const char *p = name; *p; p++) putchar(upper ? toupper((unsigned char)*p) : *p);
printf("!\n");
}
return EXIT_SUCCESS;
}Hello, ASHA!
Hello, ASHA!On Linux and macOS, echo $? shows the last program's exit code; in PowerShell, use $LASTEXITCODE. For complex options, POSIX systems provide the getopt function (in <unistd.h>), which is not part of standard C.
Practice#
Practice exercise
Write a program that expects exactly two arguments, a word and a file-name-like string, and prints whether the second argument ends with the first (for example ./endswith .txt notes.txt). Print a usage message and return EXIT_FAILURE when the argument count is wrong.
Show solution
Running ./endswith .txt notes.txt:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "usage: %s SUFFIX TEXT\n", argv[0]);
return EXIT_FAILURE;
}
const char *suffix = argv[1], *text = argv[2];
size_t ls = strlen(suffix), lt = strlen(text);
int ends = lt >= ls && strcmp(text + lt - ls, suffix) == 0;
printf("'%s' %s with '%s'\n", text, ends ? "ends" : "does not end", suffix);
return EXIT_SUCCESS;
}'notes.txt' ends with '.txt'Key takeaway#
Finished this lesson?