分享

C语言getopt()的8个用法

 waston 2025-02-05 发布于上海

概况

查询 getopt 用法的“官方”步骤是看 man 手册:

man 3 getopt

不过这手册看的让人头晕,还是写几个例子,分解开来逐一击破吧!
写了8个例子,每个例子都有对应注释和示例用法;也可以在 main 函数中把 argc 和 argv 传递过去,分别调用和尝试!

int main(int argc, char** argv)

{

    //printf("opterr = %d\n", opterr);

    //opt_example1(argc, argv);

    //opt_example2(argc, argv);

    //opt_example3(argc, argv);

    //opt_example4(argc, argv);

    //opt_example5(argc, argv);

    //opt_example6(argc, argv);

    //opt_example7(argc, argv);

    opt_example8(argc, argv);

    return 0;

}

例子1

#include <stdio.h>

#include <unistd.h>

#include <stdbool.h>

#include <stdlib.h>

// -a 选项后面一定要有参数,参数和选项之间可以有空格,也可以没空格。解析出的参数放在 optarg 变量里。

// examples:

// ./a.out -a 6

// ./a.out -a6

// ./a.out -a s

// 参数也可以用引号包裹起来,这样可以包含空格.

// ./a.out -a "s b"

// ./a.out -a"s b"

void opt_example1(int argc, char** argv)

{

    const char* optstr = "a:";

    char ch;

    while ( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch (ch) {

            case 'a':

                printf("have option: -a\n");

                printf("the argument of -a is %s\n", optarg);

                break;

        }

    }

}

例子2

// -b 选项后面可以有参数,也可以没有参数。但是有参数情况下,必须有空格。若没有空格,得到的参数是 null

// examples:

// ./a.out -b

// ./a.out -b hello

void opt_example2(int argc, char** argv)

{

    const char* optstr = "b::";

    char ch;

    while ( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch (ch) {

            case 'b':

                printf("have option: -b\n");

                printf("the argument of -b is %s\n", optarg);

                break;

        }

    }

}

例子3

// -c 选项后面不能有参数。如果有参数,会被当成别的选项. 打印 optarg 得到 null

// examples:

// ./a.out -c

void opt_example3(int argc, char** argv)

{

    const char* optstr = "c";

    char ch;

    while ( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch (ch) {

            case 'c':

                printf("have option: -c\n");

                printf("the argument of -c is %s\n", optarg);

                break;

        }

    }

}

例子4

// -c 选项和 -d 选项可以合并

// examples:

// ./a.out -c -d

// ./a.out -d -c

// ./a.out -cd

// ./a.out -dc

void opt_example4(int argc, char** argv)

{

    const char* optstr = "cd";

    char ch;

    while ( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch (ch) {

            case 'c':

                printf("have option: -c\n");

                printf("the argument of -c is %s\n", optarg);

                break;

            case 'd':

                printf("have option: -d\n");

                printf("the argument of -d is %s\n", optarg);

                break;

        }

    }

}

例子5

// argv 中不以 "-" 开头的、并且不是跟在选项后面的,不会被 getopt() 解析

// 不被解析意味着, 调用 getopt() 之后会改变 argv 的元素顺序, 被解析的 选项+参数 们 在前,没被解析的在后

// examples:

// ./a.out shenme -a hello -b world

//     新版 argv 会是 ./a.out -a hello -b world shenme

// ./a.out -a hello shenme -b world

//     新版 argv 会是 ./a.out -a hello -b world shenme

// 被解析的选项们的顺序是不会被改变的. 如果没空格,也不会被更细出空格

// ./a.out shenme -b world -a hello

//     新版 argv 会是 ./a.out -b world -a hello shenme

// ./a.out shenme -bworld -a hello

//     新版 argv 会是 ./a.out -bworld -a hello shenme

// 调用 getopt() 后, optind 会指向第一个非选项和参数的位置

void opt_example5(int argc, char** argv)

{

    printf("original argv is:");

    for (int i = 0; i < argc; i++)

    {

        printf(" %s", argv[i]);

    }

    printf("\n");

    char ch;

    const char* optstr = "a:b:c:";

    while( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch(ch)

        {

        case 'a':

            break;

        case 'b':

            break;

        }

    }

    printf("after getopt, argv is:");

    for (int i = 0; i < argc; i++)

    {

        printf(" %s", argv[i]);

    }

    printf("\n");

    printf("and now, optind = %d, argv[%d] = %s\n",

        optind, optind, argv[optind]);

}

例子6

// 利用 optind 判断是否输出了指定选项和参数外的参数

// 若只输入了符合 optstr 的 argv, 则 optind 小于 argc

// 若输入了额外的参数, 则 optind 等于 argc

// examples:

// ./a.out -a hello world

//    输出: 

// optind = 3, argv[3] = world

// you have entered extra arguments: world

//

// ./a.out -a 0 hello world

//    输出:

// optind = 3, argv[3] = hello

// you have entered extra arguments: hello world

void opt_example6(int argc, char** argv)

{

    char ch;

    const char* optstr = "a:b:c:";

    while( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch(ch)

        {

        case 'a':

            break;

        case 'b':

            break;

        }

    }

    printf("optind = %d, argv[%d] = %s\n",

        optind, optind, argv[optind]);

    if (optind < argc)

    {

        printf("you have entered extra arguments:");

        for (int i = optind; i < argc; i++)

        {

            printf(" %s", argv[i]);

        }

        printf("\n");

    }

}

例子7

// argv 可能包含 getopt() 无法解析的选项,也就是不在 optstr 中的选项

// 这样的选项,对应到 getopt() 返回 `?` , 可以设置为打印help信息

// examples:

// ./a.out -s

//   输出

// ./a.out: invalid option -- 's'

// Usage: ./a.out -a <a_arg> -b <b_arg>

void opt_example7(int argc, char** argv)

{

    char ch;

    const char* optstr = "a:b:c:";

    while( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch(ch)

        {

        case 'a':

            break;

        case 'b':

            break;

        case '?':

            printf("Usage: %s -a <a_arg> -b <b_arg>\n", argv[0]);

        }

    }

}

例子8

void help_and_die(char* argv0)

{

    printf("Usage: %s [-hv] -s <num> -E <num> -b <num> -t <file>\n", argv0);

    printf("Options:\n");

    printf("  -h         Print this help message.\n");

    printf("  -v         Optional verbose flag.\n");

    printf("  -s <num>   Number of set index bits.\n");

    printf("  -E <num>   Number of lines per set.\n");

    printf("  -b <num>   Number of block offset bits.\n");

    printf("  -t <file>  Trace file.\n");

    printf("\n");

    printf("Examples:\n");

    printf("  linux>  %s -s 4 -E 1 -b 4 -t traces/yi.trace\n", argv0);

    printf("  linux>  %s -v -s 8 -E 2 -b 4 -t traces/yi.trace\n", argv0);

    exit(0);

}

// CSAPP CacheLab 的例子,模拟 csim-ref 的参数解析

void opt_example8(int argc, char* argv[])

{

    const char* optstr = "hvs:E:b:t:";

    char ch;

    bool verbose = false;

    int s = -1;

    int E = -1;

    int b = -1;

    int t = -1;

    while( (ch = getopt(argc, argv, optstr)) != -1 )

    {

        switch (ch)

        {

        case 'h':

            help_and_die(argv[0]);

            exit(0);

            break;

        case 'v':

            verbose = true;

            break;

        case 's':

            s = atoi(optarg);

            break;

        case 'E':

            E = atoi(optarg);

            break;

        case 'b':

            b = atoi(optarg);

            break;

        case 't':

            t = atoi(optarg);

            break;

        case '?':

            help_and_die(argv[0]);

            break;

        }

    }

    if (optind == 1)

    {

        printf("%s: Missing required command line argument\n", argv[0]);

        help_and_die(argv[0]);

    }

}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多