Books / 3_C#_2005_для_чайников_(Дэвис-2008)
.pdfВ зависимости от того, как именно запущена программа, данный фрагмент может оказаться очень важным. В 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 |