Методические указания к выполнению лабораторных работ по дисциплине «Программная инженерия»/ Составитель: Михайлюк Е.А.- Старый Оскол, 2013.- 96 с.
Содержатся основные сведения, необходимые для выполнения лабораторных работ по дисциплине «Программная инженерия». Методические указания разработаны с использованием учебной и специальной научно-технической литературы по программированию на языках С/С. Практическое применение иллюстрируется различными примерами. Обсуждается методика выполнения лабораторных работ, приведены перечни заданий. Предназначены для студентов специальности 080801 «Прикладная информатика (в сфере сервиса)».
Рецензент: канд. ф.-м.. наук, программист С++ ООО Боронд Фонтан, С.В.Сизов
Среда программирования Visual C++ 6.0. 5
1.1. Общий вид окна. 5
1.2. Создание консольного приложения и работа с ним.. 6
1.3. Компиляция и запуск проекта. 7
1.4. Отладка программы.. 8
1.5. Создание рабочего пространства для нескольких проектов. 8
Программирование C# — параметры командной строки и консольное приложение
Лабораторная работа №1. 9
Выполнение программы простой структуры. Вычисление выражений с использованием стандартных функций. 9
1. Цель задания: 9
2. Теоретические сведения. 9
2.1.Структура программы на С++. 9
2.2. Элементы языка C/C++. 11
2.3. Константы в C/C++. 11
2.3. Типы данных в C++. 12
2.4. Переменные. 13
2.6. Выражения. 15
2.7. Ввод и вывод данных. 15
3. Постановка задачи. 16
5. Методические указания. 22
6. Содержание отчета. 23
Лабораторная работа №2. 24
Использование основных операторов языка С++. 24
1. Цель задания: 24
2. Теоретические сведения. 24
2.1. Составные операторы.. 24
2.2. Операторы выбора. 24
2.3. Операторы циклов. 26
2.4. Операторы перехода. 27
3. Постановка задачи. 28
5. Методические указания. 31
6. Содержание отчета. 31
Лабораторная работа №3 Работа с одномерными массивами. 32
1. Цель работы: 32
2. Краткие теоретические сведения. 32
2.1. Определение массива в C/C++. 32
2.2. Понятие указателя. 32
2.3. Одномерные массивы и указатели. 34
2.4. Перебор элементов массива. 35
2.5. Классы задач по обработке массивов. 35
2.4. Сортировка массивов. 36
2.5. Поиск в отсортированном массиве. 37
3. Постановка задачи. 38
5. Методические указания. 41
6. Содержание отчета: 41
Лабораторная работа №4. 42
Функции и массивы в С++. 42
1. Цель работы: 42
2. Теоретические сведения. 42
2.1. Параметры функции. 43
2.2. Локальные и глобальные переменные. 44
2.3. Передача одномерных массивов как параметров функции. 44
2.4. Передача строк в качестве параметров функций. 44
2.5. Передача многомерных массивов в функцию.. 45
3. Постановка задачи. 47
5. Методические указания. 49
6. Содержание отчета. 49
Лабораторная работа №5. 50
Динамические массивы.. 50
Структура программы и проекта на C#
1. Цель работы: 50
2. Теоретические сведения. 50
3. Постановка задачи. 52
5. Методические указания. 53
6. Содержание отчета. 54
Лабораторная работа №6. 54
Массивы структур и массивы строк. 54
1. Цель работы: 54
2. Теоретические сведения. 54
2.1. Структуры.. 54
3. Постановка задачи. 55
5. Методические указания. 58
6. Содержание отчета. 58
Лабораторная работа №7. 59
1. Цель работы: 59
2. Теоретические сведения. 59
2.1. Функции с начальными значениями параметров (по-умолчанию) 59
2.2. Функции с переменным числом параметров. 59
2.3. Перегрузка функций. 61
2.3. Шаблоны функций. 62
2.4. Указатель на функцию.. 63
2.5. Численные методы решения уравнений. 64
3. Постановка задачи. 65
5. Методические указания. 69
6. Содержание отчета. 70
Лабораторная работа №8. 71
Динамические структуры данных. 71
1. Цель работы: 71
2. Краткие теоретические сведения. 71
2.1. Однонаправленные списки. 71
2.1. Двунаправленные списки. 74
2.3. Очередь и стек. 75
2.4. Бинарные деревья. 75
3. Постановка задачи. 77
5. Методические указания. 81
6. Содержание отчета. 82
Лабораторная работа №9. 83
Хранение данных на внешних носителях. 83
1. Цель работы: 83
2. Краткие теоретические сведения. 83
2.1. Потоковый ввод-вывод в стиле С.. 83
2.2. Обработка элементов файла. 86
2.3. Потоковый ввод-вывод в стиле С++. 87
3. Постановка задачи. 90
5. Содержание отчета. 93
Список литературы. 95
Введение
Для того, чтобы научиться программировать, в первую очередь, надо научиться строить и записывать алгоритмы решаемых задач. Алгоритм – это точное предписание, определяющее вычислительный процесс, идущий от изменяемых начальных данных к конечному результату, т. е. это рецепт достижения какой-либо цели. Совокупность средств и правил для представления алгоритма в виде пригодном для выполнения вычислительной машиной называется языком программирования, алгоритм, записанный на этом языке – программой. Для записи алгоритмов существуют разные формы:
1) словесное описание (псевдокоды),
2) графическое описание (блок-схемы),
3) алгоритмические языки.
Для того чтобы составить программу желательно выполнить по порядку следующие этапы:
1) Определить исходные данные задачи и результаты, которые должны быть получены, а также формулы, связывающие исходные данные и результаты.
2) Составить алгоритм в виде блок-схемы, с помощью которого можно от исходных данных перейти к результатам.
3) Записать алгоритм на требуемом языке программирования (т. е. каждому блоку блок-схемы надо поставить в соответствие оператор языка программирования).
4) Выполнить программу, используя какую-то систему программирования.
5) Выполнить отладку и тестирование программы. При выполнении программы могут возникать ошибки трех типов:
Самыми опасными являются именно семантические ошибки, т. к. их достаточно сложно обнаружить. Программа будет работать, но неправильно, причем, ошибки в ее работе могут возникать не все время, а только при каких-то определенных наборах исходных данных. Для обнаружения таких ошибок выполняется тестирование программы.
Набор исходных данных, для которых известен результат, называется тестом. Если результаты работы теста не совпадут с известным значением, значит, в программе имеется ошибка. Тест, выявивший ошибку, считается успешным. Отладка программы заканчивается, когда достаточное количество тестов будет выполнено неуспешно. Самым распространенным критерием для определения количества неуспешных тестов является тестирование ветвей: набор тестов в совокупности должен обеспечить прохождение каждой ветви не менее одного раза.
Начинающие программисты должны обязательно выполнять все указанные этапы. В дальнейшем этапы 2-3 можно объединить в один и сразу записывать программу на требуемом языке программирования.
В качестве изучаемого языка программирования выбран С++, т. к. этот язык позволяет выработать алгоритмическое мышление, стоить короткую программу, демонстрировать основные приемы алгоритмизации.
Среда программирования Visual C++ 6.0
Общий вид окна
Проект (project) – это набор файлов, которые совместно используются для создания одной программы.
Рабочее пространство (workspace) может включать в себя несколько проектов.
После запуска VC++ 6.0 на экране появится окно (рис. 1).
Рис. 1. Окно VC++ 6.0.
· Главное меню (1) – список основных команд VC++;
· Панель инструментов (2) — панель с кнопками команд Visual C++;
· Панель рабочего пространства Workspace (3) — содержит две вкладки:
— ClassView – отображает список классов в проекте,
— FileView – отображает список файлов, входящих в проект.
· Окно для редактирования кодов (4) – окно с текстом программы;
· Выходную панель результатов компиляции (5) — окно для вывода сообщений в процессе компиляции или отладки, показывает текущую стадию компиляции, список ошибок и предупреждений и их количество.
Создание консольного приложения и работа с ним
Консольное приложение – это приложение, которое с точки зрения программиста является программой DOS, но может использовать всю доступную оперативную память (если каждый элемент данных программы не будет превышать 1 Мб). Этот тип приложения запускается в особом окне, которое называется “Окно MS-DOS”. На примере консольных приложений прослеживаются этапы развития VC++ при переходе от одной версии к другой.
Каждое приложение, разрабатываемое как отдельный проект в среде VC++6.0, нуждается в том, чтобы ему соответствовало свое собственное рабочее пространство. Рабочее пространство включает в себя те папки, в которых будут храниться файлы, содержащие информацию о конфигурации проекта. Для того чтобы создать новое пространство для проекта, надо выполнить следующие действия:
1. В линейке меню нажать на меню File.
2. Выбрать пункт New или нажать Ctrl+N.
3. Появится окно New.В нем содержится четыре вкладки: Files, Projects, Workspaces, Other Documents. Выбрать вкладку Projects.
4. Из списка возможных проектов выбрать Win32 Console Application для создания приложения DOS.
5. В поле Project name ввести имя проекта.
6. В поле Location ввести путь для размещения каталога проекта, или, нажав на кнопку справа […], выбрать нужную директорию.
7. Должен быть установлен флажок Create New Workspace. Тогда будет создано новое рабочее окно. Нажать кнопку OK
8. Установить один из флажков:
— An empty project – создается пустой проект, не содержащий заготовок для файлов;
— A simple application – создается простейшая заготовка, состоящая из заголовочного файла StdAfx.h, файла StdAfx.cpp и файла реализации;
— A “Hello World” application и An application that supports MFC являются демонстрационными и разными способами демонстрируют вывод на экран строки символов.
Нажать кнопку Finish.Появитсяинформация о созданном проекте содержащая: тип проекта, некоторые особенности и директорию.
После создания проекта в него необходимо записать код программы. При этом можно создать новый файл или добавить в проект существующий файл.
Для создания нового файла надо выполнить следующие действия:
- Выбрать меню File > New или Project > Add to Project > New.
- Открыть вкладку Files.
- Выбрать C++ Source File.
- Чтобы создаваемый файл был автоматически присоединен к проекту, необходимо установить флаг Add to project.
- В поле Filename ввести имя файла.
- В поле Location указать путь для создания файла.
- Нажать OK.
Для добавления существующего файла надо:
1. Выбрать в меню File > Add to Project > Files
2. Указать полное имя файла, который нужно присоединить
Для открытия существующего проекта надо:
1. Выбрать меню File > Open Workspace
2. Указать файл с расширением .dsw
Для сохранения текущего проекта надо выбрать в главном меню File > Save Workspace.
Для закрытия текущего проекта надо выбрать в главном меню File > Close Workspace.
После создания или открытия проекта в окне Workspace появится или список классов, или список файлов входящих в проект. В зависимости от типа проекта, он будет или пустой, или содержать изначально некоторые файлы, присущие данному типу. Проект приложения для DOS изначально пустой. В него можно добавить новые файлы или присоединить уже существующие.
Компиляция и запуск проекта
Для компиляции проекта надо выбрать в главном меню Build > Build или нажать клавишу F7.
Visual C++ 6.0 откомпилирует исходные файлы и создаст соответствующие файлы с расширением .obj. Затем эти файлы соединяются в исполняемый файл. Весь процесс компиляции и создания исполняемого файла отображается в окне Output, вкладка Build. После компиляции файла его можно запустить.
Для запуска исполняемого файла надо выбрать в главном меню Build > Execute .exe или нажмите клавиши Ctrl+F5 . Если файл был создан, то он запустится. Для повторного запуска файла не нужно его снова компилировать. Но если в программу были внесены изменения, то перед запуском необходимо выполнить компиляцию. Выполняется именно файл с расширением .exe, а не текущий проект, т.е. в процессе запуска компиляции не происходит.
Отладка программы
Для отладки программы используется команда главного меню Build>Start Debug> Step Into – отладка с заходом в функции, которая начинается с первой строки функции main или Build>Start Debug> Run to Cursor – выполнение программы до курсора, т. е. отладка начинается с той строки, в которой установлен курсор. После выполнения этой команды выполнение программы происходит в режиме отладчика. Переход к следующей строке программы можно выполнять с помощью команды Step Into (F11) (с заходом во все вызываемые функции) или с помощью команды Step over (F10) (без захода в вызываемые функции). Выход из функции нижнего уровня выполняется командой Step Out (Shift+F11). Текущие значения переменных можно просматривать:
1) в специальных окнах Watch(отображает значения всех используемых переменных)иValue (отображает значения заданных пользователем переменных);
2) при наведении курсора мышки на переменную отображается текущее значение этой переменной.
Источник: allrefrs.ru
4.4. Структура программы консольного приложения.
В языке программирования Паскаль программа состоит из заголовка, раздела описаний и исполняемой части. Служебные слова Pascal, обозначающие начало определенного блока программы, выделены жирным белым шрифтом.
Program – блок описания заголовка программы.
Uses –вспомогательные готовые программы, собранные в библиотеки (модули). Модули объявляются в этом блоке.
Label – блок описания меток, содержит их имена перечисленные через запятую. Метки используются для организации переходов в программе. Если метки не нужны, блок отсутствует.
Const – блок описания простых и типизированных констант. Может отсутствовать если константы в программе не предусмотрены.
Type — блок описания типов данных используемых в программе. Может отсутствовать, если новые типы не вводятся.
Var — блок описания переменных с указанием их типа. Может встречаться в программе несколько раз для организации глобальных и локальных переменных
Определение процедур и функций – специально оформленные вспомогательные алгоритмы в виде подпрограмм.
Begin — end. – служебные слова, обрамляющие тело основной программы, где находятся исполняемые операторы. Т.о. Begin начинает исполняемую часть программы, а end. (точка в конце обязательна) – ее завершает.
4.5. Где описываются константы, переменные, метки и типы данных?
Const – блок описания простых и типизированных констант.
Var — блок описания переменных с указанием их типа.
Label – блок описания меток, содержит их имена перечисленные через запятую.
4.6. Стандартные функции. Арифметические функции
Арифметические функции можно использовать только с величинами целого и вещественного типа.
абсолютное значение аргумента
совпадает с типом аргумента
совпадает с типом аргумента
квадратный корень аргумента
целая часть числа
дробная часть числа
Функции преобразования типов
Эти функции предназначены для преобразования типов величин, например, символа в целое число, вещественного числа в целое и т.д.
— возвращает порядковый номер аргумента и, таким образом, преобразует величину порядкового типа в величину целого типа.
— округляет вещественное число до ближайшего целого.
— выдает целую часть вещественного числа, отбрасывая дробную.
Функции для величин порядкового типа
— проверяет аргумент на нечетность. Аргумент функции величина типа longint, результат true, если аргумент нечетный, false – если четный.
— определяет предыдущее значение величины x.
— определяет последующее значение величины x.
— возвращает порядковый номер величины x.
4.7. Инструкция присваивания.
Присваивание записывается как M := N, означающее, что значение N переходит к M.
4.8. Пустая и составная инструкция.
Пустой оператор не включает никаких символов, не выполняет никаких действий и используется в двух случаях:
1. Для использования символа ; после последнего оператора в блоке.
2. Для пометки места, следующего за последним оператором в блоке.
Составной оператор — конструкция языка программирования, состоящая из нескольких команд (операторов) языка программирования, но участвующая в программе в качестве единого оператора.
4.9. Процедуры ввода read и readln.
Процедуры Read и ReadLn выполняют чтение информации из устройства ввода.
4.10. Процедуры вывода write и writeln.
Процедуры Write и WriteLn выполняют вывод информации в устройство стандартного вывода. В консольных приложениях этим устройством может быть консоль (то есть экран), в графических приложениях — файл на диске.
Эти процедуры выполняют одно и то же действие. Отличие между ними только одно: процедура WriteLn после завершения вывода выполняет перевод строки.
4.11. Последовательность действий при выполнении оператора присваивания.
При выполнении оператора присваивания происходит замена текущего значения переменной, стоящей слева от знака присваивания, новым значением, полученным в результате вычисления выражения. Например, после выполнения оператора k : = k+1;
текущее значение переменной k увеличится на 1.
4.12. Приоритетность выполнения операций в выражениях.
Операции одного приоритетного уровня выполняются слева направо. Порядок операций можно изменить, воспользовавшись круглыми скобками. Значения функций вычисляются раньше, чем выполняются другие операции. Приоритетные уровни операций следующие (по убыванию приоритета):
- Одноместные (унарные) операции: +, -, not.
- Мультипликационные операции: *, /, div, mod, and.
- Аддитивные операции: +, -, or, xor.
- Операции отношения: , >=, =, <>.
Источник: studfile.net
Консольное приложение
Это руководство раскроет для вас некоторые возможности .NET и языка C#. Вы узнаете:
- общие сведения о .NET CLI;
- структура консольного приложения C#;
- консольный ввод-вывод;
- основные сведения об интерфейсах API файлового ввода-вывода в .NET;
- основные сведениях об асинхронном программировании задач в .NET.
Вам предстоит создать приложение, которое считывает текстовый файл и выводит его содержимое в консоль. Вывод в консоль осуществляется с такой скоростью, которая позволяет читать текст вслух. Вы можете ускорить или замедлить темп, нажав клавиши «» (больше). Это приложение можно запустить в ОС Windows, Linux, macOS или в контейнере Docker.
В этом руководстве описано множество функций. Попробуем собрать их по одному.
Предварительные требования
- Пакет SDK для .NET 6.
- Редактор кода.
Создание приложения
Первым шагом является создание нового приложения. Откройте командную строку и создайте новый каталог для приложения. Перейдите в этот каталог. В командной строке введите команду dotnet new console . Эта команда создает начальный набор файлов для базового приложения Hello World.
Прежде чем вносить изменения, давайте запустим простое приложение Hello World. Когда вы создадите приложение, наберите в командной строке команду dotnet run . Эта команда запускает процесс восстановления пакета NuGet, создает исполняемый файл приложения и запускает этот файл.
Весь код простого приложения Hello World размещается в файле Program.cs. Откройте этот файл в любом текстовом редакторе. Замените код в Program.cs на следующий код:
namespace TeleprompterConsole; internal class Program < static void Main(string[] args) < Console.WriteLine(«Hello World!»); >>
В верхней части файла вы видите инструкцию namespace . Как и другие объектно ориентированные языки, с которыми вы могли работать ранее, C# использует пространства имен для организации типов. В нашей программе Hello World все точно так же. Как вы видите, программа находится в пространстве имен TeleprompterConsole .
Чтение и вывод файла
Первая функция, которую мы добавим, будет считывать данные из текстового файла и выводить полученный текст в консоль. Сначала нам нужно добавить текстовый файл. Скопируйте в каталог проекта файл sampleQuotes.txt из репозитория GitHub для этого примера. Он будет источником текста для вашего приложения. Чтобы скачать пример приложения для этого раздела, воспользуйтесь инструкциями в разделе Примеры и руководства.
Теперь добавьте в класс Program (он расположен сразу за методом Main ) следующий метод:
static IEnumerable ReadFrom(string file) < string? line; using (var reader = File.OpenText(file)) < while ((line = reader.ReadLine()) != null) < yield return line; >> >
Этот метод является особым типом метода C#, который называется методом итератора. Методы итератора возвращают последовательности, которые оцениваются отложенно.
Это означает, что каждый элемент в последовательности создается только в тот момент, когда к нему выполняется обращение в коде обработки последовательности. Методы итератора — это методы, содержащие один или несколько yield return операторов. Возвращаемый методом ReadFrom объект содержит код для создания каждого элемента последовательности.
В нашем примере он читает следующую строку текста из исходного файла и возвращает эту строку. Каждый раз, когда вызывающий код запрашивает следующий элемент из последовательности, код считывает из файла и возвращает следующую строку текста. Когда файл закончится, последовательность сообщает, что в ней больше нет элементов.
Здесь используются два элемента синтаксиса C#, которые могут быть для вас новыми. Инструкция using в этом методе управляет освобождением ресурсов. Переменная, которая инициализируется в инструкции using (в нашем примере это reader ) должна реализовывать интерфейс IDisposable. Этот интерфейс определяет единственный метод ( Dispose ), который вызывается для освобождения ресурса. Компилятор создает такой вызов, когда выполнение кода достигает закрывающей скобки инструкции using . Созданный компилятором код гарантирует освобождение ресурса даже в том случае, если в блоке кода, определенном инструкцией using, будет создано исключение.
Переменная reader определена с ключевым словом var . Ключевое слово var определяет неявно типизированную локальную переменную. Это означает, что тип переменной определяется во время компиляции по типу объекта, присвоенного этой переменной. Здесь это возвращаемое значение метода OpenText(String), то есть объект StreamReader.
Теперь давайте создадим в методе Main код для чтения файла:
var lines = ReadFrom(«sampleQuotes.txt»); foreach (var line in lines)
Запустите программу командой dotnet run и убедитесь в том, что все текстовые строки выводятся в консоль.
Добавление задержек и форматирование выходных данных
Сейчас данные отображаются слишком быстро для чтения. Поэтому нам нужно добавить задержку в процесс вывода. Для этого вы создадите несложный код, выполняющий асинхронную обработку. Но первые наши действия будут нарушать стандартные рекомендации. Эти нарушения мы укажем в комментариях при создании кода, а затем заменим этот код в последующих шагах.
В этом разделе описаны два действия. Во-первых, обновите метод итератора, чтобы он возвращал не всю строку целиком, а каждое слово отдельно. Для этого внесите такие изменения. Замените инструкцию yield return line; следующим кодом:
var words = line.Split(‘ ‘); foreach (var word in words) < yield return word + » «; >yield return Environment.NewLine;
Теперь следует изменить код обработки строк файла, добавив задержку после вывода каждого слова. Замените инструкцию Console.WriteLine(line) в методе Main на такой блок кода:
Console.Write(line); if (!string.IsNullOrWhiteSpace(line)) < var pause = Task.Delay(200); // Synchronously waiting on a task is an // anti-pattern. This will get fixed in later // steps. pause.Wait(); >
Запустите пример и проверьте выходные данные. Теперь слова появляются по одному и с задержками по 200 мс.
Но пока с выводом сохраняются некоторые проблемы, поскольку в исходном текстовом файле есть несколько строк длиной более 80 символов, и они выводятся без перевода строки. Это не очень удобно читать с прокруткой. Но эту проблему легко исправить. Вам нужно лишь отслеживать длину каждой строки и создавать новую строку каждый раз, когда эта длина достигает определенного порога. После объявления words в методе ReadFrom объявите локальную переменную для хранения длины строки:
var lineLength = 0;
Теперь добавьте следующий код после инструкции yield return word + » «; (перед закрывающей фигурной скобкой):
lineLength += word.Length + 1; if (lineLength > 70)
Запустите пример, и теперь вы сможете читать текст вслух в заданном темпе.
Асинхронные задачи
И на последнем этапе мы добавим код, который позволяет выполнять две асинхронные задачи, одна из которых — вывод текста, а вторая — ожидание ввода от пользователя для ускорения, замедления или прекращения вывода текста. Этот этап разделяется на несколько шагов, по завершении которых вы получите все необходимые обновления. Первым шагом является создание асинхронной задачи (Task), которая возвращает метод с тем кодом, который вы создали ранее для чтения и отображения файла.
Добавьте следующий метод в класс Program . Этот текст основан на тексте метода Main :
private static async Task ShowTeleprompter() < var words = ReadFrom(«sampleQuotes.txt»); foreach (var word in words) < Console.Write(word); if (!string.IsNullOrWhiteSpace(word)) < await Task.Delay(200); >> >
Вы можете заметить два изменения. Во-первых, в тексте нет вызова Wait(), который в синхронном режиме ожидает завершения задачи.
Вместо него в этой версии используется ключевое слово await . Чтобы это работало, в сигнатуру метода нужно добавить модификатор async . Этот метод возвращает Task . Обратите внимание, что здесь нет инструкции для возвращения объекта Task . Вместо этого объект Task создается в коде, который компилятор предоставляет в точке использования оператора await . Представьте, что метод завершает выполнение при достижении await . Он возвращает Task в знак того, что работа еще не завершена. Метод возобновит свою работу, когда завершится ожидаемая задача. Когда работа метода завершится, это будет отражено в возвращаемом объекте Task . Вызывающий код может отслеживать состояние полученного Task , чтобы определить момент завершения метода.
await Добавьте ключевое слово перед вызовом : ShowTeleprompter
await ShowTeleprompter();
Для этого необходимо изменить сигнатуру Main метода следующим образом:
static async Task Main(string[] args)
Дополнительные сведения о методе async Main см. в разделе «Основы».
Затем необходимо написать второй асинхронный метод для чтения из консоли и watch для ключей «» (больше) и «X» или «x». Для выполнения этой задачи добавьте приведенный ниже метод.
private static async Task GetInput() < var delay = 200; Action work = () =>< do < var key = Console.ReadKey(true); if (key.KeyChar == ‘>’) < delay -= 10; >else if (key.KeyChar == ‘ <‘) < delay += 10; >else if (key.KeyChar == ‘X’ || key.KeyChar == ‘x’) < break; >> while (true); >; await Task.Run(work); >
При этом создается лямбда-выражение для представления делегата Action , который считывает ключ из консоли и изменяет локальную переменную, представляющую задержку, когда пользователь нажимает клавиши «» (больше). Метод делегата завершается, когда пользователь нажимает клавиши «X» или «x», что позволяет пользователю в любое время остановить отображение текста. Этот метод использует метод ReadKey(), чтобы блокировать выполнение и ожидать нажатия клавиши.
Чтобы завершить создание этой функции, нам нужна новая инструкция async Task , которая вернет метод, запускающий обе задачи ( GetInput и ShowTeleprompter ) и управляющий обменом данными между этими задачами.
Пришло время создать класс, который может обрабатывать совместное использование данных двумя задачами. Этот класс содержит два открытых свойства: delay (задержка) и флаг Done , который означает, что файл прочитан полностью:
namespace TeleprompterConsole; internal class TelePrompterConfig < public int DelayInMilliseconds < get; private set; >= 200; public void UpdateDelay(int increment) // negative to speed up < var newDelay = Min(DelayInMilliseconds + increment, 1000); newDelay = Max(newDelay, 20); DelayInMilliseconds = newDelay; >public bool Done < get; private set; >public void SetDone() < Done = true; >>
Поместите этот класс в отдельный новый файл и включите его в пространство имен TeleprompterConsole , как показано выше. Также следует добавить оператор using static в верхнюю часть файлами, чтобы можно было ссылаться на методы Min и Max без указания имени внешнего класса или пространства имен. Инструкция using static импортирует все методы из одного класса. Это отличается от оператора using без static , который импортирует все классы из пространства имен.
using static System.Math;
Теперь вам нужно обновить методы ShowTeleprompter и GetInput для использования нового объекта config . И еще одна инструкция Task , которая возвращает метод async , запускающий обе задачи и завершающий работу после окончания первой задачи:
private static async Task RunTeleprompter()
Новым методом здесь является WhenAny(Task[]). Этот метод создает задачу ( Task ), которая завершается сразу, как только завершится любая из задач в списке аргументов.
Теперь вам нужно обновить методы ShowTeleprompter и GetInput , чтобы они использовали объект config для задержки:
private static async Task ShowTeleprompter(TelePrompterConfig config) < var words = ReadFrom(«sampleQuotes.txt»); foreach (var word in words) < Console.Write(word); if (!string.IsNullOrWhiteSpace(word)) < await Task.Delay(config.DelayInMilliseconds); >> config.SetDone(); > private static async Task GetInput(TelePrompterConfig config) < Action work = () =>< do < var key = Console.ReadKey(true); if (key.KeyChar == ‘>’) config.UpdateDelay(-10); else if (key.KeyChar == ‘ <‘) config.UpdateDelay(10); else if (key.KeyChar == ‘X’ || key.KeyChar == ‘x’) config.SetDone(); >while (!config.Done); >; await Task.Run(work); >
Новая версия метода ShowTeleprompter вызывает новый метод из класса TeleprompterConfig . Сейчас нужно изменить метод Main , чтобы вместо ShowTeleprompter он вызывал RunTeleprompter :
await RunTeleprompter();
Заключение
В этом учебнике мы продемонстрировали вам ряд функций языка C# и библиотек .NET Core, связанных с работой в консольных приложениях. На основе полученных знаний вы сможете развивать свои представления о языке и представленных здесь классах.
Вы увидели базовые примеры использования файлового и консольного ввода-вывода, асинхронного программирования на основе задач с блокировкой и без блокировки. Вы узнали о языке C# и структуре программ на C#, а также о .NET CLI.
Дополнительные сведения о файловом вводе-выводе см. в статье Файловый и потоковый ввод-вывод. Дополнительные сведения о модели асинхронного программирования, используемой в учебнике, см. в статьях Асинхронное программирование на основе задач и Асинхронное программирование.
Источник: learn.microsoft.com