getline() not working as intended [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Hi I am having an unknown issue with getline(). My program is supposed to cout a prompt and then getline() should read in the user input but for some reason every time I run it just couts the prompt and skips to the next prompt, not allowing for me to input anything. I'll post the code and hopefully you guys can offer some advice.
int main()
{
int students = 0;
students = getStudents(students);
int quizzes = 0;
quizzes = getQuizzes(quizzes);
string studentArray[50];
int* quizArray = new int[quizzes];
double* studentAverage = new double[students];
string studentName = "";
for(int i = 0; i < students; i++)
{
cout << "Enter the students name: ";
getline(cin, studentName);
studentArray[i] = studentName;
cout << studentName;
for(int j = 0; j < quizzes; j++)
{
cout << "Enter quiz " << j+1 << ":";
cin >> quizArray[j];
}
studentAverage[i] = calculateAvergage(quizArray,quizzes);
cout << studentArray[i];
cout << studentName;
}
cout << endl;
cout << "Student Quiz Average" << endl << endl;
cout << "---------------------------------" << endl << endl;
for(int i = 0; i < students; i++)
{
cout << studentArray[i];
cout << setw(10) << studentAverage[i] << endl << endl;
}
}
int getStudents(int students)
{
cout << "How many students? ";
cin >> students;
cout << endl;
if(students > 50)
{
cout << "Invalid number of students, enter a number less than 50: ";
cin >> students;
cout << endl;
}
return students;
}
int getQuizzes(int quizzes)
{
cout << "How many quizzes? ";
cin >> quizzes;
cout << endl;
if(quizzes > 10)
{
cout << "Invalid number of quizzes, enter a number less than 10: ";
cin >> quizzes;
cout << endl;
}
return quizzes;
}
double calculateAvergage(int quiz_array[],int num_quizzes)
{
double average = 0;
for(int i = 0; i < num_quizzes; i++)
{
average = quiz_array[i] + average;
}
average = (average/num_quizzes);
return average;
}

Reading single values from a stream like this
cin >> quizzes;
does not consume the trailing end of line character (or any other invalid characters that were left over after attempting to read quizzes), so the next call to getline will continue reading from the same line of input (usually you would expect the line to be empty after reading quizzes, so getline ends up reading nothing).
Your program should work if use the following after reading quizzes:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
or you can just simply read studentName in the same way as the other values
std::cin >> studentName;
As with all calls to operator>> this strips all leading whitespace including newlines.

Related

Why my array doesn't print different subjects name inputted by a user?

The objective is to take input of subjects and their marks from a user and finally display them as a report card. Everything works as expected except that the compiler prints the name of the last subject entered for each different subject name in the final report.
Here is the C++ code that I tried:
#include <iostream>
using namespace std;
int main() {
string fname, lname;
int subjects;
float totalMarks;
cout << "Enter your first name: ";
cin >> fname;
cout << "Enter your last name: ";
cin >> lname;
cout << "Enter total marks: ";
cin >> totalMarks;
cout << "Marks of how many subjects: ";
cin >> subjects;
float subjectMarks[subjects];
string subjectNames[subjects];
for (int i = 0; i < subjects; i++) {
for (int j = 0; j < subjects; j++) {
cout << "Enter name of subject: ";
cin >> subjectNames[j];
break; // I've used 'break' to exit the inner loop and go to outer loop for
// entering the marks obtained in the subject
};
cout << "Enter marks obtained in the subject: ";
cin >> subjectMarks[i];
};
cout << "Dear, " << fname << " " << lname << "! The subjects and their marks are shown below: \n";
cout << "RESULTS IN SUBJECTS\n\n";
for (int i = 0; i < subjects; i++) {
for (int j = 0; j < subjects; j++) {
cout << subjectNames[j] << "\t\t";
break;
}
cout << subjectMarks[i] << endl;
};
return 0;
}
What I expected?
As you can see in the screenshot, 'Chemistry' is printed twice with different marks. It should have printed first 'Physics' with marks '80' and then 'Chemistry' with marks '70' as inputted by the user. I doubt there is a problem with subjectNames[] array.
But this is what actually happened
enter image description here
I'm stuck on this problem for more than 3 hours. Please help!
The loop for reading and the loop for writing is wrong. You don't need nested loops. Just have one variable when reading and one when writing:
// reading
for (int i = 0; i < subjects; i++) {
std::cout << "Enter name of subject: ";
std::cin >> subjectNames[i];
std::cout << "Enter marks obtained in the subject: ";
std::cin >> subjectMarks[i];
};
// writing
std::cout << "Dear, " << fname << " " << lname
<< "! The subjects and their marks are shown below:\n"
"RESULTS IN SUBJECTS\n\n";
for (int i = 0; i < subjects; i++) {
std::cout << subjectNames[i] << "\t\t"
<< subjectMarks[i] << '\n';
}
Also note that your subjectMarks and subjectNames are Variable Length Arrays (VLAs) and those aren't supported in standard C++. Only some compilers supports them as an extension. I recommend that you use std::vectors instead:
#include <vector>
// ...
std::vector<float> subjectMarks(subjects);
std::vector<std::string> subjectNames(subjects);

Program doesn't execute for loop until the end

I'm writing a code to enter subjects' information where I put void function and array as an object. But not sure when I wanna loop it, it doesn't come until the end. Have a look at the code.
void calculateCGPA::getGPA() {
cout << "Enter the the name of the subject: ";
cin >> subjectName;
cout << "Enter the credit hour:";
cin >> credithour;
cout << "Enter the grade: ";
cin >> grade;
}
int main () {
for (year=1; year<=4; year++) {
for (sem=1; sem<=2; sem++) {
cout << "Enter total subject you take in Year " << year << " Semester " << sem <<": ";
cin >> totalSubjectSem;
calculateCGPA ob[totalSubjectSem];
for(int i = 1; i <= totalSubjectSem; i++) {
cout << "Subject " << i << ": \n";
ob[i].getGPA();
}
}
}
return 0;
}
Here's the error. You can see the compiler only shows until entering the subject name but credit hour and grade are omitted. What should I do?
Expected: It should everything in void function until 3 (since I put 3) and then start over again "Enter total subject you take in Year 1 sem 2" but it also omits that
Take note that in C++ 0 is the first element, and n-1 is the last element. By looping to n, you cause a buffer overflow, hence resulting an error.
A solution would be as follows
void calculateCGPA::getGPA() {
cout << "Enter the the name of the subject: ";
cin >> subjectName;
cout << "Enter the credit hour:";
cin >> credithour;
cout << "Enter the grade: ";
cin >> grade;
}
int main () {
for (year=0; year<4; year++) {
for (sem=0; sem<2; sem++) {
cout << "Enter total subject you take in Year " << year << " Semester " << sem <<": ";
cin >> totalSubjectSem;
calculateCGPA ob[totalSubjectSem];
for(int i = 0; i < totalSubjectSem; i++) {
cout << "Subject " << i << ": \n";
ob[i].getGPA();
}
}
}
}
calculateCGPA ob[totalSubjectSem];
It's GCC extension called Variable-length automatic arrays and not valid C++ (because totalSubjectSem is not const). Use std::vector<calculateCGPA> instead.
for(int i = 1; i <= totalSubjectSem; i++) {
Indices start from 0 and going to array_length - 1. On last iteration you reading out of array bounds and program is crashing.

c++ why is there still input buffer left?

After my first entry, my second entery name field fills up with the input buffer from the previous entry. Why? I am even using the getline but the problem still persists. Please help me with the problem. This is question from Jumping Into C++ book .
#include <iostream>
#include <string>
using namespace std;
struct Person
{
string name;
string address;
long long int PhoneNumber;
};
void displayEntries(Person p[])
{
int enteryNumber;
cout << "Enter the entry number of the person for details(enter 0 to display all entries): ";
cin >> enteryNumber;
if(enteryNumber == 0)
{
for(int i = 0; i < 10; i++)
{
cout << "Entery Number: " << i + 1;
cout << "Name: " << p[i].name << endl;
cout << "Address: " << p[i].address << endl;
cout << "Phone Number: " << p[i].PhoneNumber << endl;
}
}
do
{
cout << "Entery Number: " << enteryNumber;
cout << "Name: " << p[enteryNumber].name << endl;
cout << "Address: " << p[enteryNumber].address << endl;
cout << "Phone Number: " << p[enteryNumber].PhoneNumber << endl;
} while (enteryNumber != 0);
}
int main()
{
Person p[10];
for(int i = 0; i < 10; i++)
{
cout << "Enter the details of the person\n\n";
cout << "Name: ";
getline(cin, p[i].name);
cout << "Address: ";
getline(cin, p[i].address);
cout << "Phone Number: ";
cin >> p[i].PhoneNumber;
cout << endl;
}
displayEntries(p);
return 0;
}
You can see what is happening when you read the reference for getline:
When used immediately after whitespace-delimited input, e.g. after
int n;
std::cin >> n;
getline(cin, n); //if used here
getline consumes the endline character left on the input stream by operator>>, and returns immediately. A common solution is to ignore all leftover characters on the line of input with
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
before switching to line-oriented input.
cin >> p[i].PhoneNumber; only gets the number. That leaves the line ending still in the input buffer to be read the next time you try to read a line.

c++ how do you store a full string into a string array using getline?

After it gets the first string and first double the program doesn't get the other strings.
for (int i = 0; i< NUM_MOVIES; i++)
{
cout << "Enter the name of the movie: ";
getline(cin, names[i]);
cout << "How much did " << names[i] << " earn <in millions>: ";
cin >> earnings[i];
cout << endl;
}
The second time you call getline you are actually reading a newline character because cin >> does not discard newline characters after the value it has just read.
So you end up in this cycle of reading bad data. Try this:
getline(cin >> std::ws, names[i]);
The problem is that >> doesn't read past the end of line so the following std::getline() does that instead of grabbing your next input.
You can use std::ws (absorb whitespace chars):
for (int i = 0; i< NUM_MOVIES; i++)
{
cin >> std::ws; // clear previous line
cout << "Enter the name of the movie: ";
getline(cin, names[i]);
cout << "How much did " << names[i] << " earn <in millions>: ";
cin >> earnings[i];
cout << endl;
}
cin >> earnings[i];
This should correct as follows
getline(cin, earnings[i])
// Example program
#include <iostream>
#include <string>
using namespace std;
int main()
{
string names[10];
string earnings[10];
for (int i = 0; i< 10; i++)
{
cout << "Enter the name of the movie: ";
getline(cin, names[i]);
cout << "How much did " << names[i] << " earn <in millions>: ";
getline(cin, earnings[i]);
cout << endl;
}
cout<< names[0]<< names[1]<<"\n";
cout<<earnings[0] << earnings[1]<<"\n";
return 0;
}

Accepting input in relation to an array of structures

I am currently practicing C++ and I am doing this question from the textbook C++ Primer Plus, and I am stuck at this very last step. Basically I am to make an array out of a structure that contains info a car and the issue that I am having trouble with is recording the user's input.
My code:
#include <iostream>
#include <string>
struct car{
std::string make;
int year;
};
int main()
{
std::cout << "How many cars do you wish to catalog? ";
int lim;
std::cin >> lim;
car* info = new car[lim];
for(int i = 0; i<lim; i++)
{
std::cout << "Please enter the make: ";
getline(std::cin, info[i].make); // problem here..
std::cout << "Please enter the year made: ";
std::cin >> info[i].year; // problem here as well :(
}
std::cout << "here is your collection:\n";
while(int i = 0 < lim)
{
std::cout << info[i].make << " " << info[i].year << std::endl;
//std::cout << "here is your collection:\n"
i++;
}
return 0;
}
Can someone help explain why it isn't working?
Specifically, my issue is that it is not getting my input correctly, and my exe file seems to skip the input of the "make" question and jumps to the year..Then it crashes into oblivious..possibly a segmentation fault.
After you read numbers using
std::cin >> lim;
and
std::cin >> info[i].year;
a newline character is left on the stream, which is picked up by getline as valid input.
You need to add code to ignore the rest of the line.
std::cin >> lim;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
and
std::cin >> info[i].year;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
See documentation on istream::ignore.
Also, change
while(int i = 0 < lim)
{
std::cout << info[i].make << " " << info[i].year << std::endl;
//std::cout << "here is your collection:\n"
i++;
}
to
for(int i = 0; i < lim; ++i)
{
std::cout << info[i].make << " " << info[i].year << std::endl;
//std::cout << "here is your collection:\n"
}
#include <iostream>
#include <string>
struct car{
std::string make;
int year = 0;
};
int main()
{
int i = 0; //increment value
std::cout << "How many cars do you wish to catalog? ";
int lim;
std::cin >> lim;
car* info = new car[lim];
for(i; i < lim; i++)
{
std::cout << "Please enter the make: ";
std::cin >> info[i].make; // change to cin, just like the one for year
std::cout << "Please enter the year made: ";
std::cin >> info[i].year; // this was fine
}
std::cout << "here is your collection:\n";
i = 0; //resets the increment value
while(i < lim)
{
std::cout << info[i].make << " " << info[i].year << std::endl;
//std::cout << "here is your collection:\n"
i++;
}
return 0;
}
combining cin and getline is ... funky. cin never read the newline character from the first string, so your first getline call is going to pretty much just return a blank string. What I normally do when I have an issue like this is perform a throwaway getline() call after my cin.
combining getline and cin is not normally very friendly. Maybe you should switch to all getlines and do a little bit of string manipulation?