c++ 检查空的sstream

xurqigkl  于 2022-12-30  发布在  其他
关注(0)|答案(1)|浏览(155)

我写了一个函数,可以用cin替换整数和可能的双精度数,它包括错误检查功能。使用cin.fail()我可以检查大多数情况,但这不包括输入后面跟着一个没有空格的字符串的情况。例如,“23 tewnty-three”。下面的代码可以解决这个问题。

int getUserInt(string prompt = "Enter an integer: ", string errorMessage "Error: Invalid Input") {
    const int IGNORE_MAX = 100;
    int userInt = 0;

    bool isContinue = true;
    do {
        // initialize and reset variables
        string inputStr;
        istringstream inputCheck;
        userInt = 0;

        // get input
        cout << prompt;
        cin >> inputStr;
        inputCheck.str(inputStr);

        // check for valid input
        inputCheck >> userInt;
        if (!inputCheck.fail()) {
            // check for remaining characters
            if (inputCheck.eof()) {    // Edit: This is the section that I tried replacing with different code (made code compilable in response to comment)
                isContinue = false;
            }
            else {
                cout << errorMessage << endl;
            }
        }
        else {
            // reset cin and print error message
            cin.ignore(IGNORE_MAX, '\n');
            cin.clear();
            cout << errorMessage << endl;
        }
    } while (isContinue);

    return userInt;
}

这段代码可以工作,但是我之所以把它贴在Stack Overflow而不是Code Review上,是因为我的主要问题是为什么有些代码没有像我预期的那样工作。下面是我在前面的代码中尝试的inputCheck.eof()。我的问题是下面的代码之间有什么区别?为什么方法2)和3)不工作?哪种方法更好?

  1. inputCheck.eof()
  2. inputCheck.peek() == EOF
  3. inputCheck.str().empty()
  4. inputCheck.rdbuf()->in_avail() == 0
    1)和4)按预期工作,但2)和3)没有。

**编辑:**我认为3)没有像预期的那样工作,因为当inputCheck.str(inputStr)被调用时,inputCheck.str()返回inputStr中包含的内容。

如果这是相关的信息,我正在通过bash g++在windows上编译和运行。

plicqrtu

plicqrtu1#

对于您提供的每个提示,您可以预期用户按Enter键。获取字符串形式的输入,然后尝试转换。(不要尝试从cin转换。)
额外的好处:这里有一个函数可以执行转换。

template <typename T>
auto string_to( const std::string & s )
{
  T value;
  std::istringstream ss( s );
  return ((ss >> value) and (ss >> std::ws).eof())
    ? value
    : std::optional<T> { };
}

你需要C++17,或者改为#include <boost/optional.hpp>
现在:

std::cout << "Enter an integer! ";
std::string s;
getline( std::cin, s );
auto x = string_to <int> ( s );
if (!x)
{
  std::cout << "That was _not_ an integer.\n";
}
else
{
  std::cout << "Good job. You entered the integer " << *x << ".\n";
}

不用再担心清除或重置cin了。轻松地执行一些循环(比如允许用户在退出前尝试三次)等等。

相关问题