一、简介

getopt()函数是一个标准库调用,可允许您使用直接的 while/switch 语句方便地逐个处理命令行参数和检测选项(带或不带附加的参数)。与其类似的getopt_long()允许在几乎不进行额外工作的情况下处理更具描述性的长选项,这非常受开发人员的欢迎。

二、示例

1、getopt()
函数原型

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

参数说明

argc和argv一般就将main函数的那两个参数原样传入。
optstring是一段自己规定的选项串,“:”表示该选项必须带有额外的参数,全域变量optarg会指向此额外参数,“::”标识该额外的参数可选(带的额外参数必须紧挨着该选项,有些Uinx可能不支持“::”)
全域变量optind指示下一个要读取的参数在argv中的位置。如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符。如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。

使用示例

#include <stdio.h>
#include <unistd.h> int main(int argc,char *argv[])
{
int ch;
opterr=0; while((ch=getopt(argc,argv,"a:b::cde"))!=-1)
{
printf("optind:%d\n",optind);
printf("optarg:%s\n",optarg);
printf("ch:%c\n",ch);
switch(ch)
{
case 'a':
printf("option a:'%s'\n",optarg);
break;
case 'b':
printf("option b:'%s'\n",optarg);
break;
case 'c':
printf("option c\n");
break;
case 'd':
printf("option d\n");
break;
case 'e':
printf("option e\n");
break;
default:
printf("other option:%c\n",ch);
}
printf("optopt+%c\n",optopt);
}
}

运行

2、getopt_long()

函数原型

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

参数说明

函数中的argc和argv通常直接从main()的两个参数传递而来。optsting是选项参数组成的字符串:

字符串optstring可以下列元素:

    1.单个字符,表示选项,

     2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。

     3.单个字符后跟两个冒号,表示该选项后可以有参数也可以没有参数。如果有参数,参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。

参数longopts,其实是一个结构的实例:

    struct option 
   {
const char *name;//name表示的是长参数名
int has_arg; //has_arg有3个值,no_argument(或者是0),表示该参数后面不跟参数值
// required_argument(或者是1),表示该参数后面一定要跟个参数值
// optional_argument(或者是2),表示该参数后面可以跟,也可以不跟参数值
int *flag; //用来决定,getopt_long()的返回值到底是什么。如果flag是null(通常情况),则函数会返回与该项option匹配的val值;
                        //如果flag不是NULL,则将val值赋予flag所指向的内存,并且返回值设置为0
        int val;         //和flag联合决定返回值
} 参数longindex,表示当前长参数在longopts中的索引值

使用示例

#include <stdio.h>
#include <getopt.h> int do_name, do_gf_name;
char *l_opt_arg; 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, ":l:", longopts, NULL)) != -1)
{
switch (c)
{
case 'n':
printf("My name is Jay.\n");
break;
case 'g':
printf("Her name is Afra.\n");
break;
case 'l':
l_opt_arg = optarg;
printf("Our love is %s!\n", l_opt_arg);
break;
}
}
return 0;
}

运行

3、使用 gperf实现高效的C/C++ 命令行处理

三、Apache 命令行处理分析

Apache通过apr_getopt_init函数对命令行结构opt进行初始化

apr_getopt_init(&opt, pcommands, process->argc, process->argv);

apr_getopt_init函数实现在文件:srclib\apr\misc\unix\getopt.c,代码如下:

APR_DECLARE(apr_status_t) apr_getopt_init(apr_getopt_t **os, apr_pool_t *cont, int argc, const char *const *argv)
{
void *argv_buff; *os = apr_palloc(cont, sizeof(apr_getopt_t));
(*os)->cont = cont;
(*os)->reset = 0;
(*os)->errfn = (apr_getopt_err_fn_t*)(fprintf);
(*os)->errarg = (void*)(stderr); (*os)->place = EMSG;
(*os)->argc = argc; /* The argv parameter must be compatible with main()'s argv, since
that's the primary purpose of this function. But people might
want to use this function with arrays other than the main argv,
and we shouldn't touch the caller's data. So we copy. */
argv_buff = apr_palloc(cont, (argc + 1) * sizeof(const char *));
memcpy(argv_buff, argv, argc * sizeof(const char *));
(*os)->argv = argv_buff;
(*os)->argv[argc] = NULL; (*os)->interleave = 0;
(*os)->ind = 1;
(*os)->skip_start = 1;
(*os)->skip_end = 1; return APR_SUCCESS;
}

而后调用apr_getopt(opt, AP_SERVER_BASEARGS, &c, &optarg)进行命令行解析处理,代码如下

while ((rv = apr_getopt(opt, AP_SERVER_BASEARGS, &c, &optarg)) == APR_SUCCESS) 
{
char **new; switch (c) {
case 'c':
new = (char **)apr_array_push(ap_server_post_read_config);
*new = apr_pstrdup(pcommands, optarg);
break; case 'C':
new = (char **)apr_array_push(ap_server_pre_read_config);
*new = apr_pstrdup(pcommands, optarg);
break; case 'd':
def_server_root = optarg;
break; case 'D':
new = (char **)apr_array_push(ap_server_config_defines);
*new = apr_pstrdup(pcommands, optarg);
/* Setting -D DUMP_VHOSTS is equivalent to setting -S */
if (strcmp(optarg, "DUMP_VHOSTS") == 0)
configtestonly = 1;
/* Setting -D DUMP_MODULES is equivalent to setting -M */
if (strcmp(optarg, "DUMP_MODULES") == 0)
configtestonly = 1;
break; case 'e':
if (strcasecmp(optarg, "emerg") == 0) {
ap_default_loglevel = APLOG_EMERG;
}
else if (strcasecmp(optarg, "alert") == 0) {
ap_default_loglevel = APLOG_ALERT;
}
else if (strcasecmp(optarg, "crit") == 0) {
ap_default_loglevel = APLOG_CRIT;
}
else if (strncasecmp(optarg, "err", 3) == 0) {
ap_default_loglevel = APLOG_ERR;
}
else if (strncasecmp(optarg, "warn", 4) == 0) {
ap_default_loglevel = APLOG_WARNING;
}
else if (strcasecmp(optarg, "notice") == 0) {
ap_default_loglevel = APLOG_NOTICE;
}
else if (strcasecmp(optarg, "info") == 0) {
ap_default_loglevel = APLOG_INFO;
}
else if (strcasecmp(optarg, "debug") == 0) {
ap_default_loglevel = APLOG_DEBUG;
}
else {
usage(process);
}
break; case 'E':
temp_error_log = apr_pstrdup(process->pool, optarg);
break; case 'X':
new = (char **)apr_array_push(ap_server_config_defines);
*new = "DEBUG";
break; case 'f':
confname = optarg;
break; case 'v':
printf("Server version: %s\n", ap_get_server_description());
printf("Server built: %s\n", ap_get_server_built());
destroy_and_exit_process(process, 0); case 'V':
show_compile_settings();
destroy_and_exit_process(process, 0); case 'l':
ap_show_modules();
destroy_and_exit_process(process, 0); case 'L':
ap_show_directives();
destroy_and_exit_process(process, 0); case 't':
configtestonly = 1;
break; case 'S':
configtestonly = 1;
new = (char **)apr_array_push(ap_server_config_defines);
*new = "DUMP_VHOSTS";
break; case 'M':
configtestonly = 1;
new = (char **)apr_array_push(ap_server_config_defines);
*new = "DUMP_MODULES";
break; case 'h':
case '?':
usage(process);
}
} /* bad cmdline option? then we die */
if (rv != APR_EOF || opt->ind < opt->argc) {
usage(process);
}

apr_getopt函数实现在文件:srclib\apr\misc\unix\getopt.c,逻辑如下:

1、进行(os->reset || !*os->place)判断,作用未知

2、通过strchr(opts, os->opt)判断选项(os->opt)是否合法

3、若选项合法,则通过(*++oli != ':')判断该选项是否需要额外参数

4、若需要额外参数,则通过optch、optarg返回解析结果

APR_DECLARE(apr_status_t) apr_getopt(apr_getopt_t *os, const char *opts, char *optch, const char **optarg)
{
const char *oli; /* option letter list index */ if (os->reset || !*os->place) { /* update scanning pointer */
os->reset = 0;
if (os->ind >= os->argc || *(os->place = os->argv[os->ind]) != '-') {
os->place = EMSG;
*optch = os->opt;
return (APR_EOF);
}
if (os->place[1] && *++os->place == '-') { /* found "--" */
++os->ind;
os->place = EMSG;
*optch = os->opt;
return (APR_EOF);
}
} /* option letter okay? */
if ((os->opt = (int) *os->place++) == (int) ':' ||
!(oli = strchr(opts, os->opt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (os->opt == (int) '-') {
*optch = os->opt;
return (APR_EOF);
}
if (!*os->place)
++os->ind;
if (os->errfn && *opts != ':') {
(os->errfn)(os->errarg, "%s: illegal option -- %c\n",
apr_filepath_name_get(*os->argv), os->opt);
}
*optch = os->opt;
return (APR_BADCH);
}
if (*++oli != ':') { /* don't need argument */
*optarg = NULL;
if (!*os->place)
++os->ind;
}
else { /* need an argument */
if (*os->place) /* no white space */
*optarg = os->place;
else if (os->argc <= ++os->ind) { /* no arg */
os->place = EMSG;
if (*opts == ':') {
*optch = os->opt;
return (APR_BADARG);
}
if (os->errfn) {
(os->errfn)(os->errarg,
"%s: option requires an argument -- %c\n",
apr_filepath_name_get(*os->argv), os->opt);
}
*optch = os->opt;
return (APR_BADCH);
}
else /* white space */
*optarg = os->argv[os->ind];
os->place = EMSG;
++os->ind;
}
*optch = os->opt;
return APR_SUCCESS;
}

C语言命令行处理的更多相关文章

  1. 【嵌入式开发】C语言 命令行参数 函数指针 gdb调试

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21551397 | http://www.hanshul ...

  2. C语言 命令行参数 函数指针 gdb调试

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21551397 | http://www.hanshul ...

  3. Go语言命令行操作命令详细介绍

    转自:http://www.jb51.net/article/56781.htm Go 命令 Go语言自带有一套完整的命令操作工具,你可以通过在命令行中执行go来查看它们: 图 Go命令显示详细的信息 ...

  4. c语言命令行参数

    int main(int argc, char * argv[]) { ..... } argc: 代表启动程序时,命令行参数的个数.C和C++语言规定,可执行程序程序本身的文件名,也算是一个命令行参 ...

  5. Go语言 命令行解析(一)

    命令行启动服务的方式,在后端使用非常广泛,如果有写过C语言的同学相信不难理解这一点!在C语言中,我们可以根据argc和argv来获取和解析命令行的参数,从而通过不同的参数调取不同的方法,同时也可以用U ...

  6. C语言命令行解析函数:getopt/getopt_long

    命令行工具下的参数选项有两种,长选项和短选项.短选项以-开头,后面跟单个字母:长选项以--开头,后面可跟多个字母. 一. getopt() 1.功能:解析命令行短选项参数 2.函数原型: #inclu ...

  7. 关于C语言命令行参数问题

    1 int main(int argc,char** argv) 参数: argc:命令行参数的个数 argv:保存命令行参数:argv[0]保存本程序自己的名称 现在自己只知道这些以后再有学习继续补 ...

  8. R 语言命令行参数处理

    在unix.windows外部需要调用R脚本执行,然后又需要输入不同的参数,类似shell脚本的命令行参数输入,可以使用Rcript命令实现. 命令格式:Rscript [options] [-e e ...

  9. R语言命令行参数

        批量画图任务中,需要在R中传入若干参数,之前对做法是在perl中每一个任务建立一个Rscript,这种方式超级不cool,在群里学习到R的@ARGV调用方式,差不多能够达到批量任务的要求: a ...

随机推荐

  1. Codeforces 1009D:Relatively Prime Graph

    D. Relatively Prime Graph time limit per test 2 seconds memory limit per test 256 megabytes input st ...

  2. SqlServer高级特性--游标

    游标 用途:在数据很多的时候,如果在java代码中进行循环之后再进行更新数据,会造成频繁的连接数据库,耗费性能,所以就可以使用到游标 作用:查询出来的集合直接在SQL中进行遍历在进行更新 DECLAR ...

  3. LogHelp 日记分天记录,只记30天日记

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

  4. java 面向对象 — 封装

      

  5. 智能家居入门DIY——【三、GP2Y10之颗粒物传感器】

    这个传感器接线算比较简单的,程序也不麻烦.不过这东西是颗粒物传感器吧,不是神马PM2.5(总悬浮颗粒物),不是神马PM10(可吸入颗粒物).插个螺丝刀进去度数也是变的,不是说的很清楚原理是反光嘛……… ...

  6. buffer cache —— buffer busy waits/read by other session

    oracle提供非常精确.有效的row level lock机制,多个用户同时修改数据时,为了保护数据,以块为单位挂起锁的情况不会发生.但这不太正确.以块为单位的锁虽然不存在,但正因为oracle I ...

  7. 前端开发中常用的CSS选择器解析(一)

    你也许已经掌握了id.class.后台选择器这些基本的css选择器.但这远远不是css的全部.下面向大家系统的介绍css中最常用的选择器,包括我们最头痛的浏览器兼容性问题.掌握了它们,才能真正领略cs ...

  8. Linux下安装MATLAB

    Why do I see "Preparing installation files ... Installing ... Finished..." in the terminal ...

  9. verilog 计算机网络 仿真 激励 pcap

    做verilog网络逻辑时,需要产生正确的数据包格式激励,手写激励真烦人,现在让testbench读取pcap文件,则可以精确还原数据包的bit与时序,省去了一大批麻烦 1.设计读取逻辑 `times ...

  10. java普通类、抽象类、接口、面向对象理解

    1.面向对象编程: 面向对象编程的语言不止java一种,还有: simula 67(第一个面向对象语言,支持单继承和一定含义的多态和部分动态绑定): Smalltalk(第一个支持动态类型的语言,支持 ...