我有一些关于将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时,将其打印到文件或屏幕
时,不必使用字符串大小答案 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;