# getopt.h Parsing `argv` by hand gets old fast once you have more than two flags. **`getopt.h`** is a POSIX/GNU header that provides `getopt` for short options (`-v`, `-o file`) and `getopt_long` for long options (`--verbose`, `--output=file`). It handles the argument loop, the option string, and the `optarg`/`optind` bookkeeping. ```c #include #include int main(int argc, char *argv[]) { int verbose = 0; const char *outfile = NULL; int c; while ((c = getopt(argc, argv, "vo:")) != -1) { switch (c) { case 'v': verbose = 1; break; case 'o': outfile = optarg; break; // optarg points to the argument case '?': return 1; // unknown option, getopt printed an error } } // non-option arguments start at argv[optind] for (int i = optind; i < argc; i++) printf("input: %s\n", argv[i]); return 0; } ``` The option string `"vo:"` means: `-v` takes no argument; `-o` requires one (the colon). A leading colon in the string (`":vo:"`) suppresses getopt's automatic error message and returns `':'` for a missing argument instead, letting you handle errors yourself. `getopt_long` adds long option support via a `struct option` array: ```c static struct option long_opts[] = { {"verbose", no_argument, NULL, 'v'}, {"output", required_argument, NULL, 'o'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0} // sentinel }; while ((c = getopt_long(argc, argv, "vo:h", long_opts, NULL)) != -1) { ... } ``` The third field in `struct option` can point to a flag variable to set instead of returning a character — useful for boolean flags you want to set directly. Long options with `optional_argument` require `--opt=value` syntax; `--opt value` is not recognised as providing an argument. `getopt` permutes `argv` as it processes it, moving non-option arguments to the end (GNU behaviour). Setting `POSIXLY_CORRECT` in the environment, or using a leading `+` in the option string, stops processing at the first non-option argument instead. ## Practice ```c // compile: gcc -o tool tool.c // run: ./tool -v --output=out.txt file1.txt file2.txt // description: parse a mix of short and long options #include #include int main(int argc, char *argv[]) { int verbose = 0; const char *outfile = "a.out"; int c; static struct option opts[] = { {"verbose", no_argument, NULL, 'v'}, {"output", required_argument, NULL, 'o'}, {0, 0, 0, 0} }; while ((c = getopt_long(argc, argv, "vo:", opts, NULL)) != -1) { switch (c) { case 'v': verbose = 1; break; case 'o': outfile = optarg; break; case '?': return 1; } } printf("verbose=%d output=%s\n", verbose, outfile); for (int i = optind; i < argc; i++) printf(" input: %s\n", argv[i]); return 0; } ``` Try `./tool --output out.txt file.txt` (space-separated) — it works. Then try `./tool --output=out.txt file.txt` (equals sign) — it also works. Now try `optional_argument` for a flag and compare: `--opt value` will not bind `value` as the argument, only `--opt=value` will.