Работа со строками.
При работе с фрагментам текста т.е. строкой применяют тип STRING и рассматривают его как одномерный массив ARRAY [0..10] OF CHAR. В ПАСКАЛЕ строка рассматривается как цепочка символов. К любому символу можно обратиться как к элементу одномерного массива.
program rtx;
var a:string; i,k:integer;
begin
write('введите слово');
read (a);
for i:=1 to 255 do
if a[i]='а' then k:=k+1;
write (k);
end.
Методы и процедуры работы со строками |
Вы уже знаете, что к строке можно обращаться как к массиву, работать с отдельными ее символами. Но это далеко не единственная возможность Паскаля по обработке строк. На самом деле существует достаточное количество стандартных процедур, чтобы разрешить практически любую проблему с манипуляцией со строками. А такие проблемы иногда возникают.
К примеру, известная нам функция Length, которая вычисляет длину строки. Разве не удобно ее использовать? По моему, вполне. Но хочется отметить, что по сути Length даже и не относиться к функциям работы со строками (точнее, к функциям по обработке строк), так как она не манипулирует со строкой непосредственно. Вычисление размера, на мой взгляд, это не прямая работа... хотя у каждого есть на этот счет свое мнение, а я должен придержаться сути нашего урока.
Итак, для начала я перечислю все процедуры и функции, имеющиеся в языке Turbo Pascal 7.0, которые служат для обработки строк:
- function Copy (S: String; Index:
Integer; Count: Integer): String;
- procedure Delete (S: String;
Index: Integer; Count: Integer);
- procedure Insert (Source: string;
S: string; Index: Integer);
- function Pos (Substr, S: String):
Byte;
- function Concat (S1, S2, .....,
Sx: String): String;
Ну а теперь давайте рассмотрим все эти процедуры
в отдельности и заодно немного с ними попрактикуемся. Найдутся и
примеры создания собственных функций.
1. function Copy
(S: String; Index: Integer; Count: Integer): String;
Начнем с функции Copy. Эта функция создает из имеющейся строки подстроку. Проще говоря, выделяет какой-то кусок имеющейся строки и возвращает его как результат своей работы. Результат этот как всегда (помните, определение функций?) может быть присвоен переменной, использован в выражении, в процедуре (например, выведен на экран).
Теперь о параметрах. Как вы видите, их у Copy три. Разберем их по отдельности:
- S: String;
Этот параметр - исходная строка, то есть та строка, из которой мы будем "вырезать кусок". - Index: Integer;
Номер первого символа, начиная с которого начнется выделение строки. При этом если этот параметр больше реальной длины строки, то функция возвратит пустую строку. - Count: Integer;
Количество символов, которые будут выделены, начиная с номера, задаваемого параметром Index: Integer;
Чтобы показать наглядно работу функции Copy, представьте себе такую строку:
АБВГДЕ
Допустим, мы хотим выделить три символа, начиная со второго, то есть получить такую строку:
БВГ
При использовании Copy для реализации такой задачи давайте напишет следующую программу:
Program
N2;
var
S,
S1: String;
begin
S
:= 'АБВГДЕ';
S1
:= Copy(S, 2, 3);
Write(S1);
Readln;
end.
Эта программа делает именно то, что нам нужно. Думаю, здесь все понятно и двигаемся дальше.
Проще это можно рассмотреть следующим образом:
COPY(строка, x, y) – копирует из строки y символов начиная с символа с номером x.
Например: составить программу где в переменную будет выводится часть заданной фразы (мама мыла раму).
Program ttt;
var a,b:string; x:integer;
begin
write ('введите фразу'); фраза – мама мыла раму
read (a);
b:=copy (a,6,4);
write (b);
end.
А нам пора двигатсья дальше и мы переходим в новой процедуре - Delete.
2. procedure Delete (S: String; Index: Integer; Count: Integer);
Delete - англ. "Удалять". Соответственно, исходя из названия уже понятна работа процедуры. Она удаляет из строки определенную ее часть. Параметры:
- S: String;
Исходная строка, в которой будет происходить удаление; - Index: Integer; Номер первого удаляемого символа. При этом, как и в случае с функцией Copy, если это число больше, чем длина строки, процедура прорабатает вхолостую и символы не удалятся.
- Count: Integer;
Число удаляемых символов. Если символом в строке не хватает, то удаляются все оставшиеся.
Работает эта процедура очень просто. Все происходит по принципу:
- имеется строка S, допустим, 'Это 1-я строка'.
- Хотим удалить из нее (вырезать) символы '1-я '.
- Используем Delete(S, 5, 4);
- Получаем: 'Это строка'
При этом число 5 (параметр Index: Integer) - это номер символа "1" в текущей строке S. Число 4 - количество символов до начала слова "строка". Вот и вырезаем все это дело :).
Если всмотреться в эту процедуру, то можно увидеть сходство с функцией Copy. Она вырезает кусок строки - только Copy возвращает его в качестве новой строки, а Delete - вырезает его из строки, передаваемой в качестве параметра. Короче, Delete изменяет саму строку.
DELETE(строка, x, y) – удаляет у символов из строки начиная с символа х.
program ttt;
var a,b:string; x:integer;
begin
write ('введите фразу');
read (a);
delete (a,6,4);
write (a);
end.
А сейчас переходим к новой процедуре - Insert.
3. procedure Insert (Source: string; S: string; Index: Integer);
Эта процедура производит совершенно обратное действие предыдущей - вставляет подстроку в строку. При этом если новая получившаяся строка больше 255 символов, что, как вы должны помнить, является максимальным размером строки, то она усекается до 255 символов. Разберемся со всеми параметры в отдельности:
- Source: String;
Подстрока, которая помещается в строку. - S: String;
Исходная строка, то есть та, в которую будет влеплена строка Source. - Index: Integer;
Позиция в исходной строке S, начиная с которой будет помещена подстрока.
Например, имеется у нас две строки:
S := 'Это строка';
S1 := ' 1я';
... и хотим мы слепить их так, чтобы строка S получилась такой:
S := 'Это 1я
строка';
, то есть поместить S1 в S начиная с позиции ... считаем ... с позиции 4. Для того, чтобы получить такой результат с помощью Insert, мы напишем следующее:
Insert(S1, S,
4);
Это можно прочитать по-русски: Вставляем подстроку S1 в строку S, начиная с позиции 4. Видите, как все просто? Кстати, написать самому процедуру Insert тоже совсем несложно. Очень советую! Это несколько отличается то функции Copy и процедуры Delete, поможет разобраться в некоторых нюансах и, возможно, заставит подумать.
А теперь давайте напишем небольшую программку, которая будет делать следующее:
- Вводим две строки;
- Проверяем: если слить первую строку со второй - не перевалит ли за 255 символов? Если нет, то:
- Вводим Integer;
- Вставляем в 1ю строку 2ю строку и выводим результат на экран.
Эта программа еще раз продемонстрирует работу процедуры Insert, что совсем не лишнее. Итак, текст программы:
Program N4;
uses Crt;
var
S, S1: String;
I: Integer;
begin
ClrScr;
Write('Введите 1ю строку: ');
Readln(S);
Write('Введите 2ю строку: ');
Readln(S1);
If Length(S)+Length(S1) <= 255 then
begin
Write('Введите позицию вставки: ');
Readln(I);
Insert(S1, S, I);
Write(S);
end
else Write('Слишком длинные строки!');
Readln;
end.
Как вы видите, использование этой процедуры не вызывает труда. Продолжаем дальше.
4. function Pos (Substr, S: String): Byte;
Эта функция предназначена для поиска строки в строке. Она возвращает номер символа, в которой начинается искомая строка, или, если такой строки нет, возвращает 0. Параметры:
- Substr: String;
Это искомая строка, то есть та, которую фукнция пытается найти. - S: String;
Это строка, в которой производиться поиск.
Например, мы вводим две строки и нужно проверить, сущетсвует ли в первой введенной строке вторая, и если это верно, то вычислить ее позицию. Для этого мы напишем такую программу:
Program N5;
var
S, S1: String;
I: Integer;
begin
Write('Введите 1ю строку: ');
Readln(S);
Write('Введите 2ю строку: ');
Readln(S1);
I := Pos(S1, S);
If I <> 0 then
Write('Такая строка есть! Позиция: ', I)
else Write('Нет такой строки!');
Readln;
end.
Как вы видите, все очень просто. При этом если ввести в качестве первой строки символы '12345', а в качестве второй - '234', то позиция будет равна 2.
Опять же, как и с пред. процедурами и функциями, советую попробовать написать такую процедуру. Кстати, это уже сложнее - придется учитывать много нюансов и т.п. Напоследок хочу напомнить - если все же будете писать свою фукнцию Pos, не забывайте о оптимизации. Иначе в использовании вашей функции просто не будет смысла.
5. function Concat (S1, S2, ....., Sx: String): String;
Ну об этой функции и говорить особо нечего. Concat - это объединение нескольких строк в одну. Если вы сейчас вспомнили о операции объединения двух строк посредством сложения их знаком "+", то совершенно правильно сделали. Эта функция - абсолютный аналог этой операции. На мой взгляд, использование сложения строк через "+" гораздо лучше, чем использование Concat, так как занимает меньше места в программе, да и вообще... наглядней. Возможно, и работает чуть быстрее, хотя кто знает.
Итак, параметры Concat:
- S1, S2, .....,
Sx: String;
Список строк, которые будут сложены. Возвращает от своей работы получившуюся строку.
Исходя из вышесказанного, эти два действия абсолютно идентичны (переменные все типа String):
- S := S + S1 + S2;
- S := Concat(S, S1, S2);
Можно даже смеха ради сделать так:
- S := Concat(S + S1, S2);
- S := Concat(S, S1 + S2);
- .........
Это все про Concat, да и в целом про работу со строками. Это очень интересная тема, я советую вам всеже написать собственные процедуры, хотя бы попробовать. В дальнешем мы еще обязательно вернемся к этим процедурам и функциям, когда будем писать программы, требующие работу со строками. Ну а на сегодня все, переходим к преобразованию типов.
Преобразование
типов
Под фразой "Преобразование типов" я понимаю переход из одного типа к другому. К примеру, имеется число типа Integer и нам необходимо перевести его в строку, то есть преобразовать в тип Integer. Или наоборот - имеем строку и нам нужно преобразовать ее в число (иногда очень полезная возможность!). Это и есть преобразование типов.
При этом надо понимать, что на самом деле переменная не меняет свой тип. Это невозможно физически: в памяти компьютера все типы занимают разное количество байтов и изменить его для конкретной переменной невозможно. Преобразование типов сводиться лишь к возможности поместить значение переменной одного типа в переменную другого типа - в том виде, в котором оно этой переменной соответсвует. То есть переводя Integer в String мы всего лишь будем заполнять переменную типа String символами, которые соответсвуют цифрам переменной типа типа Integer.
Давайте теперь вспомним, сколько у нас основных типов. На самом деле всего два символьный и числовой (еще логический - Boolean - но он не основной, фактически это число). Оба они имеют несколько интерпритаций, к примеру сивольные типы это String и Char, а числовые - это Integer, Byte, Real, Single, Word.... При этом массивы и создаваемые пользователем типы (перечисляемые, объекты и т.п.) сюда не относятся, так как это что-то типа "контейнеров", которые содержат все те же основные типы.
Итак, основных типов у нас два. Для их взаимного преобразования в Паскале существует две очень простые процедуры:
- procedure Str
(X [: M [: N]]; S: String);
Преобразует число в последовательность символов - иначе говоря строку. При этом: - X: Выражение вещественного (Single, Real,...) или целого (Byte, Integer, Word...) типа;
- S: Строка типа String, в которую будет записано полученное значение.
- M, N: Это параметры, аналогично тем, которые используются в процедуре Write. Могут быть опущены.
- procedure Val
(S: String; V; Code: Integer);
Преобразует строку символов в числовой тип. Параметры: - S: Строка типа String;
- V: Переменная целого или вещественного типа для записи получившегося числа.
- Code: Это переменная для указания ошибки, если таковая существует в строке S. При наличии ошибки указывает номер символа в строке, в котором содержится ошибка, в случае отсутсвия таковых устанавливается в 0.
Ну а теперь давайте попрактикуемся в преобразовании типов. Для начала примеры простейшего преобразования:
Из строк в
числа
var S: String; I, Code: Integer;
begin Write('Введите строку: '); Readln(S); Val(S, I, Code); Writeln('Получилось число: ', I); Write('Можно даже возвести в квадрат: ', I*I); Readln; end. |
Из чисел в
строки |
var S: String; I, Code: Integer;
begin Write('Введите число: '); Readln(I); Str(I, S); Writeln('Получилась строка: ', S); Write('Можно даже сложит ее с собой: ', S+S); Readln; end. |
Это примеры использования процедур преобразования. А теперь давайте составим более полезную программу, которая уже будут выполнять кое-какие действия. Итак, заадчей, которую мы выполним будет ввод целого числа по символам, с выводом ошибки при вводе недопустимого символа. Работать программа будет так:
Теперь давайте разберем алгоритм работы такой программы:
Текст самой программы: |
Program N6; uses Crt;
var S: String; C: Char; I, Code: Integer;
begin repeat C := ReadKey; case C of '0'..'9': begin S := S + C; Write(C); end; #13: begin Val(S, I, Code); Writeln; Writeln('Число: ', I); Writeln; Readln; Break; end; #27: Break; end; until false; end. |
Текущую длинну строки можно получить при помощи команды LENGTH(СЛОВО)
program ttt;
var a:string;
x:integer;
begin
write ('введите фразу'); read (a); x:=length(a); write (x);
end.
При работе со строками наиболее часто применяются команды:
VAL( строка, переменная, код.) преобразовывает строку символов содержащих цифры в число которое заносится в переменную у принимает значение 0 если преобразование прошло успешно и числовое значение той позиции где произошла ошибка.
program ttt;
var a,b:string;
x,y:integer;
begin
write ('введите число');
read (a);
val (a,x,y);
write (x+5);