2

我正在尝试遵循打开文件的标准参考,但在调用 Ada.Text_IO.Create() 时遇到了约束错误。它说“范围检查失败”。任何帮助表示赞赏,这是代码:

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;
4

3 回答 3

3

可能不是create给你这个问题,而是数组范围检查OutFileName(1..OutNameLength)

为此,需要 1 或 OutNameLength 超出为 OutFileName 指定的范围。由于它被定义为RANGE 1..MaxName(通过 NameRange),我们知道它不是 1,所以罪魁祸首一定是OutNameLength.

环顾四周,您似乎从 a 的Last参数中获得了该值Get_Line。在一种情况下,您可以从该参数中得到 0:当您读取空行时。所以我的猜测是正在发生的事情。

于 2010-03-12T14:21:38.140 回答
1

对于Integer您阅读的每个内容,Ada.Integer_Text_IO.Get使用默认宽度为零,因此它“跳过任何前导空格、行终止符或页面终止符,然后读取一个加号(如果存在)或(仅对于有符号类型)一个减号(如果存在),然后读取与没有点的数字文字的语法匹配的最长可能的字符序列。” 随后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;
...
于 2010-03-12T05:53:35.263 回答
1

切线相关...

获取交互式输入的一个常见做法是避免使用“Integer_Text_IO”和相关包进行 Gets,而是使用 Get_Line 然后进行转换。例如:

   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 抓取整行,您可以避免处理行尾问题,并且可以确保输入的所有内容都是数字文字(如果在评估时引发 Constraint_Error 异常,则通过捕获'值属性)。

尽管早期的 Ada 编译器存在更多问题,但由于指定行尾、文件尾等的不同系统约定,Get 过程在不同平台上的工作并不总是相同。不过,Get_Line 非常有效在所有平台上都相同,因此它和随后的字符串->数字转换是一种广泛推荐的做法。

于 2010-03-12T13:23:30.620 回答