如何parsingC ++中的命令行参数?
可能重复:
C ++有哪些参数parsing器库?
如果程序被指定为像这样运行,那么在C ++中parsing命令行参数的最好方法是什么:
prog [-abc] [input [output]]
STL有图书馆吗?
有关:
- parsingunicode C ++应用程序中的命令行参数
Boost.Program_options应该做的伎俩
boost::program_options
和GNU getopt的build议是很好的。
但是,对于简单的命令行选项,我倾向于使用std :: find
例如,在-f
命令行参数之后读取文件的名称。 您也可以检测单个单词选项是否已经通过,如-h
寻求帮助。
#include <algorithm> char* getCmdOption(char ** begin, char ** end, const std::string & option) { char ** itr = std::find(begin, end, option); if (itr != end && ++itr != end) { return *itr; } return 0; } bool cmdOptionExists(char** begin, char** end, const std::string& option) { return std::find(begin, end, option) != end; } int main(int argc, char * argv[]) { if(cmdOptionExists(argv, argv+argc, "-h")) { // Do stuff } char * filename = getCmdOption(argv, argv + argc, "-f"); if (filename) { // Do interesting things // ... } return 0; }
在使用这种方法的时候,你必须使用std :: strings作为std :: find的值,否则在指针值上执行相等性检查。
我希望可以编辑这个响应,而不是添加一个新的响应,因为这是基于原始的答案。 我稍微重写了函数,并将它们封装在一个类中,所以这里是代码。 我也教过这种方式也可以使用它:
class InputParser{ public: InputParser (int &argc, char **argv){ for (int i=1; i < argc; ++i) this->tokens.push_back(std::string(argv[i])); } /// @author iain const std::string& getCmdOption(const std::string &option) const{ std::vector<std::string>::const_iterator itr; itr = std::find(this->tokens.begin(), this->tokens.end(), option); if (itr != this->tokens.end() && ++itr != this->tokens.end()){ return *itr; } static const std::string empty_string(""); return empty_string; } /// @author iain bool cmdOptionExists(const std::string &option) const{ return std::find(this->tokens.begin(), this->tokens.end(), option) != this->tokens.end(); } private: std::vector <std::string> tokens; }; int main(int argc, char **argv){ InputParser input(argc, argv); if(input.cmdOptionExists("-h")){ // Do stuff } const std::string &filename = input.getCmdOption("-f"); if (!filename.empty()){ // Do interesting things ... } return 0; }
我可以build议模板化的C ++命令行parsing器库 ( 在GitHub上有一些分支可用),API非常简单,并且(从网站引用):
该库完全在头文件中实现,使其易于使用和与其他软件分发。 它根据麻省理工学院许可证进行无忧发行。
这是手册中的一个例子,为简单起见,
#include <string> #include <iostream> #include <algorithm> #include <tclap/CmdLine.h> int main(int argc, char** argv) { // Wrap everything in a try block. Do this every time, // because exceptions will be thrown for problems. try { // Define the command line object, and insert a message // that describes the program. The "Command description message" // is printed last in the help text. The second argument is the // delimiter (usually space) and the last one is the version number. // The CmdLine object parses the argv array based on the Arg objects // that it contains. TCLAP::CmdLine cmd("Command description message", ' ', "0.9"); // Define a value argument and add it to the command line. // A value arg defines a flag and a type of value that it expects, // such as "-n Bishop". TCLAP::ValueArg<std::string> nameArg("n","name","Name to print",true,"homer","string"); // Add the argument nameArg to the CmdLine object. The CmdLine object // uses this Arg to parse the command line. cmd.add( nameArg ); // Define a switch and add it to the command line. // A switch arg is a boolean argument and only defines a flag that // indicates true or false. In this example the SwitchArg adds itself // to the CmdLine object as part of the constructor. This eliminates // the need to call the cmd.add() method. All args have support in // their constructors to add themselves directly to the CmdLine object. // It doesn't matter which idiom you choose, they accomplish the same thing. TCLAP::SwitchArg reverseSwitch("r","reverse","Print name backwards", cmd, false); // Parse the argv array. cmd.parse( argc, argv ); // Get the value parsed by each arg. std::string name = nameArg.getValue(); bool reverseName = reverseSwitch.getValue(); // Do what you intend. if ( reverseName ) { std::reverse(name.begin(),name.end()); std::cout << "My name (spelled backwards) is: " << name << std::endl; } else std::cout << "My name is: " << name << std::endl; } catch (TCLAP::ArgException &e) // catch any exceptions { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } }
您可以使用GNU GetOpt (LGPL)或各种C ++端口之一,例如getoptpp (GPL)。
使用GetOpt( prog [-ab]input )的简单示例如下:
// C Libraries: #include <string> #include <iostream> #include <unistd.h> // Namespaces: using namespace std; int main(int argc, char** argv) { int opt; string input = ""; bool flagA = false; bool flagB = false; // Retrieve the (non-option) argument: if ( (argc <= 1) || (argv[argc-1] == NULL) || (argv[argc-1][0] == '-') ) { // there is NO input... cerr << "No argument provided!" << endl; //return 1; } else { // there is an input... input = argv[argc-1]; } // Debug: cout << "input = " << input << endl; // Shut GetOpt error messages down (return '?'): opterr = 0; // Retrieve the options: while ( (opt = getopt(argc, argv, "ab")) != -1 ) { // for each option... switch ( opt ) { case 'a': flagA = true; break; case 'b': flagB = true; break; case '?': // unknown option... cerr << "Unknown option: '" << char(optopt) << "'!" << endl; break; } } // Debug: cout << "flagA = " << flagA << endl; cout << "flagB = " << flagB << endl; return 0; }
另一种select是精益平均C ++选项parsing器:
http://optionparser.sourceforge.net
它是一个只有头文件的库(实际上只是一个单独的头文件),与其他所有的build议不同,它也是独立的,也就是说它没有任何依赖关系。 特别是对STL没有依赖性。 它甚至不使用exception或其他任何需要库支持的东西。 这意味着它可以与简单的C或其他语言链接,而不需要引入“外部”库。
像boost :: program_options一样,它的API提供了方便的直接访问选项,即你可以这样写代码
如果(选项[帮助])…;
和
int verbosity = options [VERBOSE] .count();
与boost :: program_options不同的是,这只是使用一个用(用户提供的)枚举索引的数组。 这提供了一个没有重量的关联容器的便利。
这是有据可查的,并有一个公司友好的许可证(MIT)。
TLMC ++ OP包含一个很好的使用消息格式化程序,可以进行换行和列alignment,这对于本地化您的程序非常有用,因为它可以确保即使在消息较长的语言中输出也会很好。 它也为您节省80个列的手动格式化您的使用滋扰。
AnyOption是一个C ++类,用于轻松parsing复杂的命令行选项。 它还parsing选项值对格式中的rsourcefile选项。
AnyOption实现了传统的POSIX风格字符选项(-n)以及较新的GNU风格长选项(–name)。 或者,您可以通过要求忽略POSIX样式选项来使用更简单的长选项版本(-name)。
如果你可以使用Boost库,我会推荐boost :: program_options。
在STL和常规的C ++ / C运行库中都没有特定的东西。
尝试CLPP库。 它是用于命令行参数parsing的简单而灵活的库。 仅头和跨平台。 仅使用ISO C ++和Boost C ++库。 恕我直言,它比Boost.Program_options更容易。
库: http : //sourceforge.net/projects/clp-parser
2010年10月26日 – 新版本2.0rc。 修正了很多错误,对源代码,文档,示例和注释进行了全面的重构。
相当晚的答案,但我已经使用GetPot的一些项目: http ://getpot.sourceforge.net/
主要特点:一切都在一个单一的头文件,没有build设麻烦。 把它保存在你的机器上的某个地方,然后在你的文件中包含main()
最近没有更新,但很好的文档,并运行良好。 你可以试试看。
for (int i = 1; i < argc; i++) { if (strcmp(argv[i],"-i")==0) { filename = argv[i+1]; printf("filename: %s",filename); } else if (strcmp(argv[i],"-c")==0) { convergence = atoi(argv[i + 1]); printf("\nconvergence: %d",convergence); } else if (strcmp(argv[i],"-a")==0) { accuracy = atoi(argv[i + 1]); printf("\naccuracy:%d",accuracy); } else if (strcmp(argv[i],"-t")==0) { targetBitRate = atof(argv[i + 1]); printf("\ntargetBitRate:%f",targetBitRate); } else if (strcmp(argv[i],"-f")==0) { frameRate = atoi(argv[i + 1]); printf("\nframeRate:%d",frameRate); } }