Search code examples
c++binaryhexoctal

C++: Change of base function (i.e. hex to octal, decimal, etc.) - Output slightly off for hex values


I need to create a generic function that changes from any starting base, to any final base. I have everything down, except my original function took (and takes) an int value for the number that it converts to another base. I decided to just overload the function. I am Ok with changing between every base, but am slightly off when using my new function to take in a string hex value.

The code below should output 1235 for both functions. It does for the first one, but for the second, I am currently getting 1347. Decimal to Hex works fine - It's just the overloaded function (Hex to anything else) that is slightly off.

Thanks.

#include <iostream>
#include <stack>
#include <string>
#include <cmath>

using namespace std;

void switchBasesFunction(stack<int> & myStack, int startBase, int finalBase, int num);
void switchBasesFunction(stack<int> & myStack, int startBase, int finalBase, string s);

int main()
{

    stack<int> myStack;
    string hexNum = "4D3";

    switchBasesFunction(myStack, 8, 10, 2323);

    cout << endl << endl;

    switchBasesFunction(myStack, 16, 10, hexNum);


    return 0;
}

void switchBasesFunction(stack<int> & myStack, int startBase, int finalBase, int num)
{

    int totalVal = 0;

    string s = to_string(num);

    for (int i = 0; i < s.length(); i++)
    {
        myStack.push(s.at(i) - '0');
    }

    int k = 0;

    while (myStack.size() > 0)
    {
        totalVal += (myStack.top() * pow(startBase, k++));
        myStack.pop();

    }

    string s1;

    while (totalVal > 0)
    {

        int temp = totalVal % finalBase;
        totalVal = totalVal / finalBase;

        char c;
        if (temp < 10)
        {
            c = temp + '0';
            s1 += c;
        }

        else
        {
            c = temp - 10 + 'A';
            s1 += c;
        }

    }
    for (int i = s1.length() - 1; i >= 0; i--)
    {
        cout << s1[i];
    }
    cout << endl << endl;
}

void switchBasesFunction(stack<int> & myStack, int startBase, int finalBase, string s)
{

    int totalVal = 0;

    for (int i = 0; i < s.length(); i++)
    {
        myStack.push(s.at(i) - '0');
    }

    int k = 0;

    while (myStack.size() > 0)
    {
        totalVal += (myStack.top() * pow(startBase, k++));
        myStack.pop();

    }

    string s1;

    while (totalVal > 0)
    {

        int temp = totalVal % finalBase;
        totalVal = totalVal / finalBase;

        char c;
        if (temp < 10)
        {
            c = temp + '0';
            s1 += c;
        }

        else
        {
            c = temp - 10 + 'A';
            s1 += c;
        }

    }
    for (int i = s1.length() - 1; i >= 0; i--)
    {
        cout << s1[i];
    }
    cout << endl << endl;
}

Solution

  • Sorry, but I'm having issues understanding your code, so I thought I'd simplify it.
    Here's the algorithm / code (untested):

    void convert_to_base(const std::string& original_value,  
                         unsigned int       original_base,
                         std::string&       final_value_str,
                         unsigned int       final_base)
    {
      static const std::string digit_str =
         "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      if ((original_base > digit_str.length()) || (final_base > digit_str.length())
      {
         std::cerr << "Base value exceeds limit of " << digit_str.length() << ".\n";
         return;
      }
    
      // Parse string from right to left, smallest value to largest.
      // Convert to decimal.
      unsigned int original_number = 0;
      unsigned int digit_value = 0;
      int index = 0;
      for (index = original_value.length(); index > 0; --index)
      {
        std::string::size_type posn = digit_str.find(original_value[index];
        if (posn == std::string::npos)
        {
          cerr << "unsupported digit encountered: " << original_value[index] << ".\n";
          return;
        }
        digit_value = posn;
        original_number = original_number * original_base + digit_value;
      }
    
      // Convert to a string of digits in the final base.
      while (original_number != 0)
      {
        digit_value = original_number % final_base;
        final_value_str.insert(0, 1, digit_str[digit_value]);
        original_number = original_number / final_base;
      }
    }
    

    *Warning: code not tested via compiler.**