Reputation: 69
I've seen several examples for converting a number from decimal to hex (or base 10 to base 16), but I have a few restrictions for what I'm trying to do. I need to be able to convert a string with a decimal number into another string as a hex number. The number is potentially too big to fit inside of any primitive data types - ie: can't use ints, unsigned ints, doubles, etc...
This should be able to perform the same calculations as listed on this page. http://www.kaagaard.dk/service/convert.htm
I've tried this, but it hasn't worked for me.
The call to the function:
const int maxLen = 256;
char destination[maxLen];
int retVal = convertBase(destination, maxLen, "123487032174829820348320429437483266812812");
The function definition:
int convertBase(char* dest, int maxDestLength, const char* inputInBase10)
{
const char lookUpTable[] = { "0123456789abcdef" };
const std::string input = inputInBase10;
const unsigned int inputSize = input.length();
std::string output;
output.reserve(2 * inputSize);
for(unsigned int i = 0; i < inputSize; ++i)
{
const unsigned char c = input[i];
output.push_back(lookUpTable[c >> 4]);
output.push_back(lookUpTable[c & 15]);
}
if(output.length() < maxDestLength)
strcpy_s(dest, output.length(), output.c_str());
else
strcpy_s(dest, maxDestLength, output.c_str());
cout << dest << endl;
return strlen(dest);
}
The expected hex number: "16ae5514d07e120126dfbcb3073fddb2b8c"
The actual hex number generated: "313233343837303332313734383239383230333438333230343239343337343833323636383132383132"
Also, I keep getting an error that the buffer is too small when passing back into a char* (repeated below)
if(output.length() < maxDestLength)
strcpy_s(dest, output.length(), output.c_str());
else
strcpy_s(dest, maxDestLength, output.c_str());
Upvotes: 2
Views: 2354
Reputation: 63471
So if you're in a hurry to get anything, and are not too concerned about efficiency, try this. I've adapted a function that I wrote for the following SO question: c++ string (int) + string (int)
First, I modified the Add
function to work for any base between 2 and 36:
const int MIN_BASE = 2;
const int MAX_BASE = 36;
static bool tablesInitialised = false;
static char tblIntToChar[MAX_BASE] = {0};
static int tblCharToInt[256] = {0};
void InitTables()
{
if( tablesInitialised ) return;
for( int i = 0; i < 10; i++ ) {
tblIntToChar[i] = '0' + i;
tblCharToInt[tblIntToChar[i]] = i;
}
for( int i = 0; i < 26; i++ ) {
tblIntToChar[i+10] = 'a' + i;
tblCharToInt['a' + i] = i + 10;
tblCharToInt['A' + i] = i + 10;
}
tablesInitialised = true;
}
// Adds two numbers using long addition.
string Add( const string& a, const string& b, int base=10 )
{
InitTables();
if( base > MAX_BASE || base < MIN_BASE ) return "";
// Reserve storage for the result.
string result;
result.reserve( 1 + std::max(a.size(), b.size()) );
// Column positions and carry flag.
int apos = a.size();
int bpos = b.size();
int carry = 0;
// Do long arithmetic.
while( carry > 0 || apos > 0 || bpos > 0 )
{
if( apos > 0 ) carry += tblCharToInt[(unsigned char)a[--apos]];
if( bpos > 0 ) carry += tblCharToInt[(unsigned char)b[--bpos]];
result.push_back(tblIntToChar[carry%base]);
carry /= base;
}
// The result string is backwards. Reverse and return it.
reverse( result.begin(), result.end() );
return result;
}
// Converts a single value to some base, intended for single-digit conversions.
string AsBase( int number, int base )
{
InitTables();
if( number <= 0 ) return "0";
string result;
while( number > 0 ) {
result += tblIntToChar[number%base];
number /= base;
}
reverse( result.begin(), result.end() );
return result;
}
And, using all the above, here is a function to convert from one arbitrary base to another:
// Converts a number from one base to another.
string ConvertBase( const string & number, int oldBase, int newBase )
{
InitTables();
string result;
for( unsigned digit = 0; digit < number.size(); digit++ )
{
int value = tblCharToInt[(unsigned char)number[digit]];
if( result.empty() )
{
result = AsBase( value, newBase );
}
else
{
string temp = result;
for( int i = 1; i < oldBase; i++ ) {
temp = Add( result, temp, newBase );
}
result = Add( temp, AsBase(value, newBase), newBase );
}
}
return result;
}
This is just something I hacked up using code I mostly had kicking around in my StackOverflow 'for fun' sandbox. It's pretty clunky the way it performs oldBase
additions instead of just doing one multiplication. This would be a lot better if you made a Multiply
function to do long multiplication.
Upvotes: 3
Reputation: 3347
You can't solve the problem by going through each character individually. The reason is that two characters need to be considered when deciding which hex digit needs to be used.
for example "12" would be correctly represented as "C" where your algorithm won't take that into consideration.
You should also be reading from right to left rather than left to right
Upvotes: 1