Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- description: This is a calculator that performs +, -, *, / and $ (exponent) on hexadecimal operands.
- */
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <stdlib.h>
- using namespace std;
- //Function declarations
- void doMath(string op1, string op2, char oper, string opString);
- string add (string op1, string op2);
- string sub (string op1, string op2);
- string mul (string op1, string op2);
- string div (string op1, string op2);
- string exp (string op1, string op2);
- int hexToInt(string hex);
- int CtoI (char ch);
- char ItoC (int x);
- //-------------------------------------------------------------------------------------------------
- int main ()
- {
- ifstream in; //Declare fstream to hold string from file
- string opString, op1, op2, prompt = "Please enter the name of the file you would like to open (max 300 characters): ";
- char file[300];
- char oper;
- bool op1b = false, operb = false;
- unsigned int i = 0;
- cout << prompt << endl; //Prompt user
- cin >> file; //Read in file
- in.open(file);
- //Check if it exists
- if (!in) {
- cout << "Error. File not found.";
- return 1;
- }
- while (!in.eof())
- {
- op1.clear();
- op2.clear();
- op1b = operb = false;
- opString.clear();
- in >> opString; //Read in string from file
- //Read the string from file character by character
- for (i = 0; i < opString.size(); i++)
- {
- if (!op1b) //If we do not yet know our first operand (op1b = false, b stands for bool, clever naming eh?)
- { //Check if our next item is an operator. If it is...
- if (!(opString[i] == '+' || opString[i] == '-' || opString[i] == '*' || opString[i] == '/' || opString[i] == '$'))
- op1.push_back(opString[i]);
- else //... when we hit an symbol, our first number is known; do not repeat this if-statement block
- op1b = true;
- }
- if (op1b && !operb) //If we know our first operand but not our operator...
- {
- oper = opString[i]; //Find out what our operator is. Now we know it (operb = true)
- operb = true;
- i++; //We increment i because if we did not we'd double dip on the if statement below and wind up
- } // with an operator tacked onto the beginning of the second operand
- if (op1b && operb) //If we know our first operand and the operation, let's find operand #2
- {
- if (opString[i] == '=') //If we have an =, we know all our info. Proceed to operation.
- break;
- else
- {
- op2.push_back(opString[i]); //Add to op2.
- }
- }
- }
- if (op1.size() <= 40 || op2.size() <= 40) //Max operator size is 40
- doMath(op1,op2,oper, opString);
- else
- cout << "Operand too large.\n";
- }
- return 0;
- }
- //-------------------------------------------------------------------------------------------------
- void doMath(string op1, string op2, char oper, string opString)
- {
- string ans;
- switch (oper) //Determine what to do.
- {
- case '+': //Addition
- ans = add(op1,op2);
- break;
- case '-':
- ans = sub(op1,op2);
- break;
- case '*':
- ans = mul(op1,op2);
- break;
- case '/':
- ans = div(op1,op2);
- break;
- case '$':
- ans = exp(op1,op2);
- break;
- }
- opString.append(ans);
- cout << opString << endl; //Display final answer
- }
- //-------------------------------------------------------------------------------------------------
- string add (string op1, string op2)
- {
- string result;
- string carry;
- int length1 = op1.size(), length2 = op2.size();
- int i, num, sum, m, c = 0, j, k;
- string str;
- char chr[1];
- //Make equal size
- if (length2 > length1) //Make each operand have equal number of digits; add leading 0s
- {
- num = length2 - length1;
- for (i = 0; i < num; i++)
- str.push_back('0');
- op1.insert(0,str);
- }
- else if (length1 > length2) //Make each operand have equal number of digits; add leading 0s
- {
- num = length1 - length2;
- for (i = 0; i < num; i++)
- str.push_back('0');
- op2.insert(0,str);
- }
- //cout << endl << "OP1 AFTER: " << op1 << endl << "OP2 AFTER: " << op2 << endl << endl;
- //Do the work of adding
- for (i = op1.size()-1; i >= 0; i--)
- {
- j = k = 0;
- //Convert char to int
- j = (CtoI(op1[i]));
- k = (CtoI(op2[i]));
- //cout << endl << "Op 1 at pos i (j): " << j << " Op 2 at pos i (k): " << k << endl << endl;
- sum = j + k + c;
- carry.clear();
- c = 0;
- if (sum >= 10)
- {
- if (sum > 15 && sum < 26) //Value is in between 10 and 19 (hex), so assign appropriate digit to result
- {
- sum -= 16;
- m = sprintf(chr, "%u", sum);
- result.insert(0,chr);
- c = 1;
- carry.push_back('1');
- }
- if (sum >= 26) //Value is greater than hex 19, (but implicitly less than hex 20/dec 31), so push a carry then
- { // proceed to swith statement below. Decrement 16 in order to reuse same cases as before.
- sum -= 16;
- carry.push_back('1');
- c = 1;
- }
- switch (sum) //Long a$$ switch statement
- {
- case 10: //When our decimal sum = 10-15 (or 26-31; hex A-F or 1A-1F), we need to replace the decimal
- result.insert(0,"A"); // representations of those numbers with their hexadecimal representation (A-F).
- break;
- case 11:
- result.insert(0,"B");
- break;
- case 12:
- result.insert(0,"C");
- break;
- case 13:
- result.insert(0,"D");
- break;
- case 14:
- result.insert(0,"E");
- break;
- case 15:
- result.insert(0,"F");
- break;
- }
- }
- else
- {
- m = sprintf(chr, "%u", sum);
- result.insert(0, chr);
- }
- }
- if (c != 0) //If we have left over carry
- {
- m = sprintf(chr, "%u", c);
- result.insert(0, chr);
- }
- //cout << " FINAL RESULT: " << result << endl << endl;
- return result;
- }
- //-------------------------------------------------------------------------------------------------
- string sub (string op1, string op2)
- {
- string result;
- string borrow;
- int length1 = op1.size(), length2 = op2.size();
- int i, num, difference, m, b = 0, j, k;
- string str;
- char chr[1];
- /*Immediately check if our second operand is greater than our first. If it is, we do not do the calculation (this is mostly for division)
- since we are not anticipating bad input for subtraction alone. This will NOT verify if there are leading 0s. */
- //If we try to subtract a larger number, we can't; go back.
- if (length2 > length1)
- return op1;
- else if (length1 == length2)
- {
- for (i = 0; i < length1; i++) //Test each value in the string
- {
- //Convert char to int
- j = (CtoI(op1[i])); //Op1
- k = (CtoI(op2[i])); //Op2
- //Return op1 if too big
- if (j > k)
- break;
- if (j < k)
- return op1;
- }
- }
- if (length1 > length2) //Make each operand have equal number of digits; add leading 0s
- {
- num = length1 - length2;
- for (i = 0; i < num; i++)
- str.push_back('0');
- op2.insert(0,str);
- }
- for (i = op1.size()-1; i >= 0; i--)
- {
- j = k = 0;
- //Convert char to int
- j = (CtoI(op1[i])); //Op1
- k = (CtoI(op2[i])); //Op2
- //cout << endl << "Op 1 at pos i (j): " << j << " Op 2 at pos i (k): " << k << endl << endl;
- if (k <= j) //Make sure second number is less than or equal to the first one; if not, we borrow later.
- {
- difference = j - k; // difference = op1 - op2
- if (difference >= 10) //If our difference is >10, store our result as hex
- {
- switch (difference)
- {
- case 15:
- result.insert(0,"F");
- break;
- case 14:
- result.insert(0,"E");
- break;
- case 13:
- result.insert(0,"D");
- break;
- case 12:
- result.insert(0,"C");
- break;
- case 11:
- result.insert(0,"B");
- break;
- case 10:
- result.insert(0,"A");
- break;
- }
- }
- else
- {
- m = sprintf(chr, "%u", difference);
- result.insert(0, chr);
- }
- }
- else if (k > j) //If our second number's current place is greater than our first, we need to borrow
- {
- str.clear();
- str += op1[i];
- str.insert(0,"1"); //We will always add 16 dec (10 hex) to the first bit, so pin a "1" to the front of it
- //cout << "NEW BORROWED BIT: " << str << endl << endl;
- //Make sure we decrement 1 from next place value...
- if (i > 0) //Make sure we do not get the index out of bounds
- b = i-1; //Get index for next left value
- while (b >= 0) //We need to decrement 1 from the column we borrow from. If we cannot borrow, continue down the line until
- { // we find one we can borrow from, updating each column as necessary.
- if (op1[b] != '0') //If we need to borrow, make sure it's not 0
- {
- m = CtoI(op1[b]); //Retrieve value in that spot
- m -= 1; //Decrement that place value by 1 since borrowing
- chr[0] = ItoC(m); //Convert back to char
- op1[b] = chr[0]; //Replace place with new decremented value
- break; //Exit loop; we're done borrowing.
- }
- else if (op1[b] == '0') //If we cannot borrow from here (since the place is 0), change its value to 'F' and continue down
- { // until we find a value we can borrow from.
- op1[b] = 'F';
- b--;
- }
- }
- //Perform actual subtraction with new adjusted/borrowed values
- j = hexToInt(str); //Convert to hex
- k = (CtoI(op2[i]));
- difference = j - k; //Difference = op1 (after borrow) - op2;
- if (difference >= 10) //If our difference is >10, store our result as hex
- {
- switch (difference)
- {
- case 15:
- result.insert(0,"F");
- break;
- case 14:
- result.insert(0,"E");
- break;
- case 13:
- result.insert(0,"D");
- break;
- case 12:
- result.insert(0,"C");
- break;
- case 11:
- result.insert(0,"B");
- break;
- case 10:
- result.insert(0,"A");
- break;
- }
- }
- else
- {
- m = sprintf(chr, "%u", difference);
- result.insert(0, chr);
- }
- }
- }
- //Truncate extra leading 0s if applicable
- //Check our result size, too. Make sure we don't erase our only 0 in case we have op1 = op2 and then op1-op2!
- while (result[0] == '0' && result.size() > 1) //If first spot == 0
- result.erase(0,1); // erase it (erase between index 0 and index 1)
- return result;
- }
- //-------------------------------------------------------------------------------------------------
- string mul (string op1, string op2)
- {
- string count, result, str;
- /* * is a shortcut for + for lots of the same operand. For example, 4*3 is a different way of writing 4+4+4 or 3+3+3+3. We just need to
- add x to itself y many times in the expression x*y. */
- result.clear(); //Result starts at 0. This will cumulatively grow with the successive additions of the number in question.
- while ("0" != op2) {
- result = add(result,op1);
- op2 = sub(op2,"1");
- }
- return result;
- }
- //-------------------------------------------------------------------------------------------------
- string div (string op1, string op2)
- {
- string result, str, count, last;
- int m;
- char chr[1];
- /* / is a shortcut for - for lots of the same operand until we hit 0. For example, 12/3 is a different way of writing 12-3-3-3-3. We
- just need to subtract y from x until we hit 0. We may or may not have a remainder. */
- result = op1;
- count = "0";
- while (true)
- {
- last = result;
- result = sub(result, op2);
- if (result == last)
- break;
- else
- count = add(count, "1");
- }
- m = hexToInt(result);
- switch (m)
- {
- case 15:
- result.clear();
- result.assign("F");
- break;
- case 14:
- result.clear();
- result.assign("E");
- break;
- case 13:
- result.clear();
- result.assign("D");
- break;
- case 12:
- result.clear();
- result.assign("C");
- break;
- case 11:
- result.clear();
- result.assign("B");
- break;
- case 10:
- result.clear();
- result.assign("A");
- break;
- }
- str = "Quotient " + count + ", Remainder " + result;
- return str;
- }
- //-------------------------------------------------------------------------------------------------
- string exp(string op1, string op2)
- {
- string result, temp, count;
- temp.assign("0");
- result.assign("1");
- while ("0" != op2) {
- result = mul(result,op1);
- op2 = sub(op2,"1");
- }
- return result;
- }
- //Convert chars to ints
- int CtoI (char ch)
- {
- int result;
- //0 - 9
- if ((int) ch > 47 && (int) ch < 58)
- {
- return(int (ch) - 48);
- }
- //A - F
- else if ((int) ch > 64 && (int) ch < 71)
- {
- return(int (ch) - 55);
- }
- return result;
- }
- //-------------------------------------------------------------------------------------------------
- //Convert int to char
- char ItoC (int x)
- {
- //0-9
- char result;
- if (x >= 0 && x < 10)
- {
- result = char (x + 48);
- }
- //10-15
- else if (x >= 10 && x < 16)
- {
- result = char (x + 55);
- }
- }
- //works for 2 digit hex nums only
- int hexToInt(string hex)
- {
- int x, y, z;
- for (int i = 0; i < hex.size(); i++)
- {
- if (i == 0)
- {
- x = CtoI(hex[i]);
- x *= 16;
- }
- if (i == 1)
- y = CtoI(hex[i]);
- }
- z = x + y;
- return z;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement