
- •Происхождение языка с
- •Язык среднего уровня
- •Структурированный язык
- •Язык программирования
- •Компиляторы против интерпретаторов
- •Вид программ на с
- •Библиотеки и компоновка
- •Раздельная компиляция
- •Карта памяти с-программы
- •Переменные, константы, операторы и выражения
- •Идентификаторы
- •Типы данных
- •Модификаторы типов
- •Модификаторы доступа
- •Объявление переменных
- •Локальные переменные
- •Формальные параметры
- •Глобальные переменные
- •Спецификаторы хранения
- •Статические переменные
- •Статические локальные переменные
- •Статические глобальные переменные
- •Регистровые переменные
- •Оператор присваивания
- •Многочисленное присваивание
- •Преобразование типов при присваивании
- •Инициализация переменных
- •Константы
- •Символьные константы с обратным слэшем
- •Операторы
- •Арифметические операторы
- •Увеличение и уменьшение
- •Операторы отношения и логические операторы
- •Битовые операторы
- •Оператор ?
- •Операторы указания & и *
- •Оператор sizeof
- •Оператор «запятая»
- •Операторы [ ] u ()
- •Приоритеты в с
- •Выражения
- •Преобразование типов в выражениях
- •Принудительные преобразования
- •Пробелы и круглые скобки
- •Сокращенные операторы в с
- •Операторы управления программой
- •Истина и ложь в с
- •Операторы выбора
- •Вложенные if
- •Лесенка if-else-if
- •Оператор ?
- •Вложенные операторы switch
- •Вариации цикла for
- •Бесконечный цикл
- •Циклы for без тела
- •Метки и goto
- •Функции
- •Оператор return
- •Выход из функции
- •Возвращаемые значения
- •Значения, возвращаемые функцией main()
- •Правила видимости для функций
- •Аргументы функции
- •Передача по значению и передача по ссылке
- •Создание передачи по ссылке
- •Передача массивов в функции
- •Аргументы функции main()
- •Функции, возвращающие нецелые значения
- •Использование прототипов функции
- •Прототипы стандартных библиотечных функций
- •Создание прототипов функций, не имеющих параметров
- •Возврат указателей
- •Рекурсия
- •Сопоставление классического и современного объявления параметров
- •Указатели на функции
- •Особенности реализации
- •Параметризированные функции и функции общего назначения
- •Эффективность
- •Массивы
- •Одномерный массив
- •Создание указателя на массив
- •Передача одномерных массивов в функции
- •Двумерные массивы
- •Массивы строк
- •Многомерные массивы
- •Индексация с помощью указателей
- •Размещение массивов
- •Инициализация массива
- •Инициализация безразмерных массивов
- •Пример программы игры в крестики-нолики
- •Указатели
- •Указатели - это адреса
- •Переменные-указатели
- •Операторы для работы с указателями
- •Выражения с указателями
- •Присваивание указателей
- •Арифметические действия с указателями
- •Сравнение указателей
- •Динамическое выделение и указатели
- •Указатели на константы
- •Указатели на константы
- •Указатели на константы
- •Указатели и массивы
- •Указатели на символьные массивы
- •Массивы указателей
- •Указатели на указатели - многочисленное перенаправление
- •Инициализация указателей
- •Указатели на функции
- •Проблемы, связанные с указателями
- •Структуры, объединения и определяемые пользователем типы
- •Структуры
- •Доступ к членам структуры
- •Присваивание структур
- •Массивы структур
- •Программа инвентаризации
- •Передача структур в функции
- •Передача членов структур в функции
- •Передача всей структуры в функцию
- •Указатели на структуры
- •Объявление указателя на структуру
- •Использование указателей на структуру
- •Массивы и структуры в структурах
- •Битовые поля
- •Объединения
- •Перечисления
- •Использование sizeof для обеспечения переносимости
- •Ввод, вывод, потоки и файлы
- •Потоки и файлы
- •Текстовые потоки
- •Двоичные потоки
- •Консольный ввод/вывод
- •Чтение и запись символов
- •Чтение и запись строк: gets() и puts()
- •Форматированный консольный ввод/вывод
- •Печать символов
- •Вывод чисел
- •Вывод адресов
- •Спецификатор %n
- •Модификаторы формата
- •Спецификатор минимума ширины поля
- •Спецификатор точности
- •Выровненный вывод
- •Работа с другими типами данных
- •Модификаторы * u #
- •Спецификаторы формата
- •Ввод чисел
- •Ввод беззнаковых целых
- •Чтение отдельных символов с помощью scanf()
- •Чтение строк
- •Ввод адреса
- •Спецификатор %n
- •Использование множества сканирования
- •Пропуск нежелательных специальных символов
- •Обычные символы в управляющей строке
- •В scanf() следует передавать адреса
- •Модификаторы формата
- •Подавление ввода
- •Файловая система ansi с
- •Указатель на файл
- •Открытие файла
- •Запись символа
- •Чтение символа
- •Использование fopen(), getc(), putc() и fclose()
- •Использование feof()
- •Две расширенные функции: getw() и putw()
- •Работа со строками: fgets() и fputs()
- •Fseek() и произвольный доступ
- •Удаление файлов
- •Работа с консолью
- •Препроцессор и комментарии
- •Директивы условной компиляции
- •Использование defined
- •Операторы препроцессора # и ##
- •Предопределенные макросы
- •Комментарии
Доступ к членам структуры
Доступ к отдельным членам структуры осуществляется с помощью оператора. (обычно называется «точкой») Например, следующий фрагмент кода присваивает члену zip структурной переменой addr_info значение 12345: addr_info.zip = 12345;
За именем структурной переменной следует точка, а за ней имя члена, к которому происходит обращение. Ко всем членам структуры доступ осуществляется точно таким же способом. Стандартный вид доступа следующий: имя_структуры.имя_члена
Следовательно, для вывода поля zip на экран надо написать: printf("%ld", addr_info.zip); Данная строка выводит на экран содержимое поля zip структурной переменной addr_nfo. Таким же образом массив символов addr_info.name может использоваться в gets(): gets (addr_infо.name); Данная команда передает указатель на символ, указывающий на начало name.
Для доступа к отдельным элементам addr_info.name можно использовать индекс name. Например, можно вывести содержимое addr_info.name посимвольно с помощью следующего кода: register int t; for(t=0; addr_info.name [t]; ++t) putchar (addr_info.name [t]);
Присваивание структур
Информация, содержащаяся в одной структуре, может быть присвоена другой структуре того же типа с помощью одиночного оператора присваивания, то есть не нужно присваивать значение каждого члена по отдельности. Следующая программа демонстрирует присваивание структур: #include <stdio.h> int main(void) { struct { int a; int b; } x, y; x.a = 10; x.b = 20; у = x; /* присвоение одной структуры другой */ printf ("Contents of у: %d %d.", y.a, y.b); return 0; } После присваивания у.а и y.b будут содержать значения 10 и 20 соответственно.
Массивы структур
Возможно, наиболее часто структуры используются в виде массивов структур. Для объявления массива структур следует сначала определить структуру, а затем объявить массив переменных данного типа. Например, для объявления 100-элементного массива структур типа addr следует написать: struct addr addr_info[100]; В результате получаем набор из 100 переменных, устроенных, как объявлено в типе структуры addr.
Для доступа к отдельным структурам массива adar_info следует проиндексировать имя массива. Например, для вывода содержимого поля zip третьей структуры, следует написать: printf("%ld", addr_info[2].zip);
Как и массивы переменных, массивы структур индексируются с нуля.
Программа инвентаризации
Для иллюстрации использования структур и массивов структур рассмотрим простую программу инвентаризации, использующую массив структур для хранения инвентарной информации. Функции данной программы работают со структурами и их членами различными способами. В данном примере сохраняемая информация содержит:
имя элемента
стоимость
количество имеющегося товара
Можно определить базовую структуру данных inv для хранения информации: #define МАХ 100 struct inv { char item[30]; float cost; int on_hand; } inv_info [MAX]; В структуре inv для хранения имени элемента используется item. Член cost содержит стоимость элемента, a on_hand содержит число имеющихся элементов. Первая необходимая для программы функция - это main(): int main(void) { char choice; init_list(); /* инициализация массива структур */ for (;;) { choice = menu_select(); switch (choice) { case 1: enter(); break; case 2: del(); break; case 3: list(); break; case 4: return 0; } } } В main() вызов init_list() подготавливает для использования массив структур путем помещения нулевых символов в первый байт каждого поля item. Программа предполагает, что структура не используется, если поле item пустое, функция init_list() определяется следующим образом: /* Инициализация массива структур. */ void init_list(void) { register int t; for(t=0; t<MAX; ++t) inv_inf о [ t ].item[0] = '\ 0'; } функция menu_select() выводит меню и возвращает выбор пользователя: /* Ввод выбора пользователя. */ int menu_select(void) { char s[80]; int c; printf ("\n"); printf("1. Enter an item\n"); printf ("2. Remove an item\n"); printf ("3. List the inventory\n"); printf ("4. Quit\n"); do { printf ("\nEnter your choice: "); gets (s); с = atoi(s); } while (c<0 || c>4); return c; } Функция enter() подсказывает пользователю при вводе и размещает вводимую информацию в следующей пустой структуре. Если массив заполнен, выводится сообщение «List Full». Функция find_tiree() ищет в массиве структур неиспользуемый элемент. /* Ввод инвентарной информации. */ void enter(void) { int slot; slot = find_free(); if (slot == -1) { printf("\nList Full"); return; } printf("Enter item: "); gets(inv_info[slot].item); printf("Enter cost: "); scanf{"%f", &inv_info[slot].cost); printf("Enter number on hand: "); scanf("%d%*c",&inv_info[slot].on_hand); } /* возврат индекса первого неиспользуемого участка массива или -1, если свободных участков нет */ int find_free(void) register int t; tox(t=0; inv_info[t].item[0] && t<MAX; ++t); if(t == MAX) return -1; /* no slots free */ return t; }
Следует обратить внимание, что find_free() возвращает -1, если все структуры массива используются. Это «безопасное» число, поскольку элемент массива inv_info не может быть равен -1.
Функция del() требует, чтобы пользователь определил число элементов, которые необходимо удалить. Затем функция помещает нулевой символ в начало поля item. /* Удаление элемента из списка. */ void del(void) { register int slot; char s[80]; printf ("enter record #: "); gets (s); ' 1; slot = atoi(s); if (slot >=0 && slot < MAX) inv_info [slot].item [0] = '\0'; } Последняя функция программы - это list(). Она выводит весь инвентарный список на экран. /* Вывод списка на экран. */ void list (void) { register int t; for (t=0; t<MAX; ++t) { if(inv_info[t].item[0]) { printf("Item: %s\n", inv_info[t].item); printf("Cost: %f\n", inv_info[t].cost); printf ("On hand: %d\n\n", inv_info[t].n_hand); } } printf("\n\n"); }
Ниже приведено полное описание программы инвентаризации. Если нет уверенности в понимании работы данных структур, следует ввести данную программу в компьютер и изучить ее выполнение, внося изменения и наблюдая за эффектами. /* простая программа инвентаризации, использующая массивы структур */ #include <stdio.h> #include <stdlib.h> #define MAX 100 struct inv { char Item[30]; float cost; int on hand; } inv_info[MAX]; void init_list(void), list(void), del(void); void enter(void); int menu_select(void), find_free(void); int main(void) { char choice; init list(); /* инициализация массива структур */ for(;;) { choice = menu_select(); switch(choice) { case 1: enter(); break; case 2: del(); break; case 3: list(); break; case 4: return 0; } } } /* инициализация массива структур */ void init_list (void) { register int t; for(t=0; t<MAX; ++t) inv_info[t].item[0] = '\0'; } /* ввод выбора пользователя */ int menu_select(void) { char s[80]; int c; printf("\n"); printf("1. Enter an item\n"); printf("2. Remove an item\n"); printf("3. List the inventory\n"); printf("4. Quit\n"); do { printf("\nEnter your choice: "); gets(s); с = atoi(s); } while (c<0 || c>4); return c; } /* ввод инвентарной информации */ void enter(void) { int slot; slot = find_free(); if ( slot == -1) { printf("\nList Full"); return; } printf("Enter item: "); gets (inv_info[slot].item); printf("Enter cost: "); scanf("%f", &inv_info[slot].cost); printf("Enter number on hand: "); scanf ("%d%*c", &inv_infо[slot].on_hand); } /* возврат индекса первого неиспользуемого участка массива или -1 если свободных участков нет */ int find_free(void) { register int t; for (t=0; inv_info [t].item[0] && t<MAX; ++t); if (t == MAX) return -1; /* no slots free */ return t; } /* удаление элемента из списка */ void del(void) { register int slot; char s[80]; printf("enter record #: "); gets(s); slot = atoi (s); if (slot >= 0 && slot < MAX) inv_info[slot].item[0] = '\0'; } /* вывод списка на экран */ void list(void) { register int t; for(t=0; t<MAX; ++t) { if(inv_info[t].item[0]) { printf("Item: %s\n", inv_info[t].item); printf("Cost: %f\n", inv_info[t].cost); printf("On hand: %d\n\n", inv_info[t].on_hand); } } printf ("\n\n"); }