I have a problem about cin.
int main(void)
{
int a;
float b;
cin >> a >> b;
}
When I give a floating number (such as 3.14) as input, neither a nor b get the complete value (3.14): the output is a=3, b=0.14.
I know that cin will split the input by space, tab or Return, but 'dot' will not, right?
And why will the following code work?
int main(void)
{
int i=0;
int k=0;
float j=0;
cin >> i >> k >> j; // i =3, j=k=0
}
And one more problem, what benefit will compiler do this for us?
Thanks!
You've declared a to be of type int, in which case what do you expect it to do with the "."?
failbit The input obtained could not be interpreted as an element of
the appropriate type. Notice that some eofbit cases will also set
failbit.
The other mention you have works fine what is the issue you are asking about? You've cined 3 variables what did you expect here? 0 is valid for float or int.
cin >> a >> b;
Given an input of 3.14, the first parse on the dot (period) because dot doesn't fit the syntax for an integer. The second parse picks up with .14, which parses just fine.
cin >> i >> k >> j;
This is problematic with an input of 3.14. The first parse once again stops on the dot. The second parse can't restart with the dot, so it marks the input stream as failed.
Always check status when doing I/O.
The formatted input functions work quite simple:
They skip leading whitespace if any.
They try to read a format matching the type given.
If reading the value fails because the data doesn't match the required format, they set std::ios_base::failbit. If reading fails the input shouldn't change the variable attempted to be read (the standard input operators follow this rule but user defined input operator might not).
The first value you try to read is an int. Reading an int means that a optional leading sign is read followed by a sequence of digits (where, depending on your settings and the value given, the stream may read octal or hexadecimal numbers rather than decimal ones). That is, the int receives the value 3 and reading stops right in front of the ..
Depending on what you read next, the next read fails or doesn't:
In the first code you try to read a floating point value which starts with an optional sign, followed by an optional integral parts, followed by an optional thousands separator, followed by an optional fractional part, followed by an optional exponent. At least one digit is required in either the integral or the fractional part. In your example, there is only a thousands separate followed by a fractional part.
When trying to read an integer, a . is found which isn't a valid part of an int and reading fails.
After attempting to read a value, you should always try if the read operation was successful and report potential errors:
if (in >> value) {
std::cout << "successfully read '" << value << "'\n";
}
else {
std::cerr << "failed to read a value from input\n";
}
Note, that after a failed read you may need to clean up as well, e.g., using
in.clear();
in.ignore();
This first clears the error flags (without this, the stream would ignore any further attempts to read the data) and then it ignores the next character.
cin is reading input "3.14" and you ask to put it into an integer and then a float.
So cin starts reading, finds "3", then finds "." which is not integer. Stores 3 into a and continues. ".14" is valid float and it puts it into b.
Then you ask to read int, int, float. The second integer is not matched and cin stops, but it only appears to be working. Actually, it failed.
The compiler can't warn you that you're doing something which will not work, because the input is not known at compile time.
Related
Write a program to display the sizes of basic four datatypes i.e integer, double, float, character.
Input:
The first line of input contains integer T denoting the number of test cases. For each test case, the user can input any of the above data types.
Output:
For each test case, there is a single line output displaying the size of that data type.
Constraints:
1<=T<=100
Example:
Input:
4
1
#
7.98
9.985647851
Output:
4
1
4
8
I tried this
int main() {
//code
int x;
cin>>x;
std::string s;
for(int i = 0;i<x;i++){
cin>>s;
cout << sizeof(s) << endl;
}
return 0;
}
Output was
32
32
Wrong Answer
I started to work on this problem to provide the OP with some insight however I have come to conclusion that many others have within the comment section of the OPs original question: and that is that this question or problem has an indeterminate solution!
Reasoning:
If the user enters any of the following digits as a single entity for input { 0, 1, ... 9 } into the console this can be at the least interpreted as an int or a char type and at worst even a possible double, but without the '.' character being present we could eliminate that as a candidate. This problem definitely has ambiguity to it. Checking to see if it is a float or a double is easy; all one has to do is check the string to see if there is at least a '.' then it's either a double or a float then check the last character of the string to see if it is a f and if so then it is a float. Checking to see if it is a character that is a non digit is easy, however distinguishing a single character digit between a char and an int is the troublesome part!
Work around:
You could conclude that if the input string is a single character and is a non digit then it is definitely a char type.
You could conclude that if the input string is a single character and is a digit ASCII[48 - 57] then you could conclude that it is an int type. This would be considered a restraint.
You could conclude that if it isn't the above two it is at least a float or a double and it is a float if and only if the last character of the string is a f, but a . must be present for it to be either of the two. Again these would be restraints that you would put on the accepted data input.
int a, b;
cin >> a >> b;
cout << a << endl << b;
input1: 3.5 5.5
input2: 3 5.5
check this code
The behaviour of your code is undefined up to and including C++03. The stream halts on the .. From C++11 onwards b is set to 0; prior to that it was not modified. Currently you read its value in the fail case, which is careless.
A good fix is to always write something like
if (cin >> a >> b){
// yes, all good
} else {
// a parsing error occurred
}
On the true branch, values are guaranteed to have been written to a and b.
It reads:
spaces/tabs/newlines (just consumes that if any)
digits till something different (the dot in your case) and parse them as the number
So a becomes 3.
Then, when it tries to read the second number it is still at the . , but a 'dot' is different from spaces and digits, so it does not consume any char and assignes 0 to b and set the failbit
Thanks to #tobi303 for the specs link:
(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.
The input is not a decimal value; it's a text string, and the code will translate that text string into an integer value. So, what's the integer value that the string "3.5" represents? It's 3, just as if the input had been "3 5": the code that translates the text reads as much of the text as makes sense, then stops. What happens after that depends on what caused the translation to stop. If it hit a whitespace character, all is well. If it hit something else (in this case, a .), you're in trouble.
I have a problem about cin.
int main(void)
{
int a;
float b;
cin >> a >> b;
}
When I give a floating number (such as 3.14) as input, neither a nor b get the complete value (3.14): the output is a=3, b=0.14.
I know that cin will split the input by space, tab or Return, but 'dot' will not, right?
And why will the following code work?
int main(void)
{
int i=0;
int k=0;
float j=0;
cin >> i >> k >> j; // i =3, j=k=0
}
And one more problem, what benefit will compiler do this for us?
Thanks!
You've declared a to be of type int, in which case what do you expect it to do with the "."?
failbit The input obtained could not be interpreted as an element of
the appropriate type. Notice that some eofbit cases will also set
failbit.
The other mention you have works fine what is the issue you are asking about? You've cined 3 variables what did you expect here? 0 is valid for float or int.
cin >> a >> b;
Given an input of 3.14, the first parse on the dot (period) because dot doesn't fit the syntax for an integer. The second parse picks up with .14, which parses just fine.
cin >> i >> k >> j;
This is problematic with an input of 3.14. The first parse once again stops on the dot. The second parse can't restart with the dot, so it marks the input stream as failed.
Always check status when doing I/O.
The formatted input functions work quite simple:
They skip leading whitespace if any.
They try to read a format matching the type given.
If reading the value fails because the data doesn't match the required format, they set std::ios_base::failbit. If reading fails the input shouldn't change the variable attempted to be read (the standard input operators follow this rule but user defined input operator might not).
The first value you try to read is an int. Reading an int means that a optional leading sign is read followed by a sequence of digits (where, depending on your settings and the value given, the stream may read octal or hexadecimal numbers rather than decimal ones). That is, the int receives the value 3 and reading stops right in front of the ..
Depending on what you read next, the next read fails or doesn't:
In the first code you try to read a floating point value which starts with an optional sign, followed by an optional integral parts, followed by an optional thousands separator, followed by an optional fractional part, followed by an optional exponent. At least one digit is required in either the integral or the fractional part. In your example, there is only a thousands separate followed by a fractional part.
When trying to read an integer, a . is found which isn't a valid part of an int and reading fails.
After attempting to read a value, you should always try if the read operation was successful and report potential errors:
if (in >> value) {
std::cout << "successfully read '" << value << "'\n";
}
else {
std::cerr << "failed to read a value from input\n";
}
Note, that after a failed read you may need to clean up as well, e.g., using
in.clear();
in.ignore();
This first clears the error flags (without this, the stream would ignore any further attempts to read the data) and then it ignores the next character.
cin is reading input "3.14" and you ask to put it into an integer and then a float.
So cin starts reading, finds "3", then finds "." which is not integer. Stores 3 into a and continues. ".14" is valid float and it puts it into b.
Then you ask to read int, int, float. The second integer is not matched and cin stops, but it only appears to be working. Actually, it failed.
The compiler can't warn you that you're doing something which will not work, because the input is not known at compile time.
I am having trouble with some basic input validation. I have done a lot of searching but cant seem to find the answer that works with my code. I am trying to validate integer input. I am able to test whether a char was entered or not but I need another parameter to test if the number is actually an int and not a double or float.
do
{
cout << "\nHow many numbers would you like to enter?" << endl;
cin >> size;
if (size < 1 || cin.fail())
{
cout << "\nInvalid input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}while(size < 1 || cin.fail());
Too late. By the time operator>> does its job, the horse has left the barn already. You have to figure it out before you actually parse the value.
If you tell operator>> to extract a value into an integer, operator>> will, first, skip any spaces, parse an optional negative sign, then as many digits as it sees. And that's what you will get.
If the last digit is followed by a ".", operator>> doesn't care. It stops, because you told it to parse an integer, and calls it a day.
Similarly, if you tell operator>> to extract a value into one of the floating point types (float, double, long double), operator>> will parse anything that looks like a floating point number, and put it into the floating point type instance. Since an integer looks like a perfectly valid floating point number, either an integer or a floating point number will parse equally, and stored.
You have no indication of what was actually parsed, except the value itself.
So, there are two ways of doing this. One way is to always parse the value into a floating point number, then check if the parsed number is a whole number, or contains any fractional part, then proceed accordingly.
Or, you could parse this yourself. Use get() to parse one character at a time. Ignore any leading whitespace, then collect everything that follows: an optional minus sign, zero or more digits, an optional period followed by zero or more digits, and an optional "e" followed by an exponent.
If you collected a period or an "e", as part of this process, you know that you just parsed a floating point number, otherwise it's going to be an integer. Then, take everything that's been collected, and then parse it, with std::istringstream's assistance, into your selected value.
(Technically, "e" does not necessarily indicate a floating point value; for example 1e3 will happily live inside an int, it's up to you to decide how you wish to handle this case).
I think you could read the input first then do the validation afterward.
If you can use a c11 compiler and the application only wants positive number and do not care symbols e.g "+", "-", you could try something like the following code:
#include <regex>
...
std::regex integers(R"(\d+)");
enum{INPUT_SIZE=256};
char input[INPUT_SIZE];
do
{
memset(input, 0, INPUT_SIZE);
cin >> input;
if(std::regex_match(input, input+strlen(input), integers))
{
cout << input << " is an integer\n";
}
else
{
cout << "input is not an integer";
}
}while(1);
#include <iostream>
int main()
{
int sum = 0, value = 0;
// read until end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
How does this code know when to finish grabbing input values and display sum? Why does it only end when I input a non-integer value?
Your loop ends when std::istream& operator>>(int) evaluates to false. That happens if the stream has hit end of file or has been marked as in error. Entering a floating point number causes the latter to occur.
Details:
Every stream includes a bitmask that indicates the status of the stream. The bits in the mask comprise an eof bit, a fail bit, and a bad bit (std::ios_base::eofbit, std::ios_base::failbit, and std::ios_base::badbit). The first is rather obvious: It's set upon hitting EOF. The next two are a bit trickier. std::ios_base::failbit is set when an input operation failed to read the expected characters, or when an output operation failed to generate the desired characters. std::ios_base::badbit is set when something goes very wrong, e.g., your disk is fried. The conversion from a stream reference to a boolean eventually involves checking that none of these bits is set. The decimal point in a floating point number causes the fail bit to be set, and that in turn causes your loop to end.
Because as long as you are typing intergers, the cin >> value expression evaluates to true. If you type a non-integer, the expression will fail because you would be trying to put a non-integer into your value variable of type int.
while (std::cin >> value) will ends when there is no input (ctrl-D or end of stream) or has something bad occurred. Your input of a non-integer gives an error then it terminate the while
The line while (std::cin >> value) is saying to continue running while std::cin >> value is true. Conveniently, since value is an int, if you enter value which can't be implicitly converted to an int, then that expression will return false. Otherwise, it keeps going.