Если подсчитать контрольную сумму одного и того же текстового файла разными способами, разве результат не должен получиться одинаковым? По-моему, должен.
И мне кажется, что самый верный результат у первой проги, там она просчитывает контрольную сумму по формуле C = T%(M+1);
А остальные две проги написаны по алгоритму CRC16 (я взяла их из разных источников) и они тоже дают разный результат! Хотя казалось бы, они идентичны. Например, в текстовом файле записано "This is"
первая прога выдает: 148
вторая: 57134
а третья вообще: -23314
Почему так?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
void main (void)
{
clrscr();
int dlina_stroki;
int i,T,C;
int M=255;
FILE *in;
const n=80;
char stroka[n], p[n];
in=fopen("text.txt","rt");
fgets(stroka,n,in);
fclose(in);
dlina_stroki=strlen(stroka);
T=0;
for (i=0; i<=dlina_stroki; i++)
T=T+stroka[i];
C = T%(M+1);
printf("The control sum = %d",C);
getch();
}
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
int dlina_stroki,START;
unsigned int crc(unsigned char *buf, unsigned int n)
{
unsigned char i,carry;
int crc16=0xFFFF;
while(n)
{
crc16^=*buf;
for (i=0; i<8; i++)
{
carry=crc16&1;
crc16>>=1;
if (carry)crc16^=0xA001;
}
n--;
buf++;
}
return crc16;
}
void main(void)
{START=0; unsigned int temp;
FILE *in;
const n=1008;
unsigned char stroka[n], p[n];
in=fopen("text.txt","rt");
fgets(stroka,n,in);
fclose(in);
dlina_stroki=strlen(stroka);
clrscr();
temp=crc(stroka,dlina_stroki);
printf("%d",temp);
getch();
}
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
int dlina_stroki,START;
unsigned int crc(unsigned char *buf, int start, int cnt)
{int i,j;
unsigned int temp, flag;
temp=0xFFFF;
for (i=start; i<cnt; i++)
{ temp=temp^buf[i];
for (j=1; j<=8; j++)
{ flag=temp & 0x0001;
temp=temp>>1;
if (flag)temp=temp^0xA001;
}
}
return(temp);
}
void main(void)
{START=0; unsigned int temp;
FILE *in;
const n=1008;
unsigned char stroka[n], p[n];
in=fopen("text.txt","rt");
fgets(stroka,n,in);
fclose(in);
dlina_stroki=strlen(stroka);
clrscr();
temp=crc(stroka,START,dlina_stroki);
printf("%u",temp);
getch();
}
Первая программа - это не CRC, а простая контрольная сумма по модулю 256.
Вторая программа в общем-то идентична третьей, но в ней с ошибкой реализован сдвиг вправо, точнее, переменная crc должна быть беззнаковой, иначе сдвиг "вытягивает" 15-й бит на место ожидаемых справа нулей. Правда, такого эффекта не будет, если int - 32-битный. Правильный результат - 57134.
Кроме того, эти программы не должны компилироваться:
"const n =1008" эквивалентно "const int n = 1008", т. е. n - это переменная, в которую компилятор не даст присваивать стандартными средствами. Объявление "unsigned char stroka[n]" должно вызывать (вызывало у меня) ошибку компиляции, т. к. n - не константа, а переменная. В Си символические константы (аналогичные нетипизированным константам Паскаля) можно определить только с помощью #define или enum.
На Си это должно выглядеть примерно так:
#include <stdio.h>
#include <string.h>
int checksum(const char *buf, unsigned len)
{
int s = 0;
while (len--) s += *buf++;
return s & 0xFF; { можно заменить на "return s % M" для сумм по другому модулю }
}
unsigned crc16(const char *buf, unsigned len)
{
int i;
unsigned crc = 0xFFFF;
while (len--)
{
crc ^= *buf++;
for (i = 8; i--;)
{
int f = crc & 1;
crc >>= 1;
if (f) crc ^= 0xA001;
}
}
return crc;
}
int main()
{
char buf[4096];
int len;
FILE *f = fopen("text.txt", "rt");
fgets(buf, sizeof(buf), f);
len = strlen(buf);
printf("Checksum = %d\n", checksum(buf, len));
printf("CRC-16 = %u\n", crc16(buf, len));
putchar('\n');
fclose(f);
return 0;
}
А чем отличается CRC-16 от CRC-8?
Я нашла такой пример реализации CRC-8
void Update_CRC(char in, char *crc)
{
#define POLYNOMIAL 0x1D // x^8 + x^4 + x^3 + x^2 + 1
*crc = *crc ^ in;
for (unsigned char i=0; i<8; i++)
{
*crc = (*crc & 0x80)? (*crc << 1) ^ POLYNOMIAL : (*crc << 1);
}
}
#include <stdio.h>
#include <string.h>
...
int main()
{
int i;
const char *str = "Hello";
unsigned char crc = 0;
for (i = 0; i < strlen(str); i++)
Update_CRC(str[i], &crc);
printf("CRC-8 = %u\n", crc);
return 0;
}
Спасибо, xds, ты все доступно объяснил. Единственное, у меня еще вопрос остался невыясненным. Вот у меня есть текстовый файл в нем предположим записана такая информация:
1000
0100
0010
0001
Почему в обеих прогах (одна по модулю 256, другая по методу CRC-8) результат контрольной суммы разный? Мне казалось, что неважно каким методом считать, но ответ должен быть одинаковым, или я не права?
по модулую 256:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
void main (void)
{
clrscr();
int dlina_stroki;
unsigned int i,T,C;
int M=255;
FILE *in;
char ch;
in=fopen("text.txt","rt");
T=0;
do {
ch=getc(in);
T=T+ch;
} while (ch!=EOF);
fclose(in);
C = T%(M+1);
printf("The control sum = %u\n",C);
getch();
}
#include <stdio.h>
#include <string.h>
#include <conio.h>
void Update_CRC(char in, char *crc)
{
#define POLYNOMIAL 0x1D // x^8+x^4+x^3+x^2+1
*crc = *crc^in;
for (unsigned char i=0; i<8; i++)
{
*crc=(*crc & 0x80) ? (*crc << 1) ^POLYNOMIAL: (*crc << 1);
}
}
int main()
{
int i;
unsigned char crc = 0;
FILE *_open;
char ch;
clrscr();
_open=fopen("text.txt","rt");
do {
ch=getc(_open);
Update_CRC(ch,&crc);
} while (ch!=EOF);
fclose(_open);
printf("CRC-8 = %u\n", crc);
getch();
return 0;
}
Еще раз спасибо. Теперь все прояснилось. =)
И тебе спасибо! У меня тоже многое прояснилось по поводу CRC В одной из задач, которыми я сейчас занимаюсь, это довольно-таки важный момент.
а чему полином равен в CRC-8 в данном случае?
Тёмный Эльф,
более правильным переводом CRC будет не "контрольная сумма", а "контрольный код".
Собственно, контрольная сумма - частный случай контрольного кода, а сам контрольный код представляет собой хеш-функцию от массива данных, предназначенную для детектирования ошибок. В разных случаях ошибки имеют разную природу и, соответственно, различный характер.
контрольная сумма - хороший ваиант для контролья блоков ПЗУ фиксированного размера, для чего она, собственно, и используется. В то же время она нечувствительна к добавлению или пропуску нулевых байтов, к перестановке байтов местами, а также перестановке битов одного и того же разряда между байтами. Поэтому при передаче пакетов, особенно переменной длины, этот алгоритм неоптимален в качестве контрольного кода.
Таким образом, алгоритмы подсчета контрольного кода могут различаться - главное, чтобы конрольный код, посчитанный по конкретному алгоритму детектировал ошибки характерные для того способа передачи, который защищается этим кодом.
Блин! меня наверно за идиота посчитали! в этой программе полином не 1D! А если и 1D то тогда программа не правильная.
Доказываю: вписываем в text.txt таокй текст 12345 - получаем ответ - 30!
идем дальше. Открываем text.txt в HexWorkshop'e заменяем байты на 1D должно получиться СRC=0!!! но так не получается! Что можете сказать по этому поводу?