• 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);
            }

           ............
        }
  • 相关阅读:
    GO学习-(31) Go语言操作Elasticsearch
    GO学习-(30) Go语言操作kafka
    GO学习-(29) Go语言操作etcd
    Maven+Spring打Jar包
    话说Session
    Apache Server与多个独立Tomcat集成
    一套Tomcat处理多个域名请求
    Tomcat多实例
    Linux下安装MySQL
    Java Enum
  • 原文地址:https://www.cnblogs.com/super119/p/1996121.html
Copyright © 2020-2023  润新知