Чтение форматированных входных тестовых примеров из stdin :: OCaml - PullRequest
0 голосов
/ 06 января 2019

Я пытался свернуть код, как предложил 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?

Исходная проблема, с которой я столкнулся, заключается в следующем.

У меня проблема с количеством тестов t, указанным в первой строке ввода. Далее следуют t тестовых случаев. Каждый тестовый набор состоит из двух строк

строка # 1: количество входов n, для данного конкретного теста

строка № 2: n входные числа, разделенные пробелом

Мне нужно сделать некоторые вычисления для каждого теста. Давайте предположим, что мне просто нужно распечатать их обратно на консоль с сообщением «готовый тестовый случай» после каждого вывода тестового примера.

Например, если ввод был следующим,

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, а третий - 6, 3 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 голосов
/ 07 января 2019

Нет ошибки в вашем упрощенном извлечении кода, раскомментирование второй части должно работать, если у 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])
...