Error in Program to implement cyclic redundancy check - c

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.

Related

Why does left-shifting an integer by 24-bit yield the wrong result?

I tried left-shifting a 32-bit integer by 24:
char *int_to_bin(int num) {
int i = 0;
static char bin[64];
while (num != 0) {
bin[i] = num % 2 + 48;
num /= 2;
i++;
}
bin[i] = '\0';
return (bin);
}
int main() {
int number = 255;
printf("number: %s\n", int_to_bin(number));
printf("shifted number: %s\n", int_to_bin(number << 24));
return 0;
}
OUTPUT:
number: 11111111
shifted number: 000000000000000000000000/
and i left-shift with 23-bit it yields this result:
0000000000000000000000011111111
Well Why is it like that and what's the matter with '/' at the end of the wrong result?
Two things:
If number has the value 255 then number << 24 has the numerical value 4278190080, which overflows a 32-bit signed integer whose largest possible value is 2147483647. Signed integer overflow is undefined behavior in C, so the result could be anything at all.
What probably happens in this case is that the result of the shift is negative. When num is negative then num % 2 may take the value -1, so you store character 47 in the string, which is /.
Bit shifting math is usually better to do with unsigned types, where overflow is well-defined (it wraps around and bits just shift off the left and vanish) and num % 2 can only be 0 or 1. (Or write num & 1 instead.)
Your int_to_bin routine puts the least-significant bits at the beginning of the string (on the left), so the result is backwards from the way people usually write numbers (with the least-significant bits on the right). You may want to rewrite it.
Shift works fine, you simply print it from the wrong direction.
char *int_to_bin(char *buff, int num)
{
unsigned mask = 1U << (CHAR_BIT * sizeof(num) - 1);
char *wrk = buff;
for(; mask; mask >>= 1)
{
*wrk++ = '0' + !!((unsigned)num & mask);
}
*wrk = 0;
return buff;
}
int main()
{
char buff[CHAR_BIT * sizeof(int) + 1];
int number = 255;
printf("number: %s\n", int_to_bin(buff, number));
printf("shifted number: %s\n", int_to_bin(buff, number << 24));
return 0;
}
Shifting signed integers left is OK, but the right shift is implementation-defined. Many systems use arithmetic shift right and the result is not the same as using the bitwise one:
https://godbolt.org/z/e7f3shxd4
you are storing numbers backwards
you are using signed int32 while shifting by 23 results needs more than 32 bits to handle that operation ...you should use long long int
signed integer can lead to wrong answers as 1<<31 is -1 which results in bad characters in string
finally using unsigned long long int with storing numbers in correct order will produce correct string
you should try re write code on your own before seeing this improved version of your code
#include<stdio.h>
#include<stdlib.h>
char *int_to_bin( unsigned long long int num) {
int i = 0;
static char bin[65];
while (i != 64) {
bin[63-i] = num % 2 + 48;
num /= 2;
i++;
}
bin[64] = '\0';
return (bin);
}
int main() {
unsigned long long int number = 255;
printf("number 1: %s\n", int_to_bin(number));
printf("number 2: %s\n", int_to_bin(number << 24));
return 0;
}

Question on C program that reverses an unsigned integers bits

Hi all I am writing a C program that asks the user for an unsigned integer. The program will then call a function
unsigned int reverse_bits(unsigned int n)
This function should return an unsigned integer whose bits are the same as those of n but in reverse
order.
Print to screen the integer whose bits are in reverse order.
Example:
User enters:
12 (binary 16 bits is 0000000000001100)
Program print to screen:
12288 (0011000000000000)
This is the code i have but it does not output the right answer:
#include <stdio.h>
//function prototype
unsigned int reverse_bits(unsigned int n);
int main(void) {
unsigned int n;
unsigned int bits;
printf("Enter an unsigned integer: ");
scanf("%u",&n);
bits = reverse_bits(n);
printf("%u\n",bits);
return 0;
}
unsigned int reverse_bits(unsigned int n) {
unsigned int reverse = 0;
while (n > 0) {
reverse = reverse << 1;
if((n & 1) == 1) {
reverse = reverse | 1;
}
n = n >> 1;
}
return reverse;
}
This does not give me 12288 when I enter 12, it gives me 3, what did I do wrong?
The result depends on how many bits an unsigned int is stored on your machine. It is usually 4 bytes (32 bits). So, in your case 12 (00000000000000000000000000001100 in binary) becames 805306368 (00110000000000000000000000000000 in binary).
Apart from that, you need to iterate over all bits of an unsigned int:
for (size_t i = 0; i < sizeof(unsigned int) * 8; i++) {
reverse = reverse << 1;
if((n & 1) == 1) {
reverse = reverse | 1;
}
n = n >> 1;
}

C: How to use decimal number in hex one to one?

I want to "convert" a decimal number to a hex number. Not like 10 -> A.
E.g.: 10 -> 0x10, 55 -> 0x55, 2021 -> 0x2021, ...
My input is an int.
I already heard something about it. You can get the first digit with modulo 10. E.g. 55 % 10 is 5. But I don't know how to get the other digits and how to put it together.
I am using this function for other purpose but I did some changes and its work fine.
you can use this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define CHECK_ALPHA_HEX(REC_CHAR) (unsigned)('#' < REC_CHAR && REC_CHAR < 'G')
#define CHECK_NUM(REC_CHAR) (unsigned)('/' < REC_CHAR && REC_CHAR < ':')
void DEC_TO_HEX(int in, int *outval ) {
uint8_t tbuff[5];
uint8_t chr_count = 0;
uint8_t len = sprintf(tbuff,"%d",in);
while(chr_count < len) {
tbuff[chr_count] -= CHECK_NUM(tbuff[chr_count]) ? '0' : CHECK_ALPHA_HEX(tbuff[chr_count]) ? '7' : tbuff[chr_count];
*outval |= (tbuff[chr_count] << (4 *((len-1) - chr_count)));
chr_count++;
}
}
int main() {
int out = 0;
int in = 2021;
DEC_TO_HEX(in,&out);`
printf("%x",out);
}
https://godbolt.org/z/8T9Wqb87n
how to get the other digits
Remove the extracted digit from input.
Repeat the extraction of one digit, until there are no more digits in input.
how to put it together.
Learn C programming language. Write a program that implements the algorithm.
As I understand, an integer value has to be converted to another integer. From there it's just basic arithmetic, where the process generatally consists of:
Getting one digit from input.
Putting it in output.
Removing that digit from input.
shifting input & output to desired state
I came up with 3 separate such convert_* function implementations. First one is similar to common simple int->string conversion algorithms - it first converts the digits and that the results is "inverted". The second one extract the digits from propor position from input - getting the most significant base10 digit from input and moving between base10 digits of input. The third one, puts base10 digits on the end of hex number (startign from the mast significant base16 digit), and then shifts hex number to the right to handle 0x55000000 trailing zeros in result.
#include <limits.h>
#include <stdio.h>
const unsigned maxhexdigits = sizeof(unsigned) * CHAR_BIT / 4;
unsigned convert_andrevert(unsigned n) {
unsigned o = 0;
unsigned hexdigits = 0;
// Convert hex digits from "the back"
while (n && hexdigits != maxhexdigits) {
o <<= 4;
o += n % 10;
n /= 10;
++hexdigits;
}
const unsigned swaps = hexdigits / 2;
//printf("a %#x %d %d \n", o, hexdigits, swaps);
// Invert hex digits
for (unsigned i = 0; i < swaps; ++i) {
const unsigned m1 = 0xFu << (i * 4);
const unsigned m2 = 0xFu << ((hexdigits - i - 1) * 4);
const unsigned road = (hexdigits - i * 2 - 1) * 4;
// extract bits m1
unsigned t = (o & m1) << road;
//printf("b o=%#x i=%#x 1=%#x m2=%#x t=%#x road=%d\n", o, i, m1, m2, t, road);
// set bit m1 in place of m2
o = (o & ~m1) | ((o & m2) >> road);
// set bit m2 in place of m1
o = (o & ~m2) | t;
}
return o;
}
unsigned mypow10u(unsigned i) {
unsigned r = 1;
while (i--) {
r *= 10;
}
return r;
}
unsigned convert_frommax(unsigned n) {
n %= mypow10u(maxhexdigits);
unsigned o = 0;
// always start from the maximuim digit, because
// we know it's location.
for (int i = maxhexdigits - 1; i >= 0; --i) {
o <<= 4;
//printf("o=%#x u=%d pow10u(i)=%u digit=%u rest=%u\n",
//o, i, mypow10u(i),
//n / mypow10u(i),
//n % mypow10u(i));
// extract leading base10 digit
o += n / mypow10u(i);
n %= mypow10u(i);
}
return o;
}
unsigned convert_andshift(unsigned n) {
unsigned o = 0;
unsigned hexdigits = 0;
// Convert hex digits from "the back"
// put put them from the front.
while (n && hexdigits != maxhexdigits) {
o >>= 4;
o += (n % 10) << (maxhexdigits * 4 - 4);
//printf("o=%#x %d\n", o, n%10);
n /= 10;
++hexdigits;
}
// Shift right to handle leading (trailing?) zeros.
o >>= ((maxhexdigits - hexdigits) * 4);
return o;
}
void testin(unsigned r, unsigned rr) {
printf(" -> %#x %s", rr, r == rr ? "OK" : "FAIL");
}
void TEST(unsigned a, unsigned r) {
printf("%u", a);
testin(r, convert_andrevert(a));
testin(r, convert_frommax(a));
testin(r, convert_andshift(a));
printf("\n");
}
int main() {
TEST(1, 0x1);
TEST(55, 0x55);
TEST(123, 0x123);
TEST(2021, 0x2021);
TEST(12345678, 0x12345678);
}
From basic profiling, convert_andshift is the fastest function.
Here is an approach:
#include<stdio.h>
int main()
{
int num = 0;
char cNumHex[20];
puts("Enter a decimal formed hex number: ");
scanf("%d",&num);
sprintf(cNumHex, "0x%d", num);
printf("\nThe entered as hex: %s\n", cNumHex);
return 0;
}
The output:
Enter a decimal formed hex number:
49478
The entered as hex: 0x49478

How to get certain bits of a char array to another char array in C?

I have a char (input) array with size 60. I want to write a function that returns certain bits of the input array.
char input_ar[60];
char output_ar[60];
void func(int bits_starting_number, int total_number_bits){
}
int main()
{
input_ar[0]=0b11110001;
input_ar[1]=0b00110011;
func(3,11);
//want output_ar[0]=0b11000100; //least significant 6 bits of input_ar[0] and most significant bits (7.8.) of input_ar[1]
//want output_ar[1]=0b00000110; //6.5.4. bits of input_ar[1] corresponds to 3 2 1. bits of output_ar[1] (110) right-aligned other bits are 0, namely 8 7 ...4 bits is zero
}
I want to ask what's the termiology of this algorithm? How can I easily write the code? Any clues appricated.
Note: I use XC8, arrray of bits are not allowed.
This answer makes the following assumptions. Bits are numbered from 1, the first bit is the MS bit of the first byte. The extracted bit array must be left-aligned. Unused bits on the right are padded with 0.
#include <stdio.h>
#include <string.h>
#include <limits.h>
#define MAX_LEN 60
#define BMASK (1 << (CHAR_BIT-1))
unsigned char input_ar[MAX_LEN];
unsigned char output_ar[MAX_LEN];
int func(int bits_starting_number, int total_number_bits) {
// return the number of bits copied
int sors_ind, sors_bit, dest_ind = 0;
int i, imask, omask;
memset (output_ar, 0, MAX_LEN); // clear the result
if (bits_starting_number < 1 || bits_starting_number > MAX_LEN * CHAR_BIT)
return 0; // bit number is out of range
if (total_number_bits < 1)
return 0; // nothing to do
bits_starting_number--;
if (bits_starting_number + total_number_bits > MAX_LEN * CHAR_BIT)
total_number_bits = MAX_LEN * CHAR_BIT - bits_starting_number;
sors_ind = bits_starting_number / CHAR_BIT;
sors_bit = CHAR_BIT - 1 - (bits_starting_number % CHAR_BIT);
imask = 1 << sors_bit;
omask = BMASK;
for (i=0; i<total_number_bits; i++) {
if (input_ar[sors_ind] & imask)
output_ar[dest_ind] |= omask; // copy a 1 bit
if ((imask >>= 1) == 0) { // shift the input mask
imask = BMASK;
sors_ind++; // next input byte
}
if ((omask >>= 1) == 0) { // shift the output mask
omask = BMASK;
dest_ind++; // next output byte
}
}
return total_number_bits;
}
void printb (int value) {
int i;
for (i=BMASK; i; i>>=1) {
if (value & i)
printf("1");
else
printf("0");
}
printf (" ");
}
int main(void) {
int i;
input_ar[0]= 0xF1; // 0b11110001
input_ar[1]= 0x33; // 0b00110011
printf ("Input: ");
for (i=0; i<4; i++)
printb(input_ar[i]);
printf ("\n");
func(3,11);
printf ("Output: ");
for (i=0; i<4; i++)
printb(output_ar[i]);
printf ("\n");
return 0;
}
Program output
Input: 11110001 00110011 00000000 00000000
Output: 11000100 11000000 00000000 00000000
First of all, the returntype: You can return a boolean array of length total_number_bits.
Inside your function you can do a forloop, starting at bits_starting_number, iterating total_number_bits times. For each number you can divide the forloopindex by 8 (to get the right char) and than bitshift a 1 by the forloopindex modulo 8 to get the right bit. Put it on the right spot in the output array (forloopindex - bits_starting_number) and you are good to go
This would become something like:
for(i = bits_starting_number; i < bits_starting_number + total_number_bits; i++) {
boolarr[i - bits_starting_number] = charray[i/8] & (1 << (i % 8));
}

Is this the proper way to count the number of 0s in a binary number?

#include <stdio.h>
int NumberOfSetBits(int);
int main(int argc, char *argv[]) {
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
int n = 3;
int count = NumberOfSetBits(n);
printf("Number of set bits is: %d\n", count);
printf("Number of unset bits is: %d", total_bit_size - count);
}
int NumberOfSetBits(int x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x = x >> 1;
}
return count;
}
Number of set bits is: 2
Number of unset bits is: 30
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
^ that will get the size of the int on the system and times it by 8 which is the number of bits in each byte
EDITED: Without the use of the ~
/*
Calculate how many set bits and unset bits are in a binary number aka how many 1s and 0s in a binary number
*/
#include <stdio.h>
unsigned int NumberOfSetBits(unsigned int);
unsigned int NumberOfUnSetBits(unsigned int x);
int main() {
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
unsigned int n = 3;
printf("Number of set bits is: %u\n", NumberOfSetBits(n));
printf("Number of unset bits is: %u", NumberOfUnSetBits(n));
return 0;
}
unsigned int NumberOfSetBits(unsigned int x) {
// counts the number of 1s
unsigned int count = 0;
while (x != 0) {
count += (x & 1);
// moves to the next bit
x = x >> 1;
}
return count;
}
unsigned int NumberOfUnSetBits(unsigned int x) {
// counts the number of 0s
unsigned int count = 0;
while(x != 0) {
if ((x & 1) == 0) {
count++;
}
// moves to the next bit
x = x >> 1;
}
return count;
}
returns for input 3
Number of set bits is: 2
Number of unset bits is: 0
unset bits is 0? Doesn't seem right?
if I use NumberOfSetBits(~n) it returns 30
You've got a problem on some systems because you right shift a signed integer in your bit-counting function, which may shift 1's into the MSB each time for negative integers.
Use unsigned int (or just unsigned) instead:
int NumberOfSetBits(unsigned x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x >>= 1;
}
return count;
}
If you fix that part of the problem, you can solve the other with:
int nbits = NumberOfSetBits(~n);
where ~ bitwise inverts the value in n, and hence the 'set bit count' counts the bits that were zeros.
There are also faster algorithms for counting the number of bits set: see Bit Twiddling Hacks.
To solve the NumberOfSetBits(int x) version without assuming 2's complement nor absence of padding bits is a challenge.
#Jonathan Leffler has the right approach: use unsigned. - Just thought I'd try a generic int one.
The x > 0, OP's code work fine
int NumberOfSetBits_Positive(int x) {
int count = 0;
while (x != 0) {
count += (x & 1);
x = x >> 1;
}
return count;
}
Use the following to find the bit width and not count padding bits.
BitWidth = NumberOfSetBits_Positive(INT_MAX) + 1;
With this, the count of 0 or 1 bits is trivial.
int NumberOfClearBits(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits(x);
}
int NumberOfSetBits_Negative(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
All that is left is to find the number of bits set when x is 0. +0 is easy, the answer is 0, but -0 (1's compliment or sign magnitude) is BitWidth or 1.
int NumberOfSetBits(int x) {
if (x > 0) return NumberOfSetBits_Positive(x);
if (x < 0) return NumberOfSetBits_Negative(x);
// Code's assumption: Only 1 or 2 forms of 0.
/// There may be more because of padding.
int zero = 0;
// is x has same bit pattern as +0
if (memcmp(&x, &zero, sizeof x) == 0) return 0;
// Assume -0
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
here is a proper way to count the number of zeores in a binary number
#include <stdio.h>
unsigned int binaryCount(unsigned int x)
{
unsigned int nb=0; // will count the number of zeores
if(x==0) //for the case zero we need to return 1
return 1;
while(x!=0)
{
if ((x & 1) == 0) // the condition for getting the most right bit in the number
{
nb++;
}
x=x>>1; // move to the next bit
}
return nb;
}
int main(int argc, char *argv[])
{
int x;
printf("input the number x:");
scanf("%d",&x);
printf("the number of 0 in the binary number of %d is %u \n",x,binaryCount(x));
return 0;
}

Resources