Работа с файлами, директориями и дисковым пространством
Описание работы с файлами в языке Си: открытие, закрытие и переименование файлов, функции бинарного чтения и текстового преобразования, диагностика ошибок. Определение текущей рабочей директории, текущего каталога диска и размера дискового пространства.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | лабораторная работа |
Язык | русский |
Дата добавления | 06.07.2009 |
Размер файла | 38,2 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
2
Кафедра: Автоматика и Информационные Технологии
РАБОТА С ФАЙЛАМИ, ДИРЕКТОРИЯМИ И ДИСКОВЫМ ПРОСТРАНСТВОМ
СОДЕРЖАНИЕ
1. Работа с файлами
1.1 Открытие файла: функция fopen
1.2 Диагностика ошибок: функция perror
1.3 Функции бинарного чтения и записи fread и fwrite
1.4 Закрытие файла: функция fclose
1.5 Пример: подсчет числа символов и строк в текстовом файле
1.6 Функции текстового преобразования sscanf и sprintf
1.7 Переименование файла
1.8 Определение текущей рабочей директории
1.9 Определение текущего каталога диска
1.10 Определение размера свободного дискового пространства
1.11 Определение/установка текущего диска
1.12 Создание, удаление, смена директорий
1.13 Поиск файла
1.14 Просмотр каталога диска
1.15 Создание уникального имени файла
1.16 Редактирование имени файла
2. Лабораторные задания
2.1 Переменное число параметров.
2.2 Многострочный ввод с клавиатуры
2.3 Объединение файлов
2.4 Замена в текстовом файле.
2.5 Ввод массивов.
2.6 Просмотр дисков
2.7 Структура каталога
3. Дополнительные задания
3.1 Морзянка
3.2 Комментарии в программе
Библиографический список
1. Работа с файлами
Стандартная библиотека Си содержит набор функций для работы с файлами. Эти функции описаны в стандарте ANSI. Отметим, что файловый ввод-вывод не является частью языка Си, и ANSI-функции - не единственное средство ввода-вывода. Так, в операционной системе Unix более популярен другой набор функций ввода-вывода, который можно использовать не только для работы с файлами, но и для обмена по сети. В C++ часто используются библиотеки классов для ввода-вывода. Тем не менее, функции ANSI-библиотеки поддерживаются всеми Си-компиляторами, и потому программы, применяющие их, легко переносятся с одной платформы на другую. Прототипы функций ввода-вывода и используемые для этого типы данных описаны в стандартном заголовочном файле "stdio.h.
1.1 Открытие файла: функция fopen
Для доступа к файлу применяется тип данных FILE. Это структурный тип, имя которого задано с помощью оператора typedef в стандартном заголовочном файле <stdio.h>. Программисту не нужно знать, как устроена структура типа файл: ее устройство может быть системно зависимым, поэтому в целях переносимости программ обращаться явно к полям структуры FILE запрещено. Тип данных "указатель на структуру FILE” используется в программах как черный ящик: функция открытия файла возвращает этот указатель в случае успеха, и в дальнейшем все файловые функции применяют его для доступа к файлу.
Прототип функции открытия файла выглядит следующим образом:
FILE *fopen(const char *path, const char *mode);
Здесь path - путь к файлу (например, имя файла или абсолютный путь к файлу), mode - режим открытия файла. Строка mode может содержать несколько букв. Буква "r" (read) означает, что файл открывается для чтения (файл должен существовать). Буква "w" (write) означает запись в файл, при этом старое содержимое файла теряется, а в случае отсутствия файла он создается. Буква "a" (от слова append) означает запись в конец существующего файла или создание нового файла, если файл не существует.
В некоторых операционных системах имеются различия в работе с текстовыми и бинарными файлами (к таким системам относятся MS DOS и MS Windows; в системе Unix различий между текстовыми и бинарными файлами нет). В таких системах при открытии бинарного файла к строке mode следует добавлять букву "b" (от слова binary), а при открытии текстового файла -- букву "t" (от слова text). Кроме того, при открытии можно разрешить выполнять как операции чтения, так и записи; для этого используется символ + (плюс). Порядок букв в строке mode следующий: сначала идет одна из букв "r", "w", "a", затем в произвольном порядке могут идти символы "b", "t", "+". Буквы "b" и "t" можно использовать, даже если в операционной системе нет различий между бинарными и текстовыми файлами, в этом случае они просто игнорируются.
Значения символов в строке mode сведены в следующую таблицу:
Таблица. 1.
Режимы открытия файла
r |
Открыть существующий файл на чтение |
|
w |
Открыть файл на запись. Старое содержимое файла теряется, в случае отсутствия файла он создаётся. |
|
a |
Открыть файл на запись. Если файл существует, то запись производится в его конец. |
|
t |
Открыть текстовый файл. |
|
b |
Открыть бинарный файл. |
|
+ |
Разрешить и чтение, и запись. |
Примеры.
FILE *f, *g, *h;
// 1. Открыть текстовый файл "abcd.txt" для чтения
f = fopen("abcd.txt", "rt");
// 2. Открыть бинарный файл "c:\Windows\\Temp\\tmp.dat"
// для чтения и записи
g = fopen("c:/Windows/Temp/tmp.dat", "wb+");
// 3. Открыть текстовый файл "c:\Windows\\Temp\\abcd.log"
// для дописывания в конец файла
h = fopen("c:\\Windows\\Temp\\abcd.log", "at");
Обратите внимание, что во втором случае мы используем обычную косую черту / для разделения директорий, хотя в системах MS DOS и MS Windows для этого принято использовать обратную косую черту \. Дело в том, что в операционной системе Unix и в языке Си, который является для нее родным, символ \ используется в качестве экранирующего символа, т.е. для защиты следующего за ним символа от интерпретации как специального. Поэтому во всех строковых константах Си обратную косую черту надо повторять дважды, как это и сделано в третьем примере. Впрочем, стандартная библиотека Си позволяет в именах файлов использовать нормальную косую черту вместо обратной; эта возможность была использована во втором примере.
В случае удачи функция fopen открытия файла возвращает ненулевой указатель на структуру типа FILE, описывающую параметры открытого файла. Этот указатель надо затем использовать во всех файловых операциях. В случае неудачи (например, при попытке открыть на чтение несуществующий файл) возвращается ненулевой указатель. При этом глобальная системная переменная errno, описанная в стандартном заголовочном файле <errno.h>, содержит численный код ошибки. В случае неудачи при открытии файла этот код можно распечатать, чтобы получить дополнительную информацию:
FILE *f = fopen("filnam.txt", "rt");
if (f == NULL) {
printf( "Ошибка открытия файла с кодом %d\n", errno);
. . .
}
1.2 Диагностика ошибок: функция perror
Использовать переменную errno для печати кода ошибки не очень удобно, поскольку необходимо иметь под рукой таблицу возможных кодов ошибок и их значений. В стандартной библиотеке Си существует более удобная функция perror, которая печатает системное сообщение о последней ошибке вместо ее кода. Печать производится на английском языке, но есть возможность добавить к системному сообщению любой текст, который указывается в качестве единственного аргумента функции perror. Например, предыдущий фрагмент переписывается следующим образом:
FILE *f = fopen("filnam.txt", "rt");
if (f == 0) {
perror("Не могу открыть файл на чтение");
. . .
}
Функция perror печатает сначала пользовательское сообщение об ошибке, затем после двоеточия системное сообщение. Например, при выполнении приведенного фрагмента в случае ошибки из-за отсутствия файла будет напечатано
Не могу открыть файл на чтение: No such file or directory
1.3 Функции бинарного чтения и записи fread и fwrite
После того как файл открыт, можно читать информацию из файла или записывать информацию в файл. Рассмотрим сначала функции бинарного чтения и записи fread и fwrite. Они называются бинарными потому, что не выполняют никакого преобразования информации при вводе или выводе (с одним небольшим исключением при работе с текстовыми файлами, которое будет рассмотрено ниже): информация хранится в файле как последовательность байтов ровно в том виде, в котором она хранится в памяти компьютера.
Функции чтения fread имеет следующий прототип:
size_t fread(
char *buffer, // Массив для чтения данных
size_t elemSize, // Размер одного элемента
size_t numElems, // Число элементов для чтения
FILE *f // Указатель на структуру FILE
);
Здесь size_t определен как беззнаковый целый тип в системных заголовочных файлах. Функция пытается прочесть numElems элементов из файла, который задается указателем f на структуру FILE, размер каждого элемента равен elemSize. Функция возвращает реальное число прочитанных элементов, которое может быть меньше, чем numElems, в случае конца файла или ошибки чтения. Указатель f должен быть возвращен функцией fopen в результате успешного открытия файла. Пример использования функции fread:
FILE *f;
double buff[100];
size_t res;
f = fopen("tmp.dat", "rb"); // Открываем файл
if (f == 0) { // При ошибке открытия файла
// Напечатать сообщение об ошибке
perror("Не могу открыть файл для чтения");
exit(1); // завершить работу с кодом 1
}
// Пытаемся прочесть 100 вещественных чисел из файла
res = fread(buff, sizeof(double), 100, f);
// res равно реальному количеству прочитанных чисел
В этом примере файл "tmp.dat" открывается на чтение как бинарный, из него читается 100 вещественных чисел размером 8 байт каждое. Функция fread возвращает реальное количество прочитанных чисел, которое меньше или равно, чем 100.
Функция fread читает информацию в виде потока байтов и в неизменном виде помещает ее в память. Следует различать текстовое представление чисел и их бинарное представление! В приведенном выше примере числа в файле должны быть записаны в бинарном виде, а не в виде текста. Для текстового ввода чисел надо использовать функции ввода по формату, которые будут рассмотрены ниже.
Внимание! Открытие файла как текстового с помощью функции fopen, например,
FILE *f = fopen("tmp.dat", "rt");
вовсе не означает, что числа при вводе с помощью функции fopen будут преобразовываться из текстовой формы в бинарную! Из этого следует только то, что в операционных системах, в которых строки текстовых файлов разделяются парами символами "\r\n" (они имеют названия CR и LF - возврат каретки и продергивание бумаги, Carriage Return и Line Feed), при вводе такие пары символов заменяются на один символ "\n" (продергивание бумаги). Обратно, при выводе символ "\n" заменяется на пару "\r\n". Такими операционными системами являются MS DOS и MS Windows. В системе Unix строки разделяются одним символом "\n" (отсюда проистекает обозначение "\n", которое расшифровывается как new line). Таким образом, внутреннее представление текста всегда соответствует системе Unix, а внешнее - реально используемой операционной системе.
Функция бинарной записи в файл fwrite аналогична функции чтения fread. Она имеет следующий прототип:
size_t fwrite(
char *buffer, // Массив записываемых данных
size_t elemSize, // Размер одного элемента
size_t numElems, // Число записываемых элементов
FILE *f // Указатель на структуру FILE
);
Функция возвращает число реально записанных элементов, которое может быть меньше, чем numElems, если при записи произошла ошибка - например, не хватило свободного пространства на диске. Пример использования функции fwrite:
FILE *f;
double buff[100];
size_t num;
. . .
f = fopen("tmp.res", "wb"); // Открываем файл "tmp.res"
if (f == 0) { // При ошибке открытия файла
// Напечатать сообщение об ошибке
perror("Не могу открыть файл для записи");
exit(1); // завершить работу программы с кодом 1
}
// Записываем 100 вещественных чисел в файл
res = fwrite(buff, sizeof(double), 100, f);
// В случае успеха res == 100
1.4 Закрытие файла: функция fclose
По окончании работы с файлом его надо обязательно закрыть. Система обычно запрещает полный доступ к файлу до тех пор, пока он не закрыт. (Например, в нормальном режиме система запрещает одновременную запись в файл для двух разных программ.) Кроме того, информация реально записывается полностью в файл лишь в момент его закрытия. До этого она может содержаться в оперативной памяти (в так называемой файловой кеш-памяти), что при выполнении многочисленных операций записи и чтения значительно ускоряет работу программы.
Для закрытия файла используется функция fclose с прототипом
int fclose(FILE *f);
В случае успеха функция fclose возвращает ноль, при ошибке -- отрицательное значение (точнее, константу конец файла EOF, определенную в системных заголовочных файлах как минус единица). При ошибке можно воспользоваться функцией perror, чтобы напечатать причину ошибки. Отметим, что ошибка при закрытии файла - явление очень редкое (чего не скажешь в отношении открытия файла), так что анализировать значение, возвращаемое функцией fclose, в общем-то, не обязательно.
1.5 Пример: подсчет числа символов и строк в текстовом файле
Приведем программу, которая подсчитывает число символов и строк в текстовом файле. Программа сначала вводит имя файла с клавиатуры. Затем файл открывается на чтение как бинарный (это означает, что при чтении не будет происходить никакого преобразования разделителей строк). Используя в цикле функцию чтения fread, мы считываем содержимое файла порциями по 512 байтов, каждый раз увеличивая суммарное число прочитанных символов. После чтения очередной порции сканируется массив прочитанных символов и подсчитывается число символов "\n" продергивания бумаги, которые записаны в концах строк текстовых файлов. В конце закрывается файл и печатается результат.
#include <stdio.h>
#include <stdlib.h>
int main() {
char fileName[256]; // Путь к файлу
FILE *f; // Структура, описывающая файл
char buff[512]; // Массив для ввода символов
size_t num; // Число прочитанных символов
int numChars = 0; // Суммарное число символов := 0
int numLines = 0; // Суммарное число строк := 0
printf("Введите имя файла: ");
scanf("%s", fileName);
f = fopen(fileName, "rb"); // Открываем файл на чтение
if (f == 0) {
perror("Не могу открыть файл для чтения");
exit(1);
}
while ((num = fread(buff, 1, 512, f)) > 0) { // Читаем
// блок из 512 символов. num -- число реально
// прочитанных символов. Цикл продолжается, пока
// num > 0
numChars += num; // Увеличиваем число символов
// Подсчитываем число символов перевода строки
for (int i = 0; i < num; ++i)
if (buff[i] == '\n')
++numLines; // Увеличиваем число строк
}
fclose(f);
// Печатаем результат
printf("Число символов в файле = %d\n", numChars);
printf("Число строк в файле = %d\n", numLines);
return 0;
}
1.6 Функции текстового преобразования sscanf и sprintf
Стандартная библиотека ввода-вывода Си предоставляет две функции sscanf и sprintf ввода и вывода не в файл или поток, а в строку символов (т.е. массив байтов), расположенную в памяти компьютера. Первым аргументом функций sscanf и sprintf является строка (т.е. массив символов, ограниченный нулевым байтом), из которой производится ввод или в которую производится вывод. Эта строка как бы стоит на месте файла в функциях fscanf и fprintf.
Функции sscanf и sprintf удобны для преобразования данных из текстового представления во внутреннее и обратно. Например, в результате выполнения фрагмента
char txt[256] = "-135.76"; double x;
sscanf(txt, "%lf", &x);
текстовая запись вещественного числа, содержащаяся в строке txt, преобразуется во внутреннее представление вещественного числа, результат записывается в переменную x. Обратно при выполнения фрагмента
char txt[256]; int x = 12345;
sprintf(txt, "%d", x);
значение целочисленной переменной x будет преобразовано в текстовую форму и записано в строку txt, в результате строка будет содержать текст "12345", ограниченный нулевым байтом.
1.6.1.1 Другие полезные функции ввода-вывода
Стандартная библиотека ввода-вывода Си содержит ряд других полезных функций ввода-вывода. Отметим некоторые из них.
Таблица 2.
Посимвольный ввод-вывод |
||
int fgetc(FILE *f); |
ввести символ из потока f |
|
int fputc(int c, FILE *f); |
вывести символ в поток f |
|
Построковый ввод-вывод |
||
char *fgets(char *line,int size, FILE *f); |
ввести строку из потока f |
|
char *fputs(char *line, FILE *f); |
вывести строку в поток f |
Таблица 3.
Позиционирование в файле |
||
int fseek(FILE *f, long offset, int whence); |
установить текущую позицию в файле f |
|
long ftell(FILE *f); |
получить текущую позицию в файле f |
|
int feof(FILE *f); |
проверить,достигнут ли конец файла f |
Функция fgetc возвращает код введенного символа или константу EOF (определенную как минус единицу) в случае конца файла или ошибки чтения. Функция fputc записывает один символ в файл. При ошибке fputc возвращает константу EOF (т.е. отрицательное значение), в случае удачи - код выведенного символа c (неотрицательное значение).
Раньше в стандартную библиотеку Си входила также функция gets с прототипом
char *gets(char *line);
которая считывала очередную строку из стандартного входного потока и помещала ее в массив, адрес которого являлся ее единственным аргументом. Отличие от функции fgets в том, что не указывается размер массива line. В результате, подав на вход функции gets очень длинную строку, можно добиться переполнения массива и стереть или подменить участок памяти, используемый программой. Если программа имеет привилегии суперпользователя, то применение в ней функции gets открывает путь к взлому системы, который использовался хакерами. Поэтому в настоящее время функция gets считается опасной и применение ее не рекомендовано. Вместо gets следует использовать fgets с третьим аргументом stdin.
При выполнении файловых операций исполняющая система поддерживает указатель текущей позиции в файле. При чтении или записи n байтов указатель текущей позиции увеличивается на n; таким образом, чтение или запись происходят последовательно. Библиотека ввода-вывода Си предоставляет, однако, возможность нарушать эту последовательность путем позиционирования в произвольную точку файла. Для этого используется стандартная функция fseek с прототипом
int fseek(FILE *f, long offset, int whence);
Первый аргумент f функции определяет файл, для которого производится операция позиционирования. Второй аргумент offset задает смещение в байтах, оно может быть как положительным, так и отрицательным. Третий аргумент whence указывает, откуда отсчитывать смещение. Он может принимать одно из трех значений, заданных как целые константы в стандартном заголовочном файле "stdio.h":
SEEK_CUR |
смещение отсчитывается от текущей позиции |
|
SEEK_SET |
смещение отсчитывается от начала файла |
|
SEEK_END |
смещение отсчитывается от конца файла |
Например, фрагмент
fseek(f, 0, SEEK_SET);
устанавливает текущую позицию в начало файла. Фрагмент
fseek(f, -4, SEEK_END);
устанавливает текущую позицию в четырех байтах перед концом файла. Наконец, фрагмент
fseek(f, 12, SEEK_CUR);
продвигает текущую позицию на 12 байтов вперед.
Cмещение может быть положительным даже при использовании константы SEEK_END (т.е. при позиционировании относительно конца файла): в этом случае при следующей записи размер файла соответственно увеличивается.
Функция возвращает нулевое значение в случае успеха и отрицательное значение EOF (равное -1) при неудаче - например, если указанное смещение некорректно при заданной операции или если файл или поток не позволяет выполнять прямое позиционирование.
Узнать текущую позицию относительно начала файла можно с помощью функции ftell с прототипом
long ftell(FILE *f);
Функция ftell возвращает текущую позицию (неотрицательное значение) в случае успеха или отрицательное значение -1 при неудаче (например, если файл не разрешает прямое позиционирование).
Наконец, узнать, находится ли текущая позиция в конце файла, можно с помощью функции feof с прототипом
int feof(FILE *f);
Она возвращает ненулевое значение (т.е. истину), если конец файла достигнут, и нулевое значение (т.е. ложь) в противном случае. Например, в следующем фрагменте в цикле проверяется, достигнут ли конец файла, и, если нет, считывается очередной байт:
FILE *f;
. . .
while (!feof(f)) { // цикл пока не конец файла
int c = fgetc(f); // | прочесть очередной байт
. . . // | . . .
} // конец цикла
1.7 Переименование файла
int rename(char * oldname, char * newname);
Переименование файла с имени oldname на newname.
Если в newname указан0 имя диска, то тот же диск должен быть указан в oldname. Функция может использоваться для перемещения файла из одного каталога в другой в пределах одного диска. Символы * и ? не допускаются.
Возвращает : 0 - в случае успеха. При неудаче возвращается -1 и errno присваивается:
ENOENT - нет такого файла или директории,
EACCES - нет доступа,
ENOTSAM - указан другой диск.
#include <stdio.h>
int main(void)
{
char oldname[80], newname[80];
printf("File to rename: ");
gets(oldname);
printf("New name: ");
gets(newname);
if (rename(oldname, newname) == 0)
printf("Renamed %s to %s.\n", oldname, newname);
else
perror("rename");
return 0;
}
1.8 Определение текущей рабочей директории
char *getcwd(char * buf, , int buflen);
Определяет текущую рабочую директорию
char *_getdcwd(int disk, char * buf, , int buflen);
Определение текущей директории для указанного диска, при этом 0 - текущий диск, 1 - А, 2 - B, …
Если полное имя файла , включая нулевой признак конца строки) больше чем buflen, возникает ошибка.
Если buf =NULL, _getdcwd вызывает malloc для выделения динамической памяти по адресу buf в количестве buflen байт. Позже можно освободить эту память с помощью функции free, используя адрес, возвращаемый этими функциями.
При успехе функции возвращают buf.
При неудаче они возвращают NULL и присваивают errno одно из следующих значений:
ENODEV - нет такого диска
ENOMEM - нет памяти для размещения buf,
ERANGE - имя каталога длиннее, чем buflen.
Пример.
#include <stdio.h>
#include <dir.h>
int main(void)
{
char buffer[MAXPATH];
getcwd(buffer, MAXPATH);
printf("Текущим каталогом является: %s\n", buffer);
return 0;
}
Пример.
#include <direct.h>
#include <stdio.h>
char buf[65];
void main()
{
if (_getdcwd(3, buf, sizeof(buf)) == NULL)
perror("Нельзя получить текущую директорию на диске C: \n");
else
printf("Текущей директорией на диске C: является %s\n", buf);
}
1.9 Определение текущего каталога диска
int getcurdir(int drive, char *directory);
directory указывает на область памяти размером не менее MAXDIR, куда будет помещено имя текущего каталога. Имя не содержит указания диска.
Возвращает 0 в случае успеха и -1 при ошибке.
Пример.
char *current_directory(char *path)
{
strcpy(path, "X:\\"); /* fill string with form of response: X:\ */
path[0] = 'A' + getdisk(); /* replace X with current drive letter */
getcurdir(0, path+3); /* fill rest of string with current directory */
return path ;
}
int main(void)
{
char curdir[MAXPATH];
current_directory(curdir);
printf("The current directory is %s\n", curdir);
return 0;
}
1.10 Определение размера свободного дискового пространства
void getdfree(unsigned char drive, struct dfree *dtable);
Функция заполняет структуру dtable для указнного диска (0 - текущий диск, 1 - А, 2 - B, …).
struct dfree{
unsigned df_avail, // число свободных кластеров
unsigned df_total, // всего кластеров
unsigned df_bsec, // число байтов в секторе
unsigned df_sclus, // число секторов в кластере
}
При ошибке присваивает элементу df_sclus структуры dfree значение 0xFFFF.
#include <stdio.h>
#include <stdlib.h>
#include <dir.h>
#include <dos.h>
int main(void)
{
struct dfree free;
long avail;
int drive;
drive = getdisk();
getdfree(drive+1, &free);
if (free.df_sclus == 0xFFFF)
{
printf("Error in getdfree() call\n");
exit(1);
}
avail = (long) free.df_avail
* (long) free.df_bsec
* (long) free.df_sclus;
printf("Drive %c: has %ld bytes available\n", 'A' + drive, avail);
return 0;
}
1.11 Определение/установка текущего диска
int getdisk();
int setdisk(int drive);
Нумерация дисков: 0 - А, 1 - В, 2 - С, …
getdisk возвращает номер текущего диска, setdisk возвращает общее количество доступных дисков.
Пример.
#include <stdio.h>
#include <dir.h>
int main(void)
{
int disk, maxdrives = setdisk(2);
disk = getdisk() + 'A';
printf("\nКоличество логических дисков:%d\n", maxdrives);
printf("Текущий диск: %c\n", disk);
return 0;
}
Пример.
#include <stdio.h>
#include <dir.h>
int main(void)
{
int save, disk, disks;
/* сохранить исходный диск */
save = getdisk();
/* напечатать количество логических дисков */
disks = setdisk(save);
printf("В системе %d логических дисков\n\n", disks);
/* напечатать имена доступных логических дисков */
printf("Доступные диски:\n");
for (disk = 0;disk < 26;++disk)
{
setdisk(disk);
if (disk == getdisk())
printf("%c: диск доступен\n", disk + 'a');
}
setdisk(save);
return 0;
}
1.12 Создание, удаление, смена директорий
int mkdir(char *pathname);
int rmdir(char *pathname);
Удаляет директорию pathname, которая: должна быть пустой, не должна быть текущей рабочей директорией, не должна быть корневой директорией.
В случае успеха возвращают 0, при неудаче errno принимает значения:
ENOENT - нет такого файла или директории,
EACCES - нет доступа,
Пример.
int chdir(char *pathname);
#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <dir.h>
#define DIRNAME "testdir.$$$"
int main(void)
{
int stat;
stat = mkdir(DIRNAME);
if (!stat)
printf("Директория создана\n");
else
{
printf("Не могу создать директорию\n");
exit(1);
}
getch();
system("dir/p");
getch();
stat = rmdir(DIRNAME);
if (!stat)
printf("\nДиректория удалена\n");
else
{
perror("\nНе могу удалить директорию\n");
exit(1);
}
return 0;
}
1.13 Поиск файла
char *searchpath(char *file);
Вначале поиск осуществляется в текущем каталоге текущего диска. Если файл не найден, функция перебирает пути из переменной окружения PATH.
В случае успеха возвращает строку, содержащую полный путь к файлу. Это имя размещается в статическом буфере и перезаписывается при каждом последующем вызове. В случае неудачи возвращается NULL.
1.14 Просмотр каталога диска
int findfirst(char * pathname, struct ffblk* ffblk, int attrib);
int fidtnext(struct ffblk * ffblk);
Функция findfirst производит поиск в каталоге диска посредством системного вызова DOS 0x4E.
Параметр pathname представляет собой символьную строку, содержащую необязательную спецификацию дискового устройства, маршрут поиска и имя искомого файла. Имя файла может содержать шаблоны (такие как? или *). Если соответствующий файл найден, структура ffblk заполняется информацией о файле и каталоге, его содержащем.
Cтруктура ffblk определена следующим образом:
struct ffblk {
char ff_reserved[21]; /* зарезервировано DOS */
char ff_attrib; /* атрибуты */
int ff_ftime; /* время */
int ff_fdate; /* дата */
long ff_fsize; /* размер */
char ff_fname[13]; /* имя файла */
};
Параметр attrib - это используемый в MS-DOS байт атрибута файла, который употребляется при выборе подходящих для поиска файлов. Параметр attrib может быть одной из следующих определенных в файле dos.h констант:
FA_NORMAL = 0x00 - Обычный файл без атрибутов
FA_RDONLY = 0x01 - Атрибут "только чтение".
FA_HIDDEN = 0x02 - Скрытый файл.
FA_SYSTEM = 0x04 - Системный файл.
FA_LABEL = 0x08 - Метка тома.
FA_DIREC = 0x10 - Каталог.
FA_ARCH = 0x20 - Архив.
Отметим, что ff_ftime и ff_fdate содержат битовые поля для определения даты и времени. Эти структуры поддерживаются DOS. Обе 16-битовые структуры делятся на 3 поля:
ff_ftime:
биты 0-4 Секунды, деленные на 2. (т.е. 10 соответствует 20 секундам).
биты 5-10 минуты
биты 11-15 часы
ff_fdate:
биты 0-4 день
биты 5-8 месяц
биты 9-15 год с 1980 (т.е. 9 соответствует 1989)
При успешном завершении, то есть при успешном значение поиске файла, соответствующего параметру pathname, функция findfirst возвращает значение 0. Если подходящих файлов больше не существует, или в имени файла допущена ошибка, функция возвращают значение -1 и глобальная переменная errno получает одно из следующих значений:
ENOENT - Маршрут доступа или имя файла не найдены,
а переменной doserrno присваивается одно из следующих значений:
ENOENT - Маршрут доступа или имя файла не найдены.
ENMFILE - Нет больше файлов.
Функция findnext используется для выборки последовательности файлов, соответствующих параметру pathname, задаваемому функцией findfirst.
ffblk - это тот же самый блок, который заполняется при вызове функции findfirst. Данный блок содержит всю необходимую информацию для продолжения поиска.
При каждом вызове функции findnext будет возвращаться одно имя файла до тех пор, пока файлы, соответствующие параметру, pathname не закончатся.
При успешном завершении, то есть при успешном значение поиске файла, соответствующего параметру pathname, функция findnext возвращает значение 0. Если подходящих файлов больше не существует, или в имени файла допущена ошибка, функция возвращает значение -1 и глобальная переменная errno получает одно из следующих значений:
ENOENT - Маршрут доступа или имя файла не найдены,. а переменной doserrno присваивается одно из следующих значений:
ENOENT - Маршрут доступа или имя файла не найдены.
ENMFILE - Нет больше файлов.
Пример:
#include <stdio.h>
#include <dir.h>
int main(void)
{
struct ffblk ffblk;
int done;
printf("Листинг каталога *.*\n");
done = findfirst(**.**,&ffblk,0);
while (!done) {
printf(" %s\n", ffblk.ff_name);
done = findnext(&ffblk);
}
return 0;
}
1.15 Создание уникального имени файла
char *mktemp(char *template);
Функция заменяет строку *template уникальным именем файла и возвращает template. Параметр template должен являться строкой и заканчиваться шестью буквами X. Буквы Х заменяются уникальной коллекцией из двух последних букв имени и трех букв расширения файла. Начиная с AA.AAA, mktemp ищет уникальное имя, просматривая весь диск. При успехе возвращается адрес сформированной строки, при неудаче - NULL
Пример:
int main(void)
{
char *fname = "TXXXXXX", *ptr;
ptr = mktemp(fname);
printf("%s\n",ptr);
FILE *fp = fopen(ptr, “w”);
fname = "TXXXXXX";
ptr = mktemp(fname);
printf("%s\n",ptr);
unlink(fp);
return 0;
}
1.16 Редактирование имени файла
_makepath and fnmerge строят путь из отдельных компонентов
_splitpath and fnsplit разбивают полный путь файла на отдельные компоненты Синтаксис:
void _makepath(char *path, const char *drive, const char *dir, const char *name, const char *ext);
void fnmerge (char *path, const char *drive, const char *dir, const char *name, const char *ext);
void _splitpath(const char *path, char *drive, char *dir, char *name, char *ext);
int fnsplit (const char *path, char *drive, char *dir, char *name, char *ext);
Замечания
_makepath и fnmerge создают полное имя файла из компонентов.
_splitpath и fnsplit получают полное имя файла, как строку, и разделяют его на четыре компоненты.
Функции _makepath и _splitpath взаимнобратны. Если разбить данный путь с помощью _splitpath, а затем склеить полученные компоненты, то получим тот же путь.
Аналгично, fnmerge и fnsplit взаимнобратны.
Максимальные размеры для аргументов функций:
MAXPATH = 80
MAXDRIVE= 3 , включая :
MAXDIR = 66 , включая лидирующие и конечные символы backslashes (\)
MAXFNAME= 9
MAXEXT = 5 , включая лидирующую точку (.)
Возвращаемые значения:
_makepath, _splitpath и fnmerge ничего не возвращают
fnsplit возвращает целое число (составленное из пяти флагов, определенных в файле DIR.H), указывающее, которые из пяти компонентов присутствовали в пути.
#include <stdlib.h>
#include <stdio.h>
#include <dir.h>
int main(void)
{
char *s;
char drive[MAXDRIVE];
char dir[MAXDIR];
char file[MAXFILE];
char ext[MAXEXT];
int flags;
s= searchpath ("my.txt");
flags=fnsplit(s,drive,dir,file,ext);
printf("Информация о файле:\n");
if(flags & DRIVE)
printf("\tдиск: %s\n",drive);
if(flags & DIRECTORY)
printf("\tдиректория: %s\n",dir);
if(flags & FILENAME)
printf("\tимя файла: %s\n",file);
if(flags & EXTENSION)
printf("\tрасширение: %s\n",ext);
return 0;
}
2 Лабораторные задания
2.1 Переменное число параметров.
Написать функцию, которая организует одновременный вывод форматированного теста в файл и на экран. Прототип функции
int myvprintf(char *fname, char *format, …);
2.2 Многострочный ввод с клавиатуры
Написать программу, которая организует многострочный ввод с клавиатуры в файл. Имя файла передается через командную строку. Окончание ввода по клавише Escape. Возможность редактирования вводимого текста не разрешается.
2.3 Объединение файлов
Написать функцию с несколькими параметрами, которая конкатенирует, то есть объединяет, несколько файлов.
Прототип функции
int concat(char *target, char *source1, …);
Формальные параметры:
target - имя результирующего файла. Если файл не существует, он создается.
source1, … - имена добавляемых файлов.
Возвращает: 0 - в случае успеха,
1, если одного из исходных файлов не существует,
2 , если список исходных файлов отсутствует,
3 в остальных нештатных ситуациях.
2.4 Замена в текстовом файле.
Написать функцию, которая заменяет в текстовом файле одно слово другим. Создать программу, в которой файл, новое слово и старое слово передаются через командную строку.
2.5 Ввод массивов.
Создать двумерный динамический массив А вещественных чисел. Размеры вводятся с клавиатуры. Заполнить случайными вещественными числами из интервала [-4.3; 5.8]. Записать массив А в файл в форматированном режиме и прочитать содержимое этого файла во второй динамический массив В.
Далее, записать массив А во второй файл в неформатированном режиме и прочитать содержимое этого файла в третий динамический массив С. Сравнить на совпадение массивы А, В и С. Сделать вывод.
2.6 Просмотр дисков
Написать программу, которая выводит на экран для каждого существующего диска: имя, общий размер и размер свободной области.
2.7 Структура каталога
Программа выводит на экран структуру каталога. Каталог передается в программу через командную строку. Выводятся имена файлов и их размеры. Для каталогов выводится имя каталога и размер его содержимого. Использовать рекурсивный алгоритм для просмотра каталога.
3 Дополнительные задания
3.1 Морзянка
Вводимый с клавиатуры или из файла текст перевести в последовательность точек и тире с помощью азбуки Морзе. Результат можно иллюстрировать звуком.
Таблица 4.
Азбука Морзе для латиницы и кириллицы.
A,A |
.- |
Б,В |
-… |
B,W |
.-- |
Г,G |
--. |
Д,D |
-.. |
|
Е,Е |
. |
Ж,V |
…- |
З,Z |
--.. |
И,I |
.. |
Й,J |
.--- |
|
К,К |
-.- |
Л,L |
.-.. |
M,M |
-- |
Н,N |
-. |
O,O |
--- |
|
П,Р |
.--. |
Р,R |
.-. |
C,S |
… |
T,T |
- |
У,U |
..- |
|
Ф,F |
..-. |
Х,Н |
…. |
Ц,C |
-.-. |
Ч |
---. |
Ш |
---- |
|
Щ,Q |
--.- |
Ъ |
.--.-. |
Ы,Y |
-.-- |
Ь,Х |
-..- |
Э |
…-… |
|
Ю |
..-- |
Я |
.-.- |
1 |
.---- |
2 |
..--- |
3 |
…-- |
|
4 |
….- |
5 |
….. |
6 |
-…. |
7 |
--… |
8 |
---.. |
|
9 |
----. |
0 |
----- |
. |
.-.-.- |
, |
--..-- |
: |
---… |
|
? |
..--.. |
',' |
.----. |
- |
-….- |
/ |
-..-. |
, |
-.--.- |
3.2 Комментарии в программе
В файле дан исходный текст программы языке программирования Си. Уровнем комментированности текста будем считать отношение объема комментариев к объему всего текста (в байтах). Определить уровень комментированности данной программы.
Библиографический список
1. Керниган Б., Ритчи Д., Фьюэр А. Язык программирования Си: Задачи по языку Си. М.: Финансы и статистика, 1985. - 192с.
2. Керниган Б., Ритчи Д. Язык программирования Си. М.:Финансы и статистика, 1992. - 272с.
3. Подбельский В. В., Фомин С. С. Программирование на языке Си. Учеб.пособие. М.: Финансы и статистика, 2004. 600 с.
Подобные документы
Проверка существования и статуса файла. Определение его размера. Открытие файла для чтения, записи, добавления. Закрытие файловых дескрипторов. Запись из переменной в файл. Загрузка файла из сети. Создание и удаление каталога. Функции работы с каталогами.
презентация [133,9 K], добавлен 21.06.2014Принципы и порядок работы с файлами на языке Delphi, получение навыков программирования с использованием файлов. Создание каталога продуктов. Страница палитры компонентов, настраиваемые компоненты и их значения. Текст программы и ее тестирование.
лабораторная работа [243,9 K], добавлен 09.01.2009Теоретическое изучение и практическое применение приёмов работы с файлами в операционной системе Windows 95. Файлы и папки: основные понятия и правила формирования имен файлов в Windows. Характеристика и анализ особенностей операций с файлами и папками.
контрольная работа [139,9 K], добавлен 09.03.2011Работа с файлами, папками WINDOWS: понятие файла, папки, сохранение, переименование. Вычисление суммы порядковых номеров фамилии и имени. Алгоритм расчета себестоимости. реализация в других программах алгоритма и отчета по нему. Файлы, папки WINDOWS.
контрольная работа [17,9 K], добавлен 05.06.2008Описание типизированных файлов. Принципы работы с файлами, создание и открытие на запись нового файла. Чтение из файла, открытие существующего файла на чтение. Определение имени файла. Запись в текстовый файл. Описание множества и операции над ними.
реферат [86,4 K], добавлен 07.02.2011Специальные клавиши на клавиатуре. Составление шаблонов имен при поиске файлов. Описание и функции объекта "Мой компьютер". Способы выделения группы файлов. Этапы настройки часов. Средства работы с буфером обмена. Основные функции электронной почты.
контрольная работа [578,8 K], добавлен 14.04.2013Работа с файлами, каталогами и томами в Windows и Win32 API. Функции GetWindowsDirectory и GetSystemDirectory. Примеры работы с томами. Получение и изменение атрибутов файлов. Описание минимального набора базовых функций Windows. Чтение и запись файлов.
лекция [62,7 K], добавлен 24.06.2009Работа с файлами на языке Pascal. Типы файлов: типизированные, текстовые, нетипизированные. Сущность процедуры и функции. Использование процедуры Read и Write для операций чтения и записи в типизированном файле. Листинг программы и экранные формы.
лабораторная работа [38,4 K], добавлен 13.02.2009Основные функции Norton Commander и их реализация при работе с каталогами и файлами. Управление дисковой и файловой структурами персонального компьютера. Создание каталога, переход между каталогами, удаление каталога, создание текстового файла.
контрольная работа [20,6 K], добавлен 09.03.2011Использование программы "Total Commander": пользовательский интерфейс, клавиатурные сочетания, операции с файлами, контекстные меню, внутренний просмотр файлов. Назначение и применение функциональных клавиш. Особенности работы с каталогами и файлами.
презентация [462,3 K], добавлен 25.09.2014