设为首页 收藏本站
查看: 311|回复: 0

[经验分享] Linux下C程序命令行参数处理

[复制链接]

尚未签到

发表于 2016-3-15 09:10:34 | 显示全部楼层 |阅读模式
Linux下开发C程序,甚至是GUI程序,都可能需要处理复杂的命令行参数。健全、可靠的复杂命令行参数处理机制,可使程序方便使用,也更显专业。Linux下几乎所有的命令都提供了参数处理机制,包括短选项和长选项。

  POSIX标准中对程序名、参数作了如下相关约定:
* 程序名不宜少于2个字符且不多于9个字符;
* 程序名应只包含小写字母和阿拉伯数字;
* 选项名应该是单字符活单数字,且以短横‘-‘为前綴;
* 多个不需要选项参数的选项,可以合并。(譬如:foo -a -b -c ---->foo -abc)
* 选项与其参数之间用空白符隔开;
* 选项参数不可选。
* 若选项参数有多值,要将其并为一个字串传进来。譬如:myprog -u "arnold,joe,jane"。这种情况下,需要自己解决这些参数的分离问题。
* 选项应该在操作数出现之前出现。
* 特殊参数‘--'指明所有参数都结束了,其后任何参数都认为是操作数。
* 选项如何排列没有什么关系,但对互相排斥的选项,如果一个选项的操作结果覆盖其他选项的操作结果时,最后一个选项起作用;如果选项重复,则顺序处理。
* 允许操作数的顺序影响程序行为,但需要作文档说明。
* 读写指定文件的程序应该将单个参数'-'作为有意义的标准输入或输出来对待。

  GNU鼓励程序员使用--help、--verbose等形式的长选项。这些选项不仅不与POSIX约定冲突,而且容易记忆,另外也提供了在所有GNU工具之间保持一致性的机会。GNU长选项有自己的约定
* 对于已经遵循POSIX约定的GNU程序,每个短选项都有一个对应的长选项。
* 额外针对GNU的长选项不需要对应的短选项,仅仅推荐要有。
* 长选项可以缩写成保持惟一性的最短的字串。
* 选项参数与长选项之间或通过空白字符活通过一个'='来分隔。
* 选项参数是可选的(只对短选项有效)。
* 长选项允许以一个短横线为前缀。

  C程序通过argc和argv参数访问它的命令行参数,通过main()函数调用和处理:int main(int argc, char *argv[])。一般情况下,我们事先约定好参数的顺序位置,然后在main函数中进行简单处理。这种方式实现比较简单,然后用户使用起来很不方便,Linux下的各种工具的命令行参数可以是不分先后次序的。幸运的是,Linux为C程序员提供了相关的命令行参数解析函数:getopt()和getopt_long(),分别用于处理短选项和长选项,当然后者可以同时处理短、长选项。函数原型如下:

#include <unistd.h>

int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;

int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);


getopt() 函数是一个标准库调用,可允许使用直接的 while/switch 语句方便地逐个处理命令行参数和检测选项(带或不带附加的参数)。getopt_long() 允许在几乎不进行额外工作的情况下处理更具描述性的长选项,非常受开发人员的欢迎。下面用笔者开发的一个Daemon程序wsiod中的参数处理来说明具体的处理过程。wsiod参数帮助信息如下:

[liuag] /home/liuag/workspace/WSIO/WSIO-1.3/server > ./wsiod --help
Usage: wsiod [OPTION]

WSIO server based on web service.
Mandatory arguments to long options are mandatory for short options too.
-h, --host hostname in soap_bind, default is host which the service runs
-p, --port port which the sercer runs on, default is 8080
-b, --backlog request backlog, default is 100
-t, --type server type, default is COMMON
-k, --keepalive attempt to keep socket connections alive
-c, --chunk use HTTP chunking
-d, --dime use DIME encoding
-D, --debug print debug info
--help print this help

Server type:
COMMON the simplest server
STANDALONE stand-alone server, which can run on port 80
MULTITHREAD multi-thread stand-alone server
POOL using a pool of servers
QUEUE using a queue of requests for server
GSI prethreaded server with GSI enabled

Report bugs to <Aigui.LIU@ihep.ac.cn>.

wsiod参数处理实现C程序段如下:

#include <unistd.h>
#include <getopt.h>

enum SERVERTYPE{COMMON, STANDALONE, MULTITHREAD, POOL, QUEUE, GSI};
int keepalive = 0, dime = 0, chunk = 0;

/* WSIO server main function */
int main(int argc, char **argv)
{
int c;
char host[128] = "localhost";
char log_buf[LOGBUFSZ];
int port = 8080, backlog = 100;
enum SERVERTYPE servertype = COMMON;
int helpflg = 0,
errflg = 0,
debug = 0;
struct option longopts[] =
{
{"host", 1, 0, 'h'},
{"port", 1, 0, 'p'},
{"backlog", 1, 0, 'b'},
{"type", 1, 0, 't'},
{"keepalive", 0, 0, 'k'},
{"chunk", 0, 0, 'c'},
{"dime", 0, 0, 'd'},
{"debug", 0, 0, 'D'},
{"help", 0, &helpflg, 1},
{0, 0, 0, 0}
};

while ((c = getopt_long (argc, argv, "h:p:b:t:kcdD", longopts, NULL)) != EOF)
{
switch(c)
{
case 'h':
  sprintf(host, "%s", optarg);
  break;
case 'p':
port = atoi(optarg);
  break;
case 'b':
backlog = atoi(optarg);
  break;
case 't':
  switch(*optarg)
{
  case 'C':
  servertype = COMMON;
  break;
  case 'S':
  servertype = STANDALONE;
  break;
  case 'M':
  servertype = MULTITHREAD;
  break;
  case 'P':
  servertype = POOL;
  break;
  case 'Q':
  servertype = QUEUE;
  break;
  case 'G':
  servertype = GSI;
  default:
  break;
}
  break;
case 'k':
  keepalive = 1;
break;
case 'c':
  chunk = 1;
break;
case 'd':
  dime = 1;
break;
case 'D':
  debug = 1;
break;
case '?':
  errflg++;
break;
default:
  break;
}
}

if(helpflg || errflg)
{
fprintf(stderr,"Usage: wsiod [OPTION]/n/n%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  "WSIO server based on web service./n",
"Mandatory arguments to long options are mandatory for short options too./n",
"/t-h, --host hostname in soap_bind, default is host which the service runs/n ",
"/t-p, --port port which the sercer runs on, default is 8080/n",
"/t-b, --backlog request backlog, default is 100/n",
"/t-t, --type server type, default is COMMON/n",
"/t-k, --keepalive attempt to keep socket connections alive/n",
"/t-c, --chunk use HTTP chunking/n",
"/t-d, --dime use DIME encoding/n",
"/t-D, --debug print debug info/n",
"/t --help print this help/n/n",
"Server type:/n",
"/tCOMMON the simplest server/n",
"/tSTANDALONE stand-alone server, which can run on port 80/n"
"/tMULTITHREAD multi-thread stand-alone server/n",
"/tPOOL using a pool of servers/n",
"/tQUEUE using a queue of requests for server/n",
"/tGSI prethreaded server with GSI enabled/n/n",
"Report bugs to <Aigui.LIU@ihep.ac.cn>./n"
);
exit(0);
}

/* 省略部分 */

return 0;
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-190959-1-1.html 上篇帖子: xnee的在不同linux版本下安装说明 下篇帖子: windows下和linux下PHP支持oracle
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表