Prolog-检查流的末尾不起作用

时间:2018-08-28 16:24:14

标签: prolog swi-prolog iso-prolog

我有一个文件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

1 个答案:

答案 0 :(得分: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标准所要求的布局字符。因此,对于兼容,可靠且可移植的解决方案,请确保数据文件末尾有新行,并在此答案中使用解决方案。