Помогите пожалуйста! Как исправить ошибку? Не могу понять, как её исправить, подскажите, очень-очень надо!.. Программа по работе с данными из таблицы. Данные хранятся в текстовом файле(прикреплён к сообщению, см ниже).
Код
program TABLIZA; uses crt; const p_menu:array [1..7] of string=('-Чтение данных из файла ', '-Просмотр входной таблицы', '-Добавление записей', '-Удаление записей ', '-Обработка и просмотр данных', '-Сохранение данных в файл', '-Выход ');
type vhod_t=record {входная таблица} number:byte; FIOdir:string[15]; FIOen:string[15]; plan:real; fact:real; end;
var file_in:file of vhod_t; {входной и выходной файлы} file_out:file of vyhod_t; NewL,nach,kon,vremen:ukaz; NewE,nach1:ukaz1; nomermenu, year:integer; vh_name, vyh_name:string[20]; vh_t:vhod_t; vyh_t,vyh_t1:vyhod_t;
procedure MENU(var nomermenu:integer); var x,y,i:integer; c:char; begin x:=28; y:=1; gotoXY(x,8); textcolor(13); writeln(' Выберите пункт меню: '); textcolor(3); for i:=1 to 7 do begin gotoXY(x,i+8); writeln(p_menu[i]); end; textcolor(4); gotoXY(x,y+8); writeln(p_menu[y]); while true do begin c:=readkey; case ord(c) of 80:if y<7 then y:=y+1; 72:if y>1 then y:=y-1; 13:break; end; gotoXY(x,8); textcolor(13); writeln(' Выберите пункт меню: '); textcolor(3); for i:=1 to 7 do begin gotoXY(x,i+8); writeln(p_menu[i]); end; textcolor(4); gotoXY(x,y+8); writeln(p_menu[y]); end; nomermenu:=y; textcolor(white); end;
procedure readfile(vh_name:string); begin writeln('Введите путь к входному файлу'); readln(vh_name);
assign(file_in,vh_name); reset(file_in); if IOResult>0 then begin writeln('Ошибка открытия файла'); exit; end; read(file_in,vh_t); {=================ЗДЕСЬ ВЫДАЁТСЯ ОШИБКА===============} New(NewL); NewL^.inf.number:=vh_t.number; NewL^.inf.FIOdir:=vh_t.FIOdir; NewL^.inf.FIOen:=vh_t.FIOen; NewL^.inf.plan:=vh_t.plan; NewL^.inf.fact:=vh_t.fact; NewL^.next:=nil; nach:=NewL; kon:=NewL; reset(file_in); read(file_in,vh_t); while not EOF(file_in) do begin read(file_in,vh_t); New(NewL); NewL^.inf.number:=vh_t.number; NewL^.inf.FIOdir:=vh_t.FIOdir; NewL^.inf.FIOen:=vh_t.FIOen; NewL^.inf.plan:=vh_t.plan; NewL^.inf.fact:=vh_t.fact; NewL^.next:=nil; kon^.next:=NewL; kon:=NewL; end; end;
procedure prosmotr_vhod(nach:ukaz); var x,y,i,n,t:integer; c:char; begin writeln('Просмотр таблицы':70); x:=1;y:=1; {gotoxy(x,y);} writeln('|--------|---------------|---------------|--------------|-----------|'); writeln('| Номер | ФИО директора | ФИО главного | израсходовано| фактически|'); writeln('| | | энергетика | тыс КВт*ч | тыс КВт*ч |'); n:=0; vremen:=nach; while vremen<>nil do begin
while true do begin c:=readkey; t:=ord(c); if t= 13 then break;
if t=8 then begin Delline; delline;end; if t= 72 then begin if y>1 then y:=y-2; gotoxy(x,y); if (y=1) then vremen:=nach^.next; while vremen<>nil do begin
end; if t=80 then begin if y<n then y:=y+2; gotoxy(x,y);
end;
end;
end;
procedure dobavlenie( var kon:ukaz;var nach:ukaz); begin writeln('Введите номер завода'); readln(vh_t.number); writeln('Введите ФИО директора'); readln(vh_t.FIOdir); writeln('Введите ФИО главного энергетика'); readln(vh_t.FIOen); writeln('Израсходовано энергии по плану'); readln(vh_t.plan); writeln('Израсходовано энергии фактически'); readln(vh_t.fact); New(NewL); NewL^.inf.number:=vh_t.number; NewL^.inf.FIOdir:=vh_t.FIOdir; NewL^.inf.FIOen:=vh_t.FIOen; NewL^.inf.plan:=vh_t.plan; NewL^.inf.fact:=vh_t.fact; NewL^.next:=nil; if kon=nil then nach:=NewL else kon^.next:=NewL; kon:=NewL; write(file_in,vh_t); end;
procedure udalenie; {удаление из начала списка} var temp:ukaz; begin if nach<>nil then begin temp:=nach; nach:=nach^.next; dispose(temp); if nach=nil then kon:=nil; end; end;
procedure obrabotka_prosmotr; var sump,sumf,sumo:real; sred:real; kon:ukaz1; begin sump:=0; sumf:=0; sumo:=0; nach1:=nil; kon:=nil; seek(file_in,0); writeln('Отклонение факта от плана (со знаком)'); writeln('|--------|---------------|---------------|--------------|-----------|-----------|'); writeln('| Номер | ФИО директора | ФИО главного | израсходовано| фактически| отклонение|'); writeln('| | | энергетика | тыс КВт*ч | тыс КВт*ч | тыс КВт*ч |');
while not EOF(file_in) do begin read(file_in,vh_t); if((vh_t.plan>0)and(vh_t.fact>0)) then begin New(NewE); NewE^.inf.number:=vh_t.number; vyh_t1.number:=NewE^.inf.number; NewE^.inf.FIOdir:=vh_t.FIOdir; vyh_t1.FIOdir:=NewE^.inf.FIOdir; NewE^.inf.FIOen:=vh_t.FIOen; vyh_t1.FIOen:=NewE^.inf.FIOen; NewE^.inf.plan:=vh_t.plan; vyh_t1.plan:=NewE^.inf.plan; NewE^.inf.fact:=vh_t.fact; vyh_t1.fact:=NewE^.inf.fact; writeln('|--------|---------------|---------------|--------------|-----------|-----------|'); writeln('|',NewE^.inf.number:6,'|',NewE^.inf.FIOdir:15,'|',NewE^.inf.FIOen:15,'|', NewE^.inf.plan:4,'|',NewE^.inf.fact:4,'|',NewE^.inf.otklon:5,'|');
kon:=NewE; NewE^.next:=nil;
while kon<>nil do begin kon^.inf.otklon:=kon^.inf.plan-kon^.inf.fact; kon:=kon^.next; sump:=sump+kon^.inf.plan; sumf:=sumf+kon^.inf.fact; sumo:=sumo+kon^.inf.otklon end;
writeln('|--------|---------------|---------------|--------------|-----------|-----------|'); writeln('|',NewE^.inf.number:6,'|',NewE^.inf.FIOdir:15,'|',NewE^.inf.FIOen:15,'|', NewE^.inf.plan:4,'|',NewE^.inf.fact:4,'|',NewE^.inf.otklon:5,'|'); end; end; writeln('|--------|---------------|---------------|--------------|-----------|-----------|'); if (sump<=0) or (sumf<=0) then begin writeln('введены неверные значения');readln;exit;
procedure save_file(var vyh_t1,vyh_t:vyhod_t); begin assign(file_out,'d:\vyhodtable.txt'); rewrite (file_out); write(file_out,vyh_t1); write(file_out,vyh_t); end;
begin nach:=nil; kon:=nil; while true do begin clrscr; menu(nomermenu); case nomermenu of 1:begin clrscr;readfile(vh_name); end; 2: begin clrscr; prosmotr_vhod(nach); end; 3: begin clrscr; dobavlenie(kon,nach);end; 4:begin clrscr;udalenie;end; 5:begin clrscr;obrabotka_prosmotr;end; 6:begin clrscr;save_file(vyh_t1,vyh_t);end; 7:break; end; end; end.
Зайди попозже, завтра.. обещаю посмотреть немного пугает взгляд.. извини, размер тоже иногда важен, сама понимаешь...
Автор: volvo 2.12.2006 9:40
Цитата
Как исправить ошибку?
Ты же описываешь входной файл, как file of vhod_t, а читать пытаешься из текстового... То, что там содержится вся нужная информафия еще ничего не значит... Формат не тот...
Вот смотри: размер структуры vhod_t = 43 байта, размер файла = 926 байт, 926 на 43 НАЦЕЛО не делится, а ведь read(file_in,vh_t); будет пытаться читать данные блоками по 43 байта из файла целое число раз, при нехватке данных программа просто вылетит и все
Выходов у тебя два: первый - работать с текстовым, а не типизированным файлом, второй - при старте программы (или где нибудь в меню сделать соответствующий пункт) вызывать процедуру корректировки, которая будет читать данные из текстового файла и записывать в типизированный...
Кстати, у тебя есть 2 неточности (которые могут быть проблематичны, если не сейчас, то потом):
1) byte хранит значения 0 - 255, а у тебя в файле присутствуют бОльшие значения... 2) при записи вещественных чисел используется не запятая, а точка...
Автор: IchLiebeDich 2.12.2006 9:53
Цитата
при старте программы (или где нибудь в меню сделать соответствующий пункт) вызывать процедуру корректировки, которая будет читать данные из текстового файла и записывать в типизированный...
а как это сделать?
Автор: Ozzя 2.12.2006 11:23
Цитата(IchLiebeDich @ 2.12.2006 6:53)
а как это сделать?
Определить текстовый файл: var file_in_text:text; Читать из него построчно: Realdn(file_in_text,s); Разбить полученную строку на части ф-цией http://forum.pascal.net.ru/index.php?showtopic=2361# присвоить полям записи - полученные ф-цией значения
Автор: lapp 2.12.2006 12:04
Цитата(IchLiebeDich @ 2.12.2006 6:53)
а как это сделать?
Думаю, volvo на этот раз пошутил.. . Нет смысла делать такую процедуру и писать на диск дополнительный файл (для которого, при нормальных рабочих размерах нормальной рабочей базы может и не хватить места ). И к тому же та процедура все равно будет делать именно то, что тебе надо в основном коде - так почему бы не вставить этот код прямо туда?.. При желании можно иметь возможность записывать (и читать) два типа файлов: текстовой и типизированный. Преимуществ одного перед другим я не вижу, кроме возможности редактировать текст в другом обычном редакторе (типа Ноутпада). При записи чисел типизированный файл как правило выигрывает по размеру (не всегда), но если основное содержание текстовое (как тут), то будет скорее наоброт.. Так что я просто рекомендую тебе полностью переключиться на текст (если это разрешается условиями задачи).
если ты со всем этим согласна, читай дальше - описываю, как это сделать. volvo прав, кое-что придется немного подкорректировать. Во-первых, какой смысл иметь разный формат на вход и выход?? Непременно возникнут противоречия при чтении файлов, созданных одной и той же программой. У тебя же не конвертер, скажем, из jpeg в mp3 (типа шутка ). Короче,
1. Выбери либо тип vhod_t, либо vyhod_t, а другой тип убери совсем (то есть заменить на выбранный тип). Я думаю, это должен быть vhod_t, так как нет смысла хранить в файле отклонение - его же можно легко посчитать!
Но в типе vhod_t, как уже заметил volvo, поле number описано как byte, чего явно недостаточно при тех номерах, что фигурируют в файле. Вывод:
2. Поле number сделать integer'ом (если и этого недостаточно, то есть бывают номера больше примерно 32000, то LongInt).
Далее, как тоже говорил volvo, в программировании принята американская нотация дейсьвительных чисел, то есть вместо запятой используется точка. Значит нужно:
3. Пройтись по всему файлу данных автозаменой: "," -> ".". Это можно сделать в любом редакторе, типа в Ноутпаде..
Идем дальше. Размещение двух фамилий в одной строке означает, что надо разделять входную информацию на слова. Это некое дополнительное действие, но дело не в том, что нам лень. Дело в том, что такая ситуация может сбить программу с толку, если кому-то вместо просто фамилии захочется ввести имя-отчество или фамилию с именем - тогда пробел между именем и фамилией будет истолкован неверно. Тогда либо нужно запретить ввод в поле фамилии нескольких слов (и следить за этим), либо ввести для разделения фамилий специальный символ и соответствующим образом делить входную строку на две. Я предлагаю поступить по второму методу, и при этом в качестве признака конца фамилии использовать конец строки . Это дает явные преимущества: а. файл легче читается; б. для ввода можно использовать процедуру ReadLn. Таким образом:
4. Размести в файле каждую фамилию на отдельной строке.
Теперь касательно самого чтения. Здесь вообще каша.. Зачем ты читаешь сначала в переменную vh_t, а потом перекладываешь в список, да еще по полям?? Мало того, что можно просто переложить в одной строчке так: NewL^.inf:=vh_t; - но еще можно и сразу читать в переменную NewL^.inf ! И более того, ты забываешь про существование оператора with, который явно упрощает картину.. Допустим теперь, что ты согласна со мной и читаешь сразу в нужную переменную. Тогда это будет выглядеть так:
5. Оператор
with NewL^.inf do begin ReadLn(number); ReadLn(FIOdir); ReadLn(FIOen); ReadLn(plan,fact) end;
При этом, если ты читаешь несколько раз в разных местах (хотя я, убей Бог, не понимаю, зачем), то этот блок операторов можно засунуть в процедуру.. Тут же примерно: зачем ты ресетишь файл вторично и снова проматываешь одну запись?..
Ну и последнее (пока ). Поскольку мы теперь считаем файл текстовым, то
7. Заменить описания файлов на:
file_in:text; file_out:text;
Увы, это не самое последнее... Дальше нужно заменить оператор записи на аналогичную (как в п.5) последовательность (но с заменой Write на Read, а также вставь пробел между plan и fact:
8. Вот так:
with NewL^.inf do begin WriteLn(number); WriteLn(FIOdir); WriteLn(FIOen); WriteLn(plan,' ',fact) end;
Дальше я не понял - зачем ты читаешь файл повторно в процедуре obrabotka_prosmotr? Странно это выглядит.. Короче, это надо либо просто убрать, либо заменить чтение по описанной выше схеме..
Уфф.. Нет, размер явно имеет значение... Мне кажется, тебе достаточно для первого раза..
Автор: IchLiebeDich 2.12.2006 13:43
спасибо, сейчас попробую чё-нить сделать! Вот у меня тоько один вопрос, а как расчитать значения для поля отклонение? ведь файл текстовый.
Автор: Ozzя 2.12.2006 14:31
Цитата(IchLiebeDich @ 2.12.2006 10:43)
спасибо, сейчас попробую чё-нить сделать! Вот у меня тоько один вопрос, а как расчитать значения для поля отклонение? ведь файл текстовый.
val
Автор: IchLiebeDich 3.12.2006 19:02
Цитата(Ozzя @ 2.12.2006 9:31)
val
Эт чё значит?
Автор: Archon 3.12.2006 19:38
Цитата
Вот у меня тоько один вопрос, а как расчитать значения для поля отклонение? ведь файл текстовый.
А что за отклонение? Наверное, также, как и раньше. Ведь в текстовом файле можно хранить не только строки, но и числа.
Автор: IchLiebeDich 3.12.2006 19:55
Цитата(Archon @ 3.12.2006 14:38)
А что за отклонение?
отклонение - имя поля, куда записываются разности значений полей plan и fact.
В текстовом файле хранятся литеры...
Автор: Archon 3.12.2006 20:05
Не понимаю, в чём проблема? Считываешь plan и fact и считаешь разность.
Автор: IchLiebeDich 10.12.2006 16:35
Цитата(Archon @ 3.12.2006 15:05)
Не понимаю, в чём проблема? Считываешь plan и fact и считаешь разность.
в том-то и проблема, что оно не считывается...
Автор: Lapp 11.12.2006 15:10
Цитата(IchLiebeDich @ 10.12.2006 13:35)
в том-то и проблема, что оно не считывается...
Давай-ка поподробнее.. Покажи свой текущий вариант программы, покажи файл данных.. Скажи, какая именно ошибка возникает. Пойми, что мы не телепаты. O'kay?