C语言getopt()的8个用法
2022/2/21 6:27:43
本文主要是介绍C语言getopt()的8个用法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- 概况
- 例子1
- 例子2
- 例子3
- 例子4
- 例子5
- 例子6
- 例子7
- 例子8
概况
做 CSAPP 的 CacheLab 的第一个门槛是学习使用 getopt()
函数。它是 Linux 下的函数,Windows 先不考虑了。
查询 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]); } }
这篇关于C语言getopt()的8个用法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享