I understand that cin.eof() tests the stream format. And while giving input, end of character is not reached when there is wrong in the input. I tested this on my MSV C++ 2010 and am not understanding the strange results. No matter what I give the input, I am getting Format Error message that is present in the program.
#include <iostream>
using namespace std;
int main()
{
int i;
cin>> i;
if(!cin.eof())
{
cout<< "\n Format Error \n";
}
else
{
cout<< "\n Correct Input \n";
}
getchar();
return 0;
}
Results I expected:
Values for i =
10 => Correct Input but the output is Format Error
12a => Format Error
Could someone explain where I am going wrong. Thanks.
std::cin.eof() tests for end-of-file (hence eof), not for errors. For error checking use !std::cin.good(), the built-in conversion operator (if(std::cin)) or the boolean negation operator (if(!std::cin)).
Use a direct test of the status of the stream with:
while (cin >> i)
{
...
}
For an input stream to enter the EOF state you have to actually make an attempt to read past the end of stream. I.e. it is not enough to reach the end-of-stream location in the stream, it is necessary to actually try to read a character past the end. This attempt will result in EOF state being activated, which in turn will make cin.eof() return true.
However, in your case you are not only not doing that, you (most likely) are not even reaching the end of stream. If you input your 10 from the keyboard, you probably finished the input by pressing the [Enter] key. This resulted in a new-line character being added to the input stream. So, what you are actually parsing with >> operator in this case is actually a 10\n sequence. Since you requested an int value from the stream, it only reads the numerical characters from the stream, i.e. it reads 1 and 0, but it stops at \n. That \n remains in the stream. You never read it. So, obviously, your code never reaches the end-of-file position in the stream. You have to reason to expect cin.eof() to become true in such case.
#include <iostream>
int main() {
using namespace std;
int i;
if (cin >> i) {
cout << "Extracted an int, but it is unknown if more input exists.\n";
char c;
if (cin.get(c)) { // Or: cin >> c, depending on how you want to handle whitespace.
cin.putback(c);
cout << "More input exists.\n";
if (c == '\n') { // Doesn't work if you use cin >> c above.
cout << "But this was at the end of this line.\n";
}
}
else {
cout << "No more input exists.\n";
}
}
else {
cout << "Format error.\n";
}
return 0;
}
Also see Testing stream.good() or !stream.eof() reads last line twice.
Sample session with the above program, note that input lines are marked with comments not present in the actual output:
$ your-program
12 # input
Extracted an int, but it is unknown if more input exists.
More input exists.
But this was at the end of this line.
$ your-program
12a # input
Extracted an int, but it is unknown if more input exists.
More input exists.
$ echo -n 12 | your-program
Extracted an int, but it is unknown if more input exists.
No more input exists.
$ your-program
a # input
Format error.
Assuming your input is line based, I suggest that you read the whole line using std::getline(). Once you have the line, you can analyse it and decide whether it contains correct or wrong input. Put the line into std::istringstream and do something like the following:
Edit: Changed !! iss to static_cast<bool>(iss) for compatibility with C++0x.
std::istringstream iss (line);
char ch;
long lval;
// read the input
iss >> lval;
// result variable will contain true if the input was correct and false otherwise
result
// check that we have read a number of at least one digit length
= static_cast<bool>(iss)
// check that we cannot read anything beyond the value read above
&& ! (iss >> ch);
Adding to the previous answer:
After reading your input (like 10), you are not at end-of-file, as you can easily type some more. How is the system to know that you will not?
When reading your second input (12a), it correctly reads all the digits that can be part of an integer. The letter 'a' cannot, so it is left for some possible later input. For example, you can read all parts of 12a with this code
int i;
char c;
cin >> i >> c;
cin.eof() test if the stream has reached end of file which happens if you type something like Ctrl+C (on Windows), or if input has been redirected to a file etc.
To test if the input contains an integer and nothing but an integer, you can get input first into a string and then convert that with a stringstream. A stringstream indeed reaches eof if there's no more to be extracted from it.
#include <iostream>
#include <sstream>
#include <string>
int main() {
using namespace std;
int i;
string input;
cin >> input; //or getline(cin, input)
stringstream ss(input);
if (ss >> i && ss.eof()) { //if conversion succeeds and there's no more to get
cout<< "\n Correct Input \n";
}
else {
cout<< "\n Format Error \n";
}
return 0;
}
Related
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream in("input.txt");
int i = 0,sum=0;
char x;
while (!in.eof()){
in >> i;
if (in.good()) {
cout << "integer is " << i << endl; sum += i;
}
if (in.fail()) {
in.clear();
in >> x;
cout << "the char is " << x << endl;
}
}
cout << sum;
char z;
cin >> z;
}
and my input.txt is like:
bear: sdf 23 okI am fine 11q , 45
and my screen output is like:
the last number 45 doesn't show up
So what happened here? why 45 is regarded as one out of file. And if I add a 's' immediately right next to 45, the screen will have two s showing up, rather than just one.
The problem is that when extracting symbols for 45,it tries to extract symbol after '5' (to check if number continues further) and sees end of file, setting eofbit. This makes in.good() test to fail. Suggestions:
while (!in.eof()){
in >> i;
if ( in ) { //Not .good(), just conversion to bool
Or
while (!in.eof()){
if ( in >> i; ) { //both extraction and checking in same operation
Remember, .good() is not the same as checking stream state. .good() is telling if stream ready for further input. Bool conversion does ! .fail() and checks if last operation was executed succesfully
Well, "eof()" does work as expected, at least, how I expect it to work: it gets set when the stream somehow touches the end of file. If your file's last line actually ends with '5' rather than a newline, reading an integer stops due to touching newline and std::ios_base::eofbit gets set. Since std::ios::good() returns false if any bit is set, include std::ios_base::failbit the last value wouldn't be printed.
In general, eof() is more often misused than appropriately used. Essentially the only reasonable uses of eof() is to verify if the entire stream was consumed or to suppress an error message if eof() is set as it is expected that input fails at the end of the stream. Likewise, there is generally little use for std::ios::good().
This function keeps getting called in another function inside a while-loop while valid_office_num is false. The problem is that if the input begins with a digit but is followed by other invalid characters (e.g. 5t) it takes the digit part and accepts that as a valid input. I want it to consider the whole input and reject it so it can ask for another one. I thought I could use getline() but then I cannot use cin.fail(). How could I implement this behavior?
I forgot to mention I am very new to C++, I have only learnt the basics so far.
(To be clear the desired behavior is to reject anything that contains anything other than digits. This is not an integer range check question. If it is NOT an integer, discard it and request another one)
//Function to read a valid office number, entered by user
int read_office_num()
{
//Declaration of a local variable
int office_num;
//Read input
cin >> office_num;
//Check if input was valid
if (cin.fail())
{
//Print error message
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n";
//Clear error flags
cin.clear();
//Ignore any whitespace left on input stream by cin
cin.ignore(256, '\n');
}
else
{
//Office number entered is valid
valid_office_num = true;
}
return office_num;
}
From what I gather you want the whole line to be read as a number and fail otherwise?
Well, you can use std::getline(), but you have to follow the algorithm below (I will leave the implementation to you..)
use std::getline(cin, str) to read a line, and if this returns true
use std::stoi(str, &pos) to convert to integer and get the position of the last integer
if pos != str.size() then the whole line in not an integer (or if the above throws an exception), then it's not a valid integer, else return the value...
Read a line of input as a std::string using std::getline().
Examine the string and check if it contains any characters that are not digits.
If the string only contains digits, use a std::istringstream to read an integer from the string. Otherwise report a failure, or take whatever other recovery action is needed (e.g. discard the whole string and return to read another one).
You could use a stringstream
int read_office_num()
{
//Declaration of a local variable
int office_num;
string input = "";
while (true) {
getline(cin, input);
stringstream myStream(input);
if (myStream >> office_num)
break;
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n" << endl;
}
return office_num;
}
If you want to reject input like 123 xxx you could add an additional check to verify that the received string is indeed an integer:
bool is_number(const string& s)
{
string::const_iterator itr = s.begin();
while (itr != s.end() && isdigit(*itr)) ++itr;
return !s.empty() && itr == s.end();
}
int read_office_num()
{
//Declaration of a local variable
int office_num;
string input = "";
while (true) {
getline(cin, input);
stringstream myStream(input);
if (is_number(input) && myStream >> office_num)
break;
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n" << endl;
}
return office_num;
}
You should probably just look at the number of input characters that are left in cin. You can do that with in_avail
Your function will probably end up having a body something like this:
//Declaration of a local variable
int office_num;
//Read input and check if input was valid
for (cin >> office_num; cin.rdbuf()->in_avail() > 1; cin >> office_num){
//Print error message
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n";
//Ignore any whitespace left on input stream by cin
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
//Office number entered is valid
valid_office_num = true;
return office_num;
Points of interest:
There is always at least 1 character in cin otherwise the cin would be marked as bad and that would not be good
You don't need valid_office_num if read_office_num is implemented this way, cause valid_office_num will always be set to true before returning
Hm. I may be missing something, but why not read a line, trim it, use regular expressions to validate a number and then exploit strstream's facilities or just atoi if you must? In all reality I'd probably just let users get away with extraneous input (but discard it if I'm sure I'm always running interactively). Following the motto "be lenient in what you accept."
The "interactive" caveat is important though. One can generally not assume that cin is a terminal. Somebody may get cocky and let your program run on a text file or in a pipeline, and then it would fail. A robust approach would separate data processing (portable) from means of input (possibly machine specific and therefore also more powerful and helpful than stdin/stdout via a console).
Here's how to do it using Boost Lexical Cast:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <vector>
#include <string>
int read_office_num()
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
using namespace std;
int office_num;
while (true)
{
try
{
string input = cin.getline();
office_num = lexical_cast<int>(*argv));
break;
}
catch(const& bad_lexical_cast)
{
cout << "\nInvalid office number, it should only consist of digits!! Enter another:\n";
}
}
return office_num;
}
I have a question on the stream behavior, see the following example. What I was expecting is, since there are only 5 chars in the string, and stream read will get stuck as I am trying to read 10 chars. Instead, the output is "hellooooo" ... the last char get repeated.
My questions are two folds: first, why? second, is there anyway to make stream behave as if no more repeating of last char?
#include <sstream>
#include <iostream>
using namespace std;
int main(void) {
char c;
string msg("hello");
istringstream iss(msg);
unsigned int i = 0;
while (i < 10) {
iss >> c;
cout << c;
i++;
}
cout << endl;
return 0;
}
What you see is the result of reading form a stream in an erronous state. When you read past the last element in the stream (this being a string stream), the stream becomes erroneous and any other attempt to read from it will fail (and leave the extraction variable untouched).
You will have to check if the extraction operation succeeded before reading further:
if (iss >> c) {
// succeess
} else {
// failed to extract, handle error
}
Were you to use a stream connected to the console (for an example) your call to >> would have blocked as you expected. The behavior of stringstream is different (you cannot expect to micraculously contain more data)
The reason is that when you've read to the end of the stream, all attempts to read after that just fail, leaving the last value read in your c.
If you want to read at most 10 characters:
while (i < 10 && is >> c) {
cout << c;
i++;
}
This works because a stream can be converted to bool, and it's true if the stream is in a "good" state.
"the last char get repeated"
When iss >> c fails, c stays unmodified.
Check whether extraction of value succeeded by directly evaluating this expression: if (iss >> c), but don't even think about calling iss.good(). Check this answer and also have a look at:
How does that funky while (std::cin >> foo) syntax work?
Why does my input seem to process past the end of file?
I used "cin" to read words from input stream, which like
int main( ){
string word;
while (cin >> word){
//do sth on the input word
}
// perform some other operations
}
The code structure is something like the above one. It is compilable. During the execution, I keep inputting something like
aa bb cc dd
My question is how to end this input? In other words, suppose the textfile is just "aa bb cc dd". But I do not know how to let the program know that the file ends.
Your code is correct. If you were interactively inputting, you would need to send a EOF character, such as CTRL-D.
This EOF character isn't needed when you are reading in a file. This is because once you hit the end of your input stream, there is nothing left to "cin"(because the stream is now closed), thus the while loop exits.
As others already answer this question, I would like add this important point:
Since Ctrl-Z on Windows (and Ctrl-D on unix systems) causes EOF to reach, and you exit from the while loop, but outside the while loop you cannot read further input, since the EOF is already reached.
So to enable reading using cin again, you need to clear eof flag, and all other failure flags, as shown below:
cin.clear();
After doing this, you can start reading input using cin once again!
int main() {
string word;
while (cin >> word) {
// do something on the input word.
if (foo)
break;
}
// perform some other operations.
}
Hit Ctrl-Z (Ctrl-D on *nix systems) and hit enter. That sends an EOF and invalidates the stream.
cin >> some_variable_or_manipulator will always evaluate to a reference to cin. If you want to check and see if there is more input still to read, you need to do something like this:
int main( ){
string word;
while (cin.good()){
cin >> word;
//do sth on the input word
}
// perform some other operations
}
This checks the stream's goodbit, which is set to true when none of eofbit, failbit, or badbit are set. If there is an error reading, or the stream received an EOF character (from reaching the end of a file or from the user at the keyboard pressing CTRL+D), cin.good() will return false, and break you out of the loop.
I guess you want to jump out at the end of file.
You can get the value of basic_ios::eof , it returns true at the end of stream.
Take the input from a file. Then you will find that the while loop terminates when your program stops taking input.
Actually cin stops taking input when it finds an EOF marker. Each input file ends with this EOF marker. When this EOF marker is encountered by operator>> it modifies the value of internal flag eofbit into false and consequently the while loop stops.
It helps me to terminate loop by hitting ENTER.
int main() {
string word;
while(getline(cin,word) && s.compare("\0") != 0) {
//do sth on the input word
}
// perform some other operations
}
You can make a check for a special word in input.
F.e. "stop":
int main( ){
string word;
while (cin >> word){
if(word == "stop")
break;
//do sth on the input word
}
// perform some other operations
}
you can try this
string word;
vector<string> words;
while (cin >> word) {
words.push_back(word);
if (cin.get() == '\n')
break;
}
in this way, you don't have to end with CTRL+D(Z). program will quit while sentence end
your program doesn't take in count white spaces. make difference between cin and getline...
here is an example with a trick: the program get input and prints output until you hit twice Enter to quit:
#include <iostream>
#include <string>
using namespace std;
int main(){
char c = '\0';
string word;
int nReturn = 0;
cout << "Hit Enter twice to quit\n\n";
while (cin.peek())
{
cin.get(c);
if(nReturn > 1)
break;
if('\n' == c)
nReturn++;
else
nReturn = 0;
word += c;
cout << word;
word = "";
}
cout << endl;
return 0;
}
I just start learning C++.
When I execute my code it's jumping out of the program without any error. Why?
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char s1[20],s2[10];
cout<<" enter a number : ";
cin.get(s1,19);
cout<<" enter a number : ";
cin.get(s2,9);
cout<<s1<<"/n"<<s2;
getch();
}
The method get() reads upto the '\n' character but does not extract it.
So if you type: 122345<enter>
This line:
cin.get(s1,19);
Will read 12345, but the '\n' (created by hitting <enter>) is left on the input stream. Thus the next line to read:
cin.get(s2,9);
Will read nothing as it sees the '\n' and stops. But it does not extract the '\n' either. So the input stream still has the '\n' there. So this line:
getch();
Just reads the '\n' character from the input stream. Which then allows it to finish processing and exit the program normally.
OK. That is what is happening. But there is more to this. You should not be using get() to read formatted input. Use the operator >> to read formatted data into the correct type.
int main()
{
int x;
std::cin >> x; // Reads a number into x
// error if the input stream does not contain a number.
}
Because the std::cin is a buffered stream the data is not sent to the program until you push <enter> and the stream is flushed. Thus it is often useful to read the text (from user input) a line at a time then parse that line independently. This allows you to check the last user input for errors (on a line by line bases and reject it if there are errors).
int main()
{
bool inputGood = false;
do
{
std::string line;
std::getline(std::cin, line); // Read a user line (throws away the '\n')
std::stringstream data(line);
int x;
data >> x; // Reads an integer from your line.
// If the input is not a number then data is set
// into error mode (note the std::cin as in example
// one above).
inputGood = data.good();
}
while(!inputGood); // Force user to do input again if there was an error.
}
If you want to get advanced then you can also look at the boost libs. They provide some nice code in general and as a C++ program you should know the contents of boost. But we can re-write the above as:
int main()
{
bool inputGood = false;
do
{
try
{
std::string line;
std::getline(std::cin, line); // Read a user line (throws away the '\n')
int x = boost::lexical_cast<int>(line);
inputGood = true; // If we get here then lexical_cast worked.
}
catch(...) { /* Throw away the lexical_cast exception. Thus forcing a loop */ }
}
while(!inputGood); // Force user to do input again if there was an error.
}
You need to use cin.ignore(); to ignore the newline character from stream before getting next input.