C语言(Head First C)-4_3:创建小工具:命令行选项

 

 前文《 C语言(Head First C)-4_2:创建小工具:做一件事并把它做好》

 

 4_3 命令行选项:

 

 十个程序有九个需要选项;聊天程序有“系统设置”;游戏有调整难度的选项;而命令行工具需要有命令行选项;

 命令行选项是一些小开关,他们经常出现在命令行中;

 如:

 ps -ae //显示所有进程,包括后台运行的进程;

 

 由库代劳:

 很多程序都会使用命令行选项,因此有一个专门的库函数,可以用它来简化处理过程;

 这个库函数叫getopt(),每次调用都会返回命令行中下一个参数;说的可能比较抽象,我们接着来;

 

 C标准礼貌指南:

 unistd.h头文件不属于C标准库,而是POSIX库中的一员;POSIX的目标是创建一套能够在所有主流操作系统上使用的函数;

 

 getopt():

 -库函数getopt(),每次调用都会返回命令行中下一个参数;

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


 -此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。


 -如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。


 -getopt()使用optstring所指的字串作为短参数列表,象"1ac:d::"就是一个短参数列表。短参数的定义是一个'-'后面跟一个字母或数字,象-a, -b就是一个短参数。每个数字或字母定义一个参数。


 - 其中短参数在getopt定义里分为三种:

 1). 不带值的参数,它的定义即是参数本身。

 2). 必须带值的参数,它的定义是在参数本身后面再加一个冒号。

 3). 可选值的参数,它的定义是在参数本身后面加两个冒号 。

 在这里拿上面的"1ac:d::"作为样例进行说明,其中的1,a就是不带值的参数,c是必须带值的参数,d是可选值的参数。


 -参数不分先后顺序;

 -当没有参数的最后的一次调用时,getopt()将返回-1。

 -当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回'?'。

 -当optstring是以':'开头时,缺值参数的情况下会返回':',而不是'?' 。

 

 现在假设程序接收一组不同的选项:"1ac:d::"(对应程序中的getopt()函数使用的optstring所指代的短参数列表)

 (Code4_1)

/*
 * 库函数getopt(),每次调用都会返回命令行中下一个参数
 */

#include 
#include //getopt()包含在的头文件

int main(int argc,char * argv[]) {
    
    int ch;
    opterr = 0;//全局变量
    while ((ch = getopt(argc,argv,"1ac:d::")) != -1) {
        printf("%i=>",optind);//全局变量
        
        switch (ch) {
            case 'c':
                printf("%s\n",optarg);//全局变量
                break;
            case 'd':
                printf("%s\n",optarg);
                break;
            default:
                printf("%c\n",ch);
                break;
        }
    }
    
    argc -= optind;//读取选项之后的字符串列表,计算argc;
    argv += optind;//读取选项之后的字符串列表,赋给argv;
    
    for (int i = 0; i < argc; i++) {
        printf("%s\n",argv[i]);
    }
    
    return 0;
}

 运行时传递命令行参数如下:

 ./4_1 -1 -a -c value -d

 log:

 1

 a

 value

 ?

 

 ./4_1 -1 -a -c value -b

 log:

 1

 a

 value

 ?

 

 ./4_1 -1 -a -c value -d valued

 log:

 1

 a

 value

 valued

 

上述代码循环调用getopt()函数处理命令行参数;

 可以通过optind保存了getopt()从命令行读取了第几个选项;(修改程序)

 运行:

./4_1 -1 -a -c value -d valued

 1      2  3  4    5   6     7

 log:

 2=>1

 3=>a

 5=>value

 7=>valued

 

 最后可以使用下面这两行来跳过已读取的选项:

 argc -= optind;//读取选项之后的字符串列表,计算argc;

 argv += optind;//读取选项之后的字符串列表,赋给argv;(修改程序)

 运行:./4_1 -1 -a -c value -d valued Landon Tokyo Beijing

 2=>1

 3=>a

 5=>value

 7=>valued

 Landon

 Tokyo

 Beijing

 

 在循环中,用switch语句处理了每个有效选项;设置短参数列表的字符串告诉getopt()函数,命令行选项该如何表示和识别;

 循环结束后,为了让程序读取命令行参数,需要调整一下argv和argc变量,跳过所有选项;如上面的示例所见,最后argv数组将变成:Landon Tokyo Beijing,分别对应argv[0],argv[1],argv[2];

 现在,经过一番处理之后,0号参数不再是程序名了,他指向了选项后的第一个命令行参数;

 

 类似这种格式:程序名 命令行选项 命令行参数

 

 这一章我们学习了:

 -深入理解标准输入、标准输出、标准错误;

 -使用重定向和自己创建的数据流读写文件;

 -处理命令行参数和选项;

 

 注意:

 命令行选项是可以合并的,顺序也是无关的:-ac value <=> -c value -a;

 命令行选项需要出现在命令行参数之前;

 如果想要读取负数的选项参数,可以用--隔开参数和选项;-c -- -4;getopt()看到--就会停止读取选项,程序会把后面的内容当成不同命令行选项参数读取;

 

 要点:

 -main()函数有两个版本,一个有命令行参数,一个没有;

 -命令行参数通过两个变量传递给main()函数,一个是参数的计数,一个是指针(指向参数字符串)数组;

 -命令行选项是以‘-’开头的命令行参数;

 -getopt()函数会帮助你处理命令行选项;

 -为定义有效的选项,需要传给getopt()函数一个字符串,声明短参数列表;

 -选项之后的':'表示该选项需要接收一个参数,getopt()会用optarg变量记录选项参数;

 -读取完全部的选项之后,应该用optind变量跳过他们;

 

 工具箱:

 -printf()和scanf()使用标准输出和标准输入来交互;

 -标准输出默认在显示器上显示数据;

 -标准输入默认从键盘读取数据;

 -标准错误专门用来输出错误消息;

 -可以用重定向把标准输出,标准错误和标准输入连接到其他地方;

 -可以用fprintf(stderr,...)把数据打印到标准错误;

 -命令行参数以字符串指针数组的形式传递给main();

 -用getopt()函数读取命令行选项很方便;

 -可以用fopen("文件名","模式")创建你自己的数据流;

 -三种模式分别为w(写入)、r(读取)、a(追加);

 

你可能感兴趣的:(C-深入浅出)