程序参数

程序参数

  许多命令行运行的C程序都会有可选(或必须要有)的参数,如 gcc prog.c -o prog,“prog.c”、"-o"、"prog"这些都是参数。
  参数中有些会被称为选项(标志、开关),选项参数(options)往往被用作调整程序的功能,比如 -o 就是gcc的一个选项,它可以指定输出文件的名字(默认的输出文件名为a.out);而另外的一些参数当然就是非选项参数了。
  命令行在LINUX/UNIX中一般都会遵守一些准则,在X/Open规范中可以找到详细具体的内容。下面是一些常见且简单的描述:

  • 单字符选项参数一般要加一个短横杠( - ),也就是减号。如,gcc命令中的 -o
  • 长选项参数一般要加双短横杠( – ),就是两个连续的减号。如, gcc --helpnode --version (很多命令行都会有这两个选项,help用于查看手册、version用于查看版本)
  • 参数之间要用空格隔开。如果一个参数中包含了空白字符,就需要用双引号把整个参数闭合起来。如, Hello World 表示两个参数(一个Hello、一个World);而 “Hello World” 则代表的是一个参数。

*注:并不是所有的命令行都遵守了这个准则

简单的带参数示例

  要编写带参数的C程序就需要给main函数传入两个参数:int argc、char *argv[] .
  前者是一个整型参数,代表着一条命令行中字符串的个数(字符串之间用空格隔开,含有空格的字符串要用双引号闭合,这个和上面说过的一样);后者是一个数组,存放着指向每个字符串的指针。
  以一条命令 $ myecho hello world ! 为例($代表的是命令提示符,这个应该很清楚它不是命令的一部分),如下图所示:
argc-argv的描述
当运行这条命令时,argc就被赋值为4,而argv[]就会存放各个字符串的指针。
需要注意的是:

  • argv[]存放的是指针,而不是字符
  • 虽然myecho是程序文件的名称而非参数,但它确实是命令的一部分,字符串的个数要算上它!所以argc是4而非3

如此一个带参数的C程序大致如下所示:

int main(int argc, char *argv[])
{

	//...CODE...
	
	return 0;
}

一个简单的示例:

//FILENAME: myprogram.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
    int arg = 0;
    while(arg < argc)
    {
        printf("%s\n", argv[arg]);
        arg++;
    }
    printf("argc = %d\n", argc);
    exit(0);
}

运行结果1

$ ./myprogram hello world !
./myprogram
hello
world
!
argc = 4
$

运行结果2

$ ./myprogram "hello world" !
./myprogram
hello world
!
argc = 3
$

getopt函数

为了方便编写遵守一定命令行准则的程序,Linux提供了getopt函数,其原型如下:

#include <unistd.h>

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

>> 关于getopt的参数

getopt函数的参数有三个:

  • argc 和 argv : getopt将传递给main函数的argc和argv作为参数。
  • const char *optstring :一个字符串,其中的每一个字符代表着一个单字符选项(即用户只能使用这些选项)。

对于optstring参数:

  • 如,该字符串参数为"abcd",则表示有四个选项参数:-a-b-c-d

  • 如果一个字符后面跟着一个冒号( : ),则表示该选项参数后面必须有一个关联值。如字符串参数为"f:h",则表示有两个选项参数:-f-h ,但是 -f 后面必须有一个关联值,比如一个文件名。

  • 以命令 gcc prog.c -o prog为例, -o 表示一个选项参数,而非选项参数 prog 就是它的一个关联值。

>> 关于getopt的返回值及一些行为

  • getopt的返回值是argv数组中的下一个选项字符(循环调用getopt可遍历所有选项),如果不存在则返回-1

  • 如果选项参数有一个关联值,则外部指针变量optarg将指向该关联值。(注意在getopt函数的原型中列出了一些外部变量)

  • 如果遇到一个无法识别的选项字符(即该字符不存在于字符串参数optstring中),则getopt会返回一个问号( ? ),并且这个无法识别的字符会被保存至外部变量optopt中。

  • 如果一个选项参数要求一个关联值参数,但用户并没有提供,则getopt也会返回一个问号,并将这个选项参数保存至外部变量optopt中;但是如果字符串参数optstring中的第一个字符是一个冒号( : ),那么这种情况下getopt将不会返回问好,而是返回一个冒号。

>> getopt函数的简单示例

//FILENAME: getoptdemo.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    int opt;

    while((opt = getopt(argc, argv, ":f:h")) != -1)
    {
        switch(opt){
            case 'f':
                printf("FILENAME: %s\n", optarg);
                break;
            case 'h':
                printf("This is a demo.\n");
                break;
            case '?':
                printf("ERROR: unrecognized command line option ‘-%c’\n", optopt);
                break;
            case ':':
                printf("‘-%c’ needs a value\n", optopt);
                break;
        }
    }
    exit(0);
}

运行结果1

$ ./optdemo -f
‘-f’ needs a value
$

运行结果2

$ ./optdemo -h
This is a demo.
$

运行结果3

$ ./optdemo -f demo.c
FILENAME: demo.c
$

运行结果4

$ ./optdemo -x
ERROR: unrecognized command line option ‘-x’
$

运行结果5

$ ./optdemo -f demo.c -h
FILENAME: demo.c
This is a demo.
$

getopt_long函数

如果要让程序能够使用长选项参数,可以使用getopt_long函数(使用该函数,原来的单字符选项参数依然可以使用)。

>> getopt_long的简单示例

因为getopt_long的用法与getopt差不多,所以先直接给一个示例:

//FILENAME: longoptdemo.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define _GNU_SOURCE
#include <getopt.h>

int main(int argc, char **argv)
{
    int opt;
    struct option longopts[] = {
        {"help", 0, NULL, 'h'},
        {"file", 1, NULL, 'f'},
        {0, 0, 0, 0}
    };

    while((opt = getopt_long(argc, argv, ":hf:", longopts, NULL)) != -1)
    {
        switch(opt){
            case 'f':
                printf("FILENAME: %s\n", optarg);
                break;
            case 'h':
                printf("This is a demo.\n");
                break;
            case '?':
                printf("ERROR: unrecognized command line option ‘-%c’\n", optopt);
                break;
            case ':':
                printf("‘-%c’ needs a value\n", optopt);
                break;
        }
    }
    exit(0);
}

  该示例与getopt示例的功能基本一样,另外getopt_long函数的前三个参数和getopt的三个函数完全一模一样。第四个参数是一个结构数组,第五个参数是一个变量指针。
  该结构数组下面将提到,而变量指针相当于长选项参数版的optind(这里并没有用到它,所以设为NULL)。

>> struct option结构

  getopt_long函数的第四个参数是一个结构数组,数组中的每个元素都是一个 struct option 结构。
  这个结构用于描述一个长选项参数,它被定义在头文件 getopt.h 中,并且还要将常量 _GNU_SOURCE 一同包含进来才能使用getopt功能(见源文件的预处理部分)。

该结构的定义如下所示:

struct option{
	const char *name;
	int has_arg;
	int *flag;
	int val;
}

各成员的含义如下:

成员变量说明
name长选项的名字
has_arg用于表示该选项是否带参数(可以理解为之前的关联值)。0表示不带参数、1表示必须带一个参数、2表示可以带一个参数
flag若flag为NULL,则表示当getopt_long扫描到一个长选项参数时,将返回成员变量val的值;
若flag不为NULL,则表示当get_long扫描到一个长选项参数时,将返回0,并将成员变量val的值写入flag所指向的变量
val一个长选项结构要设置一个对应的值val,其用途为上面flag变量中所述

最后还需要注意一点: 长选项结构数组的最后一个元素必须是 {0, 0, 0, 0}

>> 运行结果

运行结果1

$ ./longoptdemo --help
This is a demo.
$

运行结果2

$ ./longoptdemo -h
This is a demo.
$

运行结果3

$ ./longoptdemo --file demo.c
FILENAME: demo.c
$

运行结果4

$ ./longoptdemo -x
ERROR: unrecognized command line option ‘-x’
$

* 该笔记并没有说明两个外部变量(optind、opterr)的作用,另外示例程序也有一些不合理的地方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值