Ada Integer'Width错误排查:一段理论规范的Ada包代码问题
Integer'Width Error in Your Ada Procedure Let's break down the issue with Integer'Width in your code and fix it step by step:
What's Causing the Error?
The Integer'Width attribute in Ada returns the maximum number of characters needed to represent any valid Integer value as a string—this includes the sign (a minus for negatives, or a leading space for positives when using Integer'Image).
For example, on a standard 32-bit system:
Integer'Last(2147483647) has anImageof" 2147483647"(11 characters: 1 space + 10 digits)Integer'First(-2147483648) has anImageof"-2147483648"(11 characters: 1 minus + 10 digits)
Your code defines String_Number : String (1 .. Integer'Width – 1);—this creates a string that’s one character too short to hold the longest possible Integer representation (like the negative minimum value). When you try to read a number that requires the full Integer'Width characters, you’ll trigger a Constraint_Error from writing beyond the string’s bounds.
How to Fix It
Here are two key fixes to resolve the issue:
Correct the String Length
Update theString_Numberdefinition to use the fullInteger'Widthinstead of subtracting 1:String_Number : String (1 .. Integer'Width);This ensures the string can accommodate any valid Integer value, including negatives and the largest positive numbers.
Add Bound Checks for Input
Track your position in the string as you read characters, and stop if you reach the end to avoid overflow. Here’s an updated version of your procedure with this logic:with Ada.Text_IO; with Ada.Characters.Handling; package body pkg_procedure is procedure Read_Integer(Num : out Integer) is Intro : constant Character := ASCII.LF; Back : constant Character := ASCII.Del; Char : Character; Fin : Boolean := False; String_Number : String (1 .. Integer'Width); -- Fixed length Index : Positive := 1; -- Track current string position Is_Negative : Boolean := False; -- Handle negative input begin Ada.Text_IO.New_Line; Ada.Text_IO.Put ("Write down a number and press Enter: "); while not Fin loop Ada.Text_IO.Get_Immediate(Char); case Char is when ASCII.CR | ASCII.LF => -- Enter key finishes input Fin := True; when Back => -- Handle backspace to delete characters if Index > 1 then Index := Index - 1; Ada.Text_IO.Put(ASCII.Back & ' ' & ASCII.Back); -- Erase from console end if; when '-' => -- Capture negative sign only at start if Index = 1 then Is_Negative := True; String_Number(Index) := Char; Index := Index + 1; end if; when '0'..'9' => -- Add digits to the string if Index <= String_Number'Last then String_Number(Index) := Char; Index := Index + 1; Ada.Text_IO.Put(Char); -- Echo input to console end if; when others => -- Ignore invalid characters null; end case; end loop; -- Convert the collected string to an Integer if Index > 1 then Num := Integer'Value(String_Number(1 .. Index - 1)); else -- Handle empty input (default to 0 or raise an error as needed) Num := 0; end if; end Read_Integer; end pkg_procedure;
Quick Alternative (If You Don't Need Manual Input Handling)
If you don’t need custom logic like backspace support, use Ada.Text_IO.Integer_IO directly—it’s safer and avoids low-level character management:
Ada.Text_IO.Integer_IO.Get(Num);
内容的提问来源于stack exchange,提问作者thmasker

