Why does this program run fine?
#include<iostream>
using namespace std;
int main()
{
cout <<"What year was your house built?\n";
int year;
cin >> year;
cout << "What is its street address?\n";
char address[80];
cin>>address;
cout << "Year built: " << year << endl;
cout << "Address: " << address << endl;
cout << "Done!\n";
return 0;
}
And why does this program not give the chance to enter the address?
#include <iostream>
int main()
{
using namespace std;
cout <<"What year was your house built?\n";
int year;
cin >> year;
cout << "What is its street address?\n";
char address[80];
cin.getline(address, 80);
cout << "Year built: " << year << endl;
cout << "Address: " << address << endl;
cout << "Done!\n";
return 0;
}
cin>> leaves the newline character (\n) in the iostream. If getline is used after cin>>, the getline sees this newline character as leading whitespace, thinks it is finished and stops reading any further.
Two ways to solve the problem:
Avoid putting getline after cin >>
OR
Consume the trailing newline character from the cin>> before calling getline, by "grabbing" it and putting it into a "dummy" variable.
string dummy;
getline(cin, dummy);
Why does the first program work & Second doesn't?
First Program:
The cin statement uses the entered year and leaves the \n in the stream as garbage. The cin statement does NOT read (or "grab") \n. The cin ignores \n when reading data. So cin in program 1 can read the data properly.
Second Program:
The getline, reads and grabs \n. So, when it sees the \n left out from cin, it grabs the \n and thinks it is finished reading, resulting in second program not working as you expected.
Sit down for a second. This is not easy to explain properly.
When your program gets to a point where it reads from std::cin, it does not just automatically wait for you to type something. std::cin is an input stream, the same as you use to read from a file on disk. The only reason it waits is if there is not enough data available yet to satisfy the read request.
Meanwhile, when you run your program from the console, the console window itself is also a program. It is interpreting your key presses and translating them into text, and feeding that text a line at a time to the standard input of your program (so that std::cin can see it). This is important and useful, because it allows the backspace key to work the way you expect it to.
So if your program is supposed to read a number, and you type a number, your program will not see the number until you hit return to complete the line. However, the newline character is still sitting in the input stream, because you didn't read it yet. The operator>> skips whitespace before the value that it's trying to read, but it leaves behind any whitespace after the value.
Now, if the next reading operation is another call to operator>>, then it does the same thing again and it works fine: the newline that we didn't read before is whitespace, so it gets skipped, and then the next thing gets read.
However, the getline() function reads from the current point until the next newline. It never skips any leading or trailing whitespace, and an empty line is considered completely valid. So if you typed a number and hit return, then the getline() call will see the newline and finish reading right away, because it already has an end of the line. The program does not stop because there was already enough data available to finish the operation.
To fix this, the safest, simplest and most robust way of dealing with the input is to always read the entire line first, and then re-interpret the contents of the line. To make this easier, we will use the std::string class to represent strings. We can read into the string instance with std::getline (notice: a global function, not a member function of cin), and create a std::stringstream instance from that string.
The idea is: the program will always wait at an input request, because the previous request always read the newline character (because we read the entire line). So that makes the control flow work the way we expected it to. The std::stringstream instance can be treated like a file or standard input: it's just another stream, except it takes its data from the string. So we can get numbers out of it with operator>>, and so on.
The other benefit of this comes when the user inputs invalid data. It can be quite hard to recover from this properly, if you are just reading directly from std::cin. But if you are using the stringstream as a "buffer", then you can just throw it away and try again with a new line of input.
An example:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
using namespace std;
string line;
int year;
while (true) {
cout << "What year was your house built?" << endl;
getline(cin, line);
stringstream input(line);
if (line >> year) { break; }
}
cout << "What is its street address?\n";
getline(cin, line);
cout << "Year built: " << year << endl;
cout << "Address: " << line << endl;
cout << "Done!\n";
}
Maybe you have a stray terminator in cin?|
Try cin.clear();
Related
I wrote a very basic program in C++ which asked the user to input a number and then a string. To my surprise, when running the program it never stopped to ask for the string. It just skipped over it. After doing some reading on StackOverflow, I found out that I needed to add a line that said:
cin.ignore(256, '\n');
before the line that gets the string input. Adding that fixed the problem and made the program work. My question is why does C++ need this cin.ignore() line and how can I predict when I will need to use cin.ignore()?
Here is the program I wrote:
#include <iostream>
#include <string>
using namespace std;
int main()
{
double num;
string mystr;
cout << "Please enter a number: " << "\n";
cin >> num;
cout << "Your number is: " << num << "\n";
cin.ignore(256, '\n'); // Why do I need this line?
cout << "Please enter your name: \n";
getline (cin, mystr);
cout << "So your name is " << mystr << "?\n";
cout << "Have a nice day. \n";
}
ignore does exactly what the name implies.
It doesn't "throw away" something you don't need. Instead, it ignores the number of characters you specify when you call it, up to the char you specify as a delimiter.
It works with both input and output buffers.
Essentially, for std::cin statements you use ignore before you do a getline call, because when a user inputs something with std::cin, they hit enter and a '\n' char gets into the cin buffer. Then if you use getline, it gets the newline char instead of the string you want. So you do a std::cin.ignore(1000,'\n') and that should clear the buffer up to the string that you want. (The 1000 is put there to skip over a specific number of chars before the specified delimiter, in this case, the '\n' newline character.)
You're thinking about this the wrong way. You're thinking in logical steps each time cin or getline is used. Ex. First ask for a number, then ask for a name. That is the wrong way to think about cin. So you run into a race condition because you assume the stream is clear each time you ask for a input.
If you write your program purely for input you'll find the problem:
int main()
{
double num;
string mystr;
cin >> num;
getline(cin, mystr);
cout << "num=" << num << ",mystr=\'" << mystr << "\'" << endl;
}
In the above, you are thinking, "first get a number." So you type in 123 press enter, and your output will be num=123,mystr=''. Why is that? It's because in the stream you have 123\n and the 123 is parsed into the num variable while \n is still in the stream. Reading the doc for getline function by default it will look in the istream until a \n is encountered. In this example, since \n is in the stream, it looks like it "skipped" it but it worked properly.
For the above to work, you'll have to enter 123Hello World which will properly output num=123,mystr='Hello World'. That, or you put a cin.ignore between the cin and getline so that it'll break into logical steps that you expect.
This is why you need the ignore command. Because you are thinking of it in logical steps rather than in a stream form so you run into a race condition.
Take another code example that is commonly found in schools:
int main()
{
int age;
string firstName;
string lastName;
cout << "First name: ";
cin >> firstName;
cout << "Last name: ";
cin >> lastName;
cout << "Age: ";
cin >> age;
cout << "Hello " << firstName << " " << lastName << "! You are " << age << " years old!" << endl;
}
The above seems to be in logical steps. First ask for first name, last name, then age. So if you did John enter, then Doe enter, then 19 enter, the application works each logic step. If you think of it in "streams" you can simply enter John Doe 19 on the "First name:" question and it would work as well and appear to skip the remaining questions. For the above to work in logical steps, you would need to ignore the remaining stream for each logical break in questions.
Just remember to think of your program input as it is reading from a "stream" and not in logical steps. Each time you call cin it is being read from a stream. This creates a rather buggy application if the user enters the wrong input. For example, if you entered a character where a cin >> double is expected, the application will produce a seemingly bizarre output.
Short answer
Why? Because there is still whitespace (carriage returns, tabs, spaces, newline) left in the input stream.
When? When you are using some function which does not on their own ignores the leading whitespaces. Cin by default ignores and removes the leading whitespace but getline does not ignore the leading whitespace on its own.
Now a detailed answer.
Everything you input in the console is read from the standard stream stdin. When you enter something, let's say 256 in your case and press enter, the contents of the stream become 256\n. Now cin picks up 256 and removes it from the stream and \n still remaining in the stream.
Now next when you enter your name, let's say Raddicus, the new contents of the stream is \nRaddicus.
Now here comes the catch.
When you try to read a line using getline, if not provided any delimiter as the third argument, getline by default reads till the newline character and removes the newline character from the stream.
So on calling new line, getline reads and discards \n from the stream and resulting in an empty string read in mystr which appears like getline is skipped (but it's not) because there was already an newline in the stream, getline will not prompt for input as it has already read what it was supposed to read.
Now, how does cin.ignore help here?
According to the ignore documentation extract from cplusplus.com-
istream& ignore (streamsize n = 1, int delim = EOF);
Extracts characters from the input sequence and discards them, until
either n characters have been extracted, or one compares equal to
delim.
The function also stops extracting characters if the end-of-file is
reached. If this is reached prematurely (before either extracting n
characters or finding delim), the function sets the eofbit flag.
So, cin.ignore(256, '\n');, ignores first 256 characters or all the character untill it encounters delimeter (here \n in your case), whichever comes first (here \n is the first character, so it ignores until \n is encountered).
Just for your reference, If you don't exactly know how many characters to skip and your sole purpose is to clear the stream to prepare for reading a string using getline or cin you should use cin.ignore(numeric_limits<streamsize>::max(),'\n').
Quick explanation: It ignores the characters equal to maximum size of stream or until a '\n' is encountered, whichever case happens first.
When you want to throw away a specific number of characters from the input stream manually.
A very common use case is using this to safely ignore newline characters since cin will sometimes leave newline characters that you will have to go over to get to the next line of input.
Long story short it gives you flexibility when handling stream input.
Ignore function is used to skip(discard/throw away) characters in the input stream. Ignore file is associated with the file istream.
Consider the function below
ex: cin.ignore(120,'/n');
the particular function skips the next 120 input character or to skip the characters until a newline character is read.
As pointed right by many other users. It's because there may be whitespace or a newline character.
Consider the following code, it removes all the duplicate characters from a given string.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
cin.ignore(); //Notice that this cin.ignore() is really crucial for any extra whitespace or newline character
while(t--){
vector<int> v(256,0);
string s;
getline(cin,s);
string s2;
for(int i=0;i<s.size();i++){
if (v[s[i]]) continue;
else{
s2.push_back(s[i]);
v[s[i]]++;
}
}
cout<<s2<<endl;
}
return 0;
}
So, You get the point that it will ignore those unwanted inputs and will get the job done.
It is better to use scanf(" %[^\n]",str) in c++ than cin.ignore() after cin>> statement.To do that first you have to include < cstdio > header.
I am new to c++ and still trying to wrap my head around how input/output streams work.
I am currently trying to write a function to make sure the user enters an int, and tell them if the input is empty or not a valid int.
I am using getline and have tried using cin.clear and cin.ignore but i cannot seem to get this to work and have no idea where i am going wrong.
It works if I input a letter however if i just press enter with nothing input it doesn't say no input detected.
void testStuff()
{
string number;
ws(cin);//skips Whitespaces
if (getline(cin, number) && number.end() !=
find_if_not(number.begin(), number.end(), &isdigit))
{
if (number.empty())
{
cout << "No input detected" << endl;
testStuff();
}
cout << "Please input a Valid number" << endl;
testStuff();
}
}
Assuming your ws works as specified (skips whitespace in the input), by the time you call getline, something other than whitespace has to have been entered. Thus, when getline gets called, that non-whitespace character has to be waiting in the input buffer, and getline must return a non-empty sequence of characters (i.e., everything from that first non-whitespace character up to the next new-line).
For example, let's write our own ws that shows what character(s) it's skipping over:
void ws(std::istream &is) {
while (std::isspace(is.peek())) {
char ch;
is.get(ch);
std::cout << "Read: " << (int)ch << '\n';
}
}
Now, when we call testStuff() and just press enter, we get Read: 10 as our output--i.e., ws has read and skipped the new-line we entered.
So, to get to the call to getline, the user has to enter something other than whitespace, and a new-line is whitespace. So, but the time getline is called at all, we know there's some non-whitespace character waiting in the input buffer, so when getline is called, it must produce a non-empty result.
I have assumed that every of function(s) that i don't know implementation are written correctly. Then, I have such code (simplified):
#include <iostream>
#include <string>
using namespace std;
int main() {
string number;
if (getline(cin, number))
{
if (number.empty())
{
cout << "No input detected" << endl;
main();
}
cout << "Please input a Valid number" << endl;
main();
}
}
I don't know find_if_not(number.begin(), number.end(), &isdigit) implementation so I skipped it. I've put source code on Ideone.com, you can view it HERE. After passing "just enter", program behaves vaildly. This means, one of function implementations that you didn't show us is working incorrectly. To help you we need full source code (if not, just only needed parts). Also, you should skip "using namespace std;". I think, number.end() != find_if_not(number.begin(), number.end(), &isdigit)) is implemented incorrectly. You should think about what someone told you in comments - "If the string is empty the only thing find_if_not can return is number.end(). number.end() == number.end() and body is not entered."
I am trying to read in an essay from a file which I then need to change each beginning letter of a sentence to an upper case letter and then send the corrected essay back to a file called correct.txt. The essay is stored in essay.txt.
So far I am just working with understanding the conversions from files to string in order for me to proceed with the rest of the question. So far, I have a string variable which which holds the essay with the words separated by a single space. I noticed that when I was trying to work with the size of my new string, it was not giving me the correct answer and I cannot figure out why. If you have any suggestions on how I can get it to notice the correct amount of characters, I would really appreciate it.
One more question while you're here, I know that moving forward, in order to change the beginning letters of the sentence to upper case, I need to first find the periods. Once I have this position, I can use pos+2 (including the preceding whitespace after the period) for the character that needs to become upper case. Is this the correct way of going about this and do you have any other tips on how to go forward with this?
Here is my code so far:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main(){
//declaring variables and creating objects
ifstream inputFile;
ofstream outputFile;
char inputFileName[20], outFileName[20];
cout << "Enter name of the file you want to open: " << endl;
cin >> inputFileName;
inputFile.open(inputFileName);
if (inputFile.fail()) {
cout << "Input file opening failed.\n";
exit(1);
}
cout << "Enter name of the file you want to send the output to: " << endl;
cin >> outFileName;
outputFile.open(outFileName);
if (outputFile.fail()) {
cout << "Output file opening failed.\n";
exit(1);
}
//while the file is open, it sends the contents to the string variable "essay"
string essay;
inputFile >> essay;
while (!inputFile.eof()) {
cout << essay << " ";
inputFile >> essay;
}
//this is to check for the correct size of the string "essay" before moving on to the rest of the code
int size = essay.size();
cout << size << endl;
return 0;
}
Your understanding of how the input stream works is incorrect.
The core of your code is this loop:
string essay;
inputFile >> essay;
while (!inputFile.eof()) {
cout << essay << " ";
inputFile >> essay;
}
What this does is that it reads the first word into essay, then, as long as the eof marker is not set on the stream it echoes back the word just read, and then reads another word, overwriting the previous one.
Here's the correct code. Note that checking for eof in a loop condition is a bad idea, because it doesn't quite do what you want, and would also get you stuck in an infinite loop if the stream instead entered an error condition.
string word;
while (inputFile >> word) { // read a word and stop if this fails for any reason
essay += word;
essay += " ";
}
Though I'm not sure why you read the file word by word instead of all at once.
Also, I feel the need to repeat what M.M. said in a comment: your use of raw character arrays on input is unsafe and unnecessary. Just use string. You need to then write inputFile.open(inputFileName.c_str()) unless your standard library is new enough to have the string overloads of these functions, but that is fine. The other way of doing it is dangerous and a very bad habit to get into.
Try include cstring on top of string as well.
String is considered char array which is a more 'unique' way of storing data. You can try the code listed below.
int size = essay.length();
I wrote a very basic program in C++ which asked the user to input a number and then a string. To my surprise, when running the program it never stopped to ask for the string. It just skipped over it. After doing some reading on StackOverflow, I found out that I needed to add a line that said:
cin.ignore(256, '\n');
before the line that gets the string input. Adding that fixed the problem and made the program work. My question is why does C++ need this cin.ignore() line and how can I predict when I will need to use cin.ignore()?
Here is the program I wrote:
#include <iostream>
#include <string>
using namespace std;
int main()
{
double num;
string mystr;
cout << "Please enter a number: " << "\n";
cin >> num;
cout << "Your number is: " << num << "\n";
cin.ignore(256, '\n'); // Why do I need this line?
cout << "Please enter your name: \n";
getline (cin, mystr);
cout << "So your name is " << mystr << "?\n";
cout << "Have a nice day. \n";
}
ignore does exactly what the name implies.
It doesn't "throw away" something you don't need. Instead, it ignores the number of characters you specify when you call it, up to the char you specify as a delimiter.
It works with both input and output buffers.
Essentially, for std::cin statements you use ignore before you do a getline call, because when a user inputs something with std::cin, they hit enter and a '\n' char gets into the cin buffer. Then if you use getline, it gets the newline char instead of the string you want. So you do a std::cin.ignore(1000,'\n') and that should clear the buffer up to the string that you want. (The 1000 is put there to skip over a specific number of chars before the specified delimiter, in this case, the '\n' newline character.)
You're thinking about this the wrong way. You're thinking in logical steps each time cin or getline is used. Ex. First ask for a number, then ask for a name. That is the wrong way to think about cin. So you run into a race condition because you assume the stream is clear each time you ask for a input.
If you write your program purely for input you'll find the problem:
int main()
{
double num;
string mystr;
cin >> num;
getline(cin, mystr);
cout << "num=" << num << ",mystr=\'" << mystr << "\'" << endl;
}
In the above, you are thinking, "first get a number." So you type in 123 press enter, and your output will be num=123,mystr=''. Why is that? It's because in the stream you have 123\n and the 123 is parsed into the num variable while \n is still in the stream. Reading the doc for getline function by default it will look in the istream until a \n is encountered. In this example, since \n is in the stream, it looks like it "skipped" it but it worked properly.
For the above to work, you'll have to enter 123Hello World which will properly output num=123,mystr='Hello World'. That, or you put a cin.ignore between the cin and getline so that it'll break into logical steps that you expect.
This is why you need the ignore command. Because you are thinking of it in logical steps rather than in a stream form so you run into a race condition.
Take another code example that is commonly found in schools:
int main()
{
int age;
string firstName;
string lastName;
cout << "First name: ";
cin >> firstName;
cout << "Last name: ";
cin >> lastName;
cout << "Age: ";
cin >> age;
cout << "Hello " << firstName << " " << lastName << "! You are " << age << " years old!" << endl;
}
The above seems to be in logical steps. First ask for first name, last name, then age. So if you did John enter, then Doe enter, then 19 enter, the application works each logic step. If you think of it in "streams" you can simply enter John Doe 19 on the "First name:" question and it would work as well and appear to skip the remaining questions. For the above to work in logical steps, you would need to ignore the remaining stream for each logical break in questions.
Just remember to think of your program input as it is reading from a "stream" and not in logical steps. Each time you call cin it is being read from a stream. This creates a rather buggy application if the user enters the wrong input. For example, if you entered a character where a cin >> double is expected, the application will produce a seemingly bizarre output.
Short answer
Why? Because there is still whitespace (carriage returns, tabs, spaces, newline) left in the input stream.
When? When you are using some function which does not on their own ignores the leading whitespaces. Cin by default ignores and removes the leading whitespace but getline does not ignore the leading whitespace on its own.
Now a detailed answer.
Everything you input in the console is read from the standard stream stdin. When you enter something, let's say 256 in your case and press enter, the contents of the stream become 256\n. Now cin picks up 256 and removes it from the stream and \n still remaining in the stream.
Now next when you enter your name, let's say Raddicus, the new contents of the stream is \nRaddicus.
Now here comes the catch.
When you try to read a line using getline, if not provided any delimiter as the third argument, getline by default reads till the newline character and removes the newline character from the stream.
So on calling new line, getline reads and discards \n from the stream and resulting in an empty string read in mystr which appears like getline is skipped (but it's not) because there was already an newline in the stream, getline will not prompt for input as it has already read what it was supposed to read.
Now, how does cin.ignore help here?
According to the ignore documentation extract from cplusplus.com-
istream& ignore (streamsize n = 1, int delim = EOF);
Extracts characters from the input sequence and discards them, until
either n characters have been extracted, or one compares equal to
delim.
The function also stops extracting characters if the end-of-file is
reached. If this is reached prematurely (before either extracting n
characters or finding delim), the function sets the eofbit flag.
So, cin.ignore(256, '\n');, ignores first 256 characters or all the character untill it encounters delimeter (here \n in your case), whichever comes first (here \n is the first character, so it ignores until \n is encountered).
Just for your reference, If you don't exactly know how many characters to skip and your sole purpose is to clear the stream to prepare for reading a string using getline or cin you should use cin.ignore(numeric_limits<streamsize>::max(),'\n').
Quick explanation: It ignores the characters equal to maximum size of stream or until a '\n' is encountered, whichever case happens first.
When you want to throw away a specific number of characters from the input stream manually.
A very common use case is using this to safely ignore newline characters since cin will sometimes leave newline characters that you will have to go over to get to the next line of input.
Long story short it gives you flexibility when handling stream input.
Ignore function is used to skip(discard/throw away) characters in the input stream. Ignore file is associated with the file istream.
Consider the function below
ex: cin.ignore(120,'/n');
the particular function skips the next 120 input character or to skip the characters until a newline character is read.
As pointed right by many other users. It's because there may be whitespace or a newline character.
Consider the following code, it removes all the duplicate characters from a given string.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
cin.ignore(); //Notice that this cin.ignore() is really crucial for any extra whitespace or newline character
while(t--){
vector<int> v(256,0);
string s;
getline(cin,s);
string s2;
for(int i=0;i<s.size();i++){
if (v[s[i]]) continue;
else{
s2.push_back(s[i]);
v[s[i]]++;
}
}
cout<<s2<<endl;
}
return 0;
}
So, You get the point that it will ignore those unwanted inputs and will get the job done.
It is better to use scanf(" %[^\n]",str) in c++ than cin.ignore() after cin>> statement.To do that first you have to include < cstdio > header.
This question already has answers here:
Need help with getline() [duplicate]
(7 answers)
Closed 7 years ago.
This is probably a very simple problem but forgive me as I am new.
Here is my code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main ()
{
string name;
int i;
string mystr;
float price = 0;
cout << "Hello World!" << endl;
cout << "What is your name? ";
cin >> name;
cout << "Hello " << name << endl;
cout << "How old are you? ";
cin >> i;
cout << "Wow " << i << endl;
cout << "How much is that jacket? ";
getline (cin,mystr);
stringstream(mystr) >> price;
cout << price << endl;
system("pause");
return 0;
}
The problem is that when asked how much is that jacket? getline does not ask the user for input and just inputs the initial value of "0". Why is this?
You have to be careful when mixing operator>> with getline. The problem is, when you use operator>>, the user enters their data, then presses the enter key, which puts a newline character into the input buffer. Since operator>> is whitespace delimited, the newline character is not put into the variable, and it stays in the input buffer. Then, when you call getline, a newline character is the only thing it's looking for. Since that's the first thing in the buffer, it finds what it's looking for right away, and never needs to prompt the user.
Fix:
If you're going to call getline after you use operator>>, call ignore in between, or do something else to get rid of that newline character, perhaps a dummy call to getline.
Another option, and this is along the lines of what Martin was talking about, is to not use operator>> at all, and only use getline, then convert your strings to whatever datatype you need. This has a side effect of making your code more safe and robust. I would first write a function like this:
int getInt(std::istream & is)
{
std::string input;
std::getline(is,input);
// C++11 version
return stoi(input); // throws on failure
// C++98 version
/*
std::istringstream iss(input);
int i;
if (!(iss >> i)) {
// handle error somehow
}
return i;
*/
}
You can create a similar function for floats, doubles and other things. Then when you need in int, instead of this:
cin >> i;
You do this:
i = getInt(cin);
Its because you have a '\n' left lying on the input stream from a previous call.
cin >> i; // This reads the number but the '\n' you hit after the number
// is still on the input.
The easiest way to do interactive user input is to make sure each line is processed independently (as the user will hit enter after each prompt).
As a result always read a line, then process the line (until you get familiar with the streams).
std::string line;
std::getline(std::cin, line);
std::stringstream linestream(line);
// Now processes linestream.
std::string garbage;
lienstream >> i >> garbage; // You may want to check for garbage after the number.
if (!garbage.empty())
{
std::cout << "Error\n";
}
Ignore some characters until line feed is reached.
cin.ignore(256, '\n')
getline (cin,mystr);