当long选项作为短选项的参数给出时 - getopt_long

时间:2016-01-01 18:38:07

标签: command-line-arguments getopt getopt-long

我正在学习如何使用getopt_long函数接受命令行参数,我做了2个长选项' filename' (必需的arg)和' clear' (没有arg)和2个简短的args' a' (使用arg)和' b' (没有arg)当我执行时:

$ ./a.out -a --filename=test.txt

而不是显示' a'没有arg它显示了' a'是: --filename = text.txt并跳过文件名长选项 有没有解决这个问题?

我的代码是:

#include <iostream>
#include <getopt.h>

using namespace std;



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

    static struct option long_options[] = {
        {"filename",1,0,0},
        {"clear",0,0,0},
        {NULL,0,0,0}
    };

    int op,option_index = 0;
    string filename;
    while((op = getopt_long(argc,argv,"a:b",long_options,&option_index))!=-1){
        switch (op){
            case 0:
                switch(option_index){
                    case 0:
                        filename = optarg;
                        cout<<filename<<endl;
                        break;
                    case 1:
                        cout<<"clear is yes\n";
                        break;
                    default:
                        cout<<"Please enter valid long option\n";
                        break;
                }break;
            case 'a':
                cout<<"a is set as "<<optarg<<endl;
                //cout<<optarg<<endl;
                break;
            case 'b':
                cout<<"b is set"<<endl;
                    break;
            default:
                cout<<"Please enter valid Arguments"<<endl;
                break;
        }
    }
    cout<<"\n\n";

    return 0;
}

2 个答案:

答案 0 :(得分:1)

我发现了一个更好的答案,我的朋友告诉了我。

我可以直接使用::而不是:这意味着'a'需要一个可选参数,所以getopt_long将检查arg是否是一个选项如果没有arg或arg是一个选项0被返回我可以处理如果“a”具有非选项arg,则表示该情况正常处理。

最终代码如下:

#include <iostream>
#include <getopt.h>

using namespace std;



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

    static struct option long_options[] = {
        {"filename",1,0,0},
        {"clear",0,0,0},
        {NULL,0,0,0}
    };

    int op,option_index = 0;
    string filename;
    while((op = getopt_long(argc,argv,"a::b",long_options,&option_index))!=-1){
        switch (op){
            case 0:
                switch(option_index){
                    case 0:
                        filename = optarg;
                        cout<<filename<<endl;
                        break;
                    case 1:
                        cout<<"clear is yes\n";
                        break;
                    default:
                        cout<<"Please enter valid long option\n";
                        break;
                }break;
            case 'a':
                if(optarg)
                    cout<<"a is set as "<<optarg<<endl;
                else 
                    cout<<"a needs an argument"<<endl;
                //cout<<optarg<<endl;
                break;
            case 'b':
                cout<<"b is set"<<endl;
                    break;
            default:
                cout<<"Please enter valid Arguments"<<endl;
                break;
        }
    }
    cout<<"\n\n";

    return 0;
}

此处不需要硬编码。

答案 1 :(得分:0)

一种方法是查看-a的参数,看看它是否真的是一种选择。如果是,请处理错误并设置optind -= 1,以便getopt_long()进一步处理将错误地跟随-a作为选项的选项。不是特别优雅,但它有效。

以下是一个例子:

#include <iostream>
#include <getopt.h>

#include <string.h>

using namespace std;


int str_startswith( char const* s, char const* prefix)
{
    return strncmp(prefix, s, strlen(prefix)) == 0;
}


bool is_option(char const* arg)
{
    int result = 0;

    result = result || str_startswith( arg, "--filename=");
    result = result || (strcmp( arg, "--clear") == 0);
    result = result || (strcmp( arg, "-b") == 0);

    return result;
}



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

    static struct option long_options[] = {
        {"filename",1,0,0},
        {"clear",0,0,0},
        {NULL,0,0,0}
    };

    int op,option_index = 0;
    string filename;
    while((op = getopt_long(argc,argv,"a:b",long_options,&option_index))!=-1){
        switch (op){
            case 0:
                switch(option_index){
                    case 0:
                        filename = optarg;
                        cout << "filename is: " <<filename<<endl;
                        break;
                    case 1:
                        cout<<"clear is yes\n";
                        break;
                    default:
                        cout<<"Please enter valid long option\n";
                        break;
                }break;
        case 'a':
                if (is_option(optarg)) {
                    cout << "-a option requires an argument" << endl;
                    optind -= 1; // put the option back into consideration for getopt_long()
                }
                else {
                    cout << "a is set as " << optarg << endl;
                }
                break;
            case 'b':
                cout<<"b is set"<<endl;
                    break;
            default:
                cout<<"Please enter valid Arguments"<<endl;
                break;
        }
    }
    cout<<"\n\n";

    return 0;
}

我希望改进这一点的一种方法是让检查参数是否可能是一个选项的函数是让它通过与getopt_long()long_options[]getopt_long()相同的结构来查看getopt_long())的字符串参数,而不是像我的快速脏例子那样硬编码。

事实上,由于这是几周内第二次我在SO上遇到这个问题(我找不到另一个),为{{创建一个包装器可能需要付出代价。 1}}和提供帮助函数的朋友正是这样做的。也许我会在本周末晚些时候开始工作......