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

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

  • автор:

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

Новичок в Си, не могу никак разобраться как записать массив обычных int’ов в файл.

Aleksandr's user avatar

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

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.7.31.43551

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

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

Встроенные функции fwrite() и fread() упрощают запись и чтение из файлов сложных данных. Рассмотрим их применение.

fwrite

Функция fwrite предназначена для записи данных из массива. Она имеет следующее определение:

Эта функция принимает следующие параметры:

buffer : указатель на первый объект из массива, который должен быть записан

size : размер каждого объекта

count : количество объектов, которые надо записать

stream указатель на файловый поток для записи

В качестве результата функция возвращает количество записанных объектов. Это количество может быть меньше параметра count , если при записи произогла ошибка

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

Для простейшего примера запишем строку:

Здесь записываем строку str в файл «data.txt». Для получения длины строки используем выражение sizeof(str) , а для получения размера одного символа — sizeof str[0] (в приниципе здесь можно сразу написать 1 — размер одного символа). И если запись пройдет успешно, то консоль выведет

fread

Функция fread предназначена для считывания данных из файла в массив. Она имеет следующее определение:

Эта функция принимает следующие параметры:

buffer : указатель на массив, в который надо считать данные

size : размер каждого объекта

count : количество объектов, которые надо считать

stream указатель на файловый поток для чтения

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

Фактически функция считывает данные с помощью функции fgetc() в буфер, который рассматривается как массив значений unsigned char .

Для простейшего примера считаем строку из вышезаписанного файла:

Здесь считываем данные в строку str. В итоге консольный вывод будет следующим:

Отслеживание ошибок

При записи или чтении могут возникнуть ошибки. Например, возьмем чтение данных. Нам может потребоваться считать определенный размер данных, но вполне возможно, что в файле не окажется такого количества данных, и мы дойдем до конца файла. Конец файла можно отследить с помощью функции feof() , в которую передается указатель на файл и которая возвращает 0, если достигнут конец файла. Дополнительно с помощью функции ferror() , в которую также передается указатель на файл, можно узнать произошла ли ошибка при работе с файлом. Например, считаем данные из файла:

В данном случае с помощью выражения feof(fp) проверяем, достигнут ли конец файла. Причем конец файла сам по себе не означает ошибку. Наличие же ошибки проверяется с помощью выражения ferror(fp)

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

Запись и чтение строки — не самая сложная задача, которую можно выполнить и другими способами. Но функции fwrite и fread позволяют работать и с другими объектами, даже если они и не представляют массив. Поскольку функции в качестве буфера принимают указатель, но в качестве указателя может выступать адрес любого объекта. Рассмотрим, как записать и считать структуры. Для этого определим следующую программу:

Здесь записываем структуру типа person. Для этого в функцию fwrite() передаем адрес структуры:

После записи считываем данные в структуру unknown, для чего передаем в функцию fread() адрес этой структуры:

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

Подобным образом можно записывать и считывать массив структур. Для этого определим следующую программу:

В данном случае записываем в файл массив структур people, а считываем — в массив users. Консольный вывод программы:

Считывание по одной структуре

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

Здесь запись и чтение разбиты на отдельные функции. Но если в функции load() записываем в файл разом весь массив структур, то в функции read_by_age() считываем по одной структуре в цикле, пока в файле есть данные. И если поле age структуры соответствует параметру age, то выводим эту структуру на консоль.

Бинарные файлы

Т екстовые файлы хранят данные в виде текста (sic!). Это значит, что если, например, мы записываем целое число 12345678 в файл, то записывается 8 символов, а это 8 байт данных, несмотря на то, что число помещается в целый тип. Кроме того, вывод и ввод данных является форматированным, то есть каждый раз, когда мы считываем число из файла или записываем в файл происходит трансформация числа в строку или обратно. Это затратные операции, которых можно избежать.

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

Выполните программу и посмотрите содержимое файла output.bin. Число, которое ввёл пользователь записывается в файл непосредственно в бинарном виде. Можете открыть файл в любом редакторе, поддерживающем представление в шестнадцатеричном виде (Total Commander, Far) и убедиться в этом.

Запись в файл осуществляется с помощью функции

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

Запись в бинарный файл объекта похожа на его отображение: берутся данные из оперативной памяти и пишутся как есть. Для считывания используется функция fread

Функция возвращает число удачно прочитанных элементов, которые помещаются по адресу ptr. Всего считывается count элементов по size байт. Давайте теперь считаем наше число обратно в переменную.

fseek

Одной из важных функций для работы с бинарными файлами является функция fseek

Эта функция устанавливает указатель позиции, ассоциированный с потоком, на новое положение. Индикатор позиции указывает, на каком месте в файле мы остановились. Когда мы открываем файл, позиция равна 0. Каждый раз, записывая байт данных, указатель позиции сдвигается на единицу вперёд.
fseek принимает в качестве аргументов указатель на поток и сдвиг в offset байт относительно origin. origin может принимать три значения

  • SEEK_SET — начало файла
  • SEEK_CUR — текущее положение файла
  • SEEK_END — конец файла. К сожалению, стандартом не определено, что такое конец файла, поэтому полагаться на эту функцию нельзя.

В случае удачной работы функция возвращает 0.

Дополним наш старый пример: запишем число, затем сдвинемся указатель на начало файла и прочитаем его.

Вместо этого можно также использовать функцию rewind, которая перемещает индикатор позиции в начало.

В си определён специальный тип fpos_t, который используется для хранения позиции индикатора позиции в файле.
Функция

используется для того, чтобы назначить переменной pos текущее положение. Функция

используется для перевода указателя в позицию, которая хранится в переменной pos. Обе функции в случае удачного завершения возвращают ноль.

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

Рассмотрим пример: пользователь вводит числа. Первые 4 байта файла: целое, которое обозначает, сколько чисел было введено. После того, как пользователь прекращает вводить числа, мы перемещаемся в начало файла и записываем туда число введённых элементов.

Вторая программа сначала считывает количество записанных чисел, а потом считывает и выводит числа по порядку.

Примеры

1. Имеется бинарный файл размером 10*sizeof(int) байт. Пользователь вводит номер ячейки, после чего в неё записывает число. После каждой операции выводятся все числа. Сначала пытаемся открыть файл в режиме чтения и записи. Если это не удаётся, то пробуем создать файл, если удаётся создать файл, то повторяем попытку открыть файл для чтения и записи.

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

3. Задача — считать данные из текстового файла и записать их в бинарный. Для решения зачи создадим функцию обёртку. Она будет принимать имя файла, режим доступа, функцию, которую необходимо выполнить, если файл был удачно открыт и аргументы этой функции. Так как аргументов может быть много и они могут быть разного типа, то их можно передавать в качестве указателя на структуру. После выполнения функции файл закрывается. Таким образом, нет необходимости думать об освобождении ресурсов.

4. Функция saveInt32Array позволяет сохранить массив типа int32_t в файл. Обратная ей loadInt32Array считывает массив обратно. Функция loadInt32Array сначала инициализирует переданный ей массив, поэтому мы должны передавать указатель на указатель; кроме того, она записывает считанный размер массива в переданный параметр size, из-за чего он передаётся как указатель.

5. Создание таблицы поиска. Для ускорения работы программы вместо вычисления функции можно произвести сначала вычисление значений функции на интервале с определённой точностью, после чего брать значения уже из таблицы. Программа сначала производит табулирование функции с заданными параметрами и сохраняет его в файл, затем подгружает предвычисленный массив, который уже используется для определения значений. В этой программе все функции возвращают переменную типа Result, которая хранит номер ошибки. Если функция отработала без проблем, то она возвращает Ok (0).

6. У нас имеются две структуры. Первая PersonKey хранит логин, пароль, id пользователя и поле offset. Вторая структура PersonInfo хранит имя и фамилию пользователя и его возраст. Первые структуры записываются в бинарный файл keys.bin, вторые структуры в бинарный файл values.bin. Поле offset определяет положение соответствующей информации о пользователе во втором файле. Таким образом, получив PersonKey из первого файла, по полю offset можно извлечь из второго файла связанную с данным ключом информацию.

Зачем так делать? Это выгодно в том случае, если структура PersonInfo имеет большой размер. Извлекать массив маленьких структур из файла не накладно, а когда нам понадобится большая структура, её можно извлечь по уже известному адресу в файле.

email

Всё ещё не понятно? – пиши вопросы на ящик

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

В этой статье мы узнаем, как считывать данные из файлов и записывать информацию в файлы в программах си. Файлы в си используются для того, чтобы сохранять результат работы программы си и использовать его при новом запуске программы . Например можно сохранять результаты вычислений , статистику игр.
Чтобы работать с файлами в си необходимо подключить библиотеку stdio.h
#include <stdio.h>
Чтобы работать с файлом в си необходимо задать указатель на файл по образцу
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 <iostream>

Оператор fscanf()

Для считывания слова из файла в си используется команда fscanf(). Эта команда аналогична команде ввода информации с клавиватуры в си scanf() только первый параметр это указатель на файл
fscanf(указатель на файл,"%формат ввода данных1% форматввода данных2…",&перменная1,&переменная2…);
Например команда
fscanf(fin,"%d%d%d",&a,&b,&c);
считает из файла, который привязан к указателю на файл fin строку из трех целочисленных переменных
Разберем пример программы, которая считывает из текстового файла data.txt в которые записаны три столбца цифр информацию и записывает ее в массивы. Для каждого столбца информации свой массив. Подробно о работе с массивами в Си.
#include <stdio.h>
#include <conio.h>
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 <stdio.h>
#include <conio.h>
#include <iostream>
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 оба эти числа и их сумму

#include <stdio.h>
#include <conio.h>

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

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

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