Reputation: 107231
I have a text file with hexadecimal values. Now I need to convert the hexadecimal value to binary and need to save it on another file. But I don't know how to convert the hexadecimal value to a binary string! Please help...
Upvotes: 10
Views: 90998
Reputation: 36537
const char input[] = "..."; // the value to be converted
char res[9]; // the length of the output string has to be n+1 where n is the number of binary digits to show, in this case 8
res[8] = '\0';
int t = 128; // set this to s^(n-1) where n is the number of binary digits to show, in this case 8
int v = strtol(input, 0, 16); // convert the hex value to a number
while(t) // loop till we're done
{
strcat(res, t < v ? "1" : "0");
if(t < v)
v -= t;
t /= 2;
}
// res now contains the binary representation of the number
As an alternative (this assumes there's no prefix like in "0x3A"
):
const char binary[16][5] = {"0000", "0001", "0010", "0011", "0100", ...};
const char digits = "0123456789abcdef";
const char input[] = "..." // input value
char res[1024];
res[0] = '\0';
int p = 0;
while(input[p])
{
const char *v = strchr(digits, tolower(input[p++]));
if (v)
strcat(res, binary[v - digits]);
}
// res now contains the binary representation of the number
Upvotes: 5
Reputation: 60143
void printBin(unsigned int num){
char str[sizeof(num)*8];
char *p = str;
for(*p='0'; num; num/=2) { *p++='0'+num%2; } //store remainders
for(--p; p>=str; putchar(*p--)) {;} //print remainders in reverse
putchar('\n');
}
Upvotes: -1
Reputation: 1
#include <stdio.h>
int main()
{
long int binaryNumber,
hexadecimalNumber = 0,
j = 1,
remainder;
printf("Enter any number any binary number: ");
scanf("%ld", &binaryNumber);
while(binaryNumber != 0) {
remainder = binaryNumber % 10;
hexadecimalNumber = hexadecimalNumber + remainder * j;
j = j * 2;
binaryNumber = binaryNumber / 10;
}
printf("Equivalent hexadecimal value: %X", hexadecimalNumber);
return 0;
}
Upvotes: -3
Reputation: 8704
The quickest and easiest way is to read the hex file and, for each character ('0' through 'F') read, do a table lookup of the equivalent (0 through 15) binary value. There are, as ever, more elegant ways but this is very straightforward, maybe something like:
switch (charval) {
case '0': binval = 0;
case '1': binval = 1;
case '2': binval = 2;
case '3': binval = 3;
....
case 'a': binval = 10;
case 'b': binval = 11;
case 'A': binval = 10;
case 'B': binval = 11;
....
case 'f': binval = 15;
case 'F': binval = 15;
default: binval = -1; // error case
}
Now you have to use shifts and IORs/ADDs to construct words of the size you want from these individual 4-bit binary values.
Upvotes: -2
Reputation: 9
That's my function to convert HEX to BIN, byte a byte.
void HexToBin(char hex_number, char* bit_number) {
int max = 128;
for(int i = 7 ; i >-1 ; i--){
bit_number [i] = (hex_number & max ) ? 1 : 0;
max >>=1;
}
}
and the call to the function:
void main (void){
char hex_number = 0x6E; //0110 1110
char bit_number[8]={0,0,0,0,0,0,0,0};
HexToBin(hex_number,bit_number);
for(int i = 7 ; i >-1 ; i--)
printf("%d",bit_number[i]);
printf("\n");
system("pause");
}
And here is the MSDOS answer:
01101110
Press a key to continue . . .
Quite easy!
Upvotes: -3
Reputation: 7174
There are many ways to solve this question that use some arithmetics to convert from ascii character ranges 0-9 and a-f (or A-F) to binary. I wanted to find a solution which only uses a lookup table and benchmark that against a solution that uses arithmetics instead. Strangly enough, none of the answers above implement a purely arithmetic solution and some answers even assume that "converting to binary" means converting to a ascii string of characters "0" and "1".
Lets first do some setups. Firstly, we want to have the whole test data in memory so that we avoid disk I/O influencing the test. Here is how I create a header with a character array "testdata" of 104857600 bytes, roughly 105 MB. As the question was how to convert files, our implementation should be fast on large data.
$ { printf "char *testdata =\""; cat /dev/urandom \
| tr -d -c "0123456789abcdefABCDEF" \
| dd count=100 iflag=fullblock bs=1M; printf "\";\n" } > testdata.h
Next, we create the lookup tables. I see two possible ways to solve this with a lookup table. Either the lookup table maps individual ascii hex characters to half bytes or it maps two hex characters to a full byte. In the former case, the lookup table has to have 256 entries. In the latter case, the lookup table has to have 256*256=65536 entries. We can reduce the size of the latter by realizing that the first bit of the first byte will never be used. So we only need a lookup table of 128*256=32768 entries. Since that solution also requires an additional calculation step (applying a bitmask) we will benchmark both. We end up with the following test cases:
The first lookup table is easy to generate using some python:
#!/usr/bin/env python
import sys,struct
sys.stdout.write("unsigned char base16_decoding_table1[256] = {\n")
for i in xrange(256):
try:
j = str(int(chr(i), 16))
except:
j = '0'
sys.stdout.write(j+',')
sys.stdout.write("};\n")
sys.stdout.write("\n")
l = 128*256*["0"]
for a in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
for b in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
l[struct.unpack("<H", a+b)[0]] = str(int(a+b, 16))
line = "unsigned char base16_decoding_table2[%d] = {"%(128*256)
for e in l:
line += e+","
if len(line) > 70:
sys.stdout.write(line+"\n")
line = ""
sys.stdout.write(line+"};\n")
sys.stdout.write("\n")
l = 256*256*["0"]
for a in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
for b in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
l[struct.unpack("<H", a+b)[0]] = str(int(a+b, 16))
line = "unsigned char base16_decoding_table3[%d] = {"%(256*256)
for e in l:
line += e+","
if len(line) > 70:
sys.stdout.write(line+"\n")
line = ""
sys.stdout.write(line+"};\n")
And then:
python gen.py > base16_decoding_table.h
Now we can write some C code to test.
#include <stdio.h>
#include <time.h>
#include <inttypes.h>
#include "testdata.h"
#include "base16_decoding_table.h"
#define TESTDATALEN 104857600
/* the resulting binary string is half the size of the input hex string
* because every two hex characters map to one byte */
unsigned char result[TESTDATALEN/2];
void test1()
{
size_t i;
char cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i++) {
cur = testdata[i];
if (cur >= 97) {
val = cur - 97 + 10;
} else if (cur >= 65) {
val = cur - 65 + 10;
} else {
val = cur - 48;
}
/* even characters are the first half, odd characters the second half
* of the current output byte */
if (i%2 == 0) {
result[i/2] = val << 4;
} else {
result[i/2] |= val;
}
}
}
void test2()
{
size_t i;
char cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i++) {
cur = testdata[i];
val = base16_decoding_table1[(int)cur];
/* even characters are the first half, odd characters the second half
* of the current output byte */
if (i%2 == 0) {
result[i/2] = val << 4;
} else {
result[i/2] |= val;
}
}
}
void test3()
{
size_t i;
uint16_t *cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i+=2) {
cur = (uint16_t*)(testdata+i);
// apply bitmask to make sure that the first bit is zero
val = base16_decoding_table2[*cur & 0x7fff];
result[i/2] = val;
}
}
void test4()
{
size_t i;
uint16_t *cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i+=2) {
cur = (uint16_t*)(testdata+i);
val = base16_decoding_table3[*cur];
result[i/2] = val;
}
}
#define NUMTESTS 1000
int main() {
struct timespec before, after;
unsigned long long checksum;
int i;
double elapsed;
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test1();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("arithmetic solution took %f seconds\n", elapsed);
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test2();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("256 entries table took %f seconds\n", elapsed);
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test3();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("32768 entries table took %f seconds\n", elapsed);
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test4();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("65536 entries table took %f seconds\n", elapsed);
return 0;
}
Lets compile the thing:
$ gcc -O3 -g -Wall -Wextra test.c
And run it:
$ ./a.out
The result:
This we can conclude lookup tables beat arithmetic solutions any time and that wasting memory for bigger lookup tables might be worth the additional runtime.
Upvotes: 2
Reputation: 11
void hex_binary(char * res){
char binary[16][5] = {"0000", "0001", "0010", "0011", "0100", "0101","0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110","1111"};
char digits [] = "0123456789abcdef";
const char input[] = "a9e6"; // input value
res[0] = '\0';
int p = 0;
int value =0;
while(input[p])
{
const char *v = strchr(digits, tolower(input[p]));
if(v[0]>96){
value=v[0]-87;
}
else{
value=v[0]-48;
}
if (v){
strcat(res, binary[value]);
}
p++;
}
printf("Res:%s\n", res);
}
Upvotes: 1
Reputation: 133112
It's quite easy, really, because the translation goes digit-by-digit.
0 - 0000
1 - 0001
2 - 0010
3 - 0011
4 - 0100
5 - 0101
6 - 0110
7 - 0111
8 - 1000
9 - 1001
A - 1010
B - 1011
C - 1100
D - 1101
E - 1110
F - 1111
So, for example, the hex number FE2F8
will be 11111110001011111000
in binary
Upvotes: 11