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

时间:2013-07-10 18:45:45

标签: c++ cin

我在google / stackoverflow上看过类似的帖子。但是,我找不到一个足够接近我的场景的人,我不太了解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&gt;&gt;输入...)但它不能阻止字符串使程序循环变得奇怪。

Good input validation loop using cin - C++

2 个答案:

答案 0 :(得分:5)

只是为了让你开始......

关键点:

  • iostreams(包括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 ..

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

编辑:aargh ..对不起,我已经离实际答案太远了。你真正想要的不是一个好的错误处理,而是类似于 sehe 写的:而不是读取整数,你应该读一个“字符串”,然后检查它,然后将它们重新解析为整数或视为字符串数据..

答案 1 :(得分:2)

这是一个稍微固定的最小例子(编译......),展示你如何做你尝试的东西

 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;
}