Д.з. на 31 марта Язык С++1
Задача 1: поиск четного // Поиск четного – без использования исключений bool find_even(const tree* p) { if (p==0) // В пустом дереве нет return false;// четных элемeнтов return // А для не пустого используем p->val%2 == 0 || // рекурсивную формулу. find_even(p->left) || find_even(p->right); }
Задача 1: поиск с исключениями Что бросать? Вариант: Указатель на вершин у void find_even1(const tree* p) { if (p!=0) // Для пустого дерева return; // ничего не делаем if (p->val % 2 ==0) // Нашли? throw p; // бросаем указатель // на вершину // Иначе обходим поддеревья find_even1(p->left); find_even1(p->right); } // find_even - вызываем find_even1 и // смотрим, было ли исключение. bool find_even(const tree* p) { try { find_even1(p); } catch (const tree* p) { return true; } return false; } Плохой стиль? (исключения только для обработки ошибок?) Язык С++ - занятие 733
Задача 4: сравнение строк без учета пробелов // Oдин из многих возможных способов решения.. bool compare(const char* s1, const char* s2) { for (;;) { // Пропускаем пробелы while (*s1==' ') s1++; while (*s2==' ') s2++; if (*s1!=*s2) // Разные символы? Выходим из цикла break; if (*s1=='\0') // Конец обеих строк? return true; s1++; s2++; } return false; // Раз мы здесь, то строки не равны }
Задача 3: исключения и утечка памяти // Исходная функция // … что-то делает со стеком … // Если стек пуст – исключение void f(stack& s) { int* p = new int[1000]; … что-то делаем с p … cout
Задача 3: еще вариант // Вариант 2: void f(stack& s) { int* p = new int[1000]; … что-то делаем с p … try { cout
Задача 3: еще вариант – "обернуть" p в класс! // Вариант 3: class wrapper { int* p; public: wrapper() { p = new int[1000]; } ~wrapper() { delete[] p; // Теперь delete точно выполниться } int* get() { return p; } }; void f(stack& s) { wrapper p; … что-то делаем с p.get() … cout
RAII Resource Acquisition Is Initialization Получение ресурса есть инициализация Пусть обязательно надо выполнить какое-то действие в конце функции (удалить память, закрыть файл, восстановить форму курсора и т.д.) Совет: завести вспомогательный класс выполнять это действие в деструкторе Преимущества: Получается короче thread safe – действие будет выполнено даже при наличии исключений Замечание: Если действие – это освободить память то можно использовать стандартные классы (vector) или классы boost (scoped_ptr, shared_ptr)
Д.з. на 7 апреля Язык С++9
Задача 3: += для строк План действий: 1. Отвести новый кусок памяти под длинную строку 2. Скопировать туда первую строку 3. Дописать вторую строку 4. Удалить старый кусок памяти 5. Установить новые p и len Язык С++10
Задача 3: += для строк string& string::operator+=(const string& from) { int newlen = len + from.len;// Вычисляем новую длину char* newp = new char[newlen + 1]; // Создаем новую строку strcpy(newp, p);// Сначала копируем первую строку strcpy(newp + len, from.p);// Потом, с нужного места, // приписываем вторую delete [] p;// Освобождаем старую строку p = newp; // И устанавливаем новую строку len = newlen; // И ее длину return *this; } Язык С++11
Доп.задачи про списки Язык С++12
Задача 5: список в обратном порядке struct list { int val; list* next; list(int val_, list* next_) : val(val_), next(next_) {} }; // Переставить элементы в // обратном порядке void reverse(list*& head) { list* head1 = 0; // Как бы создаем // новый список list* p = head; // Цикл по всем элементам while (p != 0) { list* next = p->next; // Элемент добавляем в // начало нового списка p->next = head1; head1 = p; p = next; } head = head1; } Язык С++13
Замечания про operator= и конструктор копирования Язык С++14
Замечания про оператор = и конструктор копирования class abc { string a, b, c; }; Тут оператор = и конструктор копирования по умолчанию работают правильно. a = from.a; b = from.b; c = from.c; (Вызываются переопределенные операторы =) Значит, тут оператор = и конструктор копирования лучше не переопределять. Язык С++15
Локальные, глобальные и статические переменные Язык С++16
Какие бывают переменные? Локальная Внутри функции void f() { int a = 56; Глобальная Вне функции int a = 56; void f() { … Статическая Внутри функции, static void f() { static int a = 56; Тут на доске была нарисована таблица: для каждого из этих видов переменных – когда они создаются, когда уничтожаются и из какой части программы они видны. static переменные – это, в каком-то смысле, среднее между локальными и глобальными
Пример int f() { static int i = 0; i++; return i; } Язык С++18
Статические поля и методы Язык С++19
static методы class abc { static void f(int i); … } void abc::f(int i) { … } // Вызов abc::f(56); Обычные функции (только описанные как бы внутри класса) Не могут использовать поля класса Точнее, могут использовать только статические поля Конечно, не могут быть virtual Могут быть private и protected В методах класса можно писать просто f(i); Зачем? По смыслу очень тесно связанные с классом Вспомогательные (private) Язык С++20
static методы - пример // Current time возвращает // текущее время class time { … static time current() { … } }; time t = time::current(); Язык С++21
static поля class abc { static int i; … } int abc::i = 0; // Использование аbc::i = 5; Обычные глобальные переменные (только описанные как бы внутри класса) Могут быть private и protected В методах класса можно писать просто i Не забывайте объявление int abc::i = 0; Зачем? По смыслу очень тесно связанные с классом Вспомогательные (private) Язык С++22
static поля - замечания static const целые можно описывать прямо в классе class abc { static const int maxsize = 100; … }; На старых компиляторах это не работает Можно понимать static поля, как поля, общие для всех членов класса Язык С++23
Что еще может быть в классе, кроме полей и методов Язык С++24
enum в классе class card { enum suit {spades, clubs, hearts, diamonds}; … }; // Использование card::suit s = card::spades; В методах класса можно писать просто: suit s = spades; М.б. private/protected Так часто объявляют константы: class abc { enum {maxsize = 100}; … то же, что class abc { static const int maxsize = 100; … Язык С++25
typedef в классе class abc { typedef long* myptr; … }; // Использование abc::myptr x; // Вне класса myptr x; // В классе М.б. private/protected Язык С++26
Вложенные классы class abc { class qlm { int i; void f(); … }; … }; // Определение методов void abc::qlm::f() { …} // Использование abc::qlm x; В методах класса abc можно писать просто qlm x; Методы, естественно, можно описывать и прямо в классе class abc { … void qlm::f() { … } Cовершенно обычный класс, только с таким странным именем abc::qlm Применение: вспомогательные классы Язык С++ - занятие 927
Вложенные классы и права доступа (дружба) Стандарт: не друзья Новый стандарт: внутренние классы могут использовать private поля внешнего класса.
STL – Standard Template Library Язык С++29
Alexander Stepanov
vector #include using namespace std; vector v(100); vector v; vector v1; vector v2; vector > v3; v[i] = 42; v[i] ++; v.at(i) // то же, что v[i], но с // проверкой диапазона v.push_back(56); v.pop_back(); int n = v.size() for (int i = 0; i
list #include using namespace std; list l; // Двусторонний список Некоторые операции, как для вектора: push_back, pop_back l.push_back(3); l.pop_back(); size n = l.size(); Есть дополнительные операции: push_front, pop_front l.push_front(5); Нет: l[i] resize Язык С++32
Итераторы list ::iterator p; Операции: p = l.begin(); p++; *p; cout
Еще про тип char char - это маленькое число unsigned char0 – 255 signed char-128 – 127 charзависит от компилятора Все арифметическиe операции работают if (c > '0' && c
Замечание про то, как вернуть объект из функции abc f() { … abc* p = new abc(); … return *p; } Утечка памяти! Надо как-то так abc f() { … abc x; … return x; } Язык С++35
Задачи на 14 апреля Язык С++36
Задачи на 14 апреля 1. Для string определить substr: string substr(откуда, сколько) string s = "abcdefg"; string s 1 = s.substr(2, 4); // "cdef" 2. Определить класс abc и в нем метод num(). Этот метод при вызове должен возвращать количество экземпляров abc, существующих в данный момент. abc x; abc y; // 2 экземпляра { abc z; // 3 экземпляра } // снова 2 экземпляра Замечание: В задаче есть одна тонкость (простое решение в некоторых случая дает неправильный ответ..) 3. Напишите функцию atоi_oct, которая переводит строку, содержащую запись числа в восьмеричной системе счисления в число. Например: int i = atoi_oct( "104"); // ответ д.б. 68 Пожалуйста, не пользуйтесь в этой задаче стандартными функциями. 4. Прочитать целые числа из файла и напечатать их в обратном порядке (с помощью list или vector) Язык С++37