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

 
Приведение типов
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, тогда
CODE
int a=(int)(c[i]);

если вопрос оказался не раскрыт , то подробнее, что и куда преобразовать.... чем и куда считали
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: нельзя утверждать что неправильно работает то, что работает уже десятки лет cool.gif
А относительно чтения из файла — нужно внимательно разобраться с форматом файла.
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

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