hhaf -8 / 0 / 0 Регистрация: 02.06.2017 Сообщений: 50 |
||||
1 |
||||
03.07.2017, 14:22. Показов 4230. Ответов 2 Метки нет (Все метки)
0 |
Puporev Почетный модератор 64289 / 47588 / 32739 Регистрация: 18.05.2008 Сообщений: 115,181 |
||||
03.07.2017, 14:28 |
2 |
|||
Нафига file of char?
0 |
129 / 127 / 107 Регистрация: 09.01.2017 Сообщений: 1,651 |
|
03.07.2017, 14:29 |
3 |
А если уж нужен бинарный файл,то тогда только write
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
03.07.2017, 14:29 |
3 |
hhaf -8 / 0 / 0 Регистрация: 02.06.2017 Сообщений: 50 |
||||
1 |
||||
03.07.2017, 14:22. Показов 3859. Ответов 2 Метки нет (Все метки)
__________________ 0 |
Puporev Почетный модератор 64270 / 47569 / 32739 Регистрация: 18.05.2008 Сообщений: 115,182 |
||||
03.07.2017, 14:28 |
2 |
|||
Нафига file of char?
0 |
128 / 126 / 107 Регистрация: 09.01.2017 Сообщений: 1,651 |
|
03.07.2017, 14:29 |
3 |
А если уж нужен бинарный файл,то тогда только write 0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
03.07.2017, 14:29 |
3 |
Topic: Error: Can’t use readln or writeln on typed file (Read 6639 times)
Why have i next error: Error: Can’t use readln or writeln on typed file
program PERSONEELGEGEVENS_SAVE;
{$mode objfpc}
type personeel=record
nr:integer;
naam, adres, postcode, plaats:String;
wedde:Integer;
end;
Var F:File of personeel;
Var persoon: personeel;
Var B_NAAM: String;
begin
writeln('Welkom in programma *Personeelgegevens*!');
writeln();
writeln('Geef de bestandsnaam in:');
readln(B_NAAM);
Assign(F, B_NAAM);
Rewrite(F);
writeln();
writeln('Geef de personeelsnummer in (0 => stoppen):');
readln(PERSOON.NR);
while (PERSOON.NR <> 0) do
begin
writeln('Naam:');
readln(PERSOON.NAAM);
writeln('Aders:');
//
readln(PERSOON.ADRES);
writeln('Postcode:');
//
readln(PERSOON.POSTCODE);
writeln('Plaats');
//
readln(PERSOON.PLAATS);
writeln('Wedde');
//
readln(PERSOON.WEDDE);
//
writeln(F, PERSOON);
writeln('Geef de personeelsnummer in (0 => stoppen):');
readln(PERSOON.NR);
end;
//
Close(F);
writeln();
writeln('Druk op <ENTER> om programma te verlaten');
readln();
end.
Logged
You can only use readln and writeln on text files.
Use Read and Write instead.
Logged
All posts based on: Win10 (Win64); Lazarus 2.0.10 ‘stable’ (x64) unless specified otherwise…
Yes, it’s true. I’ve changed
writeln(F, PERSOON);
to
write(F, PERSOON);
and this code works perfect. Thank you.
Logged
Во-первых, ваш код работает. Ошибка возможна потому, что не находит файл или он занять другим процессом.
Во — вторых, раз это PascalABC.Net, то почему бы не писать в его стиле
const
filename = 'dat.txt';
var
f: Text; // Файловая переменная.
i: integer; // Переменная для хранения значения количества подсчитываемых элементов.
a: real; // Промежуточная переменная для хранения значения читаемых элементов.
sum: real;// переменная для хранения значения произведения.
begin
// Rewrite(f, filename);
// f.Writeln(2);
// f.Writeln(7);
// f.Close();
f := OpenRead(filename);
i := 0; // Установка счетной переменной в нулевое состояние.
sum := 0;
while not f.Eof do // Цикл для поэлементного чтения из файла.
begin
a := f.ReadlnReal(); // Чтение информации из файла.
write(a:8:2);
sum := sum + a;
inc(i);
end;
f.Close();
writeln;
writeln('The number of extracted numbers from the file is: ', i);
writeln('Summa numbers from a file is equal to: ', sum:0:2);
readln;
end.
В программе работает все, кроме удаления записи из файла
Собственно сама ошибка:
строка (254) : Ошибка времени выполнения: Входная строка имела неверный формат.
В строке 254 находится (readln(menu);)
program Telophonia;
type
abonent = record
number: string[10]; //Номер телефона
FIO: string[40]; //ФИО абонента
adres: record //Адрес абонента в виде другой записи состоящий из:
street: string[20]; //Улица
house: string[20]; //Дом
flat: string[20]; //Квартира
end;
date: string[10]; //Дата подключения абонента
end;
var
abonents: file of abonent; //Файл содержащий записи об абонентах
x, t: abonent; //Вспомогательная переменная типа записи об абонентах
menu, ind, cnt: integer; //Вспомогательные переменные для меню, индексации и счетчика записей в некоторых процедурах
yn: char; //Переменная y/n ответов
filename: string[25]; //Имя файла, задаваемое пользователем
nmbr: string[10]; //Вспомогательная переменная для номера абонента
//Процедура вывода содержимого файла на экран
procedure show(a: file of abonent);
begin
reset(a);
ind := 1; //номер строки в выводимой таблице
while not eof(a) do
begin
read(a, x); //чтение записи из файла
write(ind, ': '); //номер строки в выводимой таблице
ind := ind + 1;
with x do
//вывод считаной записи на экран
writeln(number, ' ', FIO, ' ', adres.street, ' ', adres.house, ' ', adres.flat, ' ', date);
end;
if FileSize(a) = 0 then write('Файл пуст. Пожалуйста добавьте записи!');
writeln;
close(a);
end;
//Процедура добавления новой записи в конец файла
procedure add(a: file of abonent);
label nachalo;//метка начала процедуры
begin
nachalo: //метка начала процедуры
with x do
begin
repeat //просматривать файл на совпадение номера абонента
write('Номер = ');
readln(number);
reset(a);
while not eof(a) do
begin
read(a, t); //чтение записи из файла
if t.number = number then
begin
writeln('Абонент с таким номером уже существует!');
break; //выходим из цикла while и повторяем сначала
end;
end;
until t.number <> number;
write('ФИО = ');
readln(FIO);
write('Улица = ');
readln(adres.street);
write('Дом = ');
readln(adres.house);
write('Квартира = ');
readln(adres.flat);
write('Дата подключения = ');
readln(date);
writeln;
end;
reset(a);
seek(a, FileSize(a)); //перевод указателя в конец файла
write(a, x); //запись переменной в файл
writeln('Абонент успешно добавлен.');
writeln;
writeln('Добавить еще одного? (y/n):');
readln(yn);
if yn = 'y' then goto nachalo;
close(a);
end;
//Процедура удаления записи из файла
procedure del(a: file of abonent);
label nachalo,ex;//метка начала и конца процедуры
begin
nachalo: //метка начала процедуры
reset(a);
write('Введите номер:');
read(nmbr);
cnt := 0; //ведем счет записей из файла, чтобы в дальнейшем обратиться к нужной считанной записи и удалить ее
repeat //просматривать файл на совпадение номера абонента
if eof(a) then //если дошли до конца и не нашли нужного абонента
begin
writeln('Абонента с таким номером не существует!');
write('Найти по другому номеру? (y/n):');
readln(yn);
if yn = 'y' then goto nachalo else goto ex;
end;
read(a, t); //чтение записи из файла
cnt := cnt + 1; //увеличиваем счетчик записей на один
until t.number = nmbr;
writeln('Найденный абонент:');
writeln(t.number, ' ', t.FIO, ' ', t.adres.street, ' ', t.adres.house, ' ', t.adres.flat, ' ', t.date);
writeln;
writeln('Удалить данные об абоненте? (y/n):');
readln(yn);
if yn <> 'y' then goto ex;
cnt := cnt - 1;
while not eof(a) do
begin
if filesize(a)=cnt+1 then break;
seek(a, cnt+1); //перевод указателя на следующий элемент
read(a, t);
seek(a, cnt); //перевод указателя на удаляемого абонента
write(a, t); //перезапись следующего абонента из файла на место удаляемого
cnt := cnt + 1;
seek(a, cnt); //перевод указателя на следующую за переписанным абонентом
end;
seek(a, filesize(a) - 1); //перевод указателя на последнюю запись в файле
truncate(a); //удаление последней записи в файле
writeln('Данные удалены');
write('Найти по другому номеру? (y/n):');
readln(yn);
if yn = 'y' then goto nachalo;
ex: //метка выхода из процедуры
close(a);
end;
//Процедура корректировки записи в файле
procedure edit(a: file of abonent);
label nachalo,ex;//метки начала процедуры и выхода из нее
begin
reset(a);
nachalo: //метка начала процедуры
write('Введите номер абонента:');
read(nmbr);
cnt := 0; //ведем счет записей из файла, чтобы в дальнейшем обратиться к нужной считанной записи и перезаписать ее
yn:='n';
while not eof(a) do
begin
read(a, t); //чтение записи из файла
cnt := cnt + 1; //увеличиваем счетчик записей на один
if t.number = nmbr then break;
end;
if eof(a) then //если дошли до конца и не нашли нужного абонента
begin
writeln('Абонента с таким номером не существует!');
write('Найти по другому номеру? (y/n):');
readln(yn);
if yn = 'y' then goto nachalo else goto ex;
end;
cnt := cnt - 1; //возвращаемся к предыдущей записи, чтобы ее изменить
writeln('Изменить данные об абоненте? (y/n):');
readln(yn);
if yn <> 'y' then goto ex;
with x do
begin
repeat //просматривать файл на совпадение номера абонента
write('Номер абонента = ');
readln(number);
reset(a);
while not eof(a) do
begin
read(a, t); //чтение записи из файла
if t.number = number then
begin
writeln('Абонент с таким номером уже существует!');
break; //выходим из цикла while и повторяем сначала
end;
end;
until t.number <> number;
write('ФИО = ');
readln(FIO);
write('Улица = ');
readln(adres.street);
write('Дом = ');
readln(adres.house);
write('Квартира = ');
readln(adres.flat);
write('Дата подключения = ');
readln(date);
writeln;
end;
writeln('Изменить данные об абоненте? (y/n):');
readln(yn);
if yn <> 'y' then goto ex;
seek(a, cnt);
write(a, x); //запись переменной в файл
writeln('Изменения приняты.');
WriteLn;
writeln('Найти по другому номеру? (y/n):');
readln(yn);
if yn = 'y' then goto nachalo;
ex: //метка выхода из процедуры
close(a);
end;
//Процедура вывода содержимого файла на экран
procedure find(a: file of abonent);
label nachalo;
begin
nachalo:
with x do
begin
write('Номер абонента = ');
readln(number);
reset(a);
cnt := 0; //ведем счет удовлетворяющих запросу записей
while not eof(a) do
begin
read(a, t); //чтение записи из файла
if t.number = number then
begin
writeln('Найдено:');
writeln(number, ' ', FIO, ' ', adres.street, ' ', adres.house, ' ', adres.flat, ' ', date);
cnt := cnt + 1;
break;
end;
end;
end;
if cnt=0 then writeln('Не найдено абонента с таким номером.');
writeln;
writeln('Найти по другому номеру? (y/n):');
readln(yn);
if yn = 'y' then goto nachalo;
close(a);
end;
begin
write('Введите имя файла: ');
readln(filename);
assign(abonents, filename);
repeat
writeln('1: Вывести содержимое');
writeln('2: Добавить абонента');
writeln('3: Удалить абонента');
writeln('4: Изменить данные абонента');
writeln('5: Найти по номеру');
writeln('0: Выход');
write('Выберите действие: ');
readln(menu);
writeln;
case menu of
1: show(abonents);
2: add(abonents);
3: del(abonents);
4: edit(abonents);
5: find(abonents);
end;
until menu = 0;
end.
Основы программирования Каждый профессионал когда-то был чайником. Наверняка вам знакомо состояние, когда “не знаешь как начать думать, чтобы до такого додуматься”. Наверняка вы сталкивались с ситуацией, когда вы просто не знаете, с чего начать. Эта книга ориентирована как раз на таких людей, кто хотел бы стать программистом, но совершенно не знает, как начать этот путь. Подробнее… |
Раздел: Стандартные функции Паскаля
Процедуры Write и WriteLn выполняют вывод информации в устройство стандартного вывода. В консольных приложениях этим устройством может быть консоль (то есть экран), в графических приложениях — файл на диске.
Эти процедуры выполняют одно и то же действие. Отличие между ними только одно:
процедура WriteLn после завершения вывода выполняет перевод
строки. А процедура Write записывает данные подряд — без перевода строки.
Синтаксис для вывода на консоль:
procedure Write(Args : Arguments);
Синтаксис для вывода в файл:
procedure Write(var F: Text; Args : Arguments);
Аргументами (Arguments) могут быть переменные разных
типов.
Если используется несколько переменных, то они перечисляются через запятую. Например:
var x, y, z : integer; str : string; begin x := 1; y := 2; z := 3; str := ' - Numbers'; Write(x, y, z, str); ReadLn; end.
Причём, как уже было сказано, при выводе на консоль эти переменные могут быть разных типов. Также можно использовать и константы:
Write('Numbers - ', x, y, z, 100);
Если требуется перевод строки, то лучше использовать функцию WriteLn вместо Write:
WriteLn(x, y, z, str); //Выводим данные и переводим строку Write('Numbers - ', x, y, z); //Это будет уже в новой строке
Но можно использовать, например, символы перевода строки в конце списка аргументов:
Write('Numbers - ', x, y, #10#13); //Этот код тоже выполнит //перевод строки Write('Numbers - ', x, y, z); //Это тоже будет уже //в новой строке
При записи в файл можно работать как с типизированными файлами, так и с текстовыми файлами.
Если F (см. синтаксис) — это типизированный файл, то переменные,
передаваемые как параметры (Args) должны иметь такой же тип, какой указан
для файла F. Нетипизированные файлы использовать не допускается.
Если параметр F не указан, то предполагается, что вывод
выполняется на стандартное устройство (экран-консоль).
Если файл F имеет тип Text, то все необходимые
преобразования будут выполнены таким образом, что выходная переменная будет
в удобочитаемом формате. Это преобразование выполняется для всех числовых типов.
Строки и типы PChar выводятся точно так, как они находятся в памяти.
При выводе на консоль целые
числовые значения выводятся в обычном числовом формате. А вещественные числовые значения по умолчанию выводятся в научной нотации.
Чтобы выводить целые числа в поля фиксированной ширины или вещественные числа с
фиксированным количеством знаков после запятой, используется специальный формат
вывода. Но об этом в данной статье я говорить не буду, так как уже рассказывал
об этом здесь.
Если во время выполнения процедуры Write/WriteLn происходит
ошибка, то генерируется ошибка времени выполнения. Такое поведение не всегда
приемлемо (например, во время чтения/записи файла). Поэтому в каких-то случаях
генерацию ошибок отключают. Сделать это можно с помощью
директивы компилятора {$I}.
|
Как стать программистом 2.0
Эта книга для тех, кто хочет стать программистом. На самом деле хочет, а не просто мечтает. И хочет именно стать программистом с большой буквы, а не просто научиться кулебякать какие-то примитивные программки… |
|
Помощь в технических вопросах
Помощь студентам. Курсовые, дипломы, чертежи (КОМПАС), задачи по программированию: Pascal/Delphi/Lazarus; С/С++; Ассемблер; языки программирования ПЛК; JavaScript; VBScript; Fortran; Python и др. Разработка (доработка) ПО ПЛК (предпочтение — ОВЕН, CoDeSys 2 и 3), а также программирование панелей оператора, программируемых реле и других приборов систем автоматизации. |
Я не могу найти источник этой ошибки, которую постоянно получаю в школьном кодировании. Каждый раз, когда я ввожу одно значение в свой массив и запускается цикл for, он либо обнаруживает ошибку времени выполнения, либо остальная часть программы запускается на основе информации из первого значения и не принимает никаких других значений. Может кто-нибудь объяснить мне, как это исправить?
program Montserrat_Elections; Var cndnme : array [1..4] of String; votes : array [1..4] of Integer; highest, cnt : Integer; winner : string; begin highest:= 0; winner:= 'Dan'; For cnt:= 1 to 4 do begin Writeln('Please enter the first name of the candidate and the number of votes'); Read (cndnme[cnt], votes[cnt]); If votes[cnt] > highest then highest := votes[cnt]; winner := cndnme[cnt]; end; Writeln('The winner of this constituency is', winner, 'with', highest, 'votes') end.
1 ответ
Лучший ответ
Измените Чтение на Чтение :
Readln (cndnme[cnt], votes[cnt]);
Затем вам нужно добавить begin … end; к этой строке:
If votes[cnt] > highest then
begin
highest := votes[cnt];
winner := cndnme[cnt];
end;
Я обновляю и тестирую ваши коды:
program Montserrat_Elections;
Var cndnme : array [1..4] of String;
votes : array [1..4] of Integer;
highest, cnt : Integer;
winner : string;
begin
highest:= 0;
winner:= 'Dan';
For cnt:= 1 to 4 do
begin
Writeln('Please enter the first name of the candidate and the number of votes');
readln(cndnme[cnt], votes[cnt]);
If votes[cnt] > highest then
begin
highest := votes[cnt];
winner := cndnme[cnt];
end;
end;
Writeln('The winner of this constituency is ', winner, ' with ', highest, ' votes');
readln;
end.
Результат:
Please enter the first name of the candidate and the number of votes
Me
23
Please enter the first name of the candidate and the number of votes
You
42
Please enter the first name of the candidate and the number of votes
Ainun
18
Please enter the first name of the candidate and the number of votes
Jhon
38
The winner of this constituency is You with 42 votes
1
Metris Sovian
27 Янв 2017 в 06:42
Полезно ли:
14 голосов , оценка 4.214 из 5
Во-первых, ваш код работает. Ошибка возможна потому, что не находит файл или он занять другим процессом.
Во — вторых, раз это PascalABC.Net, то почему бы не писать в его стиле
const
filename = 'dat.txt';
var
f: Text; // Файловая переменная.
i: integer; // Переменная для хранения значения количества подсчитываемых элементов.
a: real; // Промежуточная переменная для хранения значения читаемых элементов.
sum: real;// переменная для хранения значения произведения.
begin
// Rewrite(f, filename);
// f.Writeln(2);
// f.Writeln(7);
// f.Close();
f := OpenRead(filename);
i := 0; // Установка счетной переменной в нулевое состояние.
sum := 0;
while not f.Eof do // Цикл для поэлементного чтения из файла.
begin
a := f.ReadlnReal(); // Чтение информации из файла.
write(a:8:2);
sum := sum + a;
inc(i);
end;
f.Close();
writeln;
writeln('The number of extracted numbers from the file is: ', i);
writeln('Summa numbers from a file is equal to: ', sum:0:2);
readln;
end.
│
العربية (ar) │
English (en) │
español (es) │
suomi (fi) │
français (fr) │
日本語 (ja) │
русский (ru) │
中文(中国大陆) (zh_CN) │
中文(台灣) (zh_TW) │
Введение
Каждый программист должен знать, как работать с файлами. Файлы используются для сохранения данных, т. е. в качестве хранилища данных, таким образом, что они могут быть получены в любой момент, без их воссоздания. Файлы можно использовать для сохранения пользовательских настроек, журналов ошибок, измерение или вычисление результатов, и многое другое. В данном разделе описываются основы использования файлов.
Процедурный стиль
Это довольно старый стиль, использующейся ещё во времена, когда Pascal не был объектно-ориентированным языком. Суть его в том, что задается тип файла, определяющий, какие будут храниться в нем данные. Для этого, используется конструкция вида: file of <тип данных>, где <тип данных> — название типа, который хранит в себе файл. Помимо стандартных типов (integer, extended, char и т.д.), существует особый тип — TextFile. Он определят, что каждая строка заканчивается специальным(ми) символом(ами) конца строки (См. LineEnding). Эти файлы могут быть открыты и отредактированы внутри среды Lazarus или в любом другом текстовом редакторе.
Ниже представлены примеры создания собственных типов файлов:
... type TIntegerFile = file of integer; // Позволяет писать только целые числа в файл TExtendedFile = file of extended; // Позволяет писать только дробные цифры в файл TCharFile = file of char; // Позволяет писать только одиночные символы в файл
Обработка ошибок ввода/вывода
Параметр компилятора обработки ошибок ввода/вывода указывает, как должна вести себя программа при возникновении ошибки в процессе работы с файлами: вызвать исключение или хранить результат операции ввода/вывода в специальной переменной IOResult.
Это задаётся с помощью специальной директивы компилятора:
{$I+} // В случаи ошибки будет вызвано исключение EInOutError (по умолчанию) {$I-} // Подавлять ошибки ввода-вывода: проверьте переменную IOResult для получения кода ошибки.
В случаи подавления ошибок ввода-вывода ({$I-}) результат операции с файлом будет храниться в переменной IOResult типа cardinal (числовой тип). Каждое число, хранимое в IOResult определяет тип возникшей ошибки(подробнее: [1]).
Процедуры работы с файлами
Эти процедуры и функции находятся в модуле system. Для более подробной информации смотрите документацию FPC:
ссылка на модуль 'System'.
- AssignFile (не допускайте использование процедуры Assign) — Связывает переменную с файлом
- Append — Открывает существующий файл для записи данных в конец и их редактирования
- BlockRead — Чтение данных из не типизированного файла в память
- BlockWrite — Запись данных из памяти в не типизированный файл
- CloseFile (не допускайте использование процедуры Close) — Закрыть открытый файл
- EOF — Проверка наличия конца файла
- Erase — Стереть файл с диска
- FilePos — Получить позицию в файле
- FileSize — Получить размер файла
- Flush — Записать файловый буфер на диск
- IOResult — Возвращает результат последней операции вводавывода
- Read — Считать из текстового файла
- ReadLn — Считать из текстового файла и перейти к следующей строке
- Reset — Открыть файл для чтения
- Rewrite — Создать и открыть файл для записи
- Seek — Изменить позицию в файле
- SeekEOF — Переместить позицию в файле в его конец
- SeekEOLn — Переместить позицию в файле в конец строки
- Truncate — Удалить все данные, после текущей позиции
- Write — Записать переменную в файл
- WriteLn — Записать переменную в текстовый файл и перейти к новой строке
Пример
Пример работы с текстовым файлом (тип TextFile):
program CreateFile; uses Sysutils; const C_FNAME = 'textfile.txt'; var tfOut: TextFile; begin // Связываем имя файла с переменной AssignFile(tfOut, C_FNAME); // Использовать исключение для перехвата ошибок (это по умолчанию и указывать не обязательно) {$I+} // Для обработки исключений, используем блок try/except try // Создать файл, записать текст и закрыть его. rewrite(tfOut); writeln(tfOut, 'Пример текстового файла!'); writeln(tfOut, 'Пример записи числа: ', 42); CloseFile(tfOut); except // Если ошибка - отобразить её on E: EInOutError do writeln('Ошибка обработки файла. Детали: ', E.ClassName, '/', E.Message); end; // Выводим результат операции и ожидаем нажатие Enter writeln('Файл ', C_FNAME, ' создан. Нажмите ВВОД для выхода.'); readln; end.
Теперь откройте файл в любом текстовом редакторе и вы увидите, что пример текста, записан в нем!
Вы можете проверить работу обработки ошибок, установив атрибут файла «только для чтения» и снова запустив программу.
Обратите внимание, что в примере используется блок try/except. Данный способ позволяет выполнять несколько операций с файлами и использовать обработку исключений.
Вы также можете использовать режим {$I-}, но тогда вам придется проверять переменную IOResult после каждой операции с файлами для контроля ошибок.
Ниже приведен пример записи текста в конец файла:
program AppendToFile; uses Sysutils; const C_FNAME = 'textfile.txt'; var tfOut: TextFile; begin // Связываем имя файла с переменной AssignFile(tfOut, C_FNAME); // Для обработки исключений, используем блок try/except try // Открыть файл для записи в конец, записать текст и закрыть его. append(tfOut); writeln(tfOut, 'Ещё пример текстового файла!'); writeln(tfOut, 'Результат 6 * 7 = ', 6 * 7); CloseFile(tfOut); except on E: EInOutError do writeln('Ошибка обработки файла. Детали: ', E.Message); end; // Выводим результат операции и ожидаем нажатие Enter writeln('Файл ', C_FNAME, ' возможно содержит больше текста. Нажмите ВВОД для выхода.'); readln; end.
Чтение текстового файла:
program ReadFile; uses Sysutils; const C_FNAME = 'textfile.txt'; var tfIn: TextFile; s: string; begin // Вывод некой информации writeln('Чтение содержимого файла: ', C_FNAME); writeln('========================================='); // Связываем имя файла с переменной AssignFile(tfIn, C_FNAME); // Для обработки исключений, используем блок try/except try // Открыть файл для чтения reset(tfIn); // Считываем строки, пока не закончится файл while not eof(tfIn) do begin readln(tfIn, s); writeln(s); end; // Готово. Закрываем файл. CloseFile(tfIn); except on E: EInOutError do writeln('Ошибка обработки файла. Детали: ', E.Message); end; // Выводим результат операции и ожидаем нажатие Enter writeln('========================================='); writeln('Файл ', C_FNAME, ' считан. Нажмите ВВОД для выхода.'); readln; end.
Объектный стиль
В дополнение к старому методу обработки файлов, упомянутому выше процедурному стилю, существует новая система, которая использует концепции потоков (данных) на более высоком уровне абстракции. Это означает, что данные могут считываться или записываться в любом месте (диск, память, аппаратные порты и т. д.) через один универсальный интерфейс.
Кроме того, большинство классов обработки строк, могут иметь возможность загружать/сохранять содержимое из/в файл. Эти методы обычно называются SaveToFile и LoadFromFile.
Двоичные файлы
Для прямого доступа к файлам, так же удобно использовать класс TFileStream. Этот класс представляет собой инкапсуляцию системных процедур FileOpen, FileCreate, FileRead, FileWrite, FileSeek и FileClose, расположенных в модуле SysUtils.
Процедуры ввода-вывода
В приведенном ниже примере обратите внимание, что обработка действий с файлом, расположена внутри блока try..except. Поэтому обработка ошибок происходит так же, как в случаи использования процедур работы с файлами в классическом Pascal.
program WriteBinaryData; {$mode objfpc} uses Classes, Sysutils; const C_FNAME = 'binarydata.bin'; var fsOut : TFileStream; ChrBuffer: array[0..2] of char; begin // Создать некоторые случайные данные, которые будут храниться в файле ChrBuffer[0] := 'A'; ChrBuffer[1] := 'B'; ChrBuffer[2] := 'C'; // Перехват ошибок в случае, если файл не может быть создан try // Создать экземпляр потока файла, записать в него данные и уничтожить его, чтобы предотвратить утечки памяти fsOut := TFileStream.Create( C_FNAME, fmCreate); fsOut.Write(ChrBuffer, sizeof(ChrBuffer)); fsOut.Free; // Обработка ошибки except on E:Exception do writeln('Файл ', C_FNAME, ' не создан, так как: ', E.Message); end; // Выводим результат операции writeln('Файл ', C_FNAME, ' создан. Нажмите ВВОД для выхода.'); //Ожидаем нажатие Enter readln; end.
Вы так же можете загрузить весь файл в память, если его размер существенно меньше, чем имеющийся системной памяти. Если файл превышает размер системной памяти, то ваша операционная система начнет использовать файл подкачки, снижая скорость работы с файлом.
program ReadBinaryDataInMemoryForAppend; {$mode objfpc} uses Classes, Sysutils; const C_FNAME = 'binarydata.bin'; var msApp: TMemoryStream; begin // Создаем поток в памяти msApp := TMemoryStream.Create; // Перехват ошибок в случае их возникновения try // Считать данные в память msApp.LoadFromFile(C_FNAME); // Переходим в конец данных msApp.Seek(0, soEnd); // Запись неких данных в поток msApp.WriteByte(68); msApp.WriteAnsiString('Некий текст'); msApp.WriteDWord(671202); // Запись данных на диск (файл будет перезаписан) msApp.SaveToFile(C_FNAME); // Обработка ошибки except on E:Exception do writeln('Файл ', C_FNAME, ' не удалось считать или записать, так как: ', E.Message); end; // Освобождаем память и уничтожаем объект msApp.Free; // Выводим результат операции и ожидаем нажатие Enter writeln('Файл ', C_FNAME, ' дописан. Нажмите ВВОД для выхода.'); readln; end.
Для работы с файлами большого объёма, рекомендуется использовать буфер, например в 4096 байт.
var TotalBytesRead, BytesRead : Int64; Buffer : array [0..4095] of byte; // или, array [0..4095] of char FileStream : TFileStream; try FileStream := TFileStream.Create; FileStream.Position := 0; // Установим позицию в начало файла while TotalBytesRead <= FileStream.Size do // Пока объем считанных данных меньше размера файла begin BytesRead := FileStream.Read(Buffer,sizeof(Buffer)); // Считать 4096 байт данных inc(TotalBytesRead, BytesRead); // Увеличиваем TotalByteRead на размер буфера, т.е. 4096 байт // Что-то делаем с буфером данных end;
Копирование файла
Теперь,зная методы работы с файлами, мы можем реализовать простую функцию копирования файла, скажем FileCopy.(такой функции нет в FreePascal, хотя Lazarus её имеет copyfile):
program FileCopyDemo; // Пример функции FileCopy {$mode objfpc} uses classes; const fSource = 'test.txt'; fTarget = 'test.bak'; function FileCopy(Source, Target: string): boolean; // Копируем файл с путем в Source в файл с путем Target. // Кэшируем весь файл в память. // В случаи успеха возвращаем true, в случаи ошибки - false. var MemBuffer: TMemoryStream; begin result := false; MemBuffer := TMemoryStream.Create; try MemBuffer.LoadFromFile(Source); MemBuffer.SaveToFile(Target); result := true except //Подавляем исключение; результатом функции является значение false по умолчанию end; // Очистка MemBuffer.Free end; // Пример использования begin If FileCopy(fSource, fTarget) then writeln('Файл ', fSource, ' скопирован в ', ftarget) else writeln('Файл ', fSource, ' не скопирован в ', ftarget); readln() end.
Обработка текстовых файлов (TStringList)
Для текстовых файлов можно использовать класс TStringList, чтобы загрузить весь файл в память и иметь легкий доступ к его строкам. Вы также можете записать StringList обратно в файл:
program StringListDemo; {$mode objfpc} uses Classes, SysUtils; const C_FNAME = 'textfile.txt'; var slInfo: TStringList; begin // Создаем TStringList для обработки текстового файла slInfo := TStringList.Create; // Для обработки исключений, используем блок try/except try // Загружаем файл в память slInfo.LoadFromFile(C_FNAME); // Добавляем некие строки slInfo.Add('Некая строка'); slInfo.Add('Ещё одна строка.'); slInfo.Add('Всё, хватит.'); slInfo.Add('Сейчас ' + DateTimeToStr(now)); // Записать содержимое на диск, заменив исходное содержимое slInfo.SaveToFile(C_FNAME); except // Обработка ошибки on E: EInOutError do writeln('Произошла ошибка обработки файла. Причина: ', E.Message); end; // Очистка slInfo.Free; // Выводим результат операции и ожидаем нажатие Enter writeln('Файл ', C_FNAME, ' обновлен. Нажмите ВВОД для выхода.'); readln; end.
Демо: сохранить одну строку в файл
Для того, чтобы сохранить одну строку в файл, вы можете воспользоваться процедурой, описанной ниже.
program SaveStringToPathDemo; {$mode objfpc} uses Classes, sysutils; const C_FNAME = 'textstringtofile.txt'; // SaveStringToFile: функция для хранения строк текста в файле на диске. // Если результат функции равен True, то строка была написана // Иначе произошла ошибка function SaveStringToFile(theString, filePath: AnsiString): boolean; var fsOut: TFileStream; begin // По умолчанию результат неудачный result := false; // Записать данную строку в файл, перехватывая ошибки в процессе записи. try fsOut := TFileStream.Create(filePath, fmCreate); fsOut.Write(theString[1], length(theString)); fsOut.Free; // На данном этапе известно, что запись прошла успешно. result := true except on E:Exception do writeln('Строка не записана. Детали: ', E.ClassName, ': ', E.Message); end end; // // Основная программа // begin // Пытаемся сохранить текст в файл и выводим результат операции if SaveStringToFile('>> этот текст сохраняется <<', C_FNAME) then writeln('Текст успешно записан в файл.') else writeln('Не удалось сохранить текст в файл.'); // Ждем нажатия Enter readln end.
Смотрите так же
- CopyFile — функция Lazarus, которая копирует файл
- File
7.4 Обработка текстовых файлов в языке Free Pascal
При работе с текстовыми файлами следует учесть следующее:
- Действие процедур reset, rewrite, close, rename, erase и функции eof аналогично их действию при работе с компонентными (типизированными) файлами.
- Процедуры seek, trunсate и функция filepos не работают с текстовыми файлами.
- Можно пользоваться процедурой открытия текстового файла append(f), где f — имя файловой переменной. Эта процедура служит для открытия файла в режиме дозаписи в конец файла. Она применима только к уже физически существующим файлам, открывает и готовит их для добавления информации в конец файла.
- Запись и чтение в текстовый файл осуществляются с помощью процедур write, writeln, read, readln следующей структуры:
read ( f, x1, x2, x3,…, xn );
read ( f, x );
readln ( f, x1, x2, x3,…, xn );
readln ( f, x );
write ( f, x1, x2, x3,…, xn );
write ( f, x );
writeln ( f, x1, x2, x3,…, xn );
writeln ( f, x );
В этих операторах f — файловая переменная. В операторах чтения (read, readln) x, x1, x2, x3,…, xn — переменные, в которые происходит чтение из файла. В операторах записи write, writeln x, x1, x2, x3,…, xn — переменные или константы, информация из которых записывается в файл.
Есть ряд особенностей при работе операторов write, writeln, read, readln с текстовыми файлами. Имена переменных могут быть целого, вещественного, символьного и строкового типа. Перед записью данных в текстовый файл с помощью процедуры write происходит их преобразование в тип string. Действие оператора writeln отличается тем, что после указанных переменных и констант в файл записывается символ «конец строки».
При чтении данных из текстового файла с помощью процедур read, readln происходит преобразование из строкового типа к нужному типу данных. Если преобразование невозможно, то генерируется код ошибки, значение которого можно узнать, обратившись к функции IOResult. Компилятор Free Pascal позволяет генерировать код программы в двух режимах: с проверкой корректности ввода-вывода и без неё.
В программу может быть включен ключ режима компиляции. Кроме того, предусмотрен перевод контроля ошибок ввода-вывода из одного состояния в другое:
- {$I+} — режим проверки ошибок ввода-вывода включён;
- {$I-} — режим проверки ошибок ввода-вывода отключён.
По умолчанию, как правило, действует режим {$I+}. Можно многократно включать и выключать режимы, создавая области с контролем ввода и без него. Все ключи компиляции описаны в приложении.
При включённом режиме проверки любая ошибка ввода-вывода будет фатальной, программа прервётся, выдав номер ошибки.
Если убрать режим проверки, то при возникновении ошибки ввода-вывода программа не будет останавливаться, а продолжит работу со следующего оператора. Результат операции ввода-вывода будет неопределён.
Для опроса кода ошибки лучше пользоваться специальной функцией IOResult, но необходимо помнить, что опросить её можно только один раз после каждой операции ввода или вывода: она обнуляет своё значение при каждом вызове. IOResult возвращает целое число, соответствующее коду последней ошибки ввода-вывода. Если IOResult=0, то при вводе-выводе ошибок не было, иначе IOResult возвращает код ошибки. Некоторые коды ошибок приведены в табл. 7.9.
Таблица
7.9.
Коды ошибок операций ввода-вывода
Код ошибки | Описание |
---|---|
2 | файл не найден |
3 | путь не найден |
4 | слишком много открытых файлов |
5 | отказано в доступе |
12 | неверный режим доступа |
15 | неправильный номер диска |
16 | нельзя удалять текущую директорию |
100 | ошибка при чтении с диска |
101 | ошибка при записи на диск |
102 | не применена процедура AssignFile |
103 | файл не открыт |
104 | файл не открыт для ввода |
105 | файл не открыт для вывода |
106 | неверный номер |
150 | диск защищён от записи |
Рассмотрим несколько практических примеров обработки ошибок ввода-вывода:
- При открытии проверить, существует ли заданный файл и возможно ли чтение данных из него.
assign ( f, ’ abc. dat ’ ); {$I-} reset ( f ); {$I+} if IOResult<>0 then writeln ( ’файл не найден или не читается ’ ) else begin read ( f,... ); close ( f ); end;
- Проверить, является ли вводимое с клавиатуры число целым.
var i : integer; begin {$I-} repeat write ( ’введите целое число i ’ ); readln ( i ); until ( IOResult =0); {$I+} {Этот цикл повторяется до тех пор, пока не будет введено целое число.} end.
При работе с текстовым файлом необходимо помнить специальные правила чтения значений переменных:
- Когда вводятся числовые значения, два числа считаются разделёнными, если между ними есть хотя бы один пробел, или символ табуляции, или символ конца строки.
- При вводе строк начало текущей строки идёт сразу за последним, введённым до этого символом. Вводится количество символов, равное объявленной длине строки. Если при чтении встретился символ «конец строки», то работа с этой строкой заканчивается. Сам символ конца строки является разделителем и в переменную никогда не считывается.
- Процедура readln считывает значения текущей строки файла, курсор переводится в новую строку файла, и дальнейший ввод осуществляется с неё.
В качестве примера работы с текстовыми файлами рассмотрим следующую задачу.
ЗАДАЧА 7.8. В текстовом файле abc.txt находятся матрицы и и их размеры. Найти матрицу , которую дописать в файл abc.txt.
Сначала создадим текстовый файл abc.txt следующей структуры: в первой строке через пробел хранятся размеры матрицы (числа N и M), затем построчно хранятся матрицы A и B.
Рис.
7.14.
Файл abc.txt
На рис. 7.14 приведён пример файла abc.txt, в котором хранятся матрицы A(4,5) и B(4,5).
Текст консольного приложения решения задачи 7.8 с комментариями приведён ниже.
program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils { you can add units after this }; var f : Text; i, j, N,M: word; a, b, c : array [ 1.. 1000, 1.. 1000 ] of real; begin //Связываем файловую переменную f с файлом на диске. AssignFile ( f, ’ abc. t x t ’ ); //Открываем файл в режиме чтения. Reset ( f ); //Считываем из первой строки файла abc.txt значения N и M. Read( f,N,M); //Последовательно считываем элементы матрицы А из файла. for i :=1 to N do for j :=1 to M do read ( f, a [ i, j ] ); //Последовательно считываем элементы матрицы B из файла. for i :=1 to N do for j :=1 to M do read ( f, b [ i, j ] ); //Формируем матрицу C=A+B. for i :=1 to N do for j :=1 to M do c [ i, j ] : = a [ i, j ]+b [ i ] [ j ]; //Закрываем файл f. CloseFile ( f ); //Открываем файл в режиме дозаписи. Append( f ); //Дозапись матрицы C в файл. for i :=1 to N do begin for j :=1 to M do //Дописываем в файл очередной элемент матрицы и пробел в //текстовый файл. write ( f, c [ i, j ] : 1 : 2, ’ ’ ); //По окончании вывода строки матрицы переходим на новую //строку в текстовом файле. writeln ( f ); end; //Закрываем файл. CloseFile ( f ); end.
После работы программы файл abc.txt будет примерно таким, как показано на рис. 7.15.
Рис.
7.15.
Файл abc.txt после дозаписи матрицы C
Компилятор Турбо Паскаля позволяет генерировать выполнимый код в двух режимах: с проверкой корректности ввода-вывода и без нее. В среде программирования этот режим включается в меню
— 262 —
Options/Compiler/IO-checking. При включении в программу ключ режима компиляции обозначается как
{$I+} — режим проверки включен;
{$I-} — режим отключен.
По умолчанию, как правило, действует режим $I+. Этот ключ компиляции имеет локальную сферу влияния. Можно многократно включать и выключать режим, вставляя в текст программы конструкции {$I+} и {SI-}, тем самым создавая области с контролем ввода-вывода и без него.
При включенном режиме проверки любая ошибка ввода-вывода будет фатальной: программа прервется, выдав номер ошибки. Возможные номера ошибок ввода-вывода находятся в диапазоне от 2 до 200 ( от 2 до 99 — это коды ошибок DOS, от 100 до 149 — ошибки, диагностируемые самой программой, и от 150 до 200 — критические аппаратные ошибки). Расшифровка кодов ошибок с краткими комментариями приведена в табл. 12.6 в конце этого раздела.
Если отключить режим проверки, то при возникновении ошибки ввода-вывода программа уже не будет прерываться, а продолжит работу со следующего оператора. Результат операции ввода-вывода, вызвавшей ошибку, будет неопределен. При этом код ошибки будет сохранен в предопределенной системной переменной InOutRes. Однако для опроса этого кода лучше пользоваться специальной функцией Турбо Паскаля.
Дополнительные функции работы с файлами
Модуль |
|
ChDir |
Выполняет |
MkDir |
Создает |
RmDir |
Удаляет |
GetDir |
Получить |
Модуль |
|
DiskFree |
Число |
DiskSize |
Размер |
GetFAttr |
Получение |
SetFAttr |
Задание |
FSplit |
Получение |
FExpand |
Формирование |
FSearch |
Поиск |
FindFirst |
Поиск |
FindNext |
Поиск |
Прототипы
процедур FindFirst
и FindNext
имеют вид:
FindFirst(Path:
String; Attrib: Word; Var SR: SearchRec);
FindNext(Var
SR:
SearchRec);
Для
работы с этими подпрограммами требуются
следующие предопределенные описания:
-
Константы
Const
ReadOnly
= $01; только
для чтения
Hidden = $02; скрытый
SysFile =
$04; системный (непереносимый)
Volume ID = $08; метка
диска
Directory =
$10; подкаталог
Archive = $20; архивный
AnyFile = $3F; сумма
всех предыдущих
Эти атрибуты можно
складывать или вычитать (из anyfile).
-
Переменная
DOSError.
Она используется для анализа ошибок
MS
DOS.
Значение этой переменной, равное нулю,
соответствует отсутствию ошибки. Смысл
некоторых ненулевых кодов следующий:
2
– файл не найден
3
– маршрут не найден
5
– доступ к файлу запрещен
6
– неправильная обработка
8
– недостаточно памяти
10
– неверные установки значений параметров
среды
11
– неправильный формат
18
– файлов нет
При
работе процедуры FindFirst
возможны ошибки с номерами 2 и 18, а при
работе FindNext
– только 18.
3)
Тип
Type
SearchRec
= record
Fill: array[1..21] of byte; {системное поле}
attr: byte; {байт атрибутов}
time: longint; {время
создания}
size: longint; {размер
файла}
name: string[12]; {имя файла}
end;
Поля
переменной этого типа содержат информацию
о последнем файле, найденном с помощью
FindFirst
и FindNext.
Процедура
FindFirst
при заданных имени файла и атрибутах
должна вызываться лишь один раз. Она
записывает в поля переданной ей переменной
SR
типа SearchRec
информацию о первом найденном файле,
удовлетворяющем заданным условиям. Эта
информация в дальнейшем будет
использоваться процедурой FindNext,
которая всегда вызывается после FindFirst
и заполняет поля переменной SR
информацией о следующем найденном
файле.
Контроль
работы этих процедур ведется с помощью
переменной DOSError:
если файла нет, то DOSError<>0.
Обработка ошибок ввода-вывода
Все рассмотренные
ранее программы были написаны так, что
возможные ошибки ввода-вывода
игнорировались. Однако реально это не
так. В ТР стандартной реакцией на наличие
ошибок в вашей программе является
следующее: ваша программа аварийно
завершается и выдает сообщение:
Runtime
error
<номер> <смещение>.
Такое сообщение
буде полезно вам как программистам при
поиске места и причины ошибки в программе.
Однако показывать такое сообщение
пользователю вашей программы будет не
совсем дружественно.
Для того, чтобы
ваша программа из-за ошибки аварийно
не завершалась и для того, чтобы не
пугать пользователей непонятными им
сообщениями, вам необходимо перехватить
инициативу по обработке ошибок у системы
и писать собственные обработчики ошибок
стадии выполнения (исключений). Традиционно
обработка ошибок в программах
осуществляется с помощью установки
флагов (в
случае ошибки) и последующего анализа
этих флагов. Для перехвата ошибок
ввода-вывода на Паскале необходимо:
-
Специальным
образом оформить каждый фрагмент
программы, которые потенциально могут
вызвать ошибку. К таким фрагментам
относятся — открытие файда, чтение из
файла, запись в файл. -
При наличии такого
специального оформления необходимо
по завершению фрагмента проверить:
была ошибка или нет. Если была, то вы
должны выполнить ее обработку (хотя бы
вывести свое сообщение).
Пример:
reset(f);
при попытки открытия
файла физически файл может отсутствовать
на диске. Этот оператор в программе
является потенциальным источником
ошибки.
Специальное
оформление потенциально опасных участков
программы состоит в том, что
вы должны
как бы завернуть каждый опасный участок
в специальный код: выше
и ниже опасного фрагмента программы
вы должны
расположить две директивы компилятора:
{$I-}
— указывает на то, что необходимо
отключить системный контроль ошибок
reset(f);
{$I+}
— указывает на то, что необходимо включить
системный контроль ошибок
При наличии
директивы компилятора {$I-}
даже при наличии ошибок в/в программа
аварийно не завершается и ход выполнения
программы не нарушается.
Замечание:
По умолчанию действует директива {$i+}.
Контроль ошибок
в/в производится с помощью функции
IOResult
. Если ошибка имеет место, то значение
этой функции отлично от нуля. Поэтому
типичный шаблон обработки ошибки
ввода-вывода имеет вид:
If
IOResult
<> 0 Then
{обработка ошибки};
Обычно обработка
ошибки сводится к сообщению об ошибки
и завершению вашей программы (с помощью
процедуры HALT
или EXIT).
Замечание:
Опросить функцию IOResult
можно лишь
один раз
после каждой операции ввода-вывода,
т.к. она обнуляет свое значение перед
каждым вызовом. Поэтому целесообразно
сохранять значение, возвращенное
IOResult,
в специально выделенной переменной.
Пример.
{$I-}
reset(f);
{$I+}
If
IOResult <> 0
then
begin
Writeln(‘Ошибка
открытия
файла’);
Halt;
end;
Соседние файлы в папке WORD
- #
15.04.2015439.06 Кб306.docx
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
В этом разделе обсуждаются разнообразные,
важные в практическом отношении, примемы
программирования.
1. Обработка ошибок ввода-вывода
В одном из предыдущих разделов был рассмотрен
фрагмент программы, демонстрирующий контроль за
вводимой информацией и не допускающий ввод
некорректных данных. Повторим здесь этот
фрагмент:
PROGRAM CheckInputData_1;
USES CRT;
VAR
x : Real;
BEGIN
ClrScr;
REPEAT
Write(‘Введите число в интервале от 0 до
100: ‘);
Read(x);
if not((x>=0)and(x<=100))
then writeln(‘Ошибка при вводе
числа!’);
UNTIL (x>=0)and(x<=100);
…
…
END.
Приведенная программа не допускает ввода числа
меньше нуля или больше ста. А что произойдет, если
вместо числа ввести (случайно) какой-либо иной
символ? Скорее всего это приведет к
возникновению фатальной (т.е. ведущий к
прекращению работы программы) ошибки
ввода-вывода: Error 106: Invalid numeric format. Этого можно избежать, если
воспользоваться приемом, описанным ниже.
Сначала немного теории. Компилятор
языка Турбо Паскаль позволяет генерировать
выполнимый (машинный) код в
дух режимах: с проверкой корректности
ввода-вывода и без нее. В среде программирования
этот режим включается в меню Options – Compiler –
I/O Checking. Режимом компиляции
можно управлять непосредственно в тексте
программы с помощью ключа компиляции $I
{$I+} – режим проверки включен;
{$I-} – режим отключен.
По умолчанию, как правило, действует режим $I+. Этот ключ компиляции имеет
локальную сферу влияния. Можно многократно
включать и выключать режим, вставляя в текст
программы конструкции {$I+} и {$I-},
тем самым создавая области с
контролем ввода-вывода и без него.
При включенном режиме проверки любая ошибка
ввода-вывода будет фатальной: программа
прервется, выдав номер ошибки. Если отключить
режим проверки, то при возникновении ошибки
ввода-вывода программа уже не будет прерываться,
а продолжит работу со следующего оператора.
Результат операции ввода-вывода, вызвавший
ошибку, будет неопределен. При этом код ошибки
будет сохранен и в последствии его можно узнать с
помощью специальной функции IOResult. Эта функция возвращает целое число,
соответствующее коду последней ошибки
ввода-вывода. Если же операция ввода-вывода
прошла без сбоев, то функция вернет значение 0. Опросить функцию IOResult можно только один раз, ибо она
обнуляет свое значение при каждом вызове. Обычно
это обходят запоминанием значения функции в
какой-либо переменной.
Итак, для того чтобы рассмотренная выше
программа не давала сбоев при вводе, необходимо
отключить режим проверки ошибок ввода-вывода на время работы
процедуры Read, а затем
проанализировать значение функции IOResult:
PROGRAM CheckInputData_2;
USES CRT;
VAR
x : Real;
err : Integer;
BEGIN
ClrScr;
REPEAT
Write(‘Введите число в интервале от 0 до 100: ‘);
{$I-}
Read(x);
{$I+}
err := IOResult;
if not((x>=0) and (x<=100)) or (err<>0)
then writeln(‘Ошибка при вводе числа!’);
UNTIL (x>=0) and (x<=100) and (err=0);
…
…
END.
Возможность управлять режимом обработки
ошибок и наличие функции IOResult
позволяет писать программы, никогда не дающие
сбоев при вводе или выводе данных и при работе с
файлами.
2. Управление программой с помощью меню
При написании больших и не очень больших
программ, выполняющих различные действия,
полезно сделать так, чтобы у пользователя была
возможность выбрать тот или иной режим работы с
программой. Например, если программа направлена
на решение некоторой физической задачи, то она
может иметь по крайней мере три режима работы: 1)
ввод и модификация параметров задачи; 2)
собственно вычисления; 3) представление
результатов (например, построение графиков
рассчитанных зависимостей). Организация выбора
режимов работы может быть сделана с помощью меню.
Меню, в данном случае, — это перечень команд или
режимов работы, которые можно выбрать тем или
иным способом. В простейшем случае, меню может
быть представлено на экране нумерованным списком. Выбор того или иного пункта
меню осуществляется вводом числа,
соответствующего номеру пункта. В более сложных
случаях выбор пункта меню может осуществляться
перемещением (с помощью клавиатуры или “мыши”)
курсора-подсветки, а активизация выбранного
пункта – нажатием на клавишу “Enter” или щелчком кнопки мыши.
Рассмотрим в качестве примера структуру
программы, содержащей простейшее меню в виде
нумерованного списка.
PROGRAM Example_of_Menu;
USES CRT;
VAR Ch : Char;
PROCEDURE ChangeParam;
BEGIN
END;
PROCEDURE Calculation;
BEGIN
END;
PROCEDURE ShowGraphic;
BEGIN
END;
BEGIN
repeat
ClrScr;
GotoXY(30,2);
Write(‘НАЗВАНИЕ ПРОГРАММЫ’);
GotoXY(28,6);
Write(‘- Меню режимов работы -’);
GotoXY(20,8); Write(‘1 — Ввод и изменение
параметров’);
GotoXY(20,10); Write(‘2 — Вычисление’);
GotoXY(20,12); Write(‘3 — Построение графика’);
GotoXY(20,14); Write(‘4 — Завершение работы’);
GotoXY(15,18);
Write(‘Для выбора режима работы нажмите
клавишу [1..4]: ’);
repeat
Ch := ReadKey;
until Ch in [’1’,’2’,’3’,’4’];
case Ch of
‘1’ : ChangeParam;
‘2’ : Calculation;
’3’ : ShowGraphic;
’4’ : Halt;
end; {case}
until false;
END.
Права на материал принадлежат их авторам
Вернуться на главную страницу