自定义命令行参数

时间:2011-01-24 10:19:40

标签: c++ arguments customization

我遇到命令行参数问题。我完成了程序,所以我可以从命令行启动它:

program.exe test.txt copy_test.txt

基本上,我的程序执行以下操作:

  • 输入一些文字文件
  • 对其进行排序并复制到新的文本文件

但是(总是这样但是?!),我应该从命令行启动程序,如下所示:

program.exe -input=test.txt -output=copy_test.txt

我不知道该怎么做。我研究过,但我找不到任何帮助:(

请回复。

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

int main ( int argc, char* argv[])
{
 ifstream in(argv[1]);
 ofstream out(argv[2]);
 vector <string> sV;
 string line;
 while (in >> line)
  sV.push_back(line);
 for ( int i = 0; i < sV.size(); i++)
 sort ( sV.begin(), sV.end () );
 for ( int i = 0; i < sV.size(); i++)
 out << sV[i] << endl;
 cin.get();
 return 0;
}

4 个答案:

答案 0 :(得分:7)

您应该解析mainargv个参数,以检查它们是否以-input-output等开头。

从头开始这是一个地狱,但幸运的是有很多有用的库可以做到这一点,比如boost.program_options

答案 1 :(得分:0)

您可以不必让高级用户每次运行程序时都必须输入不必要的文本,而是提供显示用法的-help开关。

这通常是大多数命令行程序采用的方法,也是许多命令行爱好者欣赏命令行的简单性和强大功能的原因。

另一种选择是提供两种方法,因为一些用户可能更喜欢更长的方法。

答案 2 :(得分:0)

好吧,使用新的格式参数,您不能只是按原样将它们传递给流构造函数。

您必须检查它们是否以特定字符串开头,例如使用strncmp,然后为输入类型传递相关位的地址,例如argv[1]+8

由于您提供--input=类型前缀,您可能还希望处理它们可能处于其他顺序的可能性。

例如,您可以替换:

int main (int argc, char* argv[]) {
    ifstream in(argv[1]);
    ofstream out(argv[2]);

有类似的东西:

int main (int argc, char* argv[]) {
    char *infile = 0;
    char *outfile = 0;
    for (int i = 1; i < argc; i++) {
        if (strncmp (argv[i], "--input=", 8) == 0) {
            infile = argv[i] + 8;
        } else {
            if (strncmp (argv[i], "--output=", 9) == 0) {
                outfile = argv[i] + 9;
            } else {
                std::cerr << "Invalid argument [" << argv[i] << "]" << std::endl;
                return -1;
            }
        }
    }
    if ((infile == 0) || (outfile == 0)) {
        std::cerr << "Need to specify input and output file" << std::endl;
        return -1;
    }

    ifstream in(infile);
    ofstream out(outfile);

答案 3 :(得分:0)

我有点迟到了,但我会提供更新的答案。您可以使用'getopt'实际获得C ++中所需的功能。使用getopt_long(),您可以创建单个字符选项(如-c)或命名选项(如--input)。您还可以使用getopt_long_only(),这样您只需使用一个短划线即可传递命名选项。例如,请参阅herethis answer

示例

这是一个应该完成你要做的事情的例子:

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

int main (int argc, char** argv)
{
    // Create the variables to store your parameters
    std::map<std::string, std::string> input_parameters ;
    input_parameters["input"] = "default_in" ;   // Storage for input
    input_parameters["output"] = "default_out" ; // Storage for output

    // Create variables to hold your parameters
    const struct option longopts[] =
    {
        {"input", required_argument, 0, 'i'},
        {"output", required_argument, 0, 'o'},
        {0,0,0,0} // This tells getopt that this is the end
    };

    // Some parameters for getopt_long
    int c(0);

    // Get the options from the command line
    while (c != -1) {
        int option_index(-1) ;

        // Read the next command line option
        // Note here that the ':' after the 'i' and 'o' denotes that
        // it requires an argument
        c = getopt_long(argc, argv, "i:o:", longopts, &option_index) ;

        // If the option is valid, fill the corresponding value
        if ((c>0)&&(option_index>=0)) {
            std::cout << option_index << std::endl;
            input_parameters[longopts[option_index].name] = optarg ;
        }

        switch (c) {
            case 'i':
                // Fill input option
                input_parameters["input"] = optarg ;
            case 'o':
                // Fill output option
                input_parameters["output"] = optarg ;
            case '?':
                // getopt_long printed an error message
                break ;
        }
    }

    std::cout << "input  = " << input_parameters["input"] << std::endl;
    std::cout << "output = " << input_parameters["output"] << std::endl;

    return 0 ;
}

请注意,在此处运行此操作会在参数和要传递给它的值之间留一个空格。这将产生以下结果:

$ ./myscript --input inputfile.txt --output outputfile.txt
input  = inputfile.txt
output = outputfile.txt

$ ./myscript -i inputfile.txt -o outpufile.txt
input  = inputfile.txt
output = outputfile.txt

您还可以互换使用--input-i(与--output-o类似)。

开始无耻插件(我自己的CLOptions代码围绕getopt构建)

我实际上对使用boopt,double,int或string参数获取getopt的完整功能所花费的工作量有点不满。我还必须在每个项目中创建一个全新的实现!所以,我把一个名为“CLOptions”的快速类放在一起,这样我就可以#include "CLOptions.h"在我的代码中(一切都在一个文件中),现在我只需要一行来定义每个附加选项。它还会为您打印帮助信息创建-h-help选项!它包括将每个参数作为bool,double,int或string的功能,具体取决于您定义每个参数的方式。您可以在GitHub here上查看how the above method could be implemented示例。请注意,该类是C ++ 11,并且在编译时需要-std=c++11(尽管如果有人问,我可以尝试编写C版本。)

虽然我还没有尝试过,但是还有许多其他人设计的其他命令行程序来解决这个问题(例如optionsdropt)。你可以通过Google搜索来找到它们。