Помощь - Поиск - Пользователи - Календарь
Полная версия: ЗАДАЧА С ФАЙЛОМ
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Vlad
Здравствуйте, помогите, пожалуйста решить задачку по паскалю. У меня курсовая в понедельник, а я немогу разобраться! ПОЖАЛУЙСТА!!!


Дано символьный файл f, найти количество слов в файле.
Krjuger
Во первых, тебе сказали что заголовок должен быть информативным.Для данной темы подошло бы что то в духе "задача с файлом".Во вторых,не знаю как другим,но мня раздражает заголовок с капсом.А в третьих,процетирую
volvo
Цитата

Где ваш код?
Vlad
злые Вы sad.gif
Krjuger
Молодой человек,а вы что хотите,чтобы вы зашли, написали условие задачи и вам скинули код работающей программы.Тогда ,видимо, я должен вас разочаровать,потому что никто этого делать не станет.Ладно я такой же студент и стиль написания у меня не ахти,но здесь есть програмисты со стажем,которые вам могут одну и ту же задачу решить 10 способами, используя разные констукции,а с вас потом все это спросят,а вы в эом ничего не понимаете и в итоге получите незачет.А вообще,то что вы спрашиваете это азы,если вы их не понимаете,то потом будет совсем тяжко,а всю жизнь на чужом горбу не выедеш.

Добавлено через 11 мин.
А теперь по сути.У вас есть файл со словами,что вы делаете, вы считываете элемент файла и проверяете есть ли он в множесте букв,если есть то берете следующий элемент и также проверяете до тех пор пока не наткнетесь на пробел,наткнулись на пробел, увеличили значение переменной считающей слова на +1 и выполняете данную операцию до конца файла.
Код

while not eof(fin) do
begin
  while ch in ['A'..'Z','a'..'z'] do{проверяем алфавит}
    read(fin,ch);{считываем элемент из файла fin и записываем в переменную ch}

S:=S+1;{Считаем слова}
end;

А инициализация файла и обьявление типов переменных,это уж будьте добры сами,если вы уж это не сможете сделать,то не быть вам програмистом.
Vlad
Так я же не прошу от begin к end всё писать, мне механизм понять нужно, остальное сделаю. good.gif Вот только не пойму как этот кусочек пробел определяет!? blink.gif
Krjuger
То что я написал онон не пробел определяет,а проверяет алфавит,все символы не входящие в английский алфавит воспринимаются как разделители слова.если надо конкретно пробел,то будет так.
Код

while not eof(fin) do
begin
  while ch <> ' ' do {до тех пор пока наш элемент все кроме пробела читаем следующий,как только робел переходим к следующему слову и увеличиваем S на 1.}
    read(fin,ch);{считываем элемент из файла fin и записываем в переменную ch}

S:=S+1;{Считаем слова}
end;

В чем заключаются аномалии этого кода.На пример,Если у тебя 2 пробела подрят,то второй пробел воспримется,как слово,так что тебе надо бы создать рекурсивную процедуру удаления пробела.В первой реализации такая же проблема,поэтому, если у тебя нету четких правил по структуре самого файла,лучше весь мусол, попадающтйся между словами, рекурсивно удалять,иначе тебе уйму слов выдаст.Ну а так,если соблюдать правила заполнения файла,то все будет работать.Возможно сторожилы форума подскажут что нибудь пограмотнее.
Vlad
вот наброски сделал, но не работает blink.gif


program lab_file;

uses crt;
var
words: file of string;
ch:char;
s:integer;
f:string;

begin
assign (words.txt,f);
while not eof(f) do begin
while ch <> ' ' do
read(f,ch);
S:=S+1;
end;
writeln(s);
end.
Krjuger
И не будет работать.В assign надо указывать полный путь к файлу,в котором информация лежит.А вообще лучше бы, наверно, сделать так.

program lab_file;

uses crt;
var 
 fin: text;
 ch:char;
 s:integer;

begin
assign (fin,'C:\Tpascal\test.txt');{как пример}
while not eof(fin) do begin
while ch <> ' ' do
read(fin,ch);
S:=S+1;
end;
writeln(s);
end.


Во первых, нельзя так организовывать assign ,я даже не знаю как сказать,что за ерунду ты написал.А теперь должно работать,только укажи точный путь к файлу.
volvo
Цитата
тебе надо бы создать рекурсивную процедуру удаления пробела
Цитата
весь мусол, попадающтйся между словами, рекурсивно удалять
Что ты пристал с рекурсией? Не надо никакой рекурсии тут: читаем очередной символ. Если это буква (ну, как задать алфавит - разберешься) - то ничего не делать, если НЕ буква - увеличить счетчик слов и читать символы дальше, до тех пор, пока не встретится буква. Продолжить цикл до тех пор, пока не доберешься до конца файла. Все. Никаких рекурсий тут даром не надо.
Krjuger
Ты посмотри(самый первый пост с кодом),я первый раз ему так и сделал,мы читали не до пробела,а пока буквы,но ему захотелось с пробелом,и вылез ему вариант с пробелом.
Vlad
ВСЁ ДОГНАЛ - СПАСИБО ЗА ПОМОЩЬ!!!


uses crt;
var
fin: text;
ch:char;
s:integer;
h:string;
begin
clrscr;
assign (fin,'D:\instal\PASCAL_7\tp7\prog\test.txt');
reset (fin);
while not eof(fin) do begin
readln(fin,h)
end;
writeln(h);
reset (fin);
while not eof(fin) do begin
if ch = ' ' then
S:=S+1;
read(fin,ch);
end;

close(fin);
write(S+1);
readln;
end.
Krjuger
Мда, ты явно не догнал.Во первых 2 раза ресет делать ненадо.И первого хватило.Во вторых ты не количество слов считаеш а количество пробелов.В третьих зачем ты собираеш весь файл в строку.сразу проходиш файл и выявляеш пробелы.Тебе лиш assign сделат надо было и все.Я тебе написал полностью работающую лабу,а ты начал что то там придумывать.Тебе только поменять путь к файлу надо было.
Vlad
считываю файл для того что бы вывести его содержимое на экран, а дважды ресет, потому что курсор в файле нужно в начало переводить перед новым чтением. пробелы или слова не важно, главное результат.
З.Ы. складывается впечетление что сам не очень то и понимаешь что подсказываешь, плохой у Вас форум, не успел зарегиться как сразу обижать стали blink.gif да и злые Вы все... но всёравно спасибо З.Ы.Ы. твой вариант ВООБЩЕ не работал
Krjuger
Понимаеш, считать пробелы немного безграмотно,потому что если человек случайно поставит 2 пробела подрят у тебя выдаст 2 слова,а это уже ошибка.во вторых а почему ты не хочеш считывать и выводить на экран при первом же проходе.Зачем тебе 2 раза полностью проходить файл,или тебе ресурсы своего компутера девать некуда.насчет того что мой вариант не работает,вполне возможно, потому что набивал я прямо на форему без паскаля под рукой,но на что тебе голова,что подправить.И если уж тебе хочется выводить на экран,то получи,твою же прогу менял. кстати о птичках зачем весь файл собирать в строку,если ты в цикле можеш каждую букву отдельно печатать и на одну переменную меньше будет.
Код

uses crt;
var
fin: text;
ch:char;
s:integer;

begin
S:=0;
clrscr;
assign (fin,'D:\instal\PASCAL_7\tp7\prog\test.txt');
reset (fin);
while not eof(fin) do begin
read(fin,ch);
if ch = ' ' then
S:=S+1;
write(сh);
end;
close(fin);
write(S+1);
readln;
end.
Вот немного оптимизированный ТВОЙ вариант,но на мой взгляд тут можно столько ошибок наштамповать.Еще я немного сомневаюсь со значениями №10 и №13 для ch либо он просто ьудет выводить то что я написал,либо совершать нужное действие.

З,Ы Форум не плохой,просто сидеть и писать за всех код никто не будет.Тут могут дать только общие советы и критику твоего кода.Это я уж тут от ожидания ответа на свой вопрос начал писать код.Плюс,как я понял ваше задание,так вам и ответил,и если я сделал не совсем правильный результат(не выводил файл на экран),то это ваша вина в том что неправильно обьяснили.(Я от Volvo сам уже пару раз получил за это)насчет того что мы злые,.......да я очень злой и страшный серый волк,я в юных прогерах знаю толк...
Гость
Цитата
твой вариант ВООБЩЕ не работал

согласен! blum.gif
Krjuger, там ты не считывал с самого сначала ch, а потом после прохода цикла в файле небыло перехода на следующий символ. nea.gif

меня заинтересовал вариант с рекурсией - можешь пожалуйста написать эту процедуру? спс.
Krjuger
Гость слишком много слов можно было просто сказать,что я забыл перед циклом написать Reset(fin);
Что bменно тебя заинтересовало?Как рекурсивно проходить пробелы и весь ненужный мусор чтоли?
Код

Procedure probel;
begin
read(fin,ch);
if ch=' ' then{здесь конекретно пробел,а можно и все что тебе не нужно}
probel'
end;

либо
Код

Procedure probel;
begin
if ch=' ' then{здесь конекретно пробел,а можно и все что тебе не нужно}
begin
  read(fin,ch);
  probel'
end;
end;
То какую сделать зависит от того места куда вы холите вставить эту процедуру.проблема первой в данном исполнении заключается в том,что мы будем после удаления вех пробелов в ch иметь первый элемент нашего слова,и выйда из пробела мы уже считываем второй в цикле,в данной программе проблем это не должно создать,но могут быть случаи,когда это вызовет проблемы.

или вы имели в виду рекурсивную реализацию самой задачи?
sheka
Цитата
Код

program lab_file;

uses crt;
var
fin: text;
ch:char;
s:integer;

begin
assign (fin,'C:\Tpascal\test.txt');{как пример}
reset (fin);
while not eof(fin) do begin
while ch <> ' ' do
read(fin,ch);
S:=S+1;
end;
writeln(s);
end.


смотри:
во-первых, ch перед 1-м входом не инициализирована, что иногда вызывает ошибки.
во-вторых, допустим мы наткнулись на пробел, то есть ch:=""; S:=S+1; заходим на следующий повтор цикла:
while not eof(fin) do begin //допустим не конец файла
while ch <> ' ' do // вот здесь ошибка - ch="", и read(fin,ch); не выполняется, программа зацикливается.

спс за рекурсию good.gif , я с ней не очень дружу. а что, всю программу тоде модно было сделать рекурсией?
Krjuger
Цитата

while ch <> ' ' do // вот здесь ошибка - ch="", и read(fin,ch); не выполняется, программа зацикливается.
Вообще то выполняется,потому что пустой элемент выполняет условие цикла и ТОЛЬко пробел обеспечивает нам вылет из цикла,насчет того что я в начале,не задаю значение ch,да туда запишется всякий мусор из памяти,и принципи там чисто теоретически может затесаться пробел,но шанс этого мал,принципи согласен лучше инициализировать ch.Это лиш увеличит стабильность.

Procedure rek;
begin
if not eod(fin) then
 begin
   if (ch <> ' ')  then
    begin
      read(fin,ch);
      rek;
    end;
   else
     begin
       S:=S+1;
       read(fin,ch);
       rek;
     end;
  end;
end;


Принципи оно должно сработать,на данный момент паскаля под рукой не имею,поэтому работоспособность проверить не могу,если где то ошибся,то сообщи исправлю.
И еще По сути любой цыкл можно заменить рекурсией, а рекурсию циклом,но есть моменты,когда это делать принципи нерационально.Вот например метод с циклом на мой взгляд в этой задаче проще,чем рекурсивный.
sheka
Цитата
Вообще то выполняется

если пробел - не выполняется read(fin,ch); посчитай сам!

вот отлаженые программы 2 способов (для файлов у которых первая и последняя буква не пробел, слова разделены 1 пробелом):

без рекурсии:
Код
var
  fin: text;
  ch:char;
  s:integer;

begin
s:=0;
assign (fin,'test.txt');
reset (fin);
while not eof(fin) do begin
  read(fin,ch);
  while (ch <> ' ')and(not eof(fin)) do read(fin,ch);
  S:=S+1;
  end;
close(fin);
end.


с рекурсией:
Код

var
  fin: text;
  ch:char;
  s:integer;

Procedure rek;
begin
while not eof(fin) do
  begin
  read(fin,ch);
   if (ch <> ' ')then rek
   else
     begin
       S:=S+1;
       rek;
     end;
  end;
end;

begin
s:=1;
assign (fin,'test.txt');
reset (fin);
rek;
close(fin);
end.


но я вчера сделал кому-то задачу, и там использовал
Цитата
Код
Procedure probel;
begin
if ch=' ' then{здесь конекретно пробел,а можно и все что тебе не нужно}
begin
  read(fin,ch);
  probel'
end;
end;
.

это самый оптимальный способ - и короткий, и для любого in-файла.

P.S то есть рекурсия используется как goto, но только на начало данной процедуры?
возникают ли с ней такие же глюки как и с goto?
volvo
Цитата
возникают ли с ней такие же глюки как и с goto?
Интересно, а какие глюки возникают с Goto? Ничего про глюки (при правильном использовании, а не втыкании куда надо и куда не надо, как и рекурсии, собственно), не слышал. Можно озвучить?

Только сразу говорю: без HolyWar-ов и догматичных утверждений о том, что goto - это плохо.
sheka
Цитата
Можно озвучить?

они возникали при нескольких вложеных циклах (штук 5-8).
приходилось пользоваться булевой переменной и break.
Lapp
Цитата(sheka @ 24.05.2009 13:33) *
они возникали при нескольких вложеных циклах (штук 5-8).
приходилось пользоваться булевой переменной и break.
Гм.. Непонятно.
Что за циклы? Реализованные на GoTo?
Какой компилятор?
Боюсь, без конкретного примера я не поверю..
sheka
Цитата(Lapp @ 24.05.2009 13:51) *

конкретного примера я не поверю..

на делфи.
задача о 8 ферзях...
только вполне возможно я ее вообще не правильно сделал когде еще использовал ГоТо, хотя вряд ли.
volvo
Цитата
приходилось пользоваться булевой переменной и break.
Ну, это ж не глюки... Глюки - это когда у тебя программа работает то так, а то - вот так, причем зависит это от положения Луны на небосводе... А проблемы выхода из вложенных циклов к глюкам не имеют никакого отношения... Это - именно проблемы. Причем в большинстве случаев решается эта проблема именно введением Goto, а не наоборот.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.