2

ファイルを開くための標準的なリファレンスに従おうとしていますが、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;
4

3 に答える 3

3

Likely it isn't the create that is giving you that problem, but an array range check on OutFileName(1..OutNameLength).

For that to happen, either 1 or OutNameLength would need to be out of the range specified for OutFileName. Since that was defined as RANGE 1..MaxName (via NameRange), we know it isn't the 1, so the culprit must be OutNameLength.

Looking around, it looks like you get that value from the Last parameter of a Get_Line. There is one situation where you can get a 0 out of that parameter: when you read a blank line. So my guess is that is what is happening.

于 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 例外を評価するときに発生した場合に Constraint_Error 例外をキャッチすることにより)。値属性)。

また、以前の Ada コンパイラではより大きな問題でしたが、Get プロシージャは、行末、ファイルの終わりなどを指定するシステムの規則が異なるため、異なるプラットフォームで常に同じように機能するとは限りませんでした。Get_Line はかなり機能しました。すべてのプラットフォームで同じであるため、その後の文字列から数値への変換は、広く推奨される方法でした。

于 2010-03-12T13:23:30.620 に答える