Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> из массива байт в int, конвертация пары байтов 
V
    Опции темы
GraNit
Дата 7.10.2012, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 20.10.2007

Репутация: нет
Всего: нет



Здравствуйте, уважемые знатоки!

суть моей проблемы:
читаю из двоичного потока. Поток это файл данных, написан еще под ДОС, поэтому формат файла свой собственный. в нем записан год в виде двух байт, а именно CA07. Это как известно 1994 (старший байт идет за младшим), так вот никак не могу добиться отображения в нормальном виде, получается всякая белиберда типа 838151.
Читаю побайтно в массив char функцией fgetc.
Долго рыл в инете, поэтому может быть много мусора, т.к. пытался применить всякие разные способы преобразования. Поэтому прошу меня сильно по голове не бить smile
Вот моя функция:
Код

AnsiString __fastcall myGetDate(FILE * handle)
{

        char day[2], month[2], year[2];
        int newYear;
        AnsiString field;

        day[0] = fgetc(handle);
        fseek(handle,1,SEEK_CUR);
        month[0] = fgetc(handle);
        fseek(handle,1,SEEK_CUR);
        year[0]=fgetc(handle);
        year[1]=fgetc(handle);
        newYear = *(unsigned int*)year;
        if ((int)day[0]<10) field = "0"+IntToStr((int)day[0]);
        else field = IntToStr((int)day[0]);
        if ((int)month[0]<10) field = field+".0"+IntToStr((int)month[0]);
        else field = field+"."+IntToStr((int)month[0]);
        field = field+"."+IntToStr(newYear);

return field;
}


Это сообщение отредактировал(а) GraNit - 7.10.2012, 13:56
PM MAIL   Вверх
Gluttton
Дата 7.10.2012, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: нет
Всего: 54



GraNit, код не осилил, но если бы мне нужно было из двух байт сделать одно многобайтовое число, то я бы сделал как то так:

Код

#include <iostream>


typedef unsigned int longer;


int main (int argc, char * argv [])
{
    // Размер массива.
    const unsigned int size = 16;

    // Дано два массива:
    // массив байт
    unsigned char bytes [size];
    // и массив чего-нибудь подлиннее.
    longer        longs [size / sizeof (longer)];


    // Для каждого элемента массива "длинных" переменных. 
    for (unsigned int i = 0; i < size; i += sizeof (longer) ) {
        // Столько раз, сколько в нем помещается байт.
        for (unsigned int j = 1; j <= sizeof (longer); ++j) {
            // Эта строка просто генерирует "случайное" содержимое и не является функциональной!
            bytes [i + sizeof (longer) - j] = i + sizeof (longer) - j;

            // В младший байт "длинной" переменной копируем очередной байт.
            longs [i / sizeof (longer)] |= bytes [i + sizeof (longer) - j];
            // Если мы не закончили работу с данным "длинным" элементом, то перед следующим
            // копированием смещаем его содержимое вправо на один байт.
            if (j != sizeof (longer) ) {
                longs [i / sizeof (longer)] <<= 8;
            }
        }
    }


    // Вывыли на консоль результат.
    for (unsigned int i = 0; i < size; ++i) {
        std::cout << static_cast <unsigned int> (bytes [i]) << " ";
    }
    std::cout << std::endl;

    for (unsigned int i = 0; i < size / sizeof (longer); ++i) {
        std::cout << longs [i] << " ";
    }
    std::cout << std::endl;
}


Это для случая если байты сложены наоборот, т.е. 4 3 2 1, а не 3 4 1 2 или 1 2 3 4 или еще как-нибудь.

Есть еще один "бесплатный" способ приведения - union'ы (в С++ есть еще и анонимные union'ы, которые позволяют обращаться внутри метогда, где они объявлены, к членам объединения непосредственно).
Тот же пример:
Код

#include <iostream>


typedef unsigned int longer;


int main (int argc, char * argv [])
{
    // Размер массива.
    const unsigned int size = 16;

    union {
        // Дано два массива:
        // массив байт
        unsigned char bytes [size];
        // и массив чего-нибудь подлиннее.
        longer        longs [size / sizeof (longer)];
    };

    
    for (unsigned int i = 0; i < size; ++i) {
        // Эта строка просто генерирует "случайное" содержимое и не является функциональной!
        bytes [i] = i;
    }


    // Вывыли на консоль результат.
    for (unsigned int i = 0; i < size; ++i) {
        std::cout << static_cast <unsigned int> (bytes [i]) << " ";
    }
    std::cout << std::endl;

    for (unsigned int i = 0; i < size / sizeof (longer); ++i) {
        std::cout << longs [i] << " ";
    }
    std::cout << std::endl;
}


Как видно, тут вообще делать ничего не пришлось. Но здесь мы не сможем изменить порядок следования байт.

Это сообщение отредактировал(а) Gluttton - 7.10.2012, 16:05


--------------------
Слава Україні!
PM MAIL   Вверх
feodorv
Дата 7.10.2012, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(GraNit @  7.10.2012,  14:55 Найти цитируемый пост)
        day[0] = fgetc(handle);
        fseek(handle,1,SEEK_CUR);
        month[0] = fgetc(handle);
        fseek(handle,1,SEEK_CUR);
        year[0]=fgetc(handle);
        year[1]=fgetc(handle);

В итоге Вы читаете 6 байт, следующие друг за другом. Для таких вещей больше подходит fread, что заодно упростит обработку ошибок (в приведённом коде она напрочь отсутствует):
Код

unsigned char date[6];
int bytes = fread( date, 6, 1, handle);
if( bytes < 0 )
  fprintf( stderr, "Can't read file\n" );
else if( bytes == 0 )
  fprintf( stderr, "No date entry in file\n" );
else
{
  int newDay = (int) date[0];
  int newMonth = (int) date[2];
  int newYear = (int) date[5] * 256 + (int) date[4];
  ...
}



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
xvr
Дата 8.10.2012, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(GraNit @  7.10.2012,  13:55 Найти цитируемый пост)
        newYear = *(unsigned int*)year;

int под Windows 4х байтовый, а не 2х байтовый, как было в DOS. Приводите тип к (unsigned short*)
Ну и fseek'и явно неправильные, как feodorv правильно заметил

PM MAIL   Вверх
GraNit
Дата 8.10.2012, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 20.10.2007

Репутация: нет
Всего: нет



Спасибо xvr!!!
Я не знал, что в windows int 4-х байтовый. Теперь все в норме.
По поводу fseek между байтами стоит 0x00 поэтому приходится сдвигать указаталь.
короче поле следующего вида в hex: 05 00 0С 00 CA 07.
Благодарю всех кто отозвался!!!
PM MAIL   Вверх
GraNit
Дата 13.10.2012, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 20.10.2007

Репутация: нет
Всего: нет



Тема закрыта.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0627 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.