Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

KN_Vse_lektsii / algan20

.pdf
Скачиваний:
84
Добавлен:
23.02.2015
Размер:
264.62 Кб
Скачать

Алгоритмический анализ. Лекция 20.

Программирование на Scheme

Ввод и вывод (продолжение)

Рассмотрим программу, которая читает посимвольно содержимое текстового файла и выводит его на экран.

(define (file-char)

(define in (open-input-file "in.txt") ) (define (next)

(define n (read-char in))

(display n); здесь можно было написать (write n) (if (equal? n eof) (write 'end) (next) ) )

(next) (close-input-port in) )

Обсудим особенности работы этой функции. В процессе чтения read-char возвращает либо очередной символ, либо признак конца файла, т.е. значение #<eof>. В программе мы сравниваем результат чтения с переменной eof, которая как раз этому значению и равна.

После работы с файлом рекомендуется закрывать порт.

Рассмотрим второй пример чтения из файла. Пусть требуется посчитать количество прочитанных символов. Тогда было бы логично, чтобы функция next имела параметр, где и накапливался бы результат. Но тогда структуру функции придется изменить.

Мы не получим результата, если напишем

(define (file-char-count)

(define in (open-input-file "in.txt") ) (define (next k)

(define n (read-char in))

(if (equal? n eof) k (next (+ k 1) ) ) )

(next 0 ) (close-input-port in) )

Правильная версия:

(define (file-char-count)

(define in (open-input-file "in.txt") ) (define (next k)

(define n (read-char in)) (if (equal? n eof)

(begin (close-input-port in) k) (next (+ k 1) ) ) )

(next 0) )

Если файл "in.txt" содержит информацию:

1 -2 3 4

5 6 7 8.5

abc 2e-4 1.23E+1 x y z

Тогда результат вызова функции (file-char) будет таким:

> (file-char) 1 -2 3 4 5 6 7 8.5

abc 2e-4 1.23E+1 x y z#<eof>end

Рассмотрим функцию

(define (file-data)

(define in (open-input-file "in.txt")) (define (next)

(define n (read in)) (write n)

(display " ")

(if (equal? n eof) (close-input-port in) (next))) (next))

> (file-data)

1 -2 3 4 5 6 7 8.5 abc 0.0002 12.3 x y z #<eof>

В случае, когда мы используем файлы не только для чтения, но и для записи, то применяется функция

(open-output-file path [#:mode mode-flag

#:exists exists-flag])

где можно задавать режимы: 'binary или 'text, а также порядок действия с существующим файлом:

'error – приводит к ошибке, если файл уже существует.

'replace – удаляет старый файл (если он был) и создает новый.

'truncate – удаляет все старые данные в существующем файле.

'must-truncate – удаляет все старые данные в существующем файле, а если его не было – сообщение об ошибке.

'truncate/replace – попытка 'truncate; если неудачная, то

'replace.

'update – открывает имеющийся файл, сохраняя там данные, а если файла нет, то ошибка.

'can-update – открывает имеющийся файл, сохраняя там данные, а если файла нет, то он будет создан.

'append – открывает файл для добавления, при этом он обязан существовать.

Пример: функция читает файл, находит сумму имеющихся в нем целых чисел, а вещественные числа записываются другой файл.

(define (file-sum)

(define in (open-input-file "in.txt"))

(define out (open-output-file "out.txt" #:exists 'replace)) (define (iter sum)

(define n (read in)) ; (write n) (display #\space) (if (equal? n eof)

(begin (close-output-port out) sum ) (cond

((integer? n) (iter (+ n sum))) ((real? n) (write n out) (iter sum)) (else (iter sum))))

)

(iter 0) )

Имеются и более мощные средства работы с файлами в scheme.

(define (file-list)

(define in (open-input-file "in.txt")) (define lines (port->lines in)) (write lines)

(close-input-port in))

Результат ее работы

> (file-list)

("1 -2 3 4" "5 6 7 8.5 " "abc 2e-4 1.23E+1 x y z")

Получили список из строк нашего файла.

Метод конечных автоматов

В задачах обработки потоковых данных особую роль играют алгоритмы, которые по сути являются итерационными и совершают следующий шаг, зная все о своем текущем состоянии и новой к этому моменту информации.

Конечный автомат — в теории алгоритмов математическая абстракция, позволяющая описывать пути изменения состояния объекта в зависимости от его текущего состояния и входных данных, при условии, что общее возможное количество состояний конечно. Конечный автомат является частным случаем абстрактного автомата.

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

Q — конечное множество состояний автомата;

q0 начальное состояние автомата ();

F — множество заключительных (или допускающих)

состояний, таких что ;

Σ — допустимый входной алфавит (конечное множество допустимых входных символов), из которого формируются строки, считываемые автоматом;

δ — заданное отображение множества во множество подмножеств Q:

(иногда δ называют функцией переходов автомата).

Автомат начинает работу в состоянии q0, считывая по одному символу входной строки. Считанный символ переводит автомат в новое состояние из Q в соответствии с функцией переходов. Если по завершении считывания входного слова (цепочки символов) автомат оказывается в одном из допускающих состояний, то слово «принимается» автоматом. В этом случае говорят, что оно принадлежит языку данного автомата. В противном случае слово «отвергается».

Конечные автоматы широко используются на практике, например в синтаксических, лексических анализаторах, и тестировании программного обеспечения на основе моделей.

Пример Пусть Q = {1,2}, , I = {1}, F = {2},

Тогда

- конечный автомат.

Замечание. Конечные автоматы можно изображать в виде диаграмм состояний (state diagram) (иногда их называют диаграммами переходов (transition diagram)). На диаграмме каждое состояние обозначается кружком, а переход - стрелкой. Стрелка из

p в q, помеченная словом x, показывает, что является переходом данного конечного автомата. Каждое начальное состояние распознается по ведущей в него короткой стрелке. Каждое допускающее состояние отмечается на диаграмме двойным кружком.

Пример. На диаграмме изображен конечный автомат из примера.

Пример программы, которая выделяет все комментарии из одного файла в другой.

(define (comment file-in file-out) (define in (open-input-file file-in))

(define out (open-output-file file-out #:exists 'replace)) (define (next s)

(define c (read-char in)) (if (equal? c eof)

(close-output-port out) (cond

((= s 0) (cond

((equal? c #\;) (next 1)) ((equal? c #\") (next 2)) ((equal? c #\\) (next 3)) (else (next s))))

((= s 1) (write-char c out)

(cond

((equal? c #\newline) (next 0)) (else (next s))))

((= s 2) (cond

((equal? c #\") (next 0)) (else (next s))))

((= s 3) (cond

((equal? c #\\) (next 3)) (else (next 0)))))))

(next 0))

Соседние файлы в папке KN_Vse_lektsii