Как правильно использовать Lwt_io.read_int?

Как правильно использовать Lwt_io.read_int? Я попробовал то, что мне показалось очевидным, но я не получил очевидных результатов...

open Lwt.Infix

let _ =
  Lwt_main.run
    (
      Lwt_io.print "Enter number: " >>=
      fun () -> Lwt_io.read_int (Lwt_io.stdin) >>=
      fun d -> Lwt_io.printf "%d\n" d
    )

Я скомпилировал, запустил и ввел 12345 при появлении запроса, и программа отобразила 875770417.

Я что-то здесь упускаю...

С помощью ниже я пришел к этому. Это работает, и я надеюсь, что это правильно.

open Lwt.Infix

let _ =
  Lwt_main.run
    (
      Lwt_io.print "Enter number: " >>=
      fun () -> Lwt_io.read_line (Lwt_io.stdin) >>=
      fun s -> 
      (
        try
          Lwt.return_some( Pervasives.int_of_string s)
        with
        | _ -> Lwt.return_none
      ) >>=
      fun o -> 
      Lwt_io.print
        (
          match o with
          | Some i -> Printf.sprintf "%d\n" i
          | None -> "Ooops, invalid format!\n"
        )
    )

Я думаю, что я должен опубликовать некоторый код, чтобы продемонстрировать правильное использование Lwt_io.read_int.

open Lwt.Infix
open Lwt_io

let _ =
  Lwt_main.run
    (
      let i, o = Lwt_io.pipe() in
      Lwt_io.write_int o 1 >>=
      fun () -> Lwt_io.flush o >>=
      fun () -> Lwt_io.close o >>=
      fun () -> Lwt_io.read_int i >>=
      fun d -> Lwt_io.printf "%d\n" d >>=
      fun () -> Lwt_io.close i
    )

2 ответа

Решение

Это читает двоичное кодированное целое число, например, для десериализации некоторых данных из файла.

Вы читаете 875770417, который находится в шестнадцатеричном формате 0x34333231, что в свою очередь соответствует кодировке ASCII '1', '2', '3' и '4' в порядке с прямым порядком байтов.

Вы, вероятно, хотите прочитать строку, используя Lwt_io.read_line и преобразовать результат, используя int_of_string,

Согласно этой странице, я попробовал несколько экспериментов.

Сначала я написал:

open Lwt.Infix

let _ =
  Lwt_main.run
    (
      let open Lwt_io in
      print "Enter number: " >>=
        fun () -> read_line stdin >>=
      fun d -> printlf "%s" d
    )

И я получил все, что хотел.

Хорошо, теперь давайте попробуем с целыми числами, так как написано, что

val read_int : Lwt_io.input_channel -> int Lwt.t

Читает 32-разрядное целое число в виде ocaml

open Lwt.Infix

let _ =
  Lwt_main.run
    (
      let open Lwt_io in
      print "Enter number: " >>=
        fun () -> read_int stdin >>=
      fun d -> write_int stdout d
    )

Ну странное поведение тут

lhooq@lhooq-linux lwt_io $ ./main.native 
Enter number: 100
100
lhooq@lhooq-linux lwt_io $ ./main.native 
Enter number: 1000
1000lhooq@lhooq-linux lwt_io $ ./main.native 
Enter number: 10000
1000lhooq@lhooq-linux lwt_io $ 
lhooq@lhooq-linux lwt_io $ ./main.native 
Enter number: 10
20
10
2lhooq@lhooq-linux lwt_io $

Итак, похоже, что три цифры - это максимум, который может обрабатывать эта функция, но, по крайней мере, она печатает число, которое вы написали.

Следующий тест:

open Lwt.Infix

let _ =
  Lwt_main.run
    (
      let open Lwt_io in
      print "Enter number: " >>=
        fun () -> read_int stdin >>=
      fun d -> printlf "%d" d
    )

Именно ваша проблема здесь:

lhooq@lhooq-linux lwt_io $ ./main.native 
Enter number: 100
170930225

Итак, давайте напишем это:

open Lwt.Infix

let _ =
  Lwt_main.run
    (
      let open Lwt_io in
      print "Enter number: " >>=
        fun () -> read_int stdin >>=
      fun d -> eprintf "%x\n" d
    )

И проверить снова:

lhooq@lhooq-linux lwt_io $ ./main.native 
Enter number: 100
a303031

Что именно "001" в ASCII.

Я надеюсь, что это поможет вам выяснить, какую функцию использовать. По моему скромному мнению, я не понимаю, почему читать целое число (и это точно так же, как с float64 или же int64 но это время ограничено 7 цифрами) кажется так сложно. Я бы предложил использовать read_line а также int_of_string по крайней мере, это работает хорошо.

Другие вопросы по тегам