[转载]Linux下getopt()函数的简单使用
转载源地址:https://www.cnblogs.com/qingergege/p/5914218.html
1、getopt()函数的出处就是unistd.h头文件(哈哈),写代码的时候千万不要忘记把他老人家include上。
2、原型:int getopt(int argc,char * const argv[ ],const char * optstring);
1)前两个参数就是main函数的两个参数;
2)第三个参数是个字符串,看名字,我们可以叫他选项字符串(后面会说明)
3)返回值返回的就是一个字符,什么字符呢,叫选项字符
3、(⊙o⊙)…在此之前还要介绍他的几个兄弟~~~~呃呃呃
小弟1、extern char* optarg;
小弟2、extern int optind;
小弟3、extern int opterr;
小弟4、extern int optopt;
队形排的不错。小弟1是用来保存选项的参数的(先混个脸熟,后面有例子);小弟2用来记录下一个检索位置;小弟3表示的是是否将错误信息输出到stderr,为0时表示不输出,小弟4表示不在选项字符串optstring中的选项(有点乱哈,后面会有例子)
问题1:选项到底是个什么鬼?
在linux下大家都用过这样一条指令吧:gcc helloworld.c -o helloworld.out; 这条指令中的-o就是命令行的选项,而后面的helloworld.out就是-o选项所携带的参数。当然熟悉shell指令的人都知道(虽然我并不熟悉),有些选项是不用带参数的,而这样不带参数的选项可以写在一起(这一点在后面的例子中会用到,希望理解),比如说有两个选项-c和-d,这两个选项都不带参数(而且明显是好基友),那么他们是可以写在一起,写成-cd的。实际的例子:当我们删除一个文件夹时可以使用指令 rm 目录名 -rf,本来-r表示递归删除,就是删除文件夹中所有的东西,-f表示不提示就立刻删除,他们两个都不带参数,这时他们就可以写在一起。
问题2:选项字符串又是何方神圣?
还是看个例子吧
"a:b:cd::e",这就是一个选项字符串。对应到命令行就是-a ,-b ,-c ,-d, -e 。冒号又是什么呢? 冒号表示参数,一个冒号就表示这个选项后面必须带有参数(没有带参数会报错哦),但是这个参数可以和选项连在一起写,也可以用空格隔开,比如-a123 和-a 123(中间有空格) 都表示123是-a的参数;两个冒号的就表示这个选项的参数是可选的,即可以有参数,也可以没有参数,但要注意有参数时,参数与选项之间不能有空格(有空格会报错的哦),这一点和一个冒号时是有区别的。
好了,先给个代码,然后再解释吧。

#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{ int ch;
printf("\n\n");
printf("optind:%d,opterr:%d\n",optind,opterr);
printf("--------------------------\n");
while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
{
printf("optind: %d\n", optind);
switch (ch)
{
case 'a':
printf("HAVE option: -a\n\n");
break;
case 'b':
printf("HAVE option: -b\n");
printf("The argument of -b is %s\n\n", optarg);
break;
case 'c':
printf("HAVE option: -c\n");
printf("The argument of -c is %s\n\n", optarg);
break;
case 'd':
printf("HAVE option: -d\n");
break;
case 'e':
printf("HAVE option: -e\n");
printf("The argument of -e is %s\n\n", optarg);
break;
case '?':
printf("Unknown option: %c\n",(char)optopt);
break;
}
} }

编译后命令行执行:# ./main -b "qing er"
输出结果为:
optind:1,opterr:1
--------------------------
optind: 3
HAVE option: -b
The argument of -b is qing er
我们可以看到:optind和opterr的初始值都为1,前面提到过opterr非零表示产生的错误要输出到stderr上。那么optind的初值为什么是1呢?
这就要涉及到main函数的那两个参数了,argc表示参数的个数,argv[]表示每个参数字符串,对于上面的输出argc就为3,argv[]分别为: ./main 和 -b 和"qing er" ,实际上真正的参数是用第二个-b 开始,也就是argv[1],所以optind的初始值为1;
当执行getopt()函数时,会依次扫描每一个命令行参数(从下标1开始),第一个-b,是一个选项,而且这个选项在选项字符串optstring中有,我们看到b后面有冒号,也就是b后面必须带有参数,而"qing er"就是他的参数。所以这个命令行是符合要求的。至于执行后optind为什么是3,这是因为optind是下一次进行选项搜索的开始索引,也是说下一次getopt()函数要从argv[3]开始搜索。当然,这个例子argv[3]已经没有了,此时getopt()函数就会返回-1。
再看一个输入:
./main -b "qing er" -c1234
输出结果为:
optind:1,opterr:1
--------------------------
optind: 3
HAVE option: -b
The argument of -b is qing er
optind: 4
HAVE option: -c
The argument of -c is 1234
对于这个过程会调用三次getopt()函数,和第一个输入一样,是找到选项-b和他的参数"qing er",这时optind的值为3,也就意味着,下一次的getopt()要从argv[3]开始搜索,所以第二次调用getopt()函数,找到选项-c和他的参数1234(选项和参数是连在一起的),由于-c1234写在一起,所以他两占一起占用argv[3],所以下次搜索从argv[4]开始,而argv[4]为空,这样第三次调用getopt()函数就会返回-1,循环随之结束。
接下来我们看一个错误的命令行输入: ./main -z 123
输出为:
optind:1,opterr:1
--------------------------
./main: invalid option -- 'z'
optind: 2
Unknown option: z
其中./main: invalid option -- 'z'就是输出到stderr的错误输出。如果把opterr设置为0那么就不会有这条输出。
在看一个错误的命令行输入: ./main -zheng
optind:1,opterr:1
--------------------------
./main: invalid option -- 'z'
optind: 1
Unknown option: z
./main: invalid option -- 'h'
optind: 1
Unknown option: h
optind: 2
HAVE option: -e
The argument of -e is ng
前面提到过不带参数的选项可以写在一起,所以当getopt()找到-z的时候,发现在optstring 中没有,这时候他就认为h也是一个选项,也就是-h和-z写在一起了,依次类推,直到找到-e,发现optstring中有。
最后要说明一下,getopt()会改变argv[]中参数的顺序。经过多次getopt()后,argv[]中的选项和选项的参数会被放置在数组前面,而optind 会指向第一个非选项和参数的位置。看例子

#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{ int i;
printf("--------------------------\n");
for(i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
printf("--------------------------\n");
//int aflag=0, bflag=0, cflag=0; int ch;
printf("\n\n");
printf("optind:%d,opterr:%d\n",optind,opterr);
printf("--------------------------\n");
while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
{
printf("optind: %d\n", optind);
switch (ch)
{
case 'a':
printf("HAVE option: -a\n\n");
break;
case 'b':
printf("HAVE option: -b\n");
printf("The argument of -b is %s\n\n", optarg);
break;
case 'c':
printf("HAVE option: -c\n");
printf("The argument of -c is %s\n\n", optarg);
break;
case 'd':
printf("HAVE option: -d\n");
break;
case 'e':
printf("HAVE option: -e\n");
printf("The argument of -e is %s\n\n", optarg);
break;
case '?':
printf("Unknown option: %c\n",(char)optopt);
break;
}
} printf("----------------------------\n");
printf("optind=%d,argv[%d]=%s\n",optind,optind,argv[optind]); printf("--------------------------\n");
for(i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
printf("--------------------------\n"); }

命令行:./main zheng -b "qing er" han -c123 qing
输出结果为:
--------------------------
./main
zheng
-b
qing er
han
-c123
qing
--------------------------
optind:1,opterr:1
--------------------------
optind: 4
HAVE option: -b
The argument of -b is qing er
optind: 6
HAVE option: -c
The argument of -c is 123
----------------------------
optind=4,argv[4]=zheng
--------------------------
./main
-b
qing er
-c123
zheng
han
qing
--------------------------
可以看到最开始argv[]内容为:
./main
zheng
-b
qing er
han
-c123
qing
在执行了多次getopt后变成了
./main
-b
qing er
-c123
zheng
han
qing
我们看到,被getopt挑出的选项和对应的参数都按顺序放在了数组的前面,而那些既不是选项又不是参数的会按顺序放在后面。而此时optind为4,即指向第一个非选项也非选项的参数,zheng
花了40多分钟整理,希望能够给需要的人带来帮助。
很多时候我都在寻思,为啥要花时间整理,明明已经非常忙碌了,有这点时间休息一下多好,多惬意?
我总结的原因有一下几个:
1、总结时会注意到之前没有关注的问题,可以加深对问题的理解。
2、方便以后忘记的时候查阅
3、与广大朋友们分享,想想我们从哪些大牛的博客里得到的太多了。我们应当向那些大神学习。把自己学到的分享出来,帮助其他人(虽然我很渣,但是三人行必有我师,应该还是会帮到些人吧)。
共勉!努力!
最后给大家介绍一个写的更加全面的文章:http://blog.csdn.net/huangxiaohu_coder/article/details/7475156
[转载]Linux下getopt()函数的简单使用的更多相关文章
- Linux下getopt()函数的简单使用
最近在弄Linux C编程,本科的时候没好好学啊,希望学弟学妹们引以为鉴. 好了,虽然啰嗦了点,但确实是忠告.步入正题: 我们的主角----getopt()函数. 英雄不问出处,getopt()函数的 ...
- Linux下getopt()函数
from https://www.cnblogs.com/qingergege/p/5914218.html 最近在弄Linux C编程,本科的时候没好好学啊,希望学弟学妹们引以为鉴. 好了,虽然啰嗦 ...
- 对于linux下system()函数的深度理解(整理)
原谅: http://blog.sina.com.cn/s/blog_8043547601017qk0.html 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同 ...
- 转:对于linux下system()函数的深度理解(整理)
这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...
- (笔记)Linux下system()函数的深度理解(整理)
注:从其它地方转的非常好的一篇文章,值得深究! 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数 ...
- linux select函数:Linux下select函数的使用详解【转】
本文转载自;http://www.bkjia.com/article/28216.html Linux下select函数的使用 Linux下select函数的使用 一.Select 函数详细介绍 Se ...
- 【C/C++】Linux下system()函数引发的错误
http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食 恋恋美食 发布时间: 2012/04/21 11:3 ...
- [转帖]Linux下fork函数及pthread函数的总结
Linux下fork函数及pthread函数的总结 https://blog.csdn.net/wangdd_199326/article/details/76180514 fork Linux多进程 ...
- linux下syscall函数,SYS_gettid,SYS_tgkill
出处:http://blog.chinaunix.net/uid-28458801-id-4630215.html linux下syscall函数,SYS_gettid,SYS_tgkill ...
随机推荐
- watch和computed的用法区别是什么?
在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作.模板是为了描述视图的结构.在模板中放入太多的逻辑会让模板过重且难以维护.这就是为什么 Vue.js 将绑定表达式限制为一个表达式.如果需 ...
- 1D mesauring
The Basics of Measure Objects 2.1 the process of 1D Edge extraction Then, the mean ...
- 使用游标、存储过程、pivot 三种方法导入数据
--使用游标循环 if (exists (select * from sys.objects where name = 'Base_RecordTend_Test')) drop proc Base_ ...
- 关于Qt中使用线程的时候函数具体在哪个线程中运行的问题
在子线程中,run函数中以及其中调用的都在单独的子线程里面运行,但是其他的类似构造函数之流都是在主线程里面运行的,不要搞混了
- vux配置i18n
根据使用文档,先引入i18n import VueI18n from 'vue-i18n'; Vue.use(VueI18n) const i18n = new VueI18n({ locale: ' ...
- C# Http方式下载文件到本地类
直接上代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using S ...
- pdf 转图片,提取图片研究心得
1.pdf 中的数据是有多种编码的,详情请看:http://www.cnblogs.com/zendu/p/7644465.html 2.我的工作场景比较特殊,pdf中全部是图片,所以pdf转图片就有 ...
- swift 定义枚举和结构体 及使用
//定义枚举 enum MapDirection { case North case South case East case West func simpleDescription() -> ...
- iPhone开发资源汇总
如何用Facebook graphic api上传视频: http://developers.facebook.com/blog/post/532/ Keychain保存数据封装: https://g ...
- 【剑指offer】不使用除法,构建乘积数组,C++实现
# 题目 # 思路 设C[i] = A[0] * A[1] * - * A[i-1],D[i] = A[i+1] * - * A[n-1],则C[i]按照从上到下的顺序计算,即C[i] = C[i- ...