为什么数字后面'string-like'值在打印时会被忽略?

  • 本文关键字:打印 数字 string-like c++ string
  • 更新时间 :
  • 英文 :


下面是一个演示这个问题的简单程序。

#include <iostream>
using namespace std;
double d;
int main() {
    cin >> d;
    if (cin.fail()) {
        cout << "Input is invalid" << endl;
    }
    else {
        cout << d << endl;
    }
    return (0);
}

输入像adsfasdf!@#$!*@#(&Adf这样的值会打印出Input is invalid。输入像13.52这样的数值返回13.52,也如预期的那样。

但是输入以数字开头,后面跟着字符串的东西,比如13.52asdfasdf!#@$!@#$!#A打印出13.52。那么为什么这种输入不打印Input is invalid呢?

我如何让这个输入被视为无效,而不是仅仅打印数字部分?

在c++中,当你尝试从流中读取一个值时,它会从流中读取尽可能多的值,只要它符合预期的格式,其他的都不动。如果读取根本无法读取任何值,那么它将在流上设置失败位。这就解释了为什么如果你输入的是总垃圾,你会得到一个错误,而如果你输入一个数字后面跟着垃圾,你会读到有效的数据,但仍然有垃圾留在流中。

解决这个问题的一种方法是使用std::getline函数从cin读取一行文本,这将获取用户输入的所有内容,然后通过std::istringstream运行它来解析它。这里有一种方法,基于我们在斯坦福大学的介绍课上使用的一些代码:

int readInt() {
    while (true) {
       std::string input;
       std::getline(cin, input); // Read a line of text from the user
       /* Set up an istringstream to read the data */
       std::istringstream converter(input);
       /* Try to read an int. If we succeed, make sure there wasn't
        * any trailing data.
        */
       int value;
       if (converter >> value) {
           char leftover;
           if (converter >> leftover) {
               std::cout << "Please enter an integer." << std::endl;
           } else {
               return value;
           }
       } else {
            std::cout << "Please enter an integer." << std::endl;
       }
    }
}

你可以很容易地自定义/模板化它来读取任何类型的数据。

最新更新