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

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

  • автор:

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

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

Структура как параметр функции

При передаче структуры в качестве параметра получает копию значений структуры:

#include struct person < char* name; int age; >; void print_person(struct person user) < printf("Name: %s \n", user.name); printf("Age: %d \n", user.age); >int main(void) < struct person tom = ; print_person(tom); return 0; >

В данном случае функция print_person() принимает объект структуры person и выводит значения его элементов на консоль.

Чтобы не писать тип параметра полностью — struct person , можно определить псевдоним структуры:

#include typedef struct < char* name; int age; >person; void print_person(person user) < printf("Name: %s \n", user.name); printf("Age: %d \n", user.age); >int main(void) < person tom = ; print_person(tom); return 0; >

Указатели на структуру как параметры

При использовании структур в качестве параметров в функции следует учитывать, что при вызове функции для структуры, также как и для параметров типа int или char, выделяется память, в которую помещаются значения элементов структуры. То есть структура в функцию передается по значению, а это значит, что переданную в функцию структуру мы изменить не можем.

Если необходимо уменьшить выделение памяти (особенно если структура большая) или иметь возможность изменять изначальную структуру в функции, то можно передавать в функцию указатель на структуру:

#include struct person < char* name; int age; >; void change_person(struct person * user) < user->age = user->age + 1; > int main(void) < struct person bob = ; printf("Before change. %s : %d \n", bob.name, bob.age); change_person(&bob); printf("After change. %s : %d \n", bob.name, bob.age); return 0; >

В этом примере функция change_person принимает указатель на структуру person и увеличивает на единицу значение элемента age.

Для проверки в функции main выводим данные объекта person на консоль до и после вызова функции change_person.

Before change. Bob : 22 After change. Bob : 23

Структура как результат функции

Также функция может возвращать объект структуры:

#include struct person < char* name; int age; >; struct person create_person(char* name, int age) < struct person user; user.name = name; user.age = age; return user; >int main(void)

Здесь функция create_person() создает на основании полученных параметров объект структуры person и возвращает его в качестве результата.

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

Хотя функции getc()/putc() позволяют вносить в файл отдельные символы, но фактически мы имеем дело с бинарными файлами. Если мы записываем в файл строку, то в принципе мы даже можем открыть записанный файл любом текстовом редакторе и понять, что там было записано. Но не всегда данные могут представлять строки. И чтобы более наглядно разобраться с работой с бинарными файлами, рассмотрим еще одни пример — с записью-чтением структуры из файла.

#include #include struct person < char name[16]; int age; >; int save(char * filename, struct person *p); int load(char * filename); int main(void) < char * filename = "person.dat"; struct person tom = < "Tom Smith", 21 >; save(filename, &tom); load(filename); return 0; > // запись структуры в файл int save(char * filename, struct person *p) < FILE * fp; char *c; int size = sizeof(struct person); // количество записываемых байтов fp = fopen(filename, "wb"); //открываем файл для бинарной записи if (!fp) // если не удалось открыть файл < printf("Error occured while opening file \n"); return 1; >// устанавливаем указатель на начало структуры c = (char *)p; // посимвольно записываем в файл структуру for (int i = 0; i < size; i++) < putc(*c++, fp); >fclose(fp); return 0; > // загрузка из файла структуры int load(char * filename) < FILE * fp; char *c; int i; // для считывания одного символа // количество считываемых байтов int size = sizeof(struct person); // выделяем память для считываемой структуры struct person * ptr = malloc(size); fp = fopen(filename, "rb"); // открываем файл для бинарного чтения if (!fp) < printf("Error occured while opening file \n"); return 1; >// устанавливаем указатель на начало блока выделенной памяти c = (char *)ptr; // считываем посимвольно из файла while ((i = getc(fp))!=EOF) < *c = i; c++; >fclose(fp); // вывод на консоль загруженной структуры printf("%-20s %5d \n", ptr->name, ptr->age); free(ptr); return 0; >

В данном случае запись и чтение структуры выделены в отдельные функции: save() и load() соответственно.

Для записи в функции save() через параметр struct person *p получаем указатель на сохраняемую структур. Фактически его значением является начальный адрес блока памяти, где располагается структура.

Функция putc записывает отдельный символ в файл, однако нам надо записать структуру. Для этого мы создаем указатель на символ (который по сути представляет один байт) и устанавливаем этот указатель на начало блока памяти, выделенного для структуры.

c = (char *)p;

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

for (int i = 0; i

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

При чтении файла в функции load() используется похожий принцип только в обратную сторону.

Во-первых, для считывания структуры из файла мы выделяем блок динамической памяти для хранения прочитанных данных:

struct person * ptr = (struct person *) malloc(size);

После этого указатель ptr будет указывать на первый адрес блока из 20 байт (наша структура занимает 20 байт = 16 символов и 4 байта для числа int ).

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

c = (char *)ptr; // считываем посимвольно из файла while ((i = getc(fp))!=EOF)

Здесь стоит обратить внимание на то, что в данном случае на самом деле считываем даже не символ, а числовой код символа в переменную типа int и только потом передаем значение указателю c. Это сделано для корректной обработки окончания файла EOF. Это значение может представлять любое отрицательное число. И если бы мы сохранили отрицательное число (например, возраст пользователя был бы отрицательным), то оно было бы некорректно интерпретировано при чтении как конец файла, и итоговый результа был бы неопределенным. Поэтому более правильно считывать именно числовой код символа в переменную int, а затем числовой код передавать в char.

Запись и чтение массива структур

Выше приведен пример по работе с одной структурой. Но, как правило, при работе с файлами мы оперируем не одной структурой, а каким-то набором структур. Поэтому усложним задачу и сохраним и считаем из файла массив структур:

#include #include struct person < char name[20]; int age; >; int save(char * filename, struct person *st, int n); int load(char * filename); int main(void) < char * filename = "people.dat"; struct person people[] = < , , , >; int n = sizeof(people) / sizeof(people[0]); save(filename, people, n); load(filename); return 0; > // запись в файл массива структур int save(char * filename, struct person * st, int n) < char *c; // для записи отдельных символов // число записываемых байтов int size = n * sizeof(struct person); FILE * fp = fopen(filename, "wb"); if (!fp) < printf("Error occured while opening file\n"); return -1; >// записываем количество структур c = (char *)&n; for (int i = 0; i < sizeof(n); i++) < putc(*c++, fp); >// посимвольно записываем в файл все структуры c = (char *)st; for (int i = 0; i < size; i++) < putc(*c, fp); c++; >fclose(fp); return 0; > // загрузка из файла массива структур int load(char * filename) < char *c; // для считывания отдельных символов int m = sizeof(int); // сколько надо считать для получения размера массива int n; // количество структур в массиве FILE * fp = fopen(filename, "r"); if (!fp) < printf("Error occured while opening file\n"); return -1; >// выделяем память для хранения количества данных int *ptr_count = malloc(m); // считываем количество структур c = (char *)ptr_count; // пока не считаем m байт, сохраняем байт в выделенный блок для размера массива while (m > 0 && (*c = getc(fp)) != EOF) < c++; m--; >//получаем число элементов n = *ptr_count; free(ptr_count); // освобождаем память // выделяем память для считанного массива структур struct person * ptr = malloc(n * sizeof(struct person)); // устанавливаем указатель на блок памяти, выделенный для массива структур c = (char *)ptr; // считываем посимвольно из файла while ((*c= getc(fp))!=EOF) < c++; >// перебор загруженных элементов и вывод на консоль printf("\nFound %d people\n\n", n); for (int i = 0; i < n; i++) < printf("%-5d %-10s %5d \n", i + 1, (ptr + i)->name, (ptr + i)->age); // или так // printf("%-5d %-10s %5d \n", i + 1, ptr[i].name, ptr[i].age); > free(ptr); fclose(fp); return 0; >

Данная задача усложнена тем, что нам надо хранить массив структур, количество которых точно может быть неизвестно. Один из вариантов рещения этой проблемы состоит в сохранении некоторой метаинформации о файле в начале файла. В частности, в данном случае в начале файла сохраняется число записанных структур.

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

c = (char *)&n; for (int i = 0; i

Затем подобным образом записываем все байты из массива структур — устанавливаем указатель на первый байт массива структур и записываем size байт в файл:

// посимвольно записываем в файл все структуры c = (char *)st; for (int i = 0; i

При чтении нам придется файктически считывать из файла два значения: количество структур и их массив. Поэтому при чтении два раза выделяется память. Вначале для количества элементов:

int *ptr_count = malloc(m);

Затем мы считываем первые 4 байта из файла для получения числа:

c = (char *)ptr_count; while (m > 0 && (*c = getc(fp)) != EOF) < c++; m--; >//получаем число элементов n = *ptr_count;

Затем аналогичные действия проделываем для массива структур.

struct person * ptr = malloc(n * sizeof(struct person)); // устанавливаем указатель на блок памяти, выделенный для массива структур c = (char *)ptr; // считываем посимвольно из файла while ((*c= getc(fp))!=EOF)

И результатом программы должен быть вывод считанных данных:

Found 4 people 1 Tom 23 2 Alice 27 3 Bob 31 4 Kate 29

Как записать структуру в файл (стиль С)?

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

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

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

Как записать структуру в файл?
Здравствуйте расскажите пожалуйста, как записать структуру в файл. Используя библиотеку <fstream> .

Как записать структуру в файл?
есть структура struct frend < char name; char tel; >;как записать ее в файл и потом.

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

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

Как записать структуру в файл (стиль С)?
Здравствуйте, передаю структуру в файл, а туда пишет каракули. Как правильно записать структуру в.

Записать структуру в бинарный файл
ЛЮДИ подскажите кто знает,чувствую,что ответ где то рядом,а где найти не могу:( Пусть есть.

Записать структуру в файл используя табуляцию
Добрый вечер. Столкнулся с проблемой, не могу записать структуру в файл. Есть структура struct.

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#include"stdafx.h" #include"stdlib.h" #include"stdio.h" #include"conio.h" #include"math.h" #include"locale.h" int i;//cчётчик char* h;//переменная для имени char* o;//переменная для отчества char* u;//переменная для фамилии int g;//год int p;//бал по русскому int m;//бал по математике int fi;//бал по физике int n;//количество студентов float c;//среднееарифметическое FILE *f; char* opros_k() { printf("введите фамилию\n"); scanf("%s",&u); printf("введите имя\n"); scanf("%s",&h); printf("введите отчество\n"); scanf("%s",&o); return u,h,o; } int opros2_k() { printf("введите год рождения\n"); scanf("%d",&g); printf("введите количество баллов по русскому\n"); scanf("%d",&p); printf("введите количество баллов по математике\n"); scanf("%d",&m); printf("введите количество баллов по физике\n"); scanf("%d",&fi); return g,p,m,fi; } struct sp { char* o,u,h; int g,p,m,fi,c; sp* next; } *start,*next,*tec,*nel; void vivod(int n)//вывод списка { tec = start; for (i = 1; i  n; i++) { fprintf(f,"Студент %d\n", i); fprintf(f,"фамилия: %s\n",tec->u); fprintf(f,"имя: %s\n",tec->h); fprintf(f,"отчество: %s\n",tec->o); fprintf(f,"бал по русскому: %d\n",tec->p); fprintf(f,"бал по математике : %d\n",tec->m); fprintf(f,"бал по физике: %d\n",tec->fi); c=((float)p+(float)m+(float)fi)/3; fprintf(f,"средний бал: %d\n",tec->c); tec = tec->next; } } void main(void) { setlocale(LC_ALL,"Russian"); f=fopen("STYDENTbl","wb"); printf("введите количество студентов\n"); fprintf(f,"введите количество студентов\n"); scanf("%d",&n); fprintf(f,"%d\n",n); for(i=0;in;i++) { opros_k(); opros2_k(); vivod(n);// не выводит в файл } fclose(f); getch(); }

Добавлено через 47 секунд
но она говорит что я залезаю в защиту (пока это всё до чего я дошёл

Добавлено через 1 минуту
введите количество студентов
2
Студент 1
(это то что записалось в бинарный файл )(до ошибки)

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

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

Сохранение структуры. Можно ли структуру записать целиком в файл?
давно интересует такой вопрос: можно ли сразу записать структуру целиком в файл? т.е.

Как записать структуру в файл?
Здравствуйте расскажите пожалуйста, как записать структуру в файл. Используя библиотеку <fstream> .

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

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

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

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