【问题标题】:Prolog - check the end of the stream doesn't workProlog - 检查流的结尾不起作用
【发布时间】:2018-08-28 16:24:14
【问题描述】:

我有一个文件 memo.dat ,包含以下条款:

memo(verdi,11).
memo(rossi,7).
memo(bianchi,9).
memo(blu,7).
memo(neri,11).
memo(carli,11).
memo(rapini,8).

为了从这个文件中获取一组元组,我编写了一个 prolog 程序:

memo_to_list(MemoList):-
    open('/home/ale/Downloads/Prolog_exercises/memo.dat',read,Stream),
    read_list_from_stream(Stream,MemoList),
    close(Stream).

read_list_from_stream(Stream,[]):-
    at_end_of_stream(Stream),!.

read_list_from_stream(Stream,[(Cognome,Ora)|RestoAppuntamenti]):-
    read(Stream,memo(Cognome,Ora)),
    read_list_from_stream(Stream,RestoAppuntamenti).

但是,谓词at_end_of_stream 无法检查流何时到达终点。可能是什么问题? (我使用ubuntu默认文本编辑器创建文件memo.dat

【问题讨论】:

    标签: prolog swi-prolog iso-prolog


    【解决方案1】:

    只有在您实际到达时才会检测到流的结尾。当您阅读最后一个事实时,文件结束标记尚未被读取。试试类似的东西:

    memo_to_list(MemoList):-
        open('/home/ale/Downloads/Prolog_exercises/memo.dat',read,Stream),
        read(Stream,Term),
        read_list_from_stream(Term,Stream,MemoList),
        close(Stream).
    
    read_list_from_stream(end_of_file,_,[]) :-
        !.
    
    read_list_from_stream(memo(Cognome,Ora),Stream,[(Cognome,Ora)|RestoAppuntamenti]):-
        read(Stream,Term),
        read_list_from_stream(Term,Stream,RestoAppuntamenti).
    

    您还可以使用setup_call_cleanup/3 内置谓词避免泄漏流句柄和未关闭的流,以防您的数据文件出现问题:

    memo_to_list(MemoList) :-
        setup_call_cleanup(
            open('/Users/pmoura/Desktop/memo.dat',read,Stream),
            (   read(Stream,Term),
                read_list_from_stream(Term,Stream,MemoList)
            ),
            close(Stream)
        ).
    

    更新

    Prolog 标准要求结束术语的. 后跟一个布局字符。您的代码仅在最后一个词的最后一个点之后没有任何字符(文件结尾除外)时才有效,这使得 Prolog 文本不符合要求,但根据 Prolog 系统,可能允许结束在读取最后一项后调用at_end_of_stream /1 谓词来检测流。另请注意,如果保存时不存在,文本编辑器通常会在最后一行文本之后添加换行符。该换行符是 Prolog 标准要求的布局字符。因此,要获得合规、可靠且可移植的解决方案,请确保数据文件末尾有一个新行,并使用此答案中的解决方案。

    【讨论】:

    • 非常感谢。无论如何,我的代码也应该可以工作。可能是文本编辑器的问题。我编写的程序是标准程序,所以它应该可以工作......
    • 用扩展解释更新了我的答案。
    • 感谢我更改了编辑器(Notepadqq),现在它可以工作了 :)
    • 你认为at_end_of_steam/1的这种行为符合吗?它不应该检查是否还有更多要阅读的内容吗? SWI 不久前就这样做了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 2014-05-10
    • 2013-01-29
    • 2011-08-25
    相关资源
    最近更新 更多