Prolog - 检查流的结尾不起作用
Prolog - check the end of the stream doesn't work
我有一个文件 memo.dat
,其中包含以下条款:
memo(verdi,11).
memo(rossi,7).
memo(bianchi,9).
memo(blu,7).
memo(neri,11).
memo(carli,11).
memo(rapini,8).
为了从这个文件中获取一组元组,我写了一个序言程序:
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
)
流的结尾只有在您实际到达时才会被检测到。当您读取最后一个事实时,文件结束标记尚未读取。试试像这样的东西:
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 标准要求的布局字符。因此,对于合规、可靠且可移植的解决方案,请确保在数据文件末尾有一个新行,并根据此答案使用解决方案。
我有一个文件 memo.dat
,其中包含以下条款:
memo(verdi,11).
memo(rossi,7).
memo(bianchi,9).
memo(blu,7).
memo(neri,11).
memo(carli,11).
memo(rapini,8).
为了从这个文件中获取一组元组,我写了一个序言程序:
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
)
流的结尾只有在您实际到达时才会被检测到。当您读取最后一个事实时,文件结束标记尚未读取。试试像这样的东西:
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 标准要求的布局字符。因此,对于合规、可靠且可移植的解决方案,请确保在数据文件末尾有一个新行,并根据此答案使用解决方案。