- •Предисловие
- •Объектная ориентация программ на C#
- •1.1. Типы, классы, объекты
- •1.2. Программа на C#
- •1.3. Пространство имен
- •1.4. Создание консольного приложения
- •Типы в языке C#
- •2.1. Типы ссылок и типы значений
- •2.2. Классификация типов C#
- •2.3. Простые типы. Константы-литералы
- •2.4. Объявления переменных и констант базовых типов
- •Операции и целочисленные выражения
- •3.1. Операции языка C#
- •3.2. Операции присваивания и оператор присваивания
- •3.3. Операции инкремента (++) и декремента (--)
- •3.4. Выражения с арифметическими операциями
- •3.5. Поразрядные операции
- •Выражения с операндами базовых типов
- •4.1. Автоматическое и явное приведение арифметических типов
- •4.2. Особые ситуации в арифметических выражениях
- •4.3. Логический тип и логические выражения
- •4.4. Выражения с символьными операндами
- •5.2. Простые (базовые) типы C# как классы
- •Операторы
- •6.1. Общие сведения об операторах
- •6.2. Метки и оператор безусловного перехода
- •6.4. Операторы цикла
- •6.5. Операторы передачи управления
- •6.6. Переключатель
- •Массивы
- •7.1. Одномерные массивы
- •7.2. Массивы как наследники класса Array
- •7.3. Виды массивов и массивы многомерные
- •7.5. Массивы массивов и поверхностное копирование
- •Строки – объекты класса string
- •8.1. Строковые литералы
- •8.2. Строковые объекты и ссылки типа string
- •8.3. Операции над строками
- •8.5. Форматирование строк
- •8.6. Строка как контейнер
- •8.7. Применение строк в переключателях
- •8.8. Массивы строк
- •8.8. Сравнение строк
- •8.10. Аргументы метода Main()
- •Методы C#
- •9.2. Соотношение фиксированных параметров и аргументов
- •9.3. Параметры с типами ссылок
- •9.4. Методы с переменным числом аргументов
- •9.5. Перегрузка методов
- •9.6. Рекурсивные методы
- •9.7. Применение метода Array.Sort()
- •Класс как совокупность статических членов
- •10.1. Статические члены класса
- •10.2. Поля классов (статические поля)
- •10.3. Статические константы
- •10.4. Статические методы
- •10.5. Статический конструктор
- •10.6. Статические классы
- •Классы как типы
- •11.1. Объявление класса
- •11.2. Поля объектов
- •11.3. Объявления методов объектов
- •11.4. Пример класса и его объектов
- •11.5. Ссылка this
- •11.6. Конструкторы объектов класса
- •11.7. Деструкторы и финализаторы
- •Средства взаимодействия с объектами
- •12.1. Принцип инкапсуляции и методы объектов
- •12.2. Свойства классов
- •12.3. Автореализуемые свойства
- •12.4. Индексаторы
- •12.5. Индексаторы, имитирующие наличие контейнера
- •Включение, вложение и наследование классов
- •13.1. Включение объектов классов
- •13.2. Вложение классов
- •13.3. Наследование классов
- •13.4. Доступность членов класса при наследовании
- •13.5. Методы при наследовании
- •13.6. Абстрактные методы и абстрактные классы
- •13.7. Опечатанные классы и методы
- •13.8. Применение абстрактых классов
- •Интерфейсы
- •14.1. Два вида наследования в ООП
- •14.2. Объявления интерфейсов
- •14.3. Реализация интерфейсов
- •14.4. Интерфейс как тип
- •14.5. Интерфейсы и наследование
- •Перечисления и структуры
- •15.1. Перечисления
- •15.2. Базовый класс перечислений
- •15.3. Структуры
- •15.4. Упаковка и распаковка
- •15.5. Реализация структурами интерфейсов
- •Исключения
- •16.1. О механизме исключений
- •16.3. Свойства исключений
- •16.5. Исключения в арифметических выражениях
- •16.6. Генерация исключений
- •16.7. Пользовательские классы исключений
- •Делегаты и события
- •17.1. Синтаксис делегатов
- •17.2. Массивы делегатов
- •17.3. Многоадресные групповые экземпляры делегатов
- •17.4. Делегаты и обратные вызовы
- •17.5. Анонимные методы
- •17.6. События
- •Литература
- •Предметный указатель
130 |
Г л а в а 8 |
|
|
Выводимая строка:
Спецификация Е4: 1,2346E+003, спецификация F4: 1234,5670
Обратите внимание на округление при выводе по формату Е4 и на дополнительный нуль в изображении числа с фиксированной точкой при выводе по формату F4. Это определяется спецификатором точности, равным 4.
Пример с целочисленным значением, выводимым с разными основаниями в поля из 4-х позиций. Обратите внимание, что ширина первого поля отрицательна:
int num = 23;
string form = "Основание 10: {0,-4:D}\n основание 16: {0,4:X}";
Console.WriteLine(form, num);
Результат в консольном окне:
Основание 10: 23 Основание 16: 17
В этом примере форматирование выполняется непосредственно при обращении к методу WriteLine(). Первый аргумент выступает в роли форматной строки, а вызов метода string.Format() осуществляется неявно.
Если в этом примере в полях подставки указать спецификаторы точности, то в изображениях целых чисел могут появиться незначащие нули, например:
int num = 23;
string form = "Основание 10: {0,-4:D3}\n основание 16: {0,4:X3}";
Console.WriteLine(form, num);
Результат:
Основание 10: 023 Основание 16: 017
Замечание. Если в поле подстановки указана ширина, недостаточная для представления выводимого значения, то ширина поля будет автоматически увеличена до необходимого количества позиций.
Строки – объекты класса string |
131 |
|
|
8.6. Строка как контейнер
Как мы уже знаем, оператор foreach предназначен для последовательного перебора всех элементов некоторого контейнера. Если в качестве контейнера выступает массив, например, с элементами типа long, то для просмотра значений всех его элементов можно использовать цикл с заголовком
foreach (long cell in массив)
В этом цикле итерационная переменная cell имеет тот же тип, что и элементы массива, и последовательно принимает значения его элементов.
Если нужно применить такой же цикл для перебора элементов объекта типа string, то используется итерационная переменная типа char. В качестве контейнера выступает строковый литерал, либо объект класса string (либо ссылка на такой объект). Пример со строковым литералом:
foreach (char numb in "0123") Console.Write("\t"+numb+"->"+(int)numb);
Результат:
0–>48 1->49 2->50 3->51
8.7. Применение строк в переключателях
Мы уже упоминали, что объекты класса string (и ссылки на них) могут использоваться в метках переключателя и служить значением переключающего выражения. Для иллюстрации этих возможностей рассмотрим схему решения такой задачи: “Ввести фамилию человека (например, служащего компании) и вывести имеющиеся сведения о нем”. Характер этих сведений и конкретные сведения нам не важны – покажем общую схему решения подобных задач с использованием переключателя и строк.
Console.Write("Введите фамилию:"); string name= Console.ReadLine(); swich(name) {
132 |
Г л а в а 8 |
|
|
case "Сергеев": Console.WriteLine("Фрол Петрович");
...Вывод данных о Сергееве ...
break;
case "Туров":
...Вывод данных о Турове ...
break;
. . . .
default: Console.Write ("Нет сведений");
}
8.8. Массивы строк
Как любые объекты, строки можно объединять в массивы. Хотя внимательный читатель заметит, что в массив помещаются не строки, а только ссылки на них, но при использовании массивов ссылок на строки не требуются никакие специальные операции для организации обращения к собственно строкам через ссылки на них. Поэтому в литературе, посвященной языку C#, зачастую говорят просто о массивах строк. В следующей программе создается массив ссылок на строки, по умолчанию инициализированный пустыми строками. Затем в цикле элементам массива (ссылкам) присваиваются значения ссылок на объекты-строки разной длины. Далее к массиву применяется оператор перебора контейнеров foreach, и строки выводятся на консоль.
// 08_01.cs – массивы строк using System;
class Program { static void Main() {
string [] stAr = new string[4]; for (int i = 0; i<star.Length; i++) stAr[i] = new string('*', i + 1);
foreach (string rs in stAr) Console.Write("\t" + rs);
}
}
Результат выполнения программы:
* ** *** ****
Строки – объекты класса string |
133 |
|
|
В программе создан массив из четырех пустых строк. Он представлен ссылкой stAr. Обратите внимание, что для создания объектов, адресуемых элементами массива, применяется конструктор с прототипом string (char, int); Этот конструктор создаёт строку в виде последовательности одинаковых символов, количество которых определяет второй параметр. (Первый параметр позволяет задать повторяемый символ.) Итерационная переменная цикла foreach имеет тип string, так как просматриваемым контейнером служит массив типа string[ ].
Для иллюстрации применения методов Split(), Join(), рассмотрим следующую задачу. Пусть значением строки является предложение, слова которого разделены пробелами. Требуется заменить каждый пробел последовательностью символов "-:-". Следующая программа решает сформулированную задачу.
// 08_02.cs – декомпозиция и объединение строк. using System;
class Program
{
static void Main()
{
string sent = "De gustibus non est disputandum"; // О вкусах не спорят
string[] words; //Ссылка на массив строк words = sent.Split(' ');
Console.WriteLine("word.Length = " + words.Length); foreach (string st in words)
Console.Write("{0}\t", st); sent = string.Join("-:-", words); Console.WriteLine("\n" + sent);
}
}
Результат выполнения программы:
word.Length = 5
De gustibus non est disputandum De-:-gustibus-:-non-:-est-:-disputandum
В строке, связанной со ссылкой sent, помещены слова, разделенные пробелами. Определена ссылка words на массив строк (объектов класса string). Обращение sent.Split(' ') «разбивает»
134 |
Г л а в а 8 |
|
|
строку, адресованную ссылкой sent, на фрагменты. Признак разбиения – символ пробел ' ', использованный в качестве аргумента. Из выделенных фрагментов формируется массив (объект класса string[]), и ссылка на него присваивается переменной words.
Выражение words.Length равно длине (количеству элементов) сформированного массива. Напомним, что Length – свойство класса массивов string[], унаследованное от базового класса Array.
Оператор foreach перебирает элементы массива words, и итерационная переменная st последовательно принимает значения каждого из них. (Напомним, что особенность итерационной переменной состоит в том, что она позволяет только получать, но не позволяет изменять значения перебираемых элементов.) В теле цикла foreach один оператор – обращение к статическому методу Write() класса Console. Его выполнение обеспечивает вывод значений элементов массива (строк). Эскейп-по- следовательность '\t' в поле подстановки разделяет табуляцией выводимые слова.
Статический метод Join() предназначен для выполнения действий в некотором смысле обратных действиям метода Split(). Обращение string.Join("-:-", words) объединяет (конкатенирует) строки массива, представленного ссылкой words, т. е. соединяет в одну строку слова исходного предложения. Между словами вставляется строка, использованная в качестве первого аргумента метода Join(). Тем самым каждый пробел между словами исходной строки заменяется строкой "-:-".
8.8. Сравнение строк
Для объектов класса string определены только две операции сравнения == и !=. Если необходимо сравнивать строки по их упорядоченности, например, в лексикографическом порядке, то этих двух операций недостаточно. Кроме уже упомянутого нестатического метода CompareTo(), в классе string есть статический метод (точнее набор перегруженных методов) с именем Compare, позволяющий сравнивать строки или их фрагменты.
Строки – объекты класса string |
135 |
|
|
Так как сравнение и сортировка строк очень важны в задачах обработки текстовой информации, то рассмотрим два варианта метода Compare().
Наиболее простой метод имеет следующий заголовок:
int static Compare (string, string)
Сравнивая две строки, использованные в качестве аргументов, метод возвращает значение 0, если строки равны. Если первая строка лексикографически меньше второй, – возвращается отрицательное значение. В противном случае возвращаемое значение положительно.
В следующем фрагменте программы определен массив ссылок на строки, из него выбирается и присваивается переменной res ссылка на лексикографически наибольшую строку (08_03.cs):
string[] eng = {"one", "two", "three", "four"}; string res = eng[0];
foreach (string num in eng)
if (string.Compare(res, num) < 0) res = num;
Значением строки, связанной со ссылкой-переменной res, будет "two".
Проиллюстрированная форма метода Compare() оценивает лексикографическую упорядоченность, соответствующую английскому алфавиту. Следующий вариант этого метода позволяет использовать разные алфавиты.
int static Compare (string, string, Boolean,CultureInfo)
Первые два параметра – сравниваемые строки. Третий параметр указывает на необходимость учитывать регистр символов строк. Если он равен true, то регистры не учитываются и строки "New" и "nEw" будут считаться равными. Четвёртый параметр – объект класса System.Globalization. CultureInfo – позволяет указать алфавит, который необходимо использовать при лексикографическом сравнении строк. Для построения объекта, который может быть использован в качестве аргумента, заменяющего четвертый параметр, используют конструктор класса CultureInfo(string). Аргумент
136 |
Г л а в а 8 |
|
|
конструктора – строка, содержащая условное обозначение нужного алфавита. Точнее сказать, обозначается не алфавит, а культура (Culture), которой принадлежит соответствующий язык. Для обозначения национальных культур приняты имена и коды, таблицу которых можно найти в литературе и документации, (см. например, [13], Приложение 2). Мы в наших примерах будем использовать два алфавита: английский (имя культуры "en", код культуры 0х0009) и русский ("ru" и 0х0019).
В следующем фрагменте программы(08_03.cs), который построен по той же схеме, что и предыдущий, определен массив ссылок на строки с русскими названиями представителей семейства тетеревиных из отряда куриных. Из массива выбираются ссылки на лексикографически наименьшую строку, т.е. расположенную после упорядочения по алфавиту в начале списка.
string[] hens = {"Куропатка белая", "Куропатка тундровая",
"Тетерев", "Глухарь", "Рябчик" }; string res = hens[0];
foreach (string hen in hens)
if (string.Compare(res, hen, true,
new System.Globalization.CultureInfo("ru")) > 0) res = hen;
Console.WriteLine(res);
Результат, выводимый на консоль:
Глухарь
Обратите внимание, что четвертый параметр метода Compare() заменен в вызове безымянным объектом класса CultureInfo, сформированным конструктором класса в выражении с операцией new. Аргумент конструктора – литерная строка "ru" – обозначение нужного алфавита (в данном примере
– русского языка). Если возвращаемый результат, больше нуля, т. е. первая строка, именуемая ссылкой res, лексикографически больше второй, то вторая строка, связанная со ссылкой hen, принимается в качестве претендента на наименьшее значение.
Строки – объекты класса string |
137 |
|
|
8.9.Преобразования
сучастием строкового типа
Рассматривая арифметические типы, мы привели правила неявных преобразований и операцию явного приведения типов:
(тип) первичное_выражение
К строковому типу неявные преобразования не применимы, и невозможно использование операции явного приведения типов.
Как уже отмечалось, для всех типов существует метод ToString(), унаследованный всеми классами от единого базового класса object. Таким образом, значение любого типа можно представить в виде строки, например, так:
int n = 8, m = 3; Console.WriteLine(m.ToString()+n.ToString() + « попугаев»);
Результат вывода на консоль:
38 попугаев.
Для обратного преобразования из строки в значение другого типа можно воспользоваться статическими методами библиотечного класса Convert, принадлежащего пространству имен System. Ещё один путь – применение статического метода Parse() или метода TryParse(). Указанные методы (их применение кратко рассмотрено в главе 5) определены в каждом классе предопределенного типа, за исключением класса object (в котором они не нужны). Эти методы часто применяется при чтении данных из входного консольного потока. Метод Console. ReadLine() возвращает в виде строки набранную на клавиатуре последовательность символов. "Расшифровку" этой последовательности, т. е. превращение символьного представления во внутреннее представление (в код) соответствующего значения, удобно выполнить с помощью метода Parse() или TryParse(). Наиболее просто, но совсем небезопасно, применить метод Parse(), например, таким образом:
int res = int.Parse(Console.ReadLine());
В данном случае изображение целого числа в виде набранной на клавиатуре последовательности цифр (возможно со знаком)