Читайте файл построчно в Прологе - PullRequest
17 голосов
/ 26 января 2011

Я хотел бы прочитать текстовый файл и применить предикат к каждой строке (предикаты содержат write, который выводит). Как бы я это сделал?

Ответы [ 3 ]

20 голосов
/ 26 января 2011

Вы можете использовать read для чтения потока. Не забудьте вызвать at_end_of_stream, чтобы избежать синтаксических ошибок.

Пример:

readFile.pl

main :-
    open('myFile.txt', read, Str),
    read_file(Str,Lines),
    close(Str),
    write(Lines), nl.

read_file(Stream,[]) :-
    at_end_of_stream(Stream).

read_file(Stream,[X|L]) :-
    \+ at_end_of_stream(Stream),
    read(Stream,X),
    read_file(Stream,L).

Myfile.txt

'line 0'.
'line 1'.
'line 2'.
'line 3'.
'line 4'.
'line 5'.
'line 6'.
'line 7'.
'line 8'.
'line 9'.

Таким образом, вызвав main, вы получите вывод:

?- main.
[line 0,line 1,line 2,line 3,line 4,line 5,line 6,line 7,line 8,line 9]
true 

Просто настройте main. Вывод здесь является примером использования write, конечно. Настройте в соответствии с вашим запросом.

Я предполагаю, что этот принцип может быть применен для ответа на ваш вопрос. Удачи.

14 голосов
/ 26 января 2011

В SWI-Prolog самое чистое решение - написать DCG, которая описывает, что такое «строка», а затем вызвать предикат для каждой строки. Используйте библиотеку (pio), чтобы применить DCG к файлу.

РЕДАКТИРОВАТЬ : По запросу рассмотрим:

:- use_module(library(pio)).

lines([])           --> call(eos), !.
lines([Line|Lines]) --> line(Line), lines(Lines).

eos([], []).

line([])     --> ( "\n" ; call(eos) ), !.
line([L|Ls]) --> [L], line(Ls).

Пример использования: ?- phrase_from_file(lines(Ls), 'your_file.txt').

0 голосов
/ 07 мая 2019

Существует несколько возможных и более разумных в производительности решений для получения неинтерпретируемых, т.е. простых текстовых строк из файла:

SWI-Prolog:

read_line(S, X) :- 
   read_line_to_codes(S, L), 
   read_line2(L, X).

read_line2(end_of_file, _) :- !, fail.
read_line2(L, X) :-
   atom_codes(X, L).

Jekejeke Prolog:

:- use_module(library(stream/console)).

Вот некоторые временные интервалы чтения файла из 655 строк:

test :-
   open('<path>', read, Stream),
   test(Stream),
   close(Stream).

test(Stream) :-
   read_line(Stream, _), !,
   test(Stream).
test(_).

SWI-Prolog:

̀?- time((between(1,100,_), test, fail; true)).
% 328,300 inferences, 0.125 CPU in 0.143 seconds (88% CPU, 2626400 Lips)
true.

Jekejeke Prolog:

?- time((between(1,100,_), test, fail; true)).
% Up 121 ms, GC 2 ms, Thread Cpu 94 ms (Current 05/07/19 17:19:05)
Yes

Полагаю, что решение SWI-Prolog, которое вместо строки читает атом, может быть быстрее.Но в приведенном выше примере мы сравниваем атом с показанием атома.

...