370 likes | 544 Views
Д.з. на 31 марта. Язык С++. 1. Задача 1 : поиск четного. // Поиск четного – без использования исключений bool find_even(const tree* p) { if ( p ==0) // В пустом дереве нет return false ; // четных элем e нтов return // А для не пустого используем
E N D
Д.з. на 31 марта Язык С++ 1
Задача 1: поиск четного // Поиск четного – без использования исключений bool find_even(const tree* p) { if (p==0) // В пустом дереве нет returnfalse; // четных элем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) // Нашли? throwp; // бросаем указатель // на вершину // Иначе обходим поддеревья 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; } Плохой стиль? (исключения только для обработки ошибок?) Язык С++ - занятие 7 3 3
Задача 4: сравнение строк без учета пробелов // Oдин из многих возможных способов решения.. bool compare(const char* s1, const char* s2) { for (;;) { // Пропускаем пробелы while (*s1==' ') s1++; while (*s2==' ') s2++; if (*s1!=*s2) // Разные символы? Выходим из цикла break; if (*s1=='\0') // Конец обеих строк? returntrue; s1++; s2++; } return false;// Раз мы здесь, то строки не равны }
// Исходная функция // … что-то делает со стеком … // Если стек пуст – исключение void f(stack& s) { int* p = new int[1000]; … что-то делаем с p … cout << s.pop(); delete [] p; } // Если стек пуст - // утечка памяти // Вариант 1: void f(stack& s) { int* p = new int[1000]; … что-то делаем с p … try { cout << s.pop(); } catch (…) { } delete [] p; } // Если стек пуст, об // этом никак не сообщается Задача 3: исключения и утечка памяти
// Вариант 2: void f(stack& s) { int* p = new int[1000]; … что-то делаем с p … try { cout << s.pop(); } catch (…) { delete [] p; throw; } delete [] p; } // Слишком сложно? // Использовать RAII? Задача 3: еще вариант
// Вариант 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 << s.pop(); } Задача 3: еще вариант – "обернуть" p в класс!
RAII Resource Acquisition Is Initialization Получение ресурса есть инициализация Пустьобязательно надо выполнить какое-то действие в конце функции (удалить память, закрыть файл, восстановить форму курсора и т.д.) Совет: • завести вспомогательный класс • выполнять это действие в деструкторе Преимущества: • Получается короче • thread safe – действие будет выполнено даже при наличии исключений • Замечание: Если действие – это ‘освободить память’ то можно использовать стандартные классы (vector) или классы boost (scoped_ptr, shared_ptr)
Д.з. на 7 апреля Язык С++ 9
Задача 3: += для строк План действий: Отвести новый кусок памяти под длинную строку Скопировать туда первую строку Дописать вторую строку Удалить старый кусок памяти Установить новые 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
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; } Задача 5: список в обратном порядке Язык С++ 13
Замечания про operator= и конструктор копирования 25.03.2008 Язык С++ 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 Применение: вспомогательные классы Язык С++ - занятие 9 27
Стандарт: не друзья Новый стандарт:внутренние классы могут использовать private поля внешнего класса. Вложенные классы и права доступа (дружба)
STL – Standard Template Library Язык С++ 29
vector #include <vector> using namespace std; vector<int> v(100); vector<int> v; vector<double> v1; vector<string> v2; vector<time> v2; vector<vector<int>> 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<v.size(); i++) cout << v[i]; v.resize(200); Язык С++ - занятие 9 31
list #include <list> using namespace std; list<int> l; // Двусторонний список Некоторые операции, как для вектора: push_back, pop_back l.push_back(3); l.pop_back(); size n = l.size(); Есть дополнительные операции: push_front, pop_frontl.push_front(5); Нет: l[i] resize Язык С++ 32
Итераторы list<int>::iterator p; Операции: p = l.begin(); p++; *p; cout << *p; *p = 66; p--; l.end(); // За концом списка // конец списка: p = l.end() ; p--; // Пример: сумма элементов sum = 0; for (p = l.begin(); p != l.end(); p++) { sum += *p; } Язык С++ 33
Еще про тип char char - это маленькое число unsigned char 0 – 255 signed char -128 – 127 char зависит от компилятора Все арифметическиe операции работают if (c > '0' && c <= '9') int i = c – '0';// Переводим символ от ‘0’ до ‘9’ // в соответствующее число Язык С++ 34
abc f() { … abc* p = new abc(); … return *p; } Утечка памяти! Надо как-то так abc f() { … abc x; … return x; } Замечание про то, как вернуть объект из функции Язык С++ 35
Задачи на 14 апреля Язык С++ 36
Задачи на 14 апреля Для string определить substr:string substr(откуда, сколько)string s = "abcdefg";string s1 = s.substr(2,4);// "cdef" Определить класс abc и в нем метод num(). Этот метод при вызове должен возвращатьколичество экземпляров abc, существующих в данный момент.abc x; abc y; // 2 экземпляра{ abc z; // 3 экземпляра} // снова 2 экземпляра Замечание: В задаче есть одна тонкость (простое решение в некоторых случая дает неправильный ответ..) • Напишите функцию atоi_oct,которая переводит строку, содержащую запись числа в восьмеричной системе счисления в число. Например: int i = atoi_oct("104"); // ответ д.б. 68 • Пожалуйста, не пользуйтесь в этой задаче стандартными функциями. • Прочитать целые числа из файла и напечатать их в обратном порядке (с помощью list или vector) Язык С++ 37