c语言学习笔记:命令行参数与命令行分析函数getopt()

       初识c语言时,我一直将main函数写作 int main(void),但随着学习的深入,我了解到main函数身为一个函数,当然也可以接收输入的参数,它的参数就是进程开始时输入的命令。所以main函数的完整形式应该写作:

int main(int argc,char *argv[]),其中argc是一个int型变量,储存命令参数的个数,argv是一个指针数组名

(所以char *argv[] 也可以写作char **argv),其中保存着命令参数字符串。

       可以写一个小程序打印传入main函数的命令参数:

       test.c

       #include

       int main(int argc,char *argv[])
       {
          int count;
          while(count < argc){
              printf("argv[%d]:%s\n",count,argv[count]);
              count++;
          }
          return 0;
       }

       将test.c编译运行,并在运行时随意添加一些参数。



           从运行结果可以看到,运行时输入的命令被保存在argv[]中。

        需要注意的是argv[]的第一个元素argv[0]默认保存的是程序名,而且argv[]是以NULL结尾的,也就是说当有n个命令参数被保存在argv[]中时,数组中第n+1个元素是NULL,即argv[argc]是NULL。将test.c稍修改一下即可验证:


       test.c

       #include

       int main(int argc,char *argv[])
       {
          int count;
          while(count < argc){
              printf("argv[%d]:%s\n",count,argv[count]);
              count++;
          }

          printf("argv[%d]:%s\n",count,argv[count]);

          return 0;
       }


c语言学习笔记:命令行参数与命令行分析函数getopt()_第1张图片






       当然,只给main函数传递参数是不够的,我们还需要在函数里分析参数,下面简要介绍常用的命令参数分析函数getopt()

        


             函数原型:

          #include

        extern char *optarg;
        extern int optind,  // 初始化值为1,下一次调用getopt时,从optind存储的位置重新开始检查选项,也就是从下一个'-'的选项开始。
        extern int opterr,  // 初始化值为1,当opterr=0时,getopt不向stderr输出错误信息。
       

        extern int optopt;  // 当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt中,getopt返回’?’。

       
        int getopt(int argc,char * const argv[ ],const char * optstring);



       argv[]数组中第1个元素argv[0]是程序名,真正的参数从第二个元素开始,即argv[1],所以optind被初始化为1。 每调用一次getopt()函数,返回一个选项,如果该选项有参数值,则optarg指向该参数值。                 
在命令行选项参数再也检查不到optstring中包含的选项时,返回-1。
       
        参数中的argc和argv[]和main函数的形参意义相同,optstring是选项字符串,用来告知getopt()接收的参数中哪些是可以处理的选项,以及哪个选项需要参数。其中,以'-'开头的是短选项参数,以'--'开头的是长选项参数,getopt()函数只能处理短选项参数。例如现在输入命令     ./test -a 123 -b c   此命令中, "-a"  "-b" 就是选项参数,而 123 和 c 是参数值。

      

        optstring中的指定的内容的意义(例如getopt(argc, argv, "ab:c:de::");)
        1)单个字符,表示选项。(如上例中的abcde各为一个选项)
        2)单个字符后接一个冒号:表示该选项后必须跟一个参数值。参数值紧跟在选项后或者以空格隔开。该参数值的指针赋给optarg。(如上例中的b:c:)
        3)单个字符后跟两个冒号::表示该选项后可以跟一个参数值,也可以不跟。如果跟一个参数值,参数值必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(如上例中的e::,如果没有跟参数值,则optarg = NULL)

       这里需要注意三点:
  1. 不带值的参数可以连写,像a和d是不带值的参数,它们可以-a -d分开写,也可以-ad或-da连写。
  2. 参数不分先后顺序,"-a  -b 123 -c 456"和"-c 456 -a -b 123"的解析结果是一样的。
  3. 要注意可选值的参数的值与参数之间不能有空格,必须写成-e123这样的格式,如果写成--e 123这样的格式就会解析错误。




       getopt() 所设置的全局变量包括:
       optarg——指向当前选项参数(如果有)的指针。
       optind——再次调用 getopt() 时的下一个 argv 指针的索引。   
       optopt——最后一个未知选项。


         举个例子说明:

        假设现在a.out是一个可以接受  "-a"  "-b"  "-f" 选项的程序,其中"-a"选项必须跟参数值,"-b"选项不需要参数值,"-f"选项可跟可不跟参数值。用getopt()函数分析命令行参数的代码如下:


        #include
        #include
        #include


        int main(int argc,char *argv[])
        {
           char ch;
           int count=0;
           opterr=0;
           while((ch=getopt(argc,argv,"a:bf::")) != -1){
                switch(ch){
                    case 'a':
                       printf("optinon a:%s\n",optarg);
                        break;
                    case 'b':
                       printf("optinon b:%s\n",optarg);
                        break;
                    case 'f':
                        printf("option f:%s\n",optarg);
                        break;
                    default:
                        printf("other option:%c\n",ch);
                        break;
                }
            }

           return 0;
        }


             编译后运行输入  ./a.out -a 123 -b asdf -c -f   运行结果如下:




        "-a"选项需要一个参数值,getopt()将"123"存入optarg。"-b"选项不需要参数值,故忽略命令中"-b"后面的参数值,optarg输出为NULL。optstring中没有"-c"选项,getopt()返回'?'。"-f"选项后面没有参数值,optarg输出NULL。

        从结果可以看出,每次调用getopt()函数会依次检查命令参数,根据optstring字符串查找选项,返回选项的字符(如"-a"选项返回'a')。并检查是否带参数值,如果有参数值则将其存入optarg中,如果在处理期间遇到了不符合optstring指定的选项,getopt()将返回'?',同时打印一个错误信息,并将optarg置为NULL,如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。




           


你可能感兴趣的:(c语言学习笔记:命令行参数与命令行分析函数getopt())