С++. Программирование на языке высокого уровня

Содержание

Слайд 2

Лекция 4. Функции

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

Лекция 4. Функции Описание и использование функций. Параметры функции. Функции стандартной библиотеки
С. Директивы препроцессора. Создание программ, состоящих из нескольких модулей. Области действия имен. Именованные области.

Слайд 3

©Павловская Т.А. (СПбГУ ИТМО)

[ класс ] тип имя ([ список_параметров ]) [throw

©Павловская Т.А. (СПбГУ ИТМО) [ класс ] тип имя ([ список_параметров ])
( исключения )]
{ тело функции }

Функции

Класс:
extern — глобальная видимость во всех модулях программы (по умолчанию);
static — видимость только в пределах модуля, в котором определена функция.

inline

Слайд 4

©Павловская Т.А. (СПбГУ ИТМО)

#include
int sum(int a, int b); // объявление
int main(){
int

©Павловская Т.А. (СПбГУ ИТМО) #include int sum(int a, int b); // объявление
a = 2, b = 3, c, d;
c = sum(a, b); // вызов
cin >> d;
cout << sum(c, d); // вызов
}
int sum(int a, int b){ // определение
return (a + b);
}

Функции - пример

Слайд 5

©Павловская Т.А. (СПбГУ ИТМО)

#include
void f(int a){
cout << "n m\n";
while (a--){
static int

©Павловская Т.А. (СПбГУ ИТМО) #include void f(int a){ cout while (a--){ static
n = 0;
int m = 0;
cout << n++ << ' ' << m++ << '\n';
}
}
int main(){ f(3);}

n m
0 0
1 0
2 0

int* f(){
int a = 5;
return &a;
// нельзя!
}

Локальные статические переменные

Слайд 6

©Павловская Т.А. (СПбГУ ИТМО)

#include
void f(int i, int* j, int& k);
int main(){
int

©Павловская Т.А. (СПбГУ ИТМО) #include void f(int i, int* j, int& k);
i = 1, j = 2, k = 3;
cout <<“ i j k\n";
cout <<“до ” << i <<' '<< j <<' '< f(i, &j, k);
cout <<“после ” << i << ' ‘ << j << ' ‘ << k;
}
void f(int i, int* j, int& k){
i++; (*j)++; k++;
}

Параметры функции

i j k
до 1 2 3
после 1 3 4

char* t(char* a, const int* b);

Слайд 7

©Павловская Т.А. (СПбГУ ИТМО)

#include
int sum(const int* mas, const int n);
int const

©Павловская Т.А. (СПбГУ ИТМО) #include int sum(const int* mas, const int n);
n = 10;
void main(){
int marks[n] = {3, 4, 5, 4, 4};
cout << "Сумма эл-в: " << sum(marks, n);
}
int sum(const int* mas, const int n){
// варианты: int sum(int mas[], int n)
// или int sum(int mas[n], int n)
// (величина n должна быть константой)
int s = 0;
for (int i = 0; i return s;
}

Пример 1 - сумма элементов массива

Слайд 8

©Павловская Т.А. (СПбГУ ИТМО)

...
int sum(const int *a, const int nstr, const int

©Павловская Т.А. (СПбГУ ИТМО) ... int sum(const int *a, const int nstr,
nstb);
void main(){
int b[2][2] = {{2, 2}, {4, 3}};
printf(" %d\n", sum(&b[0][0], 2, 2));
int i, j, nstr, nstb, *a;
printf("Введите кол. строк и столбцов: \n");
scanf("%d%d", &nstr, &nstb);
a = (int *)malloc( nstr * nstb * sizeof(int) );
for (i = 0; i for (j = 0; j scanf("%d", &a[i * nstb + j]);
printf(" %d\n", sum(a, nstr, nstb));}

Пример 2 - сумма элементов массива

Слайд 9

©Павловская Т.А. (СПбГУ ИТМО)

int sum(const int *a, const int nstr, const int

©Павловская Т.А. (СПбГУ ИТМО) int sum(const int *a, const int nstr, const
nstb){
int i, j, s = 0;
for (i = 0; i for (j = 0; j s += a[i * nstb + j];
return s;
}

Пример 2 - сумма элементов массива

Слайд 10

©Павловская Т.А. (СПбГУ ИТМО)

...
int sum(const int **a, const int nstr, const int

©Павловская Т.А. (СПбГУ ИТМО) ... int sum(const int **a, const int nstr,
nstb);
void main(){
int nstr, nstb;
cin >> nstr >> nstb;
int **a;
a = new int* [nstr];
for (int i = 0; i a[i] = new int [nstb];
/* формирование матрицы a */
...
cout << sum(a, nstr, nstb);
}

Пример 3 - сумма элементов массива

Слайд 11

©Павловская Т.А. (СПбГУ ИТМО)

int sum(const int **a, const int nstr, const int

©Павловская Т.А. (СПбГУ ИТМО) int sum(const int **a, const int nstr, const
nstb){
int i, j, s = 0;
for (i = 0; i for (j = 0; j s += a[i][j];
return s;
}

Пример 3 - сумма элементов массива

Слайд 12

©Павловская Т.А. (СПбГУ ИТМО)

Передача имен функций в качестве параметров

void f( int a

©Павловская Т.А. (СПбГУ ИТМО) Передача имен функций в качестве параметров void f(
){ /* ... */ }
void (*pf)( int ); // указатель на функцию
pf = &f; // или pf = f;
pf(10); // или (*pf)(10)

void fun(PF pf){ ... pf(10); ... }

typedef void (*PF)(int);
PF menu[]={&new, &open, &save};
menu[1](10);

Слайд 13

©Павловская Т.А. (СПбГУ ИТМО)

Параметры со значениями по умолчанию

int f(int a, int b

©Павловская Т.А. (СПбГУ ИТМО) Параметры со значениями по умолчанию int f(int a,
= 0);
void f1(int, int = 100, char* = 0);
void err(int errValue = errno);
...
f(100); f(a, 1);
f1(a); f1(a, 10); f1(a, 10, "Vasia");
f1(a,,"Vasia") // неверно!

Слайд 14

©Павловская Т.А. (СПбГУ ИТМО)

Функции с переменным числом параметров

int printf(const char* ...);
printf("Введите исходные

©Павловская Т.А. (СПбГУ ИТМО) Функции с переменным числом параметров int printf(const char*
данные");
printf("Сумма: %5.2f рублей", sum);
printf("%d %d %d %d", a, b, c, d);

Для доступа к необязательным параметрам внутри функции используются макросы библиотеки va_start, va_arg и va_end, находящиеся в заголовочном файле .

Слайд 15

©Павловская Т.А. (СПбГУ ИТМО)

Рекурсивные функции

long fact(long n){
if (n==0 || n==1) return 1;
return

©Павловская Т.А. (СПбГУ ИТМО) Рекурсивные функции long fact(long n){ if (n==0 ||
(n * fact(n - 1));
}
Или:
long fact(long n){
return (n > 1) ? n * fact(n - 1) : 1;
}

Слайд 16

©Павловская Т.А. (СПбГУ ИТМО)

Перегрузка функций

int max(int, int);
char* max(char*, char*);
int max (int, char*);
int

©Павловская Т.А. (СПбГУ ИТМО) Перегрузка функций int max(int, int); char* max(char*, char*);
max (char*, int);
void f(int a, int b, char* c, char* d){
cout << max (a, b) << max(c, d)
<< max(a, c) << max(c, b);
}

Слайд 17

©Павловская Т.А. (СПбГУ ИТМО)

Неоднозначность может появиться при:
преобразовании типа;
использовании параметров-ссылок;
использовании аргументов по умолчанию.

#include

©Павловская Т.А. (СПбГУ ИТМО) Неоднозначность может появиться при: преобразовании типа; использовании параметров-ссылок;

float f(float i){...}
double f(double i){...}
int main(){
float x = 10.09;
double y = 10.09;
cout << f(x) << endl;
cout << f(y) << endl;
// cout << f(10) << endl; Неоднозначность!
}

Неоднозначность

Слайд 18

©Павловская Т.А. (СПбГУ ИТМО)

int f(int a, int b) {…}
int f(int a, int

©Павловская Т.А. (СПбГУ ИТМО) int f(int a, int b) {…} int f(int
&b) {…}

#include
int f(int a){return a;}
int f(int a, int b = 1){return a * b;}
int main(){
cout << f(10, 2);
/* cout << f(10); Неоднозначность — что вызывается:
f(int, int) или f(int) ? */
}

Неоднозначность

Слайд 19

©Павловская Т.А. (СПбГУ ИТМО)

Правила описания перегруженных функций

Перегруженные функции должны находиться в одной

©Павловская Т.А. (СПбГУ ИТМО) Правила описания перегруженных функций Перегруженные функции должны находиться
области видимости
Перегруженные функции могут иметь параметры по умолчанию, при этом значения одного и того же параметра в разных функциях должны совпадать. В различных вариантах перегруженных функций может быть различное количество параметров по умолчанию.
Функции не могут быть перегружены, если описание их параметров отличается только модификатором const или использованием ссылки (например, int и const int или int и int&).

Слайд 20

©Павловская Т.А. (СПбГУ ИТМО)

Шаблоны функций

template <параметры> заголовок
{ /* тело функции */ }

Параметры:
class

©Павловская Т.А. (СПбГУ ИТМО) Шаблоны функций template заголовок { /* тело функции
имя
typename имя
template < … > class имя
описание параметра

template
f(...){...}

Слайд 21

©Павловская Т.А. (СПбГУ ИТМО)

template
void sort_vybor(Type *b, int n){
Type a;
for (int

©Павловская Т.А. (СПбГУ ИТМО) template void sort_vybor(Type *b, int n){ Type a;
i = 0; i int imin = i;
for (int j = i + 1; j if (b[j] < b[imin]) imin = j;
a = b[i]; b[i] = b[imin];
b[imin] = a;
}

Шаблоны функций - пример

Слайд 22

©Павловская Т.А. (СПбГУ ИТМО)

#include
template
void sort_vybor(Type *b, int n);
int

©Павловская Т.А. (СПбГУ ИТМО) #include template void sort_vybor(Type *b, int n); int
main(){
const int n = 20;
int b[n];
for (int i = 0; i> b[i];
sort_vybor(b, n);
for (int i=0; idouble a[] = {0.22, 117, -0.08, 0.21, 42.5};
sort_vybor(a, 5);
for (int i=0; i<5; i++) cout << a[i] << ' ';
}

Шаблоны функций - пример

Слайд 23

©Павловская Т.А. (СПбГУ ИТМО)

Явное задание аргументов шаблона

template

©Павловская Т.А. (СПбГУ ИТМО) Явное задание аргументов шаблона template void f(Y, Z);
Z> void f(Y, Z);
void g(){
f("Vasia", 3.0);
f("Vasia", 3.0);
// Z определяется как double
f("Vasia", 3.0);
// Y определяется как char*, а Z определяется как double
// f("Vasia", 3.0); ошибка: X определить невозможно
}

Слайд 24

©Павловская Т.А. (СПбГУ ИТМО)

class T { /* ... */ };
int i;
template

©Павловская Т.А. (СПбГУ ИТМО) class T { /* ... */ }; int
T, T i> void f(T t)
{
T t1 = i; // template-parameters T and i
::T t2 = ::i; //global namespace members T and i
}

integral or enumeration type,
pointer to object or pointer to function,
reference to object or reference to function

Описание параметра может быть:

Шаблоны функций - описание параметра (4)

template
void f(){ ... }

Слайд 25

©Павловская Т.А. (СПбГУ ИТМО)

template void f1(int a[10][i]);
template void

©Павловская Т.А. (СПбГУ ИТМО) template void f1(int a[10][i]); template void f2(int a[i][20]);
f2(int a[i][20]);
template void f3(int (&a)[i][20]);
void g()
{
int v[10][20];
f1(v); // OK: i deduced to be 20
f1<20>(v); // OK
f2<10>(v); // OK
f3(v); // OK: i deduced to be 10
}

Примеры параметра

Слайд 26

©Павловская Т.А. (СПбГУ ИТМО)

Специализация шаблона функции

void sort_vibor (int *b, int n)
{
тело

©Павловская Т.А. (СПбГУ ИТМО) Специализация шаблона функции void sort_vibor (int *b, int
специализированного метода
}

Слайд 27

©Павловская Т.А. (СПбГУ ИТМО)

Функция main()

// без параметров:
тип main(){ ... }
//

©Павловская Т.А. (СПбГУ ИТМО) Функция main() // без параметров: тип main(){ ...
с двумя параметрами:
тип main(int argc, char* argv[]){ ... }

#include
void main(int argc, char* argv[]){
for (int i = 0; i}

d:\cpp\main.exe one two three

D:\CPP\MAIN.EXE
one
two
three

Слайд 28

©Павловская Т.А. (СПбГУ ИТМО)

Функции стандартной библиотеки

Функции ввода/вывода или .

mode: (b/t) и
"r"

©Павловская Т.А. (СПбГУ ИТМО) Функции стандартной библиотеки Функции ввода/вывода или . mode:
— файл открывается для чтения;
"w" — открывается пустой файл для записи (если файл существует, он стирается);
"a" — файл открывается для добавления информации в его конец;
"r+" — файл открывается для чтения и записи (файл должен существовать);
"w+" — открывается пустой файл для чтения и записи (если файл существует, он стирается);
"a+" — файл открывается для чтения и добавления информации в его конец

FILE* fopen(const char* filename, const char* mode);

FILE *f = fopen("d:\\cpp\\data.txt", "rb+");

Слайд 29

©Павловская Т.А. (СПбГУ ИТМО)

стандартный ввод stdin
стандартный вывод stdout
стандартный вывод сообщений об ошибках

©Павловская Т.А. (СПбГУ ИТМО) стандартный ввод stdin стандартный вывод stdout стандартный вывод
stderr
стандартный дополнительный поток stdaux
стандартная печать stdprn

Предопределенные потоки

Слайд 30

©Павловская Т.А. (СПбГУ ИТМО)

Чтение и запись потока байтов — fread, fwrite.
Чтение символа

©Павловская Т.А. (СПбГУ ИТМО) Чтение и запись потока байтов — fread, fwrite.
из потока — getc, fgetc, из стандартного потока stdin — getchar.
Запись символа в поток — putc, fputc, в стандартный поток stdout — putchar.
Чтение строки из потока — fgets, из стандартного потока stdin — gets.
Запись строки в поток — fputs, в стандартный поток stdout — puts.
Форматированный ввод из потока — fscanf, из стандартного потока stdin — scanf, из строки — sscanf.
Форматированный вывод в поток — fprintf, в стандартный поток stdout — printf, в строку — sprintf.
int fclose(FILE*); int feof(FILE*);
int ferror(FILE*);

Функции ввода/вывода

Слайд 31

©Павловская Т.А. (СПбГУ ИТМО)

#include
#include
#include
#include
int main(){
FILE *fi, *fo;
if((fi =

©Павловская Т.А. (СПбГУ ИТМО) #include #include #include #include int main(){ FILE *fi,
fopen("d:\\c\\file.txt", "r")) == 0){
cout << "Ошибка"; return 1;};
if((fo = fopen("d:\\c\\binfile.out", "w+b"))==0){
cout << "Ошибка"; return 1;};
const int dl = 80;
char s[dl];

Работа с файлами - пример 1

Слайд 32

©Павловская Т.А. (СПбГУ ИТМО)

struct{
char type[20];
int opt, rozn;
char comm[40];
}mon;
while (fgets(s, dl, fi)){
// Преобразование строки в структуру:
strncpy(mon.type,

©Павловская Т.А. (СПбГУ ИТМО) struct{ char type[20]; int opt, rozn; char comm[40];
s, 19); mon.opt = atoi(&s[20]);
mon.rozn = atoi(&s[25]);
strncpy(mon.comm, &s[30], 40);
fwrite(&mon, sizeof mon, 1, fo);
}
fclose(fi);

Работа с файлами - пример 1

Слайд 33

©Павловская Т.А. (СПбГУ ИТМО)

int i; cin >> i; // Номер записи
fseek(fo, (sizeof mon)*i,

©Павловская Т.А. (СПбГУ ИТМО) int i; cin >> i; // Номер записи
SEEK_SET);
fread(&mon, sizeof mon, 1, fo);
cout << "mon.type " << mon.type << " opt "
<< mon.opt << " rozn "
<< mon.rozn << endl;
fclose(fo);
return 0;
}

Работа с файлами - пример 1

Слайд 34

©Павловская Т.А. (СПбГУ ИТМО)

isalnum
isalfa
iscntrl
isdigit
isgraph
islower
isprint
ispunct
isspace
isupper
isxdigit

double atof(const char* p)
int atoi(const char* p)
long atol(const char*

©Павловская Т.А. (СПбГУ ИТМО) isalnum isalfa iscntrl isdigit isgraph islower isprint ispunct
p)

копирование строк (strcpy, strncpy) сравнение (strcmp, strncmp), объединение строк (strcat, strncat) поиск подстроки (strstr) поиск вхождения символа (strchr, strrchr, strpbrk) определение длины строки (strlen) и другие.

Другие функции библиотеки

Математические

Слайд 35

©Павловская Т.А. (СПбГУ ИТМО)

#include
#include
#include
int main(){
char s[] = "2, 38.5,

©Павловская Т.А. (СПбГУ ИТМО) #include #include #include int main(){ char s[] =
70, 0, 0, 1", *p = s;
float m[10];
int i = 0;
do{
m[i++] = atof(p);
if (i>9) break;
}while(p = strchr(p, ','), p++);
for( int k = 0; k return 0;
}

Использование стандартных функций

Слайд 36

©Павловская Т.А. (СПбГУ ИТМО)

Директивы препроцессора

Директива #include:
#include <имя_файла>
“ “
Заголовочные

©Павловская Т.А. (СПбГУ ИТМО) Директивы препроцессора Директива #include: #include “ “ Заголовочные
файлы могут содержать:
определения типов, констант, встроенных функций, шаблонов, перечислений;
объявления функций, данных, имен, шаблонов;
пространства имен;
директивы препроцессора;
комментарии.

В заголовочном файле не должно быть определений
функций и данных.

Слайд 37

©Павловская Т.А. (СПбГУ ИТМО)

// my_header.h
extern int a;
extern double b;
// -------------------
//

©Павловская Т.А. (СПбГУ ИТМО) // my_header.h extern int a; extern double b;
one.cpp
#include "my_header.h"
int a;
// -------------------
// two.cpp
#include "my_header.h"
double b;

Внешние объявления

Чтобы сделать доступной в нескольких модулях переменную или константу, необходимо:
- определить ее ровно в одном модуле как глобальную;
- объявить ее как внешнюю с помощью модификатора extern. Поместить это объявление либо в нужные модули, либо в заголовочный файл, который включить в нужные модули.

Все объявления одной переменной должны быть согласованы

Слайд 38

©Павловская Т.А. (СПбГУ ИТМО)

используется для определения:
символических констант :
#define имя текст_подстановки
макросов:
#define имя(

©Павловская Т.А. (СПбГУ ИТМО) используется для определения: символических констант : #define имя
параметры ) текст_подстановки
символов, управляющих условной компиляцией: #define имя

Директива #define

#define M 1000
#define Vasia “Василий Иванович”
#define MAX(x,y) ((x)>(y)?(x):(y))

Практически каждый макрос свидетельствует о недостатке в языке, программе или программисте

Слайд 39

©Павловская Т.А. (СПбГУ ИТМО)

#define N(a,b) a##b /*склеить */

int N(bam,buk)(); /* => int bambuk();

©Павловская Т.А. (СПбГУ ИТМО) #define N(a,b) a##b /*склеить */ … int N(bam,buk)();
*/

Альтернативы макросам в С++:
const, inline, template, namespace

#undef имя

Слайд 40

©Павловская Т.А. (СПбГУ ИТМО)

Директивы условной компиляции: #if -- #endif

Назначение:
- исключить компиляцию отдельных

©Павловская Т.А. (СПбГУ ИТМО) Директивы условной компиляции: #if -- #endif Назначение: -
частей программы
- временно закомментировать фрагменты кода
#if конст_выражение
...
[ #elif конст_выражение
...]
[ #elif конст_выражение
...]
[ #else
]
#endif

#if OPT == 2
#include “hdr2.h”
#elif OPT == 1
#include “hdr1.h”
#elif
#include
#endif

Слайд 41

©Павловская Т.А. (СПбГУ ИТМО)

#if defined(__BORLANDC__) && __BORLANDC__ == 0x530
// Tested with BC5.3:
typedef

©Павловская Т.А. (СПбГУ ИТМО) #if defined(__BORLANDC__) && __BORLANDC__ == 0x530 // Tested
istream_iterator, ptrdiff_t>
istream_iter;
#elif defined(__BORLAND__) // Tested with BC5.2:
typedef istream_iterator istream_iter;
#else // Tested with VC5.0:
typedef istream_iterator istream_iter;
#endif

#if 0
int i, j;
double x, y;
#endif

Директивы условной компиляции: пример

Слайд 42

©Павловская Т.А. (СПбГУ ИТМО)

#ifdef символ
// Расположенный ниже код компилируется, если символ определен
#ifndef

©Павловская Т.А. (СПбГУ ИТМО) #ifdef символ // Расположенный ниже код компилируется, если
символ
// Расположенный ниже код компилируется, если символ не определен

#ifndef HEADER_INCLUDED
#include "myheader.h"
#define HEADER_INCLUDED
#endif

Директивы #ifdеf и #ifndеf

Слайд 43

©Павловская Т.А. (СПбГУ ИТМО)

Стражи включения

Содержимое каждого заголовочного файла:
#ifndef FNAME_H
#define FNAME_H

#endif /* FNAME_H

©Павловская Т.А. (СПбГУ ИТМО) Стражи включения Содержимое каждого заголовочного файла: #ifndef FNAME_H
*/

Слайд 44

©Павловская Т.А. (СПбГУ ИТМО)

#define x 3
#define f(a) f(x * (a))
#undef x

©Павловская Т.А. (СПбГУ ИТМО) #define x 3 #define f(a) f(x * (a))

#define x 2
#define g f
#define z z[0]
#define h g(~
#define m(a) a(w)
#define w 0,1
#define t(a) a

f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); g(x+(3,4)-w) | h 5) & m
(f)^m(m);

f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);

Директива #dеfine - антипример

Слайд 45

©Павловская Т.А. (СПбГУ ИТМО)

Предопределенные макросы

#ifdef __cplusplus
// Действия, специфические для С++
#endif
printf(" Дата

©Павловская Т.А. (СПбГУ ИТМО) Предопределенные макросы #ifdef __cplusplus // Действия, специфические для
компиляции — %s \n", __DATE__);
printf("Ошибка в файле %s\nВремя комп: %s\n", __FILE__, __TIME__);
__LINE__

Слайд 46

©Павловская Т.А. (СПбГУ ИТМО)

Поименованные области

namespace [ имя_области ]{ /* Объявления */}

namespace demo{
int

©Павловская Т.А. (СПбГУ ИТМО) Поименованные области namespace [ имя_области ]{ /* Объявления
i = 1;
int k = 0;
void func1(int);
void func2(int) { ... }
}
namespace demo{ // Расширение
// int i = 2; Неверно — двойное определение
void func1(double); // Перегрузка
void func2(int);//Верно (повторное объявление)
}

void demo::func1(int) { ... }

определение