Ada 使用未选中的_转换来读入值并转换为自定义类型

Ada 使用未选中的_转换来读入值并转换为自定义类型,ada,unchecked-conversion,Ada,Unchecked Conversion,当从文件中读取输入并尝试使用未选中的转换时,'Size和'Component\u Size是如何工作的,我很困惑。我知道,要成功地使用未选中的\u转换,源和目标都必须是相同的大小。我正在从一个类似000100000101001的文件中读取输入,并希望使用未经检查的转换将其放入一个位数组中。但是,转换似乎总是失败,因为它们的大小不一样或太小 与Ada.u转换; 使用Ada.Text_IO;使用Ada.Text\u IO; 使用Ada.Integer\u Text\u IO;使用Ada.Intege

当从文件中读取输入并尝试使用
未选中的转换时,
'Size
'Component\u Size
是如何工作的,我很困惑。我知道,要成功地使用
未选中的\u转换
,源和目标都必须是相同的
大小
。我正在从一个类似
000100000101001
的文件中读取输入,并希望使用未经检查的转换将其放入一个位数组中。但是,转换似乎总是失败,因为它们的大小不一样或太小

与Ada.u转换;
使用Ada.Text_IO;使用Ada.Text\u IO;
使用Ada.Integer\u Text\u IO;使用Ada.Integer\u Text\u IO;
主要程序是
类型位为mod 2,大小=>1;
类型Bit_数组是带包的位的数组(正范围);
子类型Bit15是位数组(1..15)//子类型,因为无法对无约束类型使用转换
子类型Bit11是位数组(1..11);
函数StringA_至_位15为
新的Ada.Unchecked_转换(source=>String,target=>Bit15);
开始
而不是结束\u文件循环的\u
声明
s:String:=get_行//保持第一行输入
len:自然常数:=(如果s'length-3=15
那么15
其他11项),;
i:整数;
ba:位_阵列(1..len)//基于输入长度约束位数组
开始
ba:=字符串到比特15;
新线;
结束;
端环;

这里是我的类型,位只能是0或1,大小为1位。Bit_数组只是一个不受约束的Bit数组,因为我的输入可以是15位长或11位长。我的想法是将第一行读入一个字符串,然后将其转换成一个位数组。这不起作用,因为字符串和所有其他基元类型都不是
Size=>1
。因此,我自然想创建一个新类型来处理这个问题,我尝试了以下形式:创建我自己的字符串类型并设置
size=>1
,但字符需要8位。我需要创建什么样的数据类型来读取一行数据并将其转换为一个位数组?我可能处理这个错误,但它对我来说非常困惑。任何帮助或提示都将不胜感激

您不能使用
未选中的\u转换
,因为正如您所发现的,
字符
不对应。与
0
相对应的8位ASCII
字符具有与十进制值48相对应的位模式,
1
具有值49

我想你必须咬紧牙关,循环输入字符串。一个简单的函数可以实现这一点,它要求输入字符串仅由
0
s和
1
s组成

function To_Bit_Array (S : String) return Bit_Array is
   Input : constant String (1 .. S'Length) := S;
   Result : Bit_Array (1 .. S'Length);
begin
   for J in Input'Range loop
      Result (J) := (case Input (J) is
                        when '0' => 0,
                        when '1' => 1,
                        when others => raise Constraint_Error);
   end loop;
   return Result;
end To_Bit_Array;

(声明
输入
的目的是确保两个数组的索引
J
相同;
字符串
的第一个索引只能是
,即大于0)。

但是,您可以使用未选中的\u转换,如果您正在从模块化整数类型转换为位数组。我通常避免使用未经检查的_转换,除非作为最后手段,但我可以看到从整数转换为位数组类型的诱惑。不过,我也会考虑是否只使用模块化整数,因为它也可以用于按位运算。不过,使用数组语法访问位是一个不错的特性。即使我想将一个模整数转换为一个位数组,我仍然建议尽可能避免使用未经检查的转换,或者在Ada中使用几乎未经检查的任何东西。 一个原因是,未经检查的_转换可能不太便于携带。 例如,不同的编译器和不同的目标可能以不同的顺序存储位

另一个建议是使用压缩的布尔数组,而不是 而不是一个压缩的位数组。内存中的存储应该是相同的, 但我想你会发现,用布尔人比用比特人更方便。它使您无需将值与1或0进行比较

因此,将输入字符串转换为模整数的一种方法是使用Ada.Text\u IO.modular\u IO包

type Short is mod 2**16;

package Short_IO is new Modular_IO (Num => Short);

type Bit_Array is array (Positive range <>) of Boolean
  with Component_Size => 1;
...

declare
     Input : constant String := Get_Line;
     Value : Short := 0;
     Last  : Positive;
     Bits_11 : Bit11;

     -- Instead of using Unchecked_Conversion, consider writing a 
     -- simple conversion function
     --
     function To_Bit11 (Value : Short) return Bit11 is
        ((for I in Bit11'Range => (Short(2**(I-1)) and Value) /= 0));

  begin

     --  Enclosing the input string with 2#{binary_string}#, 
     --  causes the number to be read in base 2, as a binary text
     --  string.
     Short_IO.Get (From  => "2#" & Input & "#",
                   Item  => Value,
                   Last  => Last);

     --  You could use unchecked conversion here to convert
     --  to the Bit array, but I'd recommend doing this
     --  without using unchecked features of the language
     --  e.g. using a simple loop

     for I in Bits_11'Range loop
        Bits_11 (I) := (Short(2**(I-1)) and Value) /= 0;
     end loop;

     --  or you can even try an Ada 2020 feature that already has
     --  been implemented in the latest community edition of GNAT.
     --  By assigning a new form of array aggregate to the 
     --  bit array object. You'd need to set the -gnatX compiler
     --  option to tell the compiler to use Ada extended 2020
     --  features. Many Ada 2020 features are not yet available to try
     --  out, but this one is available.

     Bits_11 :=
        (for I in Bits_11'Range => (Short (2**(I-1)) and Value) /= 0);

     -- or combine this into an expression function like above,
     -- then you have a function similar to the one you'd get using
     -- Unchecked_Conversion, except more portable, and one can
     -- examine the code to understand the implementation.

     Bits_11 := To_Bit11 (Value);
type Short为mod 2**16;
包短IO是新的模块化IO(Num=>Short);
类型Bit_数组是布尔值的数组(正范围)
组件_大小=>1;
...
声明
输入:常量字符串:=Get_行;
值:短:=0;
最后:肯定;
第11位:第11位;
代替使用UnChutkdl转换,考虑写一个
--简单转换函数
--
函数返回位11(值:Short),返回位11为
((对于位11'范围内的I=>(短(2**(I-1))和值)/=0));
开始
--用2#{binary_string}#封闭输入字符串,
--使数字以二进制文本的形式以基数2读取
--绳子。
Short_IO.Get(From=>“2#”&输入&“#”,
项目=>价值,
Last=>Last);
--您可以在此处使用未选中的转换来转换
--位数组,但我建议这样做
--不使用该语言未经检查的功能
--例如,使用一个简单的循环
对于位11'范围循环中的I
位11(I):=(短(2**(I-1))和值)/=0;
端环;
--或者你甚至可以尝试Ada2020已经具备的功能
--已在GNAT的最新社区版中实施。
--通过将新形式的数组聚合分配给
--位数组对象。您需要设置-gnatX编译器
--选项告诉编译器使用Ada extended 2020
--特征。许多ADA2020功能尚不可尝试
--出去,但这是开着的