C语言中命令行工具 (getopt和getopt_long)


#include <iostream>
#include <unistd.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

/* @getopt的全局变量
** 1. char* optarg:正在解析的选项的参数
** 2. int optind:指向下一个选项的索引
** 3. int opterr:非0时会将错误信息打印在stdout上
** 4. int optopt:若一个选项在argv中,但不在选项字符串中时,或者一个带参数的选项没有参数时,getopt()会返回字符?,同时将optopt设为该选项
*/
extern char *optarg;
extern int optind, opterr, optopt;

void test01(int argc, char *argv[])
{
    
    
    /* @param
    ** 参数选项有  -a -b -c -d
    ** 其中-a  -b后面不带“:”  所以这两个选项不可以有参数,即使有参数他也不会去识别
    ** -c 后面有一个“:”  所以这个选项后面必须有参数,参数有两种形式  1. 参数紧贴选择项 -b100 ;  2. 参数跟选项使用空格分隔  -b 100
    ** -d 后面有两个“:”  所以这个选项后面的参数可有可无,当有参数的时候  参数必须紧贴选项
    */
    int opt = -1;
    while (opt = getopt(argc, argv, "abc:d::") != -1)
    {
    
    
        cout << "opt: " << opt << endl;

        cout << "optarg:" << optarg << endl;
        cout << "optopt:" << optopt << endl;
        cout << "optind:" << optind << endl;
    }

    cout << "opterr:" << opterr << endl;
}

/*
** getopt()允许我们设置optstring的首字符为冒号":",在这种情况下,
** 当发生无法识别的选项错误时getopt()返回字符"?",当发生丢失选项参数错误时返回字符":"。
** 这样我们就可以很轻松地分辨出错误类型了,
** 不过getopt()不会再打印错误信息了,一切事物都由我们自己来处理了。
*/

void test02(int argc, char *argv[])
{
    
    
    int verbose = 0; // 一个输出的判断条件
    int n = 0;       // 用于计数
    char opt;        // 用于存getopt函数的返回值

    // 一直循环解析  直到解析完毕
    while ((opt = getopt(argc, argv, "vn:")) != -1)
    {
    
    
        switch (opt)
        {
    
    
        case 'v':
            verbose = 1; // 将输出条件判断置为1
            break;
        case 'n':
            n = atoi(optarg); // 将选项-n的参数字符串转为整数
            cout << "n : " << n << endl;
            break;
        default:
            fprintf(stderr, "usage: error");
            exit(-1); // 异常退出程序
        }
    }
    int i = 0;
    for (i = 0; i < n; ++i)
    {
    
    
        if (verbose)
            cout << i << endl;
    }
    cout << "Done counting to " << n << endl;
}

int main1(int argc, char *argv[])
{
    
    
    if (argc < 2)
        return -1;
    test02(argc, argv);

    return 0;
}

/* ---------------------------------------------------------  */
/*
** int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
** 与getopt类似  但是getopt_long可接收长选项,长选项以“--”开头
** 如果程序只接受长选项,必须将optstring设置为空字符串“”
** 长选项可以采用两种形式:--arg=param或--arg param
** longopts是一个指针指向结构体option数组
*/
/* option结构体
** struct option {
**   const char *name;      // 长选项的名字
**   int         has_arg;   // 0不需要参数,1需要参数,2参数可选
**   int        *flag;      // 指定长选项的返回结果类型:flag=NULL时getopt_long返回val(可以将val设置为等效的短选项字符),flag!=NULL时getopt_long返回0
**   int         val;       // 要返回的值
** };
*/

int main(int argc, char *argv[])
{
    
    
    int c;
    int digit_optind = 0;

    while (1)
    {
    
    
        int this_option_optind = optind ? optind : 1;
        int option_index = 0;
        static struct option long_options[] = {
    
    
            {
    
    "add", required_argument, 0, 0},
            {
    
    "append", no_argument, 0, 0},
            {
    
    "delete", required_argument, 0, 0},
            {
    
    "verbose", no_argument, 0, 0},
            {
    
    "create", required_argument, 0, 'c'},
            {
    
    "file", required_argument, 0, 0}, // optional_argument  参数可选
            {
    
    0, 0, 0, 0}
            /* 注意:option结构数组的最后一个元素必须用0填充 */
        };

        c = getopt_long(argc, argv, "abc:d:012", long_options, &option_index);
        if (c == -1)
            break;

        switch (c)
        {
    
    
        case 0:

            if (strcmp(long_options[option_index].name, "add") == 0)
                fprintf(stdout, "long option \"add\" value: %s\n", optarg);
            else if (strcmp(long_options[option_index].name, "append") == 0)
                fprintf(stdout, "long option \"append\"\n");
            else if (strcmp(long_options[option_index].name, "delete") == 0)
                fprintf(stdout, "long option \"delete\" value: %s\n", optarg);
            else if (strcmp(long_options[option_index].name, "create") == 0)
                fprintf(stdout, "long option \"create\" value: %s\n", optarg);
            else if (strcmp(long_options[option_index].name, "verbose") == 0)
                fprintf(stdout, "long option \"verbose\"\n");
            else if (strcmp(long_options[option_index].name, "file") == 0)
                fprintf(stdout, "long option \"file\" value: %s\n", optarg);
            break;
        case '0':
        case '1':
        case '2':
            if (digit_optind != 0 && digit_optind != this_option_optind)
                fprintf(stdout, "digits occur in two different argv elements.\n");
            digit_optind = this_option_optind;
            fprintf(stdout, "option %c\n", c);
            break;
        case 'a':
            fprintf(stdout, "option a\n");
            break;
        case 'b':
            fprintf(stdout, "option b\n");
            break;
        case 'c':
            fprintf(stdout, "option c with value '%s'\n", optarg);
            break;
        case 'd':
            fprintf(stdout, "option d with value '%s'\n", optarg);
            break;
        case '?':
            break;
        default:
            fprintf(stdout, "?? getopt returned character code 0%o ??\n", c);
        }
    }

    if (optind < argc)
    {
    
    
        fprintf(stdout, "non-option argv elements: ");
        while (optind < argc)
            fprintf(stdout, "%s ", argv[optind++]);
        fprintf(stdout, "\n");
    }
}

猜你喜欢

转载自blog.csdn.net/Stars____/article/details/129874598