从外部文件中读取整个事实

时间:2014-04-01 00:05:26

标签: prolog swi-prolog code-injection

根据下面的内容,当试图断言事实我有类型错误可调用期望时,我认为逐行插入事件发生成功。但是,断言不能正常工作。尽管如此,我试图转换为字符串使用(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. 

2 个答案:

答案 0 :(得分:2)

您正在尝试编写,然后阅读Prolog术语。为此,您应该使用write_term/3read_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)

这是一个很好的例子,可以在没有适当照顾的情况下在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具有相同的价值。