C++ 捕获分裂的人为错误

C++ Catching split human errors

本文关键字:人为 错误 分裂 C++      更新时间:2023-10-16

我想做一个类似"CMD"的东西。我的意思是用户可以在控制台中输入他们的命令。我遇到的问题是每个命令都有效,但是例如,如果我们不编写每个参数,prog 就会崩溃。这是一小段代码:

 void commande(std::string commandeWanted)
{
    std::vector<std::string> fields;
    boost::split(fields, commandeWanted, boost::is_any_of("|")); // I chose | as spliter
    boost::to_upper(fields[0]);
    //std::cout<< fields[1] << fields[2] <<std::endl;
    if (fields[0] == "STOP")
        stop(fields[1]);
    else if (fields[0] == "DISCONNECT")
        disconnect();
    else if (fields[0] == "CONNECT")
        connect();
    else if (fields[0] == "SEND")
        send(fields[1], fields[2]);
    else if (fields[0] == "clean")
        cleanConsole();
    else if (fields[0] == "HELP")
        displayHelp();
    else
        std::cout << "No command recognized." << std::endl;
}

知道吗?有什么建议吗?我尝试通过声明字段[1]和字段[2],但没有办法。问题是我可以输入"帮助"这将运行函数displayHelp,但例如,如果我写"发送"而不是"发送|谁|什么",这将使程序崩溃。提前谢谢你。

在访问fields[1]之前检查fields.size() >= 2,依此类推fields[2]

如果你规范化所有函数的样子,你可以避免大量的逻辑重复和参数大小检查:

struct Command {
    size_t numArgs;
    std::function<void(std::vector<std::string>)> fun;
};
std::map<std::string, Command> commands = {
    {"STOP", {1, stop}},
    {"DISCONNECT", {0, disconnect}},
    {"SEND", {2, send}},
    // ...
};
// after you split
boost::to_upper(fields[0]);
auto it = commands.find(fields[0]);
if (it != commands.end()) {
    // pop the first one
    fields.erase(fields.begin());
    // check the size
    if (fields.size() != it->second.numArgs) {
        // error: wrong number of args
    }
    else {
        // ok, call me
        it->second.fun(fields);
    }
}
else {
    // command not found
}

不幸的是,C++ python * 运算符没有很好的等价物来解压缩向量 - 但这样至少你知道你在所有正确的位置都有所有正确的参数,即使你所有的函数现在都采用一个向量。

您需要在代码中添加检查,以确保在访问它们之前存在足够的字段。

(看起来您在split通话中切换了fieldschamps

像这样:

void commande(std::string commandeWanted)
{
    std::vector<std::string> fields;
    boost::split(fields, commandeWanted, boost::is_any_of("|")); // I chose | as spliter
    boost::to_upper(fields[0]);
    //std::cout<< fields[1] << fields[2] <<std::endl;
    if (fields[0] == "STOP"){
        if(fields.size >=2)stop(fields[1]);
    }
    else if (fields[0] == "DISCONNECT")
        disconnect();
    else if (fields[0] == "CONNECT")
        connect();
    else if (fields[0] == "SEND"){
        if(fields.size() >= 3)(fields[1], fields[2]);
    }
    else if (fields[0] == "clean")
        cleanConsole();
    else if (fields[0] == "HELP")
        displayHelp();
    else
        std::cout << "No command recognized." << std::endl;
}