OCaml测试字符串是否为空或包含关键字

时间:2016-06-06 11:37:40

标签: string algorithm ocaml keyword

我在OCaml遇到了一个问题,我现在正在学习它,但我还是一个新手。我想创建一个函数,如果字符串为空或仅包含空格并且同时删除beginend的任何出现,则返回true。

我已经尝试了这个:

let isEmptyString s =  
  let rec empty i =
    if i < 0 then true
    else
          let c = String.get s i in
          if c = ' ' || c = '\009' then empty (pred i)
          else false
  in
  s = Str.global_replace( Str.regexp "begin") "" s;
  s = Str.global_replace( Str.regexp "end") "" s;
  empty (pred (String.length s))

但显然,这个函数不能正常工作,因为我在调用它之后仍然在begin中获得Formula.importNrAgentsFormula ...这是我的称呼方式:

while true do
   let input = read_line () in
   if not (isEmptyString input) then
      let (nr, f) = Formula.importNrAgentsFormula input in
      incr counter;
      flush stdout;
      match choice with
       | "graph" -> printRes (Graph.isSat ~verbose:verb nr f)
       | _ -> printUsage ()
   else ()
done

如果在OCaml有更多经验的人可以发现并向我解释错误,我会很高兴:)

提前致谢,

最诚挚的问候。

2 个答案:

答案 0 :(得分:3)

我建议你让你的函数isEmptyStringisBlankString而不是?)做它应该做的事情(只检查它是否只包含空格或什么都没有),它不应该修改原始字符串。您可以在循环中执行此操作:

while true do
   let input = read_line () in
   let input = Str.global_replace( Str.regexp "begin") "" input in
   let input = Str.global_replace( Str.regexp "end") "" input in
   if not (isEmptyString input) then
   ...

修改:对于延迟编辑感到抱歉,以下是有关您的错误的一些其他信息:

如果您在OCaml中运行您的功能,您将看到此警告:

Warning 10: this expression should have type unit.

s = Str.global_replace( Str.regexp "begin") "" s;的行上。这是因为OCaml中的=运算符在这种情况下不是赋值运算符,而是等于运算符,因此在这一行上,您只需比较两个值并返回一个布尔值。由于OCaml希望e1中的e1;e2返回unit,您会收到此警告。

在OCaml中,变量的值是不可变的,因此您可以:

  • 使用另一个变量@Jason建议:let t = Str.global_replace( Str.regexp "begin") "" s
  • “shadow”我上面建议的旧值:let s = Str.global_replace( Str.regexp "begin") "" s
  • 使用引用(指向内存中某个位置的指针):let s = ref "before" in s := "after",然后您可以使用!运算符!s访问引用指向的值。但是,如果您正在学习函数式编程,我建议您尽量不要在开始时使用OCaml的任何命令性功能来发现这种新的范例及其可能性。

答案 1 :(得分:2)

当我在工作时,我没有与我同房,但乍看之下,在你的第一眼中,文件说:

then

这意味着你不需要“;”因为当函数返回单位时,它就像

这样的语法糖
val global_replace : regexp -> string -> string -> string

此外,您需要使用let语句,因为您不能只重新分配s的值。我不建议将变量遮蔽,因为这在函数式编程中通常是不好的做法。使用类似的东西:

let () = print_endline("foobar")

此外,您的功能有两个不同的功能。你写的辅助递归函数返回true和false,这很好(我假设它有效)。然而,你最终使用它的是你要归还的东西。因此,对于第一个函数,如果“begin”和“end”已被替换,则不会真正返回字符串。因此,你应该让你的函数的结束输出实际上是一个类型的元组(bool,string)。然后你可以在打电话时匹配它(例如

    let t = (Str.global_replace( Str.regexp "begin") "" s)

我相信你对自己的功能有正确的想法。 另外在你的第二个函数中有一种方法可以让你不使用任何while循环和计数器吗? (也希望你的计数器是用引用实现的,否则你将没有任何全局的东西)。我建议重试你调用你的第一个函数的地方作为循环和计数器是命令式编程的核心而不是功能(这是使OCaml如此

的原因
let b,s = isEmptyString "foobar" in
if not b then:
  rest of your code

:)。如果没有,那么有时候只有在OCaml中你不能真正做到的事情没有使用它的命令功能。如果这些建议不起作用,请告诉我。