Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
20
Добавлен:
17.04.2013
Размер:
32.32 Кб
Скачать

Московский Институт Электронной Техники Московский Институт Электронной Техники

Кафедра ИПОВС

Лабораторная работа

Работа с каталогами файловой системы на языке С++

Цель работы:

изучить возможности работы с каталогами файловой системы;

·получить практические навыки программирования задач с использованием функций работы с каталогами файловой системы.

Теоретические сведения

Язык С++ содержит средства (функции), позволяющие работать не только с файлами, имеющимися на дисках (читать файл, создавать новый файл, изменять содержимое файла и т.д.), но и с каталогами файловой системы.

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

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

#include <dir.h>

#include <dos.h>

Функции поиска файла или каталога на диске findfirst

Прототип функции:

Int findfirst ( char *pathname,

struct ffblk *buffer,

int attrib);

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

Аргумент pathname – это адрес строки, содержащей необязательный спецификатор устройства и полное имя искомого файла (включающего имя пути). Имя файла может содержать регулярное выражение (символы ? или * с тем же значением, что и в командной строке MS-DOS).

Когда заданный файл найден, происходит заполнение структуры, адрес который задается параметром buffer, информацией о каталоге.

Синтаксис структуры ffblk:

Struct ffblk

{

char ff_reserverd[21]; //зарезервировано DOS

char ff_attrib; //найденный атрибут

int ff_ftime; //время создания

int ff_fdate; //дата создания

long ff_fsize; //размер

chat ff_name[13]; // найденное имя

};

Поле ff_fdate содержит дату создания файла или каталога в следующем в виде:

с 0 по 4 бит - число

с 5 по 8 бит - месяц

с 9 по 15 бит год.

Для получения числа даты создания необходимо значения поля ff_fdate побитово умножить на восьмеричное число 37: ff_fdate & 037.

Для получения месяца даты создания необходимо преобразовать данное поле следующим образом: (ff_fdate & 0740) >> 5.

Если требуется узнать год создания файла или каталога, то поле ff_fdate необходимо преобразовать следующим образом: ((ff_fdate & 0177000) > 9)+1980.

Поле ff_ftime содержит время создания файла или каталога в следующем виде:

с 0 по 4 бит - секунды

с 5 по 10 бит - минуты

с 11 по 15 бит часы.

Для получения значения минут времени создания необходимо выполнить операцию: (ff_ftime & 03740) >> 5, а для нахождения значений часа: (ff_ftime & 0174000) >> 11.

Параметр attrib – байт атрибутов файла MS-DOS, используемый при выборе допустимых файлов в поиске.

Параметр attrib может принимать значения:

a _normal -обычный файл (чтение/запись)

fa_rdonly - только чтение

fa_hidden - скрытый файл

fa_system - системный файл

fa_lable - метка тома

fa_direct - каталог

fa_arch - архив.

Поиск производится только в пределах каталога.

Данная функция возвращает значение 0 при успешном поиске и –1, если файл или каталог не найдены.

Функция продолжения поиска файла findnext.

Прототип функции:

Int findnext (struct ffblk *buffer);

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

Функция возвращает значение 0 при успешном поиске и значение –1, если файл не найден.

Пример использования функций findfirst и findnext.

Выведем на экран все файлы с расширением *.срр из текущего каталога.

#include <dir.h>

#include <dos.h>

#include <conio.h>

#include <stdio.h>

void main()

{

clrcsr(); // очистка экрана

ffblk f; // структура ffblk

char *path=new char[20]; // регулярное выражение

strcpy(path, “*.cpp”);

/* поиск первого файла с расширение *.cpp */

int a=findfirst(path, &f, FA_DIRECT);

while(!a) // цикл пока файл не найден

{

puts(f.ffname); // печать имени файла

a=findnext(&f); // продолжить поиск

}

} //конец функции main

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

Строка аргументов.

Как и любая другая функция, написанная на языке С++, функция main может иметь аргументы. Эти аргументы передаются функции main через командную строку. В этом случае функция main должна иметь вид:

Void main ( int argc, char *argv[])

Параметр argc определяет общее количество передаваемых аргументов.

Параметр argv представляет собой массив адресов, каждый элемент которого указывает на строковое представление соответствующего по порядку аргумента, передаваемого программе. Первый элемент массива argv(т.е. argv[0]) всегда содержит имя программы, по которому она была вызвана. Этот элемент всегда заполнен, поэтому значение argc всегда равно, по крайней мере, 1.

Задать значение аргументов командной строки можно либо из MS-DOS, например: D> prim.exe test.txt, где prim.exe имя файла исполняемой программы, а test.txt имя второго аргумента; либо из интегрированной среды Borland 3.1: пункт меню Run, подпункт Arguments.

Пример программирования

Пример 1.

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

Текст программы

#include <dir.h>

#include <dos.h>

#include <conio.h>

#include <stdio.h>

#include <string.h>

void main (int argc, char argv[])

{

struct DIR {

char name[13]; //имя файла

long size; //размер

int data; // дата создания

int time; //время создания

};

struct list{

DIR inf; // информация о файле

list *next; // адрес следующей информации

};

/* описание переменных */

list *Dir=NULL, *pntr, *p, *min;

DIR dir;

Ffblk ff;

Char *path=new char[35];

/* формирование имени файла для поиска */

if (argc == 1) strcpy (path. “*.cpp”);

else {

strcpy(path,”*.”);

strcpy(path,argc[1]);

}

/* поиск файлов и заполнение односвязанного списка информацией о файлах */

int a=findfirst(path, &ff, FA_DIRECT && FA_ARCH);

while(!a)

{ pntr= new list;

if (Dir == NULL) Dir =pntr;

else p->next=pntr;

strcpy(pntr->inf.name, ff.ff_name);

pntr->inf.size=ff.ff_fsize;

pntr->inf.data=ff.ff_fdata;

pntr->inf.time=ff.ff_ftime;

pntr->next=NULL;

p=pntr;

a=findnext(&ff);

}

/* сортировка односвязанного списка по дате создания файлов */

p=Dir;

while(!p=NULL)

{ pntr=p;

min=p;

while(pntr!=NULL)

{ if (pntr->inf.data,min->inf.data) min=pntr;

pntr=pntr->next;

}

dir=min->inf;

min->inf=p->inf;

p->inf=dir;

p=p->next;

}

/* печать односвязанного списка с информацией о файлах */

clrscr();

printf(“ имя файла размер дата\n\n”);

while(Dir!=NULL)

{ printf(“ %-|5s %|d %d\n”, Dir->inf.name,

Dir->inf.size,

((Dir->inf.data&0177000)>>9)+1980);

p=Dir;

Dir=Dir->next;

Delete p;

}

}

Пояснение к программе

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

Структура DIR содержит описание информации о файлах.

Структура List – это описание элемента однсвязанного списка.

Переменные pntr и p – это рабочие переменные, типа указатель на элемент списка.

Переменная min – это адрес элемента с информацией о файле с самой ранней датой создания файла.

Переменная dir – это переменная типа структуры DIR. Через эту переменную происходит обмен информацией.

Сотрировка односвязанного списка происходит следующим образом. Просматриваем элементы списка от начала до конца. Весь список будет разделен на две части: отсортированную и неотсортированную. Определяем адрес элемента с ранней датой создания (min), как первый элемент в неотсортированной части. Указатель p – это адрес первого несортированного элемента списка. В неотсортированной части ищем элемент с ранней датой создания файла (внутренний цикл) и информацию найденного элемента записываем по адресу переменной p, а информацию по адресу p записываем на место найденного элемента min (обмен через переменную dir).

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

Пример 2.

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

Текст программы

#include <dir.h>

#include <dos.h>

#include <conio.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

void main (int argc, char argv[])

{

struct DIR {

char name[13]; //имя файла

long size; //размер

int data; // дата создания

int time; //время создания

};

struct list{

DIR inf; // информация о файле

list *next; // адрес следующей информации

};

/* описание переменных */

list *Dir=NULL, *pntr, *p, *min;

DIR dir;

Int god=2001;

Ffblk ff;

Char path[]=”c:\\dos\\*.*”;

/* формирование года */

if (argc>1) god=atoi((argv[1]);

god = 1980;

/* поиск файлов с формированием односвязанного списка */

int a=findfirst(path, &ff, FA_DIRECT && FA_ARCH);

while(!a)

{ int year=((ff.ff_fdate & 0177000)>>9);

if (year = = god)

{ pntr= new list;

if (Dir == NULL) Dir =pntr;

else p->next=pntr;

strcpy(pntr->inf.name, ff.ff_name);

pntr->inf.size=ff.ff_fsize;

pntr->inf.data=ff.ff_fdata;

pntr->inf.time=ff.ff_ftime;

pntr->next=NULL;

p=pntr;

}

a=findnext(&ff);

}

/* сортировка односвязанного списка в алфавитном порядке имен */

p=Dir;

while(!p=NULL)

{ pntr=p;

min=p;

while(pntr!=NULL)

{ if (strcmp(pntr->inf.name,min->inf.name)<0) min=pntr;

pntr=pntr->next;

}

dir=min->inf;

min->inf=p->inf;

p->inf=dir;

p=p->next;

}

}

/* вывод односвязанного списка с информацией о файлах */

clrscr();

while(Dir!=NULL)

{ printf(“ %-|5s %|d %d %d %d\n”, Dir->inf.name,

Dir->inf.size,

Dir->inf.data & 037;

(Dir->inf data & 0740)>>5;

((Dir->inf.data&0177000)>>9)+1980);

p=Dir;

Dir=Dir->next;

Delete p;

}

}

Пояснение к программе

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

Структура DIR содержит описание информации о файлах.

Структура List – это описание элемента однсвязанного списка.

Переменные pntr и p – это рабочие переменные, типа указатель на элемент списка.

Переменная min – это адрес элемента с информацией о файле, имя которого необходимо расположить в самом начале списка..

Переменная dir – это переменная типа структуры DIR. Через эту переменную происходит обмен информацией.

Сотрировка односвязанного списка происходит следующим образом. Просматриваем последовательно все элементы списка. Список разбиваем на две части: отсортированную и неотсортированную. Определяем адрес элемента с ранней датой создания (min), как первый элемент в неотсортированной части.

Указатель p – это адрес первого несортированного элемента списка. В неотсортированной части ищем элемент, удовлетворяющий условию сортировки ( функция strcmp) и информацию найденного элемента записываем по адресу переменной p,а информацию по адресу p записываем на место найденного элемента min (обмен через переменную dir).

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

Контрольные вопросы

Какие файлы содержат прототипы функций работы с каталогами?

Каково назначение функции findfirst?

Какая функция продолжает поиск файлов, заданных в функции findfirst?

Какие аргументы может использовать функция main?

Каково минимальное количество аргументов передаваемых программе?

Лабораторное задание

Напишите программу в соответствии с вариантом задания. При написании используйте функции управления экраном.

Порядок выполнения лабораторной работы

При домашней подготовке составьте текст программы, соответствующий Вашему варианту задания.

На лабораторной работе отладьте и выполните программу с аргументами и без аргументов.

Результаты работы покажите преподавателю.

Защитите лабораторную работу.

Требования к отчету

Отчет должен содержать:

Краткие теоретические сведения.

Лабораторное задание.

Программу, соответствующую Вашему номеру варианта.

Результаты выполнения программы.

Приложение

Основные функции работы с каталогами файловой системы

Подключаемый файл dir.h

int chdir (char *pathname);

изменяет текущий каталог в соответствии с pathname. Pathname должен указывать на существующий каталог. Не позволяет изменить имя устройства. Возвращяемое значение: 0 – успех, 1 – ошибка.

char* getcwd(char *buf, int b);

читает полное имя текущего рабочего каталога (включая имя устройства) длины не более n символов, сохраняя его в buf. Возращаемое значение: адрес buf, или NULL вс случае ошибки.

void fnmerge ( char *path,

char *drive,

char *dir,

char *name,

char *ext);

создает полное имя файла из отдельных компонент:

drive - устройство, например C:

dir - путь каталога, например \DOS\BGI\

name - имя, например egavga

ext - расширение, например .bgi

path - содержит адрес буфера, в котором достаточно места, для полного имени файла.

int fnsplit( char *path,

char *drive,

char *dir,

char *name,

char *ext);

разбивает полное имя файла, заданное в path, на четыре компоненты (см. Функцию fnmerge)

int getcurdir ( int drive, char *direc);

читает имя текущего рабочего каталога на указанном параметре drive устройстве. Значение drive равное 0 соответствует устройству “А”, 1 – “В”, 2 – “С” и т.д. Имя каталога записывается в direc. Возвращаемое значение: 0 – успех, –1 – ошибка.

int getdisk (void);

возвращает номер текущего диска. 0 – диск А, 1 – диск В, 2 – диск С и т.д.

int setdisk(int drive);

устанавливает устройство drive. Возвращаемое значение – общие число дисков, имеющихся в наличии.

Варианты заданий

1, 11, 21 Вывести на экран текущего каталога информацию о файлах, с указанным расширением, в порядке уменьшения их размера. Расширение задать в строке аргументов. Если расширение не задано, то использовать расширение TXT. 2, 12, 22 Вывести на экран информацию о файлах, с одинаковыми именами, подсчитать количество таких файлов. Имя каталога задать в строке аргументов. Если имя не каталога отсутствует, выбрать текущий каталог. 3, 13, 23 Отсортировать имена файлов из каталога по дате создания файлов. Имя каталога задать в строке аргументов. Если имя не каталога отсутствует, выбрать текущий каталог. 4, 14, 24 Отсортировать имена файлов из каталога в алфавитном порядке. Имя каталога задать в строке аргументов. Если имя не каталога отсутствует, выбрать текущий каталог. 5, 15, 25 Вывести на экран из текущего каталога информацию о файлах, созданных в указанном месяце, по мере их создания. Месяц задать в строке аргументов. Если месяц не задан, то использовать текущий месяц. 6, 16, 26 Вывести на экран с диска информацию о файлах, чьи имена совпадают с a, ab, adc, и т.д. Имя диска задать в строке аргументов. Если имя диска отсутствует, то выбрать текущее устройство. 7, 17, 27 Отсортировать имена файлов из каталога в порядке увеличения размеров файлов. Имя каталога задать в строке аргументов. Если имя не каталога отсутствует, выбрать текущий каталог 8, 18, 28 Отсортировать имена файлов из каталога в порядке увеличения числа букв в имени. Имя каталога задать в строке аргументов. Если имя не каталога отсутствует, выбрать текущий каталог 9, 19, 29 Отсортировать имена имена файлов из каталога в алфавитном порядке их расширений. Имя каталога задать в строке аргументов. Если имя не каталога отсутствует, выбрать текущий каталог. 10, 20, 30 Отсортировать файлы, созданные не позднее числа Р, в алфавитном порядке Число Р задать в строке аргументов. Если число Р не задано, то выбрать текущее число.

Соседние файлы в папке C_files