Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тема9_Файлы.doc
Скачиваний:
2
Добавлен:
09.08.2019
Размер:
146.43 Кб
Скачать

Произвольный доступ к файлу

Файл предназначен для последовательного доступа к нему, другими словами, для обращения к определенному символу этого файла нужно прочитать все символы, расположенные перед ним. Однако существует функция fseek(), которая имитирует произвольный доступ. Эта функция перемещает файловый указатель на заданное количество позиций, производя отсчет от начала файла, от текущей позиции или от конца файла. Функция fseek() именно имитирует произвольный доступ, а не осуществляет его, поскольку для перемещения указателя на требуемую позицию эта функция передвигает его шаг за шагом, а не обращается к символу напрямую, как это происходит при работе с массивом.

Рассмотрим работу функции fseek() на примере файла со следующим содержимым:

.

fseek(myFile, 0, SEEK_SET);

putchar(fgetc(myFile));

fseek(myFile, -1, SEEK_END);

putchar(fgetc(myFile));

fseek(myFile, 20, SEEK_SET);

putchar(fgetc(myFile));

fseek(myFile, -20, SEEK_END);

putchar(fgetc(myFile));

fseek(myFile, 32, SEEK_SET);

putchar(fgetc(myFile));

fseek(myFile, -33, SEEK_END);

putchar(fgetc(myFile));

Константа

SEEK_SET

SEEK_CUR

SEEK_END

Позиция

Начало файла

Текущая позиция

Конец файла

Еще одна полезная функция, относящаяся к произвольному доступу, – это функция ftell(), которая возвращает номер текущей позиции, производя отсчет от начала файла.

Вывод файла в обратном порядке

FILE* inFile = fopen("main.cpp", "rb");

//Помещаем указатель в конец файла

fseek(inFile, 0, SEEK_END);

//Узнаем номер последней позиции

//Он равен размеру файла

unsigned int size = ftell(inFile);

for (int i=0; i<size; i++) {

fseek(inFile, -(i+1), SEEK_END);

//Считываем и записываем символ

putchar(fgetc(inFile));

}

fclose(inFile);

Пример нисходящей разработки

Пример 1. Написать программу, которая переписывает содержимое одного файла в другой, дублируя все английские гласные буквы.

Разработаем алгоритм решения данной задачи. Начнем с высокоуровневых шагов:

  1. открыть исходный файл для чтения;

  2. открыть другой файл для записи;

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

  4. закрыть оба файла.

Поскольку переписывать нужно все символы, то файлы следует открывать в бинарном режиме. Все шаги кроме третьего в данном алгоритме очевидны. Третий же шаг логично оформить в виде отдельной функции, куда в качестве аргументов передать файловые переменные, соответствующие открытым файлам. Программа примет следующий вид:

int main() {

FILE* inFile = fopen("main.cpp", "rb");

FILE* outFile = fopen("result.cpp", "wb");

dublicatVowels(inFile, outFile);

fclose(inFile);

fclose(outFile);

return 0;

}

Функция dublicatVowels() пока не определена, поэтому для тестовых целей, чтобы данная программа запустилась, можно поставить так называемую заглушку для этой функции. Заглушка ничего относящегося к задаче делать не будет, а просто выведет сообщение о том, что там должно быть:

void dublicateVowels(FILE* in, FILE* out) {

printf("Здесь будет дублирование гласных");

}

После запуска программы мы убеждаемся в том, что в нашей программе готово все кроме функции dublicatVowels(). Займемся этой функцией, в которой необходимо пробежаться по всему файлу и выполнить следующие шаги:

  1. считать очередной символ из файла in;

  2. записать этот символ в файл out;

  3. если этот символ является английской гласной буквой, то записать его в файл out еще раз.

В данном алгоритме тривиальными являются все действия кроме проверки буквы на третьем шаге. Эта проверка должна ответить «Да» или «Нет» в зависимости от значения символа. Таким образом, эту проверку разумно вынести в отдельную функцию, которая будет принимать в качестве аргумента проверяемый символ, а возвращать значение логического типа true или false в зависимости от результата проверки. В итоге функция dublicateVowels() примет следующий вид:

void dublicateVowels(FILE* in, FILE* out) {

while (!feof(in)) {

char symbol = fgetc(in);

fputc(symbol, out);

if (isEngVowel(symbol)) {

fputc(symbol, out);

}

}

}

В этой функции теперь неопределенна функция isEngVowel(), поэтому для нее можно поставить заглушку, возвращающую true всегда.

bool isEngVowel(char symbol) {

return true;

}

Очевидно, что теперь программа запустится, но будет дублировать все символы. Тем не менее, круг нашей разработки уже существенно сузился, поскольку осталось реализовать только функцию isEngVowel(). Разработаем ее алгоритм:

  1. создать строку с английскими гласными буквами;

  2. пробежаться в цикле по этой строке, возвращая true, если очередной символ равен аргументу функции;

  3. по окончании цикла, другими словами, если цикл не возвратил true, по ходу работы, то возвратить false.

В этом алгоритме уже все понятно, поэтому можно ее реализовать полностью.

bool isEngVowel(char symbol) {

char engVows[] = "aeiouyAEIOUY";

for (int i=0; i<strlen(engVows); i++) {

if (symbol==engVows[i]) {

return true;

}

}

return false;

}