Программирование

Автор работы: Пользователь скрыл имя, 28 Марта 2012 в 11:49, курс лекций

Описание

Лекции по дисциплине "Программирование"

Содержание

Лекция 1. Состав языка Типы данных Переменные и операции

Лекция 2. Линейные программы

Лекция 3. Простейшие операторы. Операторы ветвления

Лекция 4. Операторы цикла и передачи управления

Лекция 5. Обработка исключительных ситуаций

Лекция 6. Классы: основные понятия Описание класса

Лекция 7. Параметры методов

Лекция 8. Конструкторы и свойства

Лекция 9. . Массивы

Лекция 10. Символы и строки

Лекция 11 Дополнительные возможности методов. Индексаторы

Лекция 12. Операции класса. Деструкторы

Лекция 13. Наследование классов

Лекция 14. Интерфейсы

Лекция 15. Стандартные интерфейсы .NET

Лекция 16. Структуры и перечисления

Лекция 17. Делегаты

Лекция 18. События

Работа состоит из  1 файл

Лекции C#.doc

— 847.00 Кб (Скачать документ)

 

Пример применения методов приведен в листинге 12.3.

Листинг 12.3. Работа со строками типа string

using System;

namespace ConsoleApplication1

{   class Class1

    {   static void Main()

        {

            string s = "прекрасная королева Изольда";

            Console.WriteLine( s );

            string sub = s.Substring( 3 ).Remove( 12, 2 );              // 1

            Console.WriteLine( sub );

 

            string[] mas = s.Split(' ');                                // 2

            string joined = string.Join( "! ", mas );

            Console.WriteLine( joined );

 

            Console.WriteLine( "Введите строку" );

            string x = Console.ReadLine();                              // 3

            Console.WriteLine( "Вы ввели строку " + x );

 

            double a = 12.234;

            int b = 29;

            Console.WriteLine( " a = {0,6:C}  b = {1,2:X}", a, b );     // 4

            Console.WriteLine( " a = {0,6:0.##}  a = {1,5:0.# ' руб. '}",

                               a, b );                                  // 5

        }

    }

}

 

Результат работы программы:

прекрасная королева Изольда

красная корова Изольда

прекрасная! королева! Изольда

Введите строку

не хочу!

Вы ввели строку не хочу!

a = 12,23p.  b = 1D

 

Форматирование строк

В операторе 4 из листинга 12.3 неявно применяется метод Format, который заменяет все вхождения параметров в фигурных скобках значениями соответствующих переменных из списка вывода. После номера параметра можно задать минимальную ширину поля вывода, а также указать спецификатор формата, который определяет форму представления выводимого значения.

В общем виде параметр задается следующим образом:

{n [,m[:спецификатор_формата]]}

 

Здесь n — номер параметра. Параметры нумеруются с нуля, нулевой параметр заменяется значением первой переменной из списка вывода, первый параметр — второй переменной, и т. д. Параметр m определяет минимальную ширину поля, которое отводится под выводимое значение. Если выводимому числу достаточно меньшего количества позиций, неиспользуемые позиции заполняются пробелами. Если числу требуется больше позиций, параметр игнорируется.

Спецификатор формата, как явствует из его названия, определяет формат вывода значения. Например, спецификатор C (Currency) означает, что параметр должен форматироваться как валюта с учетом национальных особенностей представления, а спецификатор Х (Hexadecimal) задает шестнадцатеричную форму представления выводимого значения.

В операторе 5 используются так называемые пользовательские шаблоны форматирования. Если приглядеться, в них нет ничего сложного: после двоеточия задается вид выводимого значения посимвольно, причем на месте каждого символа может стоять либо #, либо 0. Если указан знак #, на этом месте будет выведена цифра числа, если она не равна нулю. Если указан 0, будет выведена любая цифра, в том числе и 0.

 

Строки типа StringBuilder

Возможности, предоставляемые классом string, широки, однако требование неизменности его объектов может оказаться неудобным. В этом случае для работы со строками применяется класс StringBuilder, определенный в пространстве имен System.Text и позволяющий изменять значение своих экземпляров. О нем можно прочитать в учебнике (Т.А.Павловская. С#. Программирование на языке высокого уровня).

 

Лекция 11. Дополнительные возможности методов. Индексаторы

Перегрузка методов

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

Компилятор определяет, какой именно метод требуется вызвать, по типу фактических параметров. Этот процесс называется разрешением (resolution) перегрузки. Тип возвращаемого методом значения в разрешении не участвует. Механизм разрешения основан на достаточно сложном наборе правил, смысл которых сводится к тому, чтобы использовать метод с наиболее подходящими аргументами и выдать сообщение, если такой не найдется. Допустим, имеется четыре варианта метода, определяющего наибольшее значение:

// Возвращает наибольшее из двух целых:

int max( int a, int b )

// Возвращает наибольшее из трех целых:

int max( int a, int b, int c )

// Возвращает наибольшее из первого параметра и длины второго:

int max ( int a, string b )

// Возвращает наибольшее из второго параметра и длины первого:

int max ( string b, int a )

...

Console.WriteLine( max( 1, 2 ) );

Console.WriteLine( max( 1, 2, 3 ) );

Console.WriteLine( max( 1, "2" ) );

Console.WriteLine( max( "1", 2 ) );

 

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

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

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

int max( int a, int b )

int max( int a, ref int b )

 

Перегрузка широко используется в классах библиотеки .NET. Например, в стандартном классе Console метод WriteLine перегружен 19 раз для вывода величин разных типов.

Рекурсивные методы

Рекурсивным называется метод, который вызывает сам себя. Такая рекурсия называется прямой. Существует еще косвенная рекурсия, когда два или более метода вызывают друг друга. Если метод вызывает себя, в стеке создается копия значений его параметров, как и при вызове обычного метода, после чего управление передается первому исполняемому оператору метода. При повторном вызове этот процесс повторяется.

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

Классическим примером рекурсивной функции является функция вычисления факториала (это не означает, что факториал следует вычислять именно так). Для того чтобы получить значение факториала числа n, требуется умножить на n факториал числа (n – 1). Известно также, что 0 != 1 и 1 != 1.

long fact( long n ) {

    if ( n == 0 || n == 1 ) return 1;        // нерекурсивная ветвь

    return ( n * fact( n – 1 ) );            // рекурсивная ветвь

}

 

То же самое можно записать короче:

long fact( long n ) {

    return ( n > 1 ) ? n * fact( n – 1 ) : 1;

}

 

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

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

Методы с переменным количеством аргументов

Иногда бывает удобно создать метод, в который можно передавать разное количество аргументов. Язык C# предоставляет такую возможность с помощью ключевого слова params. Параметр, помеченный этим ключевым словом, размещается в списке параметров последним и обозначает массив заданного типа неопределенной длины, например:

public int Calculate( int a, out int c, params int[] d ) …

 

В этот метод можно передать три и более параметров. Внутри метода к параметрам, начиная с третьего, обращаются как к обычным элементам массива. Количество элементов массива получают с помощью его свойства Length. В качестве примера рассмотрим метод вычисления среднего значения элементов массива (листинг 13.1).

Листинг 13.1. Метод с переменным числом параметров

using System;

namespace ConsoleApplication1

{    class Class1

    {

        public static double Average( params int[] a )

        {

            if ( a.Length == 0 )

                throw new Exception( "Недостаточно аргументов в методе" );

 

            double av = 0;

            foreach ( int elem in a ) av += elem;

            return av / a.Length;

        }

 

        static void Main()

        {   try

            {

                int[] a = { 10, 20, 30 };

                Console.WriteLine( Average( a ) );            // 1

                int[] b = { -11, -4, 12, 14, 32, -1, 28 };

                Console.WriteLine( Average( b ) );            // 2

                short z = 1, e = 12;

                byte v = 100;

                Console.WriteLine( Average( z, e, v ) );      // 3

                Console.WriteLine( Average() );               // 4

            }

            catch( Exception e )

            {

                Console.WriteLine( e.Message );

                return;

            }

        }

    }

}

 

Результат работы программы:

10

20

40

Недостаточно аргументов в методе

 

Параметр-массив может быть только один и должен располагаться последним в списке. Соответствующие ему аргументы должны иметь типы, для которых возможно неявное преобразование к типу массива.

Метод Main

Метод, которому передается управление после запуска программы, должен иметь имя Мain и быть статическим. Он может принимать параметры из внешнего окружения и возвращать значение в вызвавшую среду. Предусматривается два варианта метода — с параметрами и без параметров:

// без параметров:

static тип  Main() { ... }

static void Main() { ... }

// с параметрами:

static тип  Main( string[] args ) { /* ... */ }

static void Main( string[] args ) { /* ... */ }

 

Параметры, разделяемые пробелами, задаются при запуске программы из командной строки после имени исполняемого файла программы. Они передаются в массив args.

Если метод возвращает значение, оно должно быть целого типа, если не возвращает, он должен описываться как void. Ненулевое значение обычно означает аварийное завершение. Возвращаемое значение анализируется в командном файле, из которого запускается программа. Обычно это делается для того, чтобы можно было принять решение, выполнять ли командный файл дальше. В листинге 13.2 приводится пример метода Main, который выводит свои аргументы и ожидает нажатия любой клавиши.

Листинг 13.2. Параметры метода Main

using System;

namespace ConsoleApplication1

{   class Class1

    {   static void Main( string[] args )

        {

            foreach( string arg in args ) Console.WriteLine( arg );

            Console.Read();

        }

    }

}

 

Индексаторы

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

Синтаксис индексатора аналогичен синтаксису свойства:

атрибуты спецификаторы тип this [ список_параметров ]

{

    get код_доступа

    set код_доступа

}

 

Индексаторы чаще всего объявляются со спецификатором public, поскольку они входят в интерфейс объекта. Атрибуты и спецификаторы могут отсутствовать.

Код доступа представляет собой блоки операторов, которые выполняются при получении (get) или установке значения (set) элемента массива. Может отсутствовать либо часть get, либо set, но не обе одновременно. Если отсутствует часть set, индексатор доступен только для чтения (read-only), если отсутствует часть get, индексатор доступен только для записи (write-only).

Список параметров содержит одно или несколько описаний индексов, по которым выполняется доступ к элементу. Чаще всего используется один индекс целого типа.

Индексаторы в основном применяются для создания специализированных массивов, на работу с которыми накладываются какие-либо ограничения. Примеры работы с индексаторами приведены в учебнике.

Язык C# допускает использование многомерных индексаторов. Они описываются аналогично обычным и применяются в основном для контроля за занесением данных в многомерные массивы и выборке данных из многомерных массивов, оформленных в виде классов.

 

Лекция 12. Операции класса. Деструкторы

 

Операции класса

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

MyObject a, b, c;

...

c = a + b;                 // используется операция сложения класса MyObject

 

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

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

[ атрибуты ] спецификаторы объявитель_операции тело

 

В качестве спецификаторов одновременно используются ключевые слова public и static. Кроме того, операцию можно объявить как внешнюю (extern).

Объявитель операции содержит ключевое слово operator, по которому и опознается описание операции в классе. Тело операции определяет действия, которые выполняются при использовании операции в выражении. Тело представляет собой блок, аналогичный телу других методов.

Информация о работе Программирование