【问题标题】:File IO in ada, how to write Strings to file?ada中的文件IO,如何将字符串写入文件?
【发布时间】:2011-09-22 22:49:12
【问题描述】:

我在将字符串变量写入文件时遇到了一些问题。 问题是我必须指定该字符串的确切长度。否则输出文件将只包含一些废品值。我想知道是否可以以某种方式解决这个问题而无需事先告知字符串的长度?

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

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 时,当您将其打印到文件或屏幕时,您不必绝对使用字符串大小

【问题讨论】:

    标签: string io ada


    【解决方案1】:

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

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

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

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

    Namn : Variable_Length.Variable_String(50);
    

    您可以将 Unbounded_String 用于字段和变量:

    Namn : Unbounded_String;
    

    Ada.Text_IO.Unbounded_IO 用于 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 读取和写入的字符串之间来回转换。

    【讨论】:

    • 当你使用 Unbounded_String 进行文件 I/O 时,你碰巧有一些例子吗?我无法让它工作。
    • 我用我拼凑的一个快速演示编辑了这个问题。请注意,您正在使用的文件是 Ada.Text_IO 的 File_Type。
    【解决方案2】:

    通常,您无需在 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;
    

    【讨论】:

    • 我试图使用 unbounded_string,但是我收到一些抱怨说我正在尝试使用它,但它却收到了一个普通的字符串。你碰巧没有一个简单的例子如何用它来读/写文件?
    【解决方案3】:

    我个人会按照 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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      相关资源
      最近更新 更多