Advertisement
Guest User

Hexadecimal calculator, errors out on g++

a guest
Apr 20th, 2011
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.85 KB | None | 0 0
  1. /*
  2.  description:  This is a calculator that performs +, -, *, / and $ (exponent) on hexadecimal operands.
  3.  */
  4.  
  5. #include <iostream>
  6. #include <fstream>
  7. #include <string>
  8. #include <stdlib.h>
  9. using namespace std;
  10.  
  11. //Function declarations
  12. void doMath(string op1, string op2, char oper, string opString);
  13. string add (string op1, string op2);
  14. string sub (string op1, string op2);
  15. string mul (string op1, string op2);
  16. string div (string op1, string op2);
  17. string exp (string op1, string op2);
  18. int hexToInt(string hex);
  19. int CtoI (char ch);
  20. char ItoC (int x);
  21. //-------------------------------------------------------------------------------------------------
  22. int main ()
  23. {
  24.     ifstream in;        //Declare fstream to hold string from file
  25.     string opString, op1, op2, prompt = "Please enter the name of the file you would like to open (max 300 characters): ";
  26.     char file[300];
  27.     char oper;
  28.     bool op1b = false, operb = false;
  29.     unsigned int i = 0;
  30.    
  31.     cout << prompt << endl;     //Prompt user
  32.     cin >> file;        //Read in file
  33.     in.open(file);                             
  34.     //Check if it exists
  35.     if (!in) {
  36.         cout << "Error. File not found.";
  37.         return 1;
  38.     }
  39.     while (!in.eof())
  40.     {
  41.         op1.clear();
  42.         op2.clear();
  43.         op1b = operb = false;
  44.         opString.clear();
  45.         in >> opString;     //Read in string from file
  46.         //Read the string from file character by character
  47.         for (i = 0; i < opString.size(); i++)
  48.         {
  49.             if (!op1b)  //If we do not yet know our first operand (op1b = false, b stands for bool, clever naming eh?)
  50.             {       //Check if our next item is an operator. If it is...
  51.                 if (!(opString[i] == '+' || opString[i] == '-' || opString[i] == '*' || opString[i] == '/' || opString[i] == '$'))
  52.                     op1.push_back(opString[i]);
  53.                 else        //... when we hit an symbol, our first number is known; do not repeat this if-statement block
  54.                     op1b = true;               
  55.             }
  56.            
  57.             if (op1b && !operb)     //If we know our first operand but not our operator...
  58.             {
  59.                 oper = opString[i];     //Find out what our operator is.  Now we know it (operb = true)
  60.                 operb = true;
  61.                 i++;                //We increment i because if we did not we'd double dip on the if statement below and wind up
  62.             }                           // with an operator tacked onto the beginning of the second operand
  63.            
  64.             if (op1b && operb)      //If we know our first operand and the operation, let's find operand #2
  65.             {
  66.                 if (opString[i] == '=')     //If we have an =, we know all our info. Proceed to operation.
  67.                     break;
  68.                 else
  69.                 {
  70.                     op2.push_back(opString[i]);     //Add to op2.
  71.                 }
  72.             }
  73.         }
  74.         if (op1.size() <= 40 || op2.size() <= 40)       //Max operator size is 40
  75.             doMath(op1,op2,oper, opString);
  76.         else
  77.             cout << "Operand too large.\n";
  78.     }
  79.     return 0;
  80. }
  81. //-------------------------------------------------------------------------------------------------
  82. void doMath(string op1, string op2, char oper, string opString)
  83. {
  84.     string ans;
  85.     switch (oper)       //Determine what to do.
  86.     {
  87.         case '+':   //Addition
  88.             ans = add(op1,op2);
  89.             break;
  90.         case '-':
  91.             ans = sub(op1,op2);
  92.             break;
  93.         case '*':
  94.             ans = mul(op1,op2);
  95.             break;
  96.         case '/':
  97.             ans = div(op1,op2);
  98.             break;
  99.         case '$':
  100.             ans = exp(op1,op2);
  101.             break;
  102.     }
  103.    
  104.     opString.append(ans);
  105.     cout << opString << endl;       //Display final answer
  106. }
  107. //-------------------------------------------------------------------------------------------------
  108. string add (string op1, string op2)
  109. {
  110.     string result;
  111.     string carry;
  112.     int length1 = op1.size(), length2 = op2.size();
  113.     int i, num, sum, m, c = 0, j, k;
  114.     string str;
  115.     char chr[1];
  116.    
  117.     //Make equal size
  118.     if (length2 > length1)  //Make each operand have equal number of digits; add leading 0s
  119.     {
  120.         num = length2 - length1;       
  121.         for (i = 0; i < num; i++)
  122.             str.push_back('0');
  123.         op1.insert(0,str);
  124.     }
  125.     else if (length1 > length2) //Make each operand have equal number of digits; add leading 0s
  126.     {
  127.         num = length1 - length2;       
  128.         for (i = 0; i < num; i++)
  129.             str.push_back('0');
  130.         op2.insert(0,str);
  131.     }
  132.     //cout << endl << "OP1 AFTER: " << op1 << endl << "OP2 AFTER: " << op2 << endl << endl;
  133.     //Do the work of adding
  134.     for (i = op1.size()-1; i >= 0; i--)
  135.     {  
  136.         j = k = 0;
  137.         //Convert char to int
  138.         j = (CtoI(op1[i]));
  139.         k = (CtoI(op2[i]));
  140.        
  141.         //cout << endl << "Op 1 at pos i (j): " << j << "   Op 2 at pos i (k): " << k << endl << endl;
  142.        
  143.         sum = j + k + c;
  144.         carry.clear();
  145.         c = 0;
  146.        
  147.         if (sum >= 10)
  148.         {
  149.             if (sum > 15 && sum < 26)       //Value is in between 10 and 19 (hex), so assign appropriate digit to result
  150.             {
  151.                 sum -= 16;
  152.                 m = sprintf(chr, "%u", sum);
  153.                 result.insert(0,chr);
  154.                 c = 1;
  155.                 carry.push_back('1');
  156.             }
  157.             if (sum >= 26)              //Value is greater than hex 19, (but implicitly less than hex 20/dec 31), so push a carry then
  158.             {                           // proceed to swith statement below.  Decrement 16 in order to reuse same cases as before.
  159.                 sum -= 16;
  160.                 carry.push_back('1');
  161.                 c = 1;
  162.             }
  163.             switch (sum)        //Long a$$ switch statement
  164.             {
  165.                 case 10:                    //When our decimal sum = 10-15 (or 26-31; hex A-F or 1A-1F), we need to replace the decimal
  166.                     result.insert(0,"A");   // representations of those numbers with their hexadecimal representation (A-F).
  167.                     break;
  168.                 case 11:
  169.                     result.insert(0,"B");
  170.                     break;
  171.                 case 12:
  172.                     result.insert(0,"C");
  173.                     break;
  174.                 case 13:
  175.                     result.insert(0,"D");
  176.                     break;
  177.                 case 14:
  178.                     result.insert(0,"E");
  179.                     break;
  180.                 case 15:
  181.                     result.insert(0,"F");
  182.                     break;
  183.             }
  184.         }
  185.         else
  186.         {
  187.             m = sprintf(chr, "%u", sum);
  188.             result.insert(0, chr);
  189.         }
  190.     }
  191.     if (c != 0)     //If we have left over carry
  192.     {
  193.         m = sprintf(chr, "%u", c);
  194.         result.insert(0, chr);
  195.     }
  196.     //cout << " FINAL RESULT: " << result << endl << endl;
  197.    
  198.     return result;
  199. }
  200. //-------------------------------------------------------------------------------------------------
  201. string sub (string op1, string op2)
  202. {
  203.     string result;
  204.     string borrow;
  205.     int length1 = op1.size(), length2 = op2.size();
  206.     int i, num, difference, m, b = 0, j, k;
  207.     string str;
  208.     char chr[1];
  209.     /*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)
  210.         since we are not anticipating bad input for subtraction alone. This will NOT verify if there are leading 0s. */
  211.     //If we try to subtract a larger number, we can't; go back.
  212.     if (length2 > length1)
  213.         return op1;
  214.     else if (length1 == length2)
  215.     {
  216.         for (i = 0; i < length1; i++)   //Test each value in the string
  217.         {
  218.             //Convert char to int
  219.             j = (CtoI(op1[i]));     //Op1
  220.             k = (CtoI(op2[i]));     //Op2
  221.                     //Return op1 if too big
  222.                 if (j > k)
  223.                     break;
  224.             if (j < k)
  225.                 return op1;
  226.                
  227.         }
  228.     }
  229.     if (length1 > length2)  //Make each operand have equal number of digits; add leading 0s
  230.     {
  231.         num = length1 - length2;
  232.         for (i = 0; i < num; i++)
  233.             str.push_back('0');
  234.         op2.insert(0,str);
  235.     }
  236.    
  237.     for (i = op1.size()-1; i >= 0; i--)
  238.     {
  239.         j = k = 0;
  240.         //Convert char to int
  241.         j = (CtoI(op1[i]));     //Op1
  242.         k = (CtoI(op2[i]));     //Op2
  243.        
  244.         //cout << endl << "Op 1 at pos i (j): " << j << "   Op 2 at pos i (k): " << k << endl << endl;
  245.         if (k <= j)     //Make sure second number is less than or equal to the first one; if not, we borrow later.
  246.         {
  247.             difference = j - k;     // difference = op1 - op2
  248.            
  249.             if (difference >= 10)       //If our difference is >10, store our result as hex
  250.             {
  251.                 switch (difference)
  252.                 {
  253.                     case 15:
  254.                         result.insert(0,"F");
  255.                         break;
  256.                     case 14:
  257.                         result.insert(0,"E");
  258.                         break;
  259.                     case 13:
  260.                         result.insert(0,"D");
  261.                         break;
  262.                     case 12:
  263.                         result.insert(0,"C");
  264.                         break;
  265.                     case 11:
  266.                         result.insert(0,"B");
  267.                         break;
  268.                     case 10:
  269.                         result.insert(0,"A");
  270.                         break;
  271.                 }
  272.             }
  273.             else
  274.             {
  275.                 m = sprintf(chr, "%u", difference);
  276.                 result.insert(0, chr);
  277.             }
  278.         }
  279.         else if (k > j)     //If our second number's current place is greater than our first, we need to borrow
  280.         {
  281.             str.clear();   
  282.             str += op1[i];
  283.             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
  284.             //cout << "NEW BORROWED BIT: " << str << endl << endl;
  285.             //Make sure we decrement 1 from next place value...
  286.             if (i > 0)          //Make sure we do not get the index out of bounds
  287.                 b = i-1;        //Get index for next left value
  288.             while (b >= 0)      //We need to decrement 1 from the column we borrow from. If we cannot borrow, continue down the line until
  289.             {                   // we find one we can borrow from, updating each column as necessary.
  290.                 if (op1[b] != '0')  //If we need to borrow, make sure it's not 0
  291.                 {
  292.                     m = CtoI(op1[b]);   //Retrieve value in that spot  
  293.                     m -= 1;             //Decrement that place value by 1 since borrowing
  294.                     chr[0] = ItoC(m);   //Convert back to char
  295.                     op1[b] = chr[0];    //Replace place with new decremented value
  296.                     break;              //Exit loop; we're done borrowing.
  297.                 }
  298.                 else if (op1[b] == '0') //If we cannot borrow from here (since the place is 0), change its value to 'F' and continue down
  299.                 {                       // until we find a value we can borrow from.
  300.                     op1[b] = 'F';
  301.                     b--;
  302.                 }
  303.             }
  304.             //Perform actual subtraction with new adjusted/borrowed values
  305.             j = hexToInt(str);  //Convert to hex
  306.             k = (CtoI(op2[i]));
  307.            
  308.             difference = j - k;         //Difference = op1 (after borrow) - op2;
  309.            
  310.             if (difference >= 10)       //If our difference is >10, store our result as hex
  311.             {
  312.                 switch (difference)
  313.                 {
  314.                     case 15:
  315.                         result.insert(0,"F");
  316.                         break;
  317.                     case 14:
  318.                         result.insert(0,"E");
  319.                         break;
  320.                     case 13:
  321.                         result.insert(0,"D");
  322.                         break;
  323.                     case 12:
  324.                         result.insert(0,"C");
  325.                         break;
  326.                     case 11:
  327.                         result.insert(0,"B");
  328.                         break;
  329.                     case 10:
  330.                         result.insert(0,"A");
  331.                         break;
  332.                 }
  333.             }
  334.             else
  335.             {
  336.                 m = sprintf(chr, "%u", difference);
  337.                 result.insert(0, chr);                 
  338.             }
  339.         }
  340.     }
  341.     //Truncate extra leading 0s if applicable
  342.     //Check our result size, too. Make sure we don't erase our only 0 in case we have op1 = op2 and then op1-op2!
  343.         while (result[0] == '0' && result.size() > 1)   //If first spot == 0
  344.             result.erase(0,1);      // erase it (erase between index 0 and index 1)
  345.    
  346.     return result;
  347. }
  348. //-------------------------------------------------------------------------------------------------
  349. string mul (string op1, string op2)
  350. {
  351.     string count, result, str;
  352.     /*  * 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
  353.      add x to itself y many times in the expression x*y.  */
  354.     result.clear();     //Result starts at 0. This will cumulatively grow with the successive additions of the number in question.
  355.     while ("0" != op2)  {
  356.         result = add(result,op1);
  357.         op2 = sub(op2,"1");
  358.     }
  359.     return result;
  360. }
  361. //-------------------------------------------------------------------------------------------------
  362. string div (string op1, string op2)
  363. {
  364.     string result, str, count, last;
  365.     int m;
  366.     char chr[1];
  367.     /*  / 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
  368.       just need to subtract y from x until we hit 0. We may or may not have a remainder.  */
  369.     result = op1;
  370.     count = "0";
  371.     while (true)
  372.     {
  373.         last = result;
  374.         result = sub(result, op2);
  375.         if (result == last)
  376.             break;
  377.         else
  378.             count = add(count, "1");
  379.     }
  380.     m = hexToInt(result);
  381.     switch (m)
  382.     {
  383.         case 15:
  384.             result.clear();
  385.             result.assign("F");
  386.             break;
  387.         case 14:
  388.             result.clear();
  389.             result.assign("E");
  390.             break;
  391.         case 13:
  392.             result.clear();
  393.             result.assign("D");
  394.             break;
  395.         case 12:
  396.             result.clear();
  397.             result.assign("C");
  398.             break;
  399.         case 11:
  400.             result.clear();
  401.             result.assign("B");
  402.             break;
  403.         case 10:
  404.             result.clear();
  405.             result.assign("A");
  406.             break;
  407.     }
  408.     str = "Quotient " + count + ", Remainder " + result;
  409.     return str;
  410. }
  411. //-------------------------------------------------------------------------------------------------
  412. string exp(string op1, string op2)
  413. {
  414.     string result, temp, count;
  415.     temp.assign("0");
  416.     result.assign("1");
  417.    
  418.     while ("0" != op2)  {
  419.         result = mul(result,op1);
  420.         op2 = sub(op2,"1");
  421.     }
  422.    
  423.     return result;
  424. }
  425. //Convert chars to ints
  426. int CtoI (char ch)
  427. {
  428.     int result;
  429.     //0 - 9
  430.     if ((int) ch > 47 && (int) ch < 58)
  431.     {
  432.         return(int (ch) - 48);
  433.     }
  434.     //A - F
  435.     else if ((int) ch > 64 && (int) ch < 71)
  436.     {
  437.         return(int (ch) - 55);
  438.     }
  439.    
  440.     return result;
  441. }
  442. //-------------------------------------------------------------------------------------------------
  443. //Convert int to char
  444. char ItoC (int x)
  445. {
  446.     //0-9
  447.     char result;
  448.     if (x >= 0 && x < 10)
  449.     {
  450.         result = char (x + 48);
  451.     }
  452.     //10-15
  453.     else if (x >= 10 && x < 16)
  454.     {
  455.         result = char (x + 55);
  456.     }
  457.  
  458. }
  459. //works for 2 digit hex nums only
  460. int hexToInt(string hex)
  461. {
  462.     int x, y, z;
  463.     for (int i = 0; i < hex.size(); i++)
  464.     {
  465.         if (i == 0)
  466.         {
  467.             x = CtoI(hex[i]);
  468.             x *= 16;
  469.         }
  470.         if (i == 1)
  471.             y = CtoI(hex[i]);
  472.     }
  473.     z = x + y;
  474.     return z;
  475. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement