C: Convert from decimal to hexadecimal using bitwise operations - c

I have to convert a decimal number to octal and hexadecimal using bitwise operations. I know how to convert it to binary:
char * decToBin(int n)
{
unsigned int mask=128;
char *converted;
converted=(char *) malloc((log((double) mask)/log((double) 2))*sizeof(char)+2);
strcpy(converted,"");
while(mask > 0)
{
if(mask & n)
strcat(converted,"1");
else
strcat(converted,"0");
mask >>= 1;
}
return converted;
}
May you help me convert from decimal to hexadecimal? What should the basic idea be? Is it possible to use a mask for that? Thank you.

You could "cheat" and use sprintf:
char *conv = calloc(1, sizeof(unsigned) * 2 + 3); // each byte is 2 characters in hex, and 2 characters for the 0x and 1 character for the trailing NUL
sprintf(conv, "0x%X", (unsigned) input);
return conv;
Or, to elaborate on #user1113426's answer:
char *decToHex(unsigned input)
{
char *output = malloc(sizeof(unsigned) * 2 + 3);
strcpy(output, "0x00000000");
static char HEX[] = "0123456789ABCDEF";
// represents the end of the string.
int index = 9;
while (input > 0 ) {
output[index--] = HEX[(input & 0xF)];
input >>= 4;
}
return output;
}

I am not fluent in C, but you can use this pseudo code:
char * decToHex(int n){
char *CHARS = "0123456789ABCDEF";
//Initialization of 'converted' object
while(n > 0)
{
//Prepend (CHARS[n & 0xF]) char to converted;
n >>= 4;
}
//return 'converted' object
}

Related

Extracting specific bits from an integer and saving them into a string in C?

I'm having trouble with extracting specific bits from a 32-bit long integer and saving those specific bits into a string.
To better explain my problem, I'll explain it like this:
Okay, let's say I have this integer:
01010101010101010101000011010100
I want to extract (going from MSB to LSB) from the 2nd (included) to the 21th bit (included).
So I can simply create a mask that will keep only the 20 bits I want and zero all others.
Integer: 01010101010101010101000011010100
Mask: 01111111111111111111100000000000
New integer = Integer & Mask = 01010101010101010101000000000000
After that, I have no idea, how to save those 20 bits to a string.
Okay, now lets say we have a char array that can hold 100 characters.
I then need to copy those 20 bits from the integer into the char array so that only those 20 bits are displayed as text. This is how it should be:
printf("Text: %s", string); -> "Text: 10101010101010101010"
I hope I explained it well enough. If you still have questions, let me know.
unsigned long long extractbits(unsigned long long data, unsigned start, unsigned end)
{
unsigned long long mask;
if(start > end)
{
unsigned tmp = start;
end = start;
start = tmp;
}
mask = (end == sizeof(unsigned long long) * 8 - 1) ? ~0ULL : (1ULL << (end + 1))) - 1;
return ((data & mask) >> start);
}
char *to_string(char *buff, unsigned long long data)
{
char *cptr = buff;
char *sptr = buff;
while(data)
{
*cptr++ = (data & 1) ? '1' : '0';
data >>= 1;
}
*cptr-- = 0;
while(cptr > buff)
{
char tmp = *cptr;
*cptr-- = *buff;
*buff++ = tmp;
}
return sptr;
}
int main()
{
char buff[25];
printf("%s\n", to_string(buff, extractbits(0b11100011100011100011ULL, 4, 17)));
return 0;
}

Best Way to Simulate Logic Gates in C?

Hi I was wondering if anyone would be able to explain to me what is the best path to take if I wanted to simulate logic gates in a c program?
Lets say for example I create a program and use command line arguments
AND GATE
[console]% yourProgram 11001010 11110000
<console>% 11000000
If anyone could explain to me what the best route is to start with, I would greatly appreciate it. This is the code I have so far...
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
if( argc >= 3){
int result = atoi(argv[1])&&atoi(argv[2]);
printf("Input 1 is %d\n",atoi(argv[1]));
printf("Input 2 is %d\n",atoi(argv[2]));
printf("Result is %c\n",result);
}
return 0;
In addition to the comment suggesting basic corrections, if you want to make it a bit more useful and flexible, you could calculate the most significant bit and then use that to format a simple binary print routine to examine your bitwise operation.
The primary concepts are taking the input as a string of binary digits and converting them to a number with strtoul (base 2), and then following &'ing the inputs together to obtain result it is just a matter of computing how many bytes to print out and whether to format a single byte into nibbles or simply separate multiple bytes.
#include <stdio.h>
#include <stdlib.h>
/* BUILD_64 */
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif
/* BITS_PER_LONG */
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
/* CHAR_BIT */
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
char *binstrfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep);
static __always_inline unsigned long msbfls (unsigned long word);
int main (int argc, char **argv) {
if ( argc < 3) {
fprintf (stderr, "error: insufficient input. usage: %s b1 b1\n", argv[0]);
return 1;
}
/* input conversion and bitwise operation */
unsigned long b1 = strtoul (argv[1], NULL, 2);
unsigned long b2 = strtoul (argv[2], NULL, 2);
unsigned long result = b1 & b2;
/* variables to use to set binary print format */
unsigned char msb, msbmax, width, sepwidth;
msb = msbmax = width = sepwidth = 0;
/* find the greatest most significant bit */
msbmax = (msb = msbfls (b1)) > msbmax ? msb : msbmax;
msbmax = (msb = msbfls (b2)) > msbmax ? msb : msbmax;
msbmax = (msb = msbfls (result)) > msbmax ? msb : msbmax;
msbmax = msbmax ? msbmax : 1;
/* set the number of bytes to print and the separator width */
width = (msbmax / CHAR_BIT + 1) * CHAR_BIT;
sepwidth = width > CHAR_BIT ? CHAR_BIT : CHAR_BIT/2;
/* print the output */
printf("\n Input 1 : %s\n", binstrfmt (b1, width, sepwidth, '-'));
printf(" Input 2 : %s\n", binstrfmt (b2, width, sepwidth, '-'));
printf(" Result : %s\n\n", binstrfmt (result, width, sepwidth, '-'));
return 0;
}
/** returns pointer to formatted binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binstrfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
static char s[2 * BITS_PER_LONG + 1] = {0};
char *p = s + 2 * BITS_PER_LONG;
unsigned char i;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (n >> i & 1) ? '1' : '0';
}
return p;
}
/* return the most significant bit (MSB) for the value supplied. */
static __always_inline unsigned long msbfls(unsigned long word)
{
if (!word) return 0;
int num = BITS_PER_LONG - 1;
#if BITS_PER_LONG == 64
if (!(word & (~0ul << 32))) {
num -= 32;
word <<= 32;
}
#endif
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
num -= 16;
word <<= 16;
}
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
num -= 8;
word <<= 8;
}
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
num -= 4;
word <<= 4;
}
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
num -= 2;
word <<= 2;
}
if (!(word & (~0ul << (BITS_PER_LONG-1))))
num -= 1;
return num;
}
Example Output
$ ./bin/andargs 11001010 11110000
Input 1 : 1100-1010
Input 2 : 1111-0000
Result : 1100-0000
$ ./bin/andargs 1100101011110000 1111000011001010
Input 1 : 11001010-11110000
Input 2 : 11110000-11001010
Result : 11000000-11000000
Use this code. (for AND operation):
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
if( argc >= 3){
int i=0;
printf("1st i/p = %s\n2nd i/p = %s\n",argv[1],argv[2]);
for (i=0; argv[1][i]!='\0'; i++){ //this assumes there are 2 inputs, of equal size, having bits(1,0) as its digits
argv[1][i] = argv[1][i] & argv[2][i]; //modifies argv[1] to your required answer
}
printf("Answer: %s\n",argv[1]);
}
return 0;
}

Error in Program to implement cyclic redundancy check

I have tried to implement crc in c.My logic is not very good.What I have tried is to copy the message(msg) in a temp variable and at the end I have appended number of zeros 1 less than the number of bits in crc's divisor div.
for ex:
msg=11010011101100
div=1011
then temp becomes:
temp=11010011101100000
div= 10110000000000000
finding xor of temp and div and storing it in temp
gives temp=01100011101100000 counting number of zeros appearing before the first '1' of temp and shifting the characters of div right to that number and then repeating the same process until decimal value of temp becomes less than decimal value of div. Which gives the remainder.
My problem is when I append zeros at the end of temp it stores 0's along with some special characters like this:
temp=11010011101100000$#UFI#->Jp#|
and when I debugged I got error
Floating point:Stack Underflow
here is my code:
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
void main() {
char msg[100],div[100],temp[100];
int i,j=0,k=0,l=0,msglen,divlen,newdivlen,ct=0,divdec=0,tempdec=0;
printf("Enter the message\n");
gets(msg);
printf("\nEnter the divisor\n");
gets(div);
msglen=strlen(msg);
divlen=strlen(div);
newdivlen=msglen+divlen-1;
strcpy(temp,msg);
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
printf("\nModified Temp:");
printf("%s",temp);
for(i=divlen;i<newdivlen;i++)
div[i]='0';
printf("\nModified div:");
printf("%s",div);
for(i=newdivlen;i>0;i--)
divdec=divdec+div[i]*pow(2,j++);
for(i=newdivlen;i>0;i--)
tempdec=tempdec+temp[i]*pow(2,k++);
while(tempdec>divdec)
{
for(i=0;i<newdivlen;i++)
{
temp[i]=(temp[i]==div[i])?'0':'1';
while(temp[i]!='1')
ct++;
}
for(i=newdivlen+ct;i>ct;i--)
div[i]=div[i-ct];
for(i=0;i<ct;i++)
div[i]='0';
tempdec=0;
for(i=newdivlen;i>0;i--)
tempdec=tempdec+temp[i]*pow(2,l++);
}
printf("%s",temp);
getch();
}
and this part of the code :
for(i=newdivlen;i>0;i--)
divdec=divdec+div[i]*pow(2,i);
gives error Floating Point:Stack Underflow
The problem is that you wrote a 0 over the NUL terminator, and didn't put another NUL terminator on the string. So printf gets confused and prints garbage. Which is to say that this code
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
printf("\nModified Temp:");
printf("%s",temp);
should be
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
temp[i] = '\0'; // <--- NUL terminate the string
printf("\nModified Temp:");
printf("%s",temp);
You have to do this with integers
int CRC(unsigned int n);
int CRC_fast(unsigned int n);
void printbinary(unsigned int n);
unsigned int msb(register unsigned int n);
int main()
{
char buf[5];
strcpy(buf, "ABCD");
//convert string to number,
//this is like 1234 = 1*1000 + 2*100 + 3*10 + 4, but with hexadecimal
unsigned int n = buf[3] * 0x1000000 + buf[2] * 0x10000 + buf[1] * 0x100 + buf[3];
/*
- "ABCD" becomes just a number
- Any string of text can become a sequence of numbers
- you can work directly with numbers and bits
- shift the bits left and right using '<<' and '>>' operator
- use bitwise operators & | ^
- use basic math with numbers
*/
//finding CRC, from Wikipedia example:
n = 13548; // 11010011101100 in binary (14 bits long), 13548 in decimal
//padding by 3 bits: left shift by 3 bits:
n <<= 3; //11010011101100000 (now it's 17 bits long)
//17 is "sort of" the length of integer, can be obtained from 1 + most significant bit of n
int m = msb(n) + 1;
printf("len(%d) = %d\n", n, m);
int divisor = 11; //1011 in binary (4 bits)
divisor <<= (17 - 4);
//lets see the bits:
printbinary(n);
printbinary(divisor);
unsigned int result = n ^ divisor;// XOR operator
printbinary(result);
//put this in function:
n = CRC(13548);
n = CRC_fast(13548);
return 0;
}
void printbinary(unsigned int n)
{
char buf[33];
memset(buf, 0, 33);
unsigned int mask = 1 << 31;
//result in binary: 1 followed by 31 zero
for (int i = 0; i < 32; i++)
{
buf[i] = (n & mask) ? '1' : '0';
//shift the mask by 1 bit to the right
mask >>= 1;
/*
mask will be shifted like this:
100000... first
010000... second
001000... third
*/
}
printf("%s\n", buf);
}
//find most significant bit
unsigned int msb(register unsigned int n)
{
unsigned i = 0;
while (n >>= 1)
i++;
return i;
}
int CRC(unsigned int n)
{
printf("\nCRC(%d)\n", n);
unsigned int polynomial = 11;
unsigned int plen = msb(polynomial);
unsigned int divisor;
n <<= 3;
for (;;)
{
int shift = msb(n) - plen;
if (shift < 0) break;
divisor = polynomial << shift;
printbinary(n);
printbinary(divisor);
printf("-------------------------------\n");
n ^= divisor;
printbinary(n);
printf("\n");
}
printf("result: %d\n\n", n);
return n;
}
int CRC_fast(unsigned int n)
{
printf("\nCRC_fast(%d)\n", n);
unsigned int polynomial = 11;
unsigned int plen = msb(polynomial);
unsigned int divisor;
n <<= 3;
for (;;)
{
int shift = msb(n) - plen;
if (shift < 0) break;
n ^= (polynomial << shift);
}
printf("result: %d\n\n", n);
return n;
}
Previous problems with string method:
This is infinite loop:
while (temp[i] != '1')
{
ct++;
}
Previous problems with string method:
This one is too confusing:
for (i = newdivlen + ct; i > ct; i--)
div[i] = div[i - ct];
I don't know what ct is. The for loops are all going backward, this makes the code faster sometimes (maybe 1 nanosecond faster), but it makes it very confusing.
There is another while loop,
while (tempdec > divdec)
{
//...
}
This may go on forever if you don't get the expected result. It makes it very hard to debug the code.

converting decimal to exponent and mantissa

I am trying to convert a decimal number (329.39062) to binary (exponent, mentissa). I keep getting segmentation fault. on running the gdb test, It shows me feof. I have changed alot but it keeps showing me the segmentation fault at the same point. Where am i going wrong? Thank you for all the help.
#include <stdio.h>
#include <stdlib.h>
char* valueToConvert(int value);
int main(int argc, char *argv[])
{
FILE* input;
FILE* output;
input = fopen(argv[1],"r");
output = fopen(argv[2],"w");
float value;
unsigned char *charValue = (unsigned char *) &value;
int exponentValue;
long mantissaValue;
while(!feof(input))
{
fread(&charValue, sizeof(float),1, input);
exponentValue = ((charValue[0] & 0x7F) << 1)|((charValue[1] & 0x80) >> 7);
mantissaValue = ((charValue[1] & 0x7F) << 8)|((charValue[2] & 0xFF) <<8) | (charValue[3] & 0xFF);
fprintf(output,"%d %s %s\n",(charValue[0] & 0x80 >> 7),valueToConvert(exponentValue - 127),valueToConvert(mantissaValue));
}
}
char* valueToConvert(int value)
{
int counter = 0;
char* conversion = calloc(32,sizeof(int));
while(value>0)
{
if((value%2 == 1) && (value%2 != 0))
{
conversion[31 - counter++] = '1';
}
if((value%2 == 0) && (value%2 != 1))
{
conversion[31 - counter++] = '0';
}
value = value/2;
}
return conversion;
}
The problem is here:
fread(&charValue, sizeof(float),1, input);
That should be
fread(charValue, sizeof(float),1, input);
Because charValue is a pointer.
To address your problems with the output, you're filling the buffer backwards after initializing it completely with 0 via calloc, so fprintf is hitting 0 (a char used to signify the end of a string) and stopping "prematurely".
Here's a fast binary string function:
void fast_d2b(int x, char* c) {
int i;
for (i = 31; i >= 0; --i) {
*(c++) = '0' + ((x >> i) & 0x1);
}
}
It's based on the one shown here.
Only differences are that my variation doesn't write to the buffer backwards and it writes '0' and '1' instead of integral values 0 and 1.

Compare part of sha1 digest with hex string in C

I have a string for which I compute a sha1 digest like this:
SHA1(sn, snLength, sha1Bin);
If I'm correct this results in a 20 byte char (with binary data). I want to compare the last 3 bytes of this char with another char. This char contains the string "6451E6". 64, 51 & E6 are hex values. How do I convert "6451E6" so that I can compare it via:
if(memcmp(&sha1Bin[(20 - 3)], theVarWithHexValues, 3) == 0)
{
}
I have this function:
/*
* convert hexadecimal ssid string to binary
* return 0 on error or binary length of string
*
*/
u32 str2ssid(u8 ssid[],u8 *str) {
u8 *p,*q = ssid;
u32 len = strlen(str);
if( (len % 2) || (len > MAX_SSID_OCTETS) )
return(0);
for(p = str;(*p = toupper(*p)) && (strchr(hexTable,*p)) != 0;) {
if(--len % 2) {
*q = ((u8*)strchr(hexTable,*p++) - hexTable);
*q <<= 4;
} else {
*q++ |= ((u8*)strchr(hexTable,*p++) - hexTable);
}
}
return( (len) ? 0 : (p - str) / 2);
}
which does the same but I'm new to C and don't understand it :-(
It's easier to go the other way — convert the binary data to a hex string for comparison:
char suffix[7];
sprintf(suffix, "%02x%02x%02x", sha1Bin[17], sha1Bin[18], sha1Bin[19]);
return stricmp(suffix, theVarWithHexValues) == 0;
Even if you prefer converting to binary, sscanf(...%2x...) is better than manually parsing hex numbers.
Fix for AShelly's code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int hashequal(const unsigned char *sha1Bin, const char *hexstr) {
unsigned long hexvar = strtoul(hexstr, NULL, 16);
unsigned char theVarWithHexValues[] = { hexvar >> 16, hexvar >> 8, hexvar };
return memcmp(sha1Bin + 17, theVarWithHexValues, 3) == 0;
}
int main() {
unsigned char sha1Bin[20];
sha1Bin[17] = 0x64;
sha1Bin[18] = 0x51;
sha1Bin[19] = 0xE6;
printf("%d\n", hashequal(sha1Bin, "6451E6"));
printf("%d\n", hashequal(sha1Bin, "6451E7"));
}
If theVarWithHexValues is indeed a constant of some sort, then the easiest thing would be to put it into binary form directly. Instead of:
const char *theVarWithHexValues = "6451E6";
use:
const char *theVarWithHexValues = "\x64\x51\xE6";
...then you can just memcmp() directly.
char* hexstr = "6451E6";
unsigned long hexvar = strtoul(hexstr, NULL, 16);
hexvar = htonl(hexvar)<<8; //convert to big-endian and get rid of zero byte.
memcmp(&sha1Bin[(20 - 3)], (char*)hexvar, 3)

Resources