Лабораторная работа № 8.
Символы, строки, записи
Теоретические положения
Символы и строки
Delphi оперирует с символьной информацией, которая может быть представлена как отдельными символами, так и строками (последовательностью символов).
Символы
Для хранения и обработки символов используются переменные типа AnsiChar и WideChar. ТипAnsiChar представляет собой набор ANSI-символов, в котором каждый символ кодируется 8-разрядным двоичным числом (байтом). Тип WideChar представляет собой набор символов в кодировке Unicode, в которой каждый символ кодируется двумя байтами. Для обеспечения совместимости с предыдущими версиями поддерживается тип Char, эквивалентный AnsiChar.
Объявление переменной символьного типа:
var имя_переменной: char;
Значением переменной символьного типа может быть любой отображаемый или специальный символ.
Примеры:
var otv: char; ch: char;
...
otv:='y'; ch:='П';
В тексте программы вместо символа можно указать его код в десятичной системе исчисления, поставив перед числом оператор #, например, вместо константы 'в' можно записать #193. Такой способ записи, как правило, используют для записи служебных символов или символов, которые во время набора программы нельзя ввести с клавиатуры, например #13.
К символам можно применять операции сравнения (<, <=, =, >, >=, <>), при этом сравниваются коды символов.
В программах обработки символьной информации часто используют функция Chr, возвращающая символ, код которого указан в качестве параметра, и функция Ord, определяющая код символа, передаваемый ей в качестве параметра.
Например, c:=chr(32) переменной с присваивается пробел и k:=ord('*') переменная k получит число 42 — код символа *.
К символам можно применять функции Pred и Succ, возвращающие в этом случае предыдущий или следующий символ, например pred('b') => 'a' или succ('b') => 'c'.
Символьные массивы
Символьными называют массивы, элементами которых являются символы. Такие массивы традиционно использовались для представления символьной информации, например, различных текстов.
Особенности обработки символьных массивов:
1. Объявляя символьный массив как типизированную константу, значения символов можно указывать поэлементно:
Const d: array[1..10] of char = ('0','1','2','3','4','5','6','7','8','9');
или целиком, используя строковую константу, длина которой должна строго соответствовать размеру массива:
Const d: array[1..10] of char = '0123456789';
2. Присвоить значение символьному массиву также можно целиком, используя строковую константу, длина которой должна совпадать с длиной массива:
var s: array[1..11] of char;
s:='Пример один';
3. При вводе элементы символьного массива нельзя разделять пробелами, т.к. как пробел будет восприниматься как символ:
var s: array[1..10] of char;...
for i:=1 to 10 do Read(s[i]); {вводим строку «ABCDE FILN»}
4. Символьный массив можно выводить поэлементно в цикле, как обычный одномерный массив, а можно - целиком, одним оператором Write или WriteLn:
WriteLn(s); {вывод символьного массива одним оператором}
5. В операторе вывода допускается использование операции конкатенации (слияния) символьных массивов, обозначаемой символом «+». Результатом этой операции будет новый символьный массив, число элементов которого равно сумме размеров исходных массивов, а значениями элементов - элементы исходных массивов, последовательно записанные друг за другом:
WriteLn(st1 + ' ' + st2); {конкатенация символьных массивов}
Работа с одномерными символьными массивами осуществляется поэлементно, как с обычными массивами.
Пример 1. Выполнить упражнение в среде Pascal ABC.
Дана строка не более 40 символов, состоящая из слов, разделенных пробелами, и завершающаяся точкой. Составить программу удаления «лишних» пробелов. Лишними считать пробелы в начале строки, второй и более пробелы между словами и пробелы в конце строки.
Удалить пробелы в начале строки просто - не надо переписывать пробелы до первого значащего символа из исходной строки в результирующую. Несколько сложнее дело обстоит с пробелами между словами, т.к. удалить нужно не все пробелы, а только повторяющиеся. Для решения задачи используем специальный признак «первый пробел». Этот признак будем устанавливать, встретив первый пробел, и гасить, встретив символ, отличный от пробела. Используя этот признак, можно отличить первый пробел, переносимый в массив результата от последующих, которые переносить не надо.
Если в конце строки есть пробелы, то с использованием признака «первый пробел» получим в строке результата один лишний пробел. Поэтому после завершения обработки необходимо проверить признак, и если он установлен, удалить пробел, уменьшив длину строки на единицу. В программе, приведенной ниже, вместо этого на место пробела пишется точка. В том случае, если пробела в конце нет, для точки «добавляется» элемент.
Программа:
Строки
На простом примере обработки символьной информации, рассмотренном выше, видно, что обработка строк с использованием одномерных массивов представляет собой достаточно специфическую задачу. В то же время большинство операций, которые выполняют со строками текста, повторяются в разных программах: поиск, копирование, удаление и вставка фрагментов строки. Поэтому для упрощения работы со строками существует специальный тип данных - строковый, приспособленный для обработки символьной информации.
Строки могут быть представлены типами ShortString, AnsiString и WideString, различающиеся предельно допустимой длиной строки, способом выделения памяти для переменных и методом кодировки символов.
Переменной типа ShortString память выделяется статически, т.е. до начала выполнения программы, и количество символов такой строки не может превышать 255. Переменным типа AnsiString и WideString память выделяется динамически — во время работы программы, поэтому длина таких строк практически не ограничена.
Также можно применять универсальный строковый тип String, эквивалентный типу ShortString.
Объявление переменных строкового типа, так же, как и массивов, можно выполнить двумя способами:
- в операторе объявления переменных, например:
var S1, S2: string[40]; {символьные строки длиной 40 символов}
name: string[30]; {символьная строка длиной 30 символов}
buff: string; {символьная строка длиной 255 символов}
- с предварительным объявлением типов, например:
Туре S40 = string[40]; {тип - строка длиной 40 символов}
STR = string; {тип - символьная строка длиной 255 символов}
var S1, S2: S40; {символьные строки типа S40}
S3: STR; {символьная строка типа ST}
Cтрока представляет собой одномерный символьный массив, индексы которого изменяются от 0до максимального значения, указанного при объявлении строкового типа. Т.е. физическая длина строки на 1 превышает максимальную.
Инициализация строк.
Для инициализации строковых переменных можно использовать типизированные константы, причем строка-литерал может быть короче инициализируемой строки, например:
Const S: string[40] = 'Типизированная константа';
s1: string= ''; {пустая строка нулевой длины}
Операции над переменными строкового типа.
Над переменными строкового типа, помимо операции доступа к символам, определены операции присваивания, конкатенации (сцепления) и отношений.
Доступ к символам строки. Обращение к символам строки выполняется как к элементам массива символов, т.е. с указанием имени строки и номера элемента, например st[1] или s[i]. Нулевой байт содержит текущее значение длины строки, но так как строка - это массив символов, длина автоматически интерпретируется как символ. Для получения текущей длины строки в виде числа необходимо явное преобразование символьного типа в целый. Например, если i - переменная целого типа, а S3 - переменная строкового типа, то получить текущую длину строки S3 можно:
1) i:=byte(S3[0]); {явное преобразование с помощью автоопределения}
2) i:=ord(S3[0]); {явное преобразование с помощью специальной функции}
Но лучше это сделать, используя специальную функцию Length.
Присваивание строк. Можно присвоить строке значение строки и значение символа. При выполнении операции символы заполненной части строки и ее длина переписываются в строку-результат, например:
S1:= 'ABCD'; {присваиваем строке значение строковой константы}
S2:= 'А'; {присваиваем строке значение символа}
S:=S1; {переписываем одну строку в другую}
При присваивании строке значения символа последний интерпретируется как строка единичной длины. Если строка-источник длиннее, то при присваивании она усекается в соответствии с длиной строки-результата.
Конкатенация. Операция конкатенации позволяет сцепить строки с другими строками или символами. При сцеплении длины строк суммируются, а символы объединяются в одну последовательность. Например:
'fdc' + 'ghj'; {получаем ' fdcghj'}
S4 + 'vvv'; {к строке S4 дописывается 'vvv'}
Результат этой операции можно присвоить какой-либо строке или вывести на экран.
Отношения. Над строками допускается выполнять операции отношения: =, <>, >, <, >=, <=. Сравнение строк при этом выполняется последовательно слева направо с учетом внутренней кодировки символов до первого несовпадающего символа. Большей считается та строка, код несовпадающего символа которой по таблице ASCII больше. Если длина одной строки меньше другой, то недостающие значения до длины большей строки заполняются символами #0. Результатом операций отношения для строк является значение false и true. Допускается сравнение символов со строками, при этом символы преобразуются в строки единичной длины.Так, если
S4:='ABCD'; S3:='ADFH'; C:='L';
то при выполнении операций отношения:
S4 = S3 {получим false}
S4 > S3 {получим false}
S3 > S4 {получим true}
S3 = С {получим false}
Ввод-вывод строк. Ввод-вывод переменных строкового типа осуществляется одной операцией Read (ReadLn) или Write (WriteLn), например: ReadLn(S1); WriteLn(S1);
При вводе за строку принимается последовательность символов до кода клавиши ENTER. Если длина введенной строки больше указанной максимальной длины, то лишние символы отбрасываются, а в нулевой байт записывается значение максимальной длины. Иначе в нулевой байт записывается количество введенных символов. Т.к. строкой считаются все символы до кода клавиши ENTER, ввести в одной строке строковое значение, а затем, например, число нельзя. Если при вводе строки просто нажать клавишу Enter, не вводя никаких символов, то считается, что введена пустая строка.
Операции со строками
В языке Delphi есть несколько полезных при работе со строками функций и процедур.
Функция Length
Функция Length(S): Integer возвращает длину строки. Параметр функции — выражение строкового типа.
Пример:
var Str: string; Index: Integer;
begin
Str:='Привет';
index:= Length(Str);
end;
В этом примере объявлены две переменные str (строка) и index (целое число). В первой строке кода в переменную str помещается строка "Привет". После этого переменной index присваивается длина строки str. Результат, записанный в переменную index, равен числу 6 — длина строки.
Процедура Delete
Процедура Delete(var S: string; Index, Count: Integer) удаляет часть текста из указанной строки S. Index - номер символа, с которого начинается удаляемая подстрока, Count - количество удаляемых символов.
Пример:
var Str: string;
begin
Str:= 'Город Санкт-Петербург';
Delete(Str, 7, 6);
end;
Удаляем из строки str символы с 7-го по 12-й (6 символов, начиная с 7-й позиции). В результате в переменной str останется только строка 'Город Петербург'.
Функция Pos
Функция Pos(Substr: string; S: string): Integer позволяет определить положение подстроки Substr в строке S. Если подстрока найдена, то она вернет порядковый номер, начиная с которого найдена нужная строка. Если подстрока не найдена, то функция вернет 0.
Пример:
var Str: string;
begin
Str:= 'Санкт-Петербург';
index:=Pos('Пе', Str);
end;
Ищем строку 'Пе' в строке str. Результат — в переменной index будет число 7.
Ниже приведена инструкция while, в результате выполнения которой удаляются начальные пробелы из строки st.
while (pos(' ',st) = 1) and (length(st) > 0) do delete (st,1,1);
Пробелы удаляет инструкция delete (st,1, 1), выполняющаяся в цикле до тех пор, пока первым символом строки является пробел (в этом случае значение роs(' ',st) равно 1). Необходимость проверки условия length(st)>0 объясняется возможностью того, что введенная строка состоит только из пробелов.
Функция Сору
Функция Copy(S; Index, Count: Integer): string возвращает фрагмент строки S длиной count символов, начиная с символа с номером index.
Пример:
var Str1: string; Str2: string;
begin
Str1:= 'Инженер Иванов';
Str2:=Copy(Str1, 9, 6);
end;
Копирование в переменную str2 6-ти символов из переменной str1, начиная с 9-го символа. Результат в str2 строка 'Иванов'.
Процедура Insert
Процедура Insert(Source: string; var S: string; Index: Integer) вставляет подстроку символов Source в строку S, начиная с символа с номером index. Процедура обычно используется при формировании строк, включающих числовую информацию в другую, начиная с указанного символа.
Пример:
var Str: string;
begin
Str:= 'Меня Коля';
Insert('зовут ', Str, 6);
end;
В строку str вставляется текст 'зовут ', начиная с 6-го символа. Результатом будет строка 'Меня зовут Миша'.
Процедура Str
Процедура Str(x[:w [:d]], St) - преобразует результат выражения x в строку st, содержащую запись этого числа в виде последовательности символов (как при выводе).
Значение w, если оно указано, интерпретируется как длина строки, а значение d, если оно указано - как количество цифр дробной части для вещественных чисел, например:
х:=-5.67;
Str(x:7:3,s1); {получим строку ' -5.670'}
Процедура обычно используется для формирования строк, включающих числовую информацию.
Процедура Val
Процедура Val(St, х, Code) - преобразует строку St с записью числа в виде последовательности символов во внутреннее представление целого или вещественного числа и помещает его в переменную х. В целочисленной переменной Code процедура возвращает код ошибки: 0, если преобразование прошло успешно, и номер ошибочного символа, если строка st не являласьдопустимой формой записи числа. Процедура обычно используется, если необходимо предотвратить некорректный ввод чисел, например:
Var S:string; Code:integer; a:real;...
...repeat
Write('Введите число a:');
ReadLn(S); {вводим строку}
Val(S, a, Code); {пытаемся преобразовать строку в число}
if Code <> 0 then WriteLn('Число введено не верно');
until Code=0;... {до получения правильного значения числа}
Функция UpCase
Функция UpCase(ch):char - возвращает символ, соответствующий символу верхнего регистра для ch, если таковой имеется, либо сам символ ch, если для него не определен символ верхнего регистра.