Пролог - проверьте, что конец потока не работает - PullRequest
0 голосов
/ 28 августа 2018

У меня есть файл memo.dat со следующими условиями:

memo(verdi,11).
memo(rossi,7).
memo(bianchi,9).
memo(blu,7).
memo(neri,11).
memo(carli,11).
memo(rapini,8).

Я написал прологическую программу для получения набора кортежей из этого файла:

memo_to_list(MemoList):-
    open('/home/ale/Downloads/Prolog_exercises/memo.dat',read,Stream),
    read_list_from_stream(Stream,MemoList),
    close(Stream).

read_list_from_stream(Stream,[]):-
    at_end_of_stream(Stream),!.

read_list_from_stream(Stream,[(Cognome,Ora)|RestoAppuntamenti]):-
    read(Stream,memo(Cognome,Ora)),
    read_list_from_stream(Stream,RestoAppuntamenti).

Однако предикат at_end_of_stream не может проверить, когда поток достигает своего конца. В чем может быть проблема? (Я использовал текстовый редактор Ubuntu по умолчанию для создания файла memo.dat)

1 Ответ

0 голосов
/ 28 августа 2018

Конец потока обнаруживается только тогда, когда вы действительно достигли его. Когда вы читаете последний факт, маркер конца файла еще предстоит прочитать. Попробуйте вместо этого что-то вроде:

memo_to_list(MemoList):-
    open('/home/ale/Downloads/Prolog_exercises/memo.dat',read,Stream),
    read(Stream,Term),
    read_list_from_stream(Term,Stream,MemoList),
    close(Stream).

read_list_from_stream(end_of_file,_,[]) :-
    !.

read_list_from_stream(memo(Cognome,Ora),Stream,[(Cognome,Ora)|RestoAppuntamenti]):-
    read(Stream,Term),
    read_list_from_stream(Term,Stream,RestoAppuntamenti).

Вы также можете избежать утечек ручек потоков и незакрытых потоков в случае, если что-то не так с вашим файлом данных, используя встроенный предикат setup_call_cleanup/3:

memo_to_list(MemoList) :-
    setup_call_cleanup(
        open('/Users/pmoura/Desktop/memo.dat',read,Stream),
        (   read(Stream,Term),
            read_list_from_stream(Term,Stream,MemoList)
        ),
        close(Stream)
    ).

Обновление

Стандарт Пролог требует, чтобы за ., заканчивающим термин, следовал символ макета. Ваш код работает только в том случае, если после последней точки последнего термина нет символа (кроме конца файла), что делает текст Prolog несоответствующим, но, в зависимости от системы Prolog, может разрешать конец потока, который будет обнаружен путем вызова предиката at_end_of_stream /1 после чтения последнего члена. Обратите внимание также, что текстовые редакторы обычно добавляют новую строку после последней строки текста, если ее нет при сохранении. Эта новая строка является символом макета, как того требует стандарт Prolog. Поэтому для совместимого, надежного и переносимого решения убедитесь, что в конце файла данных есть новая строка, и используйте решение в этом ответе.

...