我正在使用SWI Prolog学习Prolog,我发现很多困难是如何从文件中读取文本数据并使用参见内置谓词在屏幕上打印。
我有这个程序使用读取模式中的打开谓词和与此文件关联的流读取文件的内容
readFile(InputFile, TextList):- open(InputFile, read, Stream),
readCharacter(Stream, TextList),
close(Stream),
!.
readCharacter(Stream,[]):- at_end_of_stream(Stream). %condizione di uscita
readCharacter(Stream,[Char|Rest]):-
get0(Stream,Char),
readCharacter(Stream,Rest).
这很简单但我问我是否可以使用查看谓词将输入流从用户(控制台)更改为另一个文件来实现相同的行为,然后接近此流(回到用户)使用看见内置的谓词:
我在考虑这样的事情:
readFileSee(InputFile, TextList) :- see(InputFile),
read_from_file(TextList),
seen. %or maybe: see(user).
但是现在,与前面的工作示例不同,我没有调用 get0 谓词的 Stream 变量,因此我不知道如何使用。
有人可以帮我解决这个问题,阅读InputFile的内容并将这些内容放入TextList列表中吗?
答案 0 :(得分:2)
请考虑使用library(pio)
:使用DCG描述文件内容,然后使用phrase_from_file/2
将其应用于文件。
答案 1 :(得分:2)
爱丁堡I / O很方便,但有点毛病,因为它的工作原理是绕过全球状态。这个想法是使用不带流参数的读写谓词。你假装你正在阅读标准输入或写入标准输出。然后,在调用以这种方式工作的代码之前,将全局输入或输出流更改为要读取或写入的文件。
所以,假设您想要读取三个原子字符。你可以写:
read_three([A,B,C]) :- get_char(A), get_char(B), get_char(C).
这适用于标准输入:
?- read_three(X).
|: abc
X = [a, b, c].
要使其与文件一起使用,请使用seeing(OldStream), see(filename), ..., seen, see(OldStream)
对其进行换行,其中代码位于...
部分。例如,我们可以这样做:
read_three(Filename, Three) :-
% the wrapper to switch files
seeing(OldStream), see(Filename),
% your code
read_three(Three),
% the wrapper to switch back
seen, see(OldStream).
使用它,您需要有一个可以读取的文件名,但它可能如下所示:
?- read_three('clone.sh', X).
X = [#, !, /].
这里的关键是你没有传递一个显式的流实例,你只是依赖于隐式使用标准输入或输出来完成工作的谓词。换句话说,如果您的谓词使用的是爱丁堡I / O,那么您的谓词都不应该有Stream
参数,也不应该使用open/3
。
写作的包装类似:telling(OldStream), tell(Filename), ..., told, tell(OldStream).