Процедура, чтобы открыть, написать и добавить в Ada - PullRequest
2 голосов
/ 03 июля 2010

Этот вопрос является продолжением сообщения на

Операция над файлом Ada: создание и исключение

о записи в файлы в Ada.

Я решил разместить этот вопрос в отдельном посте, чтобы он стал виден большему количеству людей, поскольку я уже принял ответ на немного другую проблему (которая касалась исключений в обработке файлов) в этом вышеупомянутом посте. *

WITH Ada.Sequential_IO;
WITH Ada.Float_Text_IO;

PROCEDURE TEST is

package Seq_Float_IO is new Ada.Sequential_IO (Element_Type => Float);
X_File : Seq_Float_IO.File_Type;
File_Name : String;


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

BEGIN

   begin
      Seq_Float_IO.Open (
         File => File,
         Mode => Seq_Float_IO.Append_File,
         Name => File_Name );
   exception
      when Seq_Float_IO.Name_Error =>
      Seq_Float_IO.Create (
         File => File,
         Mode => Seq_Float_IO.Out_File,
         Name => File_Name);
   end;

END Open_Data;


x        : CONSTANT Float := 2.0;


BEGIN --main program
   Open_Data(X_File, "xvalues.dat");
   Seq_Float_IO.Write(File => X_File,Item => x);

   Seq_Float_IO.Close(File => X_File);
END TEST;

При компиляции вышесказанного я получаю сообщение об ошибке:

  1. X_File: Seq_Float_IO.File_Type;
    1. File_Name: String; |

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

Я не знаю 2 вещей:

  1. У меня есть File_Name: String; как я хочу, чтобы иметь возможность записи в разные файлы. Поэтому я хочу общую строку, а не что-то вроде:

File_Name: CONSTANT String: = "one_File_Only.dat"

  1. Было бы лучше сохранить процедуру Open_Data в отдельных файлах объявлений и adb (для тела)?

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


NEW ...

Я изменил код следующим образом:

WITH Ada.Sequential_IO;

PROCEDURE TEST1 is

package Seq_Float_IO is new Ada.Sequential_IO (Element_Type => Float);
X_File, Y_File : Seq_Float_IO.File_Type;
Name_X : CONSTANT String := "domainvalues.dat";
Name_Y : CONSTANT String := "ordinatevalues.dat";


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

BEGIN

   begin
    Seq_Float_IO.Open (
         File => File,
         Mode => Seq_Float_IO.Append_File,
         Name => Name_X );
    exception
      when Seq_Float_IO.Name_Error =>
         Seq_Float_IO.Create (
            File => File,
            Mode => Seq_Float_IO.Out_File,
            Name => Name_X);
   end;

END Open_Data;


x        : CONSTANT Float := 2.0;


BEGIN --main program
   Open_Data(File => X_File, Name => Name_X);
   Seq_Float_IO.Write(File => X_File, Item => x);
   Seq_Float_IO.Close(File => X_File);

   Open_Data(File => Y_File, Name => Name_Y);
  Seq_Float_IO.Write(File => Y_File, Item => x);
  Seq_Float_IO.Close(File => Y_File);

END TEST1;

Как видите, у меня

Seq_Float_IO.Open (
             File => File,
             Mode => Seq_Float_IO.Append_File,
             Name => Name_X );

Я указал Name_X в качестве параметра, который принимает Name, но это неверно, так как я должен иметь возможность передавать общее имя, которое может быть либо Name_X, либо Name_Y. Извините, ребята, я не могу понять, что здесь поставить.

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

Ответы [ 2 ]

3 голосов
/ 04 июля 2010

Что касается простого String в Аде, то это то, что определенная строка, такая как ваша File_Name, должна быть фиксированной длины;но разные строки могут быть разной длины.

Вы можете написать

S1 : String := "1234";
S2 : String := "12345";

, в этом случае S1 имеет длину 4, а присваивания для него должны быть длины 4. Вы можете написать

S1 := "abcd";

, но если вы попытаетесь написать

S1 := "pqrst";

или

S1 := S2;

, вы получите Constraint_Error.

.Если в качестве параметров String используются подпрограммы, например, Open_Data, параметр String Name принимает длину и, конечно, значение!фактического параметра в вызове.Таким образом, вы можете сказать

Open_Data (X_File, "x.dat");
Open_Data (Y_File, "a_very_long_name.dat");

У вас раньше были проблемы с

procedure Open_Data(File : in out Seq_Float_IO.File_Type; 
                    Name : in String) is
begin
   Seq_Float_IO.Open (File => File,
                      Mode => Seq_Float_IO.Append_File,
                      Name => ????);

Я не хочу просто сказать вам ответ, поэтому рассмотрим часть File => File.Первый File - это имя формального параметра Seq_Float_IO.Open, а второй File - то, что должно быть передано, в этом случае Open_Data 'File параметр.

Можетпомогите, если я укажу, что я мог бы написать выше звонки как

Open_Data (File => X_File, Name => "x.dat");
Open_Data (File => Y_File, Name => "a_very_long_name.dat");
2 голосов
/ 04 июля 2010

@ Ответ Саймона Райта верный, и вам может быть полезно сравнить его ответ со вторым , который я написал ранее. Обратите внимание, что если у вас было

Name_X : constant String := "domainvalues.dat";
Name_Y : constant String := "ordinatevalues.dat";

Любая строка, Name_X или Name_Y, может использоваться в качестве фактического параметра Name для Open_Data. Формальный параметр Name имеет тип String. String не ограничен и может быть любой (определенной реализацией) максимальной длиной. Напротив, Name_X и Name_Y каждый имеют фиксированную длину, определяемую их начальным назначением.

Приложение: Вы написали подпрограмму с формальным параметром (Name) типа String, имеющую эту подпись

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

В реализации вы хотите переслать Open String, которое вы получили в качестве фактического параметра (Name), а не имя глобальной константы (Name_X).

Seq_Float_IO.Open (
    File => File,
    Mode => Seq_Float_IO.Append_File,
    Name => Name );
...