【问题标题】:Using stringstream.fail() to check whether input is int or string使用 stringstream.fail() 检查输入是 int 还是 string
【发布时间】:2013-10-11 16:20:43
【问题描述】:

我正在创建一个简单的函数 printNode,它接受一个 int 或字符串“all”,并打印相应的输出。该函数的 int 方面效果很好,但是当我调用时

printNode all

该函数打印“错误:无效参数”,我似乎无法弄清楚原因。

int main() {
    ...
    getline(cin, line)
    stringstream lineStream(line);
    stringstream elineStream(line);
    printNode(lineStream, elineStream);
    ...
}


int printNode(stringstream& lineStream, stringstream& elineStream) {
//String aspect of printNode
int nodeid;
string name;

// Parsing nodeid or name
lineStream >> nodeid;

// If parsing to nodeid fails, check if input is string "all"
if (lineStream.fail()) {
    elineStream >> name;
    if (elineStream.fail()) {
        if (elineStream.eof()) {
            cout << "Error: too few arguments" << endl;
            return 0;
        }
        else {
            cout << "Error: invalid argument" << endl;
            return 0;
        }
    }
    if (name != "all") {
        cout << "Error: invalid argument" << endl;
        return 0;
    }
    // Check for too many arguments
    elineStream >> ws; 
    if (!elineStream.eof()) {
        cout << "Error: too many arguments" << endl; 
        return 0;
    }

    // Print output for input "all" 
    cout << "Print: all nodes" << endl;
    return 1;
}

任何帮助将不胜感激。

【问题讨论】:

  • 再做一些工作,您就可以使它成为一个独立的、可编译的示例。另外,请注意,您应该返回 0 表示成功,返回 1 表示失败 - 您正在反向执行此操作。
  • @JohnZwinck 关于成功/失败的1/0,为什么不直接返回bool
  • @JoachimPileborg:你说得对!我把它弄混了,把这些返回读成来自 main()。将它们作为 bool(或异常)会更好。

标签: c++ string input int stringstream


【解决方案1】:

您将printNode all 作为输入,而它只需要all。我试过你的代码,它工作正常(当然,给它printNode all 失败,参数无效)。

附带说明,您可以通过清除第一个流上的错误标志来避免使用两个流。也就是说,如果您在看到读取数字失败后添加lineStream.clear();,则您所有的elineStream 可能只是lineStream


从你的措辞中,我看到了一些奇怪的东西,我也想澄清一下(以防万一):

但是当我打电话时

printNode all

通过在命令行中编写,您不会调用函数。编写时调用该函数:

printNode(lineStream, elineStream);

在您的源代码中。如果在命令行中写入printNode all,则所有字符串(因为您读取了整行)都将被传输到流中,而不仅仅是all

【讨论】:

    【解决方案2】:

    通过使用std::copystd::istream_iteratorstd::back_inserter 将所有单词复制到std::vector 中,有一种更简单的方法来获取“命令”及其所有选项。然后就是简单的检查一下vector的大小,看看这个命令是否合法。

    这样写的:

    std::vector<std::string> command_and_args;
    
    std::copy(std::istream_iterator<std::string>(lineStream),
              std::istream_iterator<std::string>(),
              std::back_inserter(command_and_args));
    
    if (command_and_args.size() == 0)
        std::cout << "Error: No command or arguments\n";
    else if (command_and_args.size() == 1)
        std::cout << "Error: To few arguments\n";
    else if (command_and_args.size() > 2)
        std::cout << "Error: To many arguments\n";
    else
    {
        // Got the command and one argument
        // Command in `command_and_args[0]`
        // Argument in `command_and_args[1]`
    }
    

    std::copy 部分可用于所有命令,而检查必须是单独的。


    编辑:实际上,检查参数的数量也可以是自动的,如果你创建一个详细说明命令的结构(命令字符串,布尔值来判断是否需要参数,最小参数数量,参数的最大数量,以及命令处理程序的 std::function 对象)。用这种结构创建一个表,并通过它查找命令,检查参数计数(如果需要),然后调用函数对象。然后函数对象可以检查各个参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-06
      • 1970-01-01
      • 2015-06-09
      • 1970-01-01
      • 1970-01-01
      • 2020-09-03
      • 2015-02-02
      • 1970-01-01
      相关资源
      最近更新 更多