0

I am having a problem of reading a text file that contains this information:

T11, R1, 6:00-18:00 T12, R1, 6:00-18:00 T13, R1, 18:00-6:00

For now I have a prolog code for reading it , if I add '' in each line and period in the end. It converts it to one List , but I need separate lists for each line. I also tried to use:

/*rows(Total,Rows_list):-
    atomic_list_concat(Rows_list,nl, Total),
    write(Rows_list), nl.*/

But it does not work and displays error message of too long string.

main :-
    open('taxi.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).
/*rows(Total,Rows_list):-
    atomic_list_concat(Rows_list,nl, Total),
    write(Rows_list), nl.*/
4

1 回答 1

2

read/2 不适合解析“自由文本”文件,因为它旨在解析完全结构化的 Prolog 术语,例如那些由 writeq/1 或 Listing/0 编写的术语。

通常,解析文件更简单的方法是使用 DCG。由于它是逐个字符的解析,因此您需要注意一些细节:

:- [library(dcg/basics)].

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

read_file(Stream,[X|L]) :-
    \+ at_end_of_stream(Stream),
    read_line_to_codes(Stream, Codes),
    ( phrase(parse_record(Record), Codes) -> assertz(Record) ; writeln('ERROR')),
    read_file(Stream,L).

parse_record(taxi(T1, R1, (H1:M1)-(H2:M2),
       T2, R2, (H3:M3)-(H4:M4),
       T3, R3, (H5:M5)-(H6:M6))) -->
    parse_triple(T1,R1, (H1:M1)-(H2:M2)), " ",
    parse_triple(T2,R2, (H3:M3)-(H4:M4)), " ",
    parse_triple(T3,R3, (H5:M5)-(H6:M6)).

parse_triple(T,R, (H1:M1)-(H2:M2)) -->
    string(Ts), ", ", string(Rs), ", ",
    integer(H1), ":", integer(M1),
    "-", integer(H2), ":", integer(M2),
{atom_codes(T,Ts), atom_codes(R,Rs)}.

DCG 的一个有用特性是可以相当容易地测试内联数据:

?- phrase(parse_record(R),"T11, R1, 6:00-18:00 T12, R1, 6:00-18:00 T13, R1, 18:00-6:00").
R = taxi('T11', 'R1', (6:0)- (18:0), 'T12', 'R1', (6:0)- (18:0), 'T13', 'R1', (18:0)- (6:0)) 

编辑我肯定需要更多的咖啡,因为我没有注意到您传递给 read_file 的列表参数。代码应阅读

read_file(Stream,[X|L]) :-
    \+ at_end_of_stream(Stream),
    read_line_to_codes(Stream, Codes),
    ( phrase(parse_record(X), Codes) -> true ; writeln('ERROR')),
    read_file(Stream,L).
于 2013-10-23T20:39:03.343 回答