hexada

Print a hex number with leading zeros in Ada


Is there a simple way of printing hexadecimal numbers with leading zeros in Ada? The following will print a number with leading zeros in hex but it is a bit convoluted.

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

procedure A59hex is
   package MIO is new Ada.Text_IO.Modular_IO (Interfaces.Unsigned_32);

   function Hex (hval : Interfaces.Unsigned_32; num_digits : Integer := 8)
      return String
   is
      --  Add 4 for the 16#...#
      hexstr : String (1 .. num_digits + 4);
   begin
      --  Convert to 16#...#
      MIO.Put (To => hexstr, Item => hval, Base => 16);
      declare
         --  String is right justified - trim the hex string
         thex : constant String := Trim (hexstr, Ada.Strings.Left);
         --  Remove the 16# header and # footer
         phex : constant String := thex (thex'First + 3 .. thex'Last - 1);
      begin
         --  Add leading zeros
         return (Tail (phex, num_digits, '0'));
      end;
   end Hex;

begin
   Put (Hex (16#1A#, 4));
   for ii in 0 .. 15 loop
      Put (" " & Hex (Interfaces.Unsigned_32 (ii), 2));
   end loop;
   New_Line;
   Put_Line (Hex (16#7F1B#));
   Put_Line (Hex (16#7FFF1C#));
   Put_Line (Hex (16#7FFFFF1D#));
   Put_Line (Hex (16#9FFFFF1E#));
end A59hex;

Output

001A 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00007F1B
007FFF1C
7FFFFF1D
9FFFFF1E

It creates a string with 16#...#, then removes it, remove the leading spaces and then pads the leading spaces with 0s. Is there a library routine that does what Hex does for 8, 16 and 32 bit unsigned numbers?


Solution

  • Here, a more general - and actually generic! - solution:

    with Interfaces;
    with Ada.IO_Exceptions, Ada.Text_IO;
    
    procedure A59hex is
    
       generic
          type T is mod <>;
       function Hex_Any (hval : T; num_digits : Integer := T'size / 4)
          return String;
    
       function Hex_Any (hval : T; num_digits : Integer := T'size / 4)
          return String
       is
          x : T := hval;
          hex_str : String (1 .. num_digits);
          hex_digit : constant array (T range 0 .. 15) of Character := "0123456789ABCDEF";
       begin
          for i in reverse hex_str'Range loop
             hex_str (i) := hex_digit (x and 15);
             x := x / 16;
          end loop;
          if x /= 0 then
             raise Ada.IO_Exceptions.Layout_Error
                with "Number exceeds digits available with `num_digits`";
          end if;
          return hex_str;
       end Hex_Any;
    
       function Hex is new Hex_Any (Interfaces.Unsigned_32);
    
       use Ada.Text_IO;
       
    begin
       Put (Hex (16#1A#, 4));
       for ii in Interfaces.Unsigned_32 range 0 .. 15 loop
          Put (" " & Hex (ii, 2));
       end loop;
       New_Line;
       Put_Line (Hex (16#7F1B#));
       Put_Line (Hex (16#7FFF1C#));
       Put_Line (Hex (16#7FFFFF1D#));
       Put_Line (Hex (16#9FFFFF1E#));
    end A59hex;