自定义命令行参数

问题描述:

我遇到命令行参数问题。我完成了计划,所以我可以像这样的命令行启动它:自定义命令行参数

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; 
} 

那么,你的新格式参数,你不能只是将它们传递给流构造函数。

您必须检查它们是否以特定字符串开头,例如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); 
+0

谢谢。这非常有帮助。 U'r da man:D – 2011-01-24 11:33:41

你应该分析mainargv参数,以检查它们是否开始由-input-output等等等等

从头开始做,这是一个地狱,但幸运的是有许多有用的库要做到这一点,像boost.program_options

+0

+1这个库是一个很好的发现,也是一个很好的方式来表明*不必被重新发明。 – jmort253 2011-01-24 10:26:05

你可以不再需要为高级用户不得不每次运行程序时都键入不必要的文本,而是提供一个显示使用情况的-help开关。

这通常是大多数命令行程序所采取的方法,也是很多命令行爱好者都喜欢命令行的简单性和强大功能的原因。

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

+0

这不是关于输入较少:选项(以 - 开头)应该是可选的,而参数(不以 - 开头)通常是必需的。 – 2011-01-24 10:37:12

我有点晚与此聚会,但我会提供更新的答案。实际上,您可以使用'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下同)。

开始无耻插头(即围绕getopt的建立了自己的CLOptions代码)

我其实有点不满与工作量也采取了与参数,可能是得到的getopt的完全成熟的功能boolean,double,int或string。我还必须在每个项目中创建一个全新的实现!所以,我把一个名为“CLOptions”的快速课放在一起,这样我就可以在我的代码中使用#include "CLOptions.h"(一切都在一个文件中),现在我只需要一行来定义每个附加选项。它还会创建-h-help选项来为您打印帮助信息!它包括根据您定义每个参数的方式将每个参数作为bool,double,int或字符串获取的功能。你可以在GitHub here上看看它,例如how the above method could be implemented。请注意,该类是C++ 11,编译时需要-std=c++11(但如果有人问,我可以尝试编写C版本)。

虽然我还没有尝试过,但还有一些其他人为解决此问题而设计的其他命令行程序(例如optionsdropt)。你大概可以通过使用Google搜索来找到它们。