getline delimiter using stringstream - c++

It seems that it's not separating the word within the space.
Trying to separate the words in between, and stored it in first and second.
cin >> name; //input name
stringstream file (name);
getline(file,first, ' '); //seperate the name with the first name and last name using space
getline(file,second, ' ');

Replace
cin >> name;
with
getline(cin, name); //input name
cin >> reads only upto the first space. You would have realized this if you done a cout << name; to check what's getting read - this is the first step of debugging.

When you read the initial input with cin >> name; that only reads up to the first white space character.
You then try to break that into two pieces at white space, which it doesn't contain.
Easy way:
cin >> first >> second;
Alternatively, if you start with std::getline(cin, name); instead of cin >> name;, then the rest should work correctly.

Related

Taking multiple inputs with whitespaces using cin

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;

How do I get user inputs for a string and then an int?

I have a database class that is an array that will hold a number of objects.
The function will take a couple of inputs from the user which include both strings and ints
For example:
std::cout << "Enter first name: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(std::cin, first_name);
std::cout << "Enter last name: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(std::cin, last_name);
std::cout << "Enter age: ";
std::cin >> age;
When I run the code, after I hit enter after entering the last name, it just starts a new line and I have to enter another input before it asks for the age input.
I heard it was bad to mix getline and cin, and that it's better to use one or the other. What can I do to make this work and what would be good practice moving forward?
Edit: I added in the ignores when I initially searched for solutions because without them, the code wouldn't bother waiting for user input. The output would be "Enter first name: Enter last name: "
Edit2: RESOLVED. Problem was I had used "cin >>" earlier in my code for user to input an int variable and needed the first cin.ignore statement, but not the other. Did not include that part of the code because I didn't know that was affecting it. Still new to all this so thanks everyone for their help!
Your std::cin::ignore calls are not helping you. They are only needed after an input that does not extract the end-of-line character (>>).
std::string first_name;
std::string last_name;
int age;
std::cout << "Enter first name: ";
std::getline(std::cin, first_name); // end of line is removed
std::cout << "Enter last name: ";
std::getline(std::cin, last_name); // end of line is removed
std::cout << "Enter age: ";
std::cin >> age; // doesn't remove end of line
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // this does
// input can proceed as normal
You only need the std::cin::ignore call after std::cin >> age; because that doesn't remove the end of line character whereas the std::getline calls do.
According to the documentation of std::basic_istream::ignore(), this function behaves as an Unformatted Input Function which mean it is going to block and wait for user input if there is nothing to skip in the buffer.
In your case both of your ignore statments are not neccessary since std::getline() will not leave the new line character in the buffer. So what is actually happening is:
std::cout << "Enter first name: ";
/*your first input is skipped by the next ignore line because its going to block until
input is provided since there is nothing to skip in the buffer*/
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
/* the next getline waits for input, reads a line from the buffer and also removes the
new line character from the buffer*/
std::getline(std::cin, first_name);
std::cout << "Enter last name: ";
/*your second input is skipped by the next ignore line because its going to block until
input is provided since there is nothing to skip in the buffer*/
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
/* the next getline waits for input and this is why it seems you need to provide
another input before it ask you to enter the age*/
std::getline(std::cin, last_name);
You need to remove the ignore statments to make this work. You may also want to read When and why do I need to use cin.ignore() in C++
I recommend removing the ignore function calls:
std::string name;
std::cout << "Enter name: ";
std::getline(cin, name);
unsigned int age;
std::cout << "Enter age: ";
std::cin >> age;

Why doesn't getline(cin, var) after cin.ignore() read the first character of the string?

I'm creating a simple console application in C++ that gets string and char inputs from the user. To make things simple, I would like to use the string and char data types to pass input from cin to.
To get string inputs, I'm using the getline method:
string var;
cin.ignore(); //I used ignore() because it prevents skipping a line after using cin >> var
getline(cin, var);
To get char inputs, I'm using the cin >> var method:
char var;
cin >> var;
This works fine for the most part. However, when I enter a string using getline, it ignores the first character of my string.
Is it possible to use getline and cin >> without having to use ignore, or a method I can call to ensure that my first character isn't skipped?
This is a full sample of code where I use both getline and cin >>:
string firstName;
string lastName;
char gender = 'A';
cout << "First Name: ";
cin.ignore();
getline(cin, firstName);
cout << "Last Name: ";
cin.ignore();
getline(cin, lastName);
while(genderChar != 'M' && genderChar != 'F')
{
cout << "Gender (M/F): ";
cin >> genderChar;
genderChar = toupper(genderChar);
}
cin>>var;
only grabs the var from the buffer, it leaves the \n in the buffer,
which is then immediately grabbed up by the getline
So, following is just fine, (if I understood correctly your problem)
cin>>var;
cin.ignore(); //Skip trailing '\n'
getline(cin, var);
As per your edited post
You don't have to use cin.ignore(); for geline
This extracts characters from buffer and stores them into firstName or (lastName) until the delimitation character here -newline ('\n').
ignore() does not skip a line, it skips a character. Could you send example code and elaborate on the need for cin.ignore()?
std::cin.ignore() will ignore the first character of your input.
For your case, use std::cin.ignore() after std::cin and then getline() to ignore newline character as:
cin>>ch;
cin.ignore(); //to skip the newline character in the buffer
getline(cin,var);
You are using std::isstream::ignore() before std::getline(). std::cin.ignore() will extract the first character from the input sequence and discard that.
http://www.cplusplus.com/reference/istream/istream/ignore/
So basically, cin>>var leaves the '\n' character out of its buffer. So now when you call
getline it reads the '\n' character and stops. Therefore we use cin.ignore() to ignore the first character getline reads i.e '\n' when we use it after cin.
But getline doesn't leave '\n' character instead it stores everything in its buffer till it find '\n' character, then stores '\n' character as well and then stops.
So in your code when you are using cin.ignore() after a getline and again uses getline to take input, it ignores the first character of the string instead of '\n'.
That is why the first character is missing.
Hope this answers your question.

C++ what is wrong with this do while loop

I am trying to input a string. It's working fine when I input something like John.
But if I input something like John Smite I end up in an endless loop and a terminal crash.
string fullname;
do{
cout << "Please input the Full Name of the user: ";
cin >> fullname;
}while(fullname=="");
The space is throwing cin off. You should use getline.
You can try this one:
do{
cout << "Please input the Full Name of the user: ";
cin >> fullname;
}
while(fullname.length() == 0);
As to why you get an infinite loop - operator>> overload for std::string will first discard any leading whitespace and then read up to either next whitespace or the end of avaliable input.
When you enter "John Smite", first iteration reads "John", second iteration reads "Smite" and then there's no more input for subsequent iterations. The problem is that your implementation seems to clear fullname before it attempts a read. But because the stream is not in good state anymore, no more reads are possible and there's your infinite loop.
You could do something like this instead:
string temp;
string fullname;
do {
cin.clear(); // clear any error flags
do {
if (cin >> temp) fullname += temp + ' ';
} while (cin.good());
} while (fullname.empty());
This has a (good) side effect that it collapses multiple adjacent whitespace characters, but it's still pretty clunky.
Much better way would be to just say
do std::getline(std::cin, fullname); while (fullname.empty());

iostream - reading string with embedded blanks

I have a file with records that looks like this
123 Tag Now is the time for all good men to come to the aid
There always a number and some tag followed by a series of words. I want to extract the number as integer, tag as string, and sentence as string. I've done this using getline and scan plus some substring foolishness.
Is there any way to do this ala...
ispringstream iss ("123 Tag Now is the time for all good men to come to the");
integer i;
string tag, sentence;
iss >> i >> tag >> ws >> ???? >> sentence;
I.e. It would be nice if there were some way to turnoff white space as a terminator.
You should be able to do it in two steps:
istringstream iss ("123 Tag Now is the time for all good men to come to the");
int i;
std::string tag, sentence;
iss >> i >> tag >> ws;
std::getline(iss, sentence);
If there will be no line breaks,
iss >> i >> tag;
getline(iss, sentence);