Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УТП 12 Файловые операции.doc
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
284 Кб
Скачать
☆

Запись данных массивов структур в текстовый файл

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

Список вывода fprintf состоит из полей, значения которых необходимо записать, в текстовый файл, а форматы соответствуют типам данных, хранящимся в полях.

Пример 3. Файл-функция writegroup, которая реализует построчный вывод значений всех полей структур массива с информацией об успеваемости группы студентов.

Имя текстового файла и массив структур являются входными аргументами writegroup. Содержимое файла должно иметь организацию, схожую с табл. 1 лаб. раб. №2.

Установите фиксированное число отводимых позиций под вывод строк и чисел и выравнивание в области вывода по левому краю при помощи флага. Для вывода значения поля структуры, содержащего строку, примените спецификатор формата s. Например, формат '%-10s' означает выравнивание строки по левому краю в поле вывода из 10 позиций.

function writegroup(filename, GROUP)

% Файл-функция для записи таблицы с успеваемостью группы

% студентов в текстовый файл.

% Использование writegroup(filename, GROUP)

% filename — имя файла

% group — массив структур с полями

% Family (строка), Name (строка), Year (число),

% Marks (вектор-строка с шестью отметками)

% Нахождение числа студентов в группе

N = length(GROUP);

% Открытие файла с именем filename для записи

F = fopen(filename, 'w');

% Запись шапки таблицы с выравниванием по левому краю каждой строки

fprintf(F, '%-14s %-10s %-4s %-6s\n',...

'Фамилия', 'Имя', 'Год' , 'Оценки');

% Запись в файл содержимого полей каждой структуры в строку

for s = 1:N

fprintf(F, '%-14s %-10s %4.0f %2.0f %2.0f %2.0f %2.0f %2.0f %2.0f\n',...

GROUP(s).Family, GROUP(s).Name, GROUP(s).Year, GROUP(s).Marks);

end

% Закрытие файла

fclose(F);

Перед вызовом функции не забудьте заполнить массив структур GR201.

Вызов функции

writegroup('group.txt',GR201)

Задание 7. Заполните массив структур GR201. Вызовите функцию writegroup('group.txt',GR201). Покажите содержимое файла group.txt.

Добавьте в структуру GR201 новые поля: место рождения (строковая переменная) и средняя оценка (вещественная переменная). Заполните эти поля для каждого студента.

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

Вызовите исправленную функцию writegroup('newgroup.txt',GR201). Покажите содержимое файла newgroup.txt.

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

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

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

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

а = fscanf(идентификатор, 'список_форматов', число считываемых элементов)

Для считывания строки предусмотрен спецификатор формата s, для целых чисел – d, а для вещественных – g. Необходимо следить за соответствием формата и данных, хранящихся в файле. Работу с функцией fscanf проще всего понять на нескольких простых примерах. Пусть, например, в файле studentl.txt, состоящем из одной строки, содержится информация о студенте:

Александров 1990 учащийся 201 4.5

Пример 4. Файл-программа, записывающая фамилию Александров в строковую переменную Family, целое число (год) 1990 – в переменную Year, звание учащийся– в строковую переменную status, целое число (номер группы) 201– в Group, вещественное число (средний балл) 4.5 – в MeanMark. Считывание сопровождается выводом в командное окно для контроля. Перед запуском программы не забудьте создать файл studentl.txt с информацией о студенте

F = fopen('student1.txt', 'r');

Family = fscanf(F, '%s', 1)

Year = fscanf(F, '%d', 1)

Status = fscanf(F, '%s', 1)

Group = fscanf(F, '%s', 1)

MeanMark = fscanf(F, '%g', 1)

fclose(F);

Результат работы программы

Family =

Александров

Year =

1990

Status =

учащийся

Group =

201

MeanMark =

4.5000

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

str = fscanf(F, '%s', 5)

и посмотрите содержимое str. В данном случае вся информация интерпретируется как текстовая и заносится в одну строковую переменную:

str =

Александров1990учащийся2014.5

Допустимо не указывать число считываемых объектов и вызывать функцию fscanf только с двумя входными аргументами. Если при этом используется формат %s, то все содержимое считается в строковую переменную так же, как показано выше. Числовые форматы %d и %g позволяют записать содержимое файла, состоящего из чисел, в вектор. Считывание чисел продолжается до тех пор, пока не будет достигнут конец файла или не встретится текст.

Пример 5. Пусть в файле res.dat хранится следующая информация (необязательно в одну строку):

1.2274 1.4998

-2.0337 (результаты измерений)

F = fopen('res.dat', 'r');

vect = fscanf(F, '%g')

fclose(F);

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

Задание 8.

  1. Создайте файл matrix2read с матрицей размера три на четыре.

1.4 5.2 0.4 -1.1

-2.1 3.6 7.1 0.8

2.0 2.9 8.3 -0.1

Используйте команду M = fscanf (F, '%g', [3 4]) для заполнения матрицы данными из файла и выведите ее содержимое в командное окно. Матрица считалась из файла в заданном виде. Расположение матрицы в виде таблицы в файле необязательно, ее элементы могут быть записаны в строку, столбец или произвольным образом. Способ формирования матрицы задается вектором, указанным в списке входных параметров fscanf, а сами элементы считываются последовательно и помещаются в нужные позиции. Для того чтобы убедиться в этом, считайте из файла матрицу командами

N = fscanf (F, '%g', [4 3])

K = fscanf (F, '%g', [6 2])

P = fscanf (F, '%g', [12 1])

R = fscanf (F, '%g', [2 6])

2. Свяжите файл matrix2read c указателем на файл F и выполните последовательно 4 команды считывания fscanf, приведенных выше, после чего закройте файл.

3. Перед каждым вызовом функции fscanf выполните связывание файла matrix2read и переменной F, а после каждого вызова функции fscanf закройте файлы. Сравните результаты и сделайте выводы.

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

Пример 6.

Файл-функция readgroup для считывания данных в массив структур с полями Family, Name (строковые переменные), Year (числовая переменная), Marks (вектор-строка из целых чисел). Имя текстового файла задается во входном аргументе readgroup, а выходным аргументом является массив структур. Реализуйте следующий алгоритм в файл-функции.

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

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

3. Используйте счетчик для обращения к структурам массива, который увеличивается на единицу перед работой с новой структурой.

4. Считывание производите в цикле while, пока не будет достигнут конец файла.

5. При считывании оценок в вектор-строку задайте требуемый размер (один на шесть) в третьем аргументе fscanf.

function GROUP = readgroup(filename)

% Файл-функция для считывания таблицы с успеваемостью группы

% студентов из текстового файла в массив структур.

% Использование writegroup(filename, GROUP)

% filename — имя файла

% group — массив структур с полями

% Family (строка), Name (строка), Year (число),

% Marks (вектор-строка с шестью отметками)

% Окрытие текстового файла с именем filename для записи

F = fopen(filename, 'r');

% Считывание первой строки с шапкой таблицы

if feof(F) == 0

line = fgetl(F);

end

% Обнуление счетчика числа студентов

count = 0;

% Создание пустого массива структур

GROUP = [];

% Последовательное считывание строк (начиная со второй)

% и распределение информации, содержащейся в ней,

% по полям структур массива GROUP. Каждая строка файла

% содержит информацию об одном студенте

while feof(F) == 0

count = count + 1; % увеличение счетчика студентов

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

GROUP(count).Family = fscanf(F, '%s', 1);

% Считывание строки с именем

GROUP(count).Name = fscanf(F, '%s', 1);

% Считывание года рождения

GROUP(count).Year = fscanf(F, '%d', 1);

% Считывание массива с оценками в вектор-столбец

GROUP(count).Marks = fscanf(F, '%d', [1, 6]);

end

% Закрытие файла

fclose(F);

Задание 9. Вызовите функцию Group1=readgroup('group.txt'). Покажите содержимое массива Group1.

Задание 10. Исправьте функцию readgroup для чтения данных из файла newgroup.txt. Приведите результаты вызова исправленной функции.