Math tutor program

I have been able to get the program to put out the random numbers for the addition problem and tell the user if they're correct, but I have been unsuccessful in my attempts to get the program to loop when the user inputs 'Y'. The teacher's instructions are as follows: "Each time the tutor is played the program should output the current question as well as the result of the users input. In addition, once the user quits the tutor, statistics should be displayed showing the total number of questions this session and the number the user was correct. Finally, using data in the provided input file the user should be shown how many questions they have been asked overall and the number of correct answers overall they have. This data should then be written to the math.txt file so that the numbers are accurate and can be read in the next time the user plays." This is what I have so far.
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
  #include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>

using namespace std;

void seedRandom()
{
	srand (time(NULL));
}

int getRandomInt(int lo, int hi)
{
	return rand() % (hi - lo) + lo;
}
char userLetter;
int main()
{
	const int LOW = 1;
	const int HIGH = 1000;

	
	int num1,			
		num2,			
		numCorrect,			
		numUser;	
			

	seedRandom();		

	num1 = getRandomInt (LOW, HIGH);		
	num2 = getRandomInt (LOW, HIGH);	
	numCorrect = num1 + num2;
	userLetter = 0;

	cout << "Would you still like to practice math (Y/N)?"<<endl;
	cin >> userLetter;
	if (userLetter == 'Y' || userLetter == 'y'){
	cout << "Please enter your answer to the following problem." << endl;
	cout << setw(5) << num1 << endl;
	cout << "+ " << setw(3) << num2 << endl;
	cout << "-----" << endl;
	cout << "  ";
	cin >> numUser;

	if (numUser == numCorrect)
	{
		cout << "Good job! You are correct." << endl;
	}
	else
	{
		cout << "Sorry. Maybe you should try using a calculator because the correct answer is " << numCorrect << "."<<endl;
	}
}	
	else if (userLetter == 'N' || userLetter == 'n')
	{
		cout << "Thanks for playing!"<<endl;
	}
	else if (userLetter != 'N' || userLetter != 'n' || userLetter != 'Y' || userLetter != 'y')
	{
		cout << "Invalid input."<<endl;
	}



	return 0;
}
Hello csc130,

Welcome to the forum and thank you for using code tags.

Line 10 does not need to be in a function. You can replace line 30 with line 10 and it will work fine.

Line 17 does not need to be a global variable. It will work fine inside main and it should be initialized to 'Y' when defined. Also it is a good practice to initialize all you variables.

Initializing "userLetter" when line 35 can be deleted.

Line 37 - 63 could be put into a while or do/while loop. I would normally use a do/while loop.

I will have to work on it for awhile because that existing code may need changed a little. You will have to add some code to ask the user to play again before the loop ends.

Hope that helps for now,

Andy
Thank you so much. I am still working on it, but look forward to hearing from you!
Hello csc130,

I have something working, but I wanted to see what you come up with first.

Andy
I have the loop now, but for some reason it isn't letting me input at line 47 and is just automatically saying that the problem is wrong.
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
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>

using namespace std;

void seedRandom()
{
	srand (time(NULL));
}

int getRandomInt(int lo, int hi)
{
	return rand() % (hi - lo) + lo;
}
int userLetter;
int main()
{
	const int LOW = 1;
	const int HIGH = 1000;

	
	int num1,			
		num2,			
		numCorrect,			
		numUser;	
			
do {
	seedRandom();		

	num1 = getRandomInt (LOW, HIGH);		
	num2 = getRandomInt (LOW, HIGH);	
	numCorrect = num1 + num2;
	userLetter = 0;

	
		cout << "Would you like to practice math (Y/N)?"<<endl;
		cin >> userLetter;
	//if (userLetter == 'Y' || userLetter == 'y')
	{
	cout << "Please enter your answer to the following problem." << endl;
	cout << setw(5) << num1 << endl;
	cout << "+ " << setw(3) << num2 << endl;
	cout << "-----" << endl;
	cout << "  ";
	cin >> numUser;

	if (numUser == numCorrect)
	{
		cout << "Good job! You are correct." << endl;
	}
	else
	{
		cout << "Sorry. Maybe you should try using a calculator because the correct answer is " << numCorrect << "."<<endl;
	}
}
}while(userLetter == 'Y' || userLetter == 'y');	
	if (userLetter == 'N' || userLetter == 'n')
	{
		cout << "Thanks for playing!"<<endl;
	}
return 0;
}
I'm just trying to get the loop to work before I work on writing and reading from the math.txt file.
Ok, so I scrapped a lot of stuff and have made some progress with the loops, but i need it to start over if the input is invalid. I can also send you the random files if I need to.
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
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>

using namespace std;

void seedRandom()
{
	srand (time(NULL));
}

int getRandomInt(int lo, int hi)
{
	return rand() % (hi - lo) + lo;
}
char userLetter;
int main()
{
	const int LOW = 1;
	const int HIGH = 1000;

	
	int num1,			
		num2,			
		numCorrect,			
		numUser;	
			
	//do{
	seedRandom();
		userLetter = 0;		
	do{cout << "Would you like to use the math tutor?"<<endl;
	cin >> userLetter;

	num1 = getRandomInt (LOW, HIGH);		
	num2 = getRandomInt (LOW, HIGH);	
	numCorrect = num1 + num2;
	if (userLetter == 'Y' || userLetter == 'y')
	{cout << "Please enter your answer to the following problem." << endl;
	cout << setw(5) << num1 << endl;
	cout << "+ " << setw(3) << num2 << endl;
	cout << "-----" << endl;
	cout << "  ";
	cin >> numUser;

	if (numUser == numCorrect)
	{
		cout << "Good job! You are correct." << endl;
	}
	else
	{
		cout << "Sorry. Maybe you should try using a calculator because the correct answer is " << numCorrect << "."<<endl;
	}
	}
	} while(userLetter == 'Y' || userLetter == 'y');
	while (userLetter == 'N' || userLetter == 'n'){
		cout << "Thanks For Playing!"<<endl;
		break;
	}
	while (userLetter != 'N' || userLetter != 'n' || userLetter != 'Y' || userLetter != 'y'){
		cout << "Invalid Input"<<endl;
		break;
	}
	return 0;
}
Hello csc130,

Getting better, but not there yet.

Again the function "seedRandon" is not needed. "srand" should only be called once at the beginning of main. Calling "srand" more than once could lead to problems. After seeing the warnings from my compiler this is what should be used above the do/while loop: srand(static_cast<size_t>(time(NULL))); because the call to "time returns a "size_t" or "unsigned int".

The function "getRandomInt" works, but is not needed. This is most likely optimized to an inline function by the compiler at compile time. For two uses you could just as easily call "rand" where the function call is.

Line 17 does not need to be a global variable. It should be defined inside main where it is used.

The problem you are having starts at line 33 with the first "cin". It is asking the user to enter "Y" or "N" which is entered as "Y enter key". This will extract the "Y" into "userLetter" leaving the "\n" in the input buffer. The next call to "cin" will extract the "\n" from the input buffer and not wait for any keyboard entry. I put a comment on lines 32 and 33 for now and it worked.

The problem with the do/while loop not working starts at line 31 when you set "userLetter" to "\0". Because "userLetter" is a "char" it is not the number zero.but ASCII "0" or "\0". So, when you reach the do/while condition "\0" is not "Y" or "y" and it fails. Line 31 should not be there. "userLetter" should be defined and initialized to "Y".

The two while loops starting at line 56 should not be while loops and if either would be true it would end up being an endless loop.

The first while loop at line 56 is not needed at all. The "cout" statement needs to go before the return.

The second while loop either needs to be an else to an if before the do/while loop or use an outer do/while loop moving lines 32 ans 33 up to be part of the outer do/while loop. The if statement approach only lets the program work once if there is bad input where a do/while loop will continue until you enter good input.

My first rework of your first code had some minor changes to make what you had work. The same is true for the second version. I was able to keep what you had just rearranged it a little.

You are close.

Hope that helps,

Andy
Last edited on
Hello csc130,

Earlier I said:
The problem you are having starts at line 33 with the first "cin". It is asking the user to enter "Y" or "N" which is entered as "Y enter key". This will extract the "Y" into "userLetter" leaving the "\n" in the input buffer. The next call to "cin" will extract the "\n" from the input buffer and not wait for any keyboard entry. You can disregard this because I found that "char userLetter" some how changed to "int userLetter" and I did not do this. This caused a problem when getting user input because it was not storing a letter, but a number.

Just before the do/while loop ends I added this:
1
2
std::cout << "\n Would yo like to play again? ";
std::cin >> userLetter;

and with "userLetter" defined as a char" it works now.

Sorry for the confusion.

Hope that helps,

Andy
Last edited on
Hey Andy,
I'm having one last problem that I can't figure out. I have an if statement at the end to total up the number of times the user has attempted questions if the file "math.txt" has already been opened and if not it should open the file and save the information from that attempt which should be the initial. I believe my problem is in the logic of the if statement at the end, because it will not save my overall attempts and will only overwrite what I have saved instead of adding to 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
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
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
#include <fstream>
using namespace std;

void seedRandom()
{
	srand (time(NULL));
}

int getRandomInt(int lo, int hi)
{
	return rand() % (hi - lo) + lo;
}

int main()
{
	char userLetter;
	const int LOW = 1;
	const int HIGH = 1000;
	int value = 0;
	ofstream writeFile;
	ifstream readFile;
	
	

	double correctAnswers = 0;
	double questionsAttempted = 0;
	double overallQuestions = 0;
	double overallCorrect = 0;
	int num1,			
		num2,			
		numCorrect,			
		numUser;	
			
	seedRandom();
		userLetter = 0;		
	do{




	cout << "Would you like to use the math tutor?(Y or N)"<<endl;
	cin >> userLetter;

	num1 = getRandomInt (LOW, HIGH);		
	num2 = getRandomInt (LOW, HIGH);	
	numCorrect = num1 + num2;
	if (userLetter == 'Y' || userLetter == 'y')

		

	{ 
	questionsAttempted++;
	cout << "Please enter your answer to the following problem." << endl;
	cout << setw(5) << num1 << endl;
	cout << "+ " << setw(3) << num2 << endl;
	cout << "-----" << endl;
	cout << "  ";
	cin >> numUser;
	


	if (numUser == numCorrect)
	{
		cout << "Good job! You are correct." << endl;
		correctAnswers++; 
	}
	else
	{
		cout << "Sorry. Maybe you should try using a calculator because the correct answer is " << numCorrect << "."<<endl;
	}
	}
	


	} while(userLetter == 'Y' || userLetter == 'y');






	while (userLetter == 'N' || userLetter == 'n'){
		cout << "Thanks For Playing!"<<endl;
		break;
	}



	while (userLetter != 'N' || userLetter != 'n' || userLetter != 'Y' || userLetter != 'y'){
		cout << "Invalid Input"<<endl;
		break;
	}
 



	cout << "This session you had "<< correctAnswers << " correct answer on " << questionsAttempted << " questions meaning you scored a " << (correctAnswers/questionsAttempted) * 100 << "%" << endl;
	
	if(writeFile){
	writeFile.open("math.txt");
	readFile.open("math.txt");
	readFile >> overallQuestions;
	overallQuestions = overallQuestions + questionsAttempted;
	readFile >> overallCorrect;
	overallCorrect = overallCorrect + correctAnswers;
    writeFile << overallQuestions << endl;
	writeFile << overallCorrect << endl;
	writeFile.close();
	readFile.close();
	cout << "Overall you have scored " << overallCorrect << " questions correctly out of " << overallQuestions << ". Your overall average is " << (overallCorrect/overallQuestions) * 100 << "%" << endl;

     }
	else
	{
	writeFile.open("math.txt");
 	writeFile << questionsAttempted << endl;
	writeFile << correctAnswers<< endl;
	cout << "Overall you have scored " << correctAnswers << " questions correctly out of " << questionsAttempted << ". Your overall average is " << (correctAnswers/questionsAttempted) * 100 << "%" << endl;

	}
	writeFile.close();
	readFile.close();
	return 0;
}
Hello csc130,

With just a quick look on line 104 try this writeFile.open("math.txt, std::ios::app");.

You need to open the file for append if you want to add to it.

The same applies to line 119.

You may have a problem opening the same file for input and output at the same time the way you are doing. You could define the file stream as a "fstream" and open the file with "in | out | app". That is one I have not worked with yet, so I am not exactly sure how the write and read would work.

Hope that helps,

Andy
Hey Andy,
I have it reading and writing from the file as it should and I thought I was done, but I have a problem where I say 'N' when asked if I want to continue. The program behaves the same no matter what I input as long as it's not 'Y' or 'y' and outputs both "Thanks For Playing!" and "Invalid Input.". It is suppose to output one or the other then the stats for the session. Thanks for the help and hopefully this will be my last question.
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
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
#include <fstream>
using namespace std;

void seedRandom()
{
	srand (time(NULL));
}

int getRandomInt(int lo, int hi)
{
	return rand() % (hi - lo) + lo;
}

int main()
{
	char userLetter;
	const int LOW = 1;
	const int HIGH = 1000;
	int value = 0;
	ofstream writeFile;
	ifstream readFile;
	
	

	double correctAnswers = 0;
	double questionsAttempted = 0;
	double overallQuestions = 0;
	double overallCorrect = 0;
	int num1,			
		num2,			
		numCorrect,			
		numUser;	
			
	seedRandom();
		userLetter = 0;		
	do{




	cout << "Would you like to use the math tutor?(Y or N)"<<endl;
	cin >> userLetter;

	num1 = getRandomInt (LOW, HIGH);		
	num2 = getRandomInt (LOW, HIGH);	
	numCorrect = num1 + num2;
	if (userLetter == 'Y' || userLetter == 'y')

		

	{ 
	questionsAttempted++;
	cout << "Please enter your answer to the following problem." << endl;
	cout << setw(5) << num1 << endl;
	cout << "+ " << setw(3) << num2 << endl;
	cout << "-----" << endl;
	cout << "  ";
	cin >> numUser;
	


	if (numUser == numCorrect)
	{
		cout << "Good job! You are correct." << endl;
		correctAnswers++; 
	}
	else if(numUser != numCorrect)
	{
		cout << "Sorry. The correct answer is " << numCorrect << "."<<endl;
	}
	}
	


	} while(userLetter == 'Y' || userLetter == 'y');






	do{
		cout << "Thanks For Playing!"<<endl;
		break;

	}while (userLetter == 'N' || userLetter == 'n');



	do{
		cout << "Invalid Input"<<endl;
		break;
	} while (userLetter != 'N' || userLetter != 'n' || userLetter != 'Y' || userLetter != 'y');
 



	cout << "This session you had "<< correctAnswers << " correct answer on " << questionsAttempted << " questions meaning you scored a " << (correctAnswers/questionsAttempted) * 100 << "%" << endl;
	
	
	readFile.open("math.txt");
	readFile >> overallQuestions;
	overallQuestions = overallQuestions + questionsAttempted;
	readFile >> overallCorrect;
	overallCorrect = overallCorrect + correctAnswers;

	readFile.close();
	
	cout << "Overall you have scored " << overallCorrect << " questions correctly out of " << overallQuestions << ". Your overall average is " << (overallCorrect/overallQuestions) * 100 << "%" << endl;

     
	writeFile.open("math.txt");
 	writeFile << questionsAttempted << endl;
	writeFile << correctAnswers<< endl;


	
	writeFile.close();
		return 0;
}
Hello csc130,

The two things I see right off:

1)
1
2
3
4
5
do{
		cout << "Thanks For Playing!"<<endl;
		break;

	}while (userLetter == 'N' || userLetter == 'n');

This is over kill for just a simple "cout" statement. And the do/while loop does not even loop one time just to print one line. ONLY line 2 is needed.

2)
1
2
3
4
do{
		cout << "Invalid Input"<<endl;
		break;
	} while (userLetter != 'N' || userLetter != 'n' || userLetter != 'Y' || userLetter != 'y');

This should not even be where it is that is why you are seeing it just before the program ends because you tell the output to be there. This bit of code should be an else statement at line 76. Which is an else statement to line 51. This way you will stay in the loop until either "Y" or "N", either case, is entered.

FYI line 97 the use of "!=" and "||" does not work well together. Normally when more than one "!=" is used "&&" tends to work better. Not something you need to worry about in your program because it should not be there at all.

I have not checked the file reading and writing yet because I do not know what the input file looks like, so I will have to work on it.

Hope that helps,

Andy
Hello csc130,

This is what I worked out using what you have. Read the comments in the 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
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
#include <iostream>
#include <iomanip>
#include <ctime>
//#include <cstdlib>  // <--- Not needed.
#include <fstream>

//using namespace std;

void seedRandom()
{
	srand(static_cast<size_t>(time(NULL)));
}

int getRandomInt(int lo, int hi)
{
	return rand() % (hi - lo) + lo;
}

int main()
{
	char userLetter{ 'Y' };  // <--- Changed.

	const int LOW = 1;
	const int HIGH = 1000;
	int value = 0;
	std::ofstream writeFile;
	std::ifstream readFile;

	double correctAnswers = 0;
	double questionsAttempted = 0;
	double overallQuestions = 0;
	double overallCorrect = 0;

	int num1,
		num2,
		numCorrect,
		numUser;

	seedRandom();

	do {
		std::cout << "\n Would you like to use the math tutor?(Y or N) ";  // <--- Removed the std::endl.
		std::cin >> userLetter;

		num1 = getRandomInt(LOW, HIGH);
		num2 = getRandomInt(LOW, HIGH);
		numCorrect = num1 + num2;

		if (userLetter == 'Y' || userLetter == 'y')
		{
			questionsAttempted++;
			// Changed output slightly.
			std::cout << "\n Please enter your answer to the following problem." << std::endl;
			std::cout << std::setw(6) << num1 << std::endl;
			std::cout << " + " << std::setw(3) << num2 << std::endl;
			std::cout << " -------" << std::endl;
			std::cout << "   ";
			std::cin >> numUser;

			if (numUser == numCorrect)
			{
				std::cout << "\n Good job! You are correct." << std::endl;
				correctAnswers++;
			}
			else if (numUser != numCorrect)
			{
				std::cout << "\n Sorry. The correct answer is " << numCorrect << "." << std::endl;
			}
		}
		else  if (userLetter != 'N' && userLetter != 'n')  // <--- Changed.
			std::cout << "\n Invalid Input" << std::endl;


	} while (userLetter == 'Y' || userLetter == 'y');

	std::cout << "\n Thanks For Playing!" << std::endl;  // <--- Changed.

	std::cout << "\n This session you had " << correctAnswers << " correct answer on " << questionsAttempted << " questions meaning you scored a " << (correctAnswers / questionsAttempted) * 100 << "%" << std::endl;


	readFile.open("math.txt");
	readFile >> overallQuestions;
	overallQuestions = overallQuestions + questionsAttempted;
	readFile >> overallCorrect;
	overallCorrect = overallCorrect + correctAnswers;

	readFile.close();

	std::cout << "\n Overall you have scored " << overallCorrect << " questions correctly out of " << overallQuestions << ". Your overall average is " << (overallCorrect / overallQuestions) * 100 << "%" << std::endl;


	writeFile.open("math.txt");
	writeFile << overallQuestions << std::endl;  // <--- Changed.
	writeFile << overallCorrect << std::endl;



	writeFile.close();

	return 0;
}


Line 70 I had to make an else if from the original else I was thinking of. Notice how I used "&&" with "!=".

Hope that helps,

Andy

P.S. I changed the writeFile to output the overall totals not the current totals. I thought it made more sense, but maybe that is not what you wanted.
Last edited on
Thanks So Much. This is really what I need
Registered users can post here. Sign in or register to post.