0

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

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
prak
  • 133
  • 1
  • 9
  • There is already lots of CRC code on this website in C. Or did you want to do it yourself? example http://stackoverflow.com/a/27950866/4603670 – Barmak Shemirani Mar 15 '15 at 05:22
  • want to do it myself .kindly help i could not understand that Floating Point:Stack Underflow – prak Mar 15 '15 at 16:38

2 Answers2

0

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);
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • But that isn't a problem with div[] it doesn't display any garbage value.Please tell me why? – prak Mar 15 '15 at 09:15
  • @prak Sometimes you get lucky. Maybe the `div[]` array is full of zeros to start with. You can see by printing the whole array with `for(i=0;i<100;i++)printf("%02x\n",div[i]);` – user3386109 Mar 15 '15 at 18:45
0

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.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • I know my logic is not correct and it has nothing to do with crc but on dry running it is giving the output.But when i compile it gives error.Please help – prak Mar 27 '15 at 09:49
  • You would save a lot of time if you do this right the first time. Working with strings, converting to bits, takes too long. It's easier to convert string to integers, and then you can work directly with bits. I update the example to show working with integers and bits, also printout the values in binary. – Barmak Shemirani Mar 28 '15 at 03:47