Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Проектирование программ и программирование на C++. Структурное программирование

.pdf
Скачиваний:
4
Добавлен:
12.11.2023
Размер:
3.86 Mб
Скачать

/^шаблон функции, которая находит

номер макси­

мального элемента

в массиве*/

 

#include<iostream.h>

 

templateCclass

Data>

 

Data& rmax(int

n, Data a [])

 

{

im=0;

 

 

int

 

 

for(int i=0;i<n;i++)

 

if(a[im]<a[im]) im=i;

ссылку

return d[im];

//возвращает

}

 

 

 

void main()

 

 

{

n=5;

 

 

int

 

 

int

x[]={10,20,30,15};

 

//найти номер максимального элемента в массиве

//целых чисел

cout«"\nrmax (п,х) ="«гшах (п,х) <<"\п";

ппах(п,х)=0; //заменить максимальный элемент на 0

for(int i=0;i<n;i++)

//вывод массива

cout<<x[i]<<"

 

cout«"\n";

 

//следующий массив

 

float у []={10.4,20.2,30.6, 15.5};

/*найти номер максимального элемента в массиве

вещественных чисел*/

cout«"\nrmax (п,у) ="«rmax (п,у) «"\п"; rmax(4,у)=0;//заменить максимальный элемент на 0

for(in i=0;i<n;i++)

//вывод массива

cout<<y[i]<<" ";

 

cout«"\n";

 

}

Результаты работы программы: rmax(n,х)=30

10

20

0

15

 

 

rmax(п,у)=30.6

10.4

20.2

0

15.5

Основные свойства параметров шаблона функций:

-имена параметров должны быть уникальными во всем опре­ делении шаблона;

-список параметров шаблона не может быть пустым;

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

17.12. Указатель на функцию

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

Указатель на функцию определяется следующим образом:

тип_функции(*имя_указателя)(спецификация

параметров)

с) {...}

//определение

функции

int fl(char

int(*ptrfl)(char);

//определение

указателя на

//функцию

fl

k,char

с) {...} //определение функции

char*

f2(int

char*

ptrf2 (int,char);//определение указателя

//на функцию f2

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

Вызов функции с помощью указателя имеет вид

(*имя_указателя) (список фактических параметров); #include <iostream.h>

void f1 ()

{

cout<<"\nfunction fl";

}

void f2()

{

cout<<"\nfunction f2";

void(*ptr)();

//указатель на функцию

адрес

ptr=f2;

//указателю присваивается

//функции f2

//вызов функции f2

 

(*ptr)();

адрес

ptr=f1;

//указателю присваивается

//функции fl

 

 

(*ptr) ();//вызов функции fl с помощью указателя

}

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

void (*ptr) ()=f1;

Указатели на функции могут быть объединены в массивы. На­

пример, float (*ptrMas [4] )(char) - описание массива, кото­

рый содержит четыре указателя на функции. Каждая функция имеет параметр типа char и возвращаетзначение типа float.

Обратиться ктакой функции можно следующим образом: float а=(*ptrMas[1])('f');//обращение ко

//второй функции

#include dost ream. h> #include <stdlib.h> void f1()

{

cout«"\nThe end of work";exit(0);

}

void f2 ()

{

cout<<"\nThe work #1";

}

void f3()

{

cout<<"\nThe work #2";

}

void main()

{

void(*fptr[])()={fl,f2,f3};//массив и указателей

//на функции

int n;

//бесконечный цикл

while(1)

{

cout«"\n Enter the number";

cin»n;

fptr[n]();//вызов функции с номером n

}

}

Указатели на функции удобно использовать в тех случаях, когда

функцию надо передать в другую функцию как параметр.

♦include <iostream.h>

♦include <math.h>

typedef float(*fptr)(float);//тип-указатель на //функцию уравнения

/^решение уравнения методом половинного деле­ ния, уравнение передается с помощью указателя на функцию*/

float root(fptr f, float a, float b, float e)

{

float x; do

{

x=(a+b)/2; //находим середину //отрезка

if ((*f)(a)*f(x)<0) //выбираем отрезок b=x;

else a=x;

}

while((*f)(x)>e && fabs(a-b)>e); return x;

}

//функция, для которой ищется корень float testf(float x)

{

return x*x-l;

}

{

/*в функцию root передается указатель на функ­

цию, координаты отрезка и точность*/

float res=root(testf,0,2,0.0001);

cout<<"\nX="<<res;

17.13. Ссылки на функцию

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

тип_функции(&имя_ссылки)(параметры)

инициализирующее_выражение;

int f (float a, int b) {...} //определение функции

int (&fref)(float,int)=f; //определение ссылки

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

#include dost ream. h> void f(char c)

{

cout«"\n"<<c;

void main()

{

(*pf)(char);

//указатель

на функцию

void

void

(&rf)(char);

//ссылка

на

функцию

f ('A' ); //вызов по имени

на

функцию

pf=f;

//указатель

ставится

(*pf)( 'В'); //вызов с помощью указателя rf('C'); //вызов по ссылке

}

18.ТИПЫ ДАННЫХ, ОПРЕДЕЛЯЕМЫЕ ПОЛЬЗОВАТЕЛЕМ

18.1.Переименование типов

Типу можно задавать имя с помощью ключевого слова typedef:

typedef тип имя_типа [размерность];

typedef unsigned int UNIT;

typedef char Msg[100];

Такое имя можно затем использовать так же, как и стандартное

имя типа

UNIT а,Ь,с;//переменные типа unsigned int

Msg str[10];// массив из 10 строк по 100 символов

18.2. Перечисления

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

enum [имя_типа] {список констант};

Константы должны быть целочисленными и могут инициализи­ роваться обычным образом. Если инициализатор отсутствует, то пер­ вая константа обнуляется, а остальным присваивается значение на единицу большее, чем предыдущее.

Enum Err{ErrRead, ErrWrite, ErrConvert);

Err error;

switch(error)

{

case ErrRead:

case ErrWrite:

case ErrConvert:

}

18.3. Структуры

Структура - это объединенное в единое целое множество поиме­ нованных элементов данных. Элементы структуры (поля) могут быть различного типа, они все должны иметь различные имена.

Форматы определения структурного типа следующие:

s t r u c t

им я_типа

//с п о с о б 1

 

{

 

 

 

 

 

тип1

э л е м ен т 1;

 

 

тип2

эл ем ен т2 ;

 

 

•};

 

 

 

 

 

s t r u c t

D ate

/ /о п р е д е л ен и е

структуры

{

 

 

 

 

 

i n t

d ay ;

 

 

i n t

m onth;

 

 

i n t

y e a r ;

 

 

};

 

 

 

//п е р е м е н н а я

типа D ate

D ate

b i r t h d a y ;

s t r u c t

 

//с п о с о б 2

 

{

 

 

 

 

 

тип1

эл ем ен т1 ;

 

 

тип2

эл ем ен т2 ;

 

 

}

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

 

s t r u c t

 

 

 

{

 

 

 

 

 

i n t

m in;

 

 

i n t

s e c ;

 

 

i n t

m sec;

 

 

}

tim e _ b e g , tim e _ e n d ;

 

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

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

Во втором случае описание структуры служит определением переменных.

Структурный тип можно также задать с помощью ключевого

слова ty p e d e f :

 

 

ty p e d e f

s t r u c t

//с п о с о б

3

{

 

 

 

 

f l o a r

r e ;

 

 

f l o a t

im ;

 

 

} C om plex;

 

 

Complex

a [1 0 0 ];//м асс и в и з 100

комплексных чисел.

18.3.1. Работа со структурами

Инициализация структур. Для инициализации структур значе­ ния ее полей перечисляют в фигурных скобках.

//п р и м е р 1

s t r u c t S tu d e n t

{

 

c h a r

n am e[2 0 ] ;

i n t

k u r s ;

f l o a t r a t i n g ;

S tu d e n t s = { " И в а н о в " ,1 ,3 . 5 } ;

//п р и м е р 2 s t r u c t

{

c h a r n am e[2 0 ] ; c h a r t i t l e [3 0 ] ; f l o a t r a t e ;

} em p lo y e e = { "П е т р о в ", "п р о гр ам м и ст", 10000} ;

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

S tu d e n t t = s ;

Доступ к элементам структур. Доступ к элементам структур обеспечивается с помощью уточненных имен:

и м я _ с т р у к т у р ы . и м я _ эл ем ен та

em p lo y ee . name - указатель на строку «Петров»;

e m p lo y e e . r a t e - переменная целого типа со значением 10000

# in c lu d e < io s tr e a m .h > v o id m a in ()

{

s t r u c t S tu d e n t

{

c h a r n am e[30] ; c h a r g r o u p [1 0 ] ; f l o a t r a t i n g ; };

S tu d e n t

m a s [3 5 ];

//м а с с и в стр у к ту р

//в в о д

зн ач ен и й

м асси ва

f o r ( i n t

i= 0 ;i< 3 5 ;i+ + )

 

{

 

 

 

c o u t< < " \n E n te r

nam e:

c in > > m a s [i] .n a m e ;

c o u t< < " \n E n te r g r o u p :" ; c in > > m a s [ i] .g r o u p ;

c o u t< < " \n E n te r r a t i n g : " ; c i n > > m a s [ i ] . r a t in g ;

}

//в ы в о д с т у д е н т о в , у которы х р ей ти н г меньше 3 c o u t « " R a i t n g < 3 :" ;

f o r ( i = 0 ; i< 3 5 ; i+ + ) if ( m a s [ i] .n a m e < 3 )

c o u t< < " \n " < < m a s [i] .n a m e ;

}

Указатели на структуры. Указатели на структуры определя­

ются так же, как и указатели на другие типы.

 

S tu d e n t*

p s ;

 

 

Можно ввести указатель для типа s t r u c t ,

не имеющего имени

(способ 2):

 

 

 

s t r u c t

 

 

 

{

 

 

 

 

c h a r

*nam e;

 

 

i n t

a g e ;

 

 

 

} ^ p e rs o n ;

//у к а з а т е л ь

на ст р у к ту р у

При определении указатель на структуру может быть сразу же

проинициализирован.

 

 

S tu d e n t*

p s =

& m as[0];

 

Указатель на структуру обеспечивает доступ к ее элементам двумя способами:

1.( * у к а з а т е л ь ) . и м я_ элем ента

2.у к а за т е л ь -> и м я _ эл е м е н т а

c in > > (* p s ) .n a m e ; c i n > > p s - > t i t l e ;

18.3.2. Битовые поля

Битовые поля - это особый вид полей структуры. При описании битового поля указывается его длина в битах (целая положительная константа).

s t r u c t

 

 

 

 

{

 

 

 

 

 

i n t

a : 10;

//д л и н а

п оля

10

бит

i n t

b :1 4 ;

//д л и н а

поля

14

бит

} хх , *рхх;

х х . а = 1; рхх = &хх;

рхх->Ь = 8;

Битовые поля могут быть любого целого типа. Они используют­ ся для плотной упаковки данных. Например, с их помощью удобно реализовать флажки типа «да» / «нет».

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

18.3.3. Объединения

Объединение (u n io n ) - это частный случай структуры. Все поля

объединения располагаются по одному и тому же адресу. Длина объе­ динения равна наибольшей из длин его полей. В каждый момент вре­ мени в такой переменной может храниться только одно значение. Объ­ единения применяют для экономии памяти, если известно, что более одного поля не потребуется. Также объединение обеспечивает доступ

к одному участку памяти с помощью переменных разного типа,

 

u n io n

 

 

{

 

 

 

c h a r

 

s [1 0 ];

 

i n t

x;

 

} u l ;

 

 

0

1

2 | 3

9

х - занимает 2 байта

 

s - занимает 10 байтов

 

Рис. 14. Расположение объединения в памяти

И s, и х располагаются на одном участке памяти (рис. 14). Размер такого объединения будет равен 10 байтам.

Соседние файлы в папке книги