根据下面的内容,当试图断言事实我有类型错误可调用期望时,我认为逐行插入事件发生成功。但是,断言不能正常工作。尽管如此,我试图转换为字符串使用(string_codes(?String,?Codes))或插入代码行但不成功
start:-
writeToFile,
readFromFile,
usereduc(C,D),
writef(C),
writef(D).
writeToFile:-
writef('What is your Name'),nl,
read(Name),
writef('What is your country'),nl,
read(Country),
writef('What is your education'),nl,
read(Education),
open('output.txt',write,Out),
write(Out,usercountry(Name,Country)),nl(Out),
write(Out,usereduc(Name,Education)),
close(Out).
readFromFile:-
open('output.txt',read,In),
repeat,
read_line_to_codes(In,X),nl,
readfactsFromfile(X),asserta(X),
close(In).
readfactsFromfile(end_of_file).
readfactsFromfile(X):-
writef(X),
string_codes(S, X),
asserta(S),!,
fail.
答案 0 :(得分:2)
您正在尝试编写,然后阅读Prolog术语。为此,您应该使用write_term/3
和read_term/3
组合。
由于read/1
要求您在输入字词的末尾添加一个点,我已将选项fullstop/1
添加到write_term/3
。然后,工作代码如下所示:
:- dynamic(usereduc/2).
start:-
writeToFile,
readFromFile,
usereduc(C,D),
writef(C),
writef(D).
writeToFile:-
writef('What is your Name'),nl,
read(Name),
writef('What is your country'),nl,
read(Country),
writef('What is your education'),nl,
read(Education),
setup_call_cleanup(
open('output.txt',write,Out),
(
write_term(Out,usercountry(Name,Country), [fullstop(true)]),nl(Out),
write_term(Out,usereduc(Name,Education), [fullstop(true)])
),
close(Out)
).
readFromFile:-
setup_call_cleanup(
open('output.txt',read,In),
(
repeat,
read_term(In, X, []),
readfactsFromfile(X),asserta(X), !
),
close(In)
).
readfactsFromfile(end_of_file):- !.
readfactsFromfile(X):-
asserta(X),!,
fail.
请注意,我在您的代码中添加了以下其他改进:
* usereduc/2
作为动态谓词的声明。如果遗漏这一点,Prolog会抱怨谓词不存在,因为它在运行时被断言。
*在两个位置使用剪切!
删除了不需要的确定性。
*使用setup_call_cleanup/3
确保打开的流即使在流上执行的操作有问题也会关闭。
请注意,代码仍然是非确定性的,两次给出相同的结果。这是因为代码断言相同的术语两次。
希望这有帮助!
答案 1 :(得分:1)
这是一个很好的例子,code-injection可以在没有适当照顾的情况下在Prolog中被利用。
我的名字是'a,b).\n:- initialization(dobadthings). %'
。所以output.txt看起来像
usercountry(a,b).
:- initialization(dobadthings). %whatevercountry).
userreduc(a,whatevere).
内置谓词read/1
接受完整的Prolog语法。
不幸的是,read/1
的类比不是write/1
,也不是writeq/1
(这很接近),而是:
write_term(T, [quoted(true)]).
variable_names/1
等附加选项可能有助于保留变量名称的特定情况。
另一个(潜在的)问题是特殊writef/1
的使用,这似乎是SWI独有的,并对某些字符做了一些具体的解释。在任何情况下,使用都不是一个好主意。一个简单的write/1
具有相同的价值。