Лабораторная №1 Создание кроссплатформенного приложения с использованием интерфейса ввода вывода. Цель: Целью работы является получение опыта создания приложения, использующего кроссплатформенные методы взаимодействия со стандартными интерфейсами ввода вывода. План: 1. Изучить структуру программы на языке C; 2. Изучить POSIX методы работы со стандартным интерфейсом ввода/вывода; 3. Написать программу, выполняющую манипуляции со стандартным интерфейсом ввода/вывода в ОС Linux; 4. Получить исполняемый файл программы и продемонстрировать его работу в ОС Linux; 5. Скопировать исходный код программы в ОС Windows; 6. Получить исполняемый файл для ОС Windows не меняя исходного текста программы и продемонстрировать работу программы с ОС Windows; Ход: 1. Исходный код простейшей программы на языке С имеет следующую структуру: - блок подключения заголовочных файлов библиотек (include); - блок пользовательских функций; - блок основной функции точки входа (main). Блок подключения заголовочных файлов библиотек содержит директивы подключения заголовочных файлов к исходному тексту программы. Заголовочные файлы описывают интерфейс библиотечных (сторонних) функций. При компиляции программы, на используемые библиотечные функции будут созданы специальные ссылки, по которым будет производится связь с машинными кодами этих функций при выполнении сборки (линковки) программы. Пример подключения заголовочного файла библиотеки работы со стандартным интерфейсом ввода/вывода: -------- #include -------- Блок пользовательских функций содержит описание сервисных функций простейшей программы и не является обязательным в данной лабораторной работе по причине тривиальности алгоритма. Блок основной функции точки входа в программу выглядит следующим образом: -------- int main(int argc, char** argv){ <код программы> return <значение выхода>; } -------- Функция main является функцией специального вида, которая первой получает управление после выполнения подготовительной инициализации программы. Функция возвращает результат работы программы. Если результат выполнения программы успешен, то возвращается значение 0, иначе возвращается номер ошибки. Входная переменная argc определяет количество входных параметров программы. Входные параметры указываются при запуске программы. Пример в ОС Linux: -------- vim schedule.txt -------- Программа текстовый редактор Vim открывается с входным параметром "schedule.txt", который в данном случае является именем файла, открываемого для редактирования. Аналогичный пример в ОС Windows -------- notepad.exe schedule.txt -------- Открытие файла schedule.txt в программе "Блокнот". Нулевым входным параметром является имя вызываемой программы (vim и notepad.exe в примерах). Таким образом, в рассмотренных примерах запуска argc == 2. Массив строк argv содержит в себе строковые значения входных параметров. В рассмотренном примере для ОС Linux: argv[0] == "vim" argv[1] == "schedule.txt" В рассмотренном примере для ОС Windows: argv[0] == "notepad.exe" argv[1] == "schedule.txt" 2. POSIX метод работы со стандартным интерфейсом ввода вывода программы заключается в обмене данными через дескрипторы. Дескриптор - это номер канала данных, который можно использовать для чтения и/или записи информации. При запуске программы операционной системой создается, открывается и передается в программу как минимум 3 дескриптора: - дескриптор интерфейса стандартного ввода (значение 0, данные выводятся в терминал); - дескриптор интерфейса стандартного вывода (значение 1, данные вводятся с клавиатуры); - дескриптор интерфейса стандартного вывода ошибок (значение 2, данные выводятся в терминал (для служебных сообщений)). Для записи данных в канал по дескриптору используется функция: ssize_t write(int fd, const void *buf, size_t count); из заголовочного файла unistd.h. write пишет count байт в файл, на который ссылается файловый дескриптор fd из буфера, на который указывает buf. Полное описание функции можно получить в ОС Linux при помощи выполнении в терминале команды: -------- man 2 write -------- Выход из справочного листа осуществляется клавишей q. Для чтения данных с канала по дескриптору используется функция: ssize_t read(int fd, void *buf, size_t count); из заголовочного файла unistd.h. read() пытается читать из файлового дескриптора fd байты в количестве count в буфер, начинающийся по адресу buf. Полное описание функции: man 2 read. Форматированный ввод и вывод информации через дескрипторы осуществляется при помощи функций scanf и printf соответственно. Функции располагаются в заголовочном файле stdio.h. Описание функций в ОС Linux: -------- man 3 scanf man 3 printf -------- Пример чтения/записи стандартного вывода при помощи функций scanf/printf: #include int main(int argc, char** argv){ printf("Program: %s\n", argv[0]); printf("Input number: "); int number; scanf("%d", &number); printf("Square of number: %d\n", number*number); return 0; } 3. Создание программы Алгоритм программы зависит от ФИО исполнителя и номера его группы. Условные обозначения: |Ф| - количество букв в фамилии |И| - количество букв в имени |О| - количество букв в отчестве [Ф] - ИСТИНА, если первая буква фамилии - гласная [И] - ИСТИНА, если первая буква имени - гласная [О] - ИСТИНА, если первая буква отчества - гласная ![Ф] - ИСТИНА, если первая буква фамилии - согласная ![И] - ИСТИНА, если первая буква имени - согласная ![О] - ИСТИНА, если первая буква отчества - согласная |Г| - номер группы; Задание: Ввод 3-х целых чисел (a1 a2 a3), разделенных пробелом через стандартный интерфейс ввода и 6-ти выходных целых чисел (b1 b2 b3 b4 b5 b6), определенных по следующему алгоритму: b1 = |Ф|; b2 = |И|; b3 = |О|; b4 = [Ф] ? a1 / b1 : a1 % b1; b5 = [И] ? a2 / b2 : a2 % b2; b6 = [О] ? a3 / b3 : a3 % b3; где ( ? : ) - тернарный оператор проверки условия, / - целочисленное деление, % - остаток от деления. Значение результата работы программы: (|Г| + b6) % 2; Работу производить в директории /home/user/int_lab1_<инициалы_латиницей>. Создание директории командой: mkdir <путь_к_новой_директории> Смена текущей директории: cd <путь_к_директории> Текст программы создать в доступном редакторе, например nano. Открытие или создание файла (если его не существует) командой: -------- nano <имя_файла> -------- Клавиши в nano: Ctrl+O - сохранить; Ctrl+X - выйти. 4. Создание исполняемого файла в ОС Linux и запуск Компиляция исходного текста и его сборка (линковка) будет выполнятся при помощи GNU C Compiler. Команда для компиляции и сборки программы: -------- gcc -o <имя_выходного_исполняемого_файла> <имя_исходного_текста_программы> -------- Запуск производить следующим образом: ./<имя_выходного_исполняемого_файла> Убедиться в верности работы программы и продемонстрировать исправную работу преподавателю. 5. Скопировать исходный код программы в ОС Windows; Скопировать файл исходного текста на USB носитель. Выполнить загрузку в OC Windows. 6. Получить исполняемый файл для ОС Windows не меняя исходного текста программы и продемонстрировать работу программы с ОС Windows; Компиляция исходного текста и его сборка (линковка) будет выполнятся при помощи набора компиляторов MinGW. Сборка в общем случае выполняется компилятором gcc из состава MinGW, который расположен по пути: C:\MinGW\bin Для правильной сборки может потребоваться указание директории хранения заголовочных файлов (include) с помощью ключа -I и директории хранения библиотек для линковки исполняемого файла (lib) с помощью ключа -L. Убедиться в корректности работы программы и продемонстрировать исправную работу преподавателю.