我认为在缺少最后一个换行符的情况下从io:get_line/1 处理eof 以及处理空行以指示输入结束会更容易:
-module(solution).
-export([start/0]).
process_input(Repeat, Acc)->
case io:get_line("") of
Done when Done == eof; Done == "\n" ->
output(lists:reverse(Acc));
Line ->
Val = string:strip(Line, right, $\n),
Str = lists:duplicate(Repeat, Val),
process_input(Repeat, [Str|Acc])
end.
output(Lines)->
Out = [string:join(L, "\n")++"\n" || L <- Lines],
io:format("~s", [Out]).
start()->
{ok, [Repeat]} = io:fread("", "~d"),
process_input(Repeat, []).
process_input/2 函数现在采用一个累加器,该累加器最初是一个空列表。它递归调用自身,直到检测到输入结束,然后打印输出。它调用io:get_line/1 并检查它是否返回eof 或只是一个换行符,在这种情况下,它反转其累加器并打印其输出。对于任何其他输入,它会去除最后的换行符,通过 lists:duplicate/2 重复输入,将结果存储在新的累加器中,然后将其传递给递归调用。
output/1 函数从process_input/2 获取累加器,用换行符连接重复的值,然后打印结果。请注意,此版本的solution 模块将结果的格式限制为output/1 函数,以防您想将process_input/2 的原始结果用于其他目的。
最后,我将您的 main/0 重命名为 start/0,因为通过 erl -s 命令行选项运行函数假定如果没有给出名为 start 的函数。
我们可以在 Unix shell 中使用printf 来创建一个没有最终换行符的输入文件:
$ printf '3\n1\n2\n3\n4\n' > in
然后像这样运行我们编译的solution 模块,在这种情况下获得我们期望的三倍输出:
$ cat in | erl -noshell -s solution -s init stop
1
1
1
2
2
2
3
3
3
4
4
4
在in 文件中添加最后一个换行符会得到相同的结果(试试看)。我们还可以创建每行包含多个字符的输入:
$ printf '2\nhey\nhey\nwhat\ncan\nI\ndo' > in2
$ cat in2 | erl -noshell -s solution -s init stop
hey
hey
hey
hey
what
what
can
can
I
I
do
do
对于这个in2 文件,我们也得到了预期的双倍输出。