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

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

  • автор:

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

Хотя функции 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

#3 — Массивы данных в Си

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

Видеоурок

Массивы позволяют хранить большой объем информации в одном месте. В языке Си можно найти несколько основных типов массивов.

Одномерный массив

Чтобы создать массив необходимо указать тип данных, прописать название и поставить квадратные скобки. Это очень схоже с созданием обычных переменных, но здесь после названию идут ещё квадратные скобки.

В массивах отсчет начинается с 0, поэтому первый элемент по индексу будет равен 0, второй — 1 и так далее.

Примеры создания массива:

char stroka[2]; // Создание пустого массива int[] numbers; // Будет считаться ошибкой int nums[4]; nums[0] = 1; // Добавление элементов в массив из 4 элементов int nums2[] = < 1, 2, 3, 5 >; // Присвоение всех значений сразу

Работать с элементами массива можно точно как с переменными. Мы можем их выводить или же устанавливать для них новые значения.

Многомерный массив

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

Мы не будем изучать подобные массивы, так как принцип их построения точно такой же как при работе с двумерными массивами.

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

int x[2][3] = < < 0, 34, 2 >, < 3, 4, 5 >>; printf("%d", x[0][1]); // Выведет 34 // Можно их сразу не присваивать char symbols[5][2]; symbols [0][1] = 'A';

Мы видим, что элементы первого массива являются другими массивами. Чтобы выбрать какой-либо объект используйте ту же структуру что и для одномерных массивов, вот только теперь указывайте индекс как первого массива, так и второго:

x[0][1] = 1; // Вместо 34 теперь будет 1
Весь код будет доступен после подписки на проект!

Работа с файлами в си ввод и вывод в файл в си

В этой статье мы узнаем, как считывать данные из файлов и записывать информацию в файлы в программах си. Файлы в си используются для того, чтобы сохранять результат работы программы си и использовать его при новом запуске программы . Например можно сохранять результаты вычислений , статистику игр.
Чтобы работать с файлами в си необходимо подключить библиотеку stdio.h
#include
Чтобы работать с файлом в си необходимо задать указатель на файл по образцу
FILE *имя указателя на файл;
Например
FILE *fin;
Задает указатель fin на файл
Дальше необходимо открыть файл и привязать его к файловому указателю. Для открытия файла в си на чтение используется команда
Имя указателя на файл= fopen(«путь к файлу», «r»);
Например следующая команда
fin = fopen(«C:\\Users\\user\\Desktop\\data.txt», «r»);
откроет файл data.txt, находящийся на рабочем столе по пути C:UsersuserDesktop Чтобы узнать путь к файлу можно выбрать файл мышью нажать на правую кнопку мыши и выбрать свойства файла. В разделе Расположение будет указан путь к файлу. Обратите внимание , что в си путь указывается с помощью двух слешей.
После работы с файлом в си , необходимо его закрыть с помощью команды
fclose(имя указателя на файл)

Считывание информации из текстового файла в Си

Чтобы можно было считывать русские символы из файла, необходимо настроить работу с Кириллицей с помощью команды
setlocale(LC_ALL, «Russian»);

При этом необходимо в начале программы подключить #include

Оператор fscanf()

Для считывания слова из файла в си используется команда fscanf(). Эта команда аналогична команде ввода информации с клавиватуры в си scanf() только первый параметр это указатель на файл
fscanf(указатель на файл,»%формат ввода данных1% форматввода данных2…»,&перменная1,&переменная2…);
Например команда
fscanf(fin,»%d%d%d»,&a,&b,&c);
считает из файла, который привязан к указателю на файл fin строку из трех целочисленных переменных
Разберем пример программы, которая считывает из текстового файла data.txt в которые записаны три столбца цифр информацию и записывает ее в массивы. Для каждого столбца информации свой массив. Подробно о работе с массивами в Си.
#include
#include
main()
< int a[10];
int b[10];
int c[10];
int i;
// определяем указатель на файл
FILE *fin;
// открываем файл на чтение
fin = fopen(«C:\\Users\\user\\Desktop\\data.txt», «r»);
// построчное считывание из файла
for (i=0;i <3;i++)
// считывание строки из трех значений файла и запись в массивы
fscanf(fin,»%d%d%d»,&a[i],&b[i],&c[i]);
>
// вывод массивов на экран
for (i=0;i <3;i++)
printf(«%d %d %d\n»,a[i],b[i],c[i]);
>
getch();
// закрытие файла
fclose(fin);
>

Построковое считывание информации из файла в СИ.Функция fgets ( )

Оператор fscanf() считывает из файла слово , т.е. до первого встречного пробела.
Чтобы считать из файла всю строку из файла в Си используется конструкция
if ( NULL != fgets (строковая переменная, длина строки, указатель на файл ) )
действия при считывании строки
>
Например программа на Си которая считывает две строки из файла и выводит их на экран
#include
#include
#include
main()
// задаем строковые перменные
char st1[100];
char st2[100];
//определяем указатель на файл
FILE *fin;
// настриваем работу с Кириллицей
setlocale(LC_ALL, «Russian»);
// открываем файл на чтение
fin = fopen(«C:\\data.txt», «r»);
// считываем первую строку из файла
if ( NULL != fgets ( st1, 100, fin ) )
// выводим строку на экран
printf(«%s «,st1);>
// считываем вторую строку из файла
if ( NULL != fgets ( st2, 100, fin ) )
// выводим строку на экран
printf(«%s\n»,st2);>
// закрываем файл на чтение
fclose(fin);
>

Запись информации в текстовый файл в Си

Для записи данных в файл в Си, необходимо открыть файл в режиме записи
Имя указателя на файл= fopen(«путь к файлу», «w»);
Для записи в строку текстового файла используется команда fprnitf(), которая аналогична команде printf() вывод на экран в си только первый параметр это указатель на файл
fprintf (имя указателя на файл,”%формат ввода”, переменные);
Например запись в файл out.txt значение переменной а
a=10;
fout = fopen(«C:\\Users\\user\\Desktop\\out.txt», «w»);
fprintf (fout,”%d”, a);
Пример программы на си которая запрашивает два числа и записывает в файл out.txt оба эти числа и их сумму

main()
< int a;
int b;
int c;
FILE *fout;
fout = fopen(«C:\\Users\\user\\Desktop\\out.txt», «w»);
printf («введите первое число \n»);
scanf(«%d», &a);
printf («введите второе число \n»);
scanf(«%d», &b);
c=a+b;
fprintf(fout,»%d %d %d»,a,b,c);
getch();
fclose(fout);
>

Вернуться к содержанию Перейти к уроку Ошибки в программах на си

Как записать массив в файл?

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

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

Как записать массив в файл, что добавить?
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h>.

Записать массив в файл
Массив из 50-ти элементов заполнить случайными целыми числами из диапазона от 0 до 100 и записать.

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

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

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