C Command-Line Arguments: argc, argv, Parsing & Validation Masterclass
Welcome to Phase 16 (Chapter 42): C Command-Line Arguments โ argc, argv, Parsing & Validation Masterclass! Every C program can receive arguments from the operating system shell at launch time. Mastering argc and argv transforms your programs from hardcoded toys into flexible, reusable command-line tools.
ALL arguments arrive as strings (char*). To work with them as numbers you must convert explicitly using atoi(), strtol(), or strtod().
atoi() vs strtol() โ Which to Use?
โข atoi(str) โ Simple but UNSAFE. Returns 0 for invalid input ("abc") indistinguishable from the number 0. No overflow detection.
โข strtol(str, &endptr, base) โ SAFE. Sets endptr to first invalid character. Detects overflow. Always prefer this for production code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
static long safe_parse_long(const char *str, const char *name) {
char *end;
errno = 0;
long val = strtol(str, &end, 10);
if (errno != 0 || *end != '\0' || end == str) {
fprintf(stderr, "Error: '%s' is not a valid integer for %s\n", str, name);
exit(EXIT_FAILURE);
}
return val;
}
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <num1> <op: add|sub|mul|div> <num2>\n", argv[0]);
return EXIT_FAILURE;
}
long a = safe_parse_long(argv[1], "num1");
long b = safe_parse_long(argv[3], "num2");
const char *op = argv[2];
if (strcmp(op, "add") == 0) printf("%ld + %ld = %ld\n", a, b, a + b);
else if (strcmp(op, "sub") == 0) printf("%ld - %ld = %ld\n", a, b, a - b);
else if (strcmp(op, "mul") == 0) printf("%ld * %ld = %ld\n", a, b, a * b);
else if (strcmp(op, "div") == 0) {
if (b == 0) { fprintf(stderr, "Error: Division by zero\n"); return 1; }
printf("%ld / %ld = %ld\n", a, b, a / b);
} else {
fprintf(stderr, "Error: Unknown operator '%s'\n", op);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}Q1: What is argv[argc]?
By C standard guarantee, argv[argc] is always NULL. This allows null-terminated traversal: for (char **p = argv; *p; p++).
Q2: Can argv strings be modified?
Yes! Unlike string literals, argv strings are writable. You can modify argv[1][0] = 'X'; safely. But do not replace the pointer itself.
Q3: What is the difference between strtol() and sscanf() for parsing?
strtol() is more precise for integer parsing with overflow detection. sscanf() is convenient for mixed-format parsing but provides less error granularity.
Q4: How do I read optional flags like -v or --verbose?
Use POSIX getopt(argc, argv, "vho:") from <unistd.h> for Unix systems, or write a manual loop checking argv[i][0] == '-'.
Q5: How do environment variables differ from command-line arguments?
Command-line args are positional and explicit per invocation. Environment variables are inherited from the shell session and accessible via getenv("PATH").