Программирование на C# для начинающих. Основные сведения 9785040925193

В этой книге Алексей Васильев, доктор физико-математических наук и автор популярных российских самоучителей по программи

229 24 9MB

Russian Pages 586 [585] Year 2018

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Программирование на C# для начинающих. Основные сведения
 9785040925193

Table of contents :
Оглавление
Введение Язык С# и технология .Net Framework
История создания языка С#
Особенности языка С#
Программное обеспечение
Собственно о книге
Обратная связь
Благодарности
Об авторе
Глава 1 Знакомство с языком С#
Структура программы
Первая программа
Пространство имен
Использование среды разработки
Программа с диалоговым окном
Окно с полем ввода
Настройка вида диалогового окна
Консольный ввод
Считывание чисел
Форматированный вывод
Резюме
Задания для самостоятельной работы
Глава 2 Базовые типы и операторы
Переменные и базовые типы данных
Литералы
Управляющие символы
Преобразование типов
Объявление переменных
Арифметические операторы
Операторы сравнения
Логические операторы
Побитовые операторы и двоичные коды
Оператор присваивания
Сокращенные формы операции присваивания
Тернарный оператор
Приоритет операторов
Примеры программ
Резюме
Задания для самостоятельной работы
Глава 3 Управляющие инструкции
Условный оператор if
Вложенные условные операторы
Оператор выбора switch
Оператор цикла while
Оператор цикла do-while
Оператор цикла for
Инструкция безусловного перехода goto
Перехват исключений
Резюме
Задания для самостоятельной работы
Глава 4 Массивы
Одномерные массивы
Инициализация массива
Операции с массивами
Цикл по массиву
Двумерные массивы
Многомерные массивы
Массив со строками разной длины
Массив объектных ссылок
Параметры командной строки
Резюме
Задания для самостоятельной работы
Глава 5 Статические методы
Знакомство со статическими методами
Перегрузка статических методов
Массив как аргумент метода
Массив как результат метода
Механизмы передачи аргументов методу
Рекурсия
Методы с произвольным количествомаргументов
Главный метод программы
Резюме
Задания для самостоятельной работы
Глава 6 Знакомство с классами и объектами
Базовые принципы ООП
Классы и объекты
Описание класса и создание объекта
Использование объектов
Закрытые члены класса и перегрузка методов
Конструктор
Деструктор
Статические члены класса
Ключевое слово this
Резюме
Задания для самостоятельной работы
Глава 7 Работа с текстом
Класс String
Создание текстового объекта
Операции с текстовыми объектами
Методы для работы с текстом
Метод ToString ()
Резюме
Задания для самостоятельной работы
Глава 8 Перегрузка операторов
Операторные методы
Перегрузка арифметическихи побитовых операторов
Перегрузка операторов сравнения
Перегрузка операторов true и false
Перегрузка логических операторов
Перегрузка операторов приведения типов
Команды присваиванияи перегрузка операторов
Резюме
Задания для самостоятельной работы
Глава 9 Свойства и индексаторы
Знакомство со свойствами
Использование свойств
Знакомство с индексаторами
Использование индексаторов
Двумерные индексаторы
Многомерные индексаторы
Перегрузка индексаторов
Резюме
Задания для самостоятельной работы
Глава 10 Наследование
Знакомство с наследованием
Наследование и уровни доступа
Наследование и конструкторы
Объектные переменные базовых классов
Замещение членов при наследовании
Переопределение виртуальных методов
Переопределение и замещение методов
Переопределение и перегрузка методов
Наследование свойств и индексаторов
Резюме
Задания для самостоятельной работы
Заключение Что будет дальше
Предметный указатель

Citation preview

УДК 004.43 ББК 32.973.26-018.1 В19

В19

Васильев, Алексей. Программирование на С# для начинающих. Основные сведения /

Алексей Васильев. - Москва: Эксмо, 2018. - 592 с. - (Российский компьютерный бестселлер). ISBN 978-5-04-092519-3

В этой книге Алексей Васильев, доктор физико-математических наук и автор популярных российских самоучителей по программированию, пригла­ шает читателей ознакомиться с основами языка С#. Прочитав ее, вы узнаете

историю языка, его структуру, ознакомитесь с типами данных и перемен­

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

УДКОО4.43 ББК32.973.26-018.1

ISBN 978-5-04-092519-3

©

Оформление. ООО •Издательство сЭксмо•, 2018

ОГЛАВЛ ЕН И Е

Введение. Язык С# и технология .Net Framework . История создания языка С# . Особенности языка С# . . . Программное обеспечение . Собственно о книге Обратная связь Благодарности Об авторе .... Глава 1. Знакомство с языком С# . Структура программы

.....

Первая программа . . . . . . . . Использование среды разработки Пространство имен

. . . . . . . ..

Программа с диалоговым окном . Настройка вида диалогового окна Окно с полем ввода Консольный ввод . . . . . . Считывание чисел . . . . . Форматированный вывод Резюме ............

Задания для самостоятельной работы Глава 2. Базовые типы и операторы .... Переменные и базовые типы данных

Литералы ..........

Управляющие символы ..

Преобразование типов

..

Объявление переменных . Арифметические операторы . Операторы сравнения .. . . . Логические операторы .. . .

Побитовые операторы и двоичные коды Оператор присваивания . . . . . .... . Сокращенные формы операции присваивания Тернарный оператор . .

Приоритет операторов

Примеры программ .. Резюме ......... .

Задания для самостоятельной работы

.7 .7 .9 12 17 19 19 20 21 22 25 27 31 33 42 45 50 54 57 59 60 62 63 68 71 72 77 81 85 86 90 100 102 104 105 106 112 113

3

Оглавл е н ие Глава 3. Управляющие инструкции .

Условный оператор if . . . . . .. Вложенные условные операторы .

Оператор выбора switch

.

Оператор цикла while . . . Оператор цикла do-while . Оператор цикла for

.. . .

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

Задания для самостоятельной работы Глава 4. Массивы ..... . .

Одномерные массивы .. Инициализация массива Операции с массивами Цикл по массиву .. . . Двумерные массивы . . Многомерные массивы Массив со строками разной длины Массив объектных ссылок . . .

Параметры командной строки

.. .

Резюме .................. Задания для самостоятельной работы Глава 5. Статические методы .. . . .....

Знакомство со статическими методами .

Перегрузка статических методов . Массив как аргумент метода

...... .

Массив как результат метода .......

Механизмы передачи аргументов методу Рекурсия .....................

Методы с произвольным количеством аргументов Главный метод программы .. . ..... Резюме .................... Задания для самостоятельной работы

Глава 6. Знакомство с классами и объектами . Базовые принципы ООП ........

Классы и объекты . . . . . . . ..... Описание класса и создание объекта Использование объектов . . . . .... Закрытые члены класса и перегрузка методов Конструктор .. ..... . . .

Деструктор .. . . .... . . .

Статические члены класса .

4

115 116 123 130 142 147 150 156 159 166 168 171 171 181 183 194 198 208 213 218 223 226 227 230 231 238 242 247 254 266 271 277 278 280 282 282 286 289 294 299 303 309 314

Оглавл ение Ключевое слово

this . . . . . . .... .

Резюме ....................

Задания для самостоятельной работы Глава 7. Работа с текстом ..... Класс String ........... Создание текстового объекта

Операции с текстовыми объектами Методы для работы с текстом . Метод

ToString () . . . . . . . ...

Резюме ..................

Задания для самостоятельной работы

Операторные методы . . . . .

Перегрузка арифметических и побитовых операторов . . . .... . . Перегрузка операторов сравнения . . .

true

и

false

Перегрузка логических операторов . . Перегрузка операторов приведения типов . Команды присваивания и перегрузка операторов .. . .

.. . . .

Резюме ....................

Задания для самостоятельной работы Глава 9. Свойства и индексаторы

Знакомство со свойствами . .

Использование свойств . . . . Знакомство с индексаторами Использование индексаторов . Двумерные индексаторы . . Многомерные индексаторы Перегрузка индексаторов

333 334 336 344 356 373 378 379 381 381

Глава 8. Перегрузка операторов .

Перегрузка операторов

321 328 330

.

Резюме .............

Задания для самостоятельной работы Глава 10. Наследование ........

Знакомство с наследованием .. Наследование и уровни доступа

Наследование и конструкторы . Объектные переменные базовых классов Замещение членов при наследовании . . Переопределение виртуальных методов Переопределение и замещение методов Переопределение и перегрузка методов

385 404 423 427 432 441 443 445 448 448 456 475 481 493 506 510 518 520 523 524 529 535 543 549 553 558 562

5

Оглавл е н ие Наследование свойств и индексаторов Резюме ................... . Задания для самостоятельной работы

565 575 576

Заключение.Что будет дальше

580

Предметный указатель .. . . . .

581

Вв ед ен и е ЯЗЫК С# И Т ЕХН ОЛОГИ Я .NET FRAMEWORK

Русская речь не сложнее других. Вон Марга­ дон - дикий человек - и то выучил.

из к/ф «Формула лю бви»

Язык С# уже многие годы неизменно входит в список языков програм­ мирования, самых востребованных среди разработчиков программного обеспечения. Язык является базовым для технологии .Net Framework, разработанной и поддерживаемой корпорацией Microsoft. Именно язы­ ку С# посвящена книга, которую читатель держит в руках.

И стория создания я з ы ка С# История , леденящая кровь. Под маской овцы скрывался лев.

из к/ф «Покровские ворота»

Язык С# создан инженерами компании Microsoft в 1998-2001 годах. Руководил группой разработчиков Андерс Хейлсберг, который до того трудился в фирме Borland над созданием компилятора для языка Pascal и участвовал в создании интегрированной среды разработки Delphi. Язык С# появился после языков программирования С++ и Java. Бога­ тый опыт их использования бьш во многом учтен разработчиками С#.

G)

Н А ЗАМ ЕТ КУ

Си нтаксис языка С# похож н а синтаксис языков С++ и Java. Но сход­ ство внешнее. У языка С# своя ун и кал ьная кон це п ция . В месте с тем м ногие управля ющие инструкци и в языке С# будут знакомы тем , кто п рограм м и рует в С++ и Java .

7

Вв едение Вообще же из трех язы ков п рогра м м и рования С++ , Java и С# исто­ рически первым поя вился язы к С++ . Затем на сцену вы шел язык Java. И уже после этого появился язы к п рограм м и рования С# . Для понимания места и роли языка С# на современном рынке про­ граммных технологий разумно начать с языка программирования С, ко­ торый в свое время стал мощным стимулом для развития программных технологий как таковых. Именно из языка С обычно выводят генеало­ гию языка С#. Мы тоже будем придерживаться классического подхода. Язык программирования С появился в 1 972 году, его разработал Де­ нис Ритчи. Язык С постепенно набирал популярность и в итоге стал одним из самых востребованных языков программирования. Этому способствовал ряд обстоятельств. В первую очередь, конечно, сыграл роль лаконичный и простой синтаксис языка. Да и общая концепция языка С оказалась исключительно удачной и живучей. Поэтому ког­ да встал вопрос о разработке нового языка, который бы поддерживал парадигму объектно ориентированного программирования (ООП), то выбор естественным образом пал на язык С: язык программирова­ ния С++, появившийся в 1 983 году, представлял собой расширенную версию языка С, адаптированную для написания программ с привлече­ нием классов, объектов и сопутствующих им технологий. В свою оче­ редь, при создании языка программирования Java отправной точкой стал язык С++. Идеология языкаjаvа отличается от идеологии языка

С++, но при всем этом базовые управляющие инструкции и операторы в обоих языках схожи.

G)

Н А ЗАМ ЕТ КУ

Язы к п рограм м и рования Java официально появился в 1 995 году и стал популярн ы м благодаря ун иверсал ьности п рограм м , нап и ­ санных на этом языке . Технология , испол ьзуемая в Java, позволяет п исать переноси м ы е п рограм м н ы е коды , что искл юч ител ьно важно при разработке п р ил ожени й для испол ьзован ия в lпternet. Нет ничего удивительного, что при создании языка программирова­ ния С# традиция была сохранена: синтаксис языка С# во многих мо­ ментах будет знаком тем, кто уже программирует на С++ и Java. Хотя такое сходство - внешнее. Языки очень разные, поэтому расслабляться не стоит. Да и базовые синтаксические конструкции в языке С# имеют свои особенности. Все это мы обсудим в книге.

8

Я зык С# и технология .Net Framework

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

из к/ф �Формула лю бви» Язык программирования С#

-

простой, красивый, эффективный и гибкий.

С помощью программ на языке С# решают самые разные задачи. На С# можно создавать как небольшие консольные программы, так и програм­ мы с графическим интерфейсом. Код, написанный на языке С#, лаконичен и понятен (хотя здесь, конечно, многое зависит от программиста). В этом отношении язык программирования С# практически не имеет конкурентов.

G)

Н А ЗАМ ЕТ КУ

Язык С# создавался после появления языков С++ и Java. В С# были учтен ы и по возможности устранены «недостатки » и «недоработки » , которые есть в С++ и Java. Иногда язык С # упоминается как усовер­ шенствованная версия языков С++ и Java, хотя концепции у них со­ вершенно разн ые, так что утверждение довол ьно поверхностно . Кроме собственно преимуществ языка С # , немаловажно и то, что язык поддерживается компанией Microsoft. Поэтому он идеально подходит, чтобы писать программы для выполнения под управлением операцион­ ной системы Windows.



ПОДРОБН ОСТИ

Операционной системой Windows и технологией . Net Framework ком ­ п а н и и Microsoft область применения языка С # не огран ичи вается . Существуют ал ьтернати вные п роекты (такие, например, как М опо ) , позволя ющие выпол нять п рограм м ы , написанные н а языке С#, под управлением операционных систем , отличных от Windows. Вместе с тем мы в кн и ге будем исходить из того , что испол ьзуются « родн ые» средства разработки и операционная система Windows. Как отмечалось выше, язык С# является неотъемлемой частью тех­ нологии (или платформы) .Net Framework. Основу платформы .Net Framework составляет среда исполнения CLR (сокращение от Common Language Runtime) и библиотека классов, которая используется при программировании на языке С#.

9

Вв едение

G)

Н А ЗАМ ЕТ КУ

Платформа .Net Framework позволяет испол ьзовать и иные языки программирования, а не только С# - нап ример, С++ или Visual Basic . Возможности платформы .Net Framework позволяют объединять «В одно целое» п рограммные коды , написанные на разных языках программирования. Это очень мощная технологи я , но для нас инте­ рес представляет написание програм мных кодов на языке С#. Имен­ но особенности и возможности языка С# м ы будем обсуждать в кн иге .

При компилировании программного кода, написанного н а языке С # , соз­ дается промежуточный код. Это промежуточный код реализован на языке M SIL (сокращение от Microsoft Intermediate Language ). Промежуточный код выполняется под управлением системы CLR. Система CLR запускает JIТ-компилятор (сокращение от Just In Time ), который, собственно, и пе­ реводит промежуточный код в исполняемые инструкции.



ПОДРОБН ОСТИ

Файл с программным кодом на языке С# сохраняется с расширени­ ем cs. После компиляции п рограм мы создается файл с расширени­ ем е х е . Но выполнить этот файл можно тол ько на комп ьютере, где установлена система .Net Framework. Такой код называется управля­ емым ( поскол ьку он выполняется под управлением системы CLR) . .

.

Описанная нетривиальная схема компилирования программ с привле­ чением промежуточного кода служит важной цели. Дело в том, что тех­ нология .Net Framework ориентирована на совместное использование программных кодов, написанных на разных языках программирования. Базируется эта технология на том, что программные коды с разных язы­ ков программирования «переводятся� (в процессе компиляции) в про­ межуточный код на общем универсальном языке. Проще говоря, коды на разных языках программирования приводятся «К общему знаменате­ лю�, которым является промежуточный язык M SIL.



ПОДРОБН ОСТИ

П рограм м ы , написанные на Java, тоже компилируются в промежуточ ­ ный байт- код. Байт- код выполняется под управлением ви ртуальной машины Java. Но по сравнени ю с языком С# имеется принци пиал ьное отличие. Байт- код, в который переводится при компиляции Jаvа- про­ грам ма, имеет при вязку к одному языку программирования - языку 10

Я зык С# и технология .Net Framework Java. И в Java схема с промежуточным кодом нужна для обеспечения универсальности программ , поскольку промежуточный байт- код не за­ висит от типа операционной системы (и поэтому переносим ) . Особен­ ность операционной системы учитывается той виртуальной машиной Java, которая установлена на компьютере и выполняет промежуточный байт- код. Промежуточный код, который испол ьзуется в технологии .Net Framework, не привязан к конкретному языку программирования. Например, что при компиляции программы на языке С# , что при ком­ пиляции программы на языке Visual Basic получаются наборы инструк­ ций на одном и том же промежуточном языке MSIL. И нужно это, еще раз подчеркнем , для обеспечения совместимости разных программ­ ных кодов, реализованных на разных языках.

Весь этот процесс для нас важен исключительно с познавательной точки зрения. Более принципиальными являются вопросы, касающиеся осо­ бенностей собственно языка С#. Первое, что стоит отметить: язык С# полностью объектно ориентиро­ ванный. Это означает, что даже самая маленькая программа на языке С# должна содержать описание хотя бы одного класса.

G)

Н А ЗАМ ЕТ КУ

Здесь есть методологическая проблема. Состоит она в том , что не­ подготовленному ч итател ю сложно восприни мать концепцию ООП сразу, без п редварител ьной подготовки . М ы найдем выход в том , чтобы испол ьзовать определенный шаблон п р и написании п ро­ грам м . Затем , по мере знакомства с языком С# , м ногие моменты станут просты м и и п онятн ы м и .

Как отмечалось выше, базовые синтаксические конструкции языка С # напоминают (или просто совпадают) соответствующие конструкции в языках С++ и/или Jаvа. Но, кроме них, язык С# содержит множество интересных и полезных особенностей, с которыми мы познакомимся в книге.



ПОДРОБН ОСТИ

Знакомым с языками п рограммирован ия С++ и/или Java будет полезно узнать, что в языке С# , как и в языке С++ , испол ьзуются п ространства имен , указатели , существует переопределение опе­ раторов. Также в С# , как и в Java, имеются и нтерфейсы , объекты реал изуются через ссыл ки , испол ьзуется система автоматической 11

Вв едение «уборки мусора » . А еще в С# испол ьзуются делегаты , кон цепция которых идеологически бл изка к концепции указателей на фун кци и в С++ . М ассивы в С# бол ьше напоми нают массивы Java , но вооб­ ще в С# они достаточ н о специфич н ы е . И ндексаторы в С# позво­ л я ют и ндексировать объекты - подобн ы й механ изм , основа н н ы й на переоп редел е н и и оператора « квадратн ые скобки » , есть в С++ . Свойства, которые испол ьзуются в С#, представл я ют собой нечто среднее между полем и методом , хотя , конеч н о , бол ьше напомина­ ют п ол е с особы м режи мом доступа .

Есть в языке С# и �классические� механизмы, характерные для боль­ шинства языков, поддерживающих парадигму ООП. Мы познакомим­ ся с тем, как на основе классов и объектов в языке С# реализуется ин­ капсуляция, узнаем, что такое наследование и как в С# используется полиморфизм. Будет много других тем и вопросов, которые мы изучим. Например, мы узнаем (во второй части книги), как в С# создаются при­ ложения с графическим интерфейсом, и познакомимся с основными подходами, используемыми при создании многопоточных приложений. Но обо всем этом - по порядку, тема за темой.

П рограммное обеспе ч ение Показывай свою гравицану. Если фирменная вещь - возьмем !

из к/ф -«Кин-дза-дза»

Для работы с языком программирования С# на компьютере должна быть установлена платформа .Net Framework. Компилятор языка С# входит в стандартный набор этой платформы. Поэтому, если на компью­ тере установлена платформа .Net Framework, этого достаточно для нача­ ла программирования в С#. Обычно дополнительно еще устанавливают среду разработки, благодаря которой процесс программирования на С# становится простым и приятным. Если мы хотим написать программу (на языке С#), сначала нам нужно набрать соответствующий программный код. Теоретически сделать это можно в обычном текстовом редакторе. В таком случае набираем в тек­ стовом редакторе код программы и сохраняем файл с расширением . c s (расширение для файлов с программами, написанными н а языке С#). 12

Я зык С# и технология .Net Framework После того как код программы набран и файл с программой сохранен, ее следует откомпилировать. Для этого используют программу-компи­ лятор c s c . ехе, которая устанавливается, как отмечено выше, при уста­ новке платформы .Net Framework.



ПОДРОБН ОСТИ

Ал горитм действи й тако й : в командной строке указывается назва­ ние п рограм м ы - ком пилятора csc.ехе , а затем через п робел ука­ зы вается название файла с п рограммой на языке С# . Допусти м , м ы записал и код п рограм м ы в файл MyProgram. cs. Тогда для ком ­ пиляции программы в командной строке испол ьзуем инструкци ю csc. ехе MyProgram. cs или csc MyProgram. cs ( расш ирение ехе ­ файла можно не указы вать ) . Есл и ком п ил я ция проходит нормально, то в резул ьтате получаем файл с расш ирением . ехе , а название файла совпадает с названием исходного файла с п рограммой ( в на­ шем случае это MyProgram. ехе ) . Полученный в резул ьтате ком п ил я ­ ци и ехе-файл запускают на выполнение. Файл csc.exe п о умолчан и ю находится в каталоге C : \ Window s \ Microsoft. NET\ Framework внутри папки с номером верси и - на­ пример, vЗ. 5 или v4. О. Также для ком п ил и рован ия п рограммы из командной строки п ридется , скорее всего , выпол н ить некоторые допол н ител ьные настройки - например, в переменных среды за­ дать путь для поиска ком п илятора csc. ехе .

Хотя такая консольная компиляция вполне рабочая, прибегают к ней редко. Причина в том, что не очень удобно набирать код в текстовом редакторе, затем компилировать программу через командную строку и запускать вручную исполнительный файл. Намного проще восполь­ зоваться специальной программой интегрированной средой разработ­ ки (ID E от Integrated Development Environment ). Среда разработки со­ держит в себе все наиболее важные «ингредиенты» , необходимые для «приготовления» такого «блюда», как программа на языке С#. При ра­ боте со средой разработки пользователь получает в одном комплекте ре­ дактор кодов, средства отладки, компилятор и ряд других эффективных утилит, значительно облегчающих работу с программными кодами. Мы тоже прибегнем к помощи среды разработки. Нам понадобится прило­ жение Microsoft Visual Studio. -

Загрузить установочные файлы можно с сайта компании Microsoft . m i c r o s o f t . сот (на сайте следует найти страницу загрузок).

www

13

Вв еде н ие После установки среды разработки мы получаем все, что нужно для успешной разработки приложений на языке С#.



ПОДРОБН ОСТИ

Приложение Microsoft Visual Studio я вляется ком мерчески м . Одна­ ко у него есть неком мерческая «уп рощенная» версия Visual Studio Express , которая впол н е подойдет для изучения языка п рогра м м и ­ рования С#.

G)

Н А ЗАМ ЕТ КУ

Кроме языка программ ирован ия С# среда разработки Visual Studio позволяет создавать п рограм м ы на языках Visual Basic и С++ . Часть настроек, вл ияющих на фун кциональность среды разработки , оп ре­ деляется в процессе установки .

Как выглядит окно приложения Visual Studio Express (версия 2 0 1 5), по­ казано на рис. В. 1 . og


Юout WJYS we an optmzt our network а15 and background oPtr.llЬOn.s

#DocumentDB loves

Acqualnt

1- Down�d SoluЬon

Xamarln: Planet Scale МоЫlе Арр ln Ave steps Тh.1$ IS J specQI OUest post from tht

DcкumentOB tеащ wrtten Ьу Кd

G;мytyuk. К111 works •t мo:rosol't on the OOt•"""• N

w�

н.tр

� Anкh.

-

х



Discover what's new in Express 2015 for V futUtn�bprи. lSfOfV! Lwn•� Sн�in...... -.1he.NПfr•IN'WOl'll. Eapo1 ... ll\-tul 1 rlfWJn°I� �>IUdlo fцм S.М.:t1

�...iop

Rt:•dy to Cktud·powef your �е? Connect to Azure

�t·•

@

r..,

1tк.......

а

P...ctf'lll PtO]«Ь-6Solwoм ш

,...,....

Рис. 1 . 1 . Создание нового проекта в окне среды разработки Microsoft Visual Studio Express

27

Глава 1

G)

Н А ЗАМ ЕТ КУ

Для создания нового п роекта можно воспол ьзоваться п и ктограм­ мой на панел и инструментов или нажать комбинацию клавиш ++ . В результате появляется окно создания нового проекта, показанное на рис. 1 .2 .

S..tch lnsulltd ТempllttS (Cul • EJ Windows .tt.

Ttmplltti

"Vr.iш.IC• Clщн:D..i:top r

Ttst

V'wsual В.s1с



• \fr.sualC••

fotms Applt. На рис. 1 .23 показана ситуация, когда пользователь ввел текст, но еще не нажал клавишу < Enter>.

как вас зовут? АЛ е к с е й В ас и л ь е в•

111

1

Рис . 1 . 2 3 . Консольное окно с введенным текстом перед нажатием клавиши < Eпter>

52

Знакомство с языком С# Считывание введенного пользователем текста выполняется командой n ame = C o n s o l e . Re a d L i n e ( ) . Здесь из класса C o n s o l e вызывается статический метод Re a dL i n e ( ) . Метод считывает введенное пользова­ телем текстовое значение и возвращает это значение результатом. Текст запоминается с помощью текстовой переменной n ame. Еще одна тек­ стовая переменная объявляется и инициализируется командой s t r i n g t х t = " Очен ь прия т н о , " + n ame + " ! " . Значение переменной t х t фор­ мируется объединением текста " Оче н ь прия т н о , " , значения тексто­ вой переменной n ame и текста " ! " .

G)

Н А ЗАМ ЕТ КУ

И н и циализация переменной означает первое (после объя вления или во время объявления) п рисваиван ие значения этой переменной.

После этого командой C on s o l e . Ti t l е= " Знакомс т в о с о с т о ял о с ь " консольному окну присваивается новое название, а затем с помощью команды Co n s o l e . W r i t e L i n e ( t xt ) в консольном окне отображается значение переменной t x t . Как может выглядеть в этом случае консоль­ ное окно, показано на рис. 1 .24. а! Зн1комстsо состоялось

к а к Вас з о вут? Ал е к с е й В ас и л ь е в ч е н ь п р и я т н о , Ал е к с ей Васил ьев ! л я п р одолже н и я нажмите любую к л а в ишу

Р IЦ

' \..

111

�(ШJ� .

.

.



С:

J

Рис. 1 .24 . Консольное окно после отображения сообщения с текстом, введенным пользователем

G)

Н А ЗАМ ЕТ КУ

Сообщение Для продолжен ия наж м и те л юбую клави шу , кото­ рое появляется в консол ьном окне в последней строч ке , не и меет отношения к п рограмме и добавляется автоматически . . . .

Следовательно результат выполнения программы может быть таким, как показано ниже (жирным шрифтом выделено значение, введенное пользователем). 53

Глава 1

[1i!J Результат выполнения п рограммы (из листинга 1 . 6) Как Вас зовут ? Аnехсей Васильев Очень приятно , Алексей Василь ев !

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

С ч иты вание ч и сел Ни одной буквочки ! Ни одной 4МЭЙд ин". >.> .

и з к/ф -«Кин-дза-дза»

При считывании введенного пользователем значения с помощью мето­ да Re adL i n e ( ) (при консольном вводе) или метода I nputBox ( ) (при вводе через поле в диалоговом окне) значение, введенное пользовате­ лем, считывается как текст - даже если это число. Проще говоря, если пользователь введет, например, целочисленное значение, то считано оно будет как текст, состоящий из цифр (это называется текстовое пред­ ставление числа). Чтобы «извлечь>.> из такого текста число, необходимо использовать специальные методы. Для получения целочисленного зна­ чения на основе его текстового представления используют статический метод P a r s e ( ) из структуры I nt 3 2 (структура относится к простран­ ству имен S y s t em ) .

G)

Н А ЗАМ ЕТ КУ

В языке С# структура я вляется аналогом класса. Во всяком случае, различия между ними в основном «техн ические» . М ы будем детал ь­ но обсуждать и класс ы , и структуры .

Аргументом методу передается текстовое представление числа, а ре­ зультатом метод возвращает собственно число, «спрятанное>.> в тексте. Небольшой пример считывания целочисленного значения с помощью диалогового окна с полем ввода представлен в листинге 1 .7. Программа, которая представлена там, при выполнении отображает диалоговое окно с полем ввода, в которое пользователю предлагается ввести год своего рождения. Год рождения считывается, и на основе этой информации вы­ числяется возраст пользователя. А теперь рассмотрим код программы. 54

З нако мство с языком С#

[1i!] л истинг 1 . 7 . Считывание числа u s ing Sys tem; u s ing Micros oft . VisualBas i c ; u s ing Sys tem . Windows . Forms ; c l a s s Enteringi ntege r { s tatic vo id Main ( ) { 1 1 Текстовые переменные : s t ring re s , txt ; 1 1 Целочисленные переменные : int year=2 0 1 7 , age , born ; 1 1 Отображение окна с полем ввода : res=Interaction . I nputBox ( " B каком году Вы родились ? " , " Год рождения " ) ; 1 1 Преобразование текста в число : born=Int32 . Parse ( re s ) ; 1 1 Вычисление возраста : age=year - born ; tхt=" Тогда Вам " +age+" лет " ; 1 1 Окно с сообщением : Me s s ageBox . Show ( txt , " Boзpacт " ) ;

В программе подключаются пространства имен S y s t em, Mi c r o s o f t . Vi s u a l B a s i c и S y s t em . W i ndows . F o rm s . В главном методе объявля­ ются текстовые переменные r e s и txt (команда s t r i ng r e s , txt ) . Также объявляются три целочисленные переменные ye a r , age и b o r n (команда i n t ye a r= 2 0 1 7 , age , b o r n ) , причем переменной ye a r сразу присваивается значение 2 О 1 7 . Для определения типа мы исполь­ зовали идентификатор i n t , обозначающий целочисленный тип: пере­ менные такого типа значением могут принимать целые числа.

G)

Н А ЗАМ ЕТ КУ

Можно объя влять сразу нескол ько перемен ных одного ти па. В таком случае указы вается идентификатор типа переменных, и затем через 55

Глава 1

запятую переч исляются эти переменные . В случае необходи мости части из н их ( ил и всем перемен н ы м ) могут п рисваи ваться значения .

Командой r e s = I nt e ra c t i on . I nputBox ( " В каком г оду Вы роди­ ли с ь ? " , " Г о д р ожде ния " ) отображается окно с полем ввода. Первый аргумент метода I np u t B o x ( ) определяет текст, отображаемый в диа­ логовом окне сверху над полем ввода, а второй аргумент метода задает название диалогового окна. Как выглядит окно, показано на рис. 1 .25. ГОД ро ждеtШЯ

1 97111

Рис. 1 .25 . Диалоговое окно с полем для ввода целого числа

Введенное пользователем число в виде текстового значения запоминает­ ся с помощью переменной r e s . Для получения числового значения мы используем команду b o r n= I n t 3 2 . P a r s e ( re s ) . В результате в пере­ менную b o r n записывается целое число, введенное пользователем, при­ чем сохраняется это значение именно как число, поэтому с ним можно выполнять арифметические операции.

G)

Н А ЗАМ ЕТ КУ

Есл и пол ьзовател ь введет в поле диалогового окна не числ о , то при поп ытке п реобразовать введенный текст в целое ч исло возни кнет ошибка . Она также возни кает, есл и пол ьзовател ь нажмет вместо кнопки О К кнопку Отмена .

8о1раст То гдо В ом 39 лот

ок

Рис . 1 . 2 6 . Ди алоговое окно с сообщением, содержащим возраст пользователя

56

З нако мство с языком С# Для вычисления возраста пользователя выполняется команда a g e = ye a r -b o r n . Переменной a g e , находящейся слева от оператора присваивания, присваивается значение выражения, находящегося в пра­ вой части от оператора присваивания. А в правой части вычисляется раз­ ность значений переменных ye a r (текущий год) и b o r n (год рождения). После вычисления значения переменной age она используется в команде tхt= " Т о гда Вам " +age+ " ле т " , которой определяется текстовое зна­ чение, запоминаемое с помощью переменной t x t . В правой части от опе­ ратора присваивания указано выражение " Т о гда Вам " + age + " ле т " . Значением выражения является текст, получающийся объединением текстового фрагмента " Т огд а Вам " , значения переменной age и тек­ ста " ле т " . Наконец, командой Ме s s аgеВох . Show ( t xt , " Возра с т " ) отображается диалоговое окно с названием Возраст, в котором есть со­ общение с текстом, определяемым переменной t x t . Как может выгля­ деть такое окно, показано на рис. 1 .26. После закрытия диалогового окна выполнение программы завершается.

Форматирова н н ы й вывод - В таком виде я не могу. Мне нужно сначала принять ванну, выпить чашечку кофе . . . - Будет тебе там и ванна, будет и кофе, будет и какава с чаем. Поехали !

из к/ф «Брwu� иантовая рука»

В завершении главы сделаем небольшой комментарий относительно ис­ пользования методов W r i t e L i n e ( ) и W r i te ( ) и W r i te ( ) . Мы уже знаем, что методы предназначены для отображения в консольном окне значения, переданного аргументом методу.

G)

Н А ЗАМ ЕТ КУ

Напом н и м , что разница между методами WriteLine ( ) и Write ( ) состоит в том , что при испол ьзовании метода Wri teLine ( ) п осле отображения значения в консол ьном окне вы пол няется автоматиче­ ский переход к новой строке. При испол ьзовании метода Wri te ( ) такой переход не вы пол няется .

57

Глава 1 Но аргументы методу W r i t e ( ) или W r i t e L i n e ( ) можно передавать и несколько иначе. Первым аргументом передается текстовая строка. Эта строка содержит специальные блоки инструкций, которые будем на­ зывать блоками форматирования. В самом простом случае блок форма­ тирования представляет собой пару фигурных скобок с целочисленным индексом внутри: например { О } , { 1 } , { 2 } и так далее. После текстовой строки с блоками форматирования через запятую указываются значе­ ния, которые должны быть вставлены вместо блоков форматирования при отображении строки в консоли. Допустим, мы используем коман­ ду вида Wr i t е L i n е ( 11 Знач е ния { О } , { 1 } и { 2 } 11 , А , В , С ) . В таком случае в консольном окне отображается текст 11 З н ачения { О } , { 1 } и { 2 } 11 , но только вместо блока { О } вставляется значение пере­ менной А, вместо блока { 1 } вставляется значение переменной В, а вме­ сто блока { 2 } будет вставлено значение переменной С. Фактически ин­ декс в фигурных скобках - это индекс аргумента из списка аргументов, указанных после текстовой строки (первый по порядку элемент после текстовой строки имеет нулевой индекс). В текстовой строке ссылку на один и тот же аргумент можно выполнять несколько раз.

G)

Н А ЗАМ ЕТ КУ

Допускается, чтобы перемен ные или вы ражения , указанные п осле первого текстового аргумента в методе WriteLine ( ) или Write ( ) , был и разного типа.

Что касается собственно блоков форматирования, то они могут содер­ жать больше, чем просто индекс аргумента для вставки. Кроме индекса аргумента, в фигурных скобках можно указать способ выравнивания со­ держимого и формат отображения значения. Общий шаблон для блока форматирования выглядит так (жирным шрифтом выделены ключевые элемента блока форматирования): { индекс , ширина : формат }

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

З нако мство с языком С# определяющую способ (формат) отображения значения аргумента. Для определения формата отображения числового значения используют символ #, обозначающий цифру. Символ Х используют как индикатор для отображения числа в шестнадцатеричном формате, символ Е явля­ ется индикатором для использования экспоненциального формата, сим­ вол N используют как индикатор десятичного числа, символ С позволя­ ет применять денежный формат. Например, инструкция { О , 2 О : # . # # } означает, что при отображении первого аргумента (аргумента с нулевым индексом) следует использовать поле шириной в 2 О символов (не мень­ ше) и выравниваться значение будет по правому краю (поскольку ши­ рина поля задана положительным числом). Код # . # # означает, что в дробной части числа будет отображаться не больше двух цифр. Если мы хотим, чтобы параметры отображения были те же, но выравнивание выполнялось по левому полю, то используем код { О , - 2 О : # . # # } ( ши­ рина поля определяется отрицательным числом). Блок { О : Е } означает, что число отображается в экспоненциальном формате, а для использова­ ния шестнадцатеричного формата отображения числа используем блок { О : Х } . Далее в книге по мере необходимости мы еще будем возвращать­ ся к этому вопросу и комментировать способ передачи аргументов мето­ дам W r i te ( ) и W r i t e L i n e ( ) .

Р ез ю ме Нет денег. И деньги , и документы , и валюта все осталось у экскурсовода . Ну, так получи­ лось. Отошли на секундочку, и затерялись в песках.

из к/ф -«Кин-дза-дза»

• Программа на языке С# обязательно содержит класс с главным ме­ тодом. Выполнение программы - это выполнение программного кода главного метода. • Описание класса начинается с ключевого слова c l a s s , после кото­ рого указывается имя класса и, в фигурных скобках, описывается тело класса - в данном случае тело класса содержит описание глав­ ного метода. • Описание главного метода начинается с ключевого слова s t a t i c, далее указывают название метода Ma i n ( ) с пустыми круглыми 59

Глава 1 скобками. Команды главного метода размещаются в блоке из фигур­ ных скобок. • При необходимости с помощью инструкции u s i n g подключаются пространства имен. Часто используется пространство имен S y s t em. • Для консольного вывода используются статические методы Wri te ( ) и W r i t e L i n e ( ) класса C on s o l e из пространства имен S y s t em. Для отображения диалогового окна используют статический метод S h o w ( ) класса Me s s a g e B o x (доступен после подключения про­ странства имен S y s t em . W i ndows . F o rms ) . • Для консольного считывания текста используют метод Re adL i n e ( ) из класса C o n s o l e . Текст также можно вводить через окно с по­ лем ввода. Окно отображается статическим методом I np u t B o x ( ) из класса I n t e ra c t i o n . Класс доступен после подключения про­ странства имен Mi c r o s o ft . Vi s u a l Ba s i c . • Для работы с текстом используют переменные типа s t r i n g (псев­ доним для выражения S ys t em . S t r i n g ) . Целые числа реализуются с помощью переменных типа i n t . • Для преобразования текстового представления числа в целое число используют статический метод Р а r s е ( ) из структуры I n t 3 2 (про­ странство имен S y s t em ) .

Зада н ия для самостоятел ьной работы Как говорит наш дорогой шеф, в нашем деле главное - этот самый реализм !

из к/ф «Бриллиантовая рука»

1 . Напишите программу, в которой пользователь вводит сначала имя,

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

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

З нако мство с языком С# 3. Напишите программу, в которой пользователь последовательно вво­ дит название текущего дня недели, название месяца и дату (номер дня в месяце). Программа выводит сообщение о сегодняшней дате (день недели, дата, месяц). Используйте консольный ввод и вывод данных. Предложите версию программы, в которой для ввода и вывода данных используются диалоговые окна. 4. Напишите программу, в которой пользователю предлагается ввести название месяца и количество дней в этом месяце. Программа выводит сообщение о том, что соответствующий месяц содержит указанное коли­ чество дней. Предложите версии программы для ввода/вывода данных через консоль и с помощью диалоговых окон. 5. Напишите программу, в которой по году рождения определяется воз­

раст пользователя. Используйте консольный ввод и вывод данных.

6. Напишите программу, в которой пользователь водит имя и год рожде­ ния, а программа отображает сообщение, содержащее имя пользователя и его возраст. Предложите консольную версию программы, а также вер­ сию программы, в которой ввод и вывод данных выполняется с помо­ щью диалоговых окон. 7. Напишите программу, в которой по возрасту определяется год рожде­ ния. Возраст пользователь вводит в окно с полем, а вычисленный год рождения отображается в другом диалоговом окне. Предложите вариант программы, в которой используется консольный ввод и вывод данных. 8. Напишите программу для вычисления суммы двух чисел. Оба чис­

ла вводятся пользователем. Для вычисления суммы используйте опера­ тор + . Предложите два варианта программы: программу, в которой дан­ ные вводятся и выводятся с помощью диалоговых окон, и программу, в которой используется консольный ввод и вывод данных. 9. Напишите программу, в которой пользователь вводит число, а про­ граммой отображается последовательность из трех чисел: число, на еди­ ницу меньшее введенного, введенное число и число, на единицу боль­ шее введенного. Предложите версию программы с консольным вводом и выводом данных, а также версию программы, в которой ввод и вывод выполняется с помощью диалоговых окон. 1 О. Напишите программу, в которой пользователь вводит два числа, а про­

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

Гл ава 2 БАЗОВ Ы Е Т И ПЫ И О П Е РАТО РЫ

Я представитель цивилизованной планеты и требую , чтобы вы проследили бы за своим лексиконом !

из к/ф -«Кин-дза-дза»

В этой главе мы рассмотрим базовые типы данных и основные операто­ ры, используемые в языке С#. В частности: • мы узнаем, какие базовые (или примитивные) типы данных используются в С# ; • разберемся с особенностями объявления переменных ; • выясним, каким образом в языке С# реализуются литералы ; • познакомимся с автоматическим преобразованием типов и узнаем, как выполняется явное приведение типов ; • узнаем, какие базовые операторы есть в языке С#; • составим представление о способе двоичного кодирования чисел ; • выясним особенности оператора присваивания ; • познакомимся с тернарным оператором. И это не самый полный перечень тем, которые освещаются в главе. Нач­ нем с базовых типов данных, используемых в языке С# .

62

Базовые типы и операто ры

П еремен ные и базовые ти п ы дан н ых Милый, это ж театр ! Это тебе не в об а надо !

в

гл азок смо­

треть. Тут

из к/ф -« 0 бедном гусаре замолвите слово»

С переменными мы кратко познакомились в предыдущей главе. Напом­ ним, что переменной называется именованный блок памяти. Этот блок может хранить определенное значение. Мы в программе имеем возмож­ ность прочитать это значение и изменить его. Для получения доступа к блоку памяти используется переменная. Перед тем как переменную использовать, ее необходимо объявить. Объявление переменной подра­ зумевает, что указывается имя переменной и ее тип. При выполнении команды, которой объявляется переменная, для этой переменной в па­ мяти выделяется место. Каждый раз, когда мы будем обращаться к этой переменной, в действительности будет выполняться обращение к соот­ ветствующему месту в памяти. При этом совершенно не важно, где имен­ но в памяти выделено место под переменную. Нам достаточно знать имя переменной, чтобы прочитать ее текущее значение или присвоить новое. Тип переменной определяет, какие значения могут присваиваться пере­ менной. Также тип переменной влияет на то, какие операции можно вы­ полнять с переменной. В языке С# для каждой переменной должен быть указан тип. После объявления тип переменной не может быть изменен. Тип переменной определяется с помощью специального идентифика­ тора. Проще говоря, для каждого типа данных имеется свой идентифи­ катор, который указывают при объявлении переменной. Например, мы уже знаем, что если переменная объявлена с идентификатором типа i n t , т о значением такой переменной может быть целое число. Кроме целых чисел существуют другие типы данных. С ними мы и познакомимся.

G)

Н А ЗАМ ЕТ КУ

М ы познакоми мся с базовыми ти пами дан н ых ( и ногда их еще назы­ вают п росты м и или п римити вными ти пам и ) . Способы реал изаци и переменных, описываемые здесь, и меют отношение к перемен н ы м базовых т и п о в . Помимо базовых ти пов, существуют еще и ссылоч­ ные типы дан н ых. Дан ные ссылочного типа реал изуются нескол ько иначе по сравнению реал изацией данных базовых ти пов. Ссылоч­ ные типы м ы рассмотри м п р и знакомстве с классам и и массивам и . 63

Глава 2 В языке С# большинство базовых типов предназначено для реализации числовых значений (здесь имеются в виду целые числа и числа с плава­ ющей точкой), символьных значений (значением символьной перемен­ ной может быть отдельный символ) и логических значений (переменная логического типа может принимать одно из двух логических значений истина или ложъ ). Наибольшую группу составляют целочисленные типы - то есть типы данных, предназначенных для реализации целых чисел. Мы уже знакомы с одним из целочисленных типов (речь о типе i n t ) . Но кроме типа i n t в языке С# существуют и другие целочислен­ ные типы. На первый взгляд может показаться странным, что для реали­ зации целых чисел используется несколько типов данных. Но странного здесь ничего нет: хотя каждый раз имеем дело с целыми числами, запи­ сываются они по-разному. Если кратко, то есть две �позиции�, по кото­ рым отличаются способы реализации целых чисел (при использовании разных типов): • объем памяти, выделяемой для хранения числа ; • возможность или невозможность использовать отрицательные числа.



ПОДРОБН ОСТИ

Для записи цел ых ч исел в пам яти ком п ьютера испол ьзуется б и ­ товое представл е н и е . В с я память, выдел я емая для записи ч исла , разбита на отдел ь н ы е бл оки - биты . Кажды й б и т м ожет содержать в кач естве значения О ил и 1 . Блок из 8 битов называется байтом . Для хранения дан н ых оп редел е н ного типа выдел я ется одно и то же кол ичество бито в . Напри ме р , дл я записи знач е н и й типа int в язы ­ ке С# в ыдел яется 32 бита , ил и 4 байта . Таки м образом , значение типа int представляет собой п оследовател ьность из 32 нул ей и еди н и ц . Такой код и нтерп рети руется как дво и ч ное п редставле­ н и е ч исла . Ч ем бол ьше в ыделя ется битов дл я записи ч исла , тем бол ьше ч и сел можно закоди ровать. Есл и ч е рез n обознач ить ко­ л и ч ество бито в , с п ом ощью которых коди руются ч исла , то всего " с п омо щью такого кол ичества битов м ожно реал изовать 2 раз н ых ч и сел . Для значени й типа int кол ичество ч исел , которые м ожно 2 реал изовать через перемен ную дан н ого ти п а , равно 2 3 • Диапазон возможн ых знач е н и й для перем е н н ой типа int огран ичен ч и слам и 1 1 -2 3 ( ч исло - 2 1 4 7 4 8 3 64 8 ) и 2 3 - 1 ( ч исл о 2 14 7 4 8 3 64 7 ) в ключ ител ь­ 2 но. Всего ( с учетом нул я ) получается 2 3 раз н ых ч исел . Поскол ьку в общем случае п риходится кодировать не тол ько по­ ложител ьные, но и отри цател ьные ч исла , то оди н из битов ( стар­ ш ий бит) испол ьзуется как и ндикатор того , п ол ожител ьное ч и сло

64

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

Для реализации целых чисел, кроме типа i n t , используются типы byte, sbyte, s h o r t , u s h o r t , u i n t , long и u l o n g . Значения типов b y t e и sbyte кодируются с помощью 8 битов. Различие между типами в том, что значение типа b y t e - это неотрицательное число. Значение типа sbyte может быть и положительным, и отрицательным.

G)

Н А ЗАМ ЕТ КУ

Начал ьная буква s в назван и и типа sbyte - это «остаток» от слова «signed» ( что означает «СО знаком » ) .

С помощью 8 битов можно записать 2 8 2 5 6 разных чисел. Поэтому возможное значение для переменной типа byte лежит в пределах от О до 2 5 5 включительно. Значение переменной типа s b y t e находится в пределах от - 1 2 8 до 1 2 7 включительно. =

Для хранения значения типов s h o r t и u s h o r t выделяется 1 6 битов. То есть «мощность» этих типов одинакова. Но тип s h o r t использует­ ся для работы с отрицательными и положительными числами, а тип u s ho r t используют при работе с неотрицательными числами.

G)

Н А ЗАМ ЕТ КУ

Начал ьная буква и в назва н и и типа u s hort, а также в названиях рассматри ваем ых далее ти пов uint и ulong поя вилась из слова « u nsigned» ( что означает «без знака » ) .

Следующая пара типов i n t (числа с о знаком) и u i n t (неотрицательные числа) использует 32 бита для хранения числовых значений. Наконец, самые «мощные» целочисленные типы - это l o n g и u l o n g. Перемен­ ные данных типов хранятся в ячейках памяти объемом в 64 бита. Значе­ ния типа l o n g интерпретируются как числа со знаком, а значения типа u l o n g обрабатываются как неотрицательные числа. Более подробная информация не только о целочисленных типах, но и о прочих базовых типах языка С# приведена в табл. 2 . 1 . 65

Глава 2 Табл . 2 . 1 . Базовые типы языка С# Тип

Память Диапаз он в битах з пачепий

Описапие

Структур а

byte

8

от О до 255

Целое неотрицательное число

Byte

sbyte

8

от - 1 28 до 1 2 7

Целое число

SByte

short

16

о т -32768 д о 32767

Целое число

I nt l б

u s ho r t

16

о т О д о 65535

Целое неотрицательное число

U i nt l б

int

32

от - 2 1 47483648 до 2 1 47483647

Целое число

Int32

uint

32

от о до 4294967295

Целое неотрицательное число

Uint32

long

64

от -9223372036854775808 до 9223372036854775807

Целое число

I nt 6 4

u l ong

64

от о до 1 844674407370955 1 6 1 5

Целое неотрицательное число

Uint 64

float

32

о т 1 .5Е-45 д о 3.4Е+38

Действительное число (с плавающей точкой)

Single

douЫ e

64

от 5Е-324 до 1 .7Е+308

Действительное число (с плавающей точкой) двойной точности

DouЫe

dec imal

128

от 1 Е-28 до 7.9Е+28

Действительное число для выполнения особо точных (финансовых) расчетов

D e c im a l

char

16

о т о д о 65535

Символьное значение

Char

bool

8

значения t ru e и f a l s e

Логическое значение

Boolean

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

G)

Н А ЗАМ ЕТ КУ

В де йствител ьности значения базовых типов реал изуются как эк­ зем пляры структур . Структуры м ы рассмотрим нем ного позже . В табл . 2 . 1 для каждого базового типа указана структура , которая соответствует дан н ому ти пу. Фактически идентификаторы базовых

66

Базовые типы и операто ры ти пов являются псевдо н и мам и для назван и й структур . Напри ме р , для работы с цел ы м и ч ислам и можно создать перемен ную базово­ го типа int, что означает создание экзем пля ра структуры Int3 2 . То есть ситуация н е самая тривиал ьная , но в большинстве случаев это не и грает н и какой рол и .

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

G)

Н А ЗАМ ЕТ КУ

Для ч и сел с плавающей точкой также можно испол ьзовать экспонен­ циал ьное ( ком п ьютерное) п редставление в виде мантиссы и пока­ зателя степен и . Действител ьное ч исло представляется в виде п ро­ изведения мантиссы (действител ьное ч и сло) на 1 0 в целочисленной степе н и . Зап исать ч исло в таком п редставл е н и и можно следующи м образом : указать мантиссу, затем сим вол Е ( ил и е ) и целое ч и сл о , оп ределяющее показател ь степе н и . Напри ме р , вы ражение 1. SE-45 означает ч исло 1 , 5 х 1 0-45 , а вы ражение 3. 4Е+ 38 соответствует ч ис­ лу 3 ,4 х 1 0 38 • Есл и показател ь степени положител ьн ы й , то знак + можно не указы вать.

Для реализации действительных чисел используются типы f l o a t , douЫ e и de c ima l . Для значения типа f l o a t выделяется 32 бита, а под значение типа douЫ e выделяется 64 бита. Поэтому числа, реализован­ ные как значения типа douЬ l e , имеют большую «точность�. Наимень­ 45 шее по модулю f l о а t-число равно 1 ,5 х 1 0 - , а самое маленькое по мо­ 24 -3 дулю dоuЫ е -число равно 5 х 1 0 • Верхняя граница для значений типа 0 douЫ e составляет величину 1 ,7 х 1 0 3 8 , а f l о а t-значения ограничены сверху числом 3,4 х 1 03 8 • В этом смысле тип douЫ e является более предпочтительным.

G)

Н А ЗАМ ЕТ КУ

Есть и другая п р и ч и на для приоритетного испол ьзования типа douЫe по сравнению с типом float . Ее м ы обсудим нем ного позже .

Помимо типов f l o a t и douЫ e в языке С# есть тип de c ima l . Под значение типа de c ima l выделяется 1 2 8 битов, что в два раза боль­ ше, чем для типа d o uЬ l e . Но главное назначение такой мощной 67

Глава 2 �поддержки� - обеспечить высокую точность вычислений, выполняе­ мых со значениями типа de c ima l . Обычно необходимость в высокой точности операций возникает при финансовых расчетах. Поэтому обыч­ но тип de c ima l упоминают как специальный тип, предназначенный для поддержки высокоточных финансовых вычислений. Для работы с символьными значениями предназначен тип char. Значе­ нием переменной типа c ha r может быть отдельный символ (буква). Для хранения такого значения в памяти выделяется 1 6 битов.



ПОДРОБН ОСТИ

Значения типа char коди руются так же , как и цел ые ч исла - и меем дело с 1 6 битам и , запол н е н ны м и нуля м и и еди н и цам и . Аналоги ч н ы м образом коди руются , напри ме р , значения типа u s hort. Поэтому техн ически сhаr - значение можно рассматри вать как неотри цател ь­ ное числовое значение, которое попадает в диапазон цел ых ч исел от О до 6 5 5 3 5 . Но обрабатывается такое значение нескол ько и наче (по сравне н и ю с обработкой целочисленных значени й ) , а и менно : по двоич н ому коду оп ределяется ч и сл о , и затем из кодовой табл и цы берется сим вол с соответствующи м кодом .

Наконец, тип b o o l предназначен для работы с логическими значения­ ми. Поэтому этот тип обычно называют логическим. Переменная логи­ ческого типа может принимать одно из двух значений: t ru e (истина) или f a l s e (ложь). Значения логического типа используются в управ­ ляющих инструкциях - таких, как условный оператор или операторы цикла.

Л итерал ы - Ч то они хотят ? - Ку они хотят" .

из к/ф -«Кин-дза-дза»

Под литералами подразумевают константные (такие, которые нель­ зя изменить) значения, используемые в программном коде. Приме­ рами литералов являются число 1 2 3 (целочисленный литерал), текст " Изуч а ем С # " (текстовый литерал) или буква ' ы ' (символьный

68

Базовые типы и операто ры литерал). То есть это некоторые фиксированные значения, понятные для программиста, которые могут использоваться в программе. Но пи­ кантность ситуации в том, что такие значения в программе реализуются по тому же принципу, что и переменные. Другими словами, каждый ли­ терал имеет определенный тип (или относится к определенному типу), и обрабатывается литерал в соответствии с правилами работы со зна­ чением данного типа. Возникает вопрос: к какому типу относится, на­ пример, целочисленный литерал 1 2 3 ? Понятно, что это целое число. Но для реализации целочисленных значений существует несколько ти­ пов, и в данном конкретном случае любой из них теоретически подходит для реализации числа 1 2 3 . Ответ же состоит в том, что число 1 2 3 реали­ зуется как i n t -значение. Вообще есть несколько правил, определяющих способ реализации литералов. • Целочисленный литерал реализуется как значение �наименьшего� типа, начиная с типа с i n t , достаточного для сохранения значения литерала. • Действительные числовые литералы (число с плавающей точкой, как, например, число 1 2 . 3 ) реализуются в виде значений типа douЬ l e . • Символьные литералы заключаются в одинарные кавычки (напри­ мер, ' F ' или ' я ' ) и реализуются как значения типа c h a r . • Текстовые литералы (текст) заключаются в двойные кавычки (на­ пример, " Язык С # " или " А " ) и реализуются как объекты класса S t r i n g из пространства имен S y s tem (мы используем идентифи­ катор s t r i ng для выражения S y s t em . S t r i n g).

G)

Н А ЗАМ ЕТ КУ

Си м вол ьн ый л итерал закл ючается в оди нарные кавыч ки , а тексто­ вый - в двой н ы е . Си м вол ьн ы й л итерал - это оди н символ . Текст может содержать м ного символо в . Но есл и оди н сим вол заключ ить в двой н ые кавыч ки , то это будет текст, а не си мвол ь н ы й л итерал . И ны м и словам и , вы ражение ' А ' п редставля ет собой символьны й л итерал , а вы ражение " А " я вляется текстовы м л итерал ом (состоя­ щи м из одного символа) . И хотя с формал ьной точки зрения в обоих случаях м ы и меем дело с одн и м и тем же сим волом , с техн ической точки зрения м ы и меем дело со значения м и разных ти п о в , реал изо­ ванн ых совершенно п о - разному.

69

Глава 2 Описанные выше правила применяются при реализации литералов по умолчанию. Но мы можем вносить в этот процесс разумные коррек­ тивы. Так, если мы хотим, чтобы целочисленный литерал реализовался как l оng-значение, надо использовать суффикс L или 1 . Например, ли­ терал 1 2 3 L означает число 1 2 3 , реализованное как значение типа l o ng. Если воспользоваться суффиксом U или и , то целочисленный литерал будет реализован как значение типа u i n t . Суффикс U L (а также u l , U l и u L ) позволяет определить литерал типа u l ong - например, выра­ жение 1 2 3 U L определяет число 1 2 3 , реализованное как значение типа u l ong. Если необходимо, чтобы числовой литерал реализовался как f 1 оа t-зна­ чение, используют суффикс F или f. Например, выражение 1 2 . 3 F опре­ деляет число 1 2 . 3 как значение типа f l o a t . Если использовать суффикс М или m в числовом литерале, получим чис­ ло, реализованное как значение типа de c ima l . Примером может быть выражение 1 2 . 3М.

G)

Н А ЗАМ ЕТ КУ

Целочисленн ые значения м ожно представлять шестнадцатерич­ н ы м и л итералам и . Шестнадцатерич н ы й л итерал нач и н ается с сим­ волов О х или О Х . В п редставл е н и и шестнадцатерич ного л итерала испол ьзуются цифры от О до 9 , а также лати нские буквы от А до F для обозначения ч и сел от 1 0 до 1 5 соответствен н о . Буквы можно испол ьзовать как строч н ы е , так и прописные. Есл и шестнадцате­ рич н ы й л итерал записан в виде последовател ьности цифр и букв anan_ 1 а 2а1 а0 , В которой ak (k=O, 1 , 2 , . . . , П) ЭТО цифры ОТ 0 ДО 9 ил и буквы от А до F, то в десятич н ой системе сч исления такое ч ис­ 1 2 ло выч исляется как а " а "_ 1 а 2а 1 а0 = а0 х 1 6 ° + а 1 х 1 6 + а 2 х 1 6 + . . . " 1 " + а " _ 1 х 1 6 - + а" х 1 6 . П р и этом вместо букв А , В . . . F подставля ются ч исла 1 О , 1 1 . . . 1 5 . Например, л итералу O x 2 F 9 D соответствует деся ­ 1 2 тичное ч исло 1 3 х 1 6° + 9 х 1 6 + 1 5 х 1 6 + 2 х 1 63 = 1 2 1 89 . • • •

-

• • •

70

Базовые типы и операто ры

У п равля ю щие с и м вол ы - И быть тебе з а это рыбой , мерзкой и скольз­ кой ! - Д а , но обещали котом ! - Недостоин !

из к/ф �Формула лю бви»

В С# есть группа символов, которые называются управляющими. Фор­ мально это символы, но при их «печатании� обычно выполняется опре­ деленное действие. Все управляющие символы начинаются с обратной косой черты \ . После обратной косой черты указывается некоторый символ. Например, выражение \ n является инструкцией перехода к но­ вой строке, а инструкция \ t представляет собой инструкцию для выпол­ нения горизонтальной табуляции.

G)

Н А ЗАМ ЕТ КУ

Хотя вы ражение \ n или \ t формал ьно состоит и з двух символов, интерп рети руется каждое из них как оди н символ . Поэтому такое выражение можно присвоить значен ием сим вол ьной переменной : выражение как сим вол закл ючается в оди нарные кавычки ( п олучаем л итерал ы ' \ n ' и ' \ t ' ), и такой л итерал п рисваи вается значением переменной типа char ( ил и испол ьзуется другим образом ) .

Если в текстовом литерале присутствует инструкция \ n и такой лите­ рал передан аргументом методу Wr i t e L i n e ( ) , то при отображении это­ го литерала в соответствующем месте будет выполнен переход к новой строке. Инструкция \ t в процессе отображения литерала обрабатывает­ ся так: курсор оказывается в ближайшей позиции табуляции.

G)

Н А ЗАМ ЕТ КУ

Строку, в которую выводится текст, можно условно раздел ить на « позици и » , п редназначенные для отображения символов. Среди этих « позици й » есть «особые» или « реперные» - обычно это каж­ дая восьмая « позици я » . То есть «особыми» я вляются 1 -я , 9-я , 1 7-я , 25-я и так далее позици и . Когда нужно « напечатать» инструкци ю \ t , то курсор «прыгает» в бл ижай шую « реперную» позици ю . Следующи й сим вол будет отображаться именно там . 71

Глава 2 Кроме перечисленных выше, можно выделить управляющие символы \ а (звуковой сигнал), \Ь (инструкция перемещения курсора на одну позицию назад) и \ r (инструкция перемещения курсора в начало текущей строки).



ПОДРОБН ОСТИ

Нередко возникает потребность испол ьзовать в текстовых и сим­ вол ьных л итералах двойные и одинарные кавычки или обратную косую черту. П роблема в том , что просто так добавить соответству­ ющи й сим вол не получ ится : обратная косая черта я вляется п р и ­ знаком управляющего сим вола, а двойные и оди нарные кавычки испол ьзуются для выделения л итералов (текстовых и сим вол ьных соответствен н о ) . Решение п роблемы состоит в том , чтобы исполь­ зовать допол нител ьную обратную косую черту. Например, двойные кавычки в л итерал добавля ются в виде вы ражения \ " , вы ражение \ ' можно испол ьзовать для добавления в л итерал оди нарной кавыч­ ки , а вы ражение \ \ полезно , есл и необходи мо добавить в л итерал ( одну) обратную косую черту.

G)

Н А ЗАМ ЕТ КУ

Есл и перед текстовым л итералом указать сим вол @ , то такой л итерал становится «буквал ьн ы м » или «не форматируемым» : он отображает­ ся так, как записан. Такой л итерал не подлежит форматированию, он испол ьзуется « как есть» . Например, есл и м ы передадим аргумен­ том методу WriteLine ( ) текстовый л итерал " Изуч аем \ n я зык С # " , то из-за наличия в л итерале инструкци и \ n в первой строке кон­ сол ьного окна появится текст " Изуч ае м " , а во второй - текст " я зык С # " . Но есл и передать аргументом буквал ьный текстовый л итерал @ " Изуч аем \ n я зык С # " , то в консол ьном окне появится текст " Изуч аем \ n я зык С # " .

П реобра зова н и е типов - Может, его за Нерона нам выдать - к ак будто ? - Где же ты видел Неронов в лаптях и онучах ?

из к/ф -« 0 бедном гусаре замолвите слово»

Нередко в выражения входят значения разных типов. Скажем, может возникнуть необходимость к значению типа f l o a t прибавить значение 72

Базовые типы и операто ры типа i n t и полученный результат присвоить переменной типа douЬ l e . Математически здесь все корректно, поскольку речь идет о б арифмети­ ческой операции с числами, результат этой операции представляется в виде действительного числа, а целые числа являются подмножеством чисел действительных. Но в плане программной реализации подобной операции мы имеем дело со значениями трех разных типов. К счастью, в языке С# есть встроенные механизмы, позволяющие сводить к мини­ муму неудобства, связанные с использованием в выражениях значений разных типов. В ситуациях, подобных описанной выше, выполняется ав­ томатическое преобразование типов. Обычно речь идет о преобразова­ ниях различных числовых типов. Есть несколько правил выполнения таких преобразований. И так, допустим, имеются два операнда, которые относятся к разным числовым типам. Алгоритм выполнения преобразо­ ваний такой: • Если один из операндов относится к типу de c ima l , то другой ав­ томатически преобразуется к типу de c ima l . Но если другой опе­ ранд - значение типа f l o a t или douЬ l e , то возникает ошибка. • Если один операнд - типа douЬ l e , то другой автоматически преоб­ разуется в тип douЬ l e . • Если один операнд относится к типу f l o a t , то другой операнд будет преобразован в значение типа f l o a t . • Если в выражении есть операнд типа u l ong, т о другой операнд авто­ матически приводится к типу u l ong. Ошибка возникает, если дру­ гой операнд относится к типу sbyte, s h o r t , i n t или l o ng. • Если в выражении есть операнд типа l o ng, то другой операнд будет преобразован в тип l ong. • Если один из операндов относится к типу u i n t , а другой операнд значение типа sbyte, s h o r t или i n t , то оба операнда расширяются до типа l ong. • Если в выражении оба операнда целочисленные, то они преобразу­ ются в тип i n t . Эти правила применяются последовательно. Например, если в выраже­ нии один из операндов относится к типу de c ima l , то выполняется по­ пытка преобразовать второй операнд к тому же типу, и если попытка успешная, то вычисляется результат. Он также будет относиться к типу de c ima l . До выполнения прочих правил дело не доходит. Но если 73

Глава 2 в выражении нет операндов типа de c ima l , тогда в игру вступает вто­ рое правило: при наличии операнда типа douЫ e другой операнд пре­ образуется к этому же типу, такого же типа будет результат. Далее, если в выражении нет ни операнда типа de c ima l , ни операнда типа douЬ l e , т о применяется третье правило (для типа f l o a t ) , и так далее. В этой схеме стоит обратить внимание на два момента. Во-первых, об­ щий принцип состоит в том, что автоматическое преобразование выпол­ няется к большему (в плане диапазона допустимых значений) типу, так, чтобы потеря значения исключалась - то есть автоматическое преоб­ разование выполняется всегда с расширением типа. Отсюда становит­ ся понятно, почему при попытке преобразовать значения типа douЫ e и f l o a t к значению типа de c ima l возникает ошибка. Хотя для значе­ ний типа de c imal выделяется 1 2 8 битов (и это больше, чем 64 бита для типа douЫ e и 32 бита для типа f l o a t ) , но диапазон допустимых зна­ чений для типа de c ima l меньше, чем диапазоны допустимых значений для типов douЫ e и f l o a t . Поэтому теоретически преобразуемое зна­ чение может быть потеряно, а значит, такое автоматическое преобразо­ вание не допускается.

G)

Н А ЗАМ ЕТ КУ

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

Во-вторых, если в выражении оба операнда целочисленные, то даже если ни один из них не относится к типу i n t (например, два операнда типа s h o rt), то каждый из операндов приводится к типу i n t , и, соот­ ветственно, результат также будет типа i n t . Это простое обстоятель­ ство имеет серьезные последствия. Допустим, мы командой s h o r t a = l О объявили переменную а типа s h o r t со значением 1 0 . Если после это­ го мы попытаемся использовать команду a=a + l , то такая команда бу­ дет некорректной и программный код не скомпилируется. Причина в том, что числовой литерал 1 , использованный в команде, относится к типу i n t . Поэтому в выражении a + l текущее значение переменной 74

Базовые типы и операто ры а преобразуется к типу i n t , и результат выражения a + l также вычис­ ляется как i n t -значение. Таким образом, получается, что мы пытаемся присвоить значение i n t -типа переменной типа s ho r t . А это запрещено, поскольку может произойти потеря значения.



ПОДРОБН ОСТИ

При выч ислении вы ражения а + 1 считы вается значен ие переменной а , и это число преобразуется к типу int . Сама перемен ная как была типа s h o r t , так переменной типа short и остается .

Решение проблемы может состоять в том, чтобы использовать явное приведение типа. Корректная команда выглядит так: а= ( s h o r t ) ( a+ l ) . Здесь идентификатор short в круглых скобках перед выражением ( а+ 1 ) означает, что после вычисления значения выражения полученный резуль­ тат (значение типа int) следует преобразовать в значение типа s h o r t .



ПОДРОБН ОСТИ

Для значен ия типа i n t в памяти выделяется 32 бита . Значение типа short запоминается с помощью 1 6 битов. П реобразован ие значе­ ния типа int в значение типа s h o r t выполняется путем отбрасы­ вания содержи мого в старших 1 6 битах i n t -значен ия . Есл и int ­ ч исло не очень бол ьшое (не выходит за диапазон s h о r t -значен ия ) , то старшие биты заполнены нул я м и (для положител ьного числа) , и при их отбрасы вании значение п отеряно не будет. Но даже есл и в старших битах не нул и , то биты все равно отбрасываются , и значе­ ние может быть потеряно. Поэтому п реобразован ие значения типа int в значение типа s h o r t - это потен циал ьно опасное п реобразо­ ван ие. Такие преобразования автоматически не выполняются . В не­ котором смысле инструкция ( s h o r t ) свидетел ьствует о том , что п рограм м ист понимает риск и берет ответственность на себя . Есть еще одно важное обстоятел ьство : при ини циал изации пере­ менной s h o r t командой short a= l O перемен ной типа short при­ сваи вается л итерал 1 0 , который я вляется значением типа i n t . Хотя формал ьно здесь тоже вроде бы проти вореч ие, но при п р исваива­ нии целочисленной переменной целочислен ного л итерала, есл и по­ следн и й не выходит за допусти мые предел ы для переменной данно­ го типа, при ведение ти пов выполняется автоматически .

Еще один пример: командой b y t e a = l , Ь=2 , с объявляем три пере­ менные ( а , Ь и с ) типа b yt e . Переменные а и Ь инициализируются 75

Глава 2 со значениями 1 и 2 соответственно. Но если мы захотим воспользо­ ваться командой с = а +Ь, то такая команда также будет некорректной. В отличие от предыдущего случая здесь нет литерала типа i n t . Здесь вычисляется сумма а+Ь двух переменных типа byte, и результат при­ сваивается (точнее, выполняется попытка присвоить) переменной типа byte. Проблема же в том, что, хотя в выражении а+ Ь оба операнда отно­ сятся к типу byte, они автоматически преобразуются к типу i n t (в со­ ответствии с последним пунктом в списке правил автоматического пре­ образования типов), и поэтому результатом выражения а +Ь является значение типа i n t . Получается, что мы пытаемся присвоить Ьуtе -пе­ ременной in t -значение, а это неправильно. Чтобы исправить ситуацию, необходимо использовать явное приведение типа. Корректная версия команды присваивания выглядит как с= ( b yte ) ( а +Ь ) .

G)

Н А ЗАМ ЕТ КУ

Есл и п реобразование цел ых чисел в действител ьные в случае необ­ ходимости выполняется автоматически , то обратное п реобразова­ ние требуется выполнять в я вном виде . Например, есл и нам нужно п реобразовать значение типа douЫ e в значен ие типа i n t , то пе­ ред соответствующим вы ражением указы вается инструкция ( i nt ) . П реобразование выполняется отбрасыванием дробной части дей ­ ствител ьного ч исла . Например, есл и командой douЫ e х= 1 2 . 6 объ­ является перемен ная х типа douЫ e со значением 1 2 . 6 , а командой int у объя вляется переменная у типа i n t , то в резул ьтате вы полне­ ния команды у= ( i nt ) х переменная у получ ит значение 1 2 . При этом значение переменной х не меняется .

Арифметическое выражение может содержать не только числовые, но и символьные операнды. В таких случаях сhа r-операнд автомати­ чески преобразуется к i n t-типу. Например, выражение ' А ' + ' в ' име­ ет смысл. Результат такого выражения - целое число 1 3 1 . Объяснение простое: значения типа c h a r (то есть символы) хранятся в виде целых чисел. Это последовательность из 16 битов. Вопрос только в том, как ее интерпретировать. Для целых чисел такая последовательность ин­ терпретируется как двоичное представление числа. Для символов �пре­ образование� двоичного кода выполняется в два этапа: сначала по дво­ ичному коду определяется число, а затем по этому числу определяется символ в кодовой таблице. Проще говоря, 1 6 битов для с h а r-значе­ ния - это код символа в кодовой таблице. Если символ нужно преобра­ зовать в целое число, то вместо символа используется его код из кодовой 76

Базовые типы и операто ры таблицы. У буквы ' А ' код 6 5 , а у буквы ' В ' код 6 6 , поэтому сумма сим­ волов ' А ' + ' в ' дает целочисленное значение 1 3 1 . Преобразование типа c h a r в тип i n t в случае необходимости выпол­ няется автоматически. Обратное преобразование (из целого числа в тип char) выполняется в явном виде. Например, результатом команды char s = ( ch a r ) 65 является объявление символьной переменной s со значе­ нием ' А ' . Принцип преобразования целого числа в символ такой: пре­ образуемое целочисленное значение определяет код символа в кодовой таблице. Так, поскольку у буквы ' А ' код 6 5 , то значением выражения ( cha r ) 6 5 будет символ ' А ' .

G)

Н А ЗАМ ЕТ КУ

Уч итывая п равила автоматического п реобразования типов и спо­ соб реал изаци и числовых л итералов, можно дать следующую реко­ мендаци ю : есл и нет объекти вной необходимости поступать иначе, то для работы с целочисленными значен иями разумно испол ьзовать переменные типа int , а для работы с действител ьн ы м и значен иями имеет смысл испол ьзовать перемен ные ти па douЫ e .

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

из к/ф �Формула лю бви»

Мы уже знаем (в общих чертах), что такое переменная и как она определя­ ется. Здесь сделаем некоторое обобщение. И так, напомним, что переменная предназначена для хранения в памяти некоторого значения. Переменная предоставляет пользователю доступ к области памяти, где хранится зна­ чение. С помощью переменной это значение можно прочитать и, в случае необходимости, изменить. Значение переменной присваивается в формате переменная=значение, то есть используется оператор присваивания =, слева от которого указывается переменная, которой присваивается зна­ чение, а справа значение, присваиваемое переменной. -

Перед использованием переменная должна быть объявлена. Сделать это можно практически в любом месте программного кода, но обязательно 77

Глава 2 до того, как переменная начинает использоваться. Объявляется пере­ менная просто: указывается ее тип и название. При этом можно: • Объявлять сразу несколько переменных, если они относятся к од­ ному типу. В таком случае после идентификатора типа названия переменных указываются через запятую. Например, инструкцией i n t A , В , С объявляются три переменные ( А, В и С), каждая типа i n t . • При объявлении переменной можно сразу присвоить значение (ини­ циализировать переменную). Так, командой s h o r t х= 1 2 объявля­ ется переменная х типа s h o r t , и этой переменной присваивается значение 1 2 . Командой i n t А= 5 , В , C= l O объявляются перемен­ ные А, В и С типа i n t , переменной А присваивается значение 5 , а пе­ ременной С присваивается значение 1 О . • Разрешается выполнять динамическую инициализацию переменной: это когда переменная инициализируется на основе выражения, в ко­ торое входят другие переменные. Главное условие для динамической инициализации состоит в том, что переменные, входящие в выра­ жение, на момент вычисления выражения должны иметь значения. Проще говоря, для динамической инициализации можно использо­ вать только те переменные, которым уже присвоены значения. На­ пример, сначала с помощью команды i n t x= l O , у=2 0 мы можем объявить переменные х и у со значениями 1 О и 2 О соответственно, а затем командой i n t z =x + y объявляем и динамически инициали­ зируем переменную z . Значение этой переменной будет равно 3 0 , поскольку на момент вычисления выражения х + у переменные х и у имеют значения 1 О и 2 О . Важный момент: между переменными z , с одной стороны, и х и у, с другой стороны, функциональная связь не устанавливается. Если после инициализации переменной z мы изменим значение переменной х или у, то значение переменной z не изменится. • При объявлении переменной вместо идентификатора типа мож­ но использовать ключевое слово v a r . С помощью одной vа r ­ инструкции может объявляться одна переменная (то есть нельзя использовать одну vаr-инструкцию для объявления сразу несколь­ ких переменных). Переменная, объявляемая в v а r - инструкции, должна сразу инициализироваться, и тип такой переменной опре­ деляется типом литерала (или типом значения выражения), ини­ циализирующим переменную. Например, командой v a r z = l O 78

Базовые типы и операто ры объявляется переменная z . Переменная z относится к типу i n t , поскольку значение 1 О , которое присваивается переменной, пред­ ставляет собой целочисленный литерал, а целочисленные литера­ лы реализуются как значения типа i n t . Но если мы воспользуемся командой v a r z = l O . О , то в таком случае переменная z будет типа douЬ l e , поскольку литерал 1 О . О реализуется как значение типа douЬ l e . Наконец, команда v a r z = l O F определяет переменную z типа f l o a t . Причина проста: литерал l O F (из-за суффикса F) ре­ ализуется как f l о а t -значение, и это определяет тип перемен­ ной z. Ситуация может быть и более сложной. Скажем, командой b y t e x= l , у=2 объявляется две Ь у t е -переменные (х и у со зна­ чениями 1 и 2 соответственно) . Если после этого мы объявим пере­ менную z командой v a r z =x + y, то значением переменной z будет число 3 , а сама переменная будет типа i n t . Почему? Потому что при вычислении выражения х + у, несмотря на то что оба операнда являются Ь у t е - переменными, по правилам автоматического пре­ образования типов их значения преобразуются в числа типа i n t , и результат (число 3 ) также представлен числом типа i n t . Поэтому тип переменной z - целочисленный тип i n t . • Наряду с переменными могут использоваться и константы. Прин­ ципиальное отличие константы от переменной состоит в том, что значение константы изменить нельзя. Как и переменная, констан­ та объявляется. Но кроме идентификатора типа и имени констан­ ты, указывается еще и ключевое слово c o n s t . При объявлении константа инициализируется: указанное при инициализации зна­ чение константы впоследствии изменить не получится. Например, командой c o n s t i n t num= 1 2 3 объявляется константа num типа i n t , и значение этой константы равно 1 2 3 . Командой c o n s t c h a r f i r s t = ' А ' , s e c ond= ' в ' объявляются две символьные константы f i r s t и s e c o n d со значениями ' А ' и ' В ' соответственно.

Существует такое понятие, как областъ доступности (или область види­ мости) переменной. Это место в программном коде, где переменная мо­ жет использоваться. Правило очень простое: переменная доступна в том блоке, в котором она объявлена. Блок, в свою очередь, определяется па­ рой фигурных скобок. Поэтому если переменная объявлена в главном методе программы, то она доступна в этом методе (начиная с того места, где переменная объявлена). 79

Глава 2



ПОДРОБН ОСТИ

Далее мы узнаем , что главным методом область испол ьзован ия пе­ ремен н ых не ограничи вается . Есть и другие хорошие места в про­ грамме, где могут испол ьзоваться переменные . Более того , даже в главном методе могут быть внутренние блоки . Скажем , часть ко­ манд в главном методе мы можем закл юч ить в фигурные скобки . Други м и словам и , блоки кода могут содержать внутренние блоки кода , которые, в свою очередь, также могут содержать внутренние блоки , и так далее. Переменная , объя вленная в некотором блоке (например, в главном методе ) , доступна и во всех внутренних бло­ ках. Но не наоборот: есл и перемен ная объя влена во внутреннем блоке , то во внешнем она не доступ на. Допусти м , главн ый метод п рограм м ы и меет такую структуру: s t a t i c vo i d Ma i n ( ) { / / Переме н н а я о б ъ я в л е н а в г л а в н о м ме т оде : int А ; / / Команды { / / Начало в нутр е н н е г о блока / / Переменна я объявлена в о внутренне м блоке : int В ; / / Команды } / / З а в ершение в нутре н н е г о блока / / Команды

Здесь мы имеем дело с перемен ной А, объя вленной в главном ме­ тоде , и переменной В , объя вленной во внутреннем блоке . П ричем внутрен н и й блок - это часть команд, заключенны х в фигурн ые скоб­ ки . В этом случае перемен ная А доступ на везде в главном методе , вкл ючая внутрен н и й блок. Но вот перемен ную В можно испол ьзовать тол ько во внутреннем блоке . Вне этого блока переменная «не суще­ ствует» . Название перемен ной, объя вленной во внутреннем блоке , не может совпадать с названием перемен ной, объя вленной во внешнем бло­ ке . Это означает, что есл и м ы объя вили в главном методе перемен­ ную А, то объя вить во внутреннем блоке главного метода перемен­ ную с таким же именем м ы не може м .

80

Базовые типы и операторы

А рифметичес кие операторы - Что они кричат ? - Прод ают. - Ч то продают ? - Все продают.

из к/ф -«Кин-дза-дза »

Далее мы рассмотрим основные операторы, используемые в языке С#. Начнем с арифметических операторов, используемых при выполнении арифметических операций. Вообще же все операторы в языке С# обыч­ но разделяют на четыре группы: •

арифметические операторы ;



логические операторы ;



операторы сравнения ;



побитовые операторы.

Также в языке С# есть тернарный оператор. Да и оператор присваива­ ния не такой простой, как может показаться на первый взгляд. Все эти вопросы мы обязательно обсудим. Ну а пока - арифметические опера­ торы.



П ОД РО Б Н ОСТИ

Оператор - это некий сим вол , обозначающий оп ределен ную опе­ раци ю . Оператор испол ьзуется с операндом ил и операндам и . Опе­ раци я , оп ределяемая оператором , выполняется с операндам и . Есл и оператор испол ьзуется с одн и м операндо м , то такой оператор на­ зы вается унарн ы м . Есл и оператор испол ьзуется с двумя операнда­ м и , то такой оператор назы вается бинарн ы м . В языке С# также есть один оператор, который испол ьзуется аж с тремя операндам и . Этот оператор назы вается тернарн ы м .

Назначение большинства арифметических операторов интуитивно по­ нятно каждому, кто хотя бы в минимальном объеме сталкивался с ма­ тематикой. В табл. 2 . 2 представлен полный перечень арифметических операторов языка С#. Там же дано краткое их описание.

81

Глава 2 Табл . 2 . 2 . Арифметические операторы Оператор

Описание

+

Оператор сложения. Значением выражения вида А+В является сумма зна­ чений переменных А и В Оператор вычитания. Значением выражения вида А- В является разность значений переменных А и В

*

Оператор умножения. Значением выражения вида А * В является произве­ дение значений переменных А и В

/

Оператор деления. Значением выражения вида А / В является частное значений переменных А и В. Если оба операнда А и В целочисленные, то деление выполняется нацело. Для выполнения обычного деления с це­ лочисленными операндами перед выражением указывают инструкцию -

( douЬ l e )

%

Оператор вычисления остатка от деления. Значением выражения вида А% В является остаток от целочисленного деления переменных А и В

++

Оператор инкремента. При выполнении команды вида А + + или ++А значе­ ние переменной А увеличивается на 1 Оператор декремента. При выполнении команды вида А - - или - - А значе­ ние переменной А уменьшается на 1

Описание операторов дано в предположении, что операнд (или операн­ ды) является числовым. Вместе с тем это не всегда так. Так, в операции сложения с использованием оператора + один или оба операнда могут быть, например, текстовыми. В таком случае выполняется объединение текстовых строк. Скажем, если к тексту прибавить число, то числовой операнд автоматически преобразуется в текстовый формат и результа­ том выражения является текст, получающийся объединением �сумми­ руемых» текстовых фрагментов. Имеет свои особенности и оператор деления. Дело в том, что если де­ лить два целых числа, то выполняется целочисленное деление. Напри­ мер, результатом выражения 1 2 / 5 будет не 2 . 4 , как можно бьшо бы ожидать, а целое число 2 (целая часть от деления 1 2 на 5 ) . Но вот ре­ зультат выражения 1 2 . 0 / 5 или 1 2 / 5 . О это число 2 . 4 . Объяснение простое: в выражении 1 2 / 5 оба операнда целочисленные, а в выраже­ ниях 1 2 . О / 5 и 1 2 / 5 . О целочисленный только один операнд. Поэто­ му в выражении 1 2 / 5 речь идет о целочисленном делении, а значения выражений 1 2 . О / 5 и 1 2 / 5 . О вычисляются с использованием обычно­ го деления. Если а и Ь целочисленные переменные (например, типа i n t ) , то при вычислении выражения а /Ь используется целочисленное деление. Если нужно, чтобы деление было обычным, используют коман­ ду вида ( douЬl e ) а / Ь. -

-

82

Базовые типы и операто ры Оператор % позволяет вычислить остаток от целочисленного деления. Причем операнды могут быть не только целыми, но и действительными числами. В таком случае результатом выражения вида А % В может быть не только целое, но и действительное число.



ПОДРОБН ОСТИ

Есл и А и в некоторые числа (действител ьные, в том числе они могут быть и отрицательн ы м и ) , то остаток от деления А на в (обознач им эту операцию как А%В ) вычисляется следующим образом . Сначала нахо­ дится наибол ьшее по модул ю целое число n , такое, что 1 nв 1 :5: 1 А 1 при условии совпадения знаков А и nв , и резул ьтат операции А%В вы­ А - nв . Например, есл и А 13, 7 и в 3, 1, ч исля ется как А%В 4 ( nB 1 2 , 4 ) И А% В А - nB 13, 7 - 12 , 4 1, 3. то n -13 , 7 и в - 4 ( nB - 1 2 , 4 ) и А%В 3 , 1 , то n А Есл и А nв -13 , 7 + 12 , 4 - 1 , 3 , и так далее . Есл и А и В целочисленные перемен ные, то резул ьтат вы ражения А%В совпадает с разностью значен и й переменной А и вы ражения В * ( А / В ) (то есть значения вы ражений А%В и А-В * ( А / В ) в этом слу­ чае совпадают) . =

=

=

=

=

=

=

=

=

=

=

=

=

=

=

-

Если все предыдущие операторы ( +, - , * , / и % ) были бинарными, то опера­ торы инкремента + + и декремента - - являются унарными - они исполь­ зуются с одним, а не с двумя операндами. У каждого из этих операторов есть префиксная и постфиксная формы: в префиксной форме операто­ ры инкремента и декремента указываются перед оператором (например, + +А или - -А), а в постфиксной форме сначала указывается операнд, а за­ тем - оператор (например, А++ или А- - ). В плане влияния на значение операнда префиксная и постфиксная формы эквивалентны. При выпол­ нении команды вида ++А или А++ значение переменной А увеличивается на 1 . Команда вида - -А и А- - означает уменьшение значения перемен­ ной А на 1 . Но разница между префиксными и постфиксными формами все же есть. Дело в том, что выражения вида + +А, А++, - -А и А- - име­ ют значения. Проще говоря, инструкцию ++А или, скажем, А - - мы мо­ жем интерпретировать как некоторое число (если операнд А числовой). То есть, помимо прямых последствий для операнда, само выражение на основе оператора инкремента или декремента может использовать­ ся в более сложном выражении. Правило такое: значением выражения с оператором инкремента или декремента в префиксной форме является новое (измененное) значение операнда, а значением выражения с опера­ тором инкремента или декремента в постфиксной форме является старое 83

Глава 2 (до изменения) значение операнда. Например, командой i n t А= 1 О , В объявляются две переменные А и В, и переменная А получает значение 1 О . Если затем выполняется команда В=А+ +, то переменная В получит зна­ чение 1 0 , а значение переменной А станет равным 1 1 . Почему? Потому что при выполнении инструкции А++ значение переменной А увеличива­ ется на 1 и становится равным 1 1 . Но переменной В значением присваи­ вается не значение переменной А, а значение выражения А++. Значение выражения А++, поскольку использована постфиксная форма оператора инкремента, - это старое (исходное) значение переменной А (то есть зна­ чение 1 О ). А вот если бы мы вместо команды В=А+ + использовали коман­ ду В=+ +А, то и переменная А, и переменная В получили бы значение 1 1 . Причина в том, что значением выражения + +А с оператором инкремента в префиксной форме является новое значение переменной А (число 1 1 ).

G)

Н А ЗАМ ЕТ КУ

После выполнения команд i n t A= l O , В и В=А- - у перемен ной А будет значение 9 , а у перемен ной В будет значение 1 0 . Есл и коман­ ду В=А - - замен ить на В=--А, то обе перемен ные А и В будут иметь значение 9 .

При выполнении арифметических операций, помимо числовых опе­ рандов, могут использоваться и символьные значения (значения типа c h a r ). В таком случае выполняется автоматическое преобразование значения типа c h a r в числовое значение (используется код соответ­ ствующего символа из кодовой таблицы). В этом смысле мы вполне мо­ жем вычислить, например, разность ' D ' - ' А ' (результат равен 3 - раз­ ность кодов символов ' D ' и ' А ' ).



ПОДРОБН ОСТИ

Операторы ин кремента и декремента также могут испол ьзоваться с символ ьным операндом . Но здесь есть одна особен ность. Допу­ сти м , командой char s ymb= ' А ' мы объя вили сим вол ьную пере­ мен ную s ymb со значением ' А ' . Есл и м ы испол ьзуем вы ражение s yrnЬ + 1 , то его значением я вляется целое ч исло 66 ( к коду 65 симво­ ла ' А ' прибавляется 1 ) . Поэтому, чтобы с помощью такого вы раже­ ния в переменную s yrnЬ зап исать следующи й символ после сим вола ' А ' , нужно испол ьзовать команду s ymb= ( char ) ( s yrnЬ + l ) . Буквы ал ­ фавита в кодовой табл и це идут одна за друго й , поэтому следующи м после сим вола ' А ' будет сим вол ' В ' , затем сим вол ' С ' и так далее. 84

Базовые типы и операто ры Значен ие выражения s yrnЬ + l - ч исло 6 6 , которое является кодом сим вола ' В ' в кодовой табл и це . Резул ьтат вы ражения s ymb+ 1 явно при водится к сим вол ьному виду, и полученное ч исло и нтерп рети­ руется как код сим вола. В результате значением переменной s ymb будет сим вол ' В ' . А вот есл и мы воспол ьзуемся выражением s yrnЬ + + ( ил и + + s yrnЬ ) , то значение переменной s yrnЬ станет равным ' В ' . Дело в том , что в плане последствий для операнда А выражение А++ (или + +А) экви­ валентно команде вида А= ( тип А) ( А+ 1 ) . То есть к исходному значе­ нию операнда А прибавляется еди н и ца , полученный резул ьтат при­ водится к типу операнда А , и это значение п рисваи вается операнду А. Есл и операнд А - ч ислово й , то факт при ведения типа не стол ь ва­ жен . Но вот есл и операнд символ ьн ы й - то момент с при ведением типа важен . Это же замечан ие относится и к оператору декремента .

G)

Н А ЗАМ ЕТ КУ

Помимо бинарных операторов сложения + и выч итания - есть еще унарные операторы « ПЛ ЮС» + и « м и нус» - . Унарн ый « м и нус» пишется перед отри цател ьны м и числами (то есть испол ьзуется для обозна­ чения отри цател ьных ч исел ) . Унарн ы й « ПЛЮС» обычно не испол ьзу­ ется , поскол ьку числа без знака по умолчанию интерп рети руются как положител ьн ые, но в п ринципе его можно писать.

Операторы сравнен ия Когда у общества нет цветовой дифференци­ ации штанов , то нет цели ! А когда нет цели нет будущего !

из к/ф -«Кин-дза-дза»

Операторы сравнения все бинарные и используются для сравнения зна­ чений переменных или литералов. Результатом выражения на осно­ ве оператора сравнения является логическое значение (значение типа b o o l ). Если соотношение истинно, то результатом является значение t ru e , а если соотношение ложно, то результатом является значение fa l s e . В табл. 2.3 перечислены и кратко описаны операторы сравнения, используемые в языке С#. 85

Глава 2 Табл . 2 . 3 . Операторы сравнения Оператор

Описание


=В равно f a l s e Оператор «равно ». Значение выражения вида А==В равно t ru e , если значение операнда А равно значению операнда В. В противном случае значение выражения А==В равно f a l s e

!=

Оператор «Не равно ». Значение выражения вида А ! =В равно t ru e , если значение операнда А не равно значению операнда В. В противном случае значение выражения А ! =В равно f а 1 s е

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

G)

Н А ЗАМ ЕТ КУ

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

Л огич еские операторы - Встань-ка вон там , у той липы. - В аше сиятельство, это не липа, это дуб. - Да ? А выглядит как липа . . .

из к/ф « 0 бедном гусаре замолвите слово»

Операндами в выражениях на основе логических операторов являют­ ся значения логического типа ( t r u e или f a l s e ) , и результатом таких 86

Базовые типы и операто ры выражений также являются значения логического типа. Логические операторы полезны для того, чтобы на основе некоторых простых ус­ ловий (логических значений) получить новое более сложное условие (логическое). Логические операторы перечислены и кратко описаны в табл. 2.4. Табл . 2 . 4 . Логические операторы Оператор

Описапие

&

Оператор �логическое и». Результатом выражения А & В является зна­ чение t ru e , если оба операнда А и В равны t ru e . Если хотя бы один из операндов равен f a l s e , то результатом выражения А & В является значение f a l s e

&&

Оператор �логическое и» (упрощенная форма). Значение выражения вида А& &В равно t ru e , если оба операнда А и В равны t ru e . В против­ ном случае результат выражения равен f a l s e . Если при вычислении первого операнда А оказалось, что он равен f a l s e , то значение второго операнда В не вычисляется Оператор �логическое или». Результатом выражения А 1 в является зна­ чение t ru e , если хотя бы один из операндов А или В равен t ru e . Если оба операнда равны f a l s e , то результатом выражения А 1 В является значение f a l s e

1 1

Оператор �логическое или» (упрощенная форма). Значение выраже­ ния вида А 1 1 В равно t ru e , если хотя бы один из операндов А или В равен t ru e . В противном случае результат выражения равен f a l s e . Если при вычислении первого операнда А оказалось, что о н равен t ru e , то значение второго операнда В не вычисляется Оператор �логическое исключающее или». Результатом выражения А л в является значение t ru e , если один и з операндов А или В равен t ru e , а другой равен f a l s e . Если оба операнда равны f a l s e или оба опе­ ранда равны t ru e , то результатом выражения д л в является значение fal se

Оператор �логическое отрицание». Значение выражения ! А равно t ru e , если значение операнда А равно f a l s e . Если значение операнда А равно t ru e , то значение выражения ! А равно f a l s e

Логические операторы позволяют выполнять четыре операции: «логи­ ческое и», «логическое или», «логические исключающее или» и «логическое отрицание». Более сложные логические операции выполняются путем комбинированного использования логических операторов. Для выпол­ нения операций «логическое и» и «логическое или» можно использовать две формы операторов (основную и упрощенную). Правила вычисления результата для операции «логическое и» проиллю­ стрированы в табл. 2.5. 87

Глава 2 Табл . 2 . 5. Оп ерация «логическое И» ( А & В или А & & В )



t ru e

fal se

t ru e

t ru e

fal s e

false

false

fa l s e

Если операнды А и В отождествлять с некоторыми условиями, то «слож­ ное� условие А & В (или А & & В ) состоит в том, что истинно и условие А, и условие В. Другими словами, значение выражения А & В (или А & & В) бу­ дет равно t ru e , только если равно t ru e значение операнда А и одновре­ менно равно t ru е значение операнда В. Очевидно, что если при проверке значения операнда А окажется, что его значение равно f а 1 s е, то резуль­ татом логической операции будет f а 1 se вне зависимости от того, како­ во значение операнда В. Этот факт принимается во внимание в работе упрощенной формы оператора & & : если при вычислении значения вы­ ражения вида А & & В оказалось, что значение операнда А равно f a l s e , то значение операнда В вообще не будет вычисляться. При вычислении значения выражения вида А & В значение операнда В вычисляется вне за­ висимости от того, какое значение операнда А.

(D

Н А ЗАМ ЕТ КУ

На первый взгляд может показаться , что разл ичие между операто­ рами & и & & «косметическое» . Но это не так. П роилл юстрируем это на небол ьшом примере. Допусти м , имеются две целочисленные пе­ ременные х и у. Рассмотрим выражение (х ! = 0 ) & ( y/ x > l ) . П роанал и­ зируем, как будет вычисляться значение такого вы ражения . Сначала вычисляется значение вы ражения х ! = О . Оно равно t rue , если зна­ чение переменной х отлично от нул я . Затем вычисляется значение выражения y / x> l . Оно равно t rue , есл и частное от деления у на х больше 1 . П роблема в том , что есл и значение переменной х равно О , то при выч ислении выражения у / х возникнет ошибка (деление на нол ь ) . А вот есл и вместо вы ражения (х ! = 0 ) & ( y/ x > l ) взять выра­ жение (х ! = 0 ) & & ( y/ x > l ) , то п роблема с делением на нол ь сни мает­ ся автоматически : есл и значение переменной х равно О , то значение выражения х ! = О равно f a l s e и условие y / x > l вообще вычисляться не будет.

88

Базовые типы и операто ры Как вычисляется результат операции «логические или», демонстрирует табл. 2.6. Табл . 2 . 6 . Операция «логическое или» (А 1 в ил и А 1 1 в )



true

false

t ru e

t ru e

t ru e

false

true

fal se

« Сложное» условие А 1 В (или А 1 1 В ) состоит в том, что истинно хотя бы одно условие, А или В. Значением выражений А 1 В или А 1 1 В является fa l s e только в том случае, если оба операнда А и В равны f a l s e. Поэ­ тому если при вычислении значения операнда А окажется, что его зна­ чение равно t ru e , то в принципе значение второго операнда В можно не вычислять - результат от этого не зависит. Именно по такой схеме «работает» упрощенная форма оператора 1 1 . При использовании опера­ тора 1 значение второго операнда вычисляется вне зависимости от зна­ чения первого операнда. Для операции «логическое исключающее или» можно дать такую интер­ претацию: результат является истинным, если у операндов разные зна­ чения. Более детально это показано в табл. 2.7. Табл . 2 . 7 . Оп ерация «логическое исключающее или» ( А л в )



true

false

true

false

t ru e

false

true

false

При одинаковых значениях операндов А и В значением выражения А л в является f а 1 s е , а если значения операндов А и В разные, то результатом выражения является значение t ru e .

89

Глава 2

G)

Н А ЗАМ ЕТ КУ

Операци ю «логическое исключающее или " можно выпол н ить с по­ мощью операторов & , 1 и ! . Желающие могут п роверить, что для логи­ ческих значений А и В резул ьтаты выражений д л в и ( А 1 В ) & ( ! ( А & В ) ) совпадают.

Оператор ! для выполнения операции

Условный оператор позволяет выполнять разные блоки команд в зави­ симости от истинности или ложности некоторого условия (выражение со значением логического типа). Работает это так: сначала вычисляется значение некоторого логического выражения (условие). Если значение выражения равно t ru e (условие истинно), выполняется определенный блок команд. Если значение выражения равно f a l s e (условие ложно), выполняется другой блок команд.

Условие t r ue

, 1

>" " - -

, , ... - - - - �.

f a l se

... ,

...

, - - "

" .\ ,

" ' , '

1 1 \

1

'

1

""

\ " ... "

,

' '

1

1

-\

Команды

,-- \

, - - ..,

'

, '·

Команды

,�.

. '

' 1 1

�-

1 ,

' -

i f - бл о к

'

,_ .... ' 1 ,

' '

1

- - ' ' ' , -' - ,

... _ _ _ ...

, , ,, ... " _ " ,

,'

,

,

'

1 1

�"-

'

е l s е - бл о к

\

,

, . - -

\

' ,

'

1 ' - -:

' , _

...\ ,

... ... _ _ ... ...

,

,'

,, ... _ _ _ "

Рис. 3. 1 . П р и н ци п ы выпол н е н и я условного оператора Описывается условный оператор достаточно просто: указывается клю­ чевое слово i f, после которого в круглых скобках следует условие, проверяемое при выполнении условного оператора. Блок команд, вы­ полняемых при истинном условии, указывается в фигурных скобках сразу после ключевого слова i f с условием ( i f-блок). Команды, пред­ назначенные для выполнения в случае ложного условия, указываются 116

Управля ющие инструкции в фигурных скобках после ключевого слова e l s e ( е l s е -блок). Шаблон описания условного оператора приведен ниже (жирным шрифтом выде­ лены ключевые элементы шаблона): if (условие ) { 1 1 Команды - если условие истинно

else { 1 1 Команды - если условие ложно

Принципы выполнения условного оператора также проиллюстрирова­ ны в схеме на рис. 3. 1 .

Условие f a l se

t r ue

1 1

,

,

" - - - ...:. .

, - - ... ,, ... - - ... ... 1

\ •-,

'

К оманды

,'' \

1 1 \

1

\ 1 1

1 1

'

� ... _ : \ " ... _ :: '

'

i f - блок 1

" ... ..,. _ _

" ...\ ... " ... _ _ ... ... r. '·',

...

,

'

'

'._ , - ' /

_ _ _ ,

Рис. 3.2. Выполнение условного оператора в упрощенной форме Если блок состоит всего из одной команды, то фигурные скобки для вы­ деления блока можно не использовать. У условного оператора есть упрощенная форма, в которой отсутству­ ет е l s е -блок. Если так, то оператор выполняется следующим обра­ зом: проверяется условие, и, если оно истинно, выполняются команды в i f-блоке. Если условие ложно, то ничего не происходит - выполня­ ется команда, следующая после условного оператора. Шаблон описания 1 17

Глава З условного оператора в упрощенной форме такой (жирным шрифтом вы­ делены ключевые элементы шаблона): if (условие ) { / / Команды - если условие истинно

Как выполняется условный оператор в упрощенной форме, иллюстри­ рует схема на рис. 3.2. Небольшой пример, иллюстрирующий работу условного оператора, представлен в листинге 3. 1 .

� Листин г 3. 1 . Использовани е условно го оператора us ing Sys tem . Windows . Forms ; us ing Micros oft . Vi sualBas i c ; c l a s s Usingi fDemo { s tatic vo id Main ( ) { / / Переменная для определения типа пиктограммы : Me s s ageBoxi con icon ; / / Переменные для определения текста сообщения , / / заголовка окна и имени поль зователя : s t ring msg , t i t l e , name ; / / Считывание имени пользователя : name=Interaction . InputBox ( / / Текст над полем ввода : " Как Вас зовут ? " , / / Название окна : " Знакомимся " ) ; / / Проверка введенного поль зователем текста : i f ( name== " " ) { / / Если текст не введен / / Пиктограмма ошибки : icon=Me s s ageBoxi con . Error; / / Текст сообщения : msg= " Очень жаль , что мы не познакомилис ь ! " ;

118

Управля ю щие инструкции 1 1 Заголовок окна : titlе=" Знакомство не состоялось " ;

e l s e { / / Если текст введен 11 Информационная пиктограмма : icon=Me s s ageBoxi con . I nformation ; 1 1 Текст сообщения : msg= " Очень приятно , " +name+ " ! " ; 1 1 Заголовок окна : titlе=" Знакомство состоялось " ;

1 1 Отображение сообщения ( аргументы - текст / / сообщения , заголовок, кнопки и пиктограмма ) : Me s s ageBox . Show (msg, title , Mes sageBoxButton s . OK , icon) ;

Программа простая: отображается окно с полем ввода, и пользователю предлагается ввести туда имя. Затем появляется новое диалоговое окно с сообщением, которое содержит введенное пользователем имя. Но это, если имя пользователь ввел. Однако пользователь в первом окне может на­ жать кнопку отмены или закрыть окно с помощью системной пиктограммы с крестом. Вот такая ситуация и обрабатывается с помощью условного опе­ ратора. А именно, мы воспользуемся тем, что если пользователь закрывает окно с полем ввода без ввода текста, то соответствующий метод возвращает пустую текстовую строку. Чтобы легче было понять, как организован про­ граммный код, рассмотрим результат выполнения программы. Сначала, как указывалось, появляется окно с полем ввода, представленное на рис. 3.3. Зкакомимс.я

IAnoo l O ) { 1 1 Отображение сообщения : Console . WriteLine ( " Oгo, как много букв ! " ) ;

1 1 Если в строке не больше десяти символов : else { 1 1 Отображение сообщения : Console . WriteLine ( " Oгo, как мало букв ! " ) ;

1 1 Е сли введена пустая строка : else { Console . WriteLine ( "Жaль , что не ввели текст ! " ) ;

Алгоритм выполнения программы простой: пользователю предлагается ввести текстовое значение, и это значение считывается и записывается в текстовую переменную. Затем в дело вступают вложенные условные операторы. Во внешнем операторе проверяется, не пустая ли введенная пользователем текстовая строка. И если строка не пустая, то во внутрен­ нем условном операторе проверяется, не превышает ли длина строки значение 1 О . В зависимости от истинности или ложности этих условий в консольное окно выводятся разные сообщения. 126

Управля ющие инструкции Для записи текстового значения, введенного пользователем, использу­ ется переменная t x t . Значение считывается командой txt=Co n s o l e . Re adL i n e ( ) . Во внешнем условном операторе проверяется условие t x t ! = " " . Если условие ложно, то выполняется команда C o n s o l e . W r i t e L i n e ( " Жал ь , ч т о не в в ели т е к с т ! " ) в е l s е -блоке внеш­ него условного оператора. Если же условие t x t ! = " " во внешнем ус­ ловном операторе истинное, то в i f-блоке сначала выполняется коман­ да C on s o l e . Wr i t e L i n e ( " Спа сибо , ч т о в в ели т е к с т ! " ) , после чего на сцену выходит внутренний условный оператор. В этом опера­ торе проверяется условие txt . Length> l O . Здесь мы воспользовались свойством L e n gth, которое возвращает количество символов в тексто­ вой строке. Следовательно, условие txt . Length> l O истинно в случае, если текстовая строка, на которую ссылается переменная t x t , содер­ жит больше 1 0 символов. Если так, то выполняется команда Co n s o l e . W r i t e L i n e ( " O г o , как мн о г о букв ! " ) в i f-блоке внутреннего ус­ ловного оператора. Если условие t x t . L e n g t h > 1 О ложно, то выпол­ няется команда C o n s o l e . Wr i t e L i n e ( " О г о , как мало букв ! " ) в е l s е -блоке внутреннего условного оператора. Таким образом, возможны три принципиально разных случая: •

пользователь не ввел текст ;



пользователь ввел текст, состоящий больше чем из 1 О символов ;



пользователь ввел текст, состоящий не больше чем из 1 О символов.

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

[1i!J Резул ьтат выполнения программы (из листинга 3.3 ) Введите текст : Изучаем С# Спасибо , что ввели текст ! Ого, как мало букв !

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

[1i!J Резул ьтат выполнения программы (из листинга 3.3 ) Введите текст : Продоmкаем изучать С#

127

Глава 3 Спасибо , что ввели текст ! Ого, как много букв !

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

� Резул ьтат выпол нения программы (из листинга 3.3 ) Введите текст : Жаль , что не ввели текст !

Еще один пример, рассматриваемый далее, иллюстрирует схему с вло­ женными условными операторами, когда каждый следующий вну­ тренний условный оператор формирует е l s е -блок внешнего условно­ го оператора. Программа, представленная в листинге 3.4, выполняется по простой схеме: пользователь вводит целое число (предположительно, от 1 до 4), а программа выводит текстовое название этого числа.

� Листинг 3. 4 . Определение ч исл а us ing Sys tem; c l a s s Anothe rNe stedi fDemo { s tatic vo id Main ( ) { 1 1 Переменная для запоминания введенного числа : int numЬe r ; 1 1 Отображение сообщения : Console . Write ( " Bвeдитe целое число : " ) ; 1 1 Считывание числа : numbe r= Int 3 2 . Parse ( Console . Read1ine ( ) ) ; 1 1 Е сли введена единица : i f ( numЬer==l ) Console . WriteLine ( "Eдиницa " ) ; 1 1 Е сли введена двойка : e l s e i f ( numbe r==2 ) Console . WriteLine ( " Двoйкa " ) ; 1 1 Е сли введена тройка : e l s e i f ( numbe r==З ) Console . WriteLine ( " Tpoйкa " ) ; 1 1 Е сли введена четверка :

128

Управля ющие инструкции e l s e i f ( numbe r==4 ) Console . WriteLine ( "Чeтвepкa " ) ; 1 1 Все прочие случаи : e l s e Console . WriteLine ( " Heизвecтнoe число " ) ;

Программа «узнает� числа от 1 до 4 включительно. В начале выполне­ ния программы командой C on s o l e . W r i te ( " Введите целое чис ­ л о : " ) отображается приглашение ввести целое число. Число считы­ вается командой n umb e r = I n t 3 2 . P a r s e ( C o n s o l e . Re a dL i n e ( ) ) и записывается в переменную n umЬe r. Затем задействуется блок из вло­ женных условных операторов, в каждом из которых проверяется введен­ ное значение. При наличии совпадения в консольном окне появляется сообщение соответствующего содержания (название введенного числа). Если пользователь ввел число, не попадающее в диапазон значений от 1 до 4 , то выполняется команда C o n s o l e . W r i t e L i n e ( " Неиз в е с т н о е число " ) . Ниже показано, как может выглядеть результат выполнения программы, если пользователь вводит «знакомое� для программы чис­ ло (здесь и далее жирным шрифтом выделено введенное пользователем значение).

[1i!J Резул ьтат выполнения программы (из листинга 3. 4) Введите целое число : 2 Двойка

Если программе не удается идентифицировать число, то результат та­ кой.

[1i!J Резул ьтат выполнения программы (из л истинга 3. 4) Введите целое число : 5 Неизвестное число

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

129

Глава 3

Оператор выбора switch Нет-нет, шуба подождет. Я считаю, что глав­ ное - посмотреть на мир.

из к/ф «Бриллиан товая рука»

Оператор выбора swi tch позволяет выполнить проверку значения не­ которого выражения. В языке С# выражение, которое проверяется с по­ мощью оператора выбора swi t ch, может возвращать значение целочис­ ленного, символьного или текстового типа. Описывается оператор выбора следующим образом. Сначала указывается ключевое слово swi t ch, после которого в круглых скобках следует проверяемое выражение. Тело операто­ ра выбора заключается в фигурные скобки. Там описываются с а s е-блоки. Каждый такой блок начинается с ключевого слова c a s e . После него указы­ вается контрольное значение (заканчивается двоеточием). Каждый с а s е ­ блок содержит набор команд, заканчивающийся инструкцией break. Кон­ трольные значения в с а s е-блоках сравниваются со значением выражения в switсh-инструкции. Если совпадение найдено, то выполняются коман­ ды в соответствующем с а s е-блоке. На случай, если совпадения нет, в опе­ раторе выбора s w i t ch может быть предусмотрен блок de fau l t . Общий шаблон описания оператора выбора swi tch с тремя с а s е-блоками пред­ ставлен ниже (жирным шрифтом выделены ключевые элементы шаблона): switсh(выражение){ case значение

1:

1 1 Команды break ; case значение 2 : 1 1 Команды break ; case значение 3 : 1 1 Команды break ; default : 11 Команды break ;

130

Управля ю щие инструкции Блок de fau l t не является обязательным - его можно не указывать со­ всем. На рис. 3.6 показана схема, иллюстрирующая способ выполнения оператора выбора s w i t c h .

' 1

1

'

'

,

..,, , -

, , ... " - - - - - - - (::: , , , ...

' · · -

(

---

не

'

,

...

... _

,

,,

...

'

'

\" " ,

'

о б я з а тел ь ный

_

...

... ," "

' " ... ... " блок ' ... ...

...

,

)--

:

'

/

'

_к _о _м _а.вды _ _ _ _ _

О

break

)

_ _

" ...

... _ _ _ _

_ , ,' "" - - - ' �

Рис. 3. 6. В ы полнение оператора вы б ора 131

Глава 3 Таким образом, при выполнении оператора выбора сначала вычисляется значение выражения в s w i t сh-инструкции. Полученное значение по­ следовательно сравнивается с контрольными значениями в с а s е -бло­ ках. При первом же совпадении выполняются команды в соответству­ ющем с а s е -блоке - вплоть до инструкции b r e a k. Если совпадение не найдено и в операторе выбора есть de fau l t -блoк, то выполняются команды в этом блоке. Если совпадение не найдено и de f a u l t-блока в операторе выбора нет, то ничего не происходит.



ПОДРОБН ОСТИ

И усл о в н ы й операто р , и оператор выбора, и рассматриваемые далее операторы цикл а - все переч исленные управл я ющие и н ­ струкци и есть не тол ько в языке С# , но и , скажем , в языках С++ и Java . Даже бол ьше - там они п рактически такие же , как в язы­ ке С# . И в плане си нтаксиса, и в плане п р и н ципов выпол нения . Но вот оператор выбора в С# немного особ ы й . Во-первых, кро­ ме цел оч исленных и сим вол ьных вы раже н и й в операторе выбора мо гут испол ьзоваться и текстовые вы ражения . Такого нет в языке С++ (там п роверяемое в ы ражение может быть целоч исл е н н ы м или символ ь н ы м ) . Во - вторых, в С# в операторе выбора, есл и с а s е ­ блок непусто й , он должен заканчи ваться Ь r е а k - и нструкцие й . В от­ л и ч и е от С#, в языках С++ и Java с а s е -блок может заканчи ваться инструкцией b r e a k , но это не обязател ьно. Вообще , инструкция b r e a k испол ьзуется для завершения работы оп ераторов цикл а или оператора выбора. Само по себе завершение ко манд в с а s е - бл оке оператора выбора работу это го оператора не завершает. Други­ м и сл овам и , есл и в каком -то с а s е - бл оке команды выпол н ил и с ь , т о это к автоматическому завершению в ы п о л н е н и я всего операто ­ ра выбора не п р и водит. Чтобы заверш ить оператор выбора, нужна инструкция b r e a k . Ч исто гипотетически , есл и бы с а s е - бл ок не за­ кан ч и вался инструкцией b r e a k , то п осл е завершения выполнения команд в это м бл оке должно было бы начаться выпол нение команд в следующем с а s е - блоке (даже есл и нет сов падения с контрол ь­ ным значением в этом блоке ) . В языках С++ и Java все так и п роис­ ходит. Что касается языка С # , то здесь п р и про верке знач ения в ы ­ ражения и срав нении е г о с контрол ь н ы м и знач е н и я м и с а s е - бл оки могут переби раться не в том по рядке , как они указан ы в операторе выбора. П оэтому в ы пол н е н и е кода необходимо огранич ить л и ш ь блоком , для которого выявлено сов падение контрол ьного значе­ н и я со значением п роверяемого вы ражения . Как бы там н и был о , но в языке С# непустые с а s е - блоки и блок de fau l t заканчива­ ются инструкцией b r e a k . Как и зачем испол ьзуются пустые с а s е ­ блоки - обсудим немного позже .

132

Управля ющие инструкции Несложно заметить, что в некотором смысле оператор выбора напоми­ нает блок из вложенных условных операторов, хотя полной аналогии здесь, конечно, нет. Небольшой пример, в котором использован опера­ тор выбора, представлен в листинге 3.5. Фактически это альтернативный способ реализации программы с вложенными условными операторами, в которой по введенному пользователем числу определяется название этого числа (см. листинг 3.4). Но на этот раз вместо условных операто­ ров использован оператор выбора s w i t ch.

� Листинг 3. 5 . З накомство с оператором выбора u s ing Sys tem; u s ing Sys tem . Windows . Forms ; u s ing Micros oft . VisualBas i c ; c l a s s SwitchDemo { s tatic vo id Main ( ) { / / Переменная для запоминания введенного числа : int numЬer; / / Переменная для записи названия числа : s t ring name ; / / Считывание числа : numbe r=I nt 3 2 . Parse ( Interaction . I nputBox ( / / Текст над полем ввода : "Введите число : " , / / Заголовок окна : "Число " ) ); / / Использование оператора выбора для определения / / названия введенного числа : switch ( numЬe r ) { case 1 :

/ / Если ввели число 1

nаmе=" Единица " ;

/ / Название числа

break;

/ / Завершение блока

case 2 :

/ / Если ввели число 2

133

Глава 3 nаmе=" Двойка " ;

/ / Название числа

break;

/ / Завершение блока

case 3 :

/ / Если ввели число 3

nаmе=" Тройка " ;

/ / Название числа

break;

/ / Завершение блока

case 4 :

/ / Если ввели число 4

nаmе= "Четверка " ;

/ / Название числа

break;

/ / Завершение блока

de fault :

/ / Ввели другое число

/ / Текст сообщения : nаmе= " Неизвестное число " ; break;

/ / Завершение блока

} / / Завершение оператора выбора / / Отображение сообщения : Me s s ageBox . Show ( name , "Чиcлo " ) ;

Предыдущая версия программы была консольной. Эта версия для вво­ да числа и вывода сообщения использует диалоговые окна. Но это от­ личие �косметическое» . Идеологически важное отличие состоит в том, что здесь мы используем оператор выбора s w i t c h . Целочисленная переменная numb e r предназначена для записи числа, которое вво­ дит пользователь. Текстовая переменная n ame нужна для того, чтобы сформировать и запомнить текстовое значение - название введенного пользователем числа. Для считывания числа используем статический метод I np u t B o x ( ) класса I n t e r a c t i o n . Для преобразования тек­ стового представления числа в целое число используем статический метод P a r s e ( ) из структуры I n t 3 2 . Результат записывается в пере­ менную numb e r . Для проверки значения переменной numb e r использован оператор выбора. Проверяемым выражением в нем является эта переменная. В с а s е -блоках указаны контрольные значения - целые числа от 1 до 4 включительно (всего четыре с а s е -блока). При наличии совпадения значения переменной numb e r и контрольного значения в с а s е -блоке 134

Управля ю щие инструкции получает значение переменная name (значение переменной - название введенного числа). На случай, если совпадения не будет, предусмотрен de f a u l t-блок. В этом блоке значением переменной name присваивает­ ся текст, сообщающий о невозможности идентифицировать число. Таким образом, было или не было совпадение, переменная n ame по­ лучит значение. Это значение используется в команде Me s s a g e B o x . Show ( name , " Число " ) , которой отображается диалоговое окно с сооб­ щением (название числа или сообщение о том, что число неизвестно). На рис. 3.7 показано окно с полем ввода, в которое введено число 2 . Число

Рис. 3. 7. В поле введено ч исло 2 После подтверждения ввода появляется новое диалоговое окно, пока­ занное на рис. 3.8. Число



Двойк1 ок

Рис. 3.8. Окно с соо б щением после ввода числа 2 На рис. 3.9 показано окно с полем ввода, в котором пользователь указал число 5 . ЧиU10

Рис. 3. 9 . В поле введено ч исло 5 135

Глава 3

После щелчка по кнопке ОК появляется окно с сообщением о том, что число неизвестно. Окно показано на рис. 3. 1 0. Чием



Нrю�sктн о е ч�tсло

ок

Рис. 3. 1 О. Окно с соо б щением после ввода ч исла 5 Стоит заметить, что если пользователь вместо ввода числа в окне с по­ лем щелкнет, например, кнопку Отмена, то возникнет ошибка. Жела­ ющие могут подумать, как следует модифицировать программный код, чтобы подобная ситуация обрабатывалась корректно.

G)

Н А ЗАМ ЕТ КУ

В программе испол ьзовано нескол ько пространств имен . П ростран­ ство имен Sys tem . Windows . Forms необходи мо подкл ючить для ис­ пол ьзования статического метода Show ( ) из класса Me s s ageBox . Метод отображает диалоговое окно с сообщением ( в данном слу­ чае назван ие введенного пользователем ч исла) . Пространство имен Mi c ro s o ft . V i s u a l Ba s i c нужно для испол ьзования статического метода I nputBox ( ) из класса Interaction . Метод отображает окно с полем ввода . Напом н и м , что в данном случае мы п рибегаем к по­ мощи средств разработки языка Visual Basic. Наконец, пространство имен Sys tem нам понадобилось, поскол ьку мы используем стати­ ческий метод Parse ( ) из структуры I n t 3 2 . Вообще-то м ы еще ис­ пол ьзуем и текстовый тип S t r i n g. Это класс из п ространства имен Sys tem. Но в программе ссылка на текстовый тип выпол нена через идентификатор s t ring, явля ющийся псевдонимом для инструкции Sys tem . S t r i n g. Так что s t r ing можно было бы испол ьзовать и без подкл ючения пространства имен Sys tem.

Как отмечалось ранее, с а s е -блоки в операторе выбора могут быть пу­ стыми. Так поступают в случае, если необходимо, чтобы для несколь­ ких контрольных значений выполнялись одни и те же команды. Если так, то вместо дублирования команд в соответствующих с а s е -блоках (что неудобно и не очень рационально) используют несколько идущих один за другим пустых блоков. Причем в таких пустых с а s е -блоках нет

136

Управля ющие инструкции даже Ь r е а k-инструкций. Пример подобного подхода проиллюстриро­ ван в следующей программе, представленной в листинге 3.6.

� Листинг 3.6. Оператор выбора с пустыми са sе -блоками u s ing Sys tem; u s ing Sys tem . Windows . Forms ; u s ing Micros oft . VisualBas i c ; c l a s s Anothe rSwitchDemo { s tatic vo id Main ( ) { / / Переменная для запоминания введенного числа : int numЬer; / / Переменная для текста сообщения : s t ring txt= " " ;

/ / Началь ное значение переменной

/ / Считывание числа : numbe r=I nt 3 2 . Parse ( Interaction . I nputBox ( / / Текст над полем ввода : "Введите целое число от

1

до 9 : " ,

/ / Заголовок окна : "Число " ) ); / / Проверка значения переменной numbe r : switch ( numЬe r ) { case

1:

case 9 :

/ / Оператор выбора

/ / Е сли значение

1

/ / Е сли значение 9

/ / Текст сообщения : txt=" Bы ввели нечетное , \n но не простое число . " ; break; / / Завершение блока case 2 :

/ / Е сли значение 2

case 3 :

/ / Е сли значение 3

case 5 :

/ / Е сли значение 5

case 7 :

/ / Е сли значение 7

137

Глава З / / Текст сообщения : txt=" Bы ввели простое число . " ; break; / / Завершение блока case 4 :

/ / Е сли значение 4

case 8 :

/ / Е сли значение 8

/ / Текст сообщения : txt=" Bы ввели число - степень двойки . " ; break; / / Завершение блока case 6 :

/ / Е сли значение 6

/ / Текст сообщения : txt=" Bы ввели 6 - совершенное число . " ; break; / / Завершение блока

/ / Отображение диалогового окна с сообщением : Me s s ageBox . Show ( tx t , "Чиcлo " ) ;

Данная программа в некотором смысле напоминает предыдущую. Сна­ чала пользователю предлагается ввести целое число (в диапазоне от 1 до 9 ) . Результат записывается в переменную numb e r . После этого с по­ мощью оператора выбора проверяется значение этой переменной. Мы �классифицируем» числа по следующим категориям: • Простые числа - числа, которые не имеют других делителей, кроме единицы и себя самого. В диапазоне чисел от 1 до 9 простыми явля­ ются числа 2 , 3, 5 и 7 . • Числа, которые являются степенью двойки - в диапазоне от 1 до 9 2 3 в эту категорию попадают числа 4 (2 4) и 8 (2 8). =

=

• Число 6 является совершенным - сумма его делителей (числа 1, 2 и 3 ) равна самому этому числу. Следующее совершенное число - это 2 8 (его делители 1 , 2 , 4 , 7 и 1 4 в сумме дают 2 8 ), но оно не попадает в интервал от 1 до 9 . • Нечетные числа, которые при этом н е являются простыми - в ука­ занном диапазоне это числа 1 и 9 . 138

Управля ю щие инструкции Введенное пользователем число с помощью оператора выбора «припи­ сывается� к одной из перечисленных групп. И в этом операторе выбора мы используем пустые с а s е-блоки. Например, есть в операторе выбо­ ра такая конструкция (комментарии для удобства удалены): case 2 : case 3 : case 5 : case 7 : txt= "Bы ввели простое число . " ; break;

Как это работает? Допустим, пользователь ввел значение 2. При срав­ нении этого значения с контрольными значениями в с а s е -блоке со­ впадение имеет место для блока c a s e 2 . Поэтому будут выполнены все команды от места, где идентифицировано совпадение, до первой ин­ струкции b r e a k. В результате выполняется команда t x t = " Bы в в ели про с т о е число . " . Теперь предположим, что пользователь ввел значе­ ние 5 . Совпадение проверяемого (переменная numb e r ) и контрольно­ го значения имеет место в блоке c a s e 5. Он пустой. Но это все равно с а s е-блок. Поэтому выполняются команды от места совпадения до пер­ вой инструкции b r e a k. Итог такой - выполняется команда t x t = " Bы в в ели про с т о е число . " . То же получаем, когда пользователь вводит значение 3 и 7 . Прочие блоки в операторе выбора работают по такому же принципу. Внешне все выглядит следующим образом. При запуске программы на выполнение появляется окно с полем ввода, в которое следует ввести число от 1 до 9. Окно показано на рис. 3. 1 1 . Число

Рис. З. 1 1

.

Окно с полем для ввода ч исла в диапазоне от 1 до 9

Если пользователь вводит числа 1 или 9 , то следующим появляется окно, представленное на рис. 3. 1 2 . 139

Глава 3

ЧНо

Вы е в е1 ш нечflНое.. но не: npocтot чиС/lо.

ок

Рис. 3. 1 2 . Окно появляется , есл и пол ьзовател ь вводит ч исло 1 или 9

G)

Н А ЗАМ ЕТ КУ

В операторе выбора в одном из с а s е -блоков (для значений 1 и 9 ) при оп ределении текстового значения переменной txt в текстовом л итерале испол ьзована инструкция \ n . Напом н и м , что это инструк­ ция перехода к новой строке . П ри отображен и и соответствующего текста в том месте , где размещена инструкция \ n , выполняется пе­ реход к новой строке. Резул ьтат можно видеть на рис . 3 . 1 2 , где текст в диалоговом окне отображается в две строки .

В случае, если пользователь вводит число 2 , 3 , 5 или 7 , появится окно, представленное на рис. 3. 1 3 .

Число

Вы

в аt..n и простое число.

ок

Рис. 3. 1 3. Окно появляется , есл и пол ьзовател ь вводит ч исло 2, 3, 5 или 7

Если пользователь вводит число 6 , появляется окно, показанное на рис. 3. 1 4 .

Число

Вы

авvш

6

·

совершенное число.

ок

Рис. 3. 1 4 . Окно появляется , есл и пользовател ь вводит ч исло 6 140

Управля ющие инструкции Наконец, если пользователь вводит число 4 или 8, то появляется окно, показанное на рис. 3 . 1 5 . Число

ок

Рис. 3. 1 5 . Окно появляется , есл и пол ьзовател ь вводит ч и сла 4 или 8 Хочется обратить внимание на несколько обстоятельств. Во-первых, в операторе выбора мы не использовали de f a u l t - блок. Как упоми­ налось ранее, этот блок не является обязательным, чем мы, собствен­ но, и воспользовались. Но поскольку теперь в s w i t с h-операторе de f а и 1 t-блока нет, то теоретически может получиться, что в операторе переменной txt значение не будет присвоено - например, если пользо­ ватель введет число, которое не попадает в диапазон значений от 1 до 9 . И это проблема, поскольку переменная t x t используется в команде Me s s ageBox . S h o w ( t x t , " Число " ) после оператора выбора. Такие си­ туации компилятором отслеживаются, и выдается ошибка еще на этапе компиляции. Чтобы ее избежать, при объявлении переменной txt мы ей сразу присвоили пустое текстовое значение. В таком случае, даже если пользователь введет значение вне рекомендуемого диапазона и в опера­ торе выбора значение переменной t x t присвоено не будет, переменная останется со своим старым значением. Возможно, это не самый лучший способ решения проблемы, но, во всяком случае, при компиляции не бу­ дет ошибки. Также стоит заметить, что, если пользователь в поле ввода введет не чис­ ло, отменит ввод (щелкнув кнопку Отмена) или закроет окно щелчком по системной пиктограмме, возникнет ошибка. Чтобы ее избежать, мож­ но воспользоваться системой перехвата и обработки исключений. Как это делается, кратко будет показано в одном из разделов в конце главы. Обработке исключений также посвящена одна из глав во второй части книги.

141

Глава З

Оператор ц и кла wh i l e З амечательная идея ! Ч то ж она мне самому в голову не пришла ?

из к/ф �Ирония судьбы,

WlU

С легким паром»

Оператор цикла позволяет многократно выполнять определенный набор команд. В языке С# существует несколько операторов цикла, и со всеми ними мы познакомимся. Но начнем с оператора цикла whi l e. У него до­ статочно простой синтаксис. Описание оператора начинается с ключевого слова whi l e. В круглых скобках после ключевого слова whi l e указьшает­ ся некоторое условие (выражение со значением логического типа). Затем в фигурных скобках указьшается блок из команд, формирующих тело опе­ ратора цикла. Общий синтаксис оператора цикла wh i l e, таким образом, следующий (жирным шрифтом выделены ключевые элементы шаблона): while (ycлoвиe ) { 1 1 Команды

Выполняется оператор цикла wh i l e так. Сначала проверяется условие (в круглых скобках после ключевого слова w hi 1 е ). Если условие истинно (значение t rue ), то выполняются команды в теле оператора цикла. После этого снова проверяется условие. Если оно истинно, то снова выполняют­ ся команды в теле оператора цикла, после чего опять проверяется условие, и так далее. Оператор цикла выполняется до тех пор, пока при проверке условия оно не окажется ложным (значение fa l s e). Если при проверке условия оно оказывается ложным, команды в теле оператора цикла не вы­ полняются, работа оператора цикла завершается и управление передается следующей инструкции после оператора цикла. Схема выполнения опе­ ратора цикла wh i l e проиллюстрирована на рис. 3. 1 6. Стоит заметить, что команды в теле оператора выполняются блоком то есть условие в очередной раз проверяется только после того, как вы­ полнены все команды в теле оператора цикла. Условие, указанное в круг­ лых скобках после ключевого слова wh i l e , должно быть таким, чтобы при выполнении команд в теле оператора цикла оно в принципе могло измениться. Проще говоря, чтобы в операторе цикла начали выполнять­ ся команды, условие в самом начале должно быть равно t ru e . А чтобы оператор цикла в какой-то момент завершил выполнение, условие долж­ но стать равным f a l s e . Иначе получим бесконечный цикл. 142

Управля ющие инструкции

,/ ' ' '

,. - -1

'

1

,

\

... - -

t r ue

'

- - - •

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



166

Условный оператор i f позволяет выполнять разные блоки команд в зависимости от истинности или ложности некоторого условия.

Управля ющие инструкции Проверяемое условие указывается в круглых скобках после ключе­ вого слова i f. Команды, выполняемые при истинном условии, ука­ зываются в блоке после i f-инструкции. Команды, выполняемые при ложном условии, указываются в е l s е -блоке. Существует упрощен­ ная форма условного оператора без е l s е -блока. • Оператор выбора s w i t c h позволяет выполнять разные блоки ко­ манд в зависимости от значения некоторого выражения. Проверя­ емое выражение (целочисленное, символьное или текстовое) ука­ зывается в круглых скобках после ключевого слова s w i t ch. Затем указываются с а s е -блоки с контрольными значениями. Выполняют­ ся команды в с а s е -блоке, в котором контрольное значение совпа­ дает со значением проверяемого выражения. В случае, если значе­ ние выражения не совпадает ни с одним из контрольных значений в с а s е -блоках, выполняются команды в de f a u l t-блоке. Этот блок не является обязательным. Каждый с а s е -блок и de f a u l t-блок за­ канчивается инструкцией b r e a k. В случае необходимости можно использовать пустые с а s е -блоки. • Оператор цикла wh i l e позволяет многократно выполнять блок определенных команд. После ключевого слова wh i l e в круглых скобках указывается условие, при истинности которого выполняют­ ся команды в теле оператора цикла. Каждый раз после выполнения этих команд проверяется условие, и, если оно истинно, команды вы­ полняются снова. • Оператор цикла do-wh i l e похож на оператор цикла wh i l e , но в опе­ раторе do - wh i l e сначала выполняются команды, а затем проверяет­ ся условие. Команды указываются после ключевого слова do. После блока команд следует ключевое слово wh i l e и, в круглых скобках, условие. Оператор цикла выполняется до тех пор, пока при очеред­ ной проверке условия оно не оказывается ложным. • Описание оператора цикла f o r начинается с ключевого слова f o r . В круглых скобках указывается три блока инструкций. Блоки разде­ ляются между собой точкой с запятой. Если блок содержит несколь­ ко инструкций, то они разделяются запятыми. Команды, формиру­ ющие тело оператора цикла, указываются в круглых скобках после f о r -инструкции. Выполнение оператора цикла начинается с вы­ полнения команд в первом блоке. После этого проверяется условие во втором блоке. Если оно ложно, оператор цикла завершает работу. Если условие истинно, то выполняются команды в теле оператора 167

Глава З цикла и в третьем блоке. Затем снова проверяется условие. Если ус­ ловие ложно, работа оператора цикла завершается. Если условие истинно, выполняются команды в теле оператора и в третьем блоке и снова проверяется условие. И так далее, пока при проверке усло­ вия оно не окажется ложным. • Инструкция безусловного перехода g o t o позволяет перейти к вы­ полнению программного кода в том месте, которое выделено меткой. Используя инструкцию g o t o и условный оператор, можно органи­ зовать циклическое выполнение программного кода (симулировать работу оператора цикла). Общая рекомендация состоит в том, чтобы избегать использования инструкции g o t o . • Система обработки исключений позволяет предусмотреть специаль­ ный код, выполняемый при возникновении ошибки. С этой целью используется конструкция t ry- c at ch. Программный код, при вы­ полнении которого может возникнуть ошибка, помещается в t r у­ блок. Программный код, предназначенный для выполнения в случае возникновения ошибки, помещается в с а t с h-блок. Если при выпол­ нении кода в t rу-блоке ошибка не возникает, то с а t сh-блок игно­ рируется. Если при выполнении кода в t rу-блоке возникает ошибка, то выполнение команд в блоке t r y прекращается и начинают выпол­ няться команды в блоке c a t c h .

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

из к:/ф -«Кин-дза-дза»

1 . Напишите программу, в которой пользователь вводит число, а про­ грамма проверяет, делится ли это число на 3 и на 7 . Результаты проверки отображаются в сообщении в диалоговом окне. Используйте обработку исключений. 2. Напишите программу, в которой пользователь последовательно вво­ дит два целых числа. Программа определяет, какое из чисел больше или они равны, и выводит сообщение в диалоговом окне. Используйте обра­ ботку исключений.

1 68

Управля ющие инструкции 3 . Напишите программу, в которой вычисляется сумма чисел, которые

вводит пользователь. Программа выводит запрос на ввод числа, считы­ вает введенное пользователем число, прибавляет его к сумме и снова выводит запрос на ввод числа. Процесс продолжается до тех пор, пока пользователь не введет нулевое значение. Используйте обработку ис­ ключений. 4. Напишите программу, в которой пользователь вводит целое число в диапазоне от 1 до 7 , а программа определяет по этому числу день не­ дели. Если введенное пользователем число выходит за допустимый диа­ пазон, выводится сообщение о том, что введено некорректное значение. Используйте оператор выбора s w i t ch. Предложите механизм обработ­ ки ошибки, связанной с вводом нечислового значения. 5. Напишите программу, в которой пользователю предлагается ввести

название дня недели. По введенному названию программа определяет порядковый номер дня в неделе. Если пользователь вводит неправиль­ ное название дня, программа выводит сообщение о том, что такого дня нет. Предложите версию программы на основе вложенных условных операторов и на основе оператора выбора s w i t ch. 6. Напишите программу, в которой вычисляется сумма нечетных чисел. Для проверки результата воспользуйтесь тем, что 2 + 4 + 6 + ". + 2п = п(п + 1 ). Предложите версии программы, использующие разные опера­ торы цикла. 7. Напишите программу для вычисления суммы квадратов натуральных чисел. Для проверки результата воспользуйтесь тем, что 1 2 + 2 2 + 3 2 + " . 2 n(n + 1 ) (2n + 1) +п = П редложите версии программы, использующие разные 6 операторы цикла. •

8. Напишите программу, которая выводит последовательность чисел

Фибоначчи. Первые два числа в этой последовательности равны 1 , а ка­ ждое следующее число равно сумме двух предыдущих (получается по­ следовательность 1 , 1 , 2 , 3, 5 , 8 , 1 3 , 2 1 , 3 4 , 5 5 , 8 9 и так далее). Количе­ ство чисел в последовательности вводится пользователем. Предложите версии программы, использующие разные операторы цикла. 9. Напишите программу, в которой пользователем вводится два целых числа. Программа выводит все целые числа - начиная с наименьшего (из двух введенных чисел) и заканчивая наибольшим (из двух введен­ ных чисел). Предложите разные версии программы (с использованием

169

Глава З разных операторов цикла), а также механизм обработки исключений для этой программы. 1 0 . Напишите программу, в которой вычисляется сумма чисел, удовлет­ воряющих таким критериям: при делении числа на 5 в остатке получа­ ется 2 , или при делении на 3 в остатке получается 1 . Количество чисел в сумме вводится пользователем. Программа отображает числа, которые суммируются, и значение суммы. Используйте обработку исключений. Предложите версии программы, использующие разные операторы цикла.

Гл ава 4 МАССИВЫ

- Пойдем простым логическим ходом. - Пойдем вместе .

из к/ф �Ирония судьбы,

WlU

С легким паром»

В этой главе мы обсудим исключительно важную конструкцию - речь пойдет о массивах. Среди тем, которые мы рассмотрим, будут такие: • одномерные массивы - способы их объявления и использования ; • особенности работы с двумерными массивами ; • способы инициализации массивов ; • выполнение основных операций с массивами - в частности, речь бу­ дет идти о копировании и присваивании массивов ; • создание �рваных» массивов - то есть массивов со строками разной длины ; • особенности массива из объектных ссылок. Также мы познакомимся со способами обработки аргументов командной строки. Еще в главе есть различные примеры использования массивов. Начнем же с азов - с создания одномерных массивов.

Одномерные масси вы Первый раз таких единоличников вижу.

из к/ф �девчата»

Массив - это набор элементов одного типа, которые объединены об­ щим именем. Переменные, входящие в массив, называются элемента­ ми массива. Поскольку одно и то же имя (имя массива) 4П рименяет­ ся» сразу к нескольким переменным, то эти переменные нужно как-то 171

Глава 4 идентифицировать. Идентификация выполняется с помощью индекса или индексов. Индекс - это целое число. Количество индексов, необ­ ходимых для однозначной идентификации переменной в массиве, опре­ деляет размерность массива. Под размером массива обычно подразуме­ вают общее количество элементов в массиве. Под размером массива для данной размерности имеют в виду количество значений, которые мо­ жет принимать индекс, соответствующий данной размерности. Самые простые - одномерные массивы, в которых для идентификации элемен­ та в массиве нужно указать всего один индекс. Знакомство с массива­ ми начнем именно с одномерных массивов. То есть далее в этом разделе речь идет об одномерных массивах. Мы уже выяснили, что массив - это набор переменных. Возникает есте­ ственный вопрос: как получить доступ к этому набору? Ответ состоит в том, что доступ к массиву получают с помощью специальной пере­ менной, которая называется переменной массива. Как и обычную пере­ менную, переменную массива перед использованием следует объявить. При объявлении переменной массива указывают идентификатор типа элементов массива, после него указываются пустые квадратные скобки и имя переменной массива. То есть шаблон объявления переменной мас­ сива такой: тип [ ] переменная

Например, если мы хотим объявить переменную массива с названи­ ем nums и предполагается, что массив будет состоять из целочислен­ ных значений типа i n t , то переменная массива объявляется командой i n t [ ] num s . Если бы мы объявляли переменную массива с названием s ymЬs и массив предполагался состоящим из символьных значений, то ко­ манда объявления такой переменной выглядела бы как char [ ] s ymЬ s . Н о создание (объявление) переменной массива н е означает создания массива. Другими словами, даже если мы объявили переменную масси­ ва, сам массив от этого не появляется. Его еще нет. Массив нужно со­ здать. Для создания массива используется оператор n e w . После оператора new указывается идентификатор типа, соответствующий типу элемен­ тов создаваемого массива, а в квадратных скобках после идентифика­ тора типа указывается размер массива. Шаблон для команды создания массива имеет такой вид: new тип [ размер ]

172

Масс ивы Например, если мы хотим создать одномерный целочисленный мас­ сив из 1 2 элементов, то команда создания такого массива выглядит как new in t [ 1 2 ] . Чтобы создать массив из 1 О элементов символьного типа, используем команду new char [ 1 О ] . Остается открытым вопрос о том, как переменная массива связана с собственно массивом. Ответ очень про­ стой: переменная массива ссылается на массив. Можно сказать и иначе: значением переменной массива может быть адрес массива в памяти.

G)

Н А ЗАМ ЕТ КУ

Что понимать под «адресом масси ва» и как этот адрес испол ьзуется , более детал ьно обсуждается в главе ( во второй части книги ) , посвя ­ щенной работе с указателя м и . Пока же нам достаточно самых общих представлений о том , что такое «адрес масси ва» .

Также нужно учесть, что команда создания массива не только создает массив, но еще и имеет результат. Это адрес созданного массива. А адрес массива, как мы уже знаем, может быть значением переменной массива. Главное, чтобы тип переменной массива соответствовал типу элементов в массиве. Если обобщить все вышеизложенное, то общая схема созда­ ния массива реализуется следующими командами: тип [ ] переменная ; переменная=nеw тип [ размер ] ;

То есть задача по созданию массива состоит из двух этапов: •



объявление переменной массива ; создание массива и присваивание ссылки на массив переменной мас­ сива.

Эти два этапа можно объединить и воспользоваться такой командой: тип [ ] переменная=nеw тип [ размер ] ;

Схема реализации одномерного массива проиллюстрирована на рис. 4. 1 . Например, командой i n t [ ] nums=new i n t [ 1 2 ] создается целочис­ ленный массив из 1 2 элементов, объявляется переменная массива nums и ссылка на созданный массив записывается в эту переменную. Ко­ мандой char [ ] s ymb s =new char [ 1 О ] создается массив из 1 О сим­ вольных элементов, объявляется переменная массива s ymb s и ссылка на массив записывается в переменную. 173

Глава 4

/

, ...

/

.... - "

,-

"

- ,1 - , Пер емен н а я: масс и в а '.

, , .... - - " .>, поэтому нельзя однозначно предугадать, когда именно объекты будут удалены. Можно быть уверенным лишь в том, что это произойдет.

Стати ч еские ч лены кл асса Приедут тут всякие : без профессии , без подушек" . из к/ф « д евчата>.>

Поля и методы могут быть статическими. Особенность статических по­ лей и методов в том, что они могут использоваться без создания объектов.

G)

Н А ЗАМ ЕТ КУ

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

Статические члены класса описываются с ключевым словом s t a t i c . Для обращения к статическому члену класса (полю или методу) указы­ вается имя класса, после которого через точку указывают имя поля или имя метода (с аргументами или без). Таким образом, если при обращении 314

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

(D

Н А ЗАМ ЕТ КУ

Статические поля играют рол ь глобал ьных переменных. Они «не при­ вязан ы » к какому-то кон кретному объекту и существуют «сами по себе » . Единственное огран ичение - статические поля нужно описы вать в классе и при обращении указы вать имя этого класса . Аналогично, статические методы в языке С# и грают п римерно ту же рол ь, что и фун кци и в языке С++ . Статический метод - это , по сути , блок команд, которые не подразумевают испол ьзован ия объекта , и поэтому для выполнения этих команд ( вызова метода) объект как таково не нужен .



ПОДРОБН ОСТИ

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

При работе со статическими методами существует очевидное ограниче­ ние: статический метод может обращаться только к статическим полям и методам в классе. Объяснение простое: поскольку статический метод существует без привязки к объекту, то нет смысла обращаться к полям и методам объекта (поскольку объекта как такового нет). В листинге 6.6 представлена программа. В ней используется класс со ста­ тическим полем и методом.

� Листинг 6 . 6 . Знакомство со статическими полями и методами u s ing Sys tem; 11 Класс со статическим полем и методом : c l a s s MyClas s { 1 1 Статическое поле :

315

Глава б puЫ ic static int code=l O O ; 1 1 Статический метод : puЫ ic static void show ( ) { Console . WriteLine ( " Cтaтичecкoe поле : " +code ) ;

1 1 Класс с главным методом : c l a s s StaticDemo { 1 1 Главный метод : static vo id Main ( ) { 1 1 Вызов статического метода : MyClas s . show ( ) ; 1 1 Обращение к статическому полю : MyClas s . code=2 0 0 ; 1 1 Вызов статического метода : MyClas s . show ( ) ;

Ниже представлен результат выполнения программы.

� Результат выполнения программы ( из листинга 6 . 6) Статическое поле : 1 0 0 Статическое поле : 2 0 0

В программе описьmается класс MyC l a s s , у которого есть открытое статиче­ ское целочисленное поле code с начальным значением 1 О О , а также статиче­ ский метод show ( ) (без аргументов и не возвращающий результат). Метод при вызове отображает в консольном окне значение статического поля code. В главном методе программы командой MyC l a s s . s h o w ( ) вызы­ вается статический метод s h o w ( ) класса MyC l a s s . В результате в консоли отображается текущее значение статического поля c o d e . Мы это значение можем изменить - например, с помощью команды MyC l a s s . c o de = 2 0 0 , после чего значение статического поля стано­ вится равным 2 0 0 . Проверить это легко - достаточно вызвать метод 316

З нако мство с классами и о бъекта м и s h ow ( ) (команда MyC l a s s . s how ( ) ) . В данном случае примечателен факт, что мы не создали ни одного объекта класса MyC l a s s , но это не ме­ шает нам использовать статические члены этого класса. Еще один, на этот раз �математический� пример с использованием ста­ тических полей и методов представлен в листинге 6.7. В программе опи­ сан класс МуМа th, в котором есть статические методы для вычисления значений синуса и экспоненты. В классе также имеется константное ста­ тическое поле, значение которого определяет иррациональное число л.

G)

Н А ЗАМ ЕТ КУ

Что касается статических полей , то нередко они испол ьзуются как статические константы : для такого поля указы вается идентифика­ тор типа (и есл и нужно - спецификатор уровня доступа ) , но вместо кл ючевого слова s t a t i c указы вается идентификатор c o n s t . При­ ч и на в том , что константн ые поля по умолчанию реал изуются как статические. Значение константного поля указы вается при объя в­ лении и впоследстви и не может быть изменено.



ПОДРОБН ОСТИ

Дл я вычисления экспоненты испол ьзуется следующее вы ражение: "п х2 х3 х" � ехр (х) ::::: 1 + х + 2Т + 31 ." + nг = Lk=O k! . В п рограмме описывается статический метод для выч исления сум м ы Lk=O qk q0 + q , + + qn , где при заданно �значен и и аргумента х слагаем ые в сум ме вычис­ =

···

ля ются как qk = k!· Сум ма вычисляется с помощью оператора цик­

ла, в котором после п рибавления к сум ме очередного слагаемого рассч иты вается слагаемое для следующей итераци и . При этом мы исходим из того , что есл и выч ислена добавка qk для текущей итераци и , то добавка qk+i для следующей итера ци и выч исляется как

qk+ 1 qk

х qk+ i = qk x k+ l

=

(легко п роверить, что есл и

qk

), k..!.__ +1

=





k! и qk = (k+ l)! ' то

Аналоги ч н ы м образом выч исляется си нус : испол ьзуется формула (-1 )"х>п+1 - " п (-1 )kx>k+1 xl xs х' s 1 n (x) - х - 31 + 51 - 71 + ". + (2n + l ) ! - Lk=O ( 2k + l ) ! . П одход испол ьзу •

ем тот же , что и при вычислении экспоненты - то есть выч исляет-

Lk=O qk - qo + q, + ". + qn , _ (-1 J k+ 1x2k+з qk+ 1 х' и тоrДа qk+ I qk+ 7 ( 2k + 3) ! ' qk - (2k + 3)(2k + 2) '

ся сум ма вида

_

но на этот раз =

qk х

(-1 )х'

(- 1 )kx2k+ 1 q k= (2k + l )! ,

(2k + 3)(2k + 2)

317

Глава б Для определения значения параметра п ( верхняя граница в сум мах, через которые вычисляется си нус и экспонента) в програм ме (в со­ ответствующем классе) объя влено статическое целоч исленное поле. А значение тт=З , 1 4 1 592 определяется через статическую константу.

Проанализируем представленный ниже программный код.

[1i!J Л истинг 6. 7. И спользование статических полей и методов us ing Sys tem; / / Класс со статическими методами и полями : c l a s s MyMath { / / Константное поле ( число " пи" ) : puЫ ic const douЫe Рi=З . 1 4 1 5 92 ; / / Закрытое статическое поле ( граница суммы) : private static int N=l O O ; / / Статический метод для вычисления экспоненты : puЫ ic static douЫe exp ( douЫe х ) { / / Сумма и добавка к сумме : douЫe s=O , q= l ; / / Вычисление суммы : for ( int k=O ; k=text . Length истинно в том случае, если индекс меньше нуля или больше максимально допустимого ин­ декса в тексте (определяется длиной текста). В этом случае выполня­ ется инструкция r e t u rn, которая завершает работу аксессора, и с тек­ стовым полем объекта, соответственно, ничего не происходит. Если же этого не происходит, то индекс попадает в допустимый диапазон значе­ ний и начинается процесс вычисления нового текстового значения для поля t e x t . Для этого объявляется локальная текстовая переменная t с пустой текстовой строкой в качестве начального значения. Затем запу­ скается оператор цикла, в котором к текстовой строке последовательно дописываются начальные символы из поля t e x t , но только до символа с индексом k (этот символ не копируется). Далее командой t + =va l u e к текстовой строке дописывается тот символ, который присваивает­ ся значением выражению с проиндексированным объектом. То есть 490

С в ойст ва и индекс аторы получается, что вместо символа с индексом k из текстового поля t e x t в текстовую строку дописывается тот символ, что указан в операции присваивания (определяется значением параметра val ue ). Затем сно­ ва запускается оператор цикла, с помощью которого к текстовой строке из переменной t дописываются все оставшиеся символы из текстово­ го поля t e x t . По завершении этого оператора цикла командой t e x t = t текстовое поле получает новое значение. Новое значение поля t e x t от­ личается от предыдущего значения одним символом. В главном методе программы командой MyS t r i n g t x t = " Myx a " соз­ дается объект t x t класса MyS t r i n g (здесь использована операция неявного приведения типов). Также главный метод содержит приме­ ры использования индексатора с индексом, значение которого выхо­ дит за допустимый диапазон (команды t x t [ - 1 ] = ' ы ' и t x t [ 4 ] = ' ъ ' ). Есть также команды ( t x t [ O ] = ' C ' , t x t [ l ] = ' л ' , t x t [ 2 ] = ' o ' и txt [ 3 ] = ' н ' ), в которых значение индекса корректно. Для проверки значения текстового поля объекта t x t используется переопределение метода T o S t r i n g ( ) (метод вызывается, когда объект t x t передается аргументом методу W r i t e L i n e ( ) ). В следующем примере описывается класс с индексатором, индекс кото­ рого не является целым числом. Соответствующая программа представ­ лена в листинге 9. 1 1 .

� Л истинг 9 . 1 1 . И ндексатор с нечисловым индексом u s ing Sys tem;

11 Класс с индексатором : c l a s s MyClas s {

1 1 Целочисленное поле : puЫ ic int code ;

1 1 Конструктор с одним аргументом : puЫ ic MyCla s s ( int n ) { code=n ;

1 1 Целочисленный индексатор с индексом , который является 11 объектом класса MyCla s s : puЫ ic int this [ MyC l a s s obj ] {

1 1 Метод вызывается при считывании значения 491

Гл ава 9 1 1 выражения с проиндексированным объектом : get {

1 1 Резуль тат : return code - obj . code ;

1 1 Метод вызывается при присваивании значения 11 выражению с проиндексированным объектом : set {

1 1 Присваивается значение полю : code=obj . code+value ;

1 1 Класс с главным методом : c l a s s Non intindexDemo {

1 1 Главный метод : static vo id Main ( ) {

1 1 Создание объекта : MyC l a s s A=new MyC l a s s ( l O O ) ;

1 1 Проверка значения поля объекта : Console . WriteLine ( " Oбъeкт А : { 0 } " , A . code ) ;

1 1 Создание объекта : MyC l a s s B=new MyC l a s s ( 1 5 0 ) ;

1 1 Проверка значения поля объекта : Console . WriteLine ( " Oбъeкт В : { 0 } " , B . code ) ;

1 1 Использование индексатора : int num=A [ B ] ; Console . WriteLine ( " Bыpaжeниe А [ В ] = { О } " , num) ; Console . WriteLine ( " Bыpaжeниe В [А ] = { О } " , В [А ] ) ; А [ В ] =2 0 0 ;

1 1 Проверка значения поля объекта : Console . WriteLine ( " Oбъeкт А : { 0 } " , A . code ) ;

492

С в ойст ва и индекс аторы Результат выполнения программы такой.

[1i!J Результат выполнения программы (из листинга 9 . 1 1 ) Объект А : 1 0 0 Объект В : 1 5 0 Выражение А [ В ] = - 5 0 Выражение В [ А] = 5 0 Объект А : 3 5 0

Здесь мы описываем класс MyC l a s s , у которого есть открытое целочис­ ленное поле c o de , конструктор с одним аргументом и индексатор. Тип индексатора определяется ключевым словом i n t , а вот индекс в индекса­ торе описан как MyC l a s s obj . Аксессоры индексатора описаны так, что результатом выражения вида А [ В ] , в котором А и В являются объектами класса MyC l a s s, является разность значений поля c o de объекта А и объ­ екта В. Например, если поле c o de объекта А равно 1 О О , а поле c o de объ­ екта В равно 1 5 О , то результатом выражения А [ В ] будет 5 О (разность значений 1 О О и 1 5 О ). Значение выражения В [ А ] при этом равно 5 О (раз­ ность значений 1 5 О и 1 О О ). Если выражению вида А [ В ] присваивается целочисленное значение, то поле c o de объекта А получит новое значение, которое равно сумме значения поля c o de объекта В и значения, присваи­ ваемого выражению А [ В ] . Так, при значении поля c o de объекта В равном 1 5 О в результате выполнения команды А [ В ] =2 О О поле c o de объекта А получит значение 3 5 О (сумма значений 1 5 О и 2 О О ). -

Двумерные и ндексаторы Дело государственной важности. Возможна погоня.

из к/ф «Бриллиантовая рука»

Двумерный индексатор описывается, в принципе, так же, как и одномер­ ный индексатор. Отличие лишь в том, что теперь в индексаторе опи­ сывается два индекса (могут быть разного типа). Для каждого индекса указывается тип, описания индексов в квадратных скобках разделяют­ ся запятыми. При индексировании объектов также указывается два ин­ декса. В листинге 9. 1 2 представлена программа, дающая представление о том, как описывается и используется двумерный индексатор. 493

Гл ава 9

[1i!J Л истинг 9 . 1 2 . Знакомство с двумерными индексаторами us ing Sys tem; / / Класс с двумерным индексатором : c l a s s MyClas s { / / Закрытое поле , являющееся ссылкой н а двумерный / / символьный массив : private char [ , ] s ymЬ s ; / / Конструктор с двумя аргументами : puЫ ic MyC la s s ( int а , int Ь ) { / / Создание двумерного массива : s ymbs=new char [ a , Ь ] ; / / Заполнение двумерного массива . / / Перебор строк массива : for ( int i=O ; i