Pers.narod.ru. Алгоритмы. Разбор на слова за 1 проход по строке |
Во-первых, часто требуется определить самое длинное (или самое короткое) слово. В этой главе я привожу 2 примера такого разбора, но первый неэффективен (использует много стандартных функций, портит исходную строку, удаляя из неё уже обработанные слова), а второй ценен лишь идеей сделать разбор на слова за один проход по строке. Однако обе приведённые в пособии программы могут быть удобны, если выделяемые из строки слова должны как-то дополнительно обрабатываться.
Между тем, обычно набор допустимых символов в словах ограничен условием задачи (давайте возьмём для примера только латинские и русские буквы и цифры), а сами слова сохранять и дополнительно обрабатывать не требуется. Учитывая, что в Паскале есть удобный оператор in, напишем такую программу:
Разбор на слова за 1 проход с использованием in и определением самого длинного слова. Слова при этом не сохраняются.
var s:string;
c:char;
i,all,len,maxlen:integer;
begin
writeln ('Введите предложение:');
readln (s);
len:=0;
maxlen:=0;
all:=length(s);
for i:=1 to all do begin
c:=s[i];
if c in
['a'..'z','A'..'Z','0'..'9','а'..'п','р'..'я','А'..'П','Р'..'Я','Ё','ё']
then inc (len)
else begin
if len>maxlen then maxlen:=len;
len:=0;
end;
end;
write ('Maxlen=',maxlen);
reset (input); readln;
end.
Если бы мы захотели вывести само слово, это не потребовало бы дополнительных переменных или циклов обработки. Достаточно запоминать позицию символа pos, в которой закончилось очередное слово, а затем вывести maxlen символов, начиная с позиции pos-maxlen. Вот изменённая программа:
Разбор на слова за 1 проход с использованием in и определением самого длинного слова. Находится одно слово, оно при этом выводится. Дефисы и т.п. символы не учитываются.
var s:string;
c:char;
i,all,len,maxlen,pos:integer;
begin
writeln ('Введите предложение:');
readln (s);
len:=0;
maxlen:=0;
all:=length(s);
for i:=1 to all do begin
c:=s[i];
if c in
['a'..'z','A'..'Z','0'..'9','а'..'п','р'..'я','А'..'П','Р'..'Я','Ё','ё']
then inc (len)
else begin
if len>maxlen then begin maxlen:=len; pos:=i; end;
len:=0;
end;
end;
writeln ('Maxlen=',maxlen);
write ('Word=',Copy(s,pos-maxlen,maxlen));
reset (input); readln;
end.
Наконец, в слова входят не только буквы и цифры, например, слова с дефисом наша программа никак не учитывает. Попробуем изменить код так, чтобы "буквой" считалось всё, что не является концом слова. Так как число допустимых между словами разделителей заведомо невелико, начать разбор в этом случае будет уместнее как раз с них.
Разбор на слова за 1 проход с использованием in и определением самого длинного слова. Находится одно слово, оно при этом выводится. Концом слова считается фиксированный набор разделителей.
var s:string;
c:char;
i,all,len,maxlen,pos:integer;
begin
writeln ('Введите предложение:');
readln (s);
len:=0;
maxlen:=0;
all:=length(s);
for i:=1 to all do begin
c:=s[i];
if c in [' ','.',',','?','!',':',';'] then begin {разделители}
if len>maxlen then begin maxlen:=len; pos:=i; end;
len:=0;
end
else inc(len);
end;
writeln ('Maxlen=',maxlen);
write ('Word=',Copy(s,pos-maxlen,maxlen));
reset (input); readln;
end.
Пример выдачи этой программы:
Введите предложение: Скажи-ка, дядя, ведь недаром? Maxlen=8 Word=Скажи-ка
Если мы хотим вывести все слова наибольшей длины, можно при первом проходе найти maxlen, а при втором, как только попадётся слово с длиной len=maxlen, напечатать его:
var s:string;
c:char;
i,all,len,maxlen,pos:integer;
begin
writeln ('Введите предложение:');
readln (s);
len:=0;
maxlen:=0;
all:=length(s);
for i:=1 to all do begin
c:=s[i];
if c in [' ','.',',','?','!',':',';'] then begin {разделители}
if len>maxlen then begin maxlen:=len; pos:=i; end;
len:=0;
end
else inc(len);
end;
writeln ('Maxlen=',maxlen);
write ('Words=');
for i:=1 to all do begin
c:=s[i];
if c in [' ','.',',','?','!',':',';'] then begin {разделители}
if len=maxlen then write (' ',Copy(s,i-maxlen,maxlen));
len:=0;
end
else inc(len);
end;
reset (input); readln;
end.
Соответственно, пример выдачи:
Введите предложение: Скажи-ка, дядя, ведь не даром идут гаишники с радаром? Maxlen=8 Words= Скажи-ка гаишники
Необходимо также заметить, что все приведённые программы не реагируют корректно на самое длинное слово, являющееся последним в строке - в тех случаях, когда предложение не завершается любым разделителем. Решить эту проблему можно простейшим способом, добавив в конец прочитанной строки любой разделитель, например
readln (s); s:=s+' ';
или же предумотреть в цикле обработки отдельную проверку на то,
не является ли допустимый символ последним в строке (выполняется условие i=all).
Можно сделать и дополнительное сравнение значений len и maxlen после выхода из
цикла разбора - ведь последнее значение len не потеряется. В этом случае конец
первой программы изменится так:
end;
end;
if len>maxlen then maxlen:=len;
write ('Maxlen=',maxlen);
reset (input); readln;
|
|