
- •Язык c# и структура простой программы
- •Что такое .Net Framework
- •Что такое с#
- •Создание первой программы на с#
- •Пространство имен System
- •С# как язык Объектно-Ориентированного Программирования (ооп)
- •Состав и назначение файлов проекта
- •Структура сборки
- •Элементы языка c#
- •Базовый синтаксис с#
- •Переменные
- •Числа без знака
- •Числа со знаком
- •Числа для финансистов
- •Текстовые символы
- •Логический тип данных
- •Литералы с плавающей точкой
- •Символьные литералы
- •Строковые литералы
- •Выражения и операторы с#
- •Инициализация переменных и оператор присваивания
- •Значение в левой части
- •Ввод данных с консоли
- •Математические операторы
- •Вычисление остатка при целочисленном делении
- •Унарные операторы
- •Унарное логическое отрицание
- •Составные операторы
- •Поразрядные операторы
- •Поразрядное логическое и
- •Поразрядное логическое или
- •Поразрядное логическое исключающее или
- •Унарная поразрядная операция дополнения
- •Поразрядный сдвиг
- •Пример использования поразрядных операторов
- •Логические операторы
- •Операторы отношения
- •Приоритеты операторов
- •Исполнители алгоритмов
- •Исполнитель Чертежник
- •Исполнитель Робот
- •Компьютер как формальный исполнитель алгоритмов
- •Блок-схема
- •Псевдокод
- •Необходимые свойства алгоритма
- •Понятие о временной сложности алгоритма
- •Примеры
- •Правила для определения сложности
- •Тернарный условный оператор
- •Применение логических операций
- •Конструкция выбора
- •Примеры применения оператора выбора
- •Объединение меток case
- •Пропущенный break
- •Пример программы: Простые числа
- •Пример обработки одномерного массива чисел
- •Использование генератора случайных данных
- •Использование оператора foreach
- •Типы задач обработки одномерных числовых массивов
- •Поиск элемента в массиве
- •Многомерные массивы
- •Базовые операции со строками
- •Методы типа string
- •Копирование и клонирование строк
- •Конкатенация строк
- •Извлечение подстроки
- •Вставка подстроки
- •Замена символов и строк
- •Удаление символов из строки
- •Удаление незначащих пробелов
- •Преобразование к верхнему и нижнему регистру
- •Выравнивание по левому и правому краю поля
- •Объединение массива строк
- •Разбор строки
- •Сравнение строк
- •Форматирование текстовых строк
- •Функции
- •Описание и использование функций
- •Возвращаемые значения
- •Передача параметров
- •Выходные параметры
- •Область действия переменных
- •Область действия переменных и управляющие конструкции
- •Рекурсия
- •Параметры функции Main()
- •Перегрузка функций
- •Перечислимый тип
- •Определение перечислимых типов
- •Структуры
- •Описание структур
- •Использование структур в качестве параметров функций
- •Использование структур в качестве возвращаемых значений функций
- •Функции структур
- •Файлы и потоки
- •Основные классы ввода и вывода
- •Классы для работы с потоками
- •Классы для работы с потоками текстовых символов
- •Работа с текстовыми файлами
Примеры применения оператора выбора
Вот простейший пример использования оператора switch для выбора одной из нескольких строк, отображаемых на консоли. Выбор делается в зависимости от значения переменной i :
int i = 2;
switch(i)
{
case 1:
System.Console.WriteLine("case 1");
break;
case 2 :
{
System.Console.WriteLine("case 2");
break;
}
case 3:
{
System.Console.WriteLine("case 3");
break;
}
default:
{
System.Console.WriteLine("default");
break;
}
}
Так как содержимое переменной i равно двум, на консоли всегда будет отображаться строка “case 2”.
Обратите внимание на оператор перехода break, расположенный в конце каждого блока case, а также в конце блока default. Этот оператор завершает выполнение строк программы текущего блока и передает управление вниз, за пределы оператора switch.
Далее приведен исходный текст программы, которая вводит текстовую строку с клавиатуры и сравнивает ее с одной из трех строк. При совпадении программа выводит на консоль соответствующее сообщение. Если совпадений нет, выводится сообщение об ошибке.
using System;
namespace SwitchOp
{
class SwitchOpApp
{
static void Main(string[] args)
{
System.Console.Write(
@"Введите одну из строк ""мама"", ""мыла"", ""раму"" : ");
string inputString;
inputString = System.Console.ReadLine();
switch(inputString)
{
case "мама":
System.Console.WriteLine(@"Вы ввели строку ""мама""");
break;
case "мыла":
System.Console.WriteLine(@"Вы ввели строку ""мыла""");
break;
case "раму":
System.Console.WriteLine(@"Вы ввели строку ""раму""");
break;
default:
System.Console.WriteLine("Ошибка при вводе");
break;
}
System.Console.ReadLine();
}
}
}
В отличие от предыдущего примера здесь в качестве переключающего выражения используется не число, а текстовая строка.
Объединение меток case
В некоторых случаях требуется выполнять одну и ту же обработку для разных значений выражения, расположенного после ключевого слова switch. В языке С# это можно сделать следующим образом:
int i = 2;
switch(i)
{
case 1:
case 2:
{
System.Console.WriteLine("case 1 или 2");
break;
}
case 3:
{
System.Console.WriteLine("case 3 ");
break;
}
default:
{
System.Console.WriteLine("default");
break;
}
}
Здесь мы объединили вместе метки case 1 и case 2, определив одинаковую обработку для значений переменной i, равных единице или двум. В любом из этих случаев на консоли будет отображаться строка "case 1 или 2".
Пропущенный break
Рассмотрим следующий фрагмент программы:
// Эта программа транслироваться не будет!
int i = 1;
switch(i)
{
case 1:
System.Console.WriteLine("case 1"); // Ошибка!
case 2:
{
System.Console.WriteLine("case 2"); // Ошибка!
}
case 3:
{
System.Console.WriteLine("case 3");
break;
}
default:
{
System.Console.WriteLine("default");
break;
}
}
Как видите, здесь в два первых блока case мы намеренно «забыли» вставить операторы break. К чему это приведет?
Если бы программа была написана на языке С или C++, на консоль были бы последовательно выведены 3 строки:
case 1
case 2
case 3
При отсутствии оператора break в программе С или C++ управление передается на следующий блок case или default, а не за пределы оператора switch. Эта особенность применялась многими программистами в тех случаях, когда нужно было совместить обработку, выполняемую в разных блоках case.
В языке С# такое совмещение не допускается. Вы можете объединять метки, но конструкция, приведенная выше, компилироваться не будет.
Причина этого заключается в том, что разработчики программ С или C++ часто пропускали оператор break по ошибке, а вовсе не потому, что это было необходимо для реализации логики работы программы. Компилятор С# пресекает такие ошибки еще до того, как они смогут себя проявить во время работы программы.
Циклы
Циклы (повторения) в алгоритмах и, соответственно, в программах предназначены для многократного выполнения необходимых действий. Количество повторений цикла может задаваться программистом или определяться в зависимости от некоторого условия.
Существуют три основные управляющие конструкции. Две из них управляются задаваемым программистом условием, а третья реализует цикл с заданным количеством повторений. Выбор одной из них для каждого цикла в разрабатываемой программе зависит только от программиста.
Алгоритмические структуры «Циклы» реализуется в C# с помощью четырех различных управляющих конструкций. В данном разделе рассказывается об использовании итерационных операторов while, do-while, for и foreach.
Цикл Пока
Структура повторения «Цикл-Пока» позволяет программисту задать многократное выполнение действия до тех пор, пока некоторое условие остается истинным. Следующие операторы псевдокода описывают повторяющиеся действия, происходящие во время поездки за покупками:
Пока в моем списке покупок еще остаются пункты
Сделать следующую покупку
Вычеркнуть соответствующий пункт
Все-Пока
Условие «в моем списке покупок еще остаются пункты» может быть истинным или ложным. Если оно истинно, то выполняются действия «Сделать следующую покупку» и «Вычеркнуть соответствующий пункт из списка». Эти действия будет многократно выполняться до тех пор, пока условие будет оставаться истинным. Оператор (или операторы), содержащийся в структуре повторения «Цикл-Пока», составляет тело этой структуры. Таким образом, тело структуры «Цикл-Пока» может быть простым или составным оператором.
В конце концов, условие становится ложным (когда последний предмет в списке покупок приобретен и вычеркнут из списка). В этот момент повторение завершается и выполняется первый оператор псевдокода, следующий за структурой повторения.
В общем случае в псевдокоде «Цикл-Пока» имеет вид:
Пока <Условие>
<Блок Операторов>
Все-Пока
На блок-схеме структура «Цикл-Пока» изображается следующим образом:
В качестве примера реализации структуры «Цикл-Пока» на C# рассмотрим фрагмент программы, разработанной для нахождения первой степени 2, превосходящей 1000. Предположим, что целочисленная переменная product была инициализирована значением 2. После завершения выполнения следующего оператора цикла while в переменной product будет содержаться желаемый ответ:
int product = 2;
while (product <= 1000)
{
product = 2 * product;
}
System.Console.WriteLine("{0}", product);
Рассмотрим алгоритм этого цикла, записанный в виде блок-схемы:
Блок-схема иллюстрирует поток управления в структуре повторения while. Обратите внимание, что (кроме кружков и стрелок) блок-схема содержит только символ прямоугольника и символ ромба Линия перехода, выходящая из прямоугольника, снова возвращается к блоку принятия решения, условие которого проверяется на каждом проходе цикла до тех пор, пока оно в конечном итоге не становится ложным. В этот момент происходит выход из структуры while, и управление переходит к следующему оператору программы.
При входе в структуру while значение переменной product равно 2. Переменная product многократно умножается на 2, последовательно принимая значения 4, 8, 16, 32, 64, 128, 256, 512 и 1024. Когда значение переменной product становится равным 1024, условие в структуре while, product <= 1000, становится ложным. Это завершает повторение, и конечное значение переменной product равно 1024. Выполнение программы продолжается с оператора, следующего за структурой while.
Не забывайте, что оператор while реализует цикл с предусловием, поэтому условие завершения цикла проверяется перед выполнением тела цикла:
i = 0;
while(i < 10)
{
System.Console.Write("{0} ", i);
i++;
}
Перед тем как приступить к выполнению цикла, мы устанавливаем начальное значение параметра цикла i, равное нулю. Если неверно установить значение переменных, входящих в проверяемое условие, или неправильно записать само условие, цикл может не выполниться ни разу:
i = 0;
while(i > 10)
{
System.Console.Write("{0} ", i);
i++;
}
Также важно помнить, что оператор while должен содержать в теле цикла операторы, которые могут повлиять на изменение истинности условия, записанного в его начале. Поэтому в данном примере после выполнения тела цикла мы сами изменяем значение параметра цикла, увеличивая его на единицу. Цикл будет прерван, как только значение переменной i превысит 10.
Следующий цикл будет выполняться бесконечно:
while(true)
{
System.Console.Write("{0} ", i);
i++;
}
Циклы while(true){...} являются достаточно удобным и гибким орудием в умелых руках и могут использоваться, когда в момент входа в цикл достаточно трудно сформулировать условие выхода из него. Однако при этом необходимо обеспечить способ покинуть цикл из необходимой внутренней точки (или нескольких таких точек). Для этого существуют достаточно удобные управляющие операторы, которые рассмотрены в следующем разделе.
Еще раз напоминаем, что нужно всегда предусматривать возможность выхода из цикла. Бесконечный цикл часто появляется в программе вследствие ошибки программиста и не всегда может быть обнаружен компилятором при трансляции программы.
Прерывание и возобновление цикла
В
некоторых случаях необходимо прервать
выполнение цикла до того, как его условие
станет ложным, то есть осуществить
преждевременный выход из цикла. Для
этого необходимо выполнение некоторого
дополнительного условия.
На псевдокоде это выглядит так:
Пока <Условие 1>
<Блок Операторов 1>
Если <Условие 2>
Выход из цикла
Все-Если
[<Блок Операторов 2>]
Все-Пока
На блок-схеме это изображается следующим образом:
В С# во всех видах циклов можно использовать специальные операторы прерывания цикла break и возобновления цикла continue.
С помощью оператора break можно в любой момент прервать выполнение цикла. Например, в следующем фрагменте программы мы прерываем работу цикла, когда значение переменной i становится больше пяти:
int i = 0;
while(true)
{
if(i > 5)
break;
System.Console.Write("{0} ", i++ );
}
В результате на консоль будут выведены цифры от 0 до 5:
Такая организация повторений позволяет реализовывать любую необходимую логику циклической обработки. Например, можно изменять значение переменной цикла перед итерацией, а не после нее:
int i = 0;
while(true)
{
i++;
if(i > 5)
break;
System.Console.Write("{0} ", i);
}
В результате на консоль будут выведены цифры уже от 1 до 5.
В отличие от оператора break, прерывающего цикл, оператор continue позволяет возобновить выполнение цикла с самого начала. Вот как он используется:
int i = 0;
while(true)
{
System.Console.Write("{0} ", i);
i++;
if(i < 9)
continue;
else
break;
}
Если в ходе выполнения цикла значение переменной i не достигло девяти, цикл возобновляет свою работу с самого начала (т.е. с вывода значения переменной цикла на консоль). Когда указанное значение будет достигнуто, выполнение цикла прервется оператором break.
В результате выполнения цикла на консоль будут выведены цифры от 0 до 8.
Возобновление цикла в блок-схеме и на псевдокоде выглядит так:
Пока <Условие 1>
[<Блок Операторов 1>]
Если <Условие 2>
Продолжить цикл
Все-Если
<Блок Операторов 2>
Все-Пока
Оператор continue может также использоваться для пропуска некоторых значений переменной цикла или вводимых и обрабатываемых в цикле данных. В следующем примере на консоль выводятся значения переменной i из заданного диапазона, кроме некоторых из них:
int i = 0;
while(i < 10)
{
i++;
if(i == 3 || i == 5) // Эти значения будут пропущены
continue;
System.Console.Write("{0} ", i);
}
Выполните данный код самостоятельно и проверьте, какие именно значения будут напечатаны.
Последний пример демонстрирует совместное использование операторов прерывания и возобновления цикла для обработки вводимых пользователем данных. Необходимо найти сумму вводимых пользователем четных чисел, пропуская вводимые им нечетные, при этом в качестве признака конца работы используется ввод числа 0:
using System;
namespace Rabota1
{
class Program
{
static void Main(string[] args)
{
int Sum = 0;
while (true)
{
int number;
Console.Write("Число = ");
number = Convert.ToInt32(Console.ReadLine());
if (number % 2 == 1) // Нечетные значения будут пропущены
continue;
if (number == 0) // Выход из цикла
break;
Sum += number;
}
Console.WriteLine("Сумма четных = {0}", Sum);
Console.ReadLine();
}
}
}
Результат работы данной программы:
Цикл Делать-Пока
Структура повторения «Делать-Пока» подобна структуре «Цикл-Пока». В структуре «Цикл-Пока» условие продолжения цикла проверяется в начале цикла до выполнения его тела. Структура «Делать-Пока» проверяет условие продолжения цикла после выполнения тела цикла, поэтому тело цикла будет выполнено, по крайней мере, один раз.
На следующем рисунке представлена блок-схема структуры «Делать-Пока» и ее псевдокод:
Делать
<Блок Операторов>
Пока <Условие>
Из нее становится понятно, что условие продолжения цикла проверяется только после того, как действие будет выполнено, по крайней мере, один раз. Переход назад (на следующую итерацию) возможен только после выполнения тела цикла и проверки заданного условия.
В C# структура «Делать-Пока» реализуется с помощью оператора do-while:
do
{
<Операторы>
}
while( <Условие> );
После завершения цикла do-while выполнение программы продолжается с оператора, следующего за предложением while. Обратите внимание, что при наличии только одного оператора в теле цикла в структуре do-while нет необходимости использовать фигурные скобки. Однако обычно фигурные скобки включаются во избежание путаницы между структурами do-while и while. Например, строка
while( <Условие> )
обычно рассматривается в качестве заголовка структуры while. Структура do-while без фигурных скобок вокруг ее тела, состоящего из одного оператора, выглядит как
do
<Оператор>
while( <Условие> );
Это может приводить к путанице. Последняя строка — while (условие); может быть неправильно истолкована читателем как структура while, содержащая пустой оператор. Поэтому структура do-while с одним оператором часто записывается так:
do
{
<Оператор>
}
while( <Условие> );
В следующем примере цикл do-while используется для вывода чисел от 1 до 10. Обратите внимание, что к управляющей переменной counter при проверке условия продолжения цикла применяется операция инкремента в префиксной форме. Обратите также внимание на фигурные скобки, заключающие тело структуры do-while, состоящее из одного оператора.
int counter = 1;
do
{
System.Console.Write("{0} ", counter);
}
while(++counter <= 10);
Еще один пример демонстрирует программу, определяющую (по текущему состоянию Вашего банковского счета и известному годовому проценту), через сколько лет у Вас на счету окажется нужная сумма:
using System;
namespace Rabota1
{
class Program
{
static void Main(string[] args)
{
double balance, interestRate, targetBalance;
Console.WriteLine("Текущий размер счета?");
balance = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Годовые начисления (в %)?");
interestRate = 1 + Convert.ToDouble(Console.ReadLine()) / 100.0;
Console.WriteLine("Сколько должно быть на счету?");
targetBalance = Convert.ToDouble(Console.ReadLine());
int totalYears = 0 ;
do
{
balance *= interestRate;
++totalYears;
}
while (balance < targetBalance);
Console.WriteLine("Через {0} лет на счету будет {1}.",
totalYears, balance);
Console.ReadLine();
}
}
}
Результат работы этой программы:
Цикл с параметром
Цикл с параметром предназначен для выполнения оператора или блока операторов заданное количество раз. Как правило, в цикле имеется параметр - переменная, играющая роль так называемой переменной цикла. При каждой итерации переменная цикла изменяет свое значение в заданных пределах.
Пусть в качестве параметра цикла используется переменная К, и цикл должен быть выполнен М раз. Вот как выглядит такой цикл в блок-схеме и на псевдокоде:
Для К = 1 До N [Шаг 1]
<Операторы>
Все-Для-К
На блок-схеме цикл с параметром похож на цикл с предусловием. В псевдокоде указываются начальное и конечное значение параметра, а также шаг его изменения, при этом шаг может быть опущен только в случае, если он равен единице. Завершается цикл в псевдокоде строкой Все-Для, в которой указывается имя параметра цикла.
В C# цикл с параметром реализуется оператором for, который в общем виде записывается так:
for([Инициализация];[Условие];[Приращение])
<Оператор>
Оператор [Инициализация] выполняется один раз перед началом цикла. Перед каждой итерацией (т. е. перед каждым выполнением тела цикла <Оператор>) проверяется [Условие]. И, наконец, после каждой итерации выполняется оператор [Приращение].
Начальное значение переменной цикла задается в программе до оператора for или в операторе [Инициализация]. Способ изменения переменной цикла определяется оператором приращения, а сравнение ее текущего значения с предельным значением — в блоке [Условие ].
Поясним сказанное на простом примере.
int i ;
for(i = 0; i < 10; i++)
{
System.Console.Write("{0} " , i);
}
Здесь переменная i используется в качестве переменной цикла. Перед началом цикла ей присваивается нулевое значение. Перед каждой итерацией содержимое переменной i сравнивается с числом 10. Если i меньше 10, тело цикла выполняется один раз. В тело цикла мы поместили вызов метода Write, отображающий текущее значение переменной цикла на консоли.
После выполнения тела цикла значение i увеличивается на единицу в блоке приращения. Далее переменная цикла вновь сравнивается с числом 10. Когда значение i превысит 10, цикл завершится.
Таким образом, параметр цикла анализируется перед выполнением тела цикла, а модифицируется после его выполнения.
Вот что выведет на консоль приведенный выше фрагмент программы:
Цикл for имеет настолько общий характер, что его можно использовать для получения самых разнообразных эффектов. Например, любая из трех частей цикла может быть опущена, так как не всегда заранее известно, на сколько, например, надо смещаться по последовательности или когда завершить цикл. Ниже рассмотрены некоторые варианты цикла for.
Цикл вперед. Это самая распространенная форма, как показывает приведенный ниже пример.
int Sum = 0;
for (int i = 1; i <= 10; i++)
{
Sum += i;
}
Console.WriteLine("Sum = {0}", Sum);
Этот цикл вычисляет сумму целых чисел от 1 до 10.
Цикл назад. Иногда оказывается удобнее перемещаться по массиву элементов в обратном порядке (массивы и работа с ними будут рассмотрены позже) или иметь счетчик, который в каждой итерации уменьшает свое значение. Например, цикл, который имитирует обратный отсчет времени:
for (int i = 10; i >= 0; i--)
{
Console.WriteLine("{0} Секунд до старта...", i);
}
Console.WriteLine("Поехали!!!");
Бесконечный цикл. Иногда требуется цикл, который не имеет условия завершения. Обычно в таких случаях предусматривается какой-либо способ прерывания цикла где-то в самом его теле; одной из возможностей будет оператор break. Как мы уже рассматривали ранее, можно оформить цикл следующим образом:
while( true )
{
//Тело цикла опущено
}
Однако многие программисты предпочтут такой вариант
for( ; ; )
{
//Тело цикла опущено
}
Согласно правилам, если в заголовке цикла for опущены операторы инициализации и приращения, то не выполняется никаких действий. Если же опущено условие продолжения, то цикл продолжается вечно, как если бы это условие всегда было равно true. В такой форме цикла нет особых преимуществ, это просто выражение определенного стиля программирования.
Вложенные циклы. В программах очень часто встречаются циклы, вложенные в другие циклы. Если такие циклы имеют управляющие переменные, то эти переменные должны быть различными для внешних и внутренних циклов, иначе возникнет путаница. Вложенные циклы можно использовать, например, для вывода на консоль таблицы умножения:
Console.WriteLine("Таблица умножения");
for (int i = 1; i < 10; i++)
{
for (int j = 1; j <= 10; j++)
{
Console.WriteLine("{0} * {1} = {2}", i, j, i * j);
}
Console.WriteLine();
}
Пустые циклы. В циклах while и for возможна ситуация, когда тело цикла полностью пропускается. Например, приведенный ниже цикл не выполнится ни разу, если переменная n будет иметь нулевое значение.
for(int i = 0; i < n; i++)
{
//Тело цикла опущено
}
Но чаще «пустым» именуется цикл, у которого все необходимые действия выполняются в внутри скобок после for, а тело как таковое отсутствует:
int i, n = 123;
for (i = 1; i * i < n; i++)
{}
Console.WriteLine("{0} – первое число, квадрат которого больше {1}", i, n);
При этом пустые фигурные скобки, ограничивающие тело цикла, можно опустить, поставив вместо них точку с запятой – для компилятора этого вполне достаточно. Но привыкать ставить точку с запятой после цикла весьма опасно – это может привести в будущем к труднообнаружимым ошибкам.
Пустые циклы отличаются от обычных также местом объявления управляющей переменной цикла. Поскольку главным результатом такого цикла обычно является значение управляющей переменной, с которым был закончен цикл, то эта переменная используется уже после завершения цикла, а, значит, должна быть объявлена до его начала. Например, следующая версия вышеприведенного цикла компилироваться уже не будет:
int n = 123;
for (int i = 1; i * i < n; i++)
{}
// Ошибка компиляции: Переменная i неизвестна
Console.WriteLine("{0} – первое число, квадрат которого больше {1}", i, n);
Двойные циклы. Нетрудно сделать так, чтобы в цикле существовали две управляющих переменных, которые изменяются синхронно в процессе повторения тела цикла. Приведенный ниже небольшой пример вычисляет сумму произведений 1*10 + 2*9 + 3*8+ 4*7 + 5*6 = 110.
int i, j;
int Sum = 0;
for (i = 1, j = 10; i <= j ; i++, j--)
{
Sum += i * j;
}
Console.WriteLine("Sum = {0}", Sum);
Циклы с альтернативным выходом. Если условие продолжения цикла содержит булево выражение с оператором И, тогда цикл может завершиться, если одно из условий в выражении станет равным false. Обычно необходимо знать, какое это было условие, поэтому непосредственно после цикла мы снова проверяем условия. Например, предположим, что мы хотим ввести 10 чисел, при этом цикл ввода надо завершить либо после ввода отрицательного числа, либо после ввода всех 10 чисел. Такой цикл будет иметь следующий вид:
int i, num = 0;
// Если не присвоить num начальное значение, компилятор даст ошибку!!!!
for(i = 0; i < 10; i++)
{
num = Convert.ToInt32(Console.ReadLine());
if (num < 0)
{
break;
}
}
if (num < 0)
Console.WriteLine("Отрицательное число {0}", num);
else //Цикл завершился на 10-м повторении, отрицательных чисел не было
Console.WriteLine("Нет отрицательных");