0

我有一个程序,它从输入中读取一个字符串,并使用get0get谓词删除单词之间的多个空格,将它们更改为单个空格:

squeeze :- get0(C),    
           put(C),     
           dorest(C).  

dorest(46).   

dorest(32) :- !,       
              get(C),  
              put(C),  
              dorest(C).  

dorest(Letter) :- squeeze.

这很简单,现在我有一个练习,要求 mw 创建一个仅使用内置谓词 get0的先前程序的新版本

我发现这个版本有些困难。

这是我个人对问题的解决方案(效果不佳):

squeeze2 :- NumBlank is 0,  % At the beginning of a word the number of blank character is 0
            get0(Char),     % Read a character that could be a blank
            %put(Char),
            dorest2(Char, NumBlank).

dorest2(46, _) :- !.        % If the read character is a full stop character the program end

% Read a white space but the number of white space is 1
dorest2(32, NumBlank) :- !,
                         NumBlankUpdated is NumBlank + 1,   % Update the number of blanks
                         NumBlankUpdated < 2,               % The number of blank have to be at most 1
                         put(32),                           % Print a white space
                         get0(Char),                        % Read a character
                         dorest2(Char, NumBlankUpdated).    % Call dorest2

% Read a white space but the number of white space is > 1:
dorest2(32, NumBlank) :- !,
                         NumBlankUpdated is NumBlank + 1,   % Update the number of blanks
                         NumBlankUpdated >= 2,          % The number of blanks is >1
                         get0(Char),                % Read a character and don't print anything
                         dorest2(Char, NumBlankUpdated).    % Call dorest2

% Id the read character it is a letter (not a blank) print it
dorest2(Letter2, NumBlank) :- !,
                              put(Letter2),
                              squeeze2. % Read an other character that could be a blank

我只使用get0谓词来解决它的想法涉及计算空格的数量,并根据该值做不同的事情

一个新单词开始时, squeeze2谓词被调用,因此发现它的连续空格数为 0。它从输入中读取一个字符并调用dorest2/2谓词。

现在我将dorest2/2谓词分为 4 种不同的情况,并使用 cut 运算符,这些情况是互斥的(如程序 if):

1)第一种情况,它与读取程序末尾对应的句号字符(“。”字符)相关。

2)第二种情况,它与读取两个单词之间的第一个空白字符有关,因此必须通过 put 谓词打印这个单个空格。在这种情况下,会更新计数连续白色字符数的计数器。然后,读取另一个字符。

3)第三种情况:它与程序读取第二个连续的白色字符的情况有关,在这种情况下,这个withe字符不被打印,另一个字符被读取,并且白色字符计数器用新的数量更新找到连续的白色字符。

4)第四种情况它与程序读取一个不是空格或句号字符的字符的情况有关,所以这个字符必须是一个字母,这意味着一个新单词正在开始。所以只需打印这个字母(通过put)并调用将连续白色字符计数器重置为0的squeeze2谓词并读取一个新字符

问题是在多个连续的空白字符中不起作用。

如果我执行这样的查询效果很好:

没有非空白字符的字符串:

[debug] [2]  ?- squeeze2.
|: ciao.
ciao
true.

这工作得很好。

单词之间仅包含单个白色字符的字符串:

[debug] [2]  ?- squeeze2.
|: ciao.
ciao
true.

这也很好用

但在这种情况下,我有一个错误:

单词之间包含多个字符的字符串:

[debug] [2]  ?- squeeze2.
|    multiple         blanks characters.
multiple 
false.

ERROR: Syntax error: Operator expected
ERROR: blanks 
ERROR: ** here **
ERROR: characters . 

似乎问题出在第三种情况下,但我不明白错误在哪里,因为这种情况在我看来很简单:如果连续白色字符的计数器> 1,则不打印任何内容并继续写入直到 a新词开始。

哪里有问题?有人可以帮助我吗?

肿瘤坏死因子

安德烈亚

4

1 回答 1

2

这里有一些代码工作,它显示了表示字符常量的替代方法,而不是数字代码:

squeeze2 :-
    get0(C),
    squeeze2(C, 0).

squeeze2(C, N) :-
    (   [C] == "."
    ->  true
    ;   (   [C] == " "
        ->  (   N == 0
            ->  put(C)
            ;   true
            ),
            get0(D),
            squeeze2(D, 1)
        ;   put(C),
            get0(D),
            squeeze2(D, 0)
        )
    ).

它归结为单个字符的前瞻。

关于您的代码:问题是第一个空格匹配后的剪切

dorest2(32, NumBlank) :- !,  % remove this
   ...

剪切删除后它起作用:

?- squeeze2.
|: a    b     c  .
a b c 
true .
于 2013-04-22T17:01:32.897 回答