370 likes | 514 Views
Про экзамен. Про экзамен – как он будет проходить, льготы за баллы и т.д. 10 задач / вопросов Письменно, 90 мин. Проверю примерно через 30- 6 0 мин, в зависимости от количества участников Если оценка не очевидна, или если в ответах что-то непонятно , то потом еще м.б. устные вопросы
E N D
Про экзамен – как он будет проходить, льготы за баллы и т.д. • 10 задач / вопросов • Письменно, 90 мин. • Проверю примерно через 30-60 мин, в зависимости от количества участников • Если оценка не очевидна, или если в ответах что-то непонятно, то потом еще м.б. устные вопросы • Баллы льготы • 16 допуск • 24 -1 задача/вопрос • 32 -2 • 40 -3 • 48 -3 + можно пользоваться любыми материалами • 56 -4 + можно пользоваться любыми материалами • 64 -5 + можно пользоваться любыми материалами
Про экзамен – сроки, место 22 мая – 10:00Сбор у баобаба. Для тех, кто придет позже – будет объявление на расписании 3 курса 26 мая – 5 параСбор в 2410. Поскольку время будет ограничено – только по предварительной записи, не больше 10 чел. Заявки принимаются до 24 мая включительно. Если будут желающие – можно 28 мая на 4 паре или 29 мая на 1 паре. Если кто-то хочет сдавать в один из этих дней – пишите И еще будет одна попытка во второй половине июня, точная дата будет известна позже
Задачи на 5 мая Язык С++ 4
template <class T, int maxsize=100> class fixed_queue { T s[maxsize]; int first;// Номер первого эл-та int last;// Номер последн. эл-та int size;// Количество эл-тов public: fixed_ queue():first(0), last(maxsize-1),size(0) {} void push(const T& x) { if ( size == maxsize ) throw "overflow"; size++; last = (last + 1) % maxsize; s[last] = x; } T pop() { if ( size == 0 ) throw "empty"; size--; int old_first = first; first = (first + 1) % maxsize; return s[old_first]; } }; // Пример вызова: queue<int> q; q.push(11); q.push(22); cout << q.pop(); Шаблон для очереди
perfect.h bool isPerfect(int n); perfect.cpp bool isPerfect(int n) { int sq_root = (int)sqrt((double)n); int sum = 1; for (int i = 2; i<sq_root; i++) { if (n%i == 0) sum += i + n/i; } if (n % sq_root ==0) sum += sq_root; return n == sum; } // Самый эффективный вариант bool isPerfect(int n) { return n == 6 || n == 28 || n == 496 ||n == 8128 || n == 33550336; } Совершенное число
Еще вариант // Еще вариант… namespace { const int perfects [] = { 6, 28, 496, 8128, 33550336 }; } bool isPerfect(int n) { return find(perfects, perfects + 5, n) != perfects +5; } • Или можно описать perfects, как локальную статическую переменную Язык С++
shared_string class shared_string { char* p; // lenдля краткости не используем // Воспомогaтельные методы // Поставить указатель p на // данную строку и увеличить // в ней счетчик. void set_ptr(char * newp) { p = newp; (*newp)++; } // Уменьшить счетчик в строке, // на которую указывает p. // Если надо, удалить строку. void drop_ptr() { (*p)--; if (*p == 0) { cout << "Deleting " << p + 1; delete [] p; } } public: Язык С++ 8
shared_string - продолжение shared_string(const char* s = "") { p = new char[strlen(s)+2]; *p = 1; strcpy(p + 1, s); } ~shared_string() { drop_ptr(); } shared_string(const shared_string& from) { set_ptr(from.p); } shared_string& operator= (const shared_string& from) { if (p != from.p) { drop_ptr(); set_ptr(from.p); } return *this; } void print() const { cout << p+1; } }; // Конец определения класса Язык С++ 9
Задачи на 12 мая Язык С++ 10
double integral( double (*f)(double), double a, double b) { // Метод трапеций double h = (b-a)/100; // Шаг double sum = (f(a)+f(b))*h/2; for (double x=a+h; x<b; x+=h) { sum += f(x)*h; } return sum; } // Пример вызова: double cube(double x) { return x*x*x; } ... cout << integral(cube, 0, 3); Интеграл
#include <algorithm> … int sumdig(int n) { int sum = 0; while(n != 0) { sum += n % 10; n /= 10; } return sum; } bool cmp_sumdig(int i, int j) { return sumdig(i) < sumdig(j); } // Пример использования vector<int> v; … sort(v.begin(), v.end(), cmp_sumdig); Сортировка с помощью sort
Сортировка с помощью multimap #include <map> … multimap<int, int> m; vector<int>::iterator q; for (p = v.begin(); p != v.end(); p++) { m.insert(make_pair(sumdig(*p), *p));// Заносим в m пары }// сумма цифр число multimap<int, int>::iterator q; for (q = m.begin(); q != m.end(); q++) {// Печатаем числа в cout << q->second << " "; // порядке возрастания } // ключей
template <class T> class numeric_limits { public: static T max(); // Достаточно объявления. // Описание можно не задавать, // все равно оно не потребуется }; // Специализации inline int numeric_limits<int>::max() { return 0x7FFFFFFF; } inline unsigned numeric_limits<unsigned>::max() { return 0xFFFFFFFF; } inline short numeric_limits<short>::max() { return 0x7FFF; } … и т.д. … // Примеры использования cout << numeric_limits<int>::max(); cout << numeric_limits<unsigned>::max(); cout << numeric_limits<short>::max(); numeric_limits
Прием «Trait» – класс свойств В numeric_limits задается, в некотором смысле, функция – с типом связывается число int 0x7FFFFFFF unsigned 0xFFFFFFFF … и т.д. … • Прием: если надо с классами связать значения (числа, другие типы и т.д.), это удобно делать примерно как в numeric_limits • Общий шаблон + специализации • Связываемое значение задается, как статическая функция или константа (если это число), или как typedef (если это тип) • Такой прием называется trait (класс свойств) Основной прием при программировании шаблонов... (Если у вас непонятная проблема с шаблонами – попробуйте traits…)
Препроцессор Язык С++ 16
#define ABC 123 Заменить всюду в тексте ABC на 123 Может быть с параметрами #define SQR(x) x * x Заменить всюду в тексте SQR(что-то) на что-то * что-то Например:SQR(a[i]) a[i] * a[i] Может быть без правой части #define ABC(x) Всюду заменить ABC(что-то) на пустую строку (т.е. выкинуть). #define
Опасности (почему #define хуже inline функции) #define SQR(x) x*x • Проблема: приоритет операций SQR(x+1) x+1 * x +1 Решение: • Взять все в скобки • И аргументы взять в скобки #define SQR(x) ((x)*(x)) • Еще проблема: SQR(i++)
Вместо const #define SIZE 100 const int size = 100; (или enum) Вместо inline или template #define SQR(x) x*x template <class T>inline T sqr(T x) { return x*x; } Где не надо использовать #define
Если хотим быстро и эффективно добавлять / убирать какой-то код (для отладки) #define TRACE(x) cout << (x) TRACE(a[i]); cout << (a[i]); Когда отладим, просто напишем: #define TRACE(x) и все отладочные печати вообще исчезнут из кода Если то, что мы хотим записать в define – не функции. Длялюбителей Pascal: #define BEGIN { #define END } Когда имеет смысл использовать #define?
int numeric_limits<int>::max() { return 0x7FFFFFFF; } unsigned numeric_limits<unsigned>::max() { return 0xFFFFFFFF; } … и еще несколько очень похожих определений… // Вариант с препроцессором #define NUMLIM(type, val) \ template<> type \ numeric_limits<type>::max() \ { \ return val; \ } // Теперь несколько очень похожих // определенийзаписываются // совсем коротко NUMLIM(int, 0x7FFFFFFF) NUMLIM(unsigned, 0xFFFFFFFF) … и еще несколько вызовов NUMLIM … Когда имеет смысл использовать #define? Пример
Оператор # • # x - stringize Взять x в кавычки. #define ABC(x) #x ABC(test) "test" Удобно в отладочных макро: #define TRACE(x) cout << #x " = " << (x) TRACE( 2*a[i+j] ) cout << "2*a[i+j]" " = " << (2*a[i+j]) • Напоминание: две строчки подряд – склеиваются
## - склейкаa ## x – записать a и значение x подряд, без пробела. #define ABC(x) a ## x ## b ABC(test) atestb Пример (не убедительный…): #define MYDEFS(x) \ int i##x; \ string s##x; \ double dbl##x; \ MYDEFS(Test) int iTest; string sTest; double dblTest; Оператор ##
#if #if условие … какие-то строки … #endif Включать <какие-то строки> если выполняется условие Условие –константы, препроцессорные переменные (из #define), арифметические и логические операции #define ABC 1 … #if ABC *3 < 100 … #endif М.б. #else и #elif #if ABC == 1 … #elif ABC == 2 … #else … #endif #if
#ifdef, #ifndef • #ifdef ABC Если ABC определено в #define (все равно как) • #ifndef ABC Если ABC не определено в #define
Для разных процессоров / оперционных систем #if OS == 1 … код для Windows #elif OS == 2 … код для Unix #elif OS == 3 … код для Apple #else … код для Simbian #endif Для отладки #if DEBUG cout << a[i] << b[k]; … #endif или еще лучше #if DEBUG #define TRACE(x) cout << (x) #else #define TRACE(x) #endif Примеры использования - 1
Чтобы закомментировать большой кусок #if 0 … большой кусок кода … #endif Чтобы включить #include один раз --- abc.h ------------------------ void f(int i); extern int k; class abc { … }; ----------------------------------- #include "abc.h" … #include "abc.h" Ошибка – повторное объявление А так все будет нормально: --- abc.h ------------------------------ #ifndef ABC #define ABC void f(int i); extern int k; class abc { … }; #endif ---------------------------------------- Можно еще написать #pragma once Примеры использования - 2
RTTI (динамическая идентификация типа) Язык С++ 28
typeid Пусть у нас иерархия классов: • shape • circle • square • rhomb shape* p;// Указывает на // какую-то фигуру • Вообще-то компьютер знает, на какую фигуру указывает p (за счет таблицы виртуальных функций) • И мы можемузнать!
typeid • typeid – оператор, параметром м.б. выражение или тип (примерно как у sizeof) if (typeid(*p) == typeid(square)) Тип результата: класс type_info • В основном для того, чтобы сравнивать между собой • Метод name() – имя класса • Имеет смысл, если есть виртуальные функции • Если нет виртуальных функций– не ошибка, но нет смысла • Должна быть включена опция “Enable Runtime Type Info” • Вообще-то лучше не использовать..
Объекты - функции (функторы) Язык С++ 31
Функторы (объекты – функции) • Для классов можно переопределять operator() // Довольно бессмысленный пример.. class abc { int operator () (int i) { return i*i;} }; abc x; // x ведетсебя, как функция возведения в квадрат x(n) x.operator()(n); n*n Такие объекты, называют функторами или обьектами- функциями. Язык С++ 32
class my_sorter { public: bool operator () (int i, int j) { return i % 100< j % 100;} }; my_sorterx; x ведет себя, как функция сортировки с прошлого занятия if (x(i, j)) … sort(v.begin(), v.end(), x); // Работает! А если мы хотим сортировать по последним n цифрам ?! Идея – добавить в my_sorter поле и конструктор! my_sorter x(n);// Сортирует по n цифрам sort(v.begin(), v.end(), x); // Или можно так: sort(v.begin(), v.end(), my_sorter(n));// Создается временный// обьект my_sorter Функторыдля сортировки Язык С++ 33
Задачи на 19 мая Язык С++ 34
Задачи на 19 мая - 1 • Написать макро ASSERT(условие). • Во время выполнения, если условие не выполняется, должно быть напечатано что-то вроде:"Сondition <текст условия> failed“. • Если условие выполняется, ничего не должно печататься. • И все это должно быть определено с помощью #define, чтобы потомвесь генерируемый в ASSERT код легко можно было убрать. Пример использования: ASSERT(a[i] > 0) Если действительно a[i] больше 0- ничего не происходит, иначе печатается сообщение об ошибке • Подсказка: схема решения какая-то такая:#define ASSERT(…) \ if (…) cout << … (где вместо многоточий вам надо что-то вписать).Продолжение на следующем слайде Язык С++ 35
Задачи на 19 мая - 2 • Таблица ошибок • Пусть у меня в программе есть таблица сообщений об ошибках с номерами ошибок. Например: map<int, string> errors; errors[1] = “Какая-то проблема"; errors[2] = “Все плохо.."; errors[3] = “У вас все неправильно"; … и еще много ошибок … Написать макро, чтобы этот код выглядел так: ERROR_TABLE ERROR(1, “Какая-то проблема“) ERROR(2, “Все плохо..“) ERROR(3, “У вас все неправильно“) … и еще много ошибок … Т.е. надо написать определения ERROR_TABLE и ERROR такие, чтобы ERROR_TABLE превращалось в map<int, string> errors;, ERROR(1, “Какая-то проблема“) превращалось в errors[1] = “Какая-то проблема"; и т.д. Продолжение на следующем слайде Язык С++ 36
Задачи на 19 мая – 2 • Дан вектор CShape*. Сколько среди этих фигур квадратов? • Написать my_sorter, который позволяет сортировать по последним n цифрам (см. последний слайд перед задачами) • Написать шаблон sumpos с одного из предыдущих занятий так, чтобы тип результата определялся таким правилом: • Если T::value_type – целое число любого типа (int,long, short), то результат sumpos д.б. long • Если T::value_type – вещественное число любого типа (float, double) – то результат sumpos д.б. double Подсказка 1: Я бы советовал описать trait, который всем целым типам ставит в соответствие long, а всем вещественным – double Подсказка 2: Это, видимо, должно быть что-то похожее на numeric_limits, но внутри - typedef Язык С++ 37