Exception Handling Error (Program crashing) help ASAP!

Need C++ help ASAP!!!

The program runs but when choosing option 1 to load an exam and choosing a file
C:\\temp\\testBankFile.txt
with the format below. The program crashes giving an error. I have posted the error, content of the exam and my code below. Please assist ASAP!

Error:

Unhandled exception at 0x7437D722 in CS215_Joseph_Hoffman_IP4.exe: Microsoft C++ exception: std::invalid_argument at memory location 0x00CFF410. occurred

This points to line 120. I have no idea what is wrong or what I did wrong.

Exam file:

3
TF 5
There exist birds that cannot fly?
True
MC 10
Who was the President of the USA in 1991?
6
Richard Nixon
Gerald Ford
Jimmy Carter
Ronald Reagan
George Bush Sr.
Bill Clinton
E
TF 10
The city of Boston hosted the 2004 Summer Olympics?
False

This is properly formatted based on class requirements.

My Code:
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//============================================================================
// Name: CS215_Joseph_Hoffman_IP4
// Author: Joseph Hoffman
// Description: 
//============================================================================
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;

class Question
{
protected:
	string question;
	int value;
public:
	Question() { }
	Question(string theQuestion, int points
	)
	{
		question = theQuestion;
		value = points;
	}
	string getQuestion() {
		cout << question << endl;
		return question;
	}
	int getValue() 
	{
		return value;
	}
	virtual void printOptions() = 0;
	virtual string getAnswer() = 0;
};
class QuestionTF : public Question
{
private:
	string answer;
public:
	// store answers and pass question and points back to the base class - Question
	QuestionTF(string theQuestion, int points, string theAnswer)
		: Question(theQuestion, points)
	{
		answer = theAnswer;
	}
	void printOptions()
	{
		cout << "(true/false)" << endl;
	}
	string getAnswer()
	{
		cout << "The Answer is: " << answer << endl;
		return answer;
	}
};
class QuestionMC : public Question
{
private:
	string answer;
	vector <string> options;
public:
	//store answer and pass question and points back to the base class - Question
	QuestionMC(string theQuestion, int points, string theAnswer)
		: Question(theQuestion, points)
	{
		answer = theAnswer;
	}
	// stores multiple choice options received from reading a file
	void addOption(string anOption)
	{
		options.push_back(anOption);
	}
	// print all elements in vector
	void printOptions()
	{
		for (int i = 0; i < options.size(); ++i)
		{
			cout << options[i] << endl;
		}
	}
	string getAnswer()
	{
		cout << "The answer is: " << answer << endl;
		return answer;
	}
};
class Exam
{
protected:
	vector <Question*> questions;
	int question;
public:
	Exam() { }
	bool loadExam(std::string filename) // function takes a file name
	{
		Question* question;
		vector <string> answerChoices;
		ifstream filein;
		int numQuestions, pointValue;
		string questionType, strQuestion, strAnswer, choice, num;
		filein.open(filename);
		if (!filein.is_open())
		{
			// failed to open file – return false
			return false;
		}
		else
		{
			getline(filein, num); //get number of questions
			numQuestions = stoi(num); // convert string num to integer num
			for (int i = 0; i < numQuestions; i++)
			{
				getline(filein, questionType, ' '); //get question type
				getline(filein, num); //get question points
				pointValue = stoi(num); //convert points to int
				getline(filein, strQuestion); //get the question
				if (questionType == "TF" || questionType == "tf")
				{
					//create new object
					QuestionTF *obj = new QuestionTF(strQuestion, pointValue, strAnswer);
					questions.push_back(obj); // push the object into the vector
				}
				else if (questionType == "MC" || questionType == "mc")
				{
					QuestionMC *obj = new QuestionMC(strQuestion, pointValue, strAnswer);
					questions.push_back(obj);
				}
				else // Question type not TF or MC
				{
					cout << "Error, unknown question type!\n";
				}
			}
			filein.close();
			cout << "Exam loaded successfully!\n";
		}
		return true;
	}
	void displayExam()
	{
		for (int i = 0; i < questions.size(); ++i)
		{
			cout << "Question " << i + 1 << ":";
			cout << questions[i]->getQuestion() << endl;
			cout << "Point Value: " << questions[i]->getValue() << endl;
			cout << "Answer: " << questions[i]->getAnswer() << endl;
		}
	}
};
int main()
{
	Exam theExam;
	string filename;
	char menuSelection;
	do
	{
		cout << "Menu" << endl;
		cout << "1 - Load an exam" << endl;
		cout << "2 - Display an exam" << endl;
		cout << "Q - Quit" << endl;
		cout << "Enter Option : ";
		// COMPLETE THIS SECTION!!! (COMPLETED)
		cin >> menuSelection;
		switch (menuSelection)
		{
		case '1':
			cout << "You selected Load an exam\n";
			cout << "What is the name of the exam file? \n";
			cin >> filename;
			if (theExam.loadExam(filename) == false)
			{
				cout << "Load exam failed.Please check testBank file!" << endl;
			}
			break;
		case '2':
			cout << "You selected display exam\n";
			theExam.displayExam();
			break;
		case 'q':
		case 'Q':
			cout << "Thank you and good-bye\n";
			break;
		default:
			cout << "Please try again" "\n";
		}
	} while (tolower(menuSelection) != 'q');
	system("pause");
	return 0;
};


I need to correct my code and please explain to me what is wrong. The class assignment requirements are below please make sure I did everything properly that was asked!

Requirments:

Write a C++ program that is menu-driven that allows for the following menu choices:

1. Load an exam: Loading an exam should prompt the user for an exam file. If no file exists, it should allow the user to specify a different file. Upon a successful load of an exam, the user should be presented with the menu again.

2. Display exam: The program should simply display each question, its point value, and the answer to the screen. (The functionality of actually taking the exam will be created in Week 5). Upon displaying the exam to the screen, the user should be presented with the menu again.

3. Quit: Quit the program gracefully by displaying a "thank you" message to the user, and ensure that all files have been closed along with any other housekeeping that should be done as your program shuts down.

Consider creating a class exam that will hold the actual exam and provide behavior such as loadExam and also displayExam. This class will be enhanced in Week 5.
Last edited on
If the error comes from line 120 i'd guess it comes from the stoi() function. It probably gets an argument that's not an string number.

1
2
3
4
                                getline(filein, questionType, ' '); //get question type
				filein >> num; //get question points //try reading num directly from file
                                cout << "\n Num is " << num"; // To check if num is indeed a number
				pointValue = stoi(num); //convert points to int 


Hope that helps,

Regards,

Hugo.


Last edited on
I fixed my code the following issues are corrected:

Issues:

1. getline reads the new line character from file also.. hence trimmming is necessary like i did. otherwise stoi() function will give error.
2. You are not reading any options for multiple choice questions.
3. You are not reading in the string strAnswer and directly using to create question.


My corrected code:
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

// helper method
string trim(string str) {                
        if (str[str.size() - 1] == '\r')
                str.resize(str.size() - 1);
        if (str[str.size() - 1] == '\n')
                str.resize(str.size() - 1);
        return str;
}

class Question {
protected:
    string question;
    int value;

public:
    Question() {
    }
    Question(string theQuestion, int points) {
        question = theQuestion;
        value = points;
    }

    string getQuestion() {
        return question;
    }

    int getValue() {
        return value;
    }

    virtual void print() = 0;
    virtual void printOptions() = 0;
    virtual string getAnswer() = 0;
};

class QuestionTF : public Question {
private:
    string answer;

public:
    // store answers and pass question and points back to the base class -
    // Question
    QuestionTF(string theQuestion, int points, string theAnswer)
        : Question(theQuestion, points) {
        answer = theAnswer;
    }

    void print() {
                cout << getQuestion() << endl;
                cout << "Point Value: " << getValue() << endl;
                cout << "Answer: " << getAnswer() << endl;
                cout << endl;
    }

    string getAnswer() {
        return answer;
    }

    void printOptions() {
        cout << "(true/false)" << endl;
    }
};

class QuestionMC : public Question {
private:
    string answer;
    vector<string> options;

public:
    // store answer and pass question and points back to the base class -
    // Question
    QuestionMC(string theQuestion, int points, string theAnswer)
        : Question(theQuestion, points) {
        answer = theAnswer;
    }

    // stores multiple choice options received from reading a file

    void addOption(string anOption) {
        options.push_back(anOption);
    }

    void print() {
                cout << getQuestion() << endl;
                cout << "Point Value: " << getValue() << endl;
                cout << "options:\n";
                printOptions();
                cout << "Answer: " << getAnswer() << endl;
                cout << endl;
    }

    // print all elements in vector
    void printOptions() {
        for (int i = 0; i < options.size(); ++i) {
            cout << options[i] << endl;
        }
    }

    string getAnswer() {
        return answer;
    }
};

class Exam {
protected:
    vector<Question *> questions;
    int question;

public:
    Exam() {
    }

    bool loadExam(std::string filename) // function takes a file name
    {
        Question *question;
        vector<string> answerChoices;
        ifstream filein;

        int numQuestions, pointValue, numChoices;

        string questionType, strQuestion, strAnswer, choice, num;

        filein.open(filename);

        while (!filein.is_open()) {
            cout << "Unable to open the file."
                 << "Try again." << endl;
            cout << "Enter filename: ";
            cin >> filename;
            filein.open(filename);
        }

        getline(filein, num); // get number of questions
        numQuestions = stoi(trim(num)); // convert string num to integer num

        for (int i = 0; i < numQuestions; i++) {
                        questionType = " ";
                        filein >> questionType;
            questionType = trim(questionType); // get question type

            getline(filein, num);   // get question points

            pointValue = stoi(trim(num)); // convert points to int

            getline(filein, strQuestion); // get the question

            if (questionType == "TF" || questionType == "tf") {
                    getline(filein, strAnswer); // get the answer
                // create new object
                QuestionTF *obj =
                    new QuestionTF(trim(strQuestion), pointValue, trim(strAnswer));

                questions.push_back(obj); // push the object into the vector
            } else if (questionType == "MC" || questionType == "mc") {
                            vector<string> options;

                                // read answerChoices
                                getline(filein, num);   // get question points
                                numChoices = stoi(trim(num)); // convert points to int

                                for(int j=0; j<numChoices; j++) {
                                        getline(filein, choice); 
                                        options.push_back(trim(choice));
                                }
                    getline(filein, strAnswer); // get the answer

                QuestionMC *obj =
                    new QuestionMC(trim(strQuestion), pointValue, trim(strAnswer));
                questions.push_back(obj);

                                for(int j=0; j<numChoices; j++) {
                                        obj->addOption(options[j]);
                                }

            } else // Question type not TF or MC
            {
                cout << "Error, unknown question type!\n";
            }
        }

        filein.close();
        cout << "Exam loaded successfully!\n";

        return true;
    }

    void displayExam() {
        for (int i = 0; i < questions.size(); ++i) {
            cout << "Question " << i + 1 << ":";
            questions[i]->print();
        }
    }
};

int main() {
    Exam theExam;
    string filename;
    char menuSelection;
    do {
        cout << "Menu" << endl;
        cout << "1 - Load an exam" << endl;
        cout << "2 - Display an exam" << endl;
        cout << "Q - Quit" << endl;
        cout << "Enter Option : ";

        // COMPLETE THIS SECTION!!! (COMPLETED)
        cin >> menuSelection;

        switch (menuSelection) {
        case '1':
            cout << "You selected Load an exam\n";
            cout << "What is the name of the exam file? \n";

            cin >> filename;

            if (theExam.loadExam(filename) == false) {
                cout << "Load exam failed.Please check testBank file!" << endl;
            }

            break;

        case '2':
            cout << "You selected display exam\n";
            theExam.displayExam();
            break;

        case 'q':

        case 'Q':
            cout << "Thank you and good-bye\n";
            break;

        default:
            cout << "Please try again"
                 << "\n";
        }

                cout << endl;
    } while (tolower(menuSelection) != 'q');

    return 0;
};


I hope this helps anyone else who stops by this thread.
The trim function is not needed (and you're not really doing it properly, anyway). You should be checking for '\n' first, then '\r' (since the '\n' (if present) will be the last character).

But although getline reads the newline from the file, it DOES NOT LEAVE THE NEWLINE IN THE STRING, so what is probably happening is that you are reading a windows text file in a *nix environment, so the Windows EOL character sequence (\r\n) is not being interpretted properly and a '\r' is being left at the end of the string.

But you shouldn't need to remove the '\r' (or any whitespace) from the end of the string for stoi to work. It will stop when it reaches the whitespace. It's not an error. E.g.,
1
2
3
4
5
6
7
#include <iostream>
#include <string>
using namespace std;
int main() {
    string s {"1234\r\n"};
    cout << stoi(s) << '\n';  // no problem
}


BTW, you have an extraneous semicolon after main, your indentation is inconsistent, and it is unusual to define all member functions inside the class.

You also have unused variables. E.g., these in loadExam:
1
2
        Question *question;
        vector<string> answerChoices;

Last edited on
Topic archived. No new replies allowed.