Ada 程序检测行尾

Art*_*hur 2 ada

我被分配这项任务作为我的家庭作业。我有一个文件,其中包含不同长度的文本行。该程序应该按照与写入文件的顺序完全相同的顺序将数据写入屏幕,但它未能这样做。为了达到预期的结果,我尝试每次迭代仅读取一个字符,以便检测新行字符。我究竟做错了什么?

WITH Ada.Text_IO;
WITH Ada.Characters.Latin_1;
USE Ada.Text_IO;

PROCEDURE ASCII_artwork IS
   File : File_Type;
   c : Character;
BEGIN
   Open(File, In_File, "Winnie_The_Pooh.txt");
   WHILE NOT End_Of_File(File) LOOP
      Get(File, C);
      IF (C = Ada.Characters.Latin_1.LF) THEN Put_Line(" "); ELSE
         Put(C);
      END IF;
   END LOOP;
   Close(File);
END ASCII_Artwork;
Run Code Online (Sandbox Code Playgroud)

Dee*_*Dee 5

对于每个文件,Ada 运行时都维护一个虚构的“光标”。这不是典型的文件位置光标(索引),而是指示页面、行等上的位置的光标(另请参见RM A.10 (7))。这在某种程度上继承了 Ada 的早期版本。

Get源于同一时代,并且预计在读取某些特定控制字符(例如行尾标记)时更新此光标的位置。如果Get读取这样的控制字符,它只会使用它来更新光标(内部),然后继续读取下一个字符(另请参见RM A.10.7(3))。因此,在使用 时,您永远不会检测到行尾标记Get。

然而,这种行为会产生一些令人不舒服的后果:如果文件以一系列控制字符结尾,则将Get继续读取这些字符并到达文件末尾,从而导致异常End_Error。

当然,您可以捕获此异常并处理它,但这样的构造是可疑的,因为在文件末尾有一系列控制字符实际上并不是这样的异常情况(因此如果值得异常则值得怀疑)。然而,作为一名程序员,您无法更改此行为:它是由语言定义的,并且语言不会更改,因为它已决定保持 Ada(高度)向后兼容(考虑到其应用领域,这本身是可以理解的)。

因此,就您的情况而言,如果您想坚持逐字符处理方法,我建议您放弃Get并使用(例如)流来执行 I/O,如下例所示。

主程序.adb

with Ada.Text_IO;              use Ada.Text_IO;
with Ada.Text_IO.Text_Streams; use Ada.Text_IO.Text_Streams;

procedure ASCII_artwork IS
   File   : File_Type;
   Input  : Stream_Access;
   Output : Stream_Access;
   C      : Character;
begin

   Open (File, In_File, "Winnie_The_Pooh.txt");

   Input  := Stream (File);
   Output := Stream (Standard_Output);

   while not End_Of_File (File) loop      
      Character'Read (Input, C);
      Character'Write (Output, C);      
   end loop;

   Close(File);

end ASCII_Artwork;
Run Code Online (Sandbox Code Playgroud)

输出符合预期(即ascii-art.de文件的内容)。

注意:检查GNAT 运行时的源代码以实际了解Get其内部工作原理(重点关注最后的循环)。