Про экзамен
DESCRIPTION
Про экзамен. Про экзамен – как он будет проходить, льготы за баллы и т.д. 10 задач / вопросов Письменно, 90 мин. Проверю примерно через 30- 6 0 мин, в зависимости от количества участников Если оценка не очевидна, или если в ответах что-то непонятно , то потом еще м.б. устные вопросы - PowerPoint PPT PresentationTRANSCRIPT
Про экзамен
Про экзамен – как он будет проходить, льготы за баллы и т.д. 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.hbool isPerfect(int n);
perfect.cppbool 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, как локальную статическую переменную
Язык С++ 7
shared_stringclass 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);
Сортировка с помощью sort#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);
Сортировка с помощью 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 << " "; // порядке возрастания} // ключей
numeric_limits template <class T>class numeric_limits {public:
static T max();// Достаточно объявления.// Описание можно не задавать,// все равно оно не потребуется
};
// Специализации
inline int numeric_limits<int>::max(){
return 0x7FFFFFFF;}
inline unsignednumeric_limits<unsigned>::max()
{return 0xFFFFFFFF;
}
inline shortnumeric_limits<short>::max()
{return 0x7FFF;
}
… и т.д. …
// Примеры использованияcout << numeric_limits<int>::max();cout << numeric_limits<unsigned>::max();cout << numeric_limits<short>::max();
Прием «Trait» – класс свойствВ numeric_limits задается, в некотором смысле, функция – с типом
связывается число int 0x7FFFFFFF unsigned 0xFFFFFFFF … и т.д. …
Прием: если надо с классами связать значения (числа, другие типы и т.д.), это удобно делать примерно как в numeric_limits
Общий шаблон + специализации Связываемое значение задается, как статическая функция
или константа (если это число), или как typedef (если это тип)
Такой прием называется trait (класс свойств)
Основной прием при программировании шаблонов... (Если у вас непонятная проблема с шаблонами – попробуйте
traits…)
Препроцессор
Язык С++ 16
#define #define ABC 123
Заменить всюду в тексте ABC на 123
Может быть с параметрами#define SQR(x) x * x Заменить всюду в тексте SQR(что-то) на что-то * что-тоНапример: SQR(a[i]) a[i] * a[i]
Может быть без правой части
#define ABC(x)
Всюду заменить ABC(что-то) на пустую строку (т.е. выкинуть).
Опасности (почему #define хуже inline функции)#define SQR(x) x*x
Проблема: приоритет операций
SQR(x+1) x+1 * x +1
Решение: Взять все в скобки И аргументы взять в скобки
#define SQR(x) ((x)*(x))
Еще проблема:SQR(i++)
Где не надо использовать #define Вместо 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?1. Если хотим быстро и
эффективно добавлять / убирать какой-то код (для отладки)
#define TRACE(x) cout << (x)
TRACE(a[i]); cout << (a[i]);
Когда отладим, просто напишем:
#define TRACE(x)
и все отладочные печати вообще исчезнут из кода
2. Если то, что мы хотим записать в define – не функции.
Для любителей Pascal:
#define BEGIN {#define END }
Когда имеет смысл использовать #define? Примерint numeric_limits<int>::max(){
return 0x7FFFFFFF;}
unsignednumeric_limits<unsigned>::max()
{return 0xFFFFFFFF;
}
… и еще несколько очень похожих определений…
// Вариант с препроцессором#define NUMLIM(type, val) \template<> type \
numeric_limits<type>::max() \{ \
return val; \}
// Теперь несколько очень похожих// определений записываются// совсем коротко
NUMLIM(int, 0x7FFFFFFF)NUMLIM(unsigned, 0xFFFFFFFF)
… и еще несколько вызовов NUMLIM …
Оператор # # 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
#if условие … какие-то строки …
#endif
Включать <какие-то строки> если выполняется условие
Условие – константы, препроцессорные переменные (из #define), арифметические и логические операции
#define ABC 1…
#if ABC *3 < 100…
#endif
М.б. #else и #elif
#if ABC == 1…
#elif ABC == 2…
#else…
#endif
#ifdef, #ifndef #ifdef ABC
Если ABC определено в #define (все равно как)
#ifndef ABC
Если ABC не определено в #define
Примеры использования - 11. Для разных процессоров /
оперционных систем
#if OS == 1… код для Windows
#elif OS == 2 … код для Unix#elif OS == 3 … код для Apple#else … код для Simbian#endif
2. Для отладки
#if DEBUG cout << a[i] << b[k]; …#endif
или еще лучше
#if DEBUG#define TRACE(x) cout << (x)
#else#define TRACE(x)
#endif
Примеры использования - 23. Чтобы закомментировать
большой кусок
#if 0… большой кусок кода …
#endif
4. Чтобы включить #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
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_sorter x;
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 мая - 11. Написать макро ASSERT(условие).
Во время выполнения, если условие не выполняется, должно быть напечатано что-то вроде: "Сondition <текст условия> failed“.
Если условие выполняется, ничего не должно печататься. И все это должно быть определено с помощью #define, чтобы потом весь
генерируемый в ASSERT код легко можно было убрать.
Пример использования:ASSERT(a[i] > 0)
Если действительно a[i] больше 0 - ничего не происходит, иначе печатается сообщение об ошибке
Подсказка: схема решения какая-то такая:
#define ASSERT(…) \ if (…) cout << …
(где вместо многоточий вам надо что-то вписать).
Продолжение на следующем слайдеЯзык С++ 35
Задачи на 19 мая - 22. Таблица ошибок
Пусть у меня в программе есть таблица сообщений об ошибках с номерами ошибок. Например:
map<int, string> errors;errors[1] = “Какая-то проблема";errors[2] = “Все плохо..";errors[3] = “У вас все неправильно";
… и еще много ошибок …
Написать макро, чтобы этот код выглядел так:
ERROR_TABLEERROR(1, “Какая-то проблема“)ERROR(2, “Все плохо..“)ERROR(3, “У вас все неправильно“)
… и еще много ошибок …
Т.е. надо написать определения ERROR_TABLE и ERROR такие, чтобы ERROR_TABLE превращалось в map<int, string> errors;, ERROR(1, “Какая-то проблема“) превращалось в errors[1] = “Какая-то проблема"; и т.д.
Продолжение на следующем слайде
Язык С++ 36
Задачи на 19 мая – 2 3. Дан вектор CShape*. Сколько среди этих фигур квадратов?
4. Написать my_sorter, который позволяет сортировать по последним n цифрам (см. последний слайд перед задачами)
5. Написать шаблон 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