
- •Санкт-Петербургский
- •Структура программы на языке Си
- •Структура простейшей одномодульной программы
- •Комментарии в программе на языке Си
- •Начальные сведения о препроцессоре
- •Определение функции main().
- •Пример простейшей программы
- •Алфавит, синтаксис и семантика
- •Алфавит языка Си
- •Понятие о типе
- •Система типов языка Си Система типов языка Си
- •Понятие об объекте
- •Лексемы
- •Зарезервированные слова
- •Идентификаторы
- •Литералы
- •Целочисленные литералы
- •Литерал вещественного типа
- •Символьные литералы
- •Строковый литерал
- •Переменные
- •Символические константы в языке Си
- •Операторы, выражения и инструкции. Общие сведения.
- •Классификация операторов
- •Приоритет и ассоциативность операторов.
- •Побочные эффекты и вычисления выражений
- •Порядок вычисления выражений
- •Арифметические операторы и выражения
- •Унарные операторы
- •Бинарные операторы
- •Преобразования типа при выполнении бинарных операторов
- •Автоматическое преобразование типов
- •Явное преобразование типа
- •Математические функции
- •Оператор присваивания и инструкция присваивания
- •Простой оператор присваивания
- •.Множественное присваивание
- •Составной оператор присваивания
- •Преобразование типа при присваивании
- •Начальные сведения об указателях. Выходные параметры функции
- •Принятие решений и логические величины. Операторы отношения и сравнения на равенство
- •Логические операторы
- •Поразрядные операторы
- •Условные выражения (оператор ?:)
- •Оператор запятая
- •Оператор sizeof
- •Составная инструкция
- •Инструкция ifelse
- •Полная и сокращенная формы инструкции if
- •Вложенные инструкции if
- •Инструкция switch
- •Синтаксис инструкции switch
- •1.25.2. Использование инструкции switch
- •Функциональные компоненты цикла
- •Арифметические и итерационные циклы
- •Задачи, приводящие к арифметическим циклам
- •Задачи, приводящие к итерационным циклам
- •Циклические управляющие инструкции
- •Цикл, управляемый инструкцией for
- •Цикл, управляемый инструкцией while
- •Цикл, управляемый инструкцией do … while
- •Цикл с выходом
- •Вложенные циклы
- •Понятие о варианте и инварианте цикла
- •Объявления и определения (расширенное рассмотрение)
- •Спецификаторы объявления
- •Спецификаторы класса памяти.
- •Квалификаторы типа
- •Спецификаторы типа
- •Использование спецификаторов
- •Описатели
- •Использование зарезервированного слова typedefдля объявления синонимов типов
- •Функции
- •Понятие об абстракции и инкапсуляции
- •Функция языка Си и процедурная абстракция
- •Понятие о функции
- •Назначение функций
- •Определение функции
- •Функции, возвращающие и невозвращающие значение
- •Вызов функции. Передача параметров по значению
- •Внешние переменные и процедурная абстракция
- •Понятие о прототипе. Компиляция
- •Старый стиль определения функции
- •Массивы в стиле языка с89
- •Определение и объявление массивов
- •Определение и объявление одномерных массивов. Иницициализация одномерных массивов при их определении. Доступ к элементам массива.
- •Определение и инициализация двумерных массивов
- •Операции с массивами
- •Размещение массивов в оперативной памяти
- •Указатели
- •Операторы разыменования и взятия адреса
- •Области применения указателей
- •Нулевой указатель
- •Определение указателя
- •Недействительный указатель
- •Операции с указателями
- •Дополнительные сведения о разыменовании указателей
- •Присваивание указателей
- •Операция взятия адреса для указателя. Указатели на указатели
- •Указатели и операция индексирования
- •Арифметические операции с указателями
- •Сравнение указателей
- •Указатели и динамическая память
- •Функция malloc
- •Функция calloc
- •Функция realloc
- •Функция free
- •Указатели – параметры функций. Имитация передачи по ссылке
- •Указатели на функцию
- •Инициализация указателя на функцию
- •Операции с указателями на функцию
- •Табулирование произвольной функции одного переменного
- •Использование стандартной функции qsort
- •Указатели и массивы
- •Строковый литерал
- •Символические строковые константы
- •Строковые переменные
- •Инициализация строковых переменных
- •Операции со строковыми переменными
- •Ввод строк
- •Функция scanf()
- •Опасная функция gets()
- •Использование функции fgets()
- •Вывод строк
- •Функция printf()
- •Функция puts()
- •Функция fputs()
- •Библиотечные функции для обработки строк
- •Функция strlen()
- •Функции strcpy()иstrncpy()
- •Функции strcat() иstrncat()
- •Функция strcmp()
- •Массивы строк
- •Структуры
- •Объявление структур
- •Обращение к полям структуры
- •Инициализация структур
- •Операции над структурами
- •Массивы структур
- •Объявление массива структур
- •Идентификация элементов массива структур
- •Работа с внешними устройствами
- •Понятие потока
- •Текстовый поток
- •Двоичный поток
- •Указатель файла
- •Функция fopen()
- •Функция fclose()
- •Построковый ввод – вывод
- •Блоковый ввод – вывод
- •Примеры решенных задач
- •Прямой доступ к файлу
- •Функция fseek()
Использование стандартной функции qsort
Функция qsort() предназначена для сортировки элементов массивов в порядке возрастания. Названиеqsortсвязано с первоначальной реализацией этой функции, в которой использовался алгоритм быстрой сортировки. В текущем стандарте не оговаривается, какой алгоритм сортировки должен использоваться. Рассмотрим вначале прототип этой функции.
#include <stdlib.h> void qsort(void* base, size_t nmemb, size_t size, int (* compar)(const void* p1, const void*p2));
Здесь:
base– указатель на первый элемент массива, содержащего сортируемые элементы,
nmemb – количество сортируемых элементов,
size– размер памяти, занимаемый одним элементом,
compar– указатель на функцию, выполняющую сравнение сортируемых элементов.
Остановимся отдельно на функции, которая должна выполнять сравнение. Эта функция должна получать два параметра, которые указывают на объекты, подлежащие сравнению. Эта функция должна возвращать отрицательное число, если первый элемент меньше второго, положительное число, если первое элемент больше второго и, наконец, возвращает нулевое число – в случае равентсва сравниваемых элементов.
Отметим универсальность функции qsort(). С помощью этой функции можно сортировать массивы с произвольным типом элементов массива. Универсальность функции обеспечивается использованием нетипизированных указателей.
Рассмотрим пример использования функции qsort().
Постановка задачи. Сортировать в порядке возрастания элементы массиваar. Массив состоит изn элементов типаdouble.
Решение.
Напишем функцию пользователя compar(имя функции может быть и другим). Интерфейс разрабатываемой функции задается последним (четвертым) параметром функцииqsort() и имеет следующий вид.
int compare(const void* p1,const void* p1);
Для упрощения алгоритма введем две вспомогательные переменные x1 иx2 типаdouble. Эти переменные должны представлять в разрабатываемой функции сравниваемые элементы массива. Для нахождения значений этих переменных необходимо нетипизированные указателиp1 иp2 преобразавать к указателям на тип сравниваемых элеменов (double*), а затем выполнить их разыменование. В результате можно получить следующее определение функции.
Определение функции сравнения
int compare(const void* p1, const void* p2) { double x1 = *(double*)p1; double x2 = *(double*)p2; if(x1 < x2) return -1; if(x1 > x2) return 1; return 0; }
Клиентский код.
int compare(const void* p1, const void* p2); int main(void) {
double ar[] = {25, 4, 8, -1}; int n = sizeof(ar) / sizeof(*ar); qsort(ar, n, sizeof(*ar), compar); for(int i = 0; i < n; i++) printf(“%0.4g”, ar[i]); return 0; }
Результат выполнения программы:
-1
4
8
25
Указатели и массивы
Между указателями и массивами в языке Си имеется тесная связь. Эта связь проявлется в сдудующем:
имя массива является константным укзателем.
массив, передаваемый в качестве аргумента в вызове функции, «вырождается» в указатель.
к любому указателю синтаксически применима операция индексирования (семантически это оправдано только для указателей, работающих с массивами).
Строки
На практике часто возникают задачи, связанные с обработкой текста. Текстом называется упорядоченная последовательность строк. Это положение приводит к необходимости рассмотрения вопроса о преставлении строк и способах их обработки.
Строкой в программировании называется последовательность символов переменной длины. Для работы с отдельными символами в языке Си используется тип char. А как обстоит дело со строками в языке Си? Строкового типа в языке Си нет. Концепция работы со строками в языке Си базируется на двух положениях:
Строки в языке Си хранятся в массивах, элементы которых имеют тип char.
Строки в символьном массиве хранятся в виде последовательности символов, дополненной нуль-символом.
Нуль-символ – символ, код которого равен нулю (‘\0’).