从stdin :: OCaml读取格式化的输入测试用例

时间:2019-01-06 19:52:40

标签: ocaml scanf stdout stdin

我试图按照glennsl的建议最小化代码。事实证明,我不知道如何从OCaml的多行中读取输入。

例如,假装stdin包含以下模式

5
1 2 3 4 5
3
6 7 8

我需要阅读并打印到stdout。我使用"%d %d %d %d %d\n"格式说明符,好像我事先知道输入数是5,只是为了说明我的问题。

现在以下代码失败,并显示相同的错误Fatal error: exception End_of_file(我尝试用更少的代码行重现相同的问题)如果我取消注释底部的内容

let number_of_inputs1 = read_int () in 
let input_arr1 = Scanf.scanf "%d %d %d %d %d\n" (fun a b c d e -> [a]@[b]@[c]@[d]@[e]) in 
let rec print_test_case inputs = 
        match inputs with
        |[] ->(print_newline ();print_string "done test case"; print_newline ();)
        |hd::tl -> (print_int hd; print_string " "; print_test_case tl)
    in print_int number_of_inputs1; print_newline (); print_test_case input_arr1;

(*
let number_of_inputs2 = read_int () in
let input_arr2 = Scanf.scanf "%d %d %d\n" (fun a b c -> [a]@[b]@[c]) in 
print_int number_of_inputs2; print_newline (); print_test_case input_arr2;
*)

它现在打印以下内容,

5
1 2 3 4 5 
done test case

我需要打印类似的东西

5
1 2 3 4 5 
done test case
3
6 7 8
done test case

我应该如何正确地从stdin多行读取这种格式的输入?

我最初遇到的问题是。

我有一个问题,在输入的第一行中指定了测试用例的数量tt个测试用例如下。每个测试用例由两行组成

第1行:针对此特定测试用例的输入数量n

第2行:n个输入数字,以空格分隔

我需要对每个测试用例进行一些计算。假设我只需要在每个测试用例输出之后将它们打印回控制台,并显示一条消息“ done test case”。

例如,如果输入以下内容,

5
3
1 2 3
3
2 1 3
6
3 2 1 5 4 6
4
1 3 4 2
5
3 4 5 1 2

请注意,此问题中有5个测试用例。例如,第一个测试用例有3个输入1 2 3,第三个测试用例有63 2 1 5 4 6

我需要打印

1 2 3
done test case
2 1 3
done test case
3 2 1 5 4 6
done test case
1 3 4 2
done test case
3 4 5 1 2
done test case

到目前为止,我已经尝试了以下方法,

let test_cases = read_int () in (*read the number of test cases*)
let rec print_all_test_cases tc = (*define a function that will call the individual test cases*)
    if (tc > 0) (*check if there are more test cases left*)
    then 
    let num_of_inputs = read_int() in (*read the number of inputs*)
    let rec read_inputs_for_test_case n arr = (*function to recursively read all inputs for the test case*)
        if (n == 0) 
        then arr (*if everthing is read return the accumulated array*)
        else 
        let i = Scanf.scanf "%d " (fun i -> i) in (*else read the input*)
        read_inputs_for_test_case (n-1) (arr @ [i]) (*recurse for the remaining inputs, accumulating current input to the argument*)
    in
    let rec print_test_case inputs = (*print inputs for the test case*)
        match inputs with
        |[] ->(print_newline ();print_string "done test case"; print_newline ();)
        |hd::tl -> (print_int hd; print_string " "; print_test_case tl)
    in 
    print_test_case (read_inputs_for_test_case num_of_inputs []); (*call to read and print inputs*)
    print_all_test_cases (tc-1) (*recursively do the remaining test cases*)
    else () 
in print_all_test_cases test_cases 

它将以下内容打印到stdout

1 2 3 
done test case

并在stderr上失败并显示以下错误

Fatal error: exception End_of_file

如何正确阅读所有内容并按要求打印?

1 个答案:

答案 0 :(得分:1)

简化的代码提取中没有错误,如果stdin的数据正确,则取消注释第二部分应该起作用。

您可能应该首先使用固定的字符串数据测试代码:

let text = "5
1 2 3 4 5
3
6 7 8
"

let source = Scanf.Scanning.from_string text
let number_of_inputs1 = Scanf.bscanf source "%d\n" (fun n -> n)
let input_arr1 =
  Scanf.bscanf source  "%d %d %d %d %d\n" (fun a b c d e -> [a;b;c;d;e])