Лекция 2. Переменные, Типы данных и выражения

1.Идентификаторы

В исходном тексте программ на Си++ используется довольно много англий-

ских слов и их сокращений. Все слова (идентификаторы), встречающиеся в програм-

мах, можно разделить на три категории:

1) Служебные слова языка. Например, это слова if, int и else. Назначение

этих слов предопределено и его нельзя изменить. Ниже приведен более

полный список служебных слов:


asm continue float new


signed


try


auto


default for


operator sizeof


typedef


break delete


friend


private


static


union


case do

catch double


goto

if


protected struct

public switch


unsigned

virtual


char else


inline


register template void


class enum

const extern


int

long


return

short


this

throw


volatile

while


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

2) Библиотечные идентификаторы. Назначение этих слов зависит от среды

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

изменить их смысл. Примеры таких слов: cin, cout и sqrt (имя функции

извлечения квадратного корня).

3) Идентификаторы, введенные программистом. Эти слова "создаются"

программистом – например, имена переменных (такие, как year_now и an-

other_age в программе 1.5.1).

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

По правилам Си++, идентификатор начинается с буквы или символа подчеркивания

("_") и состоит только из английских букв, цифр и символов подчеркивания.

2.Типыданных

2.1 Целые числа

Правила Си++ требуют, чтобы в программе у всех переменных был задан тип

данных. Тип данных int встречался нам уже неоднократно. Переменные этого типа

применяются для хранения целых чисел (integer). Описание переменной, как имею-

щей тип int, сообщает компилятору, что он должен связать с идентификатором

(именем) переменной количество памяти, достаточное для хранения целого числа во

время выполнения программы.

Границы диапазона целых чисел, которые можно хранить в переменных типа

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

short int и long int. Они представляют, соответственно, более узкий и более

широкий диапазон целых чисел, чем тип int. Добавление к любому из этих типов

префикса unsigned означает, что в переменной будут хранится только неотрица-

тельные числа. Например, описание:

unsigned short int year_now, age_now, another_year, another_age;



резервирует память для хранения четырех относительно небольших неотрицательных

чисел.

Приведем несколько полезных правил, касающихся записи целочисленных

значений в исходном тексте программ.

1) Нельзя пользоваться десятичной точкой. Значения 26 и 26.0 одинаковы, но

"26.0" не является значением типа "int".

2) Нельзя пользоваться запятыми в качестве разделителей тысяч. Например,

число 23,897 следует записывать как "23897".

3) Целые значения не должны начинаться с незначащего нуля. Он применяется

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

дет рассматривать значение "011" как число 9 в восьмеричной форме.

2.2 Вещественные числа

Для хранения вещественных чисел применяются типы данных float и

double. Смысл знаков "+" и "-" для вещественных типов совпадает с целыми. По-

следние незначащие нули справа от десятичной точки игнорируются. Поэтому вари-

анты записи "+523.5", "523.5" и "523.500" представляют одно и то же значение. В

Си++ также допускается запись в формате с плавающей запятой (в экспоненциальном

формате) в виде мантиссы и порядка. Например, 523.5 можно записать в виде

"5.235e+02" (т.е. 5.235*10*10), а -0.0034 в виде "-3.4e-03".

В большинстве случаев используется тип double, он обеспечивает более высо-

кую точность, чем float. Максимальную точность и наибольший диапазон чисел

достигается с помощью типа long double, но он требует больше памяти (в

Visual C++ 10 байт на число), чем double (8 байт).

2.3 Преобразование типов в выражениях

При выполнении вычислений иногда бывает нужно гарантировать, что опреде-

ленное значение будет рассматриваться как вещественное число, даже если на самом

деле это целое. Чаще всего это нужно при делении в арифметических выражениях.

Применительно к двум значениям типа int операция деления "/" означает деление

нацело, например, 7/2 равно 3. В данном случае, если необходимо получить результат

3.5, то можно просто добавить десятичную точку в записи одного или обоих чисел:

"7.0/2", "7/2.0" или "7.0/2.0". Но если и в числителе, и в знаменателе стоят перемен-

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

нить явное преобразование типа. Например, значение "7" преобразуется в значение

типа double с помощью выражения "double(7)". Поэтому в выражении

answer = double(numerator) / denominator

операция "/" всегда будет рассматриваться компилятором как вещественное деление,

даже если "numerator" и "denumerator" являются целыми числами. Для явного преоб-

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

"int(14.35)" приведет к получению целого числа 14.


2.4 Символьный тип

Для хранения символьных данных в Си++ предназначен тип "char". Перемен-

ная типа "char" рассчитана на хранение только одного символа (например, буквы

или пробела). В памяти компьютера символы хранятся в виде целых чисел. Соответ-

ствие между символами и их кодами определяется таблицей кодировки, которая зави-

сит от компьютера и операционной системы. Почти во всех таблицах кодировки есть

прописные и строчные буквы английского алфавита, цифры 0,...,9, и некоторые

специальные символы, например, #, Ј,!, +, - и др. Самой распространенной таблицей

кодировки, скорее всего, является таблица символов ASCII.

В тексте программ символьные константы типа "char" надо заключать в оди-

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

ошибке компиляции, или, что еще хуже, к ошибкам времени выполнения. Например,

"'A'" является символьной константой, но "A" будет рассматриваться компилятором в

качестве имени переменной. Аналогично, "'9'" является символом, а "9" – целочис-

ленной константой.

Т.к. в памяти компьютера символы хранятся в виде целых чисел, то тип "char"

на самом деле является подмножеством типа "int". На Си++ разрешается использо-

вать символы в арифметических выражениях. Например, на любом компьютере с

таблицей ASCII следующее выражение даст истинное значение (TRUE, или 1):

'9'-'0' == 57-48 == 9

В таблице ASCII кодом символа '9' является десятичное число 57 (в шестнадца-

теричной записи 0x39), а ASCII–код символа '0' равен десятичному числу 48 (шестна-

дцатеричное значение 0x30). Приведенное выражение можно переписать в виде:

57-48 == 0x39-0x30 == 9

Кодами ASCII удобнее пользоваться в шестнадцатеричной форме. При записи

шестнадцатеричных чисел в Си++ применяется двухсимвольный префикс "0x".

Переменные типа "char" существенно отличаются от "int" при выполнении

ввода данных с клавиатуры и вывода на экран. Рассмотрим следующую программу.

#include <iostream.h>

int number;

char character;

cout << "Напечатайте символ и нажмите Enter:\n";

cin >> character;

number = character;

cout << "Вы ввели символ '" << character;

cout << "'.\n";

cout << "В памяти компьютера он хранится в виде числа ";

cout << number << ".\n";

return 0;

Программа 2.1.

Программа 2.1 выдает на экран следующие сообщения:


Напечатайте символ и нажмите Enter:

Вы ввели символ '9'.

В памяти компьютера он хранится в виде числа 57.

Программу 2.1 можно изменить так, чтобы она печатала всю таблицу символов

ASCII. Для этого придется применить "оператор цикла for". "Цикл for" является

примером оператора цикла – эти операторы будут рассмотрены подробно в одной из

следующих лекций. Оператор for имеет следующий синтаксис:

for (инициализация; условие_повторения; изменение_значений)

{

Оператор 1;

...

...

Оператор N;

}

Цикл for выполняется в следующем порядке: (1) Сначала выполняется опера-

тор инициализации. (2) Выполняется проверка, является ли условие_повторения истин-

ным. Если условие ложно, то оператор for завершается. Если условие истинно, то

последовательно выполняются операторы тела цикла Оператор 1... Оператор N, и затем

выполняется оператор изменение_значений. После этого происходит переход на нача-

ло шага (2).

Чтобы код символа вывести на экран в шестнадцатеричной форме, надо снача-

ла послать на экран служебный символ-манипулятор. Программа для печати фраг-

мента таблицы ASCII (от 32-го символа (пробел) до 126-го (символ '~')), будет выгля-

деть так:

#include <iostream.h>

int main()

{

int number;

char character;

for (number = 32; number <= 126; number = number + 1)

{

character = number;

cout << "Символ '" << character;

cout << "' имеет код ";

cout << dec << number << " (дес.) или ";

cout << hex << number << " (шестнд.).\n";

}

return 0;

}

Программа 2.2.

Программа 2.2 напечатает на экране:

Символ ' ' имеет код 32 (дес.) или 20 (шестнд.).

Символ '!' имеет код 33 (дес.) или 21 (шестнд.).

...

...

Символ '}' имеет код 125 (дес.) или 7D (шестнд.).

Символ '~' имеет код 126 (дес.) или 7E (шестнд.).


2.5 Символьные строки

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

используются символьные строки. В Си++ символьные строки заключаются в двой-

ные кавычки. Поэтому в программах часто встречаются операторы вывода вроде:

cout << "' имеет код ";

На самом деле в Си++ строковый тип ("string") не является стандартным ти-

пом данных, таким, как, например, "int", "float" или "char". Строки хранятся в памя-

ти в виде символьных массивов, поэтому строки будут рассматриваться позднее, при

изучении массивов.

2.6 Типы данных, определяемые пользователем

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

много более подробно в последующих лекциях. Будет показано, как программист

может определить собственный тип данных, необходимый для решения конкретной

задачи. Средства определения новых типов данных – одна из наиболее мощных воз-

можностей Си++, которые позволяют хранить и обрабатывать в программах на Си++

сложные структуры данных.

3.Выводвещественныхчиселнаэкран

При выводе на экран численных значений типа "float", "double" или "long

double" возможно указание точности представления данных на экране и задание не-

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

в формате с фиксированной или плавающей точкой.

В программе 3.1 вещественное число отображается в формате с фиксированной

точкой и двумя десятичными знаками после запятой. Идентификатор "sqrt" является

именем библиотечной функции извлечения квадратного корня. Описание библиотеки

математических функций содержится в заголовочном файле "math.h".

#include <iostream.h>

#include <math.h>

int main()

{

float number;

cout << "Введите вещественное число.\n";

cin >> number;

cout << "Корень из ";

cout.setf(ios::fixed); // СТРОКА 12

cout.precision(2);

cout << number;

cout << " примерно равен " << sqrt(number) << ".\n";

return 0;

}

Программа 3.1.

Программа 3.1 напечатает на экране:


Введите вещественное число.

Корень из 200.00 примерно равен 14.14.

Если СТРОКУ 12 заменить на "cout.setf(ios::scientific);", то вид результа-

та изменится:

Введите вещественное число.

Корень из 2.00e+02 примерно равен 1.41e+01.

В выходные данные можно включить параметры табуляции. Для этого предна-

значена функция ширины поля, например, "cout.width(20)". Она задает ширину сле-

дующего выводимого на экран значения равной, как минимум, 20 символам (при

меньшей ширине автоматически будут добавлены пробелы). Эта возможность осо-

бенно полезна для печати таблиц.

В компиляторе Visual C++ при указании ширины поля по умолчанию предпо-

лагается, что значения выравниваются по правой границе. Чтобы задать выравнива-

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

ввода-вывода. Это специальные функции и операторы, содержащиеся в библиотеке

ввода/вывода Си++. Они описаны в заголовочном файле iomanip.h. Для задания вы-

равнивания по левой границе надо установить специальный флажок (переключатель)

с помощью функции setiosflags:

#include <iostream.h>

#include <iomanip.h>

#include <math.h>

int main()

{

int number;

cout << setiosflags(ios::left);

cout.width(20);

cout << "Число" << "Квадратный корень\n\n";

cout.setf(ios::fixed);

cout.precision(2);

for (number = 1; number <= 10; number = number + 1)

{

cout.width(20);

cout << number << sqrt(number) << "\n";

}

return 0;

}

Программа 3.2.

Программа 3.2 выдаст на экран следующие сообщения:


Число


Квадратный корень


1 1.00

2 1.41

3 1.73

4 2.00

5 2.24

6 2.45




7 2.65

8 2.83

9 3.00

10 3.16

(ПРИМЕЧАНИЕ: во всех примерах идентификатор "cout" является именем перемен-

ной-объекта класса "stream" (поток). Функции "setf(...)", "precision(...)" и

"width(...)" являются функциями-членами класса "stream". Понятия "объект",

"класс", "функция-член" и др. будут подробно рассматриваться в курсе объектно-

ориентированного программирования.)

4.Описания,константыиперечисления

Как вы уже знаете, в программах на Си++ переменные обязательно должны

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

float number;

После оператора описания до момента выполнения первого оператора при-

сваивания значение переменной "number" будет неопределенным, т.е. эта переменная

может иметь случайное значение. В Си++ можно (и желательно) инициализировать

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

Например, возможен следующий оператор описания с инициализацией:

float PI = 3.1416;

Если значение переменной в программе никогда не изменяется, то ее целесооб-

разно защитить от случайного изменения с помощью служебного слова "const" – т.е.,

превратить в константу.

4.1 Тип "Перечисление"

Для описания набора связанных по смыслу констант типа "int" в Си++ есть

оператор перечисления. Например, описание вида

enum { MON, TUES, WED, THURS, FRI, SAT, SUN };

эквивалентно описанию 7 констант-кодов дней недели:

const int MON = 0;

const int TUES = 1;

const int WED = 2;

const int THURS = 3;

const int FRI = 4;

const int SAT = 5;

const int SUN = 6;

По умолчанию членам перечисления "enum" присваиваются значения 0, 1, 2, и

т.д.. При необходимости члены перечисления можно инициализировать другими зна-

чениями. Неинициализированным явно членам будут присвоены значения по поряд-

ку, начиная от предыдущего проинициализированного члена:

enum { MON = 1, TUES, WED, THURS, FRI, SAT = -1, SUN };

В приведенном примере "FRI" имеет значение 5, а "SUN" – значение 0.


4.2 Расположение описаний констант и переменных в исходном тексте

В исходном тексте описания констант чаще всего размещаются в заголовке

программы перед функцией "main". После них, уже в теле функции "main", размеща-

ются описания переменных. Для иллюстрации этого порядка ниже приведен фраг-

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

ет ее длину (набирать этот пример не надо, поскольку он приведен не полностью.)

#include <iostream.h>

const float PI = 3.1416;

const float SCREEN_WIDTH = 317.24;

int drawCircle(float diameter); /* Это "прототип функции" */

int main()

{

float radius = 0;

cout << "Введите радиус окружности.\n";

cin >> radius;

drawCircle(radius*2);

cout.setf(ios::fixed);

cout.precision(2);

cout << "Длина окружности радиуса " << radius;

cout << " примерно равна " << 2*PI*radius << ".\n";

return 0;

}

int drawCircle(float diameter)

{

float radius = 0;

if (diameter > SCREEN_WIDTH)

radius = SCREEN_WIDTH/2.0;

else

radius = diameter/2.0;

...

...

}

После определения функции "main()" в этой программе содержится определе-

ние функции рисования окружности "drawCircle(...)". Детали реализации этой

функции сейчас не существенны (будем считать, что функция drawCircle(...)" реа-

лизована корректно и ею можно пользоваться так же, как, например, функцией

"sqrt(...)"). Обратите внимание, что, хотя переменная "radius" используется в обеих

функциях "main()" и "drawCircle(...)", это не одна и та же переменная, а две разных.

Если бы переменная "radius" была описана до функции "main", то в таком слу-

чае она была бы глобальной переменной (общедоступной). Тогда, предполагая, что

внутри функции "drawCircle(...)" описания переменной уже нет, если "drawCir-

cle(...)" присвоит глобальной переменной значение "SCREEN_WIDTH/2.0", то это

значение чуть позже функция "main()" использует для вычисления длины окружности

и получится неверный результат.

В приведенной программе глобальной переменной нет, а есть две локальных

переменных "radius". Например, первая переменная "radius" является локальной пе-


ременной функции "main()", или, говорят, что функция "main()" является областью

видимости этой переменной.

Константы общего назначения, такие, как "PI" и "SCREEN_WIDTH", принято опи-

сывать глобально, чтобы они были доступны внутри любой функции.

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

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

ное пользователем значение "radius" еще раз печатается на экране перед отображени-

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

5.Присваиваниеивыражения

5.1 Краткая форма записи операторов присваивания

В программах часто встречаются операторы присваивания, в которых справа

стоит выражение, модифицирующее текущее значение переменной, например:

number = number + 1;

Переменным часто присваиваются значения, вычисленные на основе их старых

значений. Поэтому в Си++ была введена краткая форма записи для подобных опера-

торов присваивания. Любую из операций "+" (сложение), "-" (вычитание), "*" (умно-

жение), "/" (деление) и "%" (остаток от деления нацело) можно указать в качестве

префикса оператора присваивания ("=") (cм. следующую таблицу).


Пример:

number += 1;

total -= discount;

bonus *= 2;

time /= rush_factor;

change %= 100;

amount *= count1 + count2;


Эквивалентное выражение:

number = number + 1;

total = total - discount;

bonus = bonus * 2;

time = time / rush_factor;

change = change % 100;

amount = amount * (count1 + count2);


Первый пример допускает еще более краткую запись с помощью оператора ин-

кремента "++":

number++;

Оператор "++" существует и в префиксной форме:

++number;

Постфиксная и префиксная форма записи имеют важное различие, которое не-

обходимо помнить. Префиксный оператор применяется ДО вычисления остальной

части выражения, а постфиксный – ПОСЛЕ. Например, посоле выполнения операто-

ров

x = 4;

y = x++;

переменная "x" получит значение 5, а "y" – значение 4. В случае операторов

x = 4;

y = ++x;

обе переменные получат значение 5. Это объясняется тем, что "++x" выполняется до

того, как значение "x" будет использовано в выражении, а "x++" – после. В Си++ су-

ществует аналогичный оператор декремента "--", уменьшающий значение перемен-

ной на 1, и у него тоже есть префиксная и постфиксная форма.



Вообще, выражение с оператором присваивания имеет значение, равное значе-

нию левой части после выполнения присваивания. Ниже приведено выражение, соот-

ветствующее правилам Си++, которое можно использовать для проверки условия:

(y = ++x) == 5

Это выражение означает следующее: "после присвоения переменной y инкре-

ментированного значения x проверить, не равно ли значение y числу 5".

5.2 Логические выражения и операторы

Интуитивно логические выражения наподобие "2<7", "1.2!=3.7" и "6>=9" вос-

принимаются человеком как утверждения, которые могут быть "истинными (true)"

или "ложными (false)" (операция "!=" означает "не равно"). Допускается объеди-

нение нескольких подобных выражений в более сложное выражение с помощью ло-

гических операций "&&" ("И"), "||" ("ИЛИ") и "!" ("НЕ") (см. таблицу).


Выражение:

(6 <= 6) && (5 < 3)

(6 <= 6) || (5 < 3)

(5!= 6)

(5 < 3) && (6 <= 6) || (5!= 6)

(5 < 3) && ((6 <= 6) || (5!= 6))

!((5 < 3) && ((6 <= 6) || (5!= 6)))


Истинно или ложно:

false

true

true

true

false

true


В таблице в четвертом примере выражение истинно, поскольку приоритет опе-

рации "&&" выше, чем у "||". Приоритет (порядок выполнения) различных операций

Си++ можно узнать в учебнике или руководстве по языку Си++, а также в справочной

системе Visual C++ (тема Operator Precedence). Если у вас возникают сомнения отно-

сительно приоритета операций, применяйте круглые скобки (). Применение этих

скобок облегчает чтение программ.

Составные логические выражения обычно применяются в качестве условий в

операторах if и в циклах for. Например:

...

...

if (total_test_score >= 50 && total_test_score < 65)

cout << "Вы прошли тест со средним результатом.\n";

...

...

У логических выражений в Си++ есть еще одно важное свойство. В Си++ ис-

тинное значение ("true") представляется в виде целого числа 1 (большинство ком-

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

значение ("false") в виде значения 0. Это может привести к ошибкам. Например,

легко напечатать "=" вместо "==". Поэтому фрагмент

...

...

if (number_of_people = 1)

cout << "Есть только один человек.\n";

...

...

всегда будет печатать сообщение "Есть только один человек", даже если до оператора

if переменная "number_of_people" была больше 1.



6.Сводкарезультатов

В данной лекции довольно подробно рассматривались переменные языка Си++.

У переменных всегда есть определенный тип данных. Переменные применяются для

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

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

значений переменных можно использовать различные арифметические и логические

операции.

7.Упражнения

Упражнение 1

Для преобразования температуры из шкалы Цельсия в абсолютную шкалу тем-

ператур (шкалу Кельвина) надо добавить к температуре по Цельсию значение 273.15.

В шкалу Фаренгейта температура по Цельсию преобразуется tf = 1.8 t o + 32.

Напишите программу преобразования значений температуры, которая будет

печатать на экране следующую таблицу:

Цельсий Фаренгейт Абсолютная температура

0 32.00 273.15

20 68.00 293.15

40 104.00 313.15

.........

.........

300 572.00 573.15

Упражнение 2

Измените программу из упражнения 1 так, чтобы она запрашивала у пользова-

теля минимальную и максимальную температуру по Цельсию, которые должны быть

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

менения температуры (на это значение должны отличаться температуры в соседних

строках таблицы, в упражнении 1 шаг был равен 20-ти градусам).

Перед таблицей программа должна вывести несколько строк с пояснением сво-

их действий, а также повторить вывод на экран введенных пользователем данных.

Упражнение 3

Напишите программу, которая считывает с клавиатуры символ (ch) и затем вы-

водит одно из следующих сообщений (вместо ch должен выводиться введенный сим-

вол, а вместо... – соответствующая прописная или строчная буква):

а) если символ ch является строчной буквой – сообщение "Букве ch соответст-

вует прописная буква...",

б) если ch является прописной буквой – сообщение "Букве ch соответствует

строчная буква...",

в) если ch не является буквой – сообщение "Символ ch не является буквой".

Для составления необходимых условий обратитесь к расширенной таблице

символов ASCII (см. п.8.3).

Упражнение 4

Напишите программу для возведения произвольного числа x в положительную

степень n с помощью цикла for. (Есть ли способы повышения эффективности вашей

программы?)


8.Приложения

8.1 Служебные слова Си++

По назначению служебные слова языка Си++ можно разделить на несколько

групп. Ниже перечислены эти группы и относящиеся к ним слова. Полужирным

шрифтом выделены слова, назначение которых вы узнаете в данном вводном курсе.

• Типы данных (определяют типы данных, которые можно хранить в памяти

компьютера).


Char

Enum

Double

Void

Struct


Short

Float

union


Int

Typedef


Long


(целые числа)

(тип "перечисление")

(вещественные числа)

(типы, определяемые

пользователем)


• Модификаторы типов данных (позволяют задать некоторые свойства хране-

ния данных в памяти).


Signed


Unsigned


volatile register

Const static


Extern


auto


• Управление порядком выполнения операторов.


if


Else


(ветвление с двумя вариантами)


Switch

For

Break

Return

goto


Case

While

Continue


Default

do


(множественное ветвление)

(циклы)

(возврат из функции)

(безусловный переход)


• Динамическое распределение памяти.


New


Delete


• Объектно-ориентированное программирование (эти слова будут подробно

рассматриваться в отдельном курсе объектно-ориентированного програм-

мирования и проектирования).


class

virtual

operator


private

this


protected public

friend template


• Обработка исключений (особый механизм обработки ошибок в объектно-

ориентированных программах).


try

• Разное.

Sizeof


throw

inline


catch

asm



8.2 Таблица символов ASCII

8.3 Расширенная таблица символов ASCII для кодовой страницы DOS-866



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: