C++ для начинающих Динамическая структура и бинарный файл

Сайт не является учебником по программированию. Это только небольшой авторский сборник информации в помощь начинающим программистам.

В этом примере изначально известно сколько записей будет в файле. Если Количество элементов в массиве создается при работе программы, то разумно сначала в файл записать число элементов в массиве, а потом дописать массив, а при прочтении сначала прочитать число, а потом массив, согласно полученному числу.

Размер во время выполнения программы.

Этот же прием можно использовать для записи класса в файл и его чтения.
ВАЖНО

  • Так записывать можно только чистые структуры и классы, в которых абсолютно всё в одной секции, т.е. в секции public или же если абсолютно однозначно и запись и чтение будут выполнятся программой, скомпилированной в одном компиляторе с одними и теми же настройками на момент компиляции, да еще и исключительно для одной платформы. Причем то, что в одной секции, должно быть объектами POD типов.
  • Вместо того, чтобы искать костыли к этой проблеме, лучше сразу писать корректно, учитывая вышеуказанное, т.е. такой прием для показанного ниже класса не стоит использовать в принципе.

Более надежный способ для такого вида структур и классов — это делать методы внутри класса/структуры для записи в файл и чтения данных из файла. Но даже при этом нужны дополнительные проверки на версию компилятора и размеры типов данных. Из-за разных версий компиляторов вполне реально словить неожиданную работу программы. А размеры типов данных в зависимости от платформ могут быть различны. Гарантирован размер только у char, а остальное все не гарантируется. Я обойдусь без этих дополнительных проверок. Но тем не менее код будет достаточно громоздок.
Некоторые важные проверки я в него-таки влепляю.

Все комментарии на сайте проверяются, поэтому ваш комментарий может появиться не сразу. Для вставки кода в комментарий используйте теги: [php]ВАШ_КОД[/php]

4 комментария: C++ для начинающих Динамическая структура и бинарный файл

  • Аноним говорит:

    1. tempY был проинициализирован нулём, а затем в него началось цикличное считывание файла, причём на каждой итерации в один и тот же участок памяти (неизвестно в какой). Это чревато тем, что tempY может указывать, например, на участок памяти, занятый другой переменной. Программа перезапишет эту переменную и всё — тройка, семёрка, туз — программе привет (это в лучшем случае). Чтобы что-то записать в tempY под неё нужно сначала выделить память.

    2. Так как x и y — указаели, то операции sizeof X и sizeof Y дадут размеры указателей, а не массивов целиком.

    Я думаю, что чтение и запись правильнее было бы переписать так:

    1. Запись в файл:

    out.write((char *) X, sizeof(MyStruct) * 5); //так как X — указатель, то оператор ‘&’ здесь не нужен

    2. Чтение из файла (если неизвестно количество записанных в файл структур (но, имхо, если уж записывать в файл массив структур, то в первой строке проще указать размер массива)):

    struct MyStruct *tempY = new struct MyStruct;
    struct MyStruct *temp = 0;
    struct MyStruct *y = 0;
    int count = 0;

    std::ifstream in;
    in.open(«123.txt», std::ios::binary | std::ios::in);
    while(in.read((char *) tempY, sizeof(struct MyStruct))) { /*Пока не достигнут конец файла*/
    count++;

    if(count == 1) { /*Считали первую структуру*/
    y = new struct MyStruct [sizeof(struct MyStruct)]; /*Выделяем под неё память*/
    y[0] = *tempY; /*Сохраняем прочитанные данные*/
    }
    else { /*Считываем остальные структуры*/
    temp = new struct MyStruct [sizeof(struct MyStruct) * count — 1]; /*Временное хранилище*/
    for(i = 0; i < (count — 1); i++) {
    temp[i] = y[i]; /*Сохраняем ранее прочитанные данные во временном хранилище*/
    }

    /*Далее будем перераспределять память, поэтому предварительно её нужно освободить*/
    if(count == 2) delete y; /*Если память выделялясь под одну структуру*/
    else delete [] y; /*Если память выделялась под массив структур*/
    y = new struct MyStruct [sizeof(struct MyStruct) * count]; /*Перераспределяем память, т.к прочитанных данных стало на 1 больше*/
    for(i = 0; i < (count — 1); i++) {
    y[i] = temp[i]; /*Считываем из временного хранилища*/
    }
    y[i] = *tempY; /*Добавляем последнюю прочитанную структуру*/
    delete [] temp; /*Освобождаем временное хранилище (чтобы не загаживать память)*/
    }
    }
    in.close();

    PS: Для выделения памяти в данном случае проще использовать malloc/realloc, сократиться код.

    Не шедевр, конечно, но мне кажется, что так будет более корректно.

    Автор сайта отвечает:
    Я об этом вначале упоминал. Так-то вы правы.

  • Mr.Ex говорит:

    Админ, а ты вкусе вообще что в файл ничего не  пишется? Посмотри размер файла после записи структуры он 4 байта, все данные просто хранятся в куче. Что бы увериться:

    Удали динамический массив сразу после того как он стал ненужным и все увидишь.:)

    Автор сайта отвечает:
    Да. Знаю.
    Еще я знаю, что этот пример должен быть в книжках типа: "Табу кодера", "Как написать и остаться без рук" и т.п.
    Один проход. Вначале количество структур. Цикл. И никакого геморроя.

    Я в течении некоторого времени перепишу всю эту ересь. Сейчас желания мало.
    Хотя мой будущий пример может быть тоже получится не очень удачным, я не против посмотреть на хороший пример.

  • desannn говорит:

    пытаюсь таким образом прочесть файл таблицы  mySQL  которую предварительно пихнул в папку с exe-шником но к сожалению на экран ничего не выводит  пользуюсь msvs 2013

  • desannn говорит:

    пытаюсь таким образом прочесть файл таблицы  mySQL  которую предварительно пихнул в папку с exe-шником но к сожалению на экран ничего не выводит  пользуюсь msvs 2013

    Автор сайта отвечает:
    Чтобы прочесть файл таблицы, нужно знать внутреннее устройство файла, я сомневаюсь, что вы знаете. В бинарном режиме можно прочитать и вывести только то, что известно, где известно какие внутри данные и в каком порядке они там записаны (как-то так). Другой способ чтения, причём более очевидный, и очевидно надёжнее — подключение библиотек, работающих с MySQL, но здесь я помочь не могу.

Добавить комментарий

Ваш e-mail не будет опубликован.

Поиск

 
     
Яндекс.Метрика

НАГРАДИ АВТОРА САЙТА
WEBMONEY
R375024497470
U251140483387
Z301246203264
E149319127674

Отец перед сном рассказывает сыну сказку: - Жил на свете богатый человек. Купил он себе самый лучший компьютер и кучу лицензионных программ. - Пап, а как это - лицензионных? - Спи, сынок, я же сказал - это сказка! . .

Выражаю свою признательность

  • Максиму очень признателен за указание на мои ошибки и неточности.
  • Sergio ===> за оказание помощи в исправлении моих ошибок
  • Gen ===> за правильное стремление помочь другим новичкам и выявления моих ошибок