如何开发命令行程序

来源:互联网 发布:java方法返回两个整数 编辑:程序博客网 时间:2024/04/28 10:59

http://blog.csdn.net/luckheadline

一.命令行规范

关于实现命令行参数,C语言有着由来已久的传统规范。

1.可选命令行参数前有一个“-”,DOSWINDOWS系统也可以用“/”。

2.多个可选命令行参数之间没有顺序要求,每个参数都可以放置在参数列表中的任何位置。

3.可选命令行参数本身可能会带有参数。

4.可能有些命令行程序并不遵从以上的规范,虽然这样做并不推荐。

 

 

二.如何实现命令行参数处理(以C语言为例)

    命令行参数总是表现为一个字符串数组,这个字符串数组被称为”argv”(代表arguments values), 还有一个整数argc(代表arguments count)用来表示命令行参数列表中参数的个数。因此,我们的main函数的格式如下:

        int main(int argc, char* argv[]), 务必要记住argv[0]是程序的名字,在usage声明中你可能会用到它。main函数中的第一任务是实现可选参数,操作argv的标准方式如下所示:

 

 

  1. int i;
  2. int quiet=0; //Value for the “-q” optional argument.
  3. for (i = 1; i < argc; i ++) //skip argv[0].
  4. {
  5. /*
  6.  *Use the ‘strcmp’ function to compare the argv values to a string
  7.  *of your choice(here, it’s a *optinal argument “-q”). When
  8.  *strcmp returns 0, it means that the two strings are identical.
  9. */
  10.     if (strcmp(argv[i], “-q”) == 0) //Process optional arguments
  11.     {
  12.         quiet = 1; //This is used as a Boolean value.
  13.     }
  14.     else
  15.     {
  16.         //Process non-optional arguments here.
  17.     }
  18. }

请注意,正如这段代码所示,可选参数“

-q”可以被放置于参数列表的任何位置而且程序都可以正常work 如果可选参数本身还有参数的话,那么代码将更加的trickier

 

 

 

  1. int i;
  2. int opt = 0;
  3. int optarg1 = 0;
  4. int optarg2 = 0;
  5. for (i = 1; i < argc; i ++)
  6. {
  7.     if (strcmp(argv[i], “-opt”) == 0)
  8.     {
  9.         opt = 1; //This is used as a boolean value.
  10.         /*
  11.          *The last argument is argv[argc -1]. Make sure there
  12.          *are enough arguments.
  13.         */
  14.         if (i + 2 <= argc - 1) //There are enough arguments in argv.
  15.         {
  16.             /*
  17.              *Increment ‘i’ twice so that you don’t check
  18.              *these arguments the next time through the loop.
  19.             */
  20.             i ++;
  21.             optarg1 = atoi(argv[i]); //Convert string to int
  22.             i ++;
  23.             optarg2 = atoi(argv[i]);
  24.         }
  25.         else
  26.         {
  27.             //Print usage statement and exit.
  28.         }
  29.     }
  30.     else
  31.     {
  32.         //Process non-optional arguments here.
  33.     }
  34. }

    在很多情况下,命令行处理可能会非常麻烦,不过上面的代码已经可以应付相当多的情况了。

 

 

BTW, Linux下,习惯上会有两种形式的命令行参数,一种是短形式,通常由”-”加一个字母组成,这种形式的好处是便捷;另一种是长形式,通常由”--”加一个单词组成,这种形式的好处是形象,好记,直观。

 

 

 

三.Usage声明

有时候,用户可能会输入不合法的命令行参数,你的程序需要处理这种情况以避免程序crash。这种情况的正确处理方式是:

1. 显示usage声明

2. 退出程序

例如,假设你的程序除了程序名还期望有3个参数,并且要接受另外一个可选参数:

usage声明的以下几点意见:

 

 

 

1.usage信息: 总是使用“usage”开头,接着是程序名和参数名。参数名应该尽可能的指明参数的意义,比如上面的filename。参数名不应该包含空格!可选参数使用[],比如上面程序中的”-w”。非可选参数不要使用[]!总是打印stderr,而非stdout,以指明程序没有正确invoke

2.程序名:总是使用argv[0]以指明程序名而非显式的指出。因为这样,当你重新命名程序之后,不用重写代码。

3.退出程序:使用exit函数(exit函数被定义在头文件<stdlib.h>)。exit函数的任何非零参数都标志着程序的非正常结束(exit0)标识程序的正常执行,但你很少会像这样用)。你也可以使用宏EXIT_FAILUREEXIT_SUCCESS以取代10作为exit函数的参数。

如果不得不多次写usage声明,你可以将它分离出来作为一个独立的函数,并且将程序名(argv[0])作为参数传给它。那样它就可以被main函数在任何需要的时候调用了。

 

四.常见错误

1.当程序接收到不正确参数时,应该总是打印一个usage消息给stderr。如果处理失败将会自动redo

2.不要假设可选参数会固定放在参数列表的某个位置上。

3.如果不方便的话,就不要尝试一遍处理所有的命令行参数。

4.不要修改argv数组。

 

五.getOpt()的使用

getOpt()是一个专门设计来减轻命令行处理负担的库函数。它位于unistd.h系统头文件中,其原型如下:

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

函数给定了命令参数的数量(argc),指向这些参数的数组(argv)和选项字符串(optstring)后,getopt()将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有识别到的选项,将返回-1,此任务就完成了。

getopt()所设置的全局变量包括:

optarg:指向当前选项参数(如果有)的指针。

optind:再次调用getopt()时的下一个argv指针的索引。

optopt:最后一个已知选项。

可以重复调用getopt(),直到其返回-1为止;任何剩下的命令行参数通常视为文件名或称程序相应的其他内容。见以下代码示例:

 

 

 

Unix程序还支持长选项,可以通过使用getopt_long()向程序添加长选项支持,因为getopt_long()是同时支持长选项和短选项的getopt()版本。getopt_long()函数还接受其他参数,其中一个是指向struct option对象数组的指针。结构如下:

成员是指向长选项名称(带两个短横线)的指针。has_arg 成员设置为 no_argument, optional_argument, required_argument(均在 getopt.h 中定义)之一,以指示选项是否具有参数。如果 flag 成员未设置为 NULL,在处理期间遇到此选项时,会使用 val 成员的值填充它所指向的 int 值。如果 flag 成员为 NULL,在 getopt_long() 遇到此选项时,将返回 val 中的值;通过将 val 设置为选项的 short 参数,可以在不添加任何其他代码的情况下使用 getopt_long()——处理 while loop switch 的现有 getopt() 将自动处理此选项。代码示例可以参见reference 5

 

 

 

 

 

Reference:

http://www.cs.caltech.edu/courses/cs11/material/c/mike/misc/cmdline_args.html

http://www.ibm.com/developerworks/cn/linux/shell/clutil/index.html

http://linux.chinaitlab.com/command/4198.html

http://www.gnu.org/software/libtool/manual/libc/Getopt.html

http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html

 

原创粉丝点击