在使用cin进行整数输入时捕获字符串

Catching strings while using cin for integer input

本文关键字:输入 字符串 整数 cin      更新时间:2023-10-16

我在google/sttackoverflow上看到过类似的帖子。然而,我找不到一个足够接近我的场景的方法,而且我对C/C++的了解也不够好,无法将其他建议移植到我的方法中。也许这本身就是一个标志。。。

无论如何,这是我的代码:

while (true)
{
    print("nSend message, enter command, or "9" for help.n");
    if (cin >> input)
    {
        if (input == TERMINAL_HELP)
        {
            //Some help code.
        }
        else if (input == TERMINAL_EXIT)
        {
            //Some exit code.
        }
        else if (input < 4 && input >= 0)
        {
            // Some processing code.
        }
        else
        {
            print("Please enter a valid message.");
        }
    }
    else
    {
        print("Please enter a valid message.");
    }
}

对于超出范围[0-4]的单个字符或整数,捕获效果良好。但当我把绳子放进去的时候,它会变得很奇怪。它不断地自我循环。然而,在第一次之后,这应该是不可能的,因为我不按回车键。它继续前进,仿佛在无限地接收空白。

如果你有任何建议,或者可以为我指明解决问题的方向,我将不胜感激!谢谢

注:

我试着遵循这一点,它在某种程度上起到了作用。(我从这个链接得到了if语句思想中的cin>>输入…)但它无法阻止字符串奇怪地使程序循环。

使用cin-C++的良好输入验证循环

只是为了让您开始做一些事情。。

要点:

  • iostream(包括cin)有一种叫做"错误标志"的东西
  • 当发生错误时,可以将流配置为*)引发异常*)跳过下一个操作
  • 默认配置为。。不抛出并跳过进一步的操作

这意味着,如果你这样做:

cin >> integer1;
cin >> integer2; // *!
cin >> integer3; // !
cin >> integer4; // !

如果用户在用(*)标记的行处提供了一个非整数,则此时cin将进入错误状态,并且用(!)标记的操作将被跳过

很可能这就是为什么你会有奇怪的行为,比如无限读取循环等。

处理此问题:

  • 将流配置为抛出异常并捕获它们
  • 或者每隔几次读取后检查错误状态,并进行处理

cin >> integer1; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer2; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer3; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer4; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }

cin.reset清除错误标志并允许对流进行进一步操作。但是,所有垃圾数据仍将在流中徘徊。因此,尝试进一步阅读是没有意义的。在cin.reset之后,您应该以某种方式删除坏数据并从这种情况中恢复。我用".."标记了这些地方,因为有很多方法可以做到。

例如,cin.ignore..

现在请参考所有其他帖子:)我相信你现在会很快找到解决方案

编辑:阿。。对不起,我说得离实际答案太远了。。实际上,您想要的不是一个好的错误处理,而是类似于sehe所写的内容:与其读取整数,不如读取一个"字符串",然后对其进行检查,然后将其重新解析为整数或将其视为字符串数据。。

这里有一个稍微固定的最小示例(编译…),展示了如何围绕进行尝试

 msg = input + '0';

即:

std::ostringstream oss;
oss << input;
auto msg = oss.str();

或者,使用更多的c++11功能(如果你的编译器有):

auto msg = to_string(input);

其他没有进一步评论:

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int const TERMINAL_EXIT = 9;
int const TERMINAL_HELP = 8;
static int devHandle = 0;
void print(char const*const  msg) { cout << msg; }
void send(int, std::string const&) {} // TODO
void receive(int, std::string&)    {} // TODO
void help_routine() {} // TODO
int main(int argc, const char *argv[])
{
    while (true)
    {
        print("nSend message, enter command, or "9" for help.n");
        // Read in message to send to DigiSpark.
        long input;
        if (cin >> input)
        {
            if (input == TERMINAL_HELP)
            {
                help_routine();
            }
            else if (input == TERMINAL_EXIT)
            {
                break;
            }
            else if (input < 4 && input >= 0)
            {
#ifdef HAVE_CXX11
                std::string msg = to_string(input);
#else
                std::ostringstream oss;
                oss << input;
                std::string msg = oss.str();
#endif
                // Send mimicking command line arguments.
                send(devHandle, msg);
                cout << "nSent message: " << msg << endl;
                print("Receiving message...n");
                receive(devHandle, msg);
                while (!msg.empty())
                {
                    receive(devHandle, msg);
                }
                cout << "Received message: " << msg << endl;
            }
            else
            {
                print("Please enter a valid message.");
            }
        }
        else
        {
            print("Please enter a valid message.");
        }
    }
    return 0;
}