Ignoring the input character - c++

So, I want to use the cin.ignore(200,'\n') to input a line and save it into a string without saving the \n as the string. But when I do:
cin.ignore(200,'\n');
getline(cin,name);
It asks me to input something twice, but I just want to ask me once and save it into name.
I've read something about the cin.clear(), but I think it's not what I need, or perhaps, I missunderstood what that clear does.
Thanks!

cin.ignore(n, ch) discards characters from the stream associated with std::cin until either n characters have been skipped, or until ch is seen. The cin.ignore(200, '\n'); is discarding the first input, up to the newline character. You're then getting a line, which will accept your second input.
You may need to use the cin.ignore(n, ch); construct if you want to read a line immediately after you perform a whitespace-delimited input operation, like
int i = 0;
std::cin >> i; // reads an integer, possibly leaving a '\n' in the stream
std::cin.ignore(200, '\n'); // reads and discards until a newline is seen
std::string name;
std::getline(std::cin, name); // reads a full line
In your case, if you haven't done any whitespace-delimited input, the cin.ignore is skipping over the first attempt to provide your line input. You should simply use std::getline immediately. The newline character at the end of the line is not appended to the string, but it is removed from the input stream.
The documentation for std::getline explains this in the "Notes" section.
For a more robust line input function, where you cannot be sure whether the previous input operation left a newline character (or whatever delimiter you're using) on the stream, you can do something like:
char ch;
std::cin.peek(ch);
if (ch == '\n') {
std::cin.ignore(1, '\n'); // or std::cin.get(ch);
}
std::string line;
std::getline(std::cin, line);
The peek member function will return the next character to be read, without removing it from the stream. If it's a newline, you can go ahead and ignore it. Otherwise, the getline call will read the entire line, including the character you just peeked at.
Alternatively, if you only want to consume whitespace, you can use the std::ws manipulator.

You don't need to use ignore() in this case. getline() will not put the new line character to the string.
The reason its asking you for an input twice is because the ignore() function is removing until your first 200 input characters or up to the newline(your deliminator) so the next getline() probably will not have anything to read thus asking you for input(unless of course your first input contains more than 200 characters,in that case it will read the remaining characters in the buffer).
std::getline() will not add the delimiter character to the string that is read, which is the newline character by default.

Related

cin is not accepting input with space in them in C++?

#include <iostream>
using namespace std;
int main(){
string doi, name, address, phone;
cout<<"Please provide these credentials:\n";
cout<<"1.Date of issue\n";
cin>>doi;
cout<<"2.Name\n";
cin>>name;
cout<<"3.Address\n";
cin>>address;
cout<<"4.Phone Number\n\n";
cin>>phone;
return 0;
}
When I am giving name input with spaces, for eg ("John Doe"), instead of storing this value is name it split value by space and store "John" in name and "Doe" in address.
If you have spaces in the string you want to read, you could use std::getline like this:
std::getline(std::cin, name);
instead of the line:
std::cin >> name;
Note that the getline will read all characters up to a newline character.
Also, please avoid using namespace std;.
You should use getline() in place of cin when you need to input strings with spaces.
In your case the syntax will be
string name;
getline(cin,name);
for more info on getline https://www.geeksforgeeks.org/getline-string-c/
There's a lot of muddled terminology in the comments and the answers. std::cin is an object; it doesn't do anything on its own.
Functions that read from input streams fit into one of two categories: they do formatted input or unformatted input. Formatted input functions translate the text that they get from the input stream (here, std::cin) into the data type that they're trying to read:
int i;
std::cin >> i; // operator>> reads text and translates it into an integer value
Formatted input functions begin by skipping whitespace, then they read characters and translate them; when the function encounters a character that isn't valid for the type that they're reading, or when they see whitespace, they stop. So in the example above, if you typed " 32 ", the stream extractor would skip the leading space, read the 3 and the 2, see the following space, and stop reading. The value stored into i would be 32.
std::string data;
std::cin >> data;
Here, if you type "Hello, world", the stream extractor (operator>>) will read up to the space, and store "Hello," in data.
If you want to read whitespace as well as non-whitespace you need an unformatted input function:
std::string data;
std::getline(std::cin, data);
Here, the call to getline reads text from std::cin up to the first newline character or to the end of the input stream. So if you typed " 32 " for this code, data would hold the text " 32 ". If you typed "Hello, world", data would hold the text "Hello, world".
And note that if you mix formatted input functions with unformatted input functions you have to be careful about leftover whitespace:
int i;
std::string data;
std::cin >> i;
std::getline(std::cin, data);
If you typed "32 Hello, world" on a single line, i would get the 32, and data would get " Hello, world".
On the other hand, if you type two lines of input, the first with "32" and the second with "Hello, world", you'll get 32 in i, but data will be empty. That's because the stream extractor read the 3 and the 2, then saw a newline character, and stopped, leaving the newline in the input buffer. std::getline then read that newline character and it, too, stopped. But it read the entire line: it swallowed the newline character.
So when your code switches from formatted input to unformatted you have to deal with whitespace characters remaining in the input buffer. If you want to read them, fine; but if you don't, you need to remove them:
int i;
std::string data;
std::cin >> i;
std::getline(std::cin, data); // read the rest of the line
std::getline(std::cin, data); // read the next line of text
A better approach is to do that cleanup with something like std::cin.ignore(42, '\n');. std::ignore is an unformatted input function; in this call it reads up to 42 characters, looking for a newline character. It stops reading when it has read 42 characters, sees a newline character, or hits the end of the input. That's better than using std::getline(std::cin, data) because it doesn't store the text into data, which could require a bunch of resizing if there's a lot of text in the remainder of the line. The more usual form for that call is to pass std::numeric_limits<int>::max() as the size argument; that's a special case, and it puts no limit on the number of characters to be read. So std::cin.ignore(std::numeric_limits<int>::max(), '\n'); will read characters until it finds a newline or hits the end of the input.
int i;
std::string data;
std::cin >> i;
std::cin.ignore(std::numeric_limits<int>::max(), '\n'); // flush the rest of the line
std::getline(std::cin, data); // read the next line of text

why does this C++ program works for the first line of input but not second or third?

I want to write a program which prints Real Fancy if the given string contains "NOT" or "not" and regularly fancy if it doesn't contain not.
Ex: "this is not a string"
o/p: Real Fancy
"this is nothing"
o/p: regularly fancy
The problem is it prints Real Fancy if my first testcase input is "not is this line". But if the same line is given as input in second or above testcase it is not working and printing regularly fancy.Why? Any help?
Here is the code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;//No.of test cases
cin>>t;
while(t--)
{
string quote;//the input from user
string found="not";//word to be found
string temp="";
int not_found=0;
cin.ignore();
getline(cin,quote);
//Splitting the given line into words and store in a vector
vector<string> words;
istringstream iss(quote);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter(words));
//Scan for "not" and if found break from for loop
for(int i=0;i<words.size();i++)
{
temp=words[i];
transform(temp.begin(),temp.end(),temp.begin(),::tolower);
if(temp==found)
{
cout<<"Real Fancy"<<endl;
not_found=1;
break;
}
}
if(not_found==0)
cout<<"regularly fancy"<<endl;
}
return 0;
}
The input pattern looks like
t
quote
quote
quote
...
The reading of t
cin>>t;
stops as soon as it finds an input that cannot possibly be an integer. This includes the newline character representing the end of the line, leaving the newline character in the stream to be consumed later (see Why does std::getline() skip input after a formatted extraction? for more on that problem). The skipping problem has been resolved with a
cin.ignore();
getline(cin,quote);
in the while loop, but that traded one bug for another. If there was no preceding formatted input to leave unwanted characters in the stream, cin.ignore(); will be throwing out the legitimate first character of the input.
This will happen on the second and subsequent reads. The input will wind up looking like
t //newline consumed by ignore
quote //newline consumed by getline. ignore consumes first character of next line
uote //newline consumed by getline. ignore consumes first character of next line
uote //newline consumed by getline. ignore consumes first character of next line
..
Solution:
Move it to after the input that leaves the unwanted character in the stream
cin>>t;
cin.ignore();
A better alternative is to the ignore so that you can make certain you get rid of all potential garbage on the end of the line
cin>>t;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
This will read from the stream up to the maximum possible length of the stream or a newline is found and discarded, whichever comes first.
Always clean up after an operation rather than before the next. It keeps the related code closer together, aiding in readability, and protects you from cases where there is nothing from before to clean up.

What cin.ignore() does exactly?

I've been told by my professor that every time I use cin, I should always follow it with cin.ignore(100, '\n'). But, I never understood why?
Here is an example:
const int MAX = 200;
char input[MAX];
cout << "Enter something: ";
cin.get(input, MAX);
cin.ignore(100, '\n'); //why necessary?!!
You don't need to use ignore every time, but it is good to use after formatted input, or in cases like yours where you only read a specified amount.
In your example, if I were to type in over 200 characters, any future input might be in for a rough surprise.
char input[200];
std::cin.get(input, 200);
After this executes, the first 200 characters were extracted, but anything after that is still left lying in the stream. It also leaves the newline ('\n') character in it. Anytime you want to extract input after this, it'll read in the remaining characters from our previous input.
This happens with formatted input, too. Take this example:
int age;
std::string name;
std::cin >> age;
std::getline(std::cin, name);
What you want is to type in an age, like 32, and a name, like "Bob". What happens is you input the age, and the program skips reading the name. When std::cin uses >> to read into variables, it leaves the '\n' character that was put into the stream by hitting enter. Then, getline reads in that newline character and stops, because it hit a newline and thinks it is done.
ignore solves this problem by discarding everything up to and including the next newline character, so that the extra input doesn't mess with future reads.
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
cin.ignore(100, '\n');
It ignores the first 100 characters, but if the function encounters '\n' before ignoring 100 characters, the function will stop discarding characters. So I assume that your professor wants you to ignore the rest of the data on the line unless it's longer than 100 characters.

Cin from stdin when it his the end of a line

I have a file for example
M
4
2
//comments
.#..
It is given to the program via stdin. I can't use fstream, just iostream.
If I want to read the whole thing character by character could I do?
char first_letter, first_num, second_num;
cin >> first_letter;
cin >> first_num;
cin >> second_num;
Or would the end of the line mess up cin? As in, does cin know after it reads M for first_letter, that it needs to go to the end line?
Secondly I dont want to read the comment lines. My plan is that if I see a / I will use getline to "trash" the line then move to the . # . . and store those in my array. Would that be the best way to do that?
Firstly, streams skip whitespace (space, tabs, newlines) by default, so that part is easy.
Now, concerning the comment lines, this is a bit more complicated. You can use std::getline() to read one line. This will store the line in a string and discard the trailing newline. However, if you e.g. read the first letter in your code above, the newline remains in the stream, so getline() will read an empty string. In short, don't mix line-based and token-based input.
In practice, you read a line and either parse the it manually or you create a stream for that:
while(getline(in, line)) {
if(line.empty()) continue; // empty line
if(line[0] == '#') continue; // comment line
// parse line
std::stringstream s(line);
char c;
s >> c;
}

getline() does not work if used after some inputs [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Need help with getline()
getline() is not working, if I use it after some inputs, i.e.
#include<iostream>
using namespace std;
main()
{
string date,time;
char journal[23];
cout<<"Date:\t";
cin>>date;
cout<<"Time:\t";
cin>>time;
cout<<"Journal Entry:\t";
cin.getline(journal,23);
cout<<endl;
system("pause");
}
where as if I use getline() on top of inputs, it does work i.e.
cout<<"Journal Entry:\t";
cin.getline(journal,23);
cout<<"Date:\t";
cin>>date;
cout<<"Time:\t";
cin>>time;
What might be the reason?
Characters are extracted until either (n - 1) characters have been
extracted or the delimiting character is found (which is delimiter if this
parameter is specified, or '\n' otherwise). The extraction also stops
if the end of the file is reached in the input sequence or if an error
occurs during the input operation.
When cin.getline() reads from the input, there is a newline character left in the input stream, so it doesn't read your c-string. Use cin.ignore() before calling getline().
cout<<"Journal Entry:\t";
cin.ignore();
cin.getline(journal,23);
Adding to what #DavidHammen said:
The extraction operations leave the trailing '\n' character in the stream. On the other hand, istream::getline() discards it. So when you call getline after an extraction operator, '\n' is the first character it encounters and it stops reading right there.
Put this after before getline call extraction:
cin.ignore()
A more robust way of taking input would be something like this:
while (true) {
cout<<"Time:\t";
if (cin>>time) {
cin.ignore(); // discard the trailing '\n'
break;
} else {
// ignore everything or to the first '\n', whichever comes first
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.clear(); // clear the error flags
cout << "Invalid input, try again.\n";
}
}
You're not checking stream status. The std::cin stream extraction operator (operator>>) can fail. When it does, the stream is marked as "bad" (failbit, badbit, or eofbit are set). Once "bad", all subsequent stream extractions on that stream will fail unless you clear the status.
Learn to be a paranoid programmer. Always check status of those formatted input operations. You could, for example throw an exception, or print an error message and exit. The one thing you shouldn't do is to simply assume that it worked.