if (cin >> x) - 为什么可以使用该条件?

发布于 2024-11-25 09:59:18 字数 274 浏览 4 评论 0原文

整个夏天我一直在使用“Accelerated C++”来学习C++,有一个概念我似乎不太理解。

为什么

int x;
if (cin >> x){}

相当于

cin >> x;
if (cin){}

通过查看代码,在我看来我们正在使用 cin 作为变量。但是,我认为这是一个功能。当 x 具有我们在键盘中输入的任何值时,为什么我们可以以这种方式使用 cin?

I have been using "Accelerated C++" to learn C++ over the summer, and there's a concept which I don't seem to understand properly.

Why is

int x;
if (cin >> x){}

equivalent to

cin >> x;
if (cin){}

By looking at the code, it seems to me that we're using cin as a variable. But, I thought it was a function. Why can we use cin in this way when it is x that has whatever value we input into our keyboard?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

卷耳 2024-12-02 09:59:18

cin 是类 istream 的对象 代表标准输入流。它对应于cstdiostdin。流的运算符>>重载返回对同一流的引用。流本身可以通过转换运算符在布尔条件下评估为 true 或 false。

cin 提供格式化流提取。操作
cin>> x;

其中“x”是一个 int,如果是非数字值,则会失败
进入。因此:

if(cin>>x)

如果您输入字母而不是数字,将返回false

这个网站上的使用 C++ I/O 的提示和技巧也会对您有所帮助。

cin is an object of class istream that represents the standard input stream. It corresponds to the cstdio stream stdin. The operator >>overload for streams return a reference to the same stream. The stream itself can be evaluated in a boolean condition to true or false through a conversion operator.

cin provides formatted stream extraction. The operation
cin >> x;

where "x" is an int will fail if a non-numeric value is
entered. So:

if(cin>>x)

will return false if you enter a letter rather than a digit.

This website on tips and tricks using C++ I/O will help you too.

热血少△年 2024-12-02 09:59:18

注意:答案在四年后更新,以解决 C++98/03 和 C++11(及更高版本)问题。

std::cinstd::istream 的实例。该类提供了两个与该问题相关的重载。

  • operator >> 将数据从流读取到目标变量(如果可能)。如果流的直接内容无法转换为目标变量的类型,则流将被标记为无效,并且目标变量保持不变。无论操作成功/失败,返回值都是对流的引用。
  • operator void*()(C++11 之前版本),将流引用转换为 void* 指针,或显式运算符 bool()< /code> (C++11),它将流引用转换为布尔值。如果流有效,则此转换的结果是非空指针(C++11 之前的版本)或 true (C++11),但空指针(C++11 之前的版本) 11) 或 false (C++11)(如果流无效)。

if 语句需要一个布尔值、一个整数或一个指针作为要测试的数量。 std::cin >> 的结果x 是对 istream 的引用,它不是以上任何一个。但是,istream 类确实具有那些转换运算符,可用于将 istream 引用转换为可在 if 语句中使用的内容。它是该语言用于 if 测试的特定于版本的转换运算符。由于读取失败会将流标记为无效,因此如果读取不起作用,if 测试将失败。

C++11 之前使用更复杂的 operator void* 转换成员的原因是,直到 C++11 才扩展了现有的 explicit 关键字适用于转换运算符和构造函数。非显式的操作符 bool() 会给程序员带来太多搬起石头砸自己脚的机会。 operator void*() 也存在问题。 “safe bool idiom”本来是一个解决方案,但简单地扩展显式就可以完成 safe bool idiom 所完成的工作,并且无需使用大量 SFINAE 魔法。

Note: Answer updated four years after the fact to address both C++98/03 and C++11 (and beyond).

std::cin is an instance of a std::istream. That class provides two overloads that pertain to this question.

  • operator >> reads data from the stream into the target variable if that is possible. If the immediate contents of the stream cannot be translated into the type of the target variable, the stream is instead marked as invalid and the target variable is left untouched. Regardless of the success/failure of the operation, the return value is a reference to the stream.
  • Either operator void*() (pre-C++11), which converts the stream reference to a void* pointer, or explicit operator bool() (C++11), which converts the stream reference to a boolean. The result of this conversion is a non-null pointer (pre-C++11) or true (C++11) if the stream is valid, but the null pointer (pre-C++11) or false (C++11) if the stream isn't valid.

An if statement needs either a boolean, an integer, or a pointer as the quantity to be tested. The result of std::cin >> x is a reference to an istream, which is none of the above. However, the class istream does have those conversion operators which can be used to transform the istream reference to something usable in an if statement. It is the version-specific conversion operator that the language uses for the if test. Since failure to read marks the stream as invalid, the if test will fail if the read didn't work.

The reason for the more convoluted operator void* conversion member prior to C++11 is that it wasn't until C++11 that the already existing explicit keyword was extended to apply to conversion operators as well as constructors. A non-explicit operator bool() would have presented far too many opportunities for programmers to shoot themselves in the foot. There are problems with operator void*() as well. The "safe bool idiom" would have been a fix, but simply extending explicit accomplished exactly what the safe bool idiom accomplishes, and without having to use a lot of SFINAE magic.

无畏 2024-12-02 09:59:18

cinistream 类型的(全局)变量,而不是函数。

istream 类重写 >> 运算符来执行输入并返回对调用它的对象 (cin) 的引用。

cin is a (global) variable of type istream, not a function.

The istream class overrides the >> operator to perform input and return a reference to the object you called it on (cin).

心意如水 2024-12-02 09:59:18

cinstd 命名空间中的变量。

operator>> 返回对 cin 的引用,因此您可以编写: cin >>>一个>> b,而不是 cin >>一个;辛>> b;

cin is variable in std namespace.

operator>> return reference to cin, because of it you can write: cin >> a >> b, instead of cin >> a; cin >> b;

可爱咩 2024-12-02 09:59:18

上面的答案内容丰富。这里我只是补充一下。

std::cinistream 类的对象,表示与 stdin< 对应的标准输入流(即键盘) C 中的/code>。

cin>> x 首先会从标准输入流中读取一个 int 并将其分配给 x。之后返回对 cin 的自引用。所以函数调用cin>>的返回值是x 仍然是 cin

因此,从 if 条件来看,if(cin)if(cin >> x) 彼此相似。标准IO库为流定义了一个像这样的函数(取决于实现):

explicit operator bool() const; // C++11

或者

operator void*() const; //C++98, C++2003

从这两个声明,我们知道它们强制转换流类型 直接或间接(通过 void* pinter 到 bool 这是显而易见的)到 bool 类型。

在这两个函数中,它们依赖于一些基本的IO steam状态(类字段)来确定是否返回false或true(对于void*情况,它是nullptr 或不)。

cin 是类istream 的一个实例,它继承了casting-to-bool 函数。所以它有效!

The answers above are informative. Here I just give an extra comment.

std::cin is an object of class istream and represents the standard input stream (i.e. the keyboard) which corresponds to stdin in C stream.

cin >> x would firstly read an int from the standard input stream and assignment it to x. After that return a self reference to cin. So the return value of function call cin >> x is still cin.

So from the point of if condition, if(cin) and if(cin >> x) resemble each other. The standard IO Library defines a function for the stream like this (depends on implementation):

explicit operator bool() const; // C++11

or

operator void*() const; //C++98, C++2003

From this two declarations, we know they cast the stream type directly or indirectly(through void* pinter to bool which is obvious) to bool type.

Within this two functions, they depends on some basic IO steam statuses(class fields) to determine whether return false or true (for void* case, it is nullptr or not).

cin is an instance of class istream which inherits the casting-to-bool function. So it works!

分开我的手 2024-12-02 09:59:18

因为表达式的结果

cin >> x

求值。

cin

在读取流后

because the result of the expression

cin >> x

evaluates to

cin

after the stream is read.

走过海棠暮 2024-12-02 09:59:18

std::cinstd::istream 类的实例。

cin>> x 只是调用 cin 对象上的函数。您可以直接调用该函数:

cin.operator >>(x);

为了允许您一次读取多个变量,operator>> 函数返回对其调用的流的引用。您可以调用:

cin >> x >> y;

或 等效:

cin.operator >>(x).operator >>(y);

或:

std::istream& stream = cin.operator >>(x);
stream.operator >>(y);

难题的最后一部分是 std::istream 可转换bool。布尔值是
相当于调用 !fail()

因此,在以下代码中:

int x;
std::istream& stream = std::cin.operator >>(x);
bool readOK = !stream.fail();
if (readOK)
{
  std::cout << x << "\n";
}

bool readOK = !stream.fail(); 可以简化为 bool readOK = stream;

您不需要单独的 bool 来存储流状态,因此只需执行 if (stream) 即可。

删除临时 stream 变量会得到 if (std::cin.operator >>(x))

使用运算符直接让我们回到原始代码:

int x;
if (std::cin >> x)
{
  std::cout << x << "\n";
}

std::cin is an instance of the std::istream class.

cin >> x is just calling a function on the cin object. You can call the function directly:

cin.operator >>(x);

To allow you to read multiple variables at once the operator >> function returns a reference to the stream it was called on. You can call:

cin >> x >> y;

or equivalently:

cin.operator >>(x).operator >>(y);

or:

std::istream& stream = cin.operator >>(x);
stream.operator >>(y);

The final part of the puzzle is that std::istream is convertible to bool. The bool is
equivalent to calling !fail().

So in the following code:

int x;
std::istream& stream = std::cin.operator >>(x);
bool readOK = !stream.fail();
if (readOK)
{
  std::cout << x << "\n";
}

bool readOK = !stream.fail(); can be reduced to just bool readOK = stream;.

You don't need a separate bool to store the stream state so can just do if (stream).

Removing the temporary stream variable gives if (std::cin.operator >>(x)).

Using the operator directly gets us back to the original code:

int x;
if (std::cin >> x)
{
  std::cout << x << "\n";
}
陌伤浅笑 2024-12-02 09:59:18

1)cinistream的一个实例,参见http://www.cplusplus.com/reference/iostream/cin/

2) istream>> 运算符将返回其左操作数,在本例中为 cin,参见 http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/。如果没有从 cin 中提取字符,则该运算符会将 failbit 设置为 on,以防读取器已完成 EOF,因此不会再有字符阅读。

3) 与上面的2)一样,当读取操作后评估条件时,if (cin >> x)应该类似于if (cin),参考此链接 http://www.cplusplus.com/reference/ios/ios/ Operator_bool/ 你将会看到,这个 if 块将返回:

  • 如果至少设置了 failbitbadbit 之一,则返回一个空指针。否则为其他值(对于 C++98 标准)。

  • 如果至少设置了这些错误标志之一,则该函数返回 false,否则返回 true。 (对于 C++11 标准)

1) cin is an instance of istream, see http://www.cplusplus.com/reference/iostream/cin/.

2) the >> operator of istream will return its left operand, in this case it is cin, see http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/. This operator will set failbit on if no characters were extracted from the cin, in case the reader has finished EOF so there will be no more character to read.

3) As of the 2) above, when the condition is evaluated after the reading operation, if (cin >> x) should be like if (cin), refer to this link http://www.cplusplus.com/reference/ios/ios/operator_bool/ you will see that, this if block will return:

  • A null pointer if at least one of failbit or badbit is set. Some other value otherwise (for C++98 standard).

  • The function returns false if at least one of these error flags is set, and true otherwise. (for C++11 standard)

时光清浅 2024-12-02 09:59:18

因为 cin 是类的对象,所以请阅读 http://www.cplusplus.com/reference 了解更多信息/iostream/cin/

because cin is an object of class, read more on http://www.cplusplus.com/reference/iostream/cin/ .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文