Confusion about cin function at run-time - c++

int main()
{
cout<< "Please enter your first name (followed by 'enter'):\n";
string first_name; // first_name is a variable of type String
cin >> first_name; // read characters into first_name
cout<<"Hello, " <<first_name<<"!\n";
cout<<" first_name "<<" is "<< first_name <<"\n";
cout << "Please enter you first name and age\n";
string new_first_name = "unentered";
int age = -1;
cin >> new_first_name;
cin >> age;
cout << "Hello, " << new_first_name << "(age " << age << ") \n";
return 0;
}
I have the above bit of code that is basically an example from a book I've been working through.
Something rather funny happens when I compile and run that I didn't understand. On the first prompt, if I enter one name say 'Joe', then the rest of the program works fine. That is, I can enter a new name 'George" and age '23' at the second prompt and the output goes just fine.
If on the other hand, I enter two words separated by a comma in the first prompt, say 'Joe Person', then in the second prompt if I enter George 23, I get the output Person (age 0).
So it seems like it took the second name, used that in the second string prompt, and then did something with the age input. I'm surprised that it doesn't output the initialized value of -1.
Could anybody tell me what might be going on here? I would have thought that for the first prompt, the program would ignore whatever came after the first whitespace, but it appears as if it gets stored somehow and then get stored in the new_first_name variable.

The C++ stream extract operators, for strings, read tokens. That is anything up to the next peice of white-space.
Generally cpp-reference is a good reference for C/C++.

Use the getline function to take input in std::string datatype when the input can consist space.
So you can write: getline(cin,first_name);
And it will work fine.
If you use cin instead, it will just ignore the string input after first space occurred. For example, if you gave input 'Joe Person', cin will only store 'Joe' in the first_name Variable. It will also leave 'Person' as the next thing to be read.
You should use cin with std::string only when the input string does not contain space, if it consists space, then you should go for getline(), this function is implemented in std::string class for the same purpose.
Find the complete explanation here
It will work definitely.

Related

Getline always ignoring first word of input c++

I'm having trouble with this code. I want it to take 2 words and it's always ignoring the first word and then taking the 2nd word. If I put in 3 words, it works perfectly and picks up the final 2 words.
The prompt for this is these bullet points.
Prompt the user to enter his/her first and last name.
Read the name from the keyboard using the getline method and store it into a variable called fullName (you will need to declare any variables you use).
Print out the fullName.
Compile, debug, and run, using your name as test data.
Since we are adding on to the same program, each time we run the program we will get the output from the previous tasks before the output of the current task.
How do you make this work correctly?
string fullName;
cout << "What is your full name" << endl;
cin >> fullName;
getline(cin, fullName);
cout << fullName << endl;
cout << endl;
cin >> fullName;
reads the first word of the full name.
getline(cin, fullName);
reads the rest of the name over top of the first word. Computer programs do exactly what you tell them to do and show somewhat less than zero mercy if that's the wrong thing to do.
So given John Jacob Jingleheimer Schmidt
cin >> fullName; // reads John into fullname
getline(cin, fullName); // reads Jacob Jingleheimer Schmidt into fullname,
// replacing John
cout << fullName << endl; // prints Jacob Jingleheimer Schmidt
Solution
Remove the cin >> fullName;
getline(cin, fullName); // reads John Jacob Jingleheimer Schmidt into fullname,
cout << fullName << endl; // prints John Jacob Jingleheimer Schmidt

cin skipping variables after entering name

I get an error when I try to run this. It lets me input the employee's name, and then once I press Enter it skips to the end, flying by hours and pay rate without letting me input them.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
string EmployeeName; //Employee Name
float EmployeeHours;
float EmployeePayRate; //Emplyee Hours, Employee PayRate
cout << setw(50) << "Employee Name: ";
cin >> EmployeeName;
cout << setw(50) << "EmployeeHours: ";
cin >> EmployeeHours;
cout << setw(50) << "EmployeePayRate: ";
cin >> EmployeePayRate;
system("PAUSE");
return 0;
}
I think the comment by #AleksandarStojadinovic provides the clue to your problem. Use
std::getline(std::cin, EmployeeName);
to read the name. Rest can be as they are.
I am having an error when I try to run this. It lets me input the
employees name, and then once you press enter it skips to the end.
flies by hours and pay rate without letting me input that.
Your name must be comprised of two/three names, maybe first middle and last or something like that. cin deals space separated string and enter separated string in the same way i.e it will take each space separated string as different input. And for that if your name has two names, the first one goes right but the second one goes to a variable which is declared as float and the program terminates abnormally. That's why using cin in this case isn't right at all.
You need to use another way to avoid that, like using getline(cin,EmployeeName) .

reading variables in struct type in for loop

I'w writing piece of code and I should read variables from for loop:
#include <iostream>
using namespace std;
#define NumOfStudents 100
#define NumOfCourses 15
struct Student{
int stdnum, FieldCode, age;
double average, res[NumOfCourses];
char name[20]; //First and Last name length
};
int main(){
struct Student students[NumOfStudents];
int i;
cout << "\tNAME || STUDENT-NUMBER || FIELD-CODE || AGE";
for(i=0; i<NumOfStudents; i++){
cout << "\nSTUDENT #" << i+1 << ": ";
cin >> students[i].name[20] >> students[i].stdnum >> students[i].FieldCode >> students[i].age;
// cin >> students[i].name[20];
}
}
EDIT:
output is:
./st
NAME || STUDENT-NUMBER || FIELD-CODE || AGE
STUDENT #1: test
STUDENT #2:
STUDENT #3:
STUDENT #4:
.
.
.
STUDENT #100:
I can just enter name of first student and loop doesn't work correctly
what is the problem?
cin >> students[i].name[20];
It shouldn't be an array of 20. It means your entered first character is stored in index 20th location which is in-correct and can cause undefined behavior as name array is indexed from 0 to 19 only.
Rather it should be cin >> students[i].name, which writes into base address of array name
I think you have to write
cin >> students[i].name
Since it is a 1D array, subscript should not be used in getting input.
cin >> students[i].name[20]
This part is wrong. This command reads one character from standard input and stores it in the 20th position in name (i.e. in the byte right after the array name). You want to use:
cin >> students[i].name >> ...
In line "cin >> students[i].name[20]".
You can't use name[20] as input variable for a character string as it points to a character at index 20, which also do not exists in your case as char name[20] stores in indexes 0-19.
Correct format:
cin>>students[i].name;
To read string of characters or name as a string.
First of all, you need to use students[i].name without the index. Your syntax tries to insert the single character it reads from the terminal beyond the end of the char array and thus messing with the pointer (note that you should make sure that the input is truncated anyway).
Second, you should type all input parameters for each student, you cannot just insert their name. So input would be:
$ ./st
STUDENT #1: TestName 3456 1 15
If that's not intended behaviour, you might want to do multiple cin >> variable statemates.
Can you make it more clear. Is it that you are not able to enter the details after the first name is typed in? Or is it that the loop is exited before the entire operation is performed?
In you code, there's a problem, I guess
students[i].name[20]
here only one character is read. This should be replaced in cin with
students[i].name
Also if you are not able to enter the details after the first iteration, try to give fflush() or setbuf() to clear the input buffer.
Also if you have to read a string with spaces, try to use cin.getline() or gets(). The format for these are available in the net.
Thank you

Combining Two Strings into One Variable in C++

I am en process of writing a simple program that assigns given student names into groups of whatever interval requested. Currently, I am focusing on the function that reads the name of the students.
Here is the code:
class student
{
public:
string nameFirst;
string nameLast;
};
student typeName()
{
student foo;
cout << "Type in a student's first name: ";
cin >> foo.nameFirst;
cout << "Type in that student's last name: ";
cin >> foo.nameLast;
cout << "\n";
return foo;
}
Since I cannot use getline(), I am forced to create two strings, one for each section of the student's full name. How can I rewrite this code to allow for it to take the full name without creating two variables and without using getline()? Or, if such isn't possible, how can I use a method within the class to combine the two strings into one?
You can just use
cin >> foo.nameFirst >> foo.nameLast;
cin >> will parse stops at white spaces, so you can just input the full name in one line split by space like James Bond.
To combine two strings into one:
string fullName = foo.nameFirst + " " + foo.nameLast;

Usage of two gets() in C++

I am learning about classes in C++. I made a simple program using the concept of classes. In the program I need the person to enter the details of the book. Here is that function:
void Book::add(){
cout << "Enter name of Book: ";
gets(book_name);gets(book_name);
cout << "\n\nPlease enter the book id: ";
cin >> book_id;
cout << "\n\nThank you the book has been added.";
total++;
input = getchar();
getchar();
}
Notice in the third line I have to use two gets to get the user input. If I use one gets
this is the output. It just skips the gets statement. Similarly at other places also I have to use two getchar statements. I was able to find the answer for that on SO itself. Ex Why my prof. is using two getchar. I couldn't find the answer for two gets statements, though. Here is the complete code in case it is required.
That is because you have a trailing new line (from Enter) character remaining on the stream that is not read by the first read operation. So the first gets(book_name) will read that and continue to the next request for input.
use getline to remove any remaining offending input from the stream.
void Book::add(){
string garbage;
getline(cin,garbage); // this will read any remaining input in stream. That is from when you entered 'a' and pressed enter.
cout << "Enter name of Book: ";
gets(book_name);
getline(cin,garbage); // this will read any remaining input in stream.
cout << "\n\nPlease enter the book id: ";
cin >> book_id;
Anyways just use the safer way of reading input from streams
cin >> book_name;
instead of gets. Then you will not have such problems.
if you want to read space separated inputs in to one string the use std::getline (like I did for garbage above)
std::getline(cin,book_name);
cin and cout are from <iostream> and gets comes from <cstdio>. It's not good idea to mix those two if you don't exactly know how those two work and what is the difference.
Better idea is to use cin.getline()
cin.getline(char* s, streamsize n );
The second parameter is the maximum length of the input.