Prolog 设置序列格式的非法参数

Prolog 设置序列格式的非法参数,prolog,swi-prolog,getline,Prolog,Swi Prolog,Getline,我试图在Prolog中编写一个getline谓词,它将获取整行。尝试使用sformat追加字符串时遇到问题: getline(_, Str, 10) :- format('NL. String: ~s\n', [Str]). getline(_, Str, -1) :- format('EOF. String: ~s\n', [Str]). getline(InStr, Str, Cd) :- sformat(NewString, '~s~c'

我试图在Prolog中编写一个getline谓词,它将获取整行。尝试使用sformat追加字符串时遇到问题:

getline(_, Str, 10) :-
        format('NL. String: ~s\n', [Str]).

getline(_, Str, -1) :-
        format('EOF. String: ~s\n', [Str]).

getline(InStr, Str, Cd) :-
        sformat(NewString, '~s~c', [Str, Cd]),
        get_code(InStr, C),
        getline(InStr, NewString, C).

getline(InStr, Str) :-
        get_code(InStr, C),
        getline(InStr, Str, C).

test(InFile) :-
        open(InFile, read, InStr),
        getline(InStr, Line).
运行目标testin.txt。通过上述操作,我得到了以下错误:

ERROR: Prolog initialisation failed:
ERROR: format/3: Illegal argument to format sequence ~s: _G940
似乎G940是一种指针,但我不确定从那里走到哪里。任何帮助都将不胜感激

编辑:现在它可以正常工作,即没有错误,但仍然会将获取完整字符串的问题留给调用方,而不会再次导致相同的问题:

getline(_, Strn, 10) :-
        format('NL. String: ~s\n', [Strn]).

getline(_, Strn, -1) :-
        format('EOF. String: ~s\n', [Strn]).

getline(InStrm, Strn, Cd) :-
        format(string(NewString), '~s~c', [Strn, Cd]),
        get_code(InStrm, C),
        getline(InStrm, NewString, C).

getline(InStrm) :-
        get_code(InStrm, Cd),
        getline(InStrm, '', Cd).

test(InFile) :-
        open(InFile, read, InStrm),
        getline(InStrm).

我对您的代码进行了一些修改,使它现在1读取给定文本文件的第一行,2以字符串形式将该文本文件的第一行返回给调用者

:- use_module(library(readutil)).

test(File, String):-
  setup_call_cleanup(
    open(File, read, In),
    read_line_to_string(In, String),
    close(In)
).
请注意,我使用library readutil来完成部分工作

此外,我还使用setup\u call\u cleanup/3确保在读取行失败或引发异常时关闭流


希望这有帮助

我正在使用SWI Prolog。下划线位于终端谓词中,即get_代码看到换行符或EOF时应调用的谓词。当这种情况发生时,它不再需要输入流的第一个参数,因为它将停止读取。我想。也许吧,这是合理的。但是,例如,如果sformat出于某种原因没有实例化NewString,那么您查询getlineInStr、NewString、C就会得到您看到的错误。我在SWI Prolog文档中没有看到sformat。它似乎已被弃用。我将其替换为新的但仍然类似的方法:formatstringNewString、~s~c、[Strn,Cd]。我还重命名了一些变量,不再出现相同的错误,所以我假设我使用了保留字或其他东西。现在我只需要弄清楚如何将整个字符串返回给调用者。酷。我不知道你展示的其他代码是否使用保留的,但最好避免使用常见名称,如test和getline,因为它们是主要候选名称。@mtbratch用下划线开头变量名只会告诉顶级解释器,您不关心变量绑定,如果查询成功,这些绑定将不会打印出来。除此之外,它和其他变量一样是一个变量。因此,说它没有价值是误导。唯一特殊的命名情况是匿名变量,它由一个下划线表示,即同一术语中的两个匿名变量代表不同的变量。例如,查询a1,2=a_u,u为真。