Wolf_dawg
Wolf_dawg

Reputation: 57

Having difficulty obtaining double after using getline() in for loop

I am trying to create a program which obtains names and test scores and places them into separate vectors. I am using getline() so I can get both first and last names. However, whenever I use the below code every name after the first loses its first letter. So, if the input for names was John Smith, Jane Smith, Jacob Smith, etc. The program outputs John Smith, ane Smith, acob Smith,... I tried taking out the cin.ignore()'s but then the program runs through after the first entry. I also tried creating separate functions for obtaining the names and scores, but this did not work either. Any advice or help would be appreciated.

int main() {
string test_taker;
int num_of_students = 0;
cout << "How many students took the exam? ";
cin >> num_of_students;
int starting = 0;
vector <double> score_list_us(num_of_students);
vector <string> name_list_us(num_of_students);
vector<double> score_list_sorted(num_of_students);
vector<string> name_list_sorted(num_of_students);
for (int i =0; i < num_of_students; i++) {
    cout << "Student #" << i + 1 << " Name: ";
    cin.ignore();
    getline(cin, name_list_us[i]);
    cout << "Student #" << i + 1 << " Score: ";
    cin >> score_list_us[i];
    cin.ignore();
}...

Upvotes: 0

Views: 60

Answers (1)

user4581301
user4581301

Reputation: 33952

Problem: Missing character

See that cin.ignore(); right in front of getline(cin, name_list_us[i]);? Guess what it does.

On the first pass through the loop that cin.ignore(); eats the newline left by cin >> num_of_students; Every other time through the loop there is no newline to be eaten, so it eats part of your data.

Solution

Always put ignore()s, if you can't avoid them entirely, AFTER the operation that left the garbage you want gone. If you put ignore() before another operation, sooner or later you're going to hit that operation without garbage in the stream. In this case you hit it sooner.

Next, you want to ignore() everything up to and including the newline. Anything the user typed in after the input we want is garbage and should be discarded. Otherwise ignore() takes out a space character or something equally useless and leaves the newline for getline to trip over. I'll leave it to an old friend to explain what you need to do.

Specifically, use

cin.ignore(numeric_limits<streamsize>::max(), '\n');

So

int main() {
    string test_taker;
    int num_of_students = 0;
    cout << "How many students took the exam? ";

    cin >> num_of_students;
    // ignore after
    cin.ignore(numeric_limits<streamsize>::max(), '\n');


    int starting = 0;
    vector <double> score_list_us(num_of_students);
    vector <string> name_list_us(num_of_students);
    vector<double> score_list_sorted(num_of_students);
    vector<string> name_list_sorted(num_of_students);
    for (int i =0; i < num_of_students; i++) {
        cout << "Student #" << i + 1 << " Name: ";
        // not before
        getline(cin, name_list_us[i]);
        cout << "Student #" << i + 1 << " Score: ";
        cin >> score_list_us[i];
        // because this guy eats the newlines
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
    }

Upvotes: 1

Related Questions