I have declared a string array of [15]. Actually to store names. I execute it fine, but when I enter the complete name (including space; First name+[space]+last name) the program misbehaves. I cannot find the fault
I have declared multiple string arrays in the program, when I input the name with space it doesn't executes fine. I am using cin>> function to input in the array. like
string name[15];
int count=0; cout << "enter your name" << endl;
cin >> name[count];
I am using cin>> function to input in the array.
That is the problem. operator>> is meant for reading formatted input, so it stops reading when it encounters whitespace between tokens. But you want unformatted input instead. To read a string with spaces in it, use std::getline() instead:
string name[15];
int count=0;
cout << "enter your name" << endl;
getline(cin, name[count]);
Online Demo
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 have a simple structure which stores details of a person whose values needs to be initialized through user input. The structure is as follows :
typedef struct {
char name[20];
int age;
char address[50];
char vehicle[10];
}Runner;
I am using cin to store the value of each Runner but wish to take the inputs (that may contain whitespace in between) using enter key after each value entered.
Below is the code :
Runner run1;
cout << "Enter name age address vehicle (pressing enter at each instance)" << endl;
cin >> run1.name >> run1.age >> run1.address >> run1.vehicle ;
It is quite evident that space separated values would be considered as two unique entries.
How do I skip the white-spaces and cin only after enter is pressed. Also if there is another approach to such situations, it would be great to know the same.
As the input may have whitespaces between them, you should use getline function.
cin.getline(run1.name,20);
cin.getline(run1.address,50);
cin.getline(run1.vehicle,10);
cin >> age
But if you want to take the value of age after taking the value of name, then you'll have to do something like this.
cin.getline(run1.name,20);
cin >> run1.age;
cin.getline(dummy,5); //cin leaves a newline at the buffer. This line of code takes the newline from the buffer.
cin.getline(run1.address,50);
cin.getline(run1.vehicle,10);
cin.getline (name,20);
cin.getline (address,50);
cin.getline (vehicle,10);
cin >> age;
I have written a program in which certain entries are made into a map. Later, using an iterator, I wanted to see the key-value pairs in this format
key=value.
But the output is coming as
=key value.
Here's the code
int main() {
map<string,string> mp;
int n;
string name, number;
cin>>n;
for(int i=0; i<n; ++i)
{
getline(cin,name);
getline(cin,number);
mp.insert(pair<string,string>(name,number));
}
string line;
map<string,string>::iterator fndr;
fndr = mp.begin();
cout << (*fndr).first << "=" << (*fndr).second;
return 0;
}
Here's the input
2
abhay 239487
hello 23478
Here's the output
=abhay 239487
Your .first is empty and the whole thing is going in .second. getline() is taking the whole string input and storing it in number variable. Quick solution (but won't work for names that contain spaces):
cin >> name;
cin >> number;
Explanation:
Before using getline(), you have used cin >> n to input the number of strings. After the input, when you press Enter a \n is appended at the end of your input. So your input actually looks like this:
2\n
abhay 239487\n
hello 23478\n
Now cin >> n uses 2 in the first line to store it in n variable but the \n is still there in the stream. When getline() is used for the next input, it finds the \n in the input stream and terminates thus storing nothing in name variable (\n is a delimiter for getline()). The next getline() finds the string abhay 239487 before it encounters another \n and terminates.
Thus, we need to ignore the \n after 2 before the first execution of getline()). We can use cin.ignore() between the last cin and the first getline(). This will ignore the next character in the input stream.
Code
int main() {
map<string,string> mp;
int n;
string name, number;
cin>>n;
cin.ignore();
for(int i=0; i<n; ++i) {
getline(cin,name);
getline(cin,number);
mp.insert(pair<string,string>(name,number));
}
string line;
map<string,string>::iterator fndr;
fndr = mp.begin();
cout << (*fndr).first << "=" << (*fndr).second;
return 0;
}
You can notice after using cin.ignore(), abhay 239487 goes in name and hello 23478 goes in number. The output is:
abhay 239487=hello 23478
which is expected for this case.
How to workaround the problem of segregating key: value pair ? There are two ways:
Either you can input the name (key) and the corresponding number (value) in two different lines (This method will work for strings which contains spaces in name) like this:
2
abhay nayar
239487
hello
23478
Or, you can use cin >> name >> number to get those values (but you cannot use names that contain spaces because any whitespace character is a delimiter for cin).
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'm an just trying to fill an array with strings using a loop. My problem is that when it enters the loop to input names it will instantaneously input a blank line for the first slot in the vector. Why does this happen? And how can I fix it. Please don't mind my lack of code style, I'm a noob trying to regain my knowledge of programming before I start in a class this winter...
Here's some sample output:
How many people are in your family?
4
Please enter the names of all of your family members
check name:
Please enter the names of all of your family members
Matt
check name:Matt
Please enter the names of all of your family members
Evan
check name:Evan
Please enter the names of all of your family members
Michelle
check name:Michelle
Matt
Evan
Michelle
and this is my code:
vector<string> Names;
bool complete=0;
while(!complete)
{
int number;
cout << "How many people are in your family?" << endl;
cin >> number;
for(int i=0; i<number; i++)
{
string names;
cin.clear();
cout << "Please enter the names of all of your family members" << endl;
getline(cin,names);
Names.push_back(names);
cout << "check name:" << names << endl;
}
complete = 1;
}
for (int i=0; i< Names.size(); i++)
{
cout << Names[i] << endl;
}
The reason you see this behavior is mixing the >> reads with getline. When you read the count, the input pointer is advanced to the end of the numeric input, i.e. 4, and stops right before the new line character is read.
This is when you call getline; the new line character is read, and the new line is returned right away.
To fix this problem, add a call to getline right after the cin >> number call, and discard the result.
May I suggest you try
std::cin >> names;
instead of
getline(std::cin, names);
getline takes in std::endl or the \n from your std::cout print string. The idea is that getline will read until the \n character (which is an indication of an endline), but it will also consume the endline character. This is why it is consuming the newline character into your vector.
Consider doing this . . .
std::cin.get();
which will read std::endl character and then use the getline function.
The problem is mixing fonatted input (std::cin >> number) with unformatted input (std::getline(std::cin, names)). The formatted input stops at first non-integer character, most likely the newline you entered after the count. The easiest fix is to skip leading whitespace explicitly:
std::getline(std::cin >> std::ws, names);
Note, that you also need to check after each input that it was successful:
if (std::cin >> number) {
// do something after a successful read
}