ada - 检测行尾的 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;
解决方案
对于每个文件,Ada 运行时维护一个虚构的“光标”。这不是典型的文件位置光标(索引),而是指示页面、行等位置的光标(另见RM A.10 (7))。这在某种程度上是 Ada 早期版本的继承。
Get
源于同一时代,预计在读取某些特定控制字符(例如行尾标记)时更新此光标的位置。如果Get
读取这样的控制字符,它将仅使用它来更新光标(内部),然后继续读取下一个字符(另见RM A.10.7 (3))。因此,您在使用时永远不会检测到行尾标记Get
。
然而,这种行为会带来一些令人不安的后果:如果文件以一系列控制字符结尾,那么Get
将继续读取这些字符并到达文件末尾,从而导致End_Error
异常。
当然,您可以捕获此异常并处理它,但这种构造是可疑的,因为在文件末尾具有一系列控制字符实际上并不是这种异常情况(因此如果值得异常,则值得怀疑)。但是,作为程序员,您无法更改此行为:它由语言定义,并且语言不会更改,因为已决定保持 Ada(高度)向后兼容(考虑到其应用领域,这本身是可以理解的)。
因此,在您的情况下,如果您想坚持逐个字符的处理方法,我建议您远离Get
并使用(例如)流来执行 I/O,如下例所示。
主文件
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;
输出符合预期(即ascii-art.de文件的内容)。
注意:检查GNAT 运行时的源代码以实际了解Get
内部是如何工作的(关注最后的循环)。
推荐阅读
- django - OSMGeoAdmin:导入的 OSM 地图:点、线和路都可以,不是多面体
- android - 未解决的参考:TabLayoutMediator
- if-statement - 使用 INDEX 和 IF 创建公式
- apache - 添加虚拟主机后 Apache 未启动
- three.js - Three.js 将加载的 glb 模型的网格几何图形转换为与边界框具有相同的中心
- c# - 是否可以连接到在程序外部创建的内存中 Sqlite 数据库?
- php - 如何使用 Laravel 生成报告票号?
- apache-kafka - 处理 kafka 消费者中的反序列化错误(死信队列)
- entity-framework - 添加数据时是否可以确保顺序?
- excel - 如何仅禁用 Excel 电子表格中特定列的填充句柄?