【Linux开发】常用命令行解析函数getopt/getopt_long

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

1.getopt
#include <unistd.h>
extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
extern int optreset;
int getopt(int argc, char * const *argv, const char *optstring);
getopt()每调用一次返回一个选项。  argc 和 argv 很显然就是 main 函数的两个参数。
字符串 optstring 可以包含下列元素:单个字符,字符后面接一个冒号说明后面跟随一个选项参数,字符后面接两个冒号说明后面跟随一个可有可无的选项参数。例如,一个选项字符 "x" 表示选项 "-x" ,选项字符 "x:" 表示选项和其参数 "-x argument",选项字符 "x::" 表示选项 x 的参数是可选的(“::” 是 GNU 增加的,不一定在所有的UNIX 系统下都可以使用)。
getopt()的返回后,如果有选项参数的话 optarg 指向选项参数,并且变量 optind 包含下一个 argv 参数作为对 getopt() 下一次调用的索引。变量 optopt 保存最后一个由 getopt() 返回的已知的选项。
当参数列已经到结尾时getopt()函数返回-1,当遇到一个未知的选项时 getopt 返回'?'。参数列中选项的解释可能会被'--'取消,由于它引起 getopt()给参数处理发送结束信号并返回-1。
很多时候,我们不希望输出任何错误信息,或更希望输出自己定义的错误信息。可以采用以下两种方法来更改getopt()函数的出错信息输出行为:
在调用getopt()之前,将opterr设置为0,这样就可以在getopt()函数发现错误的时候强制它不输出任何消息。
如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
“无效选项” ―― getopt()返回'?',并且optopt包含了无效选项字符(这是正常的行为)。
“缺少选项参数” ―― getopt()返回':',如果optstring的第一个字符不是冒号,那么getopt()返回'?',这会使得这种情况不能与无效选项的情况区分开。
/* getopt.c */
#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
    int aflag=0, bflag=0, cflag=0;
    int ch;
    while ((ch = getopt(argc, argv, "ab:c")) != -1)
    {
        printf("optind: %d/n", optind);
        switch (ch) {
        case 'a':
            printf("HAVE option: -a/n");
            aflag = 1;
            break;
        case 'b':
            printf("HAVE option: -b/n");
            bflag = 1;
            printf("The argument of -b is %s/n", optarg);
            break;
        case 'c':
            printf("HAVE option: -c");
            cflag = 1;
            break;
        case '?':
            printf("Unknown option: %c/n",(char)optopt);
            break;
        }
    }
}
2.getopt_long
int getopt_long(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);
其中我们使用了一个结构体struct options的数组,struct options longopt[].
struct options的定义如下:
struct option{
     const char *name;
     int has_arg;
     int *flag;
     int val;
};
对结构中的各元素解释如下:
    const char *name
    这是选项名,前面没有短横线。譬如"help"、"verbose"之类。
    int has_arg
    描述了选项是否有选项参数。如果有,是哪种类型的参数,此时,它的值一定是下表中的一个。
    符号常量     数值     含义
    no_argument     0     选项没有参数
    required_argument     1     选项需要参数
    optional_argument     2     选项参数可选
    int *flag
    如果这个指针为NULL,那么 getopt_long()返回该结构val字段中的数值。如果该指针不为NULL,getopt_long()会使得它所指向的变量中填入val字段中的数值,并且getopt_long()返回0。如果flag不是NULL,但未发现长选项,那么它所指向的变量的数值不变。
    int val
    这个值是发现了长选项时的返回值,或者flag不是NULL时载入*flag中的值。典型情况下,若flag不是NULL,那么val是个真/假值,譬如 1或0;另一方面,如果flag是NULL,那么 val通常是字符常量,若长选项与短选项一致,那么该字符常量应该与optstring中出现的这个选项的参数相同。
    每个长选项在长选项表中都有一个单独条目,该条目里需要填入正确的数值。数组中最后的元素的值应该全是0。数组不需要排序,getopt_long()会进行线性搜索。但是,根据长名字来排序会使程序员读起来更容易。
#include <stdio.h>
#include <getopt.h>
int do_name, do_gf_name;
char *l_opt_arg;
static const char *shortopts = "l:ng";
struct option longopts[] = {
  {"name", no_argument, NULL, 'n'},
  {"gf_name", no_argument, NULL, 'g'},
  {"love", required_argument, NULL, 'l'},
  {0, 0, 0, 0},
};
int main (int argc, char *argv[])
{
  int c;
  while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
    {
      switch (c)
    {
    case 'n':
      printf ("My name is LYR./n");
      break;
    case 'g':
      printf ("Her name is BX./n");
      break;
    case 'l':
      l_opt_arg = optarg;
      printf ("Our love is %s!/n", l_opt_arg);
      break;
    }
    }
  return 0;
}

 

具体案例:

/* getopt_demo - demonstrate getopt() usage
 *
 * This application shows you one way of using getopt() to
 * process your command-line options and store them in a
 * global structure for easy access.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* doc2html supports the following command-line arguments:
 * 
 * -I - don't produce a keyword index
 * -l lang - produce output in the specified language, lang
 * -o outfile - write output to outfile instead of stdout
 * -v - be verbose; more -v means more diagnostics
 * additional file names are used as input files
 * 
 * The optString global tells getopt() which options we
 * support, and which options have arguments.
 */
struct globalArgs_t {
    int noIndex;                /* -I option */
    char *langCode;                /* -l option */
    const char *outFileName;    /* -o option */
    FILE *outFile;
    int verbosity;                /* -v option */
    char **inputFiles;            /* input files */
    int numInputFiles;            /* # of input files */
} globalArgs;

static const char *optString = "Il:o:vh?";

/* Display program usage, and exit.
 */
void display_usage( void )
{
    puts( "doc2html - convert documents to HTML" );
    /* ... */
    exit( EXIT_FAILURE );
}

/* Convert the input files to HTML, governed by globalArgs.
 */
void convert_document( void )
{
    printf("InputFiles:%d/n",globalArgs.numInputFiles);
    /* ... */
}

int main( int argc, char *argv[] )
{
    int opt = 0;
    
    /* Initialize globalArgs before we get to work. */
    globalArgs.noIndex = 0;        /* false */
    globalArgs.langCode = NULL;
    globalArgs.outFileName = NULL;
    globalArgs.outFile = NULL;
    globalArgs.verbosity = 0;
    globalArgs.inputFiles = NULL;
    globalArgs.numInputFiles = 0;
    
    /* Process the arguments with getopt(), then 
     * populate globalArgs. 
     */
    opt = getopt( argc, argv, optString );
    while( opt != -1 ) {
        switch( opt ) {
            case 'I':
                globalArgs.noIndex = 1;    /* true */
                break;
                
            case 'l':
                globalArgs.langCode = optarg;
                break;
                
            case 'o':
                /* This generates an "assignment from
                 * incompatible pointer type" warning that
                 * you can safely ignore.
                 */
                globalArgs.outFileName = optarg;
                break;
                
            case 'v':
                globalArgs.verbosity++;
                break;
                
            case 'h':    /* fall-through is intentional */
            case '?':
                display_usage();
                break;
                
            default:
                /* You won't actually get here. */
                break;
        }
        
        printf("optind=%d/n",optind);
        opt = getopt( argc, argv, optString );
    }
    
    globalArgs.inputFiles = argv + optind;
    globalArgs.numInputFiles = argc - optind;
    printf("argc=%d/n",argc);
    printf("optind=%d/n",optind);
    convert_document();
    
    return EXIT_SUCCESS;
}

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

posted @ 2012-12-07 13:13  gnuhpc  阅读(843)  评论(0编辑  收藏  举报