使用 scanf 在非空白分隔符上分割字符串

mar*_*ler 3 string io ocaml split scanf

我的目标是扫描包含冒号作为除法的字符串,并将其两个部分保存在一个元组中。
例如:

input: "a:b"
output: ("a", "b")
Run Code Online (Sandbox Code Playgroud)

到目前为止,我的方法不断收到错误消息:
“scanf:字符号 9 处输入错误:寻找 ':',找到 '\n'”。

 Scanf.bscanf Scanf.Scanning.stdin "%s:%s" (fun x y -> (x,y));;
Run Code Online (Sandbox Code Playgroud)

此外,我的方法适用于整数,我很困惑为什么它不适用于字符串。

Scanf.bscanf Scanf.Scanning.stdin "%d:%d" (fun x y -> (x,y));;
4:3
- : int * int = (4, 3)
Run Code Online (Sandbox Code Playgroud)

kop*_*ecs 6

您看到问题的原因是,第一个问题%s将继续消耗输入,直到满足以下条件之一:

  • 发现了一个空白,
  • 遇到扫描指示,
  • 已达到输入结束。

请注意,看到冒号并不能满足任何这些要求(如果您不使用扫描指示)。这意味着第一个%s将消耗所有内容,在您的情况下,输入缓冲区中的换行符,然后:将失败。

您不会遇到同样的问题,%d:%d因为%d不会将冒号用作匹配整数的一部分。

您可以通过使用不会消耗冒号的格式字符串来解决此问题,例如%[^:]:%s. 您还可以使用扫描指示,如下所示:%s@:%s

此外,您当前的方法不会消耗缓冲区中的任何尾随空格,这可能会导致在后续使用时将换行符添加到第一个元素,因此您可能更愿意%s@:%s\n使用换行符。

所以,总而言之,

Scanf.bscanf Scanf.Scanning.stdin "%s@:%s\n" (fun x y -> (x,y));;
Run Code Online (Sandbox Code Playgroud)