I am a C beginner,
#include <iostream>
int main()
{
char v1;
// valid no warning
std::cout << (std::cin >> v1) << std::endl; // return value of the expression expected
return 0;
}
// output: 1
// return value of the expression is 1?
Is the return value of (std::cin >> v1) really 1? Why?
CodePudding user response:
std::cin >> v1
returns cin
; Not sure what type it gets converted to for std::cout
, but most likely it indicates the state of cin
, where 1
is good
CodePudding user response:
Is the return value of (std::cin >> v1) really 1
No, see the ref for cin, it will return a istream
.
Your codes will not work, we can not pass ::istream
(std::cin) to operator<< of a std::ostream
(std::cout).
Shoule be like the following:
char v1;
cout << "Input a char:";
cin >> v1;
CodePudding user response:
I don't know of a current compiler that will accept your code as it stands right now. g , clang and Microsoft all reject it, saying they can't find an overload to match the arguments (i.e., an operator<<
for ostream
that takes an istream
as an operand).
It's possible to get the result you've posited with code on this order: std::cout << !!(std::cin >> v1) << "\n";
. Depending on the age of the compiler and standard with which it complies, this does one of two things.
With a reasonably current compiler, this will use the Boolean conversion on the istream to get it to match the !
operator, then apply that (twice) to the result, so you write out the result of that operator.
With old enough compilers, there won't be a Boolean conversion operator, but there will be an overload of operator!
, which also does a conversion to Boolean (but negated in sense, of course). The result of that will then be negated by the second !
.
Either way, you end up writing out a Boolean value (or int
containing zero or one on an old enough compiler) that indicates whether the stream is in a failed or successful state.
This is done to allow you to check input as you're reading it, so you can process input data sanely. For example, when/if you want to read all the values in a file, stopping at the end of the file, or when you encounter something that can't be interpreted as the desired type, you can write code on this general order:
// read integers from a file and print out their sum
int temp;
int total = 0;
while (std::cin >> temp) {
total = temp;
}
std::cout << total << "\n";
The while
loop uses the conversion to Boolean to determine whether an attempt at reading a value was successful or not, so it continues reading values as long as that happens successfully, and quits immediately when reading is unsuccessful.
One common source of errors is to write a loop on this order instead:
while (std::cin.good()) { // or almost equivalently, check for end of file.
std::cin >> temp;
total = temp;
}
But loops like this get the sequence incorrect. One common symptom of the problem with this is that the last number in the file will be added to the total twice instead of once.
CodePudding user response:
The program only works for Pre-C 11 because the conversion to bool is not explicit.
Starting from C 11, the program will no longer work because the conversion to bool is explicit.
Note that std::cin >> v1;
returns std::cin
and not 1
. But there is no operator<<
for std::ostream
that takes a std::cin
.
The reason it works for Pre-C 11 is because in this case the conversion to bool was not explicit. But starting from C 11, the conversion to bool was made explicit and so the code no longer compiles.
For example,
bool b = std::cin; //WORKS for Pre-C 11 but FAILS for C 11 & onwards
bool b{std::cin}; //OK, WORKS for all versions(Pre-C 11 as well as C 11 & onwards) because in direct initialization we can use explicit conversion
CodePudding user response:
VS2022
Severity Code Description Project File Line Suppression State
Error C2678 binary '<<': no operator found which takes a left-hand operand of type 'std::ostream' (or there is no acceptable conversion) ConsoleApplication1 C:\work\ConsoleApplication1\ConsoleApplication1.cpp 8