Слайд 1Глава 3.
Функции. Модульное программирование
МГТУ им. Н.Э. Баумана
Факультет Информатика
и системы управления
Кафедра Компьютерные системы и сети
Лектор: д.т.н., проф.
Иванова Галина Сергеевна
Слайд 23.1 Описание функции
([])
{ [< Объявление
локальных переменных и констант >]
}
Пример:
int max(int a,
int b);
int max(int a, int b)
{ if (a>b) return a;
else return b;
}
Объявление функции-
прототип
Описание функции
Слайд 3
Параметры функции
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) { …}
Слайд 43.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;…}
Две
разные переменные
Одна и та же переменная
Автоматическая переменная, которая
внутри функции перекрывает внешнюю
Слайд 5
Классы памяти (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;
В отличие от автоматической статическая переменная увеличивается с каждым вызовом
Внешняя переменная доступна во всех файлах программы, а внешняя статическая только в том файле, где описана
По доступу аналогична автоматической, но по возможности размещается в регистрах
Слайд 6
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);
Слайд 73.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);
Слайд 83.5 Параметры-структуры
Имя структуры не является указателем на нее.
Пример 1. Сумма
элементов массива (указатель).
struct mas{int n; int a[10]; int s;} massiv;
int
summa(struct mas *x)
{ int i,s=0;
for(i=0;in;i++) s+=x->a[i];
x->s=s;
return s;
}
Вызов:
summa(&massiv);
Слайд 9Параметры-структуры (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
s+=x.a[i];
x.s=s;
return s;
}
Вызов:
summa(massiv);
Слайд 10Параметры-структуры (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
for(s=0,i=0;in;i++) s+=x->a[i];
x->s=s;
ss+=s;
}
return ss;
}
Вызов: summa(massiv);
Слайд 113.6 Параметры-функции
Пример (Ex3_01).
#include "stdafx.h"
#include
int add(int n,int m) {return
n+m;}
int sub(int n,int m) {return n-m;}
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("%d\n",a=ptr(a,b)); }
return 0; }
6+2=8
8-2=6
6*2=12
12/2=6
Указатель на функцию
Слайд 123.7 Рекурсия
Пример. Переворот строки (Ex3_02).
#include "stdafx.h"
#include
#include
void reverser(char s[],char
sr[])
{ int k;
if (!strlen(s)) sr[0]='\0';
else
{ reverser(s+1,sr);
k=strlen(sr); sr[k]=s[0]; sr[k+1]='\0'; }
}
int main(int argc, char* argv[])
{ char s[20],sr[20];
printf("Input string:");
scanf("%s",s);
reverser(s,sr);
printf("Output string: %s\n",sr);
return 0;
}
A
S
D
B
\0
B
B
\0
\0
D
\0
B
D
\0
S
B
D
\0
S
A
Слайд 133.8 Модули C++ (Ex3_03)
Файл Mod.h:
int nod(int a,int b);
Файл Mod.cpp:
#include "stdafx.h"
#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=%d\n",c);
return 0; }
Ex1.cpp
Mod.h
Mod.cpp
Зависит
Реализует
Слайд 143.9 Пространство имен
Большинство приложений состоит более чем из одного исходного
файла. При этом возникает вероятность дублирования имен, что препятствует сборке
программы из частей. Для снятия проблемы в C++ был введен механизм логического разделения области глобальных имен программы, который получил название пространства имен.
Имена, определенные в пространстве имен, становятся локальными внутри него и могут использоваться независимо от имен, определенных в других пространствах. Таким образом, снимается требование уникальности имен программы.
namespaсe [<имя>] { <Объявления и определения> }
Имя пространства имен должно быть уникальным, но может быть и опущено. Если имя пространства опущено, то считается, что определено неименованное пространство имен, локальное внутри единицы трансляции. Для доступа к его ресурсам используется внутреннее имя $$$.
Например:
namespace ALPHA { // ALPHA – имя пространства имен
long double LD; // объявление переменной
float f(float y) { return y; } // описание функции
}
Слайд 15Доступ к элементам пространства имен
Пространство имен определяет область видимости, следовательно,
функции, определенные в пространстве имен могут без ограничений использовать другие
ресурсы, объявленные там же (переменные, типы и т.д.).
Доступ к элементам других пространств имен может осуществляться тремя способами:
1) с использованием квалификатора доступа, например:
ALPHA::LD или ALPHA::f()
2) с использованием объявления using, которое указывает, что некоторое имя доступно в другом пространстве имен:
namespace BETA { …
using ALPHA::LD;/* имя ALPHA::LD доступно в BETA*/ }
3) с использованием директивы using, которая объявляет все имена одного пространства имен доступными в другом пространстве:
namespace BETA { …
using ALPHA; /* все имена ALPHA доступны в BETA*/ }
Слайд 16Непоименованное пространство имен
Непоименованное пространство имен невидимо в других модулях: 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++
}
Слайд 17Глобальное пространство имен
Приложение включает одно глобальное пространство имен. Имена, входящие
в это пространство, объявляются без указания пространства имен.
Пример:
int i;
namespace A
{
int a, b, c;
namespace B {int i, j, k;}
}
int main()
{
A::a++;
A::B::i++;
::i++; // глобальное i
}
Слайд 18Имена стандартных библиотек С++
Согласно стандарту ANSI/ISO в C++ все имена
ресурсов стандартных библиотек определены в пространстве std. При использовании этого
пространства автоматически подключаются библиотеки ,, и т.д.
Пример:
// #include - не надо!
int main()
{ std::cout << "Hello "; 1-й вариант
using namespace std; 2-й вариант
cout << "World." << endl;
}
Однако можно по-прежнему использовать определение ресурсов стандартных библиотек в глобальном пространстве. Для этого необходимо подключать , , и т.д. (кроме ).
Список доступных стандартных библиотек в старой и новой формах можно посмотреть в среде.
Слайд 193.10 Аргументы командной строки
int main( int argc,char *argv[ ]) {
... }
где argc - количество параметров командной строки +1;
argv[0] - может содержать полное имя файла программы, например “A:\ddd.exe”.
argv[1] - содержит первый параметр из командной строки;
argv[2] - содержит второй параметр из командной строки и т.д. Номер предпоследнего элемента массива argv[ ] равен argc. Он содержит последний параметр. Последний элемент массива argv содержит NULL.
Слайд 203.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);