Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методичка 25.07.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
2.05 Mб
Скачать

Арифметические операции и операции присваивания

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

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

Арифметические операции. Арифметические операции применяются к действительным и целым числам, существуют следующие арифметические операции:

Таблица 3

Бинарные арифметические операции

Обозначение

Операция

Пример

+

сложение

X + Y

-

вычитание

X - Y

*

умножение

X * Y

/

деление

X / Y

%

Остаток целочисленного деления

I % 6

Таблица 4

Унарные арифметические операции

Обозначение

Операция

Пример

+

Унарный плюс

(подтверждение знака)

+7

-

Унарный минус

(изменение знака)

++

инкремент

i++

--

декремент

i--

Для арифметических операций действуют следующие правила:

  • Бинарные операции сложения (+) и вычитания (-) применимы к целым и действительным числам.

  • В операциях умножения (*) и деления (/) операнды могут быть любых арифметических типов. При разных типах операндов применяются стандартные правила автоматического приведения типов.

  • В операции вычисления остатка от деления (%) оба операнда должны быть целыми числами.

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

  • Унарные операции инкремента (++) и декремента (--) сводятся к увеличению (++) или уменьшению (--) операнда на единицу. Операции применимы к операндам, представляющим собой выражения любых арифметических типов. Причем выражение должно быть модифицируемым значением, т.е. должно допускать изменение. Например, ошибочным является выражение (а+b)++, поскольку (a+b) не является переменной, которую можно модифицировать.

  • Операции инкремента и декремента выполняются быстрее, чем обычное сложение и вычитание. Поэтому, если переменная а должна быть увеличена на 1, лучше применить операцию (++), чем выражения а=а+1.

Операции присваивания. В Си++ определен ряд операций присваивания.

Таблица 5

Операции присваивания

Обозначение

Операция

Пример

=

Присваивание

X=Y

+=

Присваивание со сложением

Х+=Y

-=

Присваивание с вычитанием

Х-=Y

*=

Присваивание с

умножением

Х*=Y

/=

Присваивание с делением

Х/=Y

%=

Присваивание остатка

целочисленного деления

Х%=Y

<=

Присваивание со

сдвигом влево

Х<=Y

>=

Присваивание со

сдвигом вправо

Х>=Y

&=

Присваивание с

поразрядной операцией И

Х&=Y

^=

Присваивание с

поразрядной операцией

исключающее ИЛИ

Х^=Y

|=

Присваивание с

поразрядной операцией ИЛИ

Х|=Y

Помимо простой операции присваивания (=) все прочие являются составными операциями. Они присваивают первому операнду результат применения соответствующей простой операции, указанной перед символом (=), к первому и второму операндам. Например, выражение X+=Y эквивалентно выражению X=X+Y, но записывается компактнее и может выполнятся быстрее. Аналогично определяются и другие операции присваивания: X%=Y эквивалентно X=X%Y и т.д.

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

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

Приведение типов при вычислении выражений

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

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

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

double a = 5.4, b = 2;

int c = a*b;

переменная c получит значение 10, хотя истинное значение должно быть равно 10.8. Это значение действительно будет вычислено в результате умножения a * b, но затем дробная часть будет отброшена, поскольку c – целая переменная.

Результатом выполнения операторов

int m = 1, n = 2;

double A = m / n;

будет значение A = 0. Поскольку m и n – целые переменные, то деление m / n сведется к целочисленному делению с отбрасыванием дробной части, результат которого равен нулю.

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

(тип) операнд;

тип (операнд);

Если в предыдущем примере, который давал неверное значение переменной A, применить во втором операторе явное приведение типа:

double A = (double) m / n;

или

double A = double (m) / n;

то получим правильный результат A = 0.5. В этом случае переменная m, которой применяется операция приведения типа, рассматривается как действительная величина типа double, тогда и переменная n неявно приводиться к типу double, так что деление осуществляется уже не с целыми, а с действительными числами.

Препроцессорная обработка компилятора

Обработка программы препроцессором происходит перед ее компиляцией. На этом этапе предварительной обработки вы можете выполнить следующие действия: включить в компилируемый файл другие файлы, определить символические константы и макросы, задать режим условной компиляции программного кода и условного выполнения директив препроцессора. Все директивы препроцессора начинаются с символа «#» и до начала директивы в строке могут находиться только символы пробела. Любая строка, начинающаяся с символа «#», воспринимается как директива препроцессора.

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

Существует несколько форм директивы, основные из них:

#include <имя_файла>

#include “имя_файла”

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

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

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

#include <math.h>

директива включает файл math.h, который ищется в стандартном каталоге включаемых файлов.

#include “program.h”

директива включает файл program.h, который ищется прежде всего в каталоге, в котором расположен файл, содержащий данную директиву.

#include “c:\example\function.h”

директива включают файл function.h, который ищется только в каталоге c:\example.

Ввод и вывод консольных текстовых сообщений

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

В задачу данного методического пособия не входит описание программирования в графических 32 – разрядных системах типа MS Windows, поэтому в дальнейшем будут рассмотрены только операции ввода и вывода сообщений на терминал, который осуществляется на консольном окне MS Windows, MS DOS или Unix.

Форматированный ввод и вывод консольных сообщений реализуется средствами ввода-вывода стандартной библиотеки Си, подключаемой с помощью заголовочного файла stdio.h.

Форматированный вывод осуществляется с помощью функции printf (), которая имеет следующую структуру:

printf (форматная_строка, список_аргументов);

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

В примере

printf (“\na=”);

содержится текст “a=” и управляющий символ “\n”. Текст выводиться на экран в том виде, в котором он записан, а управляющие символы влияют на расположение на экране выводимых знаков. В результате выполнения этого оператора на экран с новой строки выведутся символы a=.

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

%с – символ;

%s – строка;

%d – целое десятичное число (тип int);

%u – целое десятичное число без знака (тип unsigned);

%f – вещественные числа в форме с фиксированной точкой;

%e – вещественные числа в форме с плавающей точкой (с мантиссой и порядком).

Оператор

printf (“\nПлощадь треугольника=%f”, s);

содержит все виды параметров функции printf. Список аргументов состоит из одной переменной s, значение которой выводится на экран. Пара символов %f является спецификацией формата выводимого значения этой переменной. Символ % - признак формата, а f указывает на то, что выводимое число имеет вещественный тип и выводится на экран в форме с фиксированной точкой. Например, если в результате вычислений переменная s получит значение 32.435621, то на экран выведется:

Площадь треугольника=32.435621

В результате выполнения следующих операторов

float m,p;

int k;

m=84.3; k=-12; p=32.15;

printf (“\nm=%f\tk=%d\tp=%e”,m,k,p);

на экран будет выведен следующий текст:

m=84.299999 k=-12 p=3.21500e+01

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

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

Оператор

printf(“\nm=%5.2f\tk=%5d\tp=%8.2e\tp=%11.4e”,m,k,p,p);

выведет на экран следующий текст

m=84.3 k=-12 p=3.215 p=3.2150e01

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

Форматированный ввод с клавиатуры осуществляется с помощью функции scanf (), которая имеет следующую структуру:

scanf (форматная_строка, список_аргументов);

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

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

* ширина_поля модификатор спецификатор

обязательным элементом является лишь спецификатор. Для ввода числовых данных используются те же спецификаторы, что и в функции printf().

Звездочка (*) в спецификации позволяет пропустить во входном потоке определенное количество символов, а ширина_поля – целое положительное число, позволяющее определить число символов из входного потока, принадлежащих значению соответствующей вводимой переменной.

Список_аргументов – это перечень вводимых переменных и в структуре тоже является обязательным. Перед именем переменной в списке_аргументов всегда ставится символ & - операция ссылки или взятие адреса переменой.

Оператор

scanf (“%f%f%f”,&a,&b,&c);

производит ввод числовых вещественных значений в переменные a, b, c. Если последовательность ввода будет такой:

5 3.2 2.4 <Enter>

то переменные получат следующие значения: a=5.0, b=3.2, c=2.4.

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

Потоковый ввод и вывод консольных сообщений

Более распространенным способом ввода и вывода консольных сообщений является потоковый ввод-вывод, осуществляемый стандартной библиотекой классов, подключаемой к программе с помощью заголовочного файла iostream.h. В этой библиотеке определены в качестве объектов стандартные символьные потоки со следующими именами:

сin – стандартный поток ввода с клавиатуры;

cout – стандартный поток вывода на экран.

Ввод данных интерпретируется как извлечение из потока cin и присваивание значений соответствующим переменным. В Си++ определена операция извлечения из стандартного потока, знак которой >>. Например, ввод значений в переменную x реализуется оператором

cin>>x;

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

Вывод данных интерпретируется как помещение в стандартный поток cout выводимых значений. Выводиться могут тексты, заключенные в двойные кавычки, и значения выражений. Знак операции помещения в поток <<. Примеры использования потокового вывода:

cout<<a+b;

cout<<”\nРезультат=”<<Y;

cout<<”x=”<<x<<” y=”<<y<<” z=”<<z<<endl;

Из приведенных примеров видно, что в выходном потоке можно использовать управляющие символы, перед каждым элементом вывода нужно ставить знак операции <<. Элемент вывода endl является так называемым манипулятором, определяющим перевод курсора на новую строку.

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

Таблица 6

Манипуляторы потокового ввода-вывода

Манипулятор

Управляющее действие

endl

при выводе перейти на новую строку;

ends

вывести нулевой байт (признак конца строки символов);

flush

немедленно вывести и опустошить все промежуточные буферы;

dec

выводить числа в десятичной системе (действует по умолчанию);

Продолжение табл.6

Манипулятор

Управляющее действие

oct

выводить числа в восьмеричной системе;

hex

выводить числа в шестнадцатеричной системе счисления;

setw (int n)

установить ширину поля вывода в n символов (n – целое число);

setfill(int n)

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

setprecision(int n)

установить количество цифр после запятой при выводе вещественных чисел;

setbase(int n)

установить систему счисления для вывода чисел; n может принимать значения 0, 2, 8, 10, 16, причем 0 означает систему счисления по умолчанию, т.е. 10.

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

В результате выполнения следующих операторов

int x = 53;

cout <<"Десятичный вид: "<<dec

<< x <<endl

<<"Восьмеричный вид: "<<oct

<<x<< endl

<<"Шестнадцатеричный вид: "<<hex

<<x<< endl

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

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

double x;

//вывести число в поле общей шириной

//6 символов (3 цифры до запятой,

//десятичная точка и 2 цифры после запятой)

cout <<setw(6)<<setprecision(2)<<x<<endl;

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

Пример

int x;

cin >>hex>>x;

осуществляет ввод шестнадцатеричного числа.

Описание библиотеки математических функций

В таблице 7 представлены основные математические функции, находящиеся в стандартной библиотеке, подключаемой к программе с помощью заголовочного файла math.h

Таблица 7