首先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()用来分析命令行参数。参数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; }
参考:
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