Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Цель работы: 1) получить практические навыки программирования задач ввода-вывода с использованием файлов.
Теоретические сведения
Организация ввода и вывода. Файловая система
Операции ввода/вывода в языке Си осуществляются через потоки. Поток - это логическое устройство, выдающее и принимающее информацию.
С потоком связано понятие внутреннего указателя, который определяет позицию, с которой начинается следующая операция чтения или записи. При каждой операции чтения или записи происходит автоматическое перемещение указателя.
В языке Си (С++) формат стандартных файлов ввода/вывода описан в заголовочном файле stdio.h. Имена стандартных файлов ввода/вывода для языка Си (С++) представлены в табл. 7.1. В момент начала выполнения программы на языке Си (С++) автоматически открываются три потока:
stdin, stdout, stderr.
Потоки, определяемые в языке Си и С++
Имя стандартного файла |
Описание |
stdaux |
Последовательный ввод/вывод |
stderr |
Выходной поток ошибок |
stdin |
Стандартный ввод |
stdout |
Стандартный вывод |
stdprn |
Вывод на принтер |
С++ поддерживает всю систему ввода/вывода Си и добавляет к ней дополнительные возможности, связанные в основном с вводом/выводом объектов. Описание средств для создания потоков в С++ представлено в заголовочном файле iostream.h. Когда начинает работать программа на С++, открываются потоки, приведенные в табл. 7.2.
Потоки, определяемые в языке С++
Имя стандартного файла |
Описание |
cin |
Стандартный ввод - клавиатура |
cout |
Стандартный вывод - экран |
cerr |
Стандартная ошибка - экран |
clog |
Буферизованная версия cerr - экран |
Файловая система языков Си и С++ состоит как бы из двух уровней:
логических файлов ;
физических файлов, с которыми логические файлы всегда связаны.
Логический файл описывается как указатель на открываемый поток FILE * и служит средством взаимодействия с физическим файлом.
Имя физического файла появляется в программе всего один раз, в тот момент, когда происходит открытие файла, осуществляемое функцией fopen() и одновременно его связывание с логическим файлом.
Основными действиями, производимыми над файлами, являются :
открытие файла ,
обработка файла
закрытие файла.
Обработка файлов может заключаться в следующем :
считывание блока данных из потока в оперативную память,
запись блока данных из оперативной памяти в поток,
считывание определенной записи данных из потока,
занесение определенной записи данных в поток.
При этом необходимо помнить, что понятие файла в памяти ЭВМ не определено, и приобретает смысл только после его связи с внешним физическим файлом.
Текстовые файлы
Тип FILE определяется в заголовочном файле stdio.h и обычно представляет собой структуру, содержащую параметры реализации потока, такие как адреса буферов, указатели позиций потока, маркеры ошибок потока и т.д.
При работе с дисковыми файлами в момент их открытия следует задать режим доступа, чтобы определить, к какому файлу осуществляется доступ:
к текстовому или
двоичному,
а также способ доступа:
чтение или
запись.
Все это выполняется функцией fopen(), имеющей синтаксис:
fopen("имя_файла", "режим_доступа")
Режимы доступа к файлам для функции fopen() приведены в табл. 7.3.
Режимы доступа к файлам
Режим |
Описание |
r |
Открыть файл только для чтения, модификации файла запрещены. |
w |
Создать новый файл только для записи. При попытке открыть таким способом существующий файл происходит перезапись файла. Чтение данных из файла запрещено. |
a |
Открыть файл для дозаписи. Если файла с указанным именем не существует, он будет создан. |
r+ |
Открыть существующий файл для чтения и записи. |
w+ |
Создать новый файл для чтения и записи. |
а+ |
Открыть существующий файл для дозаписи и чтения. |
Пример : Открыть текстовый файл для чтения
FILE *ft; // объявили указатель на файловый поток
ft = fopen("inp_f.txt","r"); // открыли файл inp_f.txt
При попытке открыть существующий файл можно допустить ошибку в его имени или в указании пути к нужному файлу. Это вызывает ошибку исполнения программы. Следует предвидеть подобные ситуации и проводить проверку возможности открытия файла. Такую проверку осуществить довольно легко, так как функция fopen() возвращает значение указателя в случае успешного его открытия и значение NULL, если доступ к файлу невозможен. Поэтому для проверки достаточно написать:
if (ft = fopen("inp_f.txt","r") != NULL)
{ // обработка файла
}
Текстовой файл состоит из последовательности символов, разбитой на строки путем использования управляющего символа \n. На диске текстовые файлы хранятся в виде сплошной последовательности символов, и их деление на строки становится заметным лишь в момент вывода на экран или печать, так как именно при выводе управляющие символы начинают выполнять свои функции. Текстовые файлы легко переносятся с одного типа компьютера на другой лишь в случаях, когда они содержат только символы, принадлежащие стандартному набору символов.
При работе с текстовыми файлами возможна их посимвольная или построчная обработка.
Основные методы обработки текстовых файлов
Файловые функции ввода/вывода fprintf() и fscanf() работают аналогично функциям printf() и scanf(), но имеют дополнительный аргумент, являющийся указателем на файловый поток.
Пример 7.1. Чтение одного элемента из файла, обработка и запись результата в текстовый файл.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{ FILE *f;
int dig;
if (f = (fopen("inp_f","r")) == NULL) // открыть файл для чтения
{ printf("Невозможно открыть файл!\n");
exit(0);
}
fscanf(f, "%d", &dig); // считать значение dig из файла
fclose(f); // закрыть файл
f = fopen("out_f","w"); // открыть файл для записи
fprintf(f, "Мы прочитали число %d", dig);
fclose(f); // закрыть файл
}
Мы использовали один и тот же указатель на файловый поток дважды, так как прежде, чем обращаться к нему вторично, закрыли связанный с ним файл и освободили, таким образом, указатель.
В приведенном примере имя файла было записано непосредственно в операторе открытия файла. Но можно сообщить имя открываемого файла, введя его с клавиатуры или пользуясь аргументами командной строки.
Пример 7.2. Написать программу, которая сжимает содержимое файла, записывая в выходной файл лишь каждый третий символ из входного файла.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
void main(int argc, char *argv[])
{ FILE *f_in, *f_out;
int ch;
char *name; // имя входного файла
int count = 0; // счетчик элементов
if (argc<2) // в командной строке нет имени
{ printf("Введите имя входного файла");
gets(name);
}
else name = argv[1]; // взять имя из командной строки
if ((f_in = fopen(name, "r")) != NULL)
{ strcat(name, ".out"); // добавляет расширение .out
// к имени файла
f_out = fopen(name, "w"); // открывает файл для записи
while((ch = fgetc(f_in)) != EOF)
if (count++ % 3 == 0)
fputc(ch, f_out); // выводит каждый третий символ
fclose(f_in);
fclose(f_out);
}
else printf("Невозможно открыть файл\n ");
}
При работе с текстовыми файлами возможна не только поэлементная обработка файлов, но и построчная.
Пример 7.3. Построчное чтение информации из входного файла и вывод ее на экран как на стандартное устройство вывода.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
void main(int argc, char *argv[])
{ FILE *f_in;
char buffer[256]; // максимальная длина строки - 255 символов
char *name; // имя входного файла
if (argc<2) // в командной строке нет имени
{ printf("Введите имя входного файла");
gets(name);
}
else name = argv[1]; // взять имя из командной строки
if ((f_in = fopen(name, "r")) != NULL)
{ while (fgets(buffer,255,f_in)) != NULL)
{ fputs(buffer, stdout);
fputc('\n', stdout);
}
fclose(f_in);
}
else printf("Невозможно открыть файл\n ");
}
1,14. Случайным образом создать таблицу пар целочисленных значений и записать её в текстовый файл в виде:
X Y
5 1
2 8
12 3 и т.д.
Считать из файла пары значений и в тех из них, где X>Y , поменять значения X и Y местами. Результат записать в другой текстовый файл такого же формата.
2,15. Ввести с клавиатуры попарно значения вещественного типа и записать их в текстовый файл в виде таблицы следующего формата:
X : Y
2.1 : 3.7
6.2 : 5.4 и т.д.
Считать из файла полученные пары значений и создать из них другой файл вида:
sin(x) : cos(y)
значение sin(2.1) : значение cos(3.7) и т.д.
3,16. Ввести с клавиатуры попарно значения вещественного типа и записать их в текстовый файл в виде таблицы следующего формата:
X : Y
2.1 : 3.7
6.2 : 5.4 и т.д.
Считать из файла полученные пары значений и создать из них другой файл вида:
tg(x) : ctg(y)
значение tg(2.1) : значение ctg(3.7) и т.д.
4,17. Случайным образом создать таблицу пар значений и записать её в текстовый файл в виде:
n * c
5 * m
7 * a
3 * q и т.д.
Считать из файла пары значений и создать из них другой текстовый файл вида
mmmmm
aaaaaaa
qqq
5,18. Случайным образом создать таблицу пар значений и записать её в текстовый файл в виде:
n * c
5 * 3.1
7 * 4.2
3 * 8.3 и т.д.
Считать из файла пары значений и создать из них другой текстовый файл вида произведений:
15.5
29.4
24.9
6,19. Случайным образом создать таблицу пар целочисленных значений и записать её в текстовый файл в виде:
X Y
5 1
2 8
12 3 и т.д.
Считать из файла пары значений и в тех из них, где X кратен Y , пометить строку таблицы:
X Y
5 1 ***
2 8
12 3 ***
в том же файле.
7,20. Случайным образом создать таблицу пар целочисленных значений и записать её в текстовый файл в виде:
X Y
5 8
2 1
1 3 и т.д.
Считать из файла пары значений и в тех из них, где X меньше Y , пометить строку таблицы:
X Y
5 8 ###
2 1
1 3 ###
в том же файле.
8,21. Случайным образом создать таблицу пар значений и записать её в текстовый файл в виде:
a b c
5.2 4.6 2.5
1.2 8.9 2.3 и т.д.
Считать из файла записанные данные и определить, можно ли построить треугольник с такими сторонами. Пометить соответствующие строки таблицы (в том же файле).
a b c
5.2 4.6 2.5 можно
1.2 8.9 2.3
9,22. Создать текстовый файл, содержащий вещественные значения. Считать из файла записанные данные и определить максимальное значение. Если оно находится в первой половине файла, заменить его суммой последующих элементов, если во второй суммой предыдущих элементов.
10,23. Случайным образом создать таблицу пар целочисленных значений и записать её в текстовый файл в виде:
X Y
5 25
1 3
49 7 и т.д.
Считать из файла пары значений и в тех из них, где X является точным квадратом Y или наоборот, найти сумму значений X и Y. Результат записать в другой текстовый файл в виде
X Y sum
5 25 30
1 3
49 7 56
11,24. Создать текстовый файл, содержащий целые числовые значения, например : 5 3 21 4 37 52 9 2. Считать из файла записанные данные и определить минимальное значение. Если оно кратно трем, заменить каждое третье значение файла нулем, если кратно пяти заменить его суммой первого и последнего элементов.
12,25. Создать текстовый файл, содержащий целые числовые значения, например: 15 13 21 42 37 50 9 2. Считать из файла записанные данные и заменить нулем каждое значение файла, кратное минимальному числу.
13,26. Ввести с клавиатуры значения вещественного типа и записать их в текстовый файл в виде таблицы следующего формата:
X : Y : Z
2.1 : 3.7 : 0.9
6.2 : 5.4 : 4.2 и т.д.
Считать из файла полученные значения и создать из них другой файл вида:
sin(max{X,Y,Z}) : cos(min{X,Y,Z})
значение sin(3.7) : значение cos(0.9)