Текст
                    ПРОГРАММИРУЕМ НА ЯЗЫКЕ
Quick BASIC 4.5
Учебное пособие по курсам "Основы программирования",
"Информатика и вычислительная техника"


Григорий ЗЕЛЬДНЕР Программируем на языке QuickBASIC 4.5 Учебное пособие по курсам "Информатика и вычислительная техника", "Основы программирования" Москва ABF 1996
ББК 32.97 350 УДК 681.322-181.4.004.14 ЗЕЛЬДНЕР Григорий Алексеевич 350 Программируем на языке QuickBASIC 4.5 B-е издание, исправленное и дополненное) М. ABF, 1996. — 432 с: ил. ISBN 5-87484-059-1 Книга посвящена языку QuickBASIC 4.5 — наи- более популярному средству для обучения основам программирования в учебных заведениях России. Этот язык стал стандартом de facto для всех ком- пиляторов языка BASIC. Набор управляющих опера- торов и конструкций языка QuickBASIC поддержи- вают самые современные языки программирования компании Microsoft: Visual BASIC for Windows и Visual BASIC for Application. В легкой и непринужденной манере в книге рас- сказывается о среде программирования QuickBASIC, приводится описание всех операторов и функций языка, дается понятие о том, что такое хороший стиль программирования и как стать поклонником языка BASIC. Помимо преподавателей и учащихся, она будет полезна начинающим и опытным программистам, ра- ботающим с языком BASIC. 324О40Ш00^05О им 0Ш4@3) - 96 ISBN 5—87484—059—1 © Григорий Зельднер, 1996 Обложка Виктора Монетова
Содержание BASIC — НАДЕЖДА И ОПОРА 15 gwbasic — первое поколение языка 17 QuickBASIC — второе поколение языка 17 Visual BASIC — третье поколение языка 20 О ЧЕМ ЖЕ ЭТА КНИГА ? 21 1. СРЕДА ПРОГРАММИРОВАНИЯ 23 Программы и компьютеры 23 Интерпретатор + Компилятор = QuickBASIC 27 Начинаем работу... или что нужно для начала 28 Знакомимся со средой программирования 32 Как нам обустроить QuickBASIC (*) 47 Драйвер русских букв 47 Программы-оболочки 49 Переключатель Задач 50 2. ОСНОВЫ ЯЗЫКА BASIC 53 АЛФАВИТ ЯЗЫКА 53 ТИПЫ ДАННЫХ 55 Данные и их типы 55 Числовые типы данных 55 Символьные типы данных 56 Пользовательские типы данных (записи) 56 Константы 57 Неименованные константы 57 Именованные константы 58 Переменные 60 Имена переменных 60 Переменные числового типа 61 Переменные символьного типа 64 Переменные пользовательского типа данных 65 Переменные-массивы 67
Большие динамические массивы (*) 69 Выражения и операции 71 Арифметические операции 72 Возведение в степень (Л) 72 Присвоение знака числу (-) 72 Умножение и деление (*, /) 73 Целочисленное деление (\) 73 Нахождение остатка (MOD) 73 Сложение и вычитание (+,-) 73 Порядок вычисления выражений 74 Переполнение и деление на ноль 75 Операции отношения: 75 Логические операции 77 Функциональные операции 79 Строковые операции 80 Конкатенация (сложение) строк 80 Сравнение строк 80 Операторы передачи управления 81 Операторы цикла 81 FOR...NEXT 81 DO...LOOP 82 WHILE...WEND 82 Условные операторы 82 IF...THEN...ELSE 83 SELECT... END SELECT 83 Избегайте устаревших конструкций 83 Как получить код нажатой клавиши: 84 Как выйти из цикла по условию: 84 Как избежать синдрома "ёжика в тумане" 86 Как правильно "разветвиться" 87 ВВОД И ВЫВОД ЗНАЧЕНИЙ 88 Ввод значений 88 INPUT 89 LINE INPUT 90 INPUTS 90 Вывод значений 91 PRINT 91 PRINT USING 92 LPRINT и LPRINT USING 92 LOCATE 93 Почему BASIC не выговаривает русскую букву "р" 95 Модульное программирование (*) 96 Функция DEFFN 97 Процедура FUNCTION 98 Процедура SUB 99 Рекурсия 100 Границы использования переменных и констант 100 Глобальные переменные и константы 101 4
Локальные переменные и константы 101 Совместно используемые переменные 102 Переменные в функции DEF FN 102 Параметры в процедурах SUB и FUNCTION 103 Использование включаемых (INCLUDE) файлов 104 Построение многомодульной программы 106 Исходный текст на языке BASIC 106 Построение Quick-библиотеки 118 3. ОПЕРАТОРЫ ОПИСАНИЯ 121 CONST 121 DEFTnn : 122 DIM 123 REDIM 125 LBOUND 127 UBOUND 128 TYPE 128 OPTION BASE 129 COMMON 129 Использование именованного блока COMMON 131 COMMON и .EXE файлы 132 DATA 133 READ 133 RESTORE 134 4. ОПЕРАТОРЫ ПЕРЕДАЧИ УПРАВЛЕНИЯ 137 Операторы цикла 137 FOR...NEXT 137 WHILE... WEND 141 DO...LOOP 144 Проверка выражения в начале цикла: 144 Проверка выражения в конце цикла: 146 Условные операторы 149 IF...THEN...ELSE 149 Блочная форма 149 Линейная форма 150 Логика работы при блочной и линейной форме 150 SELECT...END SELECT 151 Подпрограммы 155 GOSUB...RETURN 155 Функции 156 DEFFN 156 Линейная форма 156 Блочная форма 156 Логика работы при блочной и линейной форме 157 5
Процедуры (*) 158 FUNCTION 158 Рекурсивные процедуры FUNCTION 159 SUB 160 Передача параметров в процедуры SUB и FUNCTION (*) 161 FUNCTION или SUB — проблема выбора (*) 163 Другие управляющие операторы 166 END 166 EXIT 167 STOP 168 SYSTEM 168 5. ВВОД-ВЫВОД НА ВНЕШНИЕ УСТРОЙСТВА 171 Клавиатура 171 INPUT 171 LINE INPUT 173 INPUTS 173 INKEYS 174 Экран 175 PRINT 175 PRINT USING 176 Форматы для вывода символьных значений 177 Форматы для вывода числовых значений 177 WRITE 179 LOCATE 180 CSRLIN 181 POS 181 SPC 182 TAB 182 WIDTH 183 Файлы 184 OPEN 184 CLOSE 187 RESET 187 GET 188 PUT 190 INPUT # 191 LINE INPUT* 192 INPUTS 193 PRINT #, PRINT # USING 194 WRITE 195 BSAVE 196 BLOAD 198 EOF 199 LOF 200 FIELD 200 LSET, RSET 203 D
FILEATTR 204 FREEFILE 205 IOCTL 206 IOCTLS 206 LOC 207 LOCK..UNLOCK 207 SEEK 209 SEEK 210 Принтер 212 LPOS 212 LPRINT, LPRINT USING 212 Порты 213 INP 213 OUT 214 OPEN COM ' 214 STICK 218 STRIG 219 WAIT 220 6. ГРАФИКА И ЗВУК 221 Графика 221 CLS 221 COLOR 222 Номера экранных цветов 223 Описание экранных режимов 223 PALETTE, PALETTE USING 225 PCOPY 227 SCREEN (функция) 228 SCREEN (оператор) 228 VIEW PRINT ; 229 VIEW 229 WINDOW 230 CIRCLE 231 LINE 233 PRESET 235 PSET 235 DRAW 236 Команды движения относительно текущей точки: 236 Команды установки угла, цвета и масштаба 237 Вызов подкоманды: 238 PAINT 238 GET 241 PUT 242 POINT 244 PMAP 246 3-Х МЕРНЫЕ ОБЪЕКТЫ В ТЕКСТОВОМ РЕЖИМЕ 247 7
Объемные кнопки 247 Рамки и тени 249 Поля для ввода данных 251 Библиотеки для работы с изображениями (*) 253 PCX Programmer's ToolKit 253 VEGX for QuickBASIC 255 Звук и музыка 257 BEEP 257 PLAY 257 Команды октавы и тона 257 Команды длительности и темпа 258 Переключения звучания на основное или фоновое 259 Вызов подкоманды: 259 SOUND 264 Работа с оцифрованным звуком (*) 266 QB SoundBlaster ToolKit 267 7. ПРОЧИЕ ОПЕРАТОРЫ ЯЗЫКА 269 SLEEP 269 REM 269 SWAP 271 ERASE 272 CLEAR 273 8. ВСТРОЕННЫЕ МАТЕМАТИЧЕСКИЕ ФУНКЦИИ И ФУНКЦИИ ОБРАБОТНИ ДАННЫХ 275 Математические функции 275 ABS 275 ЕХР 276 LOG 277 MOD 277 SGN 277 SQR 277 ATTM 279 COS 279 SIN 280 TAN 281 Секанс и другие 282 RANDOMIZE 283 RND 284 Функции обработки числовых и символьных данных 286 Функции округления 286 FIX 286 INT 286
Преобразование типов данных 287 CINT 287 CLNG 287 CSNG 287 CDBL 288 CHR$ 288 ASC 289 Упаковка данных 290 CVI, CVL, CVS ,CVD 290 MKI$, MKLS, MKSS, MKDS 290 Функции обработки символьных строк 293 LCASES 293 UCASES 293 LTRIM$ 294 RTRIMS 295 SPACES 295 STRINGS 296 INSTR 297 LEFTS 298 RIGHTS 299 MIDS (функция) 299 MIDS (оператор) 300 HEXS 301 OCTS 301 STRS 302 LEN : 302 9. ДОСТУП К АБСОЛЮТНЫМ АДРЕСАМ (*) ..305 DEFSEG 305 PEEK 305 POKE 306 SADD 306 SETMEM 307 VARPTR и VARSEG 307 VARPTRS 308 Доступ к клавишам-переключателям и модификаторам 309 10. ОТСЛЕЖИВАНИЕ СОБЫТИЙ, ОБРАБОТКА ОШИБОК И ТРАССИРОВКА (*) 313 Отслеживание событий 313 ONCOM(n) 313 СОМ(п) 313 ONKEY(n) 314 KEY 316 9
KEY(n) 318 ON PEN 319 PEN ON, PEN OFF, PEN STOP 319 ON PLAY(n) 320 PLAY 320 PLAY ON, PLAY OFF, PLAY STOP 321 ONSTRIG(n) 322 ONTlMER(n) 322 TIMER ON, TIMER OFF, TIMER STOP 322 ONUEVENT 323 UEVENT ON, UEVENT OFF, UEVENT STOP 325 Обработка ошибок и трассировка 325 ON ERROR 325 ERDEVh ERDEVS 327 ERLmERR 328 ERROR 328 RESUME 328 TRONhTROFF 329 11. СВЯЗЬ С DOS (*) 331 Передача управления другой программе 331 CHAIN 331 SHELL 332 RUN 333 Работа с датой и временем 335 DATES (функция) 335 DATES (оператор) 335 TIMES (функция) 336 TIMES (оператор) 336 TIMER 337 Работа с файловой системой 338 CHDIR 338 MKDIR 339 RMDIR 339 FILES 340 KILL 341 NAME 341 Работа с окружением DOS 342 COMMANDS 342 ENVIRON 343 ENVIRONS 344 12. РАСШИРЕНИЕ ВОЗМОЖНОСТЕЙ QuickBASIC 4.5(*) 345 ю
Работа с системными прерываниями в QuickBASIC 345 Ввод малой русской буквы "р" 348 Прокрутка текстового экрана.' 349 Интерфейс с драйвером мыши 353 Функция 0: Текущее состояние драйвера мыши 354 Функция 1: Включить курсор мыши 354 Функция 2: Погасить курсор мыши 354 Функция 3.: Прочитать координаты курсора и статус кнопок...355 Функция 4: Установить координаты курсора мыши 355 Функция 5: Прочитать статус нажатой кнопки 356 Функция 6: Прочитать статус отпущенной кнопки 357 Функция 7: Ограничить горизонтальное перемещение курсора. 357 Функция 8: Ограничить вертикальное перемещение курсора.. 358 ПРИЛОЖЕНИЯ 359 ПРИЛОЖЕНИЕ 1. Описание Главного Меню QuickBASIC 4.5 359 МЕНЮ FILE (ФАЙЛЫ) 359 NEW PROGRAM (Новая программа) 360 OPEN PROGRAM (Открыть программу) 360 MERGE (Объединение) 361 SAVE (Запись) 361 SAVE AS (Записать как...) 362 SAVE ALL (Записать все) 362 CREATE FILE (Создать файл ) 362 FILE LOAD (Загрузить файл) 363 FILE UNLOAD (Выгрузить файл) 364 PRINT (Печать) 364 DOS SHELL (Временный выход в DOS) 364 EXIT (Выход) 365 МЕНЮ EDIT (РЕДАКТИРОВАНИЕ) ...365 UNDO (Отменить) 366 CUT (Вырезать) 366 COPY (Копировать) 367 PASTE (Вставить через буфер) 367 CLEAR (Очистить) 368 NEW SUB (Новая процедура SUB) 368 NEW FUNCTION (Новая процедура SUB) 368 МЕНЮ VIEW (ПРОСМОТР) 369 SUBs (Процедуры) 369 NEXT SUB (Следующая процедура) 370 SPLIT (Разделение) 370 NEXT STATEMENT (Следующий оператор) 370 OUTPUT SCREEN (Выходной экран) 371 INCLUDED FILE (Включенный файл) 371 INCLUDED LINES (Включенные строки) 372 11
МЕНЮ SEARCH (ПОИСК) 372 FIND (Поиск) 372 SELECTED TEXT (Выделенный текст) 373 REPEAT LAST FIND (Повторить последний поиск) 373 CHANGE (Замена) 374 LABEL (Метка) 374 МЕНЮ RUN (ЗАПУСК) 375 START (Запуск) 375 RESTART (Перезапуск) 376 CONTINUE (Продолжить) 376 MODIFY COMMANDS (Изменить переменную COMMANDS) 376 MAKE EXE FILE (Сделать EXE файл) 377 MAKE LIBRARY (Сделать библиотеку) 377 SET MAIN MODULE (Установить главный модуль) 378 МЕНЮ DEBUG (ОТЛАДКА) 378 ADD WATCH (Добавить наблюдение) 379 INSTANT WATCH (Установить наблюдение) 380 WATCHPOINT (Точка наблюдения) 380 DELETE WATCH (Стереть наблюдение) 381 TRACE ON (Включить трассировку) 382 HISTORY ON (История включена) 382 TOGGLE BREAKPOINT (Точка прерывания) 382 CLEAR ALL BREAKPOINTS (Стереть все точки прерывания).... 383 BREAK ON ERRORS (Обрыв на ошибках) 383 SET NEXT STATEMENT (Установить следующий оператор) 384 МЕНЮ CALLS (ВЫЗОВЫ) 384 МЕНЮ OPTIONS (ОПЦИИ) 384 DISPLAY (Экран) 385 SET PATHS (Установить пути) 385 RIGHT MOUSE (Правая кнопка мыши) 386 SYNTAX CHECKING (Проверка синтаксиса) 386 FULL MENUS (Режим полного меню) 387 МЕНЮ HELP (ПОМОЩЬ) 387 HELP INDEX (Индекс помощи) 388 HELP TABLE of CONTENTS (Таблица содержания файлов помощи) 388 HELP TOPIC (Описание) 389 HELP on HELP (Справка о помощи) 389 ПРИЛОЖЕНИЕ 2. Запуск, редактирование И ОТЛАДКА ПРОГРАММЫ 389 Ключи запуска среды QB из командной строки DOS 389 Клавиши редактирования 390 Клавиши прокрутки текста 391 Клавиши выбора текста 391 Вставка, копирование и стирание текста 392 Клавиши просмотра 392 Клавиши поиска 393 12 Клавиши запуска и отладки 393
Клавиши помощи 393 ПРИЛОЖЕНИЕ 3. КОДЫ ОШИБОК 394 ПРИЛОЖЕНИЕ 4. Ограничения QuickBASIC 396 Имена, символьные строки и числа 396 Массивы 396 Процедуры и файлы 397 Редактирование 397 ПРИЛОЖЕНИЕ 5. ASCII-коды, Скан-коды 398 ASCII-коды 398 Символы псевдографики для рисования рамок и таблиц 400 Скан-коды клавиатуры 401 ПРИЛОЖЕНИЕ 6. Типы дисплеев и экранные режимы ... 402 Описание экранных режимов SCREEN 402 SCREEN 0 402 SCREEN 1 402 SCREEN 2 403 SCREEN 3 403 SCREEN 4 403 SCREEN 7 403 SCREEN 8 403 SCREEN 9 404 SCREEN 10 404 SCREEN 11 404 SCREEN 12 404 SCREEN 13 405 ПРИЛОЖЕНИЕ 7. Словарь зарезервированных слов 405 ПРИЛОЖЕНИЕ 8. Метакоманды 414 Метакоманды SSTATIC и SDYNAMIC 415 Метакоманда SINCLUDE 415 ПРИЛОЖЕНИЕ 9 416 Что почитать о языке BASIC 416 Журнал "Монитор" 416 Журнал "Мир ПК" 416 Журнал "Компьютер Пресс" 419 Журнал "Персональные программы" 420 Газета "СофтМаркет" 421 Книги издательства "ABF" 422 ИНДЕКС 423 13
BASIC — надежда и опора "BASIC-программисты — люди меченые, путем насилия или подкупа нас можно заставить работать на другом языке, но думать-то мы все равно будем на BASIC..." С. Г. Зиновьев Название языка программирования BASIC — это первые буквы английских слов Beginner's All-purpose Symbolic Instruction Code (Всецелевой язык программирования для начинающих). Впрочем, автор предпочитает другой перевод этого названия — на английском языке слово "basic" -^ означает основной, базо- вый. Недаром нашумевший триллер последних лет называется Basic Instinct. Созданный в начале 1960-х годов двумя профессорами Дарт- мунского университета Джоном Кенеми и Томасом Куртцом, BASIC превратился в современный язык высокого уровня, про- должая оставаться простым и доступным для всех пользовате- лей — от любителей до профессионалов. По словам президента фирмы Microsoft Билла Гейтса, BASIC переживет все другие язы- ки программирования. И жизнь подтверждает это утверждение. Сегодня BASIC — нет тот, что был еще 10 лет назад. Это по- стоянно развивающийся язык, снабженный всем необходимым для профессиональной разработки программ: поддержка модуль- ного и структурного программирования, эффективная среда раз- работки, создание исполняемых модулей, мощные средства от- ладки, встроенный HELP, дополнительные библиотеки процедур различного назначения — от пользовательского интерфейса до управления базами данных. При этом BASIC сохранил свою привлекательность для на- чинающих и непрофессиональных программистов, прежде всего, за счет более простой технологии работы в среде интерпретатора и наличия большого числа операторов высокого уровня (графика, обработка строковых переменных, работа с аппаратурой и пр.). BASIC — признанный лидер по скорости разработки и отладки программ. Это качество особенно требуется в тех многочислен- ных областях прикладных разработок, в которых знание предмет-
ной области является зачастую более важным, чем высокая ква- лификация программиста. Поколение интерпретаторов GWBASIC BASICA Поколение QuickBASIC QBASIC QuickBASIC 2.0, ЯО, 40,45 BASIC Compiler &0 Microsoft BASIC PDS 7.0,7Л. Поколение Visual BASIC Visual BASIC for DOS 10 Visual BASIC for Windows lo, 2.0, ao, 40,5.o На сегодняшний день BASIC — самый распространенный язык программирования для IBM PC. По данным журнала PC World свыше 70% программистов владеют тем или иным из диа- лектов BASIC. Но в чем же причина пренебрежительного отноше- ния к языку BASIC в среде так называемых "профессиональных" программистов? Дело в том, что в современной практике програм- мирования язык непосредственно связан со своим процессором (интерпретатором или компилятором), обрабатывающим его Так, например, тяжеловесность и громоздкость Turbo BASIC относится не к самому языку BASIC, а к его программной реализации фир- мой Borland, а ошеломляющий успех QuickBASIC следует отнести к интегрированной Quick-среде, появление которой привело к ре- волюционному перевороту в технике разработке программ. Разумеется, фирма Microsoft является не единственным разработ- чиком систем BASIC Существуют также версии GFA, True, Power, Z и некоторые другие, но они не получили столь широкое распростра- нение — отношение объема продажи языков BASIC фирмы Microsoft к реализациями BASIC остальных фирм составляет 12:1. Позволю себе кратко остановиться на трех поколениях языка BASIC фирмы Microsoft: 16
этот язык занял достаточно прочные позиции среди средств раз- работки серьезных прикладных систем. Фактически на сегод- няшний день QB стал стандартом de facto для языка BASIC. Первые версии QB появились в 1985 году, последняя, 4.5 — была создана в 1988. С точки зрения функциональных возможно- стей QB 4.5 практически идентичен предыдущей версии 4.0 A987 г.), но имеет более удобную среду программирования — мощный HELP и возможность управлению опциями среды (цвета, имена директорий и пр.). В QuickBASIC в достаточно полной мере реализованы идеи структурного и модульного программирования, возможности ис- пользования процедур и функций. Наряду с созданием механизма применения двоичных библиотек, а следовательно и готовых про- граммных модулей, в том числе, написанных на других языках, это обеспечило создание достаточно больших программных систем. Внешне непохожий на традиционный BASIC, QB в очень высокой степени обеспечивает совместимость на уровне исходно- го кода с предыдущими версиями (GW, BASICA, Turbo). Специфика технологии программирования с среде QB опре- деляется наличием в ней двух трансляторов — интерпретатора и компилятора. Основу интегрированной среды, в которой выпол- няется основной объем разработки и отладки программы, состав- ляет Интеллектуальный редактор и интерпретатор компилирую- щего типа (ИКТ). ИКТ — это новый тип интерпретатора, кото- рый производит предварительные "компиляцию и компоновку" программы в специальный псевдокод, а затем уже ее выполне- ние. При завершении отладки программы пользователь может со- здать исполняемый ЕХЕ-модуль с помощью настоящего компи- лятора и компоновщика программ. Именно использование интерпретатора определяет высокую производительность на этапе отладки программы. Запуск про- граммы на выполнение после исправления ее исходного текста происходит практически мгновенно. Проблемы тяжелого зависа- ния программы, после которого требуется перегрузка компьюте- ра, почти неизвестна пользователям QB. Что касается эффективности разработки программ (основные критерии — время разработки и возможность создания сложных комплексов), то QB имеет явные преимущества по сравнению с другими реализациями BASIC. Это относится к средствам отлад- ки, межязыкового общения, технологии конструирования про- грамм и пр. А ведь это и является основным достоинством BASIC-программирования. Кроме того, необходимо иметь в виду, что повышение эффективности конечного кода программы се- годня определяется не столько встроенными возможностями 18
языковой системы, сколько использованием дополнительных специализированных инструментальных средств (то, что обозна- чается термином "Add-on Products"). В QB практически отсутствует возможности по эффективной адаптации программ к конкретной конфигурации компьюте- ра — тип процессора, наличие/отсутствие сопроцессора, мо- дель памяти и пр. Эти вопросы решаются в его более поздних системах MS BASIC — PDS, Visual. Безусловно QB 4.5 в значительной степени сохраняет свою актуальность как средство обучения и-разработки программ на компьютерах класса АТ286 и ниже, которых в России еще дос- таточно много. Простая и компактная, по сравнению с совре- менными пакетами-монстрами, Quick-система может быть ре- комендована в качестве первого этапа работы для всех, кто начинает осваивать работу с семейством Microsoft BASIC. Косвенным признанием сохранившейся популярности систе- мы является и то, что несмотря на появление PDS и Visual- систем фирма Microsoft продолжает коммерческую реализацию QB 4,5 (мировая цена — 99$). Начиная с версии MS-DOS 5.0, вместо устаревшего GW- BASIC фирма Microsoft стала поставлять систему QBASIC, кото- рая представляет собой усеченный вариант QuickBASIC без ком- пилятора и некоторых возможностей модульного программиро- вания. Ее русифицированный вариант входит в состав соответ- ствующей локализованной версии MSDOS 5.0 и 6.x. QBASIC, конечно, может вполне использоваться для обуче- ния и написания небольших программок, но не для сколь-нибудь серьезной работы. И дело здесь не только в невозможности со- здавать исполняемые модули. В версии QBASIC программа может состоять только из одного модуля (отсутствует операция LOAD) и следовательно нельзя загружать и использовать ранее созданные модули. А на разработке по принципу "напиши по-новой всю программу от начала до конца" далеко, конечно, не уедешь. В 1989 году появилась Microsoft Basic Professional Develop- ment System (система для профессиональной разработки) версии 7.0 , а на следующий год ее сменила версия 7.1, коммерческую реализацию которой фирма Microsoft ведет до сих пор. В печати мелькали самые разнообразные сокращенные названия — Basic Compiler, Microsoft Basic, Professional Basic, QuickBASIC Extended. Сегодня ее называют Microsoft BASIC или просто PDS. Говоря о PDS 7.1, необходимо упомянуть также о версии Microsoft Basic 6.0 (иногда для нее используется термин Basic Compiler 6.0), ко- торая являлась некоторым тупиковым развитием среды версии 4.0, хотя там и были реализованы некоторые идеи, получившие 19
свое законченное воплощение в Basic PDS 7.1. PDS является дальнейшим логическим развитием QB 4.5 и в этом плане назва- ние QuickBASIC Extended (расширенный) вполне оправдано. Краткая характеристика Basic PDS, по сравнению с QB 4.5, заключается в следующем: он позволяет создавать более мощные программные комплексы и расширить круг решаемых задач за счет использования дополнительных возможностей процессора и оперативной памяти, новых средств разработки программ, встро- енной системы управления большими базами данных, а также повышения эффективности программного кода (объем памяти, быстродействие). Кроме новых возможностей, в PDS исправлены ряд ошибок QB, в частности, нет проблем с вводом прописной русской буквы "р". Visual BASIC — третье поколение языка Первая версия новой системы Visual BASIC (VB) появилась в 1991 году под лозунгом "теперь и начинающие программисты мо- гут свободно работать в Windows". Действительно, с точки зрения языка VB 1.0 даже не полностью поддерживал стандарт QB 4.5, в нем не было многих дополнительных возможностей PDS 7.1. Но не это было "изюминкой" продукта. Главное — реализация прин- ципиально новой логики программирования, причем в тогда еще довольно экзотической системе Windows. Другой базовой идеей VB/Win являлась возможность использования средств системы Windows в форме обращения к ее собственным функциям. Версия VB/Win 1.0 напоминала скорее действующий макет бу- дущей среды разработки. И действительно, система "мужала" до- вольно быстро, усиливаясь за счет как развития среды программи- рования, так и включения профессиональных элементов языка и проблемно-ориентированных средств. Уже в 1992 году была выпу- щена версия 2.0, а летом 1993 — 3.0. К 1995 году была готова вер- сия 4.0, а в конце 1996 ожидается следующая, 5-я. В 1992 году была также подготовлена система VB for DOS версии 1.0. В настоящее время фирма Microsoft поддерживает и развивает Visual BASIC, как одну из своих основных систем программирования, рассчитанную для массового и профессионального использования. Появление VB однозначно связано с популяризацией идей событийно-управляемого и визуального программирования в сре- де Windows. В связи с этим прежде всего необходимо отметить, 20
что эти методы программирования не являются достоянием толь- ко системы Windows. Наиболее простым примером этого факта является создание VB для DOS. Другое дело то, что в Windows, более мощной графической среде, эти методы получили возмож- ность более яркой реализации. Что касается визуального программирования, то это доста- точно логичное развитие среды программирования, в которую включены эффективные средства разработки пользователем диа- логового интерфейса. Его суть хорошо отражена в рекламе —"те- перь вы можете создать программу, не написав ни строки кода" (используя термины — "нарисовать", "передвинуть" и пр.). Оценивая в целом новые идеи программирования, заложенные в VB, необходимо отметить, что они касаются в основном проблемы диалогового интерфейса — проблемы важной, но далеко не един- ственной при разработке программ. Причем надо иметь в виду, что по мере роста сложности программы основной объем работы пере- мещается именно в направлении создания ее прикладной начинки. Что касается самого языка, то VB является развитием QuickBASIC, в значительной степени (VB/DOS — полностью) обеспечивая совместимость "снизу-вверх". Более того, несмотря на появление новых операторов, в принципе это тот же вариант язы- ка программирования, с его некоторыми принципиальными огра- ничениями. Это в первую очередь касается того, что он по- прежнему остается процедурным, но не объектно-ориентирован- ным языком. Появление термина OBJECT (объект) в VB в данном случае вносит некоторую путаницу в представления пользователей, т.к. в здесь речь идет лишь о элементах управления диалогового интерфейса (достаточно узком классе общего понятия "объект"). Но что же требуется от программиста, имеющего навык работы с предыдущими версиями BASIC фирмы Microsoft для полноценно- го использования новых возможностей, предоставляемых версией Visual? Ни много ни мало — изучить новый язык. Именно новый, поскольку объектные конструкции Visual интерфейса мало похожи на "человеческий язык", столь милый сердцу приверженцев BASIC, а более напоминают "инопланетные" конструкции С или Pascal. О чем же эта книга ? Речь в ней пойдет о системе программирования Quick-BASIC версии 4.5 (в дальнейшем просто BASIC), выпущенной в свет в 1988 году, вы можете спросить, стоит ли работать на версии восьмилетней давности? Да, несомненно стоит. Начните хотя бы 21
потому, что овладев этой системой, вы без труда освоите более сложные версии — от Microsoft BASIC Professional Development System 7.1 (Система Microsoft BASIC для профессиональной раз- работки — тема следующей книги1) до Visual BASIC for Windows 5.0 (визуальный BASIC для Windows — впрочем автор отнюдь не является поклонником всяческих "форточек", предпочитая ус- пешно работать в старой доброй DOS). Все реализации BASIC фирмы Microsoft имеют сходный интерфейс, набор команд и, что самое главное, исходные тексты Ваших программ могут быть лег- ко перенесены в другие реализации BASIC фирмы Microsoft. Сила языка BASIC заключается в том, что любую мысль можно просто и ясно изложить, используя встроенные средства программирования, а если их недостаточно — из BASIC всегда можно обратиться к прерываниям DOS или подключить библио- теку на ассемблере или на другом языке. Все это будет описано в книге в соответствующих главах. Начните работать с языком BASIC — и вы не откажитесь от него никогда. Глава первая "Среда программирования" вводит вас в увлека- тельный мир языка QuickBASIC. Вторая глава "Основы языка" дает общее представление о BASIC как языке программирования. Главы с 3 по 11 подробно рассказывают о операторах, функ- циях и структурах языка, сгруппированных по функциональным группам. Глава 12 посвящена работе с прерываниями DOS, расширя- ющих стандартные средства QuickBASIC. В приложениях подробно рассказано о клавишах запуска, редактирования, отладки программы, ограничениях QuickBASIC, кодах ошибок, другой литературе, посвященной языку BASIC. Книга составлена таким образом, что может быть использо- вана и как учебник по языку BASIC для начинающих, и как справочник для более опытных пользователей. Те разделы, кото- рые можно опустить при первом чтении книги, помечены симво- лом (*) — это значит, что к ним можно вернуться позднее. Автор выражает свою признательность координатору ассоци- ации пользователей Microsoft BASIC Андрею Александровичу Колесову за ряд ценных замечаний по содержанию рукописи этой книги, а также за любезное разрешение воспользоваться материалами по истории развития языка BASIC. 1 "Microsoft BASIC Professional Development System 7.1", M. ABF, 400 с "Библиотеки языка BASIC", M. ABF, 400 с. 22
СРЕДА ПРОГРАММИРОВАНИЯ "BASIC — это питон, пожирающий все на своём пути. BASIC только что закончил "переваривать" язык PASCAL со всеми его уп- равляющими структурами. После небольшой паузы и нескольких отрыжек он будет в состоянии "слопать" PROLOG, так что скоро мы увидим варианты языка BASIC со встроенным механизмом до- казательства теорем методом резолюций ..." Р. Форсайт Программы и компьютеры... Любое электронное устройство, построенное человеком, вы- полняет одну общую функцию — преобразование информации в том или ином виде. Но до изобретения персонального компьютера каждое устройство выполняло только одну, изначально заложен- ную в нем функцию. Разговаривая по телефону, вы могли только мечтать увидеть лицо собеседника, смотря телевизор — иметь воз- можность получить фотографию понравившейся "звезды", а слу- шая магнитофонную запись — составить собственную программу из понравившихся песен. Напротив, персональные компьютеры — это устройство для универсальной обработки информации — достаточно только напи- сать точную инструкцию (последовательность) тех действий, кото- рые нам нужны. Словесное описание таких действий называется алгоритмом, а сама последовательность действий носит название программы. Совокупность программ — программное обеспечение.
Существует несколько категорий программ, границы между которыми достаточно условны, но принято выделять три боль- шие группы программного обеспечения: • Системные программы — выполняют вспомогательную роль: уп- равление ресурсами компьютера, передача команд на перифе- рийные устройства, сервисное обслуживание, например копиро- вание файлов, создание резервных копий, проверку работоспо- собности компьютера в целом или отдельных его частей. • Прикладные программы — это те, с которыми пользователь сталкивается каждый день — программы редактирования тек- стов, графические редакторы для подготовки иллюстраций, бухгалтерские программы для ведения хозяйственного учета и многие другие. Это самый многочисленный класс программ- ного обеспечения. • Системы программирования — наиболее интересный класс программного обеспечения. Ведь именно с помощью систем программирования создаются новые программы. Об одной из таких программ — QuickBASIC 4.5 рассказывается в этой книге. При наличии десятков тысяч прикладных программ, каждый из нас сталкивался с ситуацией, когда существующие программы его не удовлетворяют, или делают что-то недоста- точно быстро или неэффективно. В этой ситуации един- ственный выход — написание собственной программы. Программы дт персональных компьютеров Системные программы I Прикладные программы Системы программирования 24
...Давным-давно, когда DOS 3.20 еще была новинкой, a IBM и Microsoft были друзьями, автору попался электронный вариант книги Р. Джордейна "Справочник программиста IBM PC". Она занимала на диске более 500 КВ и сразу же возник вопрос: как ее распечатать. Это сейчас есть "русский народный текстовый про- цессор "Лексикон" имени Е. Веселова" , запросто решающий эти проблемы, а в те времена он еще только завоевывал заслуженную славу. Сложность заключалась в том, что имелась рулонная бума- га, и надо было распечатать текст так, чтобы сгибы листов были пропущены. Под рукой у автора имелся только горячо любимый BASIC (тогда еще QuickBASIC 4.0). Данная программа приведена ниже. Она печатает 63 строки на странице, а затем — 8 пустых строк. С косметическими изменениями, под названием "Форматель" она благополучно дожила до наших дней. 1 все переменные целые DEFINT A-Z 1 определяем константы: 'число строк на странице = 63, пустых строк = 8 CONST LinesOnP'age = 63, BlankLines = 8 'определяем Счетчик страниц Count = 1 'устанавливаем черный цвет символов на бирюзовом 'фоне и очищаем экран COLOR 0, 3: CLS 1 выводим на экран список всех файлов с расширением '"bas", после этого выводим на экран пустую строку FILES "*.bas": PRINT 'Вводим имя файла и выводим на экран пустую строку 1 а также напоминание о начале печати и ждем 1 нажатия любой клавиши INPUT "Введите, имя файла "; Filename$: PRINT PRINT "Установите сгиб у печатающей головки принтера..." DO: LOOP WHILE INKEY$ = "": PRINT 1 открываем файл для считывания OPEN Filename$ FOR INPUT AS #1 'начинаем бесконечный цикл DO-LOOP. Выход из него по 'наступлению конца файла DO FOR i = 1 ТО LinesOnPage 'проверяем не наступил ли конец файла, 'и если наступил, то уходим отсюда IF EOF(l) THEN EXIT DO 'считываем строку из файла и выводим на 25
"печать оператором LPRINT LINE INPUT #1, line$: LPRINT line$ NEXT i FOR i = 1 TO BlankLines 1 печатаем заданное количество пустых строк 1 чтобы пропустить сгиб листа LPRINT NEXT i LOOP 'очистим экран, закроем файл и закончим программу CLOSE #1: CLS : END Таких примеров можно привести множество. "Невозможно объять необъятное", и поэтому всегда возникают ситуации, когда готовые программы не обеспечивают тех возможностей, без кото- рых их эксплуатация бессмысленна. Еще один пример. До "полной и окончательной победы" альтернативной кодировки символов, в которой русским буквам соответствуют символы с кодами 128-175 и 224-241, существовала так называемая основная кодировка ГОСТ (русские буквы 176- 241), в которой на месте символов псевдографики были русские буквы. Для экрана можно было подобрать подходящий русифи- катор, но что делать, если надо распечатать текст, набранный в альтернативной кодировке на принтере, в котором "зашита" ос- новная кодировка7 Конечно, написать маленькую программу! 1 все переменные целые DEFINT A-Z 'открываем файл с текстом OPEN "ascil.doc" FOR INPUT AS #1 'читаем строки из этого файла, пока он не кончится WHILE NOT EOF(l) LINE INPUT #1, AlterLine$ 1 определяем длину этой строки AlterLen = LEN(AlterLme$) 1 открываем цикл и проверяем каждый символ в строке 'при необходимости перекодируем и присваиваем 'переменной OsnLme$ OsnLine$ = "" FOR i = 1 ТО AlterLen Symbol = ASC (MID$ (AlterLme$, i, 1)) SELECT CASE Symbol CASE 128 TO 17 5 'это символы от А до п OsnLme$ = OsnLme$ + CHR$ (Symbol + 48) CASE 176 TO 223 'это символы псевдографики 26
OsnLme$ - OsnLme$ + " " CASE ELSE 'иначе перекодирование не нужно OsnLme$ = OsnLine$ + CHR$ (Symbol) END SELECT NEXT l 'печатаем строку символов LPRINT OsnLme$ WEND 1 закрываем файл, очищаем экран и заканчиваем программу CLOSE #1: CLS : END А если любопытный читатель, прочитав эту книгу, возьмется за написание собственной программы — автор будет считать свою задачу выполненной. Интерпретатор + Компилятор = QuickBASIC Чтобы компьютер мог понять написанную программу, она должна быть переведена в так называемые машинные коды — язык, понятный самому процессору (впрочем некоторые про- граммисты могут читать машинные коды так же легко, как про- граммы на BASIC). Этот процесс перевода называется трансляци- ей. Существует два различный подхода к трансляции — интер- претация и компиляция. Языки программирования интерпретирующего типа при ис- полнении программы за один проход переводят в машинные ко- ды одну строку программы. Понятно, что при большом размере программы процесс исполнения готовой программы занимает до- вольно много времени. В тоже время при разработке программ режим интерпретации очень удобен — любое внесенное измене- ние сразу же переводится в машинные коды и исполняется. Языки компилирующего типа, напротив, сначала переводят весь текст программы в машинные коды, а уже затем полученный файл может быть запущен на выполнение. Понятно, что отком- пилированная программа выполняется гораздо быстрее (в 5-10 раз), но при наличии ошибок редактирование, компилирование, исправление ошибок на этапе компиляции, опять редактирова- ние, и так до тех пор, пока все ошибки не будут устранены, за- нимает очень много времени при разработке программ. Интерпретатор можно сравнить с синхронным переводчиком (транслятором) — вы слышите перевод сразу же, а компилятор — 27
с переводчиком, скажем, художественной литературы, — вы чи- таете книгу сразу на понятном языке, что более удобно, чем пе- реводить книгу строка за строкой. Что же мы имеем в результате? И интерпретатор и компи- лятор имеют и свои достоинства и недостатки. Но теперь у нас есть QuickBASIC — уникальная среда программирования, сочетающая в себе достоинства и интерпретатора и компиля- тора одновременно! В нем содержатся два транслятора. При подготовке програм- мы интерпретатор компилирующего типа (ИКТ) выполняет каж- дую команду почти также быстро, как если бы программа была скомпилирована. Дело в том, что при вводе текста Ваша про- грамма переводится в псевдокод сразу же, как только вы перево- дите курсор на другую строку, и к тому времени, как вы собирае- тесь запустить программу на выполнение — она уже готова для работы. Законченные программы могут быть скомпилированы в автономные .ЕХЕ программы либо внутри Quick-BASIC, либо из отдельного компилятора, управляемой из командной строки DOS. Начинаем работу... или что нужно для начала Пакет QuickBASIC записан на 5 дискетах по 360 КВ. Для ус- тановки его на жесткий диск необходимо запустить программу SETUP.EXE, которая находится на первом диске под названием "Setup/Microsoft QB Express" Для своей установки Microsoft QuickBASIC милосердно тре- бует всего 1.8 М на жестком диске, что навевает тоску по тем славным временам, когда фирма Microsoft оправдывала лозунг: I Не Microsoft, а маленькие программы по-русски! | Представьте себе: Следующая версия языка — Microsoft BASIC PDS 7.1 требует для своей установки 14 MB, а последняя версия — Visual BASIC for Windows 5.0 "изволит откушать" как минимум 60 Mb от Вашего диска, да еще потребует процессор Pentium с тактовой частотой не ниже 133 для нормальной работы. Ах "форточки", "форточки"... 28
Microsoft (R) QuickBASIC 4.50 Setup Progran Copyright (C) Microsoft Corp 1988. fill rights reserved. Setup uill install QuickBASIC on your systen by » Copying progran files ¦ Setting display options ¦ Copying needed systen files Note: QuickBASIC requires up to 1.8 Megabytes on your hard disk. If you need to free up sone disk space before proceeding, exit nou. When you're ready Use UP and DOUN arrou keys to highlight your choice, then press ENTER, or Just type the letter that appears to the right of your selection. Программа установки запишет следующие файлы: EXAMPLES\ ADVR_EX\ qb. exe qb.ini qb.plf qb.bi qb.qlb qb.lib be.exe Директория, где находятся файлы с примерами, иллюстрирующие возможности Quick-BASIC Директория, где находятся файлы для системы оперативной подсказки Среда для разработки программ Microsoft QuickBASIC (QB) Файл конфигурации среды Файл для запуска QB из под "Windows" Включаемый файл для работы с системными вызовами DOS Quick-библиотека, содержащая процедуры под- держки системных вызовов DOS в среде QB Библиотека для компиляции программ, содер- жащих системные вызовы DOS Компилятор BASIC Compiler, вызываемый ко- мандой "Маке ЕХЕ Н1е"(Сделать ЕХЕ Файл), может также запускаться из командной строки DOS 29
lib.exe link.exe brun45.lib bcom45.lib bqlb45.1ib brun45.exe noem.obj smallerr.obj qb45qck.hlp qb45ener.hlp qb45advr.hlp demol.bas demo2.bas Программа Microsoft Library Manager служит для создания библиотек (.LIB), необходимых исполняемым файлам Компоновщик Microsoft Overlay Linker служит для создания исполнимых файлов и Quick- библиотек (QLB) Библиотека времени выполнения для создания исполняемых файлов. Файлы, созданные с ис- пользованием этой библиотеки требуют для своей работы BRUN45.EXE (EXE requiring BRUN45.EXE) Альтернативная библиотека времени выполне- ния для создания исполняемых файлов. Файлы, созданные с использованием этой библиотеки не требуют BRUN45.EXE для своей работы. (Stand-Alone EXE file) Библиотека с процедурами поддержки, исполь- зуемых при создании Quick-библиотек Библиотека для работы исполняемых файлов, откомпилированных с опцией "EXE requiring BRUN45.EXE" (EXE (NO EMulation) При компоновке программ с этим объектным файлом из получаемого исполнимого файла удаляется эмуляция математического сопро- цессора, поэтому полученная программа будет ра- ботать только на машине с сопроцессором, но зато уменьшается размер исполнимого файла Файл для компоновки программ, которые не тре- буют детальных сообщений при ошибках выпол- нения, что сокращает размер исполнимого файла Файлы оперативной подсказки Файлы оперативной подсказки Файлы оперативной подсказки Демонстрационная программа звуковых эффек- тов, написанная для BASICA Та же программа, написанная для QuickBASIC 2.0 30
demo3.bas remline.bas torus.bas sortdemo.bas qcards.bas qcards.dat mouse.com Она же, но для QuickBASIC 4.0 (и выше) Программа на QuickBASIC, которая удаляет не- нужную нумерацию строк из программ на BASICA (в QuickBASIC нумерация строк НЕ нужна) Графическая демонстрационная программа, ис- пользующая переопределение цветовой палитры Программа, иллюстрирующая различные алго- ритмы сортировки Служебный файл обучающей системы Служебный файл обучающей системы Драйвер "мыши" Microsoft Mouse После окончания установки QuickBASIC вы можете запус- тить довольно милую обучающую программу LEARN.COM, ко- торая находится на первом диске "Setup/Microsoft QB Express" 1_[ > Press PgDn to continue. QuickBASIC Express поможет получить первое представление о работе в среде QB, расскажет о порядке запуска QB, покажет основные компоненты среды, научит загружать, редактировать, и выполнять программу, сохранять результаты работы. 31
Знакомимся со средой программирования Для запуска среды программирования QuickBASIC 4.5 перей- дем в директорию C:\QB45 и запустим файл QB.EXE. Нашему взору предстанет картинка, подобная той, что изображена на ри- сунке ниже. Среда QB может работать в двух режимах: Режим сокращенного меню — (о нем, в частности, рассказыва- ет обучающая программа), который больше подходит для бег- лого знакомства со средой, так как в нем опущены многие важные пункты меню, такие как работа с модулями, с quick- библиотеками, урезано меню "DEBUG" (ОТЛАДКА) и т. д.; Режим полного меню — о котором повествует эта книга. Когда этот режим включен, то в меню "OPTION" (ОПЦИИ) в пун- кте "Full Мепи"(Полное меню) стоит точка " • " Для включе- ния режима полного меню нажмите комбинацию клавиш 32
{ALT-O, F}. Для этого нажмите клавишу {ALT}, затем, не от- пуская ее, клавишу с буквой {О} (здесь и далее при работе с меню подразумевается нажатие клавиш с латинскими буква- ми). Отпустите обе клавиши и нажмите клавишу с буквой {F}. 1. Строка Главного Меню. Имена означают соответствующее меню. Чтобы войти в нужное меню нажмите клавишу {ALT} и соответствующую букву меню или подведите курсор "мыши" и нажмите правую кнопку; 2. Курсор. Он показывает, в каком месте будет напечатан следу- ющий вводимый символ. Может выглядеть как мигающий символ подчеркивания "_" (режим вставки — вновь вводимые символы раздвигают уже напечатанные) или как мигающий прямоугольник " " (режим замещения — вновь вводимые сим- волы затирают уже напечатанные); 3. Рабочее окно. Именно в рабочем окне вводится и отлаживает- ся текст программы. При разработке большой программы иногда может оказаться полезным работать с двумя частями программы одновременно. Нажмите {ALT-V, Р} (меню "VIEW" (ПРОСМОТР), пункт "Split" (Разделение) и рабочее окно разделится на два, в каждом из которых можно работать со своей частью программы. Для перехода между разделен- ными окнами и окном для немедленного выполнения служат клавиши {F6} и {SHIFT-F6}; 4. Строка заголовка. Содержит имя файла (или процедуры), ко- торый находится в рабочем окне. Чтобы сменить процедуру или модуль нажмите клавишу {F2}. 5. Курсор манипулятора "мышь". Показывает экранную позицию "мыши". С помощью мыши также можно работать с меню. Чтобы открыть меню, подведите курсор мыши к нужному пункту Главного меню и нажмите правую кнопку мыши. При работе с текстом программы нажатие левой кнопки "мыши" вызывает контекстную подсказку на тот оператор BASIC, на который указывает "мышиный" курсор (впрочем, гораздо удобнее нажать клавишу {F1}). 6. Указатель увеличения. Распахивает рабочее окно на весь эк- ран. Предназначен только для работы с "мышью" и практи- ческого значения не имеет. 7. Указатель прокрутки. Показывает относительное место курсо- ра в модуле или процедуре. Если текст модуля или процедуры достаточно длинный, то указатель прокрутки можно переме- 33
щать "мышью". Смысл этого перемещения примерно такой, какой бывает, когда открываешь толстую книгу "на глазок" — указатель прокрутки выполняет роль большого пальца. Под- ведите "мышиный" курсор к указателю прокрутки, нажмите правую кнопку "мыши", и, не отпуская ее, перемещайте кур- сор по линейке прокрутки вверх или вниз. Аналогичные кла- виатурные команды гораздо приятнее — можно просто не- сколько раз нажать клавишу {PGDN} или {PGUP}. А для пе- рехода в начало текста модуля или процедуры — {CTRL- HOME}, в конец - {CTRL-END}) 8. Линейки прокрутки. Предназначены для передвижения указа- теля прокрутки; 9. Окно для немедленного выполнения (Immediate). Для входа в него нажмите клавишу {F6}. Операторы BASIC сразу выпол- няются после нажатия клавиши {ENTER}. Очень удобно ис- пользовать при отладке: оборвав выполнение программы, можно изменить значение какой-либо переменной, и пустить программу дальше, либо проверить правильность выполнения небольшого участка кода. Это идеальное место для экспери- ментов с цветом или музыкой — введите в окне Immediate следующий фрагмент и нажмите {ENTER} — "тоска по нос- тальгии" сразу охватит вас: PLAY Mtl20o218g4.p8g>c4<g.ab4e.ea4g.fg4c." PLAY "cd4d.ef4f.g7a4b.>cd2" Вы заинтересовались? Тогда продолжение: PLAY "<g>e4d.cd4<g.g>c4<b.ab4e.ea4g.fg4c.c>c4<b.ag2" 10. Строка контекстных подсказок. Показывает текущие значения функциональных клавиш. 11. Индикаторы нажатия специальных клавиш: AQ — Появляется, когда вводится последовательность команд редактора WordStar. AK — Появляется, когда устанавливается маркер места. ЛР — Появляется, когда вводятся специальные управ- ляющие символы. 12. Индикаторы нажатия клавиш-переключателей: С — Появляет- ся, когда нажата клавиша CAPSLOCK. N — Появляется, ког- да нажата клавиша NUMLOCK. 13. Счетчик строк и столбцов. Показывает текущую позицию кур- сора в активном окне. 34
При работе со средой QB можно использовать "мышь". Что- бы указать пункт меню, можно подвести к нему курсор "мыши" и нажать правую кнопку. Но удобнее использовать клавиатуру. Нажатие клавиши {ALT} и первой буквы меню вызывает его от- крытие, а для перемещения по диалоговым окнам (например при загрузке файла или при его сохранении служат клавиши {TAB} (движение вперед) и {SHIFT}{TAB} (движение назад). Для наиболее часто используемых операций можно исполь- зовать клавиатурные сокращения: {ALT-F, S} {ALT-F, Ц {ALT-F, U} {ALT-F, X} {ALT-R, X} {F1} {F2} {F4} {SHIFT-F5} {CTRL-BREAK} {F5} {SHIFT-F9} {F9} Сохранение файла программы; осуществляет выбор пункта "Save"Canncb) из меню "FILE" (ФАЙЛЫ); Загрузка файла или документа; осуществляет выбор пункта "Load File "(Загрузить Файл) из меню "FILE" (ФАЙЛЫ); Выгрузка файла или документа; осуществляет выбор пункта "File Unload"(Выгрузить файл) из меню "FILE" (ФАЙЛЫ); Выход из среды QB; осуществляет выбор пун- кта "ЕхН"(Выход) из меню "FILE"^AKJIbI); Сделать исполнимый файл; осуществляет Вы- бор пункта "Маке ЕХЕ РИе"(Сделать ЕХЕ Файл) из меню "RUN"CAnyCK) Получение помощи; Вызвать список процедур и функций; Посмотреть на результат работы программы; Запуск программы на выполнение; Прервать выполнение программы; Продолжить выполнение после остановки Установить/снять точку наблюдения; Поставить/убрать точку прерывания 35
Кратко перечислю назначение пунктов меню: МЕНЮ FILE (ФАЙЛЫ) — используется для создания новой программы, загрузки и сохранения программ или частей про- грамм, печати файлов или частей файлов, использования команд DOS, выхода из среды QB; МЕНЮ EDIT (РЕДАКТИРОВАНИЕ) - используется для стирания, копирования или передвижения текста программы, отмены последних изменений, создания новой процедуры (SUB) и функции (FUNCTION); МЕНЮ VIEW (ПРОСМОТР) — используется для просмотра процедур (SUB) и функций (FUNCTION), включаемых (INC- LUDE) файлов, экрана программы; МЕНЮ SEARCH (ПОИСК) — предназначен для поиска или замены названий переменных, меток или фрагментов исходного текста в активном окне, в текущем модуле или во всех загружен- ных модулях; МЕНЮ RUN (ЗАПУСК) — используется для исполнения загруженной программы, продолжения выполнения прерванной программы, очистки переменных в памяти перед выполнением, создания исполняемого (.ЕХЕ) файла, определения главного мо- дуля в многомодульной программе. МЕНЮ DEBUG (ОТЛАДКА) - используется для отладки программы путем открытия окон наблюдения, которые показы- вают, как переменные изменяются при работе программы, уста- новки точек прерывания, которые прерывают выполнение про- граммы для того, чтобы вы смогли просмотреть значения пере- менных. Сам термин "debug" в дословном переводе означает "обезжучивание". Он пришел со времен ламповых ЭВМ, когда инженеры не могли отладить программы из-за того, что какой-то таракан забрался в шкаф с электронной начинкой машины и замкнул выводы одной из радиоламп. МЕНЮ CALLs (ВЫЗОВЫ) — меню CALLs показывает после- довательность вызова процедур из других процедур (стек вложенных процедур). Если программа не использует вызовы процедур из дру- гих процедур, то в меню CALLs выводится только имя главного мо- дуля программы и имя текущей вызываемой процедуры. МЕНЮ OPTIONS (ОПЦИИ) — используется для: настройки цветов экрана, установки путей для поиска служебных файлов, переопределения правой кнопки мыши, Включения/выключения 36
режимов Full Menus (Полное Меню) и Syntax Checking (Проверка Синтаксиса) МЕНЮ HELP (ПОМОЩЬ) — Используется для получения справки по ключевым словам языка BASIC, информации по язы- жу программирования QuickBASIC, контекстно-зависимой помо- щи, основанной на месторасположении курсора, дополнительных инструкций по получению помощи. Более подробно о каждом из пунктов меню рассказано в Приложении 1 "Описание Главного Меню QuickBASIC 4.5". На примере простой программы познакомимся с работой среды QB. Встроенный редактор среды QB обладает всеми ос- новными свойствами редактора текстов, а кроме того, является Интеллектуальным редактором, так как проверяет синтаксис каждой строки текста, после того, как вы ее введете. Если син- таксис верен, то строка переводится в псевдокод сразу же, в про- тивном случае появляется описание возникшей ошибки. Редак- тор также переводит все ключевые слова в заглавные буквы и ис- правляет некоторые ошибки и опечатки. Например, если при вводе строковой константы в операторе PRINT была пропущена вторая кавычка, то редактор автоматически ее поставит. Введем следующий текст. Регистр букв, в котором набирается программа, значения не имеет. После каждой строки нажимайте клавишу {ENTER}. CLS LOCATE 20, 1 PRINT "Добро пожаловать в QuickBASIC 4.5 !" В первой строке производится очистка экрана оператором CLS (сокращение от слов CLEAR SCREEN — очистить экран). Во второй строке — курсор устанавливается на 20 строку, 1 столбец (от слова LOCATE — разместить. В текстовом режиме экран делится на 25 строк, а каждая строка на 80 столбцов). В третьей строке происходит вывод на экран сообщения "Добро пожаловать в QuickBASIC 4.5". (от слова PRINT — напе- чатать). Обратите внимание, что оператор PRINT производит вы- вод только на экран. Чтобы вывести это сообщение на принтер замените PRINT на LPRINT. Запустим программу на выполнение. Это можно сделать: 1. При помощи линейки главного меню. Для этого нажмите клавишу {ALT-R}. Будет выделено меню "RUN" (ЗАПУСК). 37
С помощью клавиши {DOWN} подведите выделенную строку к пункту "Start" и нажмите {ENTER}. 2. При помощи клавиатурных сокращений. Для этого нажмите комбинацию клавиш {SHIFT-F5}. В результате выполнения этой простой программы в нижней части экрана будет напечатано: Добро пожаловать в QuickBASIC 4.5! Press any key to continue С первым сообщением все понятно — в третьей строке про- граммы было сказано напечатать это сообщение. Второе сообще- ние выводит среда QB. Оно означает "Нажмите любую кнопку для продолжения. Нажмем пробел — на экране снова верну- лась наша программа. Можно продолжать работу над текстом. Чтобы снова посмотреть на экран программы, можно нажать {F4} 1 По этому поводу хорошо сказал Брайан Ливингстон в своей книге "Секреты Windows 3 1" — "...Я конечно понимаю, что есть такие люди, которые не найдут 'любую' кнопку ('any key'), когда на экран будет выведено сообщение типа 'Press any key to continue' (Нажмите любую кнопку для продолжения), или вообще, поняв фразу буквально, нажмут действительно 'любую' кнопку (имеется ввиду кнопка питания, перезагрузки или вообще кнопка стоящего рядом телефона) " 38
или выбрать пункт "Output Screen"(Выходной экран) из меню "VIEW'(nPOCMOTP). Теперь эту программу нужно сохранить. Выберем пункт "Save" (Запись) из меню FILE (ФАЙЛ). Вообще, надо взять себе за правило регулярно записывать программу на диск. Рекоменду- ется это делать при каждом запуске программы. При каких-либо сбоях в работе программы, ее исходный текст будет сохранен. Не забывайте также по окончании работы сохранять копию Вашей программы на дискете. Как говорит в таких случаях Peter Norton "BACKUP OFTEN!" (чаще делайте резервные копии). Для ускорения работы можно нажать комбинацию клавиш {ALT-F, S}. К счастью, на все часто используемые операции в BASIC предусмотрены "быстрые клавиши". И в дальнейшем, описывая действия с линейкой главного меню, автор будет опи- раться именно на них. Надо сказать, что по моему глубокому убеждению, использо- вание мыши в любых текстовых программах является явным из- лишеством. Все, что необходимо для работы, можно гораздо быс- трее сделать с клавиатуры. Другое дело — графические "форто- чки" типа "Windows", которые сами по себе работают настолько медленно, что в них уже безразлично, чем пользоваться: мышью или клавиатурой. И вообще — "на иконки надо в церкви смот- реть, а не на дисплее". 39
Но вернемся к нашему любимому языку BASIC. Мы не при- своили имя нашей программе, поэтом сейчас самое время это сделать. На экране появится окно, для ввода имени файла и формата, в котором его можно сохранить: Программу в среде QB можно записать в двух различных форматах: 1. В виде двоичного файла ("QuickBASIC — fast load and save"— формат QuickBASIC для быстрой загрузки и записи) 2. В виде текстового файла ("Text — readable by other program"— текстовый формат, понимаемый другими программами) Автор настоятельно рекомендует сохранять программы в виде текстовых файлов — это облегчает поиск нужных модулей, упростит компиляцию программы, а главное, программы, записанные виде в текстовых файлов можно безболезненно перенести в другие версии BASIC — от PDS до Visual, хотя, впрочем, программы записанные в виде двоичных файлов в QuickBASIC 4.5 свободно можно загрузить в Microsoft BASIC PDS 7.1 (но не наоборот). Ведите имя файла: TEST (расширение .BAS вводить не обя- зательно, QB добавит его сам. Нажмите клавишу {TAB}. Курсор переместится к списку доступных дисков. Нажмите клавишу {TAB} еще раз, и используя клавиши {UP} и {DOWN}, установите точку напротив формата Text — readable by other program. Для подтверждения записи нажмите клавишу {ENTER}. 40
Программа сохранена. Ее название TEST.BAS появилось ни- же линейки главного меню, где раньше было написано "Untitled" (без названия). Покинем гостеприимную среду QB. Для этого нажмем {ALT- F, X}. Посмотрим, как можно загрузить в среду QB уже готовую программу. Это можно сделать также двумя способами: 1. Запустим среду QB из командой строки DOS, введя команду QB.EXE. Загрузим программу TEST.BAS. Для этого введем команду {ALT-F, L}. Появится окно для загрузки файла, по- казанное на рисунке. Нужная нам программа уже есть в списке файлов, поэтому нажмем клавишу {TAB}. Курсор переместился к списку файлов. Нажмем клавишу {DOWN} и подведем выделенную строку к имени TEST.BAS. Осталось нажать клавишу {ENTER}, и про- грамма загружена. 2. При запуске среды QB можно явно указать имя файла (расширение также необязательно), например: С:\QB45>qb test Если вы пользуетесь программной-оболочкой Volcov Commander (Copyright (С) Всеволод В. Волков 1994) или Norton 41
Commander (Copyright (С) 1986 to 1993, Symantec Inc.), то добавь- те в файл vc.ext (nc.ext) строку: BAS: c:\qb45\qb.exe !.! Теперь достаточно подвести выделенную строку к имени программы на BASIC и нажать {ENTER}. Вообще для каждой бо- лее-менее крупной программной разработки рекомендуется вы- делять собственный каталог (или директорию — кому как больше нравится, смысл все равно один), чтобы не путать файлы Ваших программ со служебными файлам QuickBASIC. Достаточно удоб- но использовать такую особенность оболочки Volkov Commander как задание выполнения нескольких команд на одно файловое расширение. Это может оказаться полезным, например, при трансляции программы в исполнимый файл (когда вы выбираете пункт "Make EXE File" (Сделать EXE файл) из меню "RUN" (ЗАПУСК). Построение ЕХЕ-файла происходит в два этапа. Сна- чала компилятор ВС.ЕХЕ строит объектный файл (.OBJ), в кото- ром каждый оператор BASIC заменяется на соответствующий ма- шинный код, но при этом остаются внешние ссылки, которые затем компоновщик LINK.EXE замещает исполнимым кодом из соот- ветствующей библиотеки. После окончания процесса трансляции объектные файлы уже не нужны. Можно сделать так, чтобы сразу уничтожать объектные файлы (.OBJ): BAS: c:\qb45\qb.exe !.! del *.obj Как я уже упоминал, Интеллектуальный редактор среды QB осуществляет синтаксический контроль вводимого текста. Если строка написана правильно, то после того, как вы перевели кур- сор на следующую строку, все ключевые слова BASIC будут на- писаны заглавными буквами, операторы отделены друг от друга. Это позволяет сразу понять, есть ли в строке ошибки. Например, вы набираете текст (эта маленькая программка выводит ASCII-коды1 символов от 32 то 255). for 1 = 32 to 255:pnnt chr$ (i) ; :next i После перевода курсора на следующую строку, или при за- пуске этой программы строка примет вид: FOR 1 = 32 ТО 255: PRINT CHR$(i); : NEXT l 1 О кодах символах будет подробнее рассказано в следующей главе 42
Если же допущена ошибка с точки зрения синтаксиса языка BASIC, то будет высвечено диалоговое окно с описанием воз- никшей ошибки, а курсор установится на место предполагаемой ошибки. Так, в следующем примере пропущено ключевое слово THEN в конструкции IF ... THEN. Если ошибка понятна без разъяснений, можно нажать {ENTER}. При необходимости уточнений нажмите {TAB} и выбе- рите пункт "Help" (Помощь) Кроме синтаксической поддержки редактор QB поддержива- ет работу с блоками текста. Это бывает полезно, например, при копировании участков программы между различными модулями или процедурами. Для выделения блоков текста используются клавиши: {SHIFT}+{LEFT} или {RIGHT} {SHIFT}+{UP} или {DOWN} Будет выделен строчный фрагмент. Для этого нажмите клавишу {SHIFT}, и, не от- пуская ее, клавишу-стрелку. Для выделения прямоугольного фрагмента. Заметьте, что строки могут входить в фраг- мент только целиком. 43
Клавиши для работы с выделенным фрагментом: {DEL} {SHIFT-DEL} {CTRL-INS} {SHIFT-INS} Стереть выделенный фрагмент "навсегда" Стереть, но запомнить в буфере (Clipboard); Запомнить в буфере, не стирая; Вставить как текст из буфера. Текст, запомненный в буфере можно вставить в другое место программы неограниченное число раз. К числу несомненных достоинств среды QB относится и сис- тема оперативной подсказки. Чтобы вы не делали, нажав клави- шу {F1}, всегда можно получить исчерпывающее объяснение. Но можно и самому найти нужный раздел — нажмите {ALT-H, С} для входа в Главное меню оперативной подсказки: Здесь можно получить помощь по всем разделам BASIC. Для этого подведите курсор к названию нужной темы и нажмите {ENTER}. Для получения помощи по всем ключевым словам BASIC нажмите {ALT-H, I}. Если вы подведете курсор к наиме- нованию функции или процедуры и нажмете {F1}, то получите параметры вызова, к имени переменной — ее тип, в каком месте программы она используется. Но самым важным свойством опе- 44
ративной подсказки считается возможность получения помощи по всем ключевым словам BASIC непосредственно из программы. Просто подведите курсор к нужному слову и нажмите {F1}. При- мер подсказки на оператор PRINT приведен на рисунке. Можно уточнить синтаксис оператора, уточнить детали ис- пользования, и даже, посмотрев пример, скопировать его в Вашу программу и модифицировать под собственные нужды. Вернемся к нашей программе TEST.BAS. Ее можно запустить на выполнение только из среды QB. Но что делать, если вы хотите запус- кать вашу программу вне QB? QuickBASIC предоставляет такую воз- можность. Нужно сделать исполняемый (.ЕХЕ) файл, который сможет работать непосредственно из командной строки DOS. Загрузите TEST.BAS в среду QB, как показано выше, и нажмите {ALT-R, X}. Исполнимые файлы, оттранслированные из среды QB могут быть двух типов: • "EXE requiring BRUN45.EXE" — .ЕХЕ-файлы, требующие для своей работы присутствия BRUN45.EXE, специальной биб- лиотеки времени выполнения; • "Stand-Alone EXE File" — автономные .ЕХЕ-файлы, не тре- бующие для своей работы BRUN45.EXE. Файлы получаются больше по размерам, чем в первом случае, но обладают луч- шей переносимостью — чтобы программа работала, ей не нужны никакие внешние библиотеки. 45
Автор рекомендует пользоваться именно вторым способом (Stand-alone EXE File), так как автономные .ЕХЕ-файлы не толь- ко удобнее переносить, но и работают они значительно быст- рее — ведь программы требующие BRUN45.EXE постоянно об- ращаются к ней, что сильно замедляет выполнение программы, а что касается увеличения размеров, то уменьшить его помогают программы-упаковщики типа LZEXE или PKLITE. Нажмите два раза клавишу {TAB}, клавишей {DOWN} подве- дите точку к строке "Stand-Alone EXE File" и нажмите {ENTER}. После окончания процесса компиляции вы опять вернетесь в среду QB. Выйдете из нее ({ALT-F, X}). Полученный файл TEST.EXE можно запускать из командной строки DOS: C:\QB45>test Добро пожаловать в QuickBAASIC! C:\QB45>
Как нам обустроить QuickBASIC (*) Драйвер русских букв Первое, что необходимо сделать, после установки QuickBASIC — установить подходящий драйвер русских букв для того, чтобы вы могли иметь возможность вводить и видеть на эк- ране русские буквы. Выбор подходящего драйвера производите с учетом того, какого рода задачи вы предполагаете решать с помощью QuickBASIC: 1. Если вы работаете, как и автор этих строк, преимуще- ственно в текстовом режиме экрана, и не используете графику высокого разрешения (SCREEN 11 — 640x480x2 цвета и SCREEN 12 — 640x480x16 цветов), то я могу порекомендовать очень хороший драйвер: EN_DRV.COM (v.1.6 (с) 1990 Е. Свиридов) У него очень красивые округлые экранные шрифты (боль- шинство снимков экрана в этой книге сделаны при загруженных шрифтах драйвера EN_DRV) — 8 х 8 и 8 х 14. Переключение производится при помощи клавиши {правый CTRL}. Раскладка клавиатурная — стандартная, не меняется. 2. Если вам необходима графика высокого разрешения и возможность менять раскладку клавиатуры ~ воспользуйтесь драйвером: KEYRUS.COM (v8.0_betal6 (с) 1989-1994 Д.Гуртяк) Этот драйвер обладает уникальными возможностями на- стройки — можно изменить экранные шрифты1, раскладку кла- виатуры, изменить цвет рамки, клавишу переключения — и еще бог знает сколько параметров — нужных и не очень. Причем все установки записываются в тело самого драйвера, не требуя до- полнительных файлов. 1 Что я первым делом и сделал, записав в него раскладку и экранные шриф- ты моего любимого EN_DRV 47
Раскладка клавиатуры может вам пригодится, если вы хотите иметь возможность вводить русскую букву "р" стандартными средствами языка' (INPUT, LINE INPUT, INPUTS, INKEY$). Для изменения раскладки необходимо проделать следующее: 1. Выгрузить раскладку в файл _keys.kbd (предположим, что файл keyrus.com находится на диске С: в директории UTILS) С:\UTILS>keyrus /files 2. При помощи редактора клавиатурных раскладок krkeyb.exe отредактировать файл _keys.kbd как показано на рисунке: 3. Сохраните сделанные изменения в теле драйвера: С:\UTILS>keyrus /keys=_keys.kbd /save Чтобы иметь возможность работать с русскими буквами во всех экранных режимах, необходимо включить поддержку трех экранных шрифтов: 8x8 (SCREEN I, SCREEN 2, SCREEN 7, SCREEN 8, SCREEN 13); 8x14 (SCREEN 9, SCREEN 10); 8x16 (SCREEN 11, SCREEN 12). C:\UTILS>keyrus /8x8=on /8xl4=on /8xl6=on /ALL /save 1 Эта проблема подробно обсуждается в главе второй "ОСНОВЫ ЯЗЫКА BASIC" в разделе "Почему BASIC не выговаривает русскую букву "р" 48 Поставьте здесь английскую букву "р" вместо русской р"
Программы-оболочки Редко кто пользуется для ввода команд непосредственно ко- мандной строкой DOS — обычно для этой целей используют од- ну из трех программ-оболочек, получивших наиболее широкое хождение в ех-СССР: Название Volcov Commander Norton Commander Norton Commander Номер версии 4.00 Share- ware 3.0 4.0 Copyright (C) 1991-1995 В.Волков, Киев (С) 1986, 88, 89, Peter Norton Computing (C) 1986 to 1993, Symantec Inc. Физичес кий раз- мер , Кб 63 136 207 Требуется памяти, Кб 91 174 224 При работе в среде QB часто возникает необходимость вос- пользоваться программой-оболочкой: например, если надо найти какой-нибудь модуль или скопировать файл и т. д. Запустить внешнюю программу из среды можно следующим образом: 1. Выбрать пункт "DOS Shell" (Временный выход в DOS) из меню "FILE" (ФАЙЛЫ) и ввести имя нужной программы. QB выдаст сообщение о том, что для возврата нужно ввести команду EXIT, и запустит копию командного процессора COMMAND. СОМ. Введите имя программы-оболочки в командной строке DOS: Type EXIT to return to QuickBASIC Novell DOS 7 Copyright (c) 1976, 1993 Novell, Inc. All rights reserved. C:\QB45>vc 2. В окне для немедленного выполнения Immediate введите команду SHELL с параметром — именем программы: SHELL "vc" 49
Для возврата в среду QB достаточно выйти из программы- оболочки. При запуске оболочки необходимо учитывать очень важный момент — они запускаются поверх 278 Kb модуля QB.EXE и ис- пользуют только ту память, которую BASIC может им выделить после собственной загрузки, загрузки программы пользователя и резервирования памяти под переменные и массивы программы — примерно 150-200 Kb. Какую оболочку предпочесть? Я пользуюсь Volcov Commander (VC). Она требует всего 90 Kb свободной оператив- ной памяти, и ее удается запустить, даже если загружена доволь- но большая программа. Кроме того, VC позволяет выполнять ко- пирование и перемещение как каталогов, так и файлов, имеет менеджер резидентных программ (с возможностью их выгрузки), позволяет подставлять в командную строку выделенные файлы и работать с ними, имеет встроенный редактор1, ограниченный только объемом свободной оперативной памяти, и многие другие возможности — и все это в .СОМ-файле размером 63 Kb! Можно пользоваться и NC 3. Все-таки старина третий Norton — это живая классика. Правда ему может и не хватить памяти, особенно если загружена большая программа. Что касается NC 4 — то здесь ситуация однозначная. Четвер- тый "Петя" так "разжирел, что не вызывается из-под BASIC ни под каким видом, даже если вы и не загрузили в среду ни строчки кода. Переключатель Задач Очень часто возможностей временного выхода в DOS оказы- вается недостаточно — бывает очень удобно держать несколько задач одновременно в памяти и оперативно переключаться между ними. Например, иметь возможность нажатием одной клавиши переключатся, скажем, между средой QB, текстовым редактором и программой-оболочкой. 1 А не внешний, как в NC 4, редактор, который к тому же и не умеет редак- тировать файлы, превышающие 64 Kb. 2 Злые языки утверждают, что это, а также многочисленные ошибки NC 4, связанные с обработкой архивов, работой со вложенными каталогами и др свя- заны с тем, что Автор Norton Commander Джон Соча покинул Peter Norton Computing, когда та была поглощена корпорацией Symantec, и четвертого Нор- тона делали уже совсем другие люди ... 50
Робкие попытки сделать это были предприняты компанией Microsoft в MS DOS 5.0 и 6.0. Я говорю о оболочке DOS SHELL. Однако ее неуклюжий Windows-подобный интерфейс отпугнул большинство пользователей (естественно, Norton — forever...). Но решение проблемы есть. Речь идет об операционных сис- темах DR DOS 6.00 компании Digital Research и ее следующей версии, вышедшей под маркой Novell: Novell DOS 7.00. Наряду с такими преимуществами, как защита от несанкци- онированного доступа к компьютеру, каталогам и файлам, утили- ты настройки системных параметров, гипертектекстовый спра- вочник, в эти операционные системы включена возможность ра- боты с несколькоми задачами — Переключатель Задач: В чем же его преимущество по сравнению с другими подоб- ными системами? 1. Он позволяет переключать задачи непосредственно из коман- дной строки DOS: {CTRL-1}1 — переключаемся на первую задачу; {CTRL-2} — на вторую и так далее. 2. Список загруженных задач вызывается нажатием комбинации клавиш {CTRL-ESC}. При этом для организации новой зада- чи достаточно нажать клавишу {INS}, а для удаления — {DEL}. И все! Это вам не бесконечная возня с .INI-файлами и не подбор установок в .PIF-файлах "методом научного ты- ка" в Windows. При этом Переключатель Задач занимает всего 960 байт для каждой загруженной задачи и полностью использует преимущества расширенной памяти. 3. Novell DOS 7 пошла еще дальше — Переключатель Задач мо- жет обеспечивать еще и Многозадачность — при этом не- сколько DOS-задач могут выполняться параллельно. Так как этот механизм встроен в ядро операционной системы, то все переключения выполняются быстро, четко и без сбоев. Обычно хватает возможностей только Переключателя За- дач — ведь Многозадачность снижает скорость работы программ, в то время как Переключатель нет, — в каждый момент времени выполняется только одна активная задача, а остальные мирно ждут своей очереди на диске или в расширенной памяти. Я пишу эту книгу в текстовом процессоре "Лексикон" вер- сии 1.4. Для отладки приведенных примеров переключаюсь в QuickBASIC 4.5, а для манипуляций с файлами использую Volkov Commander 4.00. При загруженном Переключателе Задач каждо- му приложению доступно 623 Kb оперативной памяти. На рисун- 1 Цифры набираются на цифровой клавиатуре 51
ке приведено главное Меню Переключателя Задач Novell DOS 7.00, вызванное нажатием {CTRL-ESQ прямо из QuickBASIC: Это сгисок активных задач 0В - активная задача Это главное меню переключателя задач Некоторые эстетствующие товарищи могли бы указать автору на существование Отца Виндоуса с его иконами1, который тоже может выступать в качестве Переключателя Задач, и даже пы- таться изобразить Многозадачность. Теоретически да, может, но... Дело в том, что при запуске DOS-программ Windows только эмулирует DOS, причем делает это из рук вон плохо. При запус- ке маломальски сложной программы (а среда QB.EXE без сомне- ния таковой является) в любой момент времени может возник- нуть такое вот сообщение... В переводе на нормаль- ный человеческий язык это означает примерно следую- щее: "А я тут не при чем, это натворила все она, плохая программа QuickBASIC 4.5...". А виновата именно Windows. Ее громоздкий графический интерфейс отнимает львиную долю ресурсов процессора. Практи- чески она работает сама на себя, а прикладным программам доста- ются "крохи с барского стола". Разве можно себе представить, рабо- тая в родной и привычной DOS, чтобы такая благовоспитанная программа, как QB.EXE так "тявкала" на своего хозяина — да ни- когда в жизни! Причем как нарочно, Windows выкидывает бедный BASIC обязательно перед сохранением программы на диске, а после такого сообщения от нее остаются только воспоминания и обида за бесцельно потраченное время... This application has violated system integrity due to an invalid general protection fault and will be terminated. Quit all applications, quit Windows, and then restart your computer. 52 1 Windows & icons
ОСНОВЫ ЯЗЫКА BASIC Алфавит языка Основной единицей хранения данных в компьютере является бит. Бит — это термин, являющийся сокращением от английских слов binary digit — bit (двоичная цифра — бит). Он может прини- мать только два значения "О" или " ("включен" или "вык- лючен"). 8 бит принято называть байтом1. В байте содержится 8 бит, т. е. 8 нулей или единиц, 8 положений "включено" или "выключено". С помощью математических расчетов легко опреде- лить, что если у нас имеется 8 каких-нибудь единиц (бит), и каждая из них может принять значение 0 или 1, то чисто возможных ком- бинаций в одном байте составит 28, т. е. 256 (от 0 до 255). В восьми двоичных разрядах умещается 256 целых чисел, что вполне достаточно для того, чтобы дать уникальное 8-битовое обо- значение каждой заглавной и строчной букве двух алфавитов, циф- рам, знакам препинания, служебным символам. Эта таблица полу- чила названия ASCII-таблица2 (American Standard Coding for Information Interchange — Американский Стандартный Код для Об- мена Информацией). Первая половина этой таблицы (стандартная ASCII-таблица — символы с кодами 0 - 127), стандартизирована, а вторая половина (расширенная ASCII-таблица) уникальна для каж- дой страны. У нас вторую половину таблицы описывает Альтерна- тивная кодировка, в которой русские буквы представлены кодами 128-175 и 223-241. Разрыв в диапазоне представления русских букв, 1 210 байт или 1024 байта — килобайт, Kb 220 байт или 1048576 байт - мегабайт, Mb 2 См. Приложение 5
связан с тем, что на этом месте находятся символы псевдографики, используемые для рисования рамок и таблиц. Существует и такая единица информации, как слово. Слово со- ставляется из 16 бит, т. е. из 2 байт. 16-разрядным словом можно представить: • целые числа без знака от 0 до 65535; • целые числа со знаком от -32768 до 32767. Вообще говоря, представление чисел — это внутреннее, глу- боко "интимное" дело самого BASIC, автор упоминает об этом только потому, что эти числа будут часто встречаться дальше — они "круглые" для BASIC. Например: • Длина строки в редакторе QB ограничена 255 символами A байт); • Целые числа (INTEGER) могут лежать в диапазоне от -32768 до 32767 B байта); • Размер массива не может превышать 64 Kb F5535 байт — слово). Рассмотрим подробнее, какие символы из таблицы ASCII можно использовать в программах. Набор символов языка Quick- BASIC 4.5 состоит из следующих символов: • Все прописные (A-Z) строчные (a-z) буквы латинского алфавита; • Цифры @-9), а также буквы (A-F) или (a-f) для представле- ния шестнадцатеричных1 чисел; • Знаки: + - * / плюс минус умножение деление = < > Л равно меньше больше возведение в степень 1 В то время, как в привычной нам десятичной счисления каждая последую- щая цифра больше предыдущей в 10 раз, в шестнадцатеричных числах каждая последующая цифра больше в 16 раз. У десятичных чисел первая позиция соот- ветствует единицам, вторая — десяткам, третья — сотням. У шестнадцатеричных числе первая позиция соответствует единицами, вторая — 16, третья 256 и т. д. Это означает, что когда в позиции единиц расположение цифра 9, то прибавле- ние единицы не приводит к переносу в следующий разряд, как это было бы в случает десятичных чисел. Но как записать десятичное число 10 одной цифрой? Ответ состоит в том, что шестнадцатеричные цифры используют первые 6 букв латинского алфавита в качестве дополнительных цифровых символов. Перечис- ление шестнадцатеричных чисел продолжается так: ... 8, 9, А, В, С, D, E, F, 10 ,11 ... 19, 1А, 1В и т. д. В BASIC шестнадцатеричные числа начинаются с симво- лов "&Н". Например число 255 можно записать как &HFF. 54
Разделители: ) запятая точка двоеточие точка с запятой » ( ) апостроф открывающая скобка закрывающая скобка подчеркивание Символы объявления типа данных: % & I # $ целые; длинные обычной двойной целые; точности; точности; символьные. Типы данных Данные и их типы Каждая переменная в языке QuickBASIC имеет тип. Тип оп- ределяет, какие данные хранятся в этой переменной. Существует две основных категории данных: числовые и символьные. Каждая категория включает в себя элементарные типы данных, о которых рассказано ниже. Числовые типы данных Числовые данные представляют собой числа. Они бывают следующих типов: целые, длинные целые, обычной точности, двойной точности: Целые (INTEGER) — занимают в памяти 2 байта и исполь- зуются для значений в диапазоне от -32768 до +32768. 55
Длинные целые (LONG) — 4 байта. Используются для зна- чений в диапазоне от -2,147,483,648 до +2,147,483,647. Они ис- пользуются в тех случаях, когда необходимы операции с целочис- ленными переменными, выходящими за рамки диапазона целых чисел в представлении BASIC. Обычной точности (SINGLE) — 4 байта. Используется для значений в диапазоне от -3.402823Е+38 до -1.40129Е-45 для от- рицательных значений и от +1.40129Е-45 до -3.402823Е+38 для положительных значений. Двойной точности (DOUBLE) — 8 байт. Используется для значений в диапазоне от 1.797693134862316Е+308 до -4.94965Е- 324 для отрицательных значений и от 4.94965Е-324 до 1.797693134862316Е+ЗО8 для положительных значений. Обычно применяется для точных математических вычислений, не допус- кающих потерю значности. Символьные типы данных Строка переменной длины (STRING)— это последователь- ность длиной до 32567 символов из таблицы ASCII. В памяти она занимает столько байт, какова ее длина + 4 байта на описатель. Строка фиксированной длины (STRING * num) — символьная строка длинною num байт. В памяти такая строка занимает num байт. Пользовательские типы данных (записи) Если данные, которые вы используете в программе, необхо- димо сгруппировать по какому-либо признаку, то для этого очень удобно использовать пользовательский тип данных (записи). Он составляется из простых типов данных (числовых и символьных), описанных выше. Например, нам необходимо ввести табельный номер работ- ника, его фамилию и тарифную ставку. 'Определим пользовательский тип данных Record 'с помощью оператора TYPE TYPE Record TabNomer AS INTEGER Family AS STRING * 15 Stavka AS DOUBLE END TYPE 56
'Присваиваем переменной Rabotnik пользовательский тип 'данных Record DIM Rabotnik AS Record 'Последовательно вводим значение каждого элемента записи INPUT "Введите табельный номер"; Rabotnik.TabNomer INPUT "Введите фамилию работника"; Rabotnik.Family INPUT "Введите тарифную ставку"; Rabotnik.Stavka Пользовательский тип данных занимает в памяти столько байт, сколько занимают в сумме каждый из составляющих его элементов. Для нашего примера запись Rabotnik включает целое число B бай- та), строку фиксированной длины A5 байт) и число удвоенной точ- ности (8 байт). Таким образом она имеет размер 25 байт. Типы данных, определяемые пользователем, могут включать любые типы стандартных данных, кроме строк переменной дли- ны и массивов1. Константы Константами называются заранее предопределенные значе- ния, которые не меняются в процессе работы программы. В каче- стве примера можно привести число PI, основание натурального логарифма, год Вашего рождения и т. д. Константы удобно ис- пользовать для тех величин в Вашей программе, которые не предполагается изменять — число строк, выводимых на экран, значения функциональных клавиш, и т. д. В языке QuickBASIC имеются 2 типа констант — неимено- ванные и именованные. Неименованные константы Они бывают символьные и числовые, и используются в программе в тех случаях, когда их значение заранее известно и не подлежит изменению. Символьные константы — это последовательность до 32767 ал- фавитно-числовых символов (за исключением кавычек (") и симво- лов перевода каретки и пропуска строки (CR — ASCII 13 и LF — ASCII 10). Они обязательно должны заключаться в кавычки: 'В пользовательский тип данных Microsoft BASIC PDS 7.1 могут входить и массивы. 57
"ПРИВЕТ" 11 $ 25,000,000" "Число работников" Пример: PRINT "Средняя заработная плата" Числовые константы представляют собой положительные или отрицательные числа. Они могут быть тех же типов, что и пере- менные — целые или длинные целые типа, обычной или двойной точности: Целый тип: 68, +407 , -1 Длинный целый тип: 95000000, -400141 Обычной точности: 9.0846 Двойной точности: 4.35D-10 Пример: PRINT 15000 Именованные константы Они также бывают символьные и числовые, тех же типов, что и неименованные. Чтобы использовать именованную кон- станту, ее необходимо объявить при помощи ключевого слова CONST, например: CONST MaxArray% = 512 В этом примере объявляется целочисленная константа МахАггау и ей присваивается значение 512. В дальнейшем к этой константе можно обращаться по имени: DIM Tovar$(МахАггау) Символьная константа объявляется и используется аналогично: CONST BAD$ = "mbtl20o016eeel2c" PLAY BAD 58
При обращении к именованным константам вы можете опускать расширение, как показано в этих примерах. Использование именованных констант имеет ряд преимуществ по сравнению с использованием для этих целей переменных: • Однажды определив константу, вы не сможете случайно из- менить ее значение. BASIC сразу выдаст сообщение об ошиб- ке "Duplicate Definition" (Двойное определение); • Именованная константа доступна всем процедурам и функ- циям данного модуля1. В случае же использования перемен- ной, вы должны будете объявить ее как SHARED во всех процедурах и функциях модуля; • BASIC выполняет операции с константами быстрее, чем с пе- ременными. Если подвести курсор к названию именованной константы где-либо в Вашей программе и нажать клавишу {F1} среда QB покажет тип и значение этой константы: Удобно использовать именованные константы для обозначе- ния функциональных клавиш. Это очень помогает при написа- нии программ — не надо держать в голове, коды этих клавиш — вместо этого можно просто написать: CONST Р1% = 59, F2% = 60, F3% = 61, F4% = 62, F5% = 63 CONST F6% = 64, F7% = 65, F8% = 66, F9% = 67, F10% = 68 SELECT CASE Kod CASE IS = Fl: ... CASE IS = F2: ... CASE F3 TO F9: ... CASE IS = F10: ... END SELECT 1 Подробнее см. в разделе "Модульное программирование" 59
Переменные Переменная — эта величина, которая может меняться при выполнении программы. Если привести пример из житейской практики, то можно сказать, что переменная величина, к приме- ру, сколько у Вас сейчас денег, или ближе к компьютерной прак- тике, сколько свободного места осталось у Вас на жестком диске. Переменные бывают простые (символьного типа, числового типа и пользовательского типа) и переменные массивы — пред- ставляющего собой группу объектов одного типа. Имена переменных Имена переменных могут содержать до 40 символов. В име- ни переменных могут содержаться латинские буквы, числа, деся- тичная точка, и символы определения типа (%, &, !, # и $). Пер- вый символ должен быть латинской буквой. Если переменная начинается с FN, подразумевается вызов функции1 DEF FN. Имя переменной не может быть зарезервированным словом QuickBASIC, хотя допускается комбинация зарезервированного слова и других символов. Так, в примере содержится ошибка — LOCATE (разместить) является зарезервированным словом (без учета регистра): locate = 7 Однако следующий пример допустим: LocateCursor = 7 Зарезервированными словами в QuickBASIC являются команды, операторы, имена функций. Список зарезервированных слов QuickBASIC и их краткое толкование приведены в Приложении 7. Давая имена переменным, вы можете комбинировать в них прописные и строчные буквы. Хотя BASIC не различает пропис- ные и строчные буквы при работе с переменными, это очень удобно для программиста, поскольку в имени переменной он может сделать акцент на ее назначение, например: 1 Подробнее см. в главе третьей главе "Программные конструкции" 60
PrixodSklad% = 1000 ErrorHandler% = 7 DetailName$ = '"Гурбодетандер" QB внимательно следит за тем, чтобы комбинация пропис- ных и строчных букв была бы одинакова для всех переменных. Так, если вы назвали переменную happynewyear, а затем, к при- меру, обратились к ней, как к переменной с именем HappyNewYear, то QB сразу же изменит название happynewyear на HappyNewYear везде, где она встречается. Переменные числового типа Переменные числового типа представляют собой, естествен- но, числа. Они бывают целые (INTEGER), длинные целые (LONG INTEGER), обычной точности (SINGLE), двойной точ- ности (DOUBLE): Целые (INTEGER) — занимают в памяти 2 байта и исполь- зуются для значений в диапазоне от -32768 до +32768. Присвоить переменной целый тип можно следующим образом: а) поставить в начало программы оператор объявления цело- го типа данных DEFINT' (DEFINED INTEGER): 'объявить переменные в программе (от А до Z) целого типа DEFINT A-Z 'Переменная Flag - целая, так как она начинается с 'буквы F, которая входит в диапазон A-Z Flag = 1 б) Явно задать переменную с помощью суффикса "%" 'Переменная Flag% - целого типа Flag% = 1 в) Использовать оператор описания переменной 1 описываем переменную как целую DIM Flag AS INTEGER 1 Считается хорошим стилем программирования начинать программу, объя- вив все переменные целыми, так как выполнение операций над целыми числами BASIC проводит гораздо быстрее, чем над данными других типов. Если же про- грамме необходимы данные других типов, воспользуйтесь явным заданием типа данных при помощи соответствующего суффикса или оператором описания пе- ременных 61
Длинные целые (LONG) — 4 байта. Используются для значе- ний в диапазоне от -2,147,483,648 до +2,147,483,647. Они исполь- зуются в тех случаях, когда необходимы операции с целочислен- ными переменными, выходящими за рамки диапазона целых чи- сел в представлении BASIC. Присвоить переменной длинный це- лый тип можно следующим образом: а) поставить в начало программы оператор объявления длин- ного целого типа данных DEFLNG (DEFINED LONG): 'объявить переменные в программе (от В до С) 'длинного целого типа DEFLNG B-C 'Переменная BisunessTotal - длинная целая, так как 'она начинается с буквы В, которая входит в диапазон В-С BisunessTotal = 999999999 б) Явно задать переменную с помощью суффикса "&": 'Переменная BisunessTotal& - длинная целая BisunessTotal& = 999999999 в) Использовать оператор описания переменной: 'описываем переменную как длинную целую DIM BisunessTotal AS LONG Обычной точности (SINGLE) — 4 байта. Используется для значений в диапазоне от -3.402823Е+38 до -1.40129Е-45 для от- рицательных значений и от +1.40129Е-45 до -3.402823Е+38 для положительных значений. Если тип числовой переменной не за- дан (оператором DEFTnn, суффиксом или оператором описания типа), то она автоматически становится обычной точности1. 1 Это приводит к типичным ошибкам начинающего BASIC-программиста. Если в начале программы не поставить DEFINT или пропустить суффикс опре- деления типа переменной, то она считается вещественной обычной точности, что приводит: • к значительному замедлению цикла FOR...NEXT, если такая переменная используется в качестве счетчика цикла (он должен быть INTEGER или LONG INTEGER); • потере значности при точных математических вычислениях (DOUBLE не дает таких ошибок округления); • снижению скорости работы (иногда в 5-10 раз, особенно на машинах без сопроцессора) при компиляции такой программы, так как BASIC подключает библиотеки для работы с числами с плавающей точкой, требующих интенсивных математических вычислений). Таким образом, старайтесь избегать использования вещественных перемен- ных обычной точности. Это окупится более быстрой, точной и аккуратной рабо- той Вашей программы. 62
Присвоить переменной тип обычной точности можно следу- ющим образом: а) поставить в начало программы оператор объявления дан- ных обычной точности DEFSNG (DEFINED SINGLE). 1 объявить переменные в программе, начинающиеся с буквы S 'обычной точности DEFSNG S 'Переменная SingleValue - обычной точности, так как она 1 начинается с буквы S SingleValue = 123.321 б) Явно задать переменную с помощью суффикса "!". Следу- ет учесть, что поскольку переменная в BASIC имеет тип обычной точности по умолчанию, то числовая переменная, у которой ука- зан суффикс "!" и та, у которой этот суффикс отсутствует, счи- таются одинаковым и не различаются языком BASIC. 'Переменная SingleValue! - обычной точности, она же 'переменная SingleValue SingleValue! = 123.321 PRINT SingleValue!, SingleValue Результат: 123.321 123.321 в) Использовать оператор описания переменной 1 описываем переменную обычной точности DIM SingleValue AS SINGLE Двойной точности (DOUBLE) — 8 байт. Используется для значений в диапазоне от 1.797693134862316Е+308 до -4.94965Е- 324 для отрицательных значений и от 4.94965Е-324 до 1.797693134862316Е+308 для положительных значений. Обычно применяется для точных математических вычислений, не допус- кающих потерю значности. Присвоить переменной тип двойной точности можно следующим образом: а) поставить в начало программы оператор объявления длин- ного типа данных типа данных DEFLNG (DEFINED LONG): 'объявить переменные, начинающие с буквы D, а также 'входящие в диапазон от М до Р, двойной точности DEFDBL D, М-Р 63
'Переменная Determinant - двойной точности, так как она 'начинается с буквы D Determinant = 53.49852432 б) Явно задать переменную с помощью суффикса "#" 'Переменная Determinant* - двойной точности Determinant* = 53.49852432 в) Использовать оператор описания переменной 1 описываем переменную двойной точности DIM Determinant AS DOUBLE Переменные символьного типа Переменные символьного типа (строки) — могут включать в себя любые символы из таблицы ASCII. Для присваивания значения символьной переменной, значение берется в кавыч- ки. Попутно замечу, что только символьным переменным можно присваивать значения, содержащие русские буквы (символы с кодами 128-175 и 224-241 согласно Альтернатив- ной кодировке). Символьные переменные бывают переменной длины и фик- сированной длины. Строка переменной длины (STRING) — это последователь- ность длиной до 32567 символов из таблицы ASCII. В памяти она занимает столько байт, какова ее длина + 4 байта на описатель. Присвоить символьной переменной тип строки переменной дли- ны можно следующим образом: а) поставить в начало программы оператор объявления типа строки переменной длины DEFSTR (DEFINE STRING): 1 объявить переменные, начинающие с буквы L 'как строки переменной длины DEFSTR L 'Переменная Language - строка переменной длины, так как 'она начинается с буквы L Language = "QuickBASIC - навсегда!" б) Явно задать переменную с помощью суффикса "$": 'Переменная Language$ - строка переменной длины Language$ = "QuickBASIC - навсегда!" 64
в) Использовать оператор описания переменной: описываем переменную как строку переменной длины DIM Determinant AS STRING Строка фиксированной длины (STRING * num) — символь- ная строка длинною num байт. В памяти такая строка занимает num байт. Присвоить символьной переменной тип строки переменной длины можно, используя оператор описания переменной: 1 описываем переменную как строку фиксированной длины DIM Language AS STRING * 10 Language = "QuickBASIC - навсегда!" PRINT ">";Language;"<" Результат: >QuickBASIC< Переменные пользовательского типа данных Если данные, которые вы используете в программе, необходимо сгруппировать по какому-либо признаку, то для этого очень удобно использовать пользовательский тип данных (записи). Он составляется из простых типов данных (числовых и символьных), описанных выше. Например, нам необходимо ввести табельный номер работ- ника, его фамилию и тарифную ставку. 1 Определим пользовательский тип данных Record 'с помощью оператора TYPE ТУРЕ Record TabNomer AS INTEGER Family AS STRING * 15 Stavka AS DOUBLE END TYPE 'Присваиваем переменной Rabotnik пользовательский тип 'данных Record DIM Rabotnik AS Record 1 Последовательно вводим значение каждого элемента записи INPUT "Введите табельный номер"; Rabotnik.TabNomer INPUT "Введите фамилию работника"; Rabotnik.Family INPUT "Введите тарифную ставку"; Rabotnik.Stavka Пользовательский тип данных занимает в памяти столько байт, сколько занимают в сумме каждый из составляющих его элементов. 65
Для нашего примера запись Rabotnik включает целое число B бай- та), строку фиксированной длины A5 байт) и число удвоенной точ- ности (8 байт). Таким образом она имеет размер 25 байт. Типы данных, определяемые пользователем, могут включать любые типы стандартных данных, кроме строк переменной дли- ны и массивов1. Сводная таблица описания типов данных Суф- фикс % & 1 # $ $ Описание ASjran INTEGER LONG SINGLE^ DOUBLE STRING STRING* num Пользо- ватель- ский тип Объявление DEF_™n DEFINT DEFLNG DEFSNG DEFDBL DE.FSTR Тип переме- ной Целая Длинная целая Обычной точности Двойной точности Строка переменной длины Строка фик- сированной длины Занимаемый объем 2 байта 4 байта 4 байта 8 байт Занимает 4 байта под описатель + 1 байт на каждый символ в строке Занимает num байт Занимает столько байт, сколько зани- мают в сумме отдельные эле- менты 1 В пользовательский тип данных Microsoft BASIC PDS 7.1 могут входить и массивы. 2 Для тех переменных и констант, тип которых не задан явно оператором описания типа, принимается тип SINGLE. 66
Переменные-массивы Если в программе используется группа однотипных пере- менных (например оценки каждого студента в группе, дневная температура в течение месяца, и т. д.), то такую группу однород- ных объектов удобно представить в виде массива переменных. Отдельные переменные в массиве называются элементами, по- этому для присвоения им значений можно использовать операто- ры и функции QuickBASIC. Каждый элемент в массиве имеет номер (индекс), по кото- рому можно обратиться к значению элемента. Индекс — число- вое выражение целого типа. Размерностью называется число ин- дексов, определяющих элемент массива. Например VA0) — зна- чение в одноразмерном массиве (векторе), Т$A,4) — двухразмер- ный массив (матрица). Количество элементов в массиве называется размером масси- ва. По умолчанию размер любого массива принимается равным 10 элементам. Организация массивов в языке BASIC 67 I Объявляется массив из 10-и DIM A%A0) ' Размерность массива — 1, это вектор I Присваивание знамения элементу Эле»*** :'aYmV ' К массива • А*'. f' ^ А%B) = 4 А%C) - 3 А%D) - 1 А% ( 5 ) "* 2 Значение элемента массива А%F) - 8 А%G) - б А%(8) - 9 А%(9) -10 А% A0) - 7 ' Индекс элементе, мяпгии^
Каждый массив, используемый в программе, должен быть заранее объявлен оператором DIM (если размер массива не пред- полагается менять) или REDIM (если размер массива будет ме- няться). При объявлении массива можно указывать границы для его размерностей (верхнюю и нижнюю), например: 'объявляется целочисленный массив с элементами 'А%A0), А%A1), А%A2), А%A3), А%A4), А%A5) DIM A%A0 ТО 15) Если массив не будет объявлен до его использования, то при запуске программы вы можете получить сообщение об ошибке: "Array not denned" (Массив не определен). При задании размеров массива вы должны учитывать следу- ющие ограничения: • Максимальный размер массива — 65535 байт; • Максимальное число размерностей — 8; • Максимальный номер индекса — 32768. Так, если вы объявляете числовой массив обычной точности, в котором каждый элемент занимает 4 байта, то максимальный размер массива, который может быть указан в операторе DIM со- ставляет 65535 / 4 = 16383. При превышении этого значения BASIC выдаст сообщение об ошибке "Subscript out of range" (Индекс вне диапазона). Более подробно об ограничениях BASIC написано в Приложении 4 "Ограничения QuickBASIC". Правила использования массива такие же, как и для пере- менной. Для обозначения отдельного элемента используется имя массива, за которым следует индекс (или индексы) этого масси- ва, заключенные в круглые скобки. Объявленный массив "может иметь любой тип, включая пользовательский. TYPE TreeNode LeftPrt AS INTEGER RightPrt AS INTEGER DataField AS STRING * 20 END TYPE DIM TreeE00) AS TreeNode Каждый элемент в массиве Tree являются записью типа TreeNode. Для доступа к каждому элементу записи используется форма: имя_переменной.имя_элемента 68
'объявляется константа CONST MAX = 500 TYPE Personal Nomer AS INTEGER Name AS STRING * 25 END TYPE DIM Farmer(MAX) AS Personal PRINT Farmer(I).Nomer; " ";Farmer(I).Name Для определения объема памяти под массив, умножьте число элементов на число байт, занимаемым каждым элементом. DIM Arrayld TO 100) AS INTEGER DIM Array2#(-5 TO 5) В первом случае в массиве Array 1 100 целых элементов. Та- ким образом он занимает 200 байт A00 *2 ). В массиве Аггау2 11 элементов двойной точности. Занимаемое место в памяти для массива — 88 байт (И * 8). Следует учесть, что фактически память отводится больше, так как QuickBASIC хранит сведения о массиве также в памяти. Большие динамические массивы (*) При написании программ иногда возникает необходимость использовать массивы размером более чем 64 Kb. Такие массивы называются большими (huge) динамическими массивами. Huge- массивы могут иметь размер, превышающий 64 Kb ограничение. Для описания huge-массива необходимо проделать следующее: 1) Загрузить среду QB с опцией /Ah (Array huge) C:\QB45>qb test.bas /Ah 2) Объявить массив как обычно, при помощи оператора DIM При этом надо иметь ввиду следующее: а) Huge-массивы не могут занимать больше 128К памяти, ес- ли размер индивидуальных элементов не является степенью чис- ла 2. Например: TYPE ElementType a AS INTEGER ' 2 байта b AS LONG ' 4 байта с AS SINGLE ' 4 байта d AS DOUBLE ' 8 байт e AS STRING * 15 '15 байт END TYPE 'Всего 33 байта - размер ElementType 69
MaxElement% = 3 971 DIM HugeArrayd to MaxElement%) AS ElementType Длина записи ElementType — 33 байта, значит массив HugeArray не может превышать 128 Kb. A28 * 1024 / 33 = 3971) б) Если же размер элементов является степенью 2 B,4,8,16,32...), то размер Huge-массива ограничен только свобод- ной оперативной памятью. Однако имейте ввиду следующее — BASIC — совершенно не "жадный" и может выделить программе всю доступную память. В результате может возникнуть ситуация, когда ему самому не хватит памяти для работы, и ошибка "Out of memory" (Исчерпана оперативная память). Поэтому используя функцию FRE(-l), выясните, сколько памяти свободно, и оставь- те QuickBASIC хотя бы 10% на его собственные нужды: TYPE ElementType a AS INTEGER '2 байта b AS LONG '4 байта с AS SINGLE '4 байта d AS DOUBLE '8 байт e AS STRING * 14 44 байта END TYPE 'Всего 32 байта - размер ElementType 'размер свободной оперативной памяти FreeMemory& = PRE(-l) 'великодушно берем всего 90% RealMemory& = .9 * FreeMemory& 'определяем максимальный элемент MaxElement% = RealMemoryk \ 32 CLS PRINT "Свободная оперативная память"; FreeMemory&\1024; PRINT "Kb" PRINT "Доступная оперативная память"; RealMemoryk \ 1024; PRINT "Kb" PRINT "Объявлен массив из"; MaxElement%; "элементов" DIM HugeArrayd TO MaxElement%) AS ElementType FreeMemory& = FRE(-l) PRINT "Осталось оперативной памяти"; FreeMemory& \ 1024; PRINT "Kb" Результат: Свободная оперативная память 241 Kb Доступная оперативная память 217 Kb Объявлен массив из 6960 элементов Осталось оперативной памяти 24 Kb 70
Использование опции /Ah заставляет все динамические мас- сивы описывать как большие (huge). Доступ к большим массивам несколько замедлен вследствие обращения к индивидуальным элементам по дальней ссылке. Если вы определили переменную с помощью оператора опи- сания типа или объявления типа, то чтобы узнать тип перемен- ной, достаточно подвести к ней курсор, и нажать F1 — среда QB определит тип этой переменой и укажет, в каком модуле, проце- дуре или функции1 она используется. Для простых переменных (числовых или символьных) указы- вается ее тип: Выражения и операции Последовательность операций, которые необходимо произве- сти над данными, чтобы получить требуемое значение называется выражением. Результатом выражения может быть символьная или числовая константа, переменная или значение. В языке BASIC существует пять категорий операций, пере- численные далее: 1 Подробнее см. в главе третьей главе "Программные конструкции" 71 Для элемента записи пользовательского типа данных, кроме того, указывается структура записи:
1. Арифметические операции; 2. Операции отношений; 3. Логические операции; 4. Функциональные операции; 5. Строковые операции. Арифметические операции В QuickBASIC существуют следующие арифметические опе- рации, которые перечислены в порядке убывания приоритета выполнения: л +,- V \ MOD +,- возведение в степень присвоение знака числу1 умножение, деление целочисленное деление остаток после целочисленного деления сложение, вычитание Возведение в степень (л) 1 обратите внимание на точку с запятой после оператора 1 PRINT - это позволяет вывести результат на одной строке INPUT "Введите число "; Number% INPUT "Введите степень "; Exponent% PRINT "Степень числа равна "; PRINT Number% л Exponent% Пример: Введите число ? 2 Введите степень ? 5 Степень числа равна 32 Присвоение знака числу (-) INPUT "Введите число ";Number% PRINT "Число с обратным знаком будет PRINT Number% 1 При возведении в степень возникает исключение. Приоритет операции присвоения знака считается выше приоритета операции возведения в степень. 72
Пример: Введите число ? -7 5 Число с обратным знаком будет 75 Умножение и деление (*, /) INPUT "Введите первое число "; Numberl% INPUT "Введите второе число "; Number2% PRINT: PRINT "Произведение", "Деление" PRINT Numberl% * Number2%, Numberl% / Number2% Пример: Введите первое число ? 10 Введите второе число ? 5 Произведение 50 Деление 2 Целочисленное деление (\) INPUT "Введите первое число "; Numberl% INPUT "Введите второе число "; Number2% PRINT "Целочисленное деление равняется ' PRINT Number1% \ Number2% Пример: Введите первое число ? 54 Введите второе число ? 21 Целочисленное деление равняется 2 Нахождение остатка (MOD) INPUT "Введите первое число "; Numberl% INPUT "Введите второе число "; Number2% PRINT "Остаток от деления равняется "; PRINT Numberl% MOD Number2% Пример: Введите первое число ? 100 Введите второе число ? 33 Остаток от деления равняется 1 Сложение и вычитание (+,-) INPUT "Введите первое число "; Numberl% INPUT "Введите второе число "; Number2% 73
PRINT: PRINT "Сложение", "Вычитание" PRINT Numberl% + Number2%, Numberl% - Number2% Пример: Введите первое число ? 43 Введите второе число ? 10 Сложение 53 Вычитание 33 Порядок вычисления выражений В выражении сначала выполняются операторы более высоко- го приоритета, затем операторы одного уровня слева направо. Например: 1 Значение А в этом выражении = 2.5 А = 3 + 6/12 * 3 - 2 Порядок выполнения операторов в этом выражении: 1.6/ 12(= 0.5) 2. 0.5 * 3(= 1.5) 3. 3 + 1.5(= 4.5) 4. 4.5 - 2(= 2.5) Скобки нарушают естественный порядок вычисления ариф- метического выражения. Сначала выполняются вычисления в скобках. Алгебраическое выражение X-Y г XY Z X + Y г X(-Y) Выражение в языке QuickBASIC (X - Y) / Z X* Y/Z (X + Y) / Z X * (-Y) 74
Две связанные операции могут быть разделены скобками. Это операции *-,*+, А-иА+.В тоже время последнее выра- жение можно записать в виде X * -Y. Переполнение и деление на ноль Если при работе программы возникает деление на ноль или арифметическое переполнение, то возникают ошибки вы- полнения "Division by Zero" (Деление на ноль) и "Overflow" (Переполнение). Их можно отследить, используя операторы отслеживания событий, о которых будет подробно рассказано позднее. Операции отношения: Эти операции используются для сравнения арифметических выражений. В QuickBASIC существует шесть операций отноше- ния, перечисленных в таблице: - > < о <= >= равно1 больше меньше не равно меньше или больше или равно равно Операторы отношения используют два значения. Результатом операции отношения является либо "TRUE" (ИСТИНА — нену- левое значение2), либо "FALSE" — (ЛОЖЬ — ноль). Управляю- щие операторы в программе могут использовать результат опера- ции отношения. 1 Символ "="обозначает не только операцию отношения, но и оператор при- сваивания 2 Внутреннее представление "TRUE" (ИСТИНА) в QuickBASIC -1 Таким об- разом, выполнив PRINT 10 > 3 мы получим в результате -1 75
Оператор = о < > <= >= Значение Равенство Неравенство Меньше Больше Меньше или равно Больше или равно Выражение в BASIC X = Y Х<> Y Х< Y X>Y X<=Y X>=Y Если в одном выражении встречаются и арифметические операторы и операторы отношения, то первыми выполняются арифметические операторы. Так, в примере, сначала вычисляется значение выражения X + Y, а затем значение (Т - 1) / Z. X + Y< (T - 1) /Z При использовании значений обычной и двойной точности будьте внимательны, используя операции отношения = и О. Де- ло в том, что результаты могут отличаться на ничтожно малую величину, но это может привести к ошибке в Вашей программе. IF А! = 0.0 THEN PRINT "Точное равенство" Но в случае, если А! — очень малая величина, например 1.0Е-23, оператор PRINT исполнятся не будет. Кроме того, .ЕХЕ-программа и программа в среде QuickBASIC могут давать различные результаты. .ЕХЕ-код более точен при сравнении чисел обычной и двойной точности. Так, следующий пример будет выдавать "Равно" в QuickBASIC и "Не равно" в ЕХЕ. В! = 1.0: А! = В! / 3.0 IF А! = В! / 3.0 THEN PRINT "Равно" ELSE PRINT "He равно" Поскольку .ЕХЕ-файл более эффективно использует микро- схему сопроцессора (или эмуляцию сопроцессора), то значение переменной А! и результат выражения В! / 3.0 не совсем тожде- ственны. 76
Присвойте значение выражения временной переменной, и вы решите эту проблему. Этот фрагмент работает одинаково и в среде QuickBASIC и в .ЕХЕ-виде. В! = 1.0: А! = В! / 3.0 Ттр! = В! / 3.0 IF A! = Trap! THEN PRINT "Равно" ELSE PRINT "He равно" Если же вам все-таки необходимо сравнение чисел обычной точности, сравните разницу этих переменных: В! = 1.0: А! = В! / 3.0 IF ABS(A! - В! / 3.0) < 9.9Е^08 THEN PRINT "Равно" ELSE PRINT "He равно" END IF Логические операции Логические операции осуществляют манипуляции над бита- ми. По другому они называются "Булевы операции". Они воз- вращают значения "TRUE" (ИСТИНА — не нулевое значение, внутренние представление BASIC = -1) и "FALSE" (ЛОЖЬ — нулевое значение, внутренние представление BASIC = 0 ) IF D < 200 AND F < 4 THEN CALL Process WHILE I > 10 OR К < 0 ... WEND IF NOT P THEN PRINT "Файл не найден" В QuickBASIC существует шесть логических операторов, на- звание и толкование которых приведены ниже: 77
Опера- тор NOT AND OR XOR EQV IMP Название Отрицание Логическое умножение Логическое сложение Исключающее ИЛИ Эквивалент- ность Импликация Объяснение NOT А истинно тогда и только тогда, когда А ложно A AND В истинно тогда и только тог- да, когда истинно А и истинно В A OR В истинно тогда и только тогда, когда хотя бы одно из А и В истинно A XOR В истинно тогда и только тогда, когда значения А и В не совпадают A EQV В истинно тогда и только тог- да, когда А и В одновременно истин- ны или одновременно ложны A IMP В принимает значение "ложь" если А истинно а В ложно, и значе- ние "истина" в других случаях. 'В этом примере показана работа со всеми логическими операторами Qu i с kBASIС: DECLARE SUB TruthTable (X%, Y%) DEFINT A-Z CLS PRINT " X Y NOT AND OR PRINT "XOR EQV IMP" PRINT I = 10: J = 15 'X = TRUE (-1); Y = TRUE (-1) X = (I = 10): Y = (J = 15) CALL TruthTable(X, Y) 'X = TRUE (-1); Y = FALSE @) X = (I > 9) : Y = (J > 15) CALL TruthTable(X, Y) "X = FALSE @); Y = TRUE (-1) X = (I <> 10): Y = (J < 16) CALL TruthTable(X, Y): ¦X = FALSE @); Y = FALSE @) X = (I < 10) : Y = (J < 15) 78
CALL TruthTable(X, Y) END SUB TruthTable (X%, Y%) STATIC PRINT X; " "; Y; " "; NOT X; " "; X AND Y; " PRINT X OR Y; " "; X XOR Y; " "; X EQV Y; PRINT " "; X IMP Y PRINT END SUB Результат X Y NOT AND OR XOR EQV IMP -1 -1 0-1-10 -1 -1 -10 0 0-1-10 0 0-1-10 -1 -1 0 -1 0 0-10 0 0-1-1 Функциональные операции Функциональные операции определяют правила работы с функциями. Функции используются в выражениях для осуществ- ления заранее определенных операций. Например: А = SQRB0.25) + SQRC7) В QuickBASIC существуют два вида функций: встроенные и определенные пользователем. Примерами встроенных функций может служить вышеприведенная пример вычисления квадратно- го корня (SQR), а также синуса (SIN), косинуса (COSI и др. Встроенные функции более подробно описаны в разделе "Обра- ботка числовых данных" и "Обработка символьных данных". Вы можете определить функцию при помощи новой конст- рукции FUNCTION...END FUNCTION или воспользоваться бо- лее старой конструкцией DEF...END DEF. Пользовательские 1 Появление синуса и косинуса в тексте нашей книги напоминает старый анекдот — "Неуспевающий студент приходит сдавать экзамен по высшей мате- матике и списывает ответ на свой вопрос. Подойдя к профессору, он не может сказать ни слова по поводу написанного. Но вдруг натыкается на знакомые бу- ковки — sin Тут он и говорит: "Профессор — а вот и синус, а вот и косинус — и это все я написал! Мне вполне можно поставить тройку..." 79
функции действуют только в той программе, где они определены и не являются частью языка (если они не скомпилированы в Quick-библиотеку). В дополнении к FUNCTION и DEF FN, вы также можете определять процедуры при помощи конструкции SUB. О пользовательских функциях рассказано в разделе "Мо- дульное программирование" этой главы. Строковые операции Над строками можно осуществлять следующие действия — конкатенация (сложение) и сравнение строк. Конкатенация (сложение) строк Конкатенация — это сложение двух символьных строк. Для сложения используется символ (+). В примере результатом сло- жения переменных А$ и В$ является значение FILENAME. А$ = "FILE": B$ = "NAME" PRINT A$ + В$; PRINT "NEW " + А$ + В$ Результат: FILENAME NEW FILENAME Сравнение строк Сравнение строк производится при помощи операторов срав- нения: <>, =, <, >, <=, >= Сравнение строк производится в со- ответствии с ASCII кодами каждого символа в сравниваемых строках. Если ASCII коды равны, то строки считаются равными. Строка, символы которой имеют большие ASCII коды, считается большей. Если одна из сравниваемых строк короче другой, то она считается меньшей (если до этого места строки были равными). При сравнении учитываются начальные и конечные пробелы. Примеры правильных операций сравнения1: "АА" < "ВБ" "FILENAME" = "FILE" + "NAME" 1 При сравнении строк, содержащих символы кириллицы следует соблюдать определенную осторожность, и не полагаться целиком на сравнение средствами BASIC. Дело в том, что расширенная ASCII таблица содержит вместо символов кириллицы буквы европейских алфавитов, что может привести к некорректному сравнению строк. 80
11 Х&" > "Х#" "фф " > "фф" "кг" > "КГ" "СЛОН" < "СЛОНЫ" В$ < "9-12-78" ' где В$ = "8-12-78" Сравнение строк можно использовать для оценки их содер- жимого, если эти строки содержат числа. ASCII коды символов приведены в Приложении 5. Операторы передачи управления При разработке программ часто приходится изменять поря- док следования операторов. Только в очень простых программах операторы выполняются один за другим — управление передает- ся последовательно, от оператору к оператору. На практике же, необходимые средства для изменения порядка следования опера- торов, другими словами, передачи управления — обеспечивают операторы цикла и условные операторы. Операторы цикла Циклы используются в том случае, когда вам необходимо не- сколько раз выполнить один и тот же фрагмент исходного текста. В BASIC существуют три вида циклов: FOR...NEXT; DO... LOOP; WHILE...WEND FOR...NEXT Цикл FOR...NEXT — это цикл с заранее заданным количе- ством повторений. Можно также выйти из цикла не дожидаясь выполнение всех повторений — воспользуйтесь альтернативным выходом из цикла при помощи оператора EXIT FOR. Управление будет передано на оператор, стоящий после NEXT. Пример: 1 этот цикл повторяется 5 раз FOR i% = 1 ТО 5 PRINT "Хорошо живет на свете Винни-Пух!" NEXT i% 81
Результат: Хорошо живет на свете Винни-Пух! Хорошо живет на свете Винни-Пух! Хорошо живет на свете Винни-Пух! Хорошо живет на свете Винни-Пух! Хорошо живет на свете Винни-Пух! DO...LOOP Цикл DO...LOOP выполняется до тех пор, пока истинно ус- ловие в начале или конце цикла. А также из цикла возможен аль- тернативный выход — вне зависимости от того выполнено ли ус- ловие выхода, из цикла можно выйти оператором EXIT DO, ко- торый передает управление на оператор, следующий за LOOP. Пример: 'этот цикл повторяется до тех пор (DO), пока пользователь 'не введет число, превышающее 10 (LOOP WHILE n <=10) — 'повторять, пока п меньше или равно 10) DO INPUT "Введите число N ?"; п LOOP WHILE n <= 10 WHILE...WEND При использовании цикла WHILE...WEND условие может быть только в начале цикла. Альтернативный выход из цикла WHILE...WEND - невозможен. Пример: WHILE n <= 10 INPUT "Введите число N ?"; п WEND Условные операторы Условные операторы BASIC помогают вам осуществить "вет- вление" программы, т. е. передать управление по условию, на ту или иную "ветку" — это может быть фрагмент текста, процедура SUB или FUNCTION, подпрограмма GOSUB...RETURN, или даже другой модуль. Виды условных операторов BASIC: IF...THEN...ELSE SELECT...END SELECT 82
IF...THEN...ELSE IF...THEN...ELSE обычно используется, когда проверяется одно или два условия в программе. Пример: IP CheckPrinter% = TRUE THEN PRINT "Принтер готов для работы..." ELSE PRINT "У принтера сегодня выходной ..." END IF SELECT... END SELECT Если же необходимо осуществить проверку более сложных условий, чем ДА/НЕТ, целесообразно использовать условный оператор SELECT... END SELECT. SELECT CASE Declaim% CASE IS = 1 PRINT "Любит ..." CASE 2 TO 999 PRINT "He любит ..." CASE IS = 0, IS = 1000, IS < -1 PRINT "Замужем" CASE ELSE PRINT "При исполнении ..." END SELECT Избегайте устаревших конструкций Может возникнуть вопрос, почему автор ни словом не об- молвился про оператор GOTO. Дело в том, что оператор GO- TO — старейший и неструктурированный оператор языка BASIC. Программу с обилием GOTO трудно читать, отлаживать, моди- фицировать, так как она не имеет четкой структуры. Использование в программе оператора GOTO свидетельству- ет о том, что программист не полностью овладел всем богатством управляющих структур языка QuickBASIC, или не знает их воз- можностей, а кроме того, не существует программных конструк- 83
ций, где действительно было бы необходимо применение опера- тора GOTO1. Приведу примеры того, как можно избежать применения GOTO и других устаревших конструкций, которые достались QuickBASIC "по наследству" от первого поколения языка BASIC — интерпретаторов GWBASIC и BASICA2. Как получить код нажатой клавиши: ml: А$ = INKEY$: IF А$ = "" GOTO ml Эту конструкцию можно переписать, используя цикл DO...LOOP WHILE: DO: A$= INKEY$: LOOP WHILE A$ = Как выйти из цикла по условию: FOR i = 1 ТО 1000 IF Flag% = TRUE THEN GOTO m999 NEXT i 1 Основная теорема структурного программирования, доказанная Э Дейкстрой гласит: "Алгоритм любой сложности можно реализовать, используя только три конструкции: следование (оператор за оператором), повторение (цикл) и выбор (альтернатива)" 2 Фирма Microsoft всегда была очень щепетильна в отношении совместимости своих программных продуктов Так, QuickBASIC полностью поддерживает все возможности языков GWBASIC и BASICA, BASIC Professional Development System — все возможности QuickBASIC. К сожалению, этого нельзя сказать о последнем поколении ялжа BASIC — Visual BASIC for Windows, который не поддерживает даже подмножество QuickBASIC. 84
m999: В этом случае можно воспользоваться альтернативным выхо- дом из цикла FOR. NEXT - EXIT FOR: FOR i = 1 TO 1000 IF Flag% = TRUE THEN EXIT FOR NEXT i Точно также можно выйти и из цикла DO...LOOP: DO IF Flag% = TRUE THEN EXIT DO LOOP Предвижу вопрос: а если нужно выйти из середины конст- рукции WHILE...WEND - ведь оператор EXIT WHILE не пре- дусмотрен (также как и EXIT SELECTI ? Казалось, бы — ведь в таких случаях можно просто написать: WHILE A$ о "Конец" IF Flag = FALSE THEN GOTO m998 WEND m998: 1 Вопросы "почему?" направляйте по адресу: United States of America Microsoft Corporation One Microsoft Way Redmond, WA 98052-6399 (800) 227-4679 85
Я считаю, что и в этом случае применение оператора GOTO излишним. Конечно, чтобы обойти это ограничение приходится идти на хитрость — обрамлять конструкцию бесконечным цик- лом DO...LOOP и выходить с помощью EXIT DO — даже в этом случае, это гораздо удобнее, нагляднее, и я бы сказал красивее: DO WHILE A$ <> "Конец" IF Flag = FALSE THEN EXIT DO WEND LOOP Также можно организовать и "EXIT SELECT": DO INPUT Kod SELECT CASE KOD CASE IS = ... CASE IS = 0: EXIT DO CASE ELSE ... END SELECT LOOP Как избежать синдрома "ёжика в тумане" При организации ветвления бесконечные операторы GOTO мешают понять логику программы: 30 INPUT A IF A > 100 THEN PRINT "Это много": GOTO 30 IF A = 100 THEN GOTO 3 00 PRINT A/100: GOTO 3 0 300 ... Вместо этого можно использовать или блочную форму опе- ратора IF..THEN...ELSE в окружении цикла DO...LOOP WHILE: DO INPUT A IF A < 100 THEN 86
PRINT A / 100 'ELSEIF A > 100 THEN PRINT "слишком много" END IF LOOP WHILE A <> 100 ...или конструкцию SELECT...CASE в окружении цикла DO ... LOOP DO INPUT A SELECT CASE A CASE IS < 100: PRINT A / 100 CASE IS > 100: PRINT "слишком много" CASE IS = 100: EXIT DO END SELECT LOOP Как правильно "разветвиться" При организации ветвления вместо устаревшей управляющей конструкции ON...GOSUB используйте более современную кон- струкцию SELECT...END SELECT: m0: INPUT A ON A GOSUB ml, m2, тЗ , тЗ , m4, m4, m4 GOTO m5 ml: X = у * z RETURN m2 : RETURN m3: RETURN m4 : RETURN m5: ... He правда ли, с первого раза трудно понять, что это фраг- мент программы делает. Приходится проговаривать про себя: 87
"Если значение А равно единице, то ... перейти на метку... метку ml, вычислить значение X... вернуться на следующий оператор пос- ле ON...GOSUB ... это переход на метку т5 ... метка т5— это продолжение выполнения программы..." Посмотрите, насколько удобнее использование конструкции SELECT...END SELECT: INPUT A SELECT CASE A •CASE IS = 1: X = у * z CASE IS = 2 CASE IS = 3, 4 CASE 5 TO 7 END SELECT "Если значение А равно единице, вычислить значение X и поки- нуть SELECT...END SELECT' - и все? - и все! В разделе "Модульное программирование" речь пойдет о том, как организовать Вашу программу в виде независимых структур — процедур SUB и FUNCTION, функций DEF FN и подпрограмм GOSUB...RETURN — объединенных в один или несколько модулей. При первом чтении этой книги вы можете пропустить этот раздел, и вернуться к нему позднее. Ввод и вывод значений Ввод значений После того, как вы определились с тем, переменные каких типов вы будете использовать в программе, им необходимо при- своить начальные значения. Если значений не много, можно использовать операцию присваивания: Message$ = "Внимание!"
Total = 555 Можно использовать константы: CONST Message$ = "Внимание!", Total = 555 Для большого количества переменных можно использовать оператор DATA: DATA "Лена", 1976, "Катя", 1975, "Оля", 1980 READ Girll$, yearl$, Girl2$, year2$, Girl3$, year3$ Эти способы удобно использовать в тех случаях, когда про- грамме нужны фиксированные, заранее заданные значения. А ес- ли нужно менять значения по ходу работы программы? Вносить изменения в текст программы при каждом изменении — не са- мый лучший выход. INPUT К счастью, в BASIC существует оператор INPUT, который позволяет запросить у пользователя значение необходимой пере- менной. 1 Введенное с клавиатуры имя присваивается 1 переменной Fam$ INPUT "Введите ваше имя "; Fam$ 'Результат выводится на экран PRINT "Здравствуйте, товарищ "; Fam$; "!" Результат: Введите ваше имя ? Петя Здравствуйте, товарищ Петя! Можно ввести одновременно значения нескольких переменных, при этом значения должны отделяться запятыми. Тип вводимых зна- чений должен соответствовать типам переменных, перечисленных в операторе INPUT, иначе BASIC выдаст сообщение "Redo from start" (Начните сначала). Нажатие клавиши {ENTER} заканчивает ввод. 89
INPUT "Введите имя и год рождения "; Fam$, уеаг% PRINT Fam$; ", вы родились в"; STR$(уеаг%); "году." Результат: Введите ваше имя и год рождения ? Вася, 1977 Вася, вы родились в 1977 году. LINE INPUT Так как вводимые значения в операторе INPUT должны от- деляться запятыми, при помощи него нельзя ввести строку сим- волов, например фразу, в которой содержатся запятые, — BASIC воспримет их как разделитель. В этом случае используется оператор LINE INPUT: LINE INPUT "Введите ключевую фразу "; frase$ PRINT "вы ввели: " + CHR$C4) + frase$ + CHR$C4) Результат: Введите ключевую фразу ? Казнить нельзя, помиловать вы ввели "Казнить нельзя, помиловать" INPUT$ Иногда необходимо ввести фиксированную строку символов так, чтобы они не печатались на экране — например, ну очень секретную информацию.. В этом случает выручает оператор INKEY$. Он ждет нажатия заданного количества символов. В данном примере это используется для ввода пароля. 1 выводим на экран напоминание PRINT "Введите пароль F букв) для дальнейшей работы" 'цикл DO...LOOP повторяется до ввода правильного пароля DO 'Ждем ввода 5 символов Parol$ = INPUT$E) LOOP WHILE Parol$ ^> "Пароль" Если же вам необходимо отследить нажатие управляющих клавиш: {ENTER}, {ESC}, функциональных клавиш, тогда целе- сообразно использовать оператор INKEY$. В отличии от опера- торов INPUT, LINE INPUT и INPUTS, которые ждут ввода зна- 90
чений с клавиатуры, INKEYS этого не делает, поэтому оператор INKEYS всегда используется в цикле: 'выводим на экран напоминание PRINT "Нажмите клавишу {ENTER} или {ESC}" 1 цикл DO... LOOP повторяется пока не будет нажата 'клавиша {ENTER} (код 13) или {ESC} (код 27) DO KeyString = INKEY$ LOOP WHILE KeyString$ <> CHR$A3) OR KeyString$ <> CHR$B7) Более подробно об операторах ввода рассказано в главе 5 "Ввод/вывод на внешние устройства" Вывод значений Недостаточно только присвоить значение переменной или кон- станте. В конечном счете программа работает не ради себя, а ради человека, и должна вывести значения в понятной ему форме. PRINT Для вывода значений на экран дисплея используется опера- тор PRINT: Vopros$ = "Почем опиум для народа ???" PRINT " Имею вопрос - "; Vopros$ Результат:' Имею вопрос - Почем опиум для народа ??? Также как и оператор INPUT, PRINT позволяет вывести не- сколько значений, при этом разделителями могут служить запя- тая "," или точка с запятой ";": Subject$ = "Компьютер" Country$ = "США" PRINT Subject$; Country$ PRINT PRINT Subject$, Country$ 91
Результат: КомпьютерСША Компьютер США Оператор PRINT без параметров выводит на экран пустую строку. Если необходимо вывести на экран строку, содержащую запятые — указывайте код запятой в таблице ASCII C4) в списке параметров вызова оператора PRINT: PRINT CHR$C4) + "QuickBASIC" + CHR$C4) Результат: "QuickBASIC" PRINT USING Если необходимо вывести на экран строку символов по за- ранее известному формату, используйте оператор PRINT USING: Subject$ = "Компьютер" Country$ = "США" Price% = 999 Format$ ="Изделие: \ \ из \ \ по цене $###.##" PRINT USING Format$; Subjects,- CountryS; Price% Результат: Изделие: Компьютер из США по цене $999.00 LPRINT и LPRINT USING Операторы PRINT и PRINT USING выводят информацию на экран. Для того, чтобы напечатать ее, используйте операторы LPRINT и LPRINT USING: Test$ = "Проверка принтера ..." 'эта строка выводит значение переменной Test$ на эк- ран PRINT Test$ 'эта строка выводит значение переменной Test$ на принтер LPRINT Test$ 92
Более подробно об операторах вывода можно прочитать в главе 5 "Ввод/вывод на внешние устройства" LOCATE Для того, чтобы красиво разместить текст на экране, в языке BASIC есть оператор LOCATE. В текстовом режиме экран разби- вается на 25 строк и 80 столбцов, что позволяет вывести символ в любом месте экрана. Пример: Вывод сообщения в центре экрана, на 12 строке, J6 столбце. LOCATE 12, 36: PRINT "И все-таки она вертится!" Для рисования одинарных и двойных линий, рамок и зак- раски изображений шаблонами, среди элементов таблицы ASCII имеются символы псевдографики, приведенные в Приложении 5 в разделе "Символы псевдографики для рисования рамок и таблиц". Они позволяют создавать изображения на экране, не используя медлительный графический режим1. См. Главу 6 "Графика и звук", раздел -х мерные объекты в текстовом режиме" Способ вывода еимволов псевдографики ничем не отличает- ся от вывода символьных переменных и констант — используйте оператор PRINT: FOR i = 1 ТО 10: PRINT STRING$(i,"|"): NEXT i Ниже приведена программа, рисующая график. Она исполь- зует оператор LOCATE для рисования самого графика, коорди- натной сетки и подписи к нему: 'Все переменные целые DEFINT A-Z DATA Урожайность зерновых в колхозе "Путь к убытку" DATA 45,50,40,30,25,20,25 1 считывание значений DIM ValueG) READ Maintitle$ FOR i = 1 TO 7 1 А при работе с Microsoft BASIC PDS вы сможете даже загрузить в текстовом режиме свои собственные экранные шрифты, расширив тем самым набор сим- волов псевдографики или изменив очертания существующих. 93
READ Valued) NEXT i 1 рисуется рамка COLOR 0, 3: CLS : COLOR 0, 7 FOR i - 4 TO 20 LOCATE i, 10: PRINT SPACE$F0) NEXT i COLOR 0, 3: LOCATE 4, 70: PRINT "m" FOR i = 5 TO 20 LOCATE i, 70: PRINT "|" NEXT i FOR i = 11 TO 70 LOCATE 21, l: PRINT»"" NEXT i COLOR 0, 7 'рисуется координатная сетка FOR i = 7 TO 17 LOCATE i, 17: PRINT "|" NEXT i FOR i = 18 TO 65 LOCATE 18, i: PRINT "-" NEXT i LOCATE 18, 16: PRINT "—{-" start = 7 FOR i = 50 TO 0 STEP -10 LOCATE start, 13: PRINT i start = start + 2 NEXT i 'Вывод заголовка LOCATE 5, 20: PRINT Maintitle$ 1 Вывод значений start = 21 FOR i = 1 TO 7 visota = Valued) / 5 COLOR i - 1, 7 LOCATE 17 - visota, start: PRINT Value(i) FOR j = visota TO 1 STEP -1 LOCATE 18 - j, Start: PRINT STRING$D, "||" ) NEXT j start = start + 6 NEXT i DO: LOOP WHILE INKEY$ = 94
Результат: Почему BASIC не выговаривает русскую букву "р" "Взирая на солнце, прищурь глаза свои, и ты смело разглядишь в нем пятна " — говаривал Козьма Прутков. Одним из самых обид- ных "пятен" языка QuickBASIC является то, что стандартными средствами (INPUT, INPUTS, LINE INPUT, INKEY$) невоз- можно ввести символ с кодом 224 — это малая русская буква "р" в альтернативной кодировке. Это связано с некорректным опро- сом клавиатуры, который выполняет BASIC. Но что же остается делать нам, "русскоговорящим" пользо- вателям? "Если нельзя, но очень хочется, то можно!". Существует три способа решения этой проблемы: 1. Использовать драйвер русских букв с изменяемой раскладкой клавиатуры, который бы подставлял английскую букву "р" вместо русской "р". (См. раздел "Как нам обустроить QuickBASIC?" из Главы Первой). Однако, если вы вводите таким способом, скажем фамилии, то их невозможно будет отсортировать по алфавиту; 2. Отказаться от стандартных операторов BASIC и опрашивать клавиатуру самостоятельно, используя прерывание BIOS 16h, 95
функция 0. Текст такой процедуры приведен в главе 12 "Расширение возможностей QuickBASIC 4.5"; 3. Перейти на следующую версию языка — Microsoft BASIC Professional Development System, где эта ошибка, наконец, ис- правлена. Модульное программирование (*) "Служил Гаврила программистом, Софтвер Гаврила сочинял. Из под пера его со свистом Программный модуль вылетал..." Почти по Ильфу и Петрову При разработке собственной программы у каждого програм- миста через некоторое время появляется большой набор соб- ственных заготовок, неординарных решений и т. д., которые он хотел бы использовать во всех своих творениях. QuickBASIC предоставляет такую возможность, позволяя разрабатывать программы по модульному принципу. Модуль — это отдельная, полностью независимая от других, часть Вашей программы. Каждая программа на QuickBASIC может состоять из одного или нескольких модулей. Каждый модуль имеет главную часть. В главной части моду- ля описываются процедуры и функции модуля (операторами DECLARE), функции DEF FN, константы (оператор CONST). Один из модулей называется главным. Он содержит так на- зываемую точку входа, с которой начинается выполнение про- граммы. В каждой программе может быть только один главный модуль. К главному модулю можно подключить один или несколько вспомогательных (дополнительных) модулей. В чем же преиму- щество модульного программирования? • Так как вспомогательные модули — это отдельные файлы программ, в них обычно выносятся процедуры и функции, которые используются одновременно в нескольких програм- мах. Таким образом, вы как бы собираете программу из гото- вых блоков (модулей); 96
Если вы дополняете или исправляете какую-либо процедуру или функцию из вспомогательного модуля, то все исправле- ния автоматически становятся доступны всем Вашим про- граммы, которые эти модули используют; Сосредоточение вспомогательных модулей в одном месте об- легчает поиск нужного фрагмента исходного текста, и позво- ляет избежать ситуации, когда одна и та же процедура суще- ствует в нескольких вариантах в каждой программе. В составе модуля можно выделить следующие самостоятель- ные блоки: функции DEF FN, процедуры SUB и FUNCTION. Функция DEF FN Функция DEF FN — входит в главную часть модуля. Как и процедура FUNCTION, DEF FN возвращает одно значение и ис- пользуется аналогично встроенной функции QuickBASIC. 1 Функция вычисляет десятичный логарифм числа, используя встроенную функцию нахождения натурального логарифма. DEF FNLoglO (X) FNLoglO = LOG(X) / LOG(IO.O) END DEF 97 Структура модульной программы Главный модуль содержит точку входа, с которой начи- нается исполнение программы Дополнительные модули, которых может несколько, содержат проце- дуры и функции для главного модуля
INPUT "Введите число: ",Num PRINT 0 Л LoglO(";Num;") is ";10.O^FNLoglO(Num) END Имя функции всегда должно начинаться с букв FN. DEF FN не может быть рекурсивной (не может вызывать сама себя), и должна быть определена перед использованием. Использовать функцию DEF FN можно только в том модуле, в котором она определена. Функция DEF FN — это устаревшая программная конструк- ция, доставшаяся QuickBASIC "по наследству" от GWBASIC. Практически во всех случаях лучше использовать более совре- менную конструкцию FUNCTION...END FUNCTION1. Процедура FUNCTION Процедура FUNCTION является более мощной альтернати- вой DEF FN. Так же как и DEF FN, FUNCTION возвращает одиночное значение и может использоваться в выражениях. Од- нако существуют и отличия. Процедура FUNCTION может быть рекурсивной (вызывать сама себя). В отличии от функции DEF FN процедура FUNCTION мо- жет использоваться вне того модуля, где она определена. Это значит, что процедура FUNCTION, которая находится во вспо- могательном модуле, становится доступна любому модулю Вашей программы. Не забудьте, однако добавить оператор DECLARE в те модули, где она используется. Текст процедуры FUNCTION не входит в главную часть модуля. DECLARE FUNCTION LoglO(X) INPUT "Введите число: ",Num PRINT 0 Л LoglO(";Num;") is ";10.O^LoglO(Num) END 1 Однако существуют редкие случаи, когда использование функции DEF FN предпочтительнее. Дело в том, что в отличии от FUNCTION, функция DEF FN не проверяет тип числового аргумента. Например функция FNS возвращает сим- вольное представление любого числового аргумента: DEF fns$ (z) 'превращение в строку fns$ = LTRIM$(STR$(z)) END DEF При использовании функции FUNCTION пришлось бы писать четыре оди- наковых функции для целых, длинных целых, обычной и двойной точности ти- пов данных. 98
1 Функция вычисляет десятичный логарифм числа, используя 1 встроенную функцию нахождения натурального логарифма. DEF FNLoglO (X) LoglO = LOG(X) / LOGA0.0) END FUNCTION Процедура SUB В отличии от функции DEF FN и FUNCTION, SUB вызыва- ется как отдельный оператор. ' Напечатать сообщение в Центре экрана. CLS CALL PrintMessage A2, 40, "Hello!") END ' процедура печати сообщения в указанных строке и столбце. SUB PrintMessage (Row%, Col%, Message$) 1 Запоминание текущей позиции курсора. CurRow% = CSRLIN CurCol% = POS(O) 1 Вывод сообщения LOCATE Row%, COL% : PRINT Message$; 1 Восстановление текущей позиции курсора. LOCATE CurRow%, CurCol% END SUB Процедура SUB может возвращать несколько значений в вы- зывающую подпрограмму. SUB не может быть использована как часть выражения, а только как оператор. Процедура SUB возвращает значения, производя вычисления над переменными из списка аргументов. Это единственная воз- можность для SUB переслать значения. Если процедура SUB объявлена оператором DECLARE, то при вызове процедуры вы можете опустить ключевое слово CALL. DECLARE SUB PrintMessage (Row%, Col%, Msg$) 1 Напечатать сообщение в центре экрана. CLS PrintMessage 12, 40, "Hello!" END Вы можете писать процедуры, которые могут вызывать сами себя — то есть процедуры SUB могут быть рекурсивными. 99
Также как и FUNCTION, процедура SUB может использо- ваться вне того модуля, где она определена. Таким образом, про- цедура SUB, которая находится во вспомогательном модуле, стано- вится доступна любому модулю Вашей программы. Не забудьте, однако добавить оператор DECLARE в те модули, где она исполь- зуется. Текст процедуры SUB не входит в главную часть модуля. Рекурсия QuickBASIC позволяет вам писать рекурсивные процедуры SUB и FUNCTION (процедуры, вызывающие сами себя). В рекурсивных процедурах реализован принцип "Разделяй и властвуй" — сложные алгоритмы разбиваются на более простые и решаются. 1 Этот пример использует рекурсивную процедуру FUNCTION 1 для поиска и возврата длины строки DECLARE FUNCTION StrgLng% (X$) CLS INPUT "Введите строку: "; InString$ PRINT "Длина строки равна "; StrgLng%(InString$) FUNCTION StrgLng% (X$) IF X$ = "" THEN 'Длина нулевой строки равна нулю StrLng% = 0 ELSE 'Ненулевая строка - рекурсивный вызов. 'Длина ненулевой строки равна 1 плюс 'длина оставшейся части строки StrgLng% = 1 + StrgLng%(MID$(X$, 2)) END IF END FUNCTION Границы использования переменных и констант В языке QuickBASIC вы можете контролировать область дей- ствия переменных и констант. Это позволит вам писать компакт- ные процедуры, которые не влияют на работу друг друга. В тоже время вы можете объявить, что часть переменных доступна всем процедурам в модуле (совместное использование). Область действия переменных и констант может быть: 1. Глобальной; 2. Локальной; 3. Совместно используемой. 100
Глобальные переменные и константы Глобальными могут быть как переменные, так и символьные константы. Переменная (константа) считается глобальной, если она определена на уровне модуля. Для того, чтобы сделать пере- менную глобальной необходимо добавить атрибут SHARED при описании переменной оператором DIM, REDIM или COMMON. Для констант достаточно оператора CONST в главном модуле: DEFINT A-Z CONST MAXLINE = 255, TABSPACE = 8 DIM SHARED TabStops(MAXLINE) SUB SetTabPos END SUB Локальные переменные и константы Локальные переменные и константы существуют только в модуле или процедуре, где они используются. Таким образом, ес- ли не объявлено иное, то все переменные в каждом модуле (процедуре) считаются локальными. В случае, если в другом мо- дуле (процедуре) используется переменная с этим же именем, то QuickBASIC считает ее новой переменной. При входе в процедуру или функцию значения переменных обнуляются. Если вы не хотите, чтобы значения переменных обнулялись, то при добавьте ключевое слово STATIC при описании процеду- ры, при этом значения переменных будут сохраняться между вы- зовами процедур. SUB SetStops (x%,xl%,i%) STATIC END SUB 101
При помощи оператора STATIC можно сохранять значения отдельных переменных между вызовами процедур1. SUB SetStops (x%,xl%,i%) STATIC i END SUB Совместно используемые переменные Вместо того, чтобы объявлять переменные глобальными при помощи оператора SHARED, вы можете совместно использовать переменные между определенными процедурами. Так, массив SetTabPos совместно используется только в главном модуле и процедурах SetTabPos и ThisIsATab. В других процедурах и функ- циях он не доступен. DIM TabStops(MAXLINE) SUB SetStops STATIC SHARED TabStopsO END SUB FUNCTION ThisIsATab(LastColum as INTEGER) STATIC SHARED TabStopsO END SUB Переменные в функции DEF FN Все переменные функции DEF FN являются частью модуль- ного кода. Чтобы сделать переменную в функции DEF FN ло- кальной, вы должны явно указать при определении переменной оператор STATIC. В данной функции DEF FN оператор STATIC делает переменную I локальной: 1 Поэтому не используйте оператор STATIC в рекурсивных процедурах. 102
CONST NO=0, YES = NOT NO DEF FNIsThereAZ (a$) STATIC I FOR 1 = 1 TO LEN(A$) IF UCASE(MID$(A$,I,1)) = "Z" THEN FNIsThereAZ = YES EXIT DEF END IF NEXT I FNIsThereAZ = NO END DEF Параметры в процедурах SUB и FUNCTION Каждая процедура SUB и FUNCTION должна быть по свое- му уникальна, поэтому невозможно точно ответить на вопрос — сколько нужно передавать параметров. Но сформулировать об- щие положения можно. Решая подобного рода задачи, как мне кажется, следует до минимума сократить количество параметров в процедурах и функ- циях. Наиболее оптимальным следует признать использования "правила кино" — как фильме не должно быть более 7 действую- щих лиц (больше человек не может запомнить), так и число пара- метров по возможности не'должно превышать этого числа. Ниже перечислены приемы минимизации количества параметров: • Значения, передаваемые между служебными процедурами, следует описывать с атрибутом SHARED и не включать в список параметров; • Цвета должны быть "зашиты" в процедуру. Если цвет все- таки необходим, то его можно передать одним шестнадцате- ричным значением: CALL ColorExample (&H16) '1 - фоновый цвет, 6 - ос- новной SUB ColorExample (col%) PRINT "Основной цвет = "; col% MOD 16 PRINT "Основной цвет = "; col% \ 16 END SUB • В процедуру или функцию не должны передаваться парамет- ры, которые можно вычислить другим способом. Например, 103
если в процедуру, формирующую окно-список, передается вектор, содержащий значения элементов, то можно вычис- лить количество элементов в векторе (функция UBOUND), и ширину окна (по самому широкому элементу). Использование включаемых (INCLUDEI файлов Для каждой процедуры SUB и FUNCTION, которые встре- чаются в программе, BASIC генерирует соответствующий опера- тор DECLARE. Если Вашей программе большое количество про- цедур и функций (а сюда еще надо прибавить процедуры и фун- кции вспомогательных модулей), то длинный список операторов DECLARE отвлекает внимание от текста основной программы. Чтобы этого избежать, можно использовать включаемый (INCLUDE) файл. Встретив в тексте программы ссылку на INC- LUDE-файл, BASIC автоматически переключается на обработку этого файла и возвращается в программу после завершения работы. Кроме операторов DECLARE, в INCLUDE-файл обычно включаются определения констант и функций DEF FN. К примеру, если Ваша программа использует процедуры SUB и FUNCTION ClearScreenO, LineDraw(), MessageBox(), Ramka(), WaitKey(), SeredinaS (), требует констант TRUE и FALSE, определя- ет все переменные как целые, и требует FN-функцию fns$(), то на- чало Вашей программы будет выглядеть примерно так: DECLARE SUB ClearScreen () DECLARE SUB LineDraw (x%, y%, xl%, yl%) DECLARE SUB MessageBox (message$, kod%) DECLARE SUB Ramka (x%, y%, menu$(), vyb%) DECLARE SUB WaitKey (kod%) DECLARE FUNCTION Seredina$ (line$, dlina%) CONST TRUE% = -1, FALSE% = 0 DEFINT A-Z DEF fns$ (z%) fns$ = LTRIM$(STR$(z)) END DEF 1 основной текст программы DO LOOP END 1 См. Приложение 7 "Метакоманды" 104
Однако, используя INCLUDE-файл INTERFAC.BI вы може- те записать то же самое гораздо проще: '$INCLUDE: 'interfас.bi' 1 основной текст программы DO LOOP END При этом содержание файла INTERFAC.BI выглядит следу- ющим образом: DECLARE SUB ClearScreen () DECLARE SUB LineDraw (x%, y%, xl%, yl%) DECLARE SUB MessageBox (message$, kod%) DECLARE SUB Ramka (x%, y%, menu$(), vyb%) DECLARE SUB WaitKey (kod%) DECLARE FUNCTION Seredina$ (line$, dlina%) CONST TRUE% = -1, FALSE% = 0 DEFINT A-Z DEF fns$ (z%) fns$ = LTRIM$(STR$B)) END DEF Чтобы добавить INCLUDE-файл в Вашу программу необхо- димо проделать следующее: 1. Выделить {SHIFT+стрелки} операторы программы, подлежащие переносу в INCLUDE-файл: DECLARE, CONST, DEFjran, функции FN и перенести их в буфер при помощи клавиш {SHIFT-DEL}; 2. Создать новый файл {ALT-F, С} как INCLUDE-файл, (пункт INCLUDE) и перенести в него содержимое буфера {SHIFT-INS}; 3. В главную часть всех модулей программы добавить директиву 'SINCLUDE: 'имявключаемогофайла'
Построение многомодульной программы Исходный текст на языке BASIC В этом разделе на конкретном примере будет показано, как построить многомодульную программу. Она содержит главный модуль TEST.BAS, а также вспомогательный модуль INTERFAC, в" котором находятся процедуры, обеспечивающие работу с пользовательским интерфейсом: • ClearScreen — заполняет экран символами ":|" • LineDraw — рисует рамку с тенью; • MessageBox — выводит сообщение в центре экрана; • Ramka — обеспечивает работу с меню; • Seredina$ — выравнивает символьную строку. Для начала введите текст программы и сохраните его под именем TEST.BAS 1 это операторы объявления процедур и функций 'QuickBASIC поставит их самостоятельно DECLARE SUB ClearScreen () DECLARE SUB LineDraw (x%, y%, xl%, yl%) DECLARE SUB MessageBox (message$, kod%) DECLARE SUB Ramka (x%, y%, menu$(), vyb%) DECLARE SUB WaitKey (kod%) DECLARE FUNCTION Seredina$ (line$, dlina%) 'объявление констант функциональных клавиш CONST UP% = 72, DOWN% = 80, ESC% = 27, LEFT% = 75 CONST RIGHT% =77, ENTER% =13 1 объявление констант TRUE и FALSE CONST TRUE% = -1, FALSE% = 0 'объявление "музыкальных констант" CONST Simple$ = MFT255L16O6CO4GEDCBT255L16O6CO4_ GEDCBT2 5 5L16O6CO4GEDC" CONST bad$ = "mftl20o016eeel2c" CONST good$ = "mft200o215cl7el7g>14c<18g>12c" 'все переменные целые DEFINT A-Z 1 в символьном массиве meny$ - 4 элемента REDIM meny$D) 106
107 'присваиваем значение элементам массива meny$(l) = "Вывести сообщение" meny$B) = "Вывести сообщение со счетчиком" meny$C) = "Вывести сообщение с кнопкой ОК" meny$D) = "Завершить работу программы" DO 'на чистом экране рисуем меню 1 после выбора элемента меню очищаем экран CALL ClearScreen CALL RamkaB, 2, meny$(), vybor) CALL ClearScreen 1 проверяем значение переменной vybor SELECT CASE vybor CASE IS = 1 1 выводим сообщение MessageBox "QuickBASIC - лучший язык _ программирования!", 1 PLAY good$: SLEEP 5 CASE IS = 2 'выводим сообщение со счетчиком MessageBox "Подождите, я думаю ...", 1 'рисуем счетчик CALL LineDrawA5, 19, 19, 62) COLOR 0, 7: LOCATE 17, 21: PRINT STRING$D0, "_") 'выводим в цикле 40 символов с кодом 219 1 и гудим для разнообразия FOR i = 1 ТО 40 LOCATE 17, 20 + i: PRINT "_" LOCATE 16, 35: PRINT STR$E00 * i) + " герц" SOUND 500 * i, 3 NEXT i CASE IS = 3. 'выводим сообщение с кнопкой ОК MessageBox "И все-таки я работаю ! ! ! ", 2 CASE IS = 4 'выводим запрос на выход flag = 3: MessageBox "вы точно хотите меня покинуть ?", flag 'если ответ "ДА" то очищаем экран 'и заканчиваем программу IF flag = TRUE THEN PLAY bad$: COLOR 7, 0: CLS : END 'иначе возвращаемся обратно PLAY good$ END SELECT LOOP
SUB ClearScreen ' Эта процедура очищает экран I******************************** 'устанавливаем черный цвет на бирюзовом поле COLOR 0, 3 'Каждая процедура или функция, которая выводит что-нибудь 'на экран должна отключать курсор, чтобы он не мелькал LOCATE , , О 1 закрашиваем экран, выводя на него '25 строк из 80 символов с кодом 176 FOR 1 = 1 ТО 25 1 точка с запятой после оператора PRINT запрещает 'прокручивать экран на 24 и 25 строке LOCATE i, 1: PRINT STRINGS(80, ); NEXT i END SUB SUB LineDraw (x, y, xl, yl) ***************************************************** ' Эта процедура рисует прямоугольную рамку с тенью 1 х,у - верхний левый угол ' xl,yl - нижний правый угол 'устанавливаем черный цвет символов на белом фоне COLOR 0, 7 'Отключаем курсор LOCATE , , 0 1 рисуем верхнюю линию LOCATE х, у: PRINT " г" + STRING$ (yl - у - 1, "-") + "-, » 'рисуем промежуточные линии FOR i = х + 1 ТО xl - 1 LOCATE i, у: PRINT "|" + SPACE$(yl - у - 1) + "|" NEXT i 1 рисуем нижние линии LOCATE xl, у: PRINT " L" + STRING$ (yl - у - 1, "-" ) + "-1 " 'Сделаем рамке "интеллектуальную тень". "Интеллектуальной" 'тень называется потому, что символы, которые она 'закрывает, не пропадают, а проступают из-под нее. 'Для этого при помощи функции SCREEN считываем код каждого 'символа и выводим его же серым на черном фоне 1 Подробнее см. Главу Шестую "Графика и звук", раздел -х мерные эффек- ты в текстовом режиме". 108
COLOR 8, О 'выводим правую часть тени FOR i=x+lTOxl+l FOR j = 1 TO 2 'код символа в i-строке j+yl-столбца kod = ASC(CHR$(SCREEN(i, j + yl))) 1 выводим его же серым на черном LOCATE i, j + yl: PRINT CHR$(kod) NEXT j NEXT i 'выводим нижнюю часть тени FOR i = у + 2 ТО yl 'код символа в xl+1-строке i-столбца kod = ASC(CHR$(SCREEN(xl + 1, i))) 1 выводим его же серым на черном LOCATE xl + 1, i: PRINT CHR$(kod) NEXT i END SUB SUB MessageBox (message$, kod) i**************************************************** 1 Эта процедура выводит сообщение message$ в центре ' экрана в зависимости от параметра kod: ' 1 - обычное сообщение 1 2 - сообщение с кнопкой " Ок " 13 - сообщение с кнопками " ДА " и " НЕТ " |**************************************************** SELECT CASE kod CASE IS = 1 ' 1 - обычное сообщение CALL LineDrawF, 15, 10, 65) COLOR 0, 7: LOCATE 8, 16 PRINT Seredina$(message$, 49) CASE IS = 2 '2 - сообщение с кнопкой " Ок " CALL LineDraw(9, 15, 15, 65) COLOR 0, 7: LOCATE 11, 16 PRINT Seredina$(message$, 49) LOCATE 12, 38: PRINT ", , " LOCATE 13, 38: PRINT "j ОК |" LOCATE 14, 38: PRINT n| '" LOCATE 13, 40, 1, 1, 13 PLAY Simple$ DO CALL WaitKey(kod) LOOP WHILE kod <> ENTER 109
CASE IS = 3 '3 - сообщение с кнопками 1 "ДА " и " НЕТ " CALL LineDraw(9, 15, 15, 65) COLOR 0, 7: LOCATE 11, 16 PRINT Seredina$(message$, 49) LOCATE 12, 30: PRINT "| 1" LOCATE 13, 30: PRINT "| Да j" LOCATE 14, 30: PRINT "' '" LOCATE 12, 45: PRINT "| 1" LOCATE 13, 45: PRINT " | Нет | " LOCATE 14, 45: PRINT "' '" kod = TRUE DO IF kod = TRUE THEN LOCATE 13, 32, 1, 1, 13 ELSE LOCATE 13, 47, 1, 1, 13 END IF WaitKey AnyKey SELECT CASE AnyKey CASE IS = ENTER EXIT DO CASE IS = ESC kod = FALSE: EXIT DO CASE IS = LEFT, RIGHT kod = NOT (kod): SOUND 500 * B - kod), .5 CASE ELSE BEEP END SELECT LOOP END SELECT END SUB SUB Ramka (x, y, line$(), vyb) i**************************************************** ' Эта процедура выводит рисует меню на экране 1 х, у - верхний левый угол меню 1 line$() - вектор названий элементов меню 1 vyb - номер выбранного элемента меню 'гасится экранный курсор LOCATE , , 0 'определяется число элементов в векторе line$() kolvo = UBOUND(line$): dlina = 1 'если номер выбора не задан, то он первый IF vyb = 0 THEN vyb = 1 НО
'определяем самого "длинного" из элементов вектора line$() FOR i = 1 ТО kolvo IF LEN(line$(i)) > dlina THEN dlina = LEN(line$(i)) NEXT i 'рисуем рамку для меню CALL LineDraw(x, у, х + kolvo + 1, у + dlina + 3) 'устанавливаем черный цвет на белом фоне COLOR 0, 7 'выводим элементы вектора line$() FOR i = 1 ТО kolvo LOCATE x + i, у + 2: PRINT line$(i) NEXT i 'устанавливаем красный цвет на белом фоне COLOR 4, 7 DO 'очищаем место для указателя FOR i = 1 ТО kolvo LOCATE x + i, у + 1: PRINT " " NEXT i 'рисуем сам указатель LOCATE x + vyb, у + 1: PRINT CHR$A6) 1 ждем нажатия клавиши WaitKey AnyKey 1 анализируем нажатую клавишу SELECT CASE AnyKey CASE IS = ENTER 'клавиша ENTER - выходим из цикла и из процедуры EXIT DO CASE IS = UP 'клавиша "стрелка вверх" - уменьшаем vyb на 1 vyb = vyb - 1: IF vyb = 0 THEN vyb = kolvo SOUND 500 * vyb, .5 CASE IS = DOWN 'клавиша "стрелка вниз" - увеличиваем vyb на 1 vyb = vyb + 1: IF vyb > kolvo THEN vyb = 1 SOUND 500 * vyb, .5 CASE ELSE 'иначе обиженно гудим BEEP END SELECT LOOP END SUB 111
FUNCTION Seredma$ (lme$, dlma) i************************************************ 1 Эта функция выравнивает символьную строку, 1 добавляя пробелы справа и слева 1 lme$ - символьная строка 1 dlma - ее будущая длина 1************************************************ 'убираем у символьной строки пробелы справа и слева lme$ = RTRIM$(LTRIM$(line$) ) 1 определяем ее реальную длину real = LEN(line$) 'определяем "добавку", и если она не нужна, то 'уходим из функции dobavka = dlma - real IF dobavka < 0 THEN EXIT FUNCTION 1 количество пробелов слева и справа spaceI = dobavka \ 2 space2 = dobavka \ 2 1 компенсируем возможные ошибки при делении IF spacel + real + space2 < dlma THEN space2 = space2 + 1 END IF 'присваиваем полученное значение функции Seredma$ = SPACES {spacel) + line$ + SPACE$ (space2) END FUNCTION SUB WaitKey (kod) 1 Эта процедура возвращает код клавиши: 1 ESC, ENTER, DOWN, UP, LEFT, RIGHT 1 код - код клавиши i*************************************** 'очищаем буфер клавиатуры DO: LOOP WHILE INKEY$ <> "" DO 'ждем нажатия какого-нибудь символа а$ = "": DO: a$ = INKEY$: LOOP WHILE a$ = "" IF LEN(a$) = 1 THEN 1 если нажата обычная клавиша и если это ENTER или ESC, 1 то выходим из цикла DO... LOOP и из процедуры IF a$ = CHR$(ENTER) THEN kod = ENTER: EXIT DO IF a$ = CHR$(ESC) THEN kod = ESC: EXIT DO ELSE 112
'если нажата функциональная клавиша, то берем ее 'скан-код и проверяем, не равен ли он коду UP, DOWN, 'LEFT или RIGHT 'если да, то выходим из цикла и из ' процедуры kod = ASC(RIGHTS(a$, 1)) IF kod = UP OR kod = DOWN OR kod = LEFT OR kod = RIGHT THEN EXIT DO END IF LOOP END SUB При запуске экрана в верхнем левом углу появляется меню, которое выводится в бесконечном цикле DO...LOOP. Меню со- держит четыре пункта: • Вывести сообщение; • Вывести сообщение со счетчиком; • Вывести сообщение с кнопкой ОК; • Завершить работу программы >Вывести сообщение Вывести сообщение со счетчиком Вывести сообщение с кнопкой ОК Завершить работу программы При выборе первого варианта вызывается процедура MessageBox с названием "QuickBASIC — лучший язык програм- мирования" и параметром 1 (вывести простое сообщение). Затем играется музыкальная константа GOD$ и производится задержка 5 секунд QuickBASIC - лучший язык программирования!
При выборе второго варианта также вызывается процедура MessageBox с параметром 1, затем в цикле производится генера- ция звуковых колебаний от 500 до 20000 герц, с имитацией эк- ранного счетчика. Подождите, я думаю 5000 герц При четвертом и последнем варианте вызывается процедура MessageBox с параметром 3 (выбор "ДА" или "НЕТ") Результат вы- бора заносится в переменную flag Если значение переменной flag равно константе TRUE (ИСТИНА) то производится выход из про- граммы с исполнением музыкальной константы BAD$. В противном случае играется константа GOODS и цикл по- вторяется 114 И все-таки я работаю !?! Ок При выборе третьего варианта вызывается процедура MessageBox с параметром 2 (кнопка ОК)
После того, как вы ввели текст этой программы, отладили ее, и она работает так, как описано выше, приступим к построе- нию многомодульной программы Все процедуры программы TEST являются универсальны- ми — их можно использовать и в других программах, а для этого необходимо их выделить в отдельный модуль, назовем его INTERFAC.BAS. Нажмите клавишу {F2} — вы увидите список загруженных модулей (он один — TEST.BAS) и процедуры SUB и FUNCTION, относящиеся к этому модулю. Создадим новый модуль с именем INTERFAS.BAS1. На- жмите {ALT-F, С}, введите название этого модуля (расширение .BAS можно не указывать) и нажмите {ENTER}. 1 Interface — "интерфейс, стых Совокупность средств и правил, обес- печивающих логическое или физическое взаимодействие устройств и/или про- грамм вычислительной системы 115 Вы точно хотите меня покинуть ?
В списке загруженных модулей появился еще один INTERFAC.BAS. Теперь наша задача заклю- чается в том, чтобы перебросить процедуры из модуля TEST в модуль INTERFAC. Установите выделенную строку на первую процедуру в списке (это ClearScreen). Используя клавишу {TAB}1 подведите курсор к ко- манде < Move > (Передвинуть) и нажмите {ENTER}. В появив- шемся окне выберите модуль, в который передвигаются проце- дуры - INTERFAC.BAS 1 Любители хвостатых могут воспользоваться мышью 116
Теперь у модуля INTERFAC появилась процедура ClearScreen. Аналогично перебросьте остальные процедуры. Теперь необходимо перенести в новый модуль INTERFAC. BAS объявления процедур и функций, определения констант и операторы объявления типа данных. Выделите необходимый фрагмент исходного текста из глав- ной части модуля TEST.BAS ({SHIFT+стрелки}), скопируйте его в буфер ({CTRL-INS}) и перенесите в главную часть модуля INTERFAC ({SHIFT+INS}). 117
Главная часть модуля INTERFAC.BAS должна выглядеть так:1 DECLARE SUB ClearScreen () DECLARE SUB LmeDraw (x%, y%, xl%, yl%) DECLARE SUB MessageBox (message$, kod%) DECLARE SUB Ramka (x%, y%, menu$(), vyb%) DECLARE SUB WaitKey (kod%) DECLARE FUNCTION Seredina$ (line$, dlina%) CONST UP% = 72, DOWN% = 80, ESC% = 27, LEFT% = 75 CONST RIGHT% = 77, ENTER% = 13 CONST TRUE% = -1, FALSE% = 0 CONST Simple$ = MFT255L16O6CO4GEDCBT255L16O6CO4_ GEDCBT255L16O6CO4GEDC" CONST bad$ = "mftl20o016eeel2c" CONST good$ = "mft200o215cl7el7g>14c<18g>12c" DEFINT A-Z Сохраните сделанные изменения. При выходе из среды QB, вы заметите, что помимо файлов TEST.BAS и INTERFAC.BAS, на диске появился файл TEST. МАК. В нем содержится список модулей, которые требуются программе TEST: TEST.BAS INTERFAC.BAS Когда вы будете загружать программу TEST в следующий раз QB автоматически подгрузит INTERFAC.BAS Построение Quick-библиотеки Если вспомогательный модуль полностью готов и отлажен, то имеет смысл скомпилировать его в Quick-библиотеку. Проце- дуры, которые находятся в Quick-библиотеках, становятся расши- рением самого языка BASIC. Загрузите в среду QB только файл INTERFAC.BAS. Нажмите {ALT-R, L}. Введите имя Quick-библиотеки (без расширения) и вы- берите пункт < Make library and Exit > (сделать библиотеку и выйти). 1 Этот фрагмент можно поместить во включаемый файл INCLUDE.BI, и помес- тить директиву 'SINCLUDE 'interfac bi' в главную часть модуля TEST BAS и INTERFAC BAS, как было описано в разделе "Использование включаемых (INCLUDE) файлов" 118
BASIC построит две библиотеки: 1. INTERFAC.QLB — служит для работы в среде QB; 2. INTERFAC.LIB — необходима для компиляции Вашей прграммы в .ЕХЕ-файл. Перед запуском программы уничтожьте файл TEST. МАК — он больше не нужен, ведь все необходимые процедуры теперь находятся в Quick-библиотеке. Для загрузки среды QB с Quick-библиотекой ис- пользуется ключ /L (более подробно о ключах запуска среды QB рас- сказано в приложении 2 "Запуск, редактирование и отладка програм- мы"). Загрузим TEST.BAS с Quick-библиотекой INTERFAC.QLB : C:\QB45>QB TEST /L INTERFAC Теперь, при нажатии клавиши {F2} высвечивается только глав- ный модуль программы TEST, а процедуры вспомогательного моду- ля INTERFAC. BAS находятся в Quick-библиотеке и не видны. Использование Quick-библиотек обладает следующими дос- тоинствами: • загрузка библиотеки в среду .QB происходит гораздо быстрее, чем исходного текста; 119
так как процедуры Quick-библиотек уже откомпилированы, они выполняются быстрее; Quick-библиотеки занимают меньше оперативной памяти, чем исходные тексты. В тоже время, следует учитывать и недостатки: откомпилированные Quick-библиотеки не содержат средств отладки, предоставляемых средой QB, поэтому при наличии в ошибок в Quick-библиотеке компьютер может "зависнуть"; при запуске среды QB к ней можно подключить только одну Quick-библиотеку, вне зависимости от наличия свободной памяти, в тоже время в виде исходных текстов можно под- ключить несколько модулей (их количество ограничено толь- ко объемом оперативной памяти1). 1 В среду QB можно загрузить в виде исходных модулей не более 5000-5500 строк текста. Это ограничение снято в Microsoft BASIC PDS 7.1 — среда QBX по- зволяет использовать для загрузки и размещения программ и данных до 1.2 Mb до- полнительной отображаемой памяти, организованной по стандарту EMS 4.0
ОПЕРАТОРЫ ОПИСАНИЯ CONST CONST — оператор, описывающий константы, которые ис- пользуются вместо числовых или символьных значений. CONST константа = выражение [, константа = выраже- ние] . . . • константа — имя константы, допускаемое в языке BASIC; • выражение — выражение, допускаемое в языке BASIC. Нельзя использовать конкатенацию (сложение символьных строк) и функции с параметрами, такие как SIN или CHR$. Тип констант определяется по суффиксу в конце имени: % & ! # $ целочисленная константа; константа двойной точности; константа обычной точности1; константа двойной точности; символьная константа. Константы, описанные в процедурах SUB или FUNCTION, являются локальными для данной SUB или FUNCTION. Кон- 1 Если суффикс опущен, то константа считается обычной точности.
станта, описанная в главном модуле, является глобальной. Ис- пользование констант обладает рядом несомненных достоинств: • Константы нужно определять только один раз во всем модуле; • Константы нельзя изменить; • В ЕХЕ-программах использование констант дает более эф- фективный код, чем использование переменных; • Константы делают программу легко изменяемой. Пример. Подсчет слов, строк, символов в текстовом файле. DEFINT A-Z CONST BLANK = 32, ENDFILE = 26, CR = 13, LF = 10 CONST TABC = 9, YES = -1, NO = 0 CLS INPUT "Введите имя файла: ",FileName$ IF FileName$ ="" THEN END OPEN FileName$ FOR INPUT AS #1 Words = 0: Lines = 0: Characters = 0 InaWord = NO DO UNTIL EOF(l) с = ASC(INPUT$A,#1)) Characters = Characters + 1 IF с = BLANK or с = CR or с = LF or С = TABC THEN 1 Если прочитанный символ является пробелом, 1 табулятором, символом перевода каретки или 1 возврата строки, то это не слово. IF с = CR THEN Lines = Lines + 1 InaWord = NO ELSEIF InaWord = NO THEN 1 Символ может входить в состав слова. InaWord = YES Words = Words + 1 END IF LOOP PRINT Characters, Words, Lines END DEFmn DEPran — оператор описания типов переменных. 122
DEFINT интервал [,интервал]... —целый; DEFLNG интервал [,интервал]... - длинный целый; DEFSNG интервал [.интервал]... — обычной точности; DEFDBL интервал [,интервал]... — двойной точности; DEFSTR интервал [,интервал]... — символьный. • интервал имеет форму буква 1[-буква2], где буква 1 и буква2 — любая из букв латинского алфавита. Переменные и функции, чьи имена начинаются с букв, вхо- дящих в данный интервал, имеют по умолчанию тип, определен- ный тремя последними буквами оператора (INT, SNG, DBL, LNG или STR). DIM DIM — оператор, объявляющий одну или несколько пере- менных и выделяющий для них необходимый объем памяти. DIM [SHARED] переменная[(границы)] [AS тип] [,переменная[(границы)] [AS тип].. . • переменная — имя переменной или массива; • SHARED — атрибут SHARED предписывает всем процедурам в данном модуле совместно использовать массивы и перемен- ные указанные в операторе DIM. Это не оператор SHARED, который влияет на переменные внутри одной процедуры SUB или FUNCTION; • границы — границы размерности массива — верхняя и ниж- няя граница индексов; • AS тип — определяет тип переменной — обычный или пользовательский. К обычным типам BASIC относятся: INTEGER, LONG, SINGLE, DOUBLE, STRING. Границы массивов в операторе DIM имеют следующую форму: [меньшая ТО] большая [,[меньшая ТО] большая]... Ключевое слово ТО предоставляет возможность указать и нижнюю и верхнюю границы массива. Следующие операторы эк- вивалентны (если OPTION BASE = 0 или отсутствует): 123
DIM A(8,3) DIM A@ TO 8, 0 TO 3) DIM A(8,0 TO 3) С ключом ТО вам не обязательно указывать только положи- тельные границы. Возможные значения границ находятся в пре- делах от -32768 до 32767: DIM A(-4 ТО 10) DIM B(-99 ТО -5,-3 ТО 0) Если у вас есть массив, не описанный оператором DIM, то верхняя граница каждой размерности не должна превышать ДО1. Если же вы обращаетесь к элементу массива, индекс которого лежит вне указанных границ, то возникает ошибка "Subscript out of range" (Индекс вне диапазона). Оператор DIM обнуляет все элементы числовых массивов, а символьным — присваивает значение пустой строки (""). Пере- менные полей и записей также обнуляются, включая поля фик- сированной длины. Если вы попытаетесь определить массив оператором DIM после того, как вы уже обращались к его элементам, то получите ошибку "Array already dimensioned" (Массив уже определен). Лучше всего поставить DIM в самом начале программы. Ограничения на размеры массивов в приведены в Приложе- нии 4 "Ограничения QuickBASIC". Оператор DIM может применяться для описания типов перемен- ных. Например, следующий оператор описывает переменную как це- лую, хотя никакой декларации типов оператором DEFINT до этого не производилось: DIM NumberOfBytes AS INTEGER DIM также дает возможность описания определенных пере- менных как записей. В следующем примере переменная TopCard описана как переменная пользовательского типа (запись): TYPE Card Suit AS STRING * 9 Value AS INTEGER END TYPE DIM TopCard AS Card Таким же образом можно описывать и массивы записей: 1 Лучше такого не допускать — описывайте каждый используемый Вами мас- сив в начале модуля или процедуры. 124
DIM Deckd TO 52) AS Card Пример. Нахождение максимального и минимального зна- чений элементов массива. CONST MAXDIM =20 DIM A(l TO MAXDIM) 1 Использование DIM для описания двух целых переменных. ' Все остальные переменные имеют обычную точность. DIM NumValues AS INTEGER, I AS INTEGER NumVal = 0 PRINT "Вводите числа. END - конец ввода." DO INPUT A$ IF UCASE$(A$) = "END" OR NumVal >= MAXDIM THEN EXIT DO NumVal = NumValues + 1 A(NumVal) = VAL(A$) LOOP IF NumVal > 0 THEN Max = A(l) Min = A(l) FOR 1=1 TO NumVal IF A(I) > Max THEN Max = A(I) IF A(I) < Min THEN Min = A(I) NEXT I PRINT "Максимум ="; Max;" Минимум ="; Min ELSE PRINT "Недостаточно чисел..." END IF Вводите числа. END - конец ввода. ? 23.2 ? 11.3 ? 1.6 ? end Максимум = 23.2 Минимум = 1.6 REDIM REDIM — оператор объявления массивов. Изменяет объем памяти, выделенной массивам $DYNAMIC (динамическим) . REDIM [SHARED] массив(границы)[AS тип] [,массив (границы) [AS тип]]... 125
• SHARED — позволяет всем процедурам модуля совместно использовать элементы массива. Отличается от оператора SHARED, который влияет только на переменные внутри мо- дуля. Атрибут SHARED может быть указан на модульном уровне; • массив — имя массива; • границы — границы размерности массива — верхняя и ниж- няя граница индексов; • AS тип — описывает переменные обычного или пользователь- ского типа. К обычным типам BASIC относятся: INTEGER, LONG, SINGLE, DOUBLE, STRING. Границы задаются следующим образом: [нижняя ТО] верхняя [,[нижняя ТО] верхняя]... Ключ ТО указывает на то, что определяются и верхняя, и нижняя границы данной размерности массива. Все массивы, описанные данным оператором, являются SDYNAMIC. Можно только изменить границы размерностей массива оператором REDIM, но нельзя изменить число размер- ностей. Следующий пример является правильным: '$DYNAMIC DIM AE0,50) ERASE A 'Массив А имеет две размерности. REDIM АB0,15) Однако, следующий пример имеет ошибку, при его выпол- нении вы получите сообщение "Wrong number of dimensions" (Неверное число размерностей): 1$DYNAMIC DIM AE0,50) ERASE A 1 Размерностей стало 3. Ошибка. REDIM AE,5,5) 126
LBOUND LBOUND — функция памяти, возвращающая нижнюю гра- ницу (наименьшее значение индекса) массива. LBOUND(массив,[размерность]) • массив — имя массива; • размерность — целое выражение в пределах от 1 до числа раз- мерностей массива. Указывает, по какой размерности брать нижнюю границу. Для массива-вектора может быть опущено. Пример: DIM A(l ТО 100, 0 ТО 50, -3 ТО 4) Значение: LBOUND (АД) = 1 LBOUND(А,2) = 0 LBOUND(А,3) = -3 Нижняя граница массивов по умолчанию равна 0 (оператор OPTION BASE = 0 или отсутствует) или 1 (оператор OPTION BASE = 1). Массивы, описанные с ключевым словом ТО в операторе DIM могут иметь любое целое значение в качестве нижней гра- ницы. Можно использовать короткий синтаксис LBOUND (массив) для одноразмерного массива (вектора). Пример: OPTION BASE I DIM AE0) Значение: LBOUND (A) = 1 Для нахождения верхней границы массива используется функция UBOUND. 127
UBOUND UBOUND — функция памяти, возвращающая верхнюю гра- ницу массива по указанной размерности. иВО1ШБ(массив[,размерность]) • массив — имя массива; • размерность — целое выражение в пределах от 1 до числа раз- мерностей массива. Указывает, по какой размерности брать верхнюю границу. Для массива-вектора может быть опущено. Примеры: DIM A(l ТО 100, 1 ТО 50, -3 ТО 4) Значение: UBOUND(А,1) = 100 UBOUND(А,2) = 50 UBOUND(А,3) = 4 TYPE TYPE — оператор описания QuickBASIC, определяющий тип данных, состоящих из нескольких типов — пользовательский тип. TYPE имя_типа элемент AS тип [элемент AS тип] END TYPE • имятипа — имя пользовательского типа данных; • элемент — имя элемента пользовательского типа; • тип — типы данных языка BASIC: INTEGER, LONG, SINGLE, DOUBLE, STRING * num или другой пользователь- ский тип. Символьные строки в пользовательском типе данных долж- ны быть строками фиксированной длины: 128
Keyword AS STRING * 40 Пользовательский тип должен быть описан оператором TYPE только в главном модуле. Для описания какой-либо пере- менной как пользовательской используются операторы DIM, REDIM, COMMON, STATIC, SHARED. Пользовательские типы данных имеют другое название — записи. OPTION BASE OPTION BASE — объявление нижней границы массивов. OPTION BASE n • n = 0 или 1. OPTION BASE не обязателен. По умолчанию равен 0. Син- таксис оператора DIM позволяет сделать это проще. OPTION BASE может использоваться только один раз в модуле, до описа- ния всех массивов. Пример. Установка нижней границы массивов = 1. CLS OPTION BASE I DIM AB0) PRINT "Нижняя граница массива А ="; LBOUND(A) PRINT "Верхняя граница массива А ="; UBOUND(A) Результат: Нижняя граница массива А = 1 Верхняя граница массива А = 20 COMMON COMMON — оператор, описывающий глобальные пере- менные для их совместного использования между модулями или для передачи в цепочную программу. COMMON [SHARED] [/имя_6лока/] список • SHARED — Атрибут, определяющий, что переменные могут совместно использоваться всеми процедурами SUB и FUNCTION в модуле. При этом нет необходимости в исполь- 129
зовании оператора SHARED внутри процедуры SUB или FUNCTION; • имяблока — идентификатор блока (до 40 знаков в имени) для указания группы переменных. Используется для разделе- ния только определенных переменных. Если у блока есть имя, он считается именованным; • список — список переменных, разделяемых между модулями или цепочными программами: переменная [AS тип][, переменная [AS тип]] ... Оператор COMMON выделяет место для переменных в спе- циальной области памяти (общая область), что позволяет моду- лями или программам совместно использовать переменные. Так как COMMON устанавливает глобальные переменные для всей программы, он должен находиться перед выполняемыми опера- торами, но ему могут предшествовать следующие операторы: COMMON DEFjran SHARED CONST DIM STATIC DATA OPTION BASE TYPE...END TYPE DECLARE REM Все метако- манды Переменные в блоках COMMON в разных модулях должны иметь одинаковый тип в одинаковых позициях, но не обязатель- но одинаковые имена. Пример: 1 Главная программа COMMON a, D, Е а = 5: D = 8: Е = 10 'Другой модуль 'А = 5, Е = 8, D = 10 COMMON a, E, D И статические и динамические массивы размещаются в COMMON путем указания имени массива с пустыми скобками. Статический массив должен быть предварительно описан опера- тором DIM. Динамический массив может быть описан позже 130
операторами DIM или REDIM, так как в блоке COMMON раз- мещаются не его элементы, а описатель массива. Размер общей области может быть различным в разных мо- дулях или программах, если используется неименованный блок COMMON. Если программа совместно использует блок COMMON с процедурой в библиотеке пользователя, то вызывае- мая программы не может увеличит размер блока. Очень трудно обнаружить причину ошибки при некоррект- ном использовании оператора COMMON. Поэтому создайте включаемый INCLUDE-файл с описанием блоков COMMON и вызывайте его с помощью метакоманды $INCLUDE в каждой программе: 'Файл menu.bas 1 $INCLUDE: 'COMDEF.BI' CF^IN "progl" END 'Файл progl.bas 1 $INCLUDE: 'COMDEF.BI' END 'Файл comdef.bi DIM aA00), B$B00) COMMON I, J, K, a() COMMON a$, B$(), X, У, Z Использование именованного блока COMMON Именованный блок COMMON представляет собой простой способ для совместного использования переменных между моду- лями, так как многие модули требуют только те переменные, ко- торые им нужны. Ниже приведен пример программы, вычисляющей объем и плотность прямоугольной призмы, которая использует имено- ванный блок COMMON для разделения различных переменных между двумя процедурами. Процедура VOLUME требует только переменные, представляющие длины сторон (COMMON блок SIDES). Процедура DENSITY требует также переменные, пред- ставляющие вес (COMMON блок WEIGHT). 'Главная программа DIM SC) COMMON /Srdes/ S() COMMON /Weight/ С С = 52: S(i) = 3: SB) = 3: SC) = 6 131
CALL Volume CALL Density END COMMON и .EXE файлы При передаче управления другой программе через CHAIN (передача управления другому файлу "по цепочке"), с помощью оператора COMMON или именованного блока COMMON невоз- можно передать глобальные переменные. Это происходит в том случае, когда вы компилируете Вашу программу "Stand-Alone EXE File" (Автономный EXE Файл). Существует три пути решения этой проблемы: 1. Компилировать программу с опцией "Requiring BRUN45.EXE" (требуется BRUN45.EXE); 2. Передавать параметры через временный дисковый файл; 3. Использовать межпрограмный 16-байтный буфер. Этот буфер специально предназначен для обмена сообщениями между программами: 'Файл programl.bas посылает сообщение Message$ DIM Message$ AS STRING * 16 Message$ = "Тестовая строка" DEF SEG = 0 FOR i = 0 TO 15 POKE &H4F0 + i, ASC(MID$(message$, i + 1, 1)) NEXT i DEF SEG CHAIN "program2" END 'Файл program2.bas считывает сообщение Message$: DIM Message$ AS STRING * 16 DEF SEG = 0 132 1 Процедура VOLUME в отдельном модуле DIM SC) COMMON SHARED /Sides/ SO SUB Volume STATIC Vol = S(l) - SB) - SC) END SUB
FOR i = О ТО 15 MID$(message$, i + 1, 1) = CHR$(PEEK(&H4F0 + i)) NEXT i DEF SEG END DATA DATA — оператор, хранящий числовые и символьные дан- ные для их последующего чтения оператором READ. DATA константа[,константа]... • константа — любая числовая или символьная константа. Если символьная константа содержит запятые, двоеточия, начальные или конечные пробелы, то она должна быть заключе- на в кавычки. Все операторы DATA должны располагаться в главной части модуля. READ READ — оператор ввода/вывода, читающий данные из спис- ка оператора DATA и присваивающий их значения переменным. READ переменные • переменные — список переменных, разделенных запятыми. Эти переменные получают данные. Данные могут быть сим- вольными или числовыми. Операторы READ всегда используются совместно с операто- рами DATA. READ присваивает значения из списка DATA свое- му списку переменных один к одному. Типы данных и перемен- ных должны соответствовать: чтение числового значения в сим- вольную переменную не приведет к ошибке, напротив, попытка считать символьную строку в числовую переменную вызовет ошибку "Type mismatch" (Ошибка в типе данных). Чтение числового значения, слишком большого для пере- менной, также приведет к ошибке "Overflow" (Переполнение). 133
Символьные строки длиннее, чем соответствующие перемен- ные, усекаются. Если они короче, то дополняются справа пробе- лами и выравниваются по левой границе. Оператором READ могут считываться только отдельные эле- менты переменных пользовательского типа. Один оператор READ может читать несколько операторов DATA (данные должны идти в соответствующем порядке), и на- оборот, несколько операторов READ могут читать один оператор DATA. Если список переменных больше, чем список данных, выдается сообщение об ошибке "Out of DATA" (Конец данных в операторе DATA). Если список переменных короче, чем список данных, следующий оператор READ начинает читать первый не- прочитанный элемент; если данные не прочитаны никакими READ, то они игнорируются. Оператор RESTORE позволяет повторно считать данные из списка DATA. Пример. Представление пустых элементов списка. DATA abc,,def DATA 1,,2 READ A$, B$, C$ 'B$ = "" PRINT A$, B$, C$ PRINT READ А, В, С 'В = О PRINT А, В, С abc de f 10 2 RESTORE RESTORE — оператор ввода/вывода, позволяющий операто- ру READ повторно считать данные из списка оператора DATA. RESTORE [метка] • метка — метка оператора DATA, с которого нужно начать считывать новую порцию данных. Если метка опущена, то следующий оператор READ будет считывать данные из первого в программе оператора DATA. 134
Пример. Представление пустых элементов списка. DATA "Красный", "Желтый", "Зеленый" ml: DATA "Синий", "Фиолетовый", "Бордовый" READ A$, В$, С$ PRINT A$, В$, С$ PRINT RESTORE READ Red$, Yellow$, Green$ PRINT Red$, Yellow$, Green$ PRINT RESTORE Ml: READ A$, B$, C$ PRINT A$, B$, C$ Вывод: Красный Желтый Зеленый Красный Желтый Зеленый Синий Фиолетовый Бордовый
От Издательства Данная книга, изданная впервые в 1994 году для широкого круга профессионалов и любителей языка QuickBASIC 4.5, приобрела большую популярность в ВУЗах, колледжах, школах и лицеях страны. Не будучи изначально кано- ническим учебником, она переиздается в качестве пособия ввиду острой пот- ребности учебных заведений в литературе по языкам программирования. Издательство, заинтересованое в усовер- шенствовании книги, с благодарностью примет все критические замечания, советы и пожелания педагогов и учащихся.
ОПЕРАТОРЫ ПЕРЕДАЧИ УПРАВЛЕНИЯ Операторы цикла Циклы повторяют блок операторов определенное количество раз, либо пока условие цикла не станет истинным или ложным. В QuickBASIC существуют три вида циклов: 1. FOR...NEXT; 2. WHILE...WEND; 3. DO... LOOP; FOR...NEXT FOR...NEXT — управляющий оператор , повторяющий блок операторов указанное число раз. Синтаксис FOR счетчик = начало ТО конец [STEP шаг] [операторы_цикла] [EXIT FOR] NEXT [счетчик [,счетчик...]] Пример FOR 1% = 1 ТО 10 Аггау%A%) = 1% NEXT
• счетчик — числовая переменная, используемая как счетчик цикла; • начало — начальное значение счетчика; • конец — конечное значение счетчика; • шаг — шаг изменения значения счетчика, по умолчанию 1. Цикл FOR...NEXT выполняется только в том случае, если начало плюс шаг меньше или равно конечному значению счетчи- ка. Если конец меньше начала, то шаг должен быть отрицатель- ным. На рисунке показана логика цикла FOR...NEXT при поло- жительном значении шага. ( Начало цикла J СЧ6ТЧИК = тттяр Логика цикла FORJMEXT при положительном значении шага Нет Выполняются операторы цикла (между TOR и NEXT) Увеличивается счетчик счет ю"счетчик +1 или подсчетчик + шаг Да С Конец цикла ) Пример: FOR i = 32 ТО 255 PRINT CHR$(i); NEXT i Далее показана логика цикла FOR...NEXT при отрицатель- ном значении шага. 138
Пример: FOR i = 255 TO 32 STEP -1 PRINT CHR$(i); NEXT i Цикл выполняется до тех пор, пока текущее значение счетчика не выйдет за рамки его конечного значения. При завершении теку- щего цикла к значению счетчика прибавляется значение шага. Если начало и конец имеют одно и то же значение, цикл выполняется один раз, вне зависимости от значения шага. Если шаг равен нулю, цикл продолжается неопределенное время. Допускается вкладывать циклы FOR...NEXT, то есть поме- щать цикл FOR...NEXT внутри другого цикла FOR...NEXT. Счет- чикам вложенных циклов необходимо давать разные имена1. Оператор NEXT для внутреннего цикла должен предшество- вать оператору NEXT для внешнего цикла. FOR I = 1 ТО 10 ' Это внешний цикл FOR J = 1 ТО 10 ' Это вложенный цикл FOR К = 1 ТО 10 ' Еще один вложенный цикл NEXT К NEXT J NEXT I 1 Обычно при использовании циклов FOR.. NEXT первому счетчику цикла дается имя i, вложенному в него — j, затем к, 1 и далее по алфавиту. 139 Логика цикла FOR-NEXT при отрицательном значении шага Начало цикла счетчик = шаг Конец цикла Выполняются операторы цикла (между FOR и NEXT) Уменьшается счетчик: счетчик=счетчик -1 или счетчик=счетчик - шаг
Оператор NEXT вида: NEXT К, J, I эквивалентен операто- рам: NEXT К: NEXT J: NEXT I Если вам необходимо выйти из цикла до его завершения, используйте оператор альтернативного выхода из цикла EXIT FOR: FOR I = 1 ТО 10 IF GodBye = TRUE THEN EXIT FOR NEXT I Если вы опустите переменную-счетчик в операторе NEXT, он будет принадлежать ближайшему открытому оператору FOR1. Ес- ли такового нет, вы получите сообщение об ошибке "NEXT without FOR" (NEXT без FOR). QuickBASIC поддерживает значения двойной точности в ка- честве параметров начала, конца и счетчика цикла FOR...NEXT, но лучше использовать целые переменные2. Пример: вывод первых 11 столбцов треугольника Паска- ля. Каждый элемент треугольника является суммой двух элементов слева от него. CLS CONST maxcol=ll DIM A(maxcol,maxcol) FOR m = 1 TO MAXCOL 'Верхняя и нижняя границы = 1. Л(т,1) = 1 : A(m,m) = 1 NEXT m 1 Рекомендуется этого не делать из соображений удобочитаемости исходного текста программы. Например: 'счетчики циклов опущены FOR i = 1 ТО 10: FOR j = 1 ТО 15: ... : NEXT :NEXT 'счетчики циклов присутствуют FOR i = 1 ТО 10: FOR j = 1 TO 15: .. : NEXTj: NEXT I 2 Это значительно сокращает время работы цикла, особенно это становится заметно в программах, требующих интенсивных математических вычислений. 140
FOR m = 3 TO MAXCOL FOR n = 2 TO m-1 A(m,n) = A(m-l,n-l) + A(m-l,n) NEXT n NEXT m 'Вывод с середины экрана. startrow = 13 FOR m = 1 TO MAXCOL col = 6 - m row = startrow FOR n = 1 TO m LOCATE row,col : PRINT A(m,n) row = row + 2 NEXT n PRINT: startrow = startrow - 1 NEXT m Результат: WHILE... WEND WHILE...WEND — управляющий оператор, выполняющий блок операторов до тех пор, пока указанное условие истинно. 141 1 1 10 1 9 1 8 45 1 7 36 1 6 28 120 15 21 84 14 15 56 210 13 10 35 126 12 6 20 70 252 13 10 25 126 14 15 56 210 15 21 84 1 6 28 120 1 7 36 1 8 45 1 9 1 10 1
Синтаксис WHILE условие [операторы] WEND INPUT R$ WHILE R$ PRINT INPUT WEND о "Д" "Ответ R$ Пример AND R$ должен о "Н" быть Д или Н" • условие — логическое выражение, возвращающее не ноль ("истина") или ноль ("ложь"); • операторы — любое количество операторов. Пока условие истинно (его значение не равно нулю), опера- торы будут циклически выполняться. Если условие ложно (его значение равно нулю), выполняется оператор, следующий за WEND. ( Начало цикла ) Логика цикла WHILE-WEND Вычисляется условие цикла Да Выполняются операторы цикла (между WHILE и WEND) Нет j ( Конец цикла J 142
Циклы WHILE...WEND могут вкладываться друг в друга лю- бое число раз, но каждому оператору WHILE должен соответ- ствовать свой WEND. WHILE без WEND приводит к ошибке "WHILE without WEND" (WHILE без WEND), a WEND без WHILE- к ошибке "WEND without WHILE" (WEND без WHILE). Пример. Пузырьковая сортировка массива. DEFINT A-Z CONST FALSE = 0, TRUE = NOT FALSE 'резервируется массив из десяти символьных элементов DIM a$A0) присваивается значение 1 каждому элементу массива пр а$A) а$B) а$C) а$D) а$E) а$F) а$G) а$(8) а$(9) а$A0) max = = "Москва" = "Ленинград" = "Куйбышев" = "Алма-Ата" = "Хабаровск" = "Новосибирск" = "Владивосток" = "Калинин" = "Дмитров" = "Жуковский" UBOUND(a$): exchange = TRUE ' Сортировать, пока все элементы не изменятся. WHILE exchange = TRUE exchange = FALSE ' Сравнение элементов массива попарно. Если произошла 1 замена, присвоить переменной exchange значение TRUE. FOR i = 2 ТО max IF a$(i - 1) > a$(i) THEN exchange = TRUE SWAP a$(i - 1), a$(i) END IF NEXT i WEND CLS 1 вывести на экран отсортированный массив FOR i = 1 ТО max: PRINT a$(i): NEXT i END ИЗ
Результат: Алма-Ата Владивосток Дмитров Жуковский Калинин Куйбышев Ленинград Москва Новосибирск Хабаровск DO...LOOP DO...LOOP — управляющий оператор, который повторяет блок операторов, пока условие истинно, или до тех пор, когда оно станет ложным. Существует два варианта цикла DO...LOOP: • Цикл DO...LOOP с проверкой выражения в начале: DO WHILE...LOOP; DO UNTIL...LOOP; • Цикл DO...LOOP с проверкой выражения в конце: DO...LOOP WHILE; DO ...LOOP UNTIL; Проверка выражения в начале цикла: Синтаксис DO [{WHILE | UNTIL} логичесое_выражение] [операторы_цикла] [EXIT DO] LOOP Пример DO UNTIL INKEY$ <> "" 'Пустой цикл, в котором ожидается 'нажатие любой клавиши LOOP логическое_выражение — выражение, имеющее ненулевое значение (истина) или нулевое (ложь); операторы_цикла — любое количество операторов, которые выполняются, пока выражение истинно. 144
145 Логика цикла DO WHILE-LOOP Логика цикла DO UNTNLJ.OOP
Проверка выражения в конце цикла: Синтаксис DO [операторы_цикла] [EXIT DO] LOOP [WHILE I UNTIL логическое_выражение] DO INPUT " Total = LOOP WHILE Пример Число: " Total + Ch <> 0 ; Ch Ch логическоевыражение — выражение, имеющее ненулевое значение (истина) или нулевое (ложь); операторыцикла — любое количество операторов, которые выполняются, пока выражение истинно. I Напало цикла ) Логика цикла DOJ.OOP WHLE истина? Нет Конец цикла 146
( Начало цикла ) Логика цикла DO-LOOP UNTIL Вьшолыяются операторы цикла (между DO и условием LOOPUNTDL) Вычисляется условие цикла Нет Если опустить проверку условия в начале или в конце цикла DO...LOOP, то вы получите бесконечный цикл. Чтобы выйти из бесконечного цикла DO...LOOP используйте оператор EXIT DO (EXIT DO также может оказаться полезным для альтернативного выхода из цикла DO...LOOP с проверкой выражения в начале или в конце): Nomeг = 1 DO Nomer = Nomer + 1 IF Nomer = 444 THEN EXIT DO LOOP Пример. Программа пузырьковой сортировки массива. DEFINT A-Z CONST noexchange = -1 'резервирование массива из 12 элементов DIM ExesA2) 147
'заполняем массив числами FOR i = 1 ТО 12 Exes(i) = 13 - i NEXT i limit = 12 CLS PRINT "Исходный массив:" FOR i = 1 TO 12 PRINT Exes(i); NEXT i LOCATE 4, 1: INPUT "Нажмите ENTER", press$ DO exchange = noexchange FOR i = 1 TO limit - 1 IF Exes(i) > Exes(i + 1) THEN SWAP Exes(i), Exes(i + 1) exchange = i END IF ¦ NEXT i limit = exchange 'Сортировать, пока все элементы не ранжированы. LOOP UNTIL exchange = noexchange PRINT PRINT "Отсортированный массив:" FOR i = 1 TO 12 PRINT Exes(i); NEXT i END Результат: Исходный массив: 12 11 10 987654321 Нажмите ENTER Отсортированный массив: 123456789 10 11 12 148
Условные операторы IF...THEN...ELSE IF...THEN...ELSE — управляющий оператор, осуществляющий условное ветвление операций, основанное на оценке логического выражения. Выражение может быть истинным или ложным. IF...THEN...ELSE можно записать в блочной или линейной форме. Блочная форма Синтаксис IF логическое_выражение_1 THEN [олераторы_1] [ELSEIF логическое выражение_2 THEN [операторы_2] • ¦ . [ELSE [операторы_п]] END IF IF X > PRINT ELSEIF PRINT ELSE PRINT END IF Примеры 0 THEN "X - положительно" X < 0 THEN "X - отрицательно" "X - ноль" • логическое_выражение_1 — выражение, возвращающее не- нулевое значение (истина) или ноль (ложь); • операторы_1 — любое количество операторов, выполняющих- ся при условии: логическое_выражение_1 — "истина"; 149
• логическое_выражение_2 — выражение, возвращающее не- нулевое значение (истина) или ноль (ложь); • операторы_2 — любое количество операторов, выполняющих- ся при условии: логическое_выражение_2 — "истина"; • операторы_п — операторы выполняющиеся при прочих усло- виях. Линейная форма IF логическое_выражение THEN операторы_1 [ELSE операторы_2] • операторы_1 — операторы, выполняющиеся при значении логического выражения "истина"; • операторы_2 — при значении "ложь". Логика работы при блочной и линейной форме При блочной форме, QuickBASIC тестирует первое логи- ческое выражение. Если оно ненулевое ("истина"), выпол- няются операторы блока THEN. Если первое выражение рав- но нулю ("ложь"), QuickBASIC оценивает каждое условие ELSEIF. При выполнении такого условия выполняются опе- раторы данного блока. Если ни одно из условий ELSEIF не выполнено (все = "ложь"), выполняются операторы блока ELSE. Блоки ELSE и ELSEIF могут быть опущены. В блочную структуру IF можно вставить любое количество условий ELSEIF. Каждый из блоков может также содержать вложенные блочные структуры IF. Для идентификации блочной структуры IF QuickBASIC оп- ределяет, что находится в строке после слова THEN. Структура считается линейной, если после THEN есть операторы (кроме комментариев). Операторы IF, ELSE, ELSEIF и END IF должны быть пер- выми операторами в строке. Блок должен заканчиваться операто- ром END IF. Если проверяется одно или два условия, то имеет смысл ис- пользовать линейную форму IF...THEN...ELSE: IF Otvet$ = "НЕТ" THEN PRINT "ПРОЩАЙ, АМИГО!" IF Nomer = 1 THEN PRINT A$ ELSE INPUT B$ 150
Если предполагается проверять больше, чем два условия, то используйте блочную форму IF...THEN...ELSE. Программы, написанные с использованием блочной формы легче читаются и отлаживаются. При проверке сложных условий можно ис- пользовать и более современную конструкцию SELECT...END SELECT. Пример. Использование линейной формы IF...THEN...ELSE: CLS DO INPUT "Введите число, большее 0 и меньшее 1000:", х IF х >= 0 AND х < 1000 THEN EXIT DO ELSE PRINT "Повторите" LOOP IF x < 10 THEN у = 1 ELSE IF x < 100 THEN у = 2 ELSE у = 3 PRINT "Число имеет"; у; "знаков" Пример. Использование блочной формы IF...THEN...ELSE: CLS DO INPUT "Введите число, большее 0 и меньшее 1000:", х IF х >= 0 AND х < 1000 THEN EXIT DO ELSE •PRINT "Повторите" END IF LOOP IF x < 10 THEN у = 1 ELSEIF x < 100 THEN У = 2 ELSE у = 3 END IF PRINT "Число имеет"; у; "знаков * SELECT...END SELECT SELECT CASE — управляющий оператор, выполняющий один из нескольких блоков операторов в зависимости от значе- ния выражения. 151
Синтаксис SELECT CASE выражение_выбора [CASE список_выражений_1] [операторы_цикла_1] [CASE список_выражений_2] [операторы_цикла_2]] [CASE ELSE [операторы_цикла_п]] END SELECT Пример INPUT TestValue SELECT CAST TestValue CASE 1, 3, 5, 7, 9 PRINT "Нечетное" CASE 2, 4, 6, 8 PRINT "Четное" CASE IS < 1 PRINT "Очень маленькое" CASE IS > 9 PRINT "Очень большое" CASE ELSE PRINT "He целое значение" END SELECT • выражениевыбора — любое числовое или символьное выра- жение; • список_выражений — одно или более выражений такого же типа, как и выражениевыбора. Ключевое слово CASE долж- но предшествовать блоку операторов; • операторыцикла — содержат любое количество операторов. Элементы списка_выражений должны иметь одну из следу- ющих трех форм: выражение[,выражение...]; выражение ТО выражение; IS выражение с операцией. выражение — любое числовое или символьное выражение того же типа, что и выражениевыбора; операция — любая из следующих операций: 152
< <= > о = меньше; меньше либо больше; больше либо не равно; равно равно; равно; Если выражение_выбора отвечает условиям спискавыра- жений данного блока CASE, выполняются операторы из этого блока. После этого управление передается оператору, следующе- му за END SELECT. Если вы используете ключевое слово ТО для определения пределов выражения, то меньшее значение должно быть первым. Например, операторы блока CASE -I TO -5 не выполняются, ес- ли выражение_выбора равно -4. Эта строка должна быть написа- на как CASE -5 ТО -1. Операции сравнения можно использовать только с ключевым словом IS. Блок операторов CASE ELSE выполняется только в том слу- чае, если выражениевыбора не удовлетворяет ни одному из ус- ловий CASE. Обычно используется для обработки нежелательных значений. Если нет блока операторов CASE ELSE и нет ни одного вы- ражения в условиях CASE, программа выполняется без ошибок. Можно использовать несколько выражений или пределов в каждом условии CASE. Например: CASE I TO 4, 7 ТО 9, 11, 13, IS > MaxNumber% Это же справедливо и для символьных выражений: CASE "трактор", "ЭЭЭЭ" ТО "ЯЯЯЯ", Testltem$ Здесь CASE выбирает те строки символов, которые^ равны значению "трактор", текущему значению TestltemS, или находят- ся между "ЭЭЭЭ" и "ЯЯЯЯ" в алфавитном порядке. Строки оцениваются в соответствии с ASCII-кодами их сим- волов. Строчные буквы имеют большие ASCII-коды, чем про- писные, например: 153
"кот" > "Кот" > "КОТ" Если выражение_выбора удовлетворяет нескольким условиям CASE, выполняется блок операторов, идущий первым. Блоки SELECT CASE могут быть вложенными. Каждый блок должен иметь завершение END SELECT. Пример. Распознавание нажатия различных клавиш. CONST DOWN = 80, UP = 72, LEFT = 75, RIGHT = 77 CONST ESC = 27, ENTER=13 CONST HOME = 71, ENDKEY = 79, PgDn = 81, PgUp = 73 DO 1 Нажатие клавиши DO choice$ = INKEY$ LOOP WHILE choice$ = "" IF LEN(choice$) = 1 THEN 'Клавиши ASCII SELECT CASE ASC(choice$) CASE ESC ' PRINT "ESC" END CASE ENTER PRINT "ENTER" CASE IS < 32, 127 PRINT "Управляющие коды" CASE 48 TO 57 PRINT "Число: "; choice$ CASE 65 TO 90, 128 TO 159 PRINT "Прописная буква: " ,• choice$ CASE 97 TO 122, 160 TO 175, 224 TO 241 PRINT "Строчная буква: "; choice$ CASE 17 6 TO 223 PRINT "Символ псевдографики: "; choice$ CASE ELSE PRINT "Знак пунктуации: "; choice$ END SELECT ELSE 'Преобразование расширенного кода choice$ = RIGHT$(choice$, 1) SELECT CASE choice$ CASE CHR$(DOWN) PRINT "Стрелка вниз" CASE CHR$(UP) PRINT "Стрелка вверх" 154
CASE CHR$(PgDn) PRINT "PGDN" CASE CHR$(PgUp) PRINT "PGUP" CASE CHR$(HOME) PRINT "HOME" CASE CHR$(ENDKEY) PRINT "END" CASE CHR$(RIGHT) PRINT "Стрелка вправо" CASE CHR$(LEFT) PRINT, "стрелка влево" CASE ELSE BEEP END SELECT END IF LOOP Подпрограммы GOSUB...RETURN GOSUB...RETURN — управляющие операторы вызова под- программы и выхода из нее. GOSUB метка_1 [операторы] RETURN [метка_2] • метка_1 — метка первой строки подпрограммы; • метка_2 — метка строки, куда возвращается управление после выхода из подпрограммы. Вы можете вызвать подпрограмму любое количество раз. Можно вызвать одну подпрограмму из другой. В тоже время под- программа не может вызывать сама себя (быть рекурсивной). Од- на подпрограмма может иметь несколько операторов RETURN. GOSUB и RETURN должны находиться в одном модуле. RETURN не может использоваться для передачи управления из одной процедуры типа SUB или FUNCTION другой процедуре. GOSUB...RETURN — устаревшая программная конструкция. Вместо нее лучше использовать процедуры SUB или FUNCTION, функцию DEF FN. Использовать в GOSUB...RETURN имеет смысл 155
только внутри процедур SUB или FUNCTION, при обращении к од- ному фрагменту текста, когда выделение фрагмента в отдельную про- цедуру нецелесообразно. х%: GOSUB DrawResult х% Л 2: GOSUB DrawResult х% Л 4: GOSUB DrawResult DrawResult: IF y% = О THEN BEEP: RETURN LOCATE 11, 10: PRINT y% RETURN SUB TestSub SELECT CASE CASE IS = CASE IS = CASE IS = CASE ELSE END SELECT END SUB (x%) x% 1: 2: 3: : . y% y% y% Функции DEFFN DEF FN — оператор, описывающий функцию как пользова- тельскую. Функция DEF FN может быть записана в блочной или в ли- нейной форме. DEF FNmmh[(параметры)] = выражение Линейная форма Блочная форма DEF FNmmh [(параметры)] [операторы] FNимя = выражение [операторы] [EXIT DEF] [операторы] END DEF • имя — имя переменной, до 40 знаков. Имя, комбинируемое с FN, является именем функции. Имя может иметь знак опре- деления типа, который указывает на тип возвращаемого зна- 156
чения. Для присвоения значения функции, присвойте его полному имени так, как обычной переменной: FNString$ = "Нет ответа." • параметры — список переменных, разделенных запятыми. При вызове функции, значения каждого аргумента присваи- ваются соответствующему параметру. Аргументы передаются по значению. DEF FN не поддерживает массивы, записи или символьные строки фиксированной длины в качестве аргу- ментов; • выражение — выражение, вычисляющее результат функции. В линейном синтаксисе выражение является телом функции. Если нет выражений, присвоенных имени функции, по умол- чанию возвращается 0 для числовой функции и пустая строка ("") для символьной функции. Логика работы при блочной и линейной форме Перед использованием, функция DEF FN должна быть оп- ределена, иначе ее вызов приведет к ошибке "Function not defined" (Функция не определена). DEF FN не может находиться внутри другого определения DEF FN. Функция также не может быть рекурсивной (вызывать сама себя). Для выхода из блочной функции до ее завершения исполь- зуйте оператор EXIT DEF. Функция может вызываться только из того модуля, в котором она определена; обращения из других мо- дулей недействительны. Поэтому, если в программе несколько модулей, то вы должны поместить определение функции DEF FN в каждый модуль, или использовать включаемый (INCLUDE) файл с определением функции DEF FN. Вместо функции DEF FN имеет смысл использовать более современную конструкцию FUNCTION...END FUNCTION. Бу- дучи один раз определена, процедура FUNCTION может затем быть вызвана из любого модуля Вашей программы. Кроме того в процедуру FUNCTION можно передавать массивы и записи. Од- нако, в редких случаях, использование функции DEF FN более целесообразно, чем процедуры FUNCTION. Функция DEF FN не проверяет тип передаваемого ей числового аргумента, что по- зволяет писать функции DEF FN, которым можно передавать любой числовой аргумент: 'функция fns$ превращает любое число в символьную строку 'и убирает начальный пробел DEF fns$ (a):fns$ (а) = LTRIM$(STR$(а)) 157
а = 100: а = 100: а# = 100: а% = 100: а& = 100: результат > 100< >100< >100< >100< >100< PRINT " PRINT " PRINT PRINT PRINT : >" ; >" ; 11 >•• ii >n 11 >" STR$(a); "<" fns$(a); "<" ; fns$(a#); "<¦ ; fns$(a%); "<' ; fns$(a&); "<" Процедуры (*) FUNCTION FUNCTION...END FUNCTION — оператор, указывающий начало и конец процедуры FUNCTION. FUNCTION имя [(параметры)][STATIC] [операторы] имя = выражение [операторы] END FUNCTION • имя — задается как обычная переменная. Определяет тип возвращаемых данных; • параметры — список переменных, значения которых переда- ются функции при ее вызове. Изменение значения параметра внутри функции изменит его значение в вызывающем модуле; • выражение — возвращаемое значение функции. Если имени функции ничего не присваивается, возвращается значение по умолчанию: для числовых функций — ноль, для символь- ных — пустая строка (""); • STATIC — указывает, что локальные переменные функции сохраняются между вызовами. Иначе локальные переменные считаются динамическими и их значения теряются при выхо- де из функции. Атрибут STATIC не влияет на переменные, описанные вне функции операторами DIM или COMMON с атрибутом SHARED. 158
Чтобы передать в процедуру в качестве аргумента массив до- статочно указать пустые скобки. FUNCTION ParseLine (Keywords$(), KeywordTypes()) Процедура FUNCTION похожа на SUB. Она принимает па- раметры, состоит из серии операторов и изменяет значения па- раметров. В отличие от SUB, FUNCTION вызывается подобно встроенной функции языка BASIC. Также как и SUB, FUNCTION имеет локальные перемен- ные. Любая переменная, не входящая в список параметров, явля- ется локальной, за исключением переменных, описанных опера- тором SHARED внутри процедуры или операторами DIM или COMMON с атрибутом SHARED в главном модуле. Для возвращения значения из функции, присвойте его име- ни функции. Например, в функции BinarySearch вы можете при- своить значение внутренней константы FALSE имени функции для указания на то, что искомый контекст не найден: FUNCTION BinarySearch(...) CONST FALSE=0 1 Ничего не найдено. Вернуть FALSE. IF Lower > Upper THEN BinarySearch=FALSE EXIT FUNCTION END IF END FUNCTION Применение ключа STATIC слегка повышает скорость вы- полнения, но STATIC не используется с рекурсивными процеду- рами FUNCTION. Кроме того, при использовании ключа STA- TIC вы должны сами заботится о присвоении начальных значе- ний всем переменных процедуры, так как их старые значения со- храняются между вызовами. Лучше не использовать этот ключ и возложить эти проблемы на BASIC. Рекурсивные процедуры FUNCTION Процедуры FUNCTION могут быть рекурсивными, то есть вызывать сами себя. Типичным случаем применения рекурсии является функция вычисления факториала1: 1 Здесь п! обозначает факториал числа п, а не переменную п обычной точности 159
n!=n*(n-l)*(n-2)*...2*1 К примеру факториал числа 5 вычисляется как: 5! = 5*3*4*2*1 = 120 При использовании рекурсии вы обязательно должны пре- дусмотреть условие выхода. В данном случае — при вводе нулево- го значения (по определению факториал нуля равен единице). Пример. Вычисление факториала DECLARE FUNCTION Factorial* (n%) Formats = "##_! = ###################« DO INPUT "Введите число от 0 до 20 (или -1 для выхода): "; Num% IF Num% >= 0 AND Num% <= 20 THEN PRINT USING Format$; Num%; Factorial*(Num%) END IF LOOP WHILE Num% >= 0 END FUNCTION Factorial* (n%) STATIC IF n% > 0 THEN 'Factorial вызывается снова, если 'N больше нуля. Factorial* = n% * Factorial*(n% - 1) ELSE Factorial* = 1 END IF END FUNCTION SUB SUB...END SUB — оператор, указывающий начало и конец процедуры SUB. SUB имя[список_параметров][STATIC] [операторы] [EXIT SUB] [операторы] END SUB • имя — переменная, до 40 знаков, имя процедуры. Это имя не должно использоваться другими операторами FUNCTION или SUB или в подключаемой библиотеке; 160
• списокпараметров — содержит имена простых переменных и массивов, передаваемых в процедуру. Имена в списке разде- ляются запятыми. Любое изменение аргумента в процедуре приведет к изменению его значения в вызывающем модуле. Список_параметров имеет следующую форму: переменная[()] [AS тип][, переменная[( )] [AS тип]]... • переменная — имя переменной или массива (массив задается с пустыми скобками); • тип — тип переменной, может быть INTEGER, LONG, SINGLE, DOUBLE, STRING или пользовательским. Не может быть фик- сированной строкой. Строки фиксированной длины необходимо преобразовать в строки переменной длины. SUB и END SUB отмечают начало и конец процедуры, вы мо- жете использовать оператор EXIT SUB для выхода из процедуры. Процедуры вызываются оператором CALL или путем указа- ния ее имени со списком аргументом. SUB используются подоб- но операторам языка. Процедура SUB (также как и FUNCTION) может быть рекурсивной. Атрибут STATIC указывает, что все переменные, локальные для процедуры SUB, являются статическими (STATIC) — их зна- чения сохраняются между вызовами. Использование ключа STA- TIC несколько повышает скорость выполнения процедуры, в то- же время STATIC не используется в рекурсивных процедурах1. Все переменные являются локальными, кроме тех, которые описаны операторами DIM, REDIM, COMMON как SHARED в главном модуле, или оператором SHARED в самой процедуре. Внутри процедуры SUB нельзя определять процедуры SUB и FUNCTION, функции DEF FN, а также использовать операторы GOSUB, GOTO, RETURN для входа в процедуру или выхода из процедуры. Передача параметров в процедуры SUB и FUNCTION (*) Прежде чем использовать в программе процедуру SUB или FUNCTION, необходимо уяснить отличие термина "параметр" от термина "аргумент". См. описание процедуры FUNCTION 161
Параметр Имя переменной, используемое в операторе SUB, FUNCTION или DECLARE Аргумент Константа, переменная или выражение, которое передает- ся в процедуру SUB или FUN- CTION при их вызове. Как показано на рисунке, когда процедура вызывается, аргу- менты передаются в тело процедуры через заголовок, причем первый параметр получает значение первого аргумента, второй параметр получает значение второго аргумента и так далее. Параметры и аргументы е процедурах SUB и FUNCTION Аргументы Вызов процедуры Заголовок процедуры CALL TestSub f (А%, В!, "text") SUB TestSub (Pl%, P2!, P3$) STATIC v. u j Параметры Этот рисунок также демонстрирует еще одно важное прави- ло: Хотя имена в списке аргументов и в списке параметров могут быть разными, но между аргументами и параметрами должно быть взаимно однозначное соответствие, т. е. должно совпадать их количество и типы. Список параметров может состоять из: • имен переменных, кроме строк фиксированной длины; • имен массивов, которые записываются следующим образом: сначала указывается имя массива, за которым следуют пустые скобки. 162
Список аргументов может состоять из: • констант; • выражений; • имен переменных; • имен массивов (с пустыми скобками) Например, определение списка параметров процедуры TestSub (Заголовок процедуры): SUB TestSub (А%, Array(), RecVar as RecType, Cs$) END SUB Первый параметр А% — целое число; второй параметр ArrayO — числовой массив обычной точности;1 третий параметр, RecVar, является переменной-записью типа RecType, и четвертый параметр, Cs$ — символьная строка. Вызов процедуры TestSub демонстрирует передачу процедуре TestSub четырех аргументов соответствующего типа: TYPE RecType Rank AS STRING * 12 SerialNum AS LONG END TYPE DIM RecVar as RecType CALL TestSub (X%, A(), RecVar, "Дельфин") FUNCTION или SUB — проблема выбора (*) Если при разработке программы, у вас возникнет вопрос, ка- кую из процедур, FUNCTION или SUB лучше всего применить, воспользуйтесь этими рекомендациями. Процедура FUNCTION возвращает одиночное значение, по- этому ее использование оправдано в тех случаях, когда возврат одного значения решает эту проблему. К примеру, если перед от- 1 Числовые переменные без явного указания их типа считаются обычной точ- ности. 163
крытием файла, вам нужно убедиться, что он существует (необ- ходимо получить одно значение — ДА или НЕТ), можно исполь- зовать процедуру FUNCTION: DECLARE FUNCTION Exist (file$) DEFINT A-Z CONST TRUE% = -1, FALSE% = 0 INPUT "Введите имя файла"; FileName$ IF Exist (FileName$) THEN PRINT "Этот файл существует" ELSE PRINT "Такого файла нет" END IF FUNCTION Exist (file$) i **************************************************** 'эта функция проверяет, если такой файл 'если есть, процедуре Exist присваивается значение -1 1 (Истина) иначе значение 0 (Ложно) |**************************************************** 1 определяем незанятый номер файла nf = FREEFILE 'открываем файл как двоичный OPEN file$ FOR BINARY AS #nf 1 проверяем длину файла в байтах IF LOF(nf) > О THEN 'если длина больше нуля, то файл существует CLOSE #nf: Exist = TRUE ELSE 'если файл не существовал, то открытие его как двоичного 1 приводит к появлению на диске файла с нулевой длиной, 1 а такой файл нужно уничтожить. CLOSE #nf: KILL file$ Exist = FALSE END IF Напротив, процедура SUB используется в тех случаях, когда необходимо провести какие-либо действия над переменными из списка аргументов, либо получить несколько выходных значений. Предположим, вам необходимо транспонировать матрицу (проще говоря — транспонировать матрицу — это значит поло- жить ее "на бок"). Использование процедуры SUB решает эту проблему: DECLARE SUB TransMatrix (a%(), b%()) 1 все переменные целые DEFINT A-Z 164
'резервируется массив для исходной 'и транспонированной матриц DIM MatrixlE, 5), matrix2E, 5) 'матрица Matrixl заполняется числами от 1 до 25 start = 1 FOR i = 1 ТО 5 FOR j = 1 TO 5 Matrixl(i, j) = start start = start + 1 NEXT j NEXT i CLS 'выводится исходная матрица PRINT "Исходная матрица:": PRINT FOR i = 1 TO 5 FOR j = 1 TO 5 PRINT USING "## "; Matrixl(i, j); NEXT j PRINT NEXT i PRINT 1 производится транспонирование матрицы CALL TransMatrix(Matrixl(), matrix2()) 1 выводится транспонированная матрица PRINT "Транспонированная матрица": PRINT FOR i = 1 TO 5 FOR j = 1 TO 5 PRINT USING "## "; matrix2(i, j); NEXT j PRINT NEXT i SUB TransMatrix (a(), b()) i л************************************** 'эта процедура транспонирует матрицу а() 'результат заносится в матрицу Ь() I*************************************** 'Определяется размерность матрицы а, 'предполагается, что матрица "квадратная" 'т. е. число строк=числу столбцов kolvo = UBOUND(a) FOR i = 1 ТО kolvo FOR j = 1 TO kolvo b(j, i) = a(i, j) NEXT j NEXT i END SUB 165
Результат Исходная ] 1 6 11 16 21 2 7 12 17 22 матрица: 3 8 13 18 23 4 9 14 19 24 Транспонированная 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 5 10 15 20 25 маа 21 22 23 24 25 Другие управляющие операторы END END — оператор-указатель конца программы, процедуры или блока. END [DEF I FUNCTION I IF I SELECT | SUB I TYPE] END DEF END FUNCTION END IF END SELECT END SUB END TYPE Конец определения функции DEF FN; Конец процедуры FUNCTION; Конец блока IF...THEN...ELSE; Конец блока SELECT CASE; Конец процедуры SUB; Конец описания пользовательского типа данных. Простой END останавливает выполнение программы и закрывает все файлы. В .ЕХЕ-программах возвращает управле- ние операционной системе. В среде QuickBASIC возвращает управление среде. Компилятор всегда подразумевает END как окончание програм- мы, так что конце программы оператор END можно опускать. 166
EXIT EXIT — управляющий оператор, производящий выход из блока или модуля до его завершения. EXIT DEF I DO I FOR I FUNCTION I SUB EXIT DEF EXIT FOR EXIT FUNCTION EXIT SUB Выход из функции DEF FN при выполнении какого-либо условия. Программа продолжает работу с оператора, идущего после вызова этой функции; Альтернативный выход из цикла FOR...NEXT; Выход из процедуры FUNCTION. Программа продолжается с оператора, идущего после вызова функции; Выход из процедуры SUB. Программа продол- жается после оператора CALL. Операторы EXIT не означают конец данной структуры или модуля. Они используются только для альтернативного выхода. Для организации конца используется управляющий оператор END. Пример. Использование оператора EXIT FOR. Удаление концевых пробелов из символьной строки. s$ = "Программное обеспечение " 3 = О 1 Сканируем строку от конца к началу и находим ' первый символ, не являющийся пробелом. FOR i = LEN(s$) TO 1 STEP -1 с$ = MID${s$,i,l) IF c$ <> " " THEN j = i EXIT FOR ' символ найден, выходим из цикла END IF NEXT i 1 Удалим ненужные символы справа. s$ = LEFT$(s$,j) PRINT ">"; s$; "<" END 167
Результат: >Программное обеспечение< STOP STOP — управляющий оператор, останавливающий выпол- нение программы. STOP При запуске в среде QuickBASIC оператор STOP оставляет файлы открытыми и не производит выхода в операционную сис- тему. Напротив, оператор STOP в .ЕХЕ-файле закрывает все файлы и передает управление операционной системе. Раньше оператор STOP использовался как средство отладки, для того, чтобы прервать выполнение программы в нужном мес- те. В среде QB имеется более удобное средство — "Toggle Breakpoint" (Точка Прерывания). Чтобы поставить точку преры- вания подведите курсор к нужной строке программы и нажмите клавишу {F9}. Запустите программу на выполнение ({SHIFT-F5}). Когда программа достигнет точки прерывания, она остановится, вы сможете посмотреть значения переменных ({SHIFT-F9}), до- бавить или убрать наблюдение, или продолжить выполнение программы {F5}. SYSTEM SYSTEM — управляющий оператор, закрывает все открытые файлы и возвращает управление операционной системе. SYSTEM Оператор SYSTEM производит выход в систему из среды QuickBASIC только тогда, когда программа запущена с команд- ной строки с ключом /RUN. Ввод SYSTEM в окне Immediate приведет к выходу из среды QuickBASIC. В .ЕХЕ-программах END и SYSTEM действуют идентично. Использовать SYSTEM имеет смысл в том случае, когда вы хоти- те запускать программу в виде исходного текста (не компилируя ее в .ЕХЕ-файл). 168
Пример. Предположим, у нас имеется программа TEST.BAS PRINT "Я очень умная программа!": PRINT PRINT "Исполняюсь автономно, как .ЕХЕ-файл" SYSTEM Если запустить эту программу с ключом1 /RUN, то она от- работает, и передаст управление операционной системе, не пока- зывая своего исходного текста: C:\QB45>qb /runTEST.BAS 1 Более подробно о ключах запуска среды QB написано в Приложении 2 "Запуск, редактирование и отладка программы". 169
ВВОД-ВЫВОД НА ВНЕШНИЕ УСТРОЙСТВА Клавиатура INPUT INPUT — оператор ввода/вывода, считывающий данные с клавиатуры во время выполнения программы и размещающий их в списке переменных. INPUT[;][вопрос"{;I,}]переменные • ; — точка с запятой сразу после INPUT оставляет курсор на той же линии экрана после нажатия клавиши {ENTER}; • "вопрос" — символьная константа. Приглашение к вводу данных; • ; — печатает знак вопроса после символьной строки; • , — печатает строку без знака вопроса; • переменные — список переменных, разделенных запятыми, принимающий введенные значения. Оператор INPUT останавливает программу и ждет ввода данных. Количество вводимых данных должно соответствовать количеству переменных в списке. Первый символ после очеред- ной запятой, если это не пробел, ASCII 13 (CR — возврат карет-
От Издательства Данная книга, изданная впервые в 1994 году для широкого круга профессионалов и любителей языка QuickBASIC 4.5, приобрела большую популярность в ВУЗах, колледжах, школах и лицеях страны. Не будучи изначально кано- ническим учебником, она переиздается в качестве пособия ввиду острой пот- ребности учебных заведений в литературе по языкам программирования. Издательство, заинтересованое в усовер- шенствовании книги, с благодарностью примет все критические замечания, советы и пожелания педагогов и учащихся.
ки) или ASCII 10 (LF — перевод строки), подразумевается как начало новой вводимой единицы. Переменные могут быть числовыми или символьными, эле- ментами массивов, элементами записей. Типы данных в списке и вводимых с клавиатуры должны совпадать. Если в символьной строке необходимо ввести запятую, то символьную строку нужно заключить в кавычки. Данные для переменных пользовательского типа (записей) юлжны вводиться раздельно: ГУРЕ Demograph FullName AS STRING * 25 Age AS INTEGER END TYPE DIM Person AS Demograph INPUT "Введите имя и возраст: ";Person.FullName, Person.Age Если вы ввели значения не тех типов, или их количество не совпадает с количеством переменных в списке, вы получите со- общение об ошибке "Redo from start" (Повторите сначала). Пока вы не закончили ввод, значения не присваиваются пе- ременным. Можно редактировать вводимые данные до нажатия клавиши {ENTER}. Клавиши редактирования в основном анало- гичны клавишам редактирования среды QB: Клавиша RIGHT LEFT CTRL+RIGHT CTRL+LEFT HOME END INS TAB DEL BACKSPACE Выполняемое действие Курсор на один символ вправо; Курсор на один символ влево; Курсор на одно слово вправо; Курсор на одно слово влево; Курсор к началу вводимой строки; Курсор к концу вводимой строки; Переключение вставка/замещение; Табуляция вправо; Стереть символ, на который указывает курсор; Стереть символ перед курсором. В начале строки — указанный курсором; 172
CTRL+END ESC ENTER CTRL+T CTRL+BREAK или CTRL+C Стереть от курсора до конца строки; Стереть всю строку ввода; Конец ввода; Включает/выключает список значений F-клавиш в последней строке экрана; В среде QuickBASIC обрывает выполнение программы. В .ЕХЕ-программе — вызывает аварийный выход в DOS. LINE INPUT LINE INPUT — оператор ввода/вывода, присваивающий вводимую строку (до 255 символов) символьной переменной без влияния знаков-разделителей. LINE INPUT[;] ["вопрос";] символьная_переменная • вопрос — символьная константа, приглашение на ввод дан- ных. Можно включить в нее знак вопроса "?"; • символьная_переменная — принимает все символы до нажа- тия клавиши ENTER. В отличии от оператора INPUT знак "?" после вопроса не выводится. Знак ";" перед вопросом сохраняет курсор на той же строке после нажатия клавиши ENTER. LINE INPUT использует те же клавиши редактирования, что и INPUT. INPUTS INPUTS — функция ввода/вывода, читающая символьные строки с клавиатуры. INPUT$(n) • п — количество символов, читаемых с клавиатуры. Знаки не дублируются на экран (ввод без эха). Можно прер- вать исполнение данной функции нажатием CTRL+BREAK. В отличии от функции INKEYS данная функция ждет ввода ука- занного количества символов. 173
Пример. Задержка исполнения программы до нажатия клавиши. CLS PRINT "Для продолжения нажмите любую клавишу" INPUT$A) INKEY$ INKEY$ — функция ввода/вывода, читающая символы с клавиатуры. INKEY$ INKEYS возвращает одно- или двухбайтную строку, содер- жащую символ, считанный с клавиатуры. Если символ не был считан, то возвращается нулевая строка (то есть данная функция не ожидает ввода в отличии от оператора INPUTS). Однобайтная строка содержит ASCII-символ. Двухбайтная строка содержит расширенный код: первый символ равен ASCII О, второй — расширенный код специальных клавиш и клавиш управления курсором. INKEYS не дублирует ввод с клавиатуры выводом на экран (ввод осуществляется без эха). Особо обрабатываются нажатия клавиш: CTRL+BREAK CTRL+ALT+DEL CTRL+NUMLOCK или PAUSE PRINT SCREEN Останавливается выполнение в среде QuickBASIC. В .ЕХЕ-виде не обрабатывается; Происходит перезагрузка компьютера; Приостановка выполнения программы; Печать содержимого экрана. Пример. Задержка до нажатия клавиши. PRINT "Нажмите любую клавишу..." DO LOOP WHILE INKEY$ ="" 174
Экран PRINT PRINT — оператор ввода/вывода, выдающий данные на эк- ран. PRINT [список_выражений][{,I;}] • Список_выражений — выражения любого типа, кроме пользовательского. Символьные константы в списке выраже- ний должны заключаться в кавычки. Если все аргументы опущены, выводится пустая строка. Если списоквыражений указан, то значения выражений выводятся на экран по порядку Положительные числа выводятся с пробелом перед значени- ем, отрицательные выводятся со знаком "минус". Существует два формата вывода чисел обычной и двойной точности: с фиксированной и плавающей точкой. Если выводит- ся значение обычной точности с семью или менее значащими цифрами или число двойной точности с пятнадцатью или менее значащими цифрами без потери точности, они выводятся в фор- мате с фиксированной точкой. Иначе — с плавающей. Например, число 1.1 Е-6 выводится как .0000011, а число 1.1Е-7 выводится как 1.1 Е-7. Или число 1.ID-15 - как .0000000000000011, а число 1.1D-16- как 1.1D-16. Для печати информации отдельных элементов пользовательско- го типа данных , пользуйтесь выводом ее отдельных элементов: ТУРЕ МуТуре Word AS STRING * 20 Count AS LONG END TYPE DIM Myrec AS MyType PRINT Myrec.Word Позиция каждого выводимого элемента списка выражений определяется знаками-разделителями списка. BASIC делит строку 175
экрана на зоны по 14 символов каждая. В списке выражений за- пятая перед элементом указывает на то, что он будет выведен с начала следующей зоны. Точка с запятой означает, что этот эле- мент будет выведен сразу после предыдущего. Пробелы или зна- ки табуляции имеют такой же эффект, как и точка с запятой. Если запятая или точка с запятой завершают список выра- жений, то следующий оператор PRINT начинает вывод с той же строки. Если список не завершается разделителем, то следующий оператор начнет вывод со следующей строки. Когда печатаемая строка длиннее, чем ширина экрана, то вывод продолжается со следующей строки. Примеры. Использование запятых и точек с запятой. CLS X = 5 PRINT Х+5, Х- 5, X* (-5),ХЛ5 END Результат: 10 0 -25 3125 CLS FOR X = 1 ТО 5 J = J + 5 К = К + 10 PRINT J; К; NEXT X Результат: 5 10 10 20 15 30 20 40 25 50 PRINT USING PRINT USING — оператор ввода/вывода, осуществляющий вывод на экран по указанному формату. PRINT USING формат; список_выражений [ {, I ,-} ] • формат — символьное выражение, содержит специальные символы, управляющие представлением выводимых данных; • Списоквыражений — выражения любого типа, кроме пользовательского. Символьные константы в списке выраже- ний должны заключаться в кавычки. 176
Форматы для вывода символьных значений Сим- вол ! \\ & Описание Вывод первого символа указанной строки; Вывод 2 + п символов из строки, где п — число пробе- лов между двумя слэшами. Если слэши набраны без пробелов, то выводятся два начальных символа строки. Если поле вывода больше, чем длина строки, то строка выравнивается влево, а справа печатаются пробелы; Вывод строки любой длины. Строка выводится без мо- дификаций. Пример. Вывод символьных данных. Конструкция: PRINT USING "!"; Москва PRINT USING "\ \"; Ленинград PRINT USING ">\ \<"; Дмитров PRINT USING "&"; Санкт-Петербург Результат: м Лен >Дмитров < Санкт-Петербург Форматы для вывода числовых значений. Сим- вол # + Описание Представляет одну цифровую позицию. Если выводимое число имеет меньше цифр, чем указано позиций, то оно выравнивается вправо, дополняясь слева пробелами. Выводит десятичную точку. Может быть вставлена в любое место числового поля. Если символ указан, точ- ка всегда печатается, независимо от точности значения. Лишние дробные знаки отсекаются. Вывод знака числа (плюс или минус), либо перед чис- ловым полем, либо после — как указано. 177
- ** $$ **$ - Вывод минуса перед отрицательным числом, либо пе- ред числовым полем, либо после — как указано. Заменить левые пробелы перед числом звездочками. Две звездочки указывают, что выводить следует два или более знака. Поставить перед числом в указанном поле знак долла- ра. Два доллара указывают, что выводить следует два знака, один из которых — доллар. Комбинирует эффект двух звездочек и двух долларов. Пустые места поля слева замещаются звездочками, а впереди числа ставится знак доллара. **$ указывают три или более позиций, одна из которых — знак долла- ра. Если выводится отрицательное число, то минус ста- вится перед долларом. Если перед числовым полем поставлена запятая, то каж- дые три знака до десятичной точки отделяются запятыми (выделяются сотни, тысячи и т. д. по американскому формату представления чисел). Запятая не влияет на вы- вод чисел в экспоненциальной форме (ЛАЛА или ЛЛЛАЛ). Знак подчеркивания означает, что следующий символ вы- водится не как управляющий, а как литерал. Для вывода одного символа подчеркивания поставьте два ( ) в строке формата. Если выводимое число не помещается в поле формата, то перед ним выводится знак процента (%). Типы выводимых значений в списке_выражений должны со- ответствовать типам полей данных в строке формата. Действие символов-разделителей списка_выражений описано в операторе PRINT. Пример. Вывод числовых данных. Конструкция: PRINT USING PRINT USING PRINT USING •##.##"; .78 '###.##"; 987.654 '##.## "; 10.2, 5.3 Результат: 0.78 987.65 10.20 5.30 178
PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT USING USING USING USING USING USING USING USING USING USING USING USING USING "####,. "##.##л ».####л "+.##АЛ "+.##лл "; -68.95, 2.4 "; -68.95, 22.44 11; 12.39, -0.9 ##"; 456.78 ##"; 2.34 ##"; 1234.5 ллл"; 234.56 л/чл-"; -888888 лл"; 123 ллл"; 123 "_!##.##_!"; 12.34 ; 111.22 .999 -68.95 +2.40 68.95- 22.45 *12.4 **0.9 $456.78 ***$2.34 1,234.50 2.35Е+02 .8889Е+06 +.12Е+03 +.12Е+003 112.34! %111.22 %1.00 WRITE WRITE — оператор ввода/вывода, посылающий данные на экран. WRITE [список_выражений] • списоквыражений — содержит одно или несколько выраже- ний, разделенных запятыми. Если список_выражений опущен, печатается пустая строка. Вы- водимые значения разделяются запятыми. Символьные строки зак- лючаются в кавычки. После печати последнего выражения в списке вставляются символы возврата каретки и перевода строки. WRITE записывает числовые значения без начальных и конечных пробелов. Пример. Различие между WRITE и PRINT. CLS А = 80: В = 90: С$ = " Это все." : D = -1.0Е-13 WRITE А, В, С$, D PRINT А, В, С$, D Результат: 80, 90, "Это все.", -1Е-13 80 90 Это все. -1Е-13 179
LOCATE LOCATE — оператор ввода/вывода, передвигающий курсор в указанную позицию экрана. LOCATE [строка][,[столбец][,[курсор][,[начало, ко- нец] ] ] ] • строка — номер строки на экране. Если параметр не указан, то номер строки не меняется; • столбец — номер столбца на экране. Если параметр не ука- зан, то номер столбца не меняется; • курсор — логический параметр, указывающий видимость кур- сора. Если равен 0, то курсор не виден, если равен 1, то ви- ден; • начало — начальная скан-линия курсора; конец — конечная скан-линия курсора. Можно опустить любой параметр в операторе. Если опустить строку и столбец, LOCATE оставит курсор на позиции, установ- ленной предыдущим оператором LOCATE или предыдущим опе- ратором ввода/вывода. Для других аргументов сохраняются пре- дыдущие значения. Начало и конец определяются скан-линиями экрана, кото- рые зависят от его разрешения. Эти аргументы описывают форму курсора. Если начало меньше конца, курсор будет двойным. Если выполнен оператор KEY ON, то последняя строка эк- рана недоступна, Выполните оператор KEY OFF, и LOCATE по- лучит доступ к ней. Примеры. CLS ' Перемещение курсора в 5 строку, 5 колонку. LOCATE 5, 5 PRINT "С" DO: LOOP WHILE INKEY$ = "" 1 Перемещение курсора в верхний левый угол экрана. LOCATE 1,1 PRINT "С" DO: LOOP WHILE 1NKEY$ = "" 1 Делает курсор видимым. Позиция не меняется. LOCATE ,,1 PRINT "С" DO: LOOP WHILE INKEY$ = "" ' Изменяет форму курсора. LOCATE,,,7 PRINT "С" . DO: LOOP WHILE INKEY$ = "" 180
1 Комбинация всех действий. LOCATE 5,1,1,0,7: PRINT "С" CSRLIN CSRLIN — функция ввода/вывода, возвращающая значение текущей строки, в которой находится курсор. n = CSRLIN Пример: LOCATE 20, 1 PRINT CSRLIN Результат: 20 POS POS — функция ввода/вывода, возвращающая номер столб- ца, в котором находится курсор. POS(O) Пример. Использование POS для печати новой строки после того, как введено 40 символов. CLS PRINT "Нажмите ESC для завершения." PRINT DO- DO WHILE POS@) < 41 'Оставаться на той же строке, DO 'пока не напечатано 40 символов. har$ = INKEY$ LOOP WHILE Char$ = "" ' Если нажата клавиша ESC, то конец. ' Иначе - вывести символ на экран. IF ASC(Char$) = 27 THEN END ELSE PRINT Char$; LOOP PRINT LOOP 181
SPC SPC1 — функция ввода/вывода, пропускающая п пробелов в текущей строке при выполнении оператора PRINT или LPRINT. SPC(n) • п — числовое выражение в пределах 0—32767, обозначает ко- личество пробелов, пропускаемых в текущей строке. Пример. CLS PRINT "ГДЕ-ТО"; SPCA5); "ЗДЕСЬ" Результат: ГДЕ-ТО ЗДЕСЬ TAB TAB — функция ввода/вывода, сдвигающая позицию вывода при использовании операторов PRINT или LPRINT. TAB(столбец) • столбец — числовое выражение, в пределах от 1 до ширины выво- да. Аргумент "столбец" — новая колонка вывода в данной стро- ке. Если текущая колонка больше, чем столбец, то вывод в дан- ную позицию будет произведен уже на другой строке. Если аргу- мент "столбец" больше, чем ширина вывода, то вывод начнется с позиции, определяемой выражением 1 + (столбец MOD ширина). Если столбец меньше 1, вывод начнется с позиции 1. TAB ис- пользуется только с операторами PRINT и LPRINT. Пример. PRINT TABA287); "Один" 'PRINT TABB55); "Два" PRINT TAB(-5); "Три" PRINT 23456789012345678901234567890"; ТАВB0); "Четыре" ' Функция SPC работает очень медленно. Вместо нее лучше использовать аналогичную по своим возможностям функцию SPACES. 182
Результат: Один Два Три 123456789012345678901234567 890 Четыре WIDTH WIDTH — оператор ввода/вывода, устанавливающий ширину строки вывода файла или устройства, а также количество строк и столбцов экрана. Форма: Синтаксис: 1 WIDTH [столбцы],[строки] 2 WIDTH #номер_файла,ширина 3 WIDTH устройство,ширина 4 WIDTH LPRINT ширина Форма 1 2 3 4 Описание Устанавливает количество столбцов и строк экрана. Число столбцов может быть 40 или 80. По умолчанию 80. Число строк может быть 25, 30, 43, 50 или 60, в зависимости от адаптера и режима экрана (см. опера- тор SCREEN). По умолчанию 25. Устанавливает ширину вывода устройства, открытого как файл (например, LPT1: или CONS:). Аргумент номер файла — это номер устройства, открытого опе- ратором OPEN. Устанавливает ширину вывода устройства, заданного символьной константой (например, "CONS:"). Это определение действует до открытия устройства как файл оператором OPEN. He действует, если устрой- ство уже открыто. Устанавливает ширину вывода принтера для всех последующих операторов LPRINT. 183
Пример. Установка 43 строк на экране1 WIDTH 80, 43 FOR i = 1 ТО 43 LOCATE i, 1 PRINT "Строка "; i; SPC(i); "*"; NEXT i DO: LOOP WHILE INKEY$ = "" Пример. Установка ширины печати в 255 символов LPRINT "Без оператора WIDTH" FOR 1% = 128 ТО 255: LPRINT CHR%(I%);: NEXT I LPRINT "С оператором WIDTH" WIDTH "LPT1:", 25 5 FOR 1% = 12 8 TO 255: LPRINT CHR%(I%);: NEXT I Файлы OPEN OPEN — оператор ввода/вывода, включающий ввод/вывод в файл или устройство. OPEN файл [FOR тип] [ACCESS доступ] [блок] AS [#]номер [LEN=nroiHa] • файл — символьное выражение, определяющее имя устрой- ства или файла, включая путь; • тип — одно из описанных ниже ключевых слов; • номер — целое выражение от 1 до 255, номер файла; • длина — длина записи. По умолчания равна 128 байт для файлов прямого доступа и 512 для файлов последовательного доступа. Для двоичных файлов длину указывать не требуется. Вы должны открыть файл перед любыми операциями вво- да/вывода, производимыми с ним. OPEN размещает буфер для ввода/вывода и устанавливает тип доступа к файлу. 1 В текстовом режиме для дисплея EGA можно установить 25 или 43 строки, для VGA — 25, 43, 50 и 60 F0 — только в графическом режиме SCREEN 12). Число столбцов может быть 40 (только 25 строк) или 80. Установки текстового экрана по умолчанию — 80 столбцов, 25 строк 184
Тип OUTPUT INPUT APPEND RANDOM BINARY Описание Определяет последовательный вывод; Определяет последовательный ввод; Определяет последовательный вывод с добавлением, т. е. устанавливает указатель записи к концу файла. Операторы PRINT # и WRITE # добавляют выво- димые данные к концу файла; Определяет прямой ввод/вывод (умалчиваемый тип). Если нет условия ACCESS, доступ выполняет- ся в следующем порядке: 1. Чтение/запись; 2. Толь- ко запись; 3. Только чтение. Определяет двоичный ввод/вывод. Можно читать или писать информацию любого байта файла опера- торами GET и PUT. Если тип опущен, по умолчанию присваивается тип RANDOM. Выражение "Доступ" определяет разрешенные операции с открытым файлом. Если другой процесс уже открыл файл, и зап- ретил к нему доступ, то оператор OPEN выдает сообщение об ошибке "Permission denied" (Доступ запрещен). Условие ACCESS работает с оператором OPEN только в вер- сии DOS, поддерживающей сети (DOS версии 3.0 или выше). В дополнение, вы должны запустить программу SHARE.EXE (или сетевую программу) для разрешения операций блокировки. Ран- ние версии DOS возвращают сообщение об ошибке "Advanced feature unavailable" (Расширенное средство невозможно). Аргу- мент "Доступ" может быть следующим: Тип доступа READ WRITE READ WRITE Описание Только для чтения; Только для записи; Чтение и запись. Этот тип доступа возможен только для файлов RANDOM, BINARY и APPEND. 185
Условие "Блок" работает в мультизадачной среде для разде- ления доступа между процессами к открытому файлу. Тип блока по умолчанию SHARED LOCK READ LOCK WRITE LOCK READ WRITE Описание Если не указан, то файл может быть открыт любое число раз для чтения/записи только данным процессом. Другие процессы не име- ют доступа к файлу, пока он открыт; Любые процессы на любой машине могут иметь доступ для чтения/записи данного файла; Другие процессы не имеют возможности чи- тать; этот файл. Эта блокировка возможна, ес- ли другие процессы ранее не блокировали до- ступ для чтения к этому файлу; Другие процессы не имеют возможности пи- сать в этот файл. Эта блокировка возможна, если другие процессы ранее не блокировали доступ для записи к этому файлу; Другие процессы не имеют возможности чи- тать и писать этот файл. Эта блокировка воз- можна, если другие процессы не блокировали ранее доступ для записи и/или для чтения к этому файлу. Когда OPEN встречает блокированный файл, он выдает ошибку "Permission denied" (Доступ запрещен). Значение длины записи не может превышать 32767 байт. Если файл открыт как двоичный, ключ LEN игнорируется. Для файлов последовательного типа длина не означает длину каждой записи, так как такие файлы могут иметь записи различной длины. Она означа- ет размер буфера — то есть сколько символов загружаются в буфер перед записью или после чтения. Чем больше буфер, тем быстрее ввод/вывод. По умолчанию размер буфера — 512 байт. Устройства, перечисленные ниже, QuickBASIC поддерживает как файлы: KYBD: CONS: SCRN: клавиатура; консоль; экран; 186
COMn: — COM порт № n; LPTn: — LPT порт № п. Система ввода/вывода позволяет вам иметь доступ к соб- ственным устройствам. Символьные устройства открываются и используются так же, как и дисковые файлы. Но символы не бу- феризуются для них, как это делается для файлов. Длина записи для устройств равна 1. BASIC посылает только символ возврата каретки (ASCII 13 — CR) после конца строки. Если устройство требует и символ перевода строки, это должен обеспечить драйвер. Ни одно из устройств прямо не поддерживает двоичный тип, за исключением принтеров (LPT1:, LPT2:). Для этого служит ключевое слово BIN: OPEN "LPT1:BIN" FOR OUTPUT AS #1 Открытие принтера по типу BIN отменяет печать символа возврата каретки (ASCII 13 — CR) в конце строки. Для типов INPUT, RANDOM и BINARY вы можете открыть тот же файл с другим номером без закрытия его. Но для типов OUTPUT или APPEND необходимо сначала закрыть открытый файл. CLOSE CLOSE — оператор ввода/вывода, закрывающий файл или устройство. CLOSE [[#]номер_файла[,[#] номер_файла]...] • номерфайла — логический номер открытого файла. Если все аргументы опущены, закрываются все файлы и уст- ройства. CLOSE очищает весь буфер для закрываемого файла или ус- тройства. Операторы CLEAR, END, RESET, RUN, и SYSTEM закрывают все файлы автоматически. RESET RESET — оператор файлового ввода/вывода, закрывающий все файлы. 187
RESET Данный оператор закрывает все открытые файлы и записы- вает данные из буферов на диск. Все файлы, находящиеся на дискете обязательно должны быть закрыты перед удалением дис- ка из дисковода. GET GET — оператор файлового ввода/вывода, читающий с диска файл в буфер прямого доступа или в переменную GET [#]номер_файла[,[номер_записи][,переменная]] • номерфайла — номер открытого оператором OPEN файла; • номерзаписи — для файлов прямого доступа — номер чита- емой записи. Для двоичных файлов — байтовая позиция в файле, откуда начинается чтение. Первая запись или байтовая позиция в файле равны 1. Если вы опустите номер записи, то будет читаться следующая запись или байт (после последних GET или PUT, или указанная последним оператором SEEK). Наибольший возможный номер равен 2Л31 - 1 или 2147483647; • переменная — переменная, получающая данные из файла. Если вы указали переменную, то CVD, CVL, CVI, CVS не требуются для преобразования полей записи в числа. Таким образом, можно не указывать оператором FIELD размещение полей в записи. Можно использовать переменную, длина ко- торой не превышает длины записи. Для двоичных файлов вы можете использовать любую пере- менную. Читается столько байт, какова длина этой переменной. Если вы используете символьную переменную переменной дли- ны, читается столько байт, сколько символов в значении пере- менной. Например, следующие два оператора читают 10 байт из файла номер 1: VarStrings$ = STRING$ A0, " ") GET #1, , VarString$ Длина записи не может быть больше 32767 байт. 188
Если вы используете GET с оператором FIELD, можно чи- тать символы из буфера операторами INPUT # или LINE INPUT # после GET. Можно использовать функцию EOF после оператора GET, чтобы посмотреть, не подошел ли указатель номера записи к концу файла. Пример. Открытие файла GULLAP.DAT для прямого доступа и вывод его содержимого на экран. TYPE TestRecord NameField AS STRING * 20 ScoreField AS SINGLE END TYPE ' Описание переменной типа запись. DIM Rec AS TestRecord I********************************************* 1 Эта часть программы создает файл прямого 1 доступа для дальнейшей демонстрации. 'Л***************************.***************** OPEN "GULLAP.DAT" FOR RANDOM AS #1 LEN = LEN(Rec) CLS RESTORE READ NameField$, ScoreField i = 0 DO WHILE UCASE$(NameField$) <> "END" i = i + 1 Rec.NameField = NameField$ Rec.ScoreField = ScoreField PUT #1, i, Rec READ NameField$, ScoreField IF NaraeField$ = "END" THEN EXIT DO LOOP CLOSE #1 DATA "Роберт", 100 DATA "Алиса", 95 DATA "Алексей", 72 DATA "Василий", 90 DATA "Григорий", 92 DATA "END", 0 ******************************** 'Демонстрация оператора GET. i******************************* DIM FileBuffer AS TestRecord OPEN "GULLAP.DAT" FOR RANDOM AS #1 LEN=LEN(FileBuffer) ' Подсчет количества записей в файле. Мах = LOF(l) \ LEN(FileBuffer) 189
' Чтение и вывод содержимого записи. FOR i = 1 ТО Мах GET #1, i, FileBuffer PRINT FileBuffer.NameField, FileBuffer.ScoreField NEXT i CLOSE #1 END Результат: Роберт Алиса Алексей Василий Григорий 100 95 72 90 92 PUT PUT — оператор файлового ввода/вывода, записывающий информацию из переменной или буфера в файл прямого доступа или двоичный файл. PUT [#]номер_файла[,[номер_записи][,переменная]] • номерфайла — номер, использованный в операторе OPEN для открытия файла прямого доступа или двоичного; • номерзаписи — для файлов прямого доступа это номер за- писи, в которую идет вывод данных. Для двоичных файлов — байтовая позиция в файле. Первая запись имеет номер 1. Ес- ли номер записи опущен, то используется следующая запись или байт после прошлого вызова GET или PUT, или указан- ная оператором SEEK. Наибольший возможный номер запи- си равен 2л31-1 или 2,147,483,647; • переменная — переменная, содержащая информацию, запи- сываемую в файл. Оператор PUT записывает столько байт в файл, сколько байт содержит переменная. Если вы используе- те переменную, то вам не нужны MKI$, MKL$, MKS$, MKD$ для преобразования типов данных и оператор FIELD. Для файлов прямого доступа можно использовать перемен- ную длиной меньше или равной длине записи. Можно опреде- 190
лить поля записи в переменной типа запись. Для двоичных фай- лов можно использовать любые переменные. Длина записи — не более 32767 байт. Можно опустить номер записи или переменную, добавив за- пятые: PUT #4, , FileBuffer Если вы опустите номер записи и переменную, то запятые не нужны: PUT #4 В этом случае в файл идет запись из буфера, определенного оператором FIELD, что возможно только для файлов прямого доступа. При использовании файлового буфера FIELD, операторы LSET, RSET, PRINT # , PRINT # USING и WRITE # могут ис- пользоваться для записи символов в буфер перед выполнением оператора PUT. При записи путем WRITE #, буфер заполняется вплоть до символа перевода каретки (ASCII 13). Любая попытка записи или чтения после конца буфера приведет к сообщению об ошибке "FIELD overflow" (FIELD переполнен). См. пример к оператору GET. INPUT # INPUT # — оператор файлового ввода/вывода, читающий данные из файла или последовательного устройства и присваи- вающий их переменным. INPUT #номер_файла,переменные • номер_файла; — это номер открытого файла; • переменные — список переменных, которым присваиваются значения, читаемые из файла. Типы данных должны соответ- ствовать друг другу. Ввод данных из файла производится так же, как ввод с кла- виатуры. Данные могут разделяться пробелами, символами воз- врата каретки, перевода строки (ASCII 13 и 10) или запятыми. Начальные пробелы игнорируются. Знак конца файла CTRL-Z (ASCII 26) завершает набор данных. 191
Если вводятся символьные строки, оператор игнорирует пробелы, а разделителями считаются запятые, символы конца строки (LF) и перевода каретки. Пример. Чтение тестовых оценок из файла последова- тельного доступа и подсчет средней оценки по группе студентов. Файл CLASS.DAT содержит оценки 97 84 63 89 100. DEFINT A-Z CLS OPEN "class.dat" FOR INPUT AS #1 DO WHILE NOT EOF(l) Count = Count + 1 INPUT #1, Score Total = Total + Score PRINT Count; Score LOOP PRINT "Всего:"; Count; " Средняя оценка:"; Total / Count END Результат: 1 97 2 84 3 63 4 89 5 100 Всего: 5 Средняя оценка: 86.6 LINE INPUT* LINE INPUT # — оператор файлового ввода/вывода, чита- ющий символьную строку без разделителей из файла последова- тельного доступа в указанную переменную. LINE INPUT #номер_файла, символьная_переменная • номер_файла — номер открытого последовательного файла; • символьная_переменная — переменная, в которую считы- ваются все символы текущей строки в файле до ее конца (до знаков ASCII 13 и 10). Пример. OPEN "LIST.DAT" FOR OUTPUT AS #1 PRINT "Информация о покупателях:" DO PRINT 192
INPUT " Фамилия: ", LName$ INPUT " Имя: ", PrName$ INPUT " Возраст: ", Age$ INPUT " Пол: ", Sex$ WRITE #1, LName$, FrName$, Age$, Sex$ INPUT "Добавить Y/N "; R$ LOOP WHILE UCASE$(R$)="Y" CLOSE #1 1 Распечатка файла. OPEN "LIST.DAT" FOR INPUT AS #1 CLS PRINT "Записи в файле:" : PRINT DO WHILE NOT EOF(l) LINE INPUT #1, REC$ PRINT REC$ LOOP Результат: Информация о покупателях: Фамилия: Тер-Иванов Имя: Роберт Возраст: 3 5 Пол: М Добавить Y/N ? у Фамилия: Иванова Имя: Лена Возраст: 27 ПОЛ: Ж Добавить Y/N ? N Записи в файле: "Тер-Иванов", "Роберт", 5", "М" "Иванова", "Лена", 7", "Ж" INPUTS INPUTS — функция файлового ввода/вывода, читающая символьные строки из указанного файла. INPUT$(n[,[#]номер_файла]) • п — числовое выражение, количество символов, читаемых из файла. Если файл открыт для прямого доступа, то аргумент п должен быть меньше или равен длине записи, установленной ключевым 193
словом LEN оператора OPEN (по умолчанию 128, если длина запи- си не установлена). Если файл открыт для двоичного или последова- тельного доступа, п должен быть меньше или равен 32767. Если номер файла не указан, то символы читаются со стандарт- ного устройства ввода. (Если ввод не переназначен, это клавиатура). Для .ЕХЕ файлов в среде DOS можно переназначить ввод путем указания в командной строке символов <, >, » или |, которые ис- пользуются для переопределения стандартного ввода и вывода. Знаки не дублируются на экран (ввод без эха). Можно обо- рвать исполнение данной функции нажатием {CTRL-BREAK}. Пример. Программа выводит файл на экран, не печатая специальные символы. Для тестирования можно взять лю- бой текстовый файл. 1 ASCII-коды для табуляции и перевода строки. CONST HTAB = 9, LFEED =10 CLS INPUT "Введите имя файла "; FileName$ OPEN FileName$ FOR INPUT AS #1 DO WHILE NOT EOF(l) 1 Ввод одного символа из файла. s$ = INPUT$A, #1) с = ASC(S$) ' Этот символ можно печатать? IF с >= 32 OR с = HTAB OR с = LFEED THEN PRINT s$; ELSE PRINT " "; END IF LOOP CLOSE: END PRINT #, PRINT # USING PRINT #, PRINT # USING — операторы файлового вво- да/вывода, записывающие данные в последовательный файл. PRINT #номер_файла, [USING формат;] спи- сок_выражений[,I;] • номер_файла — номер открытого последовательного файла; • список_выражений — содержит значения, записываемые в файл. Если он пуст, то записывается пустая строка. 194
PRINT # работает так же, как PRINT, и записывает данные в файл. Пробелы между элементами списка записываются в файл. Пример. Использование разделителей данных. CLS А$ = "ФОТОАППАРАТ АВТОМАТИЧЕСКИЙ" В$= 0 октября 1967 года" С$ = 2" : Q$ = CHR$C4) '34 - код кавычек OPEN "INVENT.DAT" FOR OUTPUT AS #1 'Запись А$, B$, C$ без разделителей. PRINT #1, А$; В$; С$ 'Запись А$, В$, С$ с разделителями. PRINT #1, Q$; A$; Q$; Q$; В$; Q$; Q$; C$; Q$ CLOSE #1 OPEN "INVENT.DAT" FOR INPUT AS #1 FOR 1% = 1 TO 2 INPUT #1, First$, Second$, Third$ PRINT First$; Second$; Third$ PRINT NEXT 1% CLOSE #1 Результат: ФОТОАППАРАТ АВТОМАТИЧЕСКИЙ30 октября 1967 года42 ФОТОАППАРАТ АВТОМАТИЧЕСКИЙ, 30 октября 1967 года, 42 WRITE WRITE # — оператор файлового ввода/вывода, посылающий данные в последовательный файл. WRITE #номер_файла[,список_выражений] • номер_файла — номер открытого оператором OPEN файла. Файл должен быть типа OUTPUT или APPEND; t • список_?ыражений — содержит одно или несколько выраже- ний, разделенных запятыми, значения которых выводятся в файл. Если список выражений опущен, выводится пустая строка. Выводимые значения разделяются запятыми. Символьные строки заключаются в кавычки. После печати последнего выра- 195
жения в списке вставляются символы ASCII 13 (CR — возврат каретки) и ASCII 10 (LF — перевод строки). WRITE # записыва- ет числовые значения без начальных и конечных пробелов. Если WRITE # попытается записать данные в последова- тельный файл, блокированный оператором LOCK, то выдается сообщение об ошибке "Permission denied" (Доступ запрещен). Пример. Иллюстрирует различия между операторами WRITE # и PRINT #. А$ = "Видеомагнитофон JVC" : В$ = "$299.00" OPEN "prices.dat" FOR OUTPUT AS #1 1 Записываем А$ и В$ оператором PRINT #. PRINT #1, А$, В$ ' Записываем А$ и В$ оператором WRITE #. WRITE #1, А$, В$ CLOSE #1 Вывод. Содержимое файла PRICES.DAT .- Видеомагнитофон JVC $299.95 "JVC Video Recorder" "$299.95" BSAVE BSAVE — оператор ввода/вывода, перемещающий содержи- мое фрагмента памяти в файл или устройство. BSAVE файл, смещение, длина • файл — символьное выражение, определяющее имя файла или устройства, куда записывается образ памяти; • смещение — стартовый адрес памяти относительно текущего сегмента, откуда берется данный фрагмент; • длина — числовое выражение от 0 до 65535 — количество байт памяти для записи. При использовании оператора BSAVE нельзя использовать устройства (SCRN: and CONS:). Пример. Рисуем розовый куб внутри белого прямоуголь- ника , затем оператором BSAVE записываем графический образ в файл MAGCUBE.GRH. 196
DIM Cubed TO 675) SCREEN 1 1 Рисуем белый прямоугольник. LINE A40, 25)-A40 + 100, 125), 3, В ' Рисуем розовый куб внутри прямоугольника. DRAW "C2 ВМ140,50 М+50,-25 М+50,25 М-50,25 М-50,-25" DRAW "М+0,50 М+50,25 М+50,-25 М+0,-50 ВМ190,75 М+0,50" ' Записываем образ в массив Cube(). GET A40, 25)-B40, 125), Cube 1 Устанавливаем сегмент памяти на массив Cube(). DEF SEG = VARSEG(CubeA)) ' Записываем файл MAGCUBE.GRH. ' 27 00 - количество байт в массиве 1 D байта на элемент - 675).- BSAVE -MAGCUBE.GRH", VARPTR(CubeA)), 27 00 1 Восстанавливаем первоначальный сегмент. DEF SEG Результат: 197
BLOAD BLOAD — оператор ввода/вывода, загружающий файл образа памяти, записанный оператором BSAVE с диска или из устрой- ства. BLOAD файл[,смещение] • файл — символьное выражение, определяющее файл или уст- ройство, на котором записан образ памяти; • смещение — место в памяти, куда загружается файл. Оператор BLOAD нельзя использовать с устройством KYBD: (клавиатура). BLOAD позволяет загружать программу или данные, записан- ные как образ фрагмента памяти. Такой файл представляет собой побайтную копию того, что находится в этот момент в памяти. Стартовый адрес для загрузки определяется как смещение относительно сегментного адреса, установленного оператором DEF SEG. Если смещение не указано, используется смещение, записанное в файле. Поэтому файл загружается по тому же адре- су, из которого он был записан. Если сегмент не определен опе- ратором DEF SEG, используется по умолчанию сегмент данных QuickBASIC. Пример. Использование BLOAD для считывания графичес- кого изображения розового куба внутри белого прямоу- гольника, записанного оператором BSAVE на диск в файл MAGCUBE.GRH. DIM Cubed TO 67 5) ' Установка режима экрана. Он должен быть таким же, ' каким был при записи в файл данного образа. SCREEN 1 ' Установка начального сегмента памяти на массив Cube(). DEF SEG = VARSEG(Cubed) ) 1 Загрузка образа из файла в массив. BLOAD "MAGCUBE.GRH", VARPTR(CubeA)) ' Восстановление первоначального сегмента памяти. DEF SEG 1 Выдача на экран содержимого массива. PUT (80, 10), Cube 198
EOF EOF — функция файлового ввода-вывода, определяющая ус- ловие конца файла. EOF(номер_файла) • номер_файла — номер открытого файла. Функция EOF возвращает -1 ("истина"), если указатель в файле последовательного доступа дошел до его конца. Эта функ- ция может использоваться для тестирования конца файла при вводе данных — для того, чтобы избежать ошибки "Input past end of file" (Ввод после конца файла). Когда EOF используется для файла прямого или двоичного доступа, то "истина" возвращается при попытке оператора GET считать запись после конца файла. EOF не может использоваться с устройствами SCRN:, KYBD:, CONS: и LPTn:. Пример. Чтение данных из файла DATA.IN в массив М, используя конструкцию DO LOOP. Цикл выполняется до тех пор, пока функция EOF не укажет на конец файла. DIM M@ ТО 2000) OPEN "DATA.IN" FOR INPUT AS 1 с = 0 DO WHILE NOT EOF(l) AND с <= 2000 INPUT #1, M(c) с = с + 1 LOOP CLS d = 0 DO WHILE d < с PRINT M(d) ; d = d + 1 LOOP Содержимое Файла DATA-IN : 10 20 30 40 50 60 70 80 90 Результат: 10 20 30 40 50 60 70 80 90 199
LOF LOF — функция файлового ввода/вывода, возвращающая длину файла в байтах. ЬОР(номерфайла) • номер_файла — номер открытого файла. При открытии файла любого типа доступа эта функция вы- дает его размер в байтах. LOF не используется для устройств SCRN:, KYBD:, CONS: и LPTn:. При обращении к устройству, открытому как файл опера- тором OPEN COM, функция LOF возвращает число свободных байт в выходном буфере. Пример: INPUT "Введите имя файла"; FileName$ OPEN FileName$ FOR BINARY AS #1 FileSize& = LOF(l) CLOSE #1 PRINT "Длина файла"; FileName$; " составляет "; FileSizek \ 1024 ; "Kb" FIELD FIELD — оператор файлового ввода/вывода, выделяющий место для переменных в буфере файла прямого доступа. FIELD [#]номер_файла, длина AS переменная [,длина AS пере- менная] . . . • номер_файла — номер открытого файла; • длина — число символов в поле данных; • переменная — переменная, которой присвоено данное поле. Общее число байт — длин полей, описанных оператором FIELD, не должно превышать длины записи, определенной при открытии файла. По умолчанию длина записи равна 128 байт. 200
Для одного файла может быть задано любое количество опе- раторов FIELD. Все описатели полей для файла уничтожаются при его зак- рытии, поэтому все символьные переменные, присвоенные по- лям, обнуляются. Не используйте переменные полей в операторе INPUT или в операторах присваивания, так как данные переменные занимают определенное место в памяти, отведенной под файловый буфер. Пример. Иллюстрация буфера файла прямого доступа: В первом операторе FIELD 62-байтовый буфер разделен между тремя переменными NameF, Addr, City Во втором операторе FIELD буфер присвоен только одной переменной Plist$. TYPE Buffer NameF AS STRING * 25 Addr AS STRING * 25 City AS STRING * 12 END TYPE DIM RecBuffer AS Buffer 1 Эта часть программы создает файл прямого 1 доступа LIST.DAT для последующей демонстрации. OPEN "LIST.DAT" FOR RANDOM AS #1 LEN = LEN(RecBuffer) CLS RESTORE READ NameF$, Addr$, City$ i = 0 DO WHILE UCASE$(NameF$) <> "END" i = i + 1 RecBuffer.NameF = NameF$ RecBuffer.Addr = Addr$ RecBuffer.City = City$ PUT #1, i, RecBuffer READ NameF$, Addr$, City$ IF NameF$ = "END" THEN EXIT DO LOOP CLOSE #1 DATA "Роберт", "ул.Ленина, д.216, кв.5", "Ленинград" DATA "Алиса", "ул.Мичурина, д.3 5 кв.4", "Владивосток" DATA "Алексей", "ул.Лавочкина, д,18", "Аклис" DATA "Антон", "ул.Дубки, д.40", "Москва" DATA "END",0,0, 201
I*************************************************** 1 Демонстрация оператора FIELD. ' Определение полей и присваивание их длин константам CONST NA = 25, AD = 25, СТ = 12 CONST RECLEN = NA + AD + СТ OPEN "LIST.DAT" FOR RANDOM AS #1 LEN = RECLEN FIELD #1, NA AS NameF$, AD AS Addr$, CT AS City$ FIELD #1, RECLEN AS Plist$ GET #1, 1 DO WHILE NOT EOF(l) Info$ = Plist$ PRINT Info$: PRINT a$ = NameF$: PRINT a$ b$ = Addr$: PRINT b$ c$ = City$: PRINT c$ PRINT GET #1 LOOP CLOSE #1 DO: LOOP WHILE INKEY$ = "" Результат: Роберт ул.Ленина, д.216, кв.5 Ленинград Роберт ул.Ленина, д.216, кв.5 Ленинград Алиса ул.Мичурина, д.35 кв.4 Владивосток Алиса ул.Мичурина, д.35 кв.4 Владивосток Алексей ул.Лавочкина, д,18 Аклис Алексей ул.Лавочкина, д,18 Аклис Антон ул.Дубки, д.40 Москва Антон ул.Дубки, д.40 Москва 202
LSET, RSET LSET, RSET — операторы файлового ввода/вывода, преобра- зующие данные из памяти в буфер файла прямого доступа (для оператора PUT), копирующие символьные переменные в пере- менные поля и выравнивающие их слева (LSET) или справа (RSET). Они копируют также одну запись в другую без сравнения типов данных. LSET I RSET переменная = выражение I переменная1 = пере- менная2 • переменная — любая символьная переменная; • выражение — символьное выражение, присваиваемое данной переменной и выравниваемое по левому (правому) краю. Символьная переменная обычно является переменной поля файла прямого доступа, описанной оператором FIELD, хотя мо- жет быть любой символьной переменной. Если символьное выражение требует меньше байт, чем опре- делено для переменной, функция LSET сдвигает его значение влево, добавляя пробелы в конец, a RIGHT — сдвигает вправо, добавляя пробелы в начало строки. Если строка длиннее, чем пе- ременная, то и LSET, и RSET отсекают лишние символы справа. Числовые значения могут быть преобразованы в строки перед присвоением их операторами LSET или RSET. Можно использовать LSET или RSET для присвоения значе- ний переменной, не определенной оператором FIELD для вы- равнивания строки влево или вправо. Например: A$=SPACE$B0) RSET A$=N$ Здесь строка N$ выравнивается вправо в 20-символьной строке А$, что удобно для форматного вывода на печать. Можно использовать LSET, RSET для присвоения значения од- ной переменной пользовательского типа (записи) — другой. Пример. Копирование содержимого переменной RecTwo в RecOne: TYPE TwoString StrFld AS STRING * 2 END TYPE 203
TYPE ThreeString StrFld AS STRING * 3 END TYPE DIM RecOne AS TwoString, RecTwo AS ThreeString LSET RecOne = RecTwo Здесь LSET использован для копирования переменных раз- личных типов. Но так как длина RecOne два байта, только два байта копируются из RecTwo. LSET копирует наименьшее коли- чество байт из двух переменных типа запись. Пример. Действия оператора RSET над строками перемен- ной и фиксированной длины. DIM TmpStr2 AS STRING * 10 CLS PRINT " 1 2 3" PRINT 2345678901234567 8901234567890" ' Используем RSET для пустой строки. ' Строка не будет печататься, т.к. она пустая. TmpStr$ = "" RSET TmpStr$ = "Первая" PRINT TmpStr$ 1 Используем RSET для строки переменной длины. TmpStr$ = SPACE$B0) RSET TmpStr$ = "Вторая" PRINT TmpStr$ 1 Используем RSET для строки фиксированной длины 10. RSET TmpStr2 = "Третья" PRINT TmpStr2 Результат: 12 3 12345678901234567 89012345 67 890 Вторая Первая FILEATTR FILEATTR — функция файлового ввода/вывода, выдающая информацию об открытом файле. FILEATTR (номер_файла, атрибут) • номерфайла — номер открытого файла; 204
атрибут — числовое выражение, имеющее значение либо 1, либо 2, определяющее вид возвращаемой информации. Если атрибут равен 1, возвращается тип файла. Если атрибут равен 2, возвращается описатель файла DOS. Возвращаемые значения при атрибуте равном 1: Значение 1 2 4 8 32 Тип INPUT OUTPUT RANDOM APPEND BINARY Пример. Открытие двух файлов и вывод описателя файла DOS и его атрибута при помощи оператора FILEATTR. OPEN "tempfll.dat" FOR APPEND AS #1 OPEN "tempfl2.dat" FOR RANDOM AS #2 PRINT "Номер Описатель Тип" PRINT 1, FILEATTRA,2) , FILEATTRA,1) PRINT 2, FILEATTRB,2), FILEATTRB,1) END Результат: Номер Описатель Тип 15 8 2 6 4 FREEFILE FREEFILE — функция файлового ввода/вывода, выдающая следующий свободный номер файла. FREEFILE Вы можете использовать эту функцию для того, чтобы про- цедуры SUB или FUNCTION не использовали занятые номера файлов. 205
Пример. INPUT "Введите имя файла: ", FileName$ Filenum = FREEFILE OPEN FileName$ FOR OUTPUT AS Filenum PRINT FileName$;" открыт как #"; Filenum CLOSE Результат: Введите имя файла: DATA.DAT DATA.DAT открыт как # 1 IOCTL IOCTL — оператор файлового ввода/вывода, передающий управляющую строку драйверу устройства. IOCTL [#]номер_файла, строка • номер_файла — номер открытого устройства; • строка — управляющая последовательность команд, посылае- мая в драйвер устройства. Длина строки не должна превы- шать 32767 байт. IOCTL работает только при выполнении трех условий: 1. Драйвер устройства установлен; 2. Драйвер устройства воспринимает команды IOCTL. См. до- кументацию драйвера. Можно протестировать драйвер на поддержку IOCTL через функцию DOS 44h прерывания 21h используя CALL INTERRUPT;' 3. Устройство открыто оператором OPEN. Большинство стандартных драйверов не воспринимают ко- манд IOCTL, хотя вы можете определить, имеет ли данный драй- вер подобный интерфейс. IOCTL$ IOCTL$ — функция файлового ввода/вывода, принимающая управляющую строку от драйвера устройства. IOCTL$ ([#]номер_файла) 1 Подробнее о вызовах прерываний DOS и BIOS см. Главу 12 "Расширение возможностей QuickBASIC 4.5" 206
• номерфайла — номер открытого устройства. Данная функция используется для проверки выполнения оператора IOCTL или для получения информации от драйвера о текущем статусе. Устройства LPT1:, СОМ1:, COM2:, SCRN:, CONS: не под- держивают IOCTL. Можно вызвать функцию IOCTL$ для опроса коммуникаци- онного устройства о его скорости обмена, информации о после- дней ошибке и т. д. Вид получаемой информации зависит от конкретного драйвера устройства. Все замечания для оператора IOCTL, справедливы и для функции IOCTL$. LOC LOC — функция файлового ввода/вывода, выдающая теку- щую позицию в файле. LOC (номер_файла) • номерфайла — номер открытого файла или устройства. Для файлов прямого доступа, LOC возвращает номер после- дней записи, к которой было обращение чтения/записи. Для файлов последовательного доступа, LOC возвращает текущую байтовую позицию, деленную на 128. Для двоичных файлов, LOC возвращает позицию последнего считанного или записанного байта. Для устройства COMn:, LOC возвращает число символов во входной очереди, ожидающей чтения. Значения зависит от того, открыто устройство как файл типа ASCII или двоичный. Для ти- па ASCII процедуры низкого уровня останавливают входной по- ток при получении символа EOF. Для двоичного файла EOF иг- норируется и файл может читаться дальше. LOC не используется с устройствами SCRN:, KYBD:, LPTn:. LOCK...UNLOCK LOCK...UNLOCK — операторы файлового ввода/вывода, контролирующие доступ других процессов ко всему или части открытого файла. Используются в сетевой среде, где несколько 207
процессов могут иметь доступ к одному файлу. Требуют наличия DOS 3.1 или выше. LOCK [#]номер_файла [.запись I[начало] ТО конец] [операторы] UNLOCK [#]номер_файла[,запись I[начало] ТО конец] • номерфайла — номер открытого файла; • запись — номер записи или байта, который требуется забло- кировать для других процессов (от 1 до 2147483647 — байто- вая позиция, от 1 до 32767 — запись). Длина записи может быть длиной до 32767 байт; • начало — номер начальной записи или байта; • конец — номер конечной записи или байта. Для файлов двоичного доступа аргументы запись, начало и конец представляются в виде байтовой позиции относительно начала файла. Первый байт в файле имеет номер 1. Для файлов прямого доступа эти аргументы представляются в виде номера записи относительно начала файла. Первая запись имеет номер 1. Операторы LOCK и UNLOCK всегда используются в паре. Аргументы в них также должны соответствовать. Если вы указали только одну запись, то именно она будет блокирована или деблокирована. Если вы указали несколько за- писей и опустили начало, то все записи от первой до указанного вами конца будут блокированы или деблокированы. LOCK без аргументов блокирует весь файл, a UNLOCK — деблокирует. Если файл был открыт для последовательного ввода или вы- вода, LOCK и UNLOCK блокируют или деблокируют весь файл, несмотря на указанные аргументы. LOCK и UNLOCK функцио- нируют только при наличии DOS, поддерживающей сети (версии 3.1 или выше). В добавление, каждый терминал и сервер должны запустить программу DOS SHARE.EXE для разрешения одновре- менного доступа к файлом. Будьте осторожны при деблокировании файла оператором UNLOCK перед закрытием файла или завершением Вашей про- граммы. Сбои при удалении блокировок могут привести к по- вреждению содержимого файла. При попытке обратиться к заблокированному файлу, воз- можны следующие сообщения об ошибках: 208
"Bad record number" (Неверный номер записи); "Permission denied" (Доступ невозможен). Пример. Требуется DOS 3.1 или выше. TYPE AccountRec Payer AS STRING * 15 Address AS STRING * 20 Place AS STRING * 20 Money AS SINGLE END TYPE DIM CustRec AS AccountRec OPEN "MONITOR" SHARED AS #1 LEN = LEN(CustRec) DO CLS: LOCATE 10,10 INPUT "Номер покупателя "; Number% 1 Блокирование текущей записи для других процессов. LOCK #1, Number% GET #1, Number% LOCATE 11,10: PRINT "Покупатель: ";CustRec.Payer LOCATE 12,10: PRINT "Адрес: ";CustRec.Address LOCATE 13,10: PRINT "Задолжал $: ";CustRec.Money LOCATE 15,10: INPUT "Вернул $: ";Change! CustRec.Owe = CustRec.Owe + Change! PUT #1, Number% ' Деблокирование записи. UNLOCK #1, Number% LOCATE 17,10: INPUT "Следующий Y/N "; Continue$ Update$ = UCASE$(LEFT$(Continue$,1)) LOOP WHILE Update$ = "Y" SEEK SEEK — функция файлового ввода/вывода, возвращает те- кущую позицию в файле. SEEK(номер_файла) • номер_файла — номер открытого файла любого типа доступа. Для файлов прямого доступа возвращает номер текущей за- писи. Для остальных — текущую байтовую позицию отно- сительно начала файла. Первый байт или запись равны 1. 209
SEEK возвращает значение в пределах 1 — 2,147,483,647 (эк- вивалентно 2А31 -1). Для устройства, открытого как файл, функция возвращает ноль. Устройства SCRN:, CONS:, KYBD:, COMn: и LPTn: не поддерживают SEEK. Пример. Фрагмент программы, приведенный ниже, выводит сообщение, показывающее, в какой части файла были сделаны последние запись или чтение: SELECT CASE (SEEK(l)) CASE IS < .333 * LOF(l) PRINT "Первая треть файла." CASE .333 * LOF(l) TO .6 67 * LOFA) PRINT "Вторая треть файла." CASE IS >= .667 - LOF(l) PRINT "Последняя треть файла." CASE ELSE END SELECT SEEK SEEK — оператор файлового ввода/вывода, устанав- ливающий позицию в файле для операций чтения или записи. SEEK [#]номер_файла,позиция • номерфайла — номер файла, открытого оператором OPEN; • позиция — числовое выражение, указывающее следующую позицию чтения или записи: для файлов типа RANDOM по- зиция — это номер записи, для файлов типа BINARY, INPUT, OUTPUT, или APPEND позиция - номер байта от начала файла. Позиция должна быть в пределах 1-2147483647 (эквивалент- но 231 - 1). Номер записи, указанный в операторах GET или PUT, ста- новится текущей позицией в файле. Выполнение SEEK с отрицательным или нулевым значением позиции производит ошибку "Bad record number" (Неверный но- мер записи). При выполнении над устройством, не поддерживающим SEEK, действие оператора игнорируется и позиция не изменяется. Пример. Использования функции и оператора SEEK. 210
CONST FALSE=0, TRUE=NOT FALSE TYPE TestRecord NameField AS STRING * 20 ScoreField AS SINGLE END TYPE DIM RecordVar AS TestRecord 1 Эта часть программы создает файл прямого 1 доступа для последующей демонстрации. ¦ *************************************************** OPEN "GULLAP.DAT" FOR RANDOM AS #1 LEN = LEN(Rec) CLS RESTORE READ NameField$, ScoreField i = 0 DO WHILE UCASE$(NameField$) <> "END" i = i + 1 RecordVar.NameField = NameField$ RecordVar.ScoreField = ScoreField PUT #1, i, RecordVar READ NameField$, ScoreField IF NameField$ = "END" THEN EXIT DO LOOP CLOSE #1 DATA "Роберт", 100 DATA "Алиса" 95 DATA "Алексей", 72 DATA "Василий", 90 DATA "Георгий", 92 DATA "END", 0 i**************************************************** ' Демонстрация функции SEEK и оператора SEEK, i**************************************************** DIM FileBuffer AS TestRecord OPEN "GULLAP.DAT" FOR RANDOM AS #1 LEN=LEN(FileBuffer) 1 Подсчитываем количество записей в файле. Мах = LOF(l) / LEN(FileBuffer) ' Читаем и проверяем содержимое записи. FOR I = 1 ТО Мах GET #1, I, FileBuffer IF FileBuffer.NameField = "Alex" THEN ReWriteFlag = TRUE EXIT FOR END IF NEXT I 211
IF ReWriteFlag = TRUE THEN 1 Установим указатель на начало данной записи, 1 т.к. сейчас он находится на начале следующей. FileBuffer.ScoreField = 50 SEEK #1, SEEK(l) * LEN(RecordVar) PUT #1 , , RecordVar END IF CLOSE #1 END Принтер LPOS LPOS — функция ввода/вывода, возвращающая текущую по- зицию печатающей головки принтера в буфере принтера. LPOS(n) • п — числовое выражение от 0 до 3, указатель порта принтера. 0 или 1 означает LPT1:, 2 означает LPT2:, и т. д. Текущая позиция, возвращаемая функцией LPOS может не совпадать с физическим положением печатающей головки, так как принтеры могут не воспринимать знаков табуляции и иметь буфер для печати. LPRINT, LPRINT USING LPRINT, LPRINT USING — операторы ввода/вывода, печа- тающие данные на принтер LPT1. LPRINT [список_выражений][;I,] LPRINT USING формат; список_выражений[;I,] • список_выражений — одно или более выражений, разделен- ных ";" или ",". • формат — в операторе LPRINT USING — символьная пере- менная или константа, содержащая специальные форма- тирующие символы и другие знаки. 212
Если все аргументы опущены, то на принтер выводится пус- тая строка. Эти операторы работают аналогично операторам PRINT и PRINT USING, но вывод данных идет на принтер и номер файла не требуется. Оператор LPRINT по умолчанию подразумевает принтер с шириной строки 80 знаков. Можно изменить ее оператором WIDTH LPRINT. При работе оператора LPRINT CHR$A3), BASIC обязатель- но выводит LPRINT CHR$A3) (возврат каретки) и LPRINT CHR$A0) (перевод строки). Пример. Изменение ширины печати для оператора LPRINT 'Ширина печати установлена в 132 символа WIDTH LPRINT 132 Порты INP INP — функция ввода/вывода, читающая байт из порта вво- да/вывода. ШР(порт) • порт — числовое выражение от 0 до 65535, определяющее порт оборудования компьютера. Операторы INP и OUT дают программе контроль над обору- дованием через порты ввода/вывода. Будьте осторожны с этими операторами, так как вы получаете доступ непосредственно к оборудованию. Пример. Проверка готовности принтера к печати IF (INP(&H379) AND 208) о 208 THEN LOCATE 1,1: PRINT "Принтер не готов к печати !" ВЕЕР ELSE LOCATE 1,1: PRINT "Принтер готов к печати !" END IF 213
OUT OUT — оператор ввода/вывода, посылающий байт в порт ввода/вывода. OUT порт, данные • порт — целое числовое выражение от 0 до 65535, определяю- щее требуемый порт ввода/вывода. • данные — целое числовое выражение от 0 до 255, данные, по- сылаемые в порт. OPEN COM OPEN COM — оператор ввода/вывода, открывающий и ини- циализирующий коммуникационный канал для связи через мо- дем или коммуникационный порт. ' OPEN "COMn: опции1 опции2" [FOR тип] AS [#]номер [ЬЕЫ=длина] • п — номер коммуникационного порта, 1 или 2 • опции 1 — имеют следующий вид: [скорость][,[проверка][,[данные][,[стоп-биты]]]] • опции2 — могут определить до 10 управляющих параметров; • номер — номер файла, присвоенный данному каналу. Опции 1 Скорость Проверка Данные Стоп-биты Описание Количество бод (бит в секунду, проходящих че- рез канал). Возможны скорости 75, ПО, 150, 300, 600, 1200, 1800, 2400 и 9600 бод. Метод проверки на четность. Значения: N (нет), Е (четность), О (нечетность), S (пусто), М (метка). Количество битов данных в байте. Возможные значения: 5, 6, 7, 8. Количество стоповых битов. Возможно 1, 1.5, 2. 214
Если вы установили 8 бит данных на байт, вы должны опре- делить проверку N. Если вы не указали одну из опций 1, то пустое место в опера- торе должно отделяться запятой: OPEN "COM1: ,,,,CD1500" FOR INPUT AS #1 Для опций2 аргумент m дается в миллисекундах. По умолча- нию m = 1000. Опции 2 ASC BIN CD[m] CS[m] DS[m] LF Описание Открывает устройство по типу ASCII. При этом симво- лы табуляции заменяются на пробелы, в конец строки ставится символ возврата каретки, а в конец файла — CTRL+Z. При закрытии канала в линию RS-232 всегда посылается CTRL+Z. Открывает устройство по двоичному типу. Эта опция ис- ключает опцию LF. BIN выбирается по умолчанию. При этом символы табуляции не заменяются на пробелы, в конец строки не добавляется символ возврата каретки, а в конец файла — символ CTRL+Z. Управляет тайм-аутом линии Data Carrier Detect (DCD — "обнаружен носитель данных")- Если DCD не получала сигнала m миллисекунд, генерируется тайма- ут устройства (задержка во времени). Управляет тайм-аутом линии Clear To Send (CTS — "очистка посылки"). Если CTS не получала сигнала m миллисекунд, генерируется тайм-аут устройства (задержка во времени). Управляет таймаутом линии Data Set Ready (DSR — "готовность набора данных"). Если DSR не получала сигнала m миллисекунд, генерируется таймаут устрой- ства (задержка во времени). Позволяет коммуникационным файлам распечатываться на принтер. Когда LF указан, символ перевода строки (OAh) автоматически добавляется к символу возврата ка- ретки (ODh). Если для чтения из такого файла исполь- зуются операторы INPUT и LINE INPUT, их ввод за- вершается при распознавании символа перевода карет- ки, игнорируя символ перевода строки. 215
OPjm] RB[n] RS TB[n] Управляет ожиданием открытия канала. Параметр m — это число от 0 до 65535, количество миллисекунд ожи- дания начала активности коммуникационных линий. Если ОР задан без параметра, оператор ожидает 10 се- кунд. Если ОР опущен, OPEN COM ожидает в 10 раз больше, чем максимальное значение таймаута опций CD и/или DS. Устанавливает размер буфера-приемника п байт. Если п опущено или опция опущена, используется текущее значение, установленное опцией /С командной строки QuickBASIC или компилятора. По умолчанию 512 байт. Максимально — 32767 байт. Suppresses detection линии Request To Send (RTS — "Запрос на посылку"). Устанавливает буфер передачи п байт. Если п опущено или опция опущена, используется текущее значение. По умолчанию — 512 байт. Опции2, разделенные запятыми, могут вводиться в список в любом порядке. Для CS[m], DS[m] и CD[m], если не получена сигнала в течение m миллисекунд, генерируется тайм-аут. Значе- ние m может быть в пределах 0-65535, по умолчанию 1000. Зна- чение CD по умолчанию 0. Если m равно 0 для опции, то опция игнорируется. Линия CTS проверяется независимо от того, есть или нет данных в буфере передачи, если указана опция CS. Ли- нии DSR и DCD проверяются на таймауты, если соответствую- щие опции (DS, CD) указаны. Аргумент тип — один из следующих: Тип OUTPUT INPUT RANDOM Описание Определяет последовательный вывод Определяет последовательный ввод Определяет прямой тип ввода/вывода Если тип опущен, то по умолчанию он устанавливается как прямой тип ввода/вывода. Оператор OPEN COM должен быть выполнен перед использованием с интерфейсом RS-232. 216
Если устройство открыто по типу RANDOM, опция LEN оп- ределяет длину буфера прямого доступа. По умолчанию длина буфера равна 128 байт. Можно использовать любые операторы прямого ввода/вывода, такие как GET и PUT для чтения/записи устройства. Оператор OPEN COM делает следующие шаги по открытию коммуникационного устройства: 1. Коммуникационные буферы размещены и прерывания включены. 2. Флаг линии Data Terminal Ready (DTR — "готовность компь- ютера") поднят. 3. Если опции ОР или DS ненулевые, оператор ожидает указанное время поднятия флага линии Data Set Ready (DSR — "готовность модема"). В случае тайм-аута процесс переходит к шагу 6. 4. Флаг линии Request To Send (RTS — "запрос на посылку") поднимается, если опция RS не указана. 5. Если опции ОР или CD ненулевые, OPEN COM ожидает указан- ное время поднятия флага линии Data Carrier Detect (DCD — "обнаружен носитель данных"). В случае таймаута процесс пере- ходит к шагу 6. Иначе, OPEN COM успешно выполнен. 6. Открытие прервано из-за тайм-аута. Процесс закрывает буфера, выключает прерывания и очищает все управляющие линии. Используйте относительно большие значения параметра оп- ции ОР по сравнению с параметрами опций CS, DS, CD. Если две программы включаются в коммуникационную связь, им обе- им требуется время для выполнения оператора СОМ. Все синтаксические ошибки оператора OPEN COM выдают сообщения вида "Bad file name" ("Плохое имя файла"). Пример: Открытие коммуникационного канала 1 (СОМ1:) по типу произвольного ввода/вывода. Установлена скорость передачи 9600 бод, без проверки на чет- ность, 8 битов данных, 1 бит стоповый. Ввод и вывод осуществляется в двоичном режиме. Канал открыт как файл номер 2. OPEN "COM1:9600, N, 8, 1, BIN" AS 2 217
Поскольку телефонная линия очень медленная1, то связь с модемом — эта одна из областей, где программирования на BASIC ничем не хуже, чем на языке ассемблера. Пример: Упрощенная схема работы с модемом: 'устанавливаем бит DTR OUT BaseAddress +4, 1 'Теперь посылаем управляющую строку для вызова и 'установления связи - этот код меняется от модема к модему DO 'получаем регистр статуса модема х = INP(BaseAddress + 2) LOOP WHILE x AND 2 о 2 'ждем, пока будет установлен бит 1 'получаем регистр статуса модема OUT BaseAddress + 4, 3 DO 'получаем регистр статуса модема х = INP(BaseAddress + 2) LOOP WHILE x AND 2 о 1 'ждем, пока будет установлен бит О 1 теперь можно начать передачу данных STICK STICK — функция ввода/вывода, возвращает х, у-координа- ты двух джойстиков. STICK(п) • п — числовое выражение в пределах 0—3, указывает возвраща- емое значение возможных координат джойстиков выдать: Аргумент 0 1 2 3 Возвращаемое значение х-координата джойстика А у-координата джойстика А х-координата джойстика В у-координата джойстика В 1 Более подробно о работе модемами, телефонными линиями и глобальными сетями вы можете прочитать в книге "Компьютер на связи!" (Григорий Зельднер и др.), выпушенной издательством "ABF" в 1996 году. 218
Координаты х и у имеют пределы 1—200. Вы должны выз- вать функцию STICK(O) перед вызовами STICK(l), STICKB), STICKC). STICK(O) не только возвращает х-координату джой- стика А, но также записывает другие координаты джойстиков. Эти записанные координаты возвращаются путем вызова STICKA)...STICKC). STRIG STRIG — функция ввода/вывода, возвращает статус указан- ного триггера джойстика. STRIG(П) • п — числовое выражение в пределах 0—7, указывает вид воз- вращаемой информации. Функция STRIG используется для проверки статуса триггера джойстика. QuickBASIC не поддерживает операторов STRIG ON и STRIG OFF. Числовое выражение п указывает джойстик и триггер, статус которого необходимо проверить: Аргу- мент 0 1 2 3 4 5 6 7 Возвращаемое значение -1, если нижняя кнопка джойстика А была нажата с прошлого вызова STRIG(O). 0, если нет -1, если нижняя кнопка джойстика А сейчас нажата. 0, если нет -1, если нижняя кнопка джойстика В была нажата с прошлого вызова STRIGB). 0, если нет -1, если нижняя кнопка джойстика В сейчас нажата. 0, если нет -1, если верхняя кнопка джойстика А была нажата с прошлого вызова STRIGD). 0, если нет -1, если верхняя кнопка джойстика А сейчас нажата. 0,если нет -1, если верхняя кнопка джойстика В была нажата с прошлого вызова STRIGF). 0, если нет -1, если верхняя кнопка джойстика В сейчас нажата. 0, если нет. 219
Можно также применить отслеживание событий джойстика оператором ON STRIG, но нельзя использовать функцию STRIG при отслеживании джойстика, т. к. это может разрушить процесс отслеживания. WAIT WAIT — управляющий оператор, приостанавливающий вы- полнение программы до получения из порта необходимых дан- ных. WAIT порт, AND-выражение[,XOR-выражение] • порт — целое выражение в пределах 0—255, адрес порта; • AND-выражение — целое выражение, комбинируемое с дан- ными, получаемыми из порта операцией AND; • XOR-выражение — целое выражение, комбинируемое с дан- ными, получаемыми из порта, операцией XOR. Оператор WAIT приостанавливает программу до тех пор, по- ка определенный битовый образ не будет получен из данного порта. Получаемые данные комбинируются операцией XOR с XOR-выражением, если оно указано. Полученный результат ком- бинируется с AND-выражением операцией AND. Если результат равен 0, BASIC читает данные из порта снова. Если результат ненулевой, выполнение программы продолжается. Если XOR-выражение опущено, подразумевается, что оно равно 0. Возможно неопределенно долгое повторение оператора WAIT, если произошел сбой порта ввода/вывода. В этом случае может помочь только перезагрузка компьютера. Пример. Иллюстрирует оператор WAIT: WAIT HandShakePort, 2 Этот оператор предписывает делать операцию AND до тех пор, пока не будет получен байт через порт HandShakePort с би- товым представлением 2 @0000010). 220
ГРАФИКА И ЗВУК Графика CLS CLS — оператор, очищающий экран дисплея. CLS [0I1I2] • если все аргументы опущены, очищаются и графический и текстовый экраны, установленные оператором VIEW или взя- тые по умолчанию; • 0 — очищает и текстовый и графический экраны; • 1 — очищает только графический экран, если он активен; • 2 — очищает только текстовый экран, исключая нижнюю строку. Пример: на графическом экране рисуются окружности. На текстовый экран выдаются сообщения. Периодически очи- щаются раздельно графический и текстовый экраны. RANDOMIZE TIMER SCREEN 1 ' Установка графического экрана вывода. VIEW E,5)-(Ю0,80) ,3,1 1 Установка текстового экрана вывода. VIEW PRINT 12 ТО 24
LOCATE 25,1 -. PRINT "Нажмите любую клавишу." Count = О DO 1 Рисуются окружности случайным образом. CIRCLE E0,40),INT(C5-4)-RND + 5),(Count MOD 4) 1 Стирание графического окна через 3 0 окружностей. IF (Count MOD 30) =0 THEN CLS 1 PRINT "Hello. 1 Стирание текстового окна через 45 сообщений. IF (Count MOD 45) =0 THEN CLS 2 Count = Count + 1 LOOP UNTIL INKEY$ <> "" He I lo He I lo Hello He I lo He I lo Hello He I lo He I He I He I He I He I He I He I lo о о, о О: о. о, Hello. Hello. Не Ilo. Hello. Hello. Hello. He No. el lo. Hello. He He He lo. He lo. ij jo el lo el lo I lo I lo He ello. He lo. lo. Ужмите любчн» клаВишч. COLOR COLOR — оператор, устанавливающий экранные цвета. COLOR [основной][,[фоновый][,рамка ]] • основной — цвет текста (в пределах 0—31, где 16—31 мерцающие); • фоновый — цвет экрана (в пределах 0—7); • рамка — цвет вокруг экрана (в пределах 0—15). 222
Номера экранных цветов 0 1 2 3 4 5 6 7 черный голубой зеленый бирюзовый красный розовый коричневый белый 8 9 10 11 12 13 14 15 серый ярко-голубой ярко-зеленый ярко-бирюзовый ярко-красный ярко-розовый желтый ярко-белый SCREEN О Описание экранных режимов Изменяет текущий основной и фоновый цвета выво- димого на экран текста и цвет рамки вокруг экрана, вы можете выбрать мерцающий вариант цвета путем добавления 16 к основному цвету. Например, мерца- ющий цвет 7 равен 7 + 16, или 23. Мерцание фоново- го цвета не поддерживается. EGA, VGA и MCGA не поддерживают цвет рамки. SCREEN 1 В данном режиме COLOR имеет особый синтаксис, который включает номер палитры. Он определяет, какой из двух наборов цветов используется. По умол- чанию, цвета для параметра палитры соответствуют цветам оператора PALETTE для EGA: COLOR , 0'Как в следующих трех операторах PALETTE 1, 2'атрибут 1 = цвет 2 (зеленый) PALETTE 2, 4'атрибут 2 = цвет 4 (красный) PALETTE 3, 6'атрибут 3 = цвет б (желтый) COLOR , 1'Как в следующих трех операторах PALETTE 1, 3'атрибут 1 = цвет 3 (бирюзовый) PALETTE 2, 5'атрибут 2 = цвет 5 (розовый) PALETTE 3, 7'атрибут 3 = цвет 7 (белый) 223
В данном режиме оператор COLOR отменяет дей- ствие предыдущих операторов PALETTE. SCREEN 2 При вызове данного оператора выдается сообщение "Illegal function call" ("Неверный вызов функции"). SCREEN 7, 8, 9, 10 В этих режимах цвет рамки не задается. Фоновый цвет определяется значением соответствующего пара- метра, тогда как основной цвет зависит от содержа- ния текущей палитры и определяется по номеру ат- рибута в данной палитре. SCREEN 11 Используйте оператор PALETTE для установки цвета в данном режиме. Оператор COLOR приведет к ошибке "Illegal function call" ("Неверный вызов фун- кции"). SCREEN 12, 13 Фоновый цвет в данных режимах отсутствует. Ис- пользуйте только основной цвет. Детали см. в описа- нии оператора SCREEN. Если основной и фоновый цвета одинаковы, выводимые символы становятся невидимыми. По умолчанию фоновый цвет — черный @) для всех конфигураций дисплейных адаптеров и всех экранных режимов. В режимах 12 и 13 вы можете установить фоновый цвет пу- тем присвоения номера цвета атрибуту 0 оператором PALETTE. Например, чтобы сделать фоновый цвет равным 8224 (светло-фи- олетовый), вы должны задать следующий оператор PALETTE: PALETTE 0, 8224 В режиме 11 вы можете определить и основной и фоновый цвета путем присвоения номера цвета атрибуту 0 оператором PALETTE. Если у вас адаптер EGA, VGA, или MCGA, оператор PA- LETTE даст вам возможность присвоить различные цвета ат- рибутам цвета в указанных пределах для основного и фоново- го цветов. 224
Пример: эффекты оператора COLOR в различных режимах экрана. SCREEN 0 ' текст COLOR 1, 2 CLS LOCATE 12,25: PRINT "Нажмите любую клавишу..." DO: LOOP WHILE INKEY$ = SCREEN 1 ' графика 320 x 200 ' фоновый = 1 (голубой) 1 основной = четная палитра (красный, зеленый, желтый) COLOR 1, 0 LINE B0, 20) - C00, 180) , 3, В LOCATE 12,7: PRINT "Нажмите любую клавишу..." DO: LOOP WHILE INKEY$ = "" 1 фоновый = 2 (зеленый) ' основной = нечетная палитра (белый, розовый, бирюзовый) COLOR 2, 1 LINE B0, 20) - C00, 180), 3, В LOCATE 12,7: PRINT "Нажмите любую клавишу..." DO: LOOP WHILE INKEY$ = "" SCREEN 0 ' текст COLOR 7, 0 CLS END PALETTE, PALETTE USING PALETTE, PALETTE USING — операторы установки цвета, изменяющие один или более цветов в палитре. Работают только с адаптерами EGA, VGA, MCGA. PALETTE [атрибут, цвет] PALETTE USING массив[(индекс)] • атрибут — атрибут палитры, который нужно изменить @—15); • цвет — цвет, присваиваемый атрибуту. Должен быть длинным целым выражением для VGA и MCGA в режимах экрана 11— 13. Целое или длинное целое выражение используется с EGA; • массив — массив, содержащий номера цветов, присваиваемых атрибутам текущего режима экрана. Адаптеры VGA и MCGA требуют длинного целого массива в режимах 11—13. EGA тре- бует целый или длинный целый массив; • индекс — индекс начального элемента массива, используемый для установки палитры. 225
Оператор предоставляет возможность изменять дисплейные цвета (двоичные значения, используемые адаптером), присвоен- ные атрибутам цвета. Все операторы BASIC, такие как CIRCLE, COLOR, DRAW, LINE используют атрибуты цвета, а не действи- тельные значения экранных цветов. Когда в программе задается режим экрана, атрибуты уста- навливаются по умолчанию. (См. оператор SCREEN, где указан список цветов по умолчанию). В адаптерах EGA, VGA и MCGA эти цвета по умолчанию могут быть выбраны из нескольких воз- можных, так как адаптер может генерировать гораздо больше цветов, чем количество атрибутов. Этим атрибутам можно присвоить различные цвета этим атри- бутам, получая доступ к управлению цветами экрана. PALETTE без аргументов восстанавливает палитру в исходное состояние. При выполнении оператора PALETTE с аргументами адаптер устанавливает дисплейный цвет, заданный оператором, вместо атрибута, используемого по умолчанию. Изменение параметра атрибута немедленно приведет к изменению цвета текущей кар- тинки на экране. Например, текущая палитра содержит цвета 0, 1, 2 и 3 в че- тырех атрибутах номер 0, 1, 2 и 3. Оператор DRAW "C3L100" выбирает атрибут 3 и рисует линию из 100 точек атрибутом 3, ко- торый содержит цвет 3. Если выполнить оператор PALETTE 3,2 то значение цвета атрибута 3 станет равным 2. Весь текст или графика, находящиеся на экране, поменяют цвет атрибута 3 на значение 2. Новая палитра содержит цвета 0, 1, 2 и 2. Используя опцию USING, можно изменить всю палитру одним оператором PALETTE. Аргумент массив представляет собой целый или длинный целый массив, а аргумент индекс указывает первый элемент массива, используемый для установки палитры. Каждый ат- рибут в палитре получает соответствующий цвет из массива, начиная с элемента, указанного индексом. Массив должен быть достаточного размера, чтобы в него вошли значения всех атрибутов палитры. На- пример, если присваиваются цвета всем 16 атрибутам и индекс равен 5, массив должен иметь размерность не менее 20 элементов (интервал 5-20 состоит из 16 элементов): 226
DIM PAL%B0) PALETTE USING PAL%E) Аргумент массива -1 оставляет атрибут без изменения. Все другие отрицательные значения ошибочны. VGA использует особый способ формирования значения цвета. Для вычисления цвета выберите интенсивность красной, зеленой и синей составляющих. Интенсивность — это число от 0 (низкая) до 63 (высокая). Формула вычисления номера цвета: цвет = 6553 6 * синий + 256 * зеленый + красный Так как существуют пустые промежутки в интервале возмож- ных цветов, используйте эту формулу перед установкой цвета. Для аналогового монохромного монитора IBM цвета VGA преобразуются в оттенки серого по следующей формуле, исполь- зующей весовые части составляющих: оттенок = 11% синий + 59% зеленый + 3 0% красный Например, если интенсивности соответственно равны 45, 20 и 20, оттенок серого будет равен: .11 * 45 + .59 * 20 + .30 * 20 или 22. PCOPY PCOPY — оператор экранного вывода, копирующий одну экранную страницу в другую. PCOPY источник, приемник • источник — целое числовое выражение от 0 до п, указывающее на сегмент видеопамяти, содержащий экранную страницу. Значе- ние п зависит от размера видеопамяти и режима экрана; • приемник — целое числовое выражение от 0 до п, указываю- щее на сегмент видеопамяти, куда помещается копия. Количество экранных страниц зависит от текущего режима экрана и типа дисплея. 227
SCREEN (функция) SCREEN — графическая функция, читающая ASCII-код символа или его цвет в указанном месте экрана. SCREEN (строка, столбец[,флаг_цвета]) • строка — номер строки экрана, целое выражение без знака; • столбец — номер столбца экрана, целое выражение без знака; • флаг_цвета — целое числовое выражение. Если флагцвета не равен нулю, SCREEN возвращает значение цвета. Если он ра- вен нулю или отсутствует, возвращается ASCII-код символа, находящегося в указанном месте; Если символ в позиции A0,10) — А, то в следующем приме- ре функция выдает 65, ASCII-код латинской буквы А. X = SCREENA0,10) Значение цвета в текстовом режиме экрана кодируется сле- дующим образом: основной + фоновый * 16. SCREEN (оператор) SCREEN — графический оператор, устанавливающий спе- цификацию экрана. SCREEN [режим] [,[цвет]][,[стр_вывода]][,[стр_экрана]] • режим — целое выражение, указывающее режим экрана; • цвет — определяет, будет ли информация выдаваться в цвете. Числовое выражение в пределах 0—255: • если цвет не равен нулю, информация выдается только черно-белом виде; • если цвет равен нулю, цвет сохраняется; • значение аргумента цвет инвертируется в режиме 0; • в режимах 2 и выше аргумент игнорируется. 228
• стр_вывода — числовое выражение, номер активной экранной страницы, на которую выводится текст или графика; • стр_экрана — числовое выражение, номер текущей экранной страницы. VIEW PRINT VIEW PRINT — оператор ввода/вывода, устанавливающий границы текстового окна вывода VIEW PRINT [верх ТО низ] • выполнение без аргументов определяет весь экран как окно выво- да; • верх — числовое выражение, первая строка текстового вывода; • низ — последняя линия текстового вывода. Число строк на экране зависит от режима экрана и наличия ключа /Н при запуске среды QB. Для информации о размерах экрана см. оператор WIDTH. Операторы и функции ввода/вывода оперируют с определен- ным окном вывода, включая операторы CLS, LOCATE, PRINT и функцию SCREEN. См. пример к оператору CLS. VIEW VIEW — графический оператор, определяющий границы виртуального экрана графического вывода. VIEW [[SCREEN] (xl,yl)-(х2, у2) [,[цвет][,рамка]]] • SCREEN — опция SCREEN определяет, что координаты х и у любой выводимой точки имеют абсолютные значения, а не относительные по отношению к границам виртуального окна. Графика выводится только внутри окна. Если SCREEN опу- щен, все точки выводятся с координатами, относительными границ окна (xl и yl добавляются к значениям координат пе- ред выводом); • (xl,yl)-(x2, у2) — определяет прямоугольную область на экра- не — виртуальное окно. Координаты xl, yl, х2, у2 являются 229
числовыми значениями верхнего левого и нижнего правого углов прямоугольника; • цвет — атрибут цвета указывает, каким цветом будет закраше- но окно. Если цвет опущен, окно не закрашивается; • рамка — любое числовое выражение рисует рамку вокруг ок- на, если есть место на экране. Если аргумент опущен, рамка не рисуется. Оператор VIEW определяет "окно вывода", или прямоуголь- ную площадь на экране, куда будет выводиться графика. Все ко- ординаты — аргументы этого оператора должны находиться в пределах экрана. Если VIEW выполняется без аргументов, окном вывода будет весь экран. Операторы RUN и SCREEN также определяют весь экран для вывода и отменяют действие оператора VIEW. См. пример к оператору CLS. WINDOW WINDOW — графический оператор, определяющий размеры текущего окна вывода. WINDOW [[SCREEN] (xl,yl) - (х2, у2)] • если все аргументы опущены, окно вывода займет весь экран; • (xl,yl) - (х2, у2) — числа обычной точности, определяющие координаты прямоугольного окна вывода. Оператор WINDOW позволяет создать координатную систему для рисования линий, графиков или других объектов без задания аб- солютных координат на экране. Таким образом, координаты всех точек определяются как относительные к данному окну вывода. Все последующие графические операторы используют новые координаты, и их вывод идет в данное окно. Размер окна вывода может быть изменен оператором VIEW. Операторы RUN или WINDOW без аргументов отменяют окно вывода. Вариант WINDOW SCREEN преобразует направле- ние координаты у в декартово представление, т. е. значения у идут от большего к меньшему сверху вниз. Следует учесть, что применение оператора WINDOW при- мерно в 2 раза снижает скорость вывода графики на экран. 230
CIRCLE CIRCLE — графический оператор, рисующий эллипс или окружность с определенным центром и радиусом. CIRCLE [STEP] (х,у),радиус[,[цвет][,[начало][,[конец][,коэф-т]]]] • (х,у) — экранные координаты центра окружности или эллипса; • радиус — радиус круга или эллипса в текущей координатной системе; • STEP — указывает, что х,у — относительный центр от текущей позиции курсора; • начало, конец — используются для рисования дуг. Их значе- ния находятся в пределах от -2 * PI до 2 * PI радиан, где PI = 3.141593. По умолчанию начало = 0, конец = 2 * PI. Если на- чало и конец < О, CIRCLE рисует радиус до этой точки дуги и считает начало и конец > 0. Начальный угол должен быть меньше конечного. Если вы указали конец без начала, дуга рисуется от 2 * PI до конца. Если вы указали начало без кон- ца, дуга рисуется от начала до нуля; • цвет — атрибут цвета. По умолчанию — основной цвет; • коэф-т — коэффициент сжатия — отношение радиуса "у" к радиусу "х". По умолчанию этот коэффициент принимается для рисования окружности. Отношение вычисляется следую- щим образом: 4 * (у-координаты точки/ х-координаты точки)/3 Здесь х-координаты точки и у-координаты точки определяют- ся разрешением экрана. Например, если режим экрана 1 C20 х 200), то коэффициент сжатия будет равен: 4 * B00/320)/3 или 5/6 Если коэффициент сжатия < 1, радиус будет — "х", если ко- эффициент > 1, радиус будет — "у". 231
Для того, чтобы нарисовать радиуса с углом 0 (горизонталь- ный вектор), не задавайте угол как -0; используйте очень малое отрицательное значение: ' Рисуется четверть круга: SCREEN 2 CIRCLE B00, 100), 60, , -.0001, -1.57 Вы можете опустить аргументы в середине оператора, но обяза- тельно включите запятые. В следующем операторе цвет опущен: CIRCLE STEPA50, 200), 94, , 0, 6.28 При опускании последних аргументов, можно не ставить за- пятые. Последняя точка после завершения CIRCLE — центр ок- ружности. Координаты вне центра окружности могут быть вне пределов экрана. Пример: Нарисовать фигуру, показанную на рисунке. CONST PI = 3.141593 SCREEN 2 1 Нарисовать круг без верхнего левого сегмента. CIRCLE C20,100), 200,, -PI, -PI/2 232
' Нарисовать круг внутри этого сегмента. CIRCLE STEP (-100,-42),100 ' Нарисовать маленький эллипс внутри круга. CIRCLE STEP@,0), 100,,,, 5/25 LOCATE 25,1 : PRINT "Нажмите любую клавишу. DO: LOOP WHILE INKEY$ ="" LINE LINE — графический оператор, рисующий линию или пря- моугольник. LINE [[STEP] (xl,yl)]-[STEP] (x2, у2) [,[цвет][,[B[F]][.стиль]]] • (xl,yl) — координаты начала линии; • (х2, у2) — координаты конца линии; • STEP — указывает на относительные координаты, то есть ко- ординаты вычисляются как смещения относительно последней точки. Последнюю точку можно указать очисткой экрана операто- рами CLS и SCREEN (центр экрана), а также операторами PSET, PRESET, CIRCLE и DRAW. Варианты рисования с аргументом STEP рассмотрены ниже. Последней точкой является A0,10): Оператор LINE -E0,50) LINE -STEPE0,50) LINE B5,25)-STEPE0,50) LINE STEPB5,25)-STEPE0,50) LINE STEPB5,25)-E0,50) Объяснение Рисует от A0,10) до E0,50) Рисует от A0,10) до F0,60), т. к. 10 + 50 = 60 Рисует от B5,25) до G5,75), т.к. 25 + 50 = 75 Рисует от C5,35) до (85,85), т. к. 10 + 25 = 35 и 35 + 50 = 85 Рисует от C5,35) до E0,50), т. к. 10 + 25 = 35 233
• цвет — номер цвета линии. Если заданы опции В или BF, прямоугольник рисуется этим цветом; • В — опция, рисующая прямоугольник с координатами верхне- го левого угла (xl,yl) и нижнего правого угла (х2, у2); • BF — опция, рисующая закрашенный указанным цветом пря- моугольник; •- стиль — 16-битовая маска, задающая тип линии. Оператор LINE читает биты маски слева направо. Если бит = 0, точка не рисуется, если бит = 1, рисуется точка данного цвета. Так как бит 0 в стиле не меняет точки на экране, можно на- рисовать фоновую линию. Стиль не влияет на закрашенные пря- моугольники. Если указанные координаты выходят за текущий экран вы- вода, "лишняя" линяя обрезается у границы экрана вывода. Пример: Построение узора при помощи оператора LINE 1 все переменные целые DEFINT A-Z 'графический режим 640x350x16 цветов SCREEN 9 FOR i = 1 ТО 600 FOR j = 1 ТО 15 COLOR j LINE G1 * j, 25)-(i * 50, 725) NEXT j NEXT i FOR i = 600 TO 1 STEP -1 FOR j = 1 TO 15 COLOR j LINE G1 * j, 25)-(i * 50, 725) NEXT j NEXT i DO: LOOP WHILE INKEY$ = "" 234
PRESET PRESET — графический оператор, рисующий точку на экране. PRESET [STEP](x,y)[,цвет] • (х,у) — координаты точки; • STEP — указывает, что координаты берутся как смещение от- носительно текущего положения графического курсора; • цвет — атрибут цвета точки. Если опущен, используется фоно- вый цвет. PRESET работает так же, как PSET, но, если цвет не указан, то используется фоновый цвет. Если координаты точки находятся вне экрана, то никаких действий не производится и сообщений об ошибке не выдается. PSET PSET — графический оператор, рисующий точку на экране. PSET [STEP](x,y) [,цвет] 235
• (х,у) — координаты точки на экране; • STEP — указывает, что координаты берутся как смещение от- носительно текущего положения графического курсора; • если цвет опущен, используется текущий основной цвет. PSET работает так же, как PRESET, но, если цвет не указан, то используется основной цвет. Если координаты точки находятся вне экрана, то никаких действий не производится и сообщений об ошибке не выдается. Пример: оператор PSET рисует линию из 20 точек, а опера- тор PRESET стирает ее. В целом получается движение отрез- ка. SCREEN I: COLOR 1,1: CLS FOR I = 0 TO 299 STEP 3 FOR J = I TO 20 + I PSET (J, 50), 2 NEXT J FOR J = I TO 20 + I PRESET (J, 50) NEXT J NEXT I DRAW DRAW — графический оператор, интерпретирующий сим- вольное выражение и рисующий графический объект. DRAW символьное_выражение • символьное_выражение — одна или более команд рисования. Оператор DRAW объединяет многие возможности других графических операторов в своем макроязыке. Команды макро- языка описывают действия, необходимые для создания образов: движение точки, углы поворота, цвет, масштаб. Команды движения относительно текущей точки: • В — двигаться, но не рисовать; • N — двигаться, рисовать, вернуться в исходную точку 236
Эти команды определяют движение в относительных единицах. По умолчанию — на одну точку. Единица движения модифицирует- ся командой S, которая устанавливает масштаб. Каждая команда движения задает перемещение относительно текущей графической позиции. До выполнения какой-либо команды — это центр экрана. Ко- манда U[n] D[n] L[n] R[n] E[n] F[n] G[n] H[n] M x,y Описание Вверх на п Вниз на п Влево на п Вправо на п Диагонально вверх и вправо на п Диагонально вниз и вправо на п Диагонально вниз и влево на п Диагонально вверх и влево на п Двигаться абсолютно или относительно. Если х или у имеют знак (+ или -), движение осуществляется относи- тельно текущей точки, т. е. значения х и у будут прибав- лены к значениям соответствующих текущих координат. ' Если знаков нет, то движение абсолютное, т. е. из теку- щей точки в точку с данными координатами. Команды установки угла, цвета и масштаба Ко- манды An ТАп Описание Установка угла поворота п. Значение п находится в преде- лах от 0 до 3, где 0 = 0°, 1 = 90°, 2 = 180° и 3 = 270°. Раз- меры фигур, повернутых на угол 90° или 270° масштаби- руются в отношении 4/3 к их размерам в углах 0° или 180° Поворачивает изображение на угол в п градусов. Зна- чение п находится в пределах от -360 до 360. Если п > 0, то поворот производится против часовой стрелки, иначе — по часовой стрелке 237
Cn ¦ Sn P n, m Установка цвета п Установка масштабного фактора п, где п находится в пределах от 1 до 255. Масштабный фактор увеличива- ет единицы перемещения команд U, D ,L ,R и отно- сительной М Установка цвета нарисованной фигуры: п — цвет со- держимого ограниченной области, m — цвет границ Вызов подкоманды: "X" + VARPTR$(символьное_выражение) Выполнить подкоманду, заданную в символьном выражении. Пример: Использования оператора DRAW для рисования бирюзового треугольника с розовыми ребрами. SCREEN 1 DRAW "C2" DRAW "F60 L120 Е60" DRAW "BD3 0" DRAW "PI,2" Результат: ' Установить розовый цвет. 1 Нарисовать треугольник. 1 Переместиться внутрь фигуры. 1 Закрасить бирюзовым цветом. PAINT PAINT — графический оператор, закрашивающий ограни- ченную площадь указанным цветом или образом. 238
PAINT [STEP] (x,у)[,[краска] [,[цвет рамки] [,фон]]] • STEP — Определяет координаты как относительные к после- дней нарисованной точке. Например, если последняя точка была A0,10), то координаты с шагом STEP D,5) будут равны D+10,5+10) или A4,15); • (х,у) — координаты, где начинается закраска. Точка может быть указана внутри фигуры или вне, но не на границе. Если точка внутри, то закрашивается внутренняя часть фигуры. Ес- ли точка вне фигуры, то закрашивается фон; • краска — числовое или символьное выражение. Если это чис- ловое выражение, оно представляет атрибут цвета. Если аргу- мент не указан, используется атрибут фона. Если аргумент яв- ляется символьным выражением, то PAINT закрашивает фигу- ру образом (указанной в этом выражении битовой маской); • цвет рамки — числовое выражение, определяющее атрибут цвета границы фигуры. Если цвет границы указан, то площадь ограничивается линиями данного цвета. Если аргумент опу- щен, используется аргумент "краска"; • фон — символьное значение "вырезка стиля фона" для про- пуска проверки завершения окраски на границах области. Ок- раска завершается, когда встречаются точки цвета краски. Указание фона позволяет окрашивать поверх закрашенной площади. Если фон опущен, то его значение равно CHR$ @) Окраска завершается, когда не осталось ни одной точки в данной области, которая не сменила цвет. Оператор допускает точки границ области за пределами экрана. Образ для оператора PAINT имеет 8 бит в ширину и до 64 битов в длину. В строке образа каждые 8 бит байта составляют маску вдоль оси х, указывающую на установку точек. Синтаксис конструкции: PAINT (x,y), CHR$(aprl) + CHR$(apr2) +...+ CHR$(aprN) Аргументы CHR$ — числа от 0 до 255, представляющие двоич- ные маски образа вдоль оси х. Всего может быть до 64 элементов, каждый из которых генерирует часть образа. Например, 85 в двоич- ном виде представляет 01010101; графический образ на черно-белом экране, генерируемый CHR$(85) — восьмиточечная линия, в кото- рой четные точки белые, а нечетные — черные. Таким образом, каждый бит 1 рисует соответствующую точку, а бит 0 — стирает ее. 239
Если указан параметр фон, он определяет "вырезку стиля фона" для пропуска границ при завершении окраски. Нельзя указать более чем два совпадающих байта в строке образа и в строке вырезки стиля фона. Указание более чем двух совпадаю- щих байт вызывает сообщение об ошибке "Illegal function call" (Неверный вызов функции). Вырезка стиля фона позволяет использовать различные от- тенки. Пример: рисунок розовой рыбки с бирюзовым хвостом. CONST PI = 3.1415926536 CLS SCREEN 1 CIRCLE A90, 100), 100, 1, , , .3 ' Тело. CIRCLE B65, 92), 5, 1, , , .7 ' Глаз. PAINT A90, 100), 2, 1 ' Окраска тела. LINE D0, 120)-STEP @, -40), 2 ' Хвост. LINE -STEP F0, 20) , 2 LINE -STEP (-60, 20) , 2 PAINT E0, 100), 1, 2 ' Окраска хвоста. CIRCLE B50,100),30, 0, PI-3/4, PI- 5/4,1.5 Жабры. FOR Y = 90 TO 110 STEP 4 LINE D0, Y)-E2, Y), 0' Оперение хвоста. NEXT Вывод: 240
GET GET — графический оператор, считывающий графическое изображение с экрана в массив. GET [STEP](xl,yl)-[STEP](x2, у 2).массив[(индексы)] • xl, yl, х2 ,у2 — координаты, отмечающие прямоугольную об- ласть на экране. Координаты левого верхнего и правого ниж- него углов прямоугольника; • STEP — параметр, указывающий, что координаты берутся от- носительно последней нарисованной точки; • массив — имя массива, для записи изображения. Массив мо- жет быть любого числового типа. Его размер должен вместить изображение; • индексы — числовые константы или переменные, указываю- щие, где начинается запись изображения в массив. GET считывает изображение с экрана в массив, PUT транс- формирует изображение из массива на экран. Размер массива в байтах вычисляется по формуле: 4 + ШТ(((х2 - xl + 1) * (бит_на_пиксел_в_слое) + 7)/8) • слои * ((у2 - yl) + 1) Число бит на точку в слое и число слоев зависят от специ- фикаций оператора SCREEN. Таблица иллюстрирует эти значе- ния для каждого режима экрана: Режим экрана 1 2 7 8 9 10 11 12 13 Битов на точку в одном слое 2 1 1 1 1 1 1 1 8 Количество слоев 1 1 4 4 4 2 1 4 1 241
Количество байт на элемент в числовых массивах: 2 — целый; 4 — длинный целый; 4 — обычной точности; 8 — двойной точности. Например, вы хотите разместить изображение среднего раз- решения (SCREEN 2). Координаты картинки: @,0)-C2,32). Тре- буемый размер массива в байтах равен: 4 + INT(C3 * 1 + 7) /8) * 1 * C3) или 169 байт. Это значит, что целый массив из 85 элементов, назовем его А% А%(85) = 85 * 2 = 170 байт вместит всю картинку. См. пример к оператору PUT. Операторы GET и PUT могут использоваться для мульти- пликации и анимации изображений, однако лучше всего для этих целей использовать специализированные библиотеки для QuickBASIC, такие как PCX Programmer's ToolKit или VEGX for QuickBASIC programmers. Речь о них пойдет дальше, в разделе "Библиотеки для работы с изображениями". PUT PUT — графический оператор, рисующий на экране изобра- жение, взятое в массив оператором GET. PUT [STEP](х, у),массив[(индексы)][,действие] • (х,у) — координаты верхнего левого угла прямоугольника, в котором будет размещаться изображение; • STEP — указывает, что координаты берутся как смещение от- носительно текущего положения графического курсора; • массив — имя массива с изображением; • индексы — начальные "координаты" массива с изображением. По умолчанию — начало массива; 242
действие — параметр, позволяющий накладывать образ на эк- ран со специальными эффектами (XOR по умолчанию): Действие PSET PRESET AND OR XOR Описание Переводит данные точка-за-точкой на экран. Каж- дая точка имеет тот же цветовой атрибут, который был при считывании массива оператором GET Так же, как и PSET, но выдается инверсное изобра- жение, ("негатив") Изображение накладывается на существующую кар- тинку. Получается результат логического умноже- ния: точки, имеющие одинаковый цвет, сохраняют- ся, а остальные меняют цвет Используется так же. Получается результат логичес- кого "или" между образом и картинкой. Новое изображение не стирает предыдущего Используется для анимации. Действует так, что точки на экране, имеющие тот же цвет, что и образ, инверти- руются. Когда образ помещается на одно и то же место дважды, предыдущая картинка восстанавливается. Это позволяет двигать образ по экрану, не стирая фона Пример: прыгающий мячик. DEFINT A-Z DIM Ball(84) ' Массив, содержащий картинку. SCREEN 2 INPUT "Нажмите ENTER, чтобы начать", Test$ CLS CIRCLE A6, 16), 14 PAINT A6, 16), 1 GET @, 0)-C2, 32), Ball X = 0 : Y = 0 Xdelta = 2 : Ydelta = 1 Рисуем мячик. DO Мячик прыгает, пока не нажата клавиша. X = X + Xdelta : Y = Y + Ydelta IF INKEY$ <> "" THEN EXIT DO 1 Отражение мячика от левой и правой границ. IF (X < 1 OR X > 600) THEN Xdelta = -Xdelta BEEP END IF 243
' Отражение мячика от верхней и нижней границ. IF (Y < 1 OR Y > 160) THEN Ydelta = -Ydelta BEEP END IF ' Перерисовываем мячик, стирая старый. PUT (X, Y), Ball, PSET LOOP END Результат: POINT POINT — графическая функция, читающая номер цвета точ- ки экрана или возвращающая координаты точки. POINT (x,y) POINT (номер) • (х,у) — координаты графической точки, цвет которой требует- ся узнать; • номер — числовое выражение от 0 до 3, указывающее один из четырех способов определения текущей позиции графического курсора. 244
При вызове функции с двумя координатами х,у можно уз- нать цвет данной точки. Если указанная точка не находится на экране, POINT возвращает -1. POINT с одним аргументом позволяет определить координа- ты графического курсора. Аргу- мент 0 1 2 3 Возвращаемое значение Физическая х-координата Физическая у-координата Относительная х-координата. Если не использовался оператор WINDOW, возвращается то же значение, что и с аргументом 0 Относительная у-координата. Если не использовался оператор WINDOW, возвращается то же значение, что и с аргументом 1 Пример: перерисовка эллипса с заданным углом наклона DEFINT X, Y SCREEN 1 INPUT "Введите угол в градусах @-90): ", Ang Ang = C.1415926* / 180) * Ang ' В радианы. Cs = COS(Ang) : Sn = SIN(Ang) CIRCLE D5, 70), 50, 2, , , 21 Рисунок эллипса. PAINT D5, 70), 2 ' Окраска эллипса. FOR У = 20 TO 120 FOR X = 20 TO 70 ' Проверка каждой точки в районе эллипса. IF POINT(X, Y) о 0 THEN 1 Если точка принадлежит эллипсу, рисуем ' соответствующую точку в "отраженном" эллипсе. Xnew = (X * Cs - Y * Sn) + 200 Ynew = (X * Sn + Y * Cs) PSET(Xnew, Ynew), 2 END IF NEXT X NEXT Y END 245
Вывод: Введите угол В градусах (О - 90>: 75 Press any key to continue PMAP PMAP — графическая функция, преобразующая относитель- ные координаты окна графического вывода в физические и об- ратно. РМАР (выражение, функция) • выражение — преобразуемые координаты точки; • функция — числовое выражение, имеющее целое значение от О до 3, указывающее вид возвращаемой информации. Зна- чение 0 1 2 3 Описание Преобразует выражение к физической х-координате Преобразует выражение к физической у-координате Преобразует выражение к относительной х-координате Преобразует выражение к относительной у-координате 246
Пример: SCREEN 2 1 Определение окна вывода. WINDOW SCREEN (80,100) - B00,200) 1 Определение физических координат ' правого нижнего угла окна вывода. X = РМАРB00,0) 'X = 63 9 Y = РМАРB00,1) 'Y = 199 ' Определение относительных координат ' точки с физическими координатами 639,199. X = РМАРF39,2) 'X = 200 Y = РМАРA99,3) "Y = 200 3-х мерные объекты в текстовом режиме Всеобщая одержимость графическими оболочкам, такими как Windows и им подобные, охватило кажется всех, или почти всех1. Однако за все приходится платить, и использование графического режима приводит к резкому снижению быстродействия2. Действительно в текстовом режиме (80 х 25) необходимо ма- нипулировать всего 2000 знакоместами на экране, в то время как в графическом режиме высокого разрешения F40 х 480) — при- ходится оперировать 307200 элементами изображения, и это еще без учета цвета. Но для большинства приложений вполне доста- точно текстового режима экрана. Используя приведенные ниже примеры, вы сможете придать своей текстовой программе эффект "объемности", не используя медлительный графический режим. Объемные кнопки При создании эффекта "объемных" кнопок применяется следующий прием. Выводится кнопка белым цветом (цвет № 7) с тенью из символов "и" и '1". При нажатии на нее кнопка стано- вится ярко-белого цвета (цвет № 15), сдвигается на один символ 1 Американский журнал "PC magazine" писал по этому подводу. "К 2000 году система Windows будет работать везде, кроме разве что стоп-сигналов и тосте- ров..." 2 Конечно, для машин с процессором i486DX и PENTIUM, это не так акту- ально, но для большинства российских программистов, имеющих в своем распо- ряжении 286 и 386 машины (а кое-где и 86), снижение быстродействия очень заметно. 247
вправо, тень убирается. В таком состоянии кнопка остается на- жатой примерно 0.5 сек. При программировании возникают две задачи: 1. Кнопка должна быть ярко белой, но BASIC может использо- вать только 8 цветов в качестве фона — здесь может помочь переопределение цветов оператором PALETTE; 2. Требуется задержка 0.5 сек, но функция TIMER и оператор SLEEP оперируют целыми секундами, а использования опе- ратора SOUND приводит к неприятному "щелчку". Решени- ем может служить прямое чтение младшего байта счетчика суток - РЕЕК(&Н46С). DEFINT A-Z 'переопределяем цвета - цвет N6 стал ярко-белым PALETTE б, 63 'очищаем экран COLOR 0, 7: CLS : COLOR 0, 3 1 выводим рамку LOCATE 10, 23: PRINT " [—" + STRING$C0, "-") + "-, " FOR i = 1 TO 5 LOCATE 10 + i, 23: PRINT "|" + SPACE$C0) + "|" NEXT i LOCATE 16, 23: PRINT "L" + STRING$C0, "-") + "J" LOCATE 12, 27 PRINT "Эффект " + CHR$C4) + "объемной" + CHR$C4) + " кнопки " Button$ = CHR$A6) + " Ok " + CHR$A7): a$ = "" DO WHILE a$ <> CHR$B7) 'рисуем кнопку COLOR 0, 7: LOCATE 14, 33: PRINT Button$ COLOR 0, 3: LOCATE 14, 43: PRINT "e" LOCATE 15, 34: PRINT STRING$A0, "¦") 1 ждем нажатия любой клавиши DO: a$ = INKEY$: LOOP WHILE a$ = "" 1 стираем тень и сдвигаем кнопку вправо COLOR 0, 3: LOCATE 14, 33: PRINT " " COLOR 0, 6: LOCATE 14, 34: PRINT Button$ COLOR 0, 3: LOCATE 15, 34: PRINT SPACE$A0) 'обеспечиваем задержку 0.5 секунд DEF SEG = 0 start = PEEK(&H46C): finish = start + 9 248
IF finish > 255 THEN finish = finish - 255 DO: LOOP WHILE PEEK(&H46C) <> finish DEF SEG LOOP Вывод:' Рамки и тени Другим широко известным трехмерным эффектом является рисование рамок, "отбрасывающих" тень. Для рисования рамок и таблиц используются символы, приведенные в Приложении 5, раздел "Символы псевдографики для рисования рамок и таблиц". Существует несколько разновидностей рамок и теней. Рамки могут состоять : • из одинарных линий; • из двойных линий; • из комбинации одинарных и двойных линий; • только из пробелов. В свою очередь тени подразделяются на: • "Изящные", составленные из символов "¦"и "|", могут быть использованы только на однородном фоне; • "Неинтеллектуальные", составленные из символов "Щ'и 'Щ' (или " и "|1", Ц' и "ШГ, "Щ' и "И')> которые могут выво- дится на любом фоне. Однако символы, которые закрывает тень, не видны из-под нее; 1 В дополнение к "объемным" кнопкам в текстовом режиме, в Microsoft BASIC PDS существует еще возможность загрузить свои собственные экран- ные шрифты. Это позволяет вывести в текстовом режиме недостающие симво- лы, и в частности, расширить символы псевдографики набором своих соб- ственных рамок. 249
• "Интеллектуальные", меняющие цвет символов, которые они закрывают, на серый (основной цвет № 8, фоновый — № 0); т е символы как бы "проступают" из-под тени, создавая полную иллюзию "объемности". Пример: вывод трех рамок: а) из пробелов с "изящной" тенью; б) из одиночных линий с "неителлектуальной" тенью; в) из пробелов с "интеллектуальной" тенью. DEFINT A-Z COLOR 0, 3: CLS 'рамка из пробелов с "изящной" тенью COLOR 0, 7: LOCATE 4, 5- PRINT SPACE$C0) LOCATE 4, 35: COLOR 0, 3: PRINT "ш": COLOR 0, 7 FOR l = 1 TO 6 LOCATE 4+1, 5: PRINT SPACE$C0); "§" NEXT l COLOR 0, 3: LOCATE 11, 6: PRINT STRING$C0, "¦") COLOR 0, 7: LOCATE 7, 12: PRINT "Рамка без линии" 'рамка из одиночных линий с "неинтеллектуальной" тенью COLOR 0, 7 LOCATE 4, 45: PRINT" г" + STRING$B8, "-" ) + "-, " FOR l = 1 ТО 5 LOCATE 4 + 1, 45: PRINT " | " + SPACE$B8) + "|"; "Щ" NEXT l , LOCATE 10, 45: PRINT " L" + STRING$B8, "-") + "-> "; "¦" LOCATE 7, 52: PRINT "Рамка с линией" COLOR 0,3: LOCATE 11, 47: PRINT STRING$C0, "¦") 'рамка из пробелов с "интеллектуальной" тенью COLOR 0, 3 j 'заполнение фоном FOR 1 = 1 ТО 12 ,» , LOCATE 13 + 1, 2: PRINT STRING$G8, "*"); NEXT l JN 'рисование рамки у COLOR 0, 7: LOCATE 16, 5: PRINT SPACE$G0) FOR l = 1 TO б LOCATE 16 + l, 5: PRINT SPACE${70) NEXT l 'Рисование "интеллектуальной" тени 'С помощью функции SCREEN считываются коды символов, 'и выводятся на то же место, но другого цвета1 1 Вместо этого можно было напрямую менять атрибуты символов, не перери- совывая их, а обращаясь к видеопамяти с помощью операторов РЕЕК и РОКЕ, однако это неоправдано усложнило бы программу 250
COLOR 8,0 'боковая тень FOR i = 1 ТО 6 FOR з = 1 ТО 2 symbol$ = CHR$(SCREENA6 + i, 7 4 + ц)) LOCATE 16 + l, 74 + 3: PRINT symbol$ NEXT j NEXT 1 1 Нижняя тень FOR 1 = 1 TO 7 0 symbol$ = CHR$(SCREENB3, 6+1)) LOCATE 23, 6 + 1: PRINT symbol$ NEXT 1 COLOR 0, 7: LOCATE 19, 26: PRINT "Рамка с " + CHR$C4) + "интеллектуальной" CHR$C4) + "тенью" DO: LOOP WHILE INKEY$ = "" Результат: Поля для ввода данных Еще одной трехмерной структурой можно считать поля для ввода данных Здесь эффект объемности возникает из за того, что часть рам- ки, состоящей из одинарных или двойных линий выводится ярко- белым цветом (№ 15), а часть черным (№ 0). При этом сама рамка размещается на белом фоне (№ 7). 251
Поле может быть1 • Выпуклым' Верхняя половина рамки ярко-белая, нижняя —- черная; • "Впуклым Верхняя половина рамки черная, нижняя — ярко- белая Комбинируя одинарные и двойные линии, а также эффект выпуклости и "впуклости" можно выделять активное поле, кон- струировать из полей "нажимающиеся" кнопки и т д. Пример: Рисование объемных полей для ввода данных DEFINT A-Z 1 заполнение фоном COLOR 0, 7: CLS FOR 1 = 1 ТО 25 LOCATE 1, 1: PRINT STRING${80, " "); NEXT i 1 рисование рамки COLOR 0, 7 LOCATE 4, 4: PRINT "r" + STRINGSF9, "-") + "n" FOR l = 1 TO 14 LOCATE 4 + i, 4: PRINT "|" + SPACE$F9) + "|" NEXT l LOCATE 18, 4: PRINT " L" + STRING$F9, "-") + "-I " 1 выпуклое поле для ввода данных COLOR 15, 7: LOCATE 7, 22: PRINT "г" + STRINGSD8, "-") LOCATE 8, 22: PRINT "|" LOCATE 9, 22: PRINT "L" COLOR 0, 7: LOCATE 7, 71: PRINT " LOCATE 8, 71: PRINT ' j" LOCATE 9, 23: PRINT STRING$D8, "-"); "-I " LOCATE 8, 6: PRINT "Выпуклое поле:" '"впуклое" поле для ввода данных COLOR 0, 7: LOCATE 12, 22: PRINT "г" + STRINGSD8, "-") LOCATE 13, 22: PRINT "|" LOCATE 14, 22: PRINT "L" COLOR 15, 7: LOCATE 12, 71: PRINT "-] " 1 Автор берет на себя смелость обогатить "великий и могучий" русский язык этим термином В математике можно сказать про кривые — выпуклые и вогну- тые, но где вы видели вогнутое поле для ввода9 252
LOCATE 13, 71: PRINT "|" LOCATE 14, 23: PRINT STRING$D8, "-"); "J" COLOR 0, 7 LOCATE 13, 6: PRINT CHR$C4) + "Впуклое" + CHR$C4) + " поле:" DO: LOOP WHILE INKEY$ = "" Результат: Библиотеки для работы с изображениями (*) Встроенные графические средства языка QuickBASIC хорошо подходят только для рисования и передвижения небольших гео- метрический объектов — прямых, эллипсов, ломанных линий. Этого оказывается недостаточно, если вы хотите работать со слож- ными сканированными или рисованными изображениями. В этом случае могут помочь специализированные библиотеки для работы с изображениями В этот разделе рассматриваются две такие биб- лиотеки: PCX Programmer's ToolKit и VEGX for QuickBASIC PCX Programmer's ToolKit Пакет разработчика графических программ в формате РСХ- "PCX Programmer's ToolKit, v 3.53, Copyright (с) GENUS Microprog- ramming, Inc, 1988-1989 All Right Reserved " 253
Пакет программиста PCX позволяет разработчикам создавать прикладные программы, обладающие средствами показа, сохра- нения, печати и манипулирования изображениями формата PCX. Вследствие того, что пакет поддерживает 95% адаптеров дисплея, он может быть использован во многих разнообразных областях — от показа заголовков и эмблем программ при начальной загрузке до создания интерактивных видео- и демонстрационных про- грамм. Его возможности: • 62 процедуры FUNCTION, 9 сервисных программ и 300 стра- ниц документации; • 21 видеорежим, вплоть до разрешения 800 х 600 в 256 цветах; • Показ изображений на всем экране или его части; плюс ди- намическая прокрутка больших изображений в окнах; • Двуцветная печать изображений на лазерном принтере; • Прокрутка, печать и замещение экранных страниц; • Библиотеки для работы с среде QB1 (.QLB — 46 Kb), компи- ляции в .ЕХЕ файл (.LIB — 52 Kb) и включаемый файл, содер- жащий определения констант и процедур (.BI — 16 Kb). Для работы с пакетом вы должны загрузить среду QB с биб- лиотекой PCX_QB.QLB: C:\QB45>qb program /L pcx_qb.qlb Пример: Вывод на экран файла SIMPLE.PCX 'включаемый файл библиотеки PCX Programmer ToolKit '$INCLUDE: 'pcxlib.bi' ' Установка типа дисплея, имени файла и кода возврата pcxtype% = pcxCGA.4 pcximage$ = "Simple.PCX" retcode% = -999 ' Установить тип дисплея retcode% = pcxSetDisplay%(pcxtype%) 1 Войти в графический режим retcode% = pcxSetMode%(pcxGRAPHICS) ' Показать картинку IF (retcode% = pcxSUCCESS) THEN dispret% = pcxFileDisplay%(pcximage$, 0, 0, 0) 1 К сожалению, пакет не включает библиотеки для работы с Microsoft BASIC PDS 7.1 254
' Ждать нажатия клавиши DO: LOOP WHILE INKEY$ = "" 1 Вернуться в текстовый режим etcode% = pcxSetMode%(pcxTEXT) END IF 1 Проверить, все ли в порядке IF (dispret% <> pcxSUCCESS) THEN PRINT "Возникла ошибка: ["; dispret%; "]" PRINT "Возможно дисплей не поддерживает CGA или же" PRINT "файла SIMPLE.PCX нет в текущей директории..." END IF END Результат: Undo Page Edit Style Adjust Pick Misc VEGX for QuickBASIC Пакет разработчика графических программ в формате VEGX: "VGA and EGA Graphics file formats for QuickBASIC and Professional BASIC Programmers, Version 2.0, November, 1990, Copyright, 1990, Dwain Goforth, Milestone Software, Arcata, California. All rights reserved." 255
VEGX — это набор двух графических форматов для QuickBASIC. VGX поддерживает 640x480 16-цветный (SCREEN 12) формат, в то время как EGX предназначен для 640x350 16-цветный (SCREEN 9) формат. К его несомненным достоинствам относятся: • Моментальная загрузка и показ графических файлов; • В нем всего две процедуры SUB с простым и удобными фор- матом вызова — VGXLoad и VGXSave; • Сжатый формат при хранении на диске; • Видеоэффекты гашения и появления изображения; • Библиотеки для работы в среде QB1 (.QLB — 15 Kb) и ком- пиляции в .ЕХЕ-файл (.LIB — 14 Kb); • Утилиты для сохранения графических экранов и перевода .PCX файлов в формат VEGX. Для работы с пакетом вы должны загрузить среду QB с биб- лиотекой VEGX45.QLB: C:\QB45>QB program /L vegx45.glb Пример: Вывод на экран файла DINON.VBX 1 Имеются библиотеки для работы с QuickBASIC 4 00, QuickBASIC 4 50 и Microsoft BASIC PDS 7 x 256
DEFINT A-Z DECLARE SUB VGXLoad (fil$, PalFlag) 'режим 640 x 480 x 16 цветов SCREEN 12 'Показать файл DINON.VBX, эффект 4 - всплывание рисунка CALL VGXLoad (" dmon" , 4) DO: LOOP WHILE INKEY$ = "" 1 текстовый режим SCREEN 0 Звук и музыка ВЕЕР ВЕЕР — оператор, генерирующий звук. ВЕЕР Звук, генерируемый оператором ВЕЕР аналогичен следую- щей команде: PRINT CHR$G) PLAY PLAY — оператор ввода/вывода, играющий музыку. PLAY командная_строка Командная строка содержит следующие музыкальные коман- ды, перечисленные в таблицах: Команды октавы и тона Октава On > < Действие Устанавливает текущую октаву. Всего семь октав, от 0 до 6 Повышает октаву на 1 Уменьшает октаву на 1 257
Тон A-G Nn Действие Играет ноту A-G ("до" - "си") Играет ноту п, в пределах 0—84 (в семи возможных октавах всего 84 ноты); п = 0 означает паузу Суф- фиксы # или + - Действие Следует за нотой и играет ее в режиме "диез" Следует за нотой и играет ее в режиме "бемоль" Команды длительности и темпа Длитель- ность Ln MN ML MS Действие Устанавливает длительность каждой ноты. L 4 — чет- вертая нота, L 1 — целая нота и т. д. Пределы п: 1-64. Длительность может следовать за нотой, если не нужно изменять длительность всей последовательнос- ти. Например, А 16 эквивалентно L 16 А Устанавливает "нормальный стиль", т. е. ноты играются 7/8 времени, определенного длительностью L Устанавливает "стиль легато", т. е. ноты играются пол- ный период, установленный командой L Устанавливает "стиль стаккато", т. е. ноты играются 3/4 периода, указанного командой L Темп Рп Тп Действие Устанавливает паузу длительностью п, в пределах 1— 64. Параметр п должен быть задан явно. Устанавливает темп звучания, число четверных нот в одной минуте. Пределы п: 32-255. По умолчанию п = 120. Из-за низкой скорости таймера E5 прерываний в сек.) некоторые ноты могут не звучать при высоких значениях темпа (L 64 при Т 255, к примеру) 258
Точка после ноты указывает на то, что она должна звучать 3/2 времени, указанного L. После ноты может стоять несколько точек, каждая из которых добавляет половину предыдущей длительности. Например: А. звучит 1 + 1/2 или 3/2 длительности; А., звучит 1 + 1/2 + 1/4 или 7/4 длительности. Точки могут стоять и после паузы Р, регулируя ее длительность. Переключения звучания на основное или фоновое Операция MF MB Действие Устанавливает музыку, генерируемую операторами PLAY и SOUND, в основное звучание. Это значит, что последующая нота звучит только после заверше- ния предыдущей. Кроме того, действие других опера- торов приостанавливается до завершения звучания Музыкальные операторы генерируют звук в фоновом режиме. Это значит, что каждая нота или звук поме- щаются в буфер, позволяя другим операторам выпол- няться, пока музыка звучит. Максимальное количе- ство нот, помещающихся в буфер, равно 32 Вызов подкоманды: "X" + VARPTR$(cTpoKa) Выполняет подкоманду, указанную в строке Пример 1: Использование оператора PLAY для генерации звуковых эффектов. DEFINT A-Z CONST Cuckoo$ = "T120Ll6MLO3BF#" CONST Zap$ = "T255L64MLO4BAGFEDC<BAGFEDEC<BAGFED_ C<BA GFEDC<BAGFEDC" CONST Tifweet$ = "T255L32O4mlDGD<G>DGDDGDGBAGF#EE" CONST Zang$ = "T255L64MLO2BCADGEFEGDACBCADGEFEGDACB" CONST Downer$ = "T150L64MSO4BGEC<AFLl6D" CONST UpScale$ = "T150L64MSO3DFA>CEGL16B" CONST Tweedle$ = "T240L64MLO4EGEGEGCFCFCFGEGEGE" CONST Whoople$ = "T255L64O4CDEFGABO3CDEFGABO2CDEFGAB" CONST Bongee$ = "T255L64MLO1BAGFEDC<BAGFEDCP16>CD_ 259
EFGAB>CDEFGABP32" CONST Uhoh$ = "T25 5L64MLO1CDEFGAB>CDEFGABP16<BAGF_ EDC<BAGFEDCP32" CONST BobWhite$ = "T120L16O4C*.Pl6T255L64mlC#DD#EF_ F#GG#AA#BO5CC#DD#EF" CONST Whung$ = "T255L32mlO3CD<CD>>CD«CD>>CD<<CD>CD" CONST Phone$ = "T240L64MLO4EGEGEGEGEGEGEGEGEGEGEGEGE_ GEGEG" CONST Tweet$ = "O4T255L64MLB-BB-BAGAG.>EGG>EGG" CONST Wolf$ = "T200L64MLO4C#DD#EFF#GG#AA#B>CC#D_ D#EFP8.<C#DD#EFF#GG#AA#B>CC#DD#EFFED#DC#C<BA#AG#GGF_ #FED#DC#" CONST Fweet$ = "T255L64MsO4C#DD#EFF#GG#AA#B>CC#_ DD#EF" COLOR i PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT DO 0, 7: " 1. 11 2. 11 3. 11 4. 11 5. 11 6. " 7. 11 8. " 9. 11 10. 11 11. " 12. " 13. " 14. 11 15. " 16. LOCATE 19, LOCATE 19 CLS Cuckoo" Zap" Tifweet" Zang" Downer" Upscale" Tweedle" Whoople" Bongee" Uhoh" BobWhite Whung" Phone" Tweet" Wolf" Fweet" 1: PRINT " " 'Введите номер эффекта @ - выход) , 45: INPUT Nomer SELECT CASE Nomer CASE CASE CASE CASE CASE CASE CASE CASE CASE CASE CASE CASE CASE CASE CASE IS = IS = IS = IS = IS = IS = IS = IS = IS = IS = IS = IS = IS = IS = IS = 0: EXIT 1: PLAY 2: PLAY 3: PLAY 4: PLAY 5: PLAY 6: PLAY 7: PLAY 8: PLAY• 9: PLAY 10: PLAY 11: PLAY 12: PLAY 13: PLAY 14: PLAY DO Cuckoo$ Zap$ Tifweet$ Zang$ Downer$ UpScale$ Tweedle$ Whoople$ Bongee$ Uhoh$ BobWhite$ Whung $ Phone$ TweetS 260
CASE IS = 15: PLAY Wolf$ CASE IS = 16: PLAY Fweet$ CASE ELSE: BEEP END SELECT LOOP COLOR 7, 0: CLS : END Пример 2: Использование оператора PLAY для проигрыва- ния музыкальных фрагментов. DEFINT A-Z DO COLOR 7, 0: CLS : PRINT PRINT " 1. Штраус. Вальс 'Голубой Дунай' " PRINT " 2. Моцарт. Симфония N 40 " PRINT " 3. Моцарт. Турецкий марш " PRINT " 4. Марш 'Прощание славянки'" PRINT PRINT " 5. Туш " PRINT " б. Песня о крокодиле Гене" PRINT " 7. Повесть о зеленом кузнечике" PRINT " 8. Марш Мендельсона в миноре" PRINT PRINT " 9. Гимн Соединенных Штатов Америки" PRINT 0. Гимн Советского Союза" PRINT : PRINT : INPUT "Введите номер мелодии @ - выход) -> ", п SELECT CASE n CASE IS = 0: EXIT DO CASE IS = 1 1 Штраус. Вальс 'Голубой Дунай' PLAY "mf ms tl37 o216d f# a 16ap6 16>a арб f# f#p6" PLAY "o216d d f# a 16ap6 16>a арб g дрб" PLAY "o216c# c# e 16b Ьрб 16>Ь Ьрб g gp6" PLAY "o216c# c# e 16b Ьрб 16>b Ьрб f# f#p6" PLAY "o216d d f# a >dp6 >d dp6 <a арб" PLAY "o216d d f# a >dp6 >d dp6 <b Ьрб" PLAY "o216e e g b 13b.. 16g# a >13f#.." PLAY "tl30 16d <f# 16f#..e b..a dpl2 112d d.p6." PLAY 6a дрб а дрб a 13>f#.. 16e <a f#p6 a f#p6 a_ 13>e.. " PLAY 6d <a дрб а дрб a 13>f#.. 16e <a >d e f#_ 13a 16gll2f# f# 16f# e d" CASE IS = 2 ' Моцарт. Симфония N 40 PLAY "msmftl90o318e- d 14d 18e- d 14d 18e-_ d 14d 14b-p4" PLAY 8b- a 14g 18g f 14e- 18e- d 14c cp4" 261
PLAY 8d с 14c 18d с 14c 18d с 14c ap4 " PLAY 8a g 14g- 18g- e- 14d 18d с о2 14b- b-p4" PLAY "o318b- a mll4a o4c o3g- a g dp4" PLAY "mso318b- a mll4a o4c o3g- a g b-" PLAY 8a g f e- 14d o2f# gab- o318c o2b- 14a_ g o3dp4" PLAY "mlo412c# 14dp4 " PLAY "mlo412c# 14dp4 " PLAY "mlo412c# 18dp8 c#p8 dp8 C#p8 dp8 " CASE IS = 3 ' Моцарт. Турецкий марш FOR i = 1 TO 2 PLAY "T130 ML L16 02 BAG#A03 C8 P8 L16 DC 02 B_ 03 С E8 P8 FED#E BAG#A BAG#A" PLAY "MN 04 C4 03 A8 04 C16.O3 G64A64 L8 В MS AGA16.ML G64A64 В MS AGA16." PLAY "ML G64A64 В MS AGF#E4" NEXT i PLAY "T130 MS 03 L8 EF GG ML LIб AGFE D8 02 MS_ G8 MS 03 L8 EF GG ML L16 AGFE" PLAY "MN D4 MS C8 D8 MS E8E8 ML FEDC 02 ML B8_ MS E8 03 MS C8D8 MS E8E8 ML FEDC" PLAY 2 MS B4 В MLAG#A 03 C8 P8 DC 02 В 03 C_ E8 P8 FED#E BAG#A BAG#A" PLAY 4 MN C4 L8 MS 03 AB04 С 03 BAG #AEFD C4O2 ML B32.C32.B32. A16 B16 A4" CASE IS = 4 1 Марш 'Прощание славянки' PLAY "T125 >03 ML L64 GA-B 04 L4 MS С L4 03 MS _ A-GF L8 E-. L16 F L8 D. L16 E- L4 C" PLAY "MN L8 GA- L4 G MN L8 E-D L4 С L8 <B >C ML L4_ D.<L8 В L4 MN G" PLAY ">MN L8 GA- L4 G L8 GG >ML L4 D L8 E-D L2_ MN C." PLAY "L8 С <B > L4 D L8 С < A-L4 F L8 A->C L4 <_ ML G. L8 E-MN L4 С MN" PLAY "L8 GA- L4 G L8 DE- L4 G L8 DE- L2 C." FOR i = 1 TO 2 PLAY "O1L4 G> L2E-. L8 D. L16C L2D.<L4 G>_ L2D. L8 E-. L16D L2C.<L4 G> L2C. L8 D. L16C_ ML L2FMS L8F " PLAY "L8 FGA-MN L4G L8 F. L16 E- L4 D L8 E-._ L16 D MS L8CL16 CC18CC L4C" NEXT i PLAY 3 ML P4 L64 bed 04 L4 MS E-E-E-<MLg>e-c<g _ 18 e-cl2 MN d.ML14 g>d< 18 gbl4>d 18e-dl2cp8" PLAY "MN<18 b-a-gl4f>dp8 <18 fgfl4e->cp8 <18_ e-fe-14da-g<b>18cll6ccl8ccc>" PLAY "MN<18 b-a-gl4f>dp8 <18 fgf14e->cp8<18_ e-fe-14da-gb>18cll6ccl8ccc>" 262
CASE IS = 5 'Туш PLAY "<C4E8G8" PLAY ">C16C16C16C1SCI6C16C16C16" PLAY "D16D16D16D16D16D16D16D16" PLAY "E4D4C8C16.C32C8P8" CASE IS = 6 1 Песня о крокодиле Гене PLAY "T255o2CL4C+L4CL4P4olF01L4GL4G+L4FL4" PLAY "o2CL4C+L4CL4P4olGL4G+L4A+olL4GL4" PLAY "T255o2CL4C+L4CL4P4olGL4G+L2A+L4o2CL4C+L4_ mlC L2CL4" CASE IS = 7 1 Повесть о зеленом кузнечике PLAY "MFT240AEAEAG#G#P4G#EG#EG#AAP4" PLAY "AEAEAG#G#P4G#EG#EG#AP2" PLAY "ABB8B8B4B4>CC8C8CCC<BAG#AAP4" PLAY "ABB8B8B4B4>CC8C8CCC<BAG#AP4n CASE IS = 8 'Марш Мендельсона в миноре PLAY "T90MLL8O2A4O3FEDC#D4O2A4B-4O2 _ C#EGB- AG F4EFD4 F4 В- А 03 DC" PLAY "F4EDCO2B-AB-16 03 C16 02 F4 E4MN F2.MS _ 03 A4 02F ML 03AGF El 6 F16 G C2" PLAY "MS F4 02 D ML 03 F E D C#16 D16 E 02 _ A4A8P8 А В 03 C# D E F" PLAY "G E C# B- A G F16 E16 D8 E4 C#4 D2" CASE IS = 9 1 Гимн Соединенных Штатов Америки PLAY "T100O3L8E-.L16CO2L4A-O3L4CE-L2A-O4L8_ C.O3L16B-L4A-CDL2E-L8E-E-O4L4C." PLAY "O3L8B-L4A-L2GL8FGL4A-A-E-CO2L4A-O4L8CCL4_ CD-E-L2E-L8D-CO3L4B-O4L4CD-L2D-L8D-" PLAY "D-L4C.O3L8B-L4A-L2GL8FL16G.L4A-CDL2E-L8E-_ E-L4A-A-L8A-GL4FFFB-O4L8D-CO3L8B-» PLAY "A-L4A-L4G.P8L8E-E-O3L4A-.L8B-O4L8CD-L2E-O_ 3L8A-B-O4L4C.L8D-O3L4B-L2A-.." CASE IS = 10 1 Гимн Советского Союза PLAY "tl20o218g4.p8g>c4<g.ab4e.ea4g.fg4c.cd4d_ .ef4f.g7" PLAY "a4b.>cd2<g>e4d.cd4<g.g>c4<b.ab4e.ea_ 4g.fg4c.c>c4<b.ag2" CASE ELSE BEEP END SELECT LOOP COLOR 7, 0: CLS : END 263
SOUND SOUND — оператор ввода/вывода, генерирующий звук через динамик. SOUND частота, длительность • частота — числовое выражение в пределах 37-32767, частота звука в циклах/сек или в Гц; • длительность — числовое выражение в пределах 0-65535, число отсчетов системного таймера, определяющее продолжительность звучания. В одной секунде 18.2 отсчетов таймера. Если длительность равна нулю, звук, генерируемый текущим оператором SOUND, выключается. Пример: Использование оператора SOUND для генерации звуковых эффектов. DEFINT A-Z COLOR 0, 7: CLS PRINT PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT " PRINT DO LOCATE ход) -> LOCATE SELECT 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. I 20 20 Oh" Space" Gurgle" Spectre" Grup" Chirp" Waver" Who" Mew" Phone" siren" Zhoup" Vrowr" Zhou" Art" Coo" Squawk" , 1: PRINT " Вве, , 45: INPUT Nomer CASE Nomer CASE IS = 0 Введите номер эффекта @ - вы- 264
265 EXIT DO CASE IS = 1 FOR I = 800 TO 2000 STEP 100 'Oh SOUND I, .2 NEXT I FOR I = 2000 TO 50 STEP -100 SOUND I, .2 NEXT I CASE IS = 2 FOR I = 1000 TO 40 STEP -20 'Space SOUND I, .2 NEXT I CASE IS = 3 FOR I = 10 TO 50 STEP 10 'Gurgle' FOR J = 50 TO 10 STEP -10 SOUND I л 2 + J л 2, .1 NEXT J NEXT I CASE IS = 4 FOR Z = 1 TO 100 'Spectre SOUND (SIN(Z) +40) * 50, .2 NEXT Z CASE IS = 5 FOR I = 10 TO 50 STEP 10 'Grup FOR J = 50 TO 10 STEP -10 SOUND I * J, .1 NEXT J NEXT I CASE IS = 6 FOR I = 30 TO 60 STEP 10 'Chirp FOR J = 60 TO 30 STEP -10 SOUND I * J, .2 NEXT J NEXT I CASE IS = 7 FOR Z = 1 TO 45 'Waver SOUND (SIN(Z) + 20) * 30, .2 NEXT Z CASE IS = 8 FOR Y = 100 TO 80 STEP -1 "Who SOUND (TAN(Y) + 36) * 25, .8 SOUND (SIN(Y) +20) * 50, .4 NEXT Y CASE IS = 9 FOR Y = 100 TO 80 STEP -1 'Mew SOUND (TAN(Y) + 50) * 25, .4 NEXT Y CASE IS = 10 FOR Y = 1 TO 10 'Phone SOUND 1195, .4 SOUND 2571, .4 NEXT Y CASE IS = 11 FOR Y = 1 TO 3 'siren SOUND 550, 9 SOUND 400, 9
Работа с оцифрованным звуком (*) Пару лет назад встроенных возможностей BASIC по извлечению звуков из встроенного динамика компьютера было более чем доста- точно. Но времена меняются. Все большее распространение получают звуковые платы, а с ними — системы multimedia1. Независимые раз- работчики библиотек для QuickBASIC тоже не стоят на месте. В этом 1 Системы "Multimedia" — аппаратные и программные средства, обеспечивающие работу с подвижными и неподвижными изображениями, анимированной компьютер- ной графикой и текстом, речью и высококачественным звуком 266 NEXT Y CASE IS = 12 FOR Z = 3 TO 12 'Zhoup SOUND 120 + Z Л 4, .1 SOUND 0, .1 NEXT Z CASE IS = 13 FOR Z = 12 TO 3 STEP -1 'Vrowr SOUND 120 + Z Л 4, .1 SOUND 0, .1 NEXT Z CASE IS = 14 FOR I = 40 TO 15 STEP -1 'Zhou SOUND I * 90, .1 SOUND I * 80, .1 SOUND I * 70, .1 SOUND I * 60, .1 SOUND I * 50, .1 NEXT I CASE IS = 15 FOR I = 1 TO 10 'Art SOUND 1195 - 50 * I, .3 SOUND 1195 + 50 * I, .3 NEXT I CASE IS = 16 FOR I = 0 TO 150 STEP 10 'Coo SOUND 1295 - I, .4 SOUND 1095 +1, .4 NEXT I CASE IS = 17 FOR I = 1 TO 20 'Squawk SOUND I * 50, .1 SOUND I * 100, .1 SOUND I * 150, .1 NEXT I CASE ELSE: BEEP END SELECT LOOP COLOR 7, 0: CLS : END
разделе речь пойдет о библиотеке для программирования звуковых карт AdLib и Sound Blaster — QBXCTV. Используя этот пакет вместе с пакетом VEGX для работы с изображениями, вы вполне сможете создавать собственные про- фессиональные приложения, работающие со звуком и изображе- ниями, ничуть не уступающие приложениям Windows, а кое в чем (хотя бы по скорости работы) значительно их превосходя- щие. Это могут быть обучающие, прикладные или игровые про- граммы высокого класса и многое другое — возможностей синте- за звука и изображения видимо-невидимо. QB SoundBlaster ToolKit Пакет для программирования звуковых карт: "QBXCTV — SoundBlaster™ Creative Voice Library for QuickBASIC 4.5, (c) Cornel Huth,1991" QBXCTV — это совместимый со звуковой картой SoundBla- ster™ пакет разработчика для работы с оцифрованным звуком в среде Microsoft QuickBASIC 4.51. Его основные возможности: • Наличие библиотек для работы в среде QB (.QLB — 14 Kb) и для компиляции в .ЕХЕ-файлы (.LIB — 15 Kb), а также включаемые файлы с описанием процедур и типов данных (.BI - 2 Kb); • Доступ к музыкальным инструментам для карт AdLib и SoundBlaster в формате BNK; • Поддержка всех функций драйвера CT-VOICE.DRV, а также звуковых файлов формата VOKXIT; • Прямой доступ к памяти (DMA) обеспечивает возможность фонового ввода ввод и вывода звука; • Подробная документация. Для работы с пакетом вы должны иметь звуковую карту, со- вместимую с SoundBlaster и загрузить среду QB с библиотекой QBXSB1N.QLB: C:\QB45>qb program /L qbxsbln.qlb 1 Имеются библиотеки для Microsoft BASIC PDS 7.x 267
Пример: Вывод звукового файла WATSON.VOC DEFINT A-Z 'Включаемые файлы пакета '$INCLUDE: 'QBXIOL.BI1 '$INCLUDE: 'QBXCTV.BI' '$INCLUDE: 'QBXFMI.BI' CLS 1 определение наличия звуковой карты STAT = CTVdetect IF STAT > 0 THEN END FileName$ = "WATSON.VOC" PRINT "Проигрывается файл: "; FileName$ 1 Открывается звуковой файл и определяется его длина STAT = OpenDevice(FileName$ + CHR$@), 2, handle, flen&) 1Считываются данные и выделяется буфер 1 достаточной длины для размещения данных REDIM VocBuff(О ТО flen&) AS INTEGER vseg = VARSEG(VocBuff@)) voff = VARPTR(VocBuff@)) STAT = ReadDevice(handle, 0, flen&, vseg, voff) STAT = CloseDevice(handle) 'Включается динамик звуковой карты STAT = CTVspeakerA) 'и воспроизводится звук STAT = CTVoutput(vseg, voff + 26) IF STAT = 0 THEN 'Во время воспроизведения можно что-либо делать DO STAT = CTVstatus LOOP WHILE STAT END IF 1 Сброс всех установок в исходное положение STAT = CTVuninstall PRINT "Готово!" END
ПРОЧИЕ ОПЕРАТОРЫ ЯЗЫКА SLEEP SLEEP — управляющий оператор, приостанавливающий вы- полнение программы. SLEEP [секунды] Если аргумент опущен или равен нулю, программа приоста- навливается до нажатия любой клавиши или возникновения раз- решенного события. Если аргумент задан, программа приостанавливается на ука- занное количество секунд, нажатия любой клавиши или возник- новения разрешенного события — в зависимости от того, что произойдет раньше. Пример: CLS PRINT "Подождите 10 секунд..." SLEEP 10 PRINT "Готово!" END REM REM — оператор, указывающий на комментарий. REM комментарий ' комментарий
• комментарий — любой текст, который вы вставляете в про- грамму как пояснение операторов и структур. В комментарий можно включать и символы кириллицы. REM не компилируется, но сохраняется в исходном тексте программы. Таким образом использование комментариев в Ва- шей программе не влияет на скорость работы .ЕХЕ файла. Комментарии нужны для программиста. Если программа хо- рошо документирована, т. е. в ней объясняется работа каждой процедуры, модуля, структуры, то с такой программой легко и удобно работать, даже если вы вернулись к ней спустя год, а при наличие комментариев вы без труда разберетесь даже в листинге вашего коллеги. Другим способом повысит удобочитаемость про- грамм является использование абзацных отступов. Например, опе- раторы внутри цикла записываются со смещением (достаточно 2-3 пробела). Кроме этого, блоки текста отделяйте пустыми строками, чтобы программа не выглядела как один сплошной свиток текста. Вместо ключевого слова REM можно использовать апостроф ('). При записи комментария с использованием REM в конце строки операторов, комментарий необходимо отделять двоеточием, а при за- писи с использованием апострофа, двоеточие можно опускать: FOR 1 = 1 ТО 10: NEXT 1: REM Это пустой цикл FOR i = 1 ТО 10: NEXT i 'Это пустой цикл Пример. Использование комментариев и абзацных отсту- пов 'Старайтесь не писать программы в таком стиле... DO INPUT A SELECT CASE A CASE IS = ... CASE IS = ... CASE ELSE ... FOR i = 1 TO 10 NEXT I EXIT DO END SELECT LOOP 'А лучше в таком... DO 'Входим в бесконечный цикл 1 Получаем значение INPUT "Введите значение переменной А"; А 270
LOOP SWAP SWAP — оператор, взаимно меняющий значения двух пере- менных. SWAP переменная1, переменная2 • переменная 1 и переменная2 — любые переменные (но не мас- сивы) одного и того же типа. Пример: сортировка символьного массива по возрастанию ASCII-кодов символов. DECLARE SUB ShellSort (Array$()) 'все переменные целые DEFINT A-Z 'максимальной количество элементов массива Аггау$() CONST Max =10 1 Объявляется размерность массива DIM Array$(Max) CLS 'присвоение значений элементам Array$A) = "Scale" Array$B) = "Масштаб" Array$C) = "Parameter" Array$D) = "Параметр" Array$E) = "Division" Array$F) = "Деление" Array$G) = "Computer" Array$(8) = "Компьютер" Array$(9) = "Ядро" Array$A0) = "Kernel" 'вызов процедуры сортировки CALL ShellSort(Array$()) 271 SELECT CASE A CASE IS = ..." в случае, если А = ... CASE IS = ..." в случае, если А = ... CASE ELSE ...' а иначе ... 'чего-нибудь считаем FOR l = 1 TO 10 NEXT I 'выходим из цикла DO EXIT DO END SELECT
'вывод исходных значений FOR i = 1 ТО Мах PRINT Array$(i%) NEXT i% END SUB Shell Sort (Array$ ()) STATIC i*************************************************** 1 Эта процедура сортирует символьный массив Array$(} Num% = UBOUND(Array$) Span% = Num% \ 2 DO WHILE Span% > 0 FOR i% = Span% TO Num% - 1 J% = i% - Span% + 1 FOR J% = (i% - Span% +1) TO 1 STEP -Span% IF Array$(J%) <= Array$(J% + Span%) THEN EXIT FOR ' Взаимная замена двух элементов массива. SWAP Array$(J%), Array$(J% + Span%) NEXT J% NEXT i% Span% = Span% \ 2 LOOP END SUB Результат: Computer Division Kernel Parameter Scale Деление Компьютер Масштаб Параметр Ядро ERASE ERASE — оператор управления памятью, обнуляющий эле- менты статических (SSTATIC) массивов или уничтожающий ди- намические (SDYNAMIC) массивы. ERASE массив [,массив...] • массив — имя описанного массива. Оператор ERASE обнуляет числовые элементы массивов SSTATIC и присваивает значение пустой строки элементам символь- 272
ных массивов. Если массив определен оператором TYPE как массив пользовательского типа, ERASE обнуляет элементы каждой записи. Использование ERASE для массивов $DYNAMIC освобожда- ет память, занятую этими массивами. Если программа вновь об- ращается к этим массивам снова, они должны быть заново опи- саны операторами DIM или REDIM. Повторное определение массива оператором DIM без предварительного стирания выдаст ошибку "Array already dimensioned" (Массив уже определен). Оператор ERASE не требуется, если массивы переопределяются с помощью REDIM. Пример: использование REDIM для размещения массива записей. Удаление массива из памяти оператором ERASE. TYPE KeyElement Word AS STRING * 20 Count AS INTEGER END TYPE 1 Метакоманда делает массивы динамическими. ' $DYNAMIC CLS 1 Описание массива записей из 100 элементов. REDIM WordsA00) AS KeyElement Words(99)-Word = "ERASE" Words(99).Count = 2 PRINT "Слово 99 = "; Words(99).Word PRINT "Счетчик ="; Words(99).Count ' Освобождение памяти, занимаемой Words(). ERASE Words END Слово 99 = ERASE Счетчик = 2 CLEAR CLEAR — оператор управления памятью, обнуляющий все пе- ременные, закрывающий файлы, устанавливающий размер стека. CLEAR [,,стек] • стек — параметр, устанавливающий размер стека для вашей программы. Если Ваша программа имеет много вложенных подпрограмм или процедур, или использует рекурсивные процедуры, то размер стека имеет смысл увеличить. 273
Очистка стека разрушает все адреса возврата из подпрограмм, вызываемых оператором GOSUB. Это может привести к некоррек- тному выполнению оператора RETURN и к ошибке "RETURN without GOSUB" (RETURN без GOSUB). Также нельзя использо- вать CLEAR внутри SUB или FUNCTION — вы получите ошибку "Illegal function call" (Неверный вызов функции). Пример: очистка всех переменных программы и увеличе- ние размера стека на 2000 байт. CLEAR , ,2000
8 ВСТРОЕННЫЕ МАТЕМАТИЧЕСКИЕ ФУНКЦИИ И ФУНКЦИИ ОБРАБОТКИ ДАННЫХ Математические функции ABS ABS — математическая функция, возвращающая абсолютное значение числового выражения. ABS(числовое выражение) Пример: вычисление приблизительного значения кубичес- кого корня методом итераций. Функция ABS используется для оценки точности приближения. DEFDBL A-Z Precision = .0000001* CLS INPUT "Введите число: ", Value 1 Начальные установки. XI = 0.0# : Х2 = Value ' Выполнять итерации, пока разница между двумя 1 приближениями не достигнет требуемой точности. DO UNTIL ABS(XI - Х2) < Precision X = (XI + Х2) / 2.0# IF X * X * X * Value < 0.0# THEN
XI = X ELSE X2 = X END IF LOOP PRINT "Кубический корень равен"; X Результат: Введите число: 27 Кубический корень равен 2.999999972060323 ЕХР ЕХР — математическая функция, вычисляющее основание натурального логарифма (число е) в степени заданного аргумента. ЕХР(числовое_выражение) • числовоевыражение — выражение, не превышающее 88.02969. Пример: расчет численности колонии бактерий. CLS INPUT "Исходная численность колонии"; ColonyO INPUT "Дневной рост колонии в процентах"; Rate R = Rate / 100 : Form$ = "## ######" PRINT : PRINT "ДеньЧисленность" FOR T = 0 TO 15 STEP 5 PRINT USING Form$; T, ColonyO * EXP(R * T) NEXT Результат: Исходная численность колонии? 10000 Дневной рост колонии в процентах? 10 День Численность 0 10000 5 16487 10 27183 15 44817 276
LOG LOG — математическая функция, возвращающая натураль- ный логарифм числового выражения. LOG(числовое_выражение) • числовое_выражение — аргумент функции, должен иметь зна- чение, большее нуля. MOD MOD — арифметическая операция. числовое_выражение1 MOD числовое_выражение2 Операция нахождения остатка от целочисленного деления. Например: PRINT 19 MOD 6.7 '19 MOD 6.7 = 5 SGN SGN — математическая функция, возвращающая знак чис- лового выражения. SGN(числовое_выражение) Числовое выражение >0 = 0 <0 Значение SNG +1 0 -1 SQR SQR — математическая функция, которая возвращает квад- ратный корень числового выражения. SQR(числовое_выражение) 277
• числовоевыражение — должно иметь значению большее или равное нулю. Пример: рисунок графика функций у = V-x для -9 <= х < О у = yfx для 0 <= х <= 9 SCREEN I : COLOR I WINDOW (-9,-.25)-(9,3.25) LINE (-9,0)-(9,0) 'Ось Х. LINE @,-.25)-@,3.25) 'Ось Y. FOR X = -9 TO 9 LINE(X,.04)-(X,-.O4) 'Шкала по оси X. NEXT FOR Y = .25 TO 3.25 STEP .25 LINE (-.08,Y)-(.12,Y) 'Шкала по оси Y. NEXT 1 Первая точка функции. PSET (-9,3) FOR X = -9 TO 9 STEP .25 Y = SQR(ABS(X)) 'Аргумент SQR не может быть отрицательным LINE -(X,Y),2 'Рисунок линии. NEXT Результат: 278
ATN ATN — математическая функция, возвращающая арктангенс числового выражения. ATN(числовое выражение) • числовое выражение — может быть любого числового типа. По умолчанию ATN выдает число обычной точности. Если аргумент функции двойной точности, ATN выдает число двойной точности. Результат выдается в радианах в пределах от PI/2 до PI/2 ра- диан. Для преобразования градусной меры в радианы умножьте градусы на PI/180. Чтобы преобразовать радианы в градусы, надо умножить радианы на 57.2958. Пример: CONST PI = 3.141592653 PRINT ATN(TAN(PI / 4.0)), PI / 4.0 Результат: .78539816325 .78539816325 COS COS — математическая функция, возвращающая значения синуса от угла в радианах. COS(числовое_выражение) • числовоевыражение — угол в радианах. Пример: рисунок спиралей Архимеда. CONST PI = 3.141593 SCREEN 1 : COLOR 7 1 Определение окна вывода. WINDOW (-4,-6) - (8,2) 1 Вывод координатной оси. LINE @,0) - B.2 * PI, 0),1 279
' Вывод десяти спиралей. FOR N = 1.1 ТО .1 STEP -.1 PSET @,0) FOR Angle = 0 ТО 2 * PI STEP .04 'Полярные координаты. R = N - Angle 'Преобразование в декартовы координаты. X = R * COS(Angle) Y = R * SIN(Angle) ' Вывод пинии. LINE -(X,Y),1 NEXT Angle NEXT N Результат: 'pess апч кеч to conti nue SIN SIN — математическая функция, возвращающая значение синуса от заданного угла в радианах. SIN(числовое_выражение) 280
• числовое выражение — угол, выраженный в радианах. Функция SIN вычисляется с двойной точностью, если чис- ловое выражение имеет двойную точность. Иначе синус вычисля- ется с обычной точностью. Можно преобразовать значение угла из градусов в радианы пу- тем умножения градусов на PI/180. Обратное преобразование полу- чается умножением радиан на 57.2958. Пример использования фун- кции COS был приведен выше, при описании функции SIN. TAN TAN — математическая функция, возвращающая тангенс уг- ла в радианах. TAN(числовое_выражение) • числовоевыражение — угол в радианах. TAN вычисляется с обычной точностью. Если аргумент задан с двойной точностью, то TAN будет вычислен также с двойной точностью. Можно преобразовать угол в градусах в радианы путем ум- ножения его на PI/180. Для обратного преобразования умножьте радианы на 57.2958. Пример. Эта программа использует функцию TAN для то- го, чтобы вычислить высоту объекта, используя рассто- яние от объекта и угол подъема. Она рисует треуголь- ник , опираясь на основание и вычисленную высоту. 'экранный режим 640 х 200 2 цвета SCREEN 2 INPUT "ДЛИНА ОСНОВАНИЯ: ", Baselen INPUT "УГОЛ ПОДЪЕМА (ГРАДУСЫ, МИНУТЫ): ", Deg, Min 'Перевод в радианы Ang = C.1415928# / 180) * (Deg + Min / 60) 'Вычисление высоты. Height = Baselen * TAN(Ang) PRINT "ВЫСОТА ="; Height 'Screen 2 - 640 x 200 пикселов. Aspect = 4 * B00 / 640) / 3 H = 180 - Height 281
В = 15 + (Baselen / Aspect) LINE A5, 180)-(В, 180) 'Рисование треугольника LINE -(В, Н) LINE -A5, 180) LOCATE 24, 1: PRINT "Нажмите любую клавишу..."; DO LOOP WHILE INKEY$ = "" Результат: Секанс и другие.... В языке BASIC нет встроенных функций секанс, косеканс, ко- тангенс, арксинус, арккосинус, арккотангенс и некоторых других тригонометрических и гиперболических функций, однако их мож- но вычислить, используя имеющиеся встроенные функции. Пример: sec х (секанс): SEC(X) = 1 / COS(X) cosec x (косеканс): COSEC(X) = 1 / SIN(X) arcsin x (арксинус): ARCSIN(X) = ATN (X/ SQR A - X * X) 282
arccos x (арккосинус): ARCCOS(X) = 1.570796 - ATN (X / SQR A - X * X) arcctg x (арккотангенс): ACTN(X) = 1.570796 - ATN (X) sh x(гиперболический синус): SINH(X) = (EXP(X) - EXP(-X)) / 2 ch x (гиперболический косинус): COSH(X) = (EXP(X) + EXP(-X)) / 2 th x {гиперболический тангенс): TANH(X) = (EXP(X) - EXP(-X)) / (EXP(X) + EXP(-X)) cth x (гиперболический котангенс): COTH(X) = (EXP(X) + EXP(-X)) / (EXP(X) - EXP(-X)) arcsh x (гиперболический арксинус): ARCSH (X) = LOG(X + SQR(X * X + 1)) arcch x (гиперболический арккосинус): ARCCOSH (X) = LOG(X + SQR(X * X - 1)) RANDOMIZE RANDOMIZE — математический оператор, запускающий ге- нератор случайных чисел. RANDOMIZE [выражение] • если аргумент опущен, BASIC выдаст сообщение для ввода любого числа, запускающего генератор: Random Number Seed (-32768 to 32767)? • выражение — может быть любого типа. Если генератор случайных чисел не запущен, функция RND будет выдавать одну и ту же последовательность чисел при каж- дом запуске программы. Для изменения последовательности по- ставьте оператор RANDOMIZE в начало программы и изменяйте аргумент перед каждым запуском программы. Используйте для этого функцию TIMER. Пример. Рисование узора при помощи случайных значений координат в операторе LINE: 1 Все переменные целые DEFINT A-Z 283
1 Запускаем генератор случайных чисел RANDOMIZE TIMER '640x350x16 цветов SCREEN 9 1 Внешний цикл FOR i = 1 ТО 1000 1 Внутренний цикл FOR j = 1 ТО 10 1 Изменяем цвет COLOR j 1 Рисуем линию LINE (i, INT(RND * 750) - (INT(RND * 750)))-(RND, i) NEXT j NEXT i Результат: RND RND — математическая функция, возвращающая случайное число обычной точности в интервале от 0 до 1. RND[(n)] 284
• если аргумент опущен, возвращается следующее число из пос- ледовательности случайных чисел; • п — определяет, как генерируется следующее число: • п < 0 — всегда возвращает то же число для любого п; • п > 0 — возвращает следующее число из последовательности; • п = 0 — возвращает последнее выданное число. В случае, если не запущен генератор случайных чисел, одна и та же последовательность будет генерироваться при каждом за- пуске программы. Для запуска генератора используйте функцию TIMER: RANDOMIZE TIMER Для генерации случайного числа в нужном интервале служит формула: INT ((max - min +1) - RND + min, где max — верхняя граница интервала, a min — нижняя. Пример: моделирование двух игровых кубиков. 1 Используем таймер для запуска ' генератора случайных чисел RANDOMIZE TIMER CLS DO ' Моделируем кубики функцией RND. Dl = INT(RND - 6) + 1 D2 = INT(RND - 6) + 1 PRINT "Выпало"; Dl; "и"; D2; " сумма"; Dl + D2 INPUT "Еще Y/N "; Resp$ PRINT LOOP UNTIL UCASE$(MID$(Resp$, 1, 1)) = "N" END Результат: Выпало З и 5 сумма 8 Еще Y/N? у Выпало 1 и 3 сумма 4 Еще Y/N? у Выпало 4 и 1 сумма 5 Еще Y/N? n 285
Функции обработки числовых и символьных данных Функции округления FIX FIX — математическая функция, возвращающая целую часть числового выражения. FIX(числовое_выражение) FIX(x) эквивалентно выражению SGN(x)*INT(ABS(x)). Раз- личие между FIX и INT состоит в том, что при х < О FIX выдает первое отрицательное целое, большее х, тогда как INT выдает первое отрицательное целое, меньшее х. INT INT — математическая функция, возвращающая первое це- лое, меньшее или равное данному числовому выражению. INT(числовое_выражение) Пример: сравнение функций INT, CINT и FIX. CLS PRINT " N", "INT(N)","CINT(N)","FIX(N)" : PRINT FOR 1% = 1 TO 6 READ N PRINT N, INT(N), CINT(N), FIX(N) NEXT DATA 99.3, 99.5, 99.7, -99.3, -99.5, -99.7 286
Результат: N 99.3 99.5 99.7 -99.3 -99.5 -99.7 INT(N) 99 99 99 -100 -100 -100 CINT(N) 99 100 100 -99 -100 -100 FIX(N) 99 99 99 -99 -99 -99 Преобразование типов данных CINT CINT — функция, преобразующая числовое выражение в це- лое число путем округления дробной части выражения. CINT(числовое_выражение) CLNG CLNG — функция преобразования, приводящая числовое выражение к длинному целому D байта) путем округления дроб- ной части. CLNG(числовое_выражение) Пример: Использование функции CLNG для округления числа перед переводом его в длинное целое. А = 32767.45: В = 32767.55 PRINT CLNG(A); CLNG(B) Результат: 32767 32768 CSNG CSNG — функция, преобразующая числовое выражение в значение обычной точности. CSNG(числовое_выражение) 287
Пример: округление перед преобразованием. А# = 975.3421115# В# = 975.3421555* PRINT A#; CSNG(A#); B#; CSNG(B#) Результат: 975.3421115 975.3421 975.3421555 975.3422 CDBL CDBL — функция, преобразующая числовое выражение в число двойной точности. CDBL(числовое_выражение) Пример: Влияние точности на преобразование. X = 7 / 9 ' выражение обычной точности Х# = 7 / 9 ' выражение обычной точности PRINT X PRINT X# PRINT CDBL(X) PRINT 7# / 9# ' выражение двойной точности Результат: .7777 78 .7777777910232544 .7777777910232544 .7777777777777778 CHR$ CHR$ — символьная функция, возвращающая строку из од- ного символа, ASCII-код которого является аргументом. CHR$(код) • код — числовое выражение от 0 до 255, один из ASCII-кодов. Пример: Вывод второй половины ASCII-таблицы 1 Все переменные целые DEFINT A-Z 288
1 Заголовок таблицы CLS PRINT SPACE$B0) + "Расширенная ASCII-таблица" PRINT 'Верхняя рамка PRINT "Т"'": F0R 1 = 1 ТО 8: PRINT " 1 г"'' :NEXT i PRINT 'Рисование таблицы. Функция CHR$ используется для 1 представления символа по его коду. FOR i = 1 ТО 16 FOR j = 128 ТО 255 STEP 16 PRINT USING "|###| ! "; j + i - 1; CHR$(j + l - 1); NEXT j PRINT "|" NEXT i 1 Нижняя рамка PRINT "-1-" ; : FOR l = 1 TO 8 : PRINT " ' L" ; : NEXT i 1 Ожидание нажатия любой клавиши DO: LOOP WHILE INKEY$ = "" Результат: Расширенная ASCII-таблица 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 й Б В Г д Е Ж 3 И Й к л м н 0 п 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 Р С Т У ф X Ц Ч и щ Ъ Ы Ь 3 0 я 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 а 6 В г Ъ в ж 3 и й к л и н о 11 176 177 178 179 180 181 182 1ВЗ 1В4 185 186 187 188 189 190 191 11 л II 11 л 1 192 193 194 195 196 19? 198 199 ZOO 201 202 203 Z04 205 206 207 L X т 4- \ | и If Л Т[ 1 i х 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 л т И t г 1 + J i i 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 Р с т и Ф X Ц ч и ч ь ы ь э ю я 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 Ё в > < J "Г SS » п г ш ASC ASC — функция, возвращающая числовое значение ASCII- кода первого символа в символьном выражении. ASC(символьное_выражение) 289
Пример: подсчет контрольной суммы. CLS INPUT "Введите строку : ", Nm$ TmpVal = 0 FOR i = 1 ТО LEN(Nm$) 1 Суммирование кодов отдельных букв. TmpVal = TmpVal + ASC(MID$(Nm$, i, 1)) NEXT I PRINT "Контрольная сумма = "; TmpVal Вывод: Введите строку : United States Контрольная сумма = 1277 Упаковка данных CVI, CVL, CVS ,CVD CVI, CVL, CVS ,CVD — функции, интерпретирующие сим- вольные переменные как числа. CVI( 2-байтная строка) CVL D-байтная строка) CVS D-байтная строка) CVD (8-байтная строка) CVI, CVL, CVS и CVD обычно используются оператором FIELD для чтения упакованных чисел из файла прямого доступа. Они обратны функциям MKI$, MKL$, MKS$, и MKD$. CVI$ CVL$ cvs$ CVD$ Преобразует 2-байтную строку в целое число Преобразует 4-байтную строку в длинное целое число Преобразует 4-байтную строку в число обычной точности Преобразует 8-байтную строку в число двойной точности MKI$, MKL$, MKS$, MKD$ MKI$, MKL$, MKS$, MKD$ — функции, интерпретирую- щие числа как символьные переменные. 290
МК1$ (целое_выражение) MKS$ (выражение_обычной_точности) MKL$ (длинное_целое_выражение) MKD$ (выражение_двойной_точности) Эти функции используются с операторами FIELD и PUT для за- писи числовых значений в файл произвольного доступа. Они преобра- зуют числа в символьные строки, которые могут размещаться в буфере оператора FIELD. Функции обратны CVI, CVL, CVS, CVD. MKIS MKL$ MKS$ MKD$ Преобразует целое число в 2-байтную строку Преобразует длинное целое число в 4-байтную строку Преобразует число обычной точности в 4-байтную строку Преобразует число двойной точности в 8-байтную строку Переменные пользовательского типа (записи) предоставляют более простой и удобный способ чтения и записи файлов произ- вольного доступа. Пример. Использования функций MKS$ и CVS: TYPE Buffer AccName AS STRING * 25 Check AS STRING * 4 END TYPE DIM BankBuffer AS Buffer I**************************************************** 'Открытие файла и занесение значений с использованием 'переменный пользовательского типа ¦ **************************************************** OPEN "ACCOUNT.INF" FOR RANDOM AS #1 LEN = 29 CLS RESTORE READ AccName$, Check i = 0 DO WHILE UCASE$(AccName$) <> "END" i = i + l BankBuffer.AccName = AccName$ 1 Преобразование числа в символьную переменную BankBuffer.Check = MKS$(Check) PUT #1, i, BankBuffer READ AccName$, Check$ IF AccName$ = "END" THEN EXIT DO LOOP CLOSE #1 291
DATA "Роберт", 3 00 DATA "Алиса", 150 DATA "Алексей", 7 5 DATA "Василий", 5 0 DATA "Григорий", 25 DATA "END", 0 1 Открытие файла и обработка значений при помощи 'буфера FIELD, функций MKS$ и CVS OPEN "ACCOUNT.INF" FOR RANDOM AS #2 LEN =29 FIELD #2, 25 AS AccName$, 4 AS Check$ Format$ = "$$#####.##" DO PRINT DO INPUT "Введите номер счета: ", Rec% GET #2, Rec% PRINT "Этот счет открыл "; AccName$ INPUT "Нужно изменить Y/N "; R$ LOOP WHILE UCASE$(MID$(R$, 1, 1)) о "Y" 1 Преобразование символьной переменной в число. Checkamt! = CVS(Check$) PRINT PRINT "Входящее сальдо по этому счету равно"; PRINT USING Format$; Checkamt! PRINT "Введите приход и расход по этому счету." PRINT "По завершению введите 0." DO INPUT Check! Checkamt! = Checkamt! + Check! LOOP UNTIL Check! = 0 PRINT PRINT "Исходящее сальдо по этому счету равно"; PRINT USING Format$; Checkamt! 'Преобразование числа в символьную переменную. LSET Check$ = MKS$(Checkamt!) PUT #2, Rec% INPUT "Изменить следующий Y/N "; R$ LOOP UNTIL UCASE$(MID$(R$, 1, 1)) <> "Y" CLOSE #2 END Результат: Введите номер счета: 3 Этот счет открыл Алексей Нужно изменить Y/N ? у Входящее сальдо по этому счету равно $300.00 Введите приход и расход по этому счету. По завершению введите 0. 292
? 560 ? -180 ? 0 Исходящее сальдо по этому счету равно $680.00 Изменить следующий Y/N ? п Функции обработки символьных строк LCASE$ LCASE$ — символьная функция, возвращающая символьную строку, в которой все латинские буквы преобразованы в строчные. LCASE$(символьное_выражение) • символьноевыражение — символьная строка, может быть пе- ременной или фиксированной длины. Пример: CLS READ Word$ PRINT LCASE$(Word$); DATA "THIS IS THE STRING in lower case." this is the string in lower case. Данная функция не преобразует символы кириллицы. При- мер, приведенный далее при описании функции UCASE, иллюс- трирует, как можно этого избежать. UCASE$ UCASES — символьная функция, возвращающая символьное значение, в котором все латинские буквы — заглавные. UCASE$(символьное_выражение) Функция UCASES может работать со строками фиксированной и переменной длины. Она не преобразует символы кириллицы. 293
Пример. Использование функции UCASERus$ вместо UCASE$ снимает ограничение на работу с символами кириллицы: DECLARE FUNCTION UCASERus$ (text$) DEFINT A-Z CLS INPUT First$ PRINT PRINT UCASERus${First$) END FUNCTION UCASERus$ (text$) CONST Urus$ = "ЙЦУКЕНГШЩЗХФЫВАПРОЛДЖЭЯЧСМИТЬВЮЪ" CONST Lrus$ = "йцукенлшцзхфывапролджэячсмитьбюъ" 1 длина входной переменной kolvo = LEN(text$) 1 вспомогательная переменная temp$ = "" FOR i = 1 TO kolvo 1 берем по одному символу из входной строки symbol$ = MID$(text$, i, 1) 'если это русские буквы, то ... IF symbol$ >= CHR$A28) THEN 'если они маленькие - меняем на большие place = INSTR(Lrus$, symbol$) IF place > 0 THEN symbol$ = MID$(Urus$, place, 1) ELSE 1 ... пользуемся UCASES symbo1$ = UCASE$(symbo1$) END IF 1 накапливаем значение во вспомогательной переменной temp$ = temp$ + symbols NEXT i 'присваиваем значение функции UCASERus$ = temp$ END FUNCTION Результат: ? Штирлиц вошел в лес и увидел ... ШТИРЛИЦ ВОШЕЛ В ЛЕС И УВИДЕЛ ... LTRIM$ LTRIM$ — символьная функция, возвращающая копию строки с удаленными начальными пробелами. 294
LTRIM$(символьное_выражение) пример: копирование текстового файла с удалением на- чальных и конечных пробелов. INPUT "Введите имя исходного файла: ", InFile$ INPUT "Введите имя получаемого файла: ", OutFile$ OPEN InFile$ FOR INPUT AS #1 OPEN OutFile$ FOR OUTPUT AS #2 ' Чтение, обработка и запись каждой строки DO WHILE NOT EOF(l) LINE INPUT #1, Lineln$ Lineln$ = LTRIM$(RTRIM$(LineIn$)) PRINT #2, Lineln$ LOOP CLOSE #1, #2 END RTRIM$ RTRIM$ — символьная функция, которая возвращает сим- вольную строку с удаленными правыми пробелами. RTRIM$(символьное_выражение) См. пример к функции LTRIM$. SPACES SPACES — символьная функция, возвращает строку пробе- лов длиной п. SPACE$(n) • п — числовое выражение в пределах 0—32767, количество пробелов в строке. Пример: CLS FOR i = 1 ТО 5 Х$ = SPACE$(i): PRINT X$; I NEXT i Вывод:_ 1 2 3 4 5 295
STRINGS STRINGS — символьная функция, возвращает строку запол- ненную символами данного ASCII-кода или данным символом. STRINGS(m,n) STRINGS(—m, символьное_выражение) • m — числовое выражение, длина строки; • п — числовое выражение в пределах 0—255, ASCII-код симво- ла-заполнителя строки; • символьное_выражение — указывает строку, первый символ которой используется для заполнения строки. Пример: Построение линейного графика. CLS PRINT " Рост удоев на ферме г.Нью-Васюки" PRINT FOR Month = 1 ТО 12 STEP 2 READ Month$, Temp 296
'Вывод Temp-3 5 звездочек. PRINT Month$; " +"; STRING$(Temp - 35, "*") PRINT " I" NEXT Month 'Вывод горизонтальной линии. PRINT " +"; FOR X = 1 TO 7 PRINT " +"; NEXT X PRINT 1 Вывод шкалы высоких удоев. FOR X = 4 ТО 39 STEP 5 PRINT TAB(X); X + 31; NEXT X PRINT DATA Янвр, 70, Март, 60, Май , 50 DATA Июль, 45, Сент, 50, Нояб, 40 1NSTR INSTR — символьная функция, возвращающая позицию первого вхождения подстроки в указанной строке. INSTR([начало,]строка1,строка2) • начало — условное смещение от начала строки, устанавливающее позицию начала поиска. Число в пределах 1—32767. Если не зада- но, функция INSTR начинает поиск с первого символа строки1; • строка 1 — строка, в которой производится поиск; • строка2 — искомая подстрока. Значение, возвращаемое INSTR зависит от следующих условий: Условие строка2 найдена в строке 1 начало больше длины строки 1 строка 1 — пустая строка строка2 не найдена строка2 — пустая строка Значение позиция, с которой строка2 на- чинается в строке1 0 0 0 начало (если есть), иначе I 297
Пример: определить, пол человека, если дано полное английское написание фамилии. CLS DO INPUT "Введите имя: ", Nm$ LOOP UNTIL LEN(Nm$) >= 3 Nm$ = UCASE$(Nm$) 1 Ищем MS, MRS, или MR для установки Sex$. IF INSTR(Nm$, "MS") > 0 OR INSTR(Nm$, "MRS") > 0 THEN Sex$ = "W" ELSEIF INSTR(Nm$, "MR") > 0 THEN Sex$ = "M" ELSE ' Невозможно определить, лучше спросим. DO INPUT "Введите пол (M/W): ", Sex$ Sex$ = UCASE$(Sex$) LOOP WHILE Sex$ <> "M" AND Sex$ <> "W" END IF IF Sex$ = "M" THEN PRINT "Джентльмен" ELSE PRINT "Леди" Вывод: Введите имя: Mrs. Higgins Леди Введите имя: Col. Pickering Введите пол (M/W): М Джентльмен LEFTS LEFTS — символьная функция, возвращающая строку, со- держащую п левых символов исходной строки. LEFT$(символьное_выражение, п) • символьное_выражение — исходная строка; • п — числовое выражение в пределах 0—32767. Если п = 0, возвращается пустая строка. Пример: CLS А$ = "QuickBASIC Forever ! " В$ = LEFT$(A$, 5) PRINT B$ Вывод: Quick 298
299 RIGHTS RIGHTS — символьная функция, возвращающая правые п символов символьной строки. RIGHT$(символьное_выражение, п) • символьное_выражение — исходная строка; • п — числовое выражение от 0 до 32767, указывающее сколько символов справа требуется взять. Если п = 0, возвращается пу- стая строка. Пример: преобразование имени вида "Имя Фамилия* в форму "Фамилия, Имя". CLS LINE INPUT "Имя: "; Nm$ Sppos = INSTRfl, Nm$, » ») IF Sppos = 0 THEN PRINT Nm$ 'Введена только фамилия. ELSE Lastname$ = RIGHT$(Nm$, LEN(Nm$) - Sppos) Firstname$ = LEFT$(Nm$, Sppos - 1) PRINT Lastname$; " ,"; Firstname$ END IF END Результат: Имя: Билл Гейтс Гейтс, Вилл МЮ$ (функция) МШ$ — символьная функция, возвращающая фрагмент ука- занной строки. MID$(символьное_выражение,начало[,длина]) • символьное_выражение — исходная строка; • начало — числовое выражение от 1 до 32767, начальная сим- вольная позиция фрагмента данной строки; • длина — длина фрагмента.
Если длина опущена или количество символов от начала до конца строки меньше длины, то функция МГО$ возвращает фрагмент от начала до конца строки. Если начало больше, чем длина символьного выражения, MID$ возвращает пустую строку. Пример: использование MID$ для преобразования двоич- ного числа в десятичную форму. CLS INPUT "Введите двоичное число =", Binary$ Length = LEN(Binary$) Decimal = 0 FOR k = 1 TO Length 1 Извлечение единиц и нулей. Digit$ = MID$(Binary$, k, 1) IF Digit$ = " OR Digit$ = " THEN 1 Преобразование в десятичное число. Decimal = 2 * Decimal + VAL(Digit$) ELSE PRINT "Неверно введено число: "; Digit$ EXIT FOR END IF NEXT k PRINT "Десятичное число = "; Decimal Вывод: Введите двоичное число = 10110 Десятичное число =22 МЮ$ (оператор) MID$ — символьный оператор, заменяющий фрагмент стро- ки на содержимое другой строки. MID$(строка, начало[,длина]) = символьное_выражение • строка — символьная переменная, в которой требуется произ- вести изменения; • начало — числовое выражение, определяющее начальную по- зицию в исходной строке, с которой производится замена; • длина — количество символов из символьного выражения; • символьное_выражение — представляет новые символы. Аргументы начало и длина — целые выражения. Аргумент строка должен быть только символьной переменной, но сим- 300
вольное выражение может быть переменной, константой или вы- ражением. Если длина опущена, то производится замена полным со- держимым символьного выражения. Если длина задана, то про- изводится замена указанным количеством символов слева из символьного выражения. Заменяемый фрагмент не может превы- сить текущей длины переменной. Пример: CLS Test$ = "Париж, Франция " PRINT Test$ MID$(Test$, 7, 8)= "шт.Техас" PRINT Test$ Paris, Франция Paris, шт.Техас НЕХ$ НЕХ$ — символьная функция, возвращающая шестнадцате- ричное представление десятичного аргумента. НЕХ$(выражение) • выражение — любое выражение, имеющее десятичное значение. CLS INPUT X А$ = НЕХ$(Х) PRINT X; "в десятичной форме — это"; А$; " в шестнадцате- ричной" Вывод: ? 32 32 в десятичной форме - это 20 в шестнадцатеричной ост$ ОСТ$ — символьная функция, возвращающая символьное представление восьмеричного значения аргумента. 301
ОСТ$(числовое_выражение) • числовое_выражение — может быть любого типа. STR$ STR$ — символьная функция, возвращает символьное пред- ставление числа или числового выражения. STR$(числовое_выражение) Если числовое выражение положительно, строка возвращается с начальным пробелом. Превращение числа в символьное выра- жение позволяет производить над ним те же действия, что и с символьной строкой: складывать, выделять фрагменты числа, за- менять, форматировать и т. д. Пример: CLS Profit% = 50000 PRINT "Прибыль составила" + STR$(Profit%) + ".00 рублей" Результат: Прибыль составила 50000.00 рублей LEN LEN — символьная функция, возвращающая количество символов данной строки или количество байт, занимаемых пере- менной. п = ЬЕЫ(символьное_выражение) n = LEN(переменная) • символьное_выражение — строка символов; • переменная — объект любого типа, для которого требуется уз- нать занимаемый объем памяти. Пример: определение длины переменных различных типов (байт). TYPE EmpRec EmpName AS STRING * 2 EmpNum AS INTEGER END TYPE 302
DIM A AS INTEGER, В AS LONG, С AS SINGLE, D AS DOUBLE DIM E AS EmpRec PRINT "Строка символов: "; LEN("Строка") PRINT "Целое число: "; LEN(A) PRINT "Длинное целое: "; LEN(В) PRINT "Обычной точности: "; LEN(С) PRINT "Двойной точности: "; LEN(D) PRINT "Запись типа EmpRec: "; LEN(E) END Вывод: Строка символов: б Целое число: 2 Длинное целое: 4 Обычной точности: 4 Двойной точности: 8 Запись типа EmpRec: 22
От Издательства Данная книга, изданная впервые в 1994 году для широкого круга профессионалов и любителей языка QuickBASIC 4.5, приобрела большую популярность в ВУЗах, колледжах, школах и лицеях страны. Не будучи изначально кано- ническим учебником, она переиздается в качестве пособия ввиду острой пот- ребности учебных заведений в литературе по языкам программирования. Издательство, заинтересованое в усовер- шенствовании книги, с благодарностью примет все критические замечания, советы и пожелания педагогов и учащихся.
Доступ к абсолютным адресам (*) DEF SEG DEF SEG — оператор управления памятью, устанавливаю- щий текущий сегментный адрес для выполнения операторов PEEK, BLOAD, BSAVE, CALL ABSOLUTE, POKE. DEF SEG [= адрес] • адрес — целое выражение в интервале от 0 до 65535, указыва- ющее сегментный адрес. После выполнения оператора DEF SEG = адрес, необходимо выполнить оператор DEF SEG без параметров, для установления текущего сегментного адреса самого языка. Иначе продолжение выполнения программы будет просто диверсией против работы BASIC: DEF SEG = О DEF SEG PEEK PEEK — функция памяти, возвращающая байт, размещен- ный в памяти по указанному адресу. РЕЕК(адрес)
• адрес — числовое выражение от 0 до 65535, смещение относи- тельно текущего сегмента памяти, установленного оператором DEF SEG. Пример использования оператора РЕЕК приведен ниже, в разделе "Доступ к клавишам-переключателям и модификаторам". РОНЕ РОКЕ — оператор памяти, записывающий байт по данному адресу. РОКЕ адрес, байт • адрес — числовое выражение от 0 до 65535, смещение относи- тельно текущего сегмента памяти, установленного оператором DEF SEG; • байт — числовое целое выражение от 0 до 255, данные, запи- сываемые по данному адресу памяти. Пример использования оператора РОКЕ приведен ниже, в разделе "Доступ к клавишам-переключателям и модификаторам". SADD SADD — функция памяти, возвращающая адрес указанной символьной переменной. Часто используется для передачи пара- метров в процедуру, написанную на другом языке, или для вызо- ва процедуры в машинных кодах, записанной в символьную строку. SADD(символьная_переменная) • символьнаяпеременная — указывает символьную перемен- ную, размещение в памяти которой требуется узнать. Функция SADD возвращает адрес символьной строки как смещение (ближняя адресация) от текущего сегмента данных. Это двухбайтовое целое число. SADD часто используется в про- граммировании на разных языках. Аргумент может быть символьной переменной или элемен- тов символьного массива. Нельзя использовать строки фиксиро- ванной длины. 306
Вызывайте функцию осторожно, так как строки могут пере- мещаться в пределах памяти при выполнении символьных опера- торов и функций. Не добавляйте символов в начало или конец строки, переда- ваемой функциям SADD и LEN — это может вызвать ошибку при работе программы. SETMEM SETMEM — функция памяти, изменяющая размер памяти, используемой дальними объектами — динамическими массивами и внешними таблицами. SETMEM(числовое_выражение) • числовое_выражение — имеет значение большее, меньшее или равное нулю. Оно указывает, на сколько байт увеличить или уменьшить дальнюю память. Если числовое выражение отрицательно, SETMEM уменьша- ет используемую память на указанное количество байт, а если положительно, то SETMEM пытается увеличить используемую память на указанное количество байт SETMEM возвращает общее число байт дальней памяти. Ес- ли числовое выражение равно нулю, он возвращает текущее зна- чение памяти. Если SETMEM не может изменить дальнюю память на ука- занное количество байт, он добавляет или отнимает столько байт, сколько возможно. SETMEM может использоваться в смешанном программиро- вании для уменьшения дальней памяти, если другому языку тре- буется динамически разместить переменные в этой памяти. Первый запуск SETMEM не увеличит дальнюю память, так как программы выделяют всю память для дальних объектов при запуске. VARPTR и VARSEG VARPTR и VARSEG — функции памяти, возвращающие ад- рес переменной. VARPTR(переменная) VARSEG(переменная) 307
• переменная — может быть любого типа, включая записи или элементы записей. Функция VARSEG возвращает сегментный адрес переменной в виде целого числа без знака. Функция VARPTR возвращает смещение относительно сегментного адреса как целое число без знака. Если переменная не была определена до вызова VARPTR или VARSEG, она создается и возвращается ее адрес. Если пере- менная является символьной, функции VARPTR и VARSEG воз- вращают адрес первого байта описателя. Не используйте значения, возвращенные VARPTR и VARSEG после выполнения операторов и вызовов функций, так как многие операторы BASIC изменяют местоположение пере- менных в памяти. VARPTR и VARSEG часто используются с BLOAD, BSAVE, CALL ABSOLUTE, CALL INTERRUPT, PEEK, POKE или для передачи адресов массивов в процедуры, написанные на других языках. Для получения адреса массива задавайте в качестве аргумента функций его первый элемент. Его адрес — это адрес начала раз- мещения массива в памяти: DIM AA50) ArrAddress = VARPTR(AA)) вы должны вызвать обе функции для получения полного ад- реса переменной, особенно, если она может иметь дальний адрес, так как одна VARPTR выдает адреса переменных, размещенных только в DGROUP (ближние адреса — в пределах 64К сегмента данных). VARPTR$ VARPTRS — функция памяти, возвращающая символьное представление адреса переменной для использования в операто- рах DRAW и PLAY. VARPTR$(переменная) • переменная — имя переменной для операторов DRAW и PLAY Если переменная является элементом массива, он должен быть определен до вызова VARPTRS как символьный, перемен- ной длины. 308
Так как многие операторы языка QuickBASIC изменяют мес- тоположение переменных в памяти, не используйте значения, возвращенные VARPTRS после выполнения символьных опера- торов и вызовов функций. Пример: использование VARPTRS в операторе PLAY. SCALE$ = "CDEFGAB" PLAY "oO X" + VARPTR$(SCALE$) FOR l = 1 TO б PLAY ">X" + VARPTR$(SCALE$) NEXT l PLAY "Об X" + VARPTR$(SCALE$) FOR l = 1 TO 6 PLAY "<X" + VARPTR$(SCALE$) NEXT I Доступ к клавишам-переключателям и модификаторам При помощи операторов DEF SEG, РЕЕК и РОКЕ можно программным образом определять и изменять состояние клавиш- переключателей ({NUM LOCK}, {CAPS LOCK}, {SCROLL LOCK} и {INSERT}) и клавиш-модификаторов ({ALT}, {CTRL} и {SHIFT}). Для этого необходимо прочитать два байта памяти с адресами &Н417 и &Н418. После этого необходимо сразу же вос- становить текущий сегментный адрес BASIC, выполнив оператор DEF SEG без параметров: DEF SEG = О с = РЕЕК(&Н417) d = РЕЕК(&Н418) DEF SEG Если условие IF с AND a THEN ... истинно, то мы можем "разветвиться" в зависимости от значения переменной а: 128 — включен режим INSERT; 64 — включен режим CAPS LOCK; 32 — включен режим NUM LOCK; 16 — включен режим SCROLL LOCK; 309
8 — в данный момент нажата клавиша {ALT}; 4 — в данный момент нажата клавиша {CTRL}; 2 — в данный момент нажата левая клавиша {SHIFT}; 1 — в данный момент нажата правая клавиша {SHIFT}. Если же истинно условие IF d AND a THEN ... то, в зависимости от значения переменной а: 128 — в данный момент нажата клавиша {INSERT}; 64 — в данный момент нажата клавиша {CAPS LOCK}; 32 — в данный момент нажата клавиша {NUM LOCK}; 16 — в данный момент нажата клавиша {SCROLL LOCK}. В программе можно предусмотреть изменение состояния ключевых клавиш. Для этого надо считать значение байта &Н417, изменить его и вновь передать в память:1 1 Включение режима DEF SEG = О POKE &H417, РЕЕК(&Н417) OR a DEF SEG 1 Выключение режима DEF SEG = О POKE &H417, РЕЕК(&Н417) AND f DEF SEG Значение переменных а и f показаны ниже: Клавиша a f {INSERT} 128 127 {CAPS LOCK} 64 191 1 У компьютеров класса XT связь клавиатуры с системным блоком односто- ронняя, поэтому при изменении состояния ключей {CAPS LOCK}, {NUM LOCK} или {SCROLL LOCK} в программе, лампочки этих клавиш не загорают- ся. У компьютеров класса AT и выше — связь двусторонняя, и лампочки всегда показывают правильное состояние соответствующего ключа, в независимости от того, изменялось или оно в программе или просто нажатием на клавишу 310
{NUM LOCK} 32 223 {SCROLL LOCK} 16 239 Пример. Использование операторов DEF SEG, PEEK и POKE для программного управления клавишами-переключателями. DEFINT A-Z CLS PRINT "Клавиша Num Lock включена" DEF SEG = 0 POKE &H417, PEEK(&H417) OR 32 DEF SEG DO: LOOP WHILE INKEY$ = PRINT "Клавиша Num Lock выключена": PRINT DEF SEG = 0 POKE &H417, PEEK(&H417) AND 223 DEF SEG DO: LOOP WHILE INKEY$ = "" PRINT "Клавиша Caps Lock включена" DEF SEG = 0 POKE &H417, PEEK(&H417) OR 64 DEF SEG DO: LOOP WHILE INKEY$ = PRINT "Клавиша Caps Lock выключена": PRINT DEF SEG = 0 POKE &H417, PEEK(&H417) AND 191 DEF SEG DO: LOOP WHILE INKEY$ = PRINT "Клавиша Scroll Lock включена" DEF SEG = 0 POKE &H417, PEEK(&H417) OR 16 DEF SEG DO: LOOP WHILE INKEY$ = "" PRINT "Клавиша Scroll Lock выключена": PRINT PRINT DEF SEG = 0 POKE &H417, PEEK(&H417) AND 239 DEF SEG DO: LOOP WHILE INKEY$ = "" 311
От Издательства Данная книга, изданная впервые в 1994 году для широкого круга профессионалов и любителей языка QuickBASIC 4.5, приобрела большую популярность в ВУЗах, колледжах, школах и лицеях страны. Не будучи изначально кано- ническим учебником, она переиздается в качестве пособия ввиду острой пот- ребности учебных заведений в литературе по языкам программирования. Издательство, заинтересованое в усовер- шенствовании книги, с благодарностью примет все критические замечания, советы и пожелания педагогов и учащихся.
10 ОТСЛЕЖИВАНИЕ СОБЫТИЙ, ОБРАБОТКА ОШИБОК И ТРАССИРОВКА (*) Отслеживание событий ON COM(n) ON COM(n) — оператор отслеживания событий, передаю- щий управление подпрограмме при получении символов через коммуникационный порт п. ON COM(n) GOSUB метка • п — числовое выражение, номер коммуникационного порта; • метка — первая строка подпрограммы обработки события. Если ваша программа получает данные через асинхронный коммуникационный адаптер, то используйте опцию /С при за- пуске QuickBASIC или компиляции для установления размера буфера данных. СОМ(п) СОМ(п) — оператор отслеживания событий, который вклю- чает, выключает или приостанавливает отслеживание коммуни- кационной активности порта ввода/вывода.
COM(n) ON COM(n) OFF COM(n) STOP • n — номер коммуникационного порта, 1 или 2. COM ON включает отслеживание порта. Если символ при- бывает в СОМ-порт, выполняется подпрограмма, указанная опе- ратором ON COM. COM OFF выключает отслеживание. COM STOP приостанавливает отслеживание порта до вы- полнения оператора COM ON. Все события запоминаются в бу- фере и обрабатываются после следующего оператора COM ON. ON KEY(n) ON KEY(n) — оператор отслеживания событий, передающий управление подпрограмме при нажатии клавиши п. ON KEY(n) GOSUB метка • п — целое выражение, номер функциональной или пользова- тельской клавиши; • метка — первая строка подпрограммы обработки данного со- бытия. Клавиши обрабатываются в следующем порядке: 1. Клавиши переключения вывода на принтер. 2. Функциональные и клавиши управления курсором. 3. Клавиши, определенные пользователем. Оператор ON KEY может обрабатывать любую клавишу, за исключением {CTRL-BREAK} или {CTRL-ALT-DEL}. Старайтесь не использовать оператор ON KEY (и другие опе- раторы отслеживания событий) без особой необходимости. Дело в том, что при компиляции программы, в которой содержится от- слеживание событий, BASIC расставляет запрос к своей внутрен- ней процедуре отслеживания после каждого оператора программы, что приводит к значительному замедлению работы программы, увеличению размеров .ЕХЕ файла, и, при большом размере исход- ного текста может не всегда правильно срабатывать. В большинстве случаев применения отслеживания событий связано к контролем нажатия клавиш управления (функци- 314
ональных, клавиш управления курсором и прочих), что значи- тельно проще и удобнее может быть реализовано с помощью оператора INKEY$ в режиме опроса клавиатуры. Пример 1: Отслеживание нажатия клавиши {F1} с помощью оператора ON KEY. Если вы хотите, чтобы Ваша програм- ма выполнялась быстро и безошибочно, избегайте таких приемов. DEFINT A-Z 'Устанавливаем отслеживания ON KEY(l) GOSUB Keytrap 'Разрешаем его KEYA) ON CLS PRINT "Для выхода нажмите клавишу F10" DO: DO: a$ = INKEY$: LOOP WHILE a$ = " " IF LEN(a$) > 1 THEN kod = ASC(RIGHT$(a$, 1)) END IF LOOP WHILE kod о 68 END Keytrap: BEEP: PRINT "Обработка клавиши Fl" RETURN Пример 2: Отслеживание нажатия клавиши {Fl} с помощью оператора INKEY$. Выделяйте фрагмент, отвечающий за чтение кода нажатой клавиши, в отдельную процедуру. DEFINT A-Z DECLARE SUB ink (kod%) CLS PRINT "Для выхода нажмите клавишу F10" DO 'процедура чтения кода клавиши ink kod IF kod = 59 THEN BEEP: PRINT "Отработка клавиши Fl" IF kod =68 THEN EXIT DO LOOP END SUB ink (kod) DO DO: a$ = INKEY$: LOOP WHILE a$ = "" IF LEN(a$) > 1 THEN kod = ASC(RIGHT$(a$, 1)): EXIT SUB END IF LOOP END SUB 315
KEY KEY — оператор ввода/вывода, присваивающий символьные строки функциональным клавишам, а также показывающий те- кущий статус функциональных клавиш. KEY LIST Выводит значения F-клавиш. KEY {ON I OFF} Включает/выключает строку статуса F-клавиш внизу экрана. KEY n, строка Присваивает значение F-клавише. • п — номер функциональной клавиши, выбираемый из списка: 1-10 Функциональные F1-F10 11 Стрелка вверх 12 Стрелка влево 13 Стрелка вправо на расширенной клавиатуре 14 Стрелка вниз 15-25 Пользовательские 30-31 Функциональные F11-F12 • строка — для всех п, исключая 15—25, это строка, вводимая программой при нажатии данной клавиши. До 15 символов. Для п = 15—25, строка имеет следующий вид: СШ$(флаг) + CHR$ (скан-код) Присвоение пустой строки клавише выключает ее. Мож- но посмотреть значения клавиш путем KEY ON, KEY OFF и KEY LIST: 316
Опе- ратор KEY ON KEY OFF KEY LIST Действие Показывает 6 первых символов значений F-клавиш в нижней строке экрана Стирает демонстрацию F-клавиш из нижней строки, делая ее свободной для использования. Не стирает зна- чения клавиш Показывает 15 символов всех определенных операто- ром KEY клавиш Если подобная клавиша нажата, эффект от нее такой же, как и от набора данной строки с клавиатуры. Их могут читать опера- торы INPUTS, INPUT и INKEYS. Пример: ' Присвоение значений программируемым клавишам. CLS KEY 4, "MENU" + CHR$A3) 'Присвоение F4 KEY LIST KEY 4, "" 'Отмена F4. KEY LIST 'Присвоение клавишам Fl - F3 значений опций меню. CLS DIM KeyText$C) DATA Добавить, Стереть, Выход FOR i = 1 TO 3 READ KeyText$(i) KEY i, KeyText$(i) + CHR$A3) NEXT I 1 Вывод меню. PRINT " Главное Меню" : PRINT PRINT " Добавить (Fl)" PRINT " Стереть (F2)" PRINT " Выход (F3)" : PRINT 'Выбор опции из меню. DO LOCATE 7,1 : PRINT SPACE$E0) LOCATE 7,1 : INPUT " Ваш выбор: ", R$ SELECT CASE R$ CASE "Добавить", "Стереть" LOCATE 10,1 : PRINT SPACE$A5); LOCATE 10,1 : PRINT R$; CASE "Выход" EXIT DO CASE ELSE LOCATE 10,1 PRINT "Введите слово или нажмите клавишу." END SELECT LOOP 317
KEY(n) KEY(n) — оператор отслеживания операций, включающий, выключающий или останавливающий отслеживание указанной F- клавиши. KEY(n) ON KEY(n) OFF KEY(n) STOP • KEY(n) ON — включает отслеживание клавиши оператором ON KEY; • KEY(n) OFF — выключает отслеживание. Если клавиша была уже нажата, она не запоминается; • KEY(n) STOP — приостанавливает отслеживание. Если кла- виша была нажата, она запоминается, и после включения опе- ратором KEY(n) ON выполняется действие, связанное с дан- ной клавишей оператором ON KEY. Аргумент п описан выше, в комментарии к оператору KEY. Здесь дано описание флагов клавиатуры и скан-кодов, необходи- мых для отслеживания клавиш, определенных пользователем. Флаги клавиатуры имеют следующие значения: &Н00 нет флага &Н01-&Н03 SHIFT &Н04 CTRL &Н08 ALT &Н20 NUMLOCK &H40 CAPSLOCK &H80 добавочные клавиши расширенной клавиатуры Можно сложить значения флагов для одновременно нажатых клавиш. Значение флага &Н12 означает, что будет тестироваться нажатие CTRL+ALT. Так как отслеживание клавиш подразумевает, что левый и правый SHIFT — это одно и то же, можно использовать флаги &Н01, &Н02 или &Н03 для указания клавиши SHIFT. 318
Пример: отслеживание клавиши "Стрелка вниз" и комбинации {CTRL-s} i = О CLS PRINT "Клавиша {DOWN} - конец работы " KEY 15, CHR$(&H04) + CHR$(&Hlf) KEYA5) ON 'Отслеживание CTRL+s. KEYA4) ON 'Отслеживание DOWN. ON KEYA5) GOSUB Keytrap ON KEYA4) GOSUB Endprog DO: LOOP 'Бесконечный цикл Keytrap: 'Подсчет числа нажатий {CTRL-s} i = i + 1 RETURN Endprog: PRINT "Клавиша {CTRL-s} нажата"; i; "раз" END RETURN ON PEN ON PEN — оператор отслеживания событий, передающий управ- ление подпрограмме при получении сигнала от светового пера. ON PEN GOSUB метка • метка — первая строка подпрограммы обработки события. PEN ON, PEN OFF, PEN STOP PEN ON, PEN OFF, PEN STOP — операторы отслеживания событий, включающие, выключающие и приостанавливающие отслеживание светового пера. • Оператор PEN ON включает отслеживание светового пера коман- дой ON PEN. По умолчанию перо выключено. Событие происхо- дит при нажатии пером экрана или нажатии специального кольца на световом пере. Оператор PEN ON должен быть выполнен пе- ред всеми вызовами функций чтения пера, иначе возникает ошибка "Illegal function call" (Неверный вызов функции); 319
• Оператор PEN OFF выключает отслеживание светового пера; • Оператор PEN STOP приостанавливает отслеживание; при этом все, что касается светового пера запоминается и выпол- няется при включении отслеживания. Для ускорения выполнения программы световое перо должно быть выключено оператором PEN OFF, если не нужно его отсле- живание. Световое перо требует, как минимум, адаптера IBM CGA. В настоящее время световое перо практически не использу- ется в связи с повсеместным распространением "мышей" и трек- болов1 . См. Глава 12, раздел "Интерфейс с драйвером мыши". ON PLAY(n) ON PLAY(n) — оператор отслеживания событий, передаю- щий управление подпрограмме по окончании звучания нот. ON PLAY(лимит) GOSUB метка • лимит — целое выражение, минимальное количество нот, зву- чащих в фоновом режиме (от 1 до 32); • метка — первая строка подпрограммы, принимающей управление. Учтите следующие моменты: 1. Обработка не производится, если фоновое исполнение музыки не закончилось; 2. Если лимит — достаточно большое число, это замедляет прог- рамму. PLAY PLAY — оператор отслеживания событий, возвращающий число нот, находящихся в фоновом музыкальном буфере. PLAY(n) • п — любой числовой параметр. 1 "Мышь", лежащая на спине, с большим шариком, который двигают рука- ми. 320
PLAY(n) возвращает 0, если музыка исполняется в основном (не фоновом) режиме. PLAY ON, PLAY OFF, PLAY STOP PLAY ON, PLAY OFF, PLAY STOP — операторы отслежива- ния событий, включающие, выключающие и приостанавлива- ющие отслеживание звучания музыки. • PLAY ON — включает отслеживание оператором ON PLAY; • PLAY OFF — выключает отслеживание. Если событие насту- пило, оно не запоминается; • PLAY STOP — приостанавливает отслеживание. Если событие наступило, оно запоминается, и оператор ON PLAY выполня- ется при включении отслеживания оператором PLAY ON. Эти операторы используются совместно с оператором ON PLAY для отслеживания событий музыкального буфера. При возникновении события выполняется подпрограмма, указанная оператором ON PLAY; при этом автоматически отсле- живание приостанавливается во избежание рекурсивного вызова подпрограммы-обработчика (что не должно иметь места). При выходе из подпрограммы путем RETURN, отслеживание возоб- новляется. Пример: программа играет музыку вызывая подпрограмму обработки события. Событие наступает, когда в музы- кальном буфере осталось менее 3 нот. ON PLAYC) GOSUB Background 1 Включение отслеживания. PLAY ON 1 Строка, содержащая мелодию. Lizzie$ = "оЗ L8 Е D+ Е D+ Е о2 В оЗ D С L2 о2 А" 1 Мелодия играется в первый раз. PLAY "MB X" + VARPTR$(Lizzie$) ' Продолжать до нажатия клавиши. LOCATE 2,1: PRINT "Нажмите клавишу для остановки" DO WHILE INKEY$ = "": LOOP END ' Подпрограмма. Background: ' Счетчик вызова подпрограммы. Count% = Count% + 1 LOCATE 1, 1 321
PRINT "Подпрограмма вызвана "; Count%; "раз" 1 Исполнить музыку еще раз как фоновую. PLAY "MB X" + VARPTR$(Lizzie$) RETURN ON STRIG(n) ON STRIG(n) — оператор отслеживания событий, указыва- ющий на подпрограмму обработки нажатия кнопки джойстика с триггером п. ON STRIG(n) GOSUB метка • n — номер триггера: О = нижняя кнопка 1-го джойстика 2 = нижняя кнопка 2-го джойстика 4 = верхняя кнопка 1-го джойстика 6 = верхняя кнопка 2-го джойстика • метка — первая строка подпрограммы обработки нажатия кно- пки джойстика. ON TIMER(n) ON TIMER(n) — оператор отслеживания событий. Указывает на подпрограмму, которая выполняется по прошествии п секунд. ON TIMER(n) GOSUB метка • n — числовое выражение от 1 до 86400 — число секунд интер- вала времени; • метка — первая строка подпрограммы обработки временного события. TIMER ON, TIMER OFF, TIMER STOP TIMER ON, TIMER OFF, TIMER STOP - операторы отсле- живания событий, включающие, выключающие, приостанавли- вающие отслеживание таймера. • TIMER ON — включает отслеживание таймера оператором ON TIMER. Пока отслеживание включено, проверка наступ- ления указанного времени делается после каждого оператора. 322
Если время наступило, выполняется подпрограмма обработки события, указанная оператором ON TIMER; • TIMER OFF — выключает отслеживание. Если событие имело место, оно не запоминается для оператора TIMER ON; • TIMER STOP — приостанавливает отслеживание. Если собы- тие произошло, то оно запоминается, и оператор ON TIMER запускает свою подпрограмму при включении отслеживания оператором TIMER ON. Пример: программа рисует случайным образом выбранную ломаную линию каждые 3 секунды. SCREEN 9 DEFINT A-Z DIM Х(б), YF) TIMER ON 'Включение отслеживания ON TIMERC) GOSUB Drawpoly PRINT "Нажмите любую клавишу для остановки" INPUT "Нажмите {ENTER} для начала ...",Test$ DO: LOOP WHILE INKEY$ = "" END Drawpoly: CLS n = INTE * RND + 2)'Случайное число от 2 до б. FOR i = О ТО п X(i) = INT(RND * 649)'Координаты вершин ломаной линии. Y(i) = INT(RND * 349) NEXT PSET (X(n), Y(n)) FOR i = 0 TO n LINE -(X(i), Y(i)), 15 NEXT RETURN ON UEVENT ON UEVENT — оператор отслеживания событий, указываю- щий на обработчик пользовательского события. ON UEVENT GOSUB метка • метка — первая строка подпрограммы обработки пользова- тельского события. 323
Обычно пользовательским событием служит аппаратное пре- рывание. Это дает событиям, определенным пользователем, те же возможности, что и событиям типа COM, KEY, и др. Если эти события определены оператором ON, они обрабатываются как прерывания. Поэтому программе не обязательно следить за каж- дым своим шагом: при возникновении подобного события она передает управление подпрограмме-обработчику. Необходимо вставить в программу три фрагмента для уста- новки пользовательского события: 1. Процедуру сервиса прерывания. 2. Процедуру инициализации для установки адреса сервисной процедуры в таблице векторов прерываний. 3. Подпрограмму обработки данных, собранных сервисной про- цедурой. Если процедура инициализации перехватит прерывание, ис- пользуемое другой сервисной процедурой, ее адрес должен быть восстановлен перед завершением Вашей программы. Обычно эти процедуры пишутся на языке ассемблера. Мож- но использовать другие языки, позволяющие генерировать сер- висные процедуры для обработки прерываний. Таким образом, существует четыре шага для генерации пользовательского события: 1. Написать подпрограмму обработки события на BASIC. 2. Выполнить оператор ON UEVENT GOSUB для определения подпрограммы-обработчика. 3. Выполнить оператор UEVENT ON для включения отслеживания. 4. Вызвать процедуру инициализации прерывания для установки адреса сервисной процедуры в таблице векторов прерываний. При возникновении прерывания управление передается сер- висной процедуре, которая собирает и размещает необходимые данные в памяти. Далее эта процедура вызывает процедуру SetUEvent, которая устанавливает флаг, распознаваемый про- граммой перед переходом к следующему оператору (или метке, если программа компилирована с ключом /W, а не /V). Когда флаг установлен, управление передается подпрограмме-обработ- чику, определенному ON EVENT GOSUB. Процедура SetUEvent является частью BASIC и автоматичес- ки включается в компилируемые модули или при запуске Quick BASIC с опцией /L в командной строке. Сервисная процедура 324
должна вызвать SetUEvent; это единственный способ, позволяю- щий вашей программе обработать событие. SetUEvent — не функция; она не возвращает значения в BASIC. UEVENT ON, UEVENT OFF, UEVENT STOP UEVENT ON, UEVENT OFF, UEVENT STOP - операторы от- слеживания событий, включающие, выключающие и приостанавли- вающие отслеживание события, определенного пользователем. Действия операторов UEVENT аналогичны действиям других операторов отслеживания событий. При выполнении UEVENT ON отслеживание включается и при возникновении события уп- равление передается подпрограмме-обработчику. При выпол- нении UEVENT OFF отслеживание выключается и все события игнорируются. При выполнении UEVENT STOP отслеживание приостанавливается. Все события запоминаются и обрабатыва- ются подпрограммой при выполнении оператора UEVENT ON. Пример: ON UEVENT GOSUB Event1 UEVENT ON INPUT "Введите число "; a IF a = 5 THEN CALL SetUevent END Event1: PRINT "Обработка события" RETURN Обработка ошибок и трассировка ON ERROR ON ERROR — оператор обработки ошибок, указывающий начало подпрограммы обработки ошибок, включающий отслежи- вание ошибок и передающий управление подпрограмме при их возникновении. ON ERROR GOTO метка I RESUME NEXT • метка — первая строка подпрограммы обработки ошибок; • RESUME NEXT — указывает, что при возникновении ошибок управление передается на следующий оператор. 325
Если обработчик не найден, выдается сообщение об ошибке и программа останавливается. Сообщение об ошибке зависит от типа ошибки. Коды ошибок приведены в Приложении 5 "ASCII- коды, скан-коды и коды ошибок". Метка 0 выключает отслеживание ошибок. Обработчик ошибок не может быть процедурой SUB или FUNCTION или функцией DEF FN, а только обычным блоком с меткой. Пример: реакция на ошибки при чтении файла. ON ERROR GOTO Handler OpenFile: INPUT "Введите имя файла"; FileSpec$ IF FileSpec$ = "" THEN END OPEN FileSpec$ FOR INPUT AS #1 PRINT "Первые 5 строк файла "; FileSpec$;" :" : PRINT FOR I = 1 TO 5 LINE INPUT #1, Temp$ PRINT Temp$ NEXT PRINT : INPUT "Это правильный файл Y/N "; R$ 1 Установим ошибку 200 при ответе N. IF UCASE$(R$) <> "Y" THEN ERROR 200 END Handler: Number = ERR 1 Если программа генерирует ошибку "файл не най- ден" , 1 выводим специальное сообщение. IF Number =53 THEN CLOSE #1 PRINT "Файл не найден." PRINT "Введите новое имя или нажмите" PRINT "{ENTER}, чтобы закончить программу." RESUME OpenFile ' Реакция на ответ N. ELSEIF Number = 200 THEN CLOSE #1 RESUME OpenFile ELSE ' Другая ошибка. Остановка программы. ERROR Number ON ERROR GOTO 0 END IF 326
ERDEV и ERDEV$ ERDEV и ERDEV$ — функции обработки ошибок, выдающие информацию об устройстве, в котором произошла ошибка. ERDEV ERDEV$ • ERDEV — целая функция, возвращающая код ошибки с пос- леднего устройства, в котором произошла ошибка; • ERDEV$ — символьная функция, возвращающая имя устрой- ства, в котором произошла ошибка. Если ошибка произошла на именованном устройстве (напри- мер принтер), то ERDEVS содержит 8-байтовое имя устройства. Если устройство не имеет имени, то 2-байтовое имя блока (А:, В: и т. д.). Значение ERDEV содержит информацию DOS об ошибке. Нижние 8 бит (первый байт) содержат код ошибки DOS, от 0 до 12. Верхние 8 бит (второй байт) содержат биты 15, 14, 13, XX, 3, 2, 1 и 0, являющиеся атрибутом устройства. XX указывает, что биты всегда нулевые. Пример: попытка чтения несуществующего файла или чте- ния файла с отсутствующего диска. DEFINT A-Z ' Указание на обработчик. ON ERROR GOTO ErrorHandler 1 Открытие файла, которого нет. OPEN "A:JUNK.DAT" FOR INPUT AS #1 END ' Блок обработки ошибок. ' Выводит значения ERDEV и ERDEV$. ' Производится остановка программы. ErrorHandler: PRINT "ERDEV = "; ERDEV PRINT "Устройство "; ERDEV$ ON ERROR GOTO 0 Вывод: при отсутствии диска А. 327
ERDEV = 2 Устройство А: ERL и ERR ERL и ERR — функции обработки ошибок, возвращающие информацию о возникшей ошибке. ERR ERL • ERR —функция, возвращающая код ошибки A — 255); • ERL — функция, возвращающая номер строки, где возникла ошибка. Функция ERL возвращает только номер строки, а не ее мет- ку. Если программа не имеет номеров строк, ERL возвратит 0. ERROR ERROR — оператор обработки ошибок, симулирующий воз- никновение ошибки и позволяющий пользователю тестировать программу путем задания ошибки по ее коду. ERROR целое_выражение • целое_выражение между 1 и 255 — код ошибки. Обработчик ошибок должен находится в главном модуле ва- шей программы1. Если вам нужно отрабатывать собственные коды ошибок, то используйте значения большие чем 255. RESUME RESUME — оператор обработки ошибок, продолжающий выполнение программы после обработки ошибочной ситуации. RESUME [0] RESUME NEXT 1 В Microsoft BASIC PDS 7 1 возможно также и отслеживание локальных ошибок при помощи оператора ON LOCAL ERROR GOTO .. При этот обработ- чик ошибок размещается в процедуре или функции. 328
RESUME метка Оператор RESUME [0] RESUME NEXT RESUME метка Действие Передает управление тому оператору, который вызвал ошибку. Оператор должен находиться в главном модуле, там же где и обработчик ошибок На следующий оператор после вызвавшего ошибку На оператор с данной меткой. Оператор RESUME, находящийся не в подпрограмме обра- ботки ошибок, вызывает ошибку "RESUME without error" (RE- SUME без ошибки). Если обработчик не имеет в конце RESUME, то выдается сообщение "No RESUME" (Нет RESUME). Пример: обработка наличия отрицательного аргумента при вызове функции извлечения квадратного корня SQR. CLS ON ERROR GOTO Handler FOR i = 4 TO -2 STEP -1 PRINT l, SQR(i) NEXT END Handler: PRINT "Аргумент отрицательный" RESUME NEXT Вывод: 4 2 3 1.7320509 2 1.4142136 1 1 0 0 -1 Аргумент отрицательный -2 Аргумент отрицательный TRON и TROFF TRON и TROFF — операторы трассировки выполнения программы. 329
TRON TROFF В среде QuickBASIC выполнение оператора TRON имеет та- кой же эффект, как выбор опции "Trace On" ("Трассировка включена") из МЕНЮ "DEBUG" (ОТЛАДКА) - каждый опера- тор высвечивается на экране. Оператор TROFF выключает трас- сировку. Операторы TRON и TROFF показывают номера строк в том случае, если программа скомпилирована с опцией Debug (/D).
11 СВЯЗЬ С DOS (*) Передача управления другой программе CHAIN CHAIN — оператор, передающий управление другой про- грамме ("по цепочке"). CHAIN имя_файла • имя_файла — символьное выражение, имя программы, кото- рой передается управление. Может включать путь длиной до 127 символов. Программы, работающие внутри среды QB должны иметь расширение .BAS (по умолчанию). Нельзя передавать управление файлам типов .СОМ и .ЕХЕ; Программы, имеющие расширение ЕХЕ могут передавать управление файлам .СОМ и .ЕХЕ, но не исходным файлам на BASIC (с расширением .BAS). Вы можете переслать переменные между программами, ис- пользуя оператор COMMON. Если вы компилируете программу вне среды QB в автономный ЕХЕ файл, то полученная программа не будет поддерживать передачу значений переменных при по- мощи COMMON. Существует три способа переслать переменные между "це- почными" программами вне среды QB:
1. Компилировать программу с опцией "Requiring BRUN45.EXE" (Требуется BRUN45.EXE); 2. Передавать параметры через временный дисковый файл; 3. Использовать межпрограмный 16-байтный буфер. Этот буфер специально предназначен для обмена сообщениями между программами: 'Файл programl.bas посылает сообщение Messages DIM Message$ AS STRING * 16 Message$ = "Тестовая строка" DEF SEG = 0 FOR i = 0 TO 15 POKE &H4F0 + i, ASC(MID$ (message$, i + 1. D) NEXT i DEF SEG CHAIN "program2" END 'Файл program2.bas считывает сообщение Message$: DIM Message$ AS STRING * 16 DEF SEG = 0 FOR i = 0 TO 15 MID$(messages, i + 1, 1) = CHR$(PEEK(&H4F0 + i)) NEXT i DEF SEG END Действие CHAIN и RUN в основном идентично. Отличия в том, что RUN закрывает все открытые файлы и не поддерживает блоки COMMON. Если программы скомпилированы как авто- номные ЕХЕ файлы, то открытые файлы перед вызовом другой программы должны быть закрыты оператором CLOSE. SHELL SHELL — оператор связи с DOS, применяемый для выхода из программы, запуска файла типа *.СОМ, *.ЕХЕ, *.ВАТ или ко- манды DOS, и возвращения в программу (временный выход в DOS). SHELL [команда] • если все аргументы опущены, DOS загрузит новую копию C0MMAND.COM, и можно вводить команды на приглаше- ние DOS; 332
• команда — символьное выражение, содержащее имя про- граммы для ее запуска или команду DOS, включая все необ- ходимые параметры. Любые файлы типа *.СОМ, *.ЕХЕ, *.ВАТ или функции DOS могут быть исполнены при вызове оператора SHELL, так как он со- здает "порожденный процесс". Такой процесс выполняется путем загрузки новой копии COMMAND.COM с опцией /С. Эта опция позволяет передать порожденному процессу значение командной строки. Она также позволяет переопределить стандартный ввод или вывод при выполнении таких команд, как DIR, PATH и SORT. Если в командной строке нет расширений файла, COM- MAND.COM ищет сначала файл типа *.СОМ, затем *.ЕХЕ, а по- том *.ВАТ. Если сам файл COMMAND.COM не найден, SHELL выдаст сообщение об ошибке "File not found" (Файл не найден). Но если C0MMAND.COM не найдет файл, указанный в команд- ной строке, то BASIC не выведет сообщения об ошибке. Любой текст, отделенный от имени программы хотя бы од- ним пробелом, воспринимается как строка параметров, пересы- лаемых программе. BASIC не освобождает память при исполнении порожденно- го процесса. При завершении процесса основная программа про- должается. Не загружайте таким образом резидентные программы. При возврате в среду QB область памяти, занятая резидентной про- граммой окажется занятой, что может привести к фрагментации оперативной памяти, ее нехватке, и сбоям в работе самого BASIC. Для возврата в программу введите команду EXIT. Пример: простой оператор SHELL подгружает новую копию командного процессора C0MMAND.COM. SHELL Novell DOS 7 Copyright (с) 1976, 1993 Novell, Inc. All rights reserved. C:\QB45>_ RUN RUN — оператор связи с DOS, перезапускающий программу, находящуюся в памяти или исполняющий указанную программу. 333
RUN [номер_строки I файл] • номер_строки — числовая метка, указывающая строку, с ко- торой начинается перезапуск. Если номер строки не указан, исполнение начинается с первой строки; • файл — символьное выражение, указывающее программу, ко- торую надо загрузить и запустить. Текущая программа удаля- ется из памяти. Строка, с которой начинается перезапуск, должна находить- ся на модульном уровне. Поэтому, оператор RUN в процедурах SUB или FUNCTION должен указывать на номер строки в мо- дульном коде. Если строка не указана, перезапуск начинается с первой ис- полняемой строки в главном модуле. Номер строки может быть только числовой меткой. Вы можете опустить расширение файла, если нужно загру- зить программу. В среде QB по умолчанию загружается файл .BAS, а в откомпилированной программе — файл .ЕХЕ, но не обязательно написанный на языке BASIC. Если вызванная программа закончила работу, управление не передается в исходную программу. В среде QB управление пе- редается среде, а в DOS — операционной системе. RUN закрывает все файлы и очищает память перед загрузкой программы. Используйте оператор CHAIN, если вы хотите оста- вить файлы открытыми. Пример: 10 А = 9 20 В = 7 30 С = 5 40 D = 4 50 PRINT А, В, С, D 60 IF A = 0 THEN 70 ELSE RUN 20 70 IF В = 0 THEN 80 ELSE RUN 30 80 IF С = 0 THEN 90 ELSE RUN 40 90 IF D = 0 THEN END ELSE RUN 50 Вывод: 9 0 0 0 0 7 7 0 0 0 5 5 5 0 0 4 4 4 4 0 334
Работа с датой и временем DATES (функция) DATES — функция, возвращающая строку, содержащую те- кущую системную дату. DATE$ • возвращается 10-символьная строка в форме ММ-ДД-ГГТТ ММ - месяц @1-12) ДД - день @1-31) ГГГГ - год A980-2099) Пример: PRINT DATE$ 10-30-1967 DATES (оператор) DATES — оператор, устанавливающий текущую систем- ную дату. DATE$ = символьное_выражение • символьноевыражение может иметь одну из следующих форм: мм-дд-гг ММ-ДД-ГГГГ мм/дд/гг, мм/дд/гггг где: • ММ — месяц • ДД — день • ГГ или ГГГГ — год 335
Пример: PRINT "Введите дату (по умолчанию 1994 год)." INPUT " Месяц: ",Month$ INPUT " Дата: ",Day$ INPUT " Год: ",Year$ IF Year$ = "" THEN Year$ = "94" DATE$ = Month$ + "-" + Day$ + "-" + Year$ TIMES (функция) TIMES — функция, возвращающая текущее системное время. Т1МЕ$ • возвращается 8-символьная строка в форме ЧЧ:ММ:СС ЧЧ - часы @0-23) ММ - минуты @0-59) СС - секунды @0-59) Пример: преобразование 24-часового представления вре- мени в 12-часовое. Т$ = Т1МЕ$ Hr = VAL(T$) IF Hr < 12 THEN Ampm$ = " AM" ELSE Arapm$ = " PM" IF Hr > 12 THEN Hr = Hr - 12 PRINT "Текущее время "; STR$(Hr); RIGHT$(T$,6); Ampm$ Текущее время 11:26:31 AM TIME$ (оператор) TIMES — оператор, устанавливающий текущее системное время. Т1МЕ$ = символьное_выражение • символьное_выражение — может иметь одну из форм: ЧЧ ЧЧ:ММ ЧЧ:ММ:СС 336
где: • ЧЧ — часы • ММ — минуты • СС — секунды Пример: установка текущего времени 8:00. Т1МЕ$ = 8:00:00" TIMER TIMER — функция, возвращающая число секунд, прошед- ших с полуночи. TIMER Обычно используется с оператором RANDOMIZE для уста- новки начального значения генератора случайных чисел. Пример: поиск первых простых чисел от 3 до 10000. Ис- пользуется принцип "Решето Эратосфена". Функция TIMER применяется для подсчета времени, затраченного на по- иск . DEFINT A-Z CONST Markit = -1 DIM Mark(lOOOO) CLS Start! = TIMER Num = 0 FOR n = 3 TO 10000 STEP 2 IF NOT Mark(n) THEN 'Если вам нужно вывести числа, удалите комментарий 'PRINT n. Delta = 2 - п FOR i = 3 - n TO 10000 STEP Delta Mark(i) = Markit NEXT Num = Num + 1 END IF NEXT Finish! = TIMER PRINT PRINT "Поиск продолжался"/Finish! - Start!; PRINT "сек. Найдено"; Num; "чисел." END Вывод: Поиск продолжался .109375 сек. Найдено 1228 чисел. 337
Работа с файловой системой CHDIR CHDIR — оператор, использующий DOS для смены текущей директории. CHDIR имя_пути • имя_пути — символьное выражение, определяющее директо- рию, которая должна стать текущей по умолчанию. Имя пути не должно превышать 64 символов. Например: [диск:][\]директория[Хдиректория]... CHDIR отличается от команды DOS CHDIR: • оператор не может быть сокращен до CD; • нет форм оператора, возвращающих значение текущей дирек- тории1 . CHDIR меняет директорию, но не меняет диск. Примеры: ' Переход в директорию \QB\BAS на текущем диске. CHDIR "\QB\BAS" ' Смена текущей директории на диске В. ' Переход на диск В не осуществляется. CHDIR "В:USERS" 1 Операторы работы с файловой системой значительно расширены в Microsoft BASIC PDS. В нем значительно проще стало переходить на другой диск (CHDRIVE), получать имя текущего каталога (CURDIRS) и список файлов за- данного каталога (DIRS). 338
MKDIR MKDIR — оператор, использующий DOS для создания но- вой директории. MKDIR путь • путь — символьное выражение, указывающее имя и местопо- ложение создаваемой директории. Его длина не должна пре- вышать 128 символов. Данный оператор работает аналогично команде DOS MKDIR, но не допускается сокращать его до MD. Пример: CLS PRINT "Эта программа создает директорию MONTHS," PRINT "а затем создает файл в этой директории." PRINT MKDIR "MONTHS" INPUT "Файл "; File$ IF File$ = "" THEN END OPEN "MONTHSV + File$ FOR OUTPUT AS #1 PRINT "Создан файл "; File$; " в директории MONTHS." CLOSE #1 RMDIR RMDIR — оператор связи с DOS, удаляющий существующую директорию. RMDIR путь • путь — символьное выражение, определяющее удаляемую ди- ректорию, не более 128 символов. Удаляемая директория должна быть пустой и существовать, иначе выдаются сообщения об ошибке "Path not found" (Путь не найден) или "Path/File access error" (Ошибка доступа к пути/ файлу). 339
RMDIR аналогичен команде DOS. Однако, его нельзя сокра- тить до RD как в DOS. Пример: CHDIR "C:\SALES\TEMP" 'Переходим в данную директорию KILL " * . * " 'Стираем все файлы CHDIR " . . " 'Переходим в старшую директорию RMDIR "TEMP" 'Стираем данную директорию FILES FILES — оператор связи с DOS, выдающий на экран имена файлов на указанном диске в указанной директории. FILES [спецификация] • спецификация — символьная переменная или константа, со- держащая имя файла, путь, диск. Можно использовать шабло- ны DOS (? или *). Если аргумент опущен, то на экран дисплея выдается список файлов текущей директории. Примеры: 'Показывает все файлы в текущей директории. FILES 1 Показывает все файлы с расширением BAS. FILES "*.BAS" 'Показывает все файлы на диске В. FILES "В:*.*" 1 Эквивалентно "В:*.*". FILES "В:11 'Показывает все файлы .BAS, имена которых имеют 'пять букв и начинаются символами "TEST". FILES "TEST?.BAS" 'Если SALES — директория, то показывает все 1 файлы в' этой директории. 'Если SALES — имя файла в текущей директории, 'показывает только файл SALES. FILES "\SALES" 340
KILL KILL — оператор, использующий DOS для стирания файла. KILL файл • файл — символьное выражение, указывающее файл, который нужно стереть. Может содержать путь. Соответствует команде DOS ERASE (DEL). Используется для всех типов файлов (кроме скрытых и только для чтения). Сим- вольное выражение может содержать шаблоны DOS: ? или *. Для стирания директорий используйте команду RMDIR. По- пытка стереть открытый файл приведет к ошибке и сообщению "File already open" (Файл уже открыт). Пример: стирание файлов. 'Стирает все файлы .DAT, имена которых состоят 1 из 6 букв и начинаются символами DATA1. KILL "DATA17.DAT" 'То же, но стираются файлы с любыми расширениями. KILL "DATA1.*" 'Стирает все файлы .DAT в директории GREG. KILL "\GREG\*.DAT" NAME NAME — оператор, использующий DOS для изменения име- ни файла. NAME старое_имя AS новое_имя • старое_имя — символьное выражение, имя существующего файла; • новоеимя — символьное выражение, имя еще не существую- щего файла. Эти аргументы могут содержать путь. Если оба аргумента имеют разные пути, данный оператор перемещает файл и пере- именовывает его. Оба файла должны находиться на одном диске, 341
в противном случае выдается сообщение об ошибке "Rename across disks" (Перемещение между дисками). Оператор соответствует команде DOS RENAME. NAME мо- жет переместить файл в другую директорию, но не может пере- местить всю директорию. Использование NAME для открытого файла приведет к со- общению об ошибке "File already open" (Файл уже открыт). Пример: переименование файла README.DOC. CLS 'Переименование README.DOC в READMINE.DOC NAME "README.DOC" AS "READMINE.DOC" FILES PRINT PRINT "README.DOC переименован в READMINE.DOC" PRINT "Нажмите любую клавишу" DO: LOOP WHILE INKEY$ = "" 1 Переименование обратно в README.DOC NAME "READMINE.DOC" AS "README.DOC" FILES PRINT PRINT "README.DOC восстановлен" Работа с окружением DOS COMMANDS COMMANDS — функция, возвращающая значение команд- ной строки DOS, заданной при запуске программы. COMMAND$ Функция COMMANDS возвращает полную командную строку, введенную после имени вашей программы, включая параметры оп- ций. COMMANDS удаляет все начальные пробелы из данной строки и преобразует все буквы в заглавные (верхний регистр). COMMANDS может быть использована .ЕХЕ-файлами, а в среде QB она может быть задана опцией /CMD при запуске BASIC или путем выбора из МЕНЮ "RUN" (ЗАПУСК) пункта меню "Modify COMMANDS" (Изменить переменную COM- MANDS). 342
Пример: Включение музыкальной заставки, если програм- ма запущена с ключом "/М". CommandString$ = COMMAND$ IF INSTR(CommandString$,"/M") > 0 THEN PLAY "mbt200o215cl7el7g>14c<18g>12c" END IF ENVIRON ENVIRON — оператор связи с DOS для изменения парамет- ра в таблиЦе окружения DOS. ENVIRON символьное_выражение • символьноевыражение может иметь вид: • параметр=текст • параметр текст Все, что находится слева от знака равенства или пробела, воспринимается как параметр, все, что справа — как текст. Если параметр до выполнения оператора не существовал в таблице окружения, он добавляется в конец таблицы. Если он существовал, то его значение заменяется на данный текст, сам параметр ставится в конец таблицы. Если текст параметра — пустая строка ("") или точка с запя- той ( ; ), то существующий параметр удаляется из таблицы окру- жения, а сама таблица сжимается. DOS восстанавливает таблицу окружения после завершения программы до ее исходного состояния. Вы можете применить этот оператор для изменения пара- метра PATH для порожденного процесса (программы или коман- ды, выполняемой оператором SHELL) или для пересылки пара- метров этому процессу путем создания нового параметра таблицы окружения. Пример: изменение переменной PATH. ENVIRON "РАТН=С:\SALES;С:\ACCOUNT" 343
ENVIRONS ENVIRONS — функция связи с DOS, возвращающая строку параметра из таблицы окружения DOS. ENVIRONS (имя_параметра) ENVIRONS (n) • имя_параметра — символьная переменная или константа, со- держащая имя параметра из таблицы окружения DOS; • п — номер параметра в таблице окружения. Если вы указали имя параметра или номер, которого нет в таблице, возвращается пустая строка. Если параметр присутству- ет, то возвращается его значение. Пример: вывод текущего содержимого таблицы окружения. CLS i = l DO WHILE ENVIRONS(i) <> "" PRINT ENVIRONS(i) i = i + 1 LOOP Вывод: (аналогичен команде DOS SET) COMSPEC=C:\COMMAND.COM PROMPT=$P$G OS=NWDOS VER=7 PATH=C:;С:\NWDOS;С:\NORTON;С:\BC7\BIN;С:\UTILS;D:\LEXICON INCLUDE=C:\BC7\INCLUDE BIN=C:\BC7\BIN LIB=C:\BC7\LIB HELP=C:\BC7\HELP VC=C:\NORTON TEMP=C:\NWDOS\TMP LEXTEMP=C:\NWDOS\TMP 344
12 РАСШИРЕНИЕ ВОЗМОЖНОСТЕЙ QuickBASIC 4.5(*) Работа с системными прерываниями в QuickBASIC Исторически сложилось так, что многие стандартные функ- ции управления устройствами компьютера (памятью, дисковода- ми, монитором, клавиатурой) были реализованы по принципу прерываний (interrupt). Часть из них закодирована в постоянной памяти — BIOS, часть — обеспечивается операционной системой. Прерывания используются для переключения процессора на об- служивание того или иного устройства или процесса. Все произ- водители микросхем BIOS и разработчики DOS придерживаются определенных стандартов, то есть функционально управление ус- тройствами компьютеров одинаково. Программисты чаще всего используют следующие прерывания: INT 10h Видеосервис; INT llh Информация об оборудов^нии; INT 13h Дисковый ввод/вывод; INT 14h Обслуживание последовательного порта; INT 16h Сервис клавиатуры; INT 17h Управление принтером ; INT lAh Сервис таймера; INT 21h Сервис DOS; INT 27h Оставляет программу резидентной; INT 33h Сервис мыши.
Получив доступ к этим средствам, вы получаете доступ не- посредственно к оборудованию, вы пересылаете в регистры про- цессора нужные параметры, а контроллер прерываний переклю- чает процессор на обслуживание требуемого устройства. Большинство прерываний имеют свои функции, которые конкретизируют их действия (номер функции необходимо пере- слать в регистр процессора АН). Программисту проще вызвать нужное прерывание, чем пи- сать сложный модуль обработки состояния какого-либо оборудо- вания. В справочниках и руководствах1 обычно подробно описа- ны функции BIOS и DOS, какие данные необходимо переслать в регистры процессора, и что из этого получается. Для доступа к системным прерываниям необходимо загру- зить библиотеку QB.QLB: C:>QB45>qb program /L QB.QLB QB.QLB — библиотека, которая загружается по умолчанию, поэтому при вызове среды QB ее имя можно не указывать, огра- ничившись указанием ключа /L: C:>QB45>qb program /L Библиотека QB.QLB содержит 4 процедуры, работающие с прерываниями, разрешенными BIOS и DOS: Процедуры INTERRUPT INTERRUPTX INT86OLD2 INT86XOLD** Вызов CALL INTERRUPT (параметры) CALL INTERRUPTX (параметры) CALL INT86OLD (параметры) CALL INT86XOLD (параметры) Для пересылки параметров в процедуры INTERRUPT и IN- TERRUPTX используется пользовательский тип данных RegType. В нем каждый элемент соответствует регистру процессора. Ре- 1 Рекомендую: Р. Джордейн. Справочник программиста персональных компью- теров типа IBM PC, XT и AT. Москва, "Финансы и статистика", 1991 2 Отличие данных процедур от двух предыдущих в том, что данные передают- ся и принимаются с помощью двух целых одномерных массивов, длиной 8 и 10 элементов соответственно. Они оставлены для совместимости со старыми верси- ями языка BASIC. 346
гистры процессора, в которые разрешено пересылать данные сле- дующие: АХ вх сх DX ВР SI DI DS ES (АН, (ВН, (СН (DH AL) BL) CL) , DL) аккумулятор базовый регистр счетчик регистр данных указатель базы индекс источника индекс приемника флаговый регистр указатель сегмента данных указатель дополнительного сегмента Процедура INTERRUPT не использует значения в регистрах DS и ES, поэтому чаще всего она и применяется. Если вы вызываете процедуру INTERRUPTX и вам требуется использовать текущие значения в регистрах DS и ES, установите элементы DS и ES переменной типа RegType равными -1. Для обеспечения доступа к системным прерываниям создай- те включаемый (INCLUDE) файл INTERUPT.BI, в котором со- держатся все необходимые объявления: 1 В этом включаемом файле определены типы и описания ' процедур, необходимых для доступа к системным прерываниям: 1 Interrupt, InterruptX, Int86Old, и Int86XOld. i**************************************************** 'все переменные целые DEFINT A-Z 'Типы данных, необходимые для процедуры Interrupt TYPE RegType ах AS INTEGER bx AS INTEGER ex AS INTEGER dx AS INTEGER bp AS INTEGER si AS INTEGER di AS INTEGER flags AS INTEGER END TYPE 347
DIM SHARED inreg AS RegType, outreg AS RegType 'Типы данных, необходимые для процедуры InterruptX TYPE RegTypeX ax AS INTEGER bx AS INTEGER ex AS INTEGER dx AS INTEGER bp AS INTEGER si AS INTEGER di AS INTEGER flags AS INTEGER ds AS INTEGER es AS INTEGER END TYPE DIM SHARED inregx AS RegTypeX, outregx AS RegTypeX 'объявления процедур DECLARE SUB Interrupt (intnum AS INTEGER, inreg AS_ RegType, outreg AS RegType) DECLARE SUB InterruptX (intnum AS INTEGER, inregx AS_ RegTypeX, outregx AS RegTypeX) DECLARE SUB Int86Old (intnum AS INTEGER, inarrayO AS_ INTEGER, outarrayO AS INTEGER) DECLARE SUB Int86XOld (intnum AS INTEGER, inarrayO AS_ INTEGER, outarrayO AS INTEGER) Включите этот INCLUDE-файл в начало вашей программы: '$INCLUDE: 'interupt.bi' Обратите особое внимание на следующее обстоятельство: все переменные, пересылаемые в процедуру INTERRUPT должны быть целыми! Пересылка нецелых значений приведет к зависанию систе- мы. Вот почему в начале файла INTERUPT.BI стоит оператор DEFINT, объявляющий целыми все переменные программы. Дальше приведены несколько примеров, иллюстрирующих работу с системными прерываниями в QuickBASIC. Ввод малой русской буквы "р" Как уже упоминалось в главе второй "ОСНОВЫ ЯЗЫКА BASIC" стандартными средствами языка BASIC невозможно вве- сти символ с кодом 224 — это малая русская буква "р" в Альтер- нативной кодировке. Исправить положение помогает процедура Char$, которая использует прерывание BIOS INT 16H, функцию 0 — "Чтение символа". 348
'$INCLUDE: 'interupt.bi' DECLARE SUB Char (c$) ' Вызов процедуры CHAR, печать всех вводимых символов 1 ESC - конец работы программы DO CALL Char(a$): PRINT a$; IF a$ = CHR$B7) THEN EXIT DO LOOP END SUB Char (c$) ***************************************************** ' Данная процедура корректно обрабатывает ввод всех ' символов ASCII, включая малую русскую букву "р" ' используя прерывание BIOS 16h, функция 0. ' Вызов: CALL Char (variable$) ' Аналог: ' DO: variable$ = INKEY$: LOOP WHILE variable$ = "" ***************************************************** n = &H16: ' прерывание 16h inreg.ax =0: ' функция О CALL Interrupt(n, inreg, outreg) nah = outreg.ax \ 256: nal = outreg.ax MOD 256 c$ = CHR$(nal): IF nal = 0 THEN c$ = c$ + CHR$(nah) END SUB Прокрутка текстового экрана Для организации оконного интерфейса требуется "прокрут- ка" (скроллинг) фрагмента экрана. Перепечатка занимает слиш- ком много времени, так как BASIC утомительно медлителен в своих манипуляциях с экраном. Решением проблемы может стать использование прерывания BIOS ЮН, функция 6 — "Прокрутка экрана вверх" и 7 — "Про- крутка экрана вниз". Приведенная ниже программа рисует окно-список и прокру- чивает его в окне на экране. Для прокрутки используется проце- дура Scroll(). '$INCLUDE: 'interupt.bi' DECLARE SUB Scroll (x%, y%, xl%, yl, lines%, back%, dir%) 349
DECLARE SUB WaitKey (kod%) CONST UP% = 72, DOWN% = 80, ESC% = 27, ENTER% = 13 CONST TRUE% = -1, FALSE% = 0, шах = 100 'заполняем вектор Test$() значениями REDIM test$(max) FOR i = 1 TO max test$(i) = STRING$D0, CHR$(i +47)) NEXT i 'рисуем рамку COLOR 0, 3: CLS : COLOR 0, 7 LOCATE 3, 18: PRINT " r" + STRING$D2, "-") + "-, " FOR i = 4 TO 21 LOCATE i, 18 PRINT "| " + test$(i - 3) + " II" NEXT i LOCATE 22, 18: PRINT "L» + STRING$D2, "-") + "-J " COLOR 0, 3: LOCATE 23, 20: PRINT STRING$D3, "¦") COLOR 0, 7 1 locator - позиция на экране 'nomer - начальный номер в векторе test$() locator = 1: nomer = 1 'основной цикл DO LOCATE 4 + locator - 1, 20, 1, 6, 13 'ждем нажатия клавиши CALL WaitKey(kod) SELECT CASE kod CASE IS = DOWN "клавиша {DOWN} IF locator < 18 THEN 'перемещаемся на экране locator = locator + 1 1 изменяем номер в векторе nomer = nomer + 1 ELSEIF nomer < max THEN 1 вызываем прокрутку окна с координатами '4,18,21,59 на одну строку, освободившуюся 1 строку выводим белым цветом G), прокрутка 'экрана вверх F) CALL ScrollD, 18, 21, 59, 1, 7, 6) 'изменяем номер в векторе nomer = nomer + 1 'выводим строку Nomer из вектора test$() LOCATE 21, 20: PRINT test$(nomer) END IF CASE IS = UP 350
IF locator > 1 THEN locator = locator - 1 noraer = nomer - 1 ELSEIF nomer > 1 THEN 1 вызываем прокрутку окна с координатами '4,18,21,59 на одну строку, освободившуюся 'строку выводим белым цветом G) , прокрутка 1 экрана внизG) CALL ScrollD, 18, 21, 59, 1, 7, 7) 'изменяем номер в векторе nomer = nomer - 1 'выводим строку Nomer из вектора test$() LOCATE 4, 20: PRINT test$(nomer) END IF CASE IS = ESC LOCATE 24, 25: PRINT "вы отказались от выбора..." EXIT DO CASE IS = ENTER LOCATE 24, 14 PRINT "Элемент N"; nomer; " "; CHR$C4);_ test$(nomer); CHR$C4) EXIT DO END SELECT LOOP DO: LOOP WHILE INKEY$ = "" COLOR 0, 7: CLS : END SUB Scroll (x, y, xl, yl, lines, back, dir) ' Эта процедура производит прокрутку фрагмента экрана 1 используя прерывание BIOS 10h, функцию 6 или 7. 1 х,у - строка и столбец верхнего левого угла ' xl, yl - строка и столбец нижнего правого угол ' lines - на сколько строк опустить/поднять 1 back - каким заполнить цветом ' dir - направление: 6 - вниз, 7 - вверх ••а************************************************* n = &H10: 'прерывание 10h inreg.ах = dir * 256 + lines: 'функция 6 или 7 inreg.bx = 4096 * back: 'заполнение фоном inreg.сх = (х-1) *256+у+1: 'верхний левый угол mreg.dx = (xl - 1) * 256 + yl - 1: 'нижний правый угол CALL interrupt(n, inreg, outreg) END SUB SUB WaitKey (kod) 351
I************************************************ 1 Эта процедура возвращает код клавиши: 1 ESC, ENTER, DOWN, UP 1 код - код клавиши 1 очищаем буфер клавиатуры DO: LOOP WHILE INKEY$ <> "» DO 'ждем нажатия какого-нибудь символа а$ = "»: DO: a$ = INKEY$: LOOP WHILE a$ = "" IF LEN(a$) = 1 THEN 'если нажата обычная клавиша и если это ENTER или ESC, 'то выходим из цикла DO... LOOP и из процедуры IF a$ = CHR$(ENTER) THEN kod = ENTER: EXIT DO IF a$ = CHR$(ESC) THEN kod = ESC: EXIT DO ELSE 1 если нажата функциональная клавиша, то берем ее 'скан-код и проверяем, не равен ли он коду клавиш 'UP или DOWN kod = ASC(RIGHT$(a$, 1)) IF kod = UP OR kod = DOWN OR kod = LEFT OR _ kod = RIGHT THEN EXIT DO END IF LOOP END SUB Вывод: 352
Интерфейс с драйвером мыши Использование манипулятора "мышь", по глубокому моему убеждению, оправдано только в графических программах, кото- рые, в свою очередь, имеют очень узкую область применения: картография, проектирование, рисование, еще может быть игры. Большинство же программ — от сложных коммерческих па- кетов до математических задач ориентированы, конечно, на тек- стовый режим экрана. А использование мыши в текстовых про- граммах — явное излишество. В хорошо продуманных програм- мах всегда быстрее работать, используя клавиатуру1, нежели мышь, а программе с запутанным и неудобным интерфейсом ни одна мышь не поможет. Но не буду навязывать свою точку зре- ния. На Ваш суд предлагается процедура MOUSE, использующая прерывание INT ЗЗН: и позволяющая управлять мышью из про- граммы на BASIC2: '$INCLUDE: 'interupt.bi' DECLARE SUB MOUSE (Gl%, G2%, G3%, G4%) DEFINT A-Z SUB MOUSE (ml, m2, m3, m4) ' Эта процедура обеспечивает интерфейс с драйвером мыши 1 ml, m2, m3, т4 - параметры, передаваемые в драйвер мыши ' и возвращаемые оттуда. Они соответствуют регистрам 1 процессора АХ, ВХ, СХ, DX i ***************************************************** n = &H3 3: ' прерывание 33h inreg.ax = ml ' входные регистры inreg.bx = m2 inreg.cx = m3 inreg.dx = m4 CALL interrupt(n, inreg, outreg) ml = outreg.ax ' выходные регистры m2 = outreg.bx rr\3 = outreg. ex 1 Обратимся к классике- всеми нами любимый Norton Commander поддержи- вает мышь, но многие ли ею там пользуются7 2 Интерфейс с драйвером мыши подразумевает как минимум ее наличие и то, что драйвер мыши загружен до вызова BASIC. Как гласил рекламный плакат фирмы GENIUS на выставке "Комтек-91" — "Мышьёнок Жениус ест лучший мышьёнок для вашего компьютеру" (орфография сохранена). 12 Зах.2105 353
m4 = outreg.dx END SUB Основные функции прерывания ЗЗН, и примеры к ним при- ведены ниже: Функция 0: Текущее состояние драйвера мыши Функция 0 показывает текущее состояние драйвера мыши. На входе: • Gl%=0 На выходе: • Gl% = статус драйвера мыши (-1: установлен, 0: не установлен); • G2% = число кнопок мыши B или 3 кнопки) Пример: 'Определение состояния драйвера мыши Gl% = 0 : G2% = 0 CALL MOUSE ( Gl%, G2%, G3%, G4% ) IF G2% AND 2 THEN PRINT "Двухкнопочная мышь" IF G2% AND 3 THEN PRINT "Трехкнопочная мышь" IF NOT Gl% THEN PRINT "Драйвер мыши не установлен" Функция 1: Включить курсор мыши Функция 1 вызывает появление курсора мыши на экране. На входе: • Gl% = 1 На выходе: • Ничего. Пример: 'Включить курсор мыши Gl% = 1 CALL MOUSE ( Gl%, G2%, G3%, G4% ) Функция 2: Погасить курсор мыши Функция 2 удаляет курсор 'мыши с экрана дисплея. Хотя курсор мыши и не виден, драйвер продолжает его отслеживание. 354
вы должны вызвать эту функцию перед любыми манипуля- циями с экраном. Это поможет избежать раздвоения курсора. Для включения курсора вызовите функцию 1. На входе: . Gl% = 2 На выходе: • Ничего. Пример: 1 Выключить курсор мыши Gl% = 2 CALL MOUSE ( Gl%, G2%, G3%, G4% ) Функция З: Прочитать координаты курсора и статус кнопок Функция 3 читает статус кнопок мыши и координаты курсора. На входе: • Gl% = 3 На выходе: • G2% = статус кнопок; • G3% = горизонтальная координата курсора; • G4% = вертикальная координата курсора. = Пример: 1 Прочитать координаты курсора и статус кнопок DO Gl% = 3 CALL MOUSE(Gl%, G2%, G3%, G4%) LOCATE 1, 1 PRINT "Координаты мыши : X ="; G3%; " Y =";G4%; " " IF G2% AND 1 THEN LOCATE 3, 1: PRINT "Левая кнопка " IF G2% AND 2 THEN LOCATE 3, 1: PRINT "Правая кнопка " IF G2% AND 4 THEN LOCATE 3, 1: PRINT "Средняя кнопка" LOOP Функция 4: Установить координаты курсора мыши Функция 4 устанавливает новую текущую позицию курсо- ра мыши. Разрешение зависит от экранного режима, и может округляться при необходимости. Обратите внимание — драй- вер мыши работает с разрешением 640 х 200 в текстовом ре- 355
жиме (SCREEN 0). Эта функции необходимо передать следую- щие параметры: • Gl%=4; • G3% = новая горизонтальная координата X; • G4% = новая вертикальная координата Y На выходе: • Ничего. Экранный режим Разрешение 0 640 х 200 1 640 х 200 2 640 х 200 7 640 х 200 8 640 х 200 9 640 х 350 Ю 640 х 350 11 640 х 480 12 640 х 480 13 640 х 200 Пример: 1 Установить курсор мыши в верхнем левом углу экрана Gl% = 4: G3% = 0 : G4% = 0 CALL MOUSE ( Gl%, G2%, G3%, G4% ) Функция 5: Прочитать статус нажатой кнопки Функция 5 определяет, какая кнопка была нажата и ее коорди- наты. На входе: • Gl% = 5; • G2% = статус кнопки (левая = 0, правая = 1, средняя = 2). На выходе: • Gl% = статус кнопки; • G2% = номер нажатой кнопки ; • G3% = горизонтальная координата курсора в момент послед- него нажатия; • G4% = вертикальная координата курсора в момент последне- го нажатия. 356
Пример: ' Прочитать координату нажатой левой кнопки DO Gl% = 5: G2% = 0: CALL MOUSE(G1%, G2%, G3%, G4%) IF Gl% AND 1 THEN LOCATE 1, 1: PRINT "Нажата левая_ кнопка X = "; G3%; " " LOOP Функция 6: Прочитать статус отпущенной кнопки Функция 6 определяет, какая кнопка была отпущена и ее координаты. На входе: • Gl% = 6; • G2% = статус кнопки (левая = 0, правая = 1, средняя — 1). На выходе: • Gl% = статус кнопки; • G2% = номер отпущенной кнопки; • G3% = горизонтальная координата отпущенной кнопки; • G4% = вертикальная координата отпущенной кнопки. Пример: ' Прочитать координату отпущенной левой кнопки DO Gl% = 6: G2% = 0: CALL MOUSE(Gl%, G2%, G3%, G4%) IF NOT Gl% THEN LOCATE 1, 1: PRINT "Отпущена_ левая кнопка X = "; G3%; " " LOOP Функция 7: Ограничить горизонтальное (X) перемещение курсора Функция 7 определяет зону, ограничивающую горизонталь- ное перемещение курсора. Если в момент вызова функции кур- сор находился вне этой зоны, то он перемещается внутрь ее. На входе: • Gl% = 7 • G3% = минимальная горизонтальная координата курсора; • G4% = максимальная горизонтальная координата курсора. На выходе: 357
• Ничего. Пример: ' Ограничить горизонтальное перемещение курсора между 100 и 200 Gl% = 7 G2% = 100: G3% = 200 CALL MOUSE(Gl%, G2%, G3%, G4%) Функция 8: Ограничить вертикальное (Y) перемещение курсора Функция 8 определяет зону, ограничивающую вертикальное перемещение курсора Если в момент вызова функции курсор на- ходился вне этой зоны, то он перемещается внутрь ее. На входе: • Gl% = 8; • G2% = минимальная вертикальная координата курсора; • G3% = максимальная вертикальная координата курсора. На выходе: • Ничего. Пример: ' Ограничить вертикальное перемещение курсора 1 между 100 и 200 Gl% = 8: G2% = 100 : G3% = 200 CALL MOUSE ( Gl%, G2%, G3%, G4% )
ПРИЛОЖЕНИЯ ПРИЛОЖЕНИЕ 1 Описание Главного Меню QuickBASIC 4.5 Для входа в главное меню нажмите клавишу {ALT}. Затем необходимо нажать подсвеченную букву выбранного меню. Так, например, для входа в меню FILE (файлы), нажмите {ALT-F}. Выбор нужного пункта меню также можно производить по под- свеченной букве. Так, для выбора пункта "Load File" (Загрузить файл) достаточно нажать {ALT-F, L}. Чтобы выбрать пункт из меню можно воспользоваться мы- шью, хотя это и не так удобно: подведите курсор мыши к назва- нию нужного пункта в линейке меню и нажмите на левую кла- вишу мыши, затем выберите нужный пункт и нажмите еще раз на левую клавишу мыши. Если пункт меню оканчивается троеточием "...", то это зна- чит, что при выборе этого пункта возникнет диалоговое окно с дополнительными вопросами. Ниже приведено подробное описание каждого пункта меню: МЕНЮ FILE (ФАЙЛЫ) Используется для: • создания новой программы; • загрузки и сохранения программ или частей программ; • печати файлов или частей файлов; • использования команд DOS; • выхода из QuickBASIC.
New Program Open Program. Merge... Save Save As... Save All Create File... Load File... Unload File... Print... DOS Shell Exit Новая программа Открыть программу... Объединить... Сохранить Сохранить как... Сохранить всё Создать файл... Загрузить файл... Выгрузить файл... Печать... Временный выход в DOS Выход NEW PROGRAM (Новая программа) Используется для очистки памяти перед началом новой программы. Если программа уже находится в памяти, то может появиться диалоговое окно. Тогда: • выберите <Yes> для записи программы; • выберите <No> для очистки без записи; • выберите <Cancel> для отмены очистки. Выбор может осуществляться как клавишей {TAB}, так и курсором мыши. OPEN PROGRAM (Открыть программу) 360
Используется для очистки памяти и загрузки программы с диска, после чего ее можно запускать или вносить изменения. Вместо этого пункта меню можно использовать "Load File" (Загрузить файл) MERGE (Объединение) Используется для вставки содержимого файла, записанного в текстовом формате в текущий загруженный файл. Файл, запи- санный в формате QuickBASIC не может быть объединен с заг- руженным файлом. В таком случае его надо преобразовать в тек- стовый формат. Компилировать готовую программу (пункт "Маке ЕХЕ" из меню RUN), лучше всего также в текстовом виде. SAVE (Запись) Используется для записи содержимого файла, находяще- гося в рабочем окне, на диск. Если файл не имеет имени, то будет запрошено его имя и формат. В случае, если на диске уже существует файл с таким именем, то он будет перезапи- сан. Для записи файла удобнее всего использовать комбина- цию клавиш {ALT-F, L}. 361
SAVE AS (Записать как...) Используется для записи файла в рабочем окне на диск. Файл остается в памяти. С помощью пункта "Save As" вы сможе- те сделать несколько копий файла с различными изменениями, сохранив при этом оригинальную версию. SAVE ALL (Записать все) Используется для записи всех изменившихся модулей про- граммы. Новая программа получит имя и формат главного моду- ля. Пункт "Save All" создает и использует специальный файл, с именем главного модуля и расширением .МАК. Файл .МАК со- держит имена всех остальных модулей программы. При последу- ющей загрузке главного модуля QuickBASIC автоматически под- грузит все остальные модули. CREATE FILE (Создать файл ) Используется для ввода нового модуля в многомодульной программе. Он может быть: 362
программным модулем; включаемым файлом; файлом типа документ. Новый файл становится частью текущей загруженной про- граммы. Пункт "Create File" может быть использован, когда программа еще не загружена, вместо "New Program" для создания нового главного модуля. FILE LOAD (Загрузить файл) Используется для загрузки программы с диска, а также для: • построения многомодульной программы; • загрузки и редактирования служебных текстовых файлов; • подготовки Quick library. Для быстрой загрузки файла можно использовать комбина- цию клавиш {ALT-F, L} 363
FILE UNLOAD (Выгрузить файл) Используется при создании многомодульных программ, чтобы выгрузить ненужный модуль из памяти, оставив его записанным в виде файла на диске. QuickBASIC выведет список загруженных мо- дулей. Выберите тот, который вы хотите выгрузить, подведите к не- му выделенную строку и нажмите клавишу {ENTER}. Если выгружа- емый модуль изменялся, то Quick- BASIC спросит вас, нужно ли его сохранять. PRINT (Печать) Используется для распечатки текста, находящегося в памяти. С помощью этого пункта меню вы можете распечатать: Текст посылается на печать через порт DOS LPT1'. DOS SHELL (Временный выход в DOS) Используется для временного выхода из QuickBASIC и вы- полнения команд DOS2. Для этого необходимо следующее: 1 В дополнение к LPT1 в среде Microsoft BASIC PDS 7.1 выделенный текст можно послать на LPT2, LPT3 или в файл. 2 В Microsoft BASIC PDS 7.1 имеется меню "UTILITY" (УТИЛИТЫ), где имеется пункт "Run DOS Command" (Запустить команду DOS). При возврате в среду вводить "exit" нет необходимости. 364 • выделенный текст; • содержание активного окна; • текущий модуль (включая и про- цедуры); • все модули в многомодульной программе.
1. выберите пункт DOS Shell в МЕНЮ FILE. 2. выполняйте команды DOS , но не стирайте те файлы, кото- рые нужны QuickBASIC (загруженные файлы, библиотеки). 3. чтобы вернуться в QuickBASIC введите "exit" в ответ на приг- лашение DOS. EXIT (Выход) Используется для выхода из среды QuickBASIC. Если файл не назван, либо не сохранены последние изменения, то может появится диалоговое окно: • выберите <Yes> для записи изменений. • выберите <No> для отмены изменений. • выберите <Cancel> для отмены выхода. МЕНЮ EDIT (РЕДАКТИРОВАНИЕ) Undo Alt+Backspace Cut Shift+Del Copy Ctrl+Ins Paste Shift+Ins Clear Del New SUB... New FUNCTION... Отмена Alt+Backspace Вырезать Shift+Del Скопировать Ctrl+Ins В буфер Shift+Ins Очистить Del Новая процедура SUB... Новая процедура FUNCTION Используется для: стирания (или удаления в буфер) текста; копирования текста; передвижения (удаления и вставки через буфер) текста; отмены последних изменений в тексте; стирания текста без запоминания в буфере; создания новой процедуры (SUB) или функции (FUNCTION) 365
UNDO (Отменить) Используется для отмены всех изменений в текущей строке, пока курсор находится на ней. Для отмены изменений возможно применение комбинации клавиш {ALT-BACKSPACE}. Однако следует учитывать, что отмена изменений возможна до тех пор, пока курсор находится на текущей строке1. CUT (Вырезать) Используйте команду Cut или нажмите {SHIFT-DEL} для удаления выбранного текста из активного окна и помещения его в буфер. Затем вы можете использовать команду Paste {SHIFT- INS},чтобы вставить текст в активное окно. Чтобы начать выде- ление текста, поставьте курсор в нужное место и нажимайте кла- виши {SHIFT} и нужную клавишу-стрелку. Для стирания текста без запоминания его в буфере нажмите клавишу {DEL}. Пример: иллюстрирует действие команд Cut и Paste: Текст Буфер 1 Выделите текст, {SHIFT}+ стрел- ки 2 Выберите ко- манду Cut или нажмите {SHIFT-DEL} 3 Переместите курсор и выбери- те команду Paste {SHIFT-INS} -^ " -' Вырезанный текст остается в буфере и может быть скопиро- ван в другое место программы. 1 В Microsoft BASIC 7 I это ограничение снято В нем вы можете отменить до 20 последних изменений (UNDO) Кроме того, там появился режим "восстановления отмененных изменений" (REDO) 366
COPY (Копировать) Используйте команду Сору или нажмите {CTRL-INS} для копирования выбранного текста из активного окна в буфер Оригинальный блок текста остается без изменения. Затем вы можете использовать команду Paste {SHIFT-INS}, чтобы вставить текст в активное окно. Пример: иллюстрирует действие команд Сору и Paste: Текст Буфер 1 Выделите текст, {SHIFT}+ стрелки 2 Выберите команду Сору или нажми- те {CTRL-INS} 3 Переместите кур- сор и выберите команду Paste {SHIFT-INS} _ . - Вырезанный текст остается в буфере и может быть скопиро- ван в другое место программы. PASTE (Вставить через буфер) Используйте Paste или нажмите {SHIFT-INS} чтобы скопи- ровать блок текста из буфера в любое место активного окна. Позиция, куда будет вставлен текст определяется: 1 выделенным текстом; он стирается и текст из буфера копируется на его место. 2. позицией курсора, если нет выделенного текста; тогда. — меньше, чем одна строка копируется слева от курсора; — больше, чем одна строка копируется выше курсора 367
CLEAR (Очистить) Используйте команду Clear (или нажмите {DEL}, чтобы сте- реть выделенный текст из активного окна без запоминания в бу- фере. Содержимое буфера остается без изменения. NEW SUB (Новая процедура SUB) Используйте New SUB чтобы создать новую процедуру как часть программы или модуля в рабочем окне. Появится окно ди- алога для ввода имени про- цедуры. QuickBASIC очис- тит рабочее окно и сгенери- рует требуемые операторы SUB и END SUB, так что вы сможете начать вводить текст. Процедура может быть определена только один раз во всей программе. Когда вы вводите текст внутри новой процедуры, используй- те команду SUBs из МЕНЮ VIEW (ПРОСМОТР), или нажмите {F2}, чтобы вернуться в программу. Ваша процедура появится в списке процедур команды SUBs. Вы можете начать вводить процедуру и без использования меню. Для этого введите ключевое слово QuickBASIC SUB и имя процедуры. NEW FUNCTION (Новая процедура SUB) Используется для ввода определения функции в ра- бочем окне. Функция в QuickBASIC — это проце- дура, которая возвращает значение в Вашу програм- му. Каждая функция может быть определена только один раз во всей программе. 368
МЕНЮ VIEW (ПРОСМОТР) SUBs... Next SUB Split F2 Shift+F2 Next Statement Output Screen F4 Included File Included Lines Процедуры... F2 Следующая процедура Sh Разделение Следующий оператор Выходной экран F4 Включенный файл Включенные строки Используется для просмотра: процедур (SUB) и функций (FUNCTION); включенных файлов; выходного экрана. SUBs (Процедуры) Используется для просмотра различных частей загруженной программы. Для вызова этого пункта меню можно воспользовать- ся клавишей {F2}. вы сможете: • просмотреть содержимое рабочего окна; • разделить рабочее окно для просмотра различных частей од- ной программы или двух программ одновременно; • стереть процедуру или модуль; • передвинуть процедуру между модулями. 369
NEXT SUB (Следующая процедура) Используйте эту команду (или нажмите {SHIFT-F2}), когда вы хотите перейти к следующей процедуре. QB передвигается от процедуры к процедуре в алфавитном порядке. {SHIFT-F2} вызывает переход от А к В, следующее нажатие вызывает переход к процедуре С. {CTRL-F2} осуществляет перемеще- ние в обратном порядке. Если в программе много процедур, то быстрее воспользоваться командой SUBs (процедуры) или нажать клавишу {F2}. SPLIT (Разделение) Используется для работы с двумя частями программы или с двумя программами одновременно. Выбор этого пункта делит ра- бочее окно горизонтально. Используйте клавиши {F6} и {SHIFT- F6} для передвижения между окнами на экране: • {F6} — передвигает курсор в нижнее окно; • {SHIFT-F6} — передвигает курсор в верхнее окно; Для того, чтобы восстановить первоначальное состояние ок- на, выберите пункт Split снова. Активное окно содержит курсор, вы можете управлять раз- мерами этого окна с клавиатуры: • ALT+PLUS(+) увеличивает на одну строку; • ALT+MINUS(-) уменьшает на одну строку; • CTRL+F10 Распахивает окно на весь экран или возвращает его первоначальный размер. NEXT STATEMENT (Следующий оператор) Помещает курсор на выполнимый оператор, следующий за тем местом, где программа была приостановлена, вы можете про- должить: 370
• командой Continue (продолжить) , или нажав {F5}; • нажав {F8} чтобы исполнить следующий оператор; • использовать команду Set Next Statement (установить следу- ющий оператор), в МЕНЮ DEBUG (ОТЛАДКА), чтобы сме- нить место, с которого программа будет продолжена. OUTPUT SCREEN (Выходной экран) Используется для переключения между средой QuickBASIC и выходным экраном Вашей программы. Также можно пользовать- ся клавишей {F4}. INCLUDED FILE (Включенный файл) Эта команда используется только в том случае, если загру- женная программа имеет одну или более метакоманд SINCLUDE. Используется для загрузки включенного файла в рабочее ок- но и для его редактирования: 1. поместите курсор на метакоманду SINCLUDE с именем того файла, который вы хотите редактировать; 2. выберите команду Included File; 3. редактируйте файл в рабочем окне, затем выберите пункт "Save As" (Записать как) из меню FILE (ФАЙЛЫ), или от- ладьте программу со включенным файлом и запишите файл позднее, как часть программы. Чтобы просмотреть текст программы в то время когда вы ра- ботаете со включенным файлом: 1. разделите рабочее окно при помощи пункта Split (Разделение) из меню VIEW (ПРОСМОТР). 2. выберите пункт "Load File" (Загрузить файл) из меню FILE (ФАЙЛЫ) чтобы загрузить включенный файл. 3. вернитесь к тексту программы. Этим вы сделаете окно с программой активным. Теперь вы можете запускать прог- рамму. 371
INCLUDED LINES (Включенные строки) Используется для того чтобы включить или выключить ре- жим показа строк текста включенного файла. Если режим вклю- чен, то в меню появляется точка. Используйте эту команду только в том случае, если Ваша программа содержит метакоманду SINCLUDE. Когда режим включен, то текст включенного файла показы- вается другим цветом следом за метакомандой SINCLUDE с именем включенного файла. Эти строки только для чтения, вы должны загрузить включенный файл в свое окно, для того, чтобы редактировать его. МЕНЮ SEARCH (ПОИСК) Find... Selected Text Ctrl+\ Repeat Last Find F3 Change... Label... Найти... Выделенный т^кст Ctrl+\ Повторить последний поиск F3 Заменить... Метка... Используется для поиска текста: • только в активном окне; • в текущем модуле; • во всех загруженных модулях. FIND (Поиск) Используется для поиска текстовой строки: • в активном окне; • в текущем модуле; • во всех загруженных модулях. 372
вы можете выбрать как точный образец ( с учетом регистра), так и целое слово. Для того чтобы заменить строку, используйте команду Change (Замена). Используйте команду Selected Text (Выделенный текст) для поиска короткой строки в активном окне. SELECTED TEXT (Выделенный текст) Используется для поиска образца, размером в одну строку или меньше, который предварительно был выделен в рабочем окне. Также можно использовать клавишу {CTRL-\}. Для других ситуаций используйте пункт Find. Для работы с выделенным текстом: 1. выделите текст используя клавиши {SHIFT} и стрелки; 2. выберите Selected Text или нажмите {CTRL+\}. QuickBASIC выделит подсветкой следующее вхождение образца. REPEAT LAST FIND (Повторить последний поиск) Используется для повторения последнего поиска (может быть нажата клавиша {F3}, команды Find (Поиск) или Change (Замена). Если с момента запуска QuickBASIC команды Find (Поиск) или Change (Замена) не выполнялись, то будет найдено: • слово, на которое указывает курсор; • если курсор не указывает на слово, то будет найдено слово слева от курсора. 373
CHANGE (Замена) Используется для поиска текстовой строки и замены на ее на другую. вы можете заменить строку: • в активном окне; • в текущем модуле; • во всех загруженных модулях Можно выбрать, необходимо ли вам: • показ места, где будет произведена замена; • поиск с учетом регистра или нет. LABEL (Метка) Используется аналогично опции Find (Поиск). QuickBASIC ищет строку, оканчивающуюся двоеточием. Когда вы вводите в текстовое окно Find What (Найти что) метку, то двоеточие после метки вводить НЕ надо. Дело в том, что метки могут быть и целочисленными, а такие метки не окан- чиваются двоеточием. 374
МЕНЮ RUN (ЗАПУСК) Start Shift+F5 Restart Continue F5 Modify COMMANDS. Make EXE File... Make Library... Set Main Module... Запуск Shift+F5 Перезапуск Продолжение F5 Изменить переменную COMMANDS.. Сделать EXE файл... Сделать библиотеку. .. Установить главный модуль... Используется для: • исполнения загруженной программы; • продолжения выполнения прерванной программы; • очистки переменных в памяти перед выполнением; • создания исполняемого (.ЕХЕ) файла; • определения главного модуля в многомодульной программе. START (Запуск) Используется для очистки памяти и запуска программы на исполнение, начиная с первого исполняемого оператора в глав- ном модуле. Команда Start может использоваться после останова про- граммы нажатием {CTRL-BREAK}, для того, чтобы запустить программу с начала. Для исполнения команды Start можно также нажать {SHIFT-F5}. Вместо {CTRL-BREAK} можно пользоваться 375
точками прерывания и точками наблюдения (СМ. МЕНЮ DEBUG (ОТЛАДКА). RESTART (Перезапуск) Restart очищает память и продолжает выполнение с первого исполняемого оператора. Используйте клавишу {F8} для выполнения одного операто- ра, вы можете переопределить, какой оператор будет выполнятся следующим через опцию Set Next Statement (Установить следую- щий оператор) из меню DEBUG (ОТЛАДКА). CONTINUE (Продолжить) Используйте опцию Continue после того, как программа бы- ла остановлена, для того, чтобы продолжить ее выполнение. Эта команда часто используется для продолжения выполне- ния программы, остановленной на точке прерывания или точке наблюдения, после того как вы проверили значения переменных или просмотрели выходной экран. Для исполнения команды Continue можно также нажать кла- вишу {F5}. MODIFY COMMANDS (Изменить переменную COMMANDS) Используется для отладки QuickBASIC программы, которая использует функцию COMMANDS. COMMANDS передает ин- формацию из ко- мандной строки DOS. Команда ме- ню Modify COM- MANDS позволит вам отладить Вашу программу с новой командной стро- кой, не переключаясь между QuickBASIC и DOS. Так, например, если вы хотите, чтобы у программы была музыкальная заставка, но чтобы ее можно было отключить, используя ключ "/N0" 376
Пример: Отключение музыкальной заставки по ключу, указанному в командной строке. CommandString$ = COMMAND$ IF INSTR(CommandString$, "/NO") = 0 THEN PLAY "mbt200o215-cl7el7g>14c<18g>12c" END IF MAKE EXE FILE {Сделать EXE файл) Используется для построения .ЕХЕ (исполнимой) версии Вашей работающей QuickBASIC программы. Эта версия может исполняться прямо из командной строки DOS без загрузки среды QuickBASIC. Если вы хотите, чтобы Ваша программы выполнялась авто- номно, выберите пункт "Stand-Alone EXE File" (Автономный ис- полняемый файл). В противном случае, для работы Вашей про- граммы будет необходимо наличие библиотеки времени выпол- нения BRUN45.EXE в текущем каталоге, или в одном из катало- гов, перечисленных в PATH. MAKE LIBRARY (Сделать библиотеку) Используется для сборки программных модулей в Quick биб- лиотеку или добавления в существующую библиотеку. 377
Quick library используется, когда у вас есть набор процедур, которые вы хотите использовать в нескольких программах. Про- цедуры и функции, которые находятся в Quick библиотеке стано- вятся расширением самого языка BASIC. При запуске QB.EXE не- обходимо указать ключ "/L" и имя библиотеки. После этого бу- дет построено два файла библиотек: • .QLB — необходима для работы в среде QB; • LIB — необходима для компиляции в .ЕХЕ файл. SET MAIN MODULE (Установить главный модуль) Используется в многомодуль- ных программах для смены глав- ного модуля. При написании программ применяется для отлад- ки каждого модуля Кроме этого, если вы выгружаете из программы главный модуль, то QuickBASIC спросит вас, какой модуль из ос- тавшихся будет главным. Не за- будьте, что именно главный мо- дуль содержит точку входа, с кото- рой начинается выполнение про- граммы. МЕНЮ DEBUG (ОТЛАДКА) Add Watch... Instant Watch ..Shift+F9 Watchpoint. . Delete Watch.. Delete All Watch Trace On History On Toggle BreakpointF9 Clear All Breakpoints Break on Errors Set Next Statement Добавить наблюдение Установить Ha6flKweHHeShift+F9 Точка наблюдения .. Убрать наблюдение. . Убрать все наблюдения Трассировка включена История включена Точка прерывания F9 Убрать все точки прерывания Обрыв на ошибках Установить следующий оператор 378
Используется для настройки работы программы путем: • открытия окон наблюдения, которые показывают, как пере- менные изменяются при работе программы; • установки точек прерывания, которые прерывают выполне- ние программы для того, чтобы вы смогли просмотреть зна- чения переменных. После останова программы можно подвести курсор к любой переменной и нажать {SHIFT-F9}, чтобы узнать ее значение. Для установки точки прерывания подведите курсор к нужной строке и нажмите {F9}. ADD WATCH (Добавить наблюдение) Используется для контроля за значением переменной или значением (-1 "ДА"(Тше) или О "НЕТ" (False)) выражения при исполнении программы. Эти значения появляются в Окне отладки в верхней части экрана. Сообщение "Not watchable" (Определить невозможно) появ- ляется в Окне в том случае, если QuickBASIC не может получить доступ к значению переменной или выражения. Чаще всего это 379
происходит, когда выполнение программы прервано не в той процедуре или модуле, в котором устанавливали наблюдение. INSTANT WATCH (Установить наблюдение) Используется, когда прервано исполнение программы для того, чтобы показать: • значение переменной; • условие выражения (True или False) ; Чтобы показать значение переменной: 1. подведите курсор к имени переменной; 2. выберите Instant Watch (или нажмите {SHIFT-F9}); Чтобы показать значение выражения: 1. выберите (подсветкой) выражение в рабочем окне или подведите курсор к выраже- нию (QuickBASIC отличает перемен- ную от выражения); 2. выберите Instant Watch (или на- жмите {SHIFT-F9}; 3. если выражение верно, то в окне высвечивается -1, если же оно ложно, то 0. Значения появляются в окне диалога. С помощью этого же окна можно добавить переменную или выражение в Окно отлад- ки. При использовании мыши можно установить окно, поместив курсор мыши на переменную, либо выбрав выражение, затем од- новременно нажав {SHIFT} и правую кнопку мыши. WATCHPOINT (Точка наблюдения). Используется для остановки программы в случае, если за- данное Вами условие станет верным. Это условие может быть: 380
• именем переменной; • оператором отношения. Оператор отношения использует операторы: =, О, >, <, >=, или <=. В про- стейшем случае, если вы просто вводите имя пе- ременной или вы- ражение, Quick- BASIC подразуме- вает отношение <> 0. Например ввод X + Y означает выражение X + Y О 0. Сравнение "Add Watch" и "Watch Point": "Add Watch" (Добавить наблюдение): • высвечивает значения переменных, показывая как они изме- нились при выполнении программы; • не обрывает выполнение программы. "Watch Point" (Точка наблюдения): • не высвечивает значения переменных; • обрывает программу в случае, если введенное выражение ста- нет верным. DELETE WATCH (Стереть наблюдение) Используется для сти- рания только одного наблю- дения из окна отладки. Если же вы хотите полностью удалить все наблюдения, то для этого вам необходимо воспользоваться пунктом меню "Delete All Watch" (Стереть все наблюдения). 381
TRACE ON (Включить трассировку) Используйте этот переключатель, если вы хотите: • запустить Вашу программу в замедленном режиме, высвечивая каждый оператор, в момент его выполнения; • запомнить, как выполнялись последние 20 строк программы перед остановкой. Это позволит проследить за выполнением программы. Ис- пользуйте Trace On совместно с окнами наблюдения, точками прерывания или {CTRL-BREAK} для периодического приоста- новления выполнения программы. Затем используйте {SHIFT-F8} и {SHIFT-F10} для передвижения вперед и назад в пределах 20 строк программы. HISTORY ON (История включена) Используйте этот переключатель, когда вы хотите: • запустить Вашу программу со скоростью, близкой к нормаль- ной; • запомнить, как выполнялись последние 20 строк программы перед остановкой. После этого, используйте клавиши {SHIFT-F8} и {SHIFT- F10} для изучения последовательности выполнения операторов, включая проверку ветвления и другие действия программы в пре- делах 20 строк кода программы, которые были записаны пунктом "History On". Когда этот пункт включен, то в меню напротив TOGGLE BREAKPOINT (Точка прерывания) Используется для установки/снятия точек прерывания (мест, где программа останавливается). 382
Чтобы установить точку прерывания необходимо проделать следующее: 1. поместите курсор на строку, где вы хотите установить точку прерывания; 2. выберите "Toggle Breakpoint" (или нажмите {F9}). Quick- BASIC выделит строку другим цветом. Чтобы снять точку прерывания: 1. поместите курсор на выделенную строку; 2. выберите "Toggle Breakpoint" (или нажмите {F9}). Используйте точку прерывания для приостановки Вашей программы в том месте, где вы предполагаете наличие ошибок, а затем: • протестируйте значения переменной в окне для немедленного выполнения или с помощью опции "Instant Watch" (Ус- тановить наблюдение); • добавьте переменные в Окно наблюдения и продолжайте по- шаговое выполнение программы, начиная с точки прерывания. CLEAR ALL BREAKPOINTS (Стереть все точки прерывания) Используется для удаления всех точек прерывания из Вашей программы. Для индивидуального удаления точек прерывания используйте "Toggle Breakpoint" (Точка прерывания) или нажми- те F9. BREAK ON ERRORS (Обрыв на ошибках) Эта опция используется для отладки программы, содержа- щую процедуру обработки ошибок. "Break On Errors" (Если опция включена, то в меню появля- ется точка) приостанавливает выполнение программы на проце- дуре обработки ошибок. Включение "Break On Errors" также включает "History On" (История включена), так что будет запи- сана последовательность выполнения 20 последних операторов 383
программы. Используя {SHIFT-F8} вы можете вернуться на опе- ратор, вызвавший ошибку. Дальнейшее нажатия покажут вам операторы, предшествующие ошибке. SET NEXT STATEMENT (Установить следующий оператор) Используется для изменения естественного порядка выпол- нения операторов и исполнения того оператора, на котором сто- ит курсор. МЕНЮ CALLS (ВЫЗОВЫ) Меню CALLs показывает последовательность вызова проце- дур из других процедур (стек вложенных процедур). Если про- грамма не использует вызовы процедур из других процедур, то в меню CALLs выводится только имя главного модуля программы и имя текущей вызываемой процедуры. На рисунке показано, как может выглядеть меню CALLs при останове выполнения про- граммы DEMO3.BAS в процедуре Siren. Siren DEMO3.BAS Процедура Siren Вызвана из DEMO3.BAS Управление можно передать в любую процедуру из стека вложенных процедур, выбрав ее, и нажав клавишу {F7} (испол- нить до курсора). Меню CALLs выводит до 8 вызовов в стеке. МЕНЮ OPTIONS (ОПЦИИ) Display... Set Paths... Right Mouse... ' Syntax Checking • Full Menus Экран... Установить пути... Правая кнопка мыши. > Проверка синтаксиса > Режим полного меню Используется для: • настройки цветов экрана; • установки путей для поиска служебных файлов; 384
• переопределения правой кнопки мыши; • включения/выключения режимов Full Menus (Полное меню) и Syntax Checking (Проверка синтаксиса) Сделанные Вами установки автоматически запоминаются и используются при дальнейших вызовах QuickBASIC. DISPLAY (Экран) Опция Display используется для установки: экранных цветов; линеек прокрутки в окнах и списках; числа пробелов выдаваемых клавишей {TAB}. SET PATHS (Установить пути) Используется для установки путей, по которым QuickBASIC будет осуществлять поиск: • исполнимых файлов (.ЕХЕ и .СОМ ); • включаемых файлов (.BI и .BAS ); • библиотечных файлов (.LIB и .QLB ); • файлов помощи (.HLP). 385
RIGHT MOUSE (Правая кнопка мыши). Используется для изменения действий от однократного на- жатия правой кнопки мыши: выдать информацию об элементе на который указывает курсор (по умолчанию); исполнить программу от начала до строки, на которой стоит курсор. Right douse On right Mouse button click: (•) Context-sensitive Help ( ) Execute up to this line ОК < Cancel > < Help > SYNTAX CHECKING (Проверка синтаксиса) Эта команда включает/выключает Интеллектуальный Редак- тор QuickBASIC, который: 1. проверяет строку на наличие синтаксических ошибок; 2. форматирует строку; 3. в случае, если синтаксис строке правилен, то переводит стро- ку в исполнимую форму, при этом операторы языка Quick- BASIC становятся написанными заглавными буквами. 386
Выключение отменяет эти функции и превращает Интеллек- туальный Редактор в обычный текстовый. Когда "Syntax Checking" включена, то рядом с этим пунктом в меню появляется Интеллектуальный Редактор действует в режимах: • "New Program" (Новая программа) или "Open Program" (Отк- рыть программу); • "Create File" (Создать файл) или "Load File" (Загрузить файл), в случае если не выбран пункт "Document". Если же выбран пункт "Document", то в режимах "Create File" или "Load File" Интеллектуальный Редактор отключается, и вы можете использовать QuickBASIC как обычный редактор для ввода текста. FULL MENUS (Режим полного меню) Используется для переключения между полной (FULL) и со- кращенной формой меню QuickBASIC. При выборе опции Full Menus, рядом с ней в меню появляется точка. Сокращенное меню содержит команды, достаточные для предварительного знакомства со средой QuickBASIC. После пер- воначального освоения более удобно разрабатывать программы в режиме полного меню, которое содержит ряд дополнительных команд и дополнительное меню (МЕНЮ CALLs ). МЕНЮ HELP (ПОМОЩЬ) Индекс Содержание Описание: F1 Справка о noMoiuHShift+Fl Используется для получения: • справки по ключевым словам языка BASIC; • информации по языку программирования QuickBASIC; • контекстно-зависимой помощи, основанной на местораспо- ложении курсора; • дополнительных инструкций по получению помощи. 387
HELP INDEX (Индекс помощи) Help index — это алфавитный список тем, содержащихся в фай- лах помощи, включая ключевые слова BASIC. Каждая тема снабже- на дополняющими подразделами. Для получения помощи: • выберите пункт Index из меню HELP. • нажмите клавишу, соответствующую первой букве нужной темы; • укажите курсором подраздел, по которому вы хотите получить помощь и нажмите клавишу {F1}. HELP TABLE of CONTENTS (Таблица содержания файлов помощи) Обеспечивает доступ ко всем подразделам помощи QuickBASIC. Для получения помощи в Table of Contents: • выберите команду Contents из меню HELP; • нажмите клавишу, соответствующую первой букве нужного описания; • нажмите {F1}. 388
HELP TOPIC (Описание) При выборе этой опции высвечивается информация о пере- менной, операторе или выражения, на которой находится курсор. Выбор этой опции также может осуществляться путем нажатия клавиши {F1}. При использовании мыши нажмите на ее правую кнопку. HELP on HELP (Справка о помощи) Справка о помощи описывает как получить помощь, исполь- зуя мышь или клавиатуру. ПРИЛОЖЕНИЕ 2 Запуск, редактирование и отладка программы Ключи запуска среды QB из командной строки DOS Полный синтаксис командой строки QB : QB [/RUN [имя_программы]] [/В] [/G] [/H] [/NOHI] [/С:размер_буфера] [/L [имя_библиотеки]] [MBF] [/АН] [/СУЮстрока_команды] Ключ /RUN [имяпрограммы] /в /G Описание Загрузить и выполнить программу, не пока- зывая ее исходного текста. Имя_програм- мы — имя файла .BAS. Позволяет использовать монохромный мо- нитор с цветным адаптером (CGA/EGA- mono). Для машин с адаптером CGA. 389
/н /NOHI /С:размер_буфера /Цимя_библиотеки] /MBF /АН /CMDctpo- какоманды Запускает среду QB в режиме 43 строки на EGA-мониторе и 50 строк на VGA. Позволяет использовать монитор, где нет цветов повышенной яркости. Устанавливает размер буфера обмена данными для коммуникационной карты. По умолча- нию — 512 байт, максимально — 32767 байт. Загружает Quick-библиотека с данным име- нем. Если имя опущено, то загружается библиотека QB.QLB. Позволяет функциям преобразования дан- ных рассматривать числа IEEE-формата как числа Microsoft Binary формата. Позволяет использовать динамические мас- сивы, превышающие 64К. Передает строку функции COMMANDS. Этот ключ должен быть последним в командной строке1. Клавиши редактирования Редактор QuickBASIC совместим по командам с другими ре- дакторами фирмы Microsoft, такими как EDIT (из MS DOS 5.x или 6.x), Microsoft Word, а также с остальными интегрированны- ми Quick-средами (QuickAssembler, QuickPascal, QuickC) Символ влево Символ вправо Слово влево Слово вправо Строка вверх Строка вниз LEFT RIGHT CTRL+LEFT CTRL+RIGHT UP DOWN 1 Для передачи значения функции COMMANDS удобнее использовать пункт "Modify COMMAND" (Изменить COMMANDS) из меню "RUN" (ЗАПУСК). Это позволяет передавать функции COMMANDS значения командной строки, не выходя из среды QB. 390
Первая позиция текущей строки Начало следующей строки Конец строки Начало модуля/процедуры Конец модуля/процедуры Установить маркер места номер "п" (где п = 0-3) Перейти к маркеру номер "п" Строка вверх Строка вниз Страница вверх Страница вниз НОМЕ CTRL+ENTER END CTRL+HOME CTRL+END CTRL+K+n CTRL+Q+n Клавиши прокрутки текста CTRL+UP CTRL+DOWN PGUP PGDN Влево на одно окно Вправо на одно окно CTRL+PGUP CTRL+PGDN Символ влево Символ вправо Слово влево Слово вправо Текущая строка и ниже Строка выше Страница выше Страница ниже До начала модуля/процедуры До конца модуля/процедуры Клавиши выбора текста SHIFT+LEFT SHIFT+RIGHT SHIFT+CTRL+LEFT SHIFT+CTRL+RIGHT SHIFT+DOWN SHIFT+UP SHIFT+PGUP SHIFT+PGDN SHIFT+CTRL+HOME SHIFT+CTRL+END 391
Вставка, копирование и стирание текста Переключение вставка/замещение Копировать выбранный текст в карман Стереть текст и скопировать в карман Стереть строку и скопировать в карман Вставить содержимое кармана Вставить пустую строку ниже текущей Стереть символ слева от курсора Стереть текущий символ Стереть выбранный текст INS CTRL+INS SHIFT+DEL CTRL+Y SHIFT+INS END ENTER BACKSPACE DEL DEL Стереть начальные пробелы в выбранных SHIFT+TAB строках Клавиши просмотра Посмотреть окно вывода F4 Вывести список загруженных модулей и файлов F21 Перейти к следующей процедуре SHIFT+F2 Перейти к предыдущей процедуре CTRL+F2 Сделать следующее окно активным Сделать предыдущее окно активным Развернуть активное окно на весь экран Увеличить размер активного окна Уменьшить размер активного окна F6 SHIFT+F6 CTRL+F10 ALT+PLUS ALT+MINUS 1 Если при редактировании программы подвести курсор к имени процедуры или функции и нажать {F2}, то в выводимом списке загруженных модулей и (файлов курсор будет указывать на имя этой процедуры или функции. Нажмите {ENTER} и откроется окно для ее редактирования 392
Клавиши поиска Искать выбранный (подсвеченный) текст Ctrl+\ Повторить поиск F3 Запустить программу с начала Продолжить выполнение после остановки Выполнить программу до данной позиции Выполнить один следующий оператор Пошаговое выполнение Трассировка назад Трассировка вперед Включить/выключить точку прерывания Включить точку наблюдения Помощь по контексту Клавиши запуска и отладки SHIFT+F5 F5 F7 F8 F10 SHIFT+F8 SHIFT+F10 F9 SHIFT+F91 Клавиши помощи FF Стереть экран помощи ESC Смотреть Help on Help SHIFT+F1 Смотреть помощь через команды меню Help ALT+H Курсор — к следующему ключевому слову TAB Курсор — к предыдущему ключевому слову SHIFT+TAB К следующему ключевому слову с данной буквы буква 1 С мышью наблюдение включается: {SHIFT} + правая кнопка мыши. 2 Или правая кнопка мыши. 393
К предыдущему ключевому слову с данной буквы SHIFT+буква К предыдущему окну помощи (до 20 раз) ALT+F1 К предыдущему окну помощи в Help-файле SHIFT+CTRL+F1 ПРИЛОЖЕНИЕ 3 Коды ошибок №№ 3 4 5 6 7 9 11 14 16 19 20 24 25 27 39 40 50 51 Ошибка RETURN without GOSUB Out of DATA Illegal function call Overflow Out of memory Subscript out of range Division by zero Out of string space String formula too complex No RESUME RESUME without error Device timeout Device fault Out of paper CASE ELSE expected Variable required FIELD overflow Internal error Перевод RETURN без GOSUB Конец данных в операторе DATA Неверный вызов функции Переполнение Исчерпана оперативная па- мять Индекс вне диапазона Деление на ноль Нет места для строк Слишком сложная формула Нет RESUME RESUME при отсутствии ошибки Тайм-аут устройства Сбой на устройстве Нет бумаги на принтере Требуется CASE ELSE Обязательна переменная Переполнение FIELD Внешняя ошибка 394
№№ 52 53 54 55 56 57 58 59 61 62 63 64 67 68 69 70 71 72 73 74 75 76 Ошибка Bad file name or number File not found Bad file mode File already open FIELD statement active Device I/O error File already exists Bad record length Disk full Input past end of file Bad record number Bad file name Too many files Device unavailable Communication-buffer overflow Permission denied Disk not ready Disk-media error Advanced feature unavailable Rename across disks Path/File access error Path not found Перевод Неверное имя или номер файла Файл не найден Неверный тип файла Файл уже открыт Оператор FIELD активен Ошибка ввода/вывода Файл уже существует Неверная длина записи На диске нет места Ввод после конца файла Неверный номер записи Неверное имя файла Слишком много файлов Устройство отсутствует Переполнение коммуника- ционного буфера Доступ запрещен Диск не готов Физическое повреждение диска Расширенное средство не доступно Переименование между дис- ками Ошибка доступа/пути к файлу Путь не найден 395
ПРИЛОЖЕНИЕ 4 Ограничения QuickBASIC Имена, символьные строки и числа Ограничение Длина имени переменной, символов Длина символьной строки, символов Целые числа Длинные целые числа Числа обычной точности (>0) Числа обычной точности (<0) Числа двойной точности (>0) Числа двойной точности (<0) Максимум 40 32767 32767 2147483647 3.402823 Е+38 -1.401298 Е-45 1.797693 D+308 4.940656 D-324 Минимум 1 0 -32768 -2147483648 1.401298 Е-45 3.402823 Е+38 4.94066 D-324 1.79769 D+308 Массивы Ограничение Максимум Минимум Размер (все элементы): Static Dynamic Число размерностей Значение индекса1 65535 F4 К) Свободная оперативная память 8 32767 1 1 1 -32768 Максимальный диапазон между индексами = 32767 396
Процедуры и файлы Ограничение Размер процедуры, байт Число аргументов процедуры Вложение INCLUDE-файлов Размер модуля, байт Количество файлов Количество записей в файле Размер записи файла, байт Размер файла Путь файла, символов Сообщения об ошибках Максимум 65535 F4 К) 60 5 уровней 65535 F4 К) 255 2147483647 32767 C2 К) Свободное место на диске 127 255 Минимум 0 0 0 0 1 1 1 п 1 1 Редактирование Ограничение Поиск текста, символов Замена текста, символов Маркеры позиции курсора Точки наблюдения Число строк в окне Immediate Количество символов в одной строке: Длина строки COMMANDS, символов Максимум 79 39 4 8 10 255 124 Минимум 1 0 0 0 0 0 0 397
ПРИЛОЖЕНИЕ 5 ASCII-коды, Скан-коды ASCII-коди Основная ASCII-таблица (символы с кодами 0-127): 000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 (mil) (soh) (stx) (etx) (eot) (enq) (ack) (bel) (bs) (tab) (If) (vt) (np) (cr) (so) (si) 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 (die) (del) (dc2) (dc3) (dc4) (nak) (syn) (etb) (can) (em) (eof) (esc) (fs) (gs) (rs) (us) 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 sp i ii # $ % & ' ( ) * + - . / 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 0 1 2 3 4 5 6 7 8 9 : < = > 064 065 066 067 068 069 070 071 @ A В С D E F G 080 081 082 083 084 085 086 087 P Q R S T U V W 096 097 098 099 100 101 102 103 a b с d e f g 112 113 114 115 116 117 118 119 P q r s t u V w 398
072 073 074 075 076 077 078 079 Н I J К L M N 0 088 089 090 091 092 093 094 095 X Y Z [ \ ] Л 104 105 106 107 108 109 110 111 h i j к 1 m n о 120 121 122 123 124 125 126 127 X У z { 1 } ~ V Расширенная ASCII-таблица (символы с кодами 0-127): 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 А Б В Г д Е Ж 3 И Й К л м н О п 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 Р С т У ф X ц ч ш щ ъ ы ь э ю я 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 а б в г д е ж 3 и й к л м н о п 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 щ Щ 1 i н { 41 =1 J II J) J J 1 192 193 194 195 196 197 198 L ± T - + r 208 209 210 211 212 213 214 JL T T 1 1= p IT 224 225 226 227 228 229 230 P с T У Ф X Ц 240 241 242 243 244 245 246 > < f J
199 200 201 202 203 204 205 206 207 It It If JL ТГ If = ¦ 215 216 217 218 219 220 221 222 223 * J Г 1 H 1 1 ¦ 231 232 233 234 235 236 237 238 239 ч ш Щ ъ Ы ь э ю я 247 « 248 249 250 251 V 252 253 2 254 ¦ 255 Символы псевдографики для рисования рамок и таблиц Для ввода этих символов нажмите клавишу {ALT} и, не от- пуская ее, введите нужный код на цифровой клавиатуре, а затем отпустите клавишу {ALT}. Чтобы ввести символы с кодами меньше, чем 32 (управляющие коды), введите с клавиатуры ком- бинацию клавиш АР (нажмите клавишу {CTRL} и, не отпуская ее, клавишу с латинской буквой Р, и отпустите обе клавиши), а затем нужный управляющий код, как обычный символ через кла- вишу {ALT}. 218 г 195 192 L 179 1 Одинарная линия 194 т 197 т 193 X 196 191 п 180 i1 217 j 201 If 204 If 200 Ik 186 II Двойная линия 203 тг 206 + 202 205 187 И 185 i 188 176 219 1 220 ¦ 16 > Символы- шаблоны 177 221 1 223 17 < 178 1 222 1 254 ¦ 400
Скан-коды клавиатуры Клавиша ESC ! или 1 @ или 2 # или 3 $ или 4 % или 5 Л или 6 & или 7 * или 8 ( или 9 ) или 0 _ или - + или = LEFT TAB Q W E R T Y U I 0 P { или [ } или ] RETURN Hex- КОД 01 02 03 04 05 06 07 08 09 0A OB ОС 0D 0E OF 10 11 12 13 14 15 16 17 18 19 1A IB 1С Клавиша CTRL A S D F G H J К L : или ; " или ' ~ или LEFT SHIFT 1 или \ Z X С V В N M < или > или . ? или / RIGHT SHIFT PRTSC или * ALT Hex- код ID IE IF 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 Клавиша SPACEBAR CAPSLOCK Fl F2 F3 F4 F5 F6 F7 F8 F9 F10 NUMLOCK SCROLLOCK HCME или 7 UP или 8 PGUP или 9 - LEFT или 4 5 RIGHT или 6 + END или 1 DCWN или 2 PGDN или 3 INS или 0 DEL или . Hex- КОД 39 ЗА 3B ЗС 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53
ПРИЛОЖЕНИЕ 6 Типы дисплеев и экранные режимы Описание экранных режимов SCREEN Ниже перечислено подробное описание каждого экранного режима, задаваемого оператором SCREEN для видеоадаптеров1: • IBM Color Graphics адаптер (CGA) • IBM Enhanced Graphics адаптер (EGA) • IBM Video Graphics Array (VGA) • IBM Multicolor Graphics Array (MCGA). • Hercules Graphics Card (HGC), Graphics Card Plus (GCP) SCREEN 0 Это текстовый режим. Поддерживается адаптерами MDPA, CGA, EGA, VGA. • Формат текста 40x25, 40x43, 40x50, 80x25, 80x43, 80x50 с раз- мером символа 8x8 (CGA), 8x14, 9x14, 9x16 (EGA или VGA) точек; • 16 цветов, присваиваемых 2 атрибутам (MDPA); • 16 цветов, присваиваемых 16 атрибутам (CGA, EGA с 64К); • 64 цветов, присваиваемых 16 атрибутам (EGA, VGA). SCREEN 1 Это графический режим с разрешением 320x200. Поддержи- вается адаптерами CGA, EGA, VGA, MCGA. • Формат текста 40 х 25, размер символа 8x8 точек; • 16 фоновых цветов и одна из двух 3-цветовых палитр для ос- новного цвета (CGA); • 16 цветов, присваиваемых 4 атрибутам (EGA, VGA). ' Многие режимы поддерживают несколько комбинаций числа строк и стол- бцов на экране. Подробности — в описании оператора WIDTH. 402
SCREEN 2 Это графический режим с разрешением 640x200. Поддержи- вается адаптерами: CGA, EGA, VGA, MCGA. Формат текста 80x25 с размером символа 8x8 точек. 16 цветов, присваиваемых 2 атрибутам (EGA, VGA). SCREEN 3 Это графический режим с разрешением 720x348. Для него требуется адаптер Hercules и монохромный монитор. • Формат текста 80x25, 9x14 точек размер символа; • 2 экранные страницы A страница, если есть второй дисплей- ный адаптер); • Оператор PALETTE не поддерживается. SCREEN 4 Это графический режим с разрешением 640x400. Для него требуется адаптер Hercules и монохромный монитор. • Поддерживает компьютеры Olivetti М24, М240, М28, М280, М380, М380/С, М380/Т и AT&T 6300; • Формат текста 80x25, 8x16 точек размер символа; • 1 из 16 цветов — основной (выбирает оператор COLOR), фо- новый всегда черный. SCREEN 7 Это графический режим с разрешением 320x200. Для него требуется адаптер EGA или VGA. • 40 х 25 текстовый формат, размер символа 8x8 точек; • 32К — размер страницы, номера страниц зависят от экранной памяти: 0-1 F4К), 0-3 A28К), 0-7 B56К); • 16 цветов присваиваются 16 атрибутам. SCREEN 8 Это графический режим с разрешением 640x200. Для него требуется адаптер EGA или VGA. • 80 х 25 текстовый формат, размер символа 8x8 точек; 403
• 64К — размер страницы, номера: О F4К), 0-1 A28К), 0-3 B56К); • 16 цветов присваиваются 16 атрибутам. SCREEN 9 Это графический режим с разрешением 640x350. Для него требуется адаптер EGA или VGA. • 80x25 или 80x43 текстовые форматы, соответственно 8x14 или 8x8 точек — размер символа; • 64К — размер страницы, номер 0 F4К память адаптера), 128К; • размер страницы, номера: 0 A28К) или 0-1 B56К); • 16 цветов для 4 атрибутов F4К память адаптера); • 64 цветов для 16 атрибутов (более 64К памяти адаптера). SCREEN 10 Это графический режим с разрешением 640x350. Для него требуется адаптер EGA или VGA и монохромный монитор. • 80x25 или 80x43 текстовые форматы, соответственно 8x14 или 8x8 точек — размер символа; • 128К — размер страницы, номера: 0 A28К) или 0-1 B56К). До 9 оттенков серого для 4 атрибутов. SCREEN 11 Это графический режим с разрешением 640 х 480. Для него требуется адаптер VGA или MCGA. • 80x30 или 80x60 текстовые форматы, соответственно 8x16 или 8x8 точек — размер символа. • До 256К цветов для 2 атрибутов. SCREEN 12 Это графический режим с разрешением 640 х 480. Для него требуется адаптер VGA. • 80 х 30 или 80 х 60 текстовые форматы, соответственно 8x16 или 8x8 точек — размер символа. До 256К цветов для 2 атрибутов. • 404
SCREEN 13 Это графический режим с разрешением 320x200. Для него требуется адаптер VGA или MCGA. • 40x25 формат текста, размер символа 8x8 точек. • До 256К цветов для 256 атрибутов. ПРИЛОЖЕНИЕ 7 Словарь зарезервированных слов В этом приложении приведена таблица, содержащая список зарезервированных слов QuickBASIC. Эти слова не могут быть использованы в качестве меток или имен переменных или проце- дур. Список включает ключевые слова языка, а также служебные инструкции, которые обрабатываются средой QB и компилято- ром ВС. Во второй графе таблицы приведена краткая расшиф- ровка наименование ключевого слова языка BASIC и дается при- близительный перевод. ABS ACCESS ALIAS AND ANY APPEND AS ASC ATN BASE BEEP BINARY BLOAD BSAVE ABSOLUTE — абсолютное значение доступ замена и любой добавление в конец (файла) как ASCii code — код из таблицы ASCII арктангенс точка отсчета сигнал двоичный (файл) Binary LOAD — загрузка образа (памяти) Binary SAVE — запись образа (памяти) 405
BYVAL CALL CALLS CASE CDBL CDECL CHAIN CHDIR CHR$ CINT CIRCLE CLEAR CLNG CLOSE CLS COLOR COM COMMANDS COMMON CONST COS CSNG CSRLIN CVD CVDMBF BY VALue — (передача) по значению вызов (BASIC-процедуры) вызов (не BASIC-процедуры) случай Conversion number to DouBLe — преобразование числа к типу удвоенной точности C-language DECLare — объявить процедуру, ис- пользующую передачу параметров по правилам языка С передать управление (файлу) CHange DIRectory — сменить директорию CHaracteR — символ • Conversion number to INTeger — преобразование числа к целому типу окружность обнулять Conversion to LoNG — преобразовать к длин- ному целому числу закрыть (файл) CLear Screen — очистигь экран цвет COMmunicate port — параллельный порт командная строка общая (переменная/группа переменных) CONSTant — константа косинус Conversion to SiNGle — преобразовать к длин- ному целому числу CurSoR LINE — строка, на которой находится курсор ConVert string to Double — представить строку как число удвоенной точности ConVert Double in Microsoft Binary Format — представить строку в формате Microsoft Binary 406
CVI CVL CVS CVSMBF DATA DATES DECLARE DEF DEFDBL DEFINT DEFLNG DEFSNG DEFSTR DIM DO DOUBLE DRAW ELSE ELSEIF как число удвоенной точности1 ConVert string to Integer — представить строку как целое число ConVert string to Long — представить строку как длинное целое число ConVert string to Single — представить строку как число обычной точности ConVert Single in Microsoft Binary Format — представить строку в формате Microsoft Binary как число обычной точности1 Данные Текущая дата (ММ-ДД-ГГГГ) Объявить (процедуру/функцию) DEefine Fn function — определить функцию FN DEFine DouBLe — определить тип данных уд- военной точности DEFine INTeger — определить целый тип дан- ных DEFine LoNG — определить длинный целый тип данных DEFine SiNGle — определить тип данных обычной точности DEFine STRing — определить символьный тип данных DIMension — резервирование места (для масси- ва/переменной) делать двойной точности (переменная) рисовать иначе ELSE IF — иначе, если ... 1 Этот оператор оставлен в языке для совместимости с предыдущими версия- ми языка BASIC. Для его использования требуется загрузить среду QB с ключом MBF (Microsoft Binary Format): C:\QB45>qb /MBF 407
END ENDIF ENVIRON ENVIRONS EOF EQV ERASE ERDEV ERDEV$ ERL ERR ERROR EXIT EXP FIELD FILEATTR FILES FIX FOR FRE FREEFILE FUNCTION GET GOSUB Конец (программы/процедуры/функции или управляющей конструкции) END IF — конец условия IF ENVIRONment dos change — изменить пере- менную окружения DOS ENVIRONment dos get — получить значение переменной окружения DOS End of File — конец файла EQuiValence — эквивалентность стереть содержимое или уничтожить массив Error on DEVice code — код внешнего устрой- ства, вызвавшего ошибку Error on DEVice name — название внешнего ус- тройства, вызвавшего ошибку ERror Line — номер строки которая вызвала ошибку ERRor code — код ошибки ошибка выход (из процедуры/функции, управляющей конструкции) экспонента поле (файла прямого доступа) FILE ATTRibute — атрибут файла файлы FIXed — округление для FREe memory — свободная область памяти FREE FILE number — свободный номер файла функция взять GO SUBroutine — перейти к подпрограмме 408
GOTO HEX$ IF IMP INKEY$ INP INPUT INPUTS INSTR INT INTEGER IOCTL IOCTL$ IS KEY KILL LBOUND LCASE$ LEFTS LEN LET LINE LIST GO TO2 — перейти к HEXadecimal string — шестнадцатеричная строка если IMPlication — импликация INput KEY — ввести символ INput from Port — прочитать байт из порта вво- да/вывода ввести (переменную) INPUT string — ввести строку символов IN STRing position — позиция в строке INTeger —целое (число) целое (тип данных) Input/Output ConTroL data string to device driver — послать управляющую строку драйверу устройства Input/Output ConTroL data string from device driver — принять управляющую строку от драй- вера устройства если клавиша уничтожить (файл) Lower BOUND — нижняя граница (массива) Lower-CASE string — строка в нижнем регистре слева длина пусть будет3 линия список (функциональных клавиш) 2 Старайтесь не использовать оператор GOTO для прямой передачи управле- ния. Вместо этого используйте управляющие конструкции SELECT...END SELECT, DO...LOOP, WHILE...WEND, FOR. NEXT. Подробности см. в Главе 2 "Основы языка BASIC", раздел "Избегайте устаревших конструкций" 3 Этот оператор может опускаться при написании программы. Помните,