why its jumping out of program? - c++

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.

Related

How do I limit user to input a single character only in C++

I am a beginner and I'm trying to limit the user to input a single character only, I do aware of using cin.get(char) and it will only read one character from the input, but I don't want the other characters be left in buffer. Here is a sample of my code using EOF, but it doesn't seem to work.
#include <iostream>
#include <sstream>
using namespace std;
string line;
char category;
int main()
{
while (getline (cin, line))
{
if (line.size() == 1)
{
stringstream str(line);
if (str >> category)
{
if (str.eof())
break;
}
}
cout << "Please enter single character only\n";
}
}
I have used this for digit inputs and the eof works fine.
But for the char category the str.eof() seems to be false.
Can someone explain? Thanks in advance.
The eof flag is only set if you read try to read past the end of the stream. If str >> category read past the end of the stream, if (str >> category) would have evaluated false and not entered the loop to test (str.eof()). If there was one character on the line you would have to attempt to read two characters to trigger eof. Reading two characters is far more effort than testing the length of line to see how long it is.
while (getline (cin, line)) got the whole line from the console. If you don't consume it in the stringstream it doesn't matter, that stuff is gone is gone from cin when you loop back around in the while.
In fact, the stringstream isn't doing you any favours. Once you've confirmed the length of the line that was read, you can just use line[0].
#include <iostream>
using namespace std;
int main()
{
string line; // no point to these being global.
char category;
while (getline(cin, line))
{
if (line.size() == 1)
{
//do stuff with line[0];
}
else // need to put the fail case in an else or it runs every time.
// Not very helpful, an error message that prints when the error
// didn't happen.
{
cout << "Please enter single character only\n";
}
}
}

Reading sentences as string inputs from users

I have been trying to implement a simple code which takes a sentence as an input from the user, stores it in a string and displays it back.
Here are the issues:
1. When T = 1, the program exits immediately.
2. When T>1, the loop runs for only T-1 times.
I think the usage of cin to store the value of T is an issue here. Is the value of T entered being stored as a string due to some buffer capacity of cin?
#include <iostream>
#include <string>
int main()
{
int T;
std::cin >> T;
while (T--)
{
std::string song;
getline(std::cin, song);
std::cout << song << std::endl;
}
return 0;
}
How do you terminate the input that becomes T? With a newline. What happens with that newline after you read into T? It's still left in the input buffer. What will happen when you next call std::getline, what is the first character it will read? The newline, and what happens next? The loop iterates and then T is zero (for the first case where T was originally 1) and the loop and then the program exits.
The solution to this problem is to ignore characters up to and including the newline.
Add a getchar after cin as the \n after the input of T stays in buffer.
std::cin >> T;
getchar();
This is a strange way to do it. So you ask the user to tell the program, before any other input, how many lines will follow? Why not simply:
std::string s;
while (getline(std::cin, s)) {
std::cout << s << std::endl;
}
(This will simply echo every line (press enter to end the line) until end-of-file (Ctrl-d).
Either way, the problem with your code is the while (T--): so why don't you try to see what your T is, and what your getline gives you on each iteration? (I will let you figure it out on your own). Why not use the idiomatic:
for (int i = 0; i < T; ++i)
?
P.S. If you want to read sentences, and not lines, you might want to consider reading up to a delimiter (for example .). getline will do that for you, too:
getline(std::cin, s, '.');

How come the last character is taken in twice before the file resets?

I have a function that takes input from a file, character by character:
#include <iostream>
#include <fstream>
using namespace std;
ifstream input("sequence.txt");
char getChar(){
char nextType;
if (input.eof()) {
input.clear();
input.seekg(0,ios::beg);
}
input >> nextType;
return nextType;
}
int main(){
for(int i = 0; i < 10; i++){
cout << getChar() << endl;
}
return 0;
}
The input inside "sequence.txt" is:
I O
So the output should print alternating I's and O's, but instead outputs:
I O O I O O I O O I
How do I make the file reset after the first time it reads the last character in the file?
eof is only set when you try to read after already reaching the end of the file. Instead, first try to read a char. If that fails, then reset the stream and try again, like this:
char getChar()
{
char nextType;
if (!(input >> nextType))
{
input.clear();
input.seekg(0,ios::beg);
input >> nextType;
}
return nextType;
}
You're returning a value without testing whether the input
succeeded. You're function should be something alont the lines
of:
char
getChar()
{
char results;
input >> results;
if ( !input ) {
input.clear();
input.seekg( 0, std::ios_base:;beg );
input >> results;
if ( !input ) {
// There are no non-blanks in the input, so there's no way we're
// going to read one. Give up, generating some error condition
// (Throw an exception?)
}
}
return results;
}
The important thing is that there is no path of execution
which reads or copies results without having successfully read
it. (Unless you've assigned something to it otherwise. You
might, for example, initialize it with '\0', with the
convention that the function returns '\0' if it is unable to
read anything.)
I might add that the test for input.eof() is only valid
after you've determined that an input has failed. I may
return false even when there's no more valid input.

cin.eof() functionality

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;
}

C++: Check istream has non-space, non-tab, non-newline characters left without extracting chars

I am reading a std::istream and I need to verify without extracting characters that:
The stream is not "empty", i.e. that trying to read a char will not result in an fail state (solved by using peek() member function and checking fail state, then setting back to original state)
That among the characters left there is at least one which is not a space, a tab or a newline char.
The reason for this is, is that I am reading text files containing say one int per line, and sometimes there may be extra spaces / new-lines at the end of the file and this causes issues when I try get back the data from the file to a vector of int.
A peek(int n) would probably do what I need but I am stuck with its implementation.
I know I could just read istream like:
while (myInt << myIstream) {…} //Will fail when I am at the end
but the same check would fail for a number of different conditions (say I have something which is not an int on some line) and being able to differentiate between the two reading errors (unexpected thing, nothing left) would help me to write more robust code, as I could write:
while (something_left(myIstream)) {
myInt << myIstream;
if (myStream.fail()) {…} //Horrible things happened
}
Thank you!
There is a function called ws which eats whitespace. Perhaps you could call that after each read. If that hits eof, then you know you've got a normal termination. If it doesn't and the next read doesn't produce a valid int, then you know you've got garbage in your file. Maybe something like:
#include <fstream>
#include <iostream>
int main()
{
std::ifstream infile("test.dat");
while (infile)
{
int i;
infile >> i;
if (!infile.fail())
std::cout << i << '\n';
else
std::cout << "garbage\n";
ws(infile);
}
}
this is what I did to skip whitespace/detect EOF before the actual input:
char c;
if (!(cin >> c)) //skip whitespace
return false; // EOF or other error
cin.unget();
This is independent of what data you are going to read.
This code relies on the skipws manipulator being set by default for standard streams, but it can be set manually cin >> skipw >> c;
And simple
for(;;){
if(!(myIstream >> myInt)){
if(myIstream.eof()) {
//end of file
}else{
//not an integer
}
}
// Do something with myInt
}
does not work? Why you need to know if there are numbers left?
Edit Changed to Ben's proposition.
The usual way to handle this situation is not to avoid reading from the stream, but to put back characters, which have been read, if needed:
int get_int(std::istream& in)
{
int n = 0;
while(true) {
if (in >> n)
return n;
clean_input(in);
}
}
void clean_input(std::istream& in)
{
if (in.fail()) {
in.clear();
// throw away (skip) pending characters in input
// which are non-digits
char ch;
while (in >> ch) {
if (isdigit(ch)) {
// stuff digit back into the stream
in.unget();
return;
}
}
}
error("No input"); // eof or bad
}