【问题标题】:validate integer input C++?验证整数输入 C++?
【发布时间】:2012-11-02 10:32:52
【问题描述】:

我使用!(cin >> input) 来验证整数输入,但它没有捕获其他数据类型,例如浮点数。相反,它需要第一个整数。例如:

请输入一个数字:2.5。

我的错误信息出现在这里,假设循环,但它需要第一个数字。

输出“2”

如何让它忽略十进制输入?

【问题讨论】:

  • 发布您的代码!
  • 我们需要更多信息。最好是一个像样的代码示例,但至少是名为 input 的变量的类型。
  • @IskarJarak 显然它被声明为整数类型,当输入看起来不像整数时,他希望这会失败。它没有的原因是浮点数的开头看起来像一个整数。它读取2 并留下.5 以供下一个要读取的输入操作。
  • 如果您想完全控制您的采集工作方式,唯一的方法是将整行作为字符串获取并手动执行解析(如有必要,借助例如istringstream)。
  • 它正在读取 2 并将 0.5 留在缓冲区中。这就是cin >> int_variable 的工作原理。我建议阅读一个字符串并使用boost::lexical_cast 来规避它。

标签: c++ validation input types


【解决方案1】:

输入流认为任何以符号开头后跟至少一个十进制数字的内容都是有效的整数输入。如果您想在包含小数点的十进制输入上失败,您需要做一些不同的事情。处理此问题的一种方法是读取整数并查看成功读取整数后的字符是否为小数点:

if (!(std::cin >> value)
    || std::cin.peek() == std::char_traits<char>::to_int_type('.')) {
    deal_with_invalid_input(std::cin);
}

正如 Thomas Matthews 正确指出的那样,问题并不真正限于浮点数,而是任何带有数字前缀后跟非空格的东西(而不是 EOF:上述解决方案实际上会在文件的末尾,即后面没有任何内容,甚至没有换行符)。要仅读取后跟空格或文件末尾的整数,如下所示:

if (!(std:cin >> value)
    || (!std::isspace(std::cin.peek())
        && std::cin.peek() != std::char_traits<char>::eof())) {
    deal_with_invalid_input(std::cin);
}

实际上没有任何方法可以返回已读取的字符。由于这在很多地方都不太好使用,因此将这个函数打包到一个合适的std::num_get&lt;char&gt; facet 和imbue() 流中并带有相应的std::locale 可能是合理的。这有点高级,虽然处理代码的表达式实际上更简单。

【讨论】:

  • 仅供参考,问题也出现在“23Monkeys”中,其中将返回值 23。
  • 我认为更常见的解决方案是getline,将其放入stingstream,将其读入整数,并确认stringstream达到EOF。
  • @MooingDuck:肯定不是stringstream,而是istringstream(不是额外的i)。也就是说:这取决于你想要什么。如果一条好线看起来像这样:1 2 3 4 和像这样的破线 1 2 3.5 4 我的方法有效,你的方法无效。当然,您的方法有一种变体可以解决问题:您不是阅读一行,而是阅读一个单词。我非常相信我的方法仍然适用于大量输入。
【解决方案2】:

您正在尝试使用 cin 读取不同类型的值。

istream 重载 &gt;&gt; 运算符以匹配您期望从输入中获得的数据类型,cin 是 istream 类的一个实例。

当期望的类型是整数时,它会消耗字符到一个可以转换为整数的字符串,并将剩余的字符留在流中以供以后解析。浮点值或其他简单类型也会发生同样的情况。 请参阅this reference page,了解有关运算符及其开箱即用支持的类型的更多详细信息。 底线是,如果您想要一个整数值,但期望输入的浮点值,您必须使用要从输入解析的正确类型的值(此处为浮点),并在稍后进行任何需要的转换(这里使用trunc、floor、ceil 或任何符合您需要的舍入函数)。

这是一个简单的例子:

#include <iostream>
#include <string>

using namespace std;

int main() {

    float f;
    string str;

    cout << "please enter a float :";
    cin >> f;

    cout << "value entered : " << f << endl;

    cout << "stream error : " 
         << (cin.fail() ? "yes" : "no") 
         << endl;

    cin >> str;

    cout << "remaining data : " << str << endl;

}

这个非常简单的程序演示了在 istream 上使用 &gt;&gt; 运算符,特别是使用预期的浮点值。对于以下输入:“1.2345Z6789”(注意数字中间的Z),程序将解析值“1.2345”并在输入缓冲区中保留“Z6789”,可用于后续阅读。

如果将f 的类型从float 替换为int,则程序在同一输入上将读取值“1”,并在输入缓冲区中保留“.2345Z6789”。

注意:在您的代码中,您使用! 运算符来测试流的状态,这相当于我在示例中使用的fail 方法。

【讨论】:

    【解决方案3】:

    您需要在验证之前阅读完整的输入。您可以使用cin.getline() 或getline() 来执行此操作,然后检查输入是否是您想要的。

    【讨论】:

      猜你喜欢
      • 2013-02-20
      • 2019-06-02
      • 1970-01-01
      • 2013-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-09
      • 2020-09-06
      相关资源
      最近更新 更多