- •Введение
- •Контрольная работа № 1 разработка приложений в microsoft visual studio 2008
- •Теоретические сведения Интерфейс Microsoft Visual Studio 2008
- •Создание консольного приложения
- •Построение xml-отчета по выполненному проекту
- •Создание приложения Windows Forms
- •Контрольные вопросы
- •Содержание и порядок выполнения работы
- •Контрольная работа № 2
- •Теоретические сведения Структура программы. Переменные и выражения
- •Литеральные константы
- •Операции и их старшинство
- •Операторы c#
- •If(выражение1) if(выражение2) if(выражение3) ...
- •Контрольные вопросы
- •Содержание и порядок выполнения работы
- •Примеры решения задач
- •Контрольная работа № 3 техника работы с массивами. Процедуры и функции
- •Теоретические сведения
- •Базовый класс для массивов
- •Процедуры и функции
- •Синтаксис методов
- •Формальные и фактические аргументы
- •Соответствие формальных и фактических аргументов
- •Функции с побочным эффектом
- •Функция Main()
- •Контрольные вопросы
- •Содержание и порядок выполнения работы
- •Примеры решения задач
- •Контрольная работа № 4 перечисления и структуры
- •Теоретические сведения
- •Базовый класс перечислений - System.Enum
- •Структуры
- •Контрольные вопросы
- •Содержание и порядок выполнения работы
- •Пример решения задачи
- •Контрольная работа № 5 обработка символов и строк
- •Теоретические сведения
- •Контрольные вопросы
- •Содержание и порядок выполнения работы
- •Примеры решения задачи
- •Контрольная работа № 6 проектирование классов. Составление программ с использованием ооп
- •Теоретические сведения
- •Контрольные вопросы
- •Содержание и порядок выполнения работы
- •Пример решения задачи
- •Заключение
- •Библиографический список
- •Оглавление
- •394026 Воронеж, Московский просп., 14
Операции и их старшинство
Операции в C#, их приоритет и порядок унаследованы из языка C++.
При вычислении выражения определяется его значение и тип по типам операндов, входящих в выражение.
В табл. 3 операции перечислены по строкам в порядке убывания приоритетов.
Таблица 3
Прио-ритет |
Категория |
Операции |
Порядок |
0 |
Первичные |
(expr) x.y f(x) a[x] x++ x-- new sizeof(t) typeof(t) checked(expr) unchecked(expr) |
Слева направо |
1 |
Унарные |
+ - ! ~ ++x --x (T)x |
-“- |
2 |
Мультипликативные (Умножение) |
* / % |
-“- |
3 |
Аддитивные (Сложение) |
+ - |
-“- |
4 |
Сдвиг |
<< >> |
-“- |
5 |
Отношения, проверка типов |
< > <= >= is as |
-“- |
6 |
Эквивалентность |
== != |
-“- |
7 |
Логическое |
& |
-“- |
8 |
Логическое исключающее ИЛИ (XOR) |
^ |
-“- |
9 |
Логическое ИЛИ (OR) |
| |
-“- |
10 |
Условное И |
&& |
-“- |
11 |
Условное ИЛИ |
|| |
-“- |
12 |
Условное выражение |
? : |
Справа налево |
13 |
Присваивание |
= *= /= %= += -= <<= >>= &= ^= |= |
-“- |
Операции checked и unchecked включают и выключают проверку преобразований арифметического типа в выражениях, которым они предшествуют.
Аналогично языку С++, операции "увеличить на единицу" и "уменьшить на единицу" могут быть префиксными и постфиксными. К высшему приоритету относятся постфиксные операции (x++ и x--).
Для префиксных (++x, --x) операций результатом их выполнения является измененное значение x, постфиксные операции возвращают в качестве результата значение x до изменения.
Операции могут иметь побочный эффект.
int var1=5, var2=3, var3;
var3=var1++*--var2; //var3=10
Как и в С++, операция sizeof возвращает размер значимого типа в байтах. Она выполняется только в небезопасных блоках: проект должен быть скомпилирован с включенным свойством /unsafe.
Операция typeof возвращает тип операнда, к которому она применена. Операндом может быть имя встроенного или Пользовательского класса. Возвращаемый результат имеет тип Type.
Для экземпляра класса можно вызвать метод GetType(), наследуемый всеми классами, и получить тот же результат, что дает typeof с именем данного класса.
Пример использования вызова операции typeof:
t = typeof(Class1);
Console.WriteLine("Тип класса Class1: {0}", t);
t = typeof(Testing);
Console.WriteLine("Тип класса Testing: {0}", t);
В языке C# имеются обычные для всех языков арифметические операции - "+, -, *, /, %". Все они перегружены.
Операции "+" и "-" могут быть унарными и бинарными.
Операция деления "/" над целыми типами выполняет деление нацело, для типов с плавающей и фиксированной точкой - обычное деление.
Операция "%" определена над всеми арифметическими типами и возвращает остаток от деления нацело. Тип результата зависит от типов операндов.
Пример вычислений с арифметическими типами:
public void Ariphmetica() {
int n = 7,m =3, p,q;
p= n/m; q= p*m + n%m;
if (q==n) Console.WriteLine("q=n");
else Console.WriteLine("q!=n");
double x=7, y =3, u,v,w;
u = x/y; v= u*y;
w= x%y;
if (v==x) Console.WriteLine("v=x");
else Console.WriteLine("v!=x");
decimal d1=7, d2 =3, d3,d4,d5;
d3 = d1/d2; d4= d3*d2;
d5= d1%d2;
if (d4==d1) Console.WriteLine("d4=d1");
else Console.WriteLine("d4!=d1"); }
При проведении вычислений в двух первых случаях проверяемое условие оказалось истинным, в третьем - ложным. Для целых типов можно исходить из того, что равенство n = n/m*m + n%m истинно.
Для типов с плавающей точкой выполнение точное равенство x = x/y*y не гарантируется.
Операций отношения всего операций 6: ==, !=, <, >, <=, >= . Они имеют аналогичный смысл, что и для других языков программирования.
Операции сдвига вправо ">>" и сдвига влево "<<" особенно полезны, если данные рассматриваются как строка битов. Результатом операции является сдвиг строки битов влево или вправо на K разрядов. В применении к целым положительным числам сдвиг вправо равносилен делению нацело на 2K, а сдвиг влево - умножению на 2K.
Для отрицательных чисел сдвиг влево и деление дают разные результаты, отличающиеся на единицу.
Операции сдвига определены только для некоторых целочисленных типов - int, uint, long, ulong. Величина сдвига должна иметь тип int. Пример выполнения операций сдвига:
int result, v1=4, v2=2 ;
result=v1>>v2; // result=1
result=v1<<v2; // result=16
public void Shift()
{
int n = 17,m =3, p,q;
p= n>>2; q = m<<2;
Console.WriteLine("n= " + n + "; m= " + m + "; p=n>>2 = "+p
+ "; q=m<<2 " + q);
long x=-75, y =-333, u,v,w;
u = x>>2; v = y<<2; w = x/4;
Console.WriteLine("x= " + x + "; y= " + y + "; u=x>>2 = "+u
+ "; v=y<<2 " + v + "; w = x/4 = " + w);
}
Рис. 10. Операции сдвига
В языке C++ практически для всех типов существует неявное преобразование в логический тип. Все, что отлично от 0, является истинной, 0 - это ложь.
В языке C# неявных преобразований к логическому типу bool нет.
Так же, как и в языке C++, логические операции делятся на две категории:
- выполняемые над логическими значениями операндов,
- операции над битами операндов.
Пример:
public void Logic() {
//операции отрицания ~,!
bool b1,b2;
b1 = 2*2==4; b2 =!b1;
// b2= ~b1; ошибка!
uint j1 =7, j2;
j2= ~j1;
// j2 = !j1; ошибка!
int j4 = 7, j5;
j5 = ~j4;
Console.WriteLine("uint j2 = " + j2 +" int j5 = " + j5); }
Ошибки следующие: в первом случае сделана попытка применения операции побитового отрицания к выражению типа bool, во втором - логическое отрицание применялось к целочисленным данным.
Для переменных j5 и j2 строка битов, задающая значение - одна и та же, но интерпретируется по-разному.
Поэтому будет выведено:
uint j2 = 4294967288 int j5 = -8
//Логические побитовые операции And, Or, XOR (&,|,^)
int result, v1=4, v2=5 ;
result=v1&v2; // result=4
result=v1|v2; // result=5
result=v1^v2; // result=1
result=~v1; // result=-5
int k2 = 7, k3 = 5, k4, k5, k6;
k4 = k2 & k3; k5 = k2| k3; k6 = k2^k3;
Console.WriteLine("k4 = " + k4 + " k5 = " + k5 + " k6 = " + k6);
Результаты вывода:
k4 = 5 k5 = 7 k6 =2
Бинарные логические операции "&& - условное И" и "|| - условное ИЛИ" определены только над данными типа bool.
Операции называются условными или краткими, поскольку, будет ли вычисляться второй операнд, зависит от уже вычисленного значения первого операнда.
В операции "&&", если первый операнд равен значению false, то второй операнд не вычисляется и результат операции равен false.
Аналогично, в операции "||", если первый операнд равен значению true, то второй операнд не вычисляется и результат операции равен true.
Поэтому полезным оказывается такой пример:
//Условное And - &&
int[] ar= {1,2,3};
int search = 7; int i=0;
while ((i < ar.Length) && (ar[i]!= search)) i++;
if(i<ar.Length) Console.WriteLine("Образец найден");
else Console.WriteLine("Образец не найден");
Если значение переменной search не совпадает ни с одним из значений элементов массива ar, то последняя проверка условия цикла while будет выполняться при значении i, равном ar.Length. В этом случае первый операнд получит значение false, и, хотя второй операнд при этом не определен, цикл нормально завершит свою работу.
Второй операнд не определен в последней проверке, поскольку индекс элемента массива выходит за допустимые пределы.
Бинарные побитовые операции - "& - AND " , "| - OR ", "^ - XOR" определены как над целыми типами выше int, так и над булевыми типами.
Теперь пример поиска по образцу с использованием логического AND:
i=0; search = ar[ar.Length - 1];
while ((i < ar.Length) & (ar[i]!= search)) i++;
if(i<ar.Length) Console.WriteLine("Образец найден");
else Console.WriteLine("Образец не найден");
В этом фрагменте гарантируется наличие образца поиска в массиве, и фрагмент будет успешно выполнен. В случаях, когда массив не содержит элемента search, выбрасывается исключение.
В C#, как и в C++, разрешены условные выражения () ? :
int a = 7, b= 9, max;
max= (a>b) ? a:b;
Console.WriteLine("a = " + a + "; b= " + b +"; max(a,b) = " + max);
Условное выражение начинается с условия, заключенного в круглые скобки, после которого следует знак вопроса и пара выражений, разделенных двоеточием.
Условием является выражение типа bool. Если оно истинно, то выбирается первое выражение, в противном случае результатом является значение второго выражения. В примере переменная max получит значение 9.
Операция приведения к типу имеет следующий синтаксис:
(type) <унарное выражение>
Она задает явное преобразование типа, определенного выражением, к типу, указанному в скобках. Чтобы операция была успешной, необходимо, чтобы такое явное преобразование существовало.
Существуют явные преобразования внутри арифметического типа. При определении пользовательских типов для них могут быть заданы явные преобразования в другие типы.
Пример:
int p;
p = (int)x;
//b = (bool)x; ошибка
Существует 2 способа преобразования типов.
Неявное – преобразование типа А в тип В возможно при любых обстоятельствах, их правила преобразования просты, компилятор сам справится с этой работой.
Явное – преобразование типа А в тип В возможно лишь при определенных обстоятельствах, при этом требуются дополнительные действия.
В табл. 4 записаны допустимые неявные преобразования для численных типов.
При явном преобразовании типа необходимо записать
(<требуемый тип >)<имя>
Таблица 4
Тип |
Можно безопасно преобразовать в |
byte |
short, ushort, int, uint, long, ulong, float, double, decimal |
sbyte |
short, int, long, float, double, decimal |
short |
int, long, float, double, decimal |
ushort |
int, uint, long, ulong, float, double, decimal |
int |
long, float, double, decimal |
uint |
long, ulong, float, double, decimal |
long |
float, double, decimal |
ulong |
float, double, decimal |
float |
double |
char |
ushort, int, uint, long, ulong, float, double, decimal |
Такая запись возможна только в некоторых ситуациях. Для типов, мало похожих друг на друга, или вовсе не имеющих ничего общего, такое преобразование, будет неопределено.
byte destVar;
short sourceVar=281;
destVar=(byte)sourceVar;
Console.WriteLine(“sourceVar={0}”, sourceVar); // 281
Console.WriteLine(“destVar={0}”, destVar); // 25
Произошло это в связи с тем, что потерян самый левый бит исходного значения:
281 =100011001
25 =000011001
А максимальное значение типа byte равно 255 ( 011111111).
Можно проверить переполнение с помощью слов checked и unchecked:
checked(<выражение>)
unchecked(<выражение>)
Если добавить эту проверку
byte destVar; short sourceVar=281;
destVar=checked((byte)sourceVar);
Console.WriteLine("sourceVar={0}", sourceVar);
Console.WriteLine("destVar={0}", destVar);
то процесс выполнения будет прерван и появится сообщение об ошибке
Рис. 11. Произошло переполнение
Если вместо checked записать unchecked
byte destVar;
short sourceVar=281;
destVar=unchecked((byte)sourceVar);
Console.WriteLine("sourceVar={0}", sourceVar);
Console.WriteLine("destVar={0}", destVar);
то программа выполнится с первоначальным результатом.
Для явного преобразования используются методы класса Convert (табл. 5).
Таблица 5
Команда |
Результат: преобразовано в |
Convert.ToBoolean(val) |
bool |
Convert.ToByte(val) |
byte |
Convert.ToChar(val) |
char |
Convert.ToDecimal(val) |
decimal |
Convert.ToDouble(val) |
double |
Convert.ToInt16(val) |
short |
Convert.ToInt31(val) |
int |
Convert.ToInt64(val) |
long |
Convert.ToSbyte(val) |
sbyte |
Convert.ToSingle(val) |
float |
Convert.ToString(val) |
string |
Convert.ToUInt16(val) |
ushort |
Convert.ToUInt32(val) |
uint |
Convert.ToUInt64(val) |
ulong |
Имена типов взяты из System .NET Framework, благодаря чему их можно использовать из любых других языков, совместимых с .NET.
При таких преобразованиях всегда контролируется переполнение, не смотря на наличие checked, unchecked и установок для проекта.
Пример
short shortResult, shortVal=4;
int integerVal=67;
long longResult;
float floatVal=10.5F;
double doubleResult, doubleVal=99.999;
string stringResult, stringVal="17";
bool boolVal=true;
Console.WriteLine("Примеры преобразования типов\n");
doubleResult = floatVal*shortVal;
Console.WriteLine("Неявное, ->double: {0} * {1} -> {2}",
floatVal,shortVal,doubleResult);
shortResult = (short)floatVal;
Console.WriteLine("Явное, -> short: {0} -> {1}",floatVal,shortResult);
stringResult = Convert.ToString(boolVal)+
Convert.ToString(doubleVal);
Console.WriteLine("Явное, ->string: \"{0}\"{1}\" -> {2}",
boolVal,doubleVal,stringResult);
stringResult = stringVal+ floatVal;
Console.WriteLine("Неявное, ->string: \"{0}\"+ {1} -> {2}",
stringVal,floatVal,stringResult);
longResult=integerVal + Convert.ToInt64(stringVal);
Console.WriteLine("Смешенное, -> long: {0} + {1} -> {2}",
integerVal,stringVal,longResult);
Рис. 12. Результаты преобразования типов