
- •Предисловие
- •Раздел 1. Полный курс программирования на стандартном языке Си Глава 1. Базовые понятия языка
- •1.1. Алфавит, идентификаторы, служебные слова Алфавит
- •Идентификатор
- •Служебные (ключевые) слова
- •1.2. Константы и строки
- •Символы, или символьные константы.
- •Целые константы.
- •Вещественные константы.
- •Предельные значения и типы арифметических констант.
- •Целые константы и выбираемые для них типы
- •Данные вещественных типов
- •Нулевой указатель.
- •Строки, или строковые константы.
- •1.3. Переменные и именованные константы Переменная как объект.
- •Определение переменных.
- •Предельные значения переменных.
- •Основные типы данных
- •Инициализация переменных.
- •Именованные константы.
- •1.4. Операции
- •Знаки операций.
- •Приоритеты (ранги) операций
- •Унарные (одноместные) операции.
- •1.5. Разделители
- •Квадратные скобки.
- •Круглые скобки.
- •Запятая.
- •Точка с запятой.
- •Двоеточие.
- •Многоточие.
- •Звездочка.
- •Обозначение присваивания.
- •Признак препроцессорных средств.
- •1.6. Выражения и приведение арифметических типов
- •Отношения и логические выражения.
- •Присваивание (выражение и оператор).
- •Приведение типов.
- •Правила преобразования типов
- •Правила стандартных арифметических преобразований
- •Выражения с поразрядными операциями.
- •Условное выражение.
- •Глава 2. Введение в программирование на языке си
- •2.1. Структура и компоненты простой программы
- •Текст программы и препроцессор.
- •Структура программы.
- •Функция форматированного вывода.
- •Программы печати предельных констант.
- •Применимость вещественных данных.
- •Выделение лексем из текста программы.
- •2.2. Элементарные средства программирования Деление операторов языка Си на группы.
- •Программа оценки машинного нуля.
- •Трассировочная таблица
- •Ввод данных.
- •Вычисление объема цилиндра.
- •Сумма членов ряда Фибоначчи.
- •2.3. Операторы цикла Три формы операторов цикла.
- •Приближенное значение экспоненты.
- •Оператор break.
- •Сумма отрезка степенного ряда.
- •Оператор continue.
- •Суммирование положительных чисел.
- •2.4. Массивы и вложение операторов цикла Массивы и переменные с индексами.
- •Вычисление среднего и дисперсии.
- •Упорядочение в одномерных массивах.
- •Инициализация массивов.
- •2.5. Функции Определение функций.
- •Функция для вычисления объема цилиндра.
- •Функция для вычисления скалярного произведения векторов.
- •Обращение к функции и ее прототип.
- •Вычисление биномиального коэффициента.
- •Вычисление объема цилиндра
- •Вычисление площади треугольника.
- •Скалярное произведение векторов.
- •2.6. Переключатели
- •Глава 3. Препроцессорные средства
- •3.1. Стадии и команды препроцессорной обработки
- •Стадии препроцессорной обработки.
- •Директивы препроцессора.
- •3.2. Замены в тексте Директива #define.
- •Цепочка подстановок.
- •3.3. Включение текстов из файлов
- •3.4. Условная компиляция Директивы ветвлений.
- •Операция defined.
- •3.5. Макроподстановки средствами препроцессора
- •Моделирование многомерных массивов.
- •Отличия макросов от функций.
- •Препроцессорные операции в строке замещения.
- •3.6. Вспомогательные директивы
- •Препроцессорные обозначения строк.
- •Реакция на ошибки.
- •Пустая директива.
- •Прагмы.
- •3.7. Встроенные (заранее определенные) макроимена
- •Глава 4. Указатели, массивы, строки
- •4.1. Указатели на объекты Адреса и указатели.
- •Операции над указателями.
- •Арифметические операции и указатели.
- •Указатели и отношения.
- •4.2. Указатели и массивы Указатели и доступ к элементам массивов.
- •Массивы динамической памяти.
- •Функции для выделения и освобождения памяти
- •Массивы указателей и моделирование многомерных массивов.
- •"Матрица" со строками разной длины.
- •4.3. Символьная информация и строки
- •Ввод-вывод символьных данных.
- •Внутренние коды и упорядоченность символов.
- •Строки, или строковые константы.
- •Строки и указатели.
- •Глава 5. Функции
- •5.1. Общие сведения о функциях Определение функции.
- •Описание функции и ее тип.
- •Вызов функции.
- •5.2. Указатели в параметрах функций Указатель-параметр.
- •Имитация подпрограмм.
- •5.3. Массивы и строки как параметры функций Массивы в параметрах.
- •Резюме по строкам-параметрам.
- •5.4. Указатели на функции Указатели при вызове функций.
- •Указатели на функции как параметры
- •Указатель на функцию как возвращаемое функцией значение.
- •Библиотечные функции с указателями на функции в параметрах.
- •5.5. Функции с переменным количеством параметров
- •Доступ к адресам параметров из списка.
- •Макросредства для переменного числа параметров.
- •Примеры функций с переменным количеством параметров.
- •5.6. Рекурсивные функции
- •5.7. Классы памяти и организация программ Локализация объектов.
- •Глобальные объекты.
- •Динамическая память
- •Внешние объекты.
- •5.8. Параметры функции main( )
- •Глава 6. Структуры и объединения
- •6.1. Структурные типы и структуры Производные типы.
- •Структурный тип.
- •Определение структур.
- •Выделение памяти для структур.
- •Инициализация и присваивание структур.
- •Доступ к элементам структур.
- •6.2. Структуры, массивы и указатели Массивы и структуры в качестве элементов структур.
- •Массивы структур.
- •Указатели на структуры.
- •Указатели как средство доступа к компонентам структур.
- •Указатели на структуры как компоненты структур.
- •6.3. Структуры и функции
- •Имитация абстрактных типов данных.
- •6.4. Динамические информационные структуры Статическое и динамическое представление данных.
- •Односвязный список.
- •Рекурсия при обработке списка.
- •6.5. Объединения и битовые поля Объединения.
- •Битовые поля.
- •Глава 7. Ввод и вывод
- •7.1. Потоковый ввод-вывод
- •7.1.1. Открытие и закрытие потока
- •7.1.2. Стандартные файлы и функции для работы с ними
- •Ввод-вывод отдельных символов.
- •Ввод-вывод строк.
- •Форматный ввод-вывод.
- •Спецификаторы форматной строки для функции форматного вывода
- •Спецификаторы форматной строки для функции форматного ввода
- •7.1.3. Работа с файлами на диске
- •Двоичный (бинарный) режим обмена с файлами.
- •Строковый обмен с файлами.
- •Позиционирование в потоке.
- •Трехъязычный словарь "Цифры
- •7.2. Ввод-вывод нижнего уровня
- •7.2.1. Открытие / закрытие файла
- •7.2.2. Чтение и запись данных
- •7.2.3. Произвольный доступ к файлу
- •Глава 8. Примеры разработки программ
- •8.1. Программа с объектами разных классов памяти Постановка задачи.
- •Программная реализация.
- •8.2. Структуры и обработка списков в основной памяти Постановка задачи.
- •Функция main( ).
- •Функция init( ) - "Инициализировать базу данных".
- •Функция delete() - "Удалить все сведения о сотруднике из базы данных".
- •Функция fr( ) - "Возвратить освобожденный элемент в список свободных элементов".
- •Функция input( ) - "Ввести в базу данных сведения о новом сотруднике".
- •Функция print( ) - "Печать списка занятых элементов".
- •Сохранение (восстановление) базы данных.
- •8.3. Сортировка на основе бинарного дерева Статические и динамические данные.
- •Управление динамической памятью.
- •Сортировка с помощью бинарного дерева.
- •Печать результатов сортировки.
- •Раздел 2. Выполнение программ в разных операционных системах Глава 9. Подготовка и выполнение программ
- •9.1. Подготовка программ в операционной системе unix
- •9.1.1. Команда make
- •Формат файла описаний зависимостей модулей.
- •Формат команды make.
- •Макроопределения.
- •Встроенные правила.
- •9.1.2. Библиотеки объектных модулей
- •Стандартные библиотеки.
- •Создание и сопровождение собственных библиотек.
- •9.2. Сборка и выполнение программ в интегрированной среде Turbo с 2.0
- •9.2.1. Состав системы программирования Turbo с 2.0
- •9.2.2. Экран интегрированной среды Turbo с 2.0
- •9.2.3. Система меню среды Turbo с 2.0
- •9.2.4. Настройка среды Turbo с
- •Создание рабочего каталога.
- •Установка в среде Turbo с 2.0 полных имен каталогов.
- •Настройка параметров управления проектом.
- •9.5. Окно определения проекта
- •Сборка и выполнение программы.
- •1. Команды управления курсором:
- •2. Команды вставки и удаления:
- •3. Команды обработки блоков текста:
- •4. Дополнительные команды:
- •9.3.2. Экран интегрированной среды
- •9.3.3. Система меню интегрированной среды
- •Задание полных имен основных и рабочего каталогов.
- •Выбор стандарта языка Си.
- •Установка параметров подсистемы Make.
- •Создание проекта.
- •Задание аргументов командной строки.
- •Сохранение параметров настройки интегрированной среды.
- •Сборка и выполнение программы.
- •Работа в интегрированной среде в последующих сеансах.
- •Раздел 3. Практикум по программированию на языке Си Глава 10. Задачи по программированию
- •10.1. Ознакомительная работа
- •10.2. Итерационные методы и ряды
- •Варианты заданий по итерационным методам и рядам
- •10.3. Работа со строками. Указатели, динамические одномерные массивы
- •10..1. Варианты задач по обработке строк*
- •10.3.2. Рекомендации по обработке строк
- •10.3.3. Пример выполнения задания по обработке строк
- •10.4. Многомерные динамические массивы с переменными размерами
- •10.4.1. Варианты задач для 1-й части задания по многомерным массивам (правила формирования многомерного массива)
- •10.4.2. Варианты для 2-й части задания по многомерным массивам
- •10.4.3. Пример выполнения задания по многомерным динамическим массивам
- •10.5. Функции и указатели
- •10.6. Функции и массивы
- •10.7. Работа со структурами
- •10.7.1. Варианты структур для выполнения работы
- •10.8. Списки и деревья
- •10.8.1. Списки
- •10.8.2. Деревья
- •Приложение 1. Таблицы кодов ascii
- •Коды управляющих символов (0 31)
- •Символы с кодами 32 127
- •Символы с кодами 128 255 (Кодовая таблица 866 - ms-dos)
- •Символы с кодами 128 255 (Кодовая таблица 1251 - ms Windows)
- •Приложение 2. Константы предельных значений
- •Приложение 3. Стандартная библиотека функций языка Си
- •Функции для работы с терминалом в текстовом режиме (файл conio.H)
- •Специальные функции
- •Литература
- •Содержание
- •Раздел 1. Полный курс программирования на стандартном языке Си 4
- •Глава 1. Базовые понятия языка 4
- •Глава 2. Введение в программирование на языке си 33
- •Глава 3. Препроцессорные средства 73
- •Глава 4. Указатели, массивы, строки 91
- •Глава 5. Функции 114
- •Глава 6. Структуры и объединения 155
- •Глава 7. Ввод и вывод 186
- •Глава 8. Примеры разработки программ 218
- •Раздел 2. Выполнение программ в разных операционных системах 256
- •Глава 9. Подготовка и выполнение программ 256
- •Раздел 3. Практикум по программированию на языке Си 282
- •Глава 10. Задачи по программированию 282
- •Подбельский Вадим Валерьевич Фомин Сергей Сергеевич программирование на языке си
- •101000, Москва, ул. Покровка, 7 Телефон (095) 925-35-02, факс (095) 925-09-57
Библиотечные функции с указателями на функции в параметрах.
Библиотечные функции с указателями на функции в параметрах. Эти функции играют важную роль при решении задач на языке Си. В стандартную библиотеку компилятора с языка Си включены по крайней мере следующие функции:
qsort ( ) - функция быстрой сортировки массива;
search ( ) - функция поиска в массиве элемента с заданными свойствами.
У каждой из этих функций один из параметров - указатель на функцию. Для функции быстрой сортировки нужен указатель на функцию, позволяющую задать правила упорядочения (сравнения) элементов. В функции поиска параметр - указатель на функцию позволяет задать функцию, с помощью которой программист должен сформулировать требования к искомому элементу массива.
Опыт работы на языке Си показал, что даже не новичок в области программирования испытывает серьезные неудобства, разбирая синтаксис определения конструкций, включающих указатели на функции. Например, не каждому сразу становится понятным такое определение прототипа функции:
void qsort(void * base, size_t nelem, size_t width,
int (*fcmp)(const void * pl, const void * p2));
Это прототип функции быстрой сортировки, входящей в стандартную библиотеку функций. Прототип находится в заголовочном файле stdlib.h. Функция qsort( ) сортирует содержимое таблицы (массива) однотипных элементов, неоднократно вызывая функцию сравнения, подготовленную пользователем. Для вызова функции сравнения ее адрес должен заместить указатель fcmp, специфицированный как формальный параметр. При использовании qsort( ) программист должен подготовить таблицу сортируемых элементов в виде одномерного массива фиксированной длины и написать функцию, позволяющую сравнивать два любых элемента сортируемой таблицы. Остановимся на параметрах функции qsort( ):
base - указатель на начало таблицы (массива) сортируемых элементов (адрес нулевого элемента массива);
nelem - количество сортируемых элементов в таблице (целая величина, не большая размера массива) -сортируются первые nelem элементов от начала массива;
width - размер элемента таблицы (целая величина, определяющая в байтах размер одного элемента массива);
fcmp - указатель на функцию сравнения, получающую в качестве параметров два указателя p1, р2 на элементы таблицы и возвращающую в зависимости от результата сравнения целое число:
если *p1 < *р2, функция fcmp ( ) возвращает отрицательное целое < 0;
если *p1 == *p2, fcmp ( ) возвращает 0;
если *p1 > *p2, fcmp ( ) возвращает положительное целое > 0.
При сравнении символ "меньше, чем" (<) означает, что после сортировки левый элемент отношения *p1 должен оказаться в таблице перед правым элементом *р2, т.е. значение *p1 должно иметь меньшее значение индекса в массиве, чем *р2. Аналогично (но обратно) определяется расположение элементов при выполнении соотношения "больше, чем" (>).
В следующей программе функция qsort( ) используется для упорядочения массива указателей на строки разной длины. Упорядочение должно быть выполнено таким образом, чтобы последовательный перебор массива указателей позволял получать строки в алфавитном порядке. Сами строки в процессе сортировки не меняют своих положений. Изменяются только значения указателей в массиве.
Результаты выполнения программы: до сортировки:
Вывод адресов, т.е. значений указателей pc[i], выполняется в шестнадцатеричном виде с помощью спецификации преобразования %р.
Обратите внимание на значения указателей pc[i]. До сортировки разность между рс[1] и рс[0] равна длине строки "One -1" и т.д. После упорядочения рс[0] получит значение, равное исходному значению рс[7], и т.д.
Для выполнения сравнения строк (а не элементов массива рс[ ] ) в функции compare( ) использована библиотечная функция strcmp( ), прототип которой в заголовочном файле string.h имеет вид:
int strcmp(const char *sl, const char *s2);
Функция strcmp( ) сравнивает строки, связанные с указателями s1 и s2. Сравнение выполняется посимвольно, начиная с начальных символов строк и до тех пор, пока не встретятся несовпадающие символы либо не закончится одна из строк.
Прототип функции strcmp( ) требует, чтобы параметры имели тип (const char *). Входные параметры функции compare( ) имеют тип (const void *), как предусматривает определение функции qsort( ). Необходимые преобразования для наглядности выполнены в два этапа. В теле функции compare( ) определены два вспомогательных указателя типа (unsigned long *), которым присваиваются значения адресов элементов сортируемой таблицы (элементов массива рс[ ] ) указателей. В свою очередь, функция strcmp( ) получает разыменования этих указателей, т.е. адреса символьных строк. Таким образом, выполняется сравнение не элементов массива char * рс[ ], а тех строк, адреса которых являются значениями pc[i]. Однако функция qsort() работает с массивом рс[ ] и меняет местами только значения его элементов. Последовательный перебор массива рс[ ] позволяет в дальнейшем получить строки в алфавитном порядке, что иллюстрирует результат выполнения программы. Так как pc[i] - указатель на некоторую строку, то по спецификации преобразования %s выводится сама строка.
Если не использовать вспомогательных указателей pa, pb, то функцию сравнения строк можно вызвать из тела функции compare( ) таким оператором:
return strcmp((char *)(*(unsigned long *)a),
(char *)(*(unsigned long )b));
где каждый указатель (void *) вначале преобразуется к типу (unsigned long *).
Последующее разыменование "достает" из нескольких смежных байтов значение соответствующего указателя pc[i], затем преобразование (char *) формирует такой указатель на строку, который нужен функции strcmp( ).