Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Math Tutor.cpp : Defines the entry point for the console application.
- // Author: Ben Henning
- // Date: 10/18/2011
- // Updated: 10/27/2011
- //
- // No output provided because the program flow is too complex for standard output.
- // This satisfies criteria beyond chapters 3, 4 and 5 in which this problem is assigned.
- //
- // Ugh, probably contains memory leaks as well
- #include <iostream>
- #include <iomanip>
- #include <cstdlib>
- #include <ctime>
- #include <conio.h>
- #include <cmath>
- #include <cctype>
- using namespace std;
- #define MODE_FLOAT false
- #define MODE_INT true
- int difficulty = 1; // DEFAULT
- int difficultyDigits[] = { 1, 1, 2, 3, 3 };
- bool difficultyModes[] = { MODE_INT, MODE_FLOAT, MODE_INT, MODE_INT, MODE_FLOAT };
- int numDigits = difficultyDigits[difficulty - 1];
- bool mode = difficultyModes[difficulty - 1];
- inline float fround(float val) {
- float expansion = pow(10.f, numDigits);
- float ipart = (float)(int)floorf(val);
- // force the float to x number of decimal points
- float fpart = (float)(int)floorf((val - ipart) * expansion);
- // put it back together
- return ipart + (fpart / expansion);
- }
- struct OP {
- bool typeInt;
- OP() { this->typeInt = MODE_INT; };
- union {
- int ival;
- float fval;
- } val;
- OP operator =(OP);
- OP operator +(OP);
- OP operator -(OP);
- OP operator /(OP);
- OP operator *(OP);
- bool operator ==(OP);
- };
- OP OP::operator=(OP op) {
- if (typeInt)
- this->val.ival = op.val.ival;
- else
- this->val.fval = op.val.fval;
- return *this;
- }
- OP OP::operator+(OP op) {
- if (typeInt)
- this->val.ival += op.val.ival;
- else
- this->val.fval = fround(this->val.fval + op.val.fval);
- return *this;
- }
- OP OP::operator-(OP op) {
- if (typeInt)
- this->val.ival -= op.val.ival;
- else
- this->val.fval = fround(this->val.fval - op.val.fval);
- return *this;
- }
- OP OP::operator*(OP op) {
- if (typeInt)
- this->val.ival *= op.val.ival;
- else
- this->val.fval = fround(this->val.fval * op.val.fval);
- return *this;
- }
- OP OP::operator/(OP op) {
- if (typeInt)
- this->val.ival /= op.val.ival;
- else
- this->val.fval = fround(this->val.fval / op.val.fval);
- return *this;
- }
- bool OP::operator==(OP op) {
- if (typeInt)
- return this->val.ival == op.val.ival;
- else {
- float expansion = pow(10.f, numDigits);
- return (int)(this->val.fval * expansion) == (int)(op.val.fval * expansion);
- }
- }
- void init();
- bool handleMenu();
- template<typename T> void printResults(bool, int, bool (*func)(T, T, bool, OP *));
- void printOperation(OP, OP, char);
- bool handleAddition(OP, OP, bool, OP *);
- bool handleSubtraction(OP, OP, bool, OP *);
- bool handleMultiplication(OP, OP, bool, OP *);
- bool handleDivision(OP, OP, bool, OP *);
- // use function pointers for pratice
- bool (*add)(OP, OP, bool, OP *);
- bool (*sub)(OP, OP, bool, OP *);
- bool (*mul)(OP, OP, bool, OP *);
- bool (*divi)(OP, OP, bool, OP *); // 'div' is ambiguous for some reason...
- int main() {
- printf("Welcome to Math Tutor!\n");
- // initialize...
- init();
- while (true)
- if (!handleMenu())
- break;
- printf("Thank you for using Math Tutor!\n");
- return 0;
- }
- void init() {
- add = handleAddition;
- sub = handleSubtraction;
- mul = handleMultiplication;
- divi = handleDivision;
- srand((unsigned int) time(0));
- }
- bool handleMenu() {
- printf("\nPlease enter an option (h for help): ");
- cin.clear();
- int val = tolower(cin.get());
- // XXX: figure out how to get rid of newline by a cleaner means...
- if (val == '\n')
- val = tolower(cin.get());
- switch (val) {
- case '+': case 'a': // addition
- printResults(mode, numDigits, add);
- //cout << endl;
- break;
- case '-': case 's': // subtraction
- printResults(mode, numDigits, sub);
- //cout << endl;
- break;
- case '*': case 'm': // multiplication
- printResults(mode, numDigits, mul);
- //cout << endl;
- break;
- case '/': case 'd': // division
- printResults(mode, numDigits, divi);
- //cout << endl;
- break;
- case 'x': // settings
- {
- printf("Current difficulty level: %i\n (number digits/decimals: %i, number mode: %s)\n", difficulty,
- numDigits, mode ? "integers only" : "floating point digits");
- printf("Would you like you change the difficulty mode? (y/n): ");
- cin.clear();
- int val = tolower(cin.get());
- if (val == '\n')
- val = tolower(cin.get());
- if (val == 'y') {
- cin.clear();
- printf("New difficulty mode: ");
- int diff;
- cin >> diff;
- if (diff < 1 || diff > 5)
- printf("Error: The difficulty mode must be between 1 and 5.\n");
- else {
- difficulty = diff;
- numDigits = difficultyDigits[diff - 1];
- mode = difficultyModes[diff - 1];
- printf("New difficulty level: %i\n (number of digits/decimals: %i, number mode: %s)\n", diff,
- numDigits, mode ? "integers only" : "floating point digits");
- }
- }
- }
- break;
- case 'h': // help
- printf("Menu options:\n");
- printf(" a OR + Run the addition tutor\n");
- printf(" s OR - Run the subtraction tutor\n");
- printf(" m OR * Run the multiplication tutor\n");
- printf(" d OR / Run the division tutor\n");
- printf(" x Change the difficulty for the tutor\n");
- printf(" h Print this help menu\n");
- printf(" e Exit the application\n");
- break;
- case 'e': // exit
- return false;
- default:
- printf("Unknown menu option: %c.\n", val);
- }
- return true;
- }
- bool handleAddition(OP first, OP second, bool typeInt, OP * result) {
- printOperation(first, second, '+');
- *result = first + second;
- OP * input = new OP;
- if (typeInt) {
- int i;
- cin >> i;
- (*input).val.ival = i;
- } else {
- float f;
- cin >> f;
- (*input).val.fval = fround(f);
- }
- cin.clear();
- return *input == *result;
- }
- bool handleSubtraction(OP first, OP second, bool typeInt, OP * result) {
- printOperation(first, second, '-');
- *result = first - second;
- OP * input = new OP;
- if (typeInt) {
- int i;
- cin >> i;
- (*input).val.ival = i;
- } else {
- float f;
- cin >> f;
- (*input).val.fval = fround(f);
- }
- cin.clear();
- return *input == *result;
- }
- bool handleMultiplication(OP first, OP second, bool typeInt, OP * result) {
- printOperation(first, second, '*');
- *result = first * second;
- OP * input = new OP;
- if (typeInt) {
- int i;
- cin >> i;
- (*input).val.ival = i;
- } else {
- float f;
- cin >> f;
- (*input).val.fval = fround(f);
- }
- cin.clear();
- return *input == *result;
- }
- bool handleDivision(OP first, OP second, bool typeInt, OP * result) {
- printOperation(first, second, '/');
- *result = first / second;
- OP * input = new OP;
- if (typeInt) {
- int i;
- cin >> i;
- (*input).val.ival = i;
- } else {
- float f;
- cin >> f;
- (*input).val.fval = fround(f);
- }
- cin.clear();
- return *input == *result;
- }
- inline float frand() {
- return (float) (((double) rand()) / ((double) RAND_MAX));
- }
- inline int powi(int a, int b) {
- return (int) pow((float) a, (float) b);
- }
- template<typename T> void printResults(bool typeInt, int numDigits, bool (*func)(T, T, bool, OP *)) {
- OP * first = new OP;
- OP * second = new OP;
- OP * result = new OP;
- (*first).typeInt = (*second).typeInt = (*result).typeInt = typeInt;
- if (typeInt) {
- int expansion = powi(10, numDigits);
- (*first).val.ival = rand() % expansion;
- (*second).val.ival = rand() % expansion;
- } else {
- float expansion = pow((float) 10, (float) numDigits);
- (*first).val.fval = fround(frand() * expansion);
- (*second).val.fval = fround(frand() * expansion);
- }
- if (func(*first, *second, typeInt, result))
- printf("Congratulations! You gave the correct value. =)\n");
- else if (typeInt)
- cout << "Sorry, but the correct answer is " << (*result).val.ival << endl;
- else
- cout << "Sorry, but the correct answer is " << (*result).val.fval << endl;
- }
- void printOperation(OP a, OP b, char oper) {
- if (a.typeInt) {
- cout << ' ' << a.val.ival << endl;
- cout << oper << b.val.ival << endl;
- } else {
- cout << ' ' << a.val.fval << endl;
- cout << oper << b.val.fval << endl;
- }
- cout << "-----" << endl;
- }
Add Comment
Please, Sign In to add comment