Aptem |
Отправлено: 02.03.2005, 12:14 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
Здравствуйте!
Что-то я совсем запутался с преобразованиями типов.
У меня проблема. Предположим, что я считал из файла 2 байта (это 16-битное число). Мне необходимо привести это число в десятичную форму. Как это сделать???
А как перевести 4-байтное (32-битное) число в десятичную форму?
Спасибо за внимание.
|
|
Bond |
Отправлено: 02.03.2005, 12:26 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
CODE | char buffer[10];
// 16bit, buffer[0] & buffer[1]
short val16= *((short*)buffer);
// 16bit, buffer[4] & buffer[5]
val16 = *((short*)(buffer+4);// 16bit
// 32bit, buffer[0] & buffer[1] & buffer[2] & buffer[3]
int val32= *((int*)buffer);
// 32bit, buffer[4] & buffer[5] & buffer[6] & buffer[7]
val16 = *((int*)(buffer+4); |
|
|
Guest |
Отправлено: 02.03.2005, 12:27 |
|
Не зарегистрирован
|
Десятичное — это не тип а формат представления
Вы считали два байта в __int16 ival16
Посмотреть в десятичном виде например так AnsiString(int(ival16))
с __int32 еще проще
вы считываете 4 байта в int ival AnsiString(ival)
PS. конструктор AnsiString можно заменить на ltoa
PPS. Нужно следить за порядком следования байтов в файле — может понадобиться их переставить, но это зависит от способа записи.
|
|
Konstantine |
Отправлено: 02.03.2005, 12:30 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
читайте в int и отображайте как надо (в десятичном виде — ShowMessage(IntToStr(a)))... это не является преобразованием... другое дело если Вы считали в char[], а ходите поместить в int, тогда
если вопрос оказался не раскрыт , то подробнее, что и куда преобразовать.... чем и куда считали
|
|
Aptem |
Отправлено: 02.03.2005, 19:30 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
Проблема вообщем в следующем...
Это касается работы с HDF файлом. В спецификации к формату говорится, то первые 4 байта это слово "NCSA". Я считываю эти 4 байта. То есть каждый байт это одна буква, проблем нет. Но дальше говорится, что идет 16-ти битное число. Я его считываю в char buf[2] и теперь хочу увидеть его в десятичной форме. В этом собственно и задача!
|
|
Bond |
Отправлено: 02.03.2005, 19:39 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Смотри ниже: short val16 = *((short*)buf);
|
|
Bond |
Отправлено: 02.03.2005, 19:41 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
int — число 32-тиразрядное в билдере
short — 16-тиразрядное
|
|
** Admin |
Отправлено: 02.03.2005, 22:22 |
|
Не зарегистрирован
|
Я делаю по другому.
Объявляю объединение
union U1{
short a;
char ch[2];
}u1;
и получается что в одной области памяти
лежит или 2 символа или одно короткое целое
(для int — соответственно char ch[4]; )
Далее считываю как 2 байта в u1.ch[]
а работаю как с коротким целым как u1.a
|
|
Konstantine |
Отправлено: 03.03.2005, 09:16 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
смотри сам — оба метода (предложенных Bond и Admin) используют одно и то же.... разница — первый удобен при однократном использовании, а второй — при многократных вхождениях — читабельней текст... хотя — кому как...
да, кстати — в первом необходимо следить, чтоб буфер СУЩЕСТВОВАЛ причём минимум на 2 байта...
а вообще — зачем читать в char буфер? ведь можно сделать так:
CODE | short a;
FileRead(iFileHandle, &a, 2); | т.е. сразу считать в short
|
|
Bond |
Отправлено: 03.03.2005, 13:18 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Создаешь структуру
CODE | typedef struct
{
char chNCSA[4];
short shVal16;
...
} HDF_head_t;
HDF_head_t HDF_head |
и с fread(...)-ом вычитываешь в &HDF_head, sizeof(HDF_head_t)
|
|
Konstantine |
Отправлено: 03.03.2005, 18:00 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
а названия зачем такие сложные???
Присоединить изображение
|
|
Aptem |
Отправлено: 06.03.2005, 06:05 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
Появилась еще одна проблема. Преобразования которые вы предлагали не совсем корректны. Сейчас поясню почему. Предположим я считываю 2 байта из файла, например 1-ый байт (hex:00), а второй (hex:1е). Если я преобразую это в число как *((short*)buf), то она покажет всякую ерунду, на самом деле здесь закодировано число 30. То есть если откинуть все нули (в данном случае только один), то получается как надо. Теперь вопрос: Как можно отбросить все нули с левой стороны? Я считываю байты в char buf[2].
Спасибо.
|
|
Георгий |
Отправлено: 06.03.2005, 13:34 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
это не просто проблема — это проблема маленьких и больших индейцев BigEndian и LittleEndian;
должны помочь функции ntoh и hton -вернее, как помнится, это не функции, а макросы.
Отредактировано Георгий — 06/03/2005, 13:34 |
|
timson |
Отправлено: 06.03.2005, 20:17 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 82
|
нее, тута это было уже, самый реальный способ чтения бинарников:
CODE | short buf;
fread(&buf, 1, 2, f);
|
|
|
Admin |
Отправлено: 06.03.2005, 22:28 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
to timson:
QUOTE | short buf;
fread(&buf, 1, 2, f); |
Это НЕ ВСЕГДА возможно. А если я читаю из COM-порта с прибора,
с ответной посылкой байта после каждого прочитанного байта ?
(реальные приборы). То есть я при всем своем желании просто не могу
прочитать сразу более одного байта информации !
to Aptem
QUOTE | Преобразования которые вы предлагали не совсем корректны. |
А то что я предлагал ???
union U{
short a;
char ch[2];
}u;
У меня такое работает корректно, тоже приходится считывать
в char[] или byte[] буфер и потом идти по буферу и местами
преобразовывать в различные форматы — в int и в short и в double
и обратно в этот char[] буфер.
Например, у меня объявление, что-то типа:
union MY_BUF{
char buf[1024];
struct{ // это эти-же 1024 байта что и buf — для этого union и нужен
char ser_num[110];
int freq; // 4 байта
short volt; // 2 байта
double price; // 8 байт
char wrong[900];
};
}un;
То есть все читаю в буфер buf[1024], а работаю то с этим буфером
(кое-что так делать удобней), то с данными из struct:
un.freq
un.volt
un.ser_num[]
un.price и так далее...
Зачем это мне нужно — могу объяснить:
Есть приборы — они работает по COM-порту, по принципу -
послал 1 байт — прочитал 1 байт, то есть сразу прочитать/записать
n-байт невозможно, например, целое число пересылается
как 4 отдельных байта — по 1 — прочитал байт — записал в порт байт, прочитал — записал ...
Отредактировано Admin — 06/03/2005, 22:34
|
|
Konstantine |
Отправлено: 09.03.2005, 11:56 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
преобразования правильны, а по поводуQUOTE | Предположим я считываю 2 байта из файла, например 1-ый байт (hex:00), а второй (hex:1е). Если я преобразую это в число как *((short*)buf)... | — это неправильное понимание Вами хранения двубайтных чисел в файлах... расскажу — на самом деле — если в файле записано 00 1е, то это число 7680 , а не 30 ... поэтому проще всего — написАть функцию перевода — ей дать указатель на буфер, а она вернёт число, тело например такое:CODE | res=255*buf[0]+buf[1];
|
|
|
Bond |
Отправлено: 09.03.2005, 12:46 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Согласен с Konstantine: нельзя утверждать что неправильно работает то, что работает уже десятки лет
А относительно чтения из файла — нужно внимательно разобраться с форматом файла.
|
|
AVC |
Отправлено: 09.03.2005, 12:58 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE |
Преобразования которые вы предлагали не совсем корректны. Сейчас поясню почему. Предположим я считываю 2 байта из файла, например 1-ый байт (hex:00), а второй (hex:1е). Если я преобразую это в число как *((short*)buf), то она покажет всякую ерунду, на самом деле здесь закодировано число 30
|
Ваша проблема характерна для работы с протоколом TCP/IP. Там порядок следования байтов обратен тому, который используется для хранения чисел в памяти (то, что описал Konstantine). Для приведения из одного стандарта к другому используются функции из серии hton.. |
|
Aptem |
Отправлено: 22.03.2005, 04:53 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
У меня такая проблема. Теперь необходимо все записать в файл, делаю так:CODE | union DIG
{
short i;
char c[4];
} digit;
digit.i = 23654;
FILE *file = fopen ( "1.txt", "wb" );
fwrite ( digit.c, 4, 1, file );
fclose ( file ); |
Вроде бы все нормально, но когда я открыл файл в hex-редакторе, то увидел следующее: 66 5C 00 00, на самом деле число 23654 это 5C 66, то есть оно перевернуто вверх ногами.
Как исправить?
Спасибо
|
|
Георгий |
Отправлено: 22.03.2005, 09:31 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
QUOTE (Георгий @ 06/03/2005, 13:34) | это не просто проблема — это проблема маленьких и больших индейцев BigEndian и LittleEndian;
должны помочь функции ntoh и hton -вернее, как помнится, это не функции, а макросы. |
ещё раз повторяюсь... |
|
Admin |
Отправлено: 22.03.2005, 13:27 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
QUOTE | union DIG
{
short i;
char c[4];
} digit;
|
А почему 4 байта, а не 2 на short ? (char c[2])
Тогда в остальных 2 байтах может быть мусор.
|
|
Aptem |
Отправлено: 22.03.2005, 15:21 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
QUOTE (Георгий @ 22/03/2005, 09:31) | это не просто проблема — это проблема маленьких и больших индейцев BigEndian и LittleEndian;
должны помочь функции ntoh и hton -вернее, как помнится, это не функции, а макросы. |
А где их взять то?
|
|
Guest |
Отправлено: 22.03.2005, 15:30 |
|
Не зарегистрирован
|
winsock2.h или winsock.h |
|