简单的ada程序使用get_line()和put_line()产生错误的空行

时间:2019-03-28 13:56:43

标签: stdin ada

我在一个较大的程序中遇到了这个问题,所以我制作了一个新的ada程序对其进行测试,我得到了相同的结果。

我有一个文本文件(Unix行尾):

000_1000_0010_1001
100_0000_0010_1001
100_1000_0000_1001
100_1000_0010_0001
100_1000_0010_1001
000_0000_0011_0011
100_1000_0100
000_0000_0110
111_1111_1111
011_1111_1111
000_0000_0110

我想要做的很简单,将每行放在一个字符串中,然后直接打印出来即可。

这是我的代码:

with Ada.Text_IO; use Ada.Text_IO;
procedure Read is
   input: String(1..18);
   len: Natural;
begin
   while not End_Of_File loop
      Get_Line(input, len);
      Put_Line(input(1..len));
   end loop;

end Read;

容易吗?它使用get_line接收每一行,将其保存到“ input”变量,然后打印出所读取的任何量(使用get_line()返回的长度。

不幸的是,运行此代码时,我得到了一堆空白行:

gnatmake read read.adb
read < input.txt
000_1000_0010_1001

100_0000_0010_1001

100_1000_0000_1001

100_1000_0010_0001

100_1000_0010_1001

000_0000_0011_0011

100_1000_0100
000_0000_0110
111_1111_1111
011_1111_1111
000_0000_0110

我已经仔细检查并确保输入文件中没有任何怪异的行尾字符或类似的字符(我只是在vim中将其键入)。

这弄乱了我的程序,因为我必须考虑这些错误的空行。

知道我在做什么错吗?

2 个答案:

答案 0 :(得分:5)

您的input变量可以容纳18个字符,而Get_Line知道这一点,因此,当您的输入行长度超过18个字符时,它将仅读取18个字符。然后它将继续读取同一行,直到读取了另外18个字符或到达行尾为止。在您的情况下,输入行完全是 18个字符(不计算行尾),当到达行尾且没有任何字符读入input时,这看起来很奇怪变量(len返回0)...

您可以将input缓冲区的长度增加到大于您可以想到的任何输入的长度,或者通过使用function Get_Line return String;让运行时找出行的长度:

with Ada.Text_IO; use Ada.Text_IO;
procedure Read is
begin
   while not End_Of_File loop
      declare
         input : String := Get_Line;
      begin
         Put_Line(input);
      end;
   end loop;
end Read;

答案 1 :(得分:0)

除了egilhh的答案,

首先要了解背景:文本行可能比提供的字符串长,因此行读取不完整,需要多次调用Get_Line才能读取整行。

要检测这种情况,应用程序只需检查字符串是否已满,然后读取其余部分。为此,Get_Line将匹配长度的情况视为不完整的行,从而使行的“其余”(0个字符)未读。

因此,存在另一种解决方案:

   while not End_Of_File loop
      Get_Line(input, len);
      if len < input'Last then
          Put_Line(input(1..len)); -- whole (or the rest of previous) line read,
      else
          Put(input); -- (non-final) part of long line read, do not go to next
      end if;
   end loop;

   while not End_Of_File loop
      Get_Line(input, len);
      Put(input(1..len)); -- do not emit eol yet...
      if len < input'Last then
          New_Line; -- now we know: line is finished
      end if;
   end loop;