0

簡単にできるはずの何かで頭を壁にぶつけているような気がします。おそらく私のアプローチは間違っています。Prolog の I/O の背後にある概念を理解しているような気がしません。(例: ストリーム エイリアスと open/3 によってバインドされた変数の違いは何ですか?) しかし、私は脱線します:

GNU Prologでファイルを1行ずつ読み取るにはどうすればよいですか? (したがって、SWI が持っている便利な関数にアクセスすることはできません。) get_char/1 と peek_char/1 (終了改行をチェックするため) に関係があると思いますが、実行可能な解決策を実装する私の試みはこれまでのところ失敗しています。

これが私が得た限りです:

readl_as_list(ID, X):-
    current_input(ID),
    readl_as_list(X).

readl_as_list([X]):-
    (peek_char(NextChar), ==(NextChar, '\n'); 
        get_code(Char1),
        append([X], [Char1], X),
        readl_as_list(X)).

printl_list([]):-
    !, nl.
printl_list([H|X]):-
    put_code(H), printl_list(X).

これをインタープリターにロードすると、次のようになります (読みやすくするために空の行は削除されています)。

| ?- open('word_list.txt', read, ID).
ID = '$stream'(2)
yes
| ?- readl_as_list(ID, X).
ID = '$stream'(0)
X = [_] ? 
% (interpreter pauses until I press return)
yes
| ?- printl_list(X).
X = []
yes

行は必ずしも文字リストとして読み込まれる必要はありませんが、私の目標は特定の条件 (たとえば、文字の繰り返しがない) に一致する単語のリストを検索することであるため、それが最も賢明な方法のように思われました。それ。

4

1 に答える 1

2

コードの行をフェッチするユーティリティを作成しました。最後にend_of_fileを返します...

read_line_codes(S, SoFar, L) :-
    get_code(S, C),
    (   C == -1
    ->  (  SoFar == []
        ->  L = end_of_file
        ;   reverse(SoFar, L)
        )
    ;   (  C == 0'\n
        -> reverse(SoFar, L)
        ;  read_line_codes(S, [C|SoFar], L)
        )
    ).

テスト:

?- open('data_grid.pl',read,S),repeat,read_line_codes(S,[],L),format('~s',[L]).
/*  File:    data_grid.pl
S = <stream>(0x335c9e0),
L = [47, 42, 32, 32, 70, 105, 108, 101, 58|...] ;
    Author:  Carlo,,,
S = <stream>(0x335c9e0),
L = [32, 32, 32, 32, 65, 117, 116, 104, 111|...] ;
    Created: Oct 20 2011
S = <stream>(0x335c9e0),
L = [32, 32, 32, 32, 67, 114, 101, 97, 116|...] ;
...
于 2012-11-28T22:16:57.863 に答える