Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Программирование в Visual С++ 2005 10 страница




Обратите внимание на ключевое слово class в определении перечисления, кото-
рое следует за ключевым словом enum. Оно не появлялось в определении перечисле-
ний в ISO/ANSI С++, как вы видели ранее, а идентифицирует только перечисления
C++/CLI. Кроме того, оно указывает на еще одно отличие от перечислений ISO/ANSI
С++; здесь константы, определенные в перечислении — Hearts, Clubs и так далее —
являются объектами, а не простыми значениями фундаментального типа, как в версии
ISO/ANSI С++. Фактически, по умолчанию они являются объектами типа Int32, поэ-
тому каждая из них инкапсулирует значение типа int; однако перед тем как пытаться
использовать их как таковые, вы должны привести эти константы к типу int.

Поскольку перечисления C++/CLI являются типом класса, вы не можете объяв-
лять их локально, например, внутри функции, поэтому если вы хотите определить та-
кое перечисление для использования, к примеру, в main (), то должны объявить его в
глобальном контексте.


Ниже предлагается очень простой пример использования перечисления:



Этот пример выдаст на консоль следующее:



Это легко проиллюстрировать примером.

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

Поскольку это тип класса, перечисление Suit не может быть определено внутри
функции main (), поэтому его определение помещено перед определением main (), а


 


134 Глава 2

 

потому относится к глобальному контексту. В примере объявляется переменная suit
типа Suit и размещает в ней значение следующим оператором:

 

 


Квалификация имени константы Clubs именем типа Suit существенна; без нее
компилятор не может распознать Suit.

Если вы посмотрите на вывод, то увидите, что значение переменной suit отобра-
жается как имя соответствующей константы, в первом случае — Clubs. Чтобы полу-
чить константное значение, соответствующее объекту, вы должны явно привести его
к типу int, как в следующем операторе:

 

 


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

Спецификация типа перечислимых констант

Константы в перечислениях C++/CLI могут относиться к любому из следующих
типов:

 

 


Чтобы специфицировать тип констант перечисления, название типа констант за-
писывается после имени типа перечисления и отделяется двоеточием — как и в пере-
числениях "родного" С++. Например, чтобы специфицировать константу перечисле-
ния как char, потребуется написать:



 

 


Константы в перечислении будут иметь тип Char, а лежащий в их основе фунда-
ментальный тип будет char. Первая константа по умолчанию соответствует кодовому
значению 0, а все последующие присваиваются по порядку возрастания. Чтобы полу-
чить лежащее в основе значение, следует явно привести его к требуемому типу.

Спецификация значений для перечислимых констант

Вы не обязаны принимать значения по умолчанию для констант перечисле-
ний. Можно явно присвоить значения любой или всем константам перечисления.
Например:

 


В результате этого Асе будет иметь значение 1, Two — 2 и так далее, вплоть до
King, которое примет значение 13. Если же вы хотите, чтобы значения констант ото-
бражали старшинство карт, где самый старший — туз (Асе), то можете написать опре-
деление перечисления так:

 

 


В этом случае Two принимает значение 2, а последующие константы — последую-
щие значения в порядке возрастания, так что King опять будет равен 13. Асе получа-
ет значение 14 — в соответствии с явным присваиванием.


Данные, переменные и вычисления 135

 

Значения, присвоенные перечислимым константам, не обязательно должны быть
уникальными. Это дает возможность использовать значения констант для выражения
некоторого дополнительного свойства. Например:

 

 


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

 

Резюме

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

□ Программа на С++ состоит как минимум из одной функции по имени main ().

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

□ Операторы в С++ завершаются точкой с запятой.

□ Именованные объекты С++, такие как переменные и функции, могут иметь
имена, состоящие из последовательностей букв и цифр, начинающихся с бук-
вы, причем знак подчеркивания трактуется как буква. Символы верхнего и
нижнего регистра считаются различными.

□ Для именования объектов программы, таких как переменные, нельзя исполь-
зовать ключевые слова С++. Полный список зарезервированных слов С++ при-
веден в приложении А.

□ Все константы и переменные в С++ относятся к определенному типу. Фундамен-
тальные типы ISO/ANSI С++ — char, int, long, float и double. В C++/CLI
также определены типы Intl6, Int32 и Int64.

□ Имя и тип переменной определяются в операторе объявления, завершающем-
ся точкой с запятой. В объявлениях может выполняться инициализация пере-
менных начальными значениями.

□ Можно защищать значения переменных базовых типов с помощью модифика-
тора const. Это предотвращает непосредственные модификации таких пере-
менных в программе. В любом месте программы, где обнаружится попытка из-
менить значение константы, выдается ошибка компиляции.

□ По умолчанию переменная является автоматической; это означает, что она су-
ществует, только начиная с точки ее объявления и до конца блока, в котором
она объявлена, указанного закрывающей фигурной скобкой.

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

□ Переменные могут быть объявлены вне любых блоков программы — в этом слу-
чае они имеют глобальную область видимости. Переменные, имеющие глобаль-
ную область видимости, доступны из любой ее точки, за исключением тех мест,


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

□ Пространство имен определяет область видимости, объявленные в которой
имена квалифицированы дополнительным именем — именем пространства
имен. Обращение к таким именам извне этого пространства имен требует обя-
зательной квалификации (полного имени).

□ Стандартная библиотека ISO /ANSI С++ содержит функции и операторы, кото-
рые вы можете применять в своих программах. Все они объявлены в простран-
стве имен std. Корневое пространство имен библиотек C++/CLI называется
System. Получить доступ к индивидуальным объектам в пространстве можно
путем указания имени пространства имен в составе квалифицированного име-
ни с применением операции разрешения контекста, либо после указания в
объявлении using имени этого пространства имен.

□ lvalue — это объект, который может стоять в левой части выражения присваи-
вания. Примерами lvalue могут быть неконстантные переменные.

□ Можно смешивать разнотипные переменные и константы в пределах одного
выражения, но при этом они при необходимости автоматически преобразуют-
ся к одному общему типу. Преобразование типа выражения, стоящего справа
от знака равенства в выражениях присваивания, к типу левой части также при
необходимости выполняется автоматически. Это может привести к потере ин-
формации, когда тип левого элемента не может содержать информацию типа
правого выражения: например double, преобразованное в int, или long, пре-
образованное в short.

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

□ Ключевое слово typedef позволяет определять синонимы для других типов.

Хотя я привел описание всех фундаментальных типов, не стоит думать, что это
все типы, которые имеются. Как вы вскоре увидите, существуют также более слож-
ные типы, основанные на базовом наборе, а вдобавок к этому со временем вы научи-
тесь создавать и собственные типы.

В этой главе вы узнали о трех стратегиях кодирования, которых можно придержи-
ваться при написании программ C++/CLI.

□ Вы должны использовать имена фундаментальных типов для переменных, но
иметь в виду, что на самом деле они — синонимы имен классов типа значения в
программах C++/CLI. Важность этого обстоятельства станет более очевидной,
когда вы узнаете больше о классах.

□ Вы должны использовать в своем коде C++/CLI saf e_cast, а не static_cast.
Разница между ними более важна в контексте объектов классов, но если вы вы-
работаете привычку применять saf ecast, то можно ожидать, что тем самым
избежите проблем.

□ Для объявления перечислимых типов в C++/CLI вы должны использовать enum
class.


Данные, переменные и вычисления 137

 

Упражнения

Исходные коды упражнений и их решения можно загрузить с Web-сайта издатель-
ства.

1. Напишите программу ISO/ANSI С++, которая приглашает пользователя ввести
число, а затем печатает его, используя локальную целочисленную переменную.

2. Напишите программу, которая читает целое значение, вводимое с клавиатуры,
в переменную типа int и использует одну из битовых операций (но не %!) для
определения положительного остатка от деления на 8. Например, 29 = (3 х 8) + 5
и -14 = (-2 х 8) + 2 имеют положительные остатки 5 и 2 соответственно.

3. Снабдите скобками следующие выражения, чтобы проиллюстрировать приори-
теты и ассоциативность:

 

 


4. Создайте программу, которая вычисляет коэффициент пропорциональности
(aspect ratio) экрана вашего компьютера по заданным значениям ширины и вы-
соты в пикселях, используя следующие операторы:

5.

 

 


Какой ответ вы получите в результате? Будет ли он удовлетворительным? Если
нет — как следует модифицировать код, не добавляя новых переменных?

6. (Усложненное.) Не запуская на выполнение следующий код, можете ли вы ска-
зать, какой результат он выдаст и почему?

 

 


6. Напишите консольную программу C++/CLI, которая использует перечисле-
ние для идентификации месяцев года значениями номеров месяцев от 1 до 12.
Программа должна выдавать каждую константу перечисления и лежащее в осно-
ве значение.

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

Комната 1: 10,5 на 17,6, Комната 2: 12,7 на 18,9, Комната 3: 16,3 на 15,4

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


Решения и циклы

 

В этой главе вы узнаете, как можно добавить в программы С++ средства принятия
решений. Кроме того, вы научитесь тому, как заставить программу повторно выпол-
нять набор действий до наступления определенного условия. Это позволит вам обра-
батывать значительные объемы входной информации, а также выполнять проверку
корректности прочтенных данных. Вы сможете писать программы, которые адапти-
руют свое поведение в зависимости от входных данных, и иметь дело с проблемами,
где принятие решений основано на логике. После изучения этой главы вы узнаете
следующие моменты.

□ Как сравнивать значения данных.

□ Как изменять последовательность выполнения программы на основе некоторо-
го результата.

□ Как применять логические операции и выражения.

□ Как справляться с ситуациями с множеством вариантов выбора.

□ Как писать и использовать циклы в программах.

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

 

Сравнение значений

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


140 Глава 3

 

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

Операция сравнения "равно" состоит из двух подряд знаков равенства. Это не то же са-
мое, что операция присваивания, которая состоит лишь из одного знака равенства.
Распространенная ошибка связана с использованием операции присваивания вместо опера-
ции сравнения, поэтому будьте внимательны.

Каждая из этих операций сравнивает значения двух своих операндов и возвраща-
ет одно из двух возможных значений типа bool: true — если сравнение истинно, и
false — если нет. Вы можете увидеть, как это работает, рассмотрев несколько про-
стых примеров сравнений. Предположим, что объявлены целочисленные перемен-
ные i и j со значениями 10 и -5 соответственно. Все представленные ниже выраже-
ния возвращают значение true:

Далее предположим, что вы определили следующие переменные:

Вот несколько примеров сравнений, использующих эти символьные переменные:

 

 


Все четыре выражения сравнивают значения кодов ASCII. Первое выражение воз-
вращает true, потому что first инициализировано символом ' А', что эквивалент-
но десятичному числу 65. Второе выражение проверяет, меньше ли значение first,
которое равно ' А', чем значение last, которое равно ' Z 1. Если заглянуть в табли-
цу кодов символов ASCII в приложении Б, то мы увидим, что заглавные буквы пред-
ставлены последовательными числовыми величинами — от 65 до 90, при чем 65 пред-
ставляет ' А', а 90 — ' Z ', поэтому второе сравнение также вернет true. Третье же
выражение вернет false, потому что ' Е1 больше, чем значение first. Последнее
выражение вернет true, поскольку 'А' определенно не равно * Z'.

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

взгляните на такие выражения:

Как видите, в качестве операндов сравнения можно использовать выражения,
возвращающие числовые значения. Если вы заглянете в таблицу приоритетов, при-
веденную в главе 2, то увидите, что скобки не являются совершенно необходимыми,
однако они помогают сделать выражения яснее. Первое сравнение истинно, поэтому
возвращает bool-значение true. Переменная у содержит очень малое отрицательное
число, — 0,000000000025, а потому оно больше, чем -1. Второе сравнение возвращает
false. Выражение 10 — i равно 20, то есть тому же, что и j. Третье выражение воз-
вращает true, потому что 3 + у чуть меньше, чем 3.


Решения и циклы 141

 

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

 

Оператор if

Базовый оператор i f позволяет программировать выполнение единственно-
го оператора или блока операторов, заключенных в фигурные скобки, если данное
условное выражение оценено как истинное, или же пропустить оператор или блок
операторов, если условие оценено как ложное. Это показано на рис. 3.1.

Рис. 3.1. Базовый оператор if
Вот простой пример оператора if:

Проверяемое условие помещается в скобки, следующие за ключевым словом if,
после чего следует оператор, который должен быть выполнен, если условие возвра-
щает true. Обратите внимание на то, где находится точка с запятой. Она идет после
следующего за if со скобками оператора; то есть, не должно быть точки с запятой сра-
зу после проверочного условия в скобках, так как эти две строки, по сути, составляют
единый оператор. Вы также можете видеть, как оператор, следующий за if, сдвинут,
чтобы отметить, что он должен быть выполнен только в том случае, когда условие if
вернет true. Такой отступ не является необходимым, чтобы программа компилиро-
валась и исполнялась, но он помогает вам увидеть отношение между условием if и
оператором, который от него зависит. Оператор вывода в этом фрагменте кода вы-
полняется только в том случае, если переменная letter содержит значение 'А'.

Вы можете расширить этот пример, добавив оператор, изменяющий значение
letter, если оно равно 'А':

 

 

 


 


Блок операторов, управляемый оператором if, ограничен фигурными скобками.
Здесь операторы блока выполняются, только если условие (letter == 'А') оцени-
вается как true. Без этих скобок лишь первое из них было бы субъектом if, а при-
сваивание 1 а * переменной letter выполнялось бы всегда, независимо от условия if.
Обратите внимание, что после каждого оператора в блоке ставится точка с запятой,
но не после закрывающей фигурной скобки. В блоке может быть столько операторов,
сколько вам нужно. Здесь в результате того, что letter содержит ' А', его значение
изменяется на 1 а' после вывода такого же сообщения, как и раньше. Если же условие
вернет false, ни один из операторов блока не выполняется.

Вложенные операторы if


Рассмотрим пример вложенных операторов i f в рабочем примере.

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


Решения и циклы 143

 

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

Программа начинается с обычных строк комментариев; затем идет оператор
#include для включения заголовочного файла поддержки ввода-вывода и объявле-
ние using для cin, cout и endl из пространства имен std. Первое действие в теле
main () — приглашение пользователю на ввод буквы. Введенная буква сохраняется в
переменной типа char по имени letter.

Оператор if, который следует за вводом, проверяет введенный символ на пред-
мет того, больше или равен он 1 А1. Поскольку коды ASCII для прописных букв
(от 97 до 122) больше, чем коды заглавных букв (от 65 до 90), ввод прописной бук-
вы заставит программу выполнить блок первого оператора if, потому что условие

возвращает true для всех букв. В этом случае выполняется вло-
женный оператор if, который проверяет, меньше или равен введенный символ 1Z'.
Если он равен ' Z' или меньше, это значит, что введена заглавная буква, отображается
соответствующее сообщение, и на этом программа завершается оператором return.
Оба оператора заключены в фигурные скобки, поэтому оба они выполняются, если
условие вложенного if возвращает true.

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

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

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

Ниже показан пример выполнения этого примера.

 

 


Можно легко организовать преобразование символа верхнего регистра в ниж-
ний, добавив только один дополнительный оператор к if, проверяющий верхний
регистр:

 


Здесь добавлено один дополнительный оператор. Он преобразует заглавную букву
в прописную, увеличивая значение letter на разность ' а' - 'А'. Это работает, по-
тому что ASCII-коды от ' А' до 1 Z 1 и от 1 а1 до ' z ' представляют две непрерывных
группы последовательных числовых кодов, поэтому выражение 1 а1 - 'А1 представ-
ляет значение, которое должно быть добавлено к букве верхнего регистра, чтобы по-
лучить эквивалентную букву нижнего регистра.

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


144 Глава 3

 

Существует библиотечная функция ISO/ANSI С++ для преобразования букв в верхний ре-
гистр, поэтому обычно вам не придется программировать эту операцию самостоятельно.
Она называется toupper (), и ее заголовок содержится в стандартном библиотечном фай-
ле <ctype>. Позднее вы узнаете больше о библиотечных средствах, когда мы поговорим о
написании функций.

Расширенный оператор if

Оператор if, который вы использовали до сих пор, выполнял оператор или блок,
если указанное условие возвращало true. Затем выполнение программы продолжа-
лось со следующего оператора по порядку. Но есть и другая версия if, которая позво-
ляет выполнить один оператор, когда условие if возвращает true, и другой — когда
оно возвращает false. После этого выполнение программы продолжается со следу-
ющего оператора по порядку. Как вы уже видели в главе 2, блок операторов всегда
может заменить один оператор, и это также касается расширенной версии if

 

 


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

После чтения входного значения в number оно проверяется на четность путем взя-
тия остатка от деления на 2 (используя для этого операцию %, с которой вы познако-
мились в предыдущей главе) и проверки его в условии оператора if. В данном случае

условие оператора if возвращает целое, а не булевское значение. Оператор if ин-
терпретирует ненулевое значение, возвращенное условием, как true, а нулевое — как
false. Другими словами, условное выражение:

(number % 2L)

Типичный вывод этой программы:

 
 

Решения и циклы 145

 

эквивалентно такому:

 


Если остаток равен 1, условие равно true, и тогда выполняется оператор, следу-
ющий непосредственно за if. Если же остаток равен 0, то условие оценивается как
false, и тогда выполняется оператор, следующий за ключевым словом else.

Условие оператора if может быть выражением, возвращающим значение любого из фунда-
ментальных типов данных, с которыми вы познакомились в главе 2. Когда условное выраже-
ние возвращает числовое значение вместо bool, то компилятор вставляет автоматическое
приведение результата такого выражения к типу bool. Приведение к bool ненулевого зна-
чения дает true, а нулевого— false.

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

Ключевое слово else пишется без точки с запятой— так же, как часть оператора if.
Опять-таки, отступы служат для визуального выделения отношений между операторами.
Благодаря им, вы можете ясно видеть, какой оператор выполняется в случае true или нену-
левого результата, а какое— в случае false или нуля. Вы всегда должны сдвигать операторы
в своей программе, чтобы подчеркнуть ее логическую структуру

Комбинация if-else предоставляет выбор между двумя возможностями. Общая
логика if-else показана на рис. 3.2.


146 Глава 3

 

Стрелочки на диаграмме указывают последовательность выполнения операторов,
в зависимости от того, возвращает условие if значение true или false.


Дата добавления: 2015-11-04; просмотров: 22 | Нарушение авторских прав







mybiblioteka.su - 2015-2024 год. (0.033 сек.)







<== предыдущая лекция | следующая лекция ==>