Помощь - Поиск - Пользователи - Календарь
Полная версия: Задача с использованием файла
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
-Студент-
Вечер добрый форумчане.
вощем задал препод на первый взгляд не очень сложную задачу , но он у меня вызывает ряд затруднений ...
задание : Подсчитать кол-во слов содержащих хотябы одну букву "m"

вот текст программы , написал что мог

Код

program laba51;
var f1:text;
i:integer;
s:string;
begin
assign(f1,'laba51.txt');
rewrite(f1);
for i:=1 to 5 do begin
readln(s);
writeln(f1,s);
end;
close(f1);
end.

program laba52;
uses crt;
var f1:text;
i,k,l:integer;
s:string;
begin
assign(f1,'laba51.txt');
reset(f1);
k:=0;
while not eof(f1) do
for i:=1 to length(s) do
begin
readln(f1,s);
if s[i]='m' then k:=k+1;
i:=i+1;
end;
writeln ('kol-vo slov = ',k);
close(f1);
READKEY;
end.


если не сложно , исправте пожалуйста ... очень мне поможите

в программе я не реализовал нахождеименно слова ... неполучается это сделать unsure.gif
-Студент-
знающие люди , подскажите пожалуйста ... горю , на след. неделе начинается сессия , исправте алгоритм если вам это под силу unsure.gif
andriano
У тебя проблема в этом фрагменте:

for i:=1 to length(s) do
begin
readln(f1,s);
if s[i]='m' then k:=k+1;
i:=i+1;
end;


Смотри, ты организуешь цикл по всей длине строки ДО того, как ее прочитал. И чтение целой строки у тебя оказалось ВНУТРИ цикла по буквам строки.
Оператор чтения нужно вынести из цикла - поставить его выше, чтобы к моменту начала цикла строка уже была прочитана.
Далее, как только ты переставишь строчку, она окажеся вне begin...end, поэтому для выполнения всего цикла while понадобится еще парочка.
Ну и переопределять переменную цикла внутри этого цикла недопустимо.

Айра

for i:=1 to length(s) do
begin
readln(f1,s); //замени на read, иначе будет считываться только 1-й символ каждой строки
if s[i]='m' then k:=k+1;
i:=i+1; //так нельзя делать
end;

А как такой вариант:
program laba52;
uses crt;
const simvol : set of char = [',','.',':',';','-', '!', '?', ' ']; //множество символов-разделителей слов
var f1:text;
k:integer;
l: boolean;
ch: char;
begin
l:=true; //true, если началось новое слово
assign(f1,'laba51.txt');
{$I-}
reset(f1);
{$I+}
if IoResult = 0 then //проверям, найден ли нужный файл
begin
k:=0;
while not eof(f1) do
begin
read(f1,ch); //считываем посимвольно
write(ch); //выводим для нагляности
if ch in simvol then l:=true; //если ch символ-разделитель, то мы в новом слове
if (ch='m') and l then //если ch нужный символ и слово новое, то...
begin
inc(k);
l:=false; //теперь слово уже не новое, это значит, что если в слове несколько 'm',
//то оно считается как одно слово с этой буквой, а не несколько
end;
end;
writeln;
writeln ('kol-vo slov = ',k);
close(f1);
end
else writeln('файл не найден');
end.

если что непонятно, спрашивай smile.gif
andriano
Вообще-то s - это строка, так что проблем с этой строчкой кода быть не должно (кроме того, что она не в том месте)
    readln(f1,s);   //замени на read, иначе будет считываться только 1-й символ каждой строки

А вот эти две строки меня озадачивают:
            if ch in simvol then l:=true;   //если ch символ-разделитель, то мы в новом слове
if (ch='m') and l then //если ch нужный символ и слово новое, то...

Строго говоря, первую строку можно записать в виде:
l := ch in simvol

А их вместе:
            if (ch='m') and (ch in simvol) then  //если  ch нужный символ и слово новое, то...

Что эквивалентно
if FALSE then
т.к. один и тот же символ не может одновременно равняться m и быть разделителем.
Таким образом весь этот блок можно выбросить, оставив только вывод нуля на экран.
Malice
Цитата(andriano @ 14.12.2007 21:11) *

А вот эти две строки меня озадачивают:

А что если назначение этой строки проявит себя на следующем витке цикла while ? Ее все равно можно сократить ? Коль уж вы взвалили на себя нелегкую миссию цензора, комментирущего код не вопрошающего, а отвечающего, то будьте добры производить наиполнейший анализ всего кода, чтобы от столь пространных умозаключений хотя бы не было вреда.
andriano
Да, признаю, в анализе допустил ошибку.
Тогда получается, что если текущий символ m, а предыдущий - разделитель, то учитываем.
И эта возможность учесть у нас сохраняется до первого m, а затем утрачивается до нового разделителя.
Да, получается, что приведенный код может работать. Но логика работы достаточно запутана.
В исходной программе, вроде бы, предполагается, что текст содержит по одному слову на строке. Неплохо бы прояснить этот момент.
Кстати, если учитывать разделители, то мне кажется, в их число необходимо внасти пробел и символ табуляции. А, возможно, даже все символы, явно не описанные как буквы. (опять же - неопределенность условия)
Но не лучше ли поступить по следующему алгоритму:
1. Все разделители заменяются на пробелы.
2. Все двуойные пробелы заменяются на одинарные.
3. Строка режется на фрагменты по пробелам.
4. Каждый фрагмент проверяется на наличие искомого символа.
?
Мне кажется, такой алгоритм более прозрачен и подходящ для учебных целей.
Айра
Цитата
Но логика работы достаточно запутана.

Женская логика завораживает своей алогичностью (с) blum.gif
Цитата
В исходной программе, вроде бы, предполагается, что текст содержит по одному слову на строке

В исходной программе, но в задании об этом ничего не сказано.. Будем ждать разъяснений автора?..
Цитата
в их число необходимо внасти пробел и символ табуляции

пробела там действительно нехватает.. внесла.. табуляцию внесла бы, если б знала как она выглядит))
Цитата
Мне кажется, такой алгоритм более прозрачен и подходящ для учебных целей.

Это твое ИМХО, если тебе так понятнее, то делай так, я же сделала как легче мне, тем более каких-то определенных условий по алгоритму в задании нет..
andriano
Табуляция в Паскале обозначается #9.
С точки зрения текстового файла интересна тем, что это СТАНДАРТНЫЙ разделитель для текстовых файлов экспортируемых/импортируемых Excell. То есть пример не учебный, а самый что ни на есть практический. ;)
-Студент-
Предпологается , что в строке символов слов может быть сколько угодно ...
и нужно считать именно те слова (а словом считается набор символов ограниченных с 2 - ух сторон пробелами) в которых есть хотябы 1 буква "m" т.е. слово "mama" будет считаться как 1 слово
andriano
Цитата(-Студент- @ 14.12.2007 23:38) *
словом считается набор символов ограниченных с 2 - ух сторон пробелами
Уточнение:
правильно ли я понял, что в строке "мама мыла раму" содержится только одно слово "мыла", т.к. остальные ограничены пробелами лишь с одной стороны?

И еще:
Цитата
Предпологается , что в строке символов слов может быть сколько угодно ...

в Паскале строка не может содержать более 255 символов. Означает ли это, что программа должна уметь обрабатывать и более длинные строки (это возможно, но тогда весь инструментарий работы с такими строками придется писать самостоятельно)?
volvo
Цитата
весь инструментарий работы с такими строками придется писать самостоятельно
Ты знаешь, если тебе делать особо нечего, можно и System.pas заново переписать, а так - весь инструментарий для работы со строками длиной до 64k находится в модуле Strings, можно его сразу использовать...
andriano
В Паскале строк длиннее 255 символов НЕТ!
Различные компиляторы Паскаля поддерживают разные РАСШИРЕНИЯ языка, несовместимые друг с другом. В ТМТ, напрмер, модуль strings допускает работу в 255-символьными строками, а также с оканчивающимися нулем стоками из одно- и двухбайтовых (unicode) символов. 64К-байтных строк там нет.
А если бы и были, какая разница, если требуется обработка строк ЛЮБОЙ длины?
-Студент-
2Andriano

Нет , в строке "мама мыла раму" будет 3 слова , слово с двумя и более "m" будет считаться как 1 слово , нужно подсчитать кол-во слов в которых есть хотябы 1 буква "m"
Айра
Цитата
ограниченных с 2 - ух сторон пробелами

это предполагает, что других символов в строке нет?

А вообще, программка, которую я выкладывала выше, вроде работает нормально.. Разделяет на слова она, в принципе, так, как мы привыкли разделять (в плане знаков препинания и т.п.).. и считает тоже вроде верно.. Тебе в ней что-то непонятно, что-то неустраивает? Спрашивай. А то мы развели уже тут дискуссию по поводу действительно "не очень сложной задачи" smile.gif
andriano
Цитата(-Студент- @ 15.12.2007 14:41) *

2Andriano

Нет , в строке "мама мыла раму" будет 3 слова , слово с двумя и более "m" будет считаться как 1 слово , нужно подсчитать кол-во слов в которых есть хотябы 1 буква "m"

Это явно противоречит тому, что ты писал выше:
Цитата
словом считается набор символов ограниченных с 2 - ух сторон пробелами

Так что за тобой третья попытка корректно сформулиовать условие задачи.

И, кстати, еще раз прошу уточнить насчет допустимой длины строки: если ограничение есть, целесообразнее читать файл как текст и воспользоваться стандартным набором процедур для работы со строками. Если ограничения нет, лучше читать файл как бинарный и решать задачу при помощи конечного автомата.
-Студент-
ну задача для первого курса smile.gif
нечего сверхъестественного в ней быть недолжно , мне только непонятно что за переменная IoResult или это стандартная процедура ? и что за спец. символы {$I-} , такого мы ещё не изучали ... и ещё переменная "Inc" , за что он отвечает ? Объсните пожалуйста smile.gif

2Andriano , допустимая длина строки стандартна , т.е. 255 символов.
Айра
Цитата
что за переменная IoResult ... и что за спец. символы {$I-}

{$I} - директива компилятора, которая отлавливает ошибки ввода/вывода - если, например, файла, к которому ты обращаешься нет, то компилятор "поругается" и закроет программу. А {$I-} - отключиние этой проверки -> ошибка выскакивать не будет.. {$I+} - включение этой директивы.
А вот функция IOResult возвращает результат последней операции ввода/вывода: 0 - если ошибки не было (файл нашелся) и какое-то положительное число (код ошибки), если операция ввода/вывода потерпела неудачу))

Т.е. для корректной обработки ошибок ввода/вывода я отключила стандартную проверку {$I} и использовала IoResult.

Цитата
переменная "Inc" , за что он отвечает

inc(x) - процедура, которая по умолчанию увеличивает значение аргумента x на 1, если ввести еще один параметр, например inc(x,5), то значение будет увеличиваться на 5.

Вроде объяснила, если еще что-то непонятно, спрашивай, попытаюсь расшифровать smile.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.