I am working through Accelerated C++ and am on exercise 3-5. The question is:

Write a program that will keep track of grades for several students at once. The program could keep two vectors in sync: The first should hold the student's names, and the second the final grades that can be computed as input is read. For now, you should assume a fixed number of homework grades.

...so I made the following program:

#include <iostream>
#include <string>
#include <vector>

int main() {
    // Enter students first names, separated with a space and ending in Enter+Ctrl+D (end-of-file)
    std::cout << "Please enter the students names: ";
    std::string name;
    std::vector<std::string> students;
    while (std::cin >> name) {
        students.push_back(name);
    }
    // Enter the grads in batches of 5 e.g. for two students write 10 3 4 5 6 10 6 8 9 10 and ending in end-of-file
    std::cout << "Please enter the students grades: ";
    std::vector<int> grades;
    int grade;
    int count = 0;
    int total = 0;
    while (std::cin >> grade) {
        if (count <= 4) {
            total += grade;
            ++count;
        } else {        
            grades.push_back((total / 5));
            count = total = 0;
        }
    }

    for (std::vector<std::string>::size_type i = 0; i < students.size(); i++) {
        std::cout << students[i] << " scored " << grades[i] << std::endl;
    }
    return 0;
}

...except when I run it on OpenBSD I get a segmentation fault. When compiling the app with GCC I only get the recommendation:

/usr/lib/libstdc++.so.49.0: warning: strcpy() is almost always misused, please use strlcpy()

. I know from wikipedia that a segmentation fault is the program trying to access memory it shouldn't but I can't see where the seg(fault) lies.

I'd be grateful if a more experienced C++ programmer could point me in the right direction. Thanks in advance for any help/tips/pointers :)

Edited 6 Years Ago by jrw89: Comments in program

Realize that from your code, students and grades might not be the same size. You should instead do something like this:

for each students in the vector students:{
  get student grades.
}

Realize that from your code, students and grades might not be the same size. You should instead do something like this:

for each students in the vector students:{
  get student grades.
}

Thanks for the reply. I tried the following:

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::cout << "Please enter the students names: ";
    std::string name;
    std::vector<std::string> students;
    while (std::cin >> name) {
        students.push_back(name);
    }
    std::vector<int> grades;
    for (std::vector<std::string>::size_type i = 0; i < students.size(); i++) {
        int first, second, third, fourth, fifth;
        std::cout << "Please enter the 5 grades for " << students[i] << ": ";
        std::cin >> first, second, third, fourth, fifth;
        grades.push_back((first+second+third+fourth+fifth)/5);
        std::cout << std::endl;
    }

    for (std::vector<std::string>::size_type i = 0; i < students.size(); i++) {
        std::cout << students[i] << " scored " << grades[i] << std::endl;
    }
    return 0;
}

but I get output like:

# ./3-5.exe
Please enter the students names: James David John Simon (End-of-file: Enter+Ctrl+D on OpenBSD)
Please enter the 5 grades for James:
Please enter the 5 grades for David:
Please enter the 5 grades for John:
Please enter the 5 grades for Simon:
James scored 25553126
David scored 25553126
John scored 25553126
Simon scored 25553126

...which suggests it is reading the names right but is not asking for grade input correctly. I'm going to try a few different ways of asking for grades but in my n00bness I'm probably missing something.

Once your program has reached end of file, it is no longer possible to read any more input. So if you enter end of file after reading the last student's name, it is not possible to read the grades.

The intent of the exercise was for each student's name to be followed by a list of grades for that individual student. I think that if you reorganize your program to read input in that form, you may have an easier time of it.

Once your program has reached end of file, it is no longer possible to read any more input. So if you enter end of file after reading the last student's name, it is not possible to read the grades.

The intent of the exercise was for each student's name to be followed by a list of grades for that individual student. I think that if you reorganize your program to read input in that form, you may have an easier time of it.

Thanks for the pointers. I rewrote the program to

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> students;
    std::vector<double> grades;
    std::string name;
    double grade1, grade2, grade3, grade4, grade5;
    int count = 0;
    while (std::cin) {
        std::cout << "Please enter a students first name: ";
        std::cin >> name;
        students.push_back(name);
        std::cout << "Please enter the students five most recent grades: " << std::endl;
        std::cout << "First grade: ";
        std::cin >> grade1;
        std::cout << "Second grade: ";
        std::cin >> grade2; 
        std::cout << "Third grade: ";
        std::cin >> grade3; 
        std::cout << "Fourth grade: ";
        std::cin >> grade4; 
        std::cout << "Fifth grade: ";
        std::cin >> grade5; 
        grades.push_back((grade1+grade2+grade3+grade4+grade5)/5);
        std::cout << students[count] << "'s average grade is " << grades[count] << std::endl;
        ++count;
    }
}

and now get

# ./3-5.exe
Please enter a students first name: James
Please enter the students five most recent grades:
First grade: 1
Second grade: 2
Third grade: 3
Fourth grade: 4
Fifth grade: 5
James's average grade is 3
Please enter a students first name: Tom
Please enter the students five most recent grades:
First grade: 1
Second grade: 2
Third grade: 10
Fourth grade: 10
Fifth grade: 10
Tom's average grade is 6.6
Please enter a students first name: Gary
Please enter the students five most recent grades:
First grade: 4
Second grade: 205
Third grade: 2
Fourth grade: 15
Fifth grade: 5
Gary's average grade is 46.2

which is all good until I enter Ctrl+D (end-of-file) and get:

Please enter a students first name: (Ctrl+D) Please enter the students five most recent g                          rades:
First grade: Second grade: Third grade: Fourth grade: Fifth grade: Gary's averag                          e grade is 46.2

I'm curious as to why the while loop appears to execute again after std::cin became false due to end-of-file.

Do something like this :

while(std::cin){
  if(std::cin){
    getName();
    getGrades();
  }
  
}

Thanks for the reply. I altered the code to

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> students;
    std::vector<double> grades;
    std::string name;
    double grade1, grade2, grade3, grade4, grade5;
    int count = 0;
    while (std::cin) {
        if (std::cin) {
            // Get name and grades
            std::cout << "Please enter a students first name: ";
            std::cin >> name;
            students.push_back(name);
            std::cout << "Please enter the students five most recent grades: " << std::endl;
            std::cout << "First grade: ";
            std::cin >> grade1;
            std::cout << "Second grade: ";
            std::cin >> grade2; 
            std::cout << "Third grade: ";
            std::cin >> grade3; 
            std::cout << "Fourth grade: ";
            std::cin >> grade4; 
            std::cout << "Fifth grade: ";
            std::cin >> grade5; 
        }
        // Add to vector and print result
        grades.push_back((grade1+grade2+grade3+grade4+grade5)/5);
        std::cout << students[count] << "'s average grade is " << grades[count] << std::endl;
        ++count;
    }
    return 0;
}

and it still produces the same result of running through the code one last time after end-of-file. Working logically through it it appears (at least to my n00b mind) as though I've messed up with the positioning of the while and if. I'm going to try a few more ideas and will hopefully be able to post back with something that works. Thanks for the tips!

Thanks for the reply. I altered the code to

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> students;
    std::vector<double> grades;
    std::string name;
    double grade1, grade2, grade3, grade4, grade5;
    int count = 0;
    while (std::cin) {
        if (std::cin) {
            // Get name and grades
            std::cout << "Please enter a students first name: ";
            std::cin >> name;
            students.push_back(name);
            std::cout << "Please enter the students five most recent grades: " << std::endl;
            std::cout << "First grade: ";
            std::cin >> grade1;
            std::cout << "Second grade: ";
            std::cin >> grade2; 
            std::cout << "Third grade: ";
            std::cin >> grade3; 
            std::cout << "Fourth grade: ";
            std::cin >> grade4; 
            std::cout << "Fifth grade: ";
            std::cin >> grade5; 
        }
        // Add to vector and print result
        grades.push_back((grade1+grade2+grade3+grade4+grade5)/5);
        std::cout << students[count] << "'s average grade is " << grades[count] << std::endl;
        ++count;
    }
    return 0;
}

and it still produces the same result of running through the code one last time after end-of-file. Working logically through it it appears (at least to my n00b mind) as though I've messed up with the positioning of the while and if. I'm going to try a few more ideas and will hopefully be able to post back with something that works. Thanks for the tips!

Although encasing the whole request/input block in if(std::cin) didn't work, doing the following did:

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> students;
    std::vector<double> grades;
    std::string name;
    double grade1, grade2, grade3, grade4, grade5;
    int count = 0;
    while (std::cin) {
        // Get name and grades
        if (std::cin) std::cout << "Please enter a students first name: ";
        std::cin >> name;
        if (std::cin) std::cout << "First grade: ";
        std::cin >> grade1;
        if (std::cin) std::cout << "Second grade: ";
        std::cin >> grade2; 
        if (std::cin) std::cout << "Third grade: ";
        std::cin >> grade3; 
        if (std::cin) std::cout << "Fourth grade: ";
        std::cin >> grade4; 
        if (std::cin) std::cout << "Fifth grade: ";
        std::cin >> grade5; 
        
        // Add to vector and print result
        students.push_back(name);
        grades.push_back((grade1+grade2+grade3+grade4+grade5)/5);
        if (std::cin) std::cout << students[count] << "'s average grade is " << grades[count];
        std::cout << std::endl;
        ++count;
    }
    return 0;
}

result:

# ./3-5.exe
Please enter a students first name: James
First grade: 10
Second grade: 20
Third grade: 30
Fourth grade: 40
Fifth grade: 50
James's average grade is 30
Please enter a students first name: Tom
First grade: 5
Second grade: 10
Third grade: 15
Fourth grade: 20
Fifth grade: 30
Tom's average grade is 16
Please enter a students first name: Gary
First grade: 8
Second grade: 12
Third grade: 52
Fourth grade: 64
Fifth grade: 149
Gary's average grade is 57
Please enter a students first name: ^D (*nix end-of-file)
#

. Does anyone have any links/resources to elaborate on why only targeted if's work, or do you reckon I'll figure that out as I continue learning? Thanks once again to those who took the time to post :)

This question has already been answered. Start a new discussion instead.