Если название структурного типа введено с помощью typedef, то при определении указателей название этого типа может использоваться без предшествующего служебного слова struct

При определении указателя на структуру он может быть инициализирован.

Объединения

Объединение подобно структуре, однако в каждый момент времени может использоваться только один из элементов объединения. Тип объединения может задаваться в следующем виде:

union { описание элемента 1; ... описание элемента n; };

Главной особенностью объединения является то, что для каждого из объявленных элементов выделяется одна и та же область памяти, т.е. они перекрываются. Хотя доступ к этой области памяти возможен с использованием любого из элементов, элемент для этой цели должен выбираться так, чтобы полученный результат не был бессмысленным.

Доступ к элементам объединения осуществляется тем же способом, что и к структурам. Идентификатор объединения может быть формализован точно так же, как и идентификатор структуры.

Объединение применяется для следующих целей:

- инициализации используемого объекта памяти, если в каждый момент времени только один объект из многих является активным;

- интерпретации основного представления объекта одного типа, как если бы этому объекту был присвоен другой тип.

Память, которая соответствует переменной типа объединения, определяется величиной, необходимой для размещения наиболее длинного элемента объединения. Когда используется элемент меньшей длины, то переменная типа объединения может содержать неиспользуемую память. Все элементы объединения хранятся в одной и той же области памяти, начиная с одного адреса.

Пример:

union { char fio[30]; char adres[80]; int vozrast; int telephone; } inform; union { int ax; char al[2]; }ua;

При использовании объекта inform типа union можно обрабатывать только тот элемент который получил значение, т.е. после присвоения значения элементу inform.fio, не имеет смысла обращаться к другим элементам. Объединение ua позволяет получить отдельный доступ к младшему ua.al[0] и к старшему ua.al[1] байтам двухбайтного числа ua.ax .

Битовые поля

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

struct { unsigned идентификатор1 : длина-поля 1; unsigned идентификатор2 : длина-поля 2; }

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

Пример:

struct { unsigned a1: 1; unsigned a2: 2; unsigned a3: 5; unsigned a4: 2; } prim;

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

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

Вопросы:

1.Понятие структурного типа.

2.Структурные типы, поддерживаемые стандартом языка С.

3.Инициализация структур.

4.Присваивание и сравнение структур.

5.Инициализация структур.

6.Доступ к компонентам структур.

7.Массивы структур.

8.Указатели на структуры.

9.Операции над указателями на структуры.

10.Выделение памяти для структур.

11.Рекурсивные структуры.

12.Объединения и битовые поля.

Задание на выполнение:

1. Для определенной пользователем структуры выполнить следующее:

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

· Написать функцию постраничного вывода на экран дисплея содержимого массива структур.

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

· Одно из полей структуры выполнить в виде битового поля.

2. Ввести структуру для описания понятия рациональная дробь. Составить и протестировать функции:

· sum(a, b, c), которая записывает в с результат сложения рациональных дробей a и b. Предусмотреть операцию сокращения результирующей дроби;

· min(a, b), которая возвращает наименьшую из двух рациональных дробей. Предусмотреть операцию сокращения результирующей дроби.

3. Ввести структуру time с полями часы, минуты, секунды. Составить и протестировать функции:

· next(t, t1, d), которая присваивает параметру t1 время на d секунд больше, чем время t. Предусмотреть возможность смены суток.

· fun(t1, t2, d), которая вычисляет время d, прошедшее от времени t1 до времени t2.

4. Определить структуры, описывающие шар и точку в трехмерном пространстве. Составить и протестировать функцию, которая проверяет:

· находится ли точка внутри заданного шара;

· находится ли центр заданного шара в заданной точке.

ЛАБОРАТОРНАЯ РАБОТА №8

Тема: Работа с файлами

(4 часа)

Потоки – это наиболее удобные средства для чтения или записи данных в файл в С. Они позволяют разрабатывать гибкий и эффективный ввод/вывод, который не зависит от используемых файлов или встроенного оборудования.

Поток является файлом или физическим устройством (принтером или монитором, например), которым вы управляете с помощью указателей на объект FILE (определенный в stdio.h). Объект FILE содержит различную информацию о потоке, включая текущую позицию потока, указатели на соответствующие буферы и индикаторы ошибки или конца файла.

Ваша программа никогда не может создавать и копировать непосредственно объекты FILE; однако, она может использовать указатели, возвращенные из функций типа fopen.

Вы должны открыть поток перед тем, как вы будете производить ввод/вывод в него. Открытый поток связывается с файлом или устройством. Функции, которые открывают потоки, это fopen, fdopen и freopen. Когда вы открываете поток, вы указываете, хотите ли вы читать или записывать в поток, или делать и то, и другое. Вы должны также указать, будете ли вы обращаться с данными из потока как с текстом или как с двоичными данными. Это последнее указание важно для уменьшения несовместимости между потоками ввода/вывода С и текстовым файлом DOS.

Текстовые и двоичные потоки.

Текстовые потоки используются для обычных текстовых файлов DOS, таких как файл, созданный редактором С. Поток ввода/вывода С предполагает, что текстовый файл разделен на строки, отделенные с помощью одного символа новой строки (которым является ASCI-символ перевода строки). Текстовый файл DOS, однако, записывается на диск с двумя символами между каждой строкой – ASCII-символами «возврат каретки» и «перевод строки». В текстовом режиме С преобразует пару возврат каретки/перевод строки (CR/LF) в один символ перевод строки при вводе; перевод строки преобразуется в пару CR/LF при выводе.

Двоичный поток значительно проще, чем текстовый. Никаких преобразований не производится. Любые символы читаются и записываются без изменений.

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

#include <stdio.h>

FILE *fp;

Функция открытия потока выглядит следующим образом:

fp=fopen(*имя_файла, *режим_открытия);

Для контроля открытия потока следует воспользоваться нижеприведенной конструкцией:

if ((fp = fopen(*имя_файла, *режим)) = = NULL){

fprintf(stderr, "Cannot open input file.\n");

exit(1) ; }

Стандартно файл, связанный с потоком, можно открыть в следующих режимах: «w», «r», «a», «w+», «r+», «a+», «b», «t».

Указатель на поток в любом режиме, отличном от аварийного, никогда не бывает равным NULL.

После того как файл открыт, с ним можно работать, записывая в него информацию или считывая ее (в зависимости от режима).

Открытые на диске файлы после окончания работы с ними рекомендуется закрыть явно. Для этого используется библиотечная функция int fclose(FILE *fp);

Открытый файл можно открыть повторно только после того, как файл будет закрыт с помощью функции fclose().

Для работы с файлами на диске предусмотрены функции:

fgetc(), fputc(), fprintf(), fscanf(), fgets(), fputs(), fseek(), ftell(), fwrite().

Вопросы:

1.Понятие потока.

2.Связь файла с потоком.

3.Функции открытия файла.

4.Двоичный и текстовый режимы работы с файлом.

5.Функции fgetc(), fputc(), fprintf(), fscanf(), fgets(), fputs(), fseek(), ftell(), fwrite().

Задание на выполнение:

1.Открыть файл для записи и записать в него произвольную информацию. Закрыть файл. Открыть его же в режиме «а+», внести изменения, характеризующие этот режим.

2.Открыть файл для чтения и считать из него:

а) n-ый символ с помощью функции fseek();

б) строку из n символов, начиная с позиции n;

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

3.Подсчитать количество предложений в заданном файле.

4.Подсчитать частоту вхождения заданного символа в файле.

ЛАБОРАТОРНАЯ РАБОТА №9

Тема: Графика на языке С

(4 часа)

Экран дисплейного монитора представляется как набор отдельных точек – пикселов (pixels, от английского picture elements), образующих регулярный прямоугольный растр. Число пикселов определяет разрешающую способность (разрешение) графической системы и обычно отражается парой чисел, первое из которых показывает количество пикселов в одной строке, а второе – число строк.

Графическое изображение, возникающее на экране монитора, является результатом выполнения следующих действий:

Атрибуты пикселов изображения должны быть загружены в память; обычно эту работу осуществляют специальные функции DOS или BIOS, однако возможна и прямая работа с видеопамятью;

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

В персональных компьютерах используются различные типы дисплейных адаптеров (CGA, EGA, Hercules и др.), большинство из которых может работать как в текстовом, так и в графическом режиме.

Графическая система языка С состоит из ядра и обширной библиотеки графических функций GRAPHICS.LIB. При создании программы, обращающейся к функциям графической библиотеки, потребуется файл graphics.h, который включается в программу оператором #include. Файл graphics.h является стандартным в С и содержит определение специфических констант и типов данных, используемых функциями графической библиотеки, а также описания (прототипы) самих функций.

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

- Инициализация графической системы и графического режима;

- Работа с растром пикселов как с двумерной структурой точек;

- Управление цветом;

- Базовые функции доступа к видеопамяти;

- Графические примитивы;

- Вывод графических текстовых сообщений;

- Обработка ошибочных ситуаций.