0Pricing
C Academy · 课时

getopt

标准选项解析

getopt 是 CoddyKit 上的免费 C Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C Academy 课程共包含 4 节课。

什么是 getopt

getopt 是 POSIX 函数,可以按照标准 Unix 约定为您解析单字符选项。

它定义在 <unistd.h> 中,可以省去手动解析标志的大部分样板代码。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "v")) != -1) {
        if (opt == 'v') printf("verbose on\n");
    }
    return 0;
}

选项字符串

getopt 的第三个参数是选项字符串:有效选项字母的列表。

"abc" 表示接受 -a、-b 和 -c 这三个布尔标志。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "abc")) != -1) {
        printf("saw option -%c\n", opt);
    }
    return 0;
}

解析循环

getopt 每次调用都会返回下一个选项字符,解析完成时返回 -1。

标准写法是使用 while 循环,并在其中使用 switch 根据返回的字符进行分派。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "xy")) != -1) {
        switch (opt) {
            case 'x': printf("x set\n"); break;
            case 'y': printf("y set\n"); break;
        }
    }
    return 0;
}

带参数的选项

在选项字符串中的字母后加冒号,表示该选项需要一个值。"o:" 表示 -o 需要一个参数。

该值会存放在全局变量 optarg 中。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "o:")) != -1) {
        if (opt == 'o') printf("output = %s\n", optarg);
    }
    return 0;
}

组合标志和带值选项

您可以在一个选项字符串中混合布尔选项和带值选项。这里 -v 是标志,而 -n 接收一个数字。

getopt 还允许用户将标志组合起来,例如 -vn 5。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt, verbose = 0, n = 0;
    while ((opt = getopt(argc, argv, "vn:")) != -1) {
        if (opt == 'v') verbose = 1;
        else if (opt == 'n') n = atoi(optarg);
    }
    printf("verbose=%d n=%d\n", verbose, n);
    return 0;
}

处理未知选项

当 getopt 遇到不在选项字符串中的选项时,会返回 '?' 并打印错误信息(除非您将其禁止)。

添加一个 case '?',即可妥善处理错误输入。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "a")) != -1) {
        switch (opt) {
            case 'a': printf("a\n"); break;
            case '?': printf("unknown option\n"); break;
        }
    }
    return 0;
}

缺少必需参数

如果提供了需要取值的选项,却没有提供对应的值,getopt 的行为取决于选项字符串。

在选项字符串开头加上冒号(":o:")后,getopt 会在缺少参数时返回 ':',这样您就能准确地报告问题。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, ":f:")) != -1) {
        if (opt == 'f') printf("file=%s\n", optarg);
        else if (opt == ':') printf("option needs a value\n");
    }
    return 0;
}

optind:解析停止的位置

循环结束后,全局变量 optind 保存 argv 中第一个非选项参数的索引。

您可以使用它处理剩余的位置参数,例如文件名。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "v")) != -1) { }
    for (int i = optind; i < argc; i++)
        printf("positional: %s\n", argv[i]);
    return 0;
}

禁止 getopt 输出消息

默认情况下,getopt 会将自身的错误消息打印到 stderr。将全局变量 opterr 设为 0,即可禁止这些消息并自行处理错误。

#include <stdio.h>
#include <unistd.h>

extern int opterr;

int main(int argc, char *argv[]) {
    opterr = 0;
    int opt;
    while ((opt = getopt(argc, argv, "a")) != -1) {
        if (opt == '?') printf("bad option, handled quietly\n");
    }
    return 0;
}

确定错误选项

当 getopt 返回 '?' 时,全局变量 optopt 包含导致错误的选项字符。

这样,您就可以打印一条有帮助的消息,准确指出出错的标志。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "a")) != -1) {
        if (opt == '?')
            printf("Unrecognized option: -%c\n", optopt);
    }
    return 0;
}

关于长选项的说明

普通的 getopt 只支持单字母选项。对于 --verbose 之类的长选项,GNU 系统在 <getopt.h> 中提供了 getopt_long。

它使用相同的循环,但增加了一个长选项描述符表。

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    printf("getopt parses %d short options\n", argc > 1 ? argc - 1 : 0);
    return 0;
}

快速检查

测试您对 getopt 选项字符串语法的理解。

回顾

您已经学习了使用 getopt 进行标准选项解析:

  • 当 getopt(argc, argv, optstring) 不等于 -1 时持续循环,并使用 switch 进行分派。
  • 字母后的冒号表示该选项需要一个值,该值位于 optarg 中。
  • optind 指向后续的第一个位置参数。
  • 全局变量 opterr、optopt 以及开头的冒号共同控制错误处理。

常见问题解答

「getopt」课时是免费的吗?

是的 — 「getopt」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C Academy 课程的其余内容,请升级到 CoddyKit PRO。 C Academy 课程共包含 4 节课。

「getopt」这节课中我会学到什么?

标准选项解析 你通过在浏览器中直接运行的动手代码来练习 C Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「getopt」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C Academy 课中编写并运行代码吗?

能。每节 C Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. argc 与 argv
  2. 解析选项
  3. getopt
  4. 构建 CLI 工具
← 返回 C Academy