AlgStr / Библиотека / Разные источники / СД - Строки (метод ук-ия)
.pdfВыход из цикла while (k<=n) and (S[k]<>i) do происходит, если закончились символы строки или найден символ, совпадающий с символом i. По умолчанию компилятор языка Pascal проверяет первое условие и если оно истинно, то только тогда проверятся второе. Если неизвестен порядок проверки условий, то необходимо обезопасить решение от выхода за границу строки (k уже больше n, но проверяется S[k]<>i). Тогда можно использовать логическую пе-
ременную flag.
program S_3_2;
var n, k, i: integer; s: string;
flag: boolean; {признак отсутствия буквы в строке} begin
writeln (’Введите строку’); readln (S);
n := length(S);
for i := ’a’ to ’z’ do begin
k := 1; flag := true; while (k<=n) and flag do
if S[k] = i then flag := false
else
k := k+1;
if not flag then write(i,’ ’)
end; writeln
end.
13
Пример 4. Даны строки S, S1 и символ C. Вставить в строку S перед
каждым символом C строку S1.
Решение оформлено в виде процедуры S41( S, S1, C ).
Входные параметры: строки S, S1, C.
Выходные параметры: строка S.
procedure S41(var S, S1: string; C: char); var i, j, k, n: integer;
begin
k:= ord(S1[0]); n:= ord(S[0]); i := 1;
while i <= n do{повторять, пока не закончилась строка S} begin
if S[i]=C then begin
{сдвиг вправо элементов от очередного символа C
до конца строки S} for j:=n downto i do
S[j+k] := S[j]; n := n+k;
S[0] := chr(n); {увеличить длину строки}
{вставить на освободившееся место символы строки S1} for j:= 1 to k do
S[i+j-1] := S1[j]; i := i+k
end;
i := i+1 end
end;
14
3 ИСПОЛЬЗОВАНИЕ СТАНДАРТНЫХ ПРОЦЕДУР И ФУНКЦИЙ
Пример 5. Дана строка. Напечатать в алфавитном порядке все различные латинские прописные буквы этой строки.
Для решения задачи используется не посимвольная обработка строки S, как в примере 3, а стандартная функция pos (см. Приложение).
program S_5_1;
var k, i: integer; S: string;
begin
writeln (’Введите строку’); readln (S);
for i := ’A’ to ’Z’ do begin
k := pos(i,S); if k > 0 then
write(i,’ ’)
end; writeln
end.
Пример 6. Даны строки S, S1, S2. Заменить в строке S все вхождения под-
строки S1 подстрокой S2.
Решение оформлено в виде процедуры S61( S, S1, S2).
Входные параметры: строки S, S1, S2.
Выходные параметры: строка S.
15
procedure S61(var S, S1, S2: string); var n, k: integer;
begin
n := length (S1);
k := pos (S1, S); {k – позиция первого вхождения S1 в S} while k <> 0 do {повторять, пока S1 входит в S}
begin
{удалить в строке S с k-ой позиции n символов} delete (S, k, n);
{вставить строку S2 в строку S с k-ой позиции} insert (S2, S, k);
k := pos (S1, S) end
end;
Способ решения, реализованный в процедуре S61, предполагает, что заме-
няемая строка S1 не содержится в строке S2. В противном случае получим либо зацикливание, либо просто неверное решение.
Способ решения, реализованный в процедуре S62, корректно решает по-
ставленную задачу при любых исходных данных. Результат формируется в новой строке Sr.
Входные параметры: строки S, S1, S2.
Выходные параметры: строка Sr.
procedure S62(var S, S1, S2, Sr: string);
var n, k: integer;
begin
n := length (S1); Sr:=’’;
k := pos (S1, S); {k – позиция первого вхождения S1 в S}
16
while k <> 0 do {повторять, пока S1 входит в S} begin
{добавить в Sr все символы S до первого вхождения S1}
Sr := Sr+copy(S,1,k-1);
{удалить из S первое вхождение S1 и все символы до него} delete (S, 1, k+n-1);
Sr := Sr+S2; {добавить S2 в строку Sr вместо S1} k := pos (S1, S)
end;
Sr := Sr+S {добавить в строку Sr остаток строки S} end;
Пример 7. Даны строки S, S1 и символ C. Вставить в строку S перед каждым символом C строку S1.
Эта задача может быть решена с использованием посимвольной обработки строки S, как в процедуре S41( S, S1, C ) примера 4.
Другой вариант решения задачи использует стандартные процедуры и функции обработки строк (см. Приложение) и оформлен в виде процедуры
S71( S, S1, Sr, C ). Результат формируется в новой строке Sr.
Входные параметры: строки S, S1, C.
Выходные параметры: строка Sr.
procedure S71(var S, S1, Sr: string; C: char);
var k: integer;
begin
Sr:=’’;
k := pos (C, S); {k - позиция первого вхождения C в S}
17
while k <> 0 do {повторять, пока C входит в S} begin
{добавить в строку Sr все символы до первого вхождения C}
Sr := Sr+copy(S,1,k-1);
{удалить из S все символы до первого вхождения C и C} delete (S, 1, k);
{вставить в строку Sr строку S1 и символ C}
Sr := Sr+S1+C; k := pos (C, S)
end;
Sr := Sr+S; {добавить в строку Sr остаток строки S} end;
Упражнения
1) Проверьте корректность выполнения кода фрагмента программы для удаления концевых пробелов в строке S:
readln(S);
n := length(S);
while S[n]=’ ’ do
n := n-1;
S[0] := chr(n);
для следующих тестовых данных |
|
||
а) S1= ’ |
6.000asd |
’ |
( -символ пробела) |
б) S2=’ |
|
|
’ (ровно 32 пробела) |
2) Исправьте код, чтобы он работал корректно для любых входных данных.
18
Пример 8. Дана строка S. Удалить «лишние» пробелы в строке, то есть удалить начальные, концевые пробелы, и внутри строки не должно быть несколько пробелов подряд.
Первый вариант решения использует стандартные процедуры и функции
(см. Приложение) и оформлен в виде процедуры S81( S, Sr ). Результат форми-
руется в новой строке Sr.
procedure S81(var S, Sr: string); var p:integer;
begin Sr:=S;
if Sr <>'' then begin
p:=pos(' ',Sr);
{повторять, пока есть два подряд идущих пробела} while p<>0 do
begin
delete(Sr,p,1); {удалить первый из двух пробелов} p:=pos(' ',Sr)
end;
{если первый символ Sr - пробел, то удалить его} if Sr[1]=' ' then
delete(Sr,1,1); if Sr<>'' then
{если последний символ Sr - пробел, то удалить его} if Sr[length(Sr)]=' ' then
delete(Sr,length(Sr),1)
end end;
19
Второй вариант решения оформлен в виде функции S82( S ) и использует посимвольную обработку строки S с формированием новой строки Sr : в строку
Sr копируется символ строки S, если он не является пробелом, либо он – пробел,
но предыдущий символ таковым не был.
function S82(var S: string): string; var Sr : string;
i,j:integer; {текущие индексы строк S и Sr }
flag: boolean; {признак того, что предыдущий символ является пробелом}
begin Sr:=’’;
flag: = true; j:=0;
for i:=1 to ord(S[0]) do begin
{если предыдущий символ или текущий символ – не пробел} if not flag or (S[i]<>’ ’) then
begin j:=j+1;
Sr[j]:=S[i]
end;
{flag = true, если предыдущий символ является пробелом} flag:= S[i]= ’ ’
end;
{если последний символ – пробел, то удалить его} if Sr[j]= ’ ’ then j:=j-1;
Sr[0]:=chr(j);
S82:=Sr
end;
20
4 ОБРАБОТКА СЛОВ
Пример 9. Дана строка, состоящая из слов – последовательностей симво-
лов, отличных от пробела и разделённых произвольным количеством пробелов. В начале и в конце строки, состоящей из слов, может быть произвольное количество пробелов. Вывести на печать все слова в порядке их следования в строке.
При выполнении заданий на анализ и преобразование слов главная проблема заключается в выделении каждого слова из исходной строки.
Опишем алгоритм выделения слов.
Ищется первый «непробел» в строке – это будет начало первого слова. Далее в цикле до конца строки повторяются следующие действия:
–ищется конец слова (первый пробел после слова или конец строки),
–пропускаются пробелы до первого «непробела» (начала следующего слова) или до конца строки.
Приведем вариант программы без использования стандартных процедур и функций для работы со строками.
program S_9_1;
var n, k, i: integer;
S, S1: string; {строка и слово} begin
writeln (’Введите строку’); readln (S);
n := ord(S[0]); i := 1;
{пропуск пробелов – поиск начала первого слова}
21
while (i<=n) and (S[i]=’ ’) do i := i+1;
while i<=n do {повторять, пока не конец строки S} begin
k := i; {запомнить начало текущего слова}
S1 := ’’;
while (i<=n) and (S[i]<>’ ’) do begin
S1 := S1+S[i];
i := i+1; { поиск конца текущего слова} end;
writeln(S1); {вывод слова}
{пропуск пробелов – поиск начала следующего слова} while (i<=n) and (S[i]=’ ’) do
i := i+1
end
end.
Формировать очередное слово можно не только с помощью операции конкатенации, но и используя функцию копирования строки.
Пример 10. Дана строка, состоящая из слов (см. Пример 9). Посчитать ко-
личество слов в строке.
При обработке слов в строке не всегда возникает необходимость в их выде-
лении. В этом случае может фиксироваться конец слова: либо текущий символ Si
отличен от пробела, а следующий Si+1 является пробелом, либо Si – последний символ строки.
22
