Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Ещё больше шалостей со списком делСодержание книги
Поиск на нашем сайте
В предыдущих примерах мы писали отдельные программы для до- бавления и удаления заданий в списке дел. Теперь мы собираемся объединить их в новое приложение, а что ему делать, будем указы- вать в командной строке. Кроме того, позаботимся о том, чтобы программа смогла работать с разными файлами – не только todo.txt. Назовём программу просто todo, она сможет делать три разные вещи: ® просматривать задания; ® добавлять задания; ® удалять задания. Для добавления нового задания в список дел в файле todo.txt мы будем писать: $./todo add todo.txt "Найти магический меч силы"
Просмотреть текущие задания можно будет командой view: $./todo view todo.txt Для удаления задания потребуется дополнительно указать его индекс: $./todo remove todo.txt 2
Многозадачный список задач Начнём с реализации функции, которая принимает команду в виде строки (например, "add" или "view") и возвращает функцию, кото- раявсвоюочередьпринимаетсписокаргументовивозвращаетдейс- твие ввода-вывода, выполняющее в точности то, что необходимо: import System.Environment import System.Directory import System.IO import Data.List import Control.Exception
dispatch:: String -> [String] –> IO () dispatch "add" = add dispatch "view" = view dispatch "remove" = remove Функция main будет выглядеть так: main = do (command:argList) <- getArgs dispatch command argList Первым делом мы получаем аргументы и связываем их со спис- ком (command:argsList). Таким образом, первый аргумент будет связан с именем command, а все остальные – со списком argList. В следующей строке к переменной commands применяется функ- ция dispatch, результатом которой может быть одна из функций add, view или remove. Затем результирующая функция применяется к списку аргументов argList. Предположим, программа запущена со следующими парамет- рами:
$./todo add todo.txt "Найти магический меч силы" Тогда значением command будет "add", а значением argList – спи- сок ["todo.txt", "Найти магический меч силы"]. Поэтому сработает первый вариант определения функции dispatch и будет возвраще- на функция add. Применяем её к argList, результатом оказывается действие ввода-вывода, добавляющее новое задание в список. Теперь давайте реализуем функции add, view и remove. Начнём с первой из них: add:: [String] –> IO () add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n") При вызове $./todo add todo.txt "Найти магический меч силы" функции add будет передан список ["todo.txt", "Найти магический меч силы"]. Поскольку пока мы не обрабатываем некорректный ввод, достаточно будет сопоставить аргумент функции add с двухэлемен- тным списком. Результатом функции будет действие ввода-вывода, добавляющее строку вместе с символом конца строки в конец фай- ла. Далее реализуем функциональность просмотра списка. Если мы хотим просмотреть элементы списка, то вызываем программу так: todo view todo.txt. В первом сопоставлении с образцом идентифика- тор command будет связан со строкой view, а идентификатор argList будет равен ["todo.txt"]. Вот код функции view: view:: [String] –> IO () view [fileName] = do contents <– readFile fileName let todoTasks = lines contents numberedTasks = zipWith (\n line –> show n ++ " – " ++ line) [0..] todoTasks putStr $ unlines numberedTasks Программа, которая удаляла задачу из списка, производила практически те же самые действия: мы отображали список задач, чтобы пользователь мог выбрать, какую из них удалить. Но в этой функции мы просто отображаем список.
Ну и наконец реализуем функцию remove. Функция будет очень похожа на программу для удаления элемента, так что если вы не понимаете, как работает функция удаления, прочитайте поясне- ния к её определению. Основное отличие – мы не задаём жёстко имя файла, а получаем его как аргумент. Также мы не спрашиваем у пользователя номер задачи для удаления – его мы также получаем в виде аргумента. remove:: [String] -> IO () remove [fileName, numberString] = do contents <- readFile fileName let todoTasks = lines contents number = read numberString newTodoItems = unlines $ delete (todoTasks!! number) todoTasks bracketOnError (openTempFile "." "temp") (\(tempName, tempHandle) –> do hClose tempHandle removeFile tempName) (\(tempName, tempHandle) –> do hPutStr tempHandle newTodoItems hClose tempHandle removeFile fileName renameFile tempName fileName) Мы открываем файл, полное имя которого задаётся в иденти- фикаторе fileName, открываем временный файл, удаляем строку по индексу, записываем во временный файл, удаляем исходный файл и переименовываем временный в fileName. Приведем полный лис- тинг программы во всей её красе: import System.Environment import System.Directory import System.IO import Control.Exception import Data.List
dispatch:: String -> [String] -> IO () dispatch "add" = add dispatch "view" = view dispatch "remove" = remove
main = do
(command:argList) <- getArgs dispatch command argList
add:: [String] -> IO () add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n")
view:: [String] -> IO () view [fileName] = do contents <- readFile fileName let todoTasks = lines contents numberedTasks = zipWith (\n line -> show n ++ " – " ++ line) [0..] todoTasks putStr $ unlines numberedTasks
remove:: [String] -> IO () remove [fileName, numberString] = do contents <- readFile fileName let todoTasks = lines contents number = read numberString newTodoItems = unlines $ delete (todoTasks!! number) todoTasks bracketOnError (openTempFile "." "temp") (\(tempName, tempHandle) -> do hClose tempHandle removeFile tempName) (\(tempName, tempHandle) -> do hPutStr tempHandle newTodoItems hClose tempHandle removeFile fileName renameFile tempName fileName) Резюмируем наше решение. Мы написали функцию dispatch, отображающую команды на функции, которые принимают аргумен- ты командной строки в виде списка и возвращают соответствующее действие ввода-вывода. Основываясь на значении первого аргумен- та, функция dispatch даёт нам необходимую функцию. В результате вызова этой функции мы получаем требуемое действие и выполня- ем его. Давайте проверим, как наша программа работает: $./todo view todo.txt 0 – Погладить посуду 1 – Помыть собаку
2 – Вынуть салат из печи
$./todo add todo.txt "Забрать детей из химчистки"
$./todo view todo.txt 0 – Погладить посуду 1 – Помыть собаку 2 – Вынуть салат из печи 3 – Забрать детей из химчистки
$./todo remove todo.txt 2
$./todo view todo.txt 0 – Погладить посуду 1 – Помыть собаку 2 – Забрать детей из химчистки Большой плюс такого подхода – легко добавлять новую функ- циональность. Добавить вариант определения функции dispatch, реализовать соответствующую функцию – и готово! В качестве уп- ражнения можете реализовать функцию bump, которая примет файл и номер задачи и вернёт действие ввода-вывода, которое поднимет указанную задачу на вершину списка задач.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2017-02-17; просмотров: 171; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.37.178 (0.006 с.) |