我正在尝试按照标准参考来打开文件,但在调用Ada.Text_IO.Create()时遇到了行中的constraint_error。它说“范围检查失败”。任何帮助表示赞赏,这是代码:
WITH Ada.Text_IO;
WITH Ada.Integer_Text_IO;
USE Ada.Text_IO;
USE Ada.Integer_Text_IO;
PROCEDURE FileManip IS
--Variables
Start_Int : Integer;
Stop_Int : Integer;
Max_Length : Integer;
--Output File
MaxName : CONSTANT Positive := 80;
SUBTYPE NameRange IS Positive RANGE 1..MaxName;
OutFileName : String(NameRange) := (OTHERS => '#');
OutNameLength : NameRange;
OutData : File_Type;
--Array
TYPE Chain_Array IS ARRAY(1..500) OF Integer;
Sum : Integer := 1;
BEGIN
--Inputs
Ada.Text_IO.Put(Item => "Enter a starting Integer: ");
Ada.Integer_Text_IO.Get(Item => Start_Int);
Ada.Text_IO.New_Line;
Ada.Text_IO.Put(Item => "Enter a stopping Integer: ");
Ada.Integer_Text_IO.Get(Item => Stop_Int);
Ada.Text_IO.New_Line;
Ada.Text_IO.Put(Item => "Enter a Maximum Length to search: ");
Ada.Integer_Text_IO.Get(Item => Max_Length);
Ada.Text_IO.New_Line;
Ada.Text_IO.Put(Item => "Enter a output file name > ");
Ada.Text_IO.Get_Line(
Item => OutFileName,
Last => OutNameLength);
Ada.Text_IO.Create(
File => OutData,
Mode => Ada.Text_IO.Out_File,
Name => OutFileName(1..OutNameLength));
Ada.Text_IO.New_Line;
答案 0 :(得分:3)
可能不是create
给你这个问题,而是对OutFileName(1..OutNameLength)
进行数组范围检查。
要实现这一点,要么1或OutNameLength需要超出为OutFileName指定的范围。由于那被定义为RANGE 1..MaxName
(通过NameRange),我们知道它不是1,所以罪魁祸首必须是OutNameLength
。
环顾四周,您似乎从Last
的{{1}}参数中获取了该值。有一种情况,您可以从该参数中获得0:当您读取空白行时。所以我的猜测是正在发生的事情。
答案 1 :(得分:1)
对于您阅读的每个Integer
,Ada.Integer_Text_IO.Get
使用默认的宽度为零,因此"skips any leading blanks, line terminators, or page terminators, then reads a plus sign if present or (for a signed type only) a minus sign if present, then reads the longest possible sequence of characters matching the syntax of a numeric literal without a point."后续的Ada.Text_IO.New_Line
将行终止符保留为Ada.Text_IO.Get_Line
绊倒,零不在NameRange
之内。而是使用Ada.Text_IO.Skip_Line
。例如,
Ada.Text_IO.Put(Item => "Enter a starting Integer: ");
Ada.Integer_Text_IO.Get(Item => Start_Int);
Ada.Text_IO.Skip_Line;
Ada.Text_IO.Put(Item => "Enter a stopping Integer: ");
Ada.Integer_Text_IO.Get(Item => Stop_Int);
Ada.Text_IO.Skip_Line;
Ada.Text_IO.Put(Item => "Enter a Maximum Length to search: ");
Ada.Integer_Text_IO.Get(Item => Max_Length);
Ada.Text_IO.Skip_Line;
...
答案 2 :(得分:1)
切线相关...
获取交互式输入的一种常见做法是避免使用“Integer_Text_IO”和相关的包来获取,而是使用Get_Line然后进行转换。 E.g:
S : String(1..200);
L : Natural;
...
Ada.Text_IO.Put(Item => "Enter a starting Integer: ");
Ada.Text_IO.Get_Line(Item => S, Last => L);
Start_Int := Integer'Value(S(1..L));
这种方法可以更容易地检查用户输入C / R(L = 0),而数字Get程序只读取字符,只要它们符合数字文字的语法,直到最后通过使用Get_Line抓取整行,您可以避免处理行尾问题,并确保输入的所有是一个数字文字(通过捕获如果在评估“Value属性”时引发了一个Constraint_Error异常。
尽管早期的Ada编译器存在问题,但由于不同的系统指定行尾,文件结束等惯例,Get程序并不总是在不同的平台上完全相同。但Get_Line,几乎在所有平台上都有相同的功能,因此它和随后的字符串 - >数字转换是一种广泛推荐的做法。