Htoi incorrect output at 10 digits - c++

When I input
0x123456789
I get incorrect outputs, I can't figure out why. At first I thought it was a max possible int value problem, but I changed my variables to unsigned long and the problem was still there.
#include <iostream>
using namespace std;
long htoi(char s[]);
int main()
{
cout << "Enter Hex \n";
char hexstring[20];
cin >> hexstring;
cout << htoi(hexstring) << "\n";
}
//Converts string to hex
long htoi(char s[])
{
int charsize = 0;
while (s[charsize] != '\0')
{
charsize++;
}
int base = 1;
unsigned long total = 0;
unsigned long multiplier = 1;
for (int i = charsize; i >= 0; i--)
{
if (s[i] == '0' || s[i] == 'x' || s[i] == 'X' || s[i] == '\0')
{
continue;
}
if ( (s[i] >= '0') && (s[i] <= '9') )
{
total = total + ((s[i] - '0') * multiplier);
multiplier = multiplier * 16UL;
continue;
}
if ((s[i] >= 'A') && (s[i] <= 'F'))
{
total = total + ((s[i] - '7') * multiplier); //'7' equals 55 in decimal, while 'A' equals 65
multiplier = multiplier * 16UL;
continue;
}
if ((s[i] >= 'a') && (s[i] <= 'f'))
{
total = total + ((s[i] - 'W') * multiplier); //W equals 87 in decimal, while 'a' equals 97
multiplier = multiplier * 16UL;
continue;
}
}
return total;
}

long probably is 32 bits on your computer as well. Try long long.

You need more than 32 bits to store that number. Your long type could well be as small as 32 bits.
Use a std::uint64_t instead. This is always a 64 bit unsigned type. If your compiler doesn't support that, use a long long. That must be at least 64 bits.

The idea follows the polynomial nature of a number. 123 is the same as
1*102 + 2*101 + 3*100
In other words, I had to multiply the first digit by ten two times. I had to multiply 2 by ten one time. And I multiplied the last digit by one. Again, reading from left to right:
Multiply zero by ten and add the 1 → 0*10+1 = 1.
Multiply that by ten and add the 2 → 1*10+2 = 12.
Multiply that by ten and add the 3 → 12*10+3 = 123.
We will do the same thing:
#include <cctype>
#include <ciso646>
#include <iostream>
using namespace std;
unsigned long long hextodec( const std::string& s )
{
unsigned long long result = 0;
for (char c : s)
{
result *= 16;
if (isdigit( c )) result |= c - '0';
else result |= toupper( c ) - 'A' + 10;
}
return result;
}
int main( int argc, char** argv )
{
cout << hextodec( argv[1] ) << "\n";
}
You may notice that the function is more than three lines. I did that for clarity. C++ idioms can make that loop a single line:
for (char c : s)
result = (result << 4) | (isdigit( c ) ? (c - '0') : (toupper( c ) - 'A' + 10));
You can also do validation if you like. What I have presented is not the only way to do the digit-to-value conversion. There exist other methods that are just as good (and some that are better).
I do hope this helps.

I found out what was happening, when I inputted "1234567890" it would skip over the '0' so I had to modify the code. The other problem was that long was indeed 32-bits, so I changed it to uint64_t as suggested by #Bathsheba. Here's the final working code.
#include <iostream>
using namespace std;
uint64_t htoi(char s[]);
int main()
{
char hexstring[20];
cin >> hexstring;
cout << htoi(hexstring) << "\n";
}
//Converts string to hex
uint64_t htoi(char s[])
{
int charsize = 0;
while (s[charsize] != '\0')
{
charsize++;
}
int base = 1;
uint64_t total = 0;
uint64_t multiplier = 1;
for (int i = charsize; i >= 0; i--)
{
if (s[i] == 'x' || s[i] == 'X' || s[i] == '\0')
{
continue;
}
if ( (s[i] >= '0') && (s[i] <= '9') )
{
total = total + ((uint64_t)(s[i] - '0') * multiplier);
multiplier = multiplier * 16;
continue;
}
if ((s[i] >= 'A') && (s[i] <= 'F'))
{
total = total + ((uint64_t)(s[i] - '7') * multiplier); //'7' equals 55 in decimal, while 'A' equals 65
multiplier = multiplier * 16;
continue;
}
if ((s[i] >= 'a') && (s[i] <= 'f'))
{
total = total + ((uint64_t)(s[i] - 'W') * multiplier); //W equals 87 in decimal, while 'a' equals 97
multiplier = multiplier * 16;
continue;
}
}
return total;
}

Related

Hexadecimal Calculator for Addition and Subtraction

I have an issue with my program which is used to calculate addition and subtraction for Hexadecimals. The algorithm of my program is:
Take 2 strings inputted by the user, and "+" or "-" depending on the
operator they chose
Convert the 2 strings into decimals, and add or subtract
If the second number is bigger, use the bigger number to subtract the smaller number, and put a "-" in front of it when returning the result
(1 - 8 should = -7, but instead, I take 8 - 1 = 7, and return "-" and "7" so it gives "-7)
Take the decimal result from the operation and convert back to hexadecimal
Return string of hexadecimal
However, I have run into a issue where my calculations give me wrong answers.
(For e.g FFFFFF + FFFFFFFFFF prints "FFFFFFE" instead of "10000FFFFFE")
What can I do to solve the issue?
I created my own Power function for this program as I need a a number that can go up to 16 Fs for the Hexadecimal string.
Power Function:
unsigned long long int result = 1;
int i;
for (i = 0; i < y; i++)
{
result *= x;
}
return result;
Code:
int i;
int power = FirstHexaNumber.length() - 1;
int power2 = SeconHexaNumber.length() - 1;
int checkLength = FirstHexaNumber.length();
int checkLength2 = SeconHexaNumber.length();
unsigned long long int decimalNumber = 0;
unsigned long long int decimalNumber2 = 0;
unsigned long long int totalDecimal;
int temporary;
string result;
if (Operator == '+') //check if operator is add or minus
{
//Convert Hex to Decimal for first number
for (i = 0; i < checkLength; i++)
{
if (int(FirstHexaNumber[i]) >= 48 && int(FirstHexaNumber[i]) <= 57) { // check if FirstHexaNumber 0 to 9
decimalNumber += ((int(FirstHexaNumber[i])) - 48) * powerFunc(16, power); //formula to convert hexadecimal into decimal, int(FirstHexaNumber[i]) is used to convert hexa into a number
}
else if (int(FirstHexaNumber[i]) >= 65 && int(FirstHexaNumber[i]) <= 70) // check if FirstHexaNumber is A to F
{
decimalNumber += ((int(FirstHexaNumber[i])) - 55)*powerFunc(16, power);
}
else if (int(FirstHexaNumber[i]) >= 97 && int(FirstHexaNumber[i]) <= 102) // check if FirstHexaNumber is a to f
{
int x = powerFunc(16, power);
decimalNumber += ((int(FirstHexaNumber[i])) - 87)* x;
}
power--; //power-- since it starts from "HexaNumber.length - 1". Power should decrease as assignment of power goes down
}
//Convert Hex to Decimal for second number
for (i = 0; i < checkLength2; i++)
{
if (int(SeconHexaNumber[i]) >= 48 && int(SeconHexaNumber[i]) <= 57) {
decimalNumber2 += ((int(SeconHexaNumber[i])) - 48) * powerFunc(16, power2); //formula to convert Hexadecimal to Decimal
}
else if (int(SeconHexaNumber[i]) >= 65 && int(SeconHexaNumber[i]) <= 70)
{
decimalNumber2 += ((int(SeconHexaNumber[i])) - 55)*powerFunc(16, power2); //formula to convert Hexadecimal to Decimal
}
else if (int(SeconHexaNumber[i]) >= 97 && int(SeconHexaNumber[i]) <= 102)
{
unsigned long long int x = powerFunc(16, power2);
decimalNumber2 += ((int(SeconHexaNumber[i])) - 87)*x; //formula to convert Hexadecimal to Decimal
}
power2--;
}
totalDecimal = decimalNumber + decimalNumber2; //Adds the total decimal to convert into hexadecimal
if (totalDecimal == 0)
{
return "0";
}
//Converts Decimal to Hexadecimal
for (i = 0; totalDecimal != 0; i++) //as long as totalDecimal does not hit 0 from being divided by 16, run the loop
{
temporary = totalDecimal % 16; //use temporary as a variable to temporarily hold onto the number remainder of mod 16
if (temporary >= 10) //if temporary >= 10, that means it needs to be converted to alphabet
{
result.insert(0, 1, temporary + 55); //result.insert inserts a string of text into a spot, and pushes everything else backwards.
} //in this case, result.insert assigns "temporary+55" into the spot of characters 0 to 1.
else //else, it means that the decimal will be a number, add 48 to convert to ascii
{
result.insert(0, 1, temporary + 48);
}
totalDecimal = totalDecimal / 16; //divide by 16 to move on to finding the next digit/alphabet
}
return result;
}
else if (Operator == '-') //check if operator is add or minus
{
//Convert Hex to Decimal for first number
for (i = 0; i < checkLength; i++) //as long as the loop does not exceed the length of the hexadecimal, run it
{
if (int(FirstHexaNumber[i]) >= 48 && int(FirstHexaNumber[i]) <= 57) {
decimalNumber += ((int(FirstHexaNumber[i])) - 48) * powerFunc(16, power);
}
else if (int(FirstHexaNumber[i]) >= 65 && int(FirstHexaNumber[i]) <= 70)
{
decimalNumber += ((int(FirstHexaNumber[i])) - 55)*powerFunc(16, power);
}
else if (int(FirstHexaNumber[i]) >= 97 && int(FirstHexaNumber[i]) <= 102)
{
decimalNumber += ((int(FirstHexaNumber[i])) - 87)*powerFunc(16, power);
}
power--;
}
//Convert Hex to Decimal for second number
for (i = 0; i < checkLength2; i++)
{
if (int(SeconHexaNumber[i]) >= 48 && int(SeconHexaNumber[i]) <= 57) {
decimalNumber2 += ((int(SeconHexaNumber[i])) - 48) * powerFunc(16, power2);
}
else if (int(SeconHexaNumber[i]) >= 65 && int(SeconHexaNumber[i]) <= 70)
{
decimalNumber2 += ((int(SeconHexaNumber[i])) - 55)*powerFunc(16, power2);
}
else if (int(SeconHexaNumber[i]) >= 97 && int(SeconHexaNumber[i]) <= 102)
{
decimalNumber2 += ((int(SeconHexaNumber[i])) - 87)*powerFunc(16, power2);
}
power2--;
}
if (decimalNumber >= decimalNumber2)
{
totalDecimal = decimalNumber - decimalNumber2; //subtract bigger number by smaller number.
if (totalDecimal == 0)
{
return "0";
}
for (i = 0; totalDecimal != 0; i++)
{
temporary = totalDecimal % 16;
if (temporary >= 10)
{
result.insert(0, 1, temporary + 55);
}
else
{
result.insert(0, 1, temporary + 48);
}
totalDecimal = totalDecimal / 16;
}
return result;
}
else
{
totalDecimal = decimalNumber2 - decimalNumber; //subtract bigger number by smaller number.
if (totalDecimal == 0)
{
return "0";
}
for (i = 0; totalDecimal != 0; i++)
{
temporary = totalDecimal % 16;
if (temporary >= 10)
{
result.insert(0, 1, temporary + 55);
}
else
{
result.insert(0, 1, temporary + 48);
}
totalDecimal = totalDecimal / 16;
}
return "-" + result;
}
}
return 0;
You can try this snippet:
int a,b;
cout << "\nEnter A in hex: ";
cin >> hex >> a;
cout << "\nEnter B in hex: ";
cin >> hex >> b;
cout << "\n Addition of " << hex << a <<" and "<< hex << b << " is " << hex << a+b;
cout << "\n Substraction of " << hex << a << " and " << hex << b << " is " << hex << a - b;
int x = powerFunc(16, power); should be long long x = powerFunc(16, power);
Don't know full source of the function pow, the return type should be long long too.
Hexadecimal Calculator can be more simple.
#include <sstream>
std::stringstream ss1(s1),ss2(s2);
ss1 >> std::hex >> i1;
ss2 >> std::hex >> s2;
std::cout << std::hex << std::uppercase << i1 + s2 << std::endl;
std::stringstream res;
res << std::hex << std::uppercase << i1 + i2;
return res.str();

c++ Decimal to binary, then use operation, then back to decimal

I have an array with x numbers: sets[ ](long numbers) and a char array operations[ ] with x-1 numbers. For each number from sets[ ], its binary form(in 64bits) would be the same as a set of numbers( these numbers being from 0 to 63 ), 1's and 0's representing whether it is inside a subset or not ( 1 2 4 would be 1 1 0 1, since 3 is missing)
ex: decimal 5 --->000...00101 , meaning that this subset will only have those 2 last numbers inside it(#63 and #61)
now,using the chars i get in operations[], i should work with them and the binaries of these numbers as if they were operations on subsets(i hope subset is the right word), these operations being :
U = reunion ---> 101 U 010 = 111
A = intersection ---> 101 A 001 = 001
\ = A - B ---> 1110 - 0011 = 1100
/ = B-A ---> like the previous one
so basically I'd have to read numbers, make them binary, use them as if they were sets and use operations accordingly, then return the result of all these operations on them.
my code :
include <iostream>
using namespace std;
void makeBinaryVector(int vec[64], long xx)
{
// put xx in binary form in array "vec[]"
int k = 63;
long x = xx;
if(xx == 0)
for(int i=0;i<64;i++)
vec[i] = 0;
while(x != 0)
{
vec[k] = x % 2;
x = x / 2;
k--;
}
}
void OperationInA(int A[64], char op, int B[64])
{
int i;
if(op == 'U') //reunion
for(i=0;i<64;i++)
if(B[i] == 1)
A[i] = 1;
if(op == 'A') //intersection
for(i=0;i<64;i++)
{
if((B[i] == 1) && (A[i] == 1))
A[i] = 1;
else
A[i] = 0;
}
if(op == '\\') //A-B
for(i=0;i<64;i++)
{
if( (A[i] == 0 && B[i] == 0) || (A[i] == 0 && B[i] == 1) )
A[i] = 0;
else
if((A[i] == 1) && (B[i] == 1))
A[i] = 0;
else
if((A[i] == 1) && (B[i] == 0))
A[i] = 1;
}
if(op == '/') //B-A
for(i=0;i<64;i++)
{
if(B[i] == 0)
A[i] = 0;
else
if((B[i] == 1) && (A[i] == 0))
A[i] = 1;
else
if((B[i] == 1) && (A[i] == 1))
A[i] = 0;
}
}
unsigned long setOperations(long sets[], char operations[], unsigned int x)
{
unsigned int i = 1; //not 0, since i'll be reading the 1st number separately
unsigned int j = 0;
unsigned int n = x;
int t;
long a = sets[0];
int A[64];
for(t=0;t<64;t++)
A[t] = 0;
makeBinaryVector(A, a); //hold in A the first number, binary, and the results of operations
long b;
int B[64];
for(t=0;t<64;t++) //Hold the next number in B[], in binary form
B[t] = 0;
char op;
while(i < x && j < (x-1) )
{
b = sets[i];
makeBinaryVector(B, b);
op = operations[j];
OperationInA(A, op, B);
i++; j++;
}
//make array A a decimal number
unsigned int base = 1;
long nr = 0;
for(t=63; t>=0; t--)
{
nr = nr + A[t] * base;
base = base * 2;
}
return nr;
}
long sets[100];
char operations[100];
long n,i;
int main()
{
cin>>n;
for(i=0;i<n;i++)
cin>>sets[i];
for(i=0;i<n-1;i++)
cin>>operations[i];
cout<<setOperations(sets,operations,n);
return 0;
}
So everything seems fine, except when im trying this :
sets = {5, 2, 1}
operations = {'U' , '\'}
5 U 2 is 7(111), and 7 \ 1 is 6 (111 - 001 = 110 --> 6)
the result should be 6, however when i Input them like that the result is 4 (??)
however, if i simply input {7,1} and { \ } the result is 6,as it should be. but if i input them like i first mentioned {5,2,1} and {U,} then its gonna output 4.
I can't seem to understand or see what im doing wrong...
You don't have to "convert to binary numbers".
There's no such thing as 'binary numbers'. You can just perform the operations on the variables.
For the reunion, you can use the bitwise OR operator '|', and for the intersection, you can use the bitwise AND operator '&'.
Something like this:
if (op == 'A')
result = a & b;
else if (op == 'U')
result = a | b;
else if (op == '\\')
result = a - b;
else if (op == '/')
result = b - a;
Use bitwise operators on integers as shown in #Hugal31's answer.
Note that integer size is usually 32bit, not 64bit. On a 64bit system you need long long for 64bit integer. Use sizeof operator to check. int is 4 bytes (32bit) and long long is 8 bytes (64bit).
For the purpose of homework etc., your conversion to vector cannot be right. You should test it to see if it outputs the correct result. Otherwise use this:
void makebinary(int vec[32], int x)
{
int bitmask = 1;
for (int i = 31; i >= 0; i--)
{
vec[i] = (x & bitmask) ? 1 : 0;
bitmask <<= 1;
}
}
Note the use of shift operators. To AND the numbers you can do something like the following:
int vx[32];
int vy[32];
makebinary(vx, x);
makebinary(vy, y);
int result = 0;
int j = 1;
for (int i = 31; i >= 0; i--)
{
int n = (vx[i] & vy[i]) ? 1 : 0;
result += n * j;
j <<= 1;
}
This is of course pointless because you can just say int result = X & Y;

unsigned char* values to hexadecimal [duplicate]

This question already has answers here:
Convert two ASCII Hexadecimal Characters (Two ASCII bytes) in one byte
(6 answers)
Closed 6 years ago.
I have a typical use case where i need to convert the unsigned char values to hexadecimal.
For example,
unsigned char *pBuffer = (unsigned char *)pvaluefromClient //where pvaluefromclient is received from a client
The length of pBuffer is 32 bytes and it holds the value as follows,
(gdb) p pBuffer
$5 = (unsigned char *) 0x7fd4b82cead0 "EBA5F7304554DCC3702E06182AB1D487"
(gdb) n
STEP 1: I need to split this pBuffer value as follows,
{EB,A5,F7,30,45,54,DC,C3,70,2E,06,18,2A,B1,D4,87 }
STEP 2: I need to convert the above splited values to decimal as follows,
const unsigned char pConvertedBuffer[16] = {
235,165,247,48,69,84,220,195,112,46,6,24,42,177,212,135
};
Any idea on how to achieve the STEP1 and STEP2? any help on this would be highly appreciated
How about something like this:
unsigned char *pBuffer = (unsigned char *)pvaluefromClient //where valuefromclient is received from a client
int i, j;
unsigned char target[16]
for(i=0;i<32;i+=2)
{
sscanf((char*)&pBuffer[i], "%02X", &j);
target[i/2] = j;
}
You can create a function that takes two unsigned chars as parameter and returns another unsigned char. The two parameters are the chars (E and B for the first byte). The returned value would be the numerical value of the byte.
The logic would be :
unsigned char hex2byte(unsigned char uchar1, unsigned char uchar2) {
unsigned char returnValue = 0;
if((uchar1 >= '0') && (uchar1 <= '9')) {
returnValue = uchar1 - 0x30; //0x30 = '0'
}
else if((uchar1 >= 'a') && (uchar1 <= 'f')) {
returnValue = uchar1 - 0x61 + 0x0A; //0x61 = 'a'
}
else if((uchar1 >= 'A') && (uchar1 <= 'F')) {
returnValue = uchar1 - 0x41 + 0x0A; //0x41 = 'A'
}
if((uchar2 >= '0') && (uchar2 <= '9')) {
returnValue = (returnValue <<8) + (uchar2 - 0x30); //0x30 = '0'
}
else if((uchar2 >= 'a') && (uchar2 <= 'f')) {
returnValue = (returnValue <<8) + (uchar2 - 0x61 + 0x0A); //0x61 = 'a'
}
else if((uchar2 >= 'A') && (uchar1 <= 'F')) {
returnValue = (returnValue <<8) + (uchar2 - 0x41 + 0x0A); //0x41 = 'A'
}
return returnValue;
}
The basic idea is to calculate the numerical value of the chars and to reassemble a number from two chars (hence the bit shift)
I'm pretty sure there are multiple more elegant solutions than mine here and there.
void Conversion(char *pBuffer, int *ConvertedBuffer)
{
int j = 0;
for(int i = 0; i < 32; i += 2)
{
std::stringstream ss;
char sz[4] = {0};
sz[0] = pBuffer[i];
sz[1] = pBuffer[i+1];
sz[2] = 0;
ss << std::hex << sz;
ss >> ConvertedBuffer[j];
++j;
}
}
int main()
{
char Buffer[] = "EBA5F7304554DCC3702E06182AB1D487";
int ConvertedBuffer[16];
Conversion(Buffer, ConvertedBuffer);
for(int i = 0; i < 16; ++i)
{
cout << ConvertedBuffer[i] << " ";
}
return 0;
}
//output:
235 165 247 48 69 84 220 195 112 46 6 24 42 177 212 135

convert any base to base 10 in C++

I have this code:
#include <stdio.h>
#include <ctype.h>
int validnumber(int b, char* p);
unsigned long base2dec(int b,char *p);
void dec2base (int b,unsigned long x);
char *number;
main() {
int base,temp=0,count;
unsigned long Decimal_number;
do {
printf ("Give the base of the number you want to tranform:");
scanf ("%d", &base);
if (base<2 || base>16)
printf("Not acceptable base number, numbers should be in range from 2 to 16\n\n");
} while (base<2 || base>16);
printf ("Give the number you want to tranform:");
scanf("%s", number);
for (count=0;count<32;count++) {
number [count]= toupper(number[count]);
}
temp=validnumber(base, number);
if (temp==0)
printf ("O arithmpos pou eisagatai periexei MH egkira symbola\n");
else
if (temp==1)
printf ("O arithmpos pou eisagatai periexei egkira symbola\n");
if (temp==1) {
Decimal_number = base2dec( base , number);
}
int validnumber(int b, char *p){
int count, a[32];
for (count=0;count<32;count++)
a[count]=p[count];
if (b>=2 && b<=10) {
for (count=0;count<32;count++) {
if (a[count]<48 || a[count]>48+b)
return 0;
break;
}
}
if (b>=11 && b<=16) {
for (count=0;count<32;count++) {
if ((a[count]>=48 && a[count]<=57) || (a[count]>=65 && a[count]<=70)) {
return 1;
}
}
}
}
From this point the main program must call the function:
unsigned long base2dec (int b, char * p)
which accepts as arguments the base b and a pointer p in character table that
corresponds to the imported string s and returns the number representing the s expressed in the decimal system.
Also, it should call the function:
void dec2base (int b, unsigned long x)
which accepts as arguments the base b and the value of the number x in the decimal system and displays the base value and the representation of the number x in this base. The main program calls this function for all of the base values from 2 to 16.
Are there any ideas on how to begin? Any guidance will be appreciated.
In your base2dec, you will simply call this method and pass in 'b' as it is and x which should be the converted string.
Here is an implementation of dec2base. It is implemented recursively.
void dec2base(int b, unsigned long x){
if (x == 0)
return;
int y = x % b;
x /= b;
if (y < 0)
x += 1;
dec2base(b, x);
//converted digits to hex after realizing this solution doesn't work
//for bases greater than 10. Credits to Trevor pointing this out.
cout<< hex << y < 0 ? y + (b * -1) : y;
return;
}
First of all please have a look at your formatting because the way your code is written makes it harder than it needs to be to follow.
Here is what I would do:
#include <stdexcept>
#include <iostream>
void dec2base(int b, long x)
{
// Quick check for zero
if (x == 0)
{
std::cout << '0';
return;
}
// Print the negative sign if present, also negate
if (x < 0)
{
std::cout << '-';
x = -x;
}
char buf[12];
int i = 0;
// Convert to a backwards BCD
do {
buf[i++] = static_cast<char>(x % b);
} while (x /= b);
// Print it starting from the last digit (really the first)
do {
if (buf[--i] <= 9) std::cout << static_cast<char>(buf[i] + '0');
else std::cout << static_cast<char>(buf[i] + ('a' - 10));
} while (i);
}
long base2dec(int b, char * p)
{
long digit; // Current digit
long mul = 1; // Current multiplier
char *pos = p; // Current position
bool neg = false; // Sign
long ret = 0; // The return value
// Find the last digit
while (*pos) pos++;
// Continue until the start of the string is reached
while (pos-- != p)
{
if (*pos < '0')
{
if (*pos == '-')
{
// Sign reached, save it an break out
neg = true;
break;
}
else // Shouldn't happen
{
throw std::invalid_argument("Not a number");
}
}
if (*pos > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*pos <= '9') digit = *pos - '0';
else if (*pos >= 'a') digit = *pos - ('a' - 10);
else if (*pos >= 'A' && *pos <= 'F')
digit = *pos - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret += digit * mul;
// Increase the multiplier
mul *= b;
}
return neg ? -ret : ret;
}
int main()
{
long val = base2dec(16, "123f");
dec2base(16, val);
return 0;
}
I realize you didn't ask for a signed version but as it is very easy to implement I have done it. If you really don't need to deal with signed values it is simple to drop the relevant parts from the functions.
This is a very quick and dirty go at this and this could no doubt be improved both for readability and performance but is, I think, a good starting point.
Here is a slightly improved version of base2dec():
long base2dec(int b, char * p)
{
long digit; // Current digit
bool neg = false; // Sign
long ret = 0; // The return value
// Check for negative number
if (*p == '-')
{
neg = true;
p++;
}
// Continue until the end of the string is reached
for (; *p != 0; p++)
{
// Rough range check
if (*p < '0' || *p > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*p <= '9') digit = *p - '0';
else if (*p >= 'a') digit = *p - ('a' - 10);
else if (*p >= 'A' && *p <= 'F')
digit = *p - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret = ret * b + digit;
}
return neg ? -ret : ret;
}
Regarding the validnumber() function. This check is best performed during the conversion both to avoid having to read the entire string twice and because base2dec() really ought to check for valid input anyway. If you still need a separate check then you need to fix validnumber(). There is no need to copy the string to an array and it is also better to use the same code for all bases. Here is a suggestion:
bool validnumber(int b, char *p)
{
// Check for valid base
if (b < 2 || b > 16) return false;
// Extract numeric and alpha parts of the base
int b_numeric = b <= 10 ? b : 10;
int b_alpha = b - 11;
// Ignore any sign
if (*p == '-') p++;
// Continue until the end of the string
for (; *p != 0; p++)
{
// Digits < 0 are always bad
if (*p < '0') return false;
// Check for valid numeric digits
if (*p > ('0' + b_numeric))
{
// Check for valid alpha digits
if (b <= 10) return false;
if (*p < 'A' || *p > ('a' + b_alpha)) return false;
if (*p > ('A' + b_alpha) && *p < 'a') return false;
}
}
return true;
}

CString Hex value conversion to Byte Array

I have been trying to carry out a conversion from CString that contains Hex string to a Byte array and have been
unsuccessful so far. I have looked on forums and none of them seem to help so far. Is there a function with just a few
lines of code to do this conversion?
My code:
BYTE abyData[8]; // BYTE = unsigned char
CString sByte = "0E00000000000400";
Expecting:
abyData[0] = 0x0E;
abyData[6] = 0x04; // etc.
You can simply gobble up two characters at a time:
unsigned int value(char c)
{
if (c >= '0' && c <= '9') { return c - '0'; }
if (c >= 'A' && c <= 'F') { return c - 'A' + 10; }
if (c >= 'a' && c <= 'f') { return c - 'a' + 10; }
return -1; // Error!
}
for (unsigned int i = 0; i != 8; ++i)
{
abyData[i] = value(sByte[2 * i]) * 16 + value(sByte[2 * i + 1]);
}
Of course 8 should be the size of your array, and you should ensure that the string is precisely twice as long. A checking version of this would make sure that each character is a valid hex digit and signal some type of error if that isn't the case.
How about something like this:
for (int i = 0; i < sizeof(abyData) && (i * 2) < sByte.GetLength(); i++)
{
char ch1 = sByte[i * 2];
char ch2 = sByte[i * 2 + 1];
int value = 0;
if (std::isdigit(ch1))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
// That was the four high bits, so make them that
value <<= 4;
if (std::isdigit(ch2))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
abyData[i] = value;
}
Note: The code above is not tested.
You could:
#include <stdint.h>
#include <sstream>
#include <iostream>
int main() {
unsigned char result[8];
std::stringstream ss;
ss << std::hex << "0E00000000000400";
ss >> *( reinterpret_cast<uint64_t *>( result ) );
std::cout << static_cast<int>( result[1] ) << std::endl;
}
however take care of memory management issues!!!
Plus the result is in the reverse order as you would expect, so:
result[0] = 0x00
result[1] = 0x04
...
result[7] = 0x0E