Страница 1 из 2
[Pascal] Число повторений слов в тексте
Добавлено: 01 дек 2008, 17:55
Horita
Нужно посчитать число слов. И мне нужна рекурсия

Ну это фигня.
На чем я застопорилась, это как найти число встречаемости слова в тексте. Посути программа должна пройти каждое слово и выписать сколько раз оно встречается.
Код: Выделить всё
PROGRAM CountWords(INPUT, OUTPUT);
CONST
Chars = [' ', '.', ',', '!', '?', ':', ';'];
VAR
Ch: CHAR;
T: TEXT;
S: STRING;
I, Wc, W: INTEGER;
PROCEDURE Count;
BEGIN
WHILE NOT (Ch IN Chars) AND NOT EOF(T)
DO
BEGIN
READ(T, Ch);
IF Ch IN Chars
THEN
BEGIN
INC(I);
READ(T, Ch);
Count;
END;
END;
IF Ch = ' '
THEN
BEGIN
READ(T, Ch);
Count;
END;
END;
BEGIN
ASSIGN(T, 'Text1.txt');
RESET(T);
Count;
WRITELN(I);
END.
Вот собствено мой подсчет с помощью рекурсии.
Re: [Pascal] Число повторений слов в тексте
Добавлено: 01 дек 2008, 23:40
Naeel Maqsudov
Какая же это рекурсия!
Если на вход подать текст "йцу,фыв,ясч,вап,апр" то рекурсивного вызова вообщене произойдет.
А еще можно запросто спровоцировать ситуацию, когда произойдет чтение за концом файла!
1) Тут ошибки
2) Даже при отсутствии ошибок подобный алгоритм для раздельного подсчета слов не годится. Надо все переделывать. Надо где-то (вопрос - где: в массиве? динамическом списке?) запоминать каждое новое слово, и счетчие для него.
На счет применения тут рекурсии я категорически несогласен!
Файл читатся последовательно. Т.е. может быть сколь угодно большим. Если каждое слово это еще один некурсивный вызов, то стек быстро закончится.
Тут надо либо считать, что файл маленький, и тогда грузить его за 1 раз в память и обрабатывать (идиотской рекурсивной функцией, которая даже тут ни разу не нужна), либо считать, что файл большой и следовательно рекурсия тут вообще не применима в принципе!
Re: [Pascal] Число повторений слов в тексте
Добавлено: 02 дек 2008, 10:06
Horita
"йцу,фыв,ясч,вап,апр" при такой строке он насчитает 4 слова, но любой текст заканчивается точкой и если в конце поставить точку то будет 5 слов.
То что подобный способ негодится, раз вы так говорите, наверное так и есть.
Будем думать....
Оффтопом: неподскажите книжки по Си ?
Re: [Pascal] Число повторений слов в тексте
Добавлено: 02 дек 2008, 12:27
somewhere
ИМХО любая рекурсия - великое зло. Здесь подойдет "псевдоалгоритм" предложенный Naeel Maqsudov
Считаем что
TWordStats = record word: string; count : integer; end;
TWords = array of TWordStats;
Words, WordsInLine : TWords;
[1] Если конец файла, то [6]
[2] Читаем строку
[3] Разбиваем на слова (см. раздел "алгоритмы", модифицировать для типов TWords, TWordStats - результат в WordsInline)
[4] Объединение массивов Words - WordsInLine
[4.1] Для каждого слова в WordsInLine выполнить поиск в Words
[4.2] Если найдено - инкремент счетчика, если нет - добавить в конец
[5] Идем к 1
[6] Вывод статистики
Re: [Pascal] Число повторений слов в тексте
Добавлено: 02 дек 2008, 19:31
Naeel Maqsudov
Horita писал(а):"йцу,фыв,ясч,вап,апр" при такой строке он насчитает 4 слова
Да. Но рекурсивного вызова при это не произойдет ниодного. Выполните по шагам, если Вам это не очевидно.
Итак для каждого слова нам нужен свой счетчик. Посторяю вопрос: как хотите хранить счетчики? В массиве (но тогда есть ограничение на максимальное количестсво уникальных слов), в динамическом массиве или в связанном списке?
Три варианта...
Re: [Pascal] Число повторений слов в тексте
Добавлено: 02 дек 2008, 20:51
Horita
В динамическом массиве.
Re: [Pascal] Число повторений слов в тексте
Добавлено: 02 дек 2008, 21:31
Naeel Maqsudov
Вот правильный подсчет слов с помощью рекурсии:
(Это вместо Вашей первой программы)
Код: Выделить всё
PROGRAM CountWords(INPUT, OUTPUT);
CONST
Chars = [' ', '.', ',', '!', '?', ':', ';',#10,#13];
VAR
T: TEXT;
Count: integer;
function NextWord:string;
var
Ch: char;
begin
Read(T,Ch);
if (Ch in Chars) or eof(T)
then NextWord:=''
else NextWord:=Ch+NextWord;
end;
BEGIN
Count:=0;
ASSIGN(T, 'c:\somefile.txt');
RESET(T);
repeat
if NextWord<>'' then inc(Count);
until eof(T);
close(T);
writeln('Найдено ',Count,' слов(а)');
readln;
END.
Re: [Pascal] Число повторений слов в тексте
Добавлено: 03 дек 2008, 10:30
Horita
Я так поняла, в функции так же можно записывать слово в файл ?
Проходя следующее слово будем сравнивать со словами в файле, если встретится, то слову которое встречается присвоить inc(counter). А если не нашлось, то записать в конец. Так можно сделать ? Щас попробую.
Re: [Pascal] Число повторений слов в тексте
Добавлено: 03 дек 2008, 17:51
Naeel Maqsudov
Я сильно извиняюсь, в турбо-паскеле нету же динамических массивов. Поэтому для турбо-паскаля оптимальнее всего использовать все-таки динамический список:
Код: Выделить всё
PROGRAM CountWords(INPUT, OUTPUT);
CONST
Chars = [' ', '.', ',', '!', '?', ':', ';',#10,#13];
type
PCounter=^TCounter;
TCounter=record
Word:string;
Count:integer;
Next:PCounter;
end;
VAR
T: TEXT;
Counts,Tmp: PCounter;
W:string;
CountTotal,CountUnique:integer;
function NextWord:string;
var
Ch: char;
begin
Read(T,Ch);
if (Ch in Chars) or eof(T)
then NextWord:=''
else NextWord:=Ch+NextWord;
end;
function AddCounter(var ioHead:PCounter;iWord:string):boolean;
var
Curr,New:PCounter;
begin
{$B-}
Curr:=ioHead;
AddCounter:=false;
if Curr<>nil then while (Curr^.Next<>nil) and (Curr^.Word <> iWord) do
Curr:=Curr^.Next;
if (Curr=nil) or ((Curr^.Next=nil) and (Curr^.Word<>iWord)) then begin
getmem(New,SizeOf(TCounter));
with New^ do begin
Word:=iWord;
Count:=1;
Next:=nil;
AddCounter:=true;
end;
if Curr=nil then ioHead:=New else Curr^.next:=New;
end else {Curr^.Word=iWord} inc(Curr^.Count);
end;
BEGIN
Counts:=nil;
CountTotal:=0;
CountUnique:=0;
ASSIGN(T, 'c:\somefile.txt');
RESET(T);
repeat
W:=NextWord;
if W<>'' then begin
inc(CountTotal);
if AddCounter(Counts,W) then inc(CountUnique);
end;
until eof(T);
close(T);
writeln('Всего слов тексте: ', CountTotal);
if CountUnique>0 then begin
writeln('Различных слов обнаружено: ', CountUnique, '. Среди них:');
Tmp:=Counts;
while Tmp<>nil do begin
writeln('Слово "',Tmp^.Word,'" встречается ',Tmp^.Count,'раз(а)');
Tmp:=Tmp^.Next;
end;
end;
readln;
END.
Если надо для Object Pascal, то можно переделать и заменить списки динамическим массивом.
Re: [Pascal] Число повторений слов в тексте
Добавлено: 03 дек 2008, 18:02
Naeel Maqsudov
Horita писал(а):...в функции так же можно записывать слово в файл ?
Проходя следующее слово будем сравнивать со словами в файле, если встретится, то слову которое встречается присвоить inc(counter)...
Не, ну а смысл, то какой в это м втором файле? С таким же успехом можно и первый перечитывать, но до того места, на котором стояли до извлечения слова.
Я бы тогда сделал так:
1) очищаем специальную временную папку
2) проберая по файлу, берем NextWord и а) если в папке есть файл с таким именем, то прочитываем из файла число, прибавляем единицу и записываем обратно в файл (переписывам содержимое файла) б) а если нету такого файла, то создаем его и записываем туда "1".
3) потом сканируем папку и выводим готовые результаты.
Т.е. в качестве хранения счетчиков (а их по одному на каждое слово) можно использовать файловую систему, а не динамический список.