66
Министерство образования и науки Российской Федерации Ярославский государственный университет им. П. Г. Демидова Кафедра компьютерной безопасности и математических методов обработки информации В. Л. Дольников О. П. Якимова Основы программирования на языке С#. Примеры лабораторных работ Лабораторный практикум Рекомендовано Научно-методическим советом университета для студентов, обучающихся по специальности Компьютерная безопасность Ярославль 2010

Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

  • Upload
    others

  • View
    12

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

Министерство образования и науки Российской Федерации Ярославский государственный университет им. П. Г. Демидова Кафедра компьютерной безопасности и математических методов

обработки информации

В. Л. Дольников

О. П. Якимова

Основы программирования на языке С#.

Примеры лабораторных работ

Лабораторный практикум

Рекомендовано Научно-методическим советом университета

для студентов, обучающихся по специальности Компьютерная безопасность

Ярославль 2010

Page 2: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

2

УДК 004.43 ББК З 973.2–018.1я73

Д 65 Рекомендовано

Редакционно-издательским советом университета в качестве учебного издания. План 2010/11 учебного года

Рецензент кафедра компьютерной безопасности и математических методов обработки

информации Ярославского государственного университета им. П. Г. Демидова

Д 65

Дольников, В. Л. Основы программирования на языке С#. При-меры лабораторных работ: лабораторный практикум / В. Л. Дольников, О. П. Якимова; Яросл. гос. ун-т им. П. Г. Демидова. – Ярославль : ЯрГУ, 2010. – 64 с.

Лабораторный практикум предназначен для студентов, обучающих-ся по специальности 090102.65 Компьютерная безопасность (дисцип-лина «Информатика», блок ЕН), очной формы обучения.

УДК 004.43ББК З 973.2–018.1я73

Ярославский государственный университет им. П. Г. Демидова, 2010

________________________________________________________________________ Учебное издание

Дольников Владимир Леонидович

Якимова Ольга Павловна

Основы программирования на языке С#. Примеры лабораторных работ

Лабораторный практикум

Редактор, корректор И. В. Бунакова Верстка Е. Л. Шелехова

Подписано в печать 01.11.10. Формат 6084 1/16. Бум. офсетная. Гарнитура "Times NewRoman".

Усл. печ. л. 3,72. Уч.-изд. л. 2,0. Тираж 35 экз. Заказ

Оригинал-макет подготовлен

в редакционно-издательском отделе Ярославского государственного университета им. П. Г. Демидова.

Отпечатано на ризографе. Ярославский государственный университет им. П. Г. Демидова.

150000, Ярославль, ул. Советская, 14.

Page 3: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

3

Введение

Microsoft .NET Framework – это программная технология, основной задачей которой является предоставление разработчику набора очень удобных средств для разработки как простых программ, так и web приложений. Платформа .Net вобрала в себя все самое лучшее, что когда-либо создавали Microsoft и ее конкуренты. Ее преимущества:

– полная сквозная интеграция языков (говоря проще, разные части проекта могут быть написаны на разных .Net совместимых языках программирования – и все будет работать!);

– обширная библиотека базовых классов; – упрощенная модель развертывания программного продукта

(в .Net не надо регистрировать двоичные компоненты в систем-ном реестре, установка приложения осуществляется простым копированием);

– безопасный код. И это лишь малая часть тех удобств, которые получили про-

граммисты. Специально для этой платформы Microsoft разработала но-

вый язык программирования C#. Синтаксис C# очень похож на Java, многие конструкции аналогичны C++, но все-таки это новый язык. Строгий, гибкий и многофункциональный. Если учесть то, насколько сильно распространена операционная система Windows, а также насколько удачным получился про-дукт, то справедливо предположить, что специалисты в данной области будут очень востребованы в ближайшем будущем.

Подобно технологии Java, среда разработки .NET из исход-ного кода программы создаёт байт-код, предназначенный для исполнения виртуальной машиной. Входной язык этой машины в .NET называется MSIL (Microsoft Intermediate Language) или просто IL. Применение байт-кода предназначено для получения кросс-платформенности. С помощью JIT-компилятора (just in time, компиляция на лету), непосредственно перед запуском

Page 4: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

4

сборки, в среде исполнения CLR происходит преобразование байт-кода в машинные коды целевого процессора.

Всю мощь C# можно оценить при использовании объектно ориентированного подхода, создавая Windows-приложения. Цель данного пособия – изучение базовых конструкций языка и создание простых консольных приложений, т. е. основ программирования.

Начинающие программисты сталкиваются с опреде-ленными трудностями при разработке первых простых программ в среде MS Visual Studio .NET. Языки програм-мирования платформы .NET являются, как правило, объектно ориентированными, а освоение ООП все-таки целесообразно проводить только после получения некоторого практического опыта разработки алгоритмов и их реализации в виде сравнительно простых программ. Именно на эту начальную стадию изучения программирования и ориентирован данный учебный материал.

Как результат, разработка программ в среде MS Visual Studio .NET будет показываться на примере конкретных прак-тических действий. Опыт разработки алгоритмов для решения учебных задач даст реальную основу для перехода к успешному освоению ООП. Задачи, которые приводятся в методических указаниях, взяты из [1, 2, 3, 5].

Необходимое программное обеспечение

Для выполнения лабораторных работ необходимо следующее программное обеспечение:

1) 32-разрядная операционная система Microsoft Windows 98, ME, 2000, XP, Vista, 7;

2) интегрированная среда разработки Microsoft Visual Studio .NET 2008, 2010, Express Edition 2008, 2010. Среду разработки можно бесплатно скачать с сайта www.microsoft.com/express /downloads/.

Page 5: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

5

Создание первой программы

Традиционно первой программой в большинстве учебников по программированию является программа, которая выводит на печать строку: «Hello, world!». Не будем отказываться от традиций и создадим наше первое приложение – HelloWorld.

Для этого запустите MS Visual Studio, после чего создайте новый проект, используя пункты меню File – New – Project, как показано на рис. 1.

Рис. 1. Создание нового проекта

Выберите проекты Visual C#, в шаблонах отметьте Console Application (консольное приложение) и введите имя для нашего проекта: HelloWorld. По умолчанию все проекты сохраняются в папке «Мои документы\Visual Studio 2008\Projects», но Вы можете указать свой каталог (см. рис. 2).

Page 6: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

6

Рис. 2. Выбор типа проекта

В открывшемся окне редактора будет код шаблона простей-шего приложения .Net на языке C#.

В него нам необходимо добавить 2 строки кода: первая будет выводить на экран сообщение «Hello World», вторая будет ожидать символ, введенный пользователем, только после этого программа завершится. Ожидание ввода нам необходимо, чтобы прочитать вывод строки программой, иначе мы просто не успеем его увидеть – программа выполнит код и завершится.

Page 7: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

7

Рис. 3. Шаблон консольного приложения

namespace HelloWorld 

    class Program 

    { 

        static void Main(string[] args) 

        { 

       // выводим текст в консоль        Console.WriteLine("Hello world!!!");       // ждем нажатия клавиши пользователем... 

       Console.ReadKey(); 

        } 

    } 

Page 8: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

8

После того как вы набрали данный код, достаточно нажать F5 и программа будет запущена, после чего вы сможете увидеть результат ее работы. Запуск программы можно произвести и через пункты меню Debug – Start Debugging.

Разберем код нашей программы. Как вы помните, большая его часть была сформирована автоматически. Начальные четыре строчки кода, каждая из которых начинается со слова using, сообщают о том, какие библиотеки подключены к нашему проекту по умолчанию.

Далее открывается наше собственное пространство имен, его имя совпадает с именем проекта, который мы создали. Пространство имен нужно прежде всего для больших программных проектов, оно служит для логической группировки идентификаторов. Один и тот же идентификатор может быть независимо определён в нескольких пространствах.

Воспользуемся аналогией. Предположим, существуют две фирмы А и Б. Сотрудник Иванов фирмы А имеет табельный но-мер 123. Сотрудник Иванов фирмы Б также имеет табельный номер 123. Единственное (с точки зрения некоей системы учета), благодаря чему Ивановы могут быть различимы при совпадающих табельных номерах, это их принадлежность к разным фирмам. Различие фирм в этом случае представляет собой систему различных пространств имён.

Следующая строка кода: class Program. Напомним, что C# прежде всего язык объектно ориентированного программи-рования (ООП). В ООП все данные (переменные) и обраба-тывающие их процедуры и функции (методы) объединяются в классы. Метод с именем Main является точкой входа в программу, то есть исполнение программы начинается именно с инструкций, записанных в методе Main.

Рассмотрим остальные строки кода. Понятно, что Console. WriteLine – это метод вывода на печать, Console.ReadKey – метод, ждущий нажатия на любую клавишу, а комментарии в C# начинаются с //.

Теперь можно переходить к чуть более сложным програм-мам. Ниже этап создания проекта консольного приложения мы будем опускать и сосредоточимся на коде метода Main.

Page 9: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

9

Лабораторная работа № 1 Простейшие конструкции языка

Цель работы. Придумать алгоритм и решить задачу на применение простейших конструкций языка – цикла и условия, осуществляя пошаговый ввод и вывод данных.

Разберем несколько примеров. Пример 1.1. Даны две целые переменные a, b. Составить

программу, после исполнения которой значения переменных поменялись бы местами (новое значение a равно старому значению b и наоборот).

Опишем две целочисленные переменные, чьи значения нам даны, и дополнительную переменную d:

int a, b, d; 

Теперь введем значения a и b с клавиатуры. Стандартный метод ввода с консоли возвращает строку. Поэтому при вводе необходимо произвести преобразование из строки в число.

Console.Write(“ Введите значение а ”); 

// чтение строки и  преобразование ее в целое число 

a = int.Parse(Console.ReadLine()); 

Далее собственно обмен значений. d  =  a;  //  сохраняем  значение  а  в  дополнительной 

переменной 

a = b; // помещаем в а значение b 

b = d; // помещаем в b значение из d 

Распространенная ошибка: a=b;  

b=a; 

Если бы мы не использовали дополнительную переменную, то при первом же присваивании потеряли значение переменной a. Приведем полностью решение этой задачи. Так как шаблон консольного приложения всегда одинаков, будем приводить код программы, начиная с метода Main.

 

Page 10: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

10

static void Main() 

        int   a, b, d; // описание целочисленных переменных 

// ввод данных 

      Console.Write(" Введите значение а "); 

      a = int.Parse(Console.ReadLine()); 

      Console.Write(" Введите значение b "); 

      b = int.Parse(Console.ReadLine()); 

// обмен значений 

      d = a; 

      a = b; 

      b = d; 

// вывод  значений a и b 

      Console.WriteLine(" a = { 0}, b = {1} ", a ,b); 

      Console.ReadKey(); 

Для решения следующего примера нам потребуется услов-ный оператор. Как известно, этот оператор используется для последующего выполнения или невыполнения некоторого оператора или группы операторов в зависимости от условия. Если предлагаемое условие истинно, то вложенный оператор или блок кода выполняется. Альтернативная ветвь, которая может присутствовать (а может и нет), выполнится, если условие ложно. Например, для определения максимального из двух различных чисел используется следующий оператор:

if ( a > b) 

{   // выполняется, если условие истинно 

  Console.WriteLine(“ Число a = {0} больше”, a); 

else  // выполняется, если условие ложно 

Console.WriteLine(“ Число b = {0} больше ”, b); 

Page 11: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

11

Пример 1.2. Даны целые числа a, b, c. Найти максимальное из этих трех чисел.

Обсудим решение этой задачи. Как и в первом примере, необходимо описать переменные целого типа для хранения зна-чений a, b, c и ввести их значения с клавиатуры.

int   a, b, с; // описание целочисленных переменных 

// ввод данных 

Console.Write(" Введите значение а "); 

// чтение строки и  преобразование ее в целое число 

a = int.Parse(Console.ReadLine()); 

Ввод значений b и c аналогичен. Теперь основная логика. if (a >= b) 

     if  (a >=  c)     Console.WriteLine(" Максимальное  значение = 

{0}", a); 

     else   Console.WriteLine(" Максимальное значение = {0}", c); 

else 

{  // a < b 

      if  ( b  >=  c) Console.WriteLine(" Максимальное  значение = 

{0}", b); 

      else      Console.WriteLine("  Максимальное  значение  =  {0}", 

c); 

Каскад условий, вложенных друг в друга, можно упростить, если использовать логические операции. Логическое «И» в C# обозначается, как &&, логическое «ИЛИ» – как ||, логическое отрицание – как !. Приведем полный код решения этой задачи с использованием логических операций.

static void Main(string[] args) 

      int a, b, c;  

// ввод данных 

Page 12: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

12

Console.Write(" Введите значение а "); 

a = int.Parse(Console.ReadLine()); 

Console.Write(" Введите значение b "); 

b = int.Parse(Console.ReadLine()); 

Console.Write(" Введите значение с "); 

c = int.Parse(Console.ReadLine()); 

// поиск максимального из трех чисел 

if ((a >= b) && (a >= c)) 

Console.WriteLine(" Максимальное значение = {0}", a); 

else  

    {    if ((b >= a) && ( b >c)) 

Console.WriteLine(" Максимальное значение = {0}", b); 

         if ((c >= a) && (c >=b)) 

Console.WriteLine(" Максимальное значение = {0}", c); 

    } 

Console.ReadKey(); 

Для решения следующего примера познакомимся с син-таксисом оператора цикла. В C# существуют четыре вида операторов цикла. Циклы реализуются с помощью следующих зарезервированных слов: while , do while , for, foreach .

Рассмотрим каждый на примере. Заметим, что переменные, объявленные в цикле (в том числе в заголовке цикла for и foreach), не видны снаружи цикла.

Оператор цикла while. Пока истинно управляющее условие, выполняется оператор (или тело цикла). Пример: вычислим значение an, если дано целое a и натуральное n. Для простоты будем значения a и n задавать прямо в программе.

int     a = 17; byte   n = 6,  

  k=1; 

int  rez = 17; 

while ( k < n) 

Page 13: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

13

  rez = rez * a; 

  k++;     // увеличение k на единицу. Эквивалентно k=k+1 

Console.WriteLine(“ {0} в степени {1} равно {2} ”, a, n, rez); 

Оператор цикла do-while. В данном случае тело цикла выполняется до проверки условия.

int    a = 17; 

byte  n = 6,  

  k = 1; 

int  rez = 17; 

do { 

  rez = rez * a; 

  k++;     // увеличение k на единицу 

} while ( k < n); 

Console.WriteLine(“ {0} в степени {1} равно {2} ”, a, n, rez); 

Оператор цикла for. Цикл for используют, как правило, когда число повторений известно заранее, т. е. в задачах, свя-занных с перебором. Мы устанавливаем начало отсчета, условие остановки и тип изменения параметра. Рассмотрим тот же пример с возведением числа a в степень n.

int     a = 17; 

byte   k,  n = 6; 

int  rez = 17; 

for( k=1; k< n; k++) 

  rez = rez * a; 

Console.WriteLine(“ {0} в степени {1} равно {2} ”, a, n, rez); 

В C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда необходимо перебрать все элементы массива или иной коллекции. Подробно мы рассмотрим его позже.

Теперь разберем пример с пошаговым вводом данных и выводом результата.

Page 14: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

14

Пример 1.3. Даны натуральное n и действительные числа a1, …, an. Все члены этой последовательности, начиная с первого положительного, уменьшить на 0,5.

Прежде всего опишем необходимые для работы переменные. byte          n;  //  натуральное  n –  число  членов 

последовательности 

double  a; // действительная переменная 

int count; // вспомогательная переменная – счетчик 

Далее стандартным способом получим значение n: Console.Write(" Введите значение n "); 

n = byte.Parse(Console.ReadLine()); 

Пользователь нашей программы может совершить ошибку и ввести нулевое значение n (если он введет отрицательное значение, то программа завершится с ошибкой, так как тип byte допускает числа от 0 до 255). Поэтому нам необходима проверка.

if (n == 0)    // проверка на равенство нулю 

Console.WriteLine(" значение n должно быть >0 "); 

return;   // завершение работы программы 

Теперь мы можем поочередно вводить члены последо-вательности ai и проверять их на положительность.

Console.Write(" Введите значение a "); 

 a = double.Parse(Console.ReadLine()); 

 count  =  1;        //  счетчик  введенных  членов 

последовательности 

while ((count <= n) && (a <= 0)) 

Console.Write(" Введите значение a "); 

a = double.Parse(Console.ReadLine()); 

count++; 

 } 

Page 15: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

15

Пока нам не встретится положительный член последо-вательности, мы будем продолжать вводить значения ai. Из этого цикла мы можем выйти либо если все n членов последо-вательности введены и все они оказались не положительными, либо если нам встретился положительный член последова-тельности. В последнем случае нам необходимо продолжить ввод и изменение членов последовательности.

if (a > 0) 

{  

a=a – 0.5; 

Console.WriteLine(" Измененное значение a = {0} ", a); 

while (count < n) 

Console.Write(" Введите значение a "); 

a = double.Parse(Console.ReadLine()); 

count++; 

a = a – 0.5; 

Console.WriteLine(" Измененное значение a = {0} ", a); 

Как и раньше, приведем полный код решения: static void Main() 

byte  n;    // число членов последовательности 

double a; // действительная переменная 

int count; // счетчик 

Console.Write(" Введите значение n "); 

n = byte.Parse(Console.ReadLine()); 

if (n == 0) 

Console.WriteLine(" значение n должно быть >0 "); 

return; 

Page 16: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

16

Console.Write(" Введите значение a "); 

a = double.Parse(Console.ReadLine()); 

count = 1; 

while ((count < n) && (a <= 0)) 

Console.Write(" Введите значение a "); 

a = double.Parse(Console.ReadLine()); 

count++; 

if (a > 0) 

{  

a=a – 0.5; 

Console.WriteLine(" Измененное значение a = {0} ", a); 

while (count < n) 

Console.Write(" Введите значение a "); 

a = double.Parse(Console.ReadLine()); 

count++; 

a = a – 0.5; 

Console.WriteLine(" Измененное значение a = {0} ", a); 

}  

Console.ReadKey(); 

Пример 1.4. Даны натуральное n и целые числа a1, …, an. Найти количество четных членов последовательности.

Для решения этого примера нам потребуются две вспомогательных целых переменных: счетчик введенных членов последовательности и счетчик четных членов последователь-ности. В цикле необходимо прочитать очередное значение a и проверить его на четность. Рассмотрим код этого примера:

Page 17: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

17

static void Main(string[] args) 

 { 

            byte n; // число членов последовательности 

            int a;    //  целочисленная переменная 

            int count, even_n; // счетчики 

 // ввод n и проверка на допустимость 

            Console.Write(" Введите значение n "); 

            n = byte.Parse(Console.ReadLine()); 

            if (n == 0) 

            { 

                Console.WriteLine(" значение n должно быть >0 "); 

                return; 

            } 

 //основной цикл. Ввод и проверка на честность 

            count =0;  // инициализация счетчиков 

            even_n =0; 

            while (count < n)  

            { 

                Console.Write(" Введите значение a "); 

                a = int.Parse(Console.ReadLine()); 

                if (a % 2 == 0) //если остаток от деления на 2 равен 0, 

                even_n++;//то увеличиваем счетчик четных чисел 

                 count++; 

            }        

           Console.WriteLine("  Количество  четных  чисел  =  {0}  ", 

even_n); 

           Console.ReadKey(); 

Пример 1.5. Даны целые числа a1,a2 … Известно, что a1>0 и что среди a2, a3, … есть хотя бы одно отрицательное число. Пусть a1, a2, …, an – члены данной последовательности,

Page 18: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

18

предшествующие первому отрицательному числу (n заранее неизвестно). Найти min( a1+ a2, a2+a3, …, an-1 + an). 

Согласно условию нашей задачи ввод чисел надо произ-водить до первого отрицательного числа. Для поиска минимума нам потребуются три переменных, две из которых будут соответ-ствовать настоящему и предыдущему члену последовательности ai, а третья – текущему значению минимума.

static void Main(string[] args) 

int pred; // предыдущий член последовательности 

int a;      // текущий член последовательности 

int min;  // минимум 

// ввод первых двух членов последовательности  

Console.Write(" Введите значение а "); 

pred = int.Parse(Console.ReadLine()); 

Console.Write(" Введите значение а "); 

a = int.Parse(Console.ReadLine()); 

//если а2<0, то выход  

if (a < 0) 

Console.WriteLine(" значение минимума ={0} ", pred); 

return; 

min = pred + a; //инициализация минимума 

pred = a; 

// ввод третьего члена последовательности 

Console.Write(" Введите значение а "); 

a = int.Parse(Console.ReadLine()); 

//основной цикл. Пока не встретим отрицательное а 

while ( a >= 0)  

if ((a +pred) < min) //если меньше тек. зн‐я минимума, 

Page 19: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

19

min = a+pred;  // то переприсваиваем 

pred = a; 

Console.Write(" Введите значение a "); 

a = int.Parse(Console.ReadLine()); 

Console.WriteLine(" значение минимума = {0} ", min); 

Console.ReadKey(); 

Задания для лабораторной работы № 1 1. Треугольник задан координатами своих вершин. Найти

площадь и периметр треугольника. 2. Дано действительное число а. Вычислить f(a), если

f(x) = 0 при 0 при 0 1

в остальных случаях.

3. Даны натуральное число n, действительные числа a1, …, an.

Вычислить: а) a1- a2+ a3- …+(-1)n+1 an; b) 2(a1 + .. + an)

2; c) sin| a1+ ..+ an|. 4. Даны натуральное число n, целые числа p, q, a1, …,

an( p > q ≥0). В последовательности a1, …, an заменить нулями члены, модуль которых при делении на p дает в остатке q.

5. Даны натуральное n, действительные числа a1, …, an. Получить min(a1

3, …, an3).

Page 20: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

20

Лабораторная работа № 2. Табулирование функции, заданной бесконечным рядом

Цель работы. Написать программу, которая выполняет вычисления с некоторой точностью. Дана функция, заданная бесконечным рядом. С клавиатуры вводятся x и e (е – точность 0.001–0.00001), нужно вычислить бесконечную сумму с заданной точностью e. Вычисления прекращаются, когда очередное слагаемое по модулю меньше точности. Требуется вывести на экран таблицу значений i и суммы i слагаемых.

Разберем эту задачу на примере функции:

1! 2

Нам потребуются следующие переменные: float x, e;           // для хранения входных данных 

double  slag, sum; // для  суммы и очередного слагаемого 

int i;                    // счетчик слагаемых 

Представим функцию в виде:

1!

12

.

Теперь слагаемое состоит из двух множителей. Заметим, что

для первого множителя для перехода от i к i+1 необходимо умножить числитель на –x, а знаменатель на (i+ 1). Это замечание позволит нам отказаться от вложенного цикла для вычисления степени и факториала. Приведем код программы целиком.

static void Main() 

float x = 1; // аргумент функции 

float e;   // точность 

double slag, sum; // для  суммы и очередного слагаемого 

int i;  // счетчик слагаемых 

Page 21: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

21

// ввод исходных данных 

Console.WriteLine("x="); 

x = float.Parse(Console.ReadLine()); 

Console.WriteLine("e="); 

e = float.Parse(Console.ReadLine()); 

// вычисление первого слагаемого  

i = 1;  

slag = 1; 

sum = 1 / 3; 

// вывод на печать заголовка таблицы 

Console.WriteLine(" i          slag         sum "); 

Console.WriteLine(" {0}    {1}   {2}", i, slag, sum); 

// цикл, пока слагаемое по модулю больше точности 

while (Math.Abs(slag/(i+2)) > e) 

i++; 

slag = slag* (‐1) * x  / i; // очередное слагаемое 

sum = sum + slag / (i + 2);  

Console.WriteLine(" {0}    {1}   {2}", i, slag, sum); 

// задержка экрана до нажатия клавиши Enter 

Console.ReadLine(); 

Как проверить, правильно ли работает программа? Протес-тировать ее, то есть задать входные данные и посмотреть, соот-ветствуют ли выходные данные вычисленным вручную. Конечно, выполнять на листке бумаги сложные вычисления довольно затруднительно. Выходом из этой ситуации является подбор входных данных. Для разобранной выше задачи значение x= 1 или x = -1 и e = 0,1 позволит легко проверить программу на корректность.

Page 22: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

22

Для выполнения вычислений нам потребовался модуль неко-торого числа. В C# для получения значения математической функции используется следующий синтаксис:

Math.Sin( x) – возвращает синус действительного x; Math.Exp( x) – возвращает ex; Math.Sqrt( x) – возвращает квадратный корень из x; Math.Pow( x, y) – возвращает xy. О других математических функциях можно посмотреть в

справочной системе.

Задания для лабораторной работы № 2

1. f(x) =

0

12

!)12(

)1(

i

ii

ii

x . 6. f(x) =

12

sin2

i

i

i

xxi

.

2. f(x) =

0

14

)14()!2(

)1(

i

ii

ii

x . 7. f(x) =

0

2

!2

)(

i

i

i

x .

3. f(x) =

0

121

)!12)(12(

)()1(

i

ii

ii

x . 8. f(x) =

02)1(

)1(

i

ii

ii

x .

4. f(x) = .!20

2

kk

k

k

x . 9. f(x) =

0

34

)34()!12(

)1(

i

ii

ii

x .

5. f(x) = .1||1

3

k xkk

x . 10. f(x) = )1(2

02

)2

())!1((

)1(

i

i

i x

i.

Лабораторная работа № 3. Вычисления с хранением последовательностей значений Цель работы. Решить задачу на обработку одномерного мас-

сива. Требуется ввести с клавиатуры размерность массива n, да-лее в цикле ввести элементы массива. Полученный ответ вывести на экран.

Типичным заданием лабораторной работы № 3 является сле-дующее.

Пример 3.1. Даны натуральное n, целые числа a1, …, an ( все числа попарно различны). Поменять в этой последовательности местами наибольший и наименьший члены.

Page 23: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

23

В отличие от лабораторной работы № 1 введенные числа нам придется где-то хранить, так как при первом просмотре после-довательности мы можем найти минимум и максимум, а об-мен произвести нельзя, нужен второй просмотр, где и произойдет обмен значений. Для хранения однотипных данных используются массивы.

Массив – это множество однотипных элементов. Доступ к элементу массива осуществляется по индексу. В C# существует три вида массивов: одномерные, многомерные и вложенные массивы. Все их можно использовать в циклах foreach.

Одномерные массивы. При описании массива указывается базовый тип элементов, которые может содержать массив. На-пример,

int[] arr_name; 

double[] arr_name2; 

Здесь arr_name и arr_name2 – имена массивов. Массив мало объявить, его нужно ещё определить, то есть задать количество элементов. Только тогда соответствующее множество однотип-ных объектов будет размещено в памяти. Массив можно опреде-лить сразу же после описания, а можно в любом другом месте программы, до первого обращения к элементам массива. Напри-мер:      arr_name= new int[10];//определение ранее описанного массива 

     byte [] m = new byte[20];//одновременное определение и описание 

     int  n =100; 

     float [] vect = new float [n]; // n должно быть определено!

Нумерация элементов массивов, так же, как в языке С/C++, начинается с нуля. Поэтому первый элемент доступен через следующее обращение – arr_name[0], последний – arr_name[9].

Теперь рассмотрим, как мы можем заполнить массивы зна-чениями, а именно – два способа заполнения. Первый способ – перебор в цикле всех элементов массива и присвоение им значе-ний (через ввод с клавиатуры или путем вычисления по неко-торой формуле): 

int n = 10; 

int[] arr_name = new int[n]; 

Page 24: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

24

for (int i = 0; i < n; i++) 

Console.Write(" arr_name[ {0} ] = ", i); 

arr_name[i] = int.Parse(Console.ReadLine()); 

Второй способ – задание элементов массива сразу при описании:

int [] arr_name = new int[] {1, 2, 3, 4, 5}; // или так 

int [] arr_name = {1, 2, 3, 4, 5}; 

У массива есть свойство Length, которое содержит общее число элементов массива, что, кстати, очень удобно. Например, для поиска максимального элемента в массиве можно исполь-зовать следующий цикл:

max = arr_name[0]; 

k = 1; 

while( k < arr_name.Length) 

if( arr_name[k] > max ) 

max = arr_name[k]; 

k++; 

Многомерные массивы. При описании массива указывается базовый тип элементов, которые может содержать массив, и количество измерений массива. Например, для двумерного массива размерностью 4 x 2:

int[,] arr_name_1 = new int[4,2];  

int[,] arr_name_2 = {{0, 1, 2, 3}, {0, 1, 2, 3}}; //здесь размер 2 х 4    

for(i = 0; i < arr_name_2.GetLength(0); i++) { 

for (j = 0; j < arr_name_2.GetLength(1); j++) { 

Console.WriteLine(arr_name_1[i,j]); } 

Page 25: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

25

В данном коде мы рассмотрели пример вывода значений из двумерного массива. Подробнее использование многомерных массивов будет рассматриваться ниже. 

Приведем решение примера 3.1. Понятно, что сначала мы должны описать размерность массива, сам массив, переменные для хранения максимального и минимального элемента, затем заполнить массив значениями, найти в массиве максимум и минимум и, наконец, поменять эти значения местами.

static void Main(string[] args) 

{ // Дано натуральное n, целые числа a1, …, an ( все числа попарно  //  различны).  Поменять  в  этой  последовательности  местами  // наибольший и  наименьший члены.    

byte n;            // размерность массива int[] a;             // исходный массив int max, min; // минимальный и максимальный элементы byte i, nom_min, nom_max; // индексы   // ввод данных Console.WriteLine(" n ="); n = byte.Parse(Console.ReadLine()); if (n == 0)      return; a = new int[n]; // определение массива for (i = 0; i < n; i++) { 

Console.Write(" a[ {0} ] = ", i); a[i] = int.Parse(Console.ReadLine()); 

} // поиск наибольшего и наименьшего элементов min = a[0]; nom_min = 0; max = a[0]; nom_max = 0; for (i = 1; i < n; i++) { 

if (a[i] < min) { 

min = a[i]; 

Page 26: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

26

nom_min = i; } if (a[i] > max) { 

max = a[i]; nom_max = i; 

} } // обмен значений a[nom_min] = max; a[nom_max] = min; // вывод результата for (i = 0; i < n; i++) 

Console.WriteLine(" a[ {0} ] =  {1}", i, a[i]); Console.ReadKey(); } 

Часто массив заполняют случайными числами. В C# встроен генератор случайных чисел. Покажем, как его использовать. Сначала необходимо создать новый экземпляр класса Random:

Random rnd = new Random(); Теперь для того, чтобы получить случайное число,

достаточно использовать созданный экземпляр класса, вызывая метод Next(), например:

a[i] = rnd.Next(); При желании можно генерировать число в заданном диапа-

зоне, указав начальное и конечное значение: a[i] = rnd.Next( 1, 100); 

Заметим, что функция rnd возвращает значение с типом int, и, если нам нужно значение другого типа, необходимо сообщить компилятору о пребразовании явным образом:

uint  some_value  = (uint)rnd.Next( 0, 20); 

Применим генерацию случайных чисел для заполнения массива в следующем примере.

Пример 3.2. Даны целые числа a1, …, a50 – количество осадков в миллиметрах, выпавших в Ярославле за последние

Page 27: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

27

50 лет. Надо вычислить среднее количество осадков и откло-нение от среднего для каждого года.

Разберем общий ход решения этой задачи. Первый шаг – это объявление необходимых переменных. Нам потребуется массив для хранения количества осадков, переменные для хранения среднего значения и отклонения и переменная индекс для просмотра элементов массива.

Второй шаг – заполнение массива случайными числами. И одновременно подсчет общей суммы осадков за 50 лет. Третий шаг – вычисление среднего количества осадков. И, наконец, четвертый шаг – просмотр в цикле элементов массива, вычис-ление отклонения и вывод на печать. Теперь приведем код этой задачи.

static void Main(string[] args) 

uint[] osadki = new uint[50]; // массив осадков 

double sr_zn = 0,  // среднее значение 

otkl =0;     // отклонение 

byte i;       // параметр цикла 

// активация генератора случ. чисел 

Random rnd = new Random(); 

// заполнение массива осадков 

for (i = 0; i < 50; i++) 

osadki[i] = (uint) rnd.Next(50, 200); 

sr_zn += osadki[i]; 

// вычисление среднего значения 

sr_zn = sr_zn / 50; 

Console.WriteLine(" Среднее значение = {0}", sr_zn); 

// подсчет отклонения и вывод результатов 

Console.WriteLine(" Значение    Отклонение"); 

for (i = 0; i < 50; i++) 

Page 28: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

28

otkl = osadki[i] – sr_zn; 

Console.WriteLine(" {0} \t   {1}", osadki[i], otkl); 

Console.ReadLine(); 

Рассмотрим более сложную задачу. Пример 3.3. Даны два массива x[1] ≤ x[2] ≤ …≤ x[k] и y[1] ≤

y[2]≤ … ≤ y[n]. Соединить их в массив z[1]≤ … ≤ z[m] (m = k+n), каждый элемент должен входить в массив z столько раз, сколько раз он входит в общей сложности в массивы x и y). Число действий в программе порядка m.

Идею решения можно пояснить следующим образом: пусть у нас есть две стопки карточек с числами, отсортированные по возрастанию (точнее, по неубыванию). Мы соединяем их в одну стопку, выбирая каждый раз ту из верхних карточек обеих стопок, чье число меньше. Если в одной стопке карточки закончились, то просто берем их из другой стопки.

static void Main(string[] args) 

            byte  n, m, k;  // размерности массивов 

            int[] x,y,z;       // исходные и результирующий массивы 

            byte  i, j;        // индексы 

   // ввод  массива x  

            Console.Write(" k ="); 

            k = byte.Parse(Console.ReadLine()); 

            if (k == 0)       return; 

            x = new int[k];  

            for (i = 0; i < k; i++) 

            { 

                Console.Write(" x[ {0} ] = ", i); 

                x[i] = int.Parse(Console.ReadLine()); 

            } 

Page 29: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

29

   // ввод массива у 

            Console.Write(" n ="); 

            n = byte.Parse(Console.ReadLine()); 

            if (n == 0)      return; 

            y = new int[n];  

            for (i = 0; i < n; i++) 

            { 

                Console.Write(" y[ {0} ] = ", i); 

                y[i] = int.Parse(Console.ReadLine()); 

            } 

            m = (byte)(n + k); 

            z = new int[m];   // определение массива z 

  //  основной цикл 

            i = 0; j = 0; 

            while ((i != k) || (j != n)) 

            { 

                if (i == k )       // j < n‐1, массив x переписан в z 

                { 

                    z[i + j] = y[j]; 

                    j++; 

                } 

                else if (j == n )     //i < k‐1, массив y уже в z 

                    { 

                        z[i + j] = x[i]; 

                        i++; 

                    } 

                    else if (x[i] <= y[j]) 

                        { 

                            z[i + j] = x[i]; 

                            i++; 

                        } 

Page 30: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

30

                        else if (x[i] >= y[j]) 

                                { 

                                    z[i + j] = y[j]; 

                                    j++; 

                                } 

            } 

            // вывод результата 

            for (i = 0; i < m; i++) 

                Console.WriteLine(" z[ {0} ] =  {1}", i, z[i]); 

            Console.ReadKey(); 

Задания для лабораторной работы № 3 1. Даны натуральные n, m, целые числа a1, …, an и b1, …, bm.

Внутри каждой из данных последовательностей нет повторяю-щихся членов. Построить пересечение данных последова-тельностей.

2. Даны натуральные n, m, целые числа a1, …, an и b1, …, bm. Внутри каждой из данных последовательностей нет повторяю-щихся членов. Получить все члены последовательности a1, …, an, которые не входят в последовательность b1, …, bm.

3. Даны массив x[1] ≤ x[2] ≤ …≤ x[n] целых чисел и число y. Выяснить, содержится ли y в этом массиве, то есть существует ли x[i] = y, i из 1..n. Число действий в программе порядка log n.

4. Даны массив x[1…n] целых чисел и число y. Переставить числа в массиве таким образом, чтобы слева от некоторой грани-цы стояли числа, меньшие или равные y, а справа – большие или равные y.

5. Даны натуральное n, целые числа a1, …, an. Если в данной последовательности ни одно четное число не расположено после нечетного, то вывести на экран все отрицательные члены после-довательности в обратном порядке, иначе – все положительные.

Page 31: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

31

Лабораторная работа № 4. Обработка последовательностей символов

Цель работы. Решить задачу на обработку текста, используя функции работы со строками. Всюду ниже, если это не оговорено особо, предполагается, что исходным является текстовый файл. В текст могут входить слова из латинских букв, цифры, знаки арифметических операций, точка, запятая, пробел. Требуется счи-тать текст из файла, вывести его на экран, после решения задачи вывести на экран результат.

Для обработки текста нам потребуются три типа данных: char (символ), string (строка), stringbuilder (тоже строка). Рассмотрим каждый из них поподробнее.

Тип Char. Прежде всего приведем пример описания и при-своения значения переменной этого типа:

char chA = 'A'; 

  char ch1 = '1'; 

Переменные типа char можно сравнивать и с помощью встро-енных методов определять их вид, а именно:

Console.WriteLine(chA.CompareTo('B'));     // Output: "‐1"  

// что означает, что  'A'  на единицу меньше, чем  'B' 

Console.WriteLine(Char.IsControl('\t'));           // Output: "True" 

Console.WriteLine(Char.IsDigit(ch1));               // Output: "True" 

Console.WriteLine(Char.IsNumber(ch1));       // Output: "True" 

Console.WriteLine(Char.IsPunctuation('.'));   // Output: "True" 

Методы IsControl, IsDigit, IsLetter, IsLetterOrDigit, IsLower, IsNumber, IsPunctuation, IsSeparator, IsSymbol, IsUpper и IsWhiteSpace служат для определения того, принадлежит ли символ к определенной категории Юникода, такой как цифра, буква, знак препинания, управляющий символ и т. д. Метод GetNumericValue служит для преобразования объекта Char, пред-ставляющего число, к числовому типу значения.

Тип string. Значением переменной типа string является либо текст, либо NULL, что означает неопределенное значение.

 // Объявление строки без инициализации 

Page 32: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

32

string message1; 

// Инициализация неопределенным значением. 

string message2 = null; 

// Строка объявлена как пустая 

string message3 = String.Empty; 

// Строка инициализирована конкретной фразой. 

string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0"; 

// причем символ \ удваивается для правильного прочтения 

Инициализация строки значением константы Empty приводит к созданию нового объекта String, строка которого имеет нуле-вую длину. Пустые строки часто используются в различных сценариях программирования, для них можно вызывать любые методы. Для строк со значениями null любая попытка вызвать метод приведет к ошибке. Однако такие строки можно исполь-зовать в операциях объединения и сравнения с другими стро-ками, что проиллюстрировано следующими примерами:

    string str = "hello"; 

    string nullStr = null; 

    string emptyStr = string.Empty; 

 

    string tempStr = str + nullStr;      // tempStr = "hello" 

    bool b = (emptyStr == nullStr);    // b = false; 

    // creates a new empty string 

   //string newStr = emptyStr + nullStr;  

    int len = nullStr.Length; // throws NullReferenceException 

Строковые объекты являются неизменяемыми: после созда-ния их нельзя изменить. Все методы String и операторы C#, которые, как можно было бы представить, изменяют строку, в действительности возвращают результаты в новый строковый объект. В следующем примере, когда содержимое строк s1 и s2 объединяется в одну строку, две исходные строки не изменяются. Оператор += создает новую строку с объединенным содер-жимым. Этот новый объект присваивается переменной s1, а исходный объект, который был присвоен строке s1, освобож-

Page 33: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

33

дается для сборки мусора, поскольку ни одна переменная не содержит ссылку на него.

string s1 = "A string is more "; 

string s2 = "than the sum of its chars."; 

// Слияние s1 и s2. Это, в действительности, создает новую строку 

// и помещает ссылку на нее в s1, предыдущая ссылка теряется  

s1 += s2; 

Console.WriteLine(s1); 

// Output: A string is more than the sum of its chars. 

Поскольку «изменение» строки в действительности является созданием новой строки, необходима осторожность при создании ссылок на строки. Если создать ссылку на строку, а затем «изменить» исходную строку, то ссылка будет по-прежнему указывать на исходный объект, а не на новый объект, который был создан при изменении строки. Это поведение демонстри-руется в следующем коде.

string s1 = "Hello "; 

string s2 = s1; 

s1 += "World"; 

Console.WriteLine(s2);  //Output: Hello 

Подстроки. Подстрокой является последовательность симво-лов, содержащихся в строке. Метод Substring используется для создания новой строки на основании части исходной строки. Одно или несколько вхождений подстроки можно найти с использованием метода IndexOf. Метод Replace используется для замены всех вхождений заданной подстроки новой строкой. Так же, как и метод Substring, метод Replace фактически возвращает новую строку и не изменяет исходную строку.

string s3 = "Visual C# Express"; 

System.Console.WriteLine(s3.Substring(7, 2)); 

// Output: "C#" 

System.Console.WriteLine(s3.Replace("C#", "Basic")); 

// Output: "Visual Basic Express" 

// Нумерация символов в строке начинается с нуля 

Page 34: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

34

int index = s3.IndexOf("C");  // index = 7 

Доступ к отдельным символам в строке. Для получения доступа только для чтения к каждому символу по отдельности в строке можно использовать нотацию аналогичную массивам, как показано в следующем примере:

string s5 = "Printing backwards"; 

for (int i = 0; i < s5.Length; i++) 

    System.Console.Write(s5[s5.Length – i – 1]); 

}     // Output: "sdrawkcab gnitnirP" 

Тип StringBuilder. Операции со строками в .NET в высокой степени оптимизированы и в большинстве случаев значительно не снижают производительность. Однако в некоторых случаях, напри-мер в непрерывных циклах, выполняющихся сотни и тысячи раз, операции со строками могут влиять на производительность. Класс StringBuilder создает строковый буфер, который позволяет по-высить производительность, если в программе обрабатывается много строк. Этот тип также позволяет заново присваивать отдель-ные знаки, что не поддерживается типом string. Например, данный код заменяет содержимое строки без создания новой строки:

StringBuilder sb = new StringBuilder("Rat: the ideal pet"); 

sb[0] = 'C'; 

Console.WriteLine(sb.ToString());   //Outputs Cat: the ideal pet 

В этом примере объект StringBuilder используется для созда-ния строки из набора числовых типов:

 static void Main() 

        StringBuilder sb = new StringBuilder(); 

// Создание строки, состоящей из цифр 0 – 9 

        for (int i = 0; i < 10; i++) 

        { 

            sb.Append(i.ToString()); 

        } 

        Console.WriteLine(sb);  // displays 0123456789 

Page 35: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

35

// Копирование одного символа  (невозможно для типа String) 

        sb[0] = sb[9]; 

        Console.WriteLine(sb);  // displays 9123456789 

    } 

Пример 4.1. Дан текст, состоящий из английских букв, цифр и символов. Надо вывести на печать такие последовательности букв и цифр, где на втором месте стоит буква 'd'. Посчитать их количество. Например, для текста, состоящего из двух строк: 1der, 6789, gdq34 +09 -dad....

tyda ne00xodi 90 su 6da idi! ответом будет: kolvo= 4 1der gdq34 6da idi! Ввод данных (текста) в этой лабораторной работе будет

производиться из файла. Для этого необходимо 1) подключить библиотеку ввода-вывода: using System.IO; 2) создать объект- читатель файла: StreamReader MyFile = new StreamReader("text.txt"); здесь MyFile – имя переменной, закрепленной за файлом

text.txt. После этого методом ReadLine() мы можем читать из входного файла строки.

Обсудим общую схему решения данной задачи. Для вывода результата нам нужна переменная-счетчик, в которой будет хра-ниться число искомых последовательностей (int counter) и строка (StringBuilder otvet), в которую мы будем заносить сами искомые последовательности. После прочтения строки из входного файла необходимо разбить ее на «слова», состоящие из букв и цифр. Границей слова будет пробел, знак препинания или арифме-тической операции. Это разбиение можно сделать вручную, посимвольно рассматривая содержимое строки, а можно восполь-зоваться методом Split, на входе которого массив символов-разделителей, а на выходе – массив слов. Нам останется лишь проверить в цикле все элементы этого массива на наличие буквы «d» на втором месте и при выполнении условия добавить к счетчику единицу, а это слово в строку-ответ.

 

Page 36: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

36

static void Main(string[] args) {             int counter = 0; // счетчик слов, где d стоит на 2м месте             string line;         // вспомогательная строка             char[] separator = { ' ', '.', '*', '+', ';', ',', '?', '!', '‐', '/' };              StringBuilder otvet = new StringBuilder();  // строка‐ответ  using (StreamReader MyFile = new StreamReader("text.txt"))             { // чтение строки из файла, пока это возможно                 while ((line = MyFile.ReadLine()) != null)                 {                     Console.WriteLine(line);  // печатаем, что прочитали // выделяем слова                     string[] words = line.Split(separator);                     foreach (string slovo in words) // цикл по словам                     {                         if ((slovo.Length >= 2) && (slovo[1] == 'd'))                         {                             counter++;                              otvet.Append(slovo);                             otvet.Append("  ");                         }                     }                 }             }             Console.WriteLine("There were {0} sequences.", counter);             Console.WriteLine(otvet.ToString());             Console.ReadLine(); } 

Пример 4.2. Дан текст. Найти наибольшее количество цифр, идущих в нем подряд.

Наиболее простой способ решения этой задачи состоит в следующем: будем посимвольно просматривать каждую прочи-

Page 37: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

37

танную строчку и, если встретилась группа цифр, сравнивать ее длину с максимальной на данный момент.

static void Main() 

      byte counter = 0, // счетчик текущей группы цифр 

                  max =0;     // длина максимальной группы цифр 

      string stroka; 

      int i; 

      using (StreamReader MyFile = new StreamReader("test.txt")) 

      { 

// пока файл не пуст, читаем строку 

              while ((stroka = MyFile.ReadLine()) != null) 

                { 

                    Console.WriteLine(stroka);   

                    i=0; // индекс символа в строке 

                    while( i < stroka.Length) 

                    { 

 // цикл, пока не встретится цифра или конец строки 

                        while( (i< stroka.Length)&& !(char.IsDigit(stroka,i))) 

                        { 

                            i++; 

                        } 

 // встретилась цифра или строка закончилась 

                        counter = 0;  

 // цикл пока очередной символ – цифра 

                        while( (i< stroka.Length)&& (char.IsDigit(stroka,i))) 

                        { 

                            counter ++;  

                            i++; 

                        } 

 // изменяем максимальную длину, если необходимо 

Page 38: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

38

                        if( counter > max ) 

                            max = counter; 

                    } 

                } 

            } 

Console.WriteLine("Длина максим. посл‐ти цифр = {0}.", max); 

Console.ReadLine(); 

}  

Следует отметить, что существует несколько различных алгоритмов решения этой задачи (да и почти любой другой). Так, можно было занести в массив разделителей все допустимые в тексте символы, кроме цифр, и воспользоваться методом Split для выделения всех «слов», состоящих из цифр. Затем просто найти максимальную длину «слова».

Проверкой правильности реализованного алгоритма является тестирование программы. Причем для каждой задачи состав-ляется набор тестов, проверяющих все возможные варианты данных. Например, для примера 4.2, целесообразно сформиро-вать следующий набор тестов:

– в тексте нет ни одной группы цифр (ответ – 0); – несколько групп цифр, причем максимальная находится в

начале строки (12345, вышел зайчик погулять 12 5, ответ – 5); – несколько групп цифр, но максимальная находится в конце

строки;( 1–2, 3–4, 3–4, 12, ответ – 2) – текст состоит из нескольких строк с группами цифр в

хаотичном порядке. Каждый тестовый пример записывается в отдельный файл

(например, test1.txt, … test4.txt), и работа программы проверяется на каждом тесте. Если обнаружена ошибка, то после ее исправления тестирование начинается опять с первого теста.

Пример 4.3. Дан текст, каждый символ которого может быть латинской буквой, цифрой или одним из знаков арифметических операций. Группой букв будем называть такую совокупность последовательно расположенных букв, которой непосредственно не предшествует и за которой непосред-ственно не следует буква. Аналогично определяется группа цифр

Page 39: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

39

и группа знаков. Выяснить, верно ли, что в данном тексте болше групп букв, чем групп цифр.

Алгоритм решения этой задачи состоит в следующем: заве-дем два счетчика для групп букв и цифр соответственно, затем в каждой прочитанной строке будем выделять группы букв и цифр и увеличивать значения соответствующих счетчиков.

 static void Main(string[] args) 

        byte dcounter = 0,  // счетчик груп цифр 

                 wcounter= 0;  // счетчик групп букв 

        string stroka; 

        int i; 

     using (StreamReader MyFile = new StreamReader("test.txt")) 

        { 

 // пока файл не пуст, читаем строку 

            while ((stroka = MyFile.ReadLine()) != null) 

            { 

                Console.WriteLine(stroka);   

                i = 0; // индекс символа в строке 

                while (i < stroka.Length) 

                { 

// цикл, пока не встретится цифра или буква или конец строки 

          while ((i < stroka.Length) && !(char.IsLetterOrDigit(stroka, i))) 

                  { 

                            i++; 

                   } 

   // встретилась цифра и строка не закончилась 

                   if ((i < stroka.Length) && (char.IsDigit(stroka, i))) 

                                dcounter++; 

    // цикл пока очередной символ – цифра 

                   while ((i < stroka.Length) && (char.IsDigit(stroka, i))) 

                    { 

Page 40: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

40

                            i++; 

                     } 

     // встретилась буква и строка не закончилась 

                    if ((i < stroka.Length) && (char.IsLetter(stroka, i))) 

                              wcounter++; 

      // цикл пока очередной символ – буква 

                    while ((i < stroka.Length) && (char.IsLetter(stroka, i))) 

                     { 

                            i++; 

                      } 

                 } 

            } 

       } 

// сравнение счетчиков и вывод результата 

       if (wcounter > dcounter) 

       { 

       Console.Write("Групп букв больше: "); 

Console.WriteLine("{0}>{1}", wcounter, dcounter); 

       } 

       else if (dcounter > wcounter) 

       { 

                  Console.Write(" Групп цифр больше: "); 

        Console.WriteLine(" {0}>{1}.", dcounter, wcounter); 

       }   

                else  

        { 

Console.Write(" Групп цифр и букв равное кол‐во: ");  

Console.WriteLine(" {0} = {1}.", wcounter, dcounter);  

        } 

            Console.ReadLine(); 

Page 41: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

41

Задания для лабораторной работы № 4 Исходным является текстовый файл. В текст могут входить

слова из латинских букв, цифры, знаки арифметических опера-ций, точка, запятая, пробел. Требуется считать текст из файла, вывести его на экран, после решения задачи вывести на экран результат. Группой букв будем называть такую совокупность последовательно расположенных букв, которой непосредственно не предшествует и за которой непосредственно не следует буква. Аналогично определяется группа цифр и группа знаков.

1. Найти число тех групп букв, которые заканчиваются той же буквой, что и первая группа букв.

2. Если в данном тексте есть группа знаков, начинающаяся знаком «*», то в следующей по порядку группе знаков (если она существует) заменить каждый из знаков нулем.

3. Вывести на экран те слова, которые отличны от последнего слова текста и все буквы этого слова различны.

4. Если в тексте нет символа «+», то оставить текст без изменения, иначе каждую из цифр, предшествующую первому вхождению знака «+», заменить на «*».

5. Вывести на экран текст, составленный из последних букв всех групп букв данного файла.

6. Выяснить, встречается ли в данном тексте группа букв «one».

7. Вывести на экран текст, составленный из последних букв всех слов (групп букв) данного файла.

Лабораторная работа № 5 Графические построения

при решении геометрических задач

Цель работы. Решить задачу, применяя методы аналитичес-кой геометрии, и отобразить решение графически на экране. Исходные данные прочитать из текстового файла.

Выполнение этой лабораторной работы состоит из двух этапов: первый – решение геометрической задачи и второй –

Page 42: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

42

отображение решения графически. Одновременное программиро-вание обеих частей задачи, как правило, приводит к большему числу ошибок.

Пример 5.1. Дана прямая, проходящая через точки (0, y1 ) и (x2, y2). Даны n квадратов со сторонами параллельными осям координат. Найти число квадратов, имеющих общую точку с прямой.

Для хранения исходных данных нам потребуются: 1) целочисленные переменные для координат точек, задаю-

щих прямую (int x1=0, y1, x2, y2;) и действительные переменные для коэффициентов прямой (float a, b,c;);

2) некоторая структура данных для хранения квадратов. Квадрат задается кординатами (x, y) четырех своих вершин. Удобно будет использовать двумерные массивы для хранения x и y координат соответственно для каждого квадрата (int[,] kvx, kvy;).

Кроме того, нам потребуется индексная переменная для пере-бора квадратов (int i;), целочисленная переменная-счетчик для хранения результата (int sq_counter;).

Алгоритм решения данной задачи основан на том факте, что прямая ax+ by+ c =0 делит плоскость на две полуплоскости, в одной из которых ax+ by+ c >0 для всех точек полуплоскости, а в другой ax+ by + c <0. Если для всех вершин квадрата выпол-няется одно из этих неравенств, то квадрат лежит в одной полу-плоскости и точек пересечения с прямой не имеет, в противном случае – имеет.

static void Main() 

int[,] kvx, kvy; // двумерные массивы координат квадрата 

int i = 0;        // индексная переменная 

string line;   // строка   

char[] delimiterChars = {' ', ',','\t' }; // символы‐разделители 

int sq_counter = 0; // кол‐во квадратов, пересек. прямую 

kvy = new int[10,4];  

kvx = new int[10,4]; 

Page 43: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

43

int x1=0, y1, x2, y2; // координаты точек 

float a, b, c;              // коэффициенты прямой  

// ввод данных 

using (StreamReader file = new StreamReader("test.txt")) 

line = file.ReadLine(); // чтение строки из файла 

// разбиваем строку на подстроки‐ числа 

string[] numbers = line.Split(delimiterChars); 

// выделение координат точек, через кот. проходит прямая 

y1= int.Parse(numbers[0]); 

x2= int.Parse(numbers[1]); 

y2 = int.Parse(numbers[2]); 

      // пока файл не пуст, читаем строки, для каждой пары строк   

     // в верхней строке – х‐координаты вершин квадрата 

     // в нижней – у‐координаты соответствующих вершин квадрата 

     // xfull – показывает, что верхнюю строку прочитали  

                bool xfull = false; 

                while ((line = file.ReadLine()) != null) 

                { 

                     Console.WriteLine(line); 

                    // выделяем числа 

                    numbers = line.Split(delimiterChars); 

                    //занесение в массив у‐координат iго квадрата 

                        if (xfull) 

                        {   kvy[i,0]= int.Parse(numbers[0]); 

                            kvy[i,1]= int.Parse(numbers[1]); 

                            kvy[i,2]= int.Parse(numbers[2]); 

                            kvy[i,3]= int.Parse(numbers[3]); 

                            xfull=false; i++; 

                        } 

 //занесение в массив х‐координат i‐го квадрата 

Page 44: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

44

                        else { 

                            kvx[i,0]= int.Parse(numbers[0]); 

                            kvx[i,1]= int.Parse(numbers[1]); 

                            kvx[i,2]= int.Parse(numbers[2]); 

                            kvx[i,3]= int.Parse(numbers[3]); 

                            xfull=true; 

                        } 

                 }                  

            }          

            int n = i; // количество квадратов 

            Console.WriteLine("Всего квадратов = {0}.", n); 

 // нахождение коэффициентов прямой  

            a = y2‐y1; 

            b=‐x2; 

            c=x2*y1; 

 // перебираем все квадраты и подставляем их координаты  

 //  в  уравнение  прямой.  Если  квадрат  лежит  в  одной 

 // полуплоскости, то счетчик увеличивается 

            float v1=0, v2=0, v3=0, v4=0; 

            for( i=0; i<n; i++) 

            { 

                v1=a*kvx[i,0]+b*kvy[i,0]+c; 

                v2=a*kvx[i,1]+b*kvy[i,1]+c; 

                v3=a*kvx[i,2]+b*kvy[i,2]+c; 

                v4=a*kvx[i,3]+b*kvy[i,3]+c; 

      if(((v1>0)&&(v2>0)&&(v3>0)&&(v4>0))|| 

                     ((v1<0)&&(v2<0)&&(v3<0)&&(v4<0))) 

                               sq_counter++; 

            } 

            sq_counter=n‐sq_counter; 

    Console.WriteLine("Количество квадратов ={0}", sq_counter); 

Page 45: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

45

            Console.ReadLine(); 

После тестирования первой части программы можно подклю-чать графику. Аналогом библиотеки OpenGL для .NET является Tao Framework. Это свободно распространяемая библиотека, с открытым исходным кодом, предназначенная для быстрой и удобной разработки кросс-платформенного мультимедийного программного обеспечения в среде .NET. Об установке этой библиотеки на компьютер можно прочитать в [7]. Рассмотрим, какие изменения нужно внести в код программы. Во-первых, указать, что мы будем использовать графические библиотеки:

using Tao.FreeGlut; 

using Tao.OpenGl; 

Во-вторых, установить на них ссылку. В окне Solution Explorer правой кнопкой мышки щелкнуть по пункту References и выбрать Add Reference. В появившемся окне выбрать две библиотеки Tao FreeGlut и Tao OpenGL, как показано на рисунке 4, и щелкнуть по кнопке ОК. Теперь можно пользоваться возможностями графических библиотек.

Page 46: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

П

следу//

   

//

//

 /

G

 /

   

//

   

   

После выующий к/Инициа

          Gl

/ для окн

/ регене

// RGB(кр

Glut.glutIn

// устано

         Glu

/ создан

         Glu

         Init

Рис. 4.

ывода сокусок кодализация

ut.glutIn

на изобр

рации д

расный з

nitDispla

овка разм

ut.glutIni

ие окна 

ut.glutCre

t(); // соб

Выбор б

ообщенида: я график

it(); 

ражения

для выбо

зеленый

ayMode(G

мера гра

tWindow

для выв

eateWin

бств. про

46

иблиотек

ия о ко

ки  

я будет и

ора цвето

й синий)

Glut.GLU

афическо

wSize(800

вода гра

dow(" Кв

оцедура

к для доба

оличеств

использо

овых зна

UT_SINGL

ого окна

0, 800);

фики с з

вадраты

а инициа

авления

е квадр

оваться о

ачений р

LE | Glut

а 

заголовк

ы и пряма

ализации

ратов вс

один буф

режим 

.GLUT_R

ком 

ая"); 

и 

тавим

фер  

RGB); 

Page 47: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

47

// посылает графическое изображение в созданное окно 

            Glut.glutDisplayFunc(new Glut.DisplayCallback(Display)); 

 // перерисовка изображения в цикле 

            Glut.glutMainLoop(); 

 // Задержка экрана 

            Console.ReadLine(); 

После метода Main разместим подпрограммы рисования и инициализации:

private static void Init() 

// задает белый цвет фона окна графики 

            Gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 

 // задает диапазон координат в окне 

            Glu.gluOrtho2D(‐15.0, (double)15, ‐15.0, (double)15); 

            Gl.glMatrixMode(Gl.GL_PROJECTION); 

 } 

 // подпрограмма рисования прямой по координатам точек 

 private static void DrawOneLine(int x1, int y1, int x2, int y2) 

 { 

           Gl.glBegin(Gl.GL_LINES); 

           Gl.glVertex2i(x1, y1); 

           Gl.glVertex2i(x2, y2); 

           Gl.glEnd(); 

 } 

//подпрограмма рисования квадрата по координатам вершин 

private static void DrawOneRectangle(int x1, int y1, int x2, int y2, 

int x3, int y3, int x4, int y4) 

         Gl.glBegin(Gl.GL_LINE_LOOP); 

         Gl.glVertex2f(x1, y1); 

         Gl.glVertex2f(x2, y2); 

Page 48: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

48

         Gl.glVertex2f(x3, y3); 

         Gl.glVertex2f(x4, y4); 

         Gl.glEnd(); 

  } 

 // подпрограмма, формирующая изображение на экране  

  private static void Display() 

  {         // очистка окна 

            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT); 

   // выбор черного цвета для рисования 

            Gl.glColor3f(0.0f, 0.0f, 0.0f); 

   // вызов процедуры рисования прямой 

            DrawOneLine(‐15, 0, 15, 0); // ось х 

            DrawOneLine(0, ‐15, 0, 15); // ось y 

   // исходная прямая 

           Gl.glColor3f(0.0f, 0.0f, 1.0f); 

           if (b != 0) 

           { 

                int y1 = (int)((‐1) * (a * (‐15) + c) / b); 

                int y2 = (int)((‐1) * (a * (15) + c) / b); 

                DrawOneLine(‐15, y1, 15, y2); 

            } 

else DrawOneLine((int)((‐1) * (c / a)), 15, (int)((‐1) * (c / a)), ‐15); 

  // рисование квадратов красным цветом 

         Gl.glColor3f(1.0f, 0.0f, 0.0f); 

         for (int i = 0; i < kvx.GetLength(0); i++) 

          { 

     DrawOneRectangle(kvx[i, 0], kvy[i, 0], kvx[i, 1], kvy[i, 1], 

               kvx[i, 2],  kvy[i, 2], kvx[i, 3], kvy[i, 3]); 

           } 

          

   Gl.glFlush(); 

Page 49: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

49

    } 

В подпрограммах рисования мы используем координаты вер-шин квадратов и коэффициенты прямой. Поэтому перенесем опи-сание этих переменных выше начала метода Main с атрибутом static: static int[,] kvx, kvy; // двумерные массивы координат квадрата 

static float a, b, c;   // коэффициенты прямой  

static void Main() 

       int i = 0;       // индексная переменная 

… } 

Пример 5.2. Окружность на плоскости может быть задана координатами x, y ее центра и радиусом r. Даны n окружностей с характеристиками x1, y1, r1, x2, y2,r2, … xn, yn, rn. Определить, имеются ли среди этих окружностей три попарно пересекаю-щиеся.

Обсудим алгоритм решения этой задачи. Две окружности пе-ресекаются, если расстояние между их центрами меньше или равно суммы их радиусов и больше или равно разности радиусов. Будем в цикле рассматривать все возможные тройки окруж-ностей. Как только пересекающиеся окружности будут найдены, запомним их номера и выйдем из цикла. В дальнейшем выведем на экран их изображение другим цветом.

static int[] x, y, r; // массивы характеристик окружностей 

static int p, q, s;   // номера искомых окружностей 

static void Main() 

int i = 0, j, k;    // индексные переменные 

string line;        // строка   

char[] delimiterChars = {' ', ',','\t' }; 

double d_ij, d_jk, d_ik; // расстояния между центрами 

 

y = new int[10];  // определение массивов 

Page 50: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

50

r = new int [10]; 

x = new int[10]; 

// ввод данных 

using (StreamReader file = new StreamReader("test.txt")) 

// пока файл не пуст, читаем строки 

while ((line = file.ReadLine()) != null) 

Console.WriteLine(line); 

// выделяем числа 

string[] numbers = line.Split(delimiterChars); 

//занесение в массивы координат i‐й окружности 

x[i]= int.Parse(numbers[0]); 

y[i]= int.Parse(numbers[1]); 

r[i]= int.Parse(numbers[2]); 

i++; 

int n = i; // количество окружностей 

Console.WriteLine("Всего окружностей = {0}.", n); 

// поиск попарно пересекающихся окружностей  

bool find = true;  // флаг неуспешного поиска 

for (i = 0; (i < n‐2) && find; i++) 

for (j = i + 1; (j < n – 1)&& find; j++) 

d_ij = Math.Sqrt((x[i]‐x[j])*(x[i]‐x[j])+(y[i]‐y[j])*(y[i]‐y[j])); 

if ((d_ij <= r[i] + r[j]) && (d_ij >= Math.Abs(r[i] – r[j]))) 

{ // если найдены две пересекающиеся окружности, 

// то в цикле ищем третью 

for(k=j+1; (k< n)&&find; k++) 

Page 51: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

51

             d_ik = Math.Sqrt((x[i]‐x[k])*(x[i]‐x[k])+(y[i]‐y[k])*(y[i]‐y[k])); 

if ((d_ik <= r[i] + r[k]) && (d_ik >= Math.Abs(r[i] – r[k]))) 

             d_jk=Math.Sqrt((x[k]‐x[j])*(x[k]‐x[j])+(y[k]‐y[j])*(y[k]‐y[j])); 

if ((d_jk <= r[j] + r[k]) && (d_jk >= Math.Abs(r[j] – r[k]))) 

{ // запоминаем номера найденных окружностей 

p = i; q = j; s = k;  

find = false;  // флаг = успеху 

} // к циклу по k 

} // к циклу по j 

} // к циклу по i 

if (p == q) 

Console.WriteLine("Таких окружностей нет"); 

else Console.WriteLine("Номера окружностей: {0}  {1}  {2}", p,q,s ); 

// инициализация библиотеки Glut 

Glut.glutInit(); 

Glut.glutInitDisplayMode(Glut.GLUT_SINGLE | Glut.GLUT_RGB); 

// задание размера и создание окна 

Glut.glutInitWindowSize(600, 600); 

Glut.glutCreateWindow("Окружности"); 

Init(); 

// отображение графики 

Glut.glutDisplayFunc(new Glut.DisplayCallback(Display)); 

Glut.glutMainLoop(); 

// задержка экрана  

Console.ReadLine(); 

Page 52: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

52

// процедура инициализации 

private static void Init() 

// задает белый цвет фона окна изображения 

Gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); 

Gl.glMatrixMode(Gl.GL_PROJECTION); 

Glu.gluOrtho2D(‐200.0, (double)200, ‐200.0, (double)200); 

// подпрограмма рисования прямой по координатам точек 

private static void DrawOneLine(int x1, int y1, int x2, int y2) 

Gl.glBegin(Gl.GL_LINES); 

Gl.glVertex2i(x1, y1); 

Gl.glVertex2i(x2, y2); 

Gl.glEnd(); 

// метод изображения точек в каждом из 8 октантов 

static void circlePlotPoints(int xc, int yc, int xt, int yt) 

Gl.glBegin(Gl.GL_POINTS); 

Gl.glVertex2i(xc + xt, yc + yt); 

Gl.glVertex2i(xc – xt, yc + yt); 

Gl.glVertex2i(xc + xt, yc – yt); 

Gl.glVertex2i(xc – xt, yc – yt); 

Gl.glVertex2i(xc + yt, yc + xt); 

Gl.glVertex2i(xc – yt, yc + xt); 

Gl.glVertex2i(xc + yt, yc – xt); 

Gl.glVertex2i(xc – yt, yc – xt); 

Gl.glEnd(); 

// метод рисования окружности "средней точки" 

Page 53: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

53

// на входе координаты центра и радиус 

static void circleMidpoint(int xc, int yc, int radius) 

int p = 1 – radius; // начальное значение параметра 

int xt = 0,   // нач. значения точки на окружности 

yt = radius; 

//рисуем в каждом квадранте первую точку 

circlePlotPoints(xc, yc, xt, yt); 

//цикл, вычисляющий положение очередной точки на окружности 

while (xt < yt) 

xt++; 

if (p < 0) 

p = p + 2 * xt + 1; 

else 

yt‐‐; 

p = p + 2 * (xt – yt) + 1; 

circlePlotPoints(xc, yc, xt, yt); 

// метод, формирующий изображение  

private static void Display() 

int i; 

// очистка окна изображения 

Gl.glClear(Gl.GL_COLOR_BUFFER_BIT); 

// выбор черного цвета для рисования 

Gl.glColor3f(0.0f, 0.0f, 0.0f); 

// вызов процедуры рисования прямой 

Page 54: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

54

DrawOneLine(‐200, 0, 200, 0); // ось х 

DrawOneLine(0, ‐200, 0, 200); // ось y 

// выбор красного цвета для рисования 

Gl.glColor3f(1.0f, 0.0f, 0.0f); 

// рисуем окружности 

for (i = 0; i < x.Length; i++) 

// вызов метода рисования окружности 

circleMidpoint(x[i], y[i],r[i]); 

// если есть пересекающиеся окружности, 

// то рисуем их синим цветом 

if ((p != q) && (p != s)) 

Gl.glColor3f(0.0f, 0.0f, 1.0f); 

circleMidpoint(x[p], y[p], r[p]); 

circleMidpoint(x[q], y[q], r[q]); 

circleMidpoint(x[s], y[s], r[s]); 

// метод, ускоряющий работу библиотеки OpenGL 

Gl.glFlush(); 

Задания для лабораторной работы № 5 1. Многоугольник на плоскости задается координатами своих

N вершин в порядке обхода их по контуру по часовой стрелке (контур самопересечений не имеет). Для заданной точки Z(x,y) определить, принадлежит ли она стороне многоугольника или ле-жит внутри или вне его.

2. Построить множество всех различных остроугольных треугольников с вершинами в заданном множестве точек на плоскости.

Page 55: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

55

3. На плоскости задано множество точек А и множество пря-мых B. Найти две такие различные точки из А, которые бы опре-деляли прямую, параллельную наибольшему количеству прямых из B.

4. Окружность на плоскости может быть задана координатами x, y ее центра и радиусом r. Даны n окружностей с характеристиками x1, y1, r1, x2, y2,r2, … xn, yn, rn. Найти среди этих окружностей все уединенные, то есть такие, которые не имеют общих точек ни с одной другой, не лежат целиком внутри и не содержат внутри себя никакую окружность.

5. Из заданного множества точек на плоскости выбрать две различные точки так, чтобы количество точек, лежащих по разные стороны прямой, проходящей через эти две точки, различались наименьшим образом.

6. Задано множество прямых на плоскости. Подсчитать коли-чество точек пересечения этих прямых.

Лабораторная работа № 6 Матричные задачи

Цель работы. Использование подпрограмм в задаче на обра-ботку двумерного массива.

Требуется вывести на экран меню, состоящее из следующих пунктов:

1) ввод матрицы с клавиатуры, 2) ввод матрицы из файла, 3) вычисление характеристики, 4) преобразование матрицы, 5) печать матрицы, 6) выход, и обеспечить его функционирование. Внутри программы характеристика оформляется в виде мето-

да с передачей параметров по значению, который возвращает значение булевского типа; преобразование в виде метода с пере-дачей параметров по ссылке. Необходимо отслеживать, был ли

Page 56: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

56

произведен ввод данных до выбора пунктов меню, которые обра-батывают матрицу.

Рассмотрим сокращенный вариант лабораторной работы № 6. Обеспечим функционирование меню, которое позволяет найти минимальный элемент матрицы и заменять побочную диагональ нулями. Каждое действие будет реализовано в виде подпро-граммы.

Для программной реализации меню удобно использовать оператор ветвления switch. Оператор ветвления может иметь большое количество альтернатив, выбор которых осуществляется с помощью значения управляющего выражения. Это очень удобный способ реализации кода, когда существует некий параметр, в зависимости от которого должны выполняться те или иные ветви кода. В C# он реализуется следующим образом:

switch ( value ) 

case 1 : {  Console.WriteLine("Цифра 1”); 

break; 

case 2 :  { Console.WriteLine("Цифра 2”); 

 break; 

}  

. . . 

default: {  Console.Write("для этого варианта действие”); 

Console.WriteLine(“ не определено”); 

break; 

Теперь разберемся с тем, как устроены подпрограммы или методы. Метод (подпрограмма) представляет собой блок кода, содержащий набор инструкций. Программа инициирует выпол-нение операторов, вызывая метод и задавая необходимые аргу-менты метода. В C# методы определяются в рамках объявления класса. Различают статические (со спецификатором static) и не-

Page 57: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

57

статические методы (объявляются без спецификатора). Не вда-ваясь в подробности ООП, заметим, что для наших целей нужны статические методы.

Определение метода задает имена и типы любых необхо-димых параметров. Параметры заключаются в круглые скобки и разделяются запятыми. Пустые скобки указывают на то, что у метода нет параметров. Когда код вызова вызывает метод, он предоставляет конкретные значения, называемые аргументами, для каждого параметра. Аргументы должны быть совместимыми с типом параметра, но имя параметра (если таковое имеется), используемое в коде вызова, не должно быть таким же, как пара-метр с именем, определенным в методе. Пример:

static void Main() 

int numA = 4; 

int productA = Square(numA); // вызов метода с цел. пер‐й 

int productC = Square(12);  // вызов метода с константой 

productC = Square(productA * 3); // вызов с целочисл. выраж. 

static int Square(int input) 

return input * input; } Возвращаемые значения. Методы могут возвращать

значения вызывающим их объектам. Если тип возвращаемого значения, указываемый перед именем метода, не равен void, для возвращения значения используется ключевое слово return. Как показано в примере выше, в результате выполнения инструкции return input*input, вызвавшему метод объекту будет возвращено целочисленное значение произведения. Кроме того, ключевое слово return останавливает выполнение метода. Если тип возвра-щаемого значения void, инструкцию return без значения можно использовать для завершения выполнения метода. Если ключевое слово return отсутствует, выполнение метода завершится, когда будет достигнут конец его блока кода.

Page 58: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

58

Параметры в подпрограмму передаются по ссылке или по значению. Если тип параметра – значимый (число, символ, булевское значение), то по умолчанию используется передача по значению, при этом передается копия объекта, а не сам объект. Поэтому изменения в аргументе не оказывают влияния на исходную копию в вызывающем методе. Для изменения в методе переменной используют передачу по ссылке с помощью ключевого слова ref. Пример:

static void TwoNumbers(int number1, ref int number2) 

{ number1 = number1 * 2;  //это изменение только здесь number2  = number1 + number2;  } static void Main() {   int a = 5, b = 1;   Console.WriteLine(“ a={0},  b= {1}”, a, b); // a=5  b=1   TwoNumbers(a, ref b);   Console.WriteLine(“ a={0},  b= {1}”, a, b); // a=5  b=11 } Если тип параметра – ссылочный (массив, матрица, строка),

то по умолчанию происходит передача адреса объекта и поэтому все изменения, кроме создания нового объекта, в методе отражаются в вызывающей программе. Для полного контроля метода над ссылочным параметром также используется ключевое слово ref. В метод печати матрицы будем передавать матрицу по значению, а в метод замены побочной диагонали – по ссылке.

static void Main() 

string line; 

char[] delimiterChars = { ' ', ',', '\t' }; 

int n;      // количество строк матрицы 

int[,] matr; // исходная матрица 

int i, j;      // индексы 

// ввод матрицы из файла 

Page 59: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

59

using (StreamReader file = new StreamReader("dat.txt")) 

// ввод размерности 

n = int.Parse(file.ReadLine()); 

matr = new int[n, n];  // определение матрицы 

// чтение строки из файла и преобразование в числовые данные 

for (i = 0; (i < n) && ((line = file.ReadLine()) != null); i++) 

string[] numbers = line.Split(delimiterChars); 

j = 0; 

foreach (string numString in numbers) 

int x; 

bool canConvert = int.TryParse(numString, out x); 

if (canConvert == true) 

matr[i, j] = x; 

j++; 

}// ввод данных закончен 

// создание меню 

string choice = "0"; 

while (choice != "4") 

Console.WriteLine(); 

Console.WriteLine("1. Печать матрицы"); 

Console.WriteLine("2. Нахождение минимального элемента"); 

Console.WriteLine("3. Замена побочной диагонали нулями"); 

Console.WriteLine("4. Выход"); 

Page 60: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

60

Console.WriteLine(" "); 

Console.WriteLine(" Введите номер пункта меню "); 

 

choice = Console.ReadLine(); 

switch (choice) 

case "1": 

Console.WriteLine(" Печать матрицы"); 

print_matrica(matr); 

Console.WriteLine(); 

break; 

case "2": 

Console.Write("Мин. элемент = {0}",min_element(matr)); 

Console.WriteLine(); 

break; 

case "3": 

Console.WriteLine(" Произведена замена."); 

zamena(ref matr); 

Console.WriteLine(); 

 break; 

case "4": 

Console.WriteLine(" До свидания!"); 

break; 

default: 

Console.WriteLine(" Введите 1, 2, 3 или 4"); 

Console.WriteLine(); 

break; 

Console.ReadLine(); 

}// k Main 

Page 61: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

61

// метод нахождения минимального элемента матрицы 

static int min_element(int[,] a) 

int min_elt=a[0,0]; 

for (int i = 0; i < a.GetLength(0); i++) 

for(int j=0; j< a.GetLength(1); j++) 

if (a[i, j] < min_elt) 

min_elt = a[i, j]; 

return min_elt; 

// метод замены побочной диагонали нулями 

static void zamena(ref int[,] a) 

int n= a.GetLength(1); 

for (int i = 0; i < a.GetLength(0); i++) 

a[i, n – i – 1] = 0; 

// метод печати матрицы 

static void print_matrica(int[,] a) 

for (int i = 0; i < a.GetLength(0); i++) 

for (int j = 0; j < a.GetLength(1); j++) 

Console.Write("{0} \t", a[i, j]); 

Page 62: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

62

Console.WriteLine(); 

 

 

 

Задания для лабораторной работы № 6 (характеристика / преобразование)

1. В матрице существует строка, элементы которой образуют симметричную последовательность.

Преобразование. Удалить из матрицы строку и столбец, на пересечении которых расположен максимальный по модулю элемент (если таких элементов несколько, то максимальный элемент с меньшими коэффициентами).

2. В строках с отрицательным элементом на главной диаго-нали найти максимум. Если максимум отрицательный или таких строк нет, ответом является число ноль, иначе единица.

Преобразование. Повернуть внешний контур матрицы на 900 по часовой стрелке, второй контур на 900 против часовой стрелки.

Page 63: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

63

Список литературы

1. Абрамов, С. А. Задачи по программированию / С. А. Абра-мов, Г. Г. Гнездилова, Е. Н. Капустина, М. И. Селюн. – М.: Наука, 1988. – 224 с.

2. Лабораторные работы по курсу «ЭВМ и программи-рование»: метод. указания / сост.: Л. Ю. Белова, Ю. В. Власов, О. В. Власова; Яросл. гос. ун-т им. П. Г. Демидова.–Ярославль: ЯрГУ, 2001.– 19 с.

3. Власова, О. В. Информатика: лабораторный практикум / О. В. Власова, О. П. Полякова. – Ярославль, 2005. – 28 с.

4. Троелсен, Э. С# и платформа .Net 3.0: специальное издание / Э. Троелсен. – СПб.: Питер, 2008. – 1456 с.

5. Шень, А. Программирование: теоремы и задачи / А. Шень. – М.: МЦНМО, 1995. – 265 с.

6. Главная страница MSDN: http://www.msdn.com 7. www.esate.ru/page/chto-takoe-tao-framework

Page 64: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

64

Оглавление

Введение .............................................................................................................. 2

Необходимое программное обеспечение ....................................................... 4

Создание первой программы .......................................................................... 5

Лабораторная работа № 1. Простейшие конструкции языка ..................... 9

Задания для лабораторной работы № 1 .......................................................... 19

Лабораторная работа № 2. Табулирование функции, заданной бесконечным рядом ........................................................................... 20

Задания для лабораторной работы № 2 .......................................................... 22

Лабораторная работа № 3. Вычисления с хранением последовательностей значений ....................................................... 22

Задания для лабораторной работы № 3 .......................................................... 30

Лабораторная работа № 4. Обработка последовательностей символов .............................................................................................. 31

Задания для лабораторной работы № 4 .......................................................... 41

Лабораторная работа № 5. Графические построения при решении геометрических задач ....................................................................... 41

Задания для лабораторной работы № 5 .......................................................... 54

Лабораторная работа № 6. Матричные задачи ............................................ 55

Задания для лабораторной работы № 6 (характеристика / преобразование) ............................................................................................................... 62

Список литературы ......................................................................................... 63

Page 65: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

65

Page 66: Основы программирования на языкеВ C# существует еще один оператор цикла – foreach. Этот цикл полезен, когда

66

В. Л. Дольников

О. П. Якимова

Основы программирования на языке С#.

Примеры лабораторных работ