在 Ada 中打开、写入和追加的过程

发布于 2024-09-07 18:11:33 字数 3047 浏览 9 评论 0 原文

这个问题是

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;
  2. 文件名:字符串; | <块引用> <块引用> <块引用>

    不允许使用不受约束的子类型(需要初始化) 提供初始值或显式数组边界

我不知道两件事:

  1. 我有 File_Name : String;因为我希望能够写入不同的文件。所以我想要一个通用字符串,而不是类似:

File_Name : CONSTANT String := "one_File_Only.dat"

  1. 将过程 Open_Data 保存在单独的 ads 和 adb (用于正文)文件中会更好吗?

非常感谢...


新...

我已将代码修改如下:

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。抱歉各位,我不知道该放什么。

我非常感谢你的帮助。谢谢

This question is a follow-up of the post at

Ada file operation: instantiation and exception

about writing to files in Ada.

I chose to place this question in a separate post so that it'll become visible to more people as I already accepted an answer on a slightly different issue (which was on exceptions in file handling) in that aforementioned post.

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;

On compiling the above I get an error as follows:

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

      unconstrained subtype not allowed (need initialization)
      provide initial value or explicit array bounds

I don't know 2 things:

  1. I have File_Name : String; as I want to be able to write to different files. So I want a general string and not something like:

File_Name : CONSTANT String := "one_File_Only.dat"

  1. Would it be better to save the procedure Open_Data in separate ads and adb (for the body) files?

Thanks a lot...


NEW...

I've modified the code as follows:

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;

As you see I have

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

I have put Name_X as the parameter that Name is taking but this is not right as I should be able to pass in a general name which can be either Name_X or Name_Y. Sorry guys, I can't figure out what to put here.

I would much appreciate your help. Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盛夏已如深秋| 2024-09-14 18:11:34

Ada 中的普通 String 的问题在于,特定的字符串(如您的 File_Name)必须是固定长度的;但不同的字符串可以有不同的长度。

您可以这样写,

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

在这种情况下,S1 的长度为 4,并且对其赋值的长度必须为 4。您可以这样写,

S1 := "abcd";

但如果您尝试这样写

S1 := "pqrst";

,否则

S1 := S2;

您将收到 Constraint_Error

对于子程序的字符串参数(例如 Open_Data),字符串参数 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 =>;文件部分。第一个 FileSeq_Float_IO.Open 形参的名称,第二个 File 是要传递的内容,在本例中 < code>Open_Data 的 File 参数。

如果我指出我可以将上面的调用写为

Open_Data (File => X_File, Name => "x.dat");
Open_Data (File => Y_File, Name => "a_very_long_name.dat");

The thing about plain String in Ada is that a particular string, like your File_Name, has to be fixed-length; but different Strings can be of different length.

You can write

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

in which case S1 is of length 4, and assignments to it have to be of length 4. You can write

S1 := "abcd";

but if you try to write

S1 := "pqrst";

or

S1 := S2;

you will get a Constraint_Error.

In the case of String parameters to subprograms, like your Open_Data, the String parameter Name takes on the length -- and of course the value! of the actual parameter in the call. So you can say

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

You were having problems earlier with

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 => ????);

I'm reluctant to just tell you the answer, so -- consider the File => File part. The first File is the name of the formal parameter of Seq_Float_IO.Open and the second File is what is to be passed, in this case Open_Data's File parameter.

It might help if I point out that I could have written the calls above as

Open_Data (File => X_File, Name => "x.dat");
Open_Data (File => Y_File, Name => "a_very_long_name.dat");
行雁书 2024-09-14 18:11:34

@Simon Wright 的答案是正确的,您可能会发现将他的答案与我之前写的第二个进行比较很有帮助。请注意,如果您有

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

字符串 Name_XName_Y,则可以用作 Open_Data 的实际 Name 参数。形式参数Name 的类型为StringString 不受约束,它可以是任何(实现定义的)最大长度。相反,Name_XName_Y 各自具有由其初始分配确定的固定长度。

附录:您编写了一个具有 String 类型的形参(Name)的子程序,具有此签名

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

在实现中,您希望转发到 Open 您作为实际参数 (Name) 收到的 String,而不是全局常量的名称 (Name_X)。

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

@Simon Wright's answer is correct, and you may find it helpful to compare his answer to the second one I wrote earlier. Note that if you had

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

Either string, Name_X or Name_Y, could be used as the actual Name parameter to Open_Data. The formal parameter, Name, is of type String. String is unconstrained, and it may be any (implementation-defined) maximum length. In contrast, Name_X and Name_Y each have a fixed length determined by their initial assignment.

Addendum: You wrote a subprogram with a formal parameter (Name) of type String, having this signature

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

In the implementation, you want to forward to Open the String you received as the actual parameter (Name), not the name of a global constant (Name_X).

Seq_Float_IO.Open (
    File => File,
    Mode => Seq_Float_IO.Append_File,
    Name => Name );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文