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;
гостевая; E-mail |