Linux——C编程 getopt函数

298 阅读2分钟

1. 家族

  • 头文件:unistd.h
  • 原型:int getopt(int argc,char * const argv[ ],const char * optstring)
  • 小弟1:extern char* optarg; 保存选项的参数;
  • 小弟2:extern int optind; 保存下一个检索位置;
  • 小弟3:extern int opterr; 保存错误信息;
  • 小弟4:extern int optopt;

2. 选项/选项字符串

  • 选项 "gcc helloworld.c -o helloworld.out" 中-o就是选项, helloworld.out就是参数。特殊的是,当某些选项不带参数时可以一起使用,如rm -rf,tar -vjzf等等。
  • 选项字符串 "a:b:cd::e",这就是一个选项字符串。对应到命令行就是-a ,-b ,-c ,-d, -e 。
    冒号表示参数,一个冒号就表示这个选项后面必须带有参数(没有带参数会报错哦),但是这个参数可以和选项连在一起写,也可以用空格隔开,比如-a123 和-a 123(中间有空格) 都表示123是-a的参数;
    两个冒号的就表示这个选项的参数是可选的,但要注意有参数时,参数与选项之间不能有空格(有空格会报错的哦),这一点和一个冒号时是有区别的。

3. 实战

int main(int argc, char * argv[])
{
    int i;
    printf("--------------------------\n");
    for(i=0;i<argc;i++)
    {
        printf("%s\n",argv[i]);
    }
    printf("--------------------------\n");
    int ch;
    printf("optind:%d,opterr:%d\n",optind,opterr);
    printf("--------------------------\n");
    printf("----------------------------\n");
    while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
    {
        switch (ch)
        {
               case 'a':
                       printf("HAVE option: -a\n");
                       break;
               case 'b':
                       printf("HAVE option: -b\n");
                       printf("The argument of -b is %s\n", optarg);
                       break;
               case 'c':
                       printf("HAVE option: -c\n");
                       printf("The argument of -c is %s\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", optarg);
                       break;
               case '?':
                       printf("Unknown option: %c\n",(char)optopt);
                       break;
          }
          printf("optind=%d,argv[%d]=%s\n\n",optind,optind,argv[optind]);
    }
    printf("--------------------------\n");
    for(i=0;i<argc;i++)
    {
        printf("%s\n",argv[i]);
    }
    printf("--------------------------\n");
}
  • 常规情况
输入: ./getopt -ab x -c y -de z
输出: 
--------------------------
./getopt
-ab
x
-c
y
-de
z
--------------------------
optind:1,opterr:1			//可见初始值为1
--------------------------
----------------------------
HAVE option: -a
optind=1,argv[1]=-ab			//ab粘合导致下次还是1

HAVE option: -b
The argument of -b is x
optind=3,argv[3]=-c

HAVE option: -c
The argument of -c is y
optind=5,argv[5]=-de

HAVE option: -d
optind=5,argv[5]=-de

HAVE option: -e
The argument of -e is (null)
optind=6,argv[6]=z

--------------------------
./getopt
-ab
x
-c
y
-de
z
--------------------------
  • 错误输入特殊情况
输入:./getopt -zheng
输出:
--------------------------
./getopt
-zheng
--------------------------
optind:1,opterr:1
--------------------------
----------------------------
./getopt: invalid option -- 'z'
Unknown option: z					// case '?'的内容
optind=1,argv[1]=-zheng

./getopt: invalid option -- 'h'
Unknown option: h
optind=1,argv[1]=-zheng

HAVE option: -e						//查到正确的为止
The argument of -e is ng
optind=2,argv[2]=(null)

--------------------------
./getopt
-zheng
--------------------------
  • 值得注意情况argv[]的改变
输入:./getopt para1 -b x -c y para2
输出:
--------------------------
./getopt
para1
-b
x
-c
y
para2
--------------------------
optind:1,opterr:1
--------------------------
----------------------------
HAVE option: -b
The argument of -b is x
optind=4,argv[4]=-c

HAVE option: -c
The argument of -c is y
optind=6,argv[6]=para2

--------------------------
./getopt
-b								//将选项及其参数移到了前面
x
-c
y
para1
para2
--------------------------