例外:Invalid_argument" String.sub / Bytes.sub" ocaml的

时间:2017-04-21 21:43:43

标签: string exception ocaml invalid-argument

let separate = fun formula ->
    let rec aux = fun counter begin size ->
    match formula.[begin + size] with
    | '(' -> aux (counter + 1) begin (size + 1)
    | ')' -> if (counter - 1) = 0 then ((String.sub formula (begin + 1) size), (String.sub formula (size + begin + 3) ((String.length formula) - (size + begin + 2)))) else aux (counter - 1) begin (size +1)
    | _ -> aux counter begin (size + 1)
  in aux 0 (String.index formula '(') 0
;;

let main s=
    print_string (fst (separate s))
;;

main "&(A)(B)"

大家好。我的问题是,当我执行这个包含将字符串分成两个的ocaml代码时,我有这个异常:invalid_argument" String.sub / Bytes.sub"。 我想知道,你们能帮助我吗?

2 个答案:

答案 0 :(得分:2)

另一个答案和顶部的第一条评论都指出了一个误用的begin关键字。这是一个小修复,但没有解决安东尼奥的问题。

对于初学者,我不熟悉您使用函数的上下文,我只是想告诉您程序在基于跟踪的方法中出错了。

首先,我对您的代码进行了一些更改,以便它更具可读性,并且更容易找出出现问题的堆栈框架:

let separate = fun formula ->
    let rec aux = fun counter start_position size ->
    match formula.[start_position + size] with
    | '(' -> aux (counter + 1) start_position (size + 1)
    | ')' -> if (counter - 1) = 0 then (
        (Printf.printf "%d %d %d\n" counter start_position size); 
    (
        ((Printf.printf "pass1\n"); (String.sub formula (start_position + 1) size))
        ,
        (String.sub formula (size + start_position + 3) ((String.length formula) - (size + start_position + 2)))
    ) 
        )
            else aux (counter - 1) start_position (size +1)
    | _ -> aux counter start_position (size + 1)
  in aux 0 (String.index formula '(') 0
;;

separate "&(A)(B)";;

(*
1 1 2 
Exception: Invalid_argument "String.sub / Bytes.sub".
Raised at file "pervasives.ml", line 33, characters 25-45
Called from file "string.ml", line 47, characters 2-23
Called from file "//toplevel//", line 10, characters 4-108
Called from file "toplevel/toploop.ml", line 180, characters 17-56
*)

运行此命令,您将发现触发无效参数异常的调用是aux 1 1 2的调用。

然后你可以使用这些代码来测试它出错的原因:

let (counter, start_position, size) = (1,1,2) in
let formula = "&(A)(B)" in
(
(size + start_position + 3)
,
(String.length formula) - (size + start_position + 2) 
)       ;;

(*
- : int * int = (6, 2) 
*)

这就是你知道为什么String.sub不接受你的论点的原因:

String.sub "&(A)(B)" 6 2;;
(*  Exception: Invalid_argument "String.sub / Bytes.sub".
Called from file "toplevel/toploop.ml", line 180, characters 17-56 *)

这是我可以帮助你的。在OCaml中进行调试需要时间,但这是可行的。回到好的打印技巧。 我希望这些信息足以让您了解逻辑错误的原因。我希望你能根据你的问题背景找出解决问题的方法。

答案 1 :(得分:0)

您的代码无法编译,因为您使用的是关键字begin

修改后:

let separate = fun formula ->
    let rec aux = fun counter b size ->
    match formula.[b + size] with
    | '(' -> aux (counter + 1) b (size + 1)
    | ')' -> if (counter - 1) = 0 then ((String.sub formula (b + 1) size), (String.sub formula (size + b + 3) ((String.length formula) - (size + b + 2)))) else aux (counter - 1) b (size +1)
    | _ -> aux counter b (size + 1)
   in aux 0 (String.index formula '(') 0
;;

现在,要获得有关异常的更多可见性,请添加以下内容:

 let () = Printexc.record_backtrace true;;

编译它(使用ocamlbuild)并运行它,你会得到像:

Fatal error: exception Invalid_argument("String.sub / Bytes.sub")
Raised at file "pervasives.ml", line 33, characters 20-45
Called from file "string.ml" (inlined), line 47, characters 2-23
Called from file "sep.ml", line 5, characters 75-153
Called from file "sep.ml" (inlined), line 11, characters 22-34
Called from file "sep.ml", line 15, characters 0-14