1 / 45

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

Д.з. на 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]; // Отводим временный массив символов.

dustin
Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

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

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

  4. Задачи на 14 апреля Язык С++ 4

  5. itoa_oct void 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; Язык С++ 5 5

  6. itoa_oct –вариантыинтерфейса • Результат – строка string itoa_oct(int n) { char buff[20]; // Можно 12… заполняем buff,как напредыдущем слайде … return string(buff); } // Пример вызова cout << itoa_oct(i); Можно сразу заполнять с конца, от buff+19 ! Язык С++ 6 6

  7. 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

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

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

  10. Задача 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_; } } Язык С++ 10 10

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

  12. Задача 5: Sierpinski - продолжение Еще способ: с помощью случайной последовательности точек Язык С++ 12

  13. Доп.задачи про строки Язык С++ 13

  14. Задача 1: strcpy // Через for void 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

  15. Задача 1: strcpy - продолжение // Самое короткое решение void strcpy(char* to, const char* from) { while (*to++ = *from++); } Язык С++ 15

  16. Задача 2:reverse void reverse (char* str) { char* p = str; char* q = str + strlen(str) – 1;// Последний символ for (;p < q; p++, q--) { // Меняем местами chartmp = *p; *p = *q; *q = tmp; } } Язык С++ 16

  17. Еще про ассоциативные контейнеры Язык С++ 17

  18. 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

  19. Алгоритмы STL – пока только самые простые Язык С++ 19

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

  21. Алгоритмы STL • #include <algorithm> • Весь интерфейс алгоритмов - через итераторы Схема: Контейнеры  Итераторы  Алгоритмы "Алгоритмы и контейнеры хорошо работают вместе, потому что ничего не знают друг о друге" Язык С++ 21

  22. Еще пример - sort #include <algorithm> … vector<int> v; … // Заполняем v sort(v.begin(), v.end()); … deque<double> d; … // Заполняем d sort(d.begin(), d.end()); • Замечание: sort работает только для vector и deque Язык С++ 22

  23. Еще пример - accumulate • accumulate – найти сумму #include <numeric>// Не в <algorihtm> !… vector<int> v; … Заполняем v … int sum = accumulate(v.begin(), v.end(), 0); // Ищем сумму Язык С++ 23

  24. Сложные (более-менее) алгоритмы sort binary_search merge max_element, min_elementmax_element(v.begin(), v.end()); возвращает итератор random_shuffle … и еще несколько… Очень простые алгоритмы accumulate reverse copy find fill – заполнить значением … и еще много … Еще некоторые возможности через несколько занятий Подробнее об алгоритмах

  25. Программы для Windows - продолжение Язык С++ 25

  26. Венгерская нотация Charles Simonyi iAbc – целая переменная bAbc – логическая переменная pAbc – указатель sAbc - строка CAbc – класс m_iAbc – поле (целое) m_pAbc – поле (указатель) Язык С++ 26

  27. Классы в MFC можно разделить на такие группы: Классы, которые используются непосредственно CPoint – точка (x, y) CRect – прямоугольник CPen, CBrush, CFont – объекты для рисования (перо, кисть, шрифт) Классы, которые используются, как базовые классыCWnd -окно CView –окно приложения - определяем C…View - переопределям OnDraw Некоторые классы используются и непосредственно, и как базовые CButton – кнопка. Язык С++ 27

  28. Файлы, из которых состоит MFC приложение • Остальные файлы, как правило, можно не смотреть. Часто нужно менять классы: CAbcView – окнодля вывода CAbcApp – ‘приложение’ – действия при начале/конце работы, место для глобальных переменных и т.д. CAbcDoc – будет позже.. Язык С++ 28

  29. Особенности рисования в Windows программах OnDraw вызывается каждый раз, когда надо изобразить окно или часть окна Следовательно: Рисование должно делаться по возможности быстро Желательно никаких операций ввода/вывода, сложных расчетов и т.д. Еще следствия дальше… Язык С++ 29

  30. Пример – программа Circles Картины из кружков. Новые кружки появляются при щелчке мышью Язык С++ 30

  31. Как что-то поменять в окне? Обработка событий. Как добавить реакцию на событие (click)? Добавляем фунцию – обработчик сообщения (инструкции на сайте). Появляется: void CirclesView::OnLButtonDown(UINT nFlags, CPoint point) { … что надо делать при щелчке левой кнопкой … } Язык С++ 31

  32. Как что-то поменять в окне? Попытка 1 (наеправильная) Что делать при обработке события, чтобы поменять картинку? void CirclesView::OnLButtonDown(UINT nFlags, CPoint point){ …откуда то взяли pDC … pDC->Ellipse(point.x – 10, point.y – 10,// Рисуем кружок point.x + 10, point.y + 10); } Плохо: картинка пропадет при перерисовке. Язык С++ 32

  33. 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); } OnLButtonDown: добавляем круг m_circles.push_back(point); Плохо: При щелчке ничего не будет изменяться. Как что-то поменять в окне. Попытка 2 (почти правильная). • Мы должны всегда быть готовы перерисовать картинку • Значит, все данные об изображении должны храниться в памяти. • Храним информацию о картинке в CCirclesView class CCirclesView { … vector<CPoint> m_circles; • Рисование очень простое Язык С++ 33

  34. Invalidate() – запрос на перерисовку окна. OnLButtonDown: добавляем круг (Правильный вариант) void CCirclesView::OnLButtonDown( UINT nFlags, CPoint point) { m_circles.push_back(point); Invalidate();// Запрос на } // перерисовку Схема обработки сообщения: При обработке сообщения, как правило, надо: Поменять информацию о картинке Сообщить системе, что надо перерисовать картинку (Invalidate()) Замечания: Изображение моргает… InvalidateRect и т.д. Обычно пишут сложнее – на следующем занятии (Document/View) Invalidate. Как что-то поменять в окне. Теперь правильно (хотя можно и улучшить) Язык С++ 34

  35. Шаблоны функций Язык С++ 35

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

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

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

  39. Порядок подбора функции double x; inti; max(x, i); // Ошибка Порядок подбора функции Обычная функция, без преобразований Шаблон, без преобразований Обычная функция, с преобразованиями Никогда: шаблон с преобразованиями! Что же делать? max(x, (double)i) max<double>(x, i) Язык С++ 39

  40. Что будет, если тип "не подходит" шаблону? complex c1, c2; max(c1, c2) // Ошибка: оператор< не определен Диагностика м.б. не очень понятная concepts в C++ 0x time t1, t2; max(t1, t2) ОК, если задать оператор < Язык С++ 40

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

  42. Замечания Может увеличится размер программы (code bloat) Обычно часто используете и редко пишете свои шаблоны. Язык С++ 42

  43. Задачи на 28 апреля Язык С++ 43

  44. Задачи на 28 апреля Для программы Circles реализовать удаление кружков (например, правой кнопкой) * Для программы Circles реализовать перетаскивание кружков с места на место. Шаблон функции swp, которая меняет местами два объекта одного типа.double x = 1.1, y = 2.2;swp(x, y);cout << x << y; // 2.2 1.1(Замечание: вообще-то лучше бы назвать ее swap, но такая функция уже есть стандартная). * Специализация swp для mystring (т.е. того string, который мы писали).string s1 = "abc";strings2 = "klm";swp(s1, s2);// klm abcПояснение: swp из пункта 3 будет, скорее всего, работать и для строк. Зачем же его тогда специализировать? Дело в том, что можно написать специализацию, которая работает гораздо быстрее(Подсказка: просто поменять местами отдельно указатели и отдельно длины). Язык С++ 44

  45. Задачи на 28апреля Еще подсказка: если хотите, для простоты можете объявить все поля string как public. Это немного упростит задачу. Опишите функцию, которая для данного вектора целых чисел ищет сумму всех его элементов, кроме максимального и минимального.(Будем для простоты считать, что и максимальный и минимальный встречаются в векторе только один раз). Если получится, пожалуйста, решите эту задачу используя стандартные алгоритмы.(Т.е. желательно самим никаких циклов не писать) Язык С++ 45

More Related