Опубликован: 15.11.2010 | Доступ: свободный | Студентов: 746 / 45 | Оценка: 4.00 / 5.00 | Длительность: 17:30:00
Специальности: Программист
Лекция 1:

Классификация ввода-вывода

Лекция 1: 12345678 || Лекция 2 >
Аннотация: В данной лекции Вы познакомитесь с основной классификацией функций и операторов ввода-вывода, применяемых в современных языках программирования.
Ключевые слова: операторы, ПО, периферийное устройство, интерфейс ввода, перенаправление вывода, WIMP, интерфейс программирования приложений, операции, вывод, текстовый формат, запись, прямой, доступ, API, MS-DOS, многозадачность, алгоритм, очереди сообщений, Windows, файл, программа, функции субд, базы данных, пункт, блок операторов, переменная класса, императивный язык, окончание блока, приложение командной строки, predicate, goal, массив символов, символическое имя, процесс исполнения, стандартный поток вывода, substitutability, диапазон строк, шаблон регулярного выражения, входная строка, потоковый редактор, BAS, спецсимвол, директива компилятора, оператор описания, шаблон оформления, VBE, скалярная величина, EOL, локальная функция, Си, информация, шаблон, псевдоним, заголовочный файл, именованные переменные, определение, переопределение, универсальность, константы, глобальные переменные, объединение, автор, GPL, para, сегментный регистр, командная оболочка, оператор безусловного перехода, выполняемый оператор

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

1.1. Классификация по способу вывода

По способу ввода-вывода информации на периферийное устройство используют следующую классификацию:

  1. Прямое программирование устройств. При этом способе программа сама, без помощи других программ, программирует периферийное устройство. Хотя этот способ является исторически первым и обеспечивает максимальное быстродействие, в настоящее время он не используется из-за своей практической "непереносимости" между компьютерами.
  2. Прямое программирование через драйвер устройства. Драйвер - это такая программа, которая "перехватывает обращение" пользователя или операционной системы к периферийному устройству, предлагая более или менее "унифицированный интерфейс" функций для работы с устройством. При этом пользователю не нужно "вникать" в аппаратную реализацию устройства, обращаться к регистрам и портам устройства по уникальным адресам, и, в конце концов, держать всю эту информацию в своей голове. Драйвер предоставляет доступ к функциям управления устройствами либо через "прерывания" (в MS-DOS), либо через специальные функции операционной системы (Windows, Unix), либо как некоторый объект с методами (Win32 и др.). Недостаток этого метода заключается в том, что написать один драйвер с интерфейсом "на все случаи жизни" не представляется возможным. Поэтому программирование через драйвер устройства является также "сложной работой" даже для профессионалов, однако такого рода ввод-вывод является: "вводом-выводом среднего уровня". На практике используется "ввод-вывод высокого уровня", когда с драйвером устройства будет работать одна или несколько "промежуточных программ", обеспечивающих единый интерфейс ввода-вывода для прикладных программ.
  3. Буферизированный (потоковый) ввод-вывод. Этот вывод реализован на уровне консоли в MS-DOS, Windows и UNIX. При этом способе в оперативной памяти ЭВМ создаётся "буфер" для записи или считывания из него символов, и непосредственным их вводом-выводом на устройство занимается операционная система.

    Недостатки буферизированного ввода-вывода следующие:

    • при таком вводе-выводе невозможно задать шрифтовое и абзацное оформление текста - используется только "поток" символов;
    • такой ввод-вывод ограничен консолью и консольными операциями перенаправления вывода. С его помощью нельзя реализовать WIMP, SILK и другие интерфейсы;
    • редактировать такой поток можно только с помощью "внешних программ-редакторов".

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

  4. Ввод-вывод с использованием API. Термин "API" расшифровывается как "Application Programming Interface" - "интерфейс программирования приложений". С помощью этого интерфейса можно создавать программы "на высоком уровне абстракции" от реальной конфигурации ЭВМ и периферийных устройств. Программа описывает свои действия на языке "в общем виде", все детали формирования изображения и ввода-вывода от него "скрыты". Программист может задавать шрифтовое и абзацное оформление, выводить графику вместе с текстом - всё это будет реализовано одинаково на любом устройстве, которое поддерживает данное API. Недостатки такого вывода следующие:
    • больший, по сравнению с буферизированным вводом-выводом, размер кода и количество подготовительных операций перед выводом;
    • привязка ввода-вывода к одному API, а значит - к определённой платформе ЭВМ, библиотекам и операционным системам;
    • невозможность "оперативного", без помощи программиста, перенаправления вывода.

Этими способами реализации ввода-вывода в основном ограничиваются операции ввода-вывода в разных языках программирования и операционных системах.

1.2. Классификация по обработке перед операцией ввода-вывода

По способу обработки информации при её вводе-выводе различают "форматированный" и "неформатированный" ("бинарный") ввод-вывод.

При форматированном вводе проводятся следующие операции:

  1. Задаётся ограничение на размер строки символов, читаемых с устройства;
  2. Числовые данные при вводе преобразуются в "двоичные" в соответствии с их форматом;
  3. При чтении чисел проверяется их формат, а именно:
    • длину строки цифр;
    • наличие и местоположение десятичной точки;
    • наличие и значение символа "порядка" при чтении чисел в "научном формате";
  4. Целые числа, в зависимости от формата чтения, могут быть десятичными, восьмеричными, шестнадцатеричными, датой, временем и т.п. Всё это указывается в опциях формата, задаваемых в операциях ввода.

При форматированном выводе производятся операции, противоположные тем, что применялись при вводе, а именно:

  1. Данные из двоичной формы преобразуются в текстовую форму, в соответствии со строкой формата;
  2. Эти текстовые данные "обрезаются" до определённой длины, а также осуществляется "выравнивание" текстовой информации в выводимой строке.

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

Существует также "неформатированный двоичный" ввод-вывод, когда данные передаются на устройство или считываются с него "как есть", безо всяких преобразований. Такие файлы являются, как правило, двоичными ("бинарными").

Кроме того, следует отметить, что записи данных, которые передаются устройству ввода-вывода "за один приём", могут иметь фиксированную или переменную длину (всё равно, являются они форматированными или нет). Тогда к файлу, запись которого имеет фиксированную длину, можно организовать "прямой доступ", т.е. любую его запись можно "прочитать", зная начало файла и номер "смещение" записи в файле. Это очень удобно при организации баз данных.

1.3. Замечания по использованию ввода-вывода при помощи API

При использовании ввода-вывода при помощи API возможны следующие нештатные ситуации:

  1. ошибка при обращении к файлу, открытым в одной части программы, и закрытым в другой её части;
  2. разные программы хотят получить одни и те же ресурсы в "монопольное использование" (так называемые "dead lock", "смертельные объятия");
  3. ошибка при выводе на устройство, контекст которого не был создан или уже закрыт в другой части программы.

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

Вот почему обязательно следующее правило:

"Операция обращения к устройству, открытия, чтения, записи и закрытия файлов, создания и уничтожения контекста устройства и вывод на него должны осуществляться в пределах обработки одного сообщения из очереди сообщений" (например, сообщений Windows).

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

Также для предупреждения "смертельных объятий" при обращении к базам данных правильно используйте вызовы функций СУБД. Если Вам отказано в доступе к файлу базы данных, не пытайтесь "обойти" этот запрет!

1.4. Резюме

Итак, в данном разделе Вы познакомились с основными классификациями ввода-вывода ЭВМ. Вы узнали, что эта классификация может идти по "способу абстрагирования" программирования ввода-вывода от конкретной реализации физических устройств, от того, преобразует ли программа данные, полученные от устройства, и какова "глубина этой обработки". При этом мы оперируем понятием "периферийное устройство ЭВМ" а не, "клавиатура Genius", "принтер Hewlett-Packard LaserJet 5100" и т.п. На данном уровне изложения это не важно.

Самым важным пунктом "Введение" является пункт 1.3. Могу спорить, что Вы вернётесь к этому пункту ещё не раз, пытаясь выправить такие ошибки, как "обращение к "закрытому" для чтения-записи периферийному устройству".

Теперь можете переходить к другим лекциям данной части курса. Все они носят справочный характер, необходимо только "уловить принцип" работы каждого из способов ввода-вывода.

1.5. Приложение I. Описание языков символьного программирования.

1.5.1. Язык Java

  1. Язык Java является императивным, объектно-ориентированным языком с байт-кодом, команды которого выполняются в командной строке либо в окне браузера Интернета [26];
  2. Текст программы на языке Java имеет имя: "имя_пакета".java - с расширением *.java. Скомпилированный байт-код имеет расширение: *.class ;
  3. Комментарии на языке Java такие же, как и в C++: пара скобок "/* … */" и "//";
  4. Переменные на языке Java требуют объявления и описания в начале функции, их использующей;
  5. Для строковых переменных существует отдельный класс: "String". Строки-литералы заключаются в двойные кавычки;
  6. В Яве любой файл-класс должен иметь заголовок:
    public class "имя класса"
    {
      … Функции класса …
    }
    Листинг 1.1.
  7. Выполняемая функция (аналог функции 'main' на языке Си) имеет следующий шаблон:
    public static (int|void) main( String[] args )
    {
      … тело функции …
    }
    Листинг 1.2.
    В скобках записывается альтернатива: "int|void". Значение int выбирается, если функция возвращает оболочке операционной системы целое значение. В противном случае лучше использовать значение void ;
  8. Блоки операторов, как и в языке Си, в Яве выделяются фигурными скобками;
  9. Класс может содержать значения класса и методы класса. Вызываются они следующим образом: "переменная класса"."имя поля" или "переменная класса"."метод"("аргументы");
  10. Переменные класса создаются, объявляются и определяются внутри других классов. При написании определённого метода в качестве имени вызывающего объекта можно использовать зарезервированное слово this ;
  11. Символ "=" в Яве используется как оператор присваивания;

В качестве иллюстрации приведём программу.

Пример 1.1.

// Файл ex01001.java
public class ex01001
{
  public static void main( String[] args )
  {
    char cAnswer;
    String junk;
    System.out.println( "Hello, World!" );
    System.out.print( "Не желаете ли поговорить? ");
    System.out.println( "Введите \'y\' или \'Y\' для Да или другую клавишу для Нет.");
    cAnswer = SavitchIn.readLineNonwhiteChar();
    if( cAnswer == 'y' || cAnswer == 'Y' )
      System.out.println( "Прекрасная погода, не так ли?" );
    System.out.println( "До свидания!" );
    System.out.println( "Press key Enter to exit..." );
    junk = SavitchIn.readLine();
  }
}

Примечание: для ввода значений в программу используется класс "SavitchIn", текст которого находится в приложении с исходными текстами программы для данного курса.

Лекция 1: 12345678 || Лекция 2 >