Королевство Дельфи"Knowledge itself is power"
F.Bacon
 Лицей
  
Главная
О лицее

Список семинаров

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  13:26[Войти] | [Зарегистрироваться]

Символьные и строковые типы данных

Andrew Fionik
дата публикации 01-10-2004 17:30

урок из цикла: Азы Delphi.


предыдущий урок содержание семинара следующий урок

Символьные и строковые типы данных

Итак, с числами мы разобрались. Настал черед текста. Delphi позволяет манипулировать текстовыми данными в виде отдельных символов, а также в виде последовательностей символов - строк.

Тут следует сделать небольшое лирическое отступление по поводу изложения материала. Дело в том, что тема хранения текстовых данных чрезвычайно обширна как по количеству, так и по сложности. Если сразу же вывалить ее на голову простого чайника во всей полноте, то он мало чего поймет и, скорее всего, запутается. Поэтому мы поступим, как делают в школе на уроках физики. Вначале законы физики объясняются по-простому, в виде Ньютоновской механики, а уж потом, много позже, начинаем рассказывать релятивистские сказки от сказочника Эйнштейна, и видим, что первоначальное мировоззрение оказывается всего лишь упрощенным представлением настоящей картины мира. Так же поступим и здесь.

Тип данных Char

Базовый тип данных (т.е. то на чем основываются все остальные текстовые типы данных) - Char. Переменная типа Char может хранить всего один символ, один из набора 256 символов. Каждый символ имеет свой код. На самом-то деле компьютер оперирует не символами, (он не знает что это такое) а кодами символов. Например, во время печати символа с определенным кодом он ищет графическое изображение символа в таблице изображений символов за определенным номером, а потом выводит именно это графическое изображение на дисплей. Символы можно сравнивать между собой на равенство и на определение, какой больше или меньше, тогда компьютер опять же сравнивает не сами символы, а их коды.

Приблизительно таблицу символов можно описать примерно так. В начале идут различные служебные управляющие символы, которые не имеют графического представления. Например, это символы табуляции, возврата каретки, перевода строки и т.п. Потом идут знаки препинания '!', '?', '.' и т.п. Далее идут цифры '1', '2', '3' и т.д. Следующими идут литеры английского алфавита 'A', 'B', 'C',...,'Z', 'a', 'b', 'c',..., 'z'. Завершают таблицу литеры национального алфавита: 'А', 'Б', 'В',...,'Я','а', 'б', 'в',...,'я'.

Следует заметить, что существует масса таких таблиц символов. Разные системы могут по-разному интерпретировать коды символов по той простой причине, что они руководствуются разными таблицами символов. В этом опусе мы будем использовать таблицу символов называемую Windows Code Page 1251 (Cyrillic). Это таблица символов для кириллицы в системах Microsoft Windows. Это означает что в системе Windows каждый символ с определенным кодом будет интерпретироваться одинаково для всех программ, если они конечно не реализуют какую-то свою, специфическую обработку символов.

Как мы уже говорили раньше, переменные символьных типов могут содержать только один символ, а не два и не три и т.д. Пример использования типа Char:

program CharDemo1;
var
  A:Char;
begin
  A:='Z';
  WriteLn(A);
end.

Эта программа присваивает переменной типа Char значение символа 'Z' а потом выводит его на консоль.

А вот эта программа не будет скомпилирована компилятором по причине ошибки компиляции. Переменной A может быть присвоено значение только одного символа.

program CharDemo2;
var
  A:Char;
begin
  A:='ZZZ';
  WriteLn(A);
end.

Для типа данных Char определены также две операции - получение кода символа из переменной типа Char и преобразование кода символа в значение типа Char. Эти операции реализованы двумя функциями стандартной библиотеки - Ord и Chr.

Функция Ord принимает один параметр типа Char а возвращает значение типа Byte которое и представляет собой код символа. Функция Chr делает все с точностью наоборот - принимает значение типа Byte а возвращает значение типа Char.

Примеры использования функций Ord и Chr:

program CharDemo3; // Наименование программы - CharDemo3.
{$APPTYPE CONSOLE} { Инструкция компилятору Delphi генерировать консольную
                     программу.}
const
  A='M'; // Объявим константу A значение которой 'M'
var
  B:Char; // Объявим переменную B типа Char.
  CodeA,CodeB:Byte; { Объявим две переменных CodeA и CodeB типа Byte.
                      В них мы будем хранить коды символов.}
begin
  WriteLn('Value of A is ',A); // Напечатаем содержимое константы A
  CodeA:=Ord(A); // Присвоим переменной CodeA код символа содержащегося в A
  WriteLn('Code of A is ',CodeA); // Напечатаем код символа содержащегося в A
  CodeB:=CodeA+1; { Присвоим перменной CodeB код символа следующего за символом
                   в A.}
  B:=Chr(CodeB); { Преобразуем код символа в значение типа Char
                   и присвоим его B.}
  WriteLn('Value of B is ',B); // Напечатаем значение B.
  WriteLn('Code of B is ', CodeB); // Напечатаем код символа лежащего в B.
  CodeB:=CodeA-1; {Присвоим перменной CodeB код символа предыдущего перед
                   символом в A}
  B:=Chr(CodeB); // Снова преобразуем код символа в переменную типа Char
  WriteLn('Value of B is ',B); // Снова печатаем содержимое B...
  WriteLn('Code of B is ', CodeB); //... и CodeB, они уже немножко другие
  ReadLn; // ждем нажатия клавиши Enter чтобы завершить программу
end.

При выполнении этой программы должен быть выдан вот такой текст:
Value of A is M
Code of A is 77
Value of B is N
Code of B is 78
Value of B is L
Code of B is 76

Тип данных String

Переменная типа String представляет собой последовательность символов - строку. Мы можем определять длину строки, можем добавлять к строке другие строки и символы, можем заменять произвольные части строки на другие строки и символы, можем удалять части строки.

Пример объявления переменной типа String:

program StringDemo1; // название программы
{$APPTYPE CONSOLE} // инструкция компилятору генерировать консольное приложение
var // секция объявления переменных
  A:String; // объявляем переменную A типа String
begin // начало тела программы
  A:='Hello world!'; // присваиваем переменной A строку 'Hello world!'
  WriteLn(A); // выводим содержимое переменной A на экран
  ReadLn; // ждем нажатия Enter
end. // конец тела программы



Операции над строками

Ниже перечислены основные, наиболее общие операции которые могут производиться со строками. В основном все операции реализуются через функции стандартной библиотеки.
  • присваивание строке значения другой строки или константы
  • получение значения строки
  • получение длины строки (количество символов в строке)
  • получение значения конкретного символа (символа находящегося в определенной позиции строки)
  • изменение значения конкретного символа в строке
  • слияние (конкатенация) двух и более строк
  • выделение подстроки из строки
  • вставка одной строки внутрь другой
  • удаление части строки
  • определение позиции вхождения одной строки в другую
  • изменение регистра символов
  • сравнение строк на равенство или больше/меньше
Кроме этих операций, существует еще масса других, более специализированных, но о них позже.

Подпрограммы

Забегая немного вперед, следует указать, что многие операции над строками выполняются с помощью различных подпрограмм. Подпрограмма - кусочек программного кода, который имеет идентификатор и может быть вызван по нему для выполнения какой-либо задачи. Зачастую подпрограмма требует передать ей какие-нибудь параметры. В качестве параметров используется либо выражение, либо идентификатор чего-либо. Например, идентификатор переменной или константы. Подпрограммы подразделяются на процедуры и функции. Разница между ними лишь в наличии возвращаемого результата. Функции возвращают результат своего выполнения, а процедуры не возвращают никакого результата, только выполняют какое-то действие. Например, Sin - функция, которая вычисляет значение синуса переданного ей параметра и возвращает результат вычисления в виде вещественного значения. В противоположность ей WriteLn является процедурой, которая никаких значений не возвращает, но выполняет действие - вывод значений переданных ей параметров на консоль. Процедуры вызываются следующим образом:

Имя_процедуры(Параметр1, Параметр2, ..., ПараметрN);

Вызов функции может быть использован внутри какого-либо выражения (для его вычисления). Также вызов функции может быть использован в операторе присваивания, чтобы присвоить какой-нибудь переменной результат выполнения функции.

Имя_переменной:=Имя_функции(Параметр1, Параметр2, ..., ПараметрN);

Присваивание значения строке, получение содержимого строки

Строковой переменной может быть присвоено значение, как и любой другой переменной. Единственное ограничение состоит в том, что тип значения должен быть String или Char (что такое один символ как не строка длиной 1).

program StringDemo01;
{$APPTYPE CONSOLE}
const
  A='Hello, world'; // объявляем константу содержащую значение 'Hello world'
var
  B,C:String; // объявляем две переменные типа String - B и C
begin
  B:=A; // присваиваем значение константы A переменной B
  WriteLn(B); // выводим на консоль содержимое переменной B
  C:=B; // присваиваем содержимое переменной B в переменную С
  WriteLn(C); // выводим на консоль содержимое переменной C
  ReadLn; // ожидаем нажатия Enter
end;



Получение длины строки

Для определения длины строки в символах используется функция стандартной библиотеки Length. Функция Length получает на вход один единственный параметр, идентификатор строковой переменной или выражение строкового типа. Результат функции, количество символов в строке, имеет тип Integer.

Формат вызова:

Length(идентификатор переменной или выражение типа String)

Пример:

program StringDemo02;
{$APPTYPE CONSOLE}
const
	A='Hello, world';
var
	B:String;
	L:Integer; {сюда мы будем заталкивать результат функции Length,
		количество символов}
begin
	B:=A; // присваиваем значение константы A переменной B
	L:=Length(B); // присваиваем переменной L количество символов в B
	// выводим на консоль содержимое переменных B и L
	WriteLn('Length of "',B,'" is ', L);
	ReadLn; // ожидаем нажатия Enter
end;



Получение и установка отдельного символа строки

К символам строки можно обращаться по их индексу (позиции в строке). Индекс первого символа строки 1. Индекс последнего символа строки будет равен результату вызова функции Length, которой в качестве параметра будет передана строка. Обратите внимание на то, что индекс первого символа 1, а не 0 как обычно делается в различных структурах данных, которые могут содержать много элементов (вообще-то больше одного). При попытке обращения к символу с индексом меньше 0 или больше Length(идентификатор строки) возникает ошибка времени выполнения.

Формат обращения к символу строки:
S[I]
... где S - идентификатор строковой переменной, а I - индекс символа.

Выражение вида S[I], где S - идентификатор строковой переменной, возвращает результат типа Char.

Пример доступа к символу строки по индексу:

program StringDemo03;
{$APPTYPE CONSOLE}
const
  A='Hello, world';
var
  B:String;
  I:Integer;
  C:Char;
begin
  B:=A;
  // Выводим значение строки B и первого символа строки B.
  WriteLn('First character of string "', B, '" is "',B[1],'"');
  // вычисляем индекс последнего символа в строке B
  I:=Length(B);
  // присваиваем переменной C значение последнего символа строки B
  C:=B[I];
  // Выведем значение последнего символа строки B
  WriteLn(C);
  {Теперь поменяем значения последнего и первого символов строки B
   друг на друга}
  // присвоим значение первого символа строки B последнему символу
  B[Length(B)]:=B[1];
  {Теперь значение последнего символа строки B потерялось поскольку было
   переписано значением первого символа. Однако копия этого значения
   осталась в переменной C, поэтому мы присвоим значение переменной C
   первому символу строки B}
  B[1]:=C;
  // Выведем измененную строку B
  WriteLn(B);
  ReadLn; // ожидаем нажатия Enter
end;

Должно вывестись следующее:
First character of string "Hello, world" is "H"
d
dello, worlH


Слияние двух строк (конкатенация)

Строки можно складывать как числовые переменные, используя оператор +. Результатом сложения является более длинная строка, включающая в себя содержимое обеих строк в порядке их употребления в операции сложения. Также существует функция Concat которая выполняет в точности то же действие что и +.

Формат операции конкатенации двух строк:
A+B
или 
Concat(A,B)
... где A - идентификатор одной строки или строковое выражение, а B - идентификатор другой строки или строковое выражение.

Пример:

program StringDemo04;
{$APPTYPE CONSOLE}
var
  A,B,C,D:String;
begin
  C:='Hello';
  D:='world';
  A:=C+D;
  B:=C+', '+D;
  C:=D+C;
  D:=Concat(A+B);
  WriteLn(A);
  WriteLn(B);
  WriteLn(C);
  WriteLn(D);
  ReadLn;
end;

Результат вывода должен быть следующим:
Helloworld
Hello, world
worldHello
HelloworldHello, world


Выделение подстроки из строки

Иногда бывает необходимо получить часть строки, а не всю ее целиком. Для этого существует функция Copy. Функция Copy получает на вход три параметра - строку, позицию с которой надо начинать копирование и количество символов которые надо скопировать. Формат вызова функции Copy:

Copy(Source,Index,Count);
... где Source - идентификатор строковой переменной или строковое выражение часть которого должна быть скопирована, Index - позиция с которой должно быть осуществлено копирование, Count - количество символов которое должно быть скопировано.
  • Если Index больше чем длина строки Source, то функция возвращает пустую строку, т.е. строку, не содержащую символов. Длина пустой строки равняется нулю.
  • Если Count указывает больше символов, чем имеется в строке Source, начиная с позиции Index, то копируются все символы Source, начиная с позиции Index и до конца.
Пример выделения подстроки:

program StringDemo04;
{$APPTYPE CONSOLE}
var
	A,B:String;
begin
	A:='Hello, world';
	B:=Copy(A,2,5);
	A:=Copy('Delphi rulez',1,6)+' great';
	WriteLn(B);
	WriteLn(A);
	ReadLn;
end;

На консоль должно быть выведено следующее:
ello,
Delphi great


Вставка одной строки внутрь другой

Вставка строки выполняется процедурой Insert. Процедура получает на вход три параметра: строку, которую нужно вставить, строку в которую должна быть произведена вставка и позицию, в которой должна быть произведена вставка. Формат вызова:

Insert(Source,Target,Position);
  • Source - строка которая будет вставлена
  • Target - идентификатор строковой переменной в которую вставляют содержимое Source
  • Position - позиция, начиная с которой будет вставлено содержимое Source в Target

Обратите внимание, что это уже не функция, а процедура. Она не возвращает никакого результата, а модифицирует содержимое Target. Еще одна особенность использования процедуры, а не функции заключается в том, что в качестве Target можно передавать только идентификатор переменной, но нельзя передавать выражение или идентификатор константы. Процедура Insert присваивает результат своей работы Target, а присвоить что-либо константе или выражению невозможно по определению.

  • Если Position меньше 1, то процедура принимает его равным 1.
  • Если Position больше чем Length(Target), то содержимое Source добавляется к Target с конца.
  • Если Source является пустой строкой, то Insert ничего не делает
Пример использования Insert

program StringDemo05;
{$APPTYPE CONSOLE}
var
	A:String;
begin
	A:='Happy friends';
	Insert(' tree',A,6);
	WriteLn(A);
	ReadLn;
end;

В результате выполнения этой программы должна быть выведена строка:
Happy tree friends


Удаление части строки

Часть строки может быть удалена с помощью процедуры Delete. Формат вызова процедуры Delete:

Delete(Target,Index,Count);
... где Target - идентификатор строковой переменной, из которой удаляются символы, Index - позиция, начиная с которой производится удаление, Count - количество удаляемых символов.
  • Если Index меньше 1 или больше чем Length(Target), то ничего из Target не удаляется.
  • Если Count указывает больше символов чем есть начиная с Index, то удаляются символы от Index и до конца строки. Если Count меньше 1, то ничего не удаляется.
Пример использования Delete:

program StringDemo06;
{$APPTYPE CONSOLE}
var
	A:String;
begin
	A:='Happy friends';
	Delete(A, 3, 5);
	WriteLn(A);
	ReadLn;
end;

Результат вывода должен быть: Hariends

Определение позиции вхождения одной строки в другую

Иногда бывает нужно определить содержится ли одна строка в другой, а также позиция с которой содержимое строк совпадает. Для этого применяется функция Pos. Формат вызова:

Pos(SubStr, Str) ... где Str - строка, в которой производится поиск SubStr. Функция возвращает позицию вхождения в качестве результата. Если строка SubStr не находится в Str, то результат выполнения функции будет равен 0. Функция различает регистр букв - большой и маленький, т.е. подстрока 'dancing' будет найдена в 'We dancing in shadows', но не будет найдена в 'We Dancing In Shadows'.

Пример использования Pos:

program StringDemo07;
{$APPTYPE CONSOLE}
var
	I:Integer;
begin
	I:=Pos('win','Good guys only win in movies');
	WriteLn(I);
	ReadLn;
end;

Должно быть напечатано число 16.

Изменение регистра символов

Каждый символ, представляющий собой букву, имеет регистр - верхний или нижний. Например, буква "а" может быть заглавной "А" и прописной "а". Заметим что "А" и "а" являются различными символами. Про заглавные буквы говорят, что они имеют верхний регистр. Про прописные буквы говорят, что они имеют нижний регистр. В некоторых случаях нужно преобразовать отдельную строку или символ в верхний или нижний регистр. Это делают функции UpCase, UpperCase, LoCase, LowerCase.

Формат вызова функции UpCase: UpCase(Source)
Source - идентификатор переменной или выражение типа Char. Результат, возвращаемый функцией, также является значением типа Char и представляет собой значение Source преобразованное в верхний регистр.
Формат вызова функции LoCase: LoCase(Source)
Source - идентификатор переменной или выражение типа Char. Результат, возвращаемый функцией, также является значением типа Char и представляет собой значение Source преобразованное в нижний регистр.
Формат вызова функции UpperCase: UpperCase(Source)
Source - идентификатор переменной или выражение типа String. Результат, возвращаемый функцией, также является значением типа String и представляет собой значение Source преобразованное в верхний регистр.
Формат вызова функции LowerCase: LowerCase(Source)
Source - идентификатор переменной или выражение типа String. Результат, возвращаемый функцией, также является значением типа String и представляет собой значение Source преобразованное в нижний регистр.
Пример использования функций изменения регистра:

program StringDemo07;
const
  SourceString='Hello world';
var
  TargetString:String;
begin
  // присвоим TargetString значение SourceString переведенное в нижний регистр
  TargetString:=LowerCase(SourceString);
  // напечатаем содержимое TargetString
  WriteLn(TargetString);
  // напечатаем значение SourceString переведенное в верхний регистр
  WriteLn(UpperCase(SourceString));
  // Возведем первый символ TargetString в верхний регистр
  TargetString[1]:=UpCase(TargetString[1]);
  // возведем последний символ TargetString в верхний регистр
  TargetString[Length(TargetString)]:=UpCase(TargetString[Length(TargetString)]);
  // напечатаем содержимое TargetString
  WriteLn(TargetString);
  // понизим регистр первого символа TargetString
  TargetString[1]:=LoCase(TargetString[1]);
  // напечатаем содержимое TargetString
  WriteLn(TargetString);
  // Ждем нажатия Enter
  ReadLn;
end.

Вывод должен быть следующим:
hello world
HELLO WORLD
Hello worlD
hello worlD


Сравнение строк на равенство или больше/меньше

Строки можно сравнивать между собой как если бы они были числами. Возможны следующие операции сравнения:
  • = - сравнение строк на предмет равенства
  • <> - сравнение строк на предмет неравенства
  • < - сравнение на "меньше"
  • > - сравнение на "больше"
  • <= - сравнение на "меньше или равно"
  • >= - сравнение на "больше или равно"
Результатом сравнения является значение типа Boolean, которое может быть только одним из двух - TRUE (Истина) и FALSE (Ложь).

Правила сравнения:

Сравнение на предмет равенства
  1. Сравнивается длина строк. Если длина разная, то значит, что строки не равны. Возвращается результат FALSE.
  2. Если длина одинаковая, производится посимвольное сравнение строк. Как только в какой-либо позиции сравниваемых строк находятся разные символы, возвращается FALSE - строки не равны.
  3. Если длина строк одинаковая и все символы на соответствующих позициях равны друг-другу, то строки считаются равными. Возвращается результат TRUE.
Сравнение на предмет неравенства

Производится сравнение на предмет равенства, затем результат "переворачивается вверх ногами". Вместо TRUE возвращается FALSE и наоборот.

Сравнение на "меньше"

Поочередно сравниваются коды символов, стоящих на соответствующих позициях. Если одна из строк больше не имеет символов, или символ, стоящий в соответствующей позиции имеет меньший код, то считается что эта строка "меньше".

Пример:
Строка 'Ivan' меньше строки 'Ivar', т.к. первые три символа равны, а четвертый символ в первой строке ('n') меньше чем четвертый символ ('r') во второй строке.

Пример:
Строка 'Doom' меньше чем строка 'Doomsday' потому что четыре первых символа совпадают, но пятого символа в первой строке уже нет, а во второй есть хоть какой-то.

Сравнение на "больше"

Поочередно сравниваются коды символов, стоящих на соответствующих позициях. Если одна из строк еще имеет символы, в то время как другая больше не имеет символов, или символ, стоящий в соответствующей позиции имеет больший код, то считается что первая строка "больше".

Нечеткие сравнения на "меньше или равно" и "больше или равно"

Фактически "меньше или равно" означает "не больше", а "больше или равно" означает "не меньше". Соответственно производится сравнение на предмет "больше" или "меньше" и результат инвертируется.

Пример:

program StringDemo08;
const
  C1='Hello World';
  C2='Hello day';
  C3='Hello baby';
  C4='Hello World';
begin
  // печатаем результат сравнения на равенство
  WriteLn(C1=C4);
  WriteLn(C1=C2);
  // печатаем результат сравнения на неравенство
  WriteLn(C3<>C4);
  WriteLn(C1<>C4);
  // печатаем результат сравнения на "меньше"
  WriteLn(C2<C3);
  WriteLn(C1<C4);
  // печатаем результат сравнения на "больше"
  WriteLn(C2>C3);
  WriteLn(C1>C4);
  ReadLn;
end.

Результат должен быть следующий:
TRUE
FALSE
TRUE
FALSE
FALSE
FALSE
TRUE
FALSE

предыдущий урок содержание семинара следующий урок




Смотрите также материалы по темам:
[Функции для работы со строками ] [Строки]

 Обсуждение материала [ 30-08-2010 05:16 ] 1 сообщение
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования