Проект для лекции Lesson3.zip
Тип данных – это некоторое фиксированное множество элементов. В объектно-ориентированном программировании элементы этого множества рассматриваются как объекты. Определить тип данных означает определить свойства и поведение объектов данного типа. По способу определения типов данных их можно разделить на три группы:
В рамках данного курса мы будем пользоваться встроенными и некоторыми библиотечными типами данных.
Как следует из названия, элементами этого типа данных являются числа. Мы будем рассматривать два подтипа, встроенные в язык C#:
int (от integer – целое), определяющий целые числа из диапазона [-231 - +231-1]. Напомню, что число 231 превосходит два миллиарда. Так что чисел типа int вполне достаточно для рассматриваемых нами задач.double. Числа этого типа имеют целую и дробную часть. На предыдущих уроках мы говорили о числах этого типа. Каждое такое число содержит примерно 16 значащих цифр, а диапазон значений практически неограничен.Над числами этого типа в языке C# определены арифметические операции, а библиотечный класс Math позволяет вычислять известные функции над числовыми аргументами – sin(x), cos(x) и другие.
Наряду с числами основным типом данным, с которым работает компьютер, является строковый тип, представляющий тексты. Мы будем рассматривать два подтипа этого типа, встроенные в язык C#:
char (от character – символ). Объекты этого типа являются символами, составляющими алфавит, из которых строятся тексты – слова в данном алфавите. В языке C# этот алфавит, определяемый кодом Unicode, включает чуть более 65 000 символов. Этот алфавит включает символы кириллицы, латиницы и других национальных алфавитов. Практически любая книга, издаваемая на земле, может рассматриваться как текст в данном алфавите.На предыдущих уроках мы говорили о том, как можно вводить и выводить тексты. Позже мы подробнее поговорим о том, какие операции определены в языке C# и библиотечных классах, позволяющие работать с текстами.
Компьютер – это логически рассуждающая машина. Поэтому логический тип данных – это базисный тип данных, встроенный во все языки программирования. В язык C# встроен логический тип, задаваемый ключевым словом bool (от Boolean – булевский. Этот тип назван в честь английского математика Джона Буля, внесшего существенный вклад в изучение логики).
Элементы этого типа принимают только два значения – true и false (истина и ложь, интерпретируемые часто как 1 и 0). Над логическими переменными в языке C# определены логические операции, о которых мы позже поговорим подробнее.
Напомню, что полезно при изучении данного курса самостоятельно на сайте intuit.ru пройти курсы "Информация и данные" и "Введение в логику".
Рассмотренные нами встроенные типы являются простыми типами. Это означает, что объекты этих типов просто устроены. Они имеют значение, которое можно рассматривать как неделимое. Число, слово, булевское значение – простые объекты. Такие объекты в программировании называются обычно переменными, а термин "объект" сохраняют для сложно организованных объектов. Так что в дальнейшем рассмотрении мы чаще всего будем использовать термин "переменная" вместо термина "объект", хотя нужно понимать, что в C# все переменные являются настоящими объектами.
Переменная, будучи простым объектом, имеет три характеристики: тип, имя, значение.
Выполнение любой программы сводится к выполнению некоторых операций над переменными. Но прежде чем выполнять какие-либо действия над переменной она должна быть объявлена.
Что представляет собой объявление переменной? В момент объявления переменной дается имя и указывается ее тип. В консольный проект Lesson3, сопровождающий этот урок, включен метод с именем TestTypesAndObjects, в котором объявляются переменные арифметического типа, над ними выполняются некоторые операции, результаты вычислений выводятся на консоль. Вот как объявляются три переменные целого типа:
int x, y, z;
Объявление переменных должно удовлетворять следующему синтаксису – вначале указывается имя типа, а затем список имен переменных этого типа. Объявление должно заканчиваться символом ";" - точка с запятой. Имена переменных в списке разделяются запятыми.
Имена должны удовлетворять следующему правилу – имя должно начинаться с буквы, после которой может идти последовательность букв и цифр. В данном примере все имена состоят из одной буквы.
В результате данного объявления наши переменные обладают двумя характеристиками из трех – у них есть имя и указан их тип, но они не обладают значениями. Пока они не получат значения их нельзя использовать в вычислениях, которые проводятся над значениями переменных.
Есть еще один вид объявления переменных – объявление с инициализацией. Переменные в момент объявления получают и третью характеристику – значение. В методе TestTypesAndObjects объявлены с инициализацией две переменные типа double:
double u = 5.0, v = 7.5;
Значения, которые получили переменные u и v в этом примере, заданы константами соответствующего типа.
Константы в языке C# также являются объектами. В отличие от переменных константы имеют значение и тип, но не имеют имени. Значение и тип определяется самой константой.
Последовательность цифр возможно с предшествующим знаком "плюс" или "минус" рассматривается как константа типа int. Сама последовательность рассматривается как десятичное целое число.
Пример: -1235
Последовательность цифр, в которой символ "точка" разделяет целую и дробную часть числа, рассматривается как константа типа double. Сама последовательность рассматривается как десятичное число с целой и дробной частью. Знак числа также может быть задан.
Пример: -12.35
Последовательность любых символов, заключенная в "двойные кавычки" рассматривается как константа типа string.
Пример: "-12.35"
Любой символ, заключенный в одиночные кавычки, рассматривается как константа типа char.
Пример: '1'
Как было показано на предыдущих уроках, при создании программного проекта в Visual Studio мы выбираем тип проекта, а студия создает заготовку – начальную программу для этого типа проекта. После чего нам необходимо в соответствующие места добавить программный код, позволяющий решить поставленную задачу.
Добавляемый код можно рассматривать как текст, состоящий из предложений, написанных на языке программирования (в нашем случае на языке C#). Как всякий разумный текст, написанный на каком-либо языке, он должен отвечать требованиям синтаксиса. Алгоритмические языки предъявляют жесткие требования к синтаксису предложений, которые мы пишем. Программа с синтаксическими ошибками не допускается на выполнение. Но ошибки свойственны человеку. К счастью компилятор (программа, преобразующая текст, написанный на C#, в текст, состоящий из команд, понятных для выполнения процессору компьютера) способен обнаруживать синтаксические ошибки и уведомлять о них программиста. Так что, благодаря помощи компилятора, синтаксические ошибки легко исправляются, и синтаксически корректная программа будет выполняться. Конечно, выполняемый текст должен иметь смысл – быть семантически корректна, чтобы она правильно решала поставленную задачу. К сожалению, вся ответственность за семантическую корректность программы лежит на программисте.
Если при записи константы типа double для отделения целой части числа от дробной вместо точки использовать запятую, то это синтаксическая ошибка, которая будет обнаружена компилятором. Но если при необходимости вычисления суммы двух переменных a + b написать a – b, то никакой компилятор ошибки не обнаружит, вычисления будут производиться, но результат будет не верен, - не соответствуя требуемому смыслу задачи. Для исправления семантических ошибок требуется процесс "отладки программы".
Предложения, которые мы будем добавлять в заготовку программы состоят из объявлений переменных и операторов программы. Объявления переменных, синтаксис которых мы только что рассмотрели, носят декларативный характер, уведомляющих программу об объектах, участвующих в выполнении операций. Операторы программы – являются выполняемыми и носят императивный характер. Каждый оператор выполняет те или иные действия над объектами программы. Ситуация напоминает описание пьесы, - вначале идет объявление списка действующих лиц, а затем описан сценарий действия этих лиц.
Рассмотрим основные операторы языка C#.
Этот оператор предназначен, как следует из названия, для присваивания переменным значений. Синтаксис этого оператора следующий:
<имя переменной> = <выражение>;
Оператор присваивания состоит из двух частей, разделенных знаком равенства. В левой части указывается имя переменной, а в правой части некоторое выражение. Семантика выполнения оператора присваивания такова – вычисляется значение выражения в правой части и это значение становится новым значением переменной. Важно понимать, что старое значение переменной в результате присваивания безвозвратно пропадает. Конечно, как чаще всего бывает, старое значение переменной может участвовать при вычислении значения выражения правой части.
В методе TestTypesAndObjects после объявления переменных написаны три оператора присваивания:
x = 5 * 2; y = -2; z = (x + y) * (x + 2 * y - 5);
В первых двух операторах переменные x и y получают значения. Выражения в правых частях содержат константы типа int. В третьем операторе присваивается значение переменной z. Выражение в правой части содержит кроме констант переменные x и y, которые к моменту выполнения уже имеют значения.
Как строятся выражения? Выражения в языках программирования строятся примерно также, как и в математике. Выражение строится из переменных и констант, объединенных знаками операций и скобками. В выражении могут также использоваться вызовы различных функций. Такие примеры появятся позже.
Следующая группа из четырех операторов присваивания демонстрирует изменение значений переменных в результате присваивания:
u = u + v; v = u + v; u = u + v; v = u + v;
Вычисленные значения переменных в методе TestTypesAndObjects выводятся на консоль:
Console.WriteLine("x = " + x); Console.WriteLine("y = " + y); Console.WriteLine("z = " + z); Console.WriteLine("u = " + u); Console.WriteLine("v = " + v);
Для вывода используется известный нам метод WriteLine класса Console. Обратите внимание на важную деталь. Аргументом метода является выражение, построенное из константы типа string и переменной арифметического типа (int и double), объединенных знаком операции "+". Как вычисляется такое выражение? В данном случае второй аргумент арифметического типа преобразуется в более общий строковый тип и затем выполняется конкатенация строк (уже знакомая нам операция).
Прежде чем запустить проект на выполнение и посмотреть на результаты выполнения этого метода, попробуйте сами определить, какие же значения будут иметь переменные в результате выполнения этих операторов присваивания.
Группа операторов, заключенная в фигурные скобки, рассматривается как один оператор – составной оператор. Составной оператор – важная синтаксическая конструкция. В ряде случаев, по синтаксису конструкции требуется, чтобы в ней присутствовал ровно один оператор, а по смыслу требуется выполнения группы операторов. В этом случае группа объединяется в единый составной оператор.
Если в группе, объединяемой скобками, присутствуют объявления переменных, то такую группу принято называть блоком.
В жизни, как витязю на распутье, часто приходится делать выбор. Без выбора нельзя обойтись и в программах. Во всех языках программирования есть оператор выбора, называемый оператором if, или if – then – else (если – то – иначе), позволяющий сделать альтернативный выбор, - выбор из двух возможностей.
В языке C# этот оператор имеет следующий синтаксис:
if (<выражение булевского типа>) <оператор А> else <оператор B>
Семантика выполнения этого оператора следующая. Вычисляется значение булевского выражения. Если значение выражения равно true (истина), то выполняется оператор А, в противном случае – оператор В.
Существует краткая форма этого оператора, когда ветвь else опускается. Тогда, когда выражение ложно ничего не делается и оператор if заканчивает работу.
По синтаксису if – ветвь и else - ветвь содержат только один оператор. Понятно, что этот оператор может быть составным, тогда выполняется группа операторов, заключенная в фигурные скобки, но синтаксически воспринимаемая как один оператор.
Несмотря на кажущуюся простоту семантики этого оператора, разобраться в его работе может быть достаточно сложно. Дело в том, что на оператор А и оператор В не накладывается никаких ограничений. Как сказано, это может быть группа операторов, каждый из операторов группы может быть сложным оператором – оператором if или оператором цикла.
Рассмотрим пример использования оператора if в классической задаче нахождения корней квадратного уравнения. В нашем проекте Lesson3 есть метод TestIf, решающий эту задачу. Приведу текст этого метода:
//объявление и ввод исходных данных double a, b, c; Console.WriteLine("Введите коэффициенты квадратного уравнения - a, b, c"); a = double.Parse(Console.ReadLine()); b = double.Parse(Console.ReadLine()); c = double.Parse(Console.ReadLine());
Выполнение метода начинается с объявления исходных данных и их ввода с консоли. Обратите внимание, знакомый нам метод ReadLine читает с консоли строку текста, представляющую число. Прежде чем это значение присвоить переменной типа double, метод Parse класса double преобразует эту строку в число типа double.
//объявление результатов - корней квадратного уравнения double x1, x2;
Объявляются результаты без инициализации. Значения этих переменных появятся в результате вычислений.
//объявление с инициализацией внутренней (вспомогательной) переменной double discriminant = b * b - 4 * a * c;
Помимо исходных данных и результатов программа в своей работе использует внутренние переменные. Таковой в данной задаче является переменная с именем discriminant. Она объявлена с инициализацией, поскольку все данные для расчета ее значения уже имеются.
//Вычисления if (discriminant > 0) { x1 = (-b + Math.Sqrt(discriminant)) / (2 * a); x2 = (-b - Math.Sqrt(discriminant)) / (2 * a); } else if (discriminant == 0) x1 = x2 = -b / (2 * a); else x1 = x2 = double.NaN;
Вычисления практически сводятся к выполнению одного оператора – оператора if. Ветвь if этого оператора содержит составной оператор, содержащий группу из двух операторов присваивания. Ветвь else содержит один оператор, - но это в свою очередь оператор выбора if. Обратите внимание, ветвь else этого оператора работает, когда квадратное уравнение не имеет вещественных корней. В данном случае корни получают специальное значение NaN (Not a Number – Это Не (вещественное) Число).
Console.WriteLine("x1 = " + x1 + " x2 = " + x2);
Последний оператор метода выводит результаты на консоль.
Если бы язык программирования содержал только описанные выше операторы – присваивания, составной оператор и оператор выбора, то компьютеры были бы не более чем простые счетные машины - калькуляторы. Компьютеры становятся по-настоящему эффективными только тогда, когда управлять вычислением можно так, чтобы один оператор в тексте программы мог выполняться многократно. Такие средства есть во всех языках программирования.
В языке C# существует оператор цикла while, позволяющий организовать циклическое выполнение некоторого фрагмента программы. Синтаксис этого оператора достаточно прост:
while(<булевское выражение>) <оператор А>
Достаточно проста и семантика этого оператора. Вычисляется значение булевского выражения, если оно истинно, то выполняется оператор А, называемый телом цикла, после чего снова проверяется истинность булевского выражения. Оператор цикла заканчивает свою работу, когда значение булевского выражения становится ложным. Другими словами, пока истинно булевское выражение оператор тела цикла будет выполняться. В соответствии с описанной семантикой возможны три ситуации:
В нашем проекте Lesson3 есть метод TestWhile, который демонстрирует применение цикла while на примере задачи нахождения обращенного числа – числа, у которого цифры идут в обратном порядке. Например, если x равно 123, то reverse(x) равно 321. Для нахождения обращенного числа мы будем в цикле получать цифру за цифрой исходного числа x, и из полученных цифр будем формировать обращенное число reverse. Вот текст этого метода, решающий поставленную задачу:
int x; Console.WriteLine("Введите целое число"); x = int.Parse(Console.ReadLine()); int digit; int reverse = 0; while(x > 0) { digit = x % 10; //получить последнюю цифру числа x x = x / 10; //отрезать последнюю цифру reverse = 10 * reverse + digit; } Console.WriteLine("Обращение числа x -" + reverse);
Как работает алгоритм? По условиям задачи на входе x – это положительное целое число, поэтому при первой проверки булевского выражение (x > 0) оно будет истинным и начнет выполняться тело цикла.
Первый оператор тела цикла в результате выполнения операции взятия остатка от деления нацело числа x на основание десятичной системы счисления позволяет получить последнюю цифру в числе x.
Следующий оператор тела цикла в результате выполнения операции деления нацело числа x на основание десятичной системы счисления позволяет отрезать последнюю цифру в числе x.
Последний оператор тела цикла формирует обращенное число reverse, делая последнюю цифру первой.
Отрезая цифру за цифрой, мы шаг за шагом приближаемся к цели. Когда все цифры будут отрезаны, булевское выражение станет ложным, но к этому моменту будет сформировано обращенное число – поставленная цель будет достигнута. Сколько шагов будет сделано, сколько раз будет выполняться тело цикла? Число шагов равно числу цифр в исходном числе x.
Следует изучить и хорошо понимать алгоритм, используемый в этой задаче. Операции взятия остатка и деления нацело, позволяющие разбирать число на цифры, будут часто встречаться в задачах, связанных с числами.
Оператор цикла while является универсальным оператором, позволяющим организовать циклическое выполнение любого фрагмента программы. Часто для организации цикла используют оператор цикла for, применимый тогда, когда число повторений тела цикла заранее известно. Этот
Вид цикла называют циклом вида арифметической прогрессии, поскольку счетчик цикла, используемый в операторе for изменятся с некоторым фиксированным шагом, как это происходит в арифметической прогрессии.
Синтаксис оператора for следующий:
for(<инициализация счетчика>; <условие окончания цикла>; <изменение счетчика цикла>) <тело цикла>
Типичная конструкция этого цикла выглядит так:
for (int i = 0; i < n; i++)
Семантика выполнения этого оператора следующая. Заголовок цикла, заключенный в круглые скобки состоит из трех частей. Первая часть заголовка служит для инициализации счетчика цикла. Она выполняется один раз в начале работы оператора. В типичном примере выполнения этого оператора первая часть состоит из объявления с инициализацией переменной i, представляющей счетчик цикла. Вторая часть заголовка содержит булевское условие, задающее условие выполнения цикла. Это условие задает ограничение на значение счетчика цикла. В типичном примере. В типичном примере применения это условие имеет вид: i < n, где n – переменная с известным значением. Если условие истинно, то выполняется тело цикла – оператор А. После чего выполняется третья часть заголовка, изменяющая счетчик на заданную величину. В типичном примере счетчик увеличивается на единицу.
В проекте Lesson3 есть метод TestFor, демонстрирующий работу цикла for на примере задачи вычисления корня квадратного из суммы квадратов целых чисел от 1 до 10. Для вычисления суммы удобно использовать цикл for, поскольку известно, что тело цикла должно выполняться 10 раз, а счетчик будет задавать искомое число, возводимое в квадрат. Вот текст данного метода:
int n = 10; double y; int summa = 0; for (int i = 0; i < n; i++) summa += (i + 1) * (i + 1); y = Math.Sqrt(summa); Console.WriteLine("Корень квадратный суммы квадратов первого десятка = " + y);
Как видите, здесь применяется типичный вариант цикла for. Вычисление суммы – это классическая задача начального этапа изучения программирования. Следует внимательно ознакомиться с этим образцом программирования.
Структурное программирование оказало большое влияние на развитие языков программирования. Впервые идеи структурного программирования были высказаны в знаменитой статье Эдсгера Дейкстры "О вреде оператора go to". Позже они были развиты в книге "Структурное программирование" трех авторов: У. Дала, Э. Дейкстры, Ч. Хоара. С тех пор все языки программирования включают в свой состав операторы, удовлетворяющие принципам структурного программирования. Все рассмотренные нами операторы соответствуют этим принципам. В чем их суть?
Сформулируем два основных принципа структурного программирования:
Из этих принципов вытекает важное следствие – "Текст программы управляет ее выполнением". Текст программы можно рассматривать как последовательность операторов S1, S2, S3, ... Sn. Выполнение программы следует этому порядку – вначале выполняется оператор S1, затем S2 и так далее, пока не будет выполнен оператор Sn.
Как же, скажете Вы, выполняются эти принципы для операторов If и While, где есть выбор и повторение? Для пояснения ответа на этот вопрос стоит рассмотреть блок-схемы трех операторов. На рис.1 показана блок-схема составного оператора:
Составной оператор – оператор с одним входом и одним выходом. На рисунке это коробочка, изображенная пунктирными линиями. Внутренность его сложная, она содержит последовательность операторов, также удовлетворяющих принципам структурного программирования.
На рис.2 показана блок-схема оператора If:
Если рассматривать оператор If как черный ящик, то у него один вход и один выход. Конечно же, когда нас интересует подробное его устройство, то мы начинаем изучать внутренние операторы. То, что они отвечают принципам структурного программирования облегчает их понимание.
На рис. 3 показана блок-схема оператора цикла While:
Принципы структурного программирования кажутся вполне естественными. Чтобы понять их достоинства следует рассмотреть неструктурированные операторы, характерные для первых языков программирования. Операторы программы могут быть помеченными. Метки операторов играют роль их имен. Оператор go to ранее широко употребляемый в программах имеет следующий синтаксис:
go to M;
Этот оператор нарушает второй принцип структурного программирования, передавая управление не своему преемнику в тексте программы, а оператору с меткой M. Следует сказать, что эти возможности сохранились и в современных языках, в том числе и в языке C#. Первоначальный вариант оператора If, появившийся в первом языке программирования Fortran, имел следующий синтаксис:
IF(<арифметическое выражение> M1, M2, M3;
Если значение арифметического выражения было положительным управление передавалось оператору с именем M1 равным нулю – M2, отрицательным – M3. Этот оператор нарушал оба принципа структурного программирования. Применение подобных операторов делало программу подобной "блюду спагетти", где вычисления перескакивали из одного фрагмента программы к другому в хаотическом порядке. Понимание работы такой программы крайне затруднительно. Это не простая задача и для структурированных программ, но не структурированность вносит излишние трудности, которые можно избежать.
Задание 1
Используя доступный образец проекта, постройте с нуля свой вариант Решения, содержащий два проекта – консольный и Windows. При проектировании интерфейса Windows проекта поэкспериментируйте со свойствами объектов интерфейса.
Задание 2
Постройте консольный проект решения следующей задачи. Для заданного значения x вычислить значение функции F(x) = 2x2 – 3x + 7.
Задание 3
Постройте Windows проект решения следующей задачи. На плоскости дан круг радиуса R с центром в начале координат. Известны координаты точки P – x и y. Необходимо определить, принадлежит ли точка кругу. Если да, то в какой квадрант она попадает.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.