47
C++ - занятие 2 1

C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

C++ - занятие 2

1

Page 2: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Какие типы вы бы использовали?

age // возраст

salary // зарплата за месяц (в рублях)

grade // средний балл

char short long int

unsigned long long float double

Я бы написал так:

int age; // short если очень экономить память

int salary; // double если вспомнить про копейки??

// long если вспомнить про 16 бит??

// Но тогда уж лучше typedef

double grade; // float если очень экономить память

Page 3: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Можно ли так написать?

Чему будут равны i, j, k?

int i=3; int j=2; int k=1;

1. i %= j;

2. i = j++ > 0 || k++ > 0;

3. (i *= 10) += j;

4. i = (int n = 2)*j;

5. i = '9' - '0';

6. i = k++ / k++;

7. i += sizeof(j++);

// i = 1

// i = 1; j = 3; k = 1;

// i = 32

// ошибка

// i = 9

// результат не определен

// i = 7 (но вообще-то зависит от компилятора), j = 2

Page 4: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Д.з.

4

Page 5: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Задача 1: 1/13 + 1/3 3 + 1/5 3 …#include <iostream>

using namespace std;

int main()

{

int n;

cin >> n;

double sum = 0;

for (int i = 1; i <= 2*n+1; i+=2) {

sum += 1.0/(i*i*i);

}

cout << sum;

return 0;

}

5

Перебираем нечетные числа

Или 1/i/i/i или pow(i,3)

Page 6: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Задача 2:

Среднее арифметическое до 0

// Найти среднее арифметическое чисел пока != 0

int sum = 0;

int num = 0;

for (;;) {

int n;

cin >> n;

if (n == 0)break;

sum += n;

num++;

}

cout << sum/num;

Прием «1.5 цикла»

Повторять до бесконечности

Page 7: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Задача 3: Количество элементов до

первого нуля

Без указателей

int i = 0;

for (; a[i] != 0; i++)

;

cout << i;

С указателями

int i = 0;

for (int* p = a; *p != 0; p++)

i++;

cout << i;

или

int* p = a;

for (; *p != 0; p++)

;

cout << p - a;

Вызов

int a[10] = {1,2,3,0,0,0,0,0,0,0};

Или можно короче

int a[10] = {1, 2, 3};

Нули можно не писать

А как можно быстрее?

Page 8: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Задача 4 – пока только некоторые

замечания

… проверяем, например на простоту …

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

Неэффективно!

Можно закончить проверять раньше

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

Неэффективно

Вычислять корень в цикле – это плохо

Page 9: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Задача 4 – еще замечание

… проверяем на почти простоту …

for (int i = 0; …; i++) {

if (n % i == 0 && isPrime(i) && isPrime(n/i) == 0)

return true;

}

return false;

Неэффективно!

То, что число не почти простое тоже можно выяснить не перебирая все делители!

Достаточно двух делителей!

Самый маленький делитель можно не проверять, он всегда простой.

Page 10: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Еще про операторы

10

Page 11: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

switch

switch ( ocenka ) {

case 1:

case 2: cout << "плохо";

break;

case 3: cout << "удовлетворительно";

break;

case 4: cout << "хорошо";

break;

case 5: cout << "отлично";

break;

default: cout << "что-то странное";

}

Page 12: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Пустой оператор

;

while (a[i++] != 0);

Page 13: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Еще про массивы

13

Page 14: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

На самом деле, вместо массивов

удобнее использовать тип vector

Забегая вперед, вообще-то удобнее всего писать так:

vector<int> v(10); // Массив из 10 чиселv[5] = 7;…

Но это мы пройдем позже

Page 15: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Многомерные массивы?

Используются массивы массивов

int c[10][10]; // Так определяемc[i][j] = 0; // Так используем

Page 16: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Еще разное

16

Page 17: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Самые частая простая ошибка

1. if (i = 0)

if (i == 0)

Page 18: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Скобки

if (i > 0 && i < n)

*p++

*(p++)

Скобки вокруг сравнений не нужны

Page 19: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Указатели

Page 20: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

20

Указатели – динамическая память Динамическая память: new и delete

p = new int;p = new int(56); // С инициализацией…delete p;

Динамическое отведение массивов

p = new int[k]; // Отвести массив из k элементов

Размер может быть любым целым выражением

Освобождение массивов

delete [] p; // Не забыть [] !!!

20

Page 21: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Инициализация в С++11 Так в С++11 можно инициализировать нулями:

int a[10] {};

int* p = new int [n] {};

Так в С++11 можно инициализировать динамический массив:

int* p = new int [n] {1, 2, 3};

21

Page 22: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Умные указатели (забегая вперед)

С++11:

shared_ptr

unique_ptr

И в результате new и delete пишут довольно редко.

Но об этом будет позже.

22

Page 23: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

23

Ошибки при работе с указателями - 1

1. p = nullptr;*p = 5;

2. int* p;*p = 5;

3. delete p;*p = 5;

4. p = q;…delete p;

…*q = 5;

Обращение к нулевому адресу

Использование не инициализированного адреса

Обращение к уже освобожденной памяти (dangling pointer)

Page 24: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Ошибки при работе с динамической

памятью - 2

1. int* p = new int;p = nullptr;

2. p = new int;…p = new int;

Утечка памяти (memory leak)

Page 25: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Указатели и массивы

Адресная арифметика

Page 26: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Указатели и массивы

int a[100];

int* p;

p = a; // a – адрес нулевого эл-та (&a[0])

p + n; // на n ячеек впередp - n; // на n ячеек назад

p += n p -= np++ p--

p1 – p2 // Сколько ячеек между p1 и p2?

if (p1 < p2)

p[i] // Как бы считаем p началом массива// p[i] тоже, что *(p+i)

Page 27: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Зачем это все?

С указателями можно работать, как с массивами

int* p = new int[k];p[3] = 1;

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

int a[100];

for (int* p = а; p < a + 100; p++) s += *p;

Page 28: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Замечания

Равенства:

&a[i] то же, что а+i

&a[0] то же, что а

Операции с массивами не отличаются (почти) от указателей

А в чем все-таки отличаются?

sizeof a - размер массива

sizeof p - размер указателя

Page 29: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Еще про функции

Page 30: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Как в C++ описать функцию, которая

ничего не возвращает?

Любую функцию можно вызывать, как процедуру -результат просто не используется

А можно написать тип результата void

void f(int i){

if (i>0) {cout << "Положительное";return;

}cout << "Отрицательное";

}

И тогда можно писать return;

Page 31: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

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

void twice(int& i){

i *= 2;}

int k = 10;twice(k);cout << k;

// Теперь 20

примерно то же, что var в Паскале подробнее про & позже

int& - параметр передается по ссылке.

Означает, что мы хотим менять параметр в функции

Page 32: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Объявление функции Вообще компилятор С++ однопроходный.

Перед тем, как использовать что-то, оно должно быть объявлено

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

void f(int i, int j);

cout << f(3, 5);…

void f(int i, int j){

…}

void f(int i, int j); - примерно то же, что forward в Паскале

Определение фунцкии

Объявление функции (прототип)

Page 33: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Массивы, как параметры

Page 34: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Что будет, если массив передать, как

параметр?

int arr[100];…cout << sum(arr);

int sum(int *a){

int s = 0;for(int i = 0; i < 100; i++)

s += a[i];return s;

}

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

Page 35: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Массив, как параметр - продолжение

И так можно писать:

int sum(int a[])

Но это транслируется в

int sum(int* a)

(Если сомневаетесь – попробуйте sizeof)

Замечание о длине массива:

А можем мы как-то в функции узнать длину массива?

Нет!

Ну и что тогда делать?

Передавать длину в качестве доп. параметра (или использовать

vector и т.д.)

Page 36: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Дополнительные

возможности для функций

Page 37: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

inline

inline int square(int i){

return i*i;}

n = square(k);

Зачем?

Будет работать быстрее (но код будет больше)

Это просто совет.. Компилятор может и не послушать

По-моему, современным компиляторам особо нет смысла что-то советовать…

Заменяется прямо в тексте на n = k*k

Page 38: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Параметры по умолчанию void f(int i, int j = 55) {

…}

f(3)

f(3, 55)

Замечания:

Умолчания могут быть для нескольких параметров

void f(int i = 0, double x = 1, int j = 100)

Нельзя опускать параметры в середине (только в конце)

Вопрос: где писать – в объявлении (прототипе) или в описании?

В обьявлении!

Page 39: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Перегрузка (overload) void f(int i) {… }

void f(double j) { … }

OK, компилятор различит:

f(5); // Первая функция

f(3.14); // Вторая функция

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

void f(int i) { … }

void f(int i, int j) { … }

f(5); // Первая функция

f(7, 8); // Вторая функция

Page 40: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Всегда ли можно перегружать

функции?

int f(int i) { … }double f(int i) { … }

Будет ошибка при вызове

f(5); // Непонятно, что вызывать

int f(int i) { … }int f(int i, int j = 0) { … }

А так можно?

Тоже будет ошибка при вызове

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

Page 41: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Ссылки

Page 42: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

42

Ссылки

int a[100];

int& k = a[5];

k++; // тоже, что a[5]++;

cout << k; // cout << a[5];

Page 43: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Типичные применения

1. Синоним для быстрого доступа к объекту

а[7].abc.b[88] += 10;

int& k = а[7].abc.b[88];

k += 10;

2. Параметры по ссылке – аналог var в Pascal

void dbl(int& i){

i *= 2;}

int m = 10;dbl(m);

// При вызове dbl выполняется int& i = m; 43

Page 44: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Применения ссылок - продолжение

3. Функции, возвращающие lvalue

Что такое lvalue?

11 x+1 sin(x) true

x a[i] *p x.abc

lvalue – то, у чего есть адрес(или можно сказать - то, что может писаться слева от равенства, но это не совсем точно)

44

Page 45: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Применения ссылок - продолжение

int& f(int* a) // Функция, возвращающая lvalue

{ // (просто для примера, совершенно бессмысленная)

return a[5];

}

int arr[100];

cout << f(arr); // то же, что cout << аrr[5]

f(arr) = 77; // то же, что аrr[5] = 77

f(arr)++; // то же, что аrr[5]++

45

Page 46: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Д.з.

46

Page 47: C++ - занятие 2msimuni.wdfiles.com/local--files/cpp/cpp2.pdf · Какие типы вы бы использовали? age // возраст salary // зарплата за

Задачи1. Описать функцию reverse.

Должна позволять переставить: массив чисел в обратном порядке.

Желательно реализовать с помощью арифметики указателей (не используя [])

(И *(a+i) тоже не используя…)

2. “Треугольный массив”Массив указателей:int* a[10];

а. Отвести динамические массивы длины 1, 2, 3… и запомнить указатели в массиве a.

б. Инициализировать массивы так: в каждом массиве последний элемент 1, остальные 0.

в. Напечатать массив.

3. Ф-я order(x, y, z); - меняет значения в x, y, z так, чтобы они шли по возрастанию,x <= y <= z. Например:

int a=5, b=1; c=3;order(a, b, c);

… теперь a==1, b==3, c==5

4. Изменение параметров без ссылок (старинный способ:)

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

Пример вызова:

int i = 5;twice(&i);… // теперь i == 10

47