【发布时间】:2020-06-04 02:15:00
【问题描述】:
我正在尝试编写一个简单的验证代码块来确保参数(Ada.Command_Line.Argument)和来自 GetLine 的输入是有效的,在我的情况下,我需要输入字符串中的所有字符都是数字( 0 到 9)。
main.adb:
pragma SPARK_Mode (On);
with test_procedure;
with Ada.Command_Line;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Main is
package CL renames Ada.Command_Line;
user_str : String := CL.Argument(1);
Flag : Boolean := False;
begin
if CL.Argument_Count = 1 then
for I in user_str'Range loop
case user_str(I) is
when '0'..'9' => Flag := True;
when others => Flag := False; exit;
end case;
end loop;
end if;
if Flag then
test_procedure.ToA(user_str);
Put(user_str);
end if ;
end Main;
test_procedure.ads:
package test_procedure with SPARK_Mode is
procedure ToA(S : in out String) with
Pre => (for all I in S'Range => S(I) >= '0' and S(I) <= '9');
end test_procedure;
test_procedure.adb
package body test_procedure with SPARK_Mode is
procedure ToA(S : in out String) is
begin
for I in S'Range loop
S(I) := 'a';
end loop;
end ToA;
end test_procedure;
该程序运行良好。如果我输入./main 01234,它将返回aaaaa,如果我输入./main f00,它将不返回任何内容。但是,当我使用 GNATprove(在 GPS -> SPARK -> Prove All 中)时,它给了我precondition might fail, cannot prove S(I) >= '0' (e.g. when I = 1 and user_str = (2 => '0', others => 'NUL'))。我不确定为什么会发生这种情况,因为如果没有数字字符存在,则不应调用 ToA 过程。
【问题讨论】:
-
如果将前置条件更改为
(for all I in S'range => S (I) in '0' .. '9'),会发生什么?这是一种更类似于 Ada 的表达方式。不过,鉴于失败的性质,它可能无济于事。
标签: command-line ada gnat spark-ada