Linux下getopt函数使用Tips

getopt函数可以用来非常方便的处理命令行参数。函数的原型是:

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

以下是关键点:
1. argc, argv就是main函数的那两个。optstring是我们给出的格式字符串,特别的是格式字符串中的:表示该command option后面是有一个value的,比如:./xtop -n 20 -i 2 1111,在这里optstring就可以写成"n:i:",这表示n和i这两个是command option,而且这两个option后面都需要给value,如果没有:,就表示该option后面不需要value。有关optstring还有一些 约定,比如以+开头就有特殊含义,具体看man 3 getopt了。
2. 返回值。正常情况下,返回的是一个char,表示当前分析到的option字母,这样,下面就可以用一个switch来处理了。全部分析完毕后,返回 -1。如果碰到一个没有出现在optstring中的option,那么,getopt返回?(默认情况下)。其实不用这么麻烦,一般coding的时 候,将我们需要处理的option字母全部列出来以后,然后用一个default就可以将其他任何getopt的返回值视为非法,打印:Usage: xxxx这样的字符串,程序退出即可。
3. 注意点:出现在optstring中的我们指定的那些option不是强制的。比如说,上面例子中,我们要求-n, -i这两个option都是必须要设置的,而用户在执行程序的时候只给出了一个-n,那么,getopt是管不了这个事的。他只是呆板的从头往后分析以- 打头的token,然后给我们返回option字母。所以,对于这种情况,我们要自己在程序中检测用户是否对我们强制要求的option都设置了,否则, 就报错。事实上,按照option和argument的原理来说,option应该都是可选的,不然怎么叫optiton呢?应该把强制要求用户设置的全 部变成argument,这样是最符合逻辑的。
4. 前面说了,对于-n 20这样的option,getopt返回的是n这个字母,然后这个20怎么取到呢?getopt将option的value放在了一个全局变量中,名字 为optarg,类型是char *。我们通过访问optarg就可以取到这个value了。如果用户写的option是-n2,那么,getopt返回n,同时optarg的值是 -n2,这里也是需要我们手工判断的。除非用户写的是-n,后面没了,此时按照optstring中的要求,getopt会打印出错信息,同时返回?。
5. 最后,关于argument。也就是getopt分析完了所有的option之后,最后剩下的就是argument了。在上面的例子中,./xtop -n 20 -i 2 1111,这个最后的1111就是argument了。getopt会设置全局变量optind(类型是int),这个optind就是第一个 argument(也就是不以-打头的token,同时也不是option value的token)在argv数组中的index,也就是说,argv[optind]就可以取出这个argument。非常方便吧。这样,由于有 了这个optind,所以,事实上,用户在写命令行的时候就可以很自由了,可以将option混着写,也可以将argument和option混着写,不 用一定要把argument放在命令行的最后。

基本上注意点就是这些,附上xtop中的相关代码。getopt还有一些特殊的说明和feature,在man 3 getopt中都可以找到。此外,还有getopt_long这样的函数,可以用来handle --打头的长option,这个在man手册中也有说明。


     int  main( int  argc,  char   * argv[])
    {
       
int  opt;

       
//  argument handling
         while  ((opt  =  getopt(argc, argv,  " n:i:o: " ))  !=   - 1 ) {
            
switch (opt) {
            
case   ' n ' :
                
if  ( ! string_is_int(optarg)) {
                    fprintf(stderr, 
" Error: <times> should be an integer. Yours is %s\n " , optarg);
                    
goto  FAILED;
                }
                check_times 
=  atoi(optarg);
                
break ;
            
case   ' i ' :
                
if  ( ! string_is_int(optarg)) {
                    fprintf(stderr, 
" Error: <time interval> should be an integer. Yours is %s\n " , optarg);
                    
goto  FAILED;
                }
                check_interval 
=  atoi(optarg);
                
break ;
            
case   ' o ' :
                output_file 
=  ( char   * )malloc(strlen(optarg)  +   1 );
                
if  (output_file  ==  NULL) {
                    fprintf(stderr, 
" Error: malloc for output file failed.\n " );
                    
goto  FAILED;
                }
                strcpy(output_file, optarg);
                
break ;
            
default :
                printf(
" Usage: xtop -n <times> -i <time interval> [-o <output file>] <pid>\n " );
                
goto  FAILED;
            }
        }

       
//  check whether the -n & -i are set
         if  (check_times  <=   0   ||  check_interval  <=   0 ) {
            fprintf(stderr, 
" Usage: xtop -n <times> -i <time interval> [-o <output file>] <pid>\n " );
            fprintf(stderr, 
" Also make sure your <times>, <time interval> are positive integers.\n " );
            
goto  FAILED;
        }

        
if  (optind  >=  argc) {
            fprintf(stderr, 
" Error: <pid> argument can't be found.\n " );
            
goto  FAILED;
        }
        
if  ( ! string_is_int(argv[optind])) {
            fprintf(stderr, 
" Error: <pid> should be an integer. Yours is %s\n " , argv[optind]);
            
goto  FAILED;
        }
        pid 
=  atoi(argv[optind]);
        
if  (pid  <=   0 ) {
            fprintf(stderr, 
" Error: illegal <pid> argument. Pid should be a positive integer. Yours is %d\n " , pid);
            
goto  FAILED;
        }

       
//  -o <output file> is optional, so check whether the user set this
       
//  xtop.out is the default output filename
         if  (output_file  ==  NULL) {
            printf(
" Begin analysing process %d, checking %d times after every %d seconds. Record results into xtop.out\n " ,
                   pid, check_times, check_interval);
        } 
else  {
            printf(
" Begin analysing process %d, checking %d times after every %d seconds. Record results into %s\n " ,
                   pid, check_times, check_interval, output_file);
        }

       ............
    }

 

你可能感兴趣的:(linux)