Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Сабуров С.В. - Язык программирования C и C++ - 2006

.pdf
Скачиваний:
312
Добавлен:
13.08.2013
Размер:
1.42 Mб
Скачать

Справочник по работе с DOS

Например:

#include <floar.h> main() {

_control87(MCW_EM,MCW_EM);

...

}

Можно определить особую ситуацию для операции с плавающей точкой, вызвав функции _status87 или _clear87.

Определенные математические ошибки могут также произойти в библиотечных функциях, например, при попытке извлечения квадратного корня из отрицательного числа. По умолчанию в таких случаях выполняется вывод на экран сообщений об ошибке и возврат значения NAN (код IEEE «not a number» — «не число»). Использование NAN (нечисловых значений) скорее всего приведет далее к возникновению особой ситуации с плавающей точкой, которая в свою очередь вызовет, если она не замаскирована, аварийное прерывание программы. Если вы не желаете, чтобы сообщение выводилось на экран, вставьте в программу соответствующую версию matherr.

#include <math.h>

int cdecl matherr(struct exception *e)

{

return 1; /* ошибка обработана */

}

Любое другое использование matherr для внутренней обработки математических ошибок недопустимо, так как она считается устаревшей и может не поддерживаться последующими версиями Borland C++.

Математические операции с комплексными числами

Комплексными называются числа вида x + yi, где x и y — это вещественные числа, а i — это корень квадратный из 1. В Borland C++ всегда существовал тип:

struct complex

{

double x, y; };

определенный в math.h. Этот тип удобен для представления комплексных чисел, поскольку их можно рассматривать в

207

Справочник по работе с DOS

качестве пары вещественных чисел. Однако, ограничения Си делают арифметические операции с комплексными числами несколько громоздкими. В С++ операции с комплексными числами выполняются несколько проще.

Для работы с комплексными числами в С++ достаточно включить файл complex.h. В complex.h для обработки комплексных чисел переопределены:

все обычные арифметические операции;

операции потоков >> и <<;

обычные арифметические функции, такие как sqrt и log.

Библиотека complex активизируется только при наличии аргументов типа complex. Таким образом, для получении комплексного квадратного корня из 1 используйте:

sqrt(complex( 1))

а не

sqrt( 1)

Использование двоично!десятичной арифметики (BCD)

Borland C++, также как и большинство прочих компьютеров и компиляторов, выполняет математические вычисления с числами в двоичном представлении (то есть в системе счисления с основанием 2). Это иногда путает людей, привыкших исключительно к десятичной математике (в системе счисления с основанием 10). Многие числа с точным представлением в десятичной системе счисления, такие как 0.01, в двоичной системе счисления могут иметь лишь приближенные представления.

В большинстве прикладных программ двоичные числа предпочтительны, однако в некоторых ситуациях ошибка округления в преобразованиях между системами счисления с основаниями 2 и 10 нежелательна. Наиболее характерным случаем здесь являются финансовые или учетные задачи, где предполагается сложение центов. Рассмотрим программу, складывающую до 100 центов и вычитающую доллар:

#include <stdio.h> int i;

float x =0.0;

for (i = 0; i < 100; ++i)

208

Справочник по работе с DOS

x += 0.01; x = 1.0;

print("100*.01 1 = %g\1",x);

Правильным ответом является 0.0, однако ответ, полученный данной программой, будет малой величиной, близкой к 0.0. При вычислении ошибка округления, возникающая во время преобразования 0.01 в двоичное число, накапливается. Изменение типа x на double или long double только уменьшает ошибку вычисления, но не устраняет ее вообще.

Для решения этой проблемы Borland C++ предлагает специфический для C++ тип bcd (двоично десятичный), объявленный в файле bcd.h. В случае двоично десятичного представления число 0.01 будет иметь точное значение, а переменная x типа bcd даст точное исчисление центов.

#include

<bcd.h>

int

i;

 

bcd

x =

0.0;

for

(i = 0; i < 100; ++i)

x

+=

0.01;

x

=

1.0;

cout << "100*0.1 1 = " << x << "\n";

При этом необходимо учитывать следующие особенности типа bcd:

bcd не уничтожает ошибку округления вообще. Вычисление типа 1.0/3.0 все равно будет иметь ошибку округления.

Обычные математические функции, такие как sqrt и log, для аргументов с типом bcd переопределяются.

Числа типа bcd имеют точность представления около 17 разрядов и диапазон принимаемых значений от 1x10 125 до 1x10125.

Преобразования двоично!десятичных чисел

Тип bcd — это определяемый тип, отличный от float, double или long double. Десятичная арифметика выполняется только когда хотя бы один операнд имеет тип bcd.

Для преобразования двоично десятичного числа обратно к обычной системе счисления с основанием 2 (тип float, double или long double), служит функция элемент real класса bcd. Функция

209

Справочник по работе с DOS

real выполняет все необходимые преобразования к типам long, double или lognd double, хотя такое преобразование не выполняется автоматически. Функция real выполняет все необходимые преобразования к типу long double, который может быть затем преобразован к другим типам при помощи обычных средств языка Си. Например:

/* Печать чисел BCD */

 

 

#include

<bcd.h>

 

 

 

 

#include

<iostream.h>

 

 

#include

<stdio.h>

 

 

 

void main(void)

{

 

 

 

bcd

a

=

12.1;

 

 

 

double

x

=

real(a);

/* преобразование

для печати

printf("\na

=

%Lg",

real(a));

 

printf("\na

=

%g",

(double)real(a));

 

cout

<<

"\na

=" <<

a; /* рекомендуемый

метод

Отметим, что поскольку printf не выполняет контроль типа аргументов, спецификатор формата должен иметь L, если передается значение real(a) типа long double.

Число десятичных знаков

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

bcd a = bcd(1000.00/7, 2)

где 2 обозначает два разряда после десятичной точки. Таким образом:

1000.00/7 = 142.85714 bcd(1000.00/7, 2) = 142.860 bcd(1000.00/7, 1) = 142.900 bcd(1000.00/7, 0) = 142.000 bcd(1000.00/7, 1) = 140.000 bcd(1000.00/7, 2) = 100.000

Округление происходит по банковским правилам, что означает округление до ближайшего целого числа, причем в случае одинакового «расстояния» до ближайшего целого в прямую и обратную сторону округление выполняется в сторону четного

210

Справочник по работе с DOS

Например:

bcd(12.335, 2) = 12.34 bcd(12.245, 2) = 12.34 bcd(12.355, 2) = 12.36

Такой метод округления задается стандартом IEEE.

Видео!функции

Borland C++ поставляется с полной библиотекой графических функций, позволяющих создание экранных графиков и диаграмм. Графические функции доступных только для 16 разрядных приложений DOS. Ниже приведено краткое описание видеорежимов и окон. Затем объясняется, как программировать в текстовом и графическом режимах.

Видеорежимы

Ваш компьютер обязательно имеет некоторый видеоадаптер. Это может быть монохромный дисплейный адаптер (MDA) для базового (только текстового) дисплея, либо это может быть графический адаптер, например цветной графический адаптер (CGA), улучшенный графический адаптер (EGA), монохромный графический адаптер Hercules или видеографическая матрица (VGA/SVGA). Каждый из этих адаптеров может работать в нескольких режимах. Режим определяет величину экрана — 80 или 40 символов в строке (только в текстовом режиме), разрешающую способность экрана (только в графическом режиме) и тип дисплея (цветной или черно белый).

Рабочий режим экрана определяется, когда ваша программа вызывает одну из функций определения режима (textmode, initgraph или setgraphmode).

В текстовом режиме экран компьютера разделен на ячейки (80 или 40 столбцов в ширину и 25, 43 или 50 строк по высоте). Каждая ячейка состоит из атрибута и символа. Символ представляет собой имеющий графическое отображение символ кода ASCII, а атрибут задает, каким образом данный символ будет выведен на экран (его цвет, яркость, и т.д.). Borland C++ предоставляет полный набор подпрограмм для манипулирования текстовым экраном, для вывода текста

211

Справочник по работе с DOS

непосредственно на экран и управления атрибутами ячеек.

В графическом режиме экран компьютера делится на элементы изображения (пикселы); каждый элемент изображения представляет собой отображение на экране одной точки. Число элементов изображения на экране (т.е. его разрешающая способность) зависит от типа подключенного к вашей системе видеоадаптера и режима, в который установлен этот адаптер. Для получения на экране графических изображений Borland C++ предоставляет библиотеку графических функций: вы можете создавать на экране линии и формы, заполненные шаблонами замкнутые области, а также управлять цветом каждого элемента изображения.

В текстовом режиме позиция верхнего левого угла экрана определяется координатами (1,1), где x координата растет слева направо, а y координата увеличивается сверху вниз. В графическом режиме позиция верхнего левого угла определяется координатами (0,0), с теми же направления возрастания координат.

Текстовые и графические окна

Borland C++ обеспечивает функции для создания окон и управления ими в текстовом режиме (и графических окон в графическом режиме).

Окно представляет собой прямоугольную область, определенную на видеоэкране вашего компьютера PC, когда он находится в текстовом режиме. Когда ваша программа выполняет вывод на экран, то область вывода будет в таком случае ограничена активным окном. Остальная часть экрана (вне окна) остается без изменений.

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

В графическом режиме вы также можете определить некоторую прямоугольную область экрана PC. Эта область называется графическим окном или областью просмотра

212

Справочник по работе с DOS

(viewport). Когда ваша графическая программа выполняет вывод рисунков и т.д., графическое окно действует как виртуальный экран. Остальная часть экрана (вне графического окна) остается без изменений. Определить графическое окно можно через экранные координаты, вызвав функцию setviewport.

За исключением функций определения текстовых и графических окон, все остальные функции, как текстового, так и графического режимов, даются в локальных координатах активного текстового или графического окна, а не в абсолютных экранных координатах. При этом верхний левый угол текстового окна будет представлять собой начало координат (1,1). В графическом режиме начало координат графического окна будет равно (0,0).

Программирование в графическом режиме

Borland C++ имеет отдельную библиотеку с более чем 70 графическими функциями, начиная от функций высокого уровня (таких как setviewport, bar3d и drawpoly) и кончая бит ориентированными функциями (типа getimage и putimage). Графическая библиотека поддерживает многочисленные типы линий и заполнителей, а также предоставляют вам различные текстовые шрифты, которые вы можете изменять по размерам, способу выравнивания, а также ориентировать их либо по горизонтали, либо по вертикали.

Эти функции находятся в библиотечном файле GRAPHICS.LIB, а их прототипы — в файле заголовка graphics.h. Кроме этих двух файлов, в состав графического пакета входят драйверы графических устройств (файлы *.BGI) и символьные шрифты (файлы *.CHR).

Если вы используете компилятор BCC.EXE, нужно в командной строке указать библиотеку GRAPHICS.LIB. Например, если ваша программа, MYPROG.C, использует графику, то командная строка компилятора BCC должна иметь вид:

BCC MYPROG GRAPHICS.LIB

При построении программы компоновщик автоматически компонует графическую библиотеку С++.

Поскольку графические функции используют указатели far, графика в случае модели памяти tiny не поддерживается.

213

Справочник по работе с DOS

Графическая библиотека только одна и не имеет версий по моделям памяти (по сравнению со стандартными библиотеками CS.LIB, CC.LIB, CM.LIB и т.д., которые зависят от используемой модели памяти). Каждая функция в файле GRAPHICS.LIB является far (дальней) функцией, а графические функции, использующие указатели работают с дальними указателями. Для правильной работы графических функций в каждом использующем графические функции модуле требуется директива

#include graphics.h.

Функции библиотеки graphics

Графические функции Borland C++ делятся на несколько категорий:

функции управления графической системой;

функции черчения и заполнения;

функции манипулирования экранами и графическими окнами;

функции вывода текстов;

функции управления цветами;

функции обработки ошибок;

функции запроса состояния.

Управление графической системой

Ниже приводится краткое перечисление всех функций управления графической системой:

closegraph

Закрывает графическую систему.

detectgraph

Проверяет аппаратное обеспечение и определяет, какие графические драйверы использовать; рекомендует предпочтительный режим.

graphdefaults

Сбрасывает все переменные графической системы в значения по умолчанию.

214

Справочник по работе с DOS

_graphfreemem

Отменяет выделенную графике память. Используется для определения собственной подпрограммы.

_graphgetmem

Распределяет память графике; используется для определения собственной подпрограммы.

getgraphmode

Возвращает текущий графический режим.

getmoderange

Возвращает минимальный и максимальный допустимые режимы для заданного драйвера.

initgraph

Инициализирует графическую систему и переводит аппаратное обеспечение в графический режим.

installuserdriver

Устанавливает дополнительный драйвер устройства в таблице драйверов устройства BGI.

installuserfont

Загружает поставляемый файл векторного (штрихового) шрифта в таблицу символьных файлов BGI.

registerbgldriver

Регистрирует внешний или загруженный пользователем файл драйвера для включения во время компоновки.

restorecrtmode

Восстанавливает первоначальный (существовавший до Initgraph) режим экрана.

setgraphbufsize

Задает размер внутреннего графического буфера.

setgraphmode

Выбирает заданный графический режим, очищает экран и восстанавливает все умолчания.

Графический пакет компилятора Borland C++ обеспечивает графические драйверы для следующих графических адаптеров (и полностью совместимых с ними):

215

Справочник по работе с DOS

Цветной/графический адаптер (CGA);

Многоцветная графическая матрица (MCGA);

Улучшенный графический адаптер (EGA);

Видеографическая матрица (VGA);

Графический адаптер Hercules;

Графический адаптер серии AT&T 400;

Графический адаптер 3270 PC;

Графический адаптер IBM 8514.

Для запуска графической системы вы должны прежде всего вызвать функцию initgraph. Функция initgraph загружает графический драйвер и переводит систему в графический режим.

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

После того, как графический драйвер загружен, вы можете определить его имя при помощи функции getdrivename, а число поддерживаемых драйвером режимов — при помощи функции getmaxmode. Функция getgraphmode сообщит вам, в каком графическом режиме вы находитесь в текущий момент. Имея номер режима, вы можете определить его имя при помощи функции getmodename. Вы также имеете возможность изменить графический режим при помощи функции setgraphmode и вернуть исходный видеорежим (тот, который был установлен до инициализации графики) с помощью restorecrtmode. Функция restorecrtmode вернет экран в текстовый режим, но не закроет при этом графическую систему (загруженные шрифты и драйверы останутся в памяти).

216

Соседние файлы в предмете Программирование на C++