I was trying to verify if the entered value was an integer with the type id function. I know that the returned value would be i and not integer. I don't know why any entered value returns false and the programs stops. Any help would be appreciated.
The program works fine without the while statement
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
int number, factorial;
cout << "Enter a number: ";
cin >> number;
factorial = 1;
while (typeid(number).name() == "i") {
for (int i = number; i >= 1; --i){
factorial *= i;
}
cout << factorial;
}
}
The returned string of the member function name of std::type_info is implementation defined. It's not guaranteed to be "i". If you want to check the type of an object against another type you should do:
typeid(object) == typeid(T)
for any T type. In your example:
typeid(number) == typeid(int)
But the above comparison will always return true because number is declared as int. typeid is usually helpful to inspect the dynamic type of a polymorphic object. In your case number is not polymorphic at all. Therefore you don't need it.
What you seem to be worried about is validation of the input. For that you should consider that if operator>> of std::cin fails the following will happen:
(until C++11)
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
(since C++11)
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set.
Therefore all you need to do is check the fail bit right after requiring it:
std::cin >> number;
if (std::cin) {
// ...
}
When streams read to an object, they check the format that's being read and parse that format into the object. If the stream cannot correctly parse that data, it sets an error in its error mask. The error mask is used to determine if an I/O operation succeeded or failed. When a stream is put into a boolean context (like in the parameters of an if() or while() loop), it will return true if its error mask is free of any errors.
If your intention is to only use an integer, then I suggest you adopt the pattern of using the stream itself to check if I/O operations succeeded. For example, this is how it will look in your code:
if (std::cin >> number) {
...
}
The formatted extractor operator>>() returns a reference to the stream which will then call its member function explicit operator bool() const to access its stream state and return true or false depending on whether the stream successfully read the contents of the stream into number.
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 have a problem that cin.ignore() can not remove input from the buffer.
#include <iostream>
#include <string>
int main() {
using namespace std;
int x=0;
string k;
cin >> x;
cin.ignore(100,'\n');
cin.clear();
cin >> k;
cout << k << endl;
}
For the above code:
input : abc (program ends when I just input abc)
output : abc
I was really surprised because cin.ignore() did not remove "abc" from the input buffer.
What is wrong with my code?
If I change the positions of cin.ignore() and cin.clear(), it works well, why is that?
This code:
int x=0;
cin >> x;
Causes cin to be put into an error state (specifically, the failbit flag is set) if the input is not convertible to an int.
Per cppreference.com:
std::basic_istream<CharT,Traits>::operator>>:
This function behaves as a FormattedInputFunction. After constructing and checking the sentry object, which may skip leading whitespace, extracts an integer value by calling std::num_get::get().
...
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
(until C++11)
If extraction fails, zero is written to value and failbit is set. For signed integers, if extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() (respectively) is written and failbit flag is set. For unsigned integers, if extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() is written and failbit flag is set.
(since C++11)
...
Thus, any further I/O operations on the stream are disabled, like ignore(), until you clear() the error state to re-enable I/O.
std::basic_ios<CharT,Traits>::clear:
Sets the stream error state flags by assigning them the value of state. By default, assigns std::ios_base::goodbit which has the effect of clearing all error state flags.
std::basic_istream<CharT,Traits>::ignore:
ignore behaves as an UnformattedInputFunction. After constructing and checking the sentry object, it extracts characters from the stream and discards them until any of the following conditions occurs:
...
C++ named requirements: UnformattedInputFunction:
An UnformattedInputFunction is a stream input function that performs the following:
Constructs an object of type basic_istream::sentry with automatic storage duration and with the noskipws argument set to true, which performs the following
if eofbit or badbit are set on the input stream, sets the failbit as well, and if exceptions on failbit are enabled in this input stream's exception mask, throws ios_base::failure.
flushes the tie()'d output stream, if applicable
Checks the status of the sentry by calling sentry::operator bool(), which is equivalent to basic_ios::good.
If the sentry returned false or sentry's constructor threw an exception:
sets the number of extracted characters (gcount) in the input stream to zero
if the function was called to write to an array of CharT, writes CharT() (the null character) to the first location of the array
...
cin.clear(); removes the error flag from cin
and cin.ignore(); ignores the next numbers of spaces.
Since you declared x as a Integer and you write it in first, the console expects that an integer to be read first. if you type abc at first instead you are typing in a string and the console returns an error flag because it expects an integer. That's why your program ends right after that.
If you put cin.clear(); right after cin>>x and type abc the error flag that is been thrown will be ignored and the console continues with cin>>k
Currently I'm self-learning C++ Primer 5th. Here comes something I'm not sure. (I couldn't find the exact relevant question on F.A.Q).
Consider this while loop:
while(std::cin>>value){...} \\value here was defined as int.
The text book says:
That expression reads the next number from the standard input and stores that number in value. The input operator (§ 1.2, p. 8) returns its left operand, which in this case is std::cin. This condition, therefore, tests std::cin.When we use an istream as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds.
My question is: does std::cin read input into value first then test the validation of std::cin, or test std::cin first then decide whether to read into 'value'? I'm quite confused about when it "returns its left operand".
Remember that your code is equivalent to:
while (std::cin.operator>>(value)) { }
Or:
while (1) {
std::cin >> value ;
if (!std::cin) break ;
}
The "code" always tries to read from std::cin into value before testing std::cin.
Let's look at the quote:
[...] The input operator (§ 1.2, p. 8) returns its left operand, which in this case is std::cin. [...]
This only means that std::cin.operator>>(value) return std::cin.
This condition, therefore, tests std::cin. When we use an istream as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds.
What the text book says is that after trying to read an integer from std::cin to value, the >> operator returns std::cin. If std::cin is in a good state after reading value, then the test passes, otherwize it fails.
Some extra details:
When you do std::cin >> value, you basically call istream::operator>>(int&), and yes there is a test inside that method: If the test passes, then the internal state of std::cin is set to ios_base::goodbit, if it fails, internal state is set to on of the error flag (eofbit, failbit or badbit).
Depending on the exception mask for std::cin, if the internal test fails, an exception may be thrown.
From your quote:
When we use an istream as a condition, the effect is to test the state of the stream.
This basically mean that:
if (std::cin) { }
Is equivalent to:
if (!std::cin.fail()) { }
And std::cin.fail() check for failbit or badbit. This means that while (std::cin >> value) { } does not test the eofbit flag and will only fail when the input cannot be converted to an integer value.
does std::cin read input into value first then test the validation of
std::cin, or test std::cin first then decide whether to read into
'value'
cin first tries to read an int from the standard input, if cin is in a good state: if it fails to, it will set the stream to a bad state; regardless of the operation done, it will return the stream itself (i.e. the "left operand" -- cin), that will allow you to check for success or failure.
If you wanted to explicitly test the validity of the stream first and only then try to read the value, you would have:
while (cin && cin >> value)
but it's pretty redundant, since, as I've told you, cin will not even try to read value if it's already in a bad state.
There are two tests.
The first test is the condition of the while statement
while(std::cin>>value){...}
This condition tests the result of calling operator function operator >>
The second test is a condition within the operator. If the state of the stream std::cin is good then the function tries to read an integer from the string. Otherwise it returns std::cin with the current erroneous state of std::cin.
In the while condition there is an expression
std::cin>>value
This expression must be evaluated. So this condition tests the result of the call of operator >> .
The result of the operator is the stream std::cin But it can be contextually converted to a bool value due to operator
explicit operator bool() const;
which returns the state of the stream
!fail().
I assume your "value" is for example an int
The stream tries to read input until the next whitespace.
if eof is found ... -> then the state will be set to "eof", >> will return the stream and the boolean evaluation of the stream will return false
if an error (I/O for example) happens during the reading process, the state will be set to "bad", >> will return the stream and the boolean evaluation of the stream will return false
if whitespace has been found, then a conversion from the read characters to int (the above assumption) will be attempted. If it fails (because the read input is for example: "xx" and not a number) the state of the stream will be set to "fail". >> will return the stream and the boolean evaluation of the stream will return false
if we are so far down the chain, eof was not found, no IO error (or other) happened, and the characters -> int conversion was successful. >> will return the stream and the boolean evaluation of the stream will return true.
And your "value" will contain the appropriate value
Presumably you wouldn't have any confusion with a simple function call:
SomeReturnType some_function(int&);
while (some_function(value)) { ... }
The above code will repeatedly call some_function until the return value from the function call, interpreted as a boolean, is false. The function is called for each step in the loop. Whether the function changes the value of value is up to the function. It certainly can do so, and presumably will do so (but that's an issue for the designer of the function).
The loop while (std::cin>>value) {...} is completely equivalent to while (std::cin.operator>>(value)) {...}. This is just a function call to the member function std::stream::operator>>(int&).
The operator first reads the value and then returns a reference to the object. The while statement first calls that operator and second tests the returned value.
I am learning C++ and I'm in doubt on how the following code works. My aim is to accept numbers (as a std::string) from the Command Line separated by spaces and separate these numbers from the string. I posted another question related to this and got the program working using the code below. Can you please explain to me how the numbers are actually extracted from the strings?
string gradesFullLine;
getline(cin, gradesFullLine);
stringstream gradeStream(gradesFullLine);
for(gradeStream >> grade; gradeStream; gradeStream >> grade) {
grades.push_back(grade);
}
Here's a simpler way to write the loop:
while(gradeStream >> grade) {
grades.push_back(grade);
}
Here's how it works:
gradeStream >> grade invokes operator>>(std::istream, int) (or whatever numeric type grade is). This attempts to "extract" a number from the stream, and updates the "stream state" indicating success or failure.
The result of the expression gradeStream >> grade, i.e. the return value of operator>>(std::istream, int), is gradeStream itself.
Any standard stream has a method equivalent to operator bool() const which lets you use the stream in a boolean context, such as an if() or while() condition. This operator returns true if the stream is "good" meaning it has not had any I/O errors (including reading past the end of the stream).
So the boolean value is used as the while condition, meaning that the loop will be entered so long as gradeStream has a "good state" which means grade has been populated with a number extracted from the stream (how this extraction happens is defined by your particular system implementation).
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.