我有一个程序,理论上应该使用look_ahead循环跳过空格。问题是,它不起作用,如果输入文件中有任何空格,则将其添加到记录数组中。我认为我的逻辑是正确的,但可以用另一双眼睛让我知道我错过了什么,以及为什么它不起作用。
PROCEDURE Read(Calc: OUT Calculation) IS
EOL: Boolean;
C: Character;
I: Integer := 1;
BEGIN
LOOP
LOOP
Look_Ahead(C, EOL);
EXIT WHEN EOL or C /= ' ';
Get(C);
END LOOP;
EXIT WHEN ADA.Text_IO.END_OF_FILE;
Look_Ahead(C, EOL);
IF Is_Digit(C) THEN
Calc.Element(I).Kind := Number;
Get(Calc.Element(I).Int_Value);
ELSE
Calc.Element(I).Kind := Symbol;
Get(Calc.Element(I).Char_Value);
END IF;
Calc.Len := Calc.Len+1;
IF Calc.Element(I).Char_Value = '=' THEN
EXIT;
END IF;
I := I+1;
END LOOP;
END Read;
编辑:如果答案需要任何其他程序,记录代码等,请告诉我,我会发布。
答案 0 :(得分:2)
对于Ada.Text_IO.Look_Ahead
,ARM A.10.7(8)说
如果在行尾,则将End_Of_Line设置为True,包括在页面末尾或文件末尾;在每种情况下,都没有指定Item的值。否则,End_Of_Line设置为False,Item设置为文件中的下一个字符(不消耗它)。
(我的重点),我认为“不消耗它”是关键。 Look_Ahead
找到有趣字符后,您需要调用Get
来检索该字符。
我一起攻击了这个小小的演示:我将文件末尾留给了异常处理,一旦看到行尾,我就调用了Skip_Line
,因为只有Get
不正确(对不起)更确切地说!)。
with Ada.Text_IO;
with Ada.IO_Exceptions;
procedure Justiciar is
procedure Read is
Eol: Boolean;
C: Character;
begin
-- Instead of useful processing, echo the input to the output
-- replacing spaces with periods.
Outer:
loop
Inner:
loop
Ada.Text_IO.Look_Ahead (C, Eol);
exit Outer when Eol; -- C is undefined
exit Inner when C /= ' ';
Ada.Text_IO.Get (C); -- consume the space
Ada.Text_IO.Put ('.'); -- instead of the space for visibility
end loop Inner;
Ada.Text_IO.Get (C); -- consume the character which isnt a space
Ada.Text_IO.Put (C); -- print it (or other processing!)
end loop Outer;
Ada.Text_IO.Skip_Line; -- consume the newline
Ada.Text_IO.New_Line; -- clear for next call
end Read;
begin
loop
Ada.Text_IO.Put ("reading: ");
Read;
end loop;
exception
when Ada.IO_Exceptions.End_Error =>
null;
end Justiciar;
答案 1 :(得分:1)
通常最好读取整行并解析它,而不是尝试逐个字符地解析。后者通常更复杂,更难理解,更容易出错。所以我建议像
这样的东西function De_Space (Source : String) return String is
Line : Unbounded_String := To_Unbounded_String (Source);
begin -- De_Space
Remove : for I in reverse 1 .. Length (Line) loop
if Element (Line, I) = ' ' then
Delete (Source => Line, From => I, Through => I);
end if;
end loop Remove;
return To_String (Line);
end De_Space;
Line : constant String := De_Space (Get_Line);
然后,您可以遍历Line'range
并解析它。因为我不清楚是否
Get(C);
Get(Calc.Element(I).Int_Value);
Get(Calc.Element(I).Char_Value);
代表1,2或3个不同的程序,我无法真正帮助那个部分。