cin.ignore(numeric_limits<streamsize>::max(), '\n');中的max()不被识别。

18

我正在学习C++入门课程,并且在Win7上使用VStudio 2013。我试图避免菜单输入错误的数据,尽管在其他所有菜单中都有效,但在这个菜单中不起作用。

    cout << "Please choose your second number" << endl;
    cin >> move2;

    if (move2 < 1 || move2 > size)
    {
        cout << "That's not a valid move" << endl;
        Sleep(2000);
        cin.sync();
        cin.clear();
    }

唯一的区别是在移动条件中使用的变量(size)是一个变量而不是数字。 当我输入一个字符时,它会返回到询问另一个输入的问题,但如果我输入一个单词,程序就会崩溃!

我尝试使用cin.ignore(numeric_limits<streamsize>::max(), '\n');,但编译器突出显示max()并显示“expecting identifier”。

这可能对所有优秀的程序员来说很容易,但我不知道如何修复它。 有人能帮帮我吗?

5个回答

23
这是因为在Visual Studio中,当您使用Windows包含文件时,它会定义一个名为max()的宏。如果您悬停在示例中的max()上,应该会收到Intellisense警告。您可以通过在所有包含文件之后,在任何代码之前取消定义max来解决此问题。
#undef max

10
要使用std :: numeric_limits<T>,您需要包含<limits>。 此外,传递给它的类型需要已知且实际上是类型std :: streamsize,即我会将其用作:
#include <iostream>
#include <limits>
// ...
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

此外,您应该确保尝试读取某些内容是否成功,如果不成功,请先使用clear()函数清除流的状态。以下是一个完整的程序(它可以在gccclang编译器中编译和运行):

#include <iostream>
#include <limits>

int main()
{
    int move2, size(3);
    while (!(std::cin >> move2) || move2 < 1 || size < move2) {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "invalid input ignored; please enter a valid move\n";
    }
    std::cout << "move2=" << move2 << '\n';
}

感谢您的快速回复,Dietmar。我尝试这样做,并包含了<limits>,但现在streamsize被突出显示,并且它说...不允许类型名称。我是否还缺少另一个库? - user3078454
@user3078454:抱歉,我是在移动设备上输入这些内容的,第二个版本使用了完全错误的表达方式。我刚刚编辑了答案来修正它。 - Dietmar Kühl
也许我应该添加整个函数。 - user3078454

0

限制潜在副作用的代码

在我的测试中,似乎不需要在任何#include之前执行#undef max

您可能希望通过首先推送max宏,然后取消定义它,然后在使用来自<limits.h>的max后弹出它,从而通常限制潜在的副作用,如下所示(仅在Windows / Visual Studio 2019上进行了测试):

  // stuff ...

#pragma push_macro("max")
#undef max
  std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
#pragma pop_macro("max")

  // more stuff ...

请参阅 Microsoft 文档:push_macropop_macro

将其放入函数中以使其更加干燥:

void CinIgnore() {

#pragma push_macro("max")
#undef max
  std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
#pragma pop_macro("max")

}

在编程中,添加std::cin.clear以创建一个CinReset函数:
void CinReset() {

  std::cin.clear();

#pragma push_macro("max")
#undef max
  std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
#pragma pop_macro("max")

}

附加信息:这个cppreference.com article关于ignore的文章有一个很好的例子,展示了如何有效地使用clearignore以及状态标志,但是没有上述Windows/Visual Studio所需的修复。

注意:尽管以上方法是标准的,但在用户交互输入EOF(ctrl-z - Windows使用Visual Studio)时效果不佳。我编写了一个IStreamUtils类,其中包括一个更健壮的Reset方法。稍后我会添加一篇关于此的文章链接。


-1
如果cin出现错误,以下代码将清除错误状态并读取该行的其余部分。
if(!cin)
{
   cin.clear();
   string junk;
   getline(cin, junk);
}

我尝试了这个,但它不起作用。它只能处理超出范围的数字,而不能处理字符串。 - user3078454

-2

包括:

#include <climits> 

看看这是否有帮助。我曾经遇到过同样的问题,当我将其从limits更改为climits时,问题得到了解决。


OP 需要使用 <limits>,而不是 <climits>。Dietmar Kühl 在他的回答中已经说过了... - HolyBlackCat
我曾经遇到过完全相同的问题,但是限制并没有起到任何作用。而 Climits 解决了它。 - Katie Stevers
很奇怪。1. numeric_limits 来自 <limits>。2. 你确定你遇到了*完全相同的问题吗?因为 OP 的解决方法似乎是 #undef max - HolyBlackCat
是的。我只使用了<climits>这行代码,它就起作用了?也许是因为我使用的是Geany..但这也很奇怪,我不知道为什么我的代码不需要<limits>。 - Katie Stevers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接