在实际编程当中,自己编写代码处理命令行参数是比较麻烦且易出错的。一般我们会直接使用getopt()getopt_long()函数,下文将介绍具体的使用方法。

getopt()

getopt()用于处理”单字母“选项,如-a, -t等。函数声明如下:

#include <unistd.h>
int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg;
extern int optind, opterr, optopt;

参数说明

对于前两个参数argcgrgv[],一般直接使用main()传递进来的数值。用过C语言的同学应该比较熟悉,简单复习一下。

#include <stdlib.h>
#include <stdio.h> int main(int argc, char const *argv[])
{
//在C99标准推出之前,变量不能在for()声明,为了兼容性,这里提前声明"i"
int i;
printf("argc = %d\n", argc); if (argc > 1)
{
for (i = 0; i < argc; ++i)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
}
return 0;
}

argc: argument count, 记录了命令行参数的个数(包括命令本身)

argv: argument vector, 记录了命令行参数的具体内容

$ ./test 1 2 3
argc = 4
argv[0] = ./test
argv[1] = 1
argv[2] = 2
argv[3] = 3

optstring: 作为getopt()的第三个参数,用于规定合法选项(option)以及选项是否带参数(argument)。一般为合法选项字母构成的字符串,如果字母后面带上冒号:就说明该选项必须有参数。如"ht:"说明有两个选项-h-t且后者(-t)必须带有参数(如-t 60)。

返回值

  • option character: 一般情况下,getopt()读取到合法选项,就返回该选项(一个字母)。
  • -1:结束标志。
while ( (opt = getopt(argc, argv, "ab:") ) != -1) {...}
  • ?: 一般情况下,遇到非法选项或者参数缺失都会返回?。如果需要区分这两种错误,可以在optstring开头加上:,如:ht: , 这样参数缺失就返回:非法选项就返回?
  • ::在optstring参数开头第一个字符为:时,遇到参数缺失返回:。参考下方代码(摘自Linux Programming by Example)可帮助理解
int oc;             /* option character */
char *b_opt_arg; while ((oc = getopt(argc, argv, ":ab:")) != -1) {
switch (oc) {
case 'a':
/* handle -a, set a flag, whatever */
break;
case 'b':
/* handle -b, get arg value from optarg */
b_opt_arg = optarg;
break;
case ':':
/* missing option argument 参数缺失*/
fprintf(stderr, "%s: option '-%c' requires an argument\n",
argv[0], optopt);
break;
case '?':
default:
/* invalid option 非法选项*/
fprintf(stderr, "%s: option '-%c' is invalid: ignored\n",
argv[0], optopt);
break;
}
}

相关变量

  • optind(option index): 数组下标,指向下一个未处理的参数。通过例子(摘自stackoverflow)能更好理解:
#include <stdio.h>
#include <string.h>
#include <unistd.h> int main(int argc, char *argv[])
{
char optStr[] = "ab";
int c; while ((c = getopt(argc, argv, optStr)) != -1) {
printf("optind: %d\n", optind);
switch (c) {
case 'a':
printf("-a\n");
break;
case 'b':
printf("-b\n");
break;
case '?':
printf("error\n");
break;
}
}
return 0;
}

测试结果:

$ ./a.out -ab  #例子1
optind: 1
-a
optind: 2
-b $ ./a.out -a #例子2
optind: 2
-a

例子1:

#argv[]数据如下
argv[0]="./a.out"
argv[1]="-ab"
argv[2]=0

optind=1开始,处理完aoptind指向b所在位置,其实还是1;处理完b,指向下一个选项,即2

例子2:

#argv[]数据如下
argv[0]="./a.out"
argv[1]="-a"
argv[2]=0

optind=1开始,处理完a,指向下一个选项,即2

  • optarg: 如果合法选项带有参数,那么对应的参数,赋值给optarg

getopt_long()

根据函数名就可以知道getopt_long()用于处理长选项,如-help。函数声明如下:

#include <getopt.h>                                                

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

参数说明

前三个选项和getopt()完全相同,在此不再赘述。

  • longopts数组: 用于规定合法长选项以及长选项是否带参数(argument)。涉及到的option结构体声明如下
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
  1. name: 长选项的名称
  2. has_arg: 参数情况
符号常量 数值 Meaning
no_argument 0 无参数
required_argument 1 有参数
optional_argument 2 参数可选

考虑到“可读性”,一般使用“符号常量”

  1. int *flag: 如果flagNULL, getup_long() 返回val的值; 如果不是NULL, val的值赋给flag指针指向的内容,同时getopt_long()返回 0
  2. int val: flagNULLval作为getopt_long()的返回值;如果flag不为NULLval赋值给flag指针所指内容;
int *flag return value
NULL val
&name(<— val) 0

通过例子(摘自webbench)可加深理解

static const struct option long_options[]=
{
{"force",no_argument,&force,1}, //-force 参数三(flag)不为NULL,force=1,getopt_long()返回0
{"reload",no_argument,&force_reload,1},
{"time",required_argument,NULL,'t'},
{"help",no_argument,NULL,'?'}, //-help 第三个参数(flag)为NULL,直接返回 "?"
{"http09",no_argument,NULL,'9'},
{"http10",no_argument,NULL,'1'},
{"http11",no_argument,NULL,'2'},
{"get",no_argument,&method,METHOD_GET},
{"head",no_argument,&method,METHOD_HEAD},
{"options",no_argument,&method,METHOD_OPTIONS},
{"trace",no_argument,&method,METHOD_TRACE},
{"version",no_argument,NULL,'V'},
{"proxy",required_argument,NULL,'p'},
{"clients",required_argument,NULL,'c'},
{NULL,0,NULL,0} //最后一个元素应该全为0
}; int main(int argc, char *argv[])
{
int options_index=0;
...
while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF )
{
...
}
}

注意: longopts数组最后一个元素应该全为0.

  • longindex: 一般设置为NULL; 如果不为NUll, 指向每次找到的长选项longopts的位置,可以通过该值(即索引)找到当前长选项的具体信息。

希望本文能帮助大家更好地理解getopt()getopt_long()

更多的相关用法可以参考Linux Programming by Example: The Fundamentals

命令行参数处理-getopt()和getopt_long()的更多相关文章

  1. 命令行参数解析函数getopt和getopt_long函数【转】

    原文地址:http://blog.csdn.net/cashey1991/article/details/7942809 getopt和getopt_long函数   平时在写程序时常常需要对命令行参 ...

  2. 【C】命令行参数解析——getopt、getopt_long及getopt_long_only

    前言 在linux下学习开源代码Webbench,遇到get_long等函数的用法,一时有点懵,故想深入了解这类命令行解析函数,并记此博文. 1.getopt getopt主要用来处理短命令行选项,例 ...

  3. [转]Python 命令行参数和getopt模块详解

    FROM : http://www.tuicool.com/articles/jaqQvq 有时候我们需要写一些脚本处理一些任务,这时候往往需要提供一些命令行参数,根据不同参数进行不同的处理,在Pyt ...

  4. Python 命令行参数和getopt模块详解

    有时候我们需要写一些脚本处理一些任务,这时候往往需要提供一些命令行参数,根据不同参数进行不同的处理,在Python里,命令行的参数和C语言很类似(因为标准Python是用C语言实现的).在C语言里,m ...

  5. 命令行参数解析函数 getopt

    命令行参数解析函数 —— getopt() getopt()函数声明如下: #include <unistd.h> int getopt(int argc, char * const ar ...

  6. shell 命令行参数(getopt和getopts)

    getopt 命令 使用getopt命令,可以解析任何命令行选项和参数,但是用法比较复杂.getopt的命令用法如下: $ getopt --help 用法: getopt optstring par ...

  7. 转载:linux编程,命令行参数输入getopt

    下面资料来自百度百科: getopt(分析命令行参数) 相关函数 表头文件 #include<unistd.h> 定义函数 int getopt(int argc,char * const ...

  8. webbench源码学习-->命令行选项解析函数getopt和getopt_long函数

    对于webbench这个网站压力测试工具网上介绍的很多,有深度详解剖析的,对于背景就不在提了, 听说最多可以模拟3万个并发连接去测试网站的负载能力,这里主要是学习了一下它的源码,做点 笔记. 官方介绍 ...

  9. getopt函数的使用——分析命令行参数

    getopt(分析命令行参数) getopt(分析命令行参数) 短参数的定义 返回值 范例 getopt_long 相关函数表头文件#include<unistd.h> 函数声明int g ...

随机推荐

  1. PropertiesUtil demo

    package com.spl.save.wmos.base.util; import java.io.File; import java.io.FileInputStream; import jav ...

  2. CloseableHttpClient 源码

    public abstract class CloseableHttpClient implements HttpClient, Closeable { private final Log log = ...

  3. MySQL (二)-- 数据类型(列类型)、数值类型、 小数类型、 时间日期类型、 字符串类型 、 MySQL记录长度、列属性

    1 数据类型(列类型) 所谓的数据类型:对数据进行统一的分类,从系统的角度出发是为了能够使用统一的方式进行管理,更好的利用有限的空间. SQL中将数据类型分成了三大类: 2 数值类型 数值类型数据:都 ...

  4. 结对编程1.四则运算GUI版

    201421123022 王若凡        201421123026  欧阳勇 coding详细代码 a.需求分析: 这个程序做成GUI(可以是Windows PC 上的,也可以是Mac.Linu ...

  5. Swing-布局管理器之FlowLayout(流式布局)-入门

    FlowLayout应该是Swing布局管理器学习中最简单.最基础的一个.所谓流式,就是内部控件像水流一样,从前到后按顺序水平排列,直到达到容器的宽度时跳转到第二行.既然是水平排列,那么就存在三种基本 ...

  6. 团队作业4——第一次项目冲刺(Alpha版本)2nd day

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 界面 1.四个用户登录界面已经完成. 2.界面内的功能完成了一小部分. 登陆部分 1.QQ授权已经申请,还未通过. 2.通过好 ...

  7. 201521123006 《java程序设计》 第13周学习总结

    1. 本周学习总结 1.以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.j ...

  8. 201521123099 《Java程序设计》第9周学习总结

    1. 本周学习总结 2. 书面作业 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 容易出现拼写错误还有数组越界的异 ...

  9. Jquery基础添加删除内容

    直入主题,工作中比较常用的功能在input框内添加内容,不白话了,上代码! 布局: <div id="content"> <input type="te ...

  10. maven profile切换正式环境和测试环境

    有时候,我们在开发和部署的时候,有很多配置文件数据是不一样的,比如连接mysql,连接redis,一些properties文件等等 每次部署或者开发都要改配置文件太麻烦了,这个时候,就需要用到mave ...