В режиме эмуляции 80Х87 циклический переход в регистрах, а также ряд других особенностей 80х87 не поддерживается

Turbo C++ Programer`s guide
Первый символ должен являться буквой или символом подчеркивания Тело функции, представляющее собой коды, выполняемые при вызове функции Выражение-приведения это пустой (null) указатель Е1 является указателем, а Е2 - константой типа пустого указателя Выражение-инремента выполняет приращения одного или нескольких цикловых счетчиков Вызвать конструктор тем же образом, что и обычную функцию, нельзя. Вызов деструктора допустим только с полностью квалифицированным именем Инициализатор конструктора (см. "инициализатор-конструктора" в описании синтаксиса декларатора класса в таблице Или 16). Ноль означает по умолчанию десятичную Мы будем обозначать все семейство математических сопроцессоров 80x87 термином "сопроцессор" В режиме эмуляции 80Х87 циклический переход в регистрах, а также ряд других особенностей 80х87 не поддерживается GrOk No error Нет ошибки Кроме того, обратите внимание на то, что функция прерывания выполняет выход с помощью команды IRET (возврата из прерывания) Как идентифицировать диагностические сообщения Что происходит, когда доступ к компоненту объекта типа объединения происходит при помощи компонента другого типа Печатаемые диагностические сообщения и поведение при завершении функции assert
668870
знаков
13
таблиц
0
изображений

1. В режиме эмуляции 80Х87 циклический переход в регистрах, а также ряд других особенностей 80х87 не поддерживается.

2. Если вы смешиваете операции с плавающей точкой и встроенные коды на языке ассемблера, то при использовании регистров вы должны принимать некоторые меры предосторожности. Это связано с тем, что набор регистров 80х87 перед вызовом функции в Turbo C++ очищается. Вам может понадобиться извлечь из стека и сохранить регистры 80х87 до вызова функции, использующей сопроцессор, если вы не уверены, что свободных регистров достаточно.

Отмена обработки особых ситуаций

для операций с плавающей точкой -------------------------

По умолчанию программа на Turbo C++ в случае переполнения или деления наноль в операциях сплавающей точкой аварийно прерывается. Вы можете замаскировать эти особые ситуациидля операций с плавающей точкой, вызывая в main _control87 перед любой операцией с плавающей точкой. Например,

#include <floar.h>

main() (*

_control87(MCW_EM,MCW_EM);

...

*)

Вы можете определить особую ситуацию для операции с плавающей точкой, вызвав функции _status87 или _clear87. См. описания этих функций в Главе 1 Справочника по библиотеке.

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

#include <math.h>

int cdecl matherr(struct exception *e)

(*

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

*)

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

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

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

struct complex

(*

double x, y;

*);

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

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

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

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

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

Дополнительную информацию см. в описании класса complex в Справочнике по библиотеке.

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

sqrt(complex(-1))

а не

sqrt(-1)

Примером вычислений с комплексными числами служит следующая функция, выполняющая комплексное преобразование Фурье:

#include <complex.h>

// вычисление дискретного преобразования Аурье для

// a[0],...,a[n-1]

void Fourier(int n, complex a[], complex b[])

(*

int j,k;

complex i(0,1); // корень квадратный из -1

for (j = 0; j < n; ++j)

(*

b[j] = 0;

for (k = 0; k < n; ++k)

b[j] += a[k] * exp(2*M_PI*j*k8i/n);

b[j] /= sqrt(n);

*)

*)

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

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

10). Многие числа с точным представлением в десятичной системе счисления, такиекак 0.01,в двоичной системе счисления могут иметь лишь приближенные представления.

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

#include <stdio.h>

int i;

float x =0.0;

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

x += 0.01;

x -= 1.0;

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

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

Для решения этой проблемы Turbo 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 разрядов и -125 125 диапазон принимаемых значений от 1x10 до 1x10.

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

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

Важное замечание !

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

bcd a = 12.1;

можно вывести при помощи любой из приводимых ниже строк кода:

double x = a; printf("a = %g", x);

printf("a = %Lg", real(a));

printf("a = %g", (double)real(a));

cout << "a =" << 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

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

bcd(12.335, 2)= 12.34

bcd(12.245, 2)= 12.34

bcd(12.355, 2)= 12.36

Использование оперативной памяти Turbo C++

При компиляции Turbo C++ не генерирует каких-либо промежуточных структур данных на диске (Turbo C++ пишет на диск только .OBJ-файлы); между проходами он помещает промежуточные структуры данных в оперативную память. Вследствие этого вы можете получить сообщение"Out of memory...", что означает, что компилятору не хватает памяти.

Решение данной проблемы состоит в том, чтобы сделать ваши функции меньше по размеру, либо разбить на несколько частей файл с большими функциями. Можно также удалить из памяти ранее размещенные там резидентные программы, чтобы освободить больше памяти для использования Turbo C++.

Оверлеи (VROOMM)

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

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

Работа программ с оверлеями

Программа управления оверлеями (VROOMM, или Virtual Run -time Object-Oriented Memory Manager) очень сложна; она выполняет за вас большую часть работы по организации оверлеев. В обычных оверлейных системах модули группируются в базовый и набор оверлейных блоков. Подпрограммы в данном оверлейном блоке могут вызывать подпрограммы из этого жеблока и из базового блока, но не из других блоков. Оверлейные блоки перекрываются друг с другом; т.е. одновременно в памяти может находиться только один оверлейный блок, и все они при активизации занимаютодин и тот же участок физической памяти. Общий объем памяти, необходимой длязапуска данной программы, определяется размером базового, плюс максимального оверлейного блока.

Эта обычная схема не обеспечивает достаточной гибкости. Она требует полного учета всехвозможных обращений между модулями программы и соответственной, планируемойвами,группировки оверлеев. Если вы не можете разбить вашу программу в соответствии со взаимозависимостями обращений между ее модулями, то вы не сможете и разбить ее на оверлеи.

Схема VROOMM совершенно иная. Она обеспечивает динамический свопинг сегментов. Базовым блоком свопинга является сегмент. Сегмент может состоять из одного или нескольких модулей. И что еще более важно, любой сегмент может вызывать любой другой сегмент.

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

Что происходит, когдавозникает необходимость поместить сегмент в область свопинга? Если эта область имеет достаточно свободного места, то данная задача выполняется просто. Если же нет, то из области свопинга должно быть выгружено один или более сегментов, чтобы искомая свободнаяобласть освободилась.Как выбрать сегменты для выгрузки? Действующий здесь алгоритм очень сложен. Упрощенная версия его такова: если в области свопинга имеется неактивный сегмент,то для выгрузки выбираетсяон. Неактивными считаются сегменты, в которых в текущий момент нет выполняемых функций.В противном случае берется активный сегмент. Удаление сегментов из памяти продолжаетсядо тех пор, пока в области свопинга не образуется достаточно свободнойпамятидля размещения там требуемогосегмента. Такой метод называется динамическим свопингом.

Чем больше памяти выделено для области свопинга, тем лучше работает программа. Область свопинга работает как кэшпамять: чем больше кэш, тем быстрее работает программа.Наилучшие значения размера области свопинга определяются размерами рабочего множества данной программы.

После загрузки оверлеяв память он помещается в оверлейный буфер, который расположен в памяти между сегментом стека и дальней кучей. По умолчаниюразмероверлейного буфера вычисляется и устанавливается при загрузке программы, но его можно изменить при помощи глобальной переменной _ovrbuffer. Еслидостаточный размер памяти недоступен, то появляется либо сообщение об ошибке DOS ("Program too big to fit in memory"

- "Программа слишком велика для имеющейся памяти"), либо сообщение кода загрузки С ("Not enough memmory to run program").

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

При использовании оверлеев память распределяется,как показано на следующем рисунке:

Модель MEDIUM Модель LARGE

\! класс CODE \! Резидентный \! класс CODE \!

\! \! код \! \!

--\!----------------\! \!----------------\!

Эти сегменты \!\!класс OVRINFO\!Данные для\!класс OVRINFO\! генерируются \! \! \! управления \! \! компоновщиком \! \! \! оверлеями \! \! автоматически-\! \!----------------\! \!----------------\!

\! \! класс STUBSEG \! Один сегмент \! класс STUBSEG \! \! \! \! stub для \! \!

\! \! \! каждого \! \!

\! \! \! оверлейного \! \!

\! \! \! сегмента \! \!

--\!----------------\! ------------ \!----------------\!

\! _DATA \! \! _DATA \!

Ближняя куча \! класс DATA \! \! класс DATA \! и стек разделяют \! \! \! \!

сегмент данных \!ближняя куча\!Отдельный\!--------------\! \! ^ \!сегмент \! ^ \!

\! | стек \!стека \! | стек \!

\!----------------\! ------------ \!----------------\!

\!оверлейный буфер\! \!оверлейный буфер\!

\!(распределяется \! \!(распределяется \!

\! при загрузке) \! \! при загрузке) \!

\!----------------\! ------------ \!----------------\!

\! | дальняя \! \! | дальняя \!

\! v куча \! \! v куча \!

\! \! \! \!

Модель HUGE

Резидентный \! класс CODE \! код \! \!

-- \!----------------\!

Эти сегменты \! Данные для \! класс OVRINFO \!

генерируются \! управления \! \!

компоновщиком \! оверлеями \! \!

автоматически-\! \!----------------\!

\! Один сегмент \! класс STUBSEG \!

\! stub для \! \!

\! каждого \! \!

\! оверлейного \! \!

\! сегмента \! \!

-- ------------ \!----------------\!

. . . Несколько \!----------------\!

сегментов \!----------------\!

данных \!----------------\!

\!----------------\!

Отдельный \!----------------\! сегмент \! ^ \!

стека \! | стек \!

------------ \!----------------\! \!оверлейный буфер\! \!(распределяется \!

\! при загрузке) \!

------------ \!----------------\! \! | дальняя \!

\! v куча \!

\! \!

Рис.4.9 Распределение памяти для оверлейных структур

Использование преимуществ использования оверлеев Turbo C++

Для полного использования преимуществ оверлейных структур, создаваемых Turbo C,

- Минимизируйте резидентный код (резидентные библиотеки исполняющей системы, обработчики прерываний и драйверы устройств).

- Установите размер оверлейного пула таким образом, чтобы добиться наиболее комфортных условий для создаваемой программы (начните со 128К и регулируйте этот размер вверх и вниз, пока не установите желаемое соотношение между бустродействием и размером программы.

- Подумайте об универсальности и многосторонности создаваемого кода: воспользуйтесь преимуществами оверлейной структуры и обеспечьте поддержку обработки специальных случаев, интерактивную справочную систему по программе и прочие не рассматриваемые здесь средства, являющиеся достоинствами с точки зрения конечного пользователя.

Требования

При создании оверлеев следует помнить несколько простых правил, а именно:

- Минимальная часть программы, которая может быть выделена в качестве лверлея, это сегмент.

- Прикладные программы с оверлейной структурой должны иметь одну из трех следующих моделей памяти: medium, large или huge; модели tiny, small и compact оверлеи не поддерживают.

- Перекрывающиеся сегменты подчиняются обычным правилам слияния сегментов. То есть, в одном и том же сегменте может участвовать несколько .OBJ- файлов.

Генерирование оверлеев во время компоновки полностью независимо от управления сегментами во время исполнения программы; компоновщик не включает автоматически каких-либокодовдля управления оверлеями. Действительно, с точки зрения компоновшика программа управления оверлеями является просто одним из подлежащих компоновке участков кода. Единственное предположение, которое делает компоновщик, состоитв том, что программа управления оверлеями принимает вектор прерываний (обычно INT 3FH), через который происходитуправление динамической загрузкой. Такой уровень прозрачности упрощает создание пользовательских программ управления оверлеями, наилучшим образом управляющих требованиям конкретной прикладной программы.

Использование оверлеев

Для создания программы с оверлейной структурой все ее модули должны компилироваться с включенной опцией компилятора -Y. Для того, чтобы сделать оверлейным конкретный модуль, его следует компилировать с опцией -Yo. (-Yo автоматически включает опцию -Y).

Опция -Yo распространяется навсе модули ибиблиотеки, следующие за ней в командной строке TCC. Отменить ее можно, задав -Yo-.Эти две опции являются единственными опциями командной строки, которые могут следовать после имен файлов. Например,для того,чтобы сделатьоверлейным модуль OVL.C, но не библиотеку GRAPHICS.LIB, можно использовать любую из следующих командных строк:

TCC -ml - Yo ovl.c -Yo- graphics.lib

или

TCC -ml graphics.lib -Yo ovl.c

Если при запуске TLINK явно задана компоновка файла .EXE, то в командной строке компоновщика должна быть задана опция/o. Использование опции /o описано в разделе TLINK главы 5, "Утилиты",

Руководства пользователя.

Пример оверлейной структуры

Предположим, вы хотите иметь оверлейную структуру в программе, состоящейиз трех модулей: MAIN.C, O1.C и O2.C. Оверлеями должны являться модули O1.C и O2.C. (MAIN.C содержит зависящие оттекущего времени подпрограммы иобработчики прерываний ипотому должна оставаться резидентной). Предположим, что данная программа использует модель памяти large.

Следующая команда позволяет выполнить данную задачу:

TCC -ml -Y main.c -Yo o1.c o2.c

В результате получится выполняющийся файл MAIN.EXE с двумя оверлеями.

Организация оверлеев в интегрированной среде разработки (IDE)

___________________________________________________________

Для организации оверлейных модулей в условиях интегрированной среды разработки следует выполнить шаги:

1. Войти в диалоговое поле Options \! Compiler \! Code Generation и установить опцию Overlays On.

2. Войти в Options \! Linker и установит опцию Overlay On.

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

Первый шаг представляет собойэквивалент интегрированной среды разработки опции -Y компилятора командной строки. Если не установить данную опцию в состояние on, то нельзя использовать и две указанных далее опции. Вторая опция управляет тем, должна ли данная информация озадании оверлеев использоваться во время компоновки в IDE. Переведя эту опцию в состояние off, вы можете тем самым глобальноотменить создание ооверлеев,не выполняя перекомпиляцию и не изменяязначений индивидуальных установок модулей в менеджере проекта. Опция на третьем шаге управляет тем, какие модули войдут в оверлеи, а какие останутся фиксированными. Эта опция похожа на опцию командной строки -Yo.

Для построения .EXE-файла с оверлеями скомпилируйтевсе модули с опцией Code Generation \! Overlays On(сперва убедитесь, что выбрана опция Options \! Full Menus On).

Ни одиниз входящих в оверлей модулей никогда не должен изменять умолчание имени класса кода (Code Class). Интегрированная среда позволяет изменить набор входящих в оверлеи модулей, не заботясь о рекомпиляции. Это возможно (с текущей информацией об .OBJ-файлах) только при условии, что оверлеи сохраняют имена класса кода по умолчанию.

Разработка программ с перекрытиями

Этот раздел содержит важные сведения о разработке программ с перекрытиями. Тщательно изучите его, поскольку некоторые рассматриваемые здесь вопросы жизненно важны для создания прикладных программ сперекрытиями, имеющих высокие характеристики.

Требование дальних (far) вызовов

При компиляции оверлейного модуля выдолжны использовать большую модель памяти (medium, large или huge). При всяком вызове функции из оверлейного модуля вы обязаны гарантировать, что все активные в текущий момент функции являются дальними.

Вы обязаны компилировать все оверлейные модули сопцией- Y, что обеспечит оверлейную структуру генерируемого кода.

Важное замечание !

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

Размер буфера

Размер оверлейного буфера по умолчанию в два раза превышает размер самого большого оверлея. Для большинства прикладных программ такое умолчание вполне адекватно. Одако же, представим себе ситуацию, когдакакая-либо функция программыреализована несколькими модулями, каждый из которых является оверлейным. Если общий размер этих модулей превышает размер оверлейного буфера, то если модули часто вызывют друг друга, это приведет к большому числу свопингов.

Очевидно, что решение здесь заключается в увеличении размера оверлейного буфера до таких размеров, чтобы в любой момент времени в нем помещались все часто вызывающие друг друга оверлеи. Это можно сделать, установив через глобальную переменную _ovrbuffer требуемый размер в параграфах. Например, для установки размера оверлейного буфера равным 128К, включите вваш код следующий оператор:

unsigned _ovrbuffer = 0x2000;

Общей формулы для определения идеального размера оверлейного буфера не существует. Turbo Prifiler фирмы Borland поможет определить необходимое значение. Если вы не располагаете данным продуктом, то найти размер буфера вам поможет понимание прикладной задачи и немного зкспериментирования.

В каких случаях не следует создавать оверлейные структуры

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

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

Отладка оверлеев

Большинство отладчиков либо имеет весьма ограниченные средства отладки программ с оверлейной структурой, либо вообще не имеет таких средств. Иначе дело обстоит синтегрированным со средой разработки отладчиком TurboC++ и отладчиком автономным отладчиком Turbo Debugger. Обаэти отладчика полностью поддерживают пошаговую отладку и установку точек прерывания в оверлеях совершенно прозрачным длявас способом. Благодаря использованию оверлеев вы имеете возможность легко разрабатывать и отлаживать громоздкие прикладные программы - как в интегрированной среде, так и при помощи Turbo Debugger.

Внешние (external) подпрограммы в оверлеях

Подобно обычнымфункциям С, внешние (external) подпрограммы на языке ассемблера должны подчиняться некоторым правилам, чтобы хорошо работать с программой управления оверлеями.

Если подпрограмма на языке ассемблера выполняет вызов любой оверлейной функции, то такая подпрограмма должна иметь объявление FAR и должна устанавливать стековый фрейм при помощи регистра BP. Например, если OtherFunc это оверлейная функция в другом модуле, и ее вызывает подпрограмма на языке ассемблера ExternFunc, то тогда ExternFunc должна быть FARи устанавливать стековый фрейм, как показано ниже:

ExternFunc PROC FAR push bp ;сохранить bp

mov bp,sp ;установить стековый фрейм

sub sp,LocalSize ;распределить локальные переменные

...

call OtherFunc ;вызов другого оверлейного модуля

...

mov sp,bp ;освобождение локальных переменных

pop bp ;восстановление BP

RET ;возврат

ExternFunc ENDP

где LocalSize - это размер локальных переменных. Если LocalSize равен нулю, вы можете опустить две строки, распределения и освобождения локальных переменных, но ни в коем случае нельзя опускать установку стекового фрейма BP, даже если аргументов и переменных в стеке нет.

Эти требования остаются теми же в случае, когда TxternFunc делает косвенные ссылки наоверлейные функции. Например, если OtherFunc вызывает оверлейные функции, носама не является оверлейной, то ExternFuncдолжнабыть FAR и также должна устанавливать стековый фрейм.

В случае, когда яссемблерная подпрограмма не делает ни прямых, ни косвенных ссылок на оверлейные функции, то специальные требования отсутствуют; подпрограмма на языке ассемблера может быть объявлена как NEAR. Она не обязана устанавливать стековый фрейм.

Оверлейные подпрограммына языке ассемблеране должны создавать переменные в кодовом сегменте, поскольку все изменения, внесенные в оверлейный кодовый сегмент, теряются при освобождении оверлея. Подобним же образом, указатели объектов, расположенных в оверлейных сегментах,не сохраняют достоверность после вызова других оверлеев, поскольку программа управления оверлеями свободно перемещает и освобождает оверлейные кодовые сегменты в памяти.

Свопинг

Если в системекомпьютера установлена дополнительная или расширенная память, вы можете сообщить программе управления оверлеев, что тот должен использовать ее при свопинге. В этом случае при удалении модуля из оверлейного буфера (когда туда требуется загрузитьновый модуль,а буфер полон) программа управления оверлеямиможет поместить удаляемый модуль вэту память. При любой последующей загрузке этого модуля экономится время за счеттого, что модуль перемещается в памяти, а не считывается с диска.

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

Дополнительная память (EMS)

Свопинг с дополнительной памятью инициализируется функцией _OvrInitEms. Вот ее прототип:

extern int far _OvrInitEms

(*

unsigned emsHandle,

unsigned emsFirst,

unsigned emsPages

*)

_OvrInitEms и _OvrinitExt определены в dos.h

Если параметр emsHandleравен нулю, программа управления оверлеями проверяет наличие дополнительной памяти и распределяет ее количество (если может), достаточное для размещения там всех оверлеев, минус размер оверлейногобуфера. В противном случае emsHandle должен быть допустимым логическим номером EMS, emsFirst - первой используемой EMS страницей, а emsPages - числом доступных программе управления оверлеями страниц. Если дополнительная память доступна, то данная функция возвращает 0.

Расширенная память (Ext)

Свопингс расширеннойпамятью инициализируется функцией _ OvrinitExt). Вот ее прототип:

extern int far -OvrininExt

(*

unsigned long extStart,

unsigned long extLength

*);

Если параметр extStart равен нулю, то программа управления оверлеями проверяет наличие расширенной памяти. Если это возможно, то для свопинга отводится ее участок, равный сумме всех оверлеев, минус размер оверлейного буфера. Впротивном случае extStart содержит начало для использования расширенной памяти, с extLength байт, доступных для использования программой управления оверлеями. Если extLength равна нулю, то программа управления оверлеями может использовать всю расширеннуюпамятьс адресами, старшимичем extStart. Данная функция возвращает 0, если расширенная память доступна. _OvrinitExt определена в dos.h.

Важное замечание !

Использование расширенной памяти не стандартизовано. Хотя программа управленияоверлеями и пробует применить все известные методы для определения размера ужеиспользованнойрасширенной памяти, эту функцию следует применять осторожно. Например, если у вас в системе установлена программа кэширования жесткого диска, использующая 2 Мб оперативной памяти (и расширенной памяти в том числе), то можно заставить программу управления оверлеями занять остальную часть расширенной памяти при помощи вызова:

if (_OvrinitExt (1024L * (2048 + 1024), OL))

puts ("Доступная расширенная память для свопинга оверлеев отсутствует");

Глава 5 Видео функции

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

Видео функцииTurboC++ аналогичны соответствующим подпрограммамв Turbo Pascal. Если вы не знакомы с методами управления экранными режимами вашего PC или создания и управления окнами и графическими окнами, потратьте несколько минут и прочтите краткое изложение этих вопросов.

Несколько слов о видео режимах

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

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

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

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

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

Несколько слов о текстовых и графических окнах

Turbo C++ обеспечивает функции для создания окон и управления ими в текстовом режиме (и графических окон в графическом режиме). Если вы не знакомыс текстовыми и графическими окнами, ознакомьтесь со следующим кратким их изложением. Функции Turbo C++, позволяющие управлять текстовыми и графическими окнами, описаны нижев разделах "Программирование в текстовом режиме" и "Программирование в графическом режиме".

Что такое окно ?

Окно представляет собой прямоуголтную область,

определенную на видео экране вашего PC, когда он находится в

текстовом режиме. Когда ваша программа выполняет вывод на

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

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

Что такое графическое окно ?

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

Координаты

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

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

В данном разделе приводится краткоеизложение функций, используемых в текстовом режиме. Более подробную информацию об этих функциях см. в Главе 1, "Библиотека исполняющей системы" В

Справочнике по библиотеке.

В Turbo C++ пакет функций прямого ввода/выводана консоль (cprintf, cputs и т.д.) обеспечивает высококачественный вывод текста, управление окнами, позиционирование курсора и управление аттрибутами видео изображений. Всеэти функции являются частью стандартных библиотек Turbo C++; они имеютпрототипы в файле заголовка conio.h.

Функции консольного ввода/вывода

Функции текстового режима TUrbo C++ работают в любом из шести возможных текстовых видео режимов.Режимы, доступные в вашей системе, зависят от типа видео адаптера и монитора системы. Текущий текстовый режим задается вызовом textmode. Мы объясним, как использовать эту функцию, ниже в данной главе, и кроме того, она описана в Главе 1 Справочника по библиотеке.

Функции текстового режима делятся на четыре отдельные группы:

- вывода и манипулирование текстом

- управления окнами и режимом

- управления аттрибутами

- запроса состояния

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

Вывод и манипулирование текстом

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

Запись и чтение текста:

cprintfПосылает на экран форматированный вывод.

cputsПосылает на экран строку.

getcheСчитывает символ с эхо-отображением его на экране

putchПосылает на экран отдельный символ.

Манипулирование текстом (и курсором) на экране:

clreolСтирание от курсора до конца строки.

clrscrСтирание текстового окна.

dellineУдаление текущей строки курсора.

gotoxyПозиционирование курсора.

InslineВставка пустой строки под текущей позицией курсора.

movetextКопирование текста из одной области экрана на другую.

Пересылка блоков текста между памятью и экраном:

gettextКопирование текста из области экрана в память.

puttextКопирование текста из памяти в область экрана.

По умолчанию ваши программы экранного вывода работают с полноэкранным текстовым окном, поэтому вы можете в них сразу же начинать писать, читать и манипулировать текстом без каких-либо предварительных установок режима. Записьтекста на экран выполняется при помощи консольных функций прямого вывода cprintf, cputs и putch, а ввод с консоли с эхо-отображением символовнаа экране выполняется функцией getche. Циклический переход текста по экрану определяется глобальной переменной -wscroll. Если _wscroll равна1, тотекст при достиженииконца строки переходит на следующую строку экрана, причем при необходимостивыполняется вертикальный скроллинг. Если _wscroll равен 0, то текст переходит на ту же самую строку, и скроллинг невыполняется. По умолчанию _wscroll равна 1.

После того, как ваш текст выведен на экран, вы можете стереть активное окно при помощи clrscr, либо стереть часть строки от текущей позиции курсора при помощи clreol, либо удальть целую строку при помощи delline, либо вставить пустую строку при помощи insline. Трипоследние функции работают относительно текущей позиции курсора; перемещение курсора в желаемую позицию выполняется при помощи gotoxy. Вы можете также скопировать целый блок текста из одной прямоугольной области в другую при помощи movetext.

Имеется также функция копирования прямоугольной области текста с экрана в память gettext и обратная функция копирования текста из памяти на экран (в любую позицию) puttext.

Управление окнами и режимом

Существует две функции управления окнами и режимом:

textmode Устанавливает текстовый режим экрана.

window Определяет окно текстового режима.

Функция textmode позволяет устанавливать для экрана один из нескольких текстовыхвидео режимов(эта возможность ограничена только типами монитора и адапрера, установленных в вашей системе. Функция инициализирует экран как полноэкранное текстовое окно в конкретном заданном режиме и очищает экран от любых оставщихся на нем текстов или изображений.

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

Управление аттрибутами

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

Установка аттрибутов переднего плана и фона:

textattr Одновременная установка (аттрибутов) цветоа

переднего плана и фона.

textbackground Установка (аттрибута) цвета фона.

textcolor Установка (аттрибута) цвета переднего плана.

Модификация яркости:

highvideo Установка повышенной яркости текста.

lowvideo Установка низкой яркости текста.

normvideo Установка обычной яркости текста.

Функцииуправления аттрибутами устанавливают текущий аттрибут, представляющий собой 8-битовое значение. Четыре младших бита аттрибута задают цвет переднего плана, следующие три бита задают цвет фона, а старший бит задает "мигание" изображения, для которого установлен данный аттрибут.

Вывод всех последующих текстов выполняется с использованием текущего аттрибута. Благодаря функциям управления аттрибутами вы можете устанавливать цвета фона и переднего плана (символов)как порознь (textbackground и textcolor), так и объединяя спецификации этих цветов в одном обращении к textattr. Вы можете задавать также аттрибут мигания переднегоплана (т.е. собственно выводимых символов). Большинство цветных мониторов в цветных режимах дает истинные заданные цвета. Не-цветные мониторы могут преобразовывать некоторые изэтих аттрибутов или все аттрибуты в различные монохроматические оттенки или другие визуальные эффекты,как например, жирный шрифт, подчеркивание, инверсное изображение и т.д.

Вы можете также переопределить для переднего плана изображения яркость цветов вывода при помощи функции lowvideo (которая выключает бит повышенной яркости отображения символов). Либо наоборот, вы можете изменить яркость на повышенную при помощи функции highvideo (которая включает бит повышенной яркости). Когда выделение яркостьюбольшене требуется,можно восстановить исходную установку яркости при помощи функции normvideo.

Запрос состояния

Ниже кратко перечислены функции, при помощи которых ваша программа может сделать запрос состояния видео параметров:

gettextinfo Заполняет структуру text_info информацией о

текущем текстовом окне.

wherex Дает x-координату ячейки экрана, в которой в

текущий момент находится курсор.

wherey Дает y-координату ячейки экрана, в которой в

текущий момент находится курсор.

Функции консольного ввода/вывода Turbo C++ включают в себя несколько специальных функций запроса состояния. При помощи этих функций вы можете получить достеп к информации о текущем текстовом режиме и текущей позиции курсора в этом окне.

Функция gettextinfoзаполняет структуру text_info (определенную в conio.h) подробными даннымио текстовом окне, включая:

- текущий видео режим

- позиция окна в абсолютных экранных координатах

- размеры окна

- текущие цвета переднего плана и фона

- текущая позиция курсора

Иногда вам нужны только некоторые из этих деталей. Вместо обращения к полной информации о данном текстовомокне можно отдельно получить сведения о текущей позиции (относительно начала окна) курсора с помощью функций wherex и wherey.

Форма курсора

Для изменения способа представления курсора служит новая функция _setcursortype. Она принимает значения _NOCURSOR, которая вообще отменяет курсор, _SOLIDCURSOR, которая дает курсор в виде сплошного прямоугольничка и _NORMALCURSOR, которое соответствует обычному курсору в форме подчеркивания.

Текстовые окна

По умолчанию текстовое окно имеет размервсего экрана;это умолчание можно изменить, создав окно, по размеру меньше экрана, с помощью функции window. Текстовые окна могут содержать до 50 строк и от 40 до 80 столбцов.

Начало координат окна(точка, от которой отсчитываются координаты окна) в Turbo C++ лежит вверхнем девомуглу окна. Координаты верхнего левого угла окна равны (1,1); координаты правого нижнего окна полноэкранного окна равны при 80столбцах и 25 строках (80,25).

Пример

Предположим, у вас имеется 100%-совместимая с PC система, находящаяся в текстовом режиме с 80 столбцами, ивы желаете создать окно. Верхний левый угол окна должен иметь экранные координаты (10.8), а нижний правый - (50,21). Для этого требуется вызвать функцию window:

window(10, 8, 50, 21);

Теперь, создав текстовое окно, вы можете поместить курсор в позицию окна (5,8) и вывести, начиная с этойпозиции, некоторый текст с использованием gotoxy и cputs.

gotoxy(5, 8);

cputs("С днем рождения, Френк Борланд");

Следующий рисунок иллюстрирует сказанное.

Столбец 1 экрана

\!

Строка 1--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx экрана x x

x x

x x

x x

x x

x x

Строка 1--x --- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x окна x x x x

x x x x

x x С днем рождения, Френк Борланд x x

x x x x

Строка 14-x---- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x окна x x

x \! \! x

x \! \! x

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-Строка \! \! \! 25

\! \! \! экрана

\! \! \!

Столбец 1 Столбец 41 Столбец 80 окна окна экрана

Рис.5.1 Окно в текстовом режиме 80x25 Тип text_mode

Вы можете перевести свой монитор в один из семи текстовых режимов PC, вызвав для этогофункцию textmode. Определяемый в conio.h перечислимый тип text_mode позволяет использовать в качестве аргумента режима, задаваемого при вызове text_mode, любое символическое имя, определенное для данного перечислимого типа, вместо "сырых" номеров режимов. Однако, чтобы воспользоваться данными симвоическими константами, следует ввести:

#include <conio.h>

в исходный код программы.

Числовые и символические значения, определенные в text_ mode, приводятся ниже:

-----------------------------------------------------------

СимволическаяЧисловое

константазначение Текстовый видео режим

LASTMODE -1 Предыдущий текстовый режим

BW40 0 Черно-белый, 40 столбцов

C40 1 16 цветов, 40 столбцов

BW80 2 Черно-белый, 80 столбцов

C80 3 16 цветов, 80 столбцов

MONO 7 Монохромный, 80 столбцов

C4350 64 EGA, 80x43; VGA, 80x50 строк

Например, следующие вызовы textmode помещаютваш цветной монитор в указанный рабочий режим:

textmode(0) Черно-белый, 40 столбцов

textmode(BW80) Черно-белый, 80 столбцов

textmode(c40) 16 цветов, 40 столбцов

textmode(3) 16 цветов, 80 столбцов

textmode(7) Монохромный, 80 столбцов

textmode(C4350) EGA, 80x43; VGA, 80x50 строк

После вызова textmode с режимомC4350 следуетпри помощи функции settextinfo задать число строк экрана.

Цвета текста

Подробную информацию о том, как хранятся аттрибуты ячеек, см. в описании textattr в Главе 1 Справочника по библиотеке.

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

Включаемый файл conio.h определяет вместо различных цветов символические имена. При использовании этих символических констант вы должны включить в исходный код conio.h.

В следующей таблице приводятся эти символические константы и соответствующие им числовые значения. Отметим, что только первые восемь цветов являются доступными и для переднего плана, и для фона; последние 8 цветов (номера 8 - 15) доступны исключительно для переднего плана (собственно символов).

-----------------------------------------------------------

Символическая Числовое Передний план

константа значение или фон?

BLACK 0 Оба

BLUE 1 Оба

GREEN 2 Оба

CYAN 3 Оба

RED 4 Оба

MAGENTA 5 Оба

BROWN 6 Оба

LIGHTGRAY 7 Оба

DARKGRAY 8 Только передний план

LIGHTBLUE 9 Только передний план

LIGHTGREEN 10 Только передний план

LIGHTCYAN 11 Только передний план

LIGHTRED 12 Только передний план

LIGHTMAGENTA 13 Только передний план

YELLOW 14 Только передний план

WHITE 15 Только передний план

BLINK128 Только передний план

Если выжелаете, чтобы символ мигал, добавьте к аргументу переднего плана символическую константу BLINK(числовое значение 128).

Высокоскоростной вывод: переменная directvideo

Пакет консольных функциий ввода/вывода Turbo C++ включает переменную directvideo. Эта переменная управляет тем,выполняется ли вывод на консоль из вашей программы непосредственно в оперативную память дисплея (directvideo =

1), либо направлфется туда через вызовы BIOS (directvideo =

0).

По умолчанию значение directvideo = 1 (консольный вывод направляется непосредственно в память дисплея). В целом, работа непосредственно с дисплейной памятью ускоряет вывод, но для этого требуется 100% совместимость вашей машины с IBM PC.Ваша видео аппаратура должна быть идентичнадисплейным адаптерам IBM. Установка directvideo=0 позволит вам работать на любой машине с IBM-совместимым BIOS, но вывод на консоль будет несколько замедлен.

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

В данном режиме приводится краткое изложение функций, используемых в графическом режиме. Более подробная информация об этих функциях находится в Главе 1 Справочника по библиотеке.

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

Эти функции находятся в библиотечном файле

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

Для использования графических функций:

- При работе в интегрированной среде переключите Full menus в состояние on и выберите Options \! Linker \! Graphics Library. При создании программы компоновщик автоматически выполнит компоновку графической библиотеки Turbo C++.

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

tcc myprog graphics.lib

Важное замечание !

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

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

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

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

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

- черчения и заполнения

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

- вывода текстов

- управления цветами

- обработки ошибок

- запроса состояния

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

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

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

detectgraph Проверяет аппаратное обеспечение и определяет,

какие графические драйверы использовать;

рекомендует предпочтительный режим.

graphdefaults  Сбрасывает все переменные графической системы

в значения по умолчанию.

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

граммы.

_graphgetmem Распределяет память графике; используется

для определения собственной подпрограммы.

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

getmoderange Допускает младший и старший допустимые режимы

для заданного драйвера.

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

аппаратное обеспечение в графический режим.

installuserdriver Инсталлирует дополнительный драйвер устрой

ства в таблицу драйверов устройста BGI.

installuserfont Загружает поставляемый файл штрихового шриф

та в таблицу символьных файлов BGI.

registerbgldriver Регистрирует внешний или загруженный

пользователем файл драйвера для включения

во время компоновки.

restorecrtmode Восстанавливает первоначальный (существовав

ший до Initgraph) режим экрана.

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

ра.

setgraphmode Выбирает заданный графический режим, очищает

зкран и восстанавливает все умолчания.

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

- Цветной/графический адаптер (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 вернет экран в текстовый режим, но не закроет при этом графическую систему (загруженные шрифты и драйверы останутся в памяти).

graphdefaults сбрасывает установки состоянияграфической системы (размеры графического окна, цвет линий, цвет и шаблон заполнителя и т.д.) в исходное состояние.

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

И наконец, закончив работу в графике,вы должны вызвать функцию closegraph для того, чтобы закрыть графическую систему. closegraph выгружаетдрайвер из памятии восстанавливает первоначальный видео режим (через обращение к restorecrtmode).

Более подробное рассмотрение графики

Выше кратко рассматривалась работа функции initgraph. В следующих параграфах initgraph, _graphgetmem и _graphfreemem будут описаны подробно.

Обычно подпрограмма initgraph загружает графический драйвер, распределяя для этого драйвера память и затем загружая туда с диска соответствующий файл .BGI. В качестве альтернативы данной схемединамической загрузкивы можете скомпоновать нужный файл графического драйвера (или несколько таких файлов) непосредственно с файлом выполняемой программы. Для этого .BGI-файл сначала преобразуетсяв .OBJ-файл (при помощи утилиты BGIOBJ -см. документацию в файле UTIL.DOC, который поставляется на одном из дистрибутивных дисков), после чего в исходный код помещается вызов registerbgidriver (до вызова initgraph), чтобы зарегистрировать графический драйвер(ы) в системе. При построении программы вы должны выполнить компоновку.OBJ-файлов всех зарегистрированных драйверов. После определения того, который графический драйвер должен быть использован (посредством detectgraph) initgraph проверяет, был ли желаемый драйвер зарегистрирован. Если был, то initgraph обращается к зарегистрированному драйверу непосредственно в памяти. В противном случае initgraph распределяет память для драйвера и зпгружает нужный .BGI-файл с диска.

Примечание

Использование функции registerbgidriverотносится к более сложным методам программирования, не рекомендуемым для начинающих программистов. Более подробно данная функция описанав Главе 1

Справочника по библиотеке.

Во время выполнения графической системе может понадобиться выполнить распределение памяти для драйверов, шрифтов и внутренних буферов. Принеобходимостиона вызывает _graphgetmemдля распределенияпамятии _graphfreemem для ее освобождения. По умолчанию данные подпрограммы просто вызывают malloc и free, соответственно.

Действиеэтих функций по умолчанию можно переопределить, определив собственные функции _graphgetmem и _graphfreemem. Благодаря этому вы можете сами управлять распределением памяти для графики. Однако, ваши варианты функций управления распределением памяти должны иметь те же имена: онизаменят собойфункции по умолчанию с теми же именами из стандартных библиотек С.

Определив собственные функции _graphgetmem и

_graphfreemem, вы можете получить предупреждение "duplicate

symbols" ("повторение символических имен"). Это предупреждение можно игнорировать.

Черчение и заполнение

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

Черчение:

arc Чертит дугу окружности.

circle Чертит окружность.

drawpoly Чертит контур многоугольника.

ellipse Чертит эллиптическую дугу.

getarccoords Возврашает координаты последнего вызова

arc или ellipse.

getaspectratio Возвращает коэффициент сжатия для текуще

го графического режима.

getlinesettings Возвращает текущий стиль линии, шаблон

линии и толщину линии.

line Чертит линию из (x0,y0) в (x1,y1).

linerel Чертит линию в точку, задаваемую относитель

ным расстоянием от текущей позиции (CP).

lineto Чертит линию из текущей позиции (CP) в (x,y).

moveto Перемещает текущую позицию (CP) в (x,y).

moverel Перемещает текущую позицию (CP) на относитель

ное расстояние.

rectangle Рисует прямоугольник.

setaspectratio Изменяет коэффициент сжатия по умолчанию.

setlinestyle Устанавливает ширину и стиль текущей ли

нии.

Заполнение:

bar Чертит и заполняет столбик.

bar3d Чертит и заполняет трехмерный столбик.

fillellipse Чертит и заполняет эллипс.

fillpoly Чертит и заполняет многоугольник.

getfillpattern Возвращает определяемый пользователем

шаблон заполнения.

getfillsettings Возвращает информацию о текущкм шаблоне

и цвете заполнения.

pieslice Чертит и заполняет сектор окружности.

sector Чертит и заполняет эллиптический сектор.

setfillpattern Выбирает шаблон заполнения, определяемый

пользвателем.

setfillstyle Устанавливает шаблон и цвет заполнения.

При помощи функций черчения и раскрашивания Turbo C++ вы можете вычерчивать цветные линии, дуги, окружности, эллипсы, прямоугольники, секторы, дву- и трехмерные столбики, многоугольники, а такжеразличные правильные или неправильные формы, являющиеся комбинациями перечисленныхграфических примитивов. Ограниченную форму изнутри или снаружи можно заполнить одним из 11 предопределенных шаблонов, либо шаблоном, определенным пользователем. Можнотакже управлять толщиной и стилем линии вычерчивания, а также местоположением текущей позиции (CP).

Линии и незаполненные формы вычерчиваются при помощи функций arc, circle, drawpoly, ellipse, line, linerel, lineto и rectangle. Затемможно заполнить эти формы с помощью floodfil, либо можно объединить вычерчивание/заполнение в одном шаге при помощи функций bar, bar3d, fillellipse, fillpoly, piesliceи sector. Функция setlinestyle позволяет задать стиль линий (играничных линий форм): толстая или тонкая, сплошная, пунктир и т.д., либоможно задать ваш собственный шаблондля вычерчивания линии. Можно выбрать предопределенный шаблон заполнения при помощи функции setfillstyle,либо определить собственный шаблон заполнения в setfill psttern. Функция moveto позволяетпереместить CP в желаемую позицию, афункция moverel позволяет сдвинуть ее на желаемую величину смещения.

Выяснить текущий стиль и толщину линии позволяет функция getlinesettings. Информацию о текущем шаблоне заполнения и цвете заполнителя можно получить через функцию getfillsettings; определяемый пользователем шаблон заполнения можно получить при помощи getfillpattern.

Получитьсведения о коэффициенте сжатия (коэффициенте масштабирования, применяемом графической системой для того, чтобы окружности выглядели круглыми) позволяет функция getaspectratio, а получить координаты последнейнарисованной дуги или эллипса - функция getarccoords. Если окружности не получаются идеально круглыми, можно исправить дело при помощи функции setaspectratio.

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

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

Манипуляции с экраном:

cleardevice Очищает экран (активную страницу).

setactivepage Устанавливает активную страницу для

графического вывода

setvisualpage Устанавливает номер визуальной графи

ческой cтраницы.

Манипуляции с графическими окнами:

clearviewport Очищает текущее графическое окно.

getviewsettings Возвращает информацию о текущем графи

ческом окне.

setviewport Устанавливает текущее графическое окно

для направления на него графического

вывода.

Манипуляции с битовыми образами:

getimage Записывает битовый образ в заданный участок

памяти.

imagesize Возвращает число байт, требуемых для хранения

некоторой прямоугольной области экрана.

putimage Помещает на экран ранее записанный в память

битовый образ.

Манипуляции с пикселями:

getpixel Принимает цвет пикселя в (x,y).

putpixel Помещает пиксель на экран в (x,y).

Помимо черчения и закрашивания, графическая библиотека предлягает несколько функций для манипулирования экраном, графическими окнами,образами и пикселями. Вызвав cleardevice, можно сразу очистить весь экран; данная подпрограмма стирает экран и помещает CP в графическое окно, но при этом оставляет действующими все прочие установки графической системы (стили линии, заполнения и текста; раскраска, установки графического окна и т.д.).

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

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

Можно взять часть экранного образа при помощи getimage, вызвать imagesize для вычисления числа байтов для хранения этого образа в памяти, а затем вернуть образ на экран (в любую желаемую позицию) с помощью функции putimage.

Координаты всех функций вывода (черчения, заполнения, тексты и т.д.) зависят от выбранного графического окна.

Можно также манипулировать цветомотдельных пикселей благодаря функциям getpixel (возвращающей цвет данного пикселя) и putpixel (которая отображает данный пиксель на экране заданным цветом).

Текстовый вывод в графическом режиме

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

gettextsettings Возвращает текущий текстовый шрифт,

направление, размер и выравнивание.

outtext Посылает строку на экран в текущую позицию

(CP).

outtextxy Посылает текст на экран в заданную позицию.

registerbgifont Регистрирует прикомпонуемый или

определяемый пользователем шрифт.

settextjustify Устанавливает значения выравнивания

текста, используемые outtext и outtextxy.

settextstyle Устанавливает шрифт, стиль и коэффициент увеличения текущего текста.

setusercharsize Устанавливает соотношение между высотой и шириной штриховых шрифтов.

textheight Возвращает высоту строки в пикселях.

textwidth Возвращает ширину строки в пикселях.

Графическая библиотека включает в себя матричный шрифт 8х8 и несколько штриховых шрифтовдля вывода текста вграфическом режиме.

- В матричном битовом шрифте каждый символ определяется как матрица пикселей.

- В штриховом шрифте каждый символ определяется как последовательность векторов, сообщающих графической системе, как создается данный символ.

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

В графике текст выводится функциями outtext или outtextxy, а управление его выравниванием (относительно CP) выполняет функция settextjustify. Вы должны выбрать символьныйшрифт,направление его размещения (горизонтальное или вертикальное) и размер (масштаб) при помощи функции settextstyle. Узнать текущие установки вывода текстов можно при помощи функции gettextsettings, которая возвращаеттекущий текстовый шрифыт, выравнивание, увеличение и направление в структуре textsettings. setusercharsize позволяет модифицировать ширину и высоту штриховых шрифтов.

Если средство отсечки включено, то выводимые функциями outtext и outtextxy текстовые строки будут отсекаться по границам графического окна. Если отсечка отключена, то тексты с матричным шрифтом, символы которыхне помещаются целиком в окне, отбрасываютсяполностью; в случае же штриховых шрифтов не поместившиеся тексты просто отсекаются по границе окна.

По умолчанию битовый 8х8 матричный шрифт является встроенным в графический пакет и поэтому всегда доступен во время выполнения. Штриховые шрифты все хранятся в отдельных .CHR-файлах; они могут загружаться во время выполнения или преобразовываться в .OBJ-файлы (при помощи утилиты BGIOBJ) и затем компоноваться с вашим .EXE-файлом.

Обычно подпрограмма settextstyle загружает файл шрифта, распределяя память для него и затем загружая с диска соответствующий .CHR-файл. В качестве альтернативы данной схеме динамической загрузки вы можете скомпоновать файл шрифта (или несколько таких файлов) непосредственно свыполняемым файлом программы. Для этого сначала требуется преобразовать .CHR-файл в .OBJ-файл (спомощью утилиты BGIOBJ - прочтите об этом в файле документации UTIL.DOC, который находится на дистрибутивном диске), а затем поместить в исходную программу вызовы registerbgifont (перед вызовом settextstyle) для того, чтобы зарегистрировать данный символьный шрифт(ы). При построении программы необходимо скомпоновать полученные .OBJ -файлы для всех зарегистрированных вами штриховых шрифтов.

Примечание

Использование registerbgifont относитсяк сложным методам программирования и не рекомендуется начинающим программистам. Более подробно эта функция описана в UTIL.DOC, который находится на дистрибутивном диске.

Управление цветом

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

Функции получения информации о цвете:

getbcolor Возврашает текущий цвет фона.

getcolor Возвращает текущий цвет вычерчивания.

getdefaultpalette Возвращает структуру определения палитры.

getmaxcolor Возвращает максимальное значение цвета,

доступное в текущем графическом режиме.

getpalette Возвращает текущую палитру и ее размер.

getpalettesize Возвращает размер просмотровой таблицы

палитры.

Функции установки одного или более цветов:

setallpalette Изменяет все цвета палитры, как задано.

setbkcolor Устанавливает текущий цвет фона

setcolor Устанавливает текущий цвет вычерчивания.

setpalette Изменяет один из цветов палитры, как

указано ее аргументами.

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

Пиксели и палитры

Графический экран представляет собой массив пикселей; каждый пиксель соответствует одной(цветной) точке на экране. Значение пикселя не задает точный цвет этой точки напрямую; насамом деле это некоторый индекс таблицы цветов, называемой палитрой. Каждый элемент палитры, соответствующий данномузначению пикселя, содержит точную информацию о цвете, которым будет отображен этот пиксель.

Такая схема косвенных обращений имеет множество следствий. Хотя аппаратное обеспечение может позволять отображение множества цветов, одновременно на экране может находиться только некоторое их подмножество. Количествоодновременно находящихся на экране цветов равно числу элементов палитры (размеру палитры). Например, EGA позволяет наличие 64 цветов, но лишь 16 из них может находиться на экране сразу; таким образом, размер палитрыEGA равен 16.

Размер палитры определяет диапазон значений, которые может принимать пиксель, от 0 до (размер-1). Функцияgetmaxcolor возвращает максимальное допустимое значение пикселя (размер-1) для текущего графического драйвера и режима.

При обсужденииграфических функций Turbo C++ мы часто используем термин "цвет", например текущий цвет вычерчивания, цвет заполнения и цвет пикселя. Фактическицветоммы здесь называем значение пикселя: это некоторый индекс в палитре. Только палитра реально определяет фактический цвет на экране.Манипулируя палитрой, выможетеизменять фактические цвета, выводимые на дисплей, даже хотя значения пикселей (цвета вычерчивания, заполнения и т.д.) могут не изменяться.

Цвет фона и вычерчивания

Цвет фона всегда соответствует значению пикселя 0. Когда выполняется очистка области экрана в цвет фона, это означает просто установку всех пикселей этой области в значение

0.

Цветомвычерчивания называется значение,в которое устанавливаются пиксели при вычерчивании линий. Цвет вычерчивания устанавливается функцией setcolor(n), где n есть допустимое для текущей палитры значение пикселя.

Управление цветом на CGA

Вследствие различий в графическом аппаратномобеспечении фактическое управление цветами различно для CGA и EGA,что заставляет нас рассмотреть их по отдельности. Управление цветом для драйвераAT&T, а также режимы низкой разрешающей способности драйвера MCGA аналогичны управлению цветом CGA.

В случае CGA вы можете выбрать либо режим низкойразрешающей способности (320х200), который допускает использование четырех цветов, либо режим высокой разрешающей способностей (640х200), где допускается использование двух цветов.

CGA в режиме низкой разрешающей способности

В режиме низкой разрешающей способности вы имеете возможность выбрать одну из четырех четырехцветных палитр. В каждой из этих четырех палитр вы можете сами установить только первый (цвет 0) элемент; цвета 1, 2 и 3 являются фиксированными. Первый элемент палитры (цвет 0) - это цвет фона. Этот цвет может являться одним из 16 имеющихся цветов (см. таблицу цветов фона, приводимую ниже).

Вы выбираете желаемую палитру, выбирая соответствующий режим (CGAC0, CGAC1, CGAC2, CGAC3); эти режимы используют палитры цветов от 0 до 3, соответственно, как показано в следующей таблице. Цвета вычерчивания в CGA и эквивалентные им константы определяются в graphics.h.

-----------------------------------------------------------

Константа, присвоенная номеру цвета (значению пикселя) Номер -------------------------------------------------- палитры 1 2 3

-----------------------------------------------------------

0 CGA_LIGHTGREENCGA_LIGHTRED CGA_YELLOW

1 CGA_LIGHTCYANCGA_LIGHTMAGENTA CGA_WHITE

2 CGA_GREENCGA_RED CGA_BROWN

3 CGA_CYANCGA_MAGENTA CGA_LIGHTGRAY

Для того, чтобы назначить один из этих цветов цветом вычерчивания CGA, нужно вызвать функцию setcolor, задав в ней в качестве аргумента либо номер цвета, либо имя соответствующей константы; например,если вы используете палитру3 и желаете назначить цветом вычерчивания cyan, то можно записать:

setcolor(1);

или

setcolor(CGA_CYAN);

В следующей таблице перечислены назначаемые для CGA цвета фона:

-----------------------------------------------------------

Числовое Символическое Числовое Символическое

значение имя значение имя

0

1

2

3

4

5

6

7

BLACK8 DARKGRAY

BLUE9 LIGHTBLUE

GREEN 10 LIGHTGREEN

CYAN 11 LIGTHCYAN

RED 12 LIGHTRED

MAGENTA 13 LIGHTMAGENTA

BROWN 14 YELLOW

LIGHTGRAY 15 WHITE

Цвета CGA для переднего плана те же, что находятся в данной таблице.

Для назначения одного изэтих цветов в качестве фонового цветаслужитфункция setbkcolor(цвет), где цвет - это один из элементов приведенной выше таблицы. Отметим, что для CGA цвет не является значением пикселя (индексом в палитре); он прямо задает фактический цвет, помещаемый в первый элемент палитры.

CGA в режиме высокой разрешающей способности

В режиме высокой разрешающей способности (640x200)CGA работает с двумя цветами - черным цветом фона и цветным передним планом. Пиксели могут принимать при этом значения только 0 или 1. В связи с особенностями CGA цветом переднего плана фактически является тот цвет, который аппаратное обеспечение считает цветом фона; таким образом, цвет переднего плана устанавливается подпрограммой setbkcolor. (Странно, но факт).

Цвет для переднего планаможет быть выбран из предыдущей таблицы. CGA далее будет использовать этот цвет для отображения им всех пикселей, имеющих значение 1.

Следующие режимы работают аналогичным оюразрм: CGAHI, MCGAMED, MCGAHI, ATT400MED и ATT400HI.

Подпрограммы управления палитрой в случае CGA

Поскольку палитра CGA является предопределенной, подпрограмму setallpaletteиспользовать в данном случае нельзя. Также не следует использовать setpalette(индекс, фактический _цвет), за исключением индекс=0. (Этоальтернативный способ установки фонового цвета CGA равным фактическому_цвету).

Управление цветом для EGA и VGA

В случае EGA палитрасодержит 16 элементов из общего количества 64 возможных цветов, причем каждый из элементов палитры можетбыть задан пользователем. Доступ к текущей палитре выполняется через getpalette, которая заполняет структуру, включающую всебя размер палитры (16) имассивфактических элементов палитры ("аппаратные номера цветов", хранимые в палитре). Элементы палитры можно изменять как по отдельностипри помощи setpalette, либо все сразу через setallpalette.

Палитра EGA по умолчанию соответствует 16 цветам CGA, которые были даны впредыдущей таблице цветов: черный равен элементу 0, голубой равен элементу 1, ... , белый равен элементу 15. В graphics.h определены константы, которые содержат соответствующие цветам аппаратные значения: это EGA_BLACK, EGA_WHITE и т.д.Эти значения могут быть также получены через getpalette.

Подпрограмма setbkcolor(цвет) на EGAработает несколько иначе, чем на CGA. На EGA setbkcolor копирует фактическое значение цвета, хранящееся в элементе #цвет, в элемент #0.

Что касается цветов, то драйвер VGA работает фактическитак же, как и драйвер EGA; он просто имеет более высокое разрешение (и меньшие по размеру пиксели).

Обработка ошибок в графическом режиме

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

grapherrormsg Возвращает строку с сообщением об ошибке для заданного кода ошибки.

graphresult Возвращает код ошибки для последней графической операции, в которой встретилась ошибка.

Если ошибка произошла при вызове графической библиотечной функции (например,не найден шрифт, запрошенный функцией settextstyle), устанавливается внутренний код ошибки. Доступ к коду ошибки для последней графической операции, сообщившей об ошибке, выполняется при помощи graphresult. Определены следующие коды возврата ошибки:

-----------------------------------------------------------

Код Константа Соответствующая строка

ошибки графической_ошибки с сообщением об ошибке


Информация о работе «Turbo C++ Programer`s guide»
Раздел: Информатика, программирование
Количество знаков с пробелами: 668870
Количество таблиц: 13
Количество изображений: 0

Похожие работы

Скачать
14945
0
7

... к сожалению, обратное утверждение не верно. C++ Builder содержит инструменты, которые при помощи drag-and-drop действительно делают разработку визуальной, упрощает программирование благодаря встроенному WYSIWYG - редактору интерфейса и пр. Delphi — язык программирования, который используется в одноимённой среде разработки. Сначала язык назывался Object Pascal. Начиная со среды разработки Delphi ...

Скачать
225728
6
0

... ориентированы на 32 разрядные шинные архитектуры компьютеров с процессорами 80386, 80486 или Pentium. Фирма Novell также подготовила варианты сетевой ОС NetWare, предназначенные для работы под управлением многозадачных, многопользовательских операционных систем OS/2 и UNIX. Версию 3.12 ОС NetWare можно приобрести для 20, 100 или 250 пользователей, а версия 4.0 имеет возможность поддержки до 1000 ...

Скачать
49224
0
9

... завдання поширюється на розробку системи обліку зареєстрованих автомобілів в ДАІ, призначеної для збору, зберігання, а також полегшення для доступу та використання інформації. Програма з обліку зареєстрованих автомобілів в ДАІ, представляє собою, перехід від паперових носіїв інформації до електронних. Система обліку зареєстрованих автомобілів значно допоможе працівникам ДАІ з обліку, аналізу та ...

Скачать
132529
1
5

... меньше времени и ответ клиенту агентство может дать уже в день подачи заявки. Каждая турфирма разрабатывает индивидуальный образец листа бронирования. Согласно Федеральному Закону «Об основах туристской деятельности в Российской Федерации» (гл. IV, ст. 9) – это конкретный заказ туриста или лица, уполномоченного представлять группу туристов, туроператору на формирование туристского продукта. ...

0 комментариев


Наверх