C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Подсчет CRC
Borgir
Отправлено: 28.08.2003, 10:32


Не зарегистрирован







Возникла у меня необходимость подсчитывать CRC в программе. А как это реализовать не знаю. То есть есть у меня некая исходная AnsiString, и надо посчитать ее CRC и соответственно выдать результат (хоть в AnsiString, хоть в CHAR). Нашел на форуме по Дельфи процедурку, но конвертировать паскалевский текст в С++ оказалось не так просто (например я не знаю С++сный аналог паскалевской функции Ord().

Может кто поможет. Заранее спасибо.
Ermakov
Отправлено: 29.08.2003, 06:16


Не зарегистрирован







Нашел кусок который когдато делал

unsigned int CRC16(int Count,char *Ptr)
{
unsigned int Data;
int CRC=0xffff;

while(Count)
{
Data=*Ptr;
CRC^=Data;
for(int j=0;j<8;j++) // побитная обработка
{
if(CRC&1)
{CRC>>=1;
CRC^=0xa001;}
else
{CRC>>=1;}
}
Ptr++;
Count--;
}
return CRC;
}

код конечно ни самый лучший, на входе исло байт которые надо подсчитать и ссылка на массив байт
Borgir
Отправлено: 29.08.2003, 07:10


Не зарегистрирован







Функция хорошая. Только подскажите, как полученное число преобразовать в ASCII, чтобы можно было добавить его к исходной строке и послать в качестве команды некоему внешнему устройству по COM-порту?
Ermakov
Отправлено: 29.08.2003, 07:30


Не зарегистрирован







ну если надо просто int в ASCII то функция itoa() преобразует. В билдере IntToStr() есть.

Если я правильно понял вопрос
Asher
Отправлено: 29.08.2003, 08:22


Мастер участка

Группа: Модератор
Сообщений: 550



Преобразование из AnsiString AStr в массив байт *CStr
CODE
AnsiString AStr = "ATDP123456";
char *CStr = AStr.c_str();

Добавление контрольной суммы к строке
CODE
char CRC = 33;
AStr += CRC;

P.S. Запрсто можно нарваться на управляющий символ или на NULL, поэтому для контрольной суммы все-таки наверное надежнее делать IntToHex(CRC, 2) чтобы получать результат стандартной длины.
Тогда получим:
CODE
char CRC = 33;
AStr += IntToHex(CRC, 2);
Borgir
Отправлено: 29.08.2003, 11:42


Не зарегистрирован







Что-то видимо я совсем чайник, но у меня ничего не получается. Наверно я не так спрашиваю. Скажем так. Есть некая строка символов. Я считаю ее CRC этой функцией, на выходе которой целое число. Но я точно знаю, что в качестве CRC к строке должны добавляться 2 символа. Как мне их получить? то что вы тут привели выше не помогает. Вот конкретный пример (я его выловил шпионом СОМ-порта):
исходная строка "#91200000C", при этом CRC "F2". Как мне его получить? Следуя вашим рекомендациям я получал совершенно другое
или еще такой вопрос. Беру я например первый символ исходной строки, мне надо получить его ASCII-код. Как это сделать? Ведь точно должна быть такая функция. И обратная должна быть.
Kot
Отправлено: 29.08.2003, 12:11


Ученик-кочегар

Группа: Участник
Сообщений: 6



Так а зачем поток с порта преобразовывать в АСКИ.
Во-вторых полином использованный в данной функции 0xa001 а может применятся и другой. Данная функция была написана для работы с протоколом ModBus.
Что у тебя за железка раскажи по подробнее.
Asher
Отправлено: 29.08.2003, 13:25


Мастер участка

Группа: Модератор
Сообщений: 550



QUOTE
Беру я например первый символ исходной строки, мне надо получить его ASCII-код. Как это сделать? Ведь точно должна быть такая функция. И обратная должна быть.

Считай что тип char это и есть символы в кодах ASCII если так надо
Преобразование из AnsiString AStr в массив байт *CStr
CODE

AnsiString AStr = "ATDP123456";
char *CStr = AStr.c_str();

CStr[0] — код ASCII первого символа, CStr[1] второго, и так далее до CStr[AStr.Length()-1]
Если символ хранящийся в char прибавляешь к строке в AnsiString, как
CODE
char CRC = 33;
AStr += CRC;

то он сам и переведется. Если хочешь сам, то
AStr += (AnsiString)CRC;

Если тебя смущает что отладчик при наведении на char пишет буквы — ну попробуй переписать из char в int и смотри на цифры, сверяясь со своей таблицей ASCII.

А чтобы получить конкретный правильный код CRC надо бы знать конкретный алгоритм. CRC это не имя собственное

Отредактировано Asher — 29/08/2003, 15:28
Nick
Отправлено: 31.08.2003, 06:42


Машинист паровоза

Группа: Участник
Сообщений: 247



QUOTE (Borgir @ 28/08/2003, 11:34)
Не знаю С++сный аналог паскалевской функции Ord().

Если те это поможет:
Ord() — насколько я помню это код символа.
В C++ он не нужен т.к.


char a = 'a';
int i = 1;
char b = a + i; // = 'b'

Можно легко сложить два char
i = a+b;
в паскале пришлось бы
i := Ord(a)+Ord(cool.gif;

Borgir
Отправлено: 02.09.2003, 06:26


Не зарегистрирован







Спасибо, всем за участие в обсуждении. Я уже во всем разобрался  — просто нашел функцию в другой программе. Там немного более сложный алгоритм, чем тот, что был приведен здесь в примере, но суть таже самая. Если кому интересно могу привести текст этой функции.
FoxVID
Отправлено: 02.01.2004, 16:20


Ученик-кочегар

Группа: Участник
Сообщений: 29



Уважаемые, однако, подсчет контрольной суммы зависит от конкретной реализации. Может быть просто суммирование всех байт, может быть "инкремент инверсии суммы байтов" *(Меркурий112Ф) и т.д.
Я уже не говорю о подсчете контрольной суммы в виде CRC-8, CRC-16, CRC-32 и т.д.
Нужно знать для какого аппарата и по какому алгоритму реализован подсчет контрольной суммы.
DVD
Отправлено: 21.05.2004, 09:42


Дежурный стрелочник

Группа: Участник
Сообщений: 33



А есть ли какой-нибудь компонент для подсчета CRC любых файлов? Даже очень больших. Ведь ручками это затруднительно делать.
exp
Отправлено: 21.05.2004, 21:24


Мастер участка

Группа: Участник
Сообщений: 304



Дааааа, дожили. Вот так мозги и ветшают.
Сначала просим компонентик, потом исходники проги, а потом мозги совсем перестанут работать. sad.gif((

По сути твоя задача состоит:
1) В представлении сообщения в двоичном виде виде
2) Выборе образующего полинома
3) Реализации деления* (или умножения**) по модулю 2.
*4) В случае деления исходного сообщения нужно добавить полученный остаток от деления в конец сообщения и отправить его.
**5) В случае умножения сообщения на образующий полином просто отправить полученный резулютат.

6) При получении сообщения на приемнике — разделить принятое сообщение на образующия полином и проверить остаток от деления на равенство нулю. В случае этого равенства считать, что принятое сообщение пришло без ошибок.

Вот и все.
//Кстати лично мне больше нравится вариант с умножением.

Вернуться в Вопросы программирования в C++Builder