【问题标题】:How do I read a line of input from a user, until an EOF is hit, in GNU Prolog?如何在 GNU Prolog 中读取用户的一行输入,直到 EOF 被击中?
【发布时间】:2021-03-31 15:59:31
【问题描述】:

我一直在阅读GNU Prolog 文档以了解如何读取一行输入,直到达到end_of_file 原子。这是我编写这样一个目标的伪代码:

read_until_end(Chars, Out):
   if peek_char unifies with end_of_file, Out = Chars
   otherwise, get the current character, add it to a buffer, and keep reading

我是这样实现的:

read_until_end(Chars, Out) :-
    peek_char(end_of_file) -> Out = Chars;
    peek_char(C) -> read_until_end([C | Chars], Out).

prompt(Line) :-
    write('> '),
    read_until_end([], Line).

以下是 REPL 中发生的情况:

| ?- prompt(Line).
> test

Fatal Error: global stack overflow (size: 32768 Kb, reached: 32765 Kb, environment variable used: GLOBALSZ)

如果我为read_until_end 的第二个分支打印C,我可以看到peek_char 总是给我相同的字符'b'。我认为我需要一种方法来推进某种类型的输入字符索引或类似的东西,但我在文档中找不到这样做的方法。如果我知道一种方法,我可能不得不使用递归来处理这样的指针,因为我不能有任何可变状态,但除此之外,我不知道该怎么做。有人有什么建议吗?

【问题讨论】:

    标签: input io prolog bufferedinputstream gnu-prolog


    【解决方案1】:

    您正在使用peek_char/1 获取下一个字符,但该谓词不使用流中的字符(它只是“窥视”流)。因此,您的代码会发生无限递归,并以全局堆栈溢出结束。

    您应该使用get_char/1 从流中读取和使用字符,并使用reverse/2 收集的字符列表:

    read_until_end(Chars, Out) :-
        get_char(Char),
        (
         Char = end_of_file -> reverse(Chars, Out)
        ;
         read_until_end([Char | Chars], Out)
        ).
    

    为避免需要反转列表,您可以稍微修改程序以按顺序构建列表(不使用累加器):

    read_until_end(Output) :-
        get_char(Char),
        (
         Char = end_of_file -> Output=[]
        ;
         (
           Output=[Char|NOutput],
           read_until_end(NOutput)
         )
        ).
    
    prompt(Line) :-
        write('> '),
        read_until_end(Line).
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      相关资源
      最近更新 更多