3

我在 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] 之外的单个字符或整数工作正常。但是当我把一根绳子放进去时,它变得很奇怪。它不断地循环通过自己。但是,在第一次之后,这应该是不可能的,因为我没有按 Enter。它继续进行,就好像它正在无限接收一个空白。

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

笔记:

我试图遵循这一点,它在一定程度上奏效了。(我从这个链接的 if 语句想法中得到了 cin >> 输入......)但是阻止字符串使程序奇怪地循环是行不通的。

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

4

2 回答 2

6

只是为了让你开始做某事..

关键点:

  • iostreams(包括 cin)有一些叫做“错误标志”的东西
  • 发生错误时,可以将流配置为 *) 引发异常 *) 跳过下一个操作
  • 默认配置是 .. 不抛出和跳过进一步的操作

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

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

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

很可能这就是为什么你会出现无限读取循环等奇怪行为的原因。

要处理这个:

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

IE

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写的东西:你应该读一个“字符串”,而不是读一个整数" 然后检查它,然后将它们重新解析为整数或视为字符串数据..

于 2013-07-10T19:08:40.560 回答
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;
}
于 2013-07-10T19:01:59.703 回答