книги / Проектирование программ и программирование на C++. Структурное программирование
.pdf/^шаблон функции, которая находит |
номер макси |
||
мального элемента |
в массиве*/ |
|
|
#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 байтам.