Строковый тип данных(STRING) предназначен для обработки цепочек символов (литер, элементов типа CHAR). Переменные типа STRING могут быть объявлены следующим образом:
<имя переменной>:STRING[длина]
или
<имя переменной>:STRING
В стандарте Паскаля такого типа данных нет.
Параметр длина задает максимальную длину строки (максимальное число символов цепочки). Если максимальный размер строки не указан, то он автоматически принимается равным 255 – максимально возможной длине строки. Для переменной типа string резервируется участок памяти длиной длина+1 байт. Дополнительный байт используется для хранения значения текущей длины строки.
В языке Паскаль широко используются константы строкового типа. Они представляют собой цепочки произвольных символов используемой кодовой таблицы, заключенные в апострофы. Например: ‘ВОТ’ – цепочка из трех символов, ‘’ – пустая цепочка.
Строка обладает всеми свойствами массива литер, то есть, структуры данных, описанной описателем array[0..длина] of char. Если имеются описания s,s1:string[10], то, в отличие от массива, допустимы присваивания
s:=’BOT’
s1:=’’.
При этом текущая длина строки s будет равна 3, текущая строка s1 – 0. Текущая длина строки – целое положительное число в диапазоне от 0 до длина – хранится в нулевом элементе строки как данное типа char (s[0]=chr(3), s1[0]=chr(0)). В первом элементе строки s – s[1] – хранится символ ‘B’, во втором – ‘O’, в третьем – ‘T’, значение элемента s[4] неопределенно, обращение к нему является ошибкой, поскольку индекс превышает текущее значение длины строки.
Текущая длина строки не должна превышать максимальную длину.
К строкам применимы стандартные процедуры ввода и вывода. Если выдать на экран значения строк s и s1, то получим:
writeln(s) – на экране строка ‘ВОТ’,
writeln(s1) – на экране пустая строка.
Над строковыми данными определена бинарная операция конкатенации (+). Результатом конкатенации двух строк является строка, содержащая последовательно все символы левого операнда, а затем все символы правого операнда. Вот примеры использования конкатенации:
writeln(s) – на экране текст ВОТВОТ;
s1:=s+’ KOT’; writeln(s1) – на экране ВОТ КОТ.
Пример использования строк для обеспечения защиты ввода целого числа от «дурака». Под «дураком» подразумевается пользователь программы, позволяющий себе, не взирая на настоятельные предупреждения разработчика о формате вводимой информации, вводить произвольную последовательность символов. При использовании стандартных средств ввода в таких случаях может возникнуть ошибка ввода, приводящая к прерыванию выполнения программы. Для обеспечения нормальной работы программы при вводе можно воспользоваться следующим средством:
program Enter_int;
type status=(beginning,znak,Ok,Err);
var s:string; zn,k,i:integer; c:char;
n:longint;
stat:status;
cifra:boolean;
begin
repeat
writeln(‘Введите целое по модулю меньшее ’,$7FFF:1);
readln(s);
k:=length(s);
zn:=1;
n:=0;
stat:=beginning;
for i:=1 to k do
begin
c:=s[i];
cifra:=(c>='0') and (c<='9');
case stat of
beginning: case c of
' ': ;
'+': stat:=znak;
'-': begin stat:=znak; zn:=-1 end;
'0'..'9': begin n:=n*10+ord(c)-ord('0');
stat:=Ok end;
else stat:=Err
end;
znak: if cifra then
begin
n:=n*10+ord(c)-ord('0'); stat:=Ok
end else stat:=Err;
Ok: if cifra then
begin
n:=n*10+ord(c)-ord('0'); stat:=Ok
end else stat:=Err;
end;
end;
n:=zn*n;
if abs(n)>=$7FFF then stat:=Err;
until stat=Ok;
writeln('rezult ',n)
end.
Переменную типа STRING можно сравнивать с другой переменной или константой типа STRING, используя отношения =, <, >, <=, >=, <>. Используется лексикографический порядок (как в каталогах библиотек).
В TP имеются следующие функции для обработки строк:
CONCAT - функция имеет произвольное число параметров строкового типа, результат - строка, полученная последовательной склейкой параметров. Если длина полученной строки превышает 255 символов, то происходит усечение;
COPY(S:string; ind,count:integer):string - возвращает подстроку S длиной count, начиная с литеры номер ind. При несоответствии с максимальной длиной используется усечение;
DELETE(var S:string; ind,count:integer) - удаляет из S count символов, начиная с ind;
INSERT(St:string; var S:string; ind:integer) - вставляет в S St, начиная с позиции ind;
LENGTH(S:string) - функция, возвращает текущую длину строки S;
Две процедуры можно рассматривать как процедуры преобразования типа:
VAL(S:string; var V; var code:integer) - где V - переменная целого или вещественного типа. Процедура выделяет из строки последовательность символов, преобразует к типу соответствующей переменной и присваивает полученное значение этой переменной. Процедура VAL является строковым аналогом процедуры READ. Если при чтении из строки встречается недопустимый символ, то в переменной code возвращается его номер. В противном случае этот параметр равен нулю;
STR(X; var S:string) - преобразует численное значение целого или вещественного типа в его строковое представление. Эта процедура является строковым аналогом процедуры WRITE. После выражения X можно указать длину и точность представления данных.
Вот примеры использования процедур VAL и STR.
var X:real; S:string; i:integer;
begin
X:=3.1415926;
STR(X:8:4, S); S:='X=' + S;
Writeln(S); { на экране 'X= 3.1416'}
S:=DELETE(S,1,2); {удалили первые два символа}
VAL(S,X,i);
if i=0 then writeln(X:10:6) {на экране ' 3.141600'}
end.
В качестве упражнения перепишите программу Enter_int, используя функции и процедуры обработки строк.
Запись - структура данных, содержащая конечное число компонент различного типа. Компоненты называются полями. Как любой тип, определяемый программистом, тип "запись" должен быть объявлен в разделе TYPE. При описание типа запись указывает тип каждого поля и идентификатор, который именует поле. Тип данных RECORD предоставляет возможность объединить в одну связанную структуру различные по типу и смыслу поля, причем элементами записи могут быть и структурированные типы данных, например массивы и другие (подчиненные) записи. Для обработки доступна как вся запись целиком, так и отдельные поля.
Описатель записей:
RECORD <фиксированная часть> <вариантная часть> END
Здесь фиксированная часть записи состоит из списка имен полей с указанием типа данных, к которым эти поля относятся. В описании записи хотя бы одна из необязательных частей (фиксированная или вариантная) должна присутствовать.
Примеры записей, содержащих только фиксированную часть:
TYPE
REC = RECORD
A, B : INTEGER;
C : CHAR
END;
DATE = RECORD
DAY : 1..31;
MONTH : 1..12;
YEAR: 1900..2100
END;
Если VAR X:REC; Y, Z:DATE; то к полям записей X, Y и Z имеется доступ по имени поля. Например, X.A - поле A записи X, элемент типа INTEGER.
Инициализация записи - инициализация всех полей записи Y.DAY := 17; Y.MONTH := 3; Y.YEAR := 1992;
Если запись Y инициализирована, то можно ее использовать в правой части оператора присваивания Z := Y ; Z и Y совместимы по присваиванию, поскольку относятся к одному и тому же типу данных.
Посмотрите, как используется запись в программе Datas лекции 5.
Вариантная часть всегда следует за фиксированной, если она есть.
CASE <тег:> тип of <список описаний вариантов>
Описание варианта - это константное значение или диапазон константных значений, относящихся к типу «тип» описания вариантной части. Далее ставится двоеточие, и в скобках - описание полей варианта. Описание полей варианта осуществляется по тем же правилам, что и полей фиксированной части. Имена всех полей должны быть уникальными идентификаторами внутри записи.
Следующий пример показывают способ задания поля тега.
TYPE SHAPE = (TRIANGLE, RECTANGLE, SQUARE, CIRCLE);
COORDINATES = RECORD { фиксированная часть }
X, Y, AREA : REAL;
CASE S : SHAPE OF { вариантная часть }
TRIANGLE : (SIDE : REAL; BASE : REAL);
RECTANGLE: (SIDEA, SIDEB : REAL);
SQUARE : (EDGE : REAL);
CIRCLE : (RADIUS : REAL)
END;
В памяти поля разместятся как показано на рисунке
фиксированная часть
вариантная часть
X
Y
AREA
S
SIDE
BASE
X
Y
AREA
S
SIDEA
SIDEB
X
Y
AREA
S
EDGE
-
X
Y
AREA
S
RADIUS
-
Если S = RECTANGLE, то доступны поля SIDEA и SIDEB. Например, при инициализации записи:
X : COORDINATES;
X.S := RECTANGLE;
X.SIDEA := 17.5;
X.SIDEB := 20.4;
В стандартном языке Pascal (и в TP) можно вообще не указывать поле тега:
COORDINATES RECORD
X, Y : REAL; { фиксированная часть }
AREA : REAL;
CASE SHAPE OF { вариантная часть }
END
В этом случае можно обращаться к любым полям вариантной части по имени, однако ответственность за правильность трактовки данных возложена на программиста.
Проанализируйте самостоятельно следующий пример:
program record_;
type
T_education=(begining,medium,higher);
T_profession=(teacher,driver,woker);
T_category=(A,B,C,D);
T_anketa=
record
name :string[20];
case profession:T_profession of
teacher:(education:T_education;
pedagogical_length_of_service:byte);
driver :(licence:record
case drivers_licence:boolean of
true :(category:T_category;
drivers_length_of_servie:byte);
false:(drivers_school:string[20])
end);
woker :(specialization:string[20];
class:string[20])
end;
var a1,a2,a3:T_anketa;
begin
writeln(sizeof(T_profession)); {1}
writeln(sizeof(T_anketa)); {64}
a1.name:='Ivan';
a1.profession:=teacher;
a1.education:=higher;
a1.pedagogical_length_of_service:=1;
a2.name:='Vlad';
a2.profession:=driver;
a2.licence.drivers_licence:=true;
a2.licence.category:=B;
a3.name:='Mike';
a3.profession:=woker;
a3.specialization:='shoe-maker';
a3.class:='master';
end.
Оператор присоединения WITH позволяет один раз указать имя записи и обращаться непосредственно к полям записи. Синтаксис оператора WITH:
WITH <список переменных> DO <оператор>,
где в списке «список переменных» указываются имена записей.
Например, если Y запись типа DATE (см. пример выше), то значения полям этой записи можно присвоить так: