如何检查一个字符串只包含 Prolog 中的某些字符?

How to check that a string contains only certain characters in Prolog?

我想写一个谓词 containsOnly(X,Y),如果字符串 X 仅包含字符串 Y 中的字符,则 return 为真。

我是这样写的:

containsOnly([],_).
containsOnly([H|T],AcceptableCharacters) :- 
    member(H, AcceptableCharacters),
    containsOnly(T,AcceptableCharacters).

但下面的查询 return 错误。我如何修改谓词以使它们 return 为真?

containsOnly('A', 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜabcdefghijklmnopqrstuvwxyzäöüАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзиклмнопрстуфхцчшщъыьэюя-').
containsOnly('a', 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜabcdefghijklmnopqrstuvwxyzäöüАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзиклмнопрстуфхцчшщъыьэюя-').

你的问题是数据类型。您使用原子,但将它们视为 char/code 列表。您可以尝试使用双引号 " 而不是单引号 ' 看看是否有帮助。

对于 SWI-Prolog 7 或更高版本,它无济于事。您将不得不使用反引号而不是双引号。

不过你真的应该搞清楚文档和数据类型。

这是 SWI-Prolog 7 中的代码列表:

`абвгд`

0'x是字符代码的Prolog表示法:

?- X = 0'г.
X = 1075.

?- X = `абв`.
X = [1072, 1073, 1074].

另一件事:如果您使用的是 SWI-Prolog,在这种特殊情况下,您应该使用 memberchk/2 而不是 member/2。但是,如果这是一个效率瓶颈,您也可以考虑使用this page最底部描述的方法。 (如果您要在 SWI-Prolog 程序中处理文本,本手册的整个部分非常重要。)

使用原子,如您的问题,符合 ISO 标准的解决方案:

containsOnly(X,Y) :- forall(sub_atom(X,_,1,_,C), sub_atom(Y,_,1,_,C)).

而 SWI-Prolog 版本。 >= 7 似乎也接受 'strings'。