Pascal abc обработка ошибок

��������� ����������

��������� ����������: �����

����� �� ����� ���������� ��������� ���������� ������, ������������ ��� ���������� ����������, ������� ����� ���������������������. ���������� ������������ ����� ������ ������, ������������ �� ������ Exception, ����������� ��� ������������� �������������� ��������.

������� ��� ����������� ����� ����������. ����� ����� ���������� ���������������� ���� ����������.

���� ���������� �� ����������, �� ��������� ���������� � �������. ��� ��������� ���������� ������������ �������� tryexcept.

������ ���������� ������������ � �������������, ��������� ����������� ������������, ��� �������, �� �����, ��� ���������� ��������� ��������. � ����� ������ ������������ ���, ��� �������, ��������, ����� ������� ������� ������������ ����������. ��������, ����� ����������� ��������� �������:

function mymod(a,b: integer): integer;

begin

Result := a — (a div b) * b;

end;

���� ������� mymod(1,0), �� ����� ���������� ���������� System.DivideByZeroException �������������� ������� �� 0.

���������� ������� ������� ���������� ��������� �������� ������ ������� mymod:

function mymod(a,b: integer): integer;

begin

if b = 0 then

writeln(‘������� mymod: ������� �� 0’);

Result := a — (a div b) * b;

end;

�������� ������� �������� ������, ��������� �����������, ��������������� ������� mymod, �� �����, ��� ��� ����� ��������������. ��������, ��� ������ ������� mymod � ����� �� ������ �� ������ ������������ ��������� �� ������.

���������� ������ — �������� �������� ������� ������� � ������������ ���������� System.DivideByZeroException:

try

readln(a,b);

writeln(mymod(a,b) mod (a-1));

except

on System.DivideByZeroException do

writeln(‘������� �� 0’);

end;

������� �� ������ ������ ������� ������� � ���, ��� ��� ���������� ��������� �� ���� ���������� ��������, ������� ���������� ��������� ��� ��������� ����������. ��� ����� ���� ������������� ��������� �� ������, ����� � ���� ������ ��� ������ �������� (� ������, ����� ��������� ��������� �������� ����������).

������, ������ ������� �������� ������������ �����������: ���������� System.DivideByZeroException ����� ���������� � ��� a=1 � �� ����� ������� � �������� mymod. ��� ���������� ��������� ���������� ��������� ����������� ����� ���������� � �������� ��� � ������� mymod:

type MyModErrorException = class(System.Exception) end;

function mymod(a,b: integer): integer;

begin

if b = 0 then

raise new MyModErrorException(‘������� mymod: ������� �� 0’);

Result := a — (a div b) * b;

end;

����� ��������� ������ ����� ��������� ���:

try

readln(a,b);

writeln(mymod(a,b) mod (a-1));

except

on System.DivideByZeroException do

writeln(‘������� �� 0’);

on e: MyModErrorException do

writeln(e.Message);

else writeln(‘�����-�� ������ ����������’)

end;

���� ������� MyModErrorException ����������� ������ System.ArithmeticException, ��� � System.DivideByZeroException, �� ��������� ��� ����� ���������:

type MyModErrorException = class(System.ArithmeticException) end;

try

readln(a,b);

writeln(mymod(a,b) mod (a-1));

except

on e: System.ArithmeticException do

writeln(e.Message);

else writeln(‘�����-�� ������ ����������’)

end;

�������, ����� ��������� ��������� �������. ���������� � ������� mymod ���������� System.DivideByZeroException � � ����� ����������� ����� — MyModErrorException:

function mymod(a,b: integer): integer;

begin

try

Result := a — (a div b) * b;

except

on e: System.DivideByZeroException do

raisenew MyModErrorException(‘������� mymod: ������� �� 0’);

end;

end;

Оператор try … except

Оператор tryexcept имеет вид:

try
 
  операторы
except
 
  блок обработки исключений
end;

Блок try называется
защищаемым блоком.
Если при выполнении программы в нем происходит ошибка, то он завершается и
выполнение передается блоку except. Если исключение
обрабатывается в блоке except, то после его обработки
программа продолжает выполняться с оператора, следующего за try
exceptend. Если исключение остается необработанным и имеется объемлющий
блок try, то выполнение передается
его блоку except. Если объемлющего
блока try нет, то программа
завершается с ошибкой. Наконец, если в блоке try
ошибки не произошло, то блок except
игнорируется и выполнение программы продолжается дальше.

Если в процессе обработки исключения (в блоке
except
) произошло другое исключение, то текущий
блок except завершается, первое
исключение считается необработанным и обработка нового исключения передается
объемлющему блоку try. Таким образом,
в каждый момент времени существует максимум одно необработанное исключение.

Блок обработки
исключений
представляет собой либо последовательность
операторов, разделенных точкой с запятой, либо последовательность обработчиков
исключений вида

on имя: тип do оператор

Обработчики разделяются символом ‘;‘,
после последнего обработчика также может следовать символ ‘;‘.
Здесь тип — тип исключения
(должен быть производным от стандартного типа Exception),
имя — имя переменной исключения (имя с последующим двоеточием может быть
опущено). В первом случае при обработке исключения выполняются все операторы из
блока except. Во втором случае среди
обработчиков осуществляется поиск типа текущего исключения (обработчики
перебираются последовательно от первого до последнего), и если обработчик
найден, то выполняется соответствующий оператор обработки исключения, в
противном случае исключение считается необработанным и передается объемлющему
блоку try. В последнем случае после всех
обработчиков on может идти ветвь else,
которая обязательно обработает исключение, если ни один из обработчиков не
выполнился.

Следует обратить внимание, что имя переменной исключения в
разных обработчиках может быть одинаковым, т.е. оно локально по отношению к
обработчику.

Поиск типа исключения в обработчиках производится с учетом
наследования: исключение будет обработано, если оно принадлежит к указанному в
обработчике типу или производному от него. Поэтому принято записывать вначале
обработчики производных классов, а затем — обработчики базовых (в противном
случае обработчик исключения производного класса никогда не сработает).
Обработчик исключения Exception обрабатывает
все возможные исключения и поэтому должен быть записан последним.

Пример.

var a: array [1..10] of integer;
try

  var i: integer;
  readln(i);
  writeln(a[i] div i);
  ...
except
  on System.DivideByZeroException do
    writeln('Деление на 0'); 
  on e: System.IndexOutOfRangeException do
    writeln(e.Message);
  on System.FormatException do
    writeln('Неверный формат ввода');
  else writeln('Какое-то другое
исключение');
end;

Оператор
try
except
имеет вид:

try
 
операторы
except
 
блок обработки исключений
end;

Блок
try
называется защищаемым блоком. Если
при выполнении программы в нем происходит
ошибка, то он завершается и выполнение
передается блоку except.
Если исключение обрабатывается в блоке
except,
то после его обработки программа
продолжает выполняться с оператора,
следующего за try
except
end.
Если исключение остается необработанным
и имеется объемлющий блок try,
то выполнение передается его блоку
except.
Если объемлющего блока try
нет, то программа завершается с ошибкой.
Наконец, если в блоке try ошибки не
произошло, то блок except
игнорируется и выполнение программы
продолжается дальше.

Если
в процессе обработки исключения (в блоке
except)
произошло другое исключение, то текущий
блок except
завершается, первое исключение остается
необработанным и обработка нового
исключения передается объемлющему
блоку try.
Таким образом, в каждый момент времени
существует максимум одно необработанное
исключение.

Блок
обработки исключений
представляет
собой либо последовательность операторов,
разделенных точкой с запятой, либо
последовательность обработчиков
исключений вида

on
имя:
тип do
оператор;

где
тип — тип исключения (должен быть
производным от типа Exception),
имя — имя переменной исключения (имя
с последующим двоеточием может быть
опущено). В первом случае при обработке
исключения выполняются все операторы
из блока except.
Во втором случае среди обработчиков
осуществляется поиск типа текущего
исключения, и если обработчик найден,
то выполняется соответствующий оператор
обработки исключения, в противном случае
исключение считается необработанным
и передается объемлющему блоку try.

Следует
обратить внимание, что имя переменной
исключения в разных обработчиках может
быть одинаковым, т.е. оно локально по
отношению к обработчику.

Поиск
типа исключения в обработчиках
производится с учетом наследования:
исключение будет обработано, если оно
принадлежит к указанному в обработчике
типу или производному от него. Поэтому
принято записывать вначале обработчики
производных классов, а затем — обработчики
базовых (в противном случае обработчик
исключения производного класса никогда
не сработает). Обработчик исключения
Exception
обрабатывает все возможные исключения
и поэтому должен быть записан последним.

Пример.

try

 
readln(x);
 
writeln(ctg(x)/(x-1));
 

except
 
on
EZeroDivide do
   
writeln(‘Деление
на
0’); 
 
on
e: ECtgError do
   
writeln(e.Message); 
end;

Оператор try … Finally

Оператор
try
finally
имеет вид:

try
 
операторы
finally
 
операторы
end;

Операторы
в блоке finally
выполняются безотносительно к тому,
возникло или нет исключение в блоке
try.
При этом само исключение не обрабатывается.

Блок
finally
используется для возвращения ранее
выделенных ресурсов.

Пример
1.
Закрытие открытого файла.

reset(f);
try
 

finally
 
close(f); 

end;

Файл
будет закрыт независимо от того, произошло
ли ислючение в блоке try.

Пример
2.
Возвращение выделенной динамической
памяти.

New(p);
try
 

finally
 
Dispose(p);
end;

Динамическая
память, контролируемая указателем p,
будет возвращена независимо от того,
произошло ли ислючение в блоке try.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Читайте также

ГЛАВА 4 Обработка исключений

ГЛАВА 4
Обработка исключений
Основное внимание в данной главе сфокусировано на структурной обработке исключений (Structured Exception Handling, SEH), но наряду с этим обсуждены также обработчики управляющих сигналов консоли и векторная обработка исключений (Vectored Exception Handling, VEH).SEH

Пример: обработка ошибок как исключений

Пример: обработка ошибок как исключений
В предыдущих примерах для обработки ошибок при выполнении системных вызовов и других ошибок используется функция ReportError. Эта функция прекращает выполнение процесса, если программист указал, что данная ошибка является

SEH и обработка исключений в C++

SEH и обработка исключений в C++
При обработке исключений в C++ используются ключевые слова catch и throw, а сам механизм исключений реализован с использованием SEH. Тем не менее, обработка исключений в C++ и SEH — это разные вещи. Их совместное применение требует внимательного

Векторная обработка исключений

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

13.1.5. Обработка исключений

13.1.5. Обработка исключений
Что произойдет, если в потоке возникнет исключение? Как выясняется, поведение можно сконфигурировать заранее.Существует флаг abort_on_exception, который работает как на уровне класса, так и на уровне экземпляра. Он реализован в виде метода доступа (то

Обработка исключений

Обработка исключений
Исключение (exception) — это результат выполнения некорректного оператора, что привело к возникновению ошибки. В языке Object Pascal для обработки исключений предназначена специальная конструкция:try //Операторы, которые могут привести к возникновению

Обработка исключений

Обработка исключений
Ввиду того, что теперь метод Accelerate() может генерировать исключение, вызывающая сторона должна быть готова обработать такое исключение. При вызове метода, способного генерировать исключение, вы должны использовать блок try/catch. Приняв исключение, вы

Обработка множеств исключений

Обработка множеств исключений
В простейшем варианте блок try имеет единственный блок catch. Но на практике часто возникает ситуация, когда операторы в рамках блока try способны создавать множество возможных исключений. Например, представьте себе, что метод Accelerate()

11. Обработка исключений

11. Обработка исключений
Обработка исключений – это механизм, позволяющий двум независимо разработанным программным компонентам взаимодействовать в аномальной ситуации, называемой исключением. В этой главе мы расскажем, как генерировать, или возбуждать, исключение в

Обработка исключений

Обработка исключений
Код PSQL может перехватывать ошибки при их появлении и затем их обрабатывать в подпрограмме обработки исключений. Если исключение будет обработано в вашем коде- вы обеспечите исправление или обход ошибки и позволите продолжить выполнение, — то

Обработка исключений

Обработка исключений
Ошибки в isql обрабатываются тем же образом, что и приложении DSQL. isql отображает сообщение об ошибке, содержащее переменную SQLCODE и текст сообщения из массива состояния Firebird, как показано на рис. 37.4.

Рис. 37.4. Пример сообщения об ошибке в isqlОшибки SQL со

Продвинутая обработка исключений

Продвинутая обработка исключений
Чрезвычайно простой механизм, разработанный до сих пор, удовлетворяет большинству потребностей обработки исключений. Но некоторые приложения могут требовать более тонкой настройки:[x]. Возможно, требуется определить природу последнего

Дополнительные функции работы с файлами

Модуль
System

ChDir

Выполняет
смену текущего каталога

MkDir

Создает
подкаталог

RmDir

Удаляет
подкаталог (пустой)

GetDir

Получить
текущий каталог на заданном диске

Модуль
DOS

DiskFree

Число
свободных байтов на диске

DiskSize

Размер
диска в байтах

GetFAttr

Получение
атрибутов неоткрытого файла

SetFAttr

Задание
атрибутов неоткрытого файла

FSplit

Получение
составных частей имени файла

FExpand

Формирование
полного имени файла

FSearch

Поиск
файла в списке католога

FindFirst

Поиск
в указанном или текущем каталоге
первого файла, соответствующего
заданному шаблону и атрибутам

FindNext

Поиск
следующего файла, соответствующего
шаблону и атрибутам, заданным в
последнем обращении к FindFirst

Прототипы
процедур FindFirst
и FindNext
имеют вид:

FindFirst(Path:
String; Attrib: Word; Var SR: SearchRec);

FindNext(Var
SR:
SearchRec);

Для
работы с этими подпрограммами требуются
следующие предопределенные описания:

  1. Константы

Const

ReadOnly
= $01; только
для чтения

Hidden = $02; скрытый

SysFile =
$04; системный (непереносимый)

Volume ID = $08; метка
диска

Directory =
$10; подкаталог

Archive = $20; архивный

AnyFile = $3F; сумма
всех предыдущих

Эти атрибуты можно
складывать или вычитать (из anyfile).

  1. Переменная
    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
<номер> <смещение>.

Такое сообщение
буде полезно вам как программистам при
поиске места и причины ошибки в программе.
Однако показывать такое сообщение
пользователю вашей программы будет не
совсем дружественно.

Для того, чтобы
ваша программа из-за ошибки аварийно
не завершалась и для того, чтобы не
пугать пользователей непонятными им
сообщениями, вам необходимо перехватить
инициативу по обработке ошибок у системы
и писать собственные обработчики ошибок
стадии выполнения (исключений). Традиционно
обработка ошибок в программах
осуществляется с помощью установки
флагов

случае ошибки) и последующего анализа
этих флагов. Для перехвата ошибок
ввода-вывода на Паскале необходимо:

  1. Специальным
    образом оформить каждый фрагмент
    программы, которые потенциально могут
    вызвать ошибку. К таким фрагментам
    относятся — открытие файда, чтение из
    файла, запись в файл.

  2. При наличии такого
    специального оформления необходимо
    по завершению фрагмента проверить:
    была ошибка или нет. Если была, то вы
    должны выполнить ее обработку (хотя бы
    вывести свое сообщение).

Пример:

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 Кб286.docx

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Рассмотрим несколько практических примеров (везде далее f — файловая переменная).

— 263 —

1. Обработка отсутствия файла с данными. Если файл отсутствует, то действие процедуры открытия Reset вызовет ошибку (рис. 12.10 ).

| Assign( f, ‘NoFile.TXT’ );

| {$I-} { выключение проверки ввода-вывода }

| Reset( f ); { попытка открыть файл f }

| {$I+} { восстановление проверки }

| if IOResult<>0 { Если файл не может быть открыт, }

| then { то дать сообщение: }

| WriteLn( ‘Файл не найден или не читается’ )

| else begin { Иначе (код равен 0) все хорошо }

| Read( f, … ); { и можно нормально работать с }

| … { файлом f… }

| Close(f)

| end; {else и if}

Рис. 12.10

В случае неудачи при открытии файла к нему не надо применять процедуру закрытия Close.

По тому же принципу можно построить функцию анализа существования файла (рис. 12.11).

| FUNCTION FileExists( FileName : String ) : Boolean;

| VAR

| f : File; { тип файла не важен }

| BEGIN

| Assign( f, FileName ); { связывание файла f }

| {$I-} Reset( f ); {$I+} { открытие без контроля }

| if IOResult=0 { Если файл существует, }

| then begin { то его надо закрыть }

| Close{ f );

| FileExists := True end {then}

| else { иначе просто дать знать}

| FileExists := False;

| END;

Рис. 12.11

2. Выбор режима дозаписи в текстовый файл или его создания. Механизм остается тот же (рис. 12.12). Здесь f — текст-файловая переменная.

— 264 —

| Assign(f,’XFile.TXT’); {связывание файла f }

| {$I-} Append( f ); {$I+} {попытка открыть его для дозаписи}

| if IOResult<>0 {Если файл не может быть открыт, }

| then Rewrite( f ); {то создать его. }

| …

| Write( f, …); { нормальная работа с файлом }

| …

| Close( f );

Рис. 12.12

3. Переход в заданный каталог или его создание, если переход возможен (рис. 12.13, S — строковая переменная).

| S := ‘C:NEWDIR’; { задано имя каталога }

| {$I-} ChDir( S ); {$I+} { попытка перейти в него }

| if IOResult<>0 { Если не получается, }

| then begin

| MkDir( S ); {то сначала создать его, }

| ChDir( S ) { а уж потом перейти. }

| end; {if}

| { Подразумевается, что каталог S в принципе создаваем. }

Рис. 12.13

4. Построение «умных» ждущих процедур чтения данных с клавиатуры. Такие процедуры не будут реагировать на данные не своего формата (рис. 12.14).

| { Здесь используется ряд процедур из библиотеки }

| CRT; { модуля CRT. Они отмечены * в комментариях. }

{Процедура считывает с клавиатуры значение типа Integer, помещая его в переменную V. При этом игнорируется любой ввод, не соответствующий этому типу. X и Y — координаты текста запроса Comment. Проверка корректности значений X и Y не производится. }

PROCEDURE ReadInteger( X,Y : Byte; Comment : String;

| VAR V : Integer );

Рис. 12.14

— 265 —

| CONST

| zone =12; { ширина окна зоны ввода числа }

| VAR

| WN.WX : Word; {переменные для хранения размеров окна }

| BEGIN

| WN:=WindMin; WX:=WindMax; {Сохранение текущего окна }

| {$I-} { отключение режима проверки }

| GotoXY( X,Y ); {*перевод курсора в X,Y }

| Write( Comment ); { печать комментария ввода }

| Inc(X, Length(Comment)); { увеличение координаты X }

| Window( X,Y, X+zone,Y ); {*определение окна на экране }

| Repeat { Главный цикл ввода числа: }

| ClrScr; {* очистка окна ввода, }

| ReadLn( V ); { считывание значения при $I- }

| until (IOResult=0); { пока не введено целое }

| {$I+} { включение режима проверки }

| {*восстановление окна: }

| Window( Lo(WN)+1, Hi(WN)+1, Lo(WX)+1, Hi(WX)+1 )

| END; {proc}

| VAR i : Integer; { === ПРИМЕР ВЫЗОВА ПРОЦЕДУРЫ === }

| BEGIN

| ClrScr; {* очистка экрана }

| ReadInteger(10,10,’Введите целое число: ‘,i); { вызов }

| WriteLn; WriteLn( ‘Введено i=’, i ); { контроль }

| ReadLn { пауза до нажатия ввода}

| END.

Рис 12.14 (окончание)

В примере можно попутно устроить проверку диапазона значений V, переписав условие окончания цикла в виде

until (IOResult=0) and (V<Vmax) and (V>Vmin);

где Vmax и Vmin — границы воспринимаемых значений V. Аналогичным способом, меняя лишь типы переменной V, можно определить процедуры ReadByte, ReadWord, ReadReal и т.п. Справедливости ради надо отметить, что хотя описанная процедура ReadInteger спокойно относится к попыткам впихнуть в нее буквы, дроби и прочие неподходящие символы, она чувствительна к превышению диапазона значений типа Integer во входном числе и не обрабатывает его.

5. Работа с текстовыми файлами данных произвольного формата. Пусть существует файл из N столбцов цифр, содержащий в некоторых строках словесные комментарии вме-

— 266 —

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

| CONST N=3; { пусть в файле данные даны в трех столбцах }

| VAR

| f : Text; { текст-файловая переменная }

| i : Byte; { счетчик }

| D : Array [1..N] of Real; { значения одной строки }

| { данных в формате Real }

| BEGIN

| Assign(f,’EXAMPLE.DAT’); { связывание файла f }

| Reset( f ); { открытие файла для чтения }

| {$I-} { отключение режима проверки }

| while not SeekEOF(f) do { Цикл до конца файла: }

| begin

| Read( f, D[1] ); { попытка считать 1-е число }

| if IOResult=0 { Если это удалось,то затем }

| then begin { читаются остальные числа: }

| for i:=2 to N do Read( f, D[i] );

| { и как-либо обрабатываются: }

| WriteLn( D[1]:9:2, D[2]:9:2, D[3]:9:2 )

| end; {if 10…}

| ReadLn( f ) { переход на следующую строку }

| end; {while} { конец основного цикла }

| {$I+} { включение режима проверки }

| Close( f ); { закрытие файла f }

| ReadLn { пауза до нажатия ввода }

| END.

Рис. 12.15

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

Обращаем внимание на то, что во всех примерах подразумевается общий режим компиляции {$I+}, который в них всегда восстанавливается после завершения операции ввода-вывода. Советуем компилировать программы и модули в режиме {$I+}, используя его отключение только там, где действительно нужно обработать ошибку.

7.4 Обработка текстовых файлов в языке Free Pascal

При работе с текстовыми файлами следует учесть следующее:

  1. Действие процедур reset, rewrite, close, rename, erase и функции eof аналогично их действию при работе с компонентными (типизированными) файлами.
  2. Процедуры seek, trunсate и функция filepos не работают с текстовыми файлами.
  3. Можно пользоваться процедурой открытия текстового файла append(f), где f — имя файловой переменной. Эта процедура служит для открытия файла в режиме дозаписи в конец файла. Она применима только к уже физически существующим файлам, открывает и готовит их для добавления информации в конец файла.
  4. Запись и чтение в текстовый файл осуществляются с помощью процедур 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 диск защищён от записи

Рассмотрим несколько практических примеров обработки ошибок ввода-вывода:

  1. При открытии проверить, существует ли заданный файл и возможно ли чтение данных из него.
    assign ( f, ’ abc. dat ’ );
    {$I-}
    reset ( f );
    {$I+}
    if IOResult<>0 then
    writeln ( ’файл не найден или не читается ’ )
    else
    begin
    read ( f,... );
    close ( f );
    end;
    
  2. Проверить, является ли вводимое с клавиатуры число целым.
    var i : integer;
    begin
    {$I-}
    repeat
    write ( ’введите целое число  i ’ );
    readln ( i );
    until ( IOResult =0);
    {$I+}
    {Этот цикл повторяется до тех пор, пока не будет введено целое число.}
    end.
    

При работе с текстовым файлом необходимо помнить специальные правила чтения значений переменных:

  • Когда вводятся числовые значения, два числа считаются разделёнными, если между ними есть хотя бы один пробел, или символ табуляции, или символ конца строки.
  • При вводе строк начало текущей строки идёт сразу за последним, введённым до этого символом. Вводится количество символов, равное объявленной длине строки. Если при чтении встретился символ «конец строки», то работа с этой строкой заканчивается. Сам символ конца строки является разделителем и в переменную никогда не считывается.
  • Процедура readln считывает значения текущей строки файла, курсор переводится в новую строку файла, и дальнейший ввод осуществляется с неё.

В качестве примера работы с текстовыми файлами рассмотрим следующую задачу.

ЗАДАЧА 7.8. В текстовом файле abc.txt находятся матрицы A(N, M ) и B(N, M ) и их размеры. Найти матрицу C = A + B, которую дописать в файл abc.txt.

Сначала создадим текстовый файл abc.txt следующей структуры: в первой строке через пробел хранятся размеры матрицы (числа N и M), затем построчно хранятся матрицы A и B.

Файл abc.txt

Рис.
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.

Файл abc.txt после дозаписи матрицы C

Рис.
7.15.
Файл abc.txt после дозаписи матрицы C

Понравилась статья? Поделить с друзьями:
  • Partlibclient dll исправить ошибку
  • Partition magic ошибка 116
  • Partition magic ошибка 0x12015
  • Paragon ошибка ввода вывода на жестком диске
  • Paragon выдает ошибку