无法在Ada 95中创建文件

时间:2010-03-12 02:23:08

标签: file ada

我正在尝试按照标准参考来打开文件,但在调用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;

3 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:1)

对于您阅读的每个IntegerAda.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,几乎在所有平台上都有相同的功能,因此它和随后的字符串 - >数字转换是一种广泛推荐的做法。