Comparing user input always equals false. Why?

Pages: 12
Looking at your original code, it's not clear whether Quiz was meant to be Exam: at the moment Quiz inherits from question.

It's also not clear whether a Student should keep track of multiple exams,given there are multiple question types, and Student is supposed to have addPointsPossible , a function which implies addition.

But I think I see what your saying since it is already public I can retrieve it with out inheritance?


Yes.

A key thing about OOP is the concept of an interface, that is a series of public functions which return the values of member variables. Other objects can use these functions to acquire the data that they need. Contrary to beginners belief, there is no need to put everything into one giant inheritance tree.

Note that one may not need access to all the class members, and one shouldn't routinely provide get / set functions for every member. The public interface to Student could be minimal, just: void PrintExamResults(const Exam& TheExam); The functions addPointsPossible, addPointsScored, getPointsPossible, and getPointsScored could all be private member functions that use the public interface of an Exam object to get those values.

I was thinking that it would go out of scope so I would have to inherit to prevent it, is that wrong?


Yes IMO that is wrong. Simplistically, in main you should have an instances of all the object types: you can use them to call whatever public functions their classes contain. In reality though, a class could have instance of another class inside it. Be careful to initialise them via the constructor.

That brings me to another point, your classes don't have constructors. The purpose of these is to initialise their member variables.

TheIdeasMan wrote:
What other thing can a student have? It relates to where they learn.


Maybe my vision was too complicated for this assignment: I am used to thinking about reuse of objects, so I tend to have more classes rather than less. I looks like the assignment is only asking for question and it's derived classes, Exam and Student.
Last edited on
No for this assignment I don't need to keep track of multiple exams. Just be able to load different exams. Quiz is meant to be exam I changed it along with most everything else due to an example I was given a few assignments ago so I'm not just copying code and using it as my own. How would I learn that way? Haha. Anyways Student doesn't have to keep track of multiple exams only the current one that would have just been taken by the user. About the constructor I think I implemented them in my other project with the header and .cpp files you suggested I use. I am working on making this current one work since I am more familiar with this way then when it is working I will move everything I added to the other project. I will post one of the classes from my other project Hopefully I am doing it right now. And yes the assignment isn't too complicated only five classes: questions, TFquestions, MCquestions, Quiz(or exam) and Student. It is suggested that I use addPointsPossibe, addpointsScored, getPointsPossible, and getPointsScored functions in the student class. Also I should extend my Quiz(Exam) class to have getPointValue and getAnswer. Though It is not required of me to do it exactly this way. It is only required that I have the student class that displays the total amount of possible points the total points the user scored during the exam and a percentage score, however I implement it is up to me. I tried to use all of the suggested functions in the student class but couldn't figure out how to get everything connected so I am attempting to simplify it somewhat with less functions. I think I am just getting lost with so many functions and classes and the flow of the program. I have been using the debugger and placing breakpoints on each line to try and watch the way everything is working. Which is helping but I am getting lost trying to get this new class to work.

this is my Questions.h file in my other project.
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
#pragma once
#include <string>
#include <iostream>


using namespace std;
class questions
{
private:
	string question;
	string answer;
	string questionType;
	int value;


public:
	
	virtual string getQuestion();
	virtual int getValue();
	virtual string getQuestionType();
	virtual void setQuestion(string answer, int value);
	virtual void setNewQuestion(string answer, int value);
	virtual void printOptions();
	virtual string getAnswer();

};


This is the questions.cpp file:
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
#include "questions.h"
#include <string>
using namespace std;



string questions::getQuestion()//gets the question
{
	return question;
}

int questions::getValue()
{
	return value;
}

string questions::getQuestionType()
{
	return questionType;
}

void questions::setQuestion(string answer, int value)
{
}

void questions::setNewQuestion(string answer, int value)
{
}

void questions::printOptions()
{
}

string questions::getAnswer()
{
	return answer;
}


Is this the correct way to use constructors or am I still getting that wrong?
Is this the correct way to use constructors or am I still getting that wrong?


Still no constructors in that. A constructor has the same name as the class, and no return type (how could you forget that? It's like forgetting what the car keys are for):

1
2
3
4
5
6
questions::questions() // default constructor, no arguments
   : //colon introduces member initialization list, set all member variable values by direct initialization, 
//may not have learnt that yet
{
 // do validation here
}


Constructors can have arguments, normally one for each member that needs to be set.

Pass std::string by const reference:

1
2
3
void questions::setQuestion(const std::string& answer, int value)
{
}


Strictly speaking you shouldn't need questionType, the derived class is the type.

Mark functions that don't change the state of the class with const:

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
string questions::getQuestion() const //gets the question
{
	return question;
}

int questions::getValue() const
{
	return value;
}

string questions::getQuestionType() const
{
	return questionType;
}

void questions::setQuestion(const std::string& answer, const int value)
{
}

void questions::setNewQuestion(const std::string& answer, const int value)
{
}

void questions::printOptions()  const
{
}

string questions::getAnswer() const
{
	return answer;
}
Haha yes now I remember. Sorry I am trying to learn too much at once I guess. With having a constructor do I also need a deconstructor (or destructor,not sure which) Questionss::~Questionss() ? I have this now
questions.h
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
#pragma once
#include <string>
#include <iostream>


using namespace std;


class questions
{
private:
	string question;
	string answer;
	string questionType;
	int value;
public:
	questions();
	~questions();
	virtual string getQuestion() const; 
	virtual int getValue() const;
	virtual string getQuestionType() const;
	virtual void setQuestion(const string& answer, const int value);
	virtual void setNewQuestion(const string& answer, const int value);
	virtual void printOptions() const;
	virtual string getAnswer() const;

};

questions.cpp
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
#include "questions.h"



questions::questions()
{
}


questions::~questions()
{
}

string questions::getQuestion() const
{
	return question;
}

int questions::getValue() const
{
	return value;
}

string questions::getQuestionType()const
{
	return questionType;
}

void questions::setQuestion(const string& answer, const int value)
{
}

void questions::setNewQuestion(const string& answer, const int value)
{
}

void questions::printOptions()const
{
}

string questions::getAnswer() const
{
	return answer;
}


Also you said "Mark functions that don't change the state of the class with const". I am not exactly sure what you mean by this, specifically the "state of the class" part. How can I tell if a function will change the state of the class? is there any reference you can point me to so I can research the subject?

So I am having this problem with implementing my student class. I have changed some stuff.

I now have two function at the end of my quiz class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
	int  getPointValue()
	{
		return totalPossiblePoints;
	}
	int setPointValue()
	{
		for (int i = 0; i < numberOfQuestions; i++)
				{
					pointValue[i] = myQuestions[i]->getValue();
				}
				for (int i = 0; i < 6; i++)
				{
					std::cout << "the point value of each question is " << pointValue[i] << std::endl;
					totalPossiblePoints += pointValue[i];
					std::cout << "The total possible points are: " << totalPossiblePoints << std::endl;
				}
				
				std::cout << totalPossiblePoints << std::endl;
				return totalPossiblePoints;
	}


and I now have this as my student class, though I am not quite finished with it I keep getting stuck on the same problem no mater how change it.

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
class Student
{
private:
	int pointsPossible = 0;
	int pointsScored = 0;
	std::string name;
	int yourScore = 0;

	//int totalScore;
public:
	void student()
	{
		Quiz a;

		pointsPossible = a.setPointValue();
		std::cout << "Please enter your name" << std::endl;
		std::getline(std::cin, name);
		std::cout << "Hello " << name << std::endl
			<< "The total possible points are: " << pointsPossible << std::endl
			<< "You scored " << score << " points out of " << pointsPossible << " possible points." << std::endl;
	}
	int getPointsPossible()
	{
		return pointsPossible;
	}

};


the output is still the same as before. I was using the debugger though and noticed something. On this line pointValue[i] = myQuestions[i]->getValue(); the myQuestions[i] array says myQuestions is undefined on the watch list. Which I am guessing is why I am getting these random negative number instead of whats in the file. I keep trying to figure out how to fix it but nothing seems to work. The only way I can get it to work is if I take the code in the new int setPointValue() function, eliminate the two new functions I have at the end of the quiz class and put the code inside of the void displayQuizQuestions(int numquestions). I think I understand why it works there and not in the new function. Because myQuestions[i] is no longer in scope since it left the function and moved to a different one. I can't figure out how to retrieve the data that I need from outside the scope of that function. If you wouldn't mind could you please help me solve this problem? I am completely stumped with this one.
Also you said "Mark functions that don't change the state of the class with const". I am not exactly sure what you mean by this, specifically the "state of the class" part. How can I tell if a function will change the state of the class?


http://www.cplusplus.com/forum/beginner/211513/#msg990467

Unfortunately you still don't have a Student constructor - but you nearly do .... C++ is case sensitive, the constructor name must be exactly the same as the class name.

Rather than getting the input inside the constructor, get the input before you create the object in main, then create the object by sending all the info as arguments to the constructor. Look at the example for constructors in the tutorial on this site.

I think a lot of your problems come from not having proper constructors.

With having a constructor do I also need a deconstructor (or destructor,not sure which) questions::~questions() ?


Yes, because you have virtual functions, the destructor needs to be virtual too:
1
2
3
virtual ~questions(); //declaration

~questions::questions() {} //definition 


Each derived class needs to have it's own destructor too.

I think you should put proper constructors and destructors for all of your classes, and review everything I have said to you, and re read the tutorials. Then post everything you have again.

Edit:

That's it for me today, someone else might help in the interim :+)
Last edited on
Thanks for all of your help so far! I have put constructors and destructors in each class. Now I have to program running as it was before I did that. However even with the constructors implemented I am still getting the same output as before when trying to get the total possible points due to a different error using the watch list in the debugger. The new error is this:
myQuestions[i]->getValue a pointer to a bound function may only be used to call the function

I have never seen this error before so I am not sure what it means. I am going to try and look it up and see if I can figure it out. If you know anything about it I am all ears(or eyes in this case). I will post updated code so you can see if I am correctly doing the constructors now. Which I think I am.
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
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <limits>
int score;
class questions//base class
{
protected://using protected rather than private for inheritance to subclasses 
	std::string question;
	std::string answer;
	int value;
	std::string questionType;

public:
	questions::questions()
	{

	}
	virtual questions::~questions()
	{

	}

	std::string getQuestion()//gets the question
	{
		return question;
	}

	virtual int getValue() //gets the point value of the question
	{
		return value;
	}

	virtual std::string getQuestionType()// gets the type of question
	{
		return questionType;
	}


	virtual void setQuestion(std::string answer, int value)
	{
	}
	virtual void setNewQuestion(std::string answer, int value)
	{
	}
	virtual void printOptions()
	{
	}

	virtual std::string getAnswer()
	{
		return answer;
	}
};


class tfQuestion : public questions// subclass of questions class for true and false questions
{
private:
	std::string options;
	std::string a1;
public:
	tfQuestion::tfQuestion()
	{

	}
	tfQuestion::~tfQuestion()
	{

	}
	void setQuestion(std::string theQuestion, int pointValue)
	{
		std::string theAnswer;
		questionType = "TF";
		question = theQuestion;
		value = pointValue;
		options = "true/false";
		//get the answer from the file
		std::getline(std::cin, theAnswer);
		answer = theAnswer;
	}

	/*void setNewQuestion(std::string theQuestion, int pointValue)
	{
	std::string theAnswer;
	questionType = "TF";
	question = theQuestion;
	value = pointValue;
	options = "true/false";
	//get the answer from user
	std::cout << "Enter answer true/false\n";
	std::getline(std::cin, theAnswer);
	answer = theAnswer;
	}*/

	int getValue() //gets the point value of the question
	{
		return value;
	}

	std::string getQuestionType()// gets the type of question
	{
		return questionType;
	}

	std::string getQuestion()
	{
		return question;
	}

	void printOptions()//prints the options for that question
	{
		std::cout << question << std::endl;

		//std::cout << answer << std::endl;//this stops output of answer for TF
	}

	std::string getAnswer()//outputs the answer for that question
	{
		return answer;
	}
};



class mcQuestion : public questions//subclass of questions class for multiple choice questions
{
private:
	int numberOfOptions;
	std::string mcAnswers[6];
public:
	mcQuestion::mcQuestion()
	{

	}
	mcQuestion::~mcQuestion()
	{

	}
	void setQuestion(std::string theQuestion, int pointValue)
	{
		std::string line;
		questionType = "MC";
		std::getline(std::cin, line);
		numberOfOptions = atoi(line.c_str());
		question = theQuestion;
		value = pointValue;
		//get the individual choice lines and load to options array
		for (int count = 0; count < numberOfOptions; count++)
		{
			std::getline(std::cin, line);
			mcAnswers[count] = line;
		}
		//get the answer from the file and load into answer
		std::getline(std::cin, line);
		answer = line;
	}

	/*	void setNewQuestion(std::string theQuestion, int pointValue)
	{

	std::string line;
	questionType = "MC";
	//get the number of choices from the user
	/*std::cout << "Enter the number of choices:  ";
	std::getline(std::cin, line);
	numberOfOptions = atoi(line.c_str());

	question = theQuestion;
	value = pointValue;
	//get the individual choice lines and load to options array
	for (int count = 0; count < numberOfOptions; count++)
	{
	std::cout << "\nEnter next option:  ";
	std::getline(std::cin, line);
	mcAnswers[count] = line;
	}
	//get the answer from the user and load into answer
	std::cout << "\nEnter Answer:  ";
	std::getline(std::cin, line);
	answer = line;
	}	*/

	void printOptions()// prints the questions, options, and answer
	{
		char first = 'A';
		std::cout << question << std::endl;
		for (int count = 0; count < numberOfOptions; count++)
		{
			std::cout << "(" << first++ << "): " << mcAnswers[count] << "\n";
		}
		//std::cout << answer << "\n";//This stops output of answer on MC
	}

	int getValue() //gets the point value of the question
	{
		return value;
	}

	std::string getQuestionType()// gets the type of question
	{
		return questionType;
	}

	std::string getAnswer()// prints the answer
	{
		return answer;
	}
};
//Will continue from here 
Last edited on
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
class Quiz : public questions
{
private:
	std::string fileName;
	//questions *myQuestions[10];
	//int numberOfQuestions;
	std::string theAnswer;
	std::string qtype;
	std::string theAnswerIs;
	std::string ans[6];
protected:
	
	questions *myQuestions[6];
	int numberOfQuestions;
	int pointValue[6];
	int totalPossiblePoints = 0;

public:
	Quiz::Quiz()
	{

	}
	Quiz::~Quiz()
	{

	}
	void setloadQuiz(int num)
	{
		std::ifstream infile;
		infile.clear();
		//checking to see if user specified file exist, as well as making sure the user has used the correct format
		while (!infile.is_open())
		{
			std::cout << "Please enter the .txt file name: " << std::endl;
			std::getline(std::cin, fileName);
			//fileName += ".txt";
			infile.open(fileName.c_str(), std::ios::in | std::ios::binary);
			if (infile)
				break;
			std::cout << "Either the file doesn't exist or you forgot the .txt extension. ";
			std::cout << "Please try again. " << std::endl << std::endl;//promt user to try again if the file name is invalid
		}


		//std::ifstream infile("quiz.txt");
		std::streambuf *cinbuf = std::cin.rdbuf();       //save old buf
		std::cin.rdbuf(infile.rdbuf());             //redirect std::cin to infile.txt!

		std::string line;
		std::string theQuestion;
		std::string questiontype;
		//std::string theAnswer;
		int  questionvalue;

		while (true)//error check to ensure the file has an acceptable amount of questions
		{

			//get the number of questions from the first line in the file
			//std::getline(infile, line);
			std::getline(std::cin, line);
			numberOfQuestions = atoi(line.c_str());
			if (numberOfQuestions != 6)
			{
				std::cout << "Error! The quiz has too many or too litte questions. The desired amount is \'6\'" << std::endl;
				std::cout << "Please check the file to ensure there is an acceptable amount of questions." << std::endl;
				throw;
			}
			else
			{
				break;
			}
		}
		for (int count = 0; count < numberOfQuestions; count++)
		{
			//std::getline(infile, line);
			std::getline(std::cin, line);
			//get the next line with the question type and the value of the question
			int npos = line.size();
			int prev_pos = 0;
			int pos = 0;
			while (line[pos] != ' ')
				pos++;
			questiontype = line.substr(prev_pos, pos - prev_pos);
			prev_pos = ++pos;
			questionvalue = atoi(line.substr(prev_pos, npos - prev_pos).c_str()); // Last word

			if (questiontype == "TF")//do this if questiontype = TF
			{
				myQuestions[count] = new tfQuestion;
				//std::getline(infile, line);
				std::getline(std::cin, theQuestion);
				myQuestions[count]->setQuestion(theQuestion, questionvalue);
			}

			if (questiontype == "MC")//do this if questiontype = MC
			{
				myQuestions[count] = new mcQuestion;
				//std::getline(infile, line);
				std::getline(std::cin, theQuestion);
				myQuestions[count]->setQuestion(theQuestion, questionvalue);
			}

		}
		std::cin.rdbuf(cinbuf);//restore cin to standard input
		infile.close();//close the file stream
		//return numberOfQuestions;
	}

	int getloadQuiz()
	{
		return numberOfQuestions;
	}

	void setdisplayQuizQuestions(int num)
	{
		score = 0;
		//print out the questions that have been processed
		for (int i = 0; i < num; i++)
		{
			qtype = myQuestions[i]->getQuestionType();
			std::cout << qtype << " " << myQuestions[i]->getValue() << "\n";
			myQuestions[i]->printOptions();
			theAnswerIs = myQuestions[i]->getAnswer();
			std::cout << theAnswerIs << std::endl;
			std::cout << "\n";
			std::cout << "Please enter your answer: ";
			std::cin >> ans[i];
			std::cout << ans[i].size() << "\n" << theAnswerIs.size() << std::endl;

			if (!theAnswerIs.empty() && theAnswerIs[theAnswerIs.size() - 1] == '\r')
				theAnswerIs.erase(theAnswerIs.size() - 1);
			std::cout << ans[i].size() << "\n" << theAnswerIs.size() << std::endl;
			if (theAnswerIs == ans[i])
			{
				std::cout << "You are correct, the answer is: " << theAnswerIs << '\n';
				score++;
				std::cout << "Your current score is " << score << std::endl;
			}
			else
			{
				std::cout << "Incorrect, the correct answer is: " << theAnswerIs << std::endl;
				std::cout << "Your score is " << score << std::endl;
			}
		}
	}
		int getdisplayQuizQuestions()
		{
			return 0;
		}
		/*		for (int i = 0; i < numquestions; i++)
				{
					pointValue[i] = myQuestions[i]->getValue();
				}
				for (int i = 0; i < 6; i++)
				{
					std::cout << "the point value of each question is " << pointValue[i] << std::endl;
					totalPossiblePoints += pointValue[i];
					std::cout << "The total possible points are: " << totalPossiblePoints << std::endl;

				}
				std::cout << totalPossiblePoints << std::endl;
				//delete myQuestions[10];
			}
*/
	int  getPointValue()
	{
		return totalPossiblePoints;
	}
	void setPointValue(int num)
	{
		for (int i = 0; i < numberOfQuestions; i++)
				{
					pointValue[i] = myQuestions[i]->getValue();
				}
				for (int i = 0; i < 6; i++)
				{
					std::cout << "the point value of each question is " << pointValue[i] << std::endl;
					totalPossiblePoints += pointValue[i];
					std::cout << "The total possible points are: " << totalPossiblePoints << std::endl;
				}
				
				std::cout << totalPossiblePoints << std::endl;
	}
	
	
};
class Student
{
private:
	int pointsPossible;
	int pointsScored = 0;
	std::string name;
	int yourScore = 0;

	//int totalScore;
public:
	Student::Student()
	{

	}
	Student::~Student()
	{

	}
	
/*	void student()
	{
		std::cout << "Please enter your name" << std::endl;
		std::getline(std::cin, name);
		std::cout << "Hello " << name << std::endl
			<< "The total possible points are: " << pointsPossible << std::endl
			<< "You scored " << score << " points out of " << pointsPossible << " possible points." << std::endl;
}
*/
	int getPointsPossible()
	{
		return pointsPossible;
	}
	void setPointsPossible(int num)
	{
		Quiz obj;
		num = 0;
		obj.setPointValue(num);
		num = obj.getPointValue();
		//student();
	}

};


int menu()
{
	int selection = 0;
	std::cout << "Please select an option from the list below." << std::endl;
	//display the menu
	std::cout << "Menu";
	std::cout << "======" << std::endl;
	std::cout << "1 - Load quiz." << std::endl;
	std::cout << "2 - Take quiz." << std::endl;
	std::cout << "3 - Show quiz results." << std::endl;
	std::cout << "4 - Press 4 to exit." << std::endl << std::endl;
	std::cout << "Enter selection: ";
	while (true)//while loop to ensure user selects an option on the menu
	{
		std::cin >> selection;
		if (std::cin.fail())
		{
			std::cerr << "Please enter an integer number." << std::endl;
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		}
		if (selection == 1 || selection == 2 || selection == 3 || selection == 4)
		{
			break;
		}
		std::cout << "The options are: \'1\'\'2\'\'3\' or \'4\': ";
	}
	std::cin.ignore();
	return selection;
}

int main()
{
	Student Sobj;
	Quiz obj;
	int num = 0;
	int selection = 0;
	while ((selection = menu()) != 4)
		switch (selection)
		{
		case 1:
			std::cout << "You selected - Load quiz." << std::endl;
			obj.setloadQuiz(num);
			num = obj.getloadQuiz();
			break;
		case 2:
			std::cout << "You selected - Take quiz." << std::endl << std::endl;
			std::cout << "========== Quiz: ==========" << std::endl;
			obj.setdisplayQuizQuestions(num);
			num = obj.getdisplayQuizQuestions();
			break;
		case 3:
			std::cout << "You selected - Show quiz results." << std::endl;
			Sobj.setPointsPossible(num);
			num = Sobj.getPointsPossible();			
			break;
		case 4:
			break;
		default: std::cout << "Invalid selection. Please try again.\n";
			}
	std::cout << std::endl << std::endl;
	std::cout << "Thank you for using this program. Goodbye.";
	std::cin.get();
	return 0;
}
It is line 173 of the second half giving me the problem. So far I get two errors while using the watch list 1:
myQuestions[i]->getValue identifier "i" is undefined
and 2:
myQuestions[i]->getValue a pointer to a bound function may only be used to call the function
. The first one goes away and changes to the second one immediately after entering the loop so I don't think that one is of much concern, but I could be wrong. Anyways I will keep at it for now and I anything changes I will post it. Thank You.
So it seems we haven't got very far: after all this time your code is not much different to what was originally :+(

So you created some constructors, bad news is they aren't doing anything. I was trying to get you to have a ctor instead of the set functions.

Why is it you don't seem to understand ctor's but have latched onto cin.rdbuf ?

I mentioned for Quiz to not inherit, but you haven't changed that.

I mentioned why protected variables are convenient, but bad and you haven't acted on that either.

On one hand you seem to appreciate what I am saying, on the other you aren't doing much about implementing it.

So what's going on ? Is it a Millienial trait of taking the easy way out, hoping someone else will do it for you? Maybe you are afraid that changing one thing will ruin every thing else? Or are you messing with me? Don't be offended by the following: You may need to grow a std::pair, and do something worthwhile, stop lollygagging about.
Okay I don't know as much as you though. Remember I am asking for help in the beginners fourm. I guess I am still confused how to use constructors. Maybe a simple example will help me see how they can be implemented in the way your suggesting? Because In the research I've done so far I haven't seen many(if any) examples on how to use them the way your suggesting. I don't really understand cin.rdbuf just know it worked. Right now I don't have the time to learn all of this stuff that isn't exactly needed in my assignment. Though I will be going back to everything once I do have the time. Also you said this
First of all, Student should not inherit from Quiz.
and I already changed that. Another thing I understand protected is bad but you have to remember I am changing stuff around through the program constantly to try and fix my problem and find a way it will work. I am planning on making sure that kind of simpler stuff is done but I have to get my current more challenging problem out of the way first. I can't do it all at once remember I am new to this so it's not easy for me to switch tasks back and forth like that. You are right I do appreciate the help and I am doing my best to learn from everything you said but it's not as easy as you make it sound where your just starting out. Anyways again I would like to say thanks for your help.
Hopefully you understand why I feel irate about this, we don't seem to be getting anywhere despite quite a bit of advice. We do suffer a lot from professional trolls on this site, it's hard to know whether someone is one or not. You seem to be bouncing around all over the place and not achieving very much.

There is an example in the tutorial on this site about constructors. The idea is to use a ctor instead of a function like setQuestion

So unless I see some evidence that you are actually doing something worthwhile, I am not prepared to repeat myself any further.
Okay understandable so your saying instead of the set functions use the constructor right? But I will still need the get functions then? I am getting an error now though with the new tf/mcQuestion I commented it.
I have changed to this:

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
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <limits>
int score;
class questions//base class
{
private:
	std::string question;
	std::string answer;
	int value;
	std::string questionType;

public:
	questions::questions()
	{

	}
	virtual questions::~questions()
	{

	}

	std::string getQuestion(const std::string& theQuestion, const int questionValue )//gets the question
	{
		return question;
	}

	virtual int getValue() //gets the point value of the question
	{
		return value;
	}

	virtual std::string getQuestionType()// gets the type of question
	{
		return questionType;
	}

	virtual void printOptions()
	{
	}

	virtual std::string getAnswer()
	{
		return answer;
	}
};


class tfQuestion : public questions// subclass of questions class for true and false questions
{
private:
	std::string options;
	std::string question;
	std::string answer;
	int value;
	std::string questionType;
public:
	tfQuestion::tfQuestion(std::string theQuestion, int pointValue)
	{
		std::string theAnswer;
		questionType = "TF";
		question = theQuestion;
		value = pointValue;
		options = "true/false";
		//get the answer from the file
		std::getline(std::cin, theAnswer);
		answer = theAnswer;
	}
	tfQuestion::~tfQuestion()
	{

	}
/*	void setQuestion(std::string theQuestion, int pointValue)
	{
		std::string theAnswer;
		questionType = "TF";
		question = theQuestion;
		value = pointValue;
		options = "true/false";
		//get the answer from the file
		std::getline(std::cin, theAnswer);
		answer = theAnswer;
	}
*/
	int getValue() //gets the point value of the question
	{
		return value;
	}

	std::string getQuestionType()// gets the type of question
	{
		return questionType;
	}

	std::string getQuestion()
	{
		return question;
	}

	void printOptions()//prints the options for that question
	{
		std::cout << question << std::endl;

		//std::cout << answer << std::endl;//this stops output of answer for TF
	}

	std::string getAnswer()//outputs the answer for that question
	{
		return answer;
	}
};



class mcQuestion : public questions//subclass of questions class for multiple choice questions
{
private:
	int numberOfOptions;
	std::string mcAnswers[6];
	std::string question;
	std::string answer;
	int value;
	std::string questionType;
public:
	mcQuestion::mcQuestion(std::string theQuestion, int pointValue)
	{
		std::string line;
		questionType = "MC";
		std::getline(std::cin, line);
		numberOfOptions = atoi(line.c_str());
		question = theQuestion;
		value = pointValue;
		//get the individual choice lines and load to options array
		for (int count = 0; count < numberOfOptions; count++)
		{
			std::getline(std::cin, line);
			mcAnswers[count] = line;
		}
		//get the answer from the file and load into answer
		std::getline(std::cin, line);
		answer = line;
	}
	mcQuestion::~mcQuestion()
	{

	}
/*	void setQuestion(std::string theQuestion, int pointValue)
	{
		std::string line;
		questionType = "MC";
		std::getline(std::cin, line);
		numberOfOptions = atoi(line.c_str());
		question = theQuestion;
		value = pointValue;
		//get the individual choice lines and load to options array
		for (int count = 0; count < numberOfOptions; count++)
		{
			std::getline(std::cin, line);
			mcAnswers[count] = line;
		}
		//get the answer from the file and load into answer
		std::getline(std::cin, line);
		answer = line;
	}
*/
	void printOptions()// prints the questions, options, and answer
	{
		char first = 'A';
		std::cout << question << std::endl;
		for (int count = 0; count < numberOfOptions; count++)
		{
			std::cout << "(" << first++ << "): " << mcAnswers[count] << "\n";
		}
		//std::cout << answer << "\n";//This stops output of answer on MC
	}

	int getValue() //gets the point value of the question
	{
		return value;
	}

	std::string getQuestionType()// gets the type of question
	{
		return questionType;
	}

	std::string getAnswer()// prints the answer
	{
		return answer;
	}
};
//will continue from here  
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
//continuing
class Quiz : public questions
{
private:
	std::string fileName;
	std::string theAnswer;
	std::string qtype;
	std::string theAnswerIs;
	std::string ans[6];
	double percentage;
	questions *myQuestions[6];
	int numberOfQuestions;
	int pointValue[6];
	double totalPossiblePoints = 0;


public:
	Quiz::Quiz()
	{
	std::ifstream infile;
	infile.clear();
	while (!infile.is_open())
	{
		std::cout << "Please enter the .txt file name: " << std::endl;
		std::getline(std::cin, fileName);
		infile.open(fileName.c_str(), std::ios::in | std::ios::binary);
		if (infile)
			break;
		std::cout << "Either the file doesn't exist or you forgot the .txt extension. ";
		std::cout << "Please try again. " << std::endl << std::endl;
	}
		std::streambuf *cinbuf = std::cin.rdbuf();       //save old buf
		std::cin.rdbuf(infile.rdbuf());             //redirect std::cin to infile.txt!
		std::string line;
		std::string theQuestion;
		std::string questiontype;
		int  questionvalue;
	while (true)
	{
		std::getline(std::cin, line);
		numberOfQuestions = atoi(line.c_str());
		if (numberOfQuestions != 6)
		{
			std::cout << "Error! The quiz has too many or too litte questions. The desired amount is \'6\'" << std::endl;
			std::cout << "Please check the file to ensure there is an acceptable amount of questions." << std::endl;
			throw;
		}
		else
		{
			break;
		}
	}
	for (int count = 0; count < numberOfQuestions; count++)
	{
		std::getline(std::cin, line);
		//get the next line with the question type and the value of the question
		int npos = line.size();
		int prev_pos = 0;
		int pos = 0;
		while (line[pos] != ' ')
			pos++;
		questiontype = line.substr(prev_pos, pos - prev_pos);
		prev_pos = ++pos;
		questionvalue = atoi(line.substr(prev_pos, npos - prev_pos).c_str()); // Last word
		if (questiontype == "TF")//do this if questiontype = TF
		{
			myQuestions[count] = new tfQuestion;
			std::getline(std::cin, theQuestion);
			myQuestions[count]->getQuestion(theQuestion, questionvalue);
		}
		if (questiontype == "MC")//do this if questiontype = MC
		{
			myQuestions[count] = new mcQuestion;//this now says no default constructor exist for class mcQuestion
			std::getline(std::cin, theQuestion);
			myQuestions[count]->getQuestion(theQuestion, questionvalue);
		}
	}
	std::cin.rdbuf(cinbuf);//restore cin to standard input
	infile.close();//close the file stream

	score = 0;
	percentage = 0;
	for (int i = 0; i < numberOfQuestions; i++)
	{
		qtype = myQuestions[i]->getQuestionType();
		std::cout << qtype << " " << myQuestions[i]->getValue() << "\n";
		myQuestions[i]->printOptions();
		theAnswerIs = myQuestions[i]->getAnswer();
		std::cout << "\n";
		std::cout << "Please enter your answer: ";
		std::cin >> ans[i];
		if (!theAnswerIs.empty() && theAnswerIs[theAnswerIs.size() - 1] == '\r')
			theAnswerIs.erase(theAnswerIs.size() - 1);
		if (theAnswerIs == ans[i])
		{
			std::cout << "You are correct, the answer is: " << theAnswerIs << '\n';
			score++;
			std::cout << "Your current score is " << score << std::endl;
		}
		else
		{
			std::cout << "Incorrect, the correct answer is: " << theAnswerIs << std::endl;
			std::cout << "Your score is " << score << std::endl;
		}
	}
	for (int i = 0; i < numberOfQuestions; i++)
	{
		pointValue[i] = myQuestions[i]->getValue();
	}
	for (int i = 0; i < 6; i++)
	{
		std::cout << "the point value of each question is " << pointValue[i] << std::endl;
		totalPossiblePoints += pointValue[i];
		std::cout << "The total possible points are: " << totalPossiblePoints << std::endl;
	}
		std::cout << "Press enter to see your total score out of the total points possible and the percentage you got for the quiz."
		<< std::endl;
		std::cin.get();
		std::cin.get();
		std::cout << "You scored " << score << " Points out of " << totalPossiblePoints << " possible points." << std::endl;
		totalPossiblePoints = .06;//this works because the only accepted ammount of questions is 6 
		percentage = score / totalPossiblePoints;
		std::cout << "Your percentage is: " << percentage << "%" << std::endl;
		for (int i = 0; i < numberOfQuestions; i++)
		{
			delete myQuestions[i];
		}
	}
	Quiz::~Quiz()
	{

	}
	int getloadQuiz()
	{
		return numberOfQuestions;
	}
	int getdisplayQuizQuestions()
	{
		return 0;
	}
	int  getPointValue()
	{
		for (int i = 0; i < numberOfQuestions; i++)
		{
			pointValue[i] = myQuestions[i]->getValue();
		}
		for (int i = 0; i < 6; i++)
		{
			std::cout << "the point value of each question is " << pointValue[i] << std::endl;
			totalPossiblePoints += pointValue[i];
			std::cout << "The total possible points are: " << totalPossiblePoints << std::endl;
		}

		std::cout << totalPossiblePoints << std::endl;
		return totalPossiblePoints;
	}


};
class Student
{
private:
	double pointsPossible;
	double pointsScored = 0;
	std::string name;
	double yourScore = 0;
	int num;
public:
	Student::Student()
	{
		Quiz obj;
		num = 0;
		obj.getPointValue();
		num = obj.getPointValue();
		student();
	}
	Student::~Student()
	{

	}

	void student()
	{
		std::cout << "Please enter your name" << std::endl;
		std::getline(std::cin, name);
		std::cout << "Hello " << name << std::endl;
		std::cout << "Press enter to see your total score out of the total points possible and the percentage you got for the quiz."
			<< std::endl;
		std::cin.get();
		std::cout << "You scored " << score << " Points out of " << pointsPossible << " possible points." << std::endl;
		pointsPossible = .06;
		yourScore = score / pointsPossible;
		std::cout << "Your percentage is: " << yourScore << "%" << std::endl;

	}

	int getPointsPossible()
	{
		return pointsPossible;
	}

};
int menu()
{
	int selection = 0;


	std::cout << "Please select an option from the list below." << std::endl;
	std::cout << "Menu";
	std::cout << "======" << std::endl;
	std::cout << "1 - Load quiz." << std::endl;
	std::cout << "2 - Take quiz." << std::endl;
	std::cout << "3 - Show quiz results." << std::endl;
	std::cout << "4 - Press 4 to exit." << std::endl << std::endl;
	std::cout << "Enter selection: ";
	while (true)
	{
		std::cin >> selection;
		if (std::cin.fail())
		{
			std::cerr << "Please enter an integer number." << std::endl;
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		}
		if (selection == 1 || selection == 2 || selection == 3 || selection == 4) 
	{
		break;
	}
	std::cout << "The options are: \'1\'\'2\'\'3\' or \'4\': ";
	}
	std::cin.ignore();
	return selection;
}
int main()
{
	Student Sobj;
	Quiz obj;
	int num = 0;

	int selection = 0;
	while ((selection = menu()) != 4)
	switch (selection)
	{
	case 1:
		std::cout << "You selected - Load quiz." << std::endl;
		obj.getloadQuiz();
		break;
	case 2:
		std::cout << "You selected - Take quiz." << std::endl << std::endl;
		std::cout << "========== Quiz: ==========" << std::endl;
		obj.getdisplayQuizQuestions();
		num = obj.getdisplayQuizQuestions();
		break;
	case 3:
		std::cout << "You selected - Show quiz results." << std::endl;
		Sobj.getPointsPossible();
		num = Sobj.getPointsPossible();
		break;
	case 4:
		break;
		default: std::cout << "Invalid selection. Please try again.\n";
		}
	std::cout << std::endl << std::endl;
	std::cout << "Thank you for using this program. Goodbye.";
	std::cin.get();
	return 0;
}
fixed the default constructor error. But now my program doesn't go through the menu in the beginning. It goes straight to asking for the file name. Then when I enter the file name it throws an exception.
You are asked for the file name whenever an object of type Quiz is created. You do this in the constructor of Student (line 171) and on line 237. Actually in the constructor of Student the whole quiz is already done.

The exception is thrown if the loaded file does not obey the requirements (line 46).
Okay I will look into it now. I think I get what you are saying about every time an object of quiz is created the program asks for the file name. Because in the constructor it says to do so. Is that correct? Thank you for the reply. Also I'm not sure why the exception is thrown on line 46 though. I have been using the exact same file since I started writing the program and numberOfQuestions is always equal to six. I have checked to be sure and it is still six as it should be, and as the error check requires.
Because in the constructor it says to do so. Is that correct?
Yes, I suggest to put that code into its own function. The constructor should initialize variables and not much more.

Also I'm not sure why the exception is thrown on line 46 though.
Well, i assume that it happens on line 46 (because that the only throw). But that might be wrong. So you should use the debugger or some debug cout to find the problem.
Thanks for all the help guys. I got my program completely working as it should,and learned a lot along the way. Though I haven't got it working just yet with the constructors, I did get it working without them. I am still working on the constructors now, just so I can learn. Thanks again!
Last edited on
Topic archived. No new replies allowed.
Pages: 12