- •Кетков ю.Л.
- •Раздел 5. Системные данные текстового типа 33
- •Раздел 6. Основные синтаксические конструкции языка c 46
- •Раздел 7. Указатели и ссылки 59
- •Раздел 8. Функции и их аргументы 62
- •Раздел 9. Работа с массивами. 74
- •Раздел 10. Пользовательские типы данных. 95
- •Раздел 11. Работа с файлами 104
- •Раздел 12. Библиотеки стандартных и нестандартных функций 118
- •Раздел 15. Классы. Создание новых типов данных 131
- •Раздел 16. Классы как средство создания больших программных комплексов 150
- •Раздел 17. Прерывания, события, обработка исключений 167
- •Введение
- •Раздел 1. Немного истории
- •Раздел 2. Структура программы на языке c
- •Раздел 3. Среда программирования
- •Раздел 4. Системные данные числового типа
- •4.1. Типы числовых данных и их представление в памяти эвм
- •4.1.1. Внутреннее представление целочисленных данных
- •4.1.2. Однобайтовые целочисленные данные
- •4.1.3. Двухбайтовые целочисленные данные
- •4.1.4. Четырехбайтовые целочисленные данные
- •4.1.5. Восьмибайтовые целочисленные данные
- •4.2. Внутреннее представление данных вещественного типа
- •4.3. Внешнее представление числовых констант
- •4.4. Объявление и инициализация числовых переменных
- •4.5. Ввод числовых данных по запросу программы
- •4.5.1. Потоковый ввод данных числового типа
- •4.5.2. Форматный ввод
- •4.6. Вывод числовых результатов
- •4.6.1. Форматный вывод
- •4.6.2. Потоковый вывод
- •4.7. Примеры программ вывода числовых данных
- •4.8. Операции над числовыми данными целого типа
- •4.9. Операции над числовыми данными вещественного типа
- •Раздел 5. Системные данные текстового типа
- •5.1. Символьные данные и их представление в памяти эвм
- •5.2. Строковые данные и их представление в памяти эвм
- •5.3. Ввод текстовых данных во время работы программы
- •5.3.1. Форматный ввод
- •5.3.3. Потоковый ввод
- •5.3.4. Специальные функции ввода текстовых данных
- •5.4. Вывод текстовых данных
- •5.4.1. Форматный вывод
- •5.5.2. Операции над строковыми данными
- •5.6. Управление дисплеем в текстовом режиме
- •Раздел 6. Основные синтаксические конструкции языка c
- •6.1. Заголовок функции и прототип функции
- •6.2. Объявление локальных и внешних данных
- •6.3. Оператор присваивания
- •6.4. Специальные формы оператора присваивания
- •6.5. Условный оператор
- •6.6. Оператор безусловного перехода
- •6.7. Операторы цикла
- •6.8. Дополнительные операторы управления циклом
- •6.9. Оператор выбора (переключатель)
- •6.10. Обращения к функциям
- •6.11. Комментарии в программах
- •Раздел 7. Указатели и ссылки
- •7.1. Объявление указателей
- •7.2. Операции над указателями
- •7.3. Ссылки
- •Раздел 8. Функции и их аргументы
- •8.1. Параметры-значения
- •8.2. Параметры-указатели
- •8.3. Параметры-ссылки
- •8.4. Параметры-константы
- •8.5. Параметры по умолчанию
- •8.6. Функции с переменным количеством аргументов
- •8.7. Локальные, глобальные и статические переменные
- •8.8. Возврат значения функции
- •8.9. Рекурсивные функции
- •8.10. Указатели на функцию и передача их в качестве параметров
- •8.11. "Левые" функции
- •Раздел 9. Работа с массивами.
- •9.1. Объявление и инициализация массивов.
- •9.2. Некоторые приемы обработки числовых массивов
- •9.2. Программирование задач линейной алгебры
- •9.2.1. Работа с векторами
- •9.2.2.Работа с матрицами
- •9.3. Поиск
- •9.3.1. Последовательный поиск
- •9.3.2. Двоичный поиск
- •9.4. Сортировка массивов.
- •9.4.1. Сортировка методом пузырька
- •9.4.2. Сортировка методом отбора
- •9.4.3. Сортировка методом вставки
- •9.4.4. Сортировка методом Шелла
- •9.4.5.Быстрая сортировка
- •9.5. Слияние отсортированных массивов
- •9.6. Динамические массивы.
- •Раздел 10. Пользовательские типы данных.
- •10.1. Структуры
- •10.1.1. Объявление и инициализация структур
- •10.1.2. Структуры – параметры функций
- •10.1.3.Функции, возвращающие структуры
- •10.2. Перечисления
- •10.3. Объединения
- •Раздел 11. Работа с файлами
- •11.1.Файлы в операционной системе
- •11.1. Текстовые (строковые) файлы
- •11.2. Двоичные файлы
- •11.3. Структурированные файлы
- •11.4. Форматные преобразования в оперативной памяти
- •11.5. Файловые процедуры в системе bcb
- •11.5.1. Проверка существования файла
- •11.5.2. Создание нового файла
- •11.5.3. Открытие существующего файла
- •11.5.4. Чтение из открытого файла
- •11.5.5. Запись в открытый файл
- •11.5.6. Перемещение указателя файла
- •11.5.7. Закрытие файла
- •11.5.8. Расчленение полной спецификации файла
- •11.5.9. Удаление файлов и пустых каталогов
- •11.5.10. Создание каталога
- •11.5.11. Переименование файла
- •11.5.12. Изменение расширения
- •11.5.13. Опрос атрибутов файла
- •11.5.14. Установка атрибутов файла
- •11.5.15. Опрос и изменение текущего каталога
- •11.6. Поиск файлов в каталогах
- •Раздел 12. Библиотеки стандартных и нестандартных функций
- •12.2. Организация пользовательских библиотек
- •12.3. Динамически загружаемые библиотеки
- •13.1. Препроцессор и условная компиляция
- •13.2. Компилятор bcc.Exe
- •13.3. Утилита grep.Com поиска в текстовых файлах
- •14.1. Переопределение (перегрузка) функций
- •14.2. Шаблоны функций
- •Раздел 15. Классы. Создание новых типов данных
- •15.1. Школьные дроби на базе структур
- •15.2. Школьные дроби на базе классов
- •15.3. Класс на базе объединения
- •15.4. Новые типы данных на базе перечисления
- •15.5. Встраиваемые функции
- •15.6. Переопределение операций (резюме)
- •15.8. Конструкторы и деструкторы (резюме)
- •Раздел 16. Классы как средство создания больших программных комплексов
- •16.1. Базовый и производный классы
- •16.1.1.Простое наследование
- •16.1.2. Вызов конструкторов и деструкторов при наследовании
- •16.1.3. Динамическое создание и удаление объектов
- •16.1.4. Виртуальные функции
- •16.1.5. Виртуальные деструкторы
- •16.1.6. Чистые виртуальные функции и абстрактные классы
- •16.2. Множественное наследование и виртуальные классы
- •16.3. Объектно-ориентированный подход к созданию графической системы
- •Раздел 17. Прерывания, события, обработка исключений
- •17.1. Аппаратные и программные прерывания
- •17.2. Исключения
4.9. Операции над числовыми данными вещественного типа
При вычислениях с вещественными данными разрешается использовать только четыре арифметические операции – сложение (+), вычитание (–), умножение (*) и деление (/). В арифметическом выражении могут встречаться операнды разных типов, поэтому важно знать, как компилятор определяет тип результирующего значения. Правило это довольно простое, но оно содержит подводные камни. Арифметические действия выполняются в соответствии общепринятыми правилами:
сначала выполняются действия в самых внутренних скобках;
внутри скобок порядок действий определяется приоритетом операций – сначала одноместные операции типа смены знака, инвертирования и вычисления функций, затем умножения и деления и, в самую последнюю очередь, сложения и вычитания;
тип результата функции описан либо в системных заголовочных файлах, либо в программе пользователя;
тип операнда, представленного сомножителями, определяется типом самого "продвинутого" сомножителя (т.е. допускающего самый широкий диапазон представления данных);
тип выражения, состоящего из слагаемых, определяется типом самого "продвинутого" слагаемого.
Несмотря на простоту и естественность описанных выше правил, результаты вычисления некоторых выражений могут поставить в тупик не очень внимательного программиста. Например, не вызывает сомнения, что тип выражения 5/2+1.0 должен быть вещественным. Однако к вещественным данным относятся и значения типа float, и значения типа double, и значения типа long double. В данном случае, компилятор ориентируется на тип числовой константы 1.0, которая по правилам системы программирования преобразуется в машинный формат длинного вещественного числа (т.е. имеет тип double). А вот результат вычисления данного выражения равен 3.000000, и это может вызвать недоумение. На самом деле, тип каждого слагаемого формулы определяется независимо от типов других слагаемых. Первое слагаемое представлено частным от деления двух целых констант, поэтому его тип тоже целый, т.е. результат деления равен 2, а не 2.5. Затем значения всех слагаемых приводятся к типу double, и итоговый результат равен 3.0.
Существенную помощь в вычислениях с вещественными данными оказывают многочисленные математические функции из раздела math.h. Список некоторых из них приведен в табл. 4.7.
Таблица 4.7
Прототип функции |
Возвращаемое значение |
double acos(double x) |
arccos x |
double asin(double x) |
arcsin x |
double atan(double x) |
arctg x |
double atan2(double x, double y) |
arctg (y/x) |
double atof(const char *s) |
машинный формат числа из строки s |
double ceil(double x) |
округление "сверху" |
double cos(double x) |
cos x |
double cosh(double x) |
ch x |
double exp(double x) |
ex |
double fabs(double x) |
| x | |
double floor(double x) |
округление "снизу" |
double log(double x) |
ln x |
double log10(double x) |
lg x |
max(a,b) |
максимум (a,b), тип совпадает с типом максимального аргумента |
min(a,b) |
минимум (a,b) , тип совпадает с типом минимального аргумента |
double pow(double x, double y) |
xy |
double pow10(int p) |
10p |
double sin(double x) |
sin x |
double sinh(double x) |
sh x |
double sqrt(double x) |
квадратный корень из x |
double tan(double x) |
tg x |
double tanh(double x) |
th x |
double hypot((double x, double y) |
квадратный корень из x2+y2 |
double poly(double x, int n, double *a) |
значение полинома |
double ldexp(double x, int n) |
x*2n |
Прототипы функций max и min, которые, на самом деле представлены не настоящими функциями, а соответствующими макроопределениями, содержатся в файле stdlib.h.
Для большинства функций типа double с аргументом типа double имеются их аналоги с данными типа long double. Названия этих функций отличаются от приведенных в табл. 4.7 добавкой окончания l – (fabs, fabsl), (acos, acosl), …:
Особо следует остановиться на функциях округления ceil и floor. Первая из них возвращает наименьшее целое значение, которое больше или равно x. Вторая возвращает наибольшее целое значение, не превосходящее x. Обратите внимание на то, что значение, возвращаемое обеими функциями, представлено в формате double.
ceil(0.1) =1.0 floor(0.1) = 0.0
ceil(0.5) =1.0 floor(0.5) = 0.0
ceil(0.9) =1.0 floor(0.9) = 0.0
ceil(-0.9)=0.0 floor(-0.9)=-1.0
ceil(-0.5)=0.0 floor(-0.5)=-1.0
ceil(-0.1)=0.0 floor(-0.1)=-1.0
Довольно часто программисты используют для округления функцию floor(x+0.5). Однако иногда она выдает результат, не совпадающий с общепринятым в математике, например floor(-0.5+0.5)=0. Конечно, жаль, что в языках C, C++ нет прямого аналога функции round из Паскаля, но построить такую функцию совсем не сложно:
int round(double x)
{ int res;
res=(x<0)? x-0.5 : x+0.5;
return res;
}
Если нужно произвести округление в том или ином знаке, то число можно предварительно разделить или умножить на 10k, округлить, а затем результат округления умножить или разделить на 10k.
Замечание 1. При выводе числовых результатов вещественного типа необходимые округления производят системные программы вывода.
Замечание 2. Если целочисленной переменной присваивается вещественное значение, то округление не производится. Дробная часть, какой бы она ни была, просто отбрасывается.
В заголовочном файле math.h приводятся определения именованных констант, которыми полезно воспользоваться в своих программах (см. табл. 4.8).
Таблица 4.8
Константа |
Значение |
Константа |
Значение |
M_PI |
|
M_E |
e=2.718… |
M_PI_2 |
/2 |
M_LOG2E |
log2e |
M_PI_4 |
/4 |
M_LOG10E |
log e |
M_2_PI |
2/ |
M_LN2 |
ln 2 |
M_1_SQRTPI |
1/ |
M_LN10 |
ln 10 |
M_2_SQRTPI |
2/ |
M_SQRT2 |
=1.414… |
|
|
M_SQRT_2 |
/2 |