Technorati 标签: getopt

 

首先man下看下基本的介绍,注意要

$man 3 getopt

因为getopt也是shell下的一个命令

基本介绍:

原型:

#include <unistd.h>

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

extern char *optarg;
extern int optind, opterr, optopt;

作用:

可以用来解析命令行选项参数,而不用自己再去写程序分析了。

参数介绍:

1.argc:即传入main函数的argc

2.argv:即传入main函数的argv

3.optstring:指定预期的选项以及该选项是否存在参数。

格式如下:

1.单个字符,表示选项,如’x’表示’-x’
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。如’x:’表示’-x argument’,但argument在这里可有可无。
3 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。如’x::’表示’-x argument’(这个特性是GNU的扩张)

举个例子:

如optstring="ab:c::d::",命令行为getopt.exe -a -b host -ckeke -d haha
host是b的参数,keke是c的参数。但haha并不是d的参数,因为它们中间有空格隔开。

英文好的直接看这里(从getopt.h里抄的):

/* For communication from `getopt' to the caller.
   When `getopt' finds an option that takes an argument,
   the argument value is returned here.
   Also, when `ordering' is RETURN_IN_ORDER,
   each non-option ARGV-element is returned here.  */

extern char *optarg;

/* Index in ARGV of the next element to be scanned.
   This is used for communication to and from the caller
   and for communication between successive calls to `getopt'.

   On entry to `getopt', zero means this is the first call; initialize.

   When `getopt' returns -1, this is the index of the first of the
   non-option elements that the caller should itself scan.

   Otherwise, `optind' communicates from one call to the next
   how much of ARGV has been scanned so far.  */

extern int optind;

/* Callers store zero here to inhibit the error message `getopt' prints
   for unrecognized options.  */

extern int opterr;

/* Set to an option character which was unrecognized.  */

extern int optopt;

1.extern char* optarg;//选项的参数指针

2.extern int optind;//储存该位置,下次将从该位置处开始检查选项(检查时遇到选项或者参数,位置+1)

3.extern int opterr;//当opterr=0时,getopt不像stderr输出错误信息

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

调用一次,返回一个选项。

在命令行选项参数再也检查不到optstring中包含的选项时,返回-1,同时optind储存第一个不包含选项的命令行参数。

其实看个例子就比较容易了:

/*
 * =====================================================================================
 *       Filename:  getopt_l.c
 *    Description:  getopt learning
 *
 *        Version:  1.0
 *        Created:  06/26/2012 08:13:49 PM
 *
 *         Author:  zhy (), [email protected]
 * =====================================================================================
 */

#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;
                printf("The argument of -a is %s\n", optarg);
                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\n");
                cflag = 1;
                break;
            case '?':
                printf("Unknown option: %c\n", (char)optopt);
                break;
        }
    }
}

可以自己先试着写下输出的结果:

y@y-VirtualBox:~/Training$ ./getopt_l -a -d -b foo
optind: 2
Have option: -a
The argument of -a is (null)
./getopt_l: invalid option -- 'd'
optind: 3
Unknown option: d
optind: 5
Have option: -b
The argument of -b is foo

逐行解释下输出:

1.-a在命令行里位置为1,下次读取位置为2,因此optind=2

2-3.optstring里有a,同时a是不带参数的,因此检测到-a选项,同时参数为null

4.optstring里没有d(注,这里的输出时getopt本身输出,通过设置opterr可以设置显示还是不显示)

5.下次从3位置,即-b开始读取

6.optstirng没有d,返回?,optopt会存储预期之外的上一个选项。

7.读取-b同时读取其参数foo,因此下一个位置为5

8optstring里有b,读取正确并打印

9.打印b的参数foo,读取不到其他预期之内的选项,完毕返回-1

 

注意:

默认情况下getopt会重新排列命令行参数的顺序,所以到最后所有不包含选项的命令行参数都排到最后。
如getopt.exe -a ima -b host -ckeke -d haha, 都最后命令行参数的顺序是: -a -b host -ckeke -d ima haha
如果optstring中的字符串以'+'加号开头或者环境变量POSIXLY_CORRE被设置。那么一遇到不包含选项的命令行参数,getopt就会停止,返回-1。

看个例子:

/*
 * =====================================================================================
 *       Filename:  getopt_l2.c
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  06/26/2012 08:37:11 PM
 *
 *         Author:  zhy (), [email protected]
 * =====================================================================================
 */

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

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

    opterr = 0;//?

    while ((result = getopt(argc, argv, "ab:c::")) != -1) {
        switch (result) {
            case 'a':
                printf("option=a, optopt=%c, optarg=%s\n", optopt, optarg);
                break;
            case 'b':
                printf("option=b, optopt=%c, optarg=%s\n", optopt, optarg);
                break;
            case 'c':
                printf("option=c, optopt=%c, optarg=%s\n", optopt, optarg);
                break;
            case '?':
                printf("result=?, optopt=%c, optarg=%s\n", optopt, optarg);
            default:
                printf("default, result=%c\n", result);
                break;
        }
        printf("argv[%d]=%s\n", optind, argv[optind]);
    }

    printf("result = -1, optind = %d\n", optind);
    for ( result = optind; result<argc; result++)
        printf("------ argv[%d] = %s\n", result, argv[result]);
    printf("\n");
    for ( result = 1; result < argc; result++)
        printf("at the end------argv[%d] = %s\n", result, argv[result]);

    return 0;
}

getopt介绍_第1张图片

 

总结:

函数说明  getopt()用来分析命令行参数。参数argc和argv是由main()传递的参数个数和内容。参数optstring 则代表欲处理的选项字符串。此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。
返回值  如果找到符合的参数则返回此参数字母,如果参数不包含在参数optstring 的选项字母则返回“?”字符,分析结束则返回-1。

 

最后实战一下,假设有以下需求:

1.同大多数程序一样,-h输出help信息

2.-c 指定文件路径,如果没有默认为/tmp/c.conf

3.-d 指定目标文件,必须指定参数,同时该选项必须指定。

我实现的:

/*
 * =====================================================================================
 *       Filename:  getopt_l3.c
 *    Description:  -h for help info
 *                    -c set the config file, default is /tmp/c.conf
 *                    -d set destination file, could not be empty.
 *
 *        Version:  1.0
 *        Created:  06/27/2012 07:12:00 PM
 *
 *         Author:  zhy (), [email protected]
 * =====================================================================================
 */

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

int main(int argc, char *argv)
{
    int result;
    int hflag = 0, cflag = 0, dflag = 0;
    opterr = 0;

    char helpinfo[] = "[Usage]: ./a.out \n\
        -h, For Help Info\n\
        -c, Set the config file, default is /tmp/c.conf\n\
        -d, Set the destination file, could not be empty";

    while ((result=getopt(argc, argv, "hc::d:")) != -1) {
        switch (result) {
            case 'h':
                hflag = 1;
                break;
            case 'c':
                cflag = 1;
                if (NULL != optarg) {
                    printf("config file set: %s.\n", optarg);
                } else {
                    printf("config file set to default: /tmp/c.conf.\n");
                }
                break;
            case 'd':
                dflag = 1;
                if (NULL != optarg) {
                    printf("destination file set to: %s.\n", optarg);
                } else {
                    printf("args could not be empty for -d options.\n");
                    return;
                }
                break;
            case '?':
                printf("unexpected option: %c.\n", optopt);
                break;
            default:
                printf("default, %c", result);
        }
    }

    printf("options(h:%d, c:%d, d:%d)\n", hflag, cflag, dflag);
    if (hflag && !cflag && !dflag) {//如果只有h选项,打印并直接返回,否则不打印.
        printf("%s.\n", helpinfo);
        return;
    }
    if (!dflag) {
        printf("-d option must be setted\n");
        return;
    }

    //参数检测完毕,程序真正开始干活了......
    //
    printf("Args Setting Right.\n");
    return 0;
}

getopt介绍_第2张图片

参考:

http://www.cnitblog.com/zouzheng/archive/2007/04/02/25034.aspx

http://en.wikipedia.org/wiki/Getopt

http://hi.baidu.com/agodliness/blog/item/554a2d516366711b367abeb2.html