【问题标题】:How do I throw error when user gives empty command line values?当用户给出空的命令行值时如何抛出错误?
【发布时间】:2017-03-14 07:55:41
【问题描述】:

我正在使用命令行选项来执行操作类型,因此,例如登录,用户必须执行类似NameOfExe --username Admin --password Admin的命令

我的问题是如何确保用户在他提供的选项中输入正确的值,并在NameOfExe --username --password 这样的情况下避免错误?

编辑:-

现在我采用这样的参数值

char* Cli::getCmdOption(char** begin,
                    char** end,
                    const std::string& option)
{
  char** itr = std::find(begin, end, option);

  if (itr != end && ++itr != end)
  {
        return *itr;
  }
    return (char*)"";
}

并将其用作getCmdOption(argv , argv+argc , "--userName")

【问题讨论】:

  • 通常你可以使用你的mainargcargv做出这样的决定
  • Boost 具有出色的命令行参数解析接口。用那个?见stackoverflow.com/questions/253556/…
  • 在您展示的示例中,它只是检查是否提供了用户名但没有密码。
  • 我确实有命令行参数,即 argc,argv,但是有多个命令需要不同的参数,例如 --name 和 --proxy
  • boost.org/doc/libs/1_36_0/doc/html/program_options.html 这是一个学习曲线(如果您之前从未使用过Boost,那么请等待一个月),但我认为值得。如果您有 Boost 经验,您的市场价值就会上升。

标签: c++


【解决方案1】:

这是进行参数解析的一种非常不寻常的方式,当参数的参数本身也是有效选项时(例如在您的--loginname "--password" 示例中),它可能会导致问题。

一种更惯用的 C++ 方法(直接在您的代码中,或隐藏在选项解析库中)迭代 argv[],依次考虑每个单词:

#include <iostream>
#include <string>
#include <vector>

int main(int argc, char **argv)
{
    std::string username;
    std::string password;
    std::vector<std::string> values;

    for (auto i = 1;  i < argc;  ++i) {
        std::string arg = argv[i];
        if (arg == "--username") {
            ++i;
            if (i >= argc) {
                std::cerr << argv[0] << ": --username requires a value" << std::endl;
                return 1;
            }
            username = argv[i];
        } else if (arg == "--password") {
            ++i;
            if (i >= argc) {
                std::cerr << argv[0] << ": --password requires a value" << std::endl;
                return 1;
            }
            password = argv[i];
        } else {
            values.emplace_back(argv[i]);
        }
    }


    std::cout << "Username = " << username << '\n';
    std::cout << "Password = " << password << '\n';
    for (auto i = 0u;  i < values.size();  ++i)
        std::cout << "Argument " << i << " = " << values[i] << '\n';
}

显然上面有很多重复,但原则适用:依次测试每个参数,如果是需要值的选项,则推进参数索引并读取该值。

一旦您通过了少量选项,您最终将创建一个从选项名称到如何处理该选项的表示的映射,然后使用或重新发明一个选项处理库。

【讨论】:

  • 使用std::string 作为密码并不是特别安全,尽管这会有所帮助:stackoverflow.com/questions/3785582/…
  • 这不是我所期望的,我已经提到有 n 个参数,而不仅仅是 --userName 和 --password 所以这不是一个通用的解决方案。 @Toby Speight
  • 就像我说的,当你有更多的参数时,你更倾向于基于表格的解决方案,但是原理不变无论你有一个级联的if/@ 987654327@链条或桌子。依次阅读每个参数,如果它需要一个或多个选项,请阅读这些选项。你需要帮助,还是只是用勺子喂食?
  • 另请注意,随着可能选项数量的增加,在参数列表中搜索每个选项的成本也会增加。对参数的基于表的迭代在参数数量上是线性的,而搜索与参数计数和可用选项数量的乘积成正比。
  • 我想你没有得到这个问题。您提供的解决方案很好,可以使用表格完成,但由于每个操作涉及不同的参数,因此无法为应用程序保留一个公共表格。
猜你喜欢
  • 2021-12-19
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 2019-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多