Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Телефонная книга. Исправить ошибки

Автор: Natalia 20.12.2006 6:48

Доброго времени суток! Помогите разобраться с задачей. Всё, что поняла, реализовала в программе.
Задача такая: Составьте программу, реализующую телефонную книгу. Каждая запись в книге включает фамилию, инициалы и три телефона (один домашний и два рабочих). Программа должна обеспечивать ввод и сохранение записей, вывод телефонов по введённой фамилии, а также вывод всех фамилий с указанием инициалов по введённому телефонному номеру.
Но у меня не выходит. wacko.gif

Код
program Telefonnaya_kniga;
uses crt;
const n=10;
type
       book=record
             first_name:string[20];
             inis:string[5];
             telrab1:shortInt;
             telrab2:shortint;
             teldom:shortint;
            end;
       Tel_Book=array[1..n] of book;
       Ffile=file of Tel_Book; {файл для хранения базы}
var f:Ffile;
    b:Tel_Book;
    t,k,tel:shortint;
    i:byte;
    s:string;
begin
  assign(f,'tel_book.txt');
  writeln('Ввод данных-0; поиск-1; сохранение-2; возврат в меню-".."');
  readln(t);
  if t=0 then begin
  append(f);
  writeln('Ввод данных в телефонную книгу:');
  while t<>'..' do
   with b[i] do begin
    write('Фамилия: ');
    readln(first_name);
    write('Инициалы: ');
    readln(inis);
    writeln('Домашний телефон: ');
    readln(teldom);
    writeln('Рабочий телефон 1: ');
    readln(telrab1);
    writeln('Рабочий телефон 2: ');
    readln(telrab2);
    writeln;
   end;
   write(f,b);
   close(f);
  end;
  if t=1 then begin
  reset(f);
  while k<>'..' do
   writeln('Поиск:')
   writeln('по фамилии-0');
   writeln('по телефону-1');
   readln(k);
  if k=0 then begin
   writeln('Введите фамилию');
   readln(s);
    for i:=1 to n do
     if s=b.first_name then writeln(b.first_name,b.inis,b.teldom,b.telrab1,b,telrab2);
    end;
  end;
  if k=1 then begin
   writeln('Введите телефон');
   readln(tel);
    for i:=1 to n do
     if tel=b.teldom then writeln(b.first_name,b.inis,b.teldom,b.telrab1,b,telrab2);
     if tel=b.telrab1 then writeln(b.first_name,b.inis,b.teldom,b.telrab1,b,telrab2);
     if tel=b.telrab2 then writeln(b.first_name,b.inis,b.teldom,b.telrab1,b,telrab2);
    end;
  end;
  close(f);
  end;
  readln;
  end.


И ещё вопрос: какой функцией воспользоваться, чтобы определить количество байтов, записанных в файл? FileSize - мне не помог. Нужна ли тут процедура FilePos?

Автор: Lapp 20.12.2006 13:20

Цитата(Natalia @ 20.12.2006 3:48) *

Но у меня не выходит.

Слишком общо.. Что именно не выходит?
Ошибок у тебя немало. Во-первых, нетекстовый файл нельзя открывать процедурой Append. Так что либо используй ReWrite, либо работай с текстовым файлом (последнее на мой взгляд, предпочтительнее).
Определишься с этим - приходи..

Автор: Natalia 20.12.2006 20:57

Основную проблему с append я знаю... У меня задание сохранять и загружать из типизированного файла. Я бы использовала rewrite, но, как я понимаю, это перезапись файла, а мне необходимо открывать файл с телефонной книгой и добавлять записи. Как-то напрямик в книжке не было сказано, что нельзя использовать append с типизированным файлом. Зменила значок '..' на цифру 3 и заменила append на rewrite. А как тогда поля записи правильно отобразить? Через точку неверно (s=b.first_name), хотя в книге приводтся два примера: через точку и with.

Автор: мисс_граффити 20.12.2006 22:18

хммм....

Цитата
В отличие от текстовых типизированные файлы допускают операции как записи, так и чтения независимо от того, какой процедурой файл открыт

так что смело открывай reset

Автор: Natalia 20.12.2006 23:46

Поковырялась с файлом. Вот что вышло. По-крайней мере он выполняется.

Код
program Telefonnaya_kniga;
uses crt;
const n=10;
type
       book=record
             first_name:string[20];
             inis:string[5];
             telrab1:shortInt;
             telrab2:shortint;
             teldom:shortint;
            end;
       Tel_Book=array[1..n] of book;
       Ffile=file of Tel_Book; {файл для хранения базы}
var f:Ffile;
    b:Tel_Book;
    t,k,tel:shortint;
    i:byte;
    s:string;
begin
  assign(f,'tel_book.txt');
  reset(f);
  writeln('Ввод данных-0; поиск-1; сохранение-2; возврат в меню-"3"');
  readln(t);
  if t=0 then
   begin
    writeln('Ввод данных в телефонную книгу:');
     while t<>3 do
      with b[i] do begin
       write('Фамилия: ');
       readln(first_name);
       write('Инициалы: ');
       readln(inis);
       writeln('Домашний телефон: ');
       readln(teldom);
       writeln('Рабочий телефон 1: ');
       readln(telrab1);
       writeln('Рабочий телефон 2: ');
       readln(telrab2);
       writeln;
      end;
      write(f,b);
    end;
  if t=1 then begin
  while k<>3 do
   begin
    writeln('Поиск:');
    writeln('по фамилии-0');
    writeln('по телефону-1');
    readln(k);
     if k=0 then
      begin
       writeln('Введите фамилию');
       readln(s);
        with b[i] do
         begin
          for i:=1 to n do
           if s=first_name then writeln(first_name,inis,teldom,telrab1,telrab2);
         end;
        end;
       end;
      if k=1 then
       begin
        writeln('Введите телефон');
        readln(tel);
         with b[i] do
          begin
           for i:=1 to n do
             begin
              if tel=teldom then writeln(first_name,inis,teldom,telrab1,telrab2);
              if tel=telrab1 then writeln(first_name,inis,teldom,telrab1,telrab2);
              if tel=telrab2 then writeln(first_name,inis,teldom,telrab1,telrab2);
             end;
          end;
        end;
   end;
  close(f);
  readln;
  end.
  


Какой функцией воспользоваться, чтобы определить количество байтов, записанных в файл? FileSize - мне не помог. Нужна ли тут процедура FilePos?

Автор: мисс_граффити 20.12.2006 23:58

размер в байтах=filesize(твоего файла)*sizeof(элемент файла)

Автор: Natalia 21.12.2006 1:36

Подскажите, пожалуйста, в чём дело. Немного переделала программу. Она запускается, но почему-то выводит только одну фразу "Ввод данных-0; поиск-1; возврат в меню-3". Почему она ничего другого не выполняет?

Код
program Telefonnaya_kniga;
uses crt;
const n=50;
type
       book=record
             first_name:string[20];
             inis:string[5];
             telrab1:shortInt;
             telrab2:shortint;
             teldom:shortint;
            end;
       Tel_Book=array[1..n] of book;
       Ffile=file of Tel_Book; {файл для хранения базы}
var f:Ffile;
    b:Tel_Book;
    t,k,tel:shortint;
    i:byte;
    s:string;
begin
  assign(f,'tel_book.txt');
  reset(f);
   while t<>3 do
    writeln('Ввод данных-0; поиск-1; возврат в меню-3');
    readln(t);
     if t=0 then
      begin
       writeln('Ввод данных в телефонную книгу:');
        with b[i] do begin
         write('Фамилия: ');
         readln(first_name);
         write('Инициалы: ');
         readln(inis);
         writeln('Домашний телефон: ');
         readln(teldom);
         writeln('Рабочий телефон 1: ');
         readln(telrab1);
         writeln('Рабочий телефон 2: ');
         readln(telrab2);
         writeln;
        end;
       write(f,b);
      end;
     if t=1 then
      begin
       writeln('Поиск:');
       writeln('по фамилии-0');
       writeln('по телефону-1');
       readln(k);
        if k=0 then
         begin
          writeln('Введите фамилию');
          readln(s);
           with b[i] do
            begin
             for i:=1 to n do
              if s=first_name then writeln(first_name,inis,teldom,telrab1,telrab2)
                              else writeln('Такой фамилии нет');
            end;
          end;
         if k=1 then
          begin
           writeln('Введите телефон');
           readln(tel);
            with b[i] do
             begin
              for i:=1 to n do
               begin
                if tel=teldom then writeln(first_name,inis,teldom,telrab1,telrab2)
                               else writeln('Такого телефона нет');
                if tel=telrab1 then writeln(first_name,inis,teldom,telrab1,telrab2)
                               else writeln('Такого телефона нет');
                if tel=telrab2 then writeln(first_name,inis,teldom,telrab1,telrab2)
                               else writeln('Такого телефона нет');
               end;
             end;
           end;
       end;
  close(f);
  readln;
  end.

Автор: Natalia 21.12.2006 1:51

Цитата(мисс_граффити @ 20.12.2006 19:58) *

размер в байтах=filesize(твоего файла)*sizeof(элемент файла)


Спасибо за подсказку)) Но у меня проблемка такая, pascal напрочь отказывается найти файл (файл нетипизированный по заданию). Вроде, поместила файл в ту директорию, даже пробовала указывать путь... Вот эта программа, пока только сделанная не до конца.

Код
uses crt;
uses crt;
var f:file;
    s:char;
    rzm:word;
    name:string;
    a:integer;
begin
  clrscr;
  write('Введите имя файла ');
  readln(name);
  assign(f,name);
  reset(f,1);
  rzm:=filesize(f);
  a:=rzm*sizeof(char);
  writeln('Размер файла',a);
  close(f);
end.

Автор: мисс_граффити 21.12.2006 1:57

var f:file;

а речь вроде шла про работу с типизированными...

Автор: Natalia 21.12.2006 2:24

Цитата(мисс_граффити @ 20.12.2006 21:57) *

var f:file;

а речь вроде шла про работу с типизированными...

с типизированным я знаю, как определить)) У меня задание с нетипизированным)) Значит, мне сначала надо определить тип содержимого файла, а затем определять количество байтов?
Подскажи, пожалуйста, в чём дело по телефонной книге. Немного переделала программу (она выложена выше). Она запускается, но почему-то выводит только одну фразу "Ввод данных-0; поиск-1; возврат в меню-3". Почему она ничего другого не выполняет?

Автор: Bokul 21.12.2006 2:46

Держи универсальную функцию нахождения размера файла. smile.gif


uses dos;
function MyFileSize(s:string):longint;
var Info:SearchRec;
begin
FindFirst(s,AnyFile,info);
MyFileSize:=info.size;
end;


Автор: volvo 21.12.2006 2:52

Цитата
Почему она ничего другого не выполняет?

А что, в этом цикле где-то меняется значение T?
   while t<>3 do
writeln('Ввод данных-0; поиск-1; возврат в меню-3');


Ты наверное забыла весь цикл взять в Begin/End

Автор: Гость 21.12.2006 3:21

Цитата(Bokul @ 20.12.2006 22:46) *

Держи универсальную функцию нахождения размера файла. smile.gif

uses dos;
function MyFileSize(s:string):longint;
var Info:SearchRec;
begin
FindFirst(s,AnyFile,info);
MyFileSize:=info.size;
end;



Э-э-э... Это наверное хорошая функция... Но мы такого модуля ещё не проходили)) Попробую поэкспериментировать, спасибо))

Автор: Natalia 21.12.2006 3:31

Цитата(volvo @ 20.12.2006 22:52) *

А что, в этом цикле где-то меняется значение T?
   while t<>3 do
writeln('Ввод данных-0; поиск-1; возврат в меню-3');


Ты наверное забыла весь цикл взять в Begin/End


Точно! Спасибо, а то не могла понять, почему получались лишние endы). Объясните ещё, пожалуйста, смысл ошибки: "0-выход за границы диапазона изменения индекса 1..50" blink.gif

Автор: мисс_граффити 21.12.2006 4:38

а почему у тебя вложенные циклы по одной переменной?
так нельзя

Автор: Natalia 21.12.2006 5:42

Цитата(мисс_граффити @ 21.12.2006 0:38) *

а почему у тебя вложенные циклы по одной переменной?
так нельзя

Пока не знаю, как сделать по-другому. И не могу уже думать... У меня так: пока не равно трём идёт цикл, в котором при t=0 - ввод данных, а при t=1 идёт поиск (поиск по двум критериям - фамилии и телефонам). Если же t=3, то переход должен быть в начало выбора: ввода или поиска. Знаю, что там напортачила, но пока не соображу, как переделать.

Автор: мисс_граффити 21.12.2006 14:28

Я в твоем форматировании запуталась.
они, оказывается, не вложенные, а независимые...
но что тогда значит это:

with b[i] do
begin
for i:=1 to n do
begin

Автор: volvo 21.12.2006 16:02

Цитата
Я в твоем форматировании запуталась.
smile.gif Кстати, есть очень хорошая утилита - для переформатирования текстов программ, написанных на Паскале, с соблюдением отступов (из комплекта FPC) - иногда просто незаменима, если код довольно большой и плохо форматированный (или вообще без отступов):

http://forum.pascal.net.ru/index.php?s=&showtopic=6186&view=findpost&p=46463

Автор: Bokul 22.12.2006 4:58

Цитата
Кстати, есть очень хорошая утилита - для переформатирования текстов программ, написанных на Паскале, с соблюдением отступов (из комплекта FPC) - иногда просто незаменима, если код довольно большой и плохо форматированный (или вообще без отступов):

И как с ней работать?

Автор: volvo 22.12.2006 5:01

Запустить из консоли не пробовал? Она показывает Хелп... Чтобы все сделать по умолчанию -

Цитата(Console)
PTOP myfile.pas myfile2.pas
где myfile.pas - название НЕформатированного файла...

Автор: Natalia 22.12.2006 11:06

Здравствуйте.
Вот новая редакция программы)) Всё, вроде, работает, только одного понять не могу, почему после того, как ввожу данные, в поиске программа их не находит? Подскажите, пожалуйста, что нужно сделать, чтобы программа не вылетала, а корректно просила ещё раз ввести данные, если, к примеру, вместо фамилии ввести телефон и т. п. И ещё: как всё-таки определить количество байт в файле, если тип данных файла неизвестен (Надо делать с модулем crt)? Просто не знаю, что и предположить...

program Telefonnaya_kniga;
uses crt;
type
book=record
first_name:string[20];
inis:string[5];
telrab1:shortInt;
telrab2:shortint;
teldom:shortint;
end;
Ffile=file of book; {файл для хранения базы}
var f:Ffile;
b:book;
t,k,tel:shortint;
n,i:integer;
s:string[20];
proverka:boolean;
label menu;
begin
assign(f,'tel_book.txt');
reset(f);
menu: writeln('Ввод данных-0; поиск-1; выход-2');
readln(t);
if t=2 then
begin
close(f);
halt;
end;
if t=0 then
begin
writeln('Ввод данных в телефонную книгу');
writeln('Сколько вводить фамилий?');
readln(n);
for i:=1 to n do
begin
with b do
begin
write('Фамилия: ');
readln(first_name);
write('Инициалы: ');
readln(inis);
writeln('Домашний телефон: ');
readln(teldom);
writeln('Рабочий телефон 1: ');
readln(telrab1);
writeln('Рабочий телефон 2: ');
readln(telrab2);
writeln;
n:=n-1;
end;
goto menu;
end;
end;
if t=1 then
begin
writeln('Поиск:');
writeln('по фамилии-0; по телефону-1; возврат в главное меню-2; выход-3');
readln(k);
if k=2 then goto menu;
if k=3 then halt;
if k=0 then
begin
writeln('Введите фамилию');
readln(s);
with b do
begin
proverka:=false;
while not(eof(f)) do
begin
if s=first_name then
begin
writeln(first_name,inis,teldom,telrab1,telrab2);
proverka:=true;
end;
end;
if eof(f) and proverka=false then writeln('Такой фамилии нет');
end;
goto menu;
end;
if k=1 then
begin
writeln('Введите телефон');
readln(tel);
proverka:=false;
with b do
begin
while not(eof(f)) do
begin
if tel=teldom then
begin
writeln(first_name,inis,teldom,telrab1,telrab2);
proverka:=true;
end;
if tel=telrab1 then
begin
writeln(first_name,inis,teldom,telrab1,telrab2);
proverka:=true;
end;
if tel=telrab2 then
begin
writeln(first_name,inis,teldom,telrab1,telrab2);
proverka:=true;
end;
end;
end;
if eof(f) and proverka=false then writeln('Такого телефона нет');
goto menu;
end;
end;
close(f);
readln;
end.




Автор: volvo 23.12.2006 5:00

Цитата
почему после того, как ввожу данные, в поиске программа их не находит?
Во-первых, ты ничего в файл не записываешь... Почему?

Во вторых - ты если пользуешься GoTo (я бы это не рекомендовал, конечно) то пользуйся им правильно:

if t=0 then begin
writeln('Ввод данных в телефонную книгу');
writeln('Сколько вводить фамилий?');
readln(n);
for i:=1 to n do begin
with b do begin
write('Фамилия: '); readln(first_name);
write('Инициалы: '); readln(inis);
writeln('Домашний телефон: '); readln(teldom);
writeln('Рабочий телефон 1: '); readln(telrab1);
writeln('Рабочий телефон 2: '); readln(telrab2);
writeln;
n:=n-1;
end;
goto menu; { <--- Ты ДОСРОЧНО выходишь из цикла }
end;
end;
, но этого не видишь из-за форматирования... Теперь понятно, почему всегда просят упорядочить исходники, перед выкладыванием на форум?

Автор: Natalia 23.12.2006 6:49

Цитата(volvo @ 23.12.2006 1:00) *

Во-первых, ты ничего в файл не записываешь... Почему?

Во вторых - ты если пользуешься GoTo (я бы это не рекомендовал, конечно) то пользуйся им правильно:

if t=0 then begin
writeln('Ввод данных в телефонную книгу');
writeln('Сколько вводить фамилий?');
readln(n);
for i:=1 to n do begin
with b do begin
write('Фамилия: '); readln(first_name);
write('Инициалы: '); readln(inis);
writeln('Домашний телефон: '); readln(teldom);
writeln('Рабочий телефон 1: '); readln(telrab1);
writeln('Рабочий телефон 2: '); readln(telrab2);
writeln;
n:=n-1;
end;
goto menu; { <--- Ты ДОСРОЧНО выходишь из цикла }
end;
end;
, но этого не видишь из-за форматирования... Теперь понятно, почему всегда просят упорядочить исходники, перед выкладыванием на форум?


Да, всё это я уже заметила и поправила, просто забыла внести поправку на форуме). Теперь другая проблема: прога не хочет преобразовывать тип string (first_name) в тип record. Пока не могу понять причину. Ведь вначале стоит with b... Пытаюсь исправить))