手寫參數解析既繁瑣又易錯。POSIX 標準庫提供 getopt()(短選項)與 getopt_long()(長選項),是專業 C 程序處理命令行參數的標準方式。
#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg; // 選項參數指針
extern int optind; // 下一個待處理 argv 下標
extern int opterr; // 錯誤輸出開關(0=關閉)
extern int optopt; // 未識別的選項字符
"ab:c::":a 無參數,b 必須有參數(-b value 或 -bvalue),c 可選參數(需 -cvalue 緊湊形式): 表示需參數,跟 :: 表示可選參數
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct {
int a_flag;
int b_flag;
char *b_arg;
int c_flag;
char *c_arg;
} Options;
int main(int argc, char **argv) {
Options opt = {0};
int c;
// 關閉默認錯誤輸出,自行處理
opterr = 0;
while ((c = getopt(argc, argv, "ab:c::")) != -1) {
switch (c) {
case 'a': opt.a_flag = 1; break;
case 'b': opt.b_flag = 1; opt.b_arg = optarg; break;
case 'c': opt.c_flag = 1; opt.c_arg = optarg; break; // optarg 可能為 NULL
case '?':
fprintf(stderr, "未知選項: -%c\n", optopt);
break;
}
}
// 處理非選項參數(文件名等)
printf("非選項參數: ");
for (int i = optind; i < argc; i++) printf("%s ", argv[i]);
printf("\n");
// 輸出解析結果
printf("解析結果: a=%d, b=%d(%s), c=%d(%s)\n",
opt.a_flag, opt.b_flag, opt.b_arg ?: "無",
opt.c_flag, opt.c_arg ?: "無");
return 0;
}
$ ./a.out -a -b hello -cworld file1 file2
非選項參數: file1 file2
解析結果: a=1, b=1(hello), c=1(world)
struct option {
const char *name; // 長選項名(如 "help")
int has_arg; // no_argument(0), required_argument(1), optional_argument(2)
int *flag; // 非NULL時設置*flag=val,返回0;NULL時返回val
int val; // 短選項字符或自定義值
};
#include <getopt.h> // 需額外包含
static struct option long_opts[] = {
{"help", no_argument, 0, 'h'},
{"output", required_argument, 0, 'o'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0} // 結束標記
};
int main(int argc, char **argv) {
int c, opt_idx = 0;
while ((c = getopt_long(argc, argv, "ho:v", long_opts, &opt_idx)) != -1) {
switch (c) {
case 'h': printf("幫助信息...\n"); exit(0);
case 'o': printf("輸出文件: %s\n", optarg); break;
case 'v': printf("詳細模式開啟\n"); break;
case '?': exit(1);
case 0: // flag 非 NULL 時進入
break;
}
}
return 0;
}
| 變量 | 含義 | 典型用法 |
|---|---|---|
| optarg | 當前選項的參數字符串 | opt.b_arg = optarg; |
| optind | 下一次掃描的 argv 下標 | 處理非選項參數:argv[optind]... |
| opterr | 非零時自動打印錯誤到 stderr | opterr=0 關閉,自行處理 |
| optopt | 未識別選項/缺參數時的選項字符 | case '?': fprintf(stderr, "-%c", optopt); |
optind 定位:: 要求 -cvalue 緊湊形式,-c value 會被視為非選項flag 非 NULL 時不返回 val,而是 *flag = val,返回 0getopt,需移植版或用 getopt_long 兼容層| 特性 | getopt() | getopt_long() |
|---|---|---|
| 頭文件 | <unistd.h> | <getopt.h> |
| 選項形式 | 單字符 -a | 短 -a + 長 --all |
| 可選參數 | 支持 :: | 支持 optional_argument |
| 標準 | POSIX.1-2001 | GNU 擴展(廣泛可用) |
掌握 getopt/getopt_long 是編寫專業級命令行工具的基本功。它們處理了選項識別、參數關聯、錯誤報告、非選項分離等所有繁瑣邏輯,讓主程序專注於業務。記住:opterr=0 自定義錯誤輸出,optind 處理剩餘參數,長選項用 struct option 數組聲明。