2

问候!

这次让我们删掉过多的介绍,直奔主题。

我在使用 isalnum 方法的 C++ 中遇到问题。

编码:

int playAgainst = 0;
do
{
    cout << "Who do you want to play against?(1/2)\n";
    cout << "1: Human player\n";
    cout << "2: Computer player\n";
    cin >> playAgainst
} while(!isalnum(playAgainst) && playAgainst != 0);

从代码中可以看出,我为用户提供了一个选择。与人对战或与计算机对战。

我想要的是,只要用户输入其他任何内容,然后输入一个整数值(cin >> playAgainst)来重复问题。但是,如果我输入一个字符或字符串值,它会不断循环。我不是 100% 肯定,但很明显,如果问题是,非 int 值已经保存为 playAgainst 的值。如果在保存之前输入值是 int,我如何检查这段代码它?

或者是唯一的可能性保存为字符/字符串然后检查?

如果是后者,就会出现新的问题。isalnum 只接受 int 作为参数,至少据我所知。我将如何检查该字符串或字符是否为 int?

感谢您花时间阅读。希望我能尽快接受答复^^

谢谢大家的回答。我得到了我想要的,一切都解决了。

我选择接受答案的原因很好......因为最初,它使我的代码按照我想要的方式工作。虽然我想接受多个答案..

4

6 回答 6

2

删除isalnum()检查。cin >> playAgainst会将除数字以外的任何内容转换为零,这将被第二次检查捕获。请注意,这只是一个选项,因为零不是有效输入。

isalnum()如果您自己解释字符,这很有用,但在这种情况下,流已经为您完成了。

于 2011-03-30T11:32:07.990 回答
2

playAgainst一个char和比较'0',不是0。现在,用户必须为字符'1''2'.

isalnum不会在int的有效范围之外的 s上工作char,除了EOF. (它接受int参数的事实是C 的遗留物,它具有与 C++ 不同的整数提升规则。以适应EOF.)

于 2011-03-30T11:20:47.927 回答
1

这就是编译器实现 isalnum 的方式:

int isalnum (int ch)
{
  return (ch >= 'a' && ch <= 'z') || 
         (ch >= 'A' && ch <= 'Z') || 
         (ch >= '0' && ch <= '9');
}

因此,您不妨在自己的代码中编写该代码片段,它与 isalnum 的内联版本等效。

于 2011-03-30T11:42:39.467 回答
1

问题是您输入的是 int,而不是 char。如果输入中的文本不是 int,则输入失败。在这种情况下, playAgainst 不会被修改,并且会记住失败,std::cin 直到您明确清除错误为止。并且从处于错误状态的流中输入是无操作的。你可能想要做的是

  1. 输入单个字符:如果您不想跳过空格,请使用 `std::cin.get(ch)` 或 `ch = std::cin.get()`。(在后一种情况下,`ch` 应该是 `int`,因为它还必须处理 `EOF`。另一方面,您可以直接在其上使用 `::isalnum`,如果 ` ch` 是一个 `char`。
  2. 全面检查有效输入:不仅仅是`::isalnum`,还要检查输入是否是列表中的合法选择器。类似于以下内容:
        ch != EOF && std::find( legalChars.begin(), legalChars.end(), (char)ch ) != legalChars.end()
    
  3. 如果出现错误,请清除任何剩余的输入,例如:
               std::cin.ignore(INT_MAX, '\n');
    

在实践中,您可能希望EOF区别对待错误命令。(如果你不清除之后的输入EOF,你将无法阅读其他任何内容。但如果你得到了EOF,大概是因为用户放弃了,不想再尝试了。)

最后,最好使用以下表格将所有信息保存在一个公共位置:

struct Command
{
    char        op;
    char const* prompt;
    void (*     func)();
};

然后循环遍历这些表以输出提示,搜索它以查看字符是否合法,最后,在找到的条目上调用该函数。或者为每个命令定义一个抽象基类,一个从它派生的具体类,并使用一个std::map<char, AbstractBase*>用于映射等。非常 C++,但对于这样一个简单的情况可能有点矫枉过正。

于 2011-03-30T17:26:48.197 回答
1

这是因为您没有清除缓冲区。当输入无效时,您需要将其从缓冲区中清除,然后您可以继续下一个输入,否则您每次都尝试提取相同的输入(失败,因为它是相同的错误输入),从而进入一个无限循环。

于 2011-03-30T11:51:14.487 回答
0

为什么不使用isdigit()

于 2011-03-30T11:22:48.370 回答