Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛР 1-АП.doc
Скачиваний:
1
Добавлен:
15.11.2018
Размер:
1.05 Mб
Скачать

2.3. Спецификаторы класса памяти

В C++ имеется четыре спецификатора класса памяти: auto, register, static, extern.

Спецификатор класса памяти может предшествовать объявлениям переменных и функций, указывая компилятору, как следует хранить переменные в памяти и как получать доступ к переменным или функциям. Переменные, объявленные со спецификаторами auto и register, являются локальными, а со спецификаторами static и extern — глобальными. Память для локальной переменной выделяется каждый раз при достижении блока, в котором объявлена переменная, и освобождается по завершении выполнения блока. Память для глобальной переменной выделяется один раз при запуске программы и освобождается, когда работа программы закончена.

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

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

Переменная, объявленная на внешнем уровне, является глобальной и по умолчанию имеет класс памяти extern. Внешнее объявление может включать инициализацию (явную либо неявную) или просто быть ссылкой на переменную, инициализируемую в другом месте программы.

static int iv; // по умолчанию неявно присваивается 0

static int iv=10; // явное присваивание

int ir=20; // явное присваивание

Область видимости глобальной переменной распространяется до конца программы. Обращение к переменной не может находиться выше той строки, в которой она объявлена.

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

С помощью спецификатора extern можно объявить переменную, которая будет доступна из любого места программы. Это может быть ссылка на переменную, описанную в другом файле или ниже в том же файле. Последняя особенность делает возможным размещение ссылок на переменную до ее инициализации.

2.4. Операции

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

Побитовые операции работают с переменными как с наборами битов, а не как с числами. Эти операции используются в тех случаях, когда необходимо получить доступ к отдельным битам данных (при выводе графических изображений на экран). Побитовые операции применимы только к целочисленным значениям. В отличие от логических операций, с их помощью сравниваются не два числа целиком, а отдельные их биты. Основные побитовые операции: И (&), ИЛИ (|) и исключающее ИЛИ (^). Сюда можно также отнести унарную операцию побитового отрицания (~), которая инвертирует значения битов числа.

Операция & записывает в бит результата единицу только в том случае, если оба сравниваемых бита, равны 1, как показано в следующей таблице:

Бит 0

Бит 1

Результат

0

0

0

0

1

0

1

0

0

1

1

1

Эта операция часто используется для маскирования отдельных битов числа. Например: 0xF1 & 0x 35 = 0x 31.

Операция | записывает в бит результата единицу в том случае, если хотя бы один из сравниваемых битов равен 1, как показано в следующей таблице:

Бит 0

Бит 1

Результат

0

0

0

0

1

1

1

0

1

1

1

1

Эта операция часто применяется для установки отдельных битов числа. Например: 0x F1 | 0x 35 = 0x F5.

Операция ^ записывает в бит результата единицу в том случае, если сравниваемые биты отличаются друг от друга, как показано в следующей таблице:

Бит 0

Бит 1

Результат

0

0

0

0

1

1

1

0

1

1

1

0

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

Например: 0x F1 ^ 0x 35 = 0x C4.

В C++ существует две операции сдвига: << - сдвиг влево, >> - сдвиг вправо. Действие первой операции состоит в сдвиге битового представления целочисленной переменной, указанной слева от операции, влево на количество битов, заданное справа от операции. При этом освобожденные младшие биты заполняются нулями, а соответствующее количество старших битов утрачивается.

Сдвиг беззнакового числа на одну позицию влево с заполнением младшего, разряда нулем эквивалентен умножению числа на 2.

unsigned int iv=65; // младший байт: 01000001

iv<<=1; //младший байт: 10000010

cout<<iv; // будет выведено 130

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

unsigned int iv=10; // младший байт: 00001010

iv>>=1; // младший байт: 00000101

cout<<iv; // будет выведено 5

Увеличение (уменьшение) значения переменной на 1 очень часто встречаются в программах, поэтому разработчики языка С++ предусмотрели для этих целей специальные операции инкрементирования (++) и декрементирования (--).

Так, вместо строки iv+1; можно ввести строку iv++; или ++iv;

В ситуации, когда операция ++ является единственной в выражении, не имеет значения место ее расположение: до имени переменной или после него. Значение переменной в любом случае увеличится на единицу.

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

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

k=++I; //i=4, k=4

k=i++; //i=4, k=3

k=--i; //i=2, k=2

k=i--; //i=2, k=3

В C++ представлены все стандартные арифметические операции: сложения (+), вычитания (-), умножения (*), деления (/) и деления по модулю (%). Первые четыре операции не требуют разъяснений. Суть операции деления по модулю:

int ia=3,ib=8,id;

id=ib % ia; // результат: 2

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

В C++ операция присваивания (=) может входить в состав других выражений. В результате выполнения операции присваивания возвращается значение, присвоенное левому операнду. Например, следующее выражение вполне корректно:

iv=8*(iw=5); //iv=40.

В данном случае сначала переменной iw присваивается значение 5, после чего это значение умножается на 8, а результат присваивается переменной iv.

Таблица 2. Комбинированные операции присваивания

Исходный оператор

Эквивалент

Комментарий

var=var+3;

var+=3;

К переменной прибавляется 3

var=var-10;

var-=10;

Из переменной вычитается 10

var=var*3.14;

var*=3.14;

Переменная умножается на 3.14

var=var/2.5;

var/=2.5;

Переменная делится 2.5

var=var&0xF;

var&=0xF;

В переменной остаются только 4 младших разряда

var=var|0xF;

var|=0xF;

В переменной устанавливаются 4 младших разряда

var=var<<3;

var<<=3;

Переменная сдвигается влево на 3 разряда

var=var>>5;

var>>=5;

Переменная сдвигается вправо на 5 разрядов

var=var%2;

Var%=2;

Взятие остатка при делении var на 2

var=var+1;

var++;

Операция инкремента

var=var-1;

var--;

Операция декремента

Операции сравнения предназначены для проверки равенства или неравенства сравниваемых операндов. Все они возвращают true в случае установления истинности выражения и false в противном случае. Ниже перечислены операторы сравнения, используемые в языках С и C++.

Операция

Выполняемая проверка

==

Равно

!=

Не равно

>

Больше

<

Меньше

<=

Меньше или равно

>=

Больше или равно

Логические операции И (&&), ИЛИ (||) и НЕ (!) возвращают значение true или false в зависимости от логического отношения между их операндами. Так, операция && возвращает true, когда истинны (не равны нулю) оба его аргумента. Оператор || возвращает false только в том случае, если оба его аргумента ложны (равны нулю). Оператор ! инвертирует значение своего операнда с false на frue и наоборот.

Пример использования логических операций и операций сравнения приведен ниже.

#include "stdafx.h"

using namespace std;

main() {

float fa=2,fb=4;

cout<<"fa<fb "<<(fa<fb)<<"\n";

cout<<"fa>fb "<<(fa>fb)<<"\n";

cout<<"fa<=fb "<<(fa<=fb)<<"\n";

cout<<"fa>=fb "<<(fa>=fb)<<"\n";

cout<<"fa==fb "<<(fa==fb)<<"\n";

cout<<"fa!=fb "<<(fa!=fb)<<"\n";

cout<<"fa&&fb "<<(fa&&fb)<<"\n";

cout<<"fa||fb "<<(fa||fb)<<"\n";

getch();

}

Результат работы программы

Условная операция имеет следующий формат:

Условное выражение ? выражение1 : выражение2;

Если условное выражение true, то выполняется выражение1. Если условие false, то выполняется выражение2. Например,

var>7 ? х=11:у=7;

Часто выражения 1 и 2 используют одну и ту же переменную, которой присваивается либо одно, либо другое значение. Тогда условная операция записывается несколько иначе:

переменная=условное выражение ? выражение1 : выражение2;

Например,

char cS=x<=max?'Y':'N';

Если x<=max, то переменная cS принимает значение 'Y', если x>max, то cS будет равна 'N'.

Операция запятая (,) позволяет последовательно выполнить два выражения, записанные в одной строке. Результатом является значение выражения, расположенного справа от запятой. Синтаксис оператора следующий:

левое_выражение, правое_выражение

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

for(min=0,max=len-1;min<max;min++,max--) { … }

Операция sizeof служит для определения размера операнда в байтах. Она может использоваться как с обозначением переменной, так и с ее типом (в последнем случае операнд следует заключить в круглые скобки). Операция sizeof особенно полезна для определения размеров агрегатных переменных - массивов и структур. Например,

char cS[]="Операция sizeof";

int cSLen=sizeof cS;

Массив cS будет занимать 16 байт памяти.

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

В таблице 3 перечислены все операции языка C++ в порядке снижения их приоритета и указано направление вычисления операндов (ассоциативность): слева направо или справа налево.

Таблица 3. Приоритет операций (от высокого к низкому)

Операция

Описание

Ассоциативность

++

Постфиксный (префиксный) инкремент

Слева направо

--

Постфиксный (префиксный) декремент

()

Вызов функции

[]

Доступ к элементу массива

->

Косвенный доступ к члену класса

.

Прямой доступ к члену класса

!

Логическое НЕ

~

Побитовое НЕ

-

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

+

Унарный плюс

&

Взятие адреса

*

Раскрытие указателя

sizeof

Получение размерности выражения в байтах

new

Динамическое создание объекта

delete

Динамическое удаление объекта

(тип данных)

Приведение типа

.*

Прямой доступ к указателю на член класса (через объект)

Слева направо

->*

Косвенный доступ к указателю на член класса (через указатель на объект)

*

Умножение

Слева направо

/

Деление

%

Деление по модулю

+

Сложение

Слева направо

-

Вычитание

<<

Сдвиг влево

Слева направо

>>

Сдвиг вправо

<

Меньше

Слева направо

>

Больше

<=

Меньше или равно

>=

Больше или равно

==

Равно

Слева направо

!=

Не равно

&

Побитовое И

Слева направо

^

Побитовое исключающее ИЛИ

Слева направо

|

Побитовое ИЛИ

Слева направо

&&

Логическое И

Слева направо

II

Логическое ИЛИ

Слева направо

?:

Условное выражение

Справа налево

=

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

Справа налево

*=

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

/=

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

%=

Присваивание с делением по модулю

+=

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

-=

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

<<=

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

>>=

Присваивание со сдвигом вправо

&=

Присваивание с побитовым И

|=

Присваивание с побитовым ИЛИ

^=

Присваивание с побитовым исключающим ИЛИ

,

Запятая

Слева направо

2.5. Стандартные библиотеки C++ и библиотечные

математические функции

Различным библиотечным функциям требуются различные заголовочные файлы. Заголовочные файлы, которые необходимы функции, указываются в ее описании. Например, функции sqrt() нужны объявления, содержащиеся в заголовочном файле math.h. В Microsoft Visual C++ Run-Time Library Reference перечислены все библиотечные функции и соответствующие заголовочные файлы.

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

Стандартные библиотечные функции

int abs(int x);

double fabs(double x);

Возвращает целое (abs) или дробное (fabs) абсолютное значение аргумента, в качестве которого можно использовать выражение соответствующего типа.

double acos (double x);

double asin (double x);

double atan (double x);

long double acosl(long double x);

long double asinl(long double x);

long double atanl(long double x);

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

double cos (double x);

double sin (double x);

double tan (double x);

long double cosl(long double x);

long double sinl(long double x);

long double tanl(long double x);

Возвращает синус, косинус или тангенс угла. Величина угла должна быть задана в радианах.

double exp(double х);

long double exp(long double (x));

Возвращает значение, равное экспоненте аргумента (еx, где е — основание натурального логарифма).

double pow (double x, double y);

long double powl(long double (x), long double (y));

Возвращает значение, равное хУ.

double sqrt(double x);

Возвращает значение, равное квадратному корню из аргумента.

Заголовочный файл: <math.h>

int rand(void);

Возвращает случайное целое число в диапазоне от 0 до RAND_MAX. Перед первым обращением к функции rand необходимо инициализировать генератор случайных чисел. Для этого надо вызвать функцию srand.

void srand(unsigned x) ;

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

Заголовочный файл: <stdlib.h>

Приведенные ниже функции выполняют преобразование строк в числовое значение и чисел в строковое представление.

double atof(const char* s) ;

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

int atoi(const char* s) ;

long atol(const char* s);

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

char *gcvt(double Значение, int Цифр, char* Строка);

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

char* itoa (int Значение, char* Строка, int Основание);

char* ltoa (long Значение, char* Строка, int Основание);

char* ultoa(unsigned long Значение, char* Строка, int Основание);

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

Строка — указатель на строку, куда будет помещено изображение числа. Основание — задает основание системы счисления (от 2 до 36).

Максимальная длина строки, формируемой функцией itoa, — 17 байт, функциями Itoa и ultoa — 33 байта.

Заголовочный файл: <stdlib.h>

int sprintf(char *Строка, const char* Формат, СписокПеременных);

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

СписокПеременных — разделенные запятыми имена переменных, задает переменные, значения которых должны быть выведены. Параметр Формат задает способ отображения значений переменных.

Действие функции sprintf аналогично действию функции printf, но вывод выполняется в строку-буфер, а не на экран.

Заголовочный файл: <stdio.h>

Библиотечные функции ввода-вывода

int printf(Формат, СписокПеременых);

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

Спецификаторы формата (необязательный параметр n задает ширину поля вывода).

Спецификатор

Форма вывода

%ni %nd

Десятичное число со знаком

%nu

Беззнаковое целое десятичное число

%n.mf

Дробное число с десятичной точкой. Необязательный параметр m задает количество цифр дробной части

%ne

Дробное число с десятичной точкой или, если число не может быть представлено в форме с десятичной точкой, в экспоненциальной форме

%ns

Строка символов

%nc

Символ

Управляющие и специальные символы.

Символ

Действие

\n

Переводит курсор в начало следующей строки

\t

Переводит курсор в очередную позицию табуляции

\\

Бэкслэш

\’

Кавычка

int scanf(const char* Формат, СписокАдресовПеременных);

Вводит с клавиатуры значения переменных, в соответствии с указанным спецификатором формата. Первая переменная получает значение в соответствии с первым спецификатором формата, вторая — со вторым и т. д.

Спецификатор

Вводит

%i %d

Десятичное число со знаком

%u

Беззнаковое целое десятичное число

%е %f

Дробное число

%s

Строка символов

Символ

puts(const char* Строка);

Выводит на экран строку символов и переводит курсор в начало следующей строки экрана. В качестве параметра функции можно использовать строковую константу или строковую переменную.

Заголовочный файл: <stdio.h>

int putch(int с);

Выводит на экран символ.

Заголовочный файл: <conio.h>

int getch(void);

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

Заголовочный файл: < conio.h >

Задача 1. Нахождение значения производной функции в точке.

Постановка задачи

Заданна функция . Найти ее производную в точке x=π/2 .

Для нахождения производной в точке используется известное выражение

.

Кроме того, так как π/2 ≈ 1,57 в качестве значения х выбираем 1,57.

Текст программы

#include <math.h>

#include <iostream>

int main()

{

double f1,f2,pf,x,dx;

dx=1.0e-11; // Выбираем приращение аргумента

x=1.57; // Выбираем точку для вычисления производной

f1=sin(x+dx); // Вычисляем значение функции в точке x+dx

f2=sin(x); // Вычисляем значение функции в точке x

pf=(f1-f2)/dx; // Находим значение производной

std::cout << "dsin(x)/dx=" << pf <<" x= "<<x;

getchar();

return 0;

}

Результат работы программы

Второй вариант написания программы. Вывод результатов в стиле С (с помощью функции printf).

#include <math.h>

#include <conio.h>

#include <stdio.h>

int main()

{

double f1,f2,pf,x,dx;

dx=1.0e-11;

x=1.57;

f1=sin(x+dx);

f2=sin(x);

pf=(f1-f2)/dx;

printf("dsin(x)/dx=%6.4f x=%4.2f",pf,x);

getch();

return 0;

}

Задания к задаче 1 лабораторной работы № 2

Таблица 1

Задание

Задание

1.

12.

2.

13.

3.

14.

4.

15.

5.

16.

6.

17.

7.

18.

8.

19.

9.

20.

10.

21.

11.

22.

Задача 2 Составить программу для нахождения значений выражений А и В по заданным значениям исходных данных x,y,z.

Исходные данные (по вариантам) находятся в таблице 2.

Таблица 2

Функции

Исходные данные

вар.

x

y

z

1

3.98

-1.62

0.52

2

-0.62

0.82

25

3

3.25

0.32

0.4

4

-0.62

3.32

5.4

5

17.4

10.3

0.82

6

1.62

-15.4

0.25

7

2.44

0.86

-0.16

8

0.33

0.02

32

9

3.25

4.2

-0.66

10

0.12

-8.75

0.76

11

1.53

-3.26

8.2

12

1.42

-1.22

3.52

13

3.74

-0.82

0.16

14

3.74

-0.82

0.16

15

0.42

-0.87

-0.47

16

-15.2

4.64

21.3

Продолжение таблицы 2

17

16.5

-2.75

0.15

18

-17.2

6.33

3.25

19

-2.23

-0.82

15.2

20

1.82

18.5

-3.29

21

47.8

-5.52

-2.3

22

-0.85

1.25

-0.22

23

3.74

-12.5

21.3

24

3.25

2.98

12.5

25

0.22

-6.72

10.2

26

12.6

-2.25

3.2

27

0.113

0.512

0.45

28

0.45

0.86

-0.16

29

0.98

-2.62

0.51

30

10.3

-6.2

1.12

Задание 3. (Дополнительно на оценку 11 и 12). Вычисление значения отношения.

Постановка задачи

Выпуклый четырехугольник ABCD задается длинами своих сторон и длиной диагонали AC. Новый четырехугольник A1B1C1D1 строится следующим образом: сторона AB продлевается в сторону вершины B так, чтобы полученный отрезок AB1 был в 2 раза длиннее отрезка AB, сторона BС продлевается в сторону вершины С так, чтобы полученный отрезок BС1 был в 2 раза длиннее отрезка BС и так далее (см. рис.).

По заданным значениям длин сторон AB, BC, CD, DA и длине диагонали AC вычислить отношение площади четырехугольника A1B1C1D1 к площади четырехугольника ABCD.

Контрольные вопросы

1.Поясните смысл понятия оператор.

2.Что понимается под типом данных?

3.Какая информация сообщается компилятору при объявлении переменных и констант?

4.Дайте определение выражения.

5.Укажите правила вычисления выражений.

6.Приведите примеры операций с одинаковым приоритетом.

7.Укажите операции с наивысшим и наименьшим приоритетом.

8.Перечислите ключевые слова, используемые при объявлении стандартных типов данных.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]