- •Основы алгоритмизации и программирования, язык Си
- •Введение
- •Блок-схема алгоритма Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Операции и выражения
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора Директива #include
- •Директива #define
- •Понятие пустого и составного операторов
- •Условные операторы
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Операторы перехода (break, continue, return, goto)
- •Примеры программ
- •Массивы Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Параметры по умолчанию
- •Передача массива в функцию
- •Inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Доступ к элементам структуры
- •Инициализация структур
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Примеры программ
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Потоки и файлы
- •Файлы Основные сведения о файловой системе
- •Организация посимвольного ввода и вывода
- •Определение конца файла feof()
- •Организация ввода и вывода строк
- •Удаление файлов
- •Дозапись потока
- •Позиционирование в файле
- •Текстовые и двоичные файлы
- •Функции fread() и fwrite()
- •Примеры программ
- •Хеширование
- •Схемы хеширования
- •Метод открытой адресации с линейным опробыванием
- •Метод цепочек
- •Машинное представление графов
- •Примеры программ
- •Литература
Потоки и файлы
Перед тем как начать изучение файловой системы языка С, необходимо уяснить, в чем разница между потоками и файлами. В системе ввода/вывода С для программ поддерживается единый интерфейс, не зависящий от того, к какому конкретному устройству осуществляется доступ. То есть в этой системе между программой и устройством находится нечто более общее, чем само устройство. Такое обобщенное устройство ввода или вывода (устройство более высокого уровня абстракции) называется потоком, в то время как конкретное устройство называется файлом. Очень важно понимать, каким образом происходит взаимодействие потоков и файлов.
Файлы Основные сведения о файловой системе
Файловая система ввода/вывода в языке С реализуется с помощью взаимосвязанных библиотечных функций, а не ключевых слов. Для их работы требуется заголовок #include <stdio.h>. Это позволяет подключить файл stdio.h, содержащий прототипы функций ввода/вывода и определяет следующие три типа: size_t, fpos_t и FILE. Типы size_t и fpos_t представляют собой определенные разновидности цело беззнакового типа. А о третьем типе, FILE, рассказывается в следующем разделе. Кроме этого определяются несколько макросов: NULL, EOF, FOPEN_MAX, SEEK_SET, SEEK_CUR и SEEK_END. Макрос NULL определяет пустой (null) указатель. Макрос EOF, часто определяемый как -1, является значением, возвращаемым тогда, когда функция ввода пытается выполнить чтение после конца файла. FOPEN_MAX определяет целое значение, равное максимальному числу одновременно открытых файлов. Другие макросы используются вместе с функцией fseek(), выполняющей операции прямого доступа к файлу.
Файл – это именованный объект, хранящий данные любого типа на каком-либо носителе. Файлы используются для размещения данных, предназначенных для длительного хранения. Каждому файлу присваивается уникальное имя, используемое далее для обращения к нему. Файл, как и массив, – это совокупность данных в этом их сходство, но также существуют и некоторые различия:
- файлы, в отличие от массивов, располагаются не в оперативной памяти, а на некотором носителе информации, в том числе и на электронном диске (в оперативной памяти);
- файл не имеет фиксированной длины, то есть может увеличиваться и уменьшаться;
- перед работой с файлом его необходимо открыть, а после работы – закрыть.
В языке С имеются два способа работы с файлами: через указатель на тип FILE и используя дескриптор файла. Рассмотрим вначале организацию работы с файлами основанную на использовании указателя. Указатель файла определяет конкретный файл и используется соответствующим потоком при выполнении функций ввода/вывода. Для выполнения в файлах операций чтения и записи, программы должны использовать указатели соответствующих файлов. Указатель на файл – это переменная, идентифицирующая конкретный дисковый файл (его адрес) и используется для организации ввода/вывода. Он указывает на структуру FILE, содержащую различные сведения о файле, такие как, имя файла, статус и указатель текущей позиции в начало файла и другие. Описание указателя на файл имеет вид:
FILE *f;
Прежде чем производить действия с файлом (чтение, запись) файл должен быть открыт. Функция fopen() открывает для использования поток, связывает файл с данным потоком и возвращает указатель на открытый файл. Функция fopen() имеет следующий прототип:
FILE *fopen(const char *физическое_имя_файла, const char *режим);
Режим указывает на строку содержащую режим открытия файла. Возможны следующие режимы (табл. 11):
Таблица 11.
-
режим
Действие
“r”
Открывает файл для чтения
“w”
Создает файл для записи
“a”
Открывает файл для дозаписи в конец файла
“rb”
Открывает двоичный файл для чтения
“wb”
Открывает двоичный файл для записи
“ab”
Открывает двоичный файл для дозаписи в конец файла
“r+”
Открывает текстовый файл для чтения/записи
“w+”
Создает текстовый файл для чтения/записи
“a+”
Открывает или создает текстовый файл для чтения/записи
“r+b”
Открывает двоичный файл для чтения/записи
“w+b”
Открывает двоичный файл для чтения/записи
“a+b”
Открывает или создает двоичный файл для чтения/записи
“rt”
Открывает текстовый файл для чтения
“wt”
Открывает текстовый файл для записи
“at”
Открывает текстовый файл для дозаписи в коне файла
“r+t”
Открывает текстовый файл для чтения
“w+t”
Открывает текстовый файл для чтения/записи
“a+t”
Открывает или создает текстовый файл для чтения/записи
Функция fopen() инициализирует указатель, идентифицирующий файл и в дальнейшем использующийся большинством функций файловой системы. В случае если спецификация файла задана неверно, то fopen() возвращает указатель NULL. Ниже приводится пример использования функции fopen()для открытия файла по имени test.
FILE *f;
f = fopen("test", "r+");
Более правильно данный код написать немного иначе:
FILE *f;
if ((f = fopen("test","r+"))==NULL)
{ printf("Ошибка при открытии файла.\n");
exit(1);
}
Этот метод помогает при открытии файла обнаружить любую ошибку, например, отсутствие файла на носителе до попытки из этого файла что-либо прочитать. Всегда нужно вначале получить подтверждение, что функция fopen() выполнилась успешно, и лишь затем выполнять с файлом операции ввода и вывода.
Функция fclose() разрывает связь указателя с файлом и закрывает его к дальнейшему использованию, до тех пор пока он вновь не будет открыт. При этом записываются в файл все данные, которые еще оставались в дисковом буфере, и выполняет закрытие файла на уровне операционной системы. Завершение работы с файлом без закрытия потока может привести к потере данных, порче файла и другим ошибкам. Прототип функции fclose() имеет вид:
int fclose(FILE *f);
где f — указатель файла. Возвращение нуля означает успешную операцию закрытия. В случае же ошибки возвращается EOF. Чтобы точно узнать, причину ошибки, можно использовать функцию ferror().
Далее кратко остановимся на некоторых, наиболее важных функциях языка С, обеспечивающих работу с файлами по организации ввода и вывода информации. В таблице приведен список наиболее часто используемых из них.
Таблица . Функции файловой системы С
-
Наименование
Назначение функции
fopen()
Открывает файл
fclose()
Закрывает файл
putc(), fputc()
Записывает символ в файл
getc(), fgetc()
Читает символ из файла
fgets()
Читает строку из файла
fputs()
Записывает строку в файл
fseek()
Устанавливает указатель текущей позиции на определенный байт файла
ftell()
Возвращает текущее значение указателя текущей позиции в файле
fprintf()
Для файла то же, что printf() для консоли
fscanf()
Для файла то же, что scanf() для консоли
feof()
Возвращает значение true если достигнут конец файла
ferror()
Возвращает значение true, если произошла ошибка
rewind()
Устанавливает указатель текущей позиции в начало файла
remove()
Стирает файл
fflush()
Дозапись потока в файл