I'm not able to get the right output when I do the following code. look at the comments for what I'm trying to print.
I did the code based on what I've been learning so far, but I'm still not getting the right output.
So any suggestions? What have I done, so I'm able to fix the problem.
When I print(A), I'm not getting 0100 0001, but it prints 49d or 49 sometimes
#include <stdio.h>
unsigned char getBit(unsigned char c, int n)
{
return ((c & (1 << n)) >> n);
}
unsigned char setBit(unsigned char c, int n)
{
c = c | (1 << n);
return c;
}
unsigned char clearBit(unsigned char c, int n)
{
c = c & (~(1 << n));
return c;
}
void printBits(unsigned char c)
{
printf("The bit of the character you inputed is %x \n", c);
}
int main(void)
{
unsigned char a = 'A';
printBits(a);
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); //should print 0100 0001, but it prints 49
putchar('\n');
a = clearBit(a, 2);
printBits(a);
putchar('\n');
}
Your current solution prints the value of c as a hexadecimal number using printf(). Since there is no printf format specifier to print a number in binary representation, we'll have to write our own solution.
#include <limits.h>
#include <stdio.h>
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) { // count from the with of a char
// in bits down to 1
putchar(c & 1 << --i // test the i-th bit (1-based)
? '1' // if true (different form 0) evaluates to '1'
: '0' // else evaluates to '0'
);
if (CHAR_BIT == 8 && i % 4 == 0) // if we use 8-bit-bytes and just
// finished printing the higher nibble
putchar(' '); // insert a seperator between the nibbles
}
}
... ftw!
No-nonsense version:
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) {
putchar(c & 1 << --i ? '1' : '0');
if (CHAR_BIT == 8 && !(i % 4))
putchar(' ');
}
}
`
unsigned char a = 'A';
printBits(a); // should print 0100 0001
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); // should print 0100 1101
putchar('\n');
a = clearBit(a, 2);
printBits(a); // should print 0100 1001
putchar('\n'
Related
Code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int x;
x = 1000000;
printf("%ld\n", x);
for(int i = 0; i < 32; i++)
{
printf("%c", (x & 0x80) ? '1' : '0');
x <<= 1;
}
printf("\n");
return 0;
}
This code is supposed to convert a decimal int to binary, but why doesn't it work correctly?
P.S. I solved this problem by replacing 0x80 with 0x80000000. But why was the wrong number displayed at 0x80?
EDIT2:
OP asks "P.S. I solved this problem by replacing 0x80 with 0x80000000. But why was the wrong number displayed at 0x80?"
What was wrong was 0x80 is equal to 0x00000080. 0x80 will never test any bits above b7 (where bits, right to left, are numbered b0 to b31.
The corrected value, 0x80000000, sets the MSB high and can be used (kind of) to 'sample' each bit of the data as the data value is 'scrolled' to the left.
//end edit2
Two concerns:
1) Mucking with the sign bit of a signed integer can be problematic
2) "Knowing" there are 32 bits can be problematic.
The following makes fewer presumptions. It creates a bit mask (only the MSB is set in an unsigned int value) and shifts that mask toward the LSB.
int main() {
long int x = 100000;
printf("%ld\n", x);
for( unsigned long int bit = ~(~0u >> 1); bit; bit >>= 1 )
printf("%c", (x & bit) ? '1' : '0');
printf("\n");
return 0;
}
100000
00000000000000011000011010100000
Bonus: Here is a version of the print statement that doesn't involve branching:
printf( "%c", '0' + !!(x & bit) );
EDIT:
Having seen the answer by #Lundin, the suggestion to insert SP's to improve readability is an excellent idea! (Full credit to #Lundin.)
Below, not only is the long string of bits output divided into "hexadecimal" chunks, but the compile time value is shown in a way to easily see it is 10million. (1e7 would have done, too.)
A new-and-improved version:
#include <stdio.h>
#include <stdlib.h>
int main() {
long int x = 10 * 1000 *1000;
printf("%ld\n", x);
for( unsigned long int bit = ~(~0u >> 1); bit; bit >>= 1 ) {
putchar( '0' + !!(x & bit) );
if( bit & 0x11111111 ) putchar( ' ' );
}
putchar( '\n' );
return 0;
}
10000000
0000 0000 1001 1000 1001 0110 1000 0000
1000000 dec = 11110100001001000000 bin.
80 hex = 10000000 bin.
And this doesn't make much sense at all:
11110100001001000000
& 10000000
Instead fix the loop body to something like this:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
long int x;
x = 1000000;
printf("%ld\n", x);
for(int i = 0; i < 32; i++)
{
unsigned long mask = 1u << (31-i);
printf("%c", (x & mask) ? '1' : '0');
if((i+1) % 8 == 0) // to print a space after 8 digits
printf(" ");
}
printf("\n");
return 0;
}
Without using an integer counter to see what digit is at the ith position, you can instead use an unsigned variable which is equal to 2^i at the ith iteration. If this variable is unsigned, when it overflows it will become zero. Here is how the code would look like. It displays the number in reversed order (first position means the coefficient of 2^0 in the polynomial decomposition of the number).
int
main()
{
int x;
x = 1000000;
printf("%lx\n", x);
for(unsigned b = 1; b; b<<=1)
printf("%c", x & b ? '1':'0');
printf("\n");
return 0;
}
I would use functions
void printBin(long int x)
{
unsigned long mask = 1UL << (sizeof(mask) * CHAR_BIT - 1);
int digcount = 0;
while(mask)
{
printf("%d%s", !!(x & mask), ++digcount % 4 ? "" : " ");
mask >>= 1;
}
}
int main(void)
{
printBin(0); printf("\n");
printBin(1); printf("\n");
printBin(0xf0); printf("\n");
printBin(-10); printf("\n");
}
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.
Logic to set a bits of given number (as show in example below) from first occurance of 1 next should must be 1 and then alternative 0 and 1 should continue till all bits field is filled up? example if num =10 then its binary is 0000 0000 0000 0000 0000 0000 0000 1010
out put should be 0000 0000 0000 0000 0000 0000 0000 1101
similar if it is 16 10000 then 0/p should be 11010 and if 15 ie 1111 then output 11010 when we get first bits as 1 in give number then next bits should be 1 and the alternative 0 and 1?my logic is below please help to fix it
int main()
{
int i,onetime=1,flag=1;
scanf("%d",&num);
for(i=31;i>=0;i++)
{
if(num & 1<<i)
break; // this will give first set bits of num ie 1
}
--i; // move to next adjacent bit and this should also be 1
for(;i>0;)
{
if(onetime=1) // here forcely making 1
{
num=num|1<<i;
onetime=0;
}
if(flag==1) // set to 0
{
num=num&~(1<<i)
flag=0;
}
if(flag==0) //set to 1
{
num=num|(1<<i);
flag =1-flag; //will keep on switch 0 and 1
}
}
}
While the logic behind doing what you want to do it fairly trivial, the implementation isn't. Ignoring the need to output a binary representation for the moment, the logic can be broken down to:
1.) finding the most significant bit (msb)
2.) toggling each bit beginning at (msb - 1) to 0 (subtracting 'x' from msb)
3.) setting each bit if (x % 2) == 0, clearing otherwise
The implementation isn't difficult, it is just rather involved (note: this is for 32-bit values only):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h> /* for CHAR_BIT */
inline int getmsb (uint32_t x);
char *fmtbinstr_32 (uint32_t x, const size_t szgrp, char *sep);
/* set or clear bit n */
inline void bit_set (uint32_t *bf, int n) { *bf |= (1 << n); }
inline void bit_clear (uint32_t *bf, int n) { *bf &= ~(1 << n); }
int
main (int argc, char *argv[]) {
if (argc < 2 ) {
fprintf (stderr, "Error: insufficient input, usage: %s int\n", argv[0]);
return 1;
}
uint32_t number = (uint32_t)atoi (argv[1]);
uint32_t newnum = number;
int msb = getmsb (number);
int it = 0;
printf ("\n number: %s\n msb : %d\n\n", fmtbinstr_32 (number, 4, "-"), msb);
it = (int)msb;
for (it = 1; it <= msb; it++) {
if ((it % 2) == 0)
bit_clear (&newnum, msb - it);
else
bit_set (&newnum, msb - it);
}
printf (" newnum: %s\n\n", fmtbinstr_32 (newnum, 4, "-"));
return 0;
}
/* return the most significant bit MSB for the value supplied (bit scan reverse)
* for 32-bit values. For 64-bit values, use 'bsrq'.
*/
inline int getmsb (uint32_t x)
{
asm ("bsr %0, %0" : "=r" (x) : "0" (x));
return x;
}
/* binary string of uint32_t x, in szgrp bits groups, separated by sep */
char *fmtbinstr_32 (uint32_t x, const size_t szgrp, char *sep)
{
char b [sizeof(uint32_t) * CHAR_BIT + 1] = {0};
static char fmtb [sizeof (uint32_t) * 2 * CHAR_BIT] = {0};
const size_t len = sizeof(uint32_t) * CHAR_BIT + 1;
register size_t z = 0;
register size_t idx = 0;
if (szgrp > ((len - 1) / 2) || szgrp <= 0) {
fprintf (stderr, "%s() error: invalid input: szgrp '%d' out of range (%d >= szgrp > 0)\n", __func__, (int) szgrp, (int) ((len - 1) / 2));
return NULL; // could make b static and return b instead
}
for (z = 0; z < len - 1; z++)
b [sizeof (uint32_t) * CHAR_BIT - 1 - z] = ((x>>z) & 0x1) ? '1' : '0';
if (sep [0] == '\0') {
fprintf (stderr, "%s() error: invalid input: 'sep' is undefined or empty string\n", __func__);
return NULL;
}
for (z = 0; z < len - 1; z++) {
if ((len - 1 - z) % szgrp == 0 && z > 0) {
fmtb [idx] = sep [0];
idx++;
}
fmtb [idx] = b [z];
idx++;
}
fmtb [idx] = '\0';
return fmtb;
}
output:
$ ./bin/bitalt 10
number: 0000-0000-0000-0000-0000-0000-0000-1010
msb : 3
newnum: 0000-0000-0000-0000-0000-0000-0000-1101
$ ./bin/bitalt 55
number: 0000-0000-0000-0000-0000-0000-0011-0111
msb : 5
newnum: 0000-0000-0000-0000-0000-0000-0011-0101
Basic Version
This version employs the same logic, but leaves out the binary print function and the getmsb function that uses assembler instructions to get the most significant bit. This example uses most of the logic from the original question, but adjust the loops as needed:
#include <stdio.h>
int main (void) {
int i = 0, msb = 0;
unsigned int num = 0;
printf ("\nEnter a number: ");
scanf ("%u", &num);
for (i = 31; i >= 0; i--) {
if (num & 1 << i)
break; // this will give first set bits of num ie 1
} // which is the most significant bit (msb)
msb = i; // save msb
printf ("\n The most significant bit (msb): %d\n", msb);
// we want the index [msb - i] to step down from (msb-1) to 0
// e.g. if num=10, then msb=3, so we want the indexes to be 2,1,0
// so let i start at 1 and we will do (msb -i) until i=msb
for (i = 1; i <= msb; i++) {
if ((i % 2) == 0) // if i mod 2 == 0, we clear the bit
num &= ~(1 << (msb - i)); // clear_bit (make it 0)
else
num |= (1 << (msb - i)); // set_bit (make it 1)
}
printf ("\n The resulting number is: %u\n\n", num);
return 0;
}
output:
$ ./bin/bas
Enter a number: 10
The most significant bit (msb): 3
The resulting number is: 13
$ ./bin/bas
Enter a number: 55
The most significant bit (msb): 5
The resulting number is: 53
I'm create CRC-CCITT Encode (Polynomail 0x1021 and Initial Value is 0xFFFF)
It is correct 8bit, 16bit, 24bit, 32bit ... (1 Byte, 2Byte, 3Byte ...)
But not correct answer 12bit, 20bit, 28bit (not Byte)
I find this algorithm
function crc(bit array bitString[1..len], int polynomial) {
shiftRegister := initial value // 00000000 OR 11111111
for i from 1 to len {
if (shiftRegister top bit) xor bitString[i] = 1
shiftRegister := (shiftRegister left shift 1) xor polynomial
else
shiftRegister := shiftRegister left shift 1
}
return shiftRegister
}
and my source code is like that
// crc_ccitt.h
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
static const char CRC_CCITT[] = "0001000000100001";
static char Shift_Register[] = "1111111111111111";
char* getCRC(char *, int);
void leftShift(char *);
void xorCalc();
char* getCRC(char* dataCode, int dataCodeLength) {
int i;
for (i = 0; i < dataCodeLength; i++) {
if ((Shift_Register[0] == '1' && dataCode[i] == '0')
|| (Shift_Register[0] == '0' && dataCode[i] == '1')) {
leftShift(Shift_Register);
xorCalc();
} else {
leftShift(Shift_Register);
}
printf("%c%c%c%c ", Shift_Register[0], Shift_Register[1], Shift_Register[2], Shift_Register[3]);
printf("%c%c%c%c ", Shift_Register[4], Shift_Register[5], Shift_Register[6], Shift_Register[7]);
printf("%c%c%c%c ", Shift_Register[8], Shift_Register[9], Shift_Register[10], Shift_Register[11]);
printf("%c%c%c%c ", Shift_Register[12], Shift_Register[13], Shift_Register[14], Shift_Register[15]);
printf("\n");
}
return Shift_Register;
}
void leftShift(char *Shift_Register) {
memmove(Shift_Register, Shift_Register + 1, strlen(Shift_Register) - 1);
memset(Shift_Register + strlen(Shift_Register) - 1, '0', 1);
}
void xorCalc() {
int i;
for (i = 0; i < 16; ++i) {
if ((Shift_Register[i] == '1' && CRC_CCITT[i] == '0')
|| (Shift_Register[i] == '0' && CRC_CCITT[i] == '1')) {
Shift_Register[i] = '1';
} else {
Shift_Register[i] = '0';
}
}
}
// crc_ccitt.c
#include "crc_ccitt.h"
int main() {
char dataCode[256];
char *CRC = "";
printf("Input Data Code: ");
gets(dataCode);
/*
puts(dataCode);
rightShift(dataCode);
puts(dataCode);
*/
CRC = getCRC(dataCode, strlen(dataCode));
//printf("%s", CRC);
return 0;
}
I confirm CRC Encode value with this page
http://www.lammertbies.nl/comm/info/crc-calculation.html
For example
Input 0001111111110010(1FF2)
page : C11F
my program : 1100 0001 0001 1111 (C11F)
But
Input 000111111111 (1FF)
page : FFAD
my program : 1101 0011 0000 1111 (D30F)
What of lack of my program??
Or, is algorithm is wrong??
Program OK
Algorithm OK
User input is likely the error.
Your CRC "0001000000100001" is for a 16-bit operation.
Your failed input is "000111111111", 12 bits.
Instead try using "0000000111111111" or "0001111111110000" (pad on the left or right)
Note: I would have tried it myself but you did not provide crc_ccitt.h
I'm to stupid right now to solve this problem...
I get a BCD number (every digit is an own 4Bit representation)
For example, what I want:
Input: 202 (hex) == 514 (dec)
Output: BCD 0x415
Input: 0x202
Bit-representation: 0010 0000 0010 = 514
What have I tried:
unsigned int uiValue = 0x202;
unsigned int uiResult = 0;
unsigned int uiMultiplier = 1;
unsigned int uiDigit = 0;
// get the dec bcd value
while ( uiValue > 0 )
{
uiDigit= uiValue & 0x0F;
uiValue >>= 4;
uiResult += uiMultiplier * uiDigit;
uiMultiplier *= 10;
}
But I know that's very wrong this would be 202 in Bit representation and then split into 5 nibbles and then represented as decimal number again
I can solve the problem on paper but I just cant get it in a simple C-Code
You got it the wrong way round. Your code is converting from BCD to binary, just as your question's (original) title says. But the input and output values you provided are correct only if you convert from binary to BCD. In that case, try:
#include <stdio.h>
int main(void) {
int binaryInput = 0x202;
int bcdResult = 0;
int shift = 0;
printf("Binary: 0x%x (dec: %d)\n", binaryInput , binaryInput );
while (binaryInput > 0) {
bcdResult |= (binaryInput % 10) << (shift++ << 2);
binaryInput /= 10;
}
printf("BCD: 0x%x (dec: %d)\n", bcdResult , bcdResult );
return 0;
}
Proof: http://ideone.com/R0reQh
Try the following.
unsigned long toPackedBcd (unsigned int val)
{
unsigned long bcdresult = 0; char i;
for (i = 0; val; i++)
{
((char*)&bcdresult)[i / 2] |= i & 1 ? (val % 10) << 4 : (val % 10) & 0xf;
val /= 10;
}
return bcdresult;
}
Also one may try the following variant (although maybe little inefficient)
/*
Copyright (c) 2016 enthusiasticgeek<enthusiasticgeek#gmail.com> Binary to Packed BCD
This code may be used (including commercial products) without warranties of any kind (use at your own risk)
as long as this copyright notice is retained.
Author, under no circumstances, shall not be responsible for any code crashes or bugs.
Exception to copyright code: 'reverse string function' which is taken from http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
Double Dabble Algorithm for unsigned int explanation
255(binary) - base 10 -> 597(packed BCD) - base 16
H| T| U| (Keep shifting left)
11111111
1 1111111
11 111111
111 11111
1010 11111 <-----added 3 in unit's place (7+3 = 10)
1 0101 1111
1 1000 1111 <-----added 3 in unit's place (5+3 = 8)
11 0001 111
110 0011 11
1001 0011 11 <-----added 3 in ten's place (6+3 = 9)
1 0010 0111 1
1 0010 1010 1 <-----added 3 in unit's place (7+3 = 10)
10 0101 0101 -> binary 597 but bcd 255
^ ^ ^
| | |
2 5 5
*/
#include <stdio.h>
#include <string.h>
//Function Prototypes
unsigned int binaryToPackedBCD (unsigned int binary);
char * printPackedBCD(unsigned int bcd, char * bcd_string);
// For the following function see http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
void reverse(char *str);
//Function Definitions
unsigned int binaryToPackedBCD (unsigned int binary) {
const unsigned int TOTAL_BITS = 32;
/*Place holder for bcd*/
unsigned int bcd = 0;
/*counters*/
unsigned int i,j = 0;
for (i=0; i<TOTAL_BITS; i++) {
/*
Identify the bit to append to LSB of 8 byte or 32 bit word -
First bitwise AND mask with 1.
Then shift to appropriate (nth shift) place.
Then shift the result back to the lsb position.
*/
unsigned int binary_bit_to_lsb = (1<<(TOTAL_BITS-1-i)&binary)>>(TOTAL_BITS-1-i);
/*shift by 1 place and append bit to lsb*/
bcd = ( bcd<<1 ) | binary_bit_to_lsb;
/*printf("=> %u\n",bcd);*/
/*Don't add 3 for last bit shift i.e. in this case 32nd bit*/
if( i >= TOTAL_BITS-1) {
break;
}
/*else continue*/
/* Now, check every nibble from LSB to MSB and if greater than or equal 5 - add 3 if so */
for (j=0; j<TOTAL_BITS; j+=4) {
unsigned int temp = (bcd & (0xf<<j))>>j;
if(temp >= 0x5) {
/*printf("[%u,%u], %u, bcd = %u\n",i,j, temp, bcd);*/
/*Now, add 3 at the appropriate nibble*/
bcd = bcd + (3<<j);
// printf("Now bcd = %u\n", bcd);
}
}
}
/*printf("The number is %u\n",bcd);*/
return bcd;
}
char * printPackedBCD(unsigned int bcd, char * bcd_string) {
const unsigned int TOTAL_BITS = 32;
printf("[LSB] =>\n");
/* Now, check every nibble from LSB to MSB and convert to char* */
for (unsigned int j=0; j<TOTAL_BITS; j+=4) {
//for (unsigned int j=TOTAL_BITS-1; j>=4; j-=4) {
unsigned int temp = (bcd & (0xf<<j))>>j;
if(temp==0){
bcd_string[j/4] = '0';
} else if(temp==1){
bcd_string[j/4] = '1';
} else if(temp==2){
bcd_string[j/4] = '2';
} else if(temp==3){
bcd_string[j/4] = '3';
} else if(temp==4){
bcd_string[j/4] = '4';
} else if(temp==5){
bcd_string[j/4] = '5';
} else if(temp==6){
bcd_string[j/4] = '6';
} else if(temp==7){
bcd_string[j/4] = '7';
} else if(temp==8){
bcd_string[j/4] = '8';
} else if(temp==9){
bcd_string[j/4] = '9';
} else {
bcd_string[j/4] = 'X';
}
printf ("[%u - nibble] => %c\n", j/4, bcd_string[j/4]);
}
printf("<= [MSB]\n");
reverse(bcd_string);
return bcd_string;
}
// For the following function see http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
void reverse(char *str)
{
if (str != 0 && *str != '\0') // Non-null pointer; non-empty string
{
char *end = str + strlen(str) - 1;
while (str < end)
{
char tmp = *str;
*str++ = *end;
*end-- = tmp;
}
}
}
int main(int argc, char * argv[])
{
unsigned int number = 255;
unsigned int bcd = binaryToPackedBCD(number);
char bcd_string[8];
printPackedBCD(bcd, bcd_string);
printf("Binary (Base 10) = %u => Packed BCD (Base 16) = %u\n OR \nPacked BCD String = %s\n", number, bcd, bcd_string);
return 0;
}
The real problem here is confusion of bases and units
The 202 should be HEX which equates to 514 decimal... and therefore the BCD calcs are correct
Binary code decimal will convert the decimal (514) into three nibble sized fields:
- 5 = 0101
- 1 = 0001
- 4 = 0100
The bigger problem was that you have the title the wrong way around, and you are converting Uint to BCD, whereas the title asked for BCD to Unint
My 2 cents, I needed similar for a RTC chip which used BCD to encode the time and date info. Came up with the following macros that worked fine for the requirement:
#define MACRO_BCD_TO_HEX(x) ((BYTE) ((((x >> 4) & 0x0F) * 10) + (x & 0x0F)))
#define MACRO_HEX_TO_BCD(x) ((BYTE) (((x / 10 ) << 4) | ((x % 10))))
A naive but simple solution:
char buffer[16];
sprintf(buffer, "%d", var);
sscanf(buffer, "%x", &var);
This is the solution that I developed and works great for embedded systems, like Microchip PIC microcontrollers:
#include <stdio.h>
void main(){
unsigned int output = 0;
unsigned int input;
signed char a;
//enter any number from 0 to 9999 here:
input = 1265;
for(a = 13; a >= 0; a--){
if((output & 0xF) >= 5)
output += 3;
if(((output & 0xF0) >> 4) >= 5)
output += (3 << 4);
if(((output & 0xF00) >> 8) >= 5)
output += (3 << 8);
output = (output << 1) | ((input >> a) & 1);
}
printf("Input decimal or binary: %d\nOutput BCD: %X\nOutput decimal: %u\n", input, output, output);
}
This is my version for a n byte conversion:
//----------------------------------------------
// This function converts n bytes Binary (up to 8, but can be any size)
// value to n bytes BCD value or more.
//----------------------------------------------
void bin2bcdn(void * val, unsigned int8 cnt)
{
unsigned int8 sz, y, buff[20]; // buff = malloc((cnt+1)*2);
if(cnt > 8) sz = 64; // 8x8
else sz = cnt * 8 ; // Size in bits of the data we shift
memset(&buff , 0, sizeof(buff)); // Clears buffer
memcpy(&buff, val, cnt); // Copy the data to buffer
while(sz && !(buff[cnt-1] & 0x80)) // Do not waste time with null bytes,
{ // so search for first significative bit
rotate_left(&buff, sizeof(buff)); // Rotate until we find some data
sz--; // Done this one
}
while(sz--) // Anyting left?
{
for( y = 0; y < cnt+2; y++) // Here we fix the nibbles
{
if(((buff[cnt+y] + 0x03) & 0x08) != 0) buff[cnt+y] += 0x03;
if(((buff[cnt+y] + 0x30) & 0x80) != 0) buff[cnt+y] += 0x30;
}
rotate_left(&buff, sizeof(buff)); // Rotate the stuff
}
memcpy(val, &buff[cnt], cnt); // Copy the buffer to the data
// free(buff); //in case used malloc
} // :D Done
long bin2BCD(long binary) { // double dabble: 8 decimal digits in 32 bits BCD
if (!binary) return 0;
long bit = 0x4000000; // 99999999 max binary
while (!(binary & bit)) bit >>= 1; // skip to MSB
long bcd = 0;
long carry = 0;
while (1) {
bcd <<= 1;
bcd += carry; // carry 6s to next BCD digits (10 + 6 = 0x10 = LSB of next BCD digit)
if (bit & binary) bcd |= 1;
if (!(bit >>= 1)) return bcd;
carry = ((bcd + 0x33333333) & 0x88888888) >> 1; // carrys: 8s -> 4s
carry += carry >> 1; // carrys 6s
}
}
Simple solution
#include <stdio.h>
int main(void) {
int binaryInput = 514 ; //0x202
int bcdResult = 0;
int digit = 0;
int i=1;
printf("Binary: 0x%x (dec: %d)\n", binaryInput , binaryInput );
while (binaryInput > 0) {
digit = binaryInput %10; //pick digit
bcdResult = bcdResult+digit*i;
i=16*i;
binaryInput = binaryInput/ 10;
}
printf("BCD: 0x%x (dec: %d)\n", bcdResult , bcdResult );
return 0;
}
Binary: 0x202 (dec: 514)
BCD: 0x514 (dec: 1300)
You can also try the following:
In every iteration the remainder ( represented as a nibble ) is positioned in its corresponding place.
uint32_t bcd_converter(int num)
{
uint32_t temp=0;
int i=0;
while(num>0){
temp|=((num%10)<<i);
i+=4;
num/=10;
}
return temp;
}