Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Прикладное программирование.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
439.97 Кб
Скачать

6.4.2. Предикаты. Пример 6.6 (использование предикатов)

Предикаты позволяют без изменения шаблона изменять критерии сравнения элементов контейнера и другие подобные действия. У предикатов объект-функция возвращает значение bool.

В файле <functional> уже определено несколько полезных предикатов:

  • equal_to бинарный предикат равенства

  • not_equal_to бинарный предикат неравенства

  • greater бинарный предикат >

  • less бинарный предикат < (используется по умолчанию)

  • greater_equal бинарный предикат >=

  • less_equal бинарный предикат <=

  • logical_and бинарный предикат И

  • logical_or бинарный предикат ИЛИ

  • logical_not унарный предикат НЕ

Например, стандартный алгоритм сортировки сортирует по возрастанию, если мы хотим сделать сортировку по убыванию – можно использовать предикат greater:

// сортировка в порядке убывания

sort(v.begin(), v.end(), greater<int>());

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

Пример 6.6. Использование предикатов

/////////////////////////////////////////////////////////////////////////////

// Прикладное программирование

// Пример 6.6. Использование предикатов

//

// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru

// СПб НИУ ИТМО

/////////////////////////////////////////////////////////////////////////////

#include <functional>

#include <numeric>

#include <algorithm>

#include <vector>

#include <iostream>

#include <iterator>

using namespace std;

/////////////////////////////////////////////////////////////////////////////

// создание объекта-функции для заполнения случайными числами

// функция Rand - шаблон, наследник от стандартной функции unary_function

// параметры шаблона: PAR - тип данных, void - возвращаемое значение оператора ()

template <class PAR>

class Rand : public unary_function<PAR, void>

{

// диапазон случайных чисел

PAR m_min, m_max;

public:

// конструктор, в котором задается диапазон случайных чисел

Rand(PAR min, PAR max)

: m_min(min), m_max(max)

{ }

// перегруженный оператор вызова функции, в котором число value заполняется случайным числом

void operator() (PAR& value)

{

value=(PAR)(rand()*(m_max-m_min))/RAND_MAX+m_min;

}

};

/////////////////////////////////////////////////////////////////////////////

// создание объекта-функции определения попадания числа в диапазон

// функция InRange - шаблон, наследник от стандартной функции unary_function

// параметры шаблона: int - тип данных, bool - возвращаемое значение оператора ()

class InRange : public unary_function<int, bool>

{

// диапазон чисел

int m_left, m_right;

public:

// конструктор, в котором задается диапазон

InRange(int left, int right)

: m_left(left), m_right(right)

{}

// перегруженный оператор вызова функции, в котором определяется

// попадание числа value в диапазон от m_left до m_right

bool operator() (const int& value)

{

return (value>m_left && value<m_right);

}

};

/////////////////////////////////////////////////////////////////////////////

// тестирование предикатов

void main()

{

vector<int> v(10);

// заполнение контейнера случайными числами при помощи объекта-функции Rand

for_each(v.begin(), v.end(), Rand<int>(-10, 10));

copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

cout<<endl;

// сортировка с использованием предиката greater

sort(v.begin(), v.end(), greater<int>());

copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

cout<<endl;

// использование InRange для подсчета количества элементов в диапазоне от 0 до 10

cout << count_if(v.begin(), v.end(), InRange(0, 10));

cout<<endl;

}

/////////////////////////////////////////////////////////////////////////////

Приложение 1. Приоритет операций в С++

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

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

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

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

Приоритет

Операция

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

Описание

1

::

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

унарная операция разрешения области действия

[ ]

операция индексирования

()

круглые скобки

.

обращение к члену структуры или класса

->

обращение к члену структуры или класса через указатель

2

++

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

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

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

3

++

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

префиксный инкремент

префиксный декремент

4

*

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

умножение

/

деление

%

остаток от деления

5

+

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

сложение

-

вычитание

6

>>

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

сдвиг вправо

<<

сдвиг влево

7

<

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

меньше

<=

меньше либо равно

>

больше

>=

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

8

==

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

равно

!=

не равно

9

&&

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

логическое И

10

||

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

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

11

?:

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

условная операция (тернарная операция)

12

=

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

присваивание

*=

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

/=

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

%=

остаток от деления с присваиванием

+=

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

-=

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

13

,

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

запятая

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

Приложение 2. Основные типы данных

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

int i; //объявление переменной и определение ее типа (declaration) i=1; // инициализация (initialization) int j=1; //объявление, определение, инициализация переменной int i,j; //объявление нескольких переменных одного типа

При назначении типа данных для переменной определяются:

  1. объем памяти, отводимый для ее хранения;

  2. диапазон значений, который эта переменная может принимать.

Название типа (type)

Ключевое слово (keyword)

Размер (size)

Диапазон значений (limits)

логический

bool

1 byte

true/false

символьный

char

1 byte

-128 ÷ 27

беззнаковый символьный

unsigned char

1 byte

0 ÷ 255

широкий символный

wchar_t

2 byte

-32768 ÷ 32767

короткий целый

short

2 bytes

-32768 ÷ 32767

беззнаковый короткий целый

unsigned short

2 bytes

0 ÷ 65535

целый

int

4 bytes

-2147483648 ÷ 2147483647

беззнаковый целый

unsigned int

4 bytes

0 ÷ 4294967295

длинный целый

long

4 bytes

-2147483648 ÷ 2147483647

беззнаковый длинный целый

unsigned long

4 bytes

0 ÷ 4294967295

вещественный

float

4 bytes

(±)1.175494351е–38 ÷ (±)3.402823466е+38

вещественный с двойной точностью

double

8 bytes

(±)2.2250738585072014е-308 ÷ (±)1.7976931348623158е+308

длинный вещественный

long double

8 bytes

(±)2.2250738585072014е-308 ÷ (±)1.7976931348623158е+308

пустой

void

Поэтому к назначению типов переменных нужно подойти очень ответственно:

  1. чтобы программа во время выполнения не требовала большого объема памяти;

  2. чтобы значения, которые могут возникать при решении задачи не превышали диапазон, не возникало переполнение (overflow).

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

float f=0.5f; int i=(int)f; //понижение типа (операторная запись в стиле С) double d=double(f); //повышение типа (функциональная запись в стиле С++)

Следует обратить внимание, на особые типы данных С++:

bool flag; //логический тип данных может принимать два значения (true/false) wchar_t wchar; //двухбайтовый символьный тип данных (для работы в кодировке UNICODE)  void func(); //пустой тип данных (для создания функций не возвращающих значений и преобразования указателей)

Оператор sizeof позволяет определить размер памяти в байтах, необходимый для хранения переменной данного типа.

int i=sizeof(int); // i=4

При определении типов переменных используются несколько ключевых слов-модификаторов:

auto; //класс памяти автоматический const; //неизменяемая величина extern; //внешнее объявление registr; //класс памяти регистровый signed; //знаковый тип (используется по умолчанию) static; //статическая переменная unsigned; //беззнаковый тип volatile; //неизменяемая величина внутри программы

if ( условие )

{

if ( условие )

блок операторов; else if( условие)

блок операторов;

else

блок операторов;

Типы данных C++

Название типа (type)

Ключевое слово (keyword)

Размер (size)

Диапазон значений (limits)

логический

bool

1 byte

true/false

символьный

char

1 byte

-128 г 127

беззнаковый символьный

unsigned char

1 byte

0 г 255

широкий символный

wchar t

2 byte

-32768 г 32767

короткий целый

short

2 bytes

-32768 г 32767

беззнаковый короткий целый

unsigned short

2 bytes

0 г 65535

целый

int

4 bytes

-2147483648 г 2147483647

беззнаковый целый

unsigned int

4 bytes

0 г 4294967295

длинный целый

long

4 bytes

-2147483648 г 2147483647

беззнаковый длинный целый

unsigned long

4 bytes

0 г 4294967295

вещественный

float

4 bytes

(±)1.175494351е-38 г (±)3.402823466е+38

вещественный с двойной точностью

double

8 bytes

(±)2.2250738585072014е-308 г (±)1.7976931348623158е+308

длинный вещественный

long double

8 bytes

(±)2.2250738585072014е-308 г (±)1.7976931348623158е+308

пустой

void

-

-

Условные конструкции

if(условие) {

блок операторов;

}

else

{

}

Селективные конструкции

switch(переменная)

{

case целая константа:

блок операторов; break;

case целая константа:

блок операторов; break;

default:

блок операторов;

}

Циклические конструкции

Цикл с предусловием

Цикл с постусловием

Остальные ключевые слова C++

while(условие)

do

asm

mutable

this

{

{

auto

namespace

try

блок операторов;

блок операторов;

catch

operator

typedef

}

} while( условие);

class

private

typeid

Пошаговый цикл

const

protected

typename

enum

public

union

for(инициализация; условие; модификация)

explicit

unsigned

{

register

блок операторов;

export

return

using

}

extern

signed

virtual

friend

static

volatile

break - оператор досрочного выхода из

continue - оператор досрочного

goto

struct

цикла

перехода к следующему шагу цикла

inline

template

Оператор (operator)

Назначеие (meaning)

Тип

Порядок

оператора

выполнения

(type)

(associativity)

область видимости (scope resolution)

unary

-

[ ]

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

unary

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

(array subscript)

( )

вызов функции (function call)

multiple

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

type( )

оператор преобразования типов,

unary

-

конструирования значения

(conversion, constructor)

->

операторы доступа к членам гетерогенных типов данных (member selection)

unary

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

++

постфиксный инкремент/декремент (postfix increment/decrement)

unary

-

new

Динамическое размещение в памяти

binary

-

переменных и массивов (allocate)

delete

delete []

удаление из памяти переменной/массива, размещенного динамически (deallocate)

binary

--

префиксный инкремент/декремент (prefix increment/decrement)

unary

-

*

получение значения по указателю (dereference)

unary

-

&

получения указателя на переменную (address-of)

unary

-

+

унарный плюс (unary plus)

unary

-

-

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

unary

-

(arithmetic negation)

!

отрицание/логическое НЕ

unary

-

(logical NOT)

побитовое дополнение

unary

-

(bitwise complement)

sizeof

определение размера переменной (size of object)

unary

-

typedef

определение имени типа (type name)

unary

-

(type)

приведение типов (type cast)

unary

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

const cast dynamic cast reinterpret cast static_cast

приведение типов (type cast)

unary

*

->*

получение указателя на член класса (pointer to class member)

unary

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

*

/

умножение/деление (multiplication/division)

binary

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

О, %

остаток от деления (remainder)

binary

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

+

-

сложение/вычитание (addition/subtraction)

binary

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

<<

>>

побитовый левый/правый сдвиг (left/right shift)

unary

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

< >

<= >=

сравнение (comparison)

binary

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

!=

равенство/неравенство (equality/inequality)

binary

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

&

побитовое И (bitwise AND)

binary

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

Л

побитовое исключающее ИЛИ (bitwise exclusive OR)

binary

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

|

побитовое ИЛИ (bitwise OR)

binary

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

||

логическое И/ ИЛИ (logical AND/OR)

binary

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

? :

арифметическая условная конструкция (ariftnetic if)

ternary

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

=

присваивание (assignment)

binary

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

/=

умножение/деление с присваиванием

(multiplication/division assignment)

binary

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

О

%=

остаток от деления с присваиванием (modulus assignment)

binary

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

+=

сложение/вычитание с присваиванием

(addition/subtraction assignment)

binary

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

<<=

>>=

побитовый левый/правый сдвиг с

присваиванием

(left/right shift assignment)

binary

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

побитовое И с присваиванием (bitwise AND assignment)

binary

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

|=

побитовое ИЛИ с присваиванием (bitwise inclusive OR assignment)

binary

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

Л=

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

(bitwise exclusive OR assignment)

binary

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

throw

генерация исключения

unary

-

разделитель (comma)

unary

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