Д.з. на 14 апреля

Preview:

DESCRIPTION

Д.з. на 14 апреля. Язык С++. 1. Задача 1: substr – с временным массивом. class string { ... string substr(int from, int len) const; // const !!  }; string string::substr(int from, int len) const { char* tmp = new char[len+1]; // Отводим временный массив символов. - PowerPoint PPT Presentation

Citation preview

Д.з. на 14 апреля

Язык С++ 1

Задача 1: substr – с временным массивомclass string {

...string substr(int from, int len) const; // const !!

}; string string::substr(int from, int len) const{

char* tmp = new char[len+1]; // Отводим временный массив символов.for (int i=0; i<len; i++) // Копируем туда подстроку. tmp[i] = str[i+from];tmp[len] = '\0';

string res(tmp); // Создаем строку-результатdelete [] tmp; // Теперь tmp можно удалитьreturn res;

}

Язык С++ 2

Задача 1: substr – с доп. конструктором// Вспомогательный конструктор – создает строку данной длиныstring::string(const char* s, int num) :

len(num){

p = new char[num + 1];for (int i = 0; i < num; i++)p[i] = s[i];p[num] = '\0';

}

// Теперь substr пишется _очень_ простоstring string::substr(int from, int num) const{

return string(p + from, num);}

Язык С++ 3

Задачи на 14 апреля

Язык С++ 4

itoa_octvoid itoa_oct(char* s, int n){

// Сначала ищем, где будет конец// строкиchar* p = s;int n1 = n;while (n1 > 0) { p++; // В цикле делим на 8 и n1 /= 8; // сдвигаем указатель.}

*p = '\0';// Сразу ставим '\0' // на конце

// Пишем цифры в обратном // порядке.

// Цикл похож на первый, но // теперь еще пишем цифры.n1 = n;while (n1 > 0) { p--; *p = n1 % 8 + '0'; n1 /= 8;}

}

// Пример вызова:char s[20]; int i;cin >> i;itoa_oct(s, i);cout << s;

Язык С++ 55

itoa_oct – варианты интерфейса Результат – строка

string itoa_oct(int n){

char buff[20]; // Можно 12… заполняем buff, как на предыдущем слайде …return string(buff);

}

// Пример вызоваcout << itoa_oct(i);

Можно сразу заполнять с конца, от buff+19 !Язык С++ 66

itoa_oct – плохие варианты интерфейса char* + динамическая память

char* itoa_oct(int n){

char* p = new char[…]; … заполняем …return p;

}

cout << itoa_oct(i);// Утечка

памяти

очень плохо: char* + локальная память

char* itoa_oct(int n){

char buff[20]; … заполняем …return buff;

}

Указатель на несуществующую память!

Язык С++ 7

Телефонная книга class person_info {public:

long phone; // Телефонstring address; // Адрес

person_info(long ph = 0, const string& addr = "") :

phone(ph), address(addr){} // Лучше описать к-р

}; // по умолчанию

// Телефонная книгаmap<string, person_info> pb;

// Пример заполнения

pb["Иванов"] = person_info(3223322, "Липовая ул. 1");

pb["Петров"] = person_info( 2991234, "Невский пр. 22");

// Пример использования

cout << pb["Иванов"].address << ", " << pb["Иванов"].phone;

// Или так более эффективно

p = pb.find("Иванов");cout << p->second.address << ", " << p->second.phone;

Задача 1: Частотный словарьmap<string, int> freq;string s;

… открываем файл …

while (f >> s) { // Читаем словоfreq[s]++; // Увеличиваем счетчик (или можно find и insert)

} // Печатаем ответ

map<string, int>::iterator p;for (p = freq.begin(); p != freq.end(); p++) {

cout << p->first << " - " << p->second << "\n";}

Задача 4: треугольникиvoid CTrianglesView::OnDraw(CDC* pDC){

// Начальные значения – примерно// равносторонний преугольникint x1=0, y1=0, x2=1000, y2=0, x3=500, y3=866;

 // Цикл "Пока не получится очень// маленький треугольник"while ((x1-x2)*(x1-x2)+ (y1-y2)*(y1-y2)>=2 ) { // Рисуем треугольник pDC->MoveTo(x1, y1); pDC->LineTo(x2, y2); pDC->LineTo(x3, y3); pDC->LineTo(x1, y1);

 

// Пересчитываем // координаты точек – теперь // нам нужны середины сторон int x1_ = (x2+x3)/2,

y1_ = (y2+y3)/2, x2_ = (x1+x3)/2, y2_ = (y1+y3)/2; x3_ = (x1+x2)/2, y3_ = (y1+y2)/2;

x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_; x3 = x3_; y3 = y3_; }}

 Язык С++ 1010

Задача 5: Sierpinski// Воспомогательная рекурсивная функцияvoid DrawSierpinski(CDC* pDC, int x1, int y1, int x2, int y2, int x3, int y3){

// Если треугольник очень маленький - ничего не делаемif ( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<=2 ) return;// Рисуем треугольникpDC->MoveTo(x1, y1); pDC->LineTo(x2, y2);pDC->LineTo(x3, y3); pDC->LineTo(x1, y1);// Считаем серединыint x1_ = (x2+x3)/2, y1_ = (y2+y3)/2, x2_ = (x1+x3)/2, y2_ = (y1+y3)/2, x3_ = (x1+x2)/2, y3_ = (y1+y2)/2;// Вызываем функцию рекурсивно для трех маленьких треугольниковDrawSierpinski(pDC, x1, y1, x2_, y2_, x3_, y3_);DrawSierpinski(pDC, x1_, y1_, x2_, y2_, x3, y3);DrawSierpinski(pDC, x1_, y1_, x2, y2, x3_, y3_);

}

Язык С++ 11

11

Задача 5: Sierpinski - продолжение Еще способ: с помощью

случайной последовательности точек

Язык С++ 12

Доп.задачи про строки

Язык С++ 13

Задача 1: strcpy// Через forvoid strcpy(char* to, const char* from){

int i;for (i=0; from[i]!='\0'; i++)

to[i] = from[i];to[i] = '\0';

}

Замечание:На самом деле strcpy имеет тип char* и возвращает to, как результат. Но мы в примерах для краткости этого не делаем.

// С использованием указателей// (и, для разнообразия, через // while)void strcpy(char* to, const char*

from){

const char* p1= from;char* p2 = to;

 while (*p1 != '\0') {

*p2 = *p1;p1++; p2++;

}p2 = '\0';

}

Язык С++ 14

Задача 1: strcpy - продолжение// Самое короткое решение

void strcpy(char* to, const char* from){

while (*to++ = *from++);}

Язык С++ 15

Задача 2: reversevoid reverse (char* str){

char* p = str;char* q = str + strlen(str) – 1; // Последний символfor (;p < q; p++, q--) { // Меняем местами char tmp = *p; *p = *q;

*q = tmp;}

}

Язык С++ 16

Еще про ассоциативные

контейнеры

Язык С++ 17

multiset и multimap - обзор#include <set>…multiset<int> s;

s.insert(6);s.insert(2);s.insert(9);s.insert(6);

for(multiset<int>::iterator p = s.begin(); p!=s.end(); p++) cout << *p << " ";

// 2 6 6 9

#include <map>…multimap<double, int> m;

m.insert(make_pair(4.5, 2));m.insert(make_pair(4.5, 8));

[] не работает find возвращает первую пару

Язык С++ 18

Алгоритмы STL – пока только самые

простые

Язык С++ 19

Пример reverse(итератор начала, итератор конца);

#include <algorithm>…vector<int> v;

… Заполняем v …reverse(v.begin(), v.end());

list<double> l;… Заполняем l …

reverse(l.begin(), l.end());

string s = “abcdef”;reverse(s.begin(), s.end());

Язык С++ 20

Алгоритмы STL #include <algorithm>

Весь интерфейс алгоритмов - через итераторы

Схема: Контейнеры Итераторы Алгоритмы

"Алгоритмы и контейнеры хорошо работают вместе, потому что ничего не знают друг о друге"

Язык С++ 21

Еще пример - sort#include <algorithm>…vector<int> v;… // Заполняем vsort(v.begin(), v.end());…deque<double> d;… // Заполняем dsort(d.begin(), d.end());

Замечание: sort работает только для vector и deque

Язык С++ 22

Еще пример - accumulate accumulate – найти сумму

#include <numeric> // Не в <algorihtm> !…

vector<int> v;

… Заполняем v …

int sum = accumulate(v.begin(), v.end(), 0); // Ищем сумму

Язык С++ 23

Подробнее об алгоритмах Сложные (более-менее)

алгоритмы sort binary_search merge max_element, min_element

max_element(v.begin(), v.end());возвращает итератор

random_shuffle … и еще несколько…

Очень простые алгоритмы accumulate reverse copy find fill – заполнить значением … и еще много …

Еще некоторые возможности через несколько занятий

Программы для Windows -

продолжение

Язык С++ 25

Венгерская нотацияCharles Simonyi

iAbc – целая переменная bAbc – логическая

переменная pAbc – указатель sAbc - строка CAbc – класс m_iAbc – поле (целое) m_pAbc – поле (указатель)

Язык С++ 26

Классы в MFC можно разделить на такие группы:1. Классы, которые

используются непосредственно

CPoint – точка (x, y)CRect – прямоугольникCPen, CBrush, CFont – объекты для рисования (перо, кисть, шрифт)

2. Классы, которые используются, как базовые классы

CWnd - окно

CView – окно приложения - определяем C…View - переопределям OnDraw

3. Некоторые классы используются и непосредственно, и как базовые

CButton – кнопка.

Язык С++ 27

Файлы, из которых состоит MFC приложениеЧасто нужно менять классы: CAbcView – окно для вывода CAbcApp – ‘приложение’ –

действия при начале/конце работы, место для глобальных переменных и т.д.

CAbcDoc – будет позже..

Язык С++ 28

Остальные файлы, как правило, можно не смотреть.

Особенности рисования в Windows программах OnDraw вызывается каждый раз, когда надо изобразить окно

или часть окна

Следовательно: Рисование должно делаться по возможности быстро

Желательно никаких операций ввода/вывода, сложных расчетов и т.д.

Еще следствия дальше…

Язык С++ 29

Пример – программа Circles Картины из кружков. Новые кружки появляются

при щелчке мышью

Язык С++ 30

Как что-то поменять в окне? Обработка событий. Как добавить реакцию на событие (click)?

Добавляем фунцию – обработчик сообщения (инструкции на сайте). Появляется:

void CirclesView::OnLButtonDown(UINT nFlags, CPoint point) {

… что надо делать при щелчке левой кнопкой …}

Язык С++ 31

Как что-то поменять в окне? Попытка 1 (наеправильная) Что делать при обработке события, чтобы поменять картинку?

void CirclesView::OnLButtonDown(UINT nFlags, CPoint point){ … откуда то взяли pDC …

pDC->Ellipse(point.x – 10, point.y – 10, // Рисуем кружок point.x + 10, point.y + 10); }

Плохо: картинка пропадет при перерисовке.

Язык С++ 32

Как что-то поменять в окне. Попытка 2 (почти правильная). Мы должны всегда быть

готовы перерисовать картинку

Значит, все данные об изображении должны храниться в памяти.

1. Храним информацию о картинкев CCirclesView

class CCirclesView { … vector<CPoint> m_circles;

2. Рисование очень простое

void OnDraw(CDC* pDC){ for (int i = 0; i < m_circles.size();

i++) { pDC->Ellipse(m_circles[i].x – 10, m_circles[i].y – 10, m_circles[i].x + 10, m_circles[i].y + 10);}

3. OnLButtonDown: добавляем круг

m_circles.push_back(point);

Плохо: При щелчке ничего не будет изменяться.

Язык С++ 33

Invalidate. Как что-то поменять в окне. Теперь правильно (хотя можно и улучшить)Invalidate() – запрос на перерисовку

окна.

OnLButtonDown: добавляем круг (Правильный вариант)

void CCirclesView::OnLButtonDown( UINT nFlags, CPoint point)

{ m_circles.push_back(point); Invalidate(); // Запрос на } // перерисовку

Схема обработки сообщения:

При обработке сообщения, как правило, надо: Поменять информацию

о картинке Сообщить системе, что

надо перерисовать картинку (Invalidate())

Замечания: Изображение моргает…

InvalidateRect и т.д. Обычно пишут сложнее –

на следующем занятии (Document/View)

Язык С++ 34

Шаблоны функций

Язык С++ 35

Зачем нужны шаблоны?int max(int x, int y){ if (x < y) return y; else return x;}

... тоже для double ... ... тоже для short ... ... тоже для time ...

и т.д.

template <class T> Т max(T x, T y){ if (x < y) return y; else return x;}

// Пример вызоваint i, j, k;...k = max(i, j); Генерируется: int max(int x, int y) { if (x<y) …}

Язык С++ 36

Синтаксис шаблонов функций, замечанияdouble x, y, z;...z = max(x, y);

Генерируется: double max(double x, double y) { if (x<y) … }

Синтаксис

template <параметры> <описание функции>

Замечания:

Параметров м.б. несколько:

template <class T1, class T2> void copy(T1* to, T2* from, int n) { for(int i = 0; i < n; i++) to[i] = from[i]; }

double a[100]; int b[100]; copy(a, b, 100);

typename T - то же, что class T

Язык С++ 37

Генерация шаблона (instantiation) Параметры шаблона должны

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

int i,j;max(i, j) T == int

М.б. не напрямую, через указатели, ссылки и т.д.

double a[100]; int b[100];copy(a, b, 100);

T1 = double, T2 = int

Так будет ошибка:

template <class T>void f(int i) // T нет в параметрах{ T x;

… }

f(5); // Could not deduce.. // Не вывести тип T

Можно явно задавать параметрf<double>(5); // OK

Для функций - редко.Язык С++ 38

Порядок подбора функцииdouble x; int i;max(x, i);

// Ошибка

Порядок подбора функции Обычная функция, без

преобразований Шаблон, без преобразований Обычная функция, с

преобразованиями

Никогда: шаблон с преобразованиями!

Что же делать?

max(x, (double)i)

max<double>(x, i)

Язык С++ 39

Что будет, если тип "не подходит" шаблону? complex c1, c2;

max(c1, c2) // Ошибка: оператор< не определен

Диагностика м.б. не очень понятнаяconcepts в C++ 0x

time t1, t2;max(t1, t2)

ОК, если задать оператор <

Язык С++ 40

Перегрузка шаблона функции. char s1[] = "abc";

char s2[] = "klm";cout << max(s1, s2); // Не то сравнение!

Специализацияchar* max(char* x, char* y){ if (strcmp(x,y) <0)

return x; else

return y;}

Тут было обсуждение того, почему такое определение max для char плохо с точки зрения поддержки константности (константных строк и т.д.), и как это можно исправить.

Язык С++ 41

Замечания Может увеличится размер программы (code bloat)

Обычно часто используете и редко пишете свои шаблоны.

Язык С++ 42

Задачи на 28 апреля

Язык С++ 43

Задачи на 28 апреля1. Для программы Circles

реализовать удаление кружков (например, правой кнопкой)

2. * Для программы Circles реализовать перетаскивание кружков с места на место.

3. Шаблон функции swp, которая меняет местами два объекта одного типа. double x = 1.1, y = 2.2; swp(x, y); cout << x << y; // 2.2 1.1

(Замечание: вообще-то лучше бы назвать ее swap, но такая функция уже есть стандартная).

4. * Специализация swp для mystring (т.е. того string, который мы писали).

string s1 = "abc"; string s2 = "klm"; swp(s1, s2); // klm abc

Пояснение: swp из пункта 3 будет, скорее всего, работать и для строк. Зачем же его тогда специализировать? Дело в том, что можно написать специализацию, которая работает гораздо быстрее

(Подсказка: просто поменять местами отдельно указатели и отдельно длины).

Язык С++ 44

Задачи на 28 апреляЕще подсказка: если хотите, для простоты можете объявить все поля string как public. Это немного упростит задачу.

5. Опишите функцию, которая для данного вектора целых чисел ищет сумму всех его элементов, кроме максимального и минимального.

(Будем для простоты считать, что и максимальный и минимальный встречаются в векторе только один раз).

Если получится, пожалуйста, решите эту задачу используя стандартные алгоритмы.(Т.е. желательно самим никаких циклов не писать)

Язык С++ 45

Recommended