Лекция 2 (13.09.2021)


Файловый ввод/вывод.

Файл — последовательность данных, имеющая имя.


Работа с файлом: (ограниченный ресурс — таблица дескрипторов файлов) (дескриптор — англ. Describe – описывать, в дескрипторе находится информация о том, в каком состоянии находится в файл)

1. Начать работу с файлом <вх: имя файла, тип работы с файлом — на чтение или на запись, вых: успех/неуспех, указатель на дескриптор файла> (открыть файл)

2. Читать из файла <вх: указатель на дескриптор файла>. Указатель на данные продвигается при этом вперед. В начале работы указатель находится в начале файлы.

3. Писать в файл (в конец файла) <вх: указатель на дескриптор файла>. Указатель сдвигается на положение после записанных данных.

4. Закончить работу с файлом (закрыть файл)


Работа с файлами на языке C:


1. fopen(“tmp.dat”, “r”) - начать работу с файлом “tmp.dat”, читать (Read)

fopen(“tmp.res”, “w”) - начать работу с файлом «tmp.res”, писать (Write)

Проверка результат открытия файла:

а) Почему файл может не открыться? Его нет, ошибка на диске, кто-то его уже захватил на запись, …

б) Как проверить, успешно ли файл открылся?

#include <stdio.h>

int main(void) {

FILE *IN; /* FILE - не базовый тип, введен в библиотеке ввода/вывода */

IN = fopen("tmp.dat", "r");

if (IN == NULL) {

printf("File not opened\n");

return -1;

}

...

}


IN – это имя переменной, которой присваивается указатель на дескриптор файла


Операторы в C: +, -, *, /, % (остаток от деления), == (проверка равенства — выражение A==B истинно, если A равно B), != (проверка неравенства), > (больше), < (меньше), >= (больше или равно), <= (меньше или равно), ! (отрицание: !A истинно <=> А ложно), && (логическое И: A&&B истинно <=> A истинно и B истинно), || (логическое ИЛИ: A||B истинно <=> A истинно или B истинно)


2. Чтение данных:

int x, y;

fscanf(IN, “%d%d”, &x, &y);


Проверка результата:


1) Почему надо проверять? Данные могли не прочитаться по следующим причинам:

a) нет данных;

б) недостаточно данных

в) данные в файле есть, но они не в том формате (например, хотели прочитать числа, а в файле лежат не числа, а, например, слова или какие-то символы)


Как проверить, что данные успешно прочитались?


!!!ФУНКЦИЯ FSCANF ВОЗВРАЩАЕТ КОЛИЧЕСТВО ПРОЧИТАННЫХ ОБЪЕКТОВ!!!


int main(void) {

int n, m, res;

...

res = fscanf(IN, "%d%d", &n, &m);

if (res != 2) {

printf("Not enough data in the file\n");

fclose(IN);

return -1;

}

return 0;

}


Другие способы проверить, прочитались ли данные (функция feof(), сравнение res c -1) – работают не всегда.


3. Запись данных:


FILE *OUT;

OUT = fopen(“tmp.res”, “w”);

if (OUT == NULL) {

printf(“File not opened\n”);

return -1;

}

fprintf(OUT, “Result: %d\n”, res);


4. Закрыть файл:


fclose(IN);

fclose(OUT); /* Записываемая информация не сохранится, если файл не закрыть */



Задача 1. Найти сумму целых чисел в файле "tmp.dat" и вывести на экран


#include <stdio.h>


int main(void) {

FILE *IN;

int sum = 0, n;


IN = fopen("tmp.dat", "r");

if (IN == NULL) {

printf("File not opened\n");

return -1;

}


while (fscanf(IN, "%d", &n) == 1) {

sum += n;

}


fclose(IN);

printf("Summa: %d\n", sum);

return 0;

}


Программа должна правильно работать для правильных входных данных и не ломаться (не «падать») для неправильных входных данных.



Задача 2. Переписать из файла tmp.dat в файл tmp.res все положительные числа (в tmp.dat – целые числа)


#include <stdio.h>

int main(void) {

FILE *IN, *OUT;

int sum = 0, n;


IN = fopen("tmp.dat", "r");

if (IN == NULL) {

printf("File not opened\n");

return -1;

}


OUT = fopen("tmp.res", "w");

if (OUT == NULL) {

fclose(IN);

printf("File not opened\n");

return -1;

}


while (fscanf(IN, "%d", &n) == 1) {

if (n > 0) {

fprintf(OUT, "%d\n", n);

}

}


fclose(IN);

fclose(OUT);

return 0;

}



В 1 семестре задачи:


1) Задачи на последовательности. Дан файл с данными в неизвестном количестве. Получить выходной файл или какую-то характеристику данных

2) Задачи на массивы (вектор, таблица, …) - array


Как мы работаем с последовательностями?

Задачи: обработать файл за одно прочтение файла. Например, найти сумму чисел.


ИНДУКТИВНЫЕ ФУНКЦИИ


Пусть xi принадлежат множеству X

Последовательности x1, x2, ..., xn - принадлежат множеству Z (множество последовательностей)


f: Z -> Y


Y – множество неких значений для последовательности


Определение. Функция f называется индуктивной, если при добавлении элемента к последовательности можно вычислить значение f на новой последовательности, зная значение f на старой последовательности и зная добавленный элемент.


То есть существует функция g(Y, X) такая, что

f(x1, x2, ..., xn) = g(f(x1, x2, ..., xn-1), xn)


Иначе: Например: пусть f(z) – сумма чисел в последовательности z = (x1x2...xn)

f(z xn+1) - ?

Для суммы f(z xn+1) = f(z) + xn+1


Вопрос 1. В задаче 1 (сумма чисел в файле) функция “сумма” индуктивна?

Ответ. Да, так как существует функция g: g(y, x) = y + x, то есть

при добавлении в последовательность нового числа сумма новой последовательности вычисляется значение f() для новой последовательности



Примеры индуктивных функций: сумма чисел в последовательности

Примеры неиндуктивных функций:


Задача 3. Найти максимальный элемент последовательности


Вопрос 2. Функция "количество максимальных элементов последовательности" индуктивна?


Примеры последовательностей:


1) 1 2 3 4 5 4 3 2 1 - количество максимальных элементов == 1

2) 4 4 4 - количество максимальных элементов == 3


Добавим число 4 к обеим последовательностям


1) y==1, x==4

2) y==3, x==4


Чему равна функция f на новых последовательностях?


1) 1

2) 4 (так как в новой последовательности 4 4 4 4 — 4 максимальных элемента)


Этот ответ невозможно получить только из значений f на старой последовательности и значения добавленного элемента


Ответ на вопрос 2. Функция не индуктивна


Определение. Индуктивным расширением функции f называется функция h(Z)

h: Z -> (Y, W)

такая, что h индуктивна и f(x) = p(h(x))

где p(y, w) = y


Пример h(x) – (количество максимальных и значение максимального)


1) y==1, h = (1, 5), x==4 => f == 1

2) y==3, h = (3, 4), x==4 => f == 4


Задача 4. Найти количество максимальных элементов последовательности


Решение.

Функция «количество максимальных элементов последовательности» не индуктивная.

Индуктивное расширение — функция « количество максимальных элементов последовательности и значение максимального элемента»


/* задача 4 */

#include <stdio.h>


int main(void) {

FILE *IN;

int maks, nmaks = 0, n;


IN = fopen("tmp.dat", "r");

if (IN == NULL) {

printf("File not opened\n");

return -1;

}


if (fscanf(IN, "%d", &maks) != 1) {

printf("Empty\n");

fclose(IN);

return -1;

}

nmaks = 1;


while (fscanf(IN, "%d", &n) == 1) {

if (n > maks) {

maks = n;

nmaks = 1;

} else if (n == maks) {

++nmaks;

}

}


fclose(IN);

printf("Number of max: %d\n", nmaks);

return 0;

}


Пример:

В последовательности — 1 число, например, 17.

Сколько максимальных чисел в последовательности? 1


17, 18 → nmaks = 1, maks = 18


Работа программы 4 по шагам:

Прочитанное число

maks

nmaks

17

17

1

18

18

1

25

25

1

25

25

2

25

25

3

26

26

1

26

26

2

26

26

3

15

26

3


Результат для последовательности (17, 18, 25, 25, 25, 26, 26, 26, 15): 3



Литература:


А.Г.Кушниренко, Г.В.Лебедев «Программирование для математиков»