while( cin >> value ) breaks the loop when i entered a character - c++

In the past, I have been programming in c# but now I am learning c++. Why the while loop exit in c++ when I enter a string and in c# if I don't use tryparse it will give an exception. Does the c++ explicitly do something like tryparse in the backend ?
Sorry if my question
I am using codeblocks as my c++ IDE.
I am reading the book c++ primes and code a simple program that continuously takes integer as input until a string is entered. I wrote the same code in c# but it leads me to an error. So I have to use tryparse method in C#.
int value = 0;
In C++
while( cin >> value );
In C#
while( value == int.parse(Console.ReadLine());

Why the while loop exit in c++ when I enter a string
operator>> performs error handling internally. If it fails to extract an integer, the stream enters a failure state, and the loop is checking the stream's state, so it exits when the stream fails.
in c# if I don't use tryparse it will give an exception.
Yes, because that is the way int.parse() is defined to work.
You can get similar behavior in C++ by enabling exceptions in the stream . That way, if an extraction failure occurs, a std::ios_base::failure exception is thrown.
Does the c++ explicitly do something like tryparse in the backend ?
In a way, yes.
I am reading the book c++ primes and code a simple program that continuously takes integer as input until a string is entered. I wrote the same code in c# but it leads me to an error.
Your C++ and C# codes are not equivalent.
Your C# code reads an entire line as-is, discarding the line break, and then tries to convert the entire line as-is to an int.
Your C++ code discards leading whitespace - including line breaks - until it encounters a non-whitespace character, then it tries to read an int value, and whatever follows after it - including a line break - remains in the stream for subsequent reads.
So I have to use tryparse method in C#.
If you don't want a failed conversion to throw an exception, then yes.

C++ knows to parse for an integer because you defined the variable "value" as type int.
From the C++ reference:
As an object of class istream, characters can be retrieved either as
formatted data using the extraction operator (operator>>) or as
unformatted data, using member functions such as read.

Related

Explain how the for loop is terminating?

I came across the a code which I didn't understand. It was on a coding website. The code was like this-
#include<iostream>
using namespace std;
char s[4];
int x;
int main()
{
for(cin>>s;cin>>s;x+=44-s[1]);
cout<<x;
}
My question is how the for loop is terminating and since it was on a coding website so answers are checked using file operation in my knowledge. But if we are running it on IDE this for loop is not terminating instead it keeps on taking input from the user.So whats the explanation for this??
Sample Input
3
x++
x--
--x
Output
-1
EDIT
This is the problem link - Bit++
This is the solution link - In status filter set language to MS C++ Author name - wafizaini (Solution id - 27116030)
The loop is terminating because istream has operator bool() (prior to C++11 it was operator void*) which returns false when no additional input is available. Basically, the reason the loop stops is the same as why a more common while loop terminates:
while (cin >> s) {
...
}
The reason this does not terminate when you run with an IDE is that you need to supply an end-of-stream mark, which is delivered in a system-dependent way. On UNIX and other systems derived from it you press Ctrl+d, while on Windows you press Ctrl+z.
Note: Your program is at risk of getting a buffer overrun in case an end-user enters more than three characters (character #4 would be used for null terminator of the string). Also note that the initial input cin>>s is thrown away, because loop condition is checked before entering the body of the loop.
That's perfectly valid, although a bit difficult to read, C++11 code.
std::istream::operator>>()
returns a reference to the input stream itself, and
std::istream::operator bool()
in turn evaluates the stream to a boolean value, returning false whenever a fail bit is set.
When reading from a file, that loop will eventually try to read past the end of file, causing the eof fail bit to be set and thus stopping the loop.
However, when running that code on a shell, you need to manually input the EOF control code on the stream, otherwise the for loop won't stop. This can be done by pressing Ctrl+D on Unix shells, for example.
A more common loop condition is while (cin >> s).
The convention is that operator>> returns a reference to the stream (cin). The stream classes then have a conversion operator that will return false in if (cin) or while (cin) after some input has failed.
This would work in the middle part of a for-loop as well, but is a bit unusual.

C++ file stream

Could someone please explain how c++ reads in files? I'm not asking the code to read in a file but after the ifstream >> variable, what are the rules to how c++ grabs the data ?
Is the file read like how a cin would read in the user input? meaning it stops after each whitespace? What happens after it reaches the end of a line? does it automatically proceed to the next line or do I have to write code for that? I know that it stops after eof, but I'm unsure of the process of extracting data and I can't write code if I don't understand the process. Thanks
Yes the input operator >> always "tokenizes" (stops at) whitespace. And reading from any input stream is working the same.
For very good information I suggest this reference. Especially the reference for the input operator is very detailed.
Basically when you call ifstream f;, you are creating a variable with access to the library. From there you must declare your intentions with that variable. Using f.open(fileName, ios::in); you can input from fileName using the >> operator, which actually operates like cin. It stops at white spaces like you'd expect. Once it reaches the end of a line, it continues as long as you have code that asks the operator to extract more. You dont have to do anything extra to tell it to move on to the next line.
More info can be found here.
The iostream formatted input and output operators are essentially defined in terms of the C library functions strtol/strtoul/strtod (cf. 22.4.2.1.2) and sprintf (cf. 22.4.2.2.2), respectively.
In C/C++ there is generally no difference in any stream input (besides details eg.: seeking).
Having C++ there are two distinguished ways of input:
Formatted Input
Unformatted Input
All formatted input operations involve an operator stream& operator >> (stream&, T). However, not all stream& operator >> (stream&, T) are performing formatted input (eg.: some are involving manipulators or a stream buffer)
Each formatted input starts with skipping white spaces and stops at the first character not being part of the input format (Note: It may be any character, it is not limited to white spaces).
Unformatted input reads all characters (does not ignore any white space) and stops if a requested amount of characters is retrieved or the stream reaches the end (EOF). Specialized functions (like std::getline) might stop early and ignore the delimiting condition character.

How do I write exception handling for bad input?

I am trying to write a function that prompts a user for a five digit number, and I want to write an exception block to handle bad input incase the user tries to enter a string or some non-integer input.
I know how to write an exception handling block for something like a division function where you thrown an exception for the denominator being 0, but I have no clue how to do this for input that I have no control over.
First of all, I'd generally advise against this -- bad input from the user is nearly the rule rather than the exception.
If you insist on doing it anyway, you'd probably do it by accepting anything as input, and then throwing an exception when/if it's not what you want:
// Warning: untested code.
// Accepting negative numbers left as an exercise for the reader.
int get_int(std::istream &is) {
std::string temp;
std::getline(temp, is);
for (int i=0; i<temp.size(); i++)
if (!isdigit(temp[i]))
throw std::domain_error("Bad input");
return atoi(temp);
}
I repeat, however, that I don't think this is generally a good idea. I'd note (for one example) that iostreams already define a fail bit specifically for situations like this (and the normal operator>> to read an int uses that mechanism).
The most straightforward solution is to read a string, and convert it to integer, for example with atoi. If you get a zero as result, and your string was not "0", you know that the input was not numerical, without needing to loop through the string yourself.
Exceptions are often appropriate when accepting data from another machine or process, where there is no reason to expect invalid data to occur within an otherwise valid data stream. With regard to user input, exceptions should only be used in cases which should represent a clear departure from normal program flow. For example, if a program has a tty-style interface, and a routine which is supposed to read a line of input gets a control-C, it may be useful for such a routine to throw an exception. The control-C shouldn't necessarily end the program, but if the program is expecting to read several lines of input from the user, typing control-C at one should frequently cause the remainder to be skipped.

gets (variable)

can anyone tell me why gets(abc) works with char[] but not with int?
int abc;
char name[] = "lolrofl";
printf("Hello %s.\n",name);
printf("\n >> ");
fflush(stdin);
gets (abc);
printf("\n die zahl ist %i.\n",abc);
system("Pause");
return(0);
The prototype for gets() is:
char* gets(char *s);
Note that the function DOES NOT read just a single character and place it in s; it actually reads an entire string into s. However, since gets() does not provide a way of specifying the maximum number of characters to read, this can actually read more characters into s than there are bytes allocated for s. Thus, this function is a serious buffer overflow vulnerability, and you should not use this function, ever. There are alternative, safer functions which allow you to read input from the user such as fgets() and getc().
If you are using C++, then using the C++ I/O Stream Library (std::cin, std::cout, std::ostream, std::istream, std::fstream, etc.) is a far better way to perform input/output than using these other functions.
The function gets() is so dangerous, in fact, that in my development and coding custom search engine, I have taken out a promotion on gets and several other such functions warning not to use it!
Because it only reads characters. Use scanf() for formatted reading.
By the way, since you appear to be using C++ (or at least your choice of tags says so), perhaps you should try std::cin/std::cout.
If you take a look at the C Reference your question will be answered. I'll paste it for you:
char *gets( char *str );
The gets() function reads characters
from stdin and loads them into str,
until a newline or EOF is reached. The
newline character is translated into a
null termination. The return value of
gets() is the read-in string, or NULL
if there is an error. Note that gets()
does not perform bounds checking, and
thus risks overrunning str. For a
similar (and safer) function that
includes bounds checking, see fgets().
So you won't be able to cast a whole string to an integer.
First, the gets function is for reading strings or text, not numbers.
Second, don't use gets as it has buffer overrun errors. See C Language FAQ for more information. The function fgets is a safer alternative.
Third, you may want to switch to C++ streams and std::string. The C++ streams are more type friendly than C streams.
Fourth, fflush does not function on input streams. The fflush function is for writing the remaining data in stream buffers to the output stream. In C++, there is a method, ignore, which will ignore incoming characters until a newline (default) or a specified character is read (or a limit is reached).
Hope that helps.

What is the best way to do input validation in C++ with cin?

My brother recently started learning C++. He told me a problem he encountered while trying to validate input in a simple program. He had a text menu where the user entered an integer choice, if they entered an invalid choice, they would be asked to enter it again (do while loop). However, if the user entered a string instead of an int, the code would break.
I read various questions on stackoverflow and told him to rewrite his code along the lines of:
#include<iostream>
using namespace std;
int main()
{
int a;
do
{
cout<<"\nEnter a number:"
cin>>a;
if(cin.fail())
{
//Clear the fail state.
cin.clear();
//Ignore the rest of the wrong user input, till the end of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(),\
'\n');
}
}while(true);
return 0;
}
While this worked ok, I also tried a few other ideas:
1. Using a try catch block. It didn't work. I think this is because an exception is not raised due to bad input.
2. I tried if(! cin){//Do Something} which didn't work either. I haven't yet figured this one out.
3. Thirdly, I tried inputting a fixed length string and then parsing it. I would use atoi(). Is this standards compliant and portable? Should I write my own parsing function?
4. If write a class that uses cin, but dynamically does this kind of error detection, perhaps by determining the type of the input variable at runtime, would it have too much overhead? Is it even possible?
I would like to know what is the best way to do this kind of checking, what are the best practices?
I would like to add that while I am not new to writing C++ code, I am new to writing good standards compliant code. I am trying to unlearn bad practices and learn the right ones. I would be much obliged if answerers give a detailed explanation.
EDIT: I see that litb has answered one of my previous edits. I'll post that code here for reference.
#include<iostream>
using namespace std;
int main()
{
int a;
bool inputCompletionFlag = true;
do
{
cout<<"\nEnter a number:"
cin>>a;
if(cin.fail())
{
//Clear the fail state.
cin.clear();
//Ignore the rest of the wrong user input, till the end of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(),\
'\n');
}
else
{
inputCompletionFlag = false;
}
}while(!inputCompletionFlag);
return 0;
}
This code fails on input like "1asdsdf". I didn't know how to fix it but litb has posted a great answer. :)
Here is code you could use to make sure you also reject things like
42crap
Where non-number characters follow the number. If you read the whole line and then parse it and execute actions appropriately it will possibly require you to change the way your program works. If your program read your number from different places until now, you then have to put one central place that parses one line of input, and decides on the action. But maybe that's a good thing too - so you could increase the readability of the code that way by having things separated: Input - Processing - Output
Anyway, here is how you can reject the number-non-number of above. Read a line into a string, then parse it with a stringstream:
std::string getline() {
std::string str;
std::getline(std::cin, str);
return str;
}
int choice;
std::istringstream iss(getline());
iss >> choice >> std::ws;
if(iss.fail() || !iss.eof()) {
// handle failure
}
It eats all trailing whitespace. When it hits the end-of-file of the stringstream while reading the integer or trailing whitespace, then it sets the eof-bit, and we check that. If it failed to read any integer in the first place, then the fail or bad bit will have been set.
Earlier versions of this answer used std::cin directly - but std::ws won't work well together with std::cin connected to a terminal (it will block instead waiting for the user to input something), so we use a stringstream for reading the integer.
Answering some of your questions:
Question: 1. Using a try catch block. It didn't work. I think this is because an exception is not raised due to bad input.
Answer: Well, you can tell the stream to throw exceptions when you read something. You use the istream::exceptions function, which you tell for which kind of error you want to have an exception thrown:
iss.exceptions(ios_base::failbit);
I did never use it. If you do that on std::cin, you will have to remember to restore the flags for other readers that rely on it not throwing. Finding it way easier to just use the functions fail, bad to ask for the state of the stream.
Question: 2. I tried if(!cin){ //Do Something } which didn't work either. I haven't yet figured this one out.
Answer: That could come from the fact that you gave it something like "42crap". For the stream, that is completely valid input when doing an extraction into an integer.
Question: 3. Thirdly, I tried inputting a fixed length string and then parsing it. I would use atoi(). Is this standards compliant and portable? Should I write my own parsing function?
Answer: atoi is Standard Compliant. But it's not good when you want to check for errors. There is no error checking, done by it as opposed to other functions. If you have a string and want to check whether it contains a number, then do it like in the initial code above.
There are C-like functions that can read directly from a C-string. They exist to allow interaction with old, legacy code and writing fast performing code. One should avoid them in programs because they work rather low-level and require using raw naked pointers. By their very nature, they can't be enhanced to work with user defined types either. Specifically, this talks about the function "strtol" (string-to-long) which is basically atoi with error checking and capability to work with other bases (hex for example).
Question: 4. If I write a class that uses cin, but dynamically do this kind of error detection, perhaps by determining the type of the input variable at runtime, will it have too much overhead? Is it even possible?
Answer: Generally, you don't need to care too much about overhead here (if you mean runtime-overhead). But it depends specifically on where you use that class. That question will be very important if you are writing a high performance system that processes input and needs to have high throughout. But if you need to read input from a terminal or a file, you already see what this comes down to: Waiting for the user to input something takes really so long, you don't need to watch runtime costs at this point anymore on this scale.
If you mean code overhead - well it depends on how the code is implemented. You would need to scan your string that you read - whether it contains a number or not, whether some arbitrary string. Depending on what you want to scan (maybe you have a "date" input, or a "time" input format too. Look into boost.date_time for that), your code can become arbitrarily complex. For simple things like classifying between number or not, I think you can get away with small amount of code.
This is what I do with C but it's probably applicable for C++ as well.
Input everything as a string.
Then, and only then, parse the string into what you need. It's sometimes better to code your own than try to bend someone else's to your will.
In order to get the exceptions with iostreams you need to set the proper exception flag for the stream.
And I would use get_line to get the whole line of input and then handle it accordingly - use lexical_cast, regular expressions (for example Boost Regex or Boost Xpressive, parse it with Boost Spirit, or just use some kind of appropriate logic
What I would do is twofold: First, try to validate the input, and extract the data, using a regular expression, if the input is somewhat not trivial. It can be very helpful also even if the input is just a series of numbers.
Then, I like to use boost::lexical_ cast, that can raise a bad_ lexical_ cast exception if the input cannot be converted.
In your example:
std::string in_str;
cin >> in_str;
// optionally, test if it conforms to a regular expression, in case the input is complex
// Convert to int? this will throw bad_lexical_cast if cannot be converted.
int my_int = boost::lexical_cast<int>(in_str);
Forget about using formatted input (the >> operator) directly in real code. You will always need to read raw text with std::getline or similar and then use your own input parsing routines (which may use of the >> operator) to parse the input.
How about a combination of the various approaches:
Snag the input from std::cin using std::getline(std::cin, strObj) where strObj is a std::string object.
Use boost::lexical_cast to perform a lexical translation from strObj to either a signed or unsigned integer of largest width (e.g., unsigned long long or something similar)
Use boost::numeric_cast to cast the integer down to the expected range.
You could just fetch the input with std::getline and then call boost::lexical_cast to the appropriately narrow integer type as well depending on where you want to catch the error. The three step approach has the benefit of accepting any integer data and then catch narrowing errors separately.
I agree with Pax, the simplest way to do this is to read everything as string, then use TryParse to verify the input. If it is in the right format, then proceed, otherwhise just notify the user and use continue on the loop.
One thing that hasn't been mentioned yet is that it is usually important that you test to see if the cin >> operation worked before using the variable that supposedly got something from the stream.
This example is similar to yours, but makes that test.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
while (true)
{
cout << "Enter a number: " << flush;
int n;
if (cin >> n)
{
// do something with n
cout << "Got " << n << endl;
}
else
{
cout << "Error! Ignoring..." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
return 0;
}
This will use the usual operator >> semantics; it will skip whitespace first, then try to read as many digits as it can and then stop. So "42crap" will give you the 42 then skip over the "crap". If that isn't what you want, then I agree with the previous answers, you should read it into a string and then validate it (perhaps using a regular expression - but that may be overkill for a simple numeric sequence).