You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNAT中Get函数从字符串读取十六进制值的异常问题咨询

问题原因解析

Ada的Ada.Integer_Text_IO.Get存在两个关键重载版本,行为差异导致了你遇到的问题:

1. 文件输入版本 vs 字符串输入版本的行为区别

  • 文件输入的Get(File_Type, Integer):会自动识别Ada标准的基数标记格式(如16#...#),无论当前设置的输入基数是什么,都会按照标记指定的基数解析数值。
  • 字符串输入的Get(From => String, ...):默认使用当前的输入基数(默认是十进制)解析字符串,不会自动识别16#...#这种基数前缀。

对应你的测试现象:

  • 输入16#12#时,字符串版本的Get会以十进制解析开头的16,遇到非十进制字符#就停止解析,所以返回结果16。
  • 输入纯十六进制值F8时,因为默认基数是十进制,F不是合法的十进制数字,直接触发异常。

2. 原测试代码的额外问题

你的代码里未声明HexString变量,且使用Get(HexString)会在空白或非字母数字字符处截断输入,无法读取完整的16#12#格式字符串,应该改用Get_Line来读取完整输入。

解决方案

要让字符串版本的Get支持16#...#格式或纯十六进制值,可以手动处理基数前缀,并设置对应的解析基数:

with Ada.Text_IO;         use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Strings.Fixed;   use Ada.Strings.Fixed;

procedure hex is
   IntValue       : Integer;
   Last           : Positive;
   HexString_Buf  : String(1..20);  -- 定义足够大的缓冲区
   Actual_Length  : Natural;
begin
   Put("Enter a hexadecimal string: ");
   Get_Line(HexString_Buf, Actual_Length);  -- 读取完整输入行
   declare
      Input : constant String := HexString_Buf(1..Actual_Length);
   begin
      -- 处理Ada风格的16#...#格式
      if Input'Length >= 4 
         and then Input(1..3) = "16#" 
         and then Input(Input'Last) = '#'
      then
         declare
            Hex_Part : constant String := Input(4..Input'Last - 1);
         begin
            Set_Base(16);  -- 设置解析基数为十六进制
            Get(From => Hex_Part, Item => IntValue, Last => Last);
            -- 验证是否整个十六进制部分都被正确解析
            if Last /= Hex_Part'Last then
               raise Constraint_Error with "无效的十六进制字符";
            end if;
         end;
      else
         -- 尝试直接解析纯十六进制字符串
         begin
            Set_Base(16);
            Get(From => Input, Item => IntValue, Last => Last);
            if Last /= Input'Last then
               raise Constraint_Error with "输入包含无效字符";
            end if;
         exception
            when others =>
               raise Constraint_Error with "输入格式错误,请使用16#...#或纯十六进制数字";
         end;
      end if;
   end;

   Put("转换后的整数值为: ");
   Put(IntValue, Width => 0);
   New_Line;
   Set_Base(10);  -- 恢复默认的十进制基数
end hex;

代码关键点说明:

  • 使用Get_Line读取完整输入行,避免Get截断问题。
  • 先判断输入是否符合16#...#格式,提取中间的十六进制部分后再解析。
  • 通过Set_Base(16)强制以十六进制解析字符串,支持0-9、A-F(大小写均可)。
  • 增加了输入有效性验证,确保整个字符串都被正确解析。

内容的提问来源于stack exchange,提问作者Erlo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 16:47:45