【问题标题】:How to use OCaml Scanf module to parse a string containing integers separated by spaces WITHOUT Str如何使用 OCaml Scanf 模块解析包含由空格分隔的整数的字符串,而不使用 Str
【发布时间】:2016-09-06 23:48:26
【问题描述】:

标题基本上说明了一切。我知道通过 OCaml 的 Str 模块使用正则表达式,这个任务非常简单 - 但是,假设您只允许使用标准库和 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 提供)对于理解如何使用该模块毫无帮助

【问题讨论】:

  • 任何机会你都可以帮助我@Virgile
  • 为什么要避开Str?这似乎是在 OCaml 中将字符串拆分为单词的常用方法。

标签: string input ocaml whitespace


【解决方案1】:

不确定它是多么地道,但它确实有效:

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|]

(更新)

正如在 cmets 中所解释的,上面的代码不是尾递归的,而下面的代码是:

...
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 ...

【讨论】:

  • FWIW,do_parse 不是尾递归的,因为 try ... with ... 块。更多详情请见here。这样的事情可以解决这个问题: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
【解决方案2】:
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|]

【讨论】:

  • 我猜sscanf 在将f (n::acc) 应用到(新)s 时会复制字符串的其余部分,因此代码的运行时间为 O(n^2)。这个answer 是 O(n)。
【解决方案3】:

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

如果你把你的字符串分成几段,你可以使用Scanf.sscanf s "%d" (fun x -> x) 把每段翻译成一个int。但是,int_of_string 函数在此方面要简单得多。

我想说你应该从把字符串分成几部分开始。

【讨论】:

    猜你喜欢
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 2015-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多