Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
FasterHarder
4 / 2 / 1
Регистрация: 28.04.2015
Сообщений: 161
1

Запись структуры (в ней есть поля типа данных char*) в бинарный файл

29.10.2016, 17:43. Просмотров 694. Ответов 6
Метки нет (Все метки)

Всем привет!
Есть такая структура:
C++
1
2
3
4
5
6
7
struct Telem
{
    int key;
    char *mark;
    float engine;
    char *color;
};
В функции main() вводится информация с клавиатуры и происходит запись в бинарный файл:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    FILE *f = fopen("d:\\telem.bin", "wb+");
    Telem tmp;
    for(int i = 1; i <= 2; i++)
    {
        tmp.key = i;
        cout << "Введите марку: ";
        tmp.mark = new char[100];
        gets(tmp.mark);
        cout << "Введите объем двигателя: ";
        cin >> tmp.engine;
        fflush(stdin);
        cout << "Введите цвет: ";
        tmp.color = new char[100];
        gets(tmp.color);
        fwrite(&tmp, sizeof(Telem), 1, f);
        cout << endl << endl;
    }
    fclose(f);
Есть функция, которая читает информацию из бинарного файла:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void ReadFile(void)
{
    Telem tmp;
    tmp.mark = new char[100];
    tmp.color = new char[100];
    FILE *f = fopen("d:\\telem.bin", "rb");
    while(fread(&tmp, sizeof(Telem), 1, f) != 0)
    {
        cout << tmp.key << endl;
        cout << tmp.mark << endl;
        cout << tmp.engine << endl;
        cout << tmp.color << endl << endl;
    }
    fclose(f);
}
Возникла такая проблема, что если ввести данные с клавиатуры, записать их в бин.файл и сразу, не закрывая программы вызвать функцию ReadFile(), то все прекрасно отрабатывает.
А вот если ввести данные с клавиатуры, записать их в бин.файл. Закрыть программу. Потом повторно запустить и только попытаться считать их из файла, то происходит крах.

Не могу понять, в чем тут подводный камень?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.10.2016, 17:43
Ответы с готовыми решениями:

Запись структуры в бинарный файл
Добрый вечере,народ. Нужна функция,которая будет записывать структуру в бинарный файл.То есть...

Запись/Чтение структуры в файл (бинарный)
Всем привет! у меня такая задачка, очень простая. Нужно записать структуру в файл, а потом хочу...

Динамические поля и запись в бинарный файл
Подскажите пожалуйста, почему при структуре, в которой есть динамические char массивы, при записи...

Запись переменной типа double в бинарный файл
Помогите справится с проблемой! допустим а меня есть переменная: double d=0.123456789; (8байт)...

Запись в файл и последующее чтение массива типа char
Добрый вечер! Я должен сделать элементарную программу: в текстовом файле изначально лежат...

6
zss
Модератор
Эксперт С++
7956 / 7140 / 4453
Регистрация: 18.12.2011
Сообщений: 18,856
Завершенные тесты: 1
29.10.2016, 18:33 2
В файл Вы пишете только содержимое структуры, т.е. вместо значений mark и color пишутся УКАЗАТЕЛИ на выделенные данные.
Их нужно писать дополнительно (и читать).
0
FasterHarder
4 / 2 / 1
Регистрация: 28.04.2015
Сообщений: 161
29.10.2016, 18:41  [ТС] 3
спс zss, но давайте кое-что уточним.
вообще, я неплохо знаю базовый С++, но давно не работал с бинарными файлами и вот, результат на лицо.

Значением указателя является адрес того участка памяти, на который он ссылается/указывает.
Когда происходит динамическое выделение памяти:
C++
1
tmp.mark = new char[100];
то значением tmp.mark является некий адрес (пусть для простоты А12). Затем по этому адресу записывается информация вводом с клавиатуры.
Когда происходит вызов fwrite, то вместо марки в файл пишется А12. Это понятно.
Если программа не закрывается и происходит считывание из файла, то в поле mark записывается адрес А12 (а в этом участке памяти "лежит" словесное значение марки). Т е в таком варианте работает все ок.

При повторном запуске, когда происходит ТОЛЬКО считывание из файла, в поле mark записывается значение адреса А12, но при этом данный участок памяти уже не принадлежит структуре в общем и полю mark в частности, поэтому при попытке вывести значение марки на экран генерируется ошибка (типа violetion). Примерно так, да?
0
nd2
2968 / 2506 / 1089
Регистрация: 29.01.2016
Сообщений: 8,354
29.10.2016, 18:59 4
Цитата Сообщение от FasterHarder Посмотреть сообщение
Примерно так, да?
Примерно так. И не нужно вот это использовать для очистки буфера ввода:
Цитата Сообщение от FasterHarder Посмотреть сообщение
fflush(stdin);
Не везде будет работать. Это предназначено для очистки буфера вывода.

Добавлено через 1 минуту
И лучше не мешать в кучу ввод/вывод Си и С++.
0
FasterHarder
4 / 2 / 1
Регистрация: 28.04.2015
Сообщений: 161
29.10.2016, 19:06  [ТС] 5
Последнее уточнение!
Если исправить объявление поля char *mark в рамках структуры на char mark[100], то все те же проблемы сохраняются, да?
P.S. Ведь имя статического массива - это КОНСТАНТНЫЙ указатель на неконстантные данные. Т е фактически mark является ссылкой/указателем на первый элемент символьного массива

всем спс. за помощь

Добавлено через 3 минуты
И еще вопрос: если нельзя записать fwrite() целых структурный элемент, содержащий поля-указатели, то как это делать? Писать по отдельности каждое поле (через какой-нибудь fprintf(...), использовать fwrite() для каждого поля или скомпоновать все поля-неуказатели в отдельную структуру, а указатели записывать в файл по одиночке?

P.S. потоки fstream не используются
0
nd2
2968 / 2506 / 1089
Регистрация: 29.01.2016
Сообщений: 8,354
29.10.2016, 19:15 6
Цитата Сообщение от FasterHarder Посмотреть сообщение
Цитата Сообщение от FasterHarder Посмотреть сообщение
Если исправить объявление поля char *mark в рамках структуры на char mark[100], то все те же проблемы сохраняются, да?
Нет. Тогда в структуре у тебя будет массив находится, а не указатель.

Добавлено через 3 минуты
Сделай sizeof() структуры с указателем и с массивом, и почувствуй разницу.
0
FasterHarder
4 / 2 / 1
Регистрация: 28.04.2015
Сообщений: 161
29.10.2016, 19:26  [ТС] 7
Я прогнал на статических массивах - все норм. отработало!
Это ведь специфика строк такого формата в языке СИ, например, т к для типов данных int, char, float, etc нужно внутрях scanf() ставить &, а для символьных стат.массивов нет!
Тут тоже самое. В файл будет писаться само значение, а не адрес 1-го элемента.

В общем, вроде разобрался! Всем спс.
0
29.10.2016, 19:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.10.2016, 19:26

Запись данных в бинарный файл
Мне нужно записать в бинарный файл координаты точек с помощью fwrite и попутно выводить их на...

Бинарный файл ( определение типа данных в нем)
Добрый вечер! Есть такая задача, имеется файл который мы открываем в бинарном режиме через fstream....

Запись введенных данных с консоли в бинарный файл
Доброго времени суток. Столкнулся с такой проблемой: Мне надо введенные данные в структуру...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru