Please Help: std::length_error

Working on a project for class using separate compilation. I have a Student class and a Roster class that holds an array of Students. When I try compiling a test program to drive the classes it works fine but when I run the executable I get the following output:

Roster:
terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_S_create
Aborted (core dumped)

everything prior to that works fine, so the problem is clearly something to do with the student objects, but I cannot for the life of me find anything wrong with my code. I think it's only necessary to show implementation files so here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// student.cpp
#include "student.h"
// include the interface header file

Student::Student(string last, string first, string dob,
                        string mat, int cred, double grade)
                                : lastname(last), firstname(first), birthdate(dob),
                matdate(mat), credits(cred), gpa(grade)
{
    if(cred < 30) {
        standing = "Freshman";
    } else if(cred < 60) {
        standing = "Sophomore";
    } else if(cred < 90) {
        standing = "Junior";
    } else {
        standing = "Senior";
    }
    // standing is set according to the amount of credits
    // the student has.  requisite values for these standings
    // are according to the definitions listed
    // at http://irr.gmu.edu/definitions.cfm
}

Student::Student() : lastname("Doe"), firstname("John"), standing("Freshman"),
        birthdate("1/1/1990"), matdate("1/1/2008"), credits(0), gpa(4.0)
{/* intentionally empty body */}
        // default constructor initializes preset values for variables
        // of the Student object

string Student::getLast() const {return lastname;}
string Student::getFirst() const {return firstname;}
string Student::getStanding() const {return standing;}
string Student::getDOB() const {return birthdate;}
string Student::getMatDate() const {return matdate;}
int Student::getCredits() const {return credits;}
double Student::getGPA() const {return gpa;}


void Student::input() {
        string last, first, stand, dob, mat;
        int credits;
        double grade;

        cout << "Last name: ";
        cin >> last;
        cout << "First name: ";
        cin >> first;
        cout << "DOB: ";
        cin >> dob;
        cout << "Matriculation Date: ";
        cin >> mat;
        cout << "Credits: ";
        cin >> credits;
        cout << "GPA: ";
        cin >> grade;

        setLast(last);
        setFirst(first);
        setDOB(dob);
        setMatDate(mat);
        setCredits(credits);
        setGPA(grade);

    // all mutator functions are used by input()

        return;
}   // input function accepts all vars from the user except standing

void Student::output() const {
        cout << "Last name: " << getLast() << endl;
        cout << "First name: " << getFirst() << endl;
        cout << "Standing: " << getStanding() << endl;
        cout << "DOB: " << getDOB() << endl;
        cout << "Matriculation Date: " << getMatDate() << endl;
        cout << "Credits: " << getCredits() << endl;
        cout << "GPA: " << getGPA() << endl;
        return;
}   // output function prints all vars


void Student::setLast(string name) {
        lastname = name;
}

void Student::setFirst(string name) {
        firstname = name;
}

void Student::setDOB(string date) {
        birthdate = date;
}

void Student::setMatDate(string date) {
        matdate = date;
}

void Student::setCredits(int cred) {
        credits = cred;
    if(cred < 30) {
        standing = "Freshman";
    } else if(cred < 60) {
        standing = "Sophomore";
    } else if(cred < 90) {
        standing = "Junior";
    } else {
        standing = "Senior";
    }
}

void Student::setGPA(double grade) {
        gpa = grade;
}

bool operator ==(Student& s1, Student& s2) {
    return (s1.firstname == s2.firstname && s1.lastname == s2.lastname);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// roster.cpp
#include "student.h"
#include "roster.h"
#include <iostream>
using namespace std;

Roster::Roster(string name, string code, string prof, int cred) :
    coursename(name), coursecode(code), instructor(prof), credits(cred)
{
    lastindex = -1;
    // assign -1 to last index so that the first index filled will be 0

    Student s1;

    for (int i = 0; i < 10; i++) {
        list[i] = s1;
    }
}

Roster::Roster() :
        coursename("C++"), coursecode("CS211"), instructor("Alayev/Yang"), credits(3)
{
        lastindex = -1;
    Student s1;
    for (int i = 0; i < 10; i++) {
        list[i] = s1;
    }
}

void Roster::addStudent(Student& stud) {
    list[lastindex + 1] = stud;
    lastindex++;
}

void Roster::delStudent(Student& stud) {
    for (int i = 0; i < lastindex; i++) {
        if (list[i] == stud) {
            for (; i < lastindex; i++) {
                list[i] = list[i + 1];
            }
            // for loop replaces each element with the next in the array
            list[lastindex].setLast("");
            list[lastindex].setFirst("");
            list[lastindex].setDOB("");
            list[lastindex].setMatDate("");
            list[lastindex].setCredits(0);
            list[lastindex].setGPA(0);
            lastindex--;
            // set lastindex of the array to empty values and
            // decrementing lastindex so that we can ignore it
            // when we output the roster
        }
        break;
        // exit loop after deleting first instance of Student stud
    }
}

string Roster::getCourseName() const {return coursename;}

string Roster::getCourseCode() const {return coursecode;}

string Roster::getInstructor() const {return instructor;}

int Roster::getCredits() const {return credits;}

void Roster::setCourseName(string name) {
    coursename = name;
}

void Roster::setCourseCode(string code) {
    coursecode = code;
}

void Roster::setInstructor(string prof) {
    instructor = prof;
}

void Roster::setCredits(int cred) {
    credits = cred;
}

void Roster::output() {
        cout << "-------------------------------------" << endl;
        cout << "Course Name: " << getCourseName() << endl;
        cout << "Course Code: " << getCourseCode() << endl;
        cout << "Instructor: " << getInstructor() << endl;
        cout << "Credits: " << getCredits() << endl;
        cout << "Roster: " << endl;
        for (int i = -1; i <= lastindex; i++) {
                if(lastindex == -1) {
                        cout << "No students registered" << endl;
            break;
                } else {
                        cout << list[i].getLast() << ", "       << list[i].getFirst() << endl;
                }
        }
    cout << "-------------------------------------" << endl;
}


and the driver program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// main.cpp
#include <iostream>
#include "student.h"
#include "roster.h"
using namespace std;

int main() {
    Roster r1;
    r1.output();
    Student s1;
    Student s2("Reghay", "Karim", "12/01/88", "06/01/06", 60, 3.2);
    r1.addStudent(s1);
    r1.addStudent(s2);
    r1.output();
    cout << "Try entering another student" << endl;
    Student s3;
    s3.input();
    r1.output();
    cout << "Try removing a student" << endl;
    r1.delStudent(s1);
    r1.output();
    return 0;
}


I know it's a lot of code to look at but I really can't figure out where the bug is. Way prefer compilation errors to run-time errors!

Thanks in advance for any and all help on this.




Located the problem, it was that in Roster::output() the for loop should have initialized i to 0 not -1
Last edited on
If you're running from a debugger... the debugger should snap and tell you exactly what line of code the exception is being thrown from... which will tell you exactly where the problem is.


That said... I do see this in Roster::output:

1
2
3
4
5
6
7
8
        for (int i = -1; i <= lastindex; i++) {
                if(lastindex == -1) {
                        cout << "No students registered" << endl;
            break;
                } else {
                        cout << list[i].getLast() << ", "       << list[i].getFirst() << endl;
                }
        }


If i == -1, you cannot do list[i] because that's an invalid index. Why are you starting this loop at -1 instead of 0?
Thanks, I actually spotted that finally myself, a few minutes before seeing your comment. Appreciate it! Frustrating when it takes so long to find such an obvious mistake :(
Topic archived. No new replies allowed.