如何使用OCaml Scanf模块解析包含由空格WITHOUT Str分隔的整数的字符串

时间:2016-09-05 17:44:06

标签: string input ocaml whitespace

标题基本上都说明了一切。我知道通过OCaml的Str模块使用regexp,这个任务非常简单 - 但是,假设您只允许使用标准库和Scanf模块。我有兴趣采用这样的字符串:

    "12 34 555 6 23 34 5663 234 ..."

返回一个看起来像这样的数组

  [|12; 34; 555; 6; 23; 34; 5663; 234; |]

有人可以帮帮我吗?我发现Scanf文档(可用http://caml.inria.fr/pub/docs/manual-ocaml/libref/Scanf.html)对于理解如何使用模块非常无益

3 个答案:

答案 0 :(得分:2)

不确定它是多么惯用,但它有效:

let parse_integers s =
  let stream = (Scanning.from_string s) in
  let rec do_parse acc =
    try
      do_parse (Scanf.bscanf stream " %d " (fun x -> x :: acc))
    with
      Scan_failure _ -> acc
    | End_of_file -> acc
  in Array.of_list (List.rev (do_parse []));;

一点点测试:

# parse_integers " 20 3 22";;
- : int array = [|20; 3; 22|]

(更新)

正如评论中所解释的那样,上面的代码不是尾递归的,而下面的代码是:

...
let rec do_parse acc = 
  match (Scanf.bscanf stream " %d " (fun x -> x :: acc)) 
with 
  | xs -> do_parse xs 
  | exception Scan_failure _ -> acc 
  | exception End_of_file -> acc
in ...

答案 1 :(得分:0)

let rec f acc s =
  if s="" then
    Array.of_list (List.rev acc)
  else
    Scanf.sscanf s "%d %[^\n]" (fun n s-> f (n::acc) s)
;;



f [] "12 34 555 6 23 34 5663 234";;
# - : int array = [|12; 34; 555; 6; 23; 34; 5663; 234|]

答案 2 :(得分:-1)

所有Scanf函数的格式字符串指定固定数量的值;因此,您不能期望使用Scanf中的函数从字符串中读取可变数量的值。

如果将字符串分成几部分,则可以使用Scanf.sscanf s "%d" (fun x -> x)将每个部分转换为int。但是,函数int_of_string对于此目的来说要简单得多。

我说你应该先把字符串分成几块。