Лекция 2 Файловый ввод/вывод #include - описание функций библиотеки ввода/вывода Функции перед вызовом должны быть описаны, чтобы компилятор мог правильно их обработать Файл - данные, у которых есть имя. Процесс работы с файлом: 1. Начать работу с файлом (открыть файл). Входные данные: имя файла (возможно, содержит путь к этому файлу). Выходные данные - указатель на дескриптор файла. 2. Читать из файла. При этом указатель двигается вперед, указывает на непрочитанные данные. 3. Писать в файл. Указатель сдвигается вперед и указывает на конец записанных данных 4. Закончить работу с файлом (закрыть файл). Без вызова этой функции записанная информация не сохранится на диск, переполняться таблица дескрипторов файлов. На языке Си: 1. fopen("tmp.dat", "r"); fopen("tmp.res", "w"); /* "r", "w" - тип работы с файлом: чтение (r) или запись (w) */ Проверка результата открытия файла: a) Почему файл может не открыться? Его может не существовать, ошибка на диске, ... b) Как проверить, что файл успешно открылся? Проверить результат функции fopen() FILE *IN; /* FILE - не базовый тип, введен в библиотеке ввода/вывода */ IN = fopen("tmp.dat", "r"); if (IN == NULL) { printf("File not opened\n"); return -1; } 2. fscanf(IN, "%d%d", &n, &m); Проверка результата чтения файла" a) Почему данные могут не прочитаться? Файл пуст, данные не в том формате (в файле буквы, а не числа), ... b) Почему надо проверять, прочитались ли данные? Потому что если данные не прочитались, то значения переменных - непредсказуемы с) Как проверить, что данные успешно прочитались? Проверить результат функции fscanf() int n, m, res; ... res = fscanf(IN, "%d%d", &n, &m); if (res != 2) { printf("Not enough data in the file\n"); return -1; } !!!ФУНКЦИЯ FSCANF ВОЗВРАЩАЕТ КОЛИЧЕСТВО ПРОЧИТАННЫХ ОБХЕКТОВ!!! 3. fprintf(IN, "Result: %d\n", res); 4. fclose(IN); Задача 1. Найти сумму целых чисел в файле "tmp.dat" и вывести на экран #include 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 все положительные числа #include 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) { 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) Задачи на массивы (вектор, таблица, ...) Последовательности. При чтении нового числа перевычислять текущий результат. По окончании чтения файла результат будет известен сразу. ИНДУКТИВНЫЕ ФУНКЦИИ xi принадлежат множеству X Последовательности x1, x2, ..., xn - принадлежат множеству Z f: Z -> Y Определение. Функция f называется индуктивной, если при добавлении элемента к последовательности можно вычислить значение f на новой последовательности, зная значение f на старой последовательности и зная добавленный элемент. То есть существует функция g(Y, X) такая, что f(x1, x2, ..., xn) = g(f(x1, x2, ..., xn-1), xn) Вопрос 1. В задаче 1 (сумма чисел в файле) функция сумма индуктивна? Ответ. Да, так как существует функция g: g(y, x) = y + x, то есть при добавлении в последовательность нового числа сумма новой последовательности вычисляется Задача 3. Найти максимальный элемент последовательности Вопрос. Функция "максимальный элемент последовательности" индуктивна? Ответ. Да, g существует: g(y, x) = max(y, x) Задача 4. Найти количество максимальных элементов последовательности Вопрос 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 Этот ответ невозможно получить только из значений f на старой последовательноти и значения добавленного элемента Ответ 2. Функция не индуктивна Определение. Индуктивным расширением функции f называется функция h(Z) h: Z -> (Y, W) такая, что h индуктивна и f(x) = p(h(x)) где p(y, w) = y Индуктивное расширение функции "количество максимальных элементов последовательности": "количество максимальных элементов последовательности" + "значение максимального элемента" 1) 1 2 3 4 5 4 3 2 1 - h(x) == (1, 5) 2) 4 4 4 - h(x) == (3, 4) /* задача 4 */ #include 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"); 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; }