初识c语言时,我一直将main函数写作 int main(void),但随着学习的深入,我了解到main函数身为一个函数,当然也可以接收输入的参数,它的参数就是进程开始时输入的命令。所以main函数的完整形式应该写作:
int main(int argc,char *argv[]),其中argc是一个int型变量,储存命令参数的个数,argv是一个指针数组名
(所以char *argv[] 也可以写作char **argv),其中保存着命令参数字符串。
可以写一个小程序打印传入main函数的命令参数:
test.c
#include<stdio.h>
int main(int argc,char *argv[])
{
int count;
while(count < argc){
printf("argv[%d]:%s\n",count,argv[count]);
count++;
}
return 0;
}
将test.c编译运行,并在运行时随意添加一些参数。
从运行结果可以看到,运行时输入的命令被保存在argv[]中。
需要注意的是argv[]的第一个元素argv[0]默认保存的是程序名,而且argv[]是以NULL结尾的,也就是说当有n个命令参数被保存在argv[]中时,数组中第n+1个元素是NULL,即argv[argc]是NULL。将test.c稍修改一下即可验证:
test.c
#include<stdio.h>
int main(int argc,char *argv[])
{
int count;
while(count < argc){
printf("argv[%d]:%s\n",count,argv[count]);
count++;
}
printf("argv[%d]:%s\n",count,argv[count]);
return 0;
}
当然,只给main函数传递参数是不够的,我们还需要在函数里分析参数,下面简要介绍常用的命令参数分析函数getopt()。
函数原型:
#include<unistd.h>
extern char *optarg;
extern int optind, // 初始化值为1,下一次调用getopt时,从optind存储的位置重新开始检查选项,也就是从下一个'-'的选项开始。
extern int opterr, // 初始化值为1,当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt; // 当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt中,getopt返回’?’。
int getopt(int argc,char * const argv[ ],const char * optstring);
argv[]数组中第1个元素argv[0]是程序名,真正的参数从第二个元素开始,即argv[1],所以optind被初始化为1。 每调用一次getopt()函数,返回一个选项,如果该选项有参数值,则optarg指向该参数值。
在命令行选项参数再也检查不到optstring中包含的选项时,返回-1。
参数中的argc和argv[]和main函数的形参意义相同,optstring是选项字符串,用来告知getopt()接收的参数中哪些是可以处理的选项,以及哪个选项需要参数。其中,以'-'开头的是短选项参数,以'--'开头的是长选项参数,getopt()函数只能处理短选项参数。例如现在输入命令 ./test -a 123 -b c 此命令中, "-a" "-b" 就是选项参数,而 123 和 c 是参数值。
这里需要注意三点:
optind——再次调用 getopt() 时的下一个 argv 指针的索引。
optopt——最后一个未知选项。
举个例子说明:
假设现在a.out是一个可以接受 "-a" "-b" "-f" 选项的程序,其中"-a"选项必须跟参数值,"-b"选项不需要参数值,"-f"选项可跟可不跟参数值。用getopt()函数分析命令行参数的代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
char ch;
int count=0;
opterr=0;
while((ch=getopt(argc,argv,"a:bf::")) != -1){
switch(ch){
case 'a':
printf("optinon a:%s\n",optarg);
break;
case 'b':
printf("optinon b:%s\n",optarg);
break;
case 'f':
printf("option f:%s\n",optarg);
break;
default:
printf("other option:%c\n",ch);
break;
}
}
return 0;
}
编译后运行输入 ./a.out -a 123 -b asdf -c -f 运行结果如下:
"-a"选项需要一个参数值,getopt()将"123"存入optarg。"-b"选项不需要参数值,故忽略命令中"-b"后面的参数值,optarg输出为NULL。optstring中没有"-c"选项,getopt()返回'?'。"-f"选项后面没有参数值,optarg输出NULL。
从结果可以看出,每次调用getopt()函数会依次检查命令参数,根据optstring字符串查找选项,返回选项的字符(如"-a"选项返回'a')。并检查是否带参数值,如果有参数值则将其存入optarg中,如果在处理期间遇到了不符合optstring指定的选项,getopt()将返回'?',同时打印一个错误信息,并将optarg置为NULL,如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。