This question already has answers here:
Value stored when istream read fails
(2 answers)
Closed last month.
Instead of atoi I use operator>> of stringstream in the following function in order to convert a string into an int.
int MyString::Int()
{
int f = 0;
std::stringstream ss;
ss << *this;
ss >> f;
return f;
}
Is it guarenteed that operator>> does not touch integer variable "f" if it cannot convert the string data coming from "*this" into the integer?
Or can it happen that stringstream "ss" is set to failure by operator<< and therefore operator>> makes undefined behaviour because I do not check the state of the stream?
Edit: The answer is already here:
istream behavior change in C++ upon failure
There it is described that the behaviour changed in C++11 regarding if the value is left unchanged in some circumstances or set to zero if a conversion cannot be made. In my example above however the int variable is initialised anyway and therefore the return value would always be zero independently if the stream reaches eof before or the conversion is not possible.
ss >> f; may (and likely will) initially set f to 0 before trying to extract an integer from its internal buffer.
Regardless whether the extraction is a success (because of a previously or newly encountered error), you will not invoke UB. The operation will fail due to the incorrect stream state. It's perfectly valid and you can check for such states.
Related
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?
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.
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
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;
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
I'm taking input using cin and storing it into a char variable. My question is if there is any input that could cause cin.fail() to return true.
I know that trying to store input such as "foo" into an int variable will fail, but is there any case in which this is possible with a char variable?
The overloads for operator>> which take a char follow the normal behavior of a formatted input function, that is they call rdbuf()->sbumpc() or rdbuf()->sgetc() to perform the extraction. Naturally, if eof is encountered, then eofbit is set. If one of the functions throw an exception, then badbit is set. If either of these are set, then failbit is set. There's no evidence to indicate that the operation would fail otherwise. (This is covered under section [istream] in the C++11 draft standard.) For other types, like int, do_get() is used to convert the character (similar to scanf). Of course, the conversion can fail, but no conversion is needed if the input is already a char.
Now the comments are misleading. CTRL+C would kill the application in Linux. CTRL+Z would send a character that signals EOF on some operating systems.
You can even use an emoji and it would work:
#include <iostream>
int main()
{
char c;
if (std::cin >> c)
std::cout << "Huzzah!";
}
With input 😁 outputs "Huzzah!" as expected.
I guess not because a char variable with just take only the first character from the given input, no matter how long the input or of what type it is (int,long,double..)
No, failbit is only set if there's a logical error reading the input stream, AKA, someone rips out the USB flashdrive containing the file from which you're reading. ;)
cout << "Enter a positive integer or zero: ";
getline(cin, streamStr);
stringstream(streamStr) >> number;
if (!number) {
cout << "invalid input detected or the input is too big.\n";
return 1;
}
inputs like "%234" or "sdf2334" always fall to 0 , which is false in bool expression, but 0 is still a number.
How to check if the input is really invalid like "%234"??
You need to check the returned value of the operator>>, which is not the same as the value of the variable you're reading into:
if (stringstream(streamStr) >> number) {
...
So what's the returned value, then? If you check the docs, you'll see it's a stream itself. It goes to the operator bool of it (because it's used in an if statement), which in turn returns the validity of the stream, or, IOW, if the last operation succeeded.
If you want to ensure the stream doesn't contain anything besides the number use
if (sstream.rdbuf()->in_avail() > 0) {
// something is still there
And to skip whitespace at the end if you want to allow it:
sstream >> std::ws;
So, all in all...
template<typename T,
// those are optional
enable_if<is_default_constructible<T>::value>::type,
enable_if<is_input_streamable<T>::value>::type
>
optional<T> myRead(string input, bool allowTrailingWs = true) {
stringstream str(input);
T val;
// check parsing
if (!(str >> val))
return none;
// allow whitespace at the end
if (allowTrailingWs)
str >> std::ws;
// check if there's any garbage left
if (str.rdbuf()->in_avail() > 0)
return none;
return val;
}
The code above is just for illustration purposes. Shall you need more advanced parsing, check out Boost.Spirit.
Also, apparently this isn't guaranteed to work every time. Using:
auto inputEnd = ss.tellg();
ss.seekg(0, std::ios::end);
if (inputEnd == ss.tellg()) {
To check if the ss is empty could help fix that.
I don't think you understand how streams work. Allow me to address your misconception:
The stream won't attempt to extract any value into number if the data being evaluated doesn't correspond to formatting requirements of the type. Extraction works by the stream iterating through each character in the character sequence one by one, and testing each character as a viable datum for the type to which the extraction is targeted. If the character is not viable, extraction stops (this is why you are seeing success upon entering something like "2342fdsf"; the stream will keep extracting until it finds an invalid character. "2342" are valid characters for an integer while "f" is not)
If the stream finds an invalid character, nothing further is done to the variable (in this case number). In fact, it is implementation-defined what value an uninitialized variable has if extraction failed to produce any characters. With that in mind, it is potentially dangerous to check the value of the operand to determine if I/O failed. This is where checking the stream state comes in:
std::istringstream iss(streamStr);
if (iss >> number)
{
std::cout << "Extraction produced: " << number << '\n';
}
If the extractions fails, the stream will set the appropriate bits. The stream will then be implicitly converted to a boolean using operator bool() (or operator void*() pre-C++11 where it will subsequently undergo conversion to boolean). The boolean function will check the stream state using !this->fail() (which checks both badbit and failbit) and if the function returns true, the if body will be executed.
If the stream is not in a good state (!this->fail() returns false), that means the extraction failed to produce a value and the if statement body goes unevaluated.
By encasing the extraction in a conditional check, not the value of the thing you tried to extract into.
Assuming number must be a char value, try using the cctype library which is helpful for dealing with strings. It has functions such as
isdigit(Char_Exp) //Returns true if the value is a digit
and
isctrl(Char_Exp) //Returns true if the value is a control character like %(modulus)
Here is a link to a C++ cctype library reference: cctype library reference
To test number I would advise you create a function of type Boolean and so that it tests all possible input errors at once.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How would std::ostringstream convert to bool?
#include<iostream.h>
void main() {
if(cin>>2) { // what is cin>>2 doing inside arg of if
cout<<"if works";
} else {
cout<<"else works";
}
}
We don't get error in this code.But Alwaysif statement works why? how?
cin >> 2 is invalid. cin >> integervar is valid, assuming that's what you mean?
The standard library class ios which basic_istream (and thus cin) inherits from overloads operator void * (and operator!) to allow you to do such tests.
operator void * returns 0 if failbit or badbit is set - aka the last extraction failed.
This is the "standard" way of combining extraction and checking if the extraction succeeded.
if(cin>>2)
This wouldn't even compile. See this : http://ideone.com/MiEkq
What you probably mean is : if(cin>>var)
If that is so, then it means IF the read from the input stream succeeds, then then if block will be executed because after successful read, the returned std::istream & can implicitly convert into true, otherwise it converts into false.
BTW, the return type of main() should be int.
What does the istream::getline method return?
I am asking because I have seen that to loop through a file, it should be done like this:
while ( file.getline( char*, int ) )
{
// handle input
}
What is being returned?
It returns a stream so that we can chain the operation.
But when you use an object in a boolean context the compiler looks for an conversion operator that can convert it into a type that can be used in the boolean context.
C++11
In this case stream has explicit operator bool() const. When called it checks the error flags. If either failbit or badbit are set then it returns false otherwise it returns true.
C++03
In this case stream has operator void*() const. As this results in a pointer it can be used in a boolean context. When called it checks the error flags. If either failbit or badbit are set then it returns NULL which is equivalent to FALSE otherwise it returns a pointer to self (or something else valid though you should not use this fact)).
Usage
So you can use a stream in any context that would require a boolean test:
if (stream >> x)
{
}
while(stream)
{
/* do Stuff */
}
Note: It is bad idea to test the stream on the outside and then read/write to it inside the body of the conditional/loop statement. This is because the act of reading may make the stream bad. It is usually better to do the read as part of the test.
while(std::getline(stream, line))
{
// The read worked and line is valid.
}
Look from reference. The istream returned from getline is converted to bool by implicit conversion to check success of operation. That conversion makes usage of if(mystream.getline(a,b)) into shorthand for if(!mystream.getline(a,b).fail()).
It returns the stream itself. The stream can convert (through void*) to bool indicating its state. In this example, your while loop will terminate when the stream's conversion to bool goes "false", which happens when your stream enters an error state. In your code, it's most likely to occur when there was an attempt to read past the end of the file. In short, it'll read as much as there is, and then stop.
The function returns a reference to the stream object itself, which can be used either to chain further read operations:
myStream.getline(...).getline(...);
or, because streams are implicitly convertible to void *s, in a loop or condition:
while (myStream.getline(...)) {
...
}
You can read more about this on the cplusplus.com website:
http://cplusplus.com/reference/iostream/istream/getline/
Everyone has told you what it is, now let me tell you, use the free form version
std::string line;
while(getline(file, line)) // assuming file is an instance of istream
{
//
}
Why this version? It should become immediately apparent - you pass in a std::string rather than some fixed size character buffer!