Как записать структуру в файл в си
Перейти к содержимому

Как записать структуру в файл в си

  • автор:

Как записать и считать структуру в файл на СИ

Всем добрый вечер, такая проблема, записываю структуру в файл, но при следующем запуске и чтении из файла, программа перестает работать. Также при удаление строчки 114 и 115 программа перестает работать, может кто подсказать почему?

#include #include #include #include using namespace std; typedef struct _date < int num; char* month; int year; >date; typedef struct _fio < char* fam; //Фамилия char* name; //Имя char* father; //отчество >fio; struct _deposid < int countName; fio client; date date; double sum; >; // Функция вывода счета void printClient(_deposid &client) < cout void sumLarge(_deposid *clients, int thisClient, int needSum, int countSum) < for (int i = 0; i < thisClient; i++ ) < if (clients[i].sum >needSum) < printClient(clients[i]); countSum++; >> if (countSum == 0) < cout countSum = 0; > void printNameLastname(_deposid *clients, int thisClient, char *firstname, char *lastname, char *father, int countSum) < for (int i = 0; i < thisClient; i++ ) < if (strcmp(clients[i].client.name, firstname) == 0 && strcmp(clients[i].client.fam, lastname) == 0 && strcmp(clients[i].client.father, father) == 0) < printClient(clients[i]); countSum++; >> if (countSum == 0) < cout countSum = 0; > // Функция создания нового клиента void newClient(_deposid &client) < char *userLastname = new char[100], *userFirstname = new char[100], *userFather = new char[100], *userMonth = new char[100]; // Ввод данных cout > userFirstname; client.client.name = new char[strlen(userFirstname)+1]; strcpy(client.client.name, userFirstname); cout > userLastname; client.client.fam = new char[strlen(userLastname)+1]; strcpy(client.client.fam, userLastname); cout > userFather; client.client.father = new char[strlen(userFather)+1]; strcpy(client.client.father, userFather); cout > client.date.num; cout > userMonth; client.date.month = new char[strlen(userMonth)+1]; strcpy(client.date.month, userMonth); cout > client.date.year; cout > client.sum; // Очистка памяти delete [] userLastname; delete [] userFirstname; > int main() < char *lastname = new char[100], *firstname = new char[100], *father = new char[100]; int n, thisClient = 0, numberFunction = 0, needSum, countSum = 0; _deposid *clients; char c; FILE *fp; fp=fopen("t.txt", "r+"); if (fp==NULL) < fclose(fp); fp=fopen("t.txt", "w+"); cout > n; clients = new _deposid[n]; // Создание массива структур > else < while((c = fgetc(fp)) != EOF) // При удалении этой и строчки ниже программа вообще не запускается putchar(c); while(fread(clients, sizeof(_deposid),1,fp)); // fputs("lol", fp); // fclose(fp); >cout > numberFunction; switch (numberFunction) < case 1: if (thisClient == n) < cout else < clients[thisClient].countName = thisClient + 1; newClient(clients[thisClient]); cout break; case 2: cout break; case 3: // Вывод счетов с суммой большей заданной cout > needSum; cout > firstname; cout > lastname; cout > father; cout > > 

Вот задание

Отслеживать
задан 16 мая 2022 в 11:18
егор виктуров егор виктуров
3 2 2 бронзовых знака

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

В принципе всё просто. Вы в файл сохраняете не все данные.

 case 5: cout  

Когда вы так пишете, в файл сохраняется сама структура. Т.е. в файл сохраняются не текстовые данные, кот. вы записывали в выделяемые через new буферы, а просто значение указателей char* month; и char* fam; char* name; char* father; . Для примера, проверьте значение sizeof(_deposid) - в размере структуры не будет размера того текста (фамилии, имени, отчества, названия месяца), которые вы вводили с клавиатуры.
А потом Вы загружаете из файла значение указателей, которые указывают в "никуда". Вам нужно написать свою функцию вывода Вашей структуры в файл. И свою функцию загрузки структуры из файла.
Существуют уже готовые библиотеки сериализации (вывода в поток и загрузки из потоков) объектов. Но для этой задачи проще написать свои функции.
Совет - каждое поле пишите отдельной строкой и считывайте построчно - так будет проще.
Ну и вот этот кусок:

 fp=fopen("t.txt", "r+"); if (fp==NULL) < clients = new _deposid[n]; // Создание массива структур >else < while((c = fgetc(fp)) != EOF) // При удалении этой и строчки ниже программа вообще не запускается putchar(c); while(fread(clients, sizeof(_deposid),1,fp)); 

Как правильно написал @JohnDoe выделение памяти под массив структур делается только если файла не существует. Если он существует, память под массив не выделяется. И дальше у Вас 2 ошибки, первая из которых не дает состояться второй. Вторая ошибка - запись данных в невыделенную область памяти:

fread(clients, sizeof(_deposid),1,fp) 

Здесь для clients память не выделена! А Вы пытаетесь записать туда что-то!
А первая ошибка не дает случиться второй - вот этими строками вы считываете весь файл.

while((c = fgetc(fp)) != EOF) putchar(c); 

Дескриптор файла указывает на конец файла. Функция fread() не может ничего считать из файла и поэтому ничего не записывает в невыделенную память.
По вашей логике при записи массива структур в файл вам нужно сначала записать туда количество объектов в массиве, а потом - сами объекты. И считывать в таком же порядке:

  • считать количество объектов,
  • выделить под них память,
  • считать сами объекты
    Ещё один момент:
void newClient(_deposid &client) < char *userLastname = new char[100], *userFirstname = new char[100], *userFather = new char[100], *userMonth = new char[100]; . delete [] userLastname; delete [] userFirstname; 

Выделили 4 массива, а освободили только 2. А в main() выделили и вообще не освободили. И зачем выделение через new() , если вы знаете размер буферов? Только чтобы память на куче была выделена? Стек выдержит ваши 400 байт, сделайте проще:

void newClient(_deposid &client)

Как записать структуру в файл на языке C++?

Нужно создать приложение которое бы записывала структуру в файл и выводило из файла на экран.
Попытался это реализовать.
Но к сожалению не записывает всю структура в файл. Или некорректно записывает.

Вот сам код который я пытался реализовать:

#include "stdafx.h" #include "string.h" #include "stdio.h" #include #include using namespace std; void inputf(ifstream &f, char a[300], char b[300], char c[300], char d[300]); void outputf1(ofstream &f, char a[300], char b[300], char c[300], char s[40]); void main() // Основная функция < int c; setlocale(LC_ALL, "Russian"); cout > c; if (c == 2) < int const N = 3; int i,j=0; struct vvod < char fam[300]; char id[300]; char number[300]; >; vvod v[N]; for (i = 0; i < N; i++) < cout > v[i].fam; cout > v[i].id; cout > v[i].number; > ofstream f1; for (i = 0; i < N; i++) < outputf1(f1, v[i].fam, v[i].id, v[i].number, "writer.txt"); >> else if (c == 1) < char str[40];//Строковая переменная (для пути к файлу) cout > str; char v[900]; char q[300]; char w[300]; char e[300]; ifstream f; inputf(f,str,q,w,e); > > void outputf1(ofstream &f, char a[300], char b[300], char c[300], char s[40])//Функция для записи < f.open(s);//Открываем файл //Проверка успешности открытия файла: if (f.fail()) < cout f void inputf(ifstream &f, char a[300],char b[300], char c[300],char d[300] )//Функция для чтения < f.open(a);//Открываем файл //Проверка успешности открытия файла: if (f.fail()) < cout f >> b;//Читаем переменную из файла f >> c; f >> d; cout 

Подскажите где накосячил.

  • Вопрос задан более трёх лет назад
  • 3557 просмотров

Чтение и запись структур в файл

Author24 — интернет-сервис помощи студентам

Запись и чтение вектора структур в бинарный файл
Есть заполненный вектор структур. Структура вида: struct struc < string a; int x; map<int.

Запись массива структур в бинарный файл и чтение
Разрабатываю иерархию классов "Больница". Есть структура отделения, функция ввода с клавиатуры.

Чтение/запись массива структур в бинарный файл
Добрый день! Задание: Дан некоторый файл, компонентами которого являются структуры типа.

Запись и чтение вектора структур в бинарный файл(2)
Есть заполненный вектор структур. Структура вида: struct struc < string a; int x; .

1272 / 1029 / 470
Регистрация: 25.12.2016
Сообщений: 3,333

Для чтения из файла используется функция fscanf , для записи - функция fprintf .

За основу можно взять код функции vvod , нужно только заменить scanf на fscanf , и передать функции предварительно открытый файл f .

1 2 3 4 5 6 7 8
Train* vvod_from_file(FILE *f, Train *a,int num) { fscanf(f, "%s", a[num].pn); // амперсанд перед строкой не нужен fscanf(f, "%d", &a[num].num); fscanf(f, "%s%*c", a[num].time); return a; }

Это чтение из файла. Запись - аналогично.
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

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

Запись в бинарный файл и чтение из него массива структур
Ребята, выручайте. Огромная проблема с записью и с чтением структуры из бинарного файла. Помогите.

Запись и чтение в файл массива структур в которую вложен вектор
Здравствуйте! Подскажите как и можно ли вообще записать в один файл данную структуру: struct.

Запись и чтение структур в файлах
Доброго времени суток. Бьюсь с проблемой уже больше недели, хотя, как мне кажется, уже верный код.

Запись и чтение структур в txt
Дана структура из 6 полей. Ввод, вывод и удаление я организовал, а вот как в текстовый файл.

Или воспользуйтесь поиском по форуму:

Как записать сразу всю структуру (содержащую string) в бинарный файл?

Структуру необходимо записать таким методом, чтобы потом запустить отдельно другую функцию, которая сможет прочитать файл, но перед этим не добавлять записи в файл(ну то есть чисто чтение)
Пробовала так: после того как пользователь введет string посчитать string.size() + 1 и приплюсовать sizeof(int), но после чтение из файла выдает какой-то бред

  • Вопрос задан более трёх лет назад
  • 4804 просмотра

15 комментариев

Средний 15 комментариев

justAnotherCluelessUser @justAnotherCluelessUser

"но после чтение из файла выдает какой-то бред"
Почему так много людей верят в ясновидящих??

Тут их особо нет. вроде.
Так что весь код на текстообменник(типа пастбин) и ссылку.

SUkI3 @SUkI3 Автор вопроса

anketa ar; int size = 0; int k = 0; fstream fout ("test.dat", ios::binary | ios::app); if(!fout) < coutcout> k; for(int i = 0; i> ar.year; cin.ignore(); cout fout.close();

Потом вот это запускаю отдельно

fstream file("test.dat", ios::binary | ios::in); if(!file) < coutif (getline( file, ar.fio, '\0' )) do < cout while(getline( file, ar.fio, '\n' )); file.close();

RabraBabr

Вы понимаете, что тут происходит?

size = sizeof(ar.year) + ar.fio.length() + 1; fout.write((char*)&ar,sizeof(size));

SUkI3 @SUkI3 Автор вопроса
RabraBabr, передаем байты и размер, который получился после как пользователь ввел данные

RabraBabr

SUkI3, какие байты? И размер чего? Внимательно подумайте.
SUkI3 @SUkI3 Автор вопроса

RabraBabr, байты которые преобразовали адрес указателя структуры, а размер, ну просто размер цифра, или похоже я не правильно понимаю работу записи в бинарник. (

Алексей Сергей @dev_random

SUkI3, почитайте про POD типы. В приведенном коде std::string не является POD типом и соответсвенно вся anketa тоже. При fout.write(&ar, sizeof(ar)) в файл попадут внутренние поля std::string (включая указатель (адрес) на строку), но не сама строка!

SUkI3 @SUkI3 Автор вопроса

Алексей Сергей, да я знаю, что структура не POD, если б было все так просто.
Поэтому и вопрос на тостере
Так возможно создать алгоритм который записывает структуру со string так, как если б там не было string, а были только POD типы?

Алексей Сергей @dev_random

SUkI3, смотрите в сторону сериализаторов.
Есть много либ на гитхабе. Например я такую пару раз использовал: https://github.com/USCiLab/cereal
Есть еще либа в бусте, но не все хотят буст в зависимости тащить. https://www.boost.org/doc/libs/1_70_0/libs/seriali.

Алексей Сергей @dev_random

SUkI3, забыл еще упомянуть, что сериализаторы обычно предоставляют несколько форматов для выходного файла. Легко делается как-минимум: бинарный, бинарный-кроссплатформа, текст, json и xml.

SUkI3 @SUkI3 Автор вопроса
Алексей Сергей, сериализаторы какое страшное слово, спасибо, почитаем)

RabraBabr

myjcom

Roman @myjcom Куратор тега C++
SUkI3, в чем смысл бинарной записи обычной строки. Байт на байт, шило на мыло.
SUkI3 @SUkI3 Автор вопроса
Roman, у string методы, модификаторы есть уже готовые, вроде как легче работаться должно

myjcom

Roman @myjcom Куратор тега C++

SUkI3,
при чем тут сейчас методы и модификаторы?
вы данные (data) сохраняете, данные в std::string это динамический массив char.
если использовать

struct anketa < int year; char fio[64]; >;

то все гораздо проще и с чтением и с записью.

Со string как раз таки мороки больше.

#include #include #include #include using namespace std; struct Data < int value = 0; string str; >; ofstream& operator<<(ofstream& ofs, Data& d) < size_t sz = d.str.size(); ofs.write(reinterpret_cast(&d.value), sizeof(d.value)); ofs.write(reinterpret_cast(&sz), sizeof(sz)); ofs.write(d.str.c_str(), sz); return ofs; > ifstream& operator>>(ifstream& ifs, Data& d) < ifs.read(reinterpret_cast(&d.value), sizeof(d.value)); size_t sz; ifs.read(reinterpret_cast(&sz), sizeof(sz)); d.str.resize(sz); ifs.read(reinterpret_cast(&*d.str.begin()), sz); return ifs; > int main() < Data d = ; ofstream ofs("D:\\file.bin", ios_base::binary); ofs > d2; assert(d.value == d2.value && d.str == d2.str); cin.get(); >

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *