Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Books / 3_C#_2005_для_чайников_(Дэвис-2008)

.pdf
Скачиваний:
86
Добавлен:
24.03.2015
Размер:
15.46 Mб
Скачать

В зависимости от того, как именно запущена программа, данный фрагмент может оказаться очень важным. В Visual Studio это можно сделать двумя способами. Если ис­ пользуется команда D e b u g ^ S t a r t , Visual Studio закрывает окно программы сразу же по ее завершении. То же происходит и при запуске программы двойным щелчком на пикто­ грамме файла в Проводнике Windows.

Вне зависимости от того, каким образом запускается программа, ожидание на­ жатия пользователем клавиши <Enter> перед завершением программы решает все проблемы.

Теперь вы можете удалить из шаблона строки от первого C o n s o l e . W r i t e L i n e до предпоследнего, и получите пустой, чистый метод Main () для использования в качестве шаблона для последующих консольных приложений. Но не убирайте последние инст­ рукции Console . WriteLin e и C o n s o l e . Read. Они понадобятся вам в ваших кон­ сольных приложениях.

Глава 2. Создание консольного приложения на С#

53

Часть ІІ

Основы программирования в С #

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

Глава 3

Объявление переменных-значений

>Создание места для хранения информации — переменные С#

>Использование целых чисел

>Работа с дробными числами

>Объявление других типов переменных

>Работа с числовыми константами

>Изменение типов

 

аиболее фундаментальной из всех концепций программирования является кон­

 

цепция переменной. Переменная С# похожа на небольшой ящик, в котором мож­

 

но хранить разные вещи (в частности, числа) для последующего применения. Термин пе­

 

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

 

Эта запись означает, что, начиная с этого момента, математик, используя п, подразу­

 

мевает 1 — т.е. пока он не изменит п на что-то другое (число, уравнение и т.д.).

 

Значение термина переменная в программировании не сильно отличается от его зна-

I

чения в математике. Программист на С# может написать:

 

Тем самым он определит "вещь" п и присвоит ей значение 1. Начиная с этого места

 

программы переменная п имеет значение 1 до тех пор, пока программист не заменит его

|

некоторым другим числом.

 

К сожалению для программистов, С# накладывает ряд ограничений на переменные —

 

ограничений, с которыми не сталкиваются математики.

 

Когда математик говорит: "и равно 1", это означает, что термин п эквивалентен 1.

 

Математик свободен в своем выборе переменных — например, он может сказать или на­

 

писать следующее:

 

х = у2+2у+1

 

Если к = у + 1 , то х = к2

 

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

 

определены ранее. Однако затем математик вводит еще одну переменную к, и дело не просто

 

в том, что ее значение на 1 больше значения переменной у, нет, здесь к замещает собой поня-

тие "у плюс 1", представляя собой что-то вроде сокращенной записи. Если вы хотите разо­ браться в этом более детально и точно — обратитесь к учебникам по математике.

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

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

Знак равенства (=) называется оператором присваивания.

Математик говорит: "и равно 1". Программист на С# выражается более точно: "Сохраним значение 1 в переменной п". Операторы С# указывают компьютеру, что именно вы хотите сделать. Другими словами, операторы — это глаголы, а не существительные. Оператор присваивания берет значение справа от него и сохраняет его в переменной, указанной слева от него.

Ч т о т а к о е int

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

Математик может написать следующее:

П= 1;

П= 1 . 1 ;

п

=

H o u s e ;

п

=

"Ну и г л у п о с т ь ! "

Приведенные строки приравнивают переменную п к разносортным вещам, и матема­ тик об этом абсолютно не беспокоится.

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

В примере в предыдущем разделе вы выбрали ящик, созданный для работы с целыми

числами — С#

называет их i n t . Целые числа — это числа,

применяющиеся для пере­

числения (1, 2,

3 и т.д.), а также 0 и отрицательные числа

 

1, -2, -3...

 

Перед тем как использовать переменную, ее надо объявить. После того как вы объявили переменную как i n t , в нее можно помещать и извлекать из нее це­ лые значения, что продемонстрировано в следующем примере:

//

Объявляем переменную п

i n t

П;

58

Часть II. Основы программирования в С#

// Объявляем переменную m и инициализируем ее значением 2 int m = 2 ;

// Присваиваем значение, хранящееся в т, переменной п п = т,-

Первая строка после комментария является объявлением, которое создает небольшую область в памяти с именем п, предназначенную для хранения целых значений. Началь­ ное значение п не определено до тех пор, пока этой переменной не будет присвоено не­ которое значение. Второе объявление не только объявляет переменную m типа i n t , но и инициализирует ее значением 2.

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

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

Правила объявления п е р е м е н н ы х

Вы можете выполнить инициализацию переменной как часть ее объявления:

// Объявление

переменной типа i n t с присваиванием ей

// начального

значения 1

int 0 = 1 ;

 

Это эквивалентно помещению 1 в ящик i n t в момент его аренды, в отличие от его вскрытия и помещения туда 1 позже.

Инициализируйте переменные при их объявлении. Во многих, но не во всех, случаях С# инициализирует переменные за вас, но рассчитывать на это нельзя.

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

//Это присваивание неверно, поскольку переменной m не

//присвоено значение перед ее использованием

int m;

 

n = m;

 

// Следующее присваивание некорректно в

силу того , что

// переменная р не была объявлена до ее

использования

р = 2;

 

'int р;

 

И последнее — нельзя дважды объявить одну и ту же переменную.

Вариации на т е м у int

Большинство простых переменных имеют тип i n t . Однако С# позволяет настраивать целый тип для конкретных случаев.

Глава 3. Объявление переменных-значений

59

Все целочисленные типы переменных ограничены хранением только целых чисел, но! диапазоны этих чисел различны. Например, переменная типа i n t может хранить только! целые числа из диапазона примерно от -2 миллиардов до 2 миллиардов.

Два миллиарда сантиметров — это больше, чем диаметр Земли. Но если этой величи-В ны вам не хватает, С# имеет еще один целочисленный тип, называемый 1опдИ (сокращение от l o n g i n t ) , который может хранить гораздо большие числа ценой уве-ш личения размера "ящика": он занимает 8 байт (64 бит) в отличие от 4-битового i n t .

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

Как будет рассказано позже, фиксированные значения — такие как 1 — тоже имеют тип. По умолчанию считается, что простая константа наподобие 1 имеет тип i n t . Константы, отличные от i n t , должны явно указывать свой т и п — так, например, 123U (обратите внимание на U) — это константа типа u i n t — беззнакового целого.

Большинство целых значений — знаковые (signed), т.е. они могут представлять наряду с положительными и отрицательные значения. Беззнаковые (unsigned) целые числа могут представлять только неотрицательные значения, но зато их диапазон представле ния удваивается по сравнению с соответствующими знаковыми типами. Как видно из табл. 3.1, имена большинства беззнаковых типов образуются из знаковых путем добав ления префикса и.

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

Множество вычислений требуют применения дробных чисел, которые никак не могут быть точно представлены целыми числами. Общее уравнение для конвертации темпера­ туры в градусах Фарегнейта в температуру в градусах Цельсия демонстрирует это:

Напомним, что автор учился в американской школе. — Примеч. пер.

60

Часть II. Основы программирования в С#

// Преобразование температуры 45°F

int nFahr =

4 1 ;

int nCelsiu s

= (nFahr - 32) * ( 5 / 9 ) ;

Для некоторых значений данное уравнение работает совершенно корректно. Напри­ мер, 41 °F равен 5°С. "Правильно, Девис!" — сказала бы мне учительница в 6 классе.

Попробуем теперь другое значение, например 100°F. Приступим к вычислениям: 100-32 = 68; 68 (5/9) дает 37. " Н е т , — сказала бы учительница,— правильный от­ вет — 37.78". И даже это не совсем верно, так как в действительности правильный от­ вет—37.777..., где 7 повторяется до бесконечности, но, увы, невозможно написать бес­ конечную книгу.

Тип i n t может представлять только целые числа. Целый эквивалент числа 37.78 — 37. При этом, для того чтобы разместить число в целой переменной, дробная часть числа отбрасывается — такое действие называется усечением

(truncation).

Усечение — совсем не то же самое, что округление (rounding). Усечение от­ брасывает дробную часть, а при округлении получается ближайшее целое значение. Так, усечение 1.9 даст 1, а округление — 2.

Для температур 37 может оказаться вполне достаточно. Вряд ли ваша одежда при 37.78°С будет существенно отличаться от одежды при 37°С. Но для множества, если не большинства, приложений такое усечение неприемлемо.

На самом деле все еще хуже. Тип i n t не в состоянии хранить значение 5/9 и преоб­ разует его в 0. Соответственно, данная формула будет давать нулевое значение nCel­ sius для любого значения nFahr. Поэтому даже такой непритязательный человек, как я, сочтет это неприемлемым.

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

 

Ограничения, накладываемые на переменные типа i n t , для многих приложений не­

 

приемлемы. Обычно главным препятствием является не диапазон возможных значений

 

(двух квинтиллионов 64-битового l o n g хватает, пожалуй, для подавляющего

большин­

 

ства задач), а невозможность представления дробных чисел.

 

 

В некоторых ситуациях нужны числа, которые могут иметь ненулевую дробную

 

часть, и которые математики называют действительными числами (real numbers). Все­

 

гда находятся люди, удивляющиеся такому названию — неужели целые числа — не­

 

действительные?

 

? в С#

Глава 3. Объявление переменных-значений

61

Обратите внимание на сказанное о том, что действительное число может иметь ненулевую дробную часть — т.е. число 1.5 является действительным так же, как и число 1.0. Например, 1.0 + 0.1 = 1.1. Просто при чтении оставшейся части этой главы все время не забывайте о наличии точки.

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

сплавающей точкой и с так называемым десятичным представлением. Гораздо более распространена плавающая точка.

О б ъ я в л е н и е переменной с п л а в а ю щ е й т о ч к о й

Переменная с плавающей точкой может быть объявлена так, как показано в следую­ щем примере:

f l o a t f = 1 . 0 ;

После того как вы объявите переменную как f l o a t , она остается таковой при всех естественных для нее операциях.

В табл. 3.2 рассматриваются использующиеся в С# типы с плавающей точкой. Все переменные этих типов — знаковые (т.е. не существует такой вещи, как переменная с плавающей точкой, не способная представлять отрицательные значения).

Вы можете решить, что тип f l o a t — это тип по умолчанию для переменных с { плавающей точкой, но на самом деле типом по умолчанию является d o u b l e . Если вы не определите явно тип для, скажем, 12.3, С# сделает его d o u b l e .

Столбец точности в табл. 3.2 указывает количество значащих цифр, которые может представлять такая переменная. Например, 5/9 на самом деле равно 0.555... с бесконечной последовательностью пятерок. Однако переменная типа f l o a t имеет точность не более 6 цифр, что означает, что все цифры после шестой могут быть проигнорированы. I Таким образом, 5/9 , будучи выражено в виде f l o a t , может выглядеть как

0 . 5 5 5 5 5 5 1 4 5 7 3 8 2

Не забывайте, что все цифры после шестой пятерки ненадежны.

На самом деле тип f l o a t имеет 6.5 значащих цифр. Дополнительные полциф­ ры получаются из-за того, что точность представления чисел с плавающей точ­ кой связана с такой функцией, как 10'°82 . Впрочем, вряд ли это должно сильно вас интересовать.

То же число 5/9 может выглядеть при использовании типа d o u b l e следующим образом:

0 . 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 7 8 2 3

Тип d o u b l e имеет 15-16 значащих цифр.

62

Часть II. Основы программирования в С#

Числа с плавающей точкой в С# по умолчанию имеют точность double, так что применяйте везде тип double, если только у вас нет веских причин по­ ступить иначе. Однако используете ли вы d o u b l e или f l o a t — все равно ваша программа будет считаться программой, работающей с числами с пла­ вающей точкой.

Более точное преобразование т е м п е р а т у р

Вот как выглядит формула преобразования температур в градусах Фаренгейта в гра­ дусы Цельсия при использовании переменных с плавающей точкой:

dCelsius = (dFahr - 3 2 . 0 ) * ( 5 . 0 / 9 . 0 ) ;

На прилагаемом к книге компакт-диске имеется double-версия программы преобразования температур ConvertTemperatureWithFloat .

Приведенный далее пример показывает результат работы программы ConvertTem­ peratureWithFloat:

Введите температуру в градуса х

Фаренгейта: 100

Температура

в

градусах Цельсия

равна: 3 7 . 7 7 7 7 7 7 7 7 7 7 7 7 8

Press Enter

to

t e r m i n a t e . . .

 

Ограничения переменных с п л а в а ю щ е й т о ч к о й

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

Перечисление

Нельзя использовать числа с плавающей точкой для перечисления. Некоторые струк­ туры С# должны быть подсчитаны (1, 2, 3 и т.д.). И всем известно, что числа 1.0, 2.0, 3.0 можно применять для подсчета количества точно так же, как и 1, 2, 3, но С# ведь этого не знает. Например, при указанной выше точности чисел с плавающей точкой откуда С# знать, что вы не сказали в действительности 1.000001?

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

Сравнение чисел

Вы должны быть очень осторожны при сравнении чисел с плавающей точкой. На­ пример, 12.5 может быть представлено как 12.500001. Большинство людей не волнуют такие мелкие добавки в конце числа, но компьютер понимает их буквально, и для С# 12.500000 и 12.500001 — это разные числа.

Так, если вы сложите 1.1 и 1.1, вы можете получить в качестве результата 2.2 или 2.200001. И если вы спросите: "Равно ли значение dDouv l e v a r i able. 2.2?", то можете получить совсем не тот ответ, который ожидаете. Такие вопросы вы должны переформу­ лировать, например, так: "Отличается ли абсолютное значение разности dDouvleVari ­ able и 2.2 менее чем на 0.000001?", другими словами, равны ли два значения с некото­ рой допустимой ошибкой.

Глава 3. Объявление переменных-значений

63