А.А. Белеванцев, С.С. Гайсарян, Л.С. Корухова, Е.А. Кузьменкова, В.С. Махнычев. Семинары по курсу Алгоритмы и алгоритмические языки (1108027), страница 11
Текст из файла (страница 11)
Задачи для самостоятельного решения8.3.1. Описать заданное понятие в виде структуры. Описать также переменную этоготипа и присвоить ей указанное значение:а) дата (число, месяц, год); 16 ноября 1999 года;б) адрес (страна, город, улица, дом, квартира); Россия, Москва, Ильинка, дом 3,кв. 34;в) треугольник (две стороны и угол между ними); 5, 6.7, 35°;8.3.2. Пусть «целочисленная» окружность на плоскости описана следующим образом:struct point { int x; int y; };struct circle { int radius; struct point center; };Пусть есть массив, содержащий информацию об окружностях на плоскости:struct circle plane[30];Описать функцию, определяющую:а) есть ли среди этих окружностей хотя бы две концентрические окружности;б) есть ли среди этих окружностей хотя бы две вложенные (не обязательноконцентрические) окружности;49в) есть ли среди этих окружностей хотя бы одна «уединенная», то есть не имеющаяобщих точек ни с какой другой окружностью массива plane.8.3.3.
Описать структурный тип для представления даты (день, месяц, год). Используяэтот тип, описать функцию, принимающую на вход массив дат и упорядочивающуюего по неубыванию.8.3.4. Описать структуру для представления информации о человеке: фамилия (неболее 30 символов), имя (не более 30 символов), возраст. Описать функцию, котораядля заданного массива из описанных структур определяет:а) возраст самого старшего человека;б) количество людей с заданным именем (имя также является параметромфункции);в) количество людей, у которых есть однофамильцы;г) фамилию человека, чей возраст ближе всего к среднему возрасту всех людей измассива (можно считать, что такой человек один).8.3.5. Даны описания:enum { circle = 0, triangle = 1, rectangle = 2};// тип фигуры на плоскостиstruct circle_info { double r; };// информация об окружности: r – радиусstruct triangle_info { double a, b, c; };// треугольник со сторонами a, b, cstruct rectangle_info { double w, h; };/* прямоугольник: w – ширина,h – высота */struct shape {// описание одной фигуры на плоскостиint kind; // 0, 1 или 2union {struct circle_info ci;struct triangle_info ti;struct rectangle_info ri;} info;};struct shape plane[50];// массив, описывающий все фигуры на плоскостиОписать функцию, которая для массива plane вычисляет:а) количество окружностей на плоскости;б) суммарный периметр всех фигур;в) наибольшую площадь одной фигуры.8.3.6.
Используя описания из предыдущей задачи, описать функцию, котораязаполняет массив plane следующим образом: первые 10 элементов – окружности сцелочисленными радиусами от 1 до 10 (радиус окружности равен ее порядковомуномеру); следующие 20 элементов – равнобедренные треугольники, основания50которых – целые числа от 1 до 20, а боковые стороны вдвое больше основания;последние 20 элементов – квадраты, стороны которых – целые числа от 1 до 20.9. ФайлыС точки зрения программы файл представляет собой произвольнуюпоследовательность данных.
Содержимое файла может быть интерпретировано какпоследовательность символов (текстовые файлы) или как двоичные данные (бинарныефайлы).Типы и функции для работы с файлами описаны в заголовочном файле stdio.h.9.1. Открытие и закрытие файлаДля открытия файла используется функция fopen:FILE *fopen(const char *filename, const char *mode);Эта функция инициализирует работу с файлом и создает структуру со служебнойинформацией типа FILE. Точный состав этой структуры может зависеть от операционнойсистемы. Функция возвращает указатель на эту структуру, который используется вдальнейшем для всех операций с файлом.Функции передаются два параметра: параметр filename – имя открываемогофайла, параметр mode – строка, определяющая режим работы с файлом.
Допустимыезначения режимов: "r" – существующий текстовый файл открывается для чтения; "w" – создается новый текстовый файл и открывается на запись. Если файл с такимименем существовал ранее, то его содержимое удаляется; "a" – текстовый файл открывается для записи в конец файла (его "старое"содержимое сохраняется) или создается; "r+" – существующий текстовый файл открывается для чтения и записи, текущаяпозиция (место в файле, по которому происходит чтение или запись)устанавливается в начало файла; "w+" – текстовый файл открывается или создается для чтения и записи, текущаяпозиция устанавливается в начало файла.
Если файл с таким именем существовалранее, то его содержимое удаляется; "а+" – текстовый файл открывается для чтения и записи, текущая позицияустанавливается в конец файла. Если файл не существовал, то он создается.Для открытия файла в бинарном режиме к значению параметра modeприписывается буква b, например, "rb" означает открытие существующего бинарногофайла на чтение, а "a+b" (или "ab+") – открытие бинарного файла для чтения и записис позиционированием в конец файла.Отличие текстового режима от бинарного в том, что в текстовом режиме некоторыепоследовательности символов могут интерпретироваться особым образом. Наборспециальных последовательностей и их интерпретация зависят от операционной системы.51Так, например, на операционной системе Windows перевод строки в текстовых файлахзаписывается как последовательность из двух символов: символ с кодом 13 и символ скодом 10.
В случае открытия файла как текстового, данная последовательность будетпроинтерпретирована как один символ '\n', и именно в таком виде будет прочитанафункциями стандартной библиотеки. В случае же открытия файла как бинарного, онабудет воспринята как последовательность из двух байт со значениями 13 и 10.В случае успешного открытия файла функция fopen возвращает указатель напеременную типа FILE.
В случае ошибки функция возвращает значение NULL.После окончания работы с файлом необходимо убедиться, что все записанныеданные попали на диск, и освободить все ресурсы, связанные с ним. Для этогоиспользуется функция закрытия файла fclose:int fclose(FILE *stream);Функция производит дозапись еще не записанных данных в файл и освобождаетвсе ресурсы, связанные с открытым файлом. В случае успешного закрытия файла функциявозвращает нулевое значение, в случае ошибки – значение EOF (константа EOF такжеописана в stdio.h и является отрицательным целым числом).9.2.
Стандартные потоки ввода-выводаСтандартный поток ввода (обычно – ввод с клавиатуры) и стандартный потоквывода (обычно – вывод на экран) с точки зрения программы также являются файлами.Для доступа к ним можно использовать описанные в stdio.h переменные stdin иstdout соответственно; например, вызов printf ("Hello\n") эквивалентен вызовуfprintf (stdout, "Hello\n"). В отличие от обычных файлов, к стандартнымпотокам нельзя применять операции позиционирования, а только последовательногочтения или записи.Третьим стандартным потоком является stderr – стандартный поток длясообщений об ошибках и диагностических сообщений.
Стандартный поток stderr такжеобычно ассоциируется с экраном и не буферизуется, сообщения, выведенные в него, сразупоявляются на экране. Отдельный поток для сообщений об ошибках выделяется для того,чтобы можно было разделить нормальный вывод программы и диагностическиесообщения. Вывод сообщения в поток stderr производится с помощью вызова функциизаписи в файл с указанием stderr как имени файла:fprintf (stderr, "Ошибка выделения памяти"\n); .9.3. Чтение из файла и запись в файлЧтение и запись выполняются в текущей позиции файла.
После чтения (илизаписи) текущая позиция сдвигается к концу файла на количество считанных (илизаписанных) символов. Чтение и запись являются буферизованными, т.е., например,окончание работы функции записи не означает немедленной модификации содержимогофайла на диске: результаты записи могут быть отражены во внутреннем буфере52библиотеки работы с файлами, которые будут сброшены при закрытии файла или привызове функции fflush.Для функций форматного ввода-вывода printf и scanf существуют аналоги приработе с файлами: fprintf и fscanf:int fprintf(FILE *stream, const char *format, ...);int fscanf(FILE *stream, const char *format, ...);Использование этих функций – такое же, как и функций printf и scanf, но вкачестве первого параметра указывается файл, с которым ведется работа.
Функцияfprintf возвращает количество записанных символов, функция fscanf – количествоуспешно прочитанных значений (или EOF в случае конца файла или ошибки чтения).Посимвольное чтение осуществляется функцией fgetc:int fgetc(FILE *stream);Функция возвращает очередной символ из файла в виде unsigned char,преобразованного к int, или значение EOF, если файл исчерпан или обнаружена ошибка.Для посимвольного вывода служит функция fputc:int fputc(int c, FILE *stream);Функция записывает символ c, преобразованный к типу unsigned char, вуказанный файл и возвращает значение записанного символа (или значение EOF в случаеошибки).Чтение из файла строки (под строкой файла понимают последовательностьсимволов, оканчивающуюся символом конца строки, '\n') осуществляется функциейfgets:char *fgets(char *s, int size, FILE *stream);Функция читает в массив s не более (size-1) символов, прекращая чтение, есливстретился символ конца строки (он при этом также заносится в s) или конец файла.
Запрочитанными символами в массиве записывается символ '\0'. Функция возвращает s вслучае успешного завершения, или NULL – в случае ошибки, а также если файл оказалсяисчерпан до того, как был прочитан хотя бы один символ.Функция fgets не имеет своего аналога для работы со стандартными потокамиввода-вывода, так как аналогичная функция gets не принимает параметра size ипродолжает чтение до тех пор, пока есть данные, невзирая на границы массива, в которыйпроизводится чтение. Поэтому организовать безопасное чтение строк с проверкой ихразмера невозможно с помощью функции gets, и необходимо использовать функциюfgets из файла sdtin вместо нее.Запись строки в файл выполняется при помощи функции fputs:int fputs(const char *s, FILE *stream);Функция записывает в файл все символы строки s (терминальный '\0' в файл непишется).
В случае ошибки функция возвращает EOF, в противном случае –неотрицательное число. Действие функции эквивалентно вызову:fprintf (stream, "%s", s);Пример 1. Дан текстовый файл input.txt, содержащий целые числа. Требуетсянапечатать сумму всех чисел в нем.53FILE *f;int sum = 0, n;f = fopen("input.txt", "r");while (fscanf (f, "%d", &n) == 1)sum += n;fclose (f);printf (”%d\n”, sum);9.4.