Глава 3.
Функции. Модульное
программирование
МГТУ им. Н.Э. Баумана
Факультет Информатика и системы управления
Кафедра Компьютерные системы и сети
Лектор: д.т.н., проф.
Иванова Галина Сергеевна
1
3.1 Описание функции
<Тип результата> <Имя > ([<Список параметров>])
{ [< Объявление локальных переменных и констант >]
<Операторы>
}
Пример:
int max(int a, int b);
int max(int a, int b)
{ if (a>b) return a;
else return b;
}
Объявление функциипрототип
Описание
функции
2
Параметры функции
1. Все параметры передаются по значению!
2. Если надо вернуть значение, то передают
указатель или ссылку:
а) указатель
void prog(int a, int *b) { *b=a; }
вызов: prog(c,&d);
б) ссылка
void prog(int a, int &b) { b=a; }
вызов: prog(c, d);
3. Если надо запретить изменение параметра,
переданного адресом, то его описывают const
int prog2(const int *a) { …}
3
3.2 Классы памяти
1. Автоматические переменные (auto)
main()
{auto int a;…}
Две разные
abc()
переменные
{auto int a;…}
2. Внешние переменные (extern)
extern int a;
main()
Одна и та же
{extern int a;…}
переменная
abc()
{extern int a;…}
Автоматическая
переменная, которая
bcd()
внутри функции
{int a;…}
перекрывает внешнюю
4
Классы памяти (2)
3. Статические переменные (static)
abc()
В отличие от автоматической
статическая переменная
{ int a=1; static int b=1;
увеличивается с каждым
… a++; b++; …}
вызовом
4. Внешние статические переменные (extern static)
int a;
Внешняя переменная доступна
во всех файлах программы, а
extern static int b;
внешняя статическая только в
Файл
том файле, где описана
5. Регистровые переменные (register)
По доступу аналогична
register int a;
автоматической, но по
возможности размещается в
регистрах
5
3.3 Параметры-массивы
В С++ отсутствует контроль размерности массива
по первому индексу!
а) int x[5] int *x int x[ ]
б) int y[ ][8] int y[4][8]
Пример:
void summa(const float x[ ][3], float *y)
{ int i,j;
for(i=0;i<5;i++)
for(y[i]=0,j=0;j<3;j++) y[i]+=x[i][j];
}
Вызов: summa(a,b);
6
3.4 Параметры-строки
Функции типа «строка» целесообразно писать как
процедуры-функции.
Пример. Функция удаления «лишних» пробелов между
словами.
char *strdel(const char *source,char *result)
{ char *ptr;
strcpy (result, source);
while ((ptr=strstr(result, " "))!=NULL)
strcpy(ptr,ptr+1);
return result;
}
Вызовы: puts(strdel(str,strres)); или
strdel(str,strres);
7
3.5 Параметры-структуры
Имя структуры не является указателем на нее.
Пример 1. Сумма элементов массива (указатель).
struct mas{int n; int a[10]; int s;} massiv;
int summa(struct mas *x)
{ int i,s=0;
for(i=0;i
x->s=s;
return s;
x
}
massiv
Вызов:
summa(&massiv);
n
a
s
8
Параметры-структуры (2)
Пример 2. Сумма элементов массива (ссылка).
struct mas{int n; int a[10]; int sum;} massiv;
int summa(struct mas &x)
{ int i,s=0;
for(i=0;i
return s;
}
x=massiv
Вызов:
summa(massiv);
n
a
s
9
Параметры-структуры (3)
Пример 3. Сумма элементов массива (массив).
struct mas{int n;int a[10];int sum;} massiv[3];
int summa(struct mas *x)
{ int i,k,s,ss=0;
for(k=0;k<3;k++,x++)
{ for(s=0,i=0;i
x->s=s;
ss+=s;
x massiv[3]
}
return ss;
n
a
}
s
Вызов: summa(massiv);
10
3.6 Параметры-функции
Пример (Ex3_01).
6+2=8
#include "stdafx.h"
8-2=6
#include
int add(int n,int m) {return n+m;}
6*2=12
int sub(int n,int m) {return n-m;}
12/2=6
int mul(int n,int m) {return n*m;}
int div(int n,int m) {return n/m;}
int main(int argc, char* argv[])
Указатель на функцию
{ int (*ptr)(int,int);
int a=6, b=2; char c='+';
while (c!=' ')
{ printf("%d%c%d=",a,c,b);
switch (c) { case '+': ptr=add; c='-';break;
case '-': ptr=sub; c='*';break;
case '*': ptr=mul; c='/';break;
case '/': ptr=div; c=' '; }
printf("%dn",a=ptr(a,b));
}
return 0; }
11
3.7 Рекурсия
Пример. Переворот строки (Ex3_02).
A S D B
#include "stdafx.h"
#include
B
#include
B D
void reverser(char s[],char sr[])
B D S
{ int k;
if (!strlen(s)) sr[0]='';
B D S A
else { reverser(s+1,sr);
k=strlen(sr); sr[k]=s[0]; sr[k+1]=''; }
}
int main(int argc, char* argv[])
{
char s[20],sr[20];
printf("Input string:");
scanf("%s",s);
reverser(s,sr);
printf("Output string: %sn",sr);
return 0;
}
12
3.8 Модули C++ (Ex3_03)
Файл Mod.h:
int nod(int a,int b);
Зависит
Файл Mod.cpp:
#include "stdafx.h"
Ex1.cpp
#include "Mod.h"
int nod(int a,int b)
{ while (a!=b)
if (a>b) a=a-b; else b=b-a;
return a; }
Файл Ex3_03.cpp:
#include "stdafx.h"
#include
#include "Mod.h"
int main(int argc, char* argv[])
{ int a=18,b=24,c;
c=nod(a,b);
printf("nod=%dn",c);
return 0; }
Реализует
Mod.h
Mod.cpp
13
3.9 Пространство имен
Большинство приложений состоит более чем из одного исходного файла. При
этом возникает вероятность дублирования имен, что препятствует сборке
программы из частей. Для снятия проблемы в C++ был введен механизм
логического разделения области глобальных имен программы, который
получил название пространства имен.
Имена, определенные в пространстве имен, становятся локальными внутри
него и могут использоваться независимо от имен, определенных в других
пространствах. Таким образом, снимается требование уникальности имен
программы.
namespaсe [<имя>] { <Объявления и определения> }
Имя пространства имен должно быть уникальным, но может быть и опущено.
Если имя пространства опущено, то считается, что определено
неименованное пространство имен, локальное внутри единицы трансляции.
Для доступа к его ресурсам используется внутреннее имя $$$.
Например:
namespace ALPHA {
// ALPHA – имя пространства имен
long double LD;
// объявление переменной
float f(float y) { return y; }
// описание функции
}
14
Доступ к элементам пространства имен
Пространство имен определяет область видимости, следовательно,
функции, определенные в пространстве имен могут без ограничений
использовать другие ресурсы, объявленные там же (переменные,
типы и т.д.).
Доступ к элементам других пространств имен может осуществляться
тремя способами:
1) с использованием квалификатора доступа, например:
ALPHA::LD или ALPHA::f()
2) с использованием объявления using, которое указывает, что
некоторое имя доступно в другом пространстве имен:
namespace BETA {
…
using ALPHA::LD;/* имя ALPHA::LD доступно в BETA*/ }
3) с использованием директивы using, которая объявляет все имена
одного пространства имен доступными в другом пространстве:
namespace BETA {
…
using ALPHA;
/* все имена ALPHA доступны в BETA*/
}
15
Непоименованное пространство имен
Непоименованное пространство имен невидимо в других модулях:
namespace { namespace-body }
При трансляции оно именуется как “unique”, доступное в самом модуле:
namespace unique { namespace-body }
using namespace unique;
Пример:
namespace { int i; }
// unique::i
void f() { i++; }
// unique::i++
namespace A {
namespace { int i,j;}} // A::unique::i A::unique::j
using namespace A;
void h()
{
i++;
// unique::i или A::unique::i ?
A::i++;
// A::i ?
j++;
// A::unique::j++
}
16
Глобальное пространство имен
Приложение включает одно глобальное пространство имен. Имена,
входящие в это пространство, объявляются без указания
пространства имен.
Пример:
int i;
namespace A
{ int a, b, c;
namespace B {int i, j, k;}
}
int main()
{
A::a++;
A::B::i++;
::i++;
// глобальное i
}
17
Имена стандартных библиотек С++
Согласно стандарту ANSI/ISO в C++ все имена ресурсов стандартных
библиотек определены в пространстве std. При использовании этого
пространства автоматически подключаются библиотеки
Пример:
// #include
int main()
{ std::cout << "Hello ";
1-й вариант
using namespace std;
2-й вариант
cout << "World." << endl;
}
Однако можно по-прежнему использовать определение ресурсов
стандартных библиотек в глобальном пространстве. Для этого
необходимо подключать
Список доступных стандартных библиотек в старой и новой формах
18
можно посмотреть в среде.
3.10 Аргументы командной строки
int main( int argc,char *argv[ ]) { ... }
где argc - количество параметров командной
строки +1;
argv[0] - может содержать полное имя
файла программы, например “A:ddd.exe”.
argv[1] - содержит первый параметр из
командной строки;
argv[2] - содержит второй параметр из
командной строки и т.д. Номер
предпоследнего элемента массива argv[ ]
равен argc. Он содержит последний
параметр. Последний элемент массива argv
содержит NULL.
19
3.11 Дополнительные возможности С++
1. Подставляемые функции
inline int abs(int a) {return a>0?a:-a;}
2. Переопределяемые функции
int lenght(int x,int y){return sqrt(x*x+y*y);}
int lenght(int x,int y,int z)
{return sqrt(x*x+y*y+z*z);}
int lenght(char *s)
{return charwidth*strlen(s);}
3. Параметры функции, принимаемые по умолчанию
void InitWindow(char *windowname,
int xSize=80, int ySize=25,
int barColor=BLUE,
int frameColor=CYAN){...}
Вызов: InitWindow(pname,20,10);
20