在ada中的文件IO,如何将字符串写入文件?

时间:2011-06-26 12:10:18

标签: string io ada

我有一些关于将String变量写入文件的问题。 问题是我必须指定该String的确切长度。否则输出文件将只包含一些废料值。我想知道这是否可以以某种方式解决,而无需事先告诉String的长度?

我知道我的Get()过程存储了该变量的长度,我只能将它返回给主程序。但是我想编写我的程序,所以它会在我开始写入out文件之前先从输入文件中读取所有内容。

with  Ada.Text_Io, Ada.Integer_Text_Io;
use Ada.Text_Io,Ada.Integer_Text_Io;

procedure Uppgift is

   type Bil_Register is
      record
     Namn    : String(1..50);
     Adress  : String(1..50);
     Post    : String(1..50);
     Reg     : String(1..6);
      end record;   

   Infil  : File_Type;
   Utfil        : File_Type;
   L, I : Integer;

   Br : Bil_Register;

   procedure Get(F : in out File_Type; Br : out Bil_Register) is
      Length : Integer;
   begin
      Get_Line(F, Br.Namn, Length);      
   end;

begin

   Open(Infil, In_File, "register.txt");
   Create(Utfil, Out_File, "test.txt");

   Get(Infil, Br);
   Put_Line(Utfil, Br.Namn);

   Close(Infil);
   Close(Utfil);

end Uppgift;

-

编辑(2011.08.20)

这似乎只是基于Unix的操作系统的一个问题。使用Windows时,将其打印到文件或屏幕

时,不必使用字符串大小

3 个答案:

答案 0 :(得分:6)

嗯,必须在某处跟踪字符串有效部分的长度。

您可以将每个记录的字符串字段的有效长度保持为单独的字段:

Namn        : String (1..50);
Namn_Length : Natural;

您可以定义自己的变量字符串类型包,或使用预先存在的变量字符串类型包,例如Variable_Length。 E.g。

Namn : Variable_Length.Variable_String(50);

您可以对字段和变量使用Unbounded_String:

Namn : Unbounded_String;

{/ 3}}用于I / O:

with Ada.Strings.Unbounded;
use Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO;

procedure UTIO_Demo is

   use Ada.Text_IO;

   F    : Ada.Text_IO.File_Type;
   Data : Unbounded_String := To_Unbounded_String("Output by Unbounded_IO");

begin
   Create(F, Ada.Text_IO.Out_File, "utio.tst");

   Unbounded_IO.Put_Line(F, Data);

   Close(F);
end UTIO_Demo;

如果您不想使用Unbounded_IO包,请使用To_String和To_Unbounded_String在Unbounded_String值和通过Text_IO读取和写入的字符串之间来回转换。

答案 1 :(得分:2)

我个人只是按照Marc C的建议使用Unbounded_String,但如果你想避免这种情况,你可以这样做:

with Ada.Text_IO;
with Ada.Containers.Indefinite_Doubly_Linked_Lists;

use Ada.Text_IO;
use Ada.Containers;

procedure Uppgift is

   type Bil_Register (Namn_Length : Natural) is
      record
         Namn    : String (1 .. Namn_Length);
         --  Other components removed for brevity.
      end record;   

   package BR_Container is new Indefinite_Doubly_Linked_Lists (Bil_Register);
   use BR_Container;

   BR_List        : BR_Container.List;
   BR_List_Cursor : BR_Container.Cursor;
   Buffer         : String (1 .. 100);
   Length         : Natural;
   Register_File  : File_Type;
   Test_File      : File_Type;

begin

   --  First we read the contents of register.txt and add all the data to
   --  our list of Bil_Register objects.
   Open (File => Register_File,
         Mode => In_File,
         Name => "register.txt");

   while not End_Of_File (File => Register_File) loop
      Get_Line (File => Register_File,
                Item => Buffer,
                Last => Length);
      declare
         BR : Bil_Register 
           (Namn_Length => Length);
      begin
         BR.Namn := Buffer (1 .. Length);
         BR_List.Append (New_Item => BR);
      end;
   end loop;

   Close (File => Register_File);

   --  Then we output the contents of our list of Bil_Register objects to 
   --  test.txt
   Create (File => Test_File,
           Mode => Out_File,
           Name => "test.txt");

   BR_List_Cursor := BR_List.First;
   while Has_Element (Position => BR_List_Cursor) loop
      Put_Line (File => Test_File,
                Item => Element (Position => BR_List_Cursor).Namn);
      Next (Position => BR_List_Cursor);
   end loop;

   Close (File => Test_File); 

end Uppgift;

我将读写分为两个块,因为你说:

  

...从输入文件中读取所有内容   在我开始写作之前   出文件

显然,使用此方法,您将必须适当地调整Buffer变量的大小。但实际上,与仅使用Unbounded_String相比,它非常笨拙。我会说,除非你有一些非常具体的问题或要求,否则Unbounded_String可能就是这样。它会极大地简化事情。

祝你好运! :O)

答案 2 :(得分:0)

一般来说,你可以逃脱,而不必在Ada中有一个特殊的“长度”变量。可悲的是,这种情况很难实现。

但是有一个技巧可以让你在这种情况下这样做。如果你不介意一点递归,或者不要指望你的字符串非常长,或者不太关心执行速度(你正在做一个I / O,所以它会很慢) 。如果这听起来不错,请尝试Carlisle's trick

function Next_Line(File : in Ada.Text_IO.File_Type :=
   Ada.Text_Io.Standard_Input) return String is
   Answer : String(1..256);
   Last   : Natural;
begin
   Ada.Text_IO.Get_Line(File => File,
      Item => Answer,
      Last => Last);
   if Last = Answer'Last then
      return Answer & Next_Line(File);
   else
      return Answer(1..Last);
   end if;
end Next_Line;

现在您可以将代码更改为:

begin

   Open(Infil, In_File, "register.txt");
   Create(Utfil, Out_File, "test.txt");

   Put_Line(Utfil, Next_Line (Infil));

   Close(Infil);
   Close(Utfil);

end Uppgift;