In the code below, the int_of_hex function converts a hexadecimal to a decimal. Is there a built-in function that does the same thing ?
I am aware of the `0x` syntax, but the naive `let int_to_hex hex=0xhex;;` is of course incorrect in OCaml).
Perhaps the Printf module can help here.

`````` exception Hexchar_exn of char;;

let int_of_hexchar c=
try List.assoc c
[
('0', 0); ('1', 1); ('2', 2); ('3', 3); ('4', 4); ('5', 5);
('6', 6); ('7', 7); ('8', 8); ('9', 9);
('A', 10); ('B', 11); ('C', 12); ('D', 13); ('E', 14); ('F', 15)
]
with _->raise(Hexchar_exn(c));;

let int_of_hex s=
let n=String.length(s)
and accu=ref(0) in
for i=1 to n do accu:=int_of_hexchar(String.get s (i-1))+16*(!accu) done;
(!accu);;
``````

You can print an int in hexadecimal notation using the `Printf` module

`````` # Printf.printf "0x%x" 12345;;
0x3039- : unit = ()
``````

Also, the `int_of_string` function recognizes hexadecimal notation:

``````# int_of_string "0x3039";;
- : int = 12345
``````

If your input string is missing the hexadecimal prefix, you can always do : `int_of_string ("0x" ^ hexadecimal_string)`

3 Likes

Thank you! The fact that int_of_string recognizes hexadecimal notation is very pleasant.

1 Like

Except for `int_of_string` which needs the `0x` prefix I don’t think there such a thing in the stdlib.

Depending on what you do allocating a new string on each parse may be a bit too slow. Also in your code I would avoid using an assoc list for that.

Here would be my take on the function (`man ascii` may help to understand the magic constants of `digit_value`):

``````let int_of_hex s =
let digit_value c =
let c = Char.code c in
if c <= 0x2F then raise_notrace Exit else
if c <= 0x39 then c - 48 else
if c <= 0x40 then raise_notrace Exit else
if c <= 0x46 then c - 55 else
if c <= 0x60 then raise_notrace Exit else
if c <= 0x66 then c - 87 else
raise_notrace Exit
in
match s with
| "" -> None
| s ->
let max = String.length s - 1 in
let rec loop i acc = match i > max with
| true -> acc
| false -> loop (i + 1) (acc * 16 + digit_value s.[i])
in
try Some (loop 0 0) with Exit -> None
``````
3 Likes

You can also do this with Scanf:

``````let int_of_hex s =
try
Scan.sscanf s "%x%!" (fun x -> x)
with Scanf.Scan_failure ->
raise (* Something *)
``````
3 Likes