Г Л А В А 4 ---------------------------------------------------------------- ТУРБО БЕЙСИК : Язык ---------------------------------------------------------------- Структура программы ---------------------------------------------------------------- Программы ТБ состоят из одной или более строк исходного текста, каждая из которых имеет следующий формат: [linenumber] statement [:statement] ... ['comment] [номер-строки] оператор [:оператор] ... ['комментарий] или label: метка : или $метаоператор $metastatement Linenumber - это целое число в интервале от 0 до 65535, ко- торое может произвольно обозначать строки программы. ТУРБО БЕЙ- СИК весьма "просто" относится к номерам строк. Они могут переме- жаться метками, использоваться в одних частях программы и не использоваться в других. Фактически они могут и не следовать в обычной последовательности, хотя две строки не могут иметь оди- наковый номер. Ни одна строка не может одновременно иметь и мет- ку и номер. Фактически номера строк и есть метки. Statements - это "строительные кирпичики", составляющие программу. В ТБ около 100 типов операторов (см. Глава 5, где да- ется весь список). В строке может не быть ни одного оператора, либо один или несколько, отделенные двоеточием. Ниже приведены все допустимые строки ТБ: Start : 'только метки 10 'только номер строки $INCLUDE "CONST.TBS" 'метаоператор 20 а = а+1 'номер строки + оператор а = а+1 : b = b+1 'два оператора 30 а = а+1 : b = b+1 : с = а+b 'номер строки, три оператора Единственным ограничетелем количества операторов, могущих поя- виться в строке, является ее размер, составляющий в ТБ 249 коло- нок. В отличие от интерпретируемого Бейсика, в ТБ пробелы, ком- ментарии и чистые строчки компилятор игнорирует. Не рекомендуется писать строки шире дисплейного окна редак- тора, имеющего 80 колонок (несмотря на шикарную возможность горизонтальной прокрутки, имеющуюся в редакторе). Выдя за пре- делы 80 колонок при редактировании, вы не сможете увидеть на дисплее строку целиком, да и при распечатке выглядеть это будет не очень красиво. В тех случаях, когда требования синтаксиса вынуждают вас создавать строку длиной более 80 символов, ставьте символ под- черкивания (_) в конце строки. Это позволяет рассматривать ТБ следующую строку как продолжение первой. Эта строка может быть таким же образом продолжена. Например: FIELD #1,30 AS name$, 30 AS address1$, 30 AS address2$,_ 15 AS city$, 2 AS state$, 5 AS zip$,_ 30 AS comments$ С точки зрения компилятора - это одна длинная строка, начи- нающаяся с FIELD и заканчивающаяся comments$, без единого символа подчеркивания. Comment - это любой текст, добавляемый в конце строки и от- деляемый от собствено программы апострофом ('). Апостроф (') можно использовать вместо REM (комментарий) для разделения ком- ментария и оператора на строке, если только это не оператор DATA (DATA посчитает его частью данных). В отличии от REM, не нужно отделять комментарий с апострофом еще и двоеточием от соседнего оператора. Приведенные ниже примеры абсолютно одинаковы для компилятора: area = radius^2*3.14159 'вычисление площади area = radius^2*3.14159 :REM вычисление площади Label (метка) должна стоять на строке одна (хотя может сопровож- даться комментарием); она служит для идентификации непосредс- твенно следующего за ней оператора. Метка начинается с буквы и может содержать любое количество букв и цифр. Регистр не важен: THISLABEL и ThisLabel эквивалентны. После метки ставится двоето- чие, а операторы, относящиеся к этой метке (например, GOSUB) не должны включать двоеточий. Например SortInvoices : GOSUB SortInvoices 'обращается к метке ExitPoint : a = a + I 'недопустимо; метка должна быть на строке $metastatements - это операторы,работающие на другом уровне, чем обычные операторы. Называемые директивами компилятора, они всегда начинаются с символа доллара ($). Стандартные операторы управляют компьютером программ; метаоператоры как режимы вариан- тного меню управляют компьютером во время компиляции. Примером служит метаоператор $INCLUDE, заставляющий компь- ютер ввести содержимое другого файла на указанное место в теку- щий файл. Заметьте, что метаоператоры ТБ не появляются в ремарках (REM) как метаоператоры некоторых других компиляторов БЕЙСИК. На строке может быть только один метаоператор. Набор сиволов ТУРБО БЕЙСИК - - - - - - - - - - - - - - Буквы от A до Z или от a до z и цифры от 0 до 9 могут быть использованы для формирования идентификаторов (меток, парамет- ров, процедур и имен функций). Цифры от 0 до 9; символы . + - ; а также буквы E, e, D и d можно использовать для создания числовых констант. Следующие символы имеют особое значение в ТБ: ---------------------------------------------------------------- Символ Описание / функция ---------------------------------------------------------------- = Знак равенства (оператор назначения, сравнения) + Знак плюс (сложение и оператор конкатенации строк) - Знак минус (вычитание и оператор отрицания) * Звездочка (оператор умножения) / Черта дроби (оператор деления) \ Наклонная черта влево (оператор деления целых чисел) ^ Каре (оператор возведения в степень) % Процент (целочисленный символ-определитель) & Символ "и" (символ-определитель длинных целых чисел и дескриптор недесятичных оснований) ! Восклицательный знак (символ-определитель с одинар- ной точностью) # Номер (символ-определитель с двойной точностью) $ Символ "доллар" (символ-определитель строки, префикс метаоператора) () Скобки (фактические параметры функции/процедуры, мас- сивы, расположение выражений по приоритету) [] Квадратные скобки (действительны только для массивов) Пробел (разделитель) , Запятая (многоцелевой отделитель) . Точка (десятичная точка, отделитель расширения файла) ' Апостроф (отделитель комментария/ремарки) ; Точка с запятой (многоцелевой отделитель) : Двоеточие (отделитель оператора) ? Знак вопроса (заменитель команды ПЕЧАТАТЬ/PRINT) < Меньше (оператор сравнения) > Больше (оператор сравнения) " Кавычки (отделитель цепочки/строки) _ Символ подчеркивания (символ продолжения строки) ---------------------------------------------------------------- Резервируемые слова - - - - - - - - - - ТУРБО БЕЙСИК резервирует использование нескольких слов для опре- деленных синтаксических целей. Эти служебные слова нельзя ис- пользовать в качестве меток, параметров, именованных констант или названий процедур или функций, хотя ваши идентификаторы и могут содержать их (см. Таблицу 4-1). Например END (Конец) - недопустимое имя переменной, т.к. оно противоречит служебному слову END. Однако ENDHERE и FRIEND при- емлемы. Начинать идентификатор с FN также нельзя, поскольку это противоречит синтаксису функций, определяемых пользователем. Попытка использования служебного слова в качестве идентифи- катора вызовет синтаксическую ошибку компиляции. Таблица 4-1 Служеные слова ТУРБО БЕЙСИКа ---------------------------------------------------------------- $COM1 CLOSE ERR LOC POKE STRING$ $COM2 CLS ERROR LOCAL POS SUB $DEBUG COLOR EXIT LOCATE PRESET SWAP $DYNAMIC COM EXP LOF PRINT SYSTEM $ELSE COMMAND EXP10 LOG PRINT # TAB $ENDIF COMMON EXP2 LOG10 PSET TAN $EVENT COS FIELD LOG2 PUT THEN $IF CSNG FILES LOOP PUT$ TIME$ $INCLUDE CSRLIN FIX LPOS RANDOM TIMER $INLINE CVD FN LPRINT RANDOMIZE TO $LISTNE CVI FOR LPRINT # READ TROFF $OPTION CVL FRE LSET REG TRON $SEGMENT CVMD GET MEMSET REM UBOUND $SOUND CVMS GET$ MID$ RESET UCASE$ $STACK CVS GOSUB MKDIR RESTORE UNTIL $STATIC DATA GOTO MKD$ RESUME USING ABS DATA$ HEX$ MKI$ RETURN USR ABSOLUTE DECR IF MKL$ RIGHTS USR0 AND DEF IMP MKMD$ RMDIR USR1 APPEND DEFDBL INCR MKMS$ RND USR2 AS DEFINT INCEY$ MKS$ RSET USR3 ASC DEFLNG INLINE MOD RUNT USR4 AT DEFSNG INP MTIMER SAVE USR5 ATN DEFSTR INPUT NAME SCREEN USR6 BASE DELAY INPUT # NEXT SEEK USR7 BEEP DIM INPUT$ NOT SEG USR8 BIN$ DO INSTAT OCT$ SELECT USR9 BINARY DRAW INSTR OFF SERVICE VAL BLOAD DYNAMIC INT ON SGN VARPTR BSAVE ELSE INTERRUPT OPEN SHARED VARPTR$ CALL ELSEIF IOCTL OPTION SHELL VARSEG CASE END IOCTL$ OR SIN VIEW COBL ENDMEM KEY OUT SOUND WAIT CEIL ENVIRON KILL OUTPUT SPACE$ WEND CHAIN ENVIRON$ LBOUND PAINT SPC WHILE CHDIR EOF LCASE$ PALETTE SQR WIDTH CHR$ EQV LEFT$ PALETTE STATIC WINDOW CINT ERADR LEN PEEK STEP WRITE CIRCLE ERASE LET PEN STICK WRITE # CLEAR ERDEV LINE PLAY STOP XOR CLNG ERDEV$ LIST PMAP STR$ ERL POINT STRIG ---------------------------------------------------------------- Числа в ТУРБО БЕЙСИКе ---------------------------------------------------------------- Осторожное обращение и загрузка числовых данных составляет важ- ную часть любой системы программирования. ТУРБО БЕЙСИК в соот- ветствии с традициями БЕЙСИК был разраьотан так, чтобы вы могли в значительной мере игнорировать технические моменты внутренней обработки числовой информации. Если вы никогда не задумывались о таких вещах, как скорость вычислений, точность и требования к памяти, ваши программы, возможно, будут работать, как вы и ожи- дали. Однако, знание основополагающих моментов поможет вам пи- сать программы более быстрые, более точные и требующие меньшего объема памяти. Для большей эффективности ТУРБО БЕЙСИК хранит и обрабатывает числа четырьмя различными способами; т.е. обеспечивает четыре уникальных числовых "типа" данных: целые числа, длинные целые числа, с одинарной точностью с плавающей запятой и с двойной точностью с плавающей запятой. Целые числа - - - - - - Самые простые числа, с которыми ТУРБО БЕЙСИК "живо спрвляется" в своих встроенных программах - целые числа. Для ТУРБО БЕЙСИКа це- лое число - это число без десятичной в интервале от -32768 до 32767. Эти значения основываются на шестнадцатиричном изображе- нии целых чисел: 32768 это 2^15. Хотя этот дапазон и ограничивает использование целых чисел, наверняка большинство параметров в каждой написанной вами прог- рамме (такие, как счетчики в циклах FOR/NEXT) будут нормально работать в этих границах. Если это так, использование целых чисел позволяет создавать быстрые и компактные программы. Ваш компьютер прекрасно приспособлен для произведения арифметических действий с целыми числами (например, производит их быстро), а каждая цифра занимает только 2 байта памяти. Переключатель режима "Переполнение"(Overflow) в Вариантном (OPTIONS) меню позволяет создавать программы, в которых случаи переполнения целочисленных переменных автоматически регистриру- ются и сообщаются. Длинные целые числа - - - - - - - - - - Значительно расширив возможности интерпретирующего БЕЙСИКа, ТУР- БО БЕЙСИК обеспечивает цифровой тип известный как длинные целые числа. Для того, чтобы избежать ошибок округления, длинные целые числа являются идеальными для бухгалтерских расчетов. Как и обычные целые числа, длинные целые числа не должны содержать де- сятичных запятых. Они занимают диапазон от -2147483648 до +2147483647 (-2^31 до 2^31-1 или от -2 млрд. до +2 млрд.). Для хранения таких чисел требуется 4 байта и расчеты выполняются несколько медленнее, чем с целыми числами. Длинные целые числа достаточно эффективны и безусловно зас- луживают более близкого рассмотрения, особенно в компьютерах, не оборудованных сопроцессором 8087. В зависимости от применения вашего компьютера, десятичные точки могут иметь гораздо меньшее значение, чем вы полагаете. Например, суммы денег можно выражать в центах, а для отображения долларов делить на 100. Таким обра- зом, можно выразить суммы до 20 млн. долларов. Числа с одинарной точностью с плавающей запятой - - - - - - - - - - - - - - - - - - - - - - - - "С одинарной точностью с плавающей запятой" (или просто с оди- нарной точностью) - вероятно, самый универсальный числовой тип в ТУРБО БЕЙСИКе. Такие значения могут содержать десятичные запятые и имеют диапазон от 10^-38 до 10^38, как отрицательный, так и положительный. Скорость счета,правда, не так высока,как в расче- тах с длинными целыми числами,и для каждого числа нужно 4 байта. Недостаток чисел с одинарной точностью в том, что они не пригодны там, где требуется точность более, чем до шестого зна- ка. Например, одинарная точность хороша для таких чисел, как $451.21 и $6411.92, но число $671421.62 не может быть представ- лено точно, так как содержит слишком много цифр, равно как и числа 234.56789 или 0.00123456789; одинарная точность представ- ления даст не более шести цифр: $671421 или 234.568 или 0.00123457. В зависимости от применения вашего компьютера это округление может быть несущественным либо критическим для вас. С двойной точностью с плавающей запятой - - - - - - - - - - - - - - - - - - - - Двойная точность соотносится с одинарной так же, как длинные це- лые числа с целыми. Они занимают вдвое больше места в памяти (8 байт вместо 4) и, следовательно, требуют больше времени для вы- числений, имеют больший диапазон (10^308) и точность (16 знаков против 6 при одинарной точности). Требование по записи с двойной точностью становится особенно важным, когда мы имеем дело с массивами. При двойной точности для хранения массива, содержащего 5000 элементов, требуется 40000 байт. Целочисленный массив с таким же числом элементов за- нимает всего 10000 байт. Обратите внимание: в ТУРБО БЕЙСИКе используется станарт ИИЭР (Институт инжененров по электротехнике и радиоэлектронике) для арифметических действий с плавающей запятой, а не патентованный формат Microsoft, используемый в Интерпретируемом БЕЙСИКе . Поэ- тому необходимо использовать специальные трансляционные функции Майкрософт/ИИЭР (CVMS,CVMD,MKMS$ и MKMD$) для считывания и запи- си данных с плавающей запятой, содержащихся в файлах прямого доступа, создаваемом в Интерпретируемом Бейсике. (Более подробно об этом см. раздел "Файлы прямого доступа" данной главы). Если вы еще не решили, какой тип с плавающей запятой исполь- зовать, мы советуем - с двойной точностью. По существу цифровой "движок" ТУРБО БЕЙСИКа лучше всего работает на горючем двойной точности. Его трансцендентные функции, такие как COS и LOG (ко- синус и логарифм), дают результаты с двойной точностью. Все-таки одинарная точность, вероятно, будет лучше для больших массивов, там, где будет более очевидно ее "размерное" преимущество. Расчеты и 8087 - - - - - - - - Сопроцессор 8087 (80287 на компьютерах AT-типа) значительно сок- ращает разницу в скорости счета между различными типами числовых данных. Поскольку 8087 ведет все расчеты с двойной точностью не- зависимо от типа, это делает двойную точность еще более привле- кательной. В отличие от Интерпретируемого БЕЙСИКа ТУРБО БЕЙСИК не всегда округляет дробные части чисел в большую сторону, а каждый раз рассматривает особым образом каждое число, содержащее 5 в дробной части: число округляется в сторону ближайшего четно- го числа. Например число 0.5 будет округлено в меньшую сторону до 0 - ближайшего четного числа. И число 9.005 тоже будет округ- лено в меньшую сторону, т.е. в данном случа до 9.000. Поскольку наиболее широко употребляемые методы округления чисел всегда округляют в большую сторону,ТУРБО БЕЙСИК фактичеки обеспечивает более равное распределение. Константы и переменные ---------------------------------------------------------------- Программы ТУРБО БЕЙСИКа обрабатывают два четко определенных класса данных: константы и переменные. Переменная может изменять свое значение во время выполнения программы. Значение константы фиксируется при компиляции и не может изменяться во время выпол- нения программы. ТУРБО БЕЙСИК обеспечивает три типа констант: строковые, числовые константы и, в дополнение к Интерпретируемо- му Бейсику, особая форма целочисленной константы - именные константы. Строковые константы - - - - - - - - - - Строковые константы - это просто группы символов: взятых в ка- вычки, например: "Это строка" "3.14159" "Тим Джоунс. Адвокат" Если строковая константа стоит последней на строке, закры- вать кавычки не обязательно: PRINT "Это небрежно, но допустимо. Числовые константы - - - - - - - - - - Числовые константы представляют числовые величины и состоят в основном из цифр от 0 до 9 и десятичной запятой. Впереди отрица- тельных констант должен ставиться знак минус (-); знак плюс (+) для положительных констант не обязателен. Величина точности, со- общаемая вами, определяет внутреннее представление (целое число, длинное целое число, с одинарной точностью, с двойной точ- ностью), которым будет пользоваться ТУРБО БЕЙСИК в обработке этой константы. Если величина не содержит десятичной запятой и находится в интервале от -32768 до 32767 - ТУРБО БЕЙСИК использует свой це- лочисленный тип. Если величина - целое число от -2^31 до 2^31-1 включительно (приблизительно от -2 млрд. до +2 млрд.), но вне диапазона целочисленных констант, - ТУРБО БЕЙСИК использует свой длинный целочисленный тип. Если величина содержит десятичную запятую и до шести цифр - ТУРБО БЕЙСИК использует тип с одинарной точностью и плавающей запятой. Числовая константа с десятичной запятой, состоящая более чем из шести цифр, или целое число слишком большое для длинного це- лочисленного формата, сохраняется в формате двойной точности с плавающей запятой. Например: 345.1 С одинарной точностью 1.10321 С одинарной точностью 1.103213 С двойной точностью 3453212*1234 С двойной точностью Идентификация целочисленных констант в других основаниях - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Иногда удобнее выражать целые числа в иных основаниях, чем деся- тичные. Это особенно актуально при выражении информации бинарной по своей природе, например, машинных адресов. ТУРБО БЕЙСИК поз- воляет специфицировать целочисленные данные в шестнадцатиричной (основание 16), восьмиричной (основание 8) и двоичной (основание 2) записи. Заметьте, что длинные целые числа не могут быть представлены в альтернативной записи. Шестнадцатиричные константы состоят максимально из четырех знаков, причем, каждый символ из интервала 0-9 и A-F, перед константой пишется &H. Восьмиричные константы содержат только цифры от 0 до 7, мак- симально могут состоять из 6 цифр и перед ними пишется &Q (или &O или просто &). Двойчные константы содержат только нули и единицы, могут состоять максимально из шестнадцати цифр и перед ними мишется &B. Каждая из следующих констант представляет целое число, деся- тичное 256 : 256 , &H100 , &O400 , &400 , &B100000000 Именные константы - - - - - - - - - ТУРБО БЕЙСИК позволяет называть целочисленные константы по име- нам. Это несолько похоже на функцию CONST Паскаля. Только целые числа можно именовать таким образом. Для того, чтобы назвать целочисленную константу , предварите ее идентификатор знаком (процент) % и назначьте ему целочислен- ную константу. В отличие от переменных можно использовать имен- ную константу в левой части оператора присваивания единожды, и только постоянное значение (не переменная или выражение) может быть присвоено ей. Например: %debug = -1 ' именная константа, значение -1 debug% = 112409 ' целочисленная переменная PRINT %debug , debug% ' это отдельные объекты Используйте именные константы для флагов условной трансляции (см. метаоператоры в Главе 5) и для повышения "читаемости" ваших программ. (Можно также использовать именные константы для сниже- ния вероятности появления "магических чисел" в ваших программах. Магические числа - это мистичесике величины, имеющие какое-то значение для вас в момент написания программы, но не через пол- года, когда вы к ней возвращаетесь). Переменные - - - - - - Переменная - это идентификатор, представляющий числовое или строковое значение. B отличие от констант значение переменной может меняться при выполнении программы. Как и метки, имена пе- ременных должны начинаться с буквы и могут содержать любое коли- чество букв и цифр. Не скупитесь при именовании важных перемен- ных. В отличие от Интерпретатора Бейсика длинные имена переменных в ТБ не занимают память в иомент выполнения. Перемен- ные EndOfMonthTotals (ИтогНаКонецМесяца) и emt занимают ровно по четыре байта памяти в момент выполнения. ТУРБО БЕЙСИК поддерживает пять типов переменных: строковую, целочисленную, длинную целочисленную, с одинарной точностью и двойной точностью. Имя переменной определяет ее тип. Обычно имя переменной заканчивается символом описания типа. Строковые переменные заканчиваются знаком "доллар" ($): a$="ТУРБО БЕЙСИК" В целочисленных переменных используется знак "процент (%): a% = 15 В длинных целочисленных использован знак "амперсанд" (&): a& = 7000 В переменных с одинарной точностью с плавающей запятой ис- пользован восклицательный знак (!): a! = 1.1 Переменные с двойной точностью с плавающей запятой оканчива- ются на знак "номер" (#): a# = 1.031 Если вы не укажете символ описания типа переменной, ТУРБО БЕЙСИК использует по умолчанию тип с одинарной точностью. Для назначения другого типа "по умолчанию" испотльзуйте оператор "DEFтип". Например: a# = 1.031 'a# - переменная с двойной точностью b =16.5 'b - с одинарной точностью a% = 3 'a% - целочисленная переменная: a# - отдельная ' переменная DEFINT m 'тип "по умолчанию" для переменных, начинающихся ' с m теперь целочисленный m = 16 'm - целое число Обратите внимание на то, что a%, a#, a&, a$ и a! - это пять различных переменных. Массивы ---------------------------------------------------------------- Массив - это группа строковых или числовых данных, имющих одно имя переменной. Отдельные значения, составляющие массив, называ- ются элементами. Элемент массива можно использовать в операторе или выражении, где обычно используются обычные строковые или числовые переменные. Другими словами, каждый элемент массива - сам по себе переменная. При запуске программы каждый элемент каждого числового или строкового массива устанавливается в нулевую величину или пустую строку (""). DIM- оператор (установка размерности) динамического массива также очищает каждый элемент. Если программа затем запускается оператором RUN, эта инициализация повторяется. Описать имя и тип массива, а также число и организацию его элементов, можно с помощью оператора DIM (установка размернос- ти). Например: DIM payments(55) создает переменную массива "payments" (выплаты), состоящего из 56 элементов с одинарной точностью, нумеруемых от 0 до 56. Мас- сив payments и переменная с одинарной точностью, также названная payments - это раличные переменные. Индексы - - - - Отдельные элементы массива помечаются индексами, целочисленными выражениями в скобках справа от имени переменной массива. Напри- мер, payments(3) и payments(44) - это два элемента из 56 элемен- тов массива "payments". Обычно первый элемент массива получает значение индекса, равное 0, хотя это можно изменить, используя операторы DIM или OPTION BASE: например: 'Данный оператор DIM описывает 56-элементный массив с индексными 'границами от 0 до 55. DIM payments(55) OPTION BASE 1 'Данный оператор DIM описывает 55-элементный массив с индексными 'границами от 0 до 55 вследствие применения оператора OPTION 'BASE. DIM payments(55) Если массив используется в программе без установки размер- ности (DIM), ТУРБО БЕЙСИК работает так, словно описан массив с одинадцатью элементами (индексы от 0 до 10). Тем не менее мы настоятельно советуем вам заняться четкой установкой размерности каждого массива, используемого вашей программой. В дополнение к функциям Интерпретируемого Бейсика по манипу- лированию массивами, ТУРБО БЕЙСИК позволяет определять диапазон значений индексов, а не просто верхнюю границу. Например, опера- тор DIM DIM b(50:60) создает массив b, состоящий из одиннадцати элементов с одинарной точностью, с номерами от 50 до 60. Оператор: DIM c(50:60,25:45) создает двумерный массив c, содержащий 231 (11*21) элемент. Возможность описать диапазоны индексов в ТУРБО БЕЙСИК позво- ляет моделировать структуру программных данных наиболее опти- мально для текущей задачи. Рассмотрим, например, программу, прослеживающую статистику рождаемости (birth) в 19 веке. Структура основных данных прог- раммы представляет собой массив с одинарной точностью, состоящий из 100 элементов, содержащих количество детей, рожденных каждый год прошлого века. В идеале следует создать массив, в котором будут использованы значения индексов, равные году учета рождае- мости (например, рождаемость(1851) представляет, сколько детей рождено в 1851 году), и поэтому отрывок программы DIM births(1899) . . . FOR n = 1800 nj 1899 PRINT "Всего было" births(n) "рождений в" n NEXT n будет предельно прост. К сожалению, DIM births(1899) создает 1900-элементный массив, в котором первые 1800 элементов беспо- лезны. Обычно программисты, работающие в Бейсике, решают эту проблему "обыгрывая" индексы и описывая массив как DIM births(99) . . . FOR n = 1800 TO 1899 PRINT "Всего было" births(n-1800) "рождений в" n NEXT n Хотя это и срабатывает, но усложняет и замедляет программу, поскольку неожиданно возникает проблема выполнения 100 вычита- ний, которых ранее не было. Соответствующий оператор OPTION BASE также можно использо- вать для определения низшего элмента массива, хотя механизм раз- бивки на диапазоны более действенный и предпочтительный. Строковые массивы - - - - - - - - - Элементы строковых массивов хранят строки, а не числа. Длина строки может быть различной:от 0 до 32767 знаков. Обычный стро- ковый объем для строк и строковых массивов составляет 64К. Например: DIM a$(50) ' создает последовательность ' из 51 независимых ' строковых переменных: a$(0)= "Строка средней длины" 'строка из 20 знаков a$(1)= "" 'пустая строка (по умолчанию) a$(0)= SPACE$(20000) 'строка из 20000 знаков . . . a$(50)="The last one" 'строка из 21 знака Многомерные массивы - - - - - - - - - - Массивы могут иметь одну или несколько размерностей, максимально - 8. Одномерный массив, например, payments - это просто список значений. Двумерный массив представляет собой таблицу чисел с рядами и колонками данных. Возможны также и многомерные массивы. DIM a(15) (одномерный список) DIM b(15,20) (двумерная таблица) DIM c(5,5,10,20,3) (пятимерный массив) Максимальное число элементов на каждую размерность - 32768. Проверка связей массива - - - - - - - - - - - - ТУРБО БЕЙСИК делает все возможное, чтобы избавить вас от непри- ятностей, связанных с неверными индексами (т.е. индексами либо слишком большими, либо слищком малыми для данного массива). И компилятор немедленно сообщает о неверном индексе: DIM a(50) a(51) = 33 Эта программа не будет транслироваться, т.к. ТУРБО БЕЙСИК сознательно не будет генерировать команду доступа к 52-му эле- менту 51-элементного массива. Однако, если в качестве индексов использовать переменные, компилятор не обнаружит ошибки: DIM a(50) n = 51 a(n) = 33 И хотя данная программа будет компилироваться без ошибки, все же можно поймать внедиапазонный индекс в 3-ей строке при вы- полнении программы путем ее компиляции с включенным режимом "От- ладка связей" (По проверке индексов см. раздел "Команды Вариан- тов" в Главе 3). Требования к хранению массивов - - - - - - - - - - - - - - - - По техническим причинам, связанным с быстродействием и эффек- тивным использованием объема программ, ТУРБО БЕЙСИК ограничивает размер каждого отдельного массива до 64 Килобайт, хотя в прог- рамме может содержаться столько 64-килобайтовых массивов, сколь- ко позволяет ЗУ. Максимальное число элементов в массиве зависит от его типа, как показано ниже: ---------------------------------------------------------- Тип Требования к объему памяти ---------------------------------------------------------- Целочисленный 2байта на элемент (32768 на 64 К) Длинный целочисленный 4байта на элемент (16384 на 64 К) С одинарной точностью 4байта на элемент (16384 на 64 К) С двойной точностью 8байт на элемент (8102 на 64 К) Строковый 4байта на элемент (16384 на 64 К) ---------------------------------------------------------- Внимание: В элементе строкового массива содержится только информация по указателям и длине. Собственно строковые данные хранятся в строковом пространстве и занимают столько байт, сколько знаков в строке. Пространство строки максимально может содержать 64К знаков. Динамическое распределение - - - - - - - - - - - - - - ТУРБО БЕЙСИК обеспечивает динамическое распределение памяти. Ди- намическое распределение означает создание массивов изменяющейся величины при выполнении, а не определение фиксированных (стати- ческих) структур при компилировании. Это позволяет создавать массивы точно таких размеров, кото- рые необходимы для обработки данных, задаваемых программе при выполнении. После завершения их функций память, отведенная дина- мическим массивам, может быть возвращена и вновь использована. Для создания динамического массива просто используйте пер- менные аргументы в операторе DIM; если есть место в ЗУ - массив будет создан. Когда программа завершила использование этого мас- сива, примените опреатор ERASE (Стереть) для того, чтобы изба- виться от него и использовать память для других целей. Например: 'выяснить, сколько записей в каталоговом файле, 'затем установить размеры динамических массивов и загрузить их OPEN "PARTS.DTA" AS #1 LEN = 56 count = LOF(1)/56 DIM partNo(count), desc$(count), quan(couny), cost(count) GOSUB LoadArrays GOSUB UseArrays ERASE partNo, desc$, quan, cost Чтобы воспользоваться преимуществами динамических массивов ТУРБО БЕЙСИКа, нужно лишь сделать оценочный опрос каждого масси- ва вашей программы: статический или динамический? Имеет ли он фиксированный размер в соответствии с конфигурацией программы, или это зависит от некоего параметра, величина которого неиз- вестна до выполнения программы? Например, массив births из ранее приведенного примера лучше всего создавать как статическую структуру - его величина всегда будет составлять 100 элементов. Небольшим неудобством динамических массивов является тот факт, что иногда можно безуспешно пытаться установить размер- ность большого массива DIM-оператором при выполнении программы, но для выполнения этой функции просто не будет достаточного ко- личества свободной памяти. Если же в программе только статичес- кие массивы и достаточно памяти для запуска - то память не будет исчерпана; массивы такой программы создаются еще до того, как начинается ее выполнение. В связи с этим программа, использующая динамические массивы, должна знать, что при выполнении может оказаться недостаточно свободной памяти для описания требуемых массивов. Прежде чем ус- тановить размерность динамического массиа DIM-оператором, вос- пользуйтесь функцией FRE(-1), чтобы проверить, достаточно ли места для него. Описание статических или динамических массивов - - - - - - - - - - - - - - - - - - - - - - - - Метаоператоры $DYNAMIC и $STATIC управляют типом задания масси- вов в программе по умолчанию. Обычно в программе содержится только один из этих метаоператоров. По умолчанию компилятор под- разумевает атрибут $STATIC. Массивы считаются динамическими в следующих случаях: - Если они описаны после употребления метаоператора $DYNAMIC: $DYNAMIC DIM A(10) - Если явно заданы как динамические: DIM DYNAMIC A(10) - Если в операторе DIM использована переменная: X% = 10 DIM A(X%) - Если массив включен в оператор COMMON: DIM A(10) COMMON A(1) - Если есть два или более операторов DIM для олного и того же идентификатора массива: DIM A(10) A(0) = 10 DIM A(10) - Если массив описывается как локальный в процедуре или функ- ции: DEF FNTest% LOCAL A() DIM A(10) FNTest = A(10) END DEF Класс хранения массива также может быть задан атрибутами STATIC и DYNAMIC в DIM-операторе. Кроме того, массив всегда ди- намический, если в соответствующем DIM-операторе используется выражение. Например: $STATIC 'отсюда и далее считать все массивы стати- 'ческими DIM a(40), b(20,20) 'поэтому a и b оба статические массивы DIM DYNAMIC c(20) 'атрибут DYNAMIC отменяет примененный по 'умолчанию $STATIC DIM d(n) 'использование переменной в DIM также ус- танавливает атрибут DINAMIC $DYNAMIC 'отсюда и далее компилятор считает массивы динамическими DIM e(50) 'поэтому e - массив динамический "Избавиться" от динамических массивов можно с помощью опера- тора ERASE: удаление статических массивов с помощью ERASE не восстанавливает память, но устанавливает их элементы на 0 (в строковых массивах в нулевую строку). Выражения ---------------------------------------------------------------- Выражение состоит из операций и операндов, осуществляющих оп- ределенные операции при вычислении выражения. В ТУРБО БЕЙСИКе существует два основных типа выражений: строковые и числовые. Строковое выражение состоит из строковых констант, строковых переменных и строковых функций (тех, которые оканчиваются на $), соединенные, где это необходимо, конкатенационной операцией - знаком плюс (+). Строковые выражения упрощают до строки; т.е. до последовательности символов ASCII известной длины. Среди приме- ров строковых выражений следующие: "Cats and dogs" a$ a$ + z$ LEFT$(a$ + z$) a$ = MID$("Cats and dogs",6,3) RIGHT$(MID$(a$ + z$,1,6),3) Числовые выражения состоят из числовых констант, переменных и функций, разделяемых, где необходимо, числовыми операциями. Числовые выражения всегда упрощаются в соответствии со значением одного из четырех числовых типов (целочисленному, длинному цело- численному, со динарной точностью, с двойной точностью). Примеры числовых выражений включают: 37 37/15 a 37/a SQR(37/a) SQR((c + d)/a) * SIN(37/a) При формировании числовых выражений следует иметь в виду, что определенные операции будут произведены первыми. Ниже приве- ден порядок вычисления выражения. Возведение в степнь имеет выс- ший приоритет; IMP(импликация) - низший. - Возведение в степень (^) - Унарный минус (-) - Умножение, Деление с плавающей запятой (*,/) - Целочисленное деление (\) - По модулю (MOD) - Сложение, Вычитание (+,-) - Операции сравнения (<,<=,=,>,>=,<>) - Отрицание (NOT) - И (AND) - ИЛИ, Исключающее ИЛИ (OR, XOR) - Эквивалентность (EQV) - Импликация (IMP) Например значение выражения 3 + 6/3 равно 5, а не 3. Пос- кольку приоритет деления выше, чем вычитания, операция деления (6/3) производится первой. При проведении операций с одинаковым приоритетом ТУРБО БЕЙ- СИК производит их слева направо. Например, в выражении 4 - 3 + 6 вычитание (4-3) производится перед сложением (3 + 6), что дает промежуточное выражение 1 + 6. Операции в скобках имеют высший приоритет и всегда произво- дятся первыми; внутри скобок действуют общие правила. Арифметические операции - - - - - - - - - - - - Арифметические операции производят обычные математические опера- ции. В Таблице 4-2 перечислены арифметические операции ТУРБО БЕЙСИК в порядке возрастания приоритетов. Таблица 4-2. Арифметические операции ---------------------------------------------------------- Операция Действие Пример ---------------------------------------------------------- ^ Возведение в степень 10^4 - Унарный минус -16 *, / Умножение, Деление с плаваю- 45 * 19, 45 / 19 щей запятой \ Целочисленное деление 45 \ 19 MOD По модулю 45 MOD 19 +,- Сложение, Вычитание 45 + 19, 45 - 19 ----------------------------------------------------------- Некоторые из этих операций заслуживают краткого пояснения. Обратная черта дроби (\) представляет целочисленное деление. Це- лочисленное деление округляет свои операнды до целых чисел и да- ет округленное частное без остатка; например, 5 \ 2 равняется 2, а 9 \ 10 равно 0. Остаток целочисленного деления можно определить с помощью операции MOD (заметьте, что операция MOD действительна только с короткими целыми числами). Операция MOD похожа на операцию цело- численного деления, только она показывает остаток деления, а не частное; например, 5 MOD 2 равно 1 , а 9 MOD 10 равно 9. Операции сравнения - - - - - - - - - - Операции сравнения позволяют сравнивать значения двух строк или двух чисел (но не строки с числами) для получения булева резуль- тата: ВЕРНО (TRUE) или НЕВЕРНО (FALSE). Результату сравнения присваивается целочисленное значение "-1", если отношение верно, и "0" - если неверно. Например: PRINT 5 > 6, 5 < 6, (5 < 6)*15 выдает 0,-1 и -15. Хотя полученные численные результаты можно использовать в любом числовом выражении (например, a = (b*c) /13), числовые результаты, получаемые в операциях сравнения, как правило, используются в IF (ЕСЛИ) или других операторах принятия решения для определения направления дальнейшего выполнения прог- раммы. В Таблице 4-3 приведены операции сравнения. Таблица 4-3. Операции сравнения --------------------------------------------------- Операция Сравнение Пример --------------------------------------------------- = Равенство x = y <> Неравенство x <> y < Меньше, чем x < y > Больше, чем x > y <= Меньше или равно x <= y >= Больше или равно x >= y ---------------------------------------------------- Если арифметические операции и операции сравнения сведены в одном выражении, арифметические операции всегда выполняются первыми. Например, 4 + 5 < 4*3 дает всегда результат "-1"(ВЕР- НО), поскольку операция сравнения в конце проверяет правильность утверждения 9 < 12. Логические операции - - - - - - - - - - Логические операции выполняют булевы действия с целыми числами. При использовании с операциями сравнения они позволяют проводмть такие комплексные тесты, как IF day > 29 AND month = 2 THEN PRINT "Error in date" ЕСЛИ день > 29 И месяц = 2 ТО ПЕЧАТАТЬ "Ошибка в дате" Этот оператор производит логичекое И с целочисленными ре- зультатами, полученными в двух операциях сравнения. (Оператор И (AND) имеет более низкий приоритет, чем операторы сравнения ">" и "=", поэтому скобки не нужны). Например, если день = 29 и ме- сяц = 2, обе операции сравнения дают результат ВЕРНО (-1). Лежа- щее в основе бинарное представление целых чисел таково, что "-1" имеет величину &HFFFF (все биты включены); "0" - &H0000, все биты выключены. Затем оператор И производит операцию логического умножения этих двух ВЕРНЫХ результатов: 1111 1111 1111 1111 (-1) AND 1111 1111 1111 1111 (-1) ------------------------ 1111 1111 1111 1111 (-1) давая ВЕРНЫЙ (ненулевой) результат. Операция ИЛИ (OR) (иногда называемая включающее ИЛИ) дает ответ ВЕРНО, если один или оба ее аргумента ВЕРНЫ; и дает ответ НЕВЕРНО только если оба аргумента НЕВЕРНЫ. Например: -1 OR 0 это ВЕРНО (TRUE) 0 OR 0 это НЕВЕРНО (FALSE) 5 > 6 OR 6 < 7 это ВЕРНО (TRUE) Операция Исключающее ИЛИ (XOR) дает ответ ВЕРНО, если прове- ряемые величины разные, и ответ - НЕВЕРНО, если они равны. -1 XOR 0 это ВЕРНО (TRUE) -1 XOR -1 это НЕВЕРНО (FALSE) 5 > 6 XOR 6 < 7 это ВЕРНО (TRUE) Функция Эквивалентно (EQV) противоположна XOR. Она дает от- вет ВЕРНО, если исследуемые две логические величины одинаковы, и ответ НЕВЕРНО, если они неодинаковы: -1 EQV 0 это НЕВЕРНО (FALSE) -1 EQV -1 это ВЕРНО (TRUE) 5 > 6 EQV 6 < 7 это НЕВЕРНО (FALSE) Оператор Импликация (IMP) дает ответ НЕВЕРНО только если первый операнд ВЕРЕН, а второй НЕВЕРЕН: -1 IMP 0 это НЕВЕРНО (FALSE) -1 IMP -1 это ВЕРНО (TRUE) 5 > 6 IMP 6 < 7 это ВЕРНО (TRUE) Обратите внимание, что логичекие операторы производят дейс- твия только над целыми числами, но не над длинными целыми числа- ми или числами с плавающей запятой. Если операнды логического выражения не могут беть преобразованы в целые числа, происходит переполнение: x = 500000 IF x OR y THEN GOTO Exit Такой оператор IF может в результате дать ошибку переполнения, если x нельзя преобразовать в целое число. Поразрядные операции - - - - - - - - - - - В дополнение к созданию комплексных тестов логические операторы позволяют управлять базовыми двоичными кодами их целочисленных операндов. Самые известные операции - AND-, OR-, XOR-маскирова- ние. Маски И используются для установки в 0 выбранных битов цело- численного значения, не затрагивая остальных битов. Например, для обнуления старших 2 битов целочисленной величины &H9700 ис- пользуйте И с маской &H3FFF,т.е. в маске содержатся все единицы, кроме тех позиций битов, которые вы желаете обнулить: 1001 0111 0000 0000 &H9700 И(AND) 0011 1111 1111 1111 &H3FFF (маска) -------------------------- 0001 0111 0000 0000 &H1700 (результат) Маска ИЛИ устанавливает в 1 выбранные биты целого числа, не влияя на остальные. Для установок в 1 двух старших битов в &H9700 используйте ИЛИ с маской &HC000; т.е. маска содержит нули, за исключением позиций тех битов, которые вы желаете уста- новить в 1: 1001 0111 0000 0000 &H9700 ИЛИ(OR) 1100 0000 0000 0000 &HC000 (маска) -------------------------- 1101 0111 0000 0000 &H9700 (результат) Маска ИсклИЛИ инвертирует выбранные биты, не влияя на другие биты. Например, чтобы инвертировать 2 старших бита в &H9700 используйте ИсклИЛИ (XOR) с маской &C0000; т.е. все нули, кроме позиций, которые нужно инвертировать. 1001 0111 0000 0000 &H9700 ИсклИЛИ(XOR) 1100 0000 0000 0000 &HC000 (маска) -------------------------- 0101 0111 0000 0000 &H9700 (результат) Операции ИсклИЛИ (XOR) часто используются в графике, пос- кольку позволяют перемещать объект без помех на сложном фоне. Используйте ИсклИЛИ один раз, чтобы нарисовать объект на ка- ком-либо фоне, а затем еще раз на этом объекте в том же месте, чтобы стереть его, возвращая фон в его первоначальное состояние. Строковые операции и операци сравнения - - - - - - - - - - - - - - - - - - - - ТУРБО БЕЙСИК позволяет сравнивать строковые данные. Строковые выражения можно проверять на эквивалентность,а также алфавитное упорядоченное "больше чем" и "меньше чем". Два строковых выражения равны тогда и только тогда, когда они содержат абсолютно одинаковые символы в одинаковой последо- вательности. Например: a$ = "CAT" PRINT a$ = "CAT", a$ = "CATS", a$ = "cat" Строковое упорядочение основано на двух критериях и в данном порядке: (1) значения ASCII содержащихся знаков, и (2) длина. Например, "A" меньше "B", т.к. ASCII код для A - 65 меньше кода для B - 66. Заметьте, однако, что "B" меньше "a", т.к. код каж- дой строчной буквы больше кода соответствующей прописной (ровно на 32). При cортировке смешанной строчно-прописной информации можно использовать функции UCASE$ или LCASE$ для того, чтобы вы- бор регистров не влиял на сортировку. Длина имеет значение только если обе строки идентичны вплоть до длины короткой строки; в этом случае более короткая строка оценивается как меньшая, чем длинная; например, "CAT" меньше, чем "CATS".