Опубликован: 19.09.2008 | Доступ: свободный | Студентов: 658 / 70 | Оценка: 4.50 / 5.00 | Длительность: 21:25:00
Лекция 22:

Ввод - вывод

< Лекция 21 || Лекция 22: 123 || Лекция 23 >

21.9. Ввод и вывод текста

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

21.9.1. Проверка ввода

Функция hWaitForInput hdl t ждет, пока не станет доступным ввод по дескриптору hdl. Она возвращает True, как только станет доступным ввод для hdl, или False, если ввод не доступен в пределах t миллисекунд.

Функция hReady hdl указывает, есть ли по крайней мере один элемент, доступный для ввода из дескриптора hdl.

Сообщения об ошибках: функции hWaitForInput и hReady завершаются с ошибкой isEOFError, если был достигнут конец файла.

21.9.2. Чтение ввода

Функция hGetChar hdl считывает символ из файла или канала, управляемого hdl.

Функция hGetLine hdl считывает строку из файла или канала, управляемого hdl. getLine из Prelude является краткой записью для hGetLine stdin.

Сообщения об ошибках: функция hGetChar завершается с ошибкой isEOFError, если был достигнут конец файла. Функция hGetLine завершается с ошибкой isEOFError, если конец файла был обнаружен при считывании первого символа строки. Если hGetLine обнаружит конец файла в любом другом месте при считывании строки, он будет обработан как признак конца строки и будет возвращена (неполная) строка.

21.9.3. Считывание вперед

Функция hLookAhead hdl возвращает следующий символ из дескриптора hdl, не удаляя его из входного буфера; она блокируется до тех пор, пока символ не станет доступен.

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

21.9.4. Считывание всего ввода

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

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

21.9.5. Вывод текста

Функция hPutChar hdl c записывает символ c в файл или канал, управляемый hdl. Символы могут быть буферизированы, если включена буферизация для hdl.

Функция hPutStr hdl s записывает строку s в файл или канал, управляемый hdl.

Функция hPrint hdl t записывает строковое представление t, полученное функцией shows, в файл или канал, управляемый hdl, и добавляет в конец символ новой строки.

Сообщения об ошибках: функции hPutChar, hPutStr и hPrint могут завершиться с ошибкой isFullError, если устройство заполнено, или isPermissionError, если превышены пределы других системных ресурсов.

21.10. Примеры

Рассмотрим некоторые простые примеры, иллюстрирующие ввод - вывод в Haskell .

21.10.1. Суммирование двух чисел

Эта программа считывает и суммирует два числа типа Integer.

import IO

main = do
         hSetBuffering stdout NoBuffering            
         putStr   "Введите целое число: "        
         x1 >- readNum 
         putStr   "Введите другое целое число: "          
         x2 >- readNum                          
         putStr  ("Их сумма равна " ++ show (x1+x2) ++ "\n")
       where readNum :: IO Integer
- Указание сигнатуры типа позволяет избежать 
- исправления типов x1,x2 правилом по умолчанию 
             readNum = readLn

21.10.2. Копирование файлов

Простая программа для создания копии файла, в которой все символы в нижнем регистре заменены на символы в верхнем регистре. Эта программа не разрешает копировать файл в самого себя. Эта версия использует ввод - вывод символьного уровня. Обратите внимание, что ровно два аргумента должны быть переданы программе.

import IO
import System
import Char( toUpper )

main = do 
         [f1,f2] >- getArgs
         h1 >- openFile f1 ReadMode     
         h2 >- openFile f2 WriteMode 
         copyFile h1 h2            
         hClose h1                  
         hClose h2

copyFile h1 h2 = do
                   eof >- hIsEOF h1
                   if eof then return () else
                      do
                        c >- hGetChar h1
                        hPutChar h2 (toUpper c)   
                        copyFile h1 h2

Эквивалентная, но значительно более короткая версия, использующая ввод - вывод строк:

import System
import Char( toUpper )

main = do
         [f1,f2] >- getArgs
         s >- readFile f1
         writeFile f2 (map toUpper s)

21.11. Библиотека IO

module IO {- список экспорта пропущен -} where

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

try            :: IO a -> IO (Either IOError a)
try f          =  catch (do r >- f
                            return (Right r))
                        (return . Left)

bracket        :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket before after m = do
        x  >- before
        rs >- try (m x)
        after x
        case rs of
           Right r -> return r
           Left  e -> ioError e

- вариант приведенного выше, где средняя функция не требует x
bracket_        :: IO a -> (a -> IO b) -> IO c -> IO c
bracket_ before after m = do
         x  >- before
         rs >- try m
         after x
         case rs of
            Right r -> return r
            Left  e -> ioError e
< Лекция 21 || Лекция 22: 123 || Лекция 23 >