45
Д.з. на 14 апреля Язык С++ 1

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

  • Upload
    dustin

  • View
    66

  • Download
    0

Embed Size (px)

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

Page 1: Д.з. на  14  апреля

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

Язык С++ 1

Page 2: Д.з. на  14  апреля

Задача 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

Page 3: Д.з. на  14  апреля

Задача 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

Page 4: Д.з. на  14  апреля

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

Язык С++ 4

Page 5: Д.з. на  14  апреля

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

Page 6: Д.з. на  14  апреля

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

string itoa_oct(int n){

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

}

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

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

Page 7: Д.з. на  14  апреля

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

Page 8: Д.з. на  14  апреля

Телефонная книга 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;

Page 9: Д.з. на  14  апреля

Задача 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";}

Page 10: Д.з. на  14  апреля

Задача 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

Page 11: Д.з. на  14  апреля

Задача 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

Page 12: Д.з. на  14  апреля

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

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

Язык С++ 12

Page 13: Д.з. на  14  апреля

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

Язык С++ 13

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

Задача 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

Page 15: Д.з. на  14  апреля

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

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

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

Язык С++ 15

Page 16: Д.з. на  14  апреля

Задача 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

Page 17: Д.з. на  14  апреля

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

контейнеры

Язык С++ 17

Page 18: Д.з. на  14  апреля

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

Page 19: Д.з. на  14  апреля

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

простые

Язык С++ 19

Page 20: Д.з. на  14  апреля

Пример 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

Page 21: Д.з. на  14  апреля

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

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

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

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

Язык С++ 21

Page 22: Д.з. на  14  апреля

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

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

Язык С++ 22

Page 23: Д.з. на  14  апреля

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

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

vector<int> v;

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

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

Язык С++ 23

Page 24: Д.з. на  14  апреля

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

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

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

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

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

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

Page 25: Д.з. на  14  апреля

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

продолжение

Язык С++ 25

Page 26: Д.з. на  14  апреля

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

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

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

Язык С++ 26

Page 27: Д.з. на  14  апреля

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

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

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

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

CWnd - окно

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

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

CButton – кнопка.

Язык С++ 27

Page 28: Д.з. на  14  апреля

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

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

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

Язык С++ 28

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

Page 29: Д.з. на  14  апреля

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

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

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

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

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

Язык С++ 29

Page 30: Д.з. на  14  апреля

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

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

Язык С++ 30

Page 31: Д.з. на  14  апреля

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

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

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

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

Язык С++ 31

Page 32: Д.з. на  14  апреля

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

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

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

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

Язык С++ 32

Page 33: Д.з. на  14  апреля

Как что-то поменять в окне. Попытка 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

Page 34: Д.з. на  14  апреля

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

окна.

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

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

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

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

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

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

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

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

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

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

Язык С++ 34

Page 35: Д.з. на  14  апреля

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

Язык С++ 35

Page 36: Д.з. на  14  апреля

Зачем нужны шаблоны?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

Page 37: Д.з. на  14  апреля

Синтаксис шаблонов функций, замечания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

Page 38: Д.з. на  14  апреля

Генерация шаблона (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

Page 39: Д.з. на  14  апреля

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

// Ошибка

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

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

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

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

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

max(x, (double)i)

max<double>(x, i)

Язык С++ 39

Page 40: Д.з. на  14  апреля

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

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

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

time t1, t2;max(t1, t2)

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

Язык С++ 40

Page 41: Д.з. на  14  апреля

Перегрузка шаблона функции. 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

Page 42: Д.з. на  14  апреля

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

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

Язык С++ 42

Page 43: Д.з. на  14  апреля

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

Язык С++ 43

Page 44: Д.з. на  14  апреля

Задачи на 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

Page 45: Д.з. на  14  апреля

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

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

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

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

Язык С++ 45