пятница, 19 ноября 2010 г.

Вопрос претенденту на вакансию "Программист C++"

На нескольких сайтах, предлагающих вакансию программиста C++, встречаются одни и те же вопросы, например, на сайте вакансий yandex. Один из них такой:
Перечислите все проблемы, которые вы видите в данном коде:


1 class Foo
2 {
3 public:
4 Foo(int j) { i=new int[j]; }
5 ~Foo() { delete i; }
6 private:
7 int* i;
8 };
9
10 class Bar: Foo
11 {
12 public:
13 Bar(int j) { i=new char[j]; }
14 ~Bar() { delete i; }
15 private:
16 char* i;
17 };
18
19
20 void main()
21 {
22 Foo* f=new Foo(100);
23 Foo* b=new Bar(200);
24 *f=*b;
25 delete f;
26 delete b;
27 }



В результате медитации, получил следующий, несовершенный код, но все же отражающий моё понимание проблем:

1 class Bar;//Добавил, чтоб в классе Foo использовать имя класса Bar
2
3 class Foo
4 {
5 public:
6 Foo(int j)
7 {
8 i=new int[j];
9 }
10 Foo() {} //Добавил, т.к. нужен конструктор по умолчанию, если бы Foo(int),
» небыло, то он бы был сгенерирован компилятором

11 ~Foo()
12 {
13 delete[] i; //Изменил, добавив [], а то удалять будет не весь массив, а
» только первый элемент массива с индексом 0, т.е. получим утечку памяти

14 }
15
16 Foo operator=(const Bar& r_)//Добавил оператор присваивания, и по идее надо
» делать глубокое копирование по членам, но для этого обеспечить доступ к полю
» Bar::i, вариантов может быть несколько

17 {
18 //На самом деле дальше код должен быть более сложный
19 delete[] i; //в общем, то надо ещё поработать с динамической памятью,
» убрать, то, что там было создано конструктором Foo(int), а то будет утечка
» памяти

20 return Foo();//сделаем так для простоты
21 }
22
23
24
25 private://Возможно надо заменить private на protected, чтоб дочерний класс мог
» обращаться к полю Foo::i

26 int* i;
27 };
28
29 class Bar: public Foo //добавил public
30 {
31 public:
32 Bar(int j)
33 {
34 i=new char[j];
35 }
36 ~Bar()
37 {
38 delete[] i; //Изменил, добавив []
39 }
40
41 private:
42 char* i;
43 };
44
45
46 int main()
47 {
48 Foo* f=new Foo(100);
49 Foo* b= new Bar(200); //Нужно в классе определить присваивание и чтоб было
» открытое наследование

50 *f=*b; //Нужно в классе определить присваивание
51 delete f;
52 delete b;
53 }



Ах, да, похоже, что надо ещё создать конструктор копирования Foo(const Foo&), надо повозится с глубоким копированием, сделать проверки в операторе присваивания, чета стало лень копать дальше.

пятница, 8 октября 2010 г.

Исчезли папки и файлы на съемном диске (flash)

Иногда подходят ко мне с проблемой, мол исчезли файлы и папки на диске. Делаю так:
Пуск - Выполнить..., набираю cmd, предположим, что съемный диск имеет имя H:\, забиваем в консоли следующее:

cd /D H:\
attrib -S -H -R *


Подробности об attrib, делаем так:

attrib /?


Интересно, что чем более удобной и технологически продвинутой становится Windows, тем больше возможностей для появления в системе вирусов. Например, файл autorun.ini в корне диска, созданный для автоматического открытия диска (запуска программ), позволяет распространять "заразу" от одного компьютера другому, путем простого подключения съемного диска.

четверг, 7 октября 2010 г.

Мета-тег от Яндекса

Добавил мета-тег от Яндекса, надеюсь, что в скором времени будет больше посещений блога, в тем более, что по некоторым оценкам, Яндекс используют как поисковую систему примерно 45% пользователей Рунета.
Добавил вот этот код проверки:

1 <meta name='yandex-verification' content='40d5e3ee817d41b6' />


Идентификатор содержит 16 символов, каждый шифрует 4 бита, 16*4=64 бита или 8 байт.
Не расточительство ли это?
Обещали проверять его наличие.

воскресенье, 26 сентября 2010 г.

Простои проект C++ с использованием wxWidgets

Понадобится кроссплатформенная утилита bakefile для поддержки генерации make-файлов и файлов-проектов для разных платформ и сред программирования. Для её использования понадобится python. Будем считать, что с установкой wxWidgets справились все. У меня, например, для этого создан командный файл build_cl.cmd в каталоге %WXWIN%\build\msw. %WXWIN% - переменная среды, содержащая путь к wxWidgets (не должен содержать пробелов). Использую, компилятор C++ идущий вместе с Microsoft Visual C++ 2005 Express Edition, установил его без IDE и MSDN, ещё установлен MS PSDK для работы.

call vcvars32
nmake -f makefile.vc MONOLITHIC=0 SHARED=0 UNICODE=1 BUILD=release
pause

В директории проекта создадим поддиректорию build, в ней создадим файл app.bkl, следующего содержания:


1 <?xml version="1.0" ?>
2 <!-- $Id$ -->
3
4 <makefile>
5
6 <!-- Путь к файлу wx.bkl, хотя можно их таскать в
۠отдельной директории с именем presets в
۠директории проекта -->

7 <include file="C:/wxWidgets-2.9.1/build/bakefiles/wxpresets/presets/wx.bkl" />
8
9 <!-- Определяем переменную BUILDDIR в стиле wxWidgets -->
10 <set-wxlike-builddir> </set-wxlike-builddir>
11
12 <exe id="app" template="wxgui">
13
14 <debug-info>off</debug-info>
15 <runtime-libs>dynamic</runtime-libs>
16
17 <!-- Здесь всякие опции для линковщика -->
18 <ldflags cond="FORMAT=='msvc'">/OPT:REF</ldflags>
19 <ldflags cond="FORMAT=='msvc'">/OPT:ICF</ldflags>
20 <ldflags cond="FORMAT=='msvc6prj'">/entry:"wWinMainCRTStartup"</ldflags>
21
22 <!-- Исходники -->
23 <sources>$(fileList('../src/*.cpp'))</sources>
24 <headers>$(fileList('../src/*.h'))</headers>
25 <win32-res>$(fileList('../src/*.rc'))</win32-res>
26 <symbian-res>$(fileList('../src/*.rss'))</symbian-res>
27
28 <!-- Здесь используемые в проекте библиотеки
۠wxWidgets -->

29 <wx-lib>core</wx-lib>
30 <wx-lib>base</wx-lib>
31 </exe>
32
33 </makefile>



Как видим, используется XML-формат. Чтобы bakefile не ругался на строки, где содержатся кириллические символы, файл должен быть в кодировке UTF-8. Имена тегов должны быть в нижнем регистре.

Для генерации makefile.vc использую командный файл, следующего содержания:

bakefile -f msvc app.bkl
call vcvars32
pause

Для сборки проекта использую командный файл, следующего содержания:

nmake /f makefile.vc WX_MONOLITHIC=0 WX_SHARED=0 WX_UNICODE=1 WX_DEBUG=0
pause


Исходники, файлы ресурсов и заголовочные файлы находятся в папке src.
В простейшем случае, там расположены следующие файлы:
app.h
app.cpp
frame.h
frame.cpp
minimal.rc
mondrian.ico
mondrian.xpm

Содержание файла app.h :

1 #include <wx/app.h>
2 #if !defined(__WXMSW__) && !defined(__WXPM__)
3 #include "mondrian.xpm"
4 #endif
5
6 #include "frame.h"
7
8 class App : public wxApp
9 {
10 public:
11 virtual bool OnInit();
12 };


Содержание файла app.cpp :

1 /// app.cpp
2 #include "app.h"
3
4 bool App::OnInit()
5 {
6 if ( !wxApp::OnInit() )
7 return false;
8
9 Frame *frame = new Frame(_T("Только фрейм"));
10 frame->Show(true);
11 return true;
12 }
13
14 IMPLEMENT_APP(App)



Содержание файла frame.h :

1 #include <wx/frame.h>
2 class Frame : public wxFrame
3 {
4 public:
5 Frame(const wxString& title);
6 private:
7 DECLARE_EVENT_TABLE()
8 };
9
10 //Идентификаторы элементов управления, которые должны реагировать на события
11 enum
12 {
13
14 };
15
16



Содержание файла frame.cpp :

1 #include "frame.h"
2
3 //Таблица событий для связи методов и идентификаторов с определенным типом
» сообщения

4 BEGIN_EVENT_TABLE(Frame, wxFrame)
5
6 END_EVENT_TABLE()
7
8 // Конструктор
9 Frame::Frame(const wxString& title)
10 : wxFrame(NULL, wxID_ANY, title)
11 {
12 SetIcon(wxICON(mondrian_xpm));
13 }
14



Содержание файла ресурсов minimal.rc :

mondrian_xpm ICON "mondrian.ico"
#include "wx/msw/wx.rc"

понедельник, 13 сентября 2010 г.

Неестественное присвоение в TextBox на VB6

Много строковое значение строковой переменной в Visual Basic 6.0 при присвоении его TextBox, не приводит к соответствующему отображению, простой установки свойства MultiLine в значение True, оказалось недостаточным. А вот такой способ работает, создавая дополнительную строку.

TexBox1.MultiLine=True
TexBox1.SelStart=Len(TextBox1.Text)
TexBox1.SelText = vbNewLine & strNewLine

Все это кажется странным.

суббота, 3 июля 2010 г.

Проверка правильности кодов банковских карт и ISIN

Вот значит, написал небольшую объектно-ориентированную программку для проверки правильности кодов, может, кому будет интересно. Конечно же, классу можно нарастить функциональности, усложнить поведение.


1 /** @FILE code_finance.cpp
2 Номер «Социальной Карты» (Москва, Россия)
3 16 цифр. Поскольку Социальные карты москвича выпускаются на основе банковских карт Visa
4 Electron Банка Москвы, номер содержит контрольное число, вычисляемое по обычным правилам для
5 16-значных банковских карт (см. ниже). 19-значный полный номер Социальной карты москвича (на
6 обороте) также содержит контрольный разряд, вычисляемый с использованием алгоритма Луна.
7
8 Номера банковских карт
9 Номера кредитных карт American Express всегда начинаются на цифру 3, VISA начинается на 4,
10 MasterCard на 5 и Maestro на 6. Алгоритм тот же, что и для «Международного идентификационного кода
11 ценной бумаги»
12
13 Международный идентификационный код ценной бумаги (ISIN)
14 Контрольные суммы вычисляются по сходному алгоритму. Правило продолжения таблицы влево (для
15 длинных номеров) и усечения её для коротких номеров очевидно.
16
17 В случае наличия в номере (коде) ISIN английских букв, каждая из них заменяется на 2 цифры,
18 представляющие собой порядковый номер буквы в латинском алфавите, увеличенный на 9 (то есть A ~ 10,
19 B ~ 11, …, Z ~ 35). Так, буквы RU заменяются на 2730.
20
21 | k16 | k15 | k14 | k13 | k12 | k11 | k10 | k9 | k8 | k7 | k6 | k5 | k4 | k3 | k2 | k1
22 ============+=====+=====+=====+=====+=====+=====+=====+====+====+====+====+====+====+====+====+====
23 Банковские | 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1
24 карты (16) |
25 |
26 Ценные | 2 1 2 1 2 1 2 1 2 1 2 1 2 1
27 бумаги (14) |
28 |
29 Банковские | 1 2 1 2 1 2 1 2 1 2 1 2 1
30 карты (13) |
31
32 Контрольная сумма. Цифры кода умножаются на коэффициенты из таблицы, если результат умножения
33 превосходит 9, то вычитаем из него 9, получившиеся числа складываем. Берём остаток от деления суммы
34 на 10. Если контрольная сумма есть 0, то номер признаётся правильным.
35
36 */

37
38 #include <string>
39 #include <iostream>
40
41 /*! \class BankingCode
42 \brief Работа над кодом карты
43
44 Наша главная задача проверить правильность номера,
45 и делать все необходимые вычисления один раз для проверяемого кода,
46 а в последующие проверки возвращать только его результат
47 */

48 class BankingCode {
49 public:
50 BankingCode() : checked_( -1) {}
51 BankingCode(std::string code): valCode_(code), checked_(-1) {}
52
53 void valCode(const std::string code) {
54 valCode_=code;
55 //Код был изменен, придется его проверять потом
56 checked_=-1;
57 }
58 std::string valCode() const {
59 return valCode_;
60 }
61
62 bool isValid() {
63 //Надо ли проверять, может уже проверено
64 if (checked_!=-1) {
65 std::cout << "Уже считали правильность" << std::endl ;
66 return checked_;// 0 - интерпритируется как false, а 1 - true
67 }
68 std::cout << "Ещё не считали правильность" << std::endl ;
69
70 int sz=valCode_.size();//Лучше хранить в переменной, а не вызывать эту функцию каждый раз
71 if(sz==16 || sz==14 || sz==13) {
72 int sumV=0;
73
74 int k[]= {2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1};//Коэффициенты
75 //Указатель, позволяющий использовать элементы массива k со сдвигом в пределах 16 эл-ов
76 int *s;
77
78 if (sz==13)
79 s=k+1;
80 else
81 s =k;
82
83 //int k[]= {1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2};//Коэффициенты
84 for(int i=sz-1; i!=-1; --i) {
85 std::cout << i << '\t' << valCode_[i] << '\t' << s[i] << '\t' << std::endl;
86 /*Попользуемс массивом коэффициентов для временного хранения данных, не пропадать
87 же памяти и цифирь получим вычитая 48 (ASCII код '0')*/

88 s[i] = (valCode_[i]-48) *s[i] ;
89 //std::cout << k[i] << std::endl;
90 //Вычитаем 9, если больше 9
91 s[i] = (s[i] >9)?(s[i]-9):(s[i]);
92 //std::cout << k[i] << std::endl;
93
94 sumV=sumV+s[i];
95 }
96 //std::cout << "=====================" << std::endl;
97 //std::cout << sumV << std::endl;
98
99 if((sumV%10)==0) {
100 checked_=1;
101 return true;
102 }
103 }
104 checked_=0;
105 return false;
106 }
107
108 private:
109 std::string valCode_;
110 int checked_;//Проверено 0 - неправильный, 1 - правильный, -1 - ещё не проверялось
111
112
113 };
114
115
116 int main(int argc,char *argv[]) {
117 /*Ну, чтоб по русски выводило в консоль, для некоторых компиляторов setlocale(0,".866") и надо
118 испльзовать std::wcout, да ещё и исходник в UTF-8*/

119 setlocale(0,"");
120
121 //Проверка на 16-значные коды
122 std::cout << "==== 16-значные коды банковских карт ====" << std::endl ;
123 BankingCode code("5610000000000001");//Известно, что это правильный 16-значный код
124 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
125 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
126 //Повторно вызываю
127 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
128 //Изменим код на неправильный
129 code.valCode("5610000000000006");
130 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
131 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
132 //Повторно вызываю
133 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
134 std::cout << "=========================================" << std::endl ;
135
136 //Проверка на 13-значные коды
137 std::cout << "==== 13-значные коды банковских карт ====" << std::endl ;
138 code.valCode("4000000000006");//Известно, что это правильный 13-значный код
139 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
140 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
141 //Повторно вызываю
142 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
143 //Изменим код на неправильный
144 code.valCode(std::string("4000000000007"));
145 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
146 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
147 //Повторно вызываю
148 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
149 std::cout << "=========================================" << std::endl ;
150
151 //Проверка на 14-значные номера ISIN (Международный идентификационный код ценной бумаги )
152 std::cout << "==== 14-значный номер банковских карт ====" << std::endl ;
153 /*RU0007661625 — ISIN акции Газпрома номиналом 5 руб.
154 Буквы RU заменяем на 2730 и получаем 14-значный номер (R ~ 27, U ~ 30)*/

155 code.valCode("27300007661625");//Известно, что это правильный 14-значный код
156 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
157 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
158 //Повторно вызываю
159 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
160 //Изменим код на неправильный
161 code.valCode(std::string("27300007661627"));
162 std::cout << "==== " << code.valCode() << " =====" << std::endl ;
163 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
164 //Повторно вызываю
165 std::cout << (code.isValid()?"Правильный код":"Неправильный код") << std::endl ;
166 std::cout << "=========================================" << std::endl ;
167
168 return 0;
169 }

пятница, 2 июля 2010 г.

Контроль правильности Штрих-кода (EAN-13, UPC-12, EAN-8 - barcode)

Где только не видно штрих-кодов. Многое, что нас окружает было когда-то произведено людьми и предназначалось для продажи, то есть кругом товары, а их надо учитывать и контролировать их движение. Для контроля надо уметь идентифицировать товары, да ещё и в удобном для считывания и обработки виде, и надо уметь проверять достоверность этих кодов.
Few programming (C):


1 /**@file isBarCode.c
2 rus: Контроль правильности Штрих-кода (Бар-кода)
3 eng: Control of the correctness of the barcode
4
5 |k13|k12|k11|k10|k9 |k8 |k7 |k6 |k5 |k4 |k3 |k2 |k1
6 =======+===+===+===+===+===+===+===+===+===+===+===+===+===
7 EAN-13 | 1 3 1 3 1 3 1 3 1 3 1 3 1
8 UPC-12 | 3 1 3 1 3 1 3 1 3 1 3 1
9 EAN-8 | 3 1 3 1 3 1 3 1
10
11 Контрольная сумма есть остаток от деления на 10 суммы из цифр номера,
12 умноженных на соответствующие коэффициенты из таблицы.
13 Если контрольная сумма есть 0, то номер признаётся правильным.
14
15 Если нужно подсчитать требуемое контрольное число для произвольного
16 номера, нужно вначале поставить «0» на крайнюю правую позицию,
17 посчитать контрольную сумму, а затем,
18 если она не равна нулю, заменить этот «0» на «10 — контрольная сумма».
19 */

20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 int is_bar_code(int cntSimbols,char* kod) {
25 //Массив коэффициентов
26 char k[]= {1,3,1,3,1,3,1,3,1,3,1,3,1};
27 int i,j,sumV=0;
28
29 if(cntSimbols==8 || cntSimbols==12 || cntSimbols==13) {
30 for(i=0,j=13-cntSimbols; i<cntSimbols; i++,j++) {
31 //Коды символов чисел отличаются на 48, типа 48='0',49='1', ...,
32 printf("%d\t%d\t%d\n",kod[i]-48,k[j],(kod[i]-48)*k[j]);
33 sumV=sumV+(kod[i]-48)*k[j];
34 }
35 return sumV%10?0:1;
36 } else {
37 return 0;
38 }
39 }
40
41 int main(int argc , char* argv[]) {
42
43 if(argc!=3) {
44 printf("Wrong number of arguments!!! \n\nThe first argument in the
» command line - \ncode for verification, type 46009333, 041689300494,
» 4600051000057\n\nThe second argument on the command line - \nthe number of
» characters in the code (8,12,13) \n\n Example:\n isBarCode.exe 46009333 8\n\n"
);
45 exit(1);
46 }
47
48 {
49 //Первый аргумент в командной строке - код для проверки, типа 46009333,
» 041689300494,4600051000057

50 char* val=argv[1];
51 int cnt=atoi(argv[2]);
52 //Второй аргумент в командной строке - число символов в коде (8,12,13)
53 printf("%s\n",is_bar_code(cnt,val)?"OK":"BAD");
54 }
55 return 0;
56 }

четверг, 1 июля 2010 г.

Раскрашиваем код для публикации в блоге (blogger.com / blogspot.com)

Проблема не уникальна, как и ее решения. В моем случае был выбран вариант с применением утилиты code2html, написанной на Perl, что естественно предполагает установку интерпретатора этого языка, например под Windows может быть инсталлирован ActivePerl, но в моём случае perl уже был в системе как часть MSYS.
Использовать code2html не трудно, важную информацию можно получить командой

perl code2html –help

При этом естественно оболочка должна знать, где лежит perl и code2html, т.е. надо указать путь к perl в переменной PATH, у меня там указан вот такой путь C:\msys\1.0\bin . И ещё вместо code2html должно быть C:\code2html-0.9.1\ code2html или что там у Вас.
А вот и мои первый реальный пример применения утилиты code2html

perl C:\code2html-0.9.1\code2html -w 80 -n -l C++ stl_pair.cpp > stl_pair.html

Есть одно, но может получиться, что полученный результат будет сильно разбавлен пустыми строками, но это можно исправить, просто перед получением html надо сделать EOL конверсию исходника к UNIX-формату, NotePad++ это поддерживает как в прочем и некоторые другие редакторы кода, например, в codeblocks есть в Settings – Editor – End-of-line options соответствующая настройка, надо выбрать CR.

Есть ещё вариант «немного программирования»

1 /// @FILE L1310.c
2 // Убирает встречающиеся друг за
» другом символы с кодами 13 и 10,
» оставляя только с кодом 13, те LF

3
4 #include <stdlib.h>
5 #include <stdio.h>
6
7 int main(int argv,char *argc[]) {
8
9 FILE* f=fopen(argc[1],"rb");
10 FILE* fo=fopen(argc[2],"wb");
11
12 int c;
13 int c1=-1;
14
15 while((c=fgetc(f))!=EOF) {
16 if(c==13) {
17 c1=c;
18 } else {
19 if(c1==13 && c==10) {
20 //putchar(13);
21 //fputc(13,fo);
22 c=13;
23 } else {
24 c1=-1;
25 }
26 //Пишем в файл и в консоль
27 fputc(c,fo);
28 putchar(c);
29
30 }
31 }
32 fclose(f);
33 fclose(fo);
34 return 0;
35 }

среда, 30 июня 2010 г.

Каждой твари по паре

Вот значит, понадобилось мне иметь объект, который будет содержать в себе справочник для получения некоторых оценок, которые в свою очередь определяются исходя из попадания в некоторый интервал значений. По сути, должны быть записи типа: значение верхней границы интервала, признак «включительно» и текст комментария, т.е. три поля. Первый (наименьший) элемент справочника оценок имеет значение нижней границы равное нулю. Естественно, значения внутри контейнера должны быть упорядочены. В качестве контейнера выбран std::map, но вот беда ключ-то нужен не простой, сложный. Одно из решений, которое пришло на ум использовать структуру std::pair, с одной стороны в качестве ключа, т.е. пару “верхняя граница интервала – признак включительно”, а с другой значением пары будет комментарий. В общем основное с чем пришлось повозиться это приведение семантики «первый-второй» к семантике «верхняя граница – включая - комментарий». Вот, что получилось:


1 #include <string>
2 #include <map>
3 #include <iostream>
4
5 class Estimation {
6 private:
7 typedef std::pair < int, bool > KeyEstimation ;
8 typedef std::pair <KeyEstimation, std::string > Estim ;
9 Estim estimation_;
10
11 public:
12 Estimation(const int up_border,const bool included,const std::string
» commentary):
» estimation_(std::make_pair(std::make_pair(up_border,included),commentary)) {}
13
14 Estimation() {}
15
16 int borderValue() const {
17 return estimation_.first.first ;
18 }
19 void borderValue(const int value) {
20 estimation_.first.first =value;
21 }
22
23 bool included() const {
24 return estimation_.first.second;
25 }
26 void included(const bool value) {
27 estimation_.first.second=value;
28 }
29
30 std::string commentary() const {
31 return estimation_.second;
32 }
33 void commentary(const std::string& s) {
34 estimation_.second=s;
35 }
36
37 Estim estimation() const {
38 return estimation_;
39 }
40
41 //Скрывая от клиента, что используется std::pair, преобразование придется делать
» явным

42 Estimation(std::map<KeyEstimation, std::string>::const_iterator& es) {
43 estimation_.first.first =es->first.first;
44 estimation_.first.second =es->first.second;
45 estimation_.second =es->second;
46 }
47
48 };
49
50 class ListEstimations {
51 private:
52 typedef std::pair < int, bool > KeyEstimation ;
53 typedef std::pair <KeyEstimation, std::string > Estim ;
54
55 public:
56 ListEstimations() {};
57 ~ListEstimations() {};
58
59 ListEstimations(const Estim& est) {
60 //Вставляет новую запись в список
61 estimations_.insert(est);
62 };//{ estimations_.push_back(est);}
63
64 //Классы исключений
65 class EstimationNotFound { };
66 class DublicateEstimation { };
67
68 ///Всталяет оценку в список и делает проверку на уникальность borderValue_ и
» included_, а вслучае совпадения делает замещение commentary_, не создавая
» нового элемента в контейнере.

69 void insertEstimation(const Estim& est) throw (DublicateEstimation) {
70 //Вставляет новую запись в список
71 estimations_.insert(est);
72 }
73
74 void insertEstimation(const int up_border,const bool included,const
» std::string commentary) {
75
»
»
»
» estimations_.insert(std::make_pair(std::make_pair(up_border,included),commentary));
76 }
77
78 ///Удаляет оценку из списка.
79 void eraseEstimation() throw (EstimationNotFound);
80
81 ///Возвращает оценку по заданным значениям value
82 //const Estimation& getEstimation(int i) const throw (EstimationNotFound);
83 Estimation& getEstimation(int i) throw (EstimationNotFound);
84
85 void print() {
86 for( std::map<KeyEstimation, std::string>::const_iterator
» i=estimations_.begin(); i!=estimations_.end(); ++i) {
87 //std::cout << i->first.first << '\t' << i->first.second << '\t' <<
» i->second << std::endl;//Делает, то же самое, что и следующая строка

88 std::cout << Estimation(i).borderValue() << '\t' <<
» Estimation(i).included() << '\t' << Estimation(i).commentary() << std::endl;
89 }
90 }
91
92 private:
93 ///Запрещение копирования
94 ListEstimations(const ListEstimations&);
95 ListEstimations& operator=(const ListEstimations&);
96
97 std::map<KeyEstimation, std::string> estimations_;
98
99 };
100
101
102 int main() {
103 setlocale(0, "") ;
104
105 Estimation est(10,false,std::string("Комментарий"));
106
107 ListEstimations ests(est.estimation());
108
109 Estimation est2(15,false,std::string("Комментарий2"));
110 ests.insertEstimation(est2.estimation());
111
112 est2.commentary("Комментарий3");
113 est2.borderValue(20);
114 est2.included(false);
115
116 ests.insertEstimation(est2.estimation());
117
118 est2.commentary("Комментарий4");
119 est2.borderValue(20);
120 est2.included(true);
121 ests.insertEstimation(est2.estimation());
122
123 ests.insertEstimation( 120,false,std::string("Комментарий5"));
124
125 ests.print();
126
127 std::cin.get();
128 return 0;
129 }
130