【问题标题】:C++ Example : Not able to understand what is being done?C++ 示例:无法理解正在做什么?
【发布时间】:2013-04-20 11:56:57
【问题描述】:

我在http://www.parashift.com/c++-faq-lite/istream-and-ignore.html找到了这个链接

显示“如何让 std::cin 跳过无效的输入字符?”

Use std::cin.clear() and std::cin.ignore().

#include <iostream>
#include <limits>

int main()
{
  int age = 0;

  while ((std::cout << "How old are you? ")
         && !(std::cin >> age)) {
    std::cout << "That's not a number; ";
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  }

  std::cout << "You are " << age << " years old\n";
  ...
}
Of course you can also print the error message when the input is out of range. For example, if you wanted the age to be between 1 and 200, you could change the while loop to:
  ...
  while ((std::cout << "How old are you? ")
         && (!(std::cin >> age) || age < 1 || age > 200)) {
    std::cout << "That's not a number between 1 and 200; ";
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  }
  ...
Here's a sample run:
How old are you? foo
That's not a number between 1 and 200; How old are you? bar
That's not a number between 1 and 200; How old are you? -3
That's not a number between 1 and 200; How old are you? 0
That's not a number between 1 and 200; How old are you? 201
That's not a number between 1 and 200; How old are you? 2
You are 2 years old

我不知道它是怎么做的> 谁能解释一下吗?

我有疑问:

while ((std::cout << "How old are you? ")
             && !(std::cin >> age)) 

它如何检查有效条目?我的意思是问表达式 "std::cout > age)" ,返回真或假,哪些是与运算?

另一个令人困惑的是用法,

std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

有什么目的?在谷歌上搜索了这些功能,但我仍然不清楚。 特别是std::numeric_limits&lt;std::streamsize&gt;::max()

有人可以帮忙吗? 谢谢

【问题讨论】:

  • cin.clear() 和 cin.ignore() 用于防止 cin 被跳过(如果没有错)。第一次,我猜是问错了。

标签: c++


【解决方案1】:

流上的插入和提取运算符&lt;&lt;&gt;&gt; 将返回对流本身的引用。这就是为什么你可以像这样将插入串起来:

std::cout << "Hello, " << "World!";

首先std::cout &lt;&lt; "Hello, " 返回一个对std::cout 的引用,然后你就有了std::cout &lt;&lt; "World!" 的等价物。

流也可以转换为bool。这基本上检查流的状态是否仍然正常。什么都没有失败。例如,您可以这样做:

if (std::cin) // ...

这将检查std::cin 流是否仍处于良好状态。

现在让我们看看你询问的代码:

while ((std::cout << "How old are you? ")
         && !(std::cin >> age))

插入std::cout 不会导致失败。它包含在此处的唯一原因是它每次都在输入age 之前发生。另一种方法是将其放置在 while 之前一次,并在 while 正文的末尾放置一次。

插入std::cout 完成后,将评估!(std::cin &gt;&gt; age)。这将首先让用户提供age。然后会发生两件事:

  1. 如果这以某种方式失败(可能用户输入字符而不是整数),则将设置失败位。这意味着std::cin &gt;&gt; age 的结果将转换为bool,即false! 会将其反转为 true。因此,因为第一个和第二个条件都为真,while 循环的主体将执行,告诉用户他们输入了一个无效值,循环将再次循环。

  2. 如果输入成功,std::cin &gt;&gt; age 的结果将为true! 将其转为false。这意味着while 循环的主体不会执行,也不会告诉用户他们输入了错误的值。

现在我们来看看:

std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

这仅在上述情况 1 中发生,即输入失败。如果流进入失败状态,则在清除状态之前,它将不再接受任何插入或提取。这就是clear() 所做的。然后对ignore 的调用表示要提取流中直到并包括下一个\n 的所有字符并丢弃它们。这消除了流中的无效输入。

【讨论】:

  • "然后调用 ignore 表示提取流中直到下一个 \n 的所有字符并丢弃它们。这消除了流中的无效输入。" - 这意味着换行符'\n'仍在流中,在“你多大了?”的下一次迭代中不会将'\n'作为输入
  • @GauravK 抱歉,应该是“直到并包括下一个 \n”。
  • 不,我只想知道 ignore() 是否也丢弃了 delim ,因为我读到如果 Delim 是 EOF 它不会被丢弃,如果它不是 'EOF' - 它是否被提取也被丢弃了?
  • @GauravK EOF 不同。流的结尾不是特殊字符。如果ignore 提取字符并到达流的末尾,那么它就会停在那里。没有要提取的分隔符。
  • @GauravK ignore 确实删除了分隔符。 See here.
【解决方案2】:
while ((std::cout << "How old are you? ")        && !(std::cin >> age)) 

coutostream 类的全局对象,cinistream 类的全局对象

这些对象与重载运算符&lt;&lt;(在ostream 中定义)和&gt;&gt;(在istream 中定义)一起使用以获取输入(通过调用为这些运算符定义的函数)

operator&lt;&lt; 的返回类型为ostream&amp;operator&gt;&gt; 的返回类型为istream&amp;。然后将它们转换为布尔值。见this

也检查this 以获取cin.ignore()cin.clear()

【讨论】:

  • 请不要链接到cplusplus.com
  • @bartek ,是的,我个人不喜欢它们,但后来在 cppfrence 上找不到合适的页面。一旦我得到它会更新它,哦,好吧,你做到了。谢谢
  • @BartekBanachewicz cpluscplus.com 有什么问题?他们有错误的信息吗? (我不知道,我真的在问。)
  • @ritwikG 见this
【解决方案3】:

std::numeric_limits 允许您获得可以适合给定类型的最大数量。

在您的示例中,它被传递给 ignore() 函数,这基本上意味着预先忽略每个换行符。

【讨论】:

猜你喜欢
  • 2019-04-14
  • 1970-01-01
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多