c++ - 处理 main 中的可选参数

标签 c++ parameters program-entry-point optional-parameters

假设我有一个 main 函数,它基本上只是调用另一个函数作为程序的入口点。该函数(以及整个程序)有一些强制参数和一些可选参数:

#include <iostream>
#include <sstream>

void function_to_call(std::string arg1,
                  std::string arg2,
                  std::string arg3,
                  std::string arg4,
                  std::string arg5 = "foo",
                  std::string arg6 = "bar",
                  int num1 = 1,
                  int num2 = 2
                  )

{
  // do fancy stuff here                                                                                                                                                                                                                                                                                                
}


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

  int num1, num2;

  std::stringstream stream;

  if( argc < 5 ) {
    std::cerr << "Usage: \n\t" << argv[0]
              << "\n\t\t1st argument"
              << "\n\t\t2nd argument"
              << "\n\t\t3rd argument"
              << "\n\t\t4th argument"
              << "\n\t\t5th argument (optional)"
              << "\n\t\t6th argument (optional)"
              << "\n\t\t7th argument (optional)"
              << "\n\t\t8th argument (optional)"
              << "\n\t\t9th argument (optional)" << std::endl;
  }
  if( argc == 5 ) {
    function_to_call( argv[1], argv[2], argv[3], argv[4] );
  }
  if( argc == 6 ) {
    function_to_call( argv[1], argv[2], argv[3], argv[4], argv[5] );
  }
  if( argc == 7 ) {
    function_to_call( argv[1], argv[2], argv[3], argv[4], argv[5], argv[6] );
  }
  if( argc == 8 ) {
    stream << argv[7];
    stream >> num1;
    function_to_call( argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], num1 );
  }
  if( argc == 9 ) {
    stream << argv[7] << ' ' << argv[8];
    stream >> num1 >> num2;
    function_to_call( argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], num1, num2 );
  }

  return 0;

}

if 链可以用 switch 替换,命令行可以通过使用 getopt 库或boost program_options,但这并没有真正改变概念上的事情。

我是否缺少一种明显的方法来处理不同数量的参数?

最佳答案

命令行参数数组是null 终止,因此您可以像这样一次解析一个元素:

void function_to_call(std::string arg1,
                  std::string arg2,
                  std::string arg3,
                  int num1,
                  int num2
                  )

{
  // do fancy stuff here
    std::cout << "arg1: " << arg1 << '\n';
    std::cout << "arg2: " << arg2 << '\n';
    std::cout << "arg3: " << arg3 << '\n';
    std::cout << "num1: " << num1 << '\n';
    std::cout << "num2: " << num2 << '\n';
}

struct config
{
    std::string arg1;
    std::string arg2;
    std::string arg3 = "wibble"; // set arg3 default here
    int arg4 = 1;                // set arg4 default here
    int arg5 = 0;                // set arg5 default here
};

config parse_command_params(char** argv)
{
    config cfg;

    if(!argv[1])
        throw std::runtime_error("At least 2 args required");

    cfg.arg1 = argv[1];

    if(!argv[2])
        throw std::runtime_error("At least 2 args required");

    cfg.arg2 = argv[2];

    // optional from here on

    if(!argv[3])
        return cfg;

    cfg.arg3 = argv[3];

    if(!argv[4])
        return cfg;

    cfg.arg4 = std::stoi(argv[4]);

    if(!argv[5])
        return cfg;

    cfg.arg5 = std::stoi(argv[5]);

    return cfg;
}

int main(int, char** argv)
{
    try
    {
        config cfg = parse_command_params(argv);

        function_to_call(cfg.arg1, cfg.arg2, cfg.arg3, cfg.arg4, cfg.arg5);
    }
    catch(std::exception const& e)
    {
        std::cerr << e.what() << '\n';
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

通过将参数存储在 struct 中,我可以使用它来设置可选参数的默认值,如果它们不存在于用户提供的参数中,则简单地忽略它们。

注意:编辑以包含@cmaster 将解析移动到专用函数的建议。

关于c++ - 处理 main 中的可选参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39550684/

相关文章:

c++ - 在 C++ 中读取未知编码的文本文件

c++ - 使用 unordered_map 分配器的非默认构造函数

c++ - C++中空字符串包含什么

bash - 在 bash 中使用参数文本文件

c - 将常量指针作为参数传递给另一个函数的问题

java - 为什么Java main 方法是静态的?

c++ - 不能在 C++ 中使用宏

ruby-on-rails - 我可以自定义 Rails 过滤参数的方式吗?

clojure - Clojure 中的多行 shebang?

c# - 在 WPF 的自定义 main() 中获取对 MainWindow 的引用