Ада: добавление исключения в отдельную процедуру при чтении файла

Это продолжение этого вопроса: Ada: чтение из файла .

Я хотел бы добавить exception, который проверяет, действительно ли файл, который я открываю, существует или нет. Я сделал процедуру separate, чтобы избежать беспорядка в коде.

Вот основной код test_read.adb:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Long_Float_Text_IO;
with Ada.Float_Text_IO;


procedure Test_Read is

   Input_File    : File_Type;
   Value         : Long_Float;

procedure Open_Data (File : in  Ada.Text_IO.File_Type; Name : in String) is separate;

begin

   Ada.Text_IO.Open (File => Input_File, Mode => Ada.Text_IO.In_File, Name => "fx.txt");

   while not End_Of_File (Input_File) loop
      Ada.Long_Float_Text_IO.Get (File => Input_File, Item => Value);
      Ada.Long_Float_Text_IO.Put (Item => value, Fore => 3, Aft  => 5, Exp  => 0);
      Ada.Text_IO.New_Line;
   end loop;
   Ada.Text_IO.Close (File => Input_File);

end Test_Read;

А вот separate тело test_read-open_data.adb процедуры Open_Data:

separate(test_read)
procedure Open_Data (File : in  out Ada.Text_IO.File_Type; 
                     Name : in String) is

   --this procedure prepares a file for reading
   begin
      begin
       Ada.Text_IO.Open
         (File => File,
          Mode => Ada.Text_IO.In_File,
          Name => Name);
       exception
       when Ada.Text_IO.Name_Error =>
          Ada.Text_IO.Put(File => Standard_Error, Item => "File not found.");
      end;
end Open_Data;

При компиляции я получаю сообщение об ошибке в теле separate test_read-open_data.adb:

actual for "File" must be a variable

Как это исправить?

Большое спасибо...

Обновление:

Теперь я сделал следующие исправления.

  1. В test_read.adb теперь у меня procedure Open_Data (File : in out Ada.Text_IO.File_Type; Name : in String) is separate;

  2. Обновлено определение той же процедуры Open_Data в test_read-open_data.adb.

Программа хорошо компилируется, хотя я не вижу, чтобы она перехватывала исключение, скажем, если я переименовал файл fx.txt в fy.txt. Сообщение об ошибке, которое я получаю, просто

raised ADA.IO_EXCEPTIONS.NAME_ERROR : fx.txt: No such file or directory

Поэтому я не получаю собственное сообщение об ошибке: Файл не найден.

Что еще не так?


person yCalleecharan    schedule 20.03.2012    source источник
comment
вы открываете файл, используя Ada.Text_IO.Open, а не свою собственную Open_Data процедуру.   -  person Rommudoh    schedule 21.03.2012
comment
@oenone Да, ты прав. Я полностью пропустил это. Это было причиной проблемы. 1 голос вверх.   -  person yCalleecharan    schedule 21.03.2012
comment
Для вашего обновления вы просто пытаетесь поймать неправильное исключение. Вместо того, чтобы ловить Ada.Text_IO.Name_Error, вы должны ловить Ada.IO_Exceptions.Name_Error. Полезно читать сообщения об ошибках, выдаваемые вашей программой. В этом случае ясно, что возникло исключение Ada.IO_Exceptions.Name_Error.   -  person Schedler    schedule 21.03.2012
comment
@ Schedler Я получаю ADA.IO_EXCEPTIONS.STATUS_ERROR либо при использовании when Ada.Text_IO.Name_Error =>, либо при использовании Ada.IO_Exceptions.Name_Error =>. Так что я не получаю Ada.IO_Exceptions.Name_Error. И это неправильно . Итак, как это исправить? 1 голос вверх!   -  person yCalleecharan    schedule 21.03.2012
comment
@Schedler Если вы посмотрите в конец adaic.org/resources/add_content/standards/05rm/html/ вы увидите, что Ada.Text_IO.Name_Error — это переименование Ada.IO_Exceptions.Name_Error. Так что подойдет любое имя.   -  person Simon Wright    schedule 21.03.2012
comment
Я сделал новый пост [здесь] stackoverflow.com/questions/9804239/, так как этот становится слишком длинным.   -  person yCalleecharan    schedule 21.03.2012
comment
@SimonWright Спасибо за информацию - я не знал об этом. Думая об этом, это имеет смысл, да.   -  person Schedler    schedule 22.03.2012


Ответы (4)


Параметр File Open_Data должен быть параметром in out (как, например, Ada.Text_IO.Create), потому что вы хотите, чтобы открытый файл был доступен в пределах Test_Read.

Вы получаете actual for "File" must be a variable, потому что параметр in доступен только для чтения.

procedure Open_Data (File : in out Ada.Text_IO.File_Type; 
                     Name : in     String) is

(Лично я редко набираю режим in, потому что он стоит по умолчанию).

Но в любом случае похоже, что причина наблюдаемого поведения в том, что Test_Read на самом деле не вызывает Open_Data!

(отредактировано, чтобы сделать рекомендуемый режим in out и предложить позвонить Open_Data)

person Simon Wright    schedule 20.03.2012
comment
@ Саймон Райт Спасибо. Я внес необходимые изменения, но мое исключение не было обнаружено, как я намеревался. См. обновленную часть поста. 1 голос вверх. - person yCalleecharan; 21.03.2012
comment
Я не проверял это, но я думаю, что это как-то связано с Ada.IO_Exceptions.Name_Error против Ada.Text_IO.Name_Error. Для отладки вы можете добавить when others => ... для проверки неожиданных исключений. - person Ansgar Esztermann; 21.03.2012
comment
@ Ансгар Эстерманн when others => ... не имеет значения. Я все еще получаю то же сообщение об ошибке, что и в моем сообщении. 1 голос вверх. - person yCalleecharan; 21.03.2012
comment
@ Ansgar Esztermann Если вместо этого поставить when Ada.IO_Exceptions.Name_Error =>, вы получите то же сообщение об ошибке. - person yCalleecharan; 21.03.2012
comment
Использование Open_Data (File => Input_File, Name => "fx.txt"); вместо неправильного Ada.Text_IO.Open (File => Input_File, Mode => Ada.Text_IO.In_File, Name => "fx.txt"); решает проблему. Я получаю сообщение: Файл не найден.... Выполнение прекращено из-за необработанного исключения Имя исключения: ADA.IO_EXCEPTIONS.STATUS_ERROR Сообщение: файл не открыт - person yCalleecharan; 21.03.2012
comment
ADA.IO_EXCEPTIONS.STATUS_ERROR не то, чего можно было ожидать. - person yCalleecharan; 21.03.2012
comment
Вызывающий не может сказать, сработал вызов Open_Data или нет, поэтому он продолжает и пытается прочитать из Input_File, который не открыт, отсюда и Status_Error. Можно было вызвать Text_IO.Is_Open (лично я бы не стал обрабатывать исключение в подпрограмме, но это ваша разработка). - person Simon Wright; 21.03.2012
comment
@ Саймон Райт Хорошо. но как бы вы обработали исключение. Да, это мой дизайн, и если он несовершенен, пожалуйста, покажите мне правильный способ сделать что-то. 1 голос вверх. - person yCalleecharan; 21.03.2012
comment
В AQ&S есть хорошее общее руководство, adaic.org. /resources/add_content/docs/95style/html/sec_5/. В вашем случае вызывающий Open_Data явно ожидает, что будет использоваться Text_IO, поэтому для него кажется разумным распространять Name_Error, а не пытаться обработать его самостоятельно или создать другое исключение. Затем вызывающий абонент (Test_Read) должен решить, что делать; в этом случае я бы поместил ваш обработчик исключений в конец Test_Read и просто позволил бы ему завершиться. Если вы действительно хотите вывести сообщение в Open_Data, рассмотрите возможность добавления оператора raise после этого? - person Simon Wright; 21.03.2012
comment
@ Саймон Райт Спасибо за ссылку и за объяснение. Если мне нужно открыть несколько файлов (что я действительно и делаю), то можно ли поместить исключения в основной файл test_read.adb? 1 голос вверх. - person yCalleecharan; 21.03.2012
comment
На этом уровне нет никакой разницы между возбуждением исключения и возвратом логического значения Status. Вам все еще нужно решить, что делать, если вы не можете открыть 7-й из 8 файлов; можете ли вы предоставить подходящие значения по умолчанию, или вам все равно придется спасаться? Вы, вероятно, использовали бы структуру begin попытаться открыть exception сделать что-то end для каждого файла, где действие может включать return (которое завершает текущую процедуру). - person Simon Wright; 21.03.2012

если ваша цель — просто проверить, существует ли файл, рассмотрите возможность использования Ada.Directories.Exists

person jdex    schedule 21.03.2012
comment
@ Jarrod Я делаю это так, как описано выше, так как тогда я могу добавить другие исключения по мере необходимости, например, Use_Error и Status_Error. 1 голос вверх. - person yCalleecharan; 21.03.2012

IIRC: Standard_Error — это не файл, а поток.

person Shark8    schedule 20.03.2012
comment
он действительно похож на один: function Standard_Error return File_Type; - person Rommudoh; 21.03.2012

Я подозреваю, что причина, по которой вы не видите свое сообщение об ошибке, заключается в том, что вы используете Put, а не Put_Line. Различные реализации/платформы по-разному обрабатывают вывод на дисплей пользователя. Чтобы быть уверенным, что вы увидите сообщение, после Put_Line следует Get_Line. Get_Line обычно заставляет вывод Put_Line.

person eryndlia    schedule 23.03.2012