http://sulfurzona.ru/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Wing-Thunder Game (fly simulator)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
Скачать игру Крыло-Гром (Wing-Thunder) бесплатно
 
 

Паскаль для новичков (часть 6)

 

Символьные массивы

 
Автор: Владислав Демьянишин
 
Паскаль для новичковРасскажу немного об одномерных массивах, состоящих из элементов типа Char. Если в качестве индекса символьного массива используется ограниченный целый тип, то такие массивы называются строками, например:
 
var
S : array [1..13] of char;
 
Pascal имеет некоторые дополнительные средства для работы с такими массивами. Во-первых, имеется возможность записывать конкретные значения строковых массивов с помощью изображения строки и использовать их в присваиваниях и передаче параметров:
 
S := ‘Пример строки’;
 
Изображение строки (то что справа) строится из цепочки символов, составляющих строковый массив, и заключается в одинарные кавычки (апострофы). Если необходимо задать апостроф внутри самой строки, то он удваивается. Допускается формирование строк с использованием десятичных кодов символов и специальных обозначений (см. главу “Символьный тип” в номере МК 51(170) от 24.12.2001). В этом случае строка составляется в виде слитной последовательности различных способов представлений символов, чередующихся в произвольном порядке, например:
 
#7’Текст сообщения’^A#176#176^B
 
Кроме того, для строковых массивов допускается операция конкатенации, обозначаемая символом “+” (плюс), смысл которой заключается в формировании нового символьного массива, число элементов которого равно сумме размеров массивов-операндов, а значениями элементов – элементы массивов-операндов, расположенные последовательно друг за другом. По сути, конкатенация – это просто сложение (склейка) двух строк в одну целую строку. Так, если в программе имеются описания:
 
var
S1 : array [1..9] of char;
S2 : array [1..6] of char;
 
То допустимы следующие операции:
 
begin
S1 := ‘Строковый’;
S2 := ‘массив’;
Writeln(S1 + ‘ ‘ + S2);
end.
 
В результате выполнения этой программы на экран дисплея будет выведено сообщение: Строковый массив
 
Обратите внимание, что в присваиваниях строк символьным массивам необходимо точное соответствие длин строк и размеров массивов. Так в символьный массив S1 длиной 9 символов заносится
строковое изображение (значение) имеющее длину тоже 9 символов.
Аналогично инициализируется и символьный массив S2. Следует иметь в виду, что операция конкатенации для символьных массивов НЕ допускается в правых частях присваиваний; например оператор
 
S := S1 + ‘ ‘ + S2;
 
вызовет ошибку компиляции “Error 26: Type mismatch” (несоответствие типов) независимо от размера символьного массива S. В подобных случаях необходимо использовать строки переменной длины (читайте далее “Строковые типы”).
 

Ошибки в работе с регулярными типами

 
Обсуждение регулярных типов я хотел бы завершить рассмотрением вопросов, связанных с ошибочными ситуациями, возникающими при их использовании. В первую очередь это относится к достаточно частым случаям вывода значения индекса за допустимые пределы. В простейших вариантах такие ошибки обнаруживаются при компиляции программы. Например, для массива
 
var
Vector : array [0..10] of real;
 
обращение вида
 
Vector [11] := 0.5;
 
Является некорректным, так как индекс 11 не принадлежит ограниченному типу 0..10, и вызовет прекращение трансляции с выдачей соответствующего диагностического сообщения “Error 76: Constant out of range” (значение вне допустимого предела).
Однако, оператор присваивания
 
Vector [ j ] := Vector [ j – 1 ] + j;
 
Компилятор не может квалифицировать как ошибочный, так как его корректность зависит от текущих значений индексов j и j –1. Если в процессе выполнения программы значение j лежит в диапазоне от 1 до 10, то этот оператор выполнится правильно; в противном случае будет зафиксирована ошибка времени выполнения.
Следует понимать, что при трансляции подобных операторов компилятор обычно вставляет в объектный код программы проверки на принадлежность текущих значений индексов допустимым диапазонам. Такие вставки увеличивают размер кода и замедляют выполнение, но делают программу более надежной.
 
Turbo Pascal позволяет частично управлять характером формирования объектного кода, относящегося к доступу к элементам массивов, посредством директивы компилятора $R. Так, если в тексте программы указана директива {$R+} то компилятор будет порождать код, делающий такие проверки. Этот режим принят по умолчанию. Директива {$R-} приводит к “облегченному” объектному коду, не содержащему проверок. В последнем случае выход индекса за пределы допустимого диапазона НЕ ПРИВЕДиТ к прекращению работы программы; обращение к “несуществующему” элементу массива даст неопределенный результат, что может сделать ход дальнейшего выполнения программы непредсказуемым, т.е. возможно вы сможете наблюдать на экране всякие блипы, свипы и другие спецэффекты
 
Как правило, при создании своих программ я применяю следующую тактику. В процессе разработки, отладки и тестирования необходимо сохранять действие директивы {$R+} в пределах всей программы. Только на завершающих этапах разработки, когда тестирование достаточно повысило мою уверенность в правильности и надежности работы программы, допустима установка директивы {$R-}, сокращающей объектный код. При этом можно сохранить действие проверок для некоторых потенциально опасных участков программы, заключив их в такой блок:
 
{$R+}
{опасный фрагмент программы}
{$R-}
 

Строковые типы (строки)

 
Строковые типы являются одним из наиболее полезных и часто используемых расширений языка Pascal, реализованных в Turbo Pascal’е. Строковый тип обобщает понятие символьных массивов, позволяя динамически изменять длину строки.
Строковый тип данных определяет множество символьных цепочек произвольной длины (от нуля символов до заданного числа). Для определения строкового типа используется служебное слово string, вслед за которым в квадратных скобках указывается максимальная длина строки, например:
 
type
TLine : string[80];
var
MyLine : TLine;
 
В приведенном примере переменная MyLine в качестве своего значения может иметь любую последовательность символов (каждый из которых имеет стандартный тип char) произвольной длины (в пределах от 0 до 80 символов). Значение строковой переменной может быть присвоено оператором присваивания либо прочитано из некоторого файла, например, текстового (см. главу “Файловые типы и ввод-вывод”) соответствующей процедурой, например:
 
MyLine := ‘Пример строки’;
MyLine := AnotherLine;
ReadLn( F, MyLine );
 
В качестве изображения строк может использоваться конструкция как и для символьных массивов. Кроме того, аналогично таким массивам для строк определена операция конкатенации ‘+’.
В определении строкового типа максимальная длина строки может быть задана целым числом или константой целого типа (но не типизированной константой!). Указание максимальной длины может быть опущено; в этом случае подразумевается число 255; такая длина является максимально возможной для строковых типов. Так, следующие два описания эквивалентны:
 
type
TLine = string;
TLine1 = string[255];
 
Таким образом, важнейшее отличие строк от обычных символьных массивов заключается в том, что строки могут динамически изменять свою длину. Например, если после присваивания
 
MyLine := ‘Короткая строка’;
 
длина строки составит 15 символов, то следующее присваивание:
 
MyLine := MyLine + ‘ стала длиннее’;
 
увеличит ее длину до 29 символов.
Замечу, что механизм динамических строк реализован в Turbo Pascal’е весьма просто, поэтому память под переменные строкового типа отводится по максимуму, а используется лишь часть этой памяти, реально занятая символами строки в данный момент. Более точно, для описанной строковой переменной длиной N символов отводится N+1 байтов памяти, из которых N байтов предназначены для хранения символов строки, а один байт – для значения текущей длины этой строки. Это можно пояснить следующим рисунком 1:
 
Рис. 1
 
Элементы строки нумеруются целыми числами, начиная с единицы. Приведенный рисунок показывает, что байт с текущей длиной строки можно считать как бы нулевым ее элементом. Это обстоятельство иногда используется для определения текущей длины строки, например:
 
begin
MyLine := ‘’; {пустая строка}
WriteLn(Ord(MyLine[0])); {будет напечатано число 0}
MyLine := ‘ABCD’;
WriteLn(Ord(MyLine[0])); {будет напечатано число 4}
MyLine[0] := char(2); {или byte(MyLine[0]) := 2;}
WriteLn(MyLine); {будет напечатана строка AB}
end.
 
Хотя в некоторых специальных случаях такой доступ является оправданным, для определения текущей длины строки, как правило, используют стандартную функцию Length, единственный параметр которой – выражение строкового типа или строковая переменная. Эта функция возвращает целое значение, равное текущей длине строки-параметра.
Кроме операции конкатенации, над значениями строковых типов определены операции сравнения с обычным смыслом: < (меньше), <= (меньше или равно), > (больше), >= (больше или равно), = (равно), <> (не равно), при выполнении которых действует следующие правила:
1) более короткая строка всегда меньше более длинной;
2) если длины сравниваемых строк равны, то происходит поэлементное сравнение символов этих строк с учетом лексикографической упорядоченности значений стандартного символьного типа char. Например, строка ‘ABCD’ меньше строки ‘ACDE’, так как первые их символы равны (‘A’), а вторые не равны и символ ‘C’ имеет ASCII код больше чем код символа ‘B’.
 
Замечу, что в случае присваивания строковой переменной строкового выражения с длиной большей, чем максимально допустимая для данной переменной, происходит обрубание строки до максимальной длины этой переменной. Эта ситуация не считается ошибочной, поэтому прерывания выполнения программы в данном случае не происходит, например:
 
var
ShortStr : string[5];
begin
ShortStr := ’очень длинная строка’;
Writeln(ShortStr); {будет напечатано: очень}
end.
 
Доступ к отдельным элементам строки производится аналогично доступу к элементам одномерного символьного массива.
 
var
MyLine : string;
j : integer;
begin
MyLine := ‘Привет!’;
WriteLn(MyLine); {выдаст: Привет!}
MyLine[Length(MyLine)] := ’?’;
WriteLn(MyLine); {выдаст: Привет?}
for j := 1 to Length(MyLine) do
MyLine[ j ] := ‘$’;
WriteLn(MyLine); {выдаст: $$$$$$$}
end.
 
Однако следует помнить, что изменяя содержимое строки как массива нужно корректировать длину этой строки в соответствии с ее новыми размерами. Так, в примере
 
var
Str : string[26];
j : integer;
begin
Str := ‘A’;
for j := 1 to 26 do
Str[ j ] := char(Ord(‘A’) + j –1 );
WriteLn(Str);
end.
 
продемонстрирована распространенная ошибка. Предполагается, что данная программа должна сформировать строку из 26 символов, содержимым которой является последовательность заглавных букв латинского алфавита. Однако на экран будет выведен только один символ ‘A’. Природа совершенной ошибки заключается в том, что присваивание значений элементам строки НЕ ВЛИЯЕТ на ее текущую длину, которая была установлена равной 1 при первом присваивании. Чтобы получить желаемый результат, надо переписать цикл так:
 
Str := ‘’;
for j := 1 to 26 do
Str := Str + char(Ord(‘A’) + j –1 );
 
здесь мы каждый раз увеличиваем строку Str на один символ, при этом автоматически корректируется длина строки, или просто вставить перед оператором WriteLn(Str); строку Str[0]:=char(26); что разом установит длину строки Str равной 26 символам.
 
Кроме стандартной функции Length, язык Turbo Pascal имеет еще несколько полезных стандартных процедур и функций для работы со строками.
 
Concat (s1[,s2,..,sn] :string ) : string;
Эта функция выполняет сложение строк-параметров, которых может быть произвольное количество. Каждый параметр может быть выражением строкового типа или строкой. Если длина результирующей строки превышает 255 символов, то она обрубается до 255 символов. Данная функция эквивалентна операции конкатенации, хотя работает медленнее, чем конкатенация.
 
Copy ( S : string; Index : integer; Count: integer) : string;
Функция возвращает часть строки S, длиной Count символов, начиная с символа под номером Index.
 
Delete ( var S : string; Index : integer; Count : integer);
Эта процедура удаляет из строки S фрагмент этой строки длиной Count символов, начиная с символа с номером Index.
 
Insert ( Source : string; var S : string; Index : integer);
Процедура вставляет строку Source в строку S, начиная с символа Index строки S.
 
Pos ( Substr, S : string ) : byte;
Данная функция производит поиск строки-фрагмента Substr в строке S и возвращает номер позиции найденного фрагмента в строке S.
 
Продолжение следует…
 
© Владислав Демьянишин
 
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ.
 

Журнал > Программирование > Паскаль для новичков (Turbo Pascal, Assembler) > Паскаль для новичков (часть 6). Символьные массивы
 
 
 
 
 
 
На главную страницу На предыдущую страницу На начало страницы