Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
#1

Связь списков - C++

27.03.2013, 18:29. Просмотров 860. Ответов 22
Метки нет (Все метки)

Доброго времени суток,

В процессе решения задачи, встретилась проблема:
есть структура
C++
1
2
3
4
struct TStruct {
std::string * m_String_1;
std::string * m_String_2;
}
есть массивы:
C++
1
2
3
4
std::string ** arr_Type_1_Strings;
unsigned int Type1StringsCount;
std::string ** arr_Type_2_Strings;
unsigned int Type2StringsCount;

Что я делал:
Идет запрос на добавление структуры (с указанием значений для ее элементов), тогда проверяется есть ли в
C++
1
arr_Type_1_Strings
строка соответствующая первому значению и то же самое для второго значния из запроса, если оба есть (а спец. функция, которая проверяет наличие, на самом деле, просто возвращает указатель на соответсвующий элемент соответствующего массива ), то функция добавления возвращает ложь, иначе создается необходимая структура
C++
1
 (TStruct *tmpStruct=new TStruct)
отсутствующие строки создаются или просто записываются указатели на них в случае если эти указатели есть, т.е.
C++
1
tmpStruct->m_String_X = указатель на элемент массива где находится добавляемая строка.
Создаются эти строки (если в списке строк запрашиваемая не была найдена) так:
в массиве выделяется память под указатель
C++
1
 (std::string**)malloc(...)
, потом создается новая строка
C++
1
arr_Type_X_Strings[number]=new std::string;
потом начинается самое интересное, методом деления массива пополам, находится индекс элемента (@index) на месте которого должна быть новая строка @Str2Add (дабы сохранять порядок в массиве).

Далее в цикле (если конечно индекс не больше числа элементов в массиве до дополнения, иначе после выделения памяти элемент запишется в последнюю ячейку):

C++
1
2
3
for(unsigned int i=Type1StringsCount;i>@index;i--){
     *arr_Type_X_Strings[i]=*arr_Type_X_Strings[i-1];
}
и наконец
C++
1
arr_Type_X_Strings[@index]=@Str2Add;
и возвращается указатель на новую строку.


Это лишь малая часть программы, пока я писал остальные части я проводил тестирование (совпало) на строках идущих по порядку, соответсвенно никаких повторяющихся данных (типа std::string во всяком случае) и все в нужном порядке, но когда написав много кода, я ввел строки идущие не попорядку я удивился выводу, содержимое структур не соответсвовало ожиданиям, оно и понятно вот здесь:
C++
1
*arr_Type_X_Strings[i]=*arr_Type_X_Strings[i-1];
менялись не указатели а сами строки (вроде так да?) а точнее они смещались, что вроде бы я и хотел, вот только двойной массив я использовал, как мне казалось, чтобы данные в структурах не съехали (потом у каждой структуры другие значения выводятся, т.к. сместилось соответствие), сейчас я понимаю что запутался просто в указателях, однако сейчас мне в голову приходят только такие решения - при каждом сдвиге части массива, проходит в цикле ВСЕ (много времени процессора) структуры и изменять там указатель на новое значение позиции строки в ее массиве, либо сделать подобие базы данных с тремя столбцами - первый столбец это не изменяемый идентификатор строки (указатель этого массива бд на который ссылается элемент структуры) второй столбец это адрес элемента в промежуточном массиве, третий столбец это физический адрес строки. Хотя нет опять ерунда какая то получается, может надо использовать два массива, в одном указано соответствие физического и порядкого в другом запрашиваемого и порядкового, и при добавлении строки менять указатели в промежуточном массиве, сохраняя таким образом значение для элемента структуры. Как видите я никак не осилю эта задачу, варианты с линейными наивными решениями (разумеется с теми, которые неоправданно используют память и процессорное время) не катят, если каждая строка по 1000 символов и у вас 8000 строк, то копировать их туда сюда целиком вместе со структурой не лучший выход поэтому массивы.

Что можете предложить?

Добавлено через 6 минут
P.S. доступные библиотеки :
C++
1
2
3
4
5
6
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
так что, к сожалению без векторов и других радостей STL, в задании проверяется умение решать задачи без STL.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.03.2013, 18:29     Связь списков
Посмотрите здесь:

C++ Обработка списков
C++ Список списков)
Сравнение списков C++
Сортировка списков C++
C++ слияние списков
Список списков C++
Рекурсия списков C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Tulosba
:)
Эксперт С++
4384 / 3227 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
28.03.2013, 07:37     Связь списков #2
Не понял в чем вопрос. Многа букаф. И зачем Вы мешаете new и malloc?
lemegeton
 Аватар для lemegeton
2915 / 1344 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
28.03.2013, 08:06     Связь списков #3
Не замутненный поток сознания.
Абзац на полторы тыщи символов в трех предложениях совершенно нечитаем.

Взаимоисключающие параграфы детектед:
Цитата Сообщение от awpe Посмотреть сообщение
так что, к сожалению без векторов и других радостей STL, в задании проверяется умение решать задачи без STL.
+
Цитата Сообщение от awpe Посмотреть сообщение
struct TStruct {
std::string * m_String_1;
std::string * m_String_2;
}
std::string тоже часть STL.

Цитата Сообщение от awpe Посмотреть сообщение
Что можете предложить?
Предлагаю сделать две вещи:
1. Кратко и емко изложить суть вопроса;
2. Выложить полностью исходный текст задания.
nonedark2008
813 / 571 / 110
Регистрация: 28.07.2012
Сообщений: 1,522
28.03.2013, 08:34     Связь списков #4
Ммм. А вообще, постановка задачи имеется? А то правда, то что делаете вы - слишком огромно. Что вообще требовалось - с этого и надо было начинать!
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
28.03.2013, 11:59  [ТС]     Связь списков #5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
 
class CCompanyIndex
 {
   public:
                             CCompanyIndex ( void );
                            ~CCompanyIndex ( void );
    bool                     Add           ( const string & oName,
                                             const string & oAddr,
                                             const string & cName,
                                             const string & cAddr );
    bool                     Del           ( const string & oName,
                                             const string & oAddr );
    bool                     Search        ( const string & oName,
                                             const string & oAddr,
                                             string       & cName,
                                             string       & cAddr ) const;
    // todo
 };
 
int main(){
bool   status;
string cName, cAddress;
CCompanyIndex  b1;
status = b1 . Add ( "Smith", "Oak road", "ACME, Ltd.", "One ACME road" );
// status = true
status = b1 . Add ( "Brown", "Second street", "MakroHard, Inc.", "Soft street" );
// status = true
status = b1 . Add ( "Hacker", "5-th avenue", "Forks and Knives, Ltd.", "Cutlery avenue" );
// status = true
status = b1 . Add ( "Hacker", "7-th avenue", "Child toys, Inc.", "Red light district" );
// status = true
status = b1 . Search ( "Brown", "Second street", cName, cAddress );
// status = true, cName = "MakroHard, Inc.", cAddress="Soft street"
status = b1 . Search ( "Hacker", "Oak road", cName, cAddress );
// status = false
status = b1 . Search ( "Smith", "Oak road", cName, cAddress );
// status = true, cName = "ACME, Ltd.", cAddress="One ACME road"
status = b1 . Del ( "Smith", "Oak road" );
// status = true
status = b1 . Search ( "Smith", "Oak road", cName, cAddress );
// status = false
 
CCompanyIndex  b2;
status = b2 . Add ( "Smith", "Michigan avenue", "ACME, Ltd.", "One ACME road" );
// status = true
status = b2 . Search ( "Smith", "Michigan avenue", cName, cAddress );
// status = true, cName = "ACME, Ltd.", cAddress="One ACME road"
status = b2 . Del ( "Smith", "Michigan avenue" );
// status = true
status = b2 . Search ( "Smith", "Michigan avenue", cName, cAddress );
// status = false
status = b2 . Del ( "Smith", "Michigan avenue" );
// status = false
status = b2 . Add ( "Smith", "Michigan avenue", "Forks and Knives, Ltd.", "Cutlery avenue" );
// status = true
status = b2 . Search ( "Smith", "Michigan avenue", cName, cAddress );
// status = true, cName = "Forks and Knives, Ltd.", cAddress="Cutlery avenue"
status = b2 . Add ( "Smith", "Michigan avenue", "Child toys, Inc.", "Red light district" );
// status = false
status = b2 . Add ( "Smith", "Michigan avenue", "MakroHard, Inc.", "Soft street" );
// status = false
status = b2 . Del ( "Smith", "Michigan avenue" );
// status = true
status = b2 . Search ( "Smith", "Michigan avenue", cName, cAddress );
// status = false
return 0;
}
Организовать реестр фирм, где пара имя владельца - его адрес уникальные, фирмы напротив могут иметь дубликаты - одна фирма может иметь несколько хозяев.

конструктор класса без параметров
деструктор освобождает память
метод Add(oName, oAddr, cName, cAddr) добавляет запись в БД, если там нет пары имя-адрес владельца, иначе возвращает ложь
метод Del(oName, oAddr) удаляет запись и возвращает истину, или ложь, если не была найдена запись или еще какие ошибки
метод Search (oName, oAddr, cName, cAddr ) ищет фирму по oName, oAddr, если есть то возвращает истину и по ссыкам cName, cAddr записывает ее(фирмы) данные

Не использовать STL кроме данных библиотек
Не использовать копирующий конструктор
Не использовать перегрузку оператора =
Имплементация должна быть эффективной с точки зрения памяти и времени
Массив строк должен быть сортирован и просматриваться (search) с помощью алгоритмов с логарифмической сложностью
Рекомендовано сразу выделить массив на 1000 записей, по его заполнении же не выделять еще одно место а изменять размер в геометрическоф прогрегресии со знаменателем ~1.5 до 2.0

Добавлено через 6 минут
начал с того что пишу вспомогательный класс CStrTbl для управления строками с методами типа addstr() getstr() findstr() delstr() isinarr() operator[]... потом в базовом классе буду выделять объекты типа CStrTbl * Companies, CStrTbl * OwnerNames CStrTbl * Addresses, и структуры struct Owner{CStrTbl * m_OwnerName; CStrTbl * m_OwnerAddress; Company* m_Company;} struct Company... Везде только указатели, строки хранятся только во вспомогательном классе в единственном экземпляре... пока так:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define bIfUnique_dflt true // sets is object will store unique elements
 
//Provides base functionality for strings databaze, by default it will react to calls
//using unsorted strings array, where strings are in the same order
//flags bSrtRtrnAutoFalse and bSrtRtrn are used to kontrol output order of strings
//bErrFlag is set to true value if error aquired
//bSpecFlag only used for special functions.
//Has 2 constructors, default creates object storing only unique strings
//Using CStrTbl(bool bIfUnique) it is possible to create object which stores
//non-unique strings.
 
class CStrTbl {
public:
    CStrTbl();
    CStrTbl(bool bIfUnique);
    ~CStrTbl();
    std::string * pStrAdd(std::string& sInsStr); //adds string and returns pointer to it
    std::string * operator[](unsigned int iX); // access to strings using [] opearator, depends on bSrtRtrn flag
    std::string * pStrFind(const std::string& sInsStr); // returns pointer if sInsStr exists in object
    bool bStrDel(const std::string& sInsStr); //deletes sInsStr string if exists;
    bool bStrDel(const unsigned int& iNdx); //deletes string iX if Exists
    unsigned int nStrFind(const std::string& sInsStr); //returns index of sInsStr if exists
    unsigned int iGetSize() const; //returns number of elements
    bool bIfExists(const std::string& sInsStr);
    bool bErrFlag; //if error happened in last operation
    bool bSpecFlag; // special flag for temp purposes
    bool bSrtRtrnAutoFalse; // if set then every timy you call method which depends on bSrtRtrn, 
    //bSrtRtrn sets to false, by default is true
    bool bSrtRtrn; // WARNING USE IT FOR OUTPUT ONLY!!! if Object should be used as been sorted or unsorted, 
    //by default everytime after call automatically changes to false
private:
    void vChngHAddr(std::string* sFind, std::string* sReplace);
    unsigned int nFindInsPos(const std::string& sInsStr); //returns propriate index for sInsStr insertion in dynamic arr
    unsigned int nFindHardPos(const std::string* sFndStr); //returns propriate index for sFndStr insertion in hard arr
    bool bIsUnique; // if Object consists of unique values
    bool ThereIsEmpty; //if string was deleted and it is place in the array for new string;
    unsigned int * iDelIndexes; //array of deleted indexes for adding and removing strings;
    unsigned int iDynSize; //size of the strings array
    std::string ** sHAddr; // hard addresses to the rest of the world, never sorted
    std::string ** aStrings; // sorted strings array for speed
};
 
CStrTbl::CStrTbl() {
    bIsUnique = bIfUnique_dflt;
    aStrings = NULL;
    sHAddr = NULL;
    iDynSize = 0;
    bErrFlag = false;
    bSpecFlag = false;
    bSrtRtrn = false;
    bSrtRtrnAutoFalse = true;
}
 
CStrTbl::CStrTbl(bool bIfUnique) {
    bIsUnique = bIfUnique;
    aStrings = NULL;
    sHAddr = NULL;
    iDynSize = 0;
    bErrFlag = false;
    bSpecFlag = false;
    bSrtRtrn = false;
    bSrtRtrnAutoFalse = true;
}
 
CStrTbl::~CStrTbl() {
    for (unsigned int i = 0; i < iDynSize; i++) {
        delete aStrings[i];
    }
    free(aStrings);
    free(sHAddr);
}
 
unsigned int CStrTbl::iGetSize() const {
    return iDynSize;
}
 
std::string * CStrTbl::operator[](unsigned int iX) {
    if ((iX > iDynSize) || (iX < 0)) {
        bErrFlag = true;
        return NULL;
    }
    if (bSrtRtrn) {
        if (bSrtRtrnAutoFalse) {
            bSrtRtrn = false;
        }
        return aStrings[iX];
    } else {
        bErrFlag = false;
        if(!sHAddr[iX]){
            bErrFlag = true;
            return NULL;
        }
        return sHAddr[iX];
    }
}
 
unsigned int CStrTbl::nFindHardPos(const std::string* sFndStr) {
    for (unsigned int i = 0; i < iDynSize; i++) {
        if (sHAddr[i] == sFndStr) {
            bSpecFlag = false;
            return i;
        }
    }
    bSpecFlag = true;
    return 0;
}
 
unsigned int CStrTbl::nFindInsPos(const std::string& sInsStr) {
    unsigned int start = 0, end = iDynSize;
    if (end == 0) {
        bSpecFlag = false;
        return 0;
    }
    if (sInsStr.std::string::compare(*aStrings[start]) < 0) {
        bSpecFlag = false;
        return 0;
    }
    if (sInsStr.compare(*aStrings[end - 1]) > 0) {
        bSpecFlag = false;
        return end;
    }
    unsigned int uiMid;
    int siCmpMidRes;
    while (start < end) {
        uiMid = start + (end - start) / 2;
        siCmpMidRes = sInsStr.compare(*aStrings[uiMid]);
        if ((siCmpMidRes < 0) || (!siCmpMidRes)) {
            end = uiMid;
        } else {
            start = uiMid + 1;
        }
    }
    int bCmpRes = sInsStr.compare(*aStrings[end]);
    if (bCmpRes < 0) {
        bSpecFlag = false;
        return end;
    }
    if (!bCmpRes) {
        bSpecFlag = true;
        return end;
    }
    return 0;
}
 
std::string * CStrTbl::pStrFind(const std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if (!bSpecFlag) {
        return NULL;
    }
    return aStrings[iX];
}
 
unsigned int CStrTbl::nStrFind(const std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if (!bSpecFlag) {
        bSpecFlag = true;
        return 0;
    }
    return iX;
}
 
bool CStrTbl::bIfExists(const std::string& sInsStr) {
    return ((bool)pStrFind(sInsStr)) && (bSpecFlag);
}
 
void CStrTbl::vChngHAddr(std::string* sFind, std::string* sReplace) {
    for (unsigned int i = 0; i < iDynSize; i++) {
        if (sHAddr[i] == sFind) {
            sHAddr[i] = sReplace;
            break;
        }
    }
}
 
std::string * CStrTbl::pStrAdd(std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if ((bIsUnique) && (!iX)&&(bSpecFlag)) {
        bSpecFlag = false;
        return NULL;
    }
    aStrings = (std::string**)realloc(aStrings, sizeof (std::string*)*(iDynSize + 1));
    if (!aStrings) {
        bErrFlag = true;
        return NULL;
    }
 
    aStrings[iDynSize] = new std::string;
    if (!aStrings[iDynSize]) {
        bErrFlag = true;
        return NULL;
    }
 
    sHAddr = (std::string**)realloc(sHAddr, sizeof (std::string*)*(iDynSize + 1));
    if (!aStrings) {
        bErrFlag = true;
        return NULL;
    }
 
    for (unsigned int i = iDynSize; i > iX; i--) {
        vChngHAddr(aStrings[i - 1], aStrings[i]);
        *aStrings[i] = *aStrings[i - 1];
    }
    *aStrings[iX] = sInsStr;
    sHAddr[iDynSize++] = aStrings[iX];
 
    return aStrings[iX];
}
 
bool CStrTbl::bStrDel(const std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if ((!iX) || (!bSpecFlag)) {
        return false;
    }
    unsigned int tmp=nFindHardPos(aStrings[iX]);
    sHAddr[tmp] = NULL;
    for (unsigned int i = iX; i < iDynSize - 1; i++) {
        vChngHAddr(aStrings[i + 1], aStrings[i]);
        *aStrings[i] = *aStrings[i + 1];
    }
    iDynSize--;
    std::cout << "!" << aStrings[iDynSize-1] << std::endl;
    
    delete aStrings[iDynSize]; //aStrings[iDynSize] = NULL;
        aStrings[iDynSize] = NULL;
    //delete sHAddr[iDynSize];    //sHAddr[iDynSize] = NULL;
    //std::cout<<"!"<<sHAddr[iDynSize-1]<<std::endl;
 
    aStrings = (std::string**)realloc(aStrings, sizeof (std::string*)*(iDynSize));
    //;
    if (!aStrings) {
        bErrFlag = true;
        return false;
    }
    //sHAddr[iDynSize + 1] = NULL;
    return true;
}
 
bool CStrTbl::bStrDel(const unsigned int& iNdx) {
    if (!sHAddr[iNdx]) {
        return false;
    }
    unsigned int iX = nFindInsPos(*sHAddr[iNdx]);
    const std::string *sInsStr = aStrings[iX];
    return bStrDel(*sInsStr);
}
 
int main(void) {
    CStrTbl arr_CompanyNames;
    std::string str = "0";
    std::cout << *arr_CompanyNames.pStrAdd(str) << std::endl;
    str = "4";
    std::cout << *arr_CompanyNames.pStrAdd(str) << std::endl;
    str = "1";
    std::cout << *arr_CompanyNames.pStrAdd(str) << std::endl;
    str = "3";
    std::cout << *arr_CompanyNames.pStrAdd(str) << std::endl;
    str = "2";
    std::cout << *arr_CompanyNames.pStrAdd(str) << std::endl;
    str = "5";
    std::cout << *arr_CompanyNames.pStrAdd(str) << std::endl;
    std::cout << std::endl;
 
    for (unsigned int i = 0; i < arr_CompanyNames.iGetSize(); i++) {
        arr_CompanyNames.bSrtRtrn = true;
        std::cout << *arr_CompanyNames[i] << std::endl;
    }
    std::cout << std::endl;
    for (unsigned int i = 0; i < arr_CompanyNames.iGetSize(); i++) {
        std::cout << *arr_CompanyNames[i] << std::endl;
    }
    std::cout << std::endl;
 
    std::cout << "!=" << *arr_CompanyNames[5] << std::endl;
    std::cout << std::endl;
    std::cout << arr_CompanyNames.bStrDel("4") << std::endl;
    std::cout << std::endl;
    std::cout << "!=" << *arr_CompanyNames[4] << std::endl;
    std::cout << std::endl;
    for (unsigned int i = 0; i < arr_CompanyNames.iGetSize(); i++) {
        arr_CompanyNames.bSrtRtrn = true;
        std::cout << *arr_CompanyNames[i] << std::endl;
    }
    std::cout << std::endl;
    for (unsigned int i = 0; i < arr_CompanyNames.iGetSize(); i++) {
 
        std::cout << *arr_CompanyNames[i] << std::endl;
    }
 
    return 0;
}


Добавлено через 1 минуту
Может у меня подход вообще не правильный...?)
Tulosba
:)
Эксперт С++
4384 / 3227 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
28.03.2013, 12:29     Связь списков #6
Короче, понятно.
Цитата Сообщение от awpe Посмотреть сообщение
Массив строк должен быть сортирован и просматриваться (search) с помощью алгоритмов с логарифмической сложностью
Реализовать свой map.
P.S. и не совмещайте malloc/new, второй раз уже говорю.
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
28.03.2013, 14:23  [ТС]     Связь списков #7
Почему? и как мне тогда выделять память под новый массив указателей? Единственное что приходит в голову это создавать временный массив указателей новой размерности и копировать туда содержимое старого, потом delete старый массив и копирование в ту старую переменную указатель на новый массив указателей, но разве тогда я не потеряю в скорости? Мой класс еще далек от совершенства, но там я держу два массива, в одном строки отсортированы а другой хранит ссылки на строки чтобы обеспечивать доступ к ним после сортировки (как то так), в бд mysql я бы сделал таблицу с тремя полями - содержимое строки, ее порядковый номер в таблице и ее не изменяемый адрес, т.е. со стороны можно организовать доступ к конкретной строке в не зависимости от сортировки + можно работать с индексами строк в алфавитном порядке, те строка номер(индекс) 1 соответствует той строке которая сейчас на первом месте в таблице (сортировка по алфавиту). Вопрос - как бы выглядело подобное в c++ ? И насчет подхода - может можно сделать все проще (без map, vector)?
nonedark2008
813 / 571 / 110
Регистрация: 28.07.2012
Сообщений: 1,522
28.03.2013, 20:19     Связь списков #8
Цитата Сообщение от awpe Посмотреть сообщение
в одном строки отсортированы а другой хранит ссылки на строки чтобы обеспечивать доступ к ним после сортировки
А не проще бы было, не сортировать именно строки в первом списке, а сортировать указатели. У тебя массив указателей на строки. Сортируешь эти указатели в списке так, чтобы строки в них были отсортированы. Тогда и указатели не собьются...
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
29.03.2013, 05:47  [ТС]     Связь списков #9
nonedark2008, Либо вы невнимательны либо я плохо описал происходящее) Всю эту эквилибристику с классами и массивами я затеял, в том числе и для того, чтобы проводить операции над указателями а не над строками, т.е. по моим соображениям строки хранятся программой в единственно виде, будучи отсортированы в одном массиве, указатели на них, оданако, также содержатся и в другом массиве, но там индекс соответствует порядку их вложения, таким образом при обращении к объекту по указателю, до вложения новой строки получаем указатель на нее, и при обращении после, указатель получим тот же самый, не смотря на то, что строки были отсортированы, и у некоторых (иногда всех если строка на первом месте) изменился указатель в том отсортированом массиве, объект данного класса все равно вернет указатель на ту же самую строку, во всяком случае такая задумка. Сейчас думаю о третьем массиве булевых значений, в котором индексы будут соответствовать индексам в массиве неотсортированых строк, значния 0 или 1, много памяти не займут, зато так я обозначу те индексы в неотсортированом массиве которые ссылаются на адрес под который не выделена память, это следует из алгоритма - после удаления строки, изменяется размер того массива который содержит отсортированые строки, после delete одной строки, указатель на нее не действителен, а он есть в неотсортированом массиве и здравствуй segfault при попытке чтения, отсортировать данные там и освободить место не получится т.к. массив (поправьте если ошибаюсь) начинается на каком то адресе, а каждый следующий эдемент это просто следующая ячейка памяти (размер "ячейки" диктуется типом) так что для сохранения первоначальной ссылки на строку менять адреса там нельзя иначе потом там где была строка "строка ваня" будет "строка петя".

Еще вопрос - может вместо булевых значений использовать целые 32битные? вроде как при сравнении проессору быстрее сравнить два числа одного типа чем заниматься приведением типов?

Самое плохое что осталось три дня до здачи)

Добавлено через 26 минут
*сдачи

Добавлено через 3 часа 11 минут
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define bIfUnique_dflt true // sets is object will store unique elements
 
//Provides base functionality for strings databaze, by default it will react to calls
//using unsorted strings array, where strings are in the same order
//flags bSrtRtrnAutoFalse and bSrtRtrn are used to kontrol output order of strings
//bErrFlag is set to true if error aquired
//bSpecFlag only used for special c.
//Has 2 constructors, default creates object storing only unique strings
//Using CStrTbl(bool bIfUnique) it is possible to create object which stores
//non-unique strings.
 
class CStrTbl {
public:
    CStrTbl();
    CStrTbl(bool bIfUnique);
    ~CStrTbl();
    std::string * pStrAdd(std::string& sInsStr); //adds string and returns pointer to it
    std::string * operator[](unsigned int iX); // access to strings using [] opearator, depends on bSrtRtrn flag
    std::string * pStrFind(const std::string& sInsStr); // returns pointer if sInsStr exists in object
    bool bStrDel(const std::string& sInsStr); //deletes sInsStr string if exists;
    bool bStrDel(const unsigned int& iNdx); //deletes string iX if Exists
    unsigned int nStrFind(const std::string& sInsStr); //returns index of sInsStr if exists
    unsigned int iGetSize() const; //returns number of elements
    bool bIfExists(const std::string& sInsStr);
    bool bErrFlag; //if error happened in last operation
    bool bSpecFlag; // special flag for temp purposes
    bool bSrtRtrnAutoFalse; // if set then every timy you call method which depends on bSrtRtrn, 
    //bSrtRtrn sets to false, by default is true
    bool bSrtRtrn; // WARNING USE IT FOR OUTPUT ONLY!!! if Object should be used as been sorted or unsorted, 
    //by default everytime after call automatically changes to false
    void Print(); //prints content
private:
    unsigned int * FreeBlocks; // indexes of free elements in sHAddr
    unsigned int FreeBlocksCount; // count of free blocks;
    void vChngHAddr(std::string* sFind, std::string* sReplace);
    unsigned int nFindInsPos(const std::string& sInsStr); //returns propriate index for sInsStr insertion in dynamic arr
    unsigned int nFindHardPos(const std::string* sFndStr); //returns propriate index for sFndStr insertion in hard arr
    bool bIsUnique; // if Object consists of unique values
    unsigned int iDynSize; //size of the strings array
    unsigned int iHardSize; //prints actual status
    std::string ** sHAddr; // hard addresses to the rest of the world, never sorted
    std::string ** aStrings; // sorted strings array for speed
};
 
CStrTbl::CStrTbl() {
    bIsUnique = bIfUnique_dflt;
    aStrings = NULL;
    sHAddr = NULL;
    iDynSize = 0;
    bErrFlag = false;
    bSpecFlag = false;
    bSrtRtrn = false;
    bSrtRtrnAutoFalse = true;
    FreeBlocksCount = 0;
    iHardSize = 0;
    FreeBlocks = NULL;
}
 
CStrTbl::CStrTbl(bool bIfUnique) {
    bIsUnique = bIfUnique;
    aStrings = NULL;
    sHAddr = NULL;
    iDynSize = 0;
    bErrFlag = false;
    bSpecFlag = false;
    bSrtRtrn = false;
    bSrtRtrnAutoFalse = true;
    FreeBlocksCount = 0;
    iHardSize = 0;
    FreeBlocks = NULL;
}
 
CStrTbl::~CStrTbl() {
    for (unsigned int i = 0; i < iDynSize; i++) {
        delete aStrings[i];
    }
    free(FreeBlocks);
    free(aStrings);
    free(sHAddr);
}
 
unsigned int CStrTbl::iGetSize() const {
    return iDynSize;
}
 
std::string * CStrTbl::operator[](unsigned int iX) {
    if ((iX > iDynSize) || (iX < 0)) {
        bErrFlag = true;
        return NULL;
    }
    if (bSrtRtrn) {
        if (bSrtRtrnAutoFalse) {
            bSrtRtrn = false;
        }
        return aStrings[iX];
    } else {
        bErrFlag = false;
        if (!sHAddr[iX]) {
            bErrFlag = true;
            return NULL;
        }
        return sHAddr[iX];
    }
}
 
unsigned int CStrTbl::nFindHardPos(const std::string* sFndStr) {
    for (unsigned int i = 0; i < iHardSize; i++) {
        if (FreeBlocksCount) {
            for (unsigned int j = 0; j < FreeBlocksCount; j++) {
                continue;
            }
        }
        if (sHAddr[i] == sFndStr) {
            bSpecFlag = false;
            return i;
        }
    }
    bSpecFlag = true;
    return 0;
}
 
unsigned int CStrTbl::nFindInsPos(const std::string& sInsStr) {
    unsigned int start = 0, end = iDynSize;
    if (end == 0) {
        bSpecFlag = false;
        return 0;
    }
    if (sInsStr.std::string::compare(*aStrings[start]) < 0) {
        bSpecFlag = false;
        return 0;
    }
    if (sInsStr.compare(*aStrings[end - 1]) > 0) {
        bSpecFlag = false;
        return end;
    }
    unsigned int uiMid;
    int siCmpMidRes;
    while (start < end) {
        uiMid = start + (end - start) / 2;
        siCmpMidRes = sInsStr.compare(*aStrings[uiMid]);
        if ((siCmpMidRes < 0) || (!siCmpMidRes)) {
            end = uiMid;
        } else {
            start = uiMid + 1;
        }
    }
    int bCmpRes = sInsStr.compare(*aStrings[end]);
    if (bCmpRes < 0) {
        bSpecFlag = false;
        return end;
    }
    if (!bCmpRes) {
        bSpecFlag = true;
        return end;
    }
    return 0;
}
 
std::string * CStrTbl::pStrFind(const std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if (!bSpecFlag) {
        return NULL;
    }
    return aStrings[iX];
}
 
unsigned int CStrTbl::nStrFind(const std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if (!bSpecFlag) {
        bSpecFlag = true;
        return 0;
    }
    return iX;
}
 
bool CStrTbl::bIfExists(const std::string& sInsStr) {
    return ((bool)pStrFind(sInsStr)) && (bSpecFlag);
}
 
void CStrTbl::vChngHAddr(std::string* sFind, std::string* sReplace) {
    for (unsigned int i = 0; i < iHardSize; i++) {
        if (!FreeBlocksCount) {
            for (unsigned int j = 0; j < FreeBlocksCount; j++) {
                if (i == FreeBlocks[j]) {
                    continue;
                }
            }
        }
        if (sHAddr[i] == sFind) {
            sHAddr[i] = sReplace;
            break;
        }
    }
}
 
std::string * CStrTbl::pStrAdd(std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if ((bIsUnique) && (!iX)&&(bSpecFlag)) {
        bSpecFlag = false;
        return NULL;
    }
    if (!FreeBlocksCount) {//if it is no free blocks
        aStrings = (std::string**)realloc(aStrings, sizeof (std::string*)*(iDynSize + 1));
        if (!aStrings) {
            bErrFlag = true;
            return NULL;
        }
        sHAddr = (std::string**)realloc(sHAddr, sizeof (std::string*)*(iHardSize + 1));
    }
    aStrings[iDynSize] = new std::string;
    if (!aStrings[iDynSize]) {
        bErrFlag = true;
        return NULL;
    }
    for (unsigned int i = iDynSize; i > iX; i--) {
        vChngHAddr(aStrings[i - 1], aStrings[i]);
        *aStrings[i] = *aStrings[i - 1];
    }
    *aStrings[iX] = sInsStr;
    if (FreeBlocksCount) {
        sHAddr[FreeBlocks[FreeBlocksCount - 1]] = aStrings[iX];
        FreeBlocksCount--;
        iDynSize++;
        return sHAddr[FreeBlocks[FreeBlocksCount]];
        //FreeBlocks = (unsigned int *) realloc(FreeBlocks, sizeof (unsigned int)*(FreeBlocksCount));
    } else {
        iHardSize++;
        sHAddr[iDynSize] = aStrings[iX];
        iDynSize++;
        return sHAddr[iDynSize - 1];
    }
    iDynSize++;
    return sHAddr[iDynSize - 1];
}
 
bool CStrTbl::bStrDel(const std::string& sInsStr) {
    unsigned int iX = nFindInsPos(sInsStr);
    if (!bSpecFlag) {
        return false;
    }
    unsigned int NewFreeIndex = nFindHardPos(aStrings[iX]);
    FreeBlocks = (unsigned int *) realloc(FreeBlocks, sizeof (unsigned int)*(FreeBlocksCount + 1));
    if (!FreeBlocks) {
        bErrFlag = true;
        return false;
    }
    FreeBlocks[FreeBlocksCount++] = NewFreeIndex;
    sHAddr[NewFreeIndex] = NULL;
    for (unsigned int i = iX; i < iDynSize - 1; i++) {
        vChngHAddr(aStrings[i + 1], aStrings[i]);
        *aStrings[i] = *aStrings[i + 1];
 
        //vChngHAddr(aStrings[i + 1], &tmp_str);
 
    }
    iDynSize--;
    delete aStrings[iDynSize];
 
    return true;
}
 
bool CStrTbl::bStrDel(const unsigned int& iNdx) {
    if (!sHAddr[iNdx]) {
        return false;
    }
    unsigned int iX = nFindInsPos(*sHAddr[iNdx]);
    const std::string *sInsStr = aStrings[iX];
    return bStrDel(*sInsStr);
}
 
void CStrTbl::Print() {
 
    std::cout << "Current status:" << std::endl;
    std::cout << std::endl;
    std::cout << "\tStrings in Dynamic array:\t\t" << iDynSize << std::endl;
    std::cout << "\tStrings in Hard Linked array:\t\t" << iHardSize << std::endl;
    std::cout << "\tNumber of UnUsed Indexes in HL Array:\t\t" << FreeBlocksCount << std::endl;
    std::cout << std::endl;
    std::cout << "\tDynamic array of strings:" << std::endl;
    std::cout << "\t\tIndex\t" << std::setw(9) << "Address\t" << std::setw(10) << "Value" << std::endl;
    for (unsigned int i = 0; i < iDynSize; i++) {
        std::cout << "\t\t" << i << "\t" << aStrings[i] << "\t" << *aStrings[i] << std::endl;
    }
    std::cout << std::endl;
    std::cout << "\tHard Linked array of strings:" << std::endl;
    std::cout << "\t\tIndex\t" << std::setw(9) << "Address\t" << std::setw(10) << "Value" << std::endl;
    for (unsigned int i = 0; i < iHardSize; i++) {
        if (FreeBlocksCount) {
            unsigned int j;
            for (j = 0; j < FreeBlocksCount; j++) {
                if (i == FreeBlocks[j]) {
                    std::cout << "\t\t" << i << "\t" << std::setw(9) << "NULL" << "\t" << "NULL" << std::endl;
                    j++;
                    break;
                }
            }
            if (i == FreeBlocks[j - 1]) {
                continue;
            }
        }
        std::cout << "\t\t" << i << "\t" << sHAddr[i] << "\t" << *sHAddr[i] << std::endl;
    }
    std::cout << std::endl;
    std::cout << "\tArray of HL free indexes:" << std::endl;
    std::cout << "\t\t" << std::setw(10) << "Index" << "\t" << std::setw(10) << "value\t" << std::endl;
    for (unsigned int i = 0; i < FreeBlocksCount; i++) {
        std::cout << "\t\t" << std::setw(10) << i << "\t" << std::setw(9) << FreeBlocks[i] << "\t" << std::setw(9) << "" << std::endl;
    }
    std::cout << std::endl;
 
}
 
int main(void) {
    CStrTbl arr_CompanyNames;
    std::string str = "fdgdfgdf gdfg dfgd fgdfg dfgdfg dgdf gd0dfgfdgdgdf";
    arr_CompanyNames.pStrAdd(str);
    str = "qknafsadvscdxeakowni";
    arr_CompanyNames.pStrAdd(str);
    str = "6735930425";
    arr_CompanyNames.pStrAdd(str);
    str = "(!%?@^+?+@?%*!@+-)+!()^?*)^+)?-!+)(!%!+)";
    arr_CompanyNames.pStrAdd(str);
    str = "XTdfEP?eB7gxc9jhk@gPZCvHdmATa0BXHE4*?3(AOdYQ*8XbY5";
    arr_CompanyNames.pStrAdd(str);
    str = "Kyk31ndmZdcm";
    arr_CompanyNames.pStrAdd(str);
 
 
    std::cout << "_____________________after all added:_________________________" << std::endl;
    arr_CompanyNames.Print();
 
 
 
 
 
    arr_CompanyNames.bStrDel("Kyk31ndmZdcm");
    std::cout << std::endl;
    std::cout << "_____________________after 4 deleted_________________________" << std::endl;
    arr_CompanyNames.Print();
 
    arr_CompanyNames.bStrDel("qknafsadvscdxeakowni");
    std::cout << std::endl;
    std::cout << "_____________________after 3 deleted_________________________" << std::endl;
    arr_CompanyNames.Print();
    
    str = "SLWCBODKEVBVFOVLHWOC";
    arr_CompanyNames.pStrAdd(str);
 
    arr_CompanyNames.bStrDel("2");
    std::cout << std::endl;
    std::cout << "_____________________after2 deleted_________________________" << std::endl;
    arr_CompanyNames.Print();
 
    arr_CompanyNames.bStrDel("0");
    std::cout << std::endl;
    std::cout << "_____________________after 0 deleted_________________________" << std::endl;
    arr_CompanyNames.Print();
 
    arr_CompanyNames.bStrDel("5");
    std::cout << std::endl;
    std::cout << "_____________________after5 deleted_________________________" << std::endl;
    arr_CompanyNames.Print();
    return 0;
}


Если не лень, попробуйте строковый класс, у меня вроде нормально работает, валгринд не ругается...
lemegeton
 Аватар для lemegeton
2915 / 1344 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
29.03.2013, 16:34     Связь списков #10
Цитата Сообщение от awpe Посмотреть сообщение
Может у меня подход вообще не правильный...?)
Точно. Вообще не правильный. С полученным интерфейсом будет просто невозможно работать. Воспользуйтесь классами.

Вот пример по вашей задаче. Из STL только iostream.
Бинарный поиск, никаких копирований, размещение сортированными массивами.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#include <iostream>
#include <cstring>
#include <ctime>
#include <cstdlib>
 
class Person {
 public:
  Person() : name(0), address(0) {}
  Person(const char *name, const char *address) : name(0), address(0) {
    setName(name);
    setAddress(address);
  }
  virtual ~Person() {
    delete [] name;
    delete [] address;
  }
  void setName(const char *name) {
    delete [] name;
    this->name = strcpy(new char[strlen(name) + 1], name);
  }
  void setAddress(const char *address) {
    delete [] address;
    this->address = strcpy(new char[strlen(address) + 1], address);
  }
  const char *getName() const { return name; }
  const char *getAddress() const { return address; }
 private:
  Person(const Person &other) : name(0), address(0) {
    setName(other.getName());
    setAddress(other.getAddress());
  }
  Person &operator=(const Person &other) {
    if (this != &other) {
      setName(other.getName());
      setAddress(other.getAddress());
    }
    return *this;
  }
  char *name;
  char *address;
};
 
std::ostream &operator<<(std::ostream &stream, const Person &person) {
  return stream << "Person{" <<
    "name=\"" << person.getName() << "\"," <<
    "address=\"" << person.getAddress() << "\"}";
}
 
bool operator<(const Person &a, const Person &b) {
  int compareNames = strcmp(a.getName(), b.getName());
  int compareAddresses = strcmp(a.getAddress(), b.getAddress());
  return (compareNames < 0) || (compareNames == 0 &&
    compareAddresses < 0);
}
 
class Company {
 public:
  Company() : name(0) {}
  Company(const char *name) : name(0) {
    setName(name);
  }
  virtual ~Company() {
    delete name;
  }
  void setName(const char *name) {
    delete [] name;
    this->name = strcpy(new char[strlen(name) + 1], name);
  }
  const char *getName() const { return name; }
 private:
  Company(const Company &other) : name(0) {
    setName(other.getName());
  }
  Company &operator=(const Company &other) {
    if (this != &other) {
      setName(other.getName());
    }
    return *this;
  }
  char *name;
};
 
bool operator<(const Company &a, const Company &b) {
  return strcmp(a.getName(), b.getName()) < 0;
}
 
std::ostream &operator<<(std::ostream &stream, const Company &company) {
  return stream << "Company{" <<
    "name=\"" << company.getName() << "\"}";
}
 
class CompanyOwner {
 public:
  CompanyOwner() : company(0), owner(0) {}
  CompanyOwner(const Company *company, const Person *owner) : company(company),
    owner(owner) {}
  const Company *getCompany() const { return company; }
  const Person *getOwner() const { return owner; }
  void setCompany(Company *company) { this->company = company; }
  void setOwner(Person *owner) { this->owner = owner; }
 private:
  CompanyOwner(const CompanyOwner&);
  CompanyOwner &operator=(const CompanyOwner &);
  const Company *company;
  const Person *owner;
};
 
bool operator<(const CompanyOwner &a, const CompanyOwner &b) {
  return (*a.getCompany() < *b.getCompany()) ||
    ((!(*b.getCompany() < *a.getCompany())) &&
    *a.getOwner() < *b.getOwner());
}
 
std::ostream &operator<<(std::ostream &stream,
  const CompanyOwner &companyOwner) {
  return stream << "CompanyOwner{" <<
    "company=" << *companyOwner.getCompany() << "," <<
    "owner=" << *companyOwner.getOwner() << "}";
}
 
template <class T>
class DataSource {
 public:
  DataSource() : capacity(1000), capacityIncrement(10), size(0),
    data(new T*[capacity]) {}
  virtual ~DataSource() {
    clear();
  }
  const T *find(const T *value) {
    return *lowerBound(data, data + size, value);
  }
  T **begin() { return data; }
  T **end() { return data + size; }
  size_t getSize() const { return size; }
  const T *operator[](size_t i) const {
    return data[i];
  }
  void clear() {
    for (size_t i = 0; i < size; ++i) {
      delete data[i];
    }
    delete [] data;
    size = 0;
  }
  T **add(T *value, bool duplicatesAllowed = false) {
    checkCapacity();
    T **position = lowerBound(data, data + size, value);
    if ((!duplicatesAllowed) && position < end() && (!(*value < **position))) {
      return position;
    }
    for (T **i = end(); i > position; --i) {
      *i = *(i - 1);
    }
    *position = value;
    ++size;
    return position;
  }
  bool erase(T *value) {
    T **position = lowerBound(data, data + size, value);
    if (position < end() && (!(*value < **position))) {
      for (T **i = position; i < data + size - 1; ++i) {
        *i = *(i + 1);
      }
      --size;
      return true;
    }
    return false;
  }
 protected:
  // убеждается, что размер массива достаточен
  void checkCapacity() {
    if (capacity == size + 1) {
      capacity += capacityIncrement;
      T **newData = new T*[capacity];
      for (size_t i = 0; i < size; ++i) {
        newData[i] = data[i];
      }
      delete [] data;
      data = newData;
    }
  }
  // бинарный поиск с реальными сравнениями, логарифмическая сложнсть
  // возвращает указатель на первый элемент списка, который не меньше value
  static T **lowerBound(T **first, T **last, const T *value) {
    int count = last - first;
    while (count > 0) {
      int step = count / 2;
      T **it = first + step;
      if (**it  < *value) {
        first = ++it;
        count -= step + 1;
      } else {
        count = step;
      }
    }
    return first;
  } 
 private:
  DataSource(const DataSource&);
  DataSource &operator=(const DataSource&);
  size_t capacity;
  size_t capacityIncrement;
  size_t size;
  T **data; 
};
 
class PersonSource : public DataSource<Person> {
 public:
  const Person *addPerson(const char *name, const char *address) {    
    Person *person = new Person(name, address); 
    Person **result = add(person);    
    if (*result != person) {
      delete person;
    }
    return *result;
  }
  bool erasePerson(const char *name, const char *address) {
    Person *person = new Person(name, address);
    bool result = erase(person);
    delete person;
    return result;
  }
};
 
class CompanySource : public DataSource<Company> {
 public:
  Company *addCompany(const char *name) {
    Company *company = new Company(name); 
    Company **result = add(company, true);
    if (*result != company) {
      delete company;
    }
    return *result;
  }
  bool eraseCompany(const char *name) {
    Company *company = new Company(name);
    bool result = erase(company);
    delete company;
    return result;
  }
};
 
class CompanyOwnerSource : public DataSource<CompanyOwner> {
 public:
  CompanyOwner *addCompanyOwner(const Company *company, const Person *owner) {
    CompanyOwner *companyOwner = new CompanyOwner(company, owner);
    CompanyOwner **result = add(companyOwner);
    if (*result != companyOwner) {
      delete companyOwner;
    }
    return *result;
  }
  bool eraseCompanyOwner(const Company *company, const Person *owner) {
    CompanyOwner *companyOwner = new CompanyOwner(company, owner);
    bool result = erase(companyOwner);
    delete companyOwner;
    return result;
  }
};
 
int main(int argc, char *argv[]) {
  srand(time(0));
 
  PersonSource personSource;
  
  personSource.addPerson("Ivan", "Lenina, 12");
  personSource.addPerson("Ivan", "Lenina, 12"); //не добавит
  personSource.addPerson("Petr", "Marksa, 78");
  personSource.addPerson("Petr", "Mapi, 35");
  personSource.addPerson("Semen", "Stalina, 6");
  personSource.addPerson("Gennadiy", "Ogorodnaya, 92");
  
  personSource.erasePerson("Petr", "Mapi, 35"); // удаление
 
  // вывод всех
  for (size_t i = 0; i < personSource.getSize(); ++i) {
    std::cout << *personSource[i] << std::endl;
  }
 
  CompanySource companySource;
  
  companySource.addCompany("Vector");
  companySource.addCompany("Vector");
  companySource.addCompany("Slalom");
  companySource.addCompany("Pshpsh");
 
  // вывод всех
  for (size_t i = 0; i < companySource.getSize(); ++i) {
    std::cout << *companySource[i] << std::endl;
  }
 
  CompanyOwnerSource companyOwnerSource;
 
  // заполнение всех компаний случайными владельцами
  for (size_t i = 0; i < companySource.getSize(); ++i) {
    for (int j = 0; j < 10 + rand() % 5; ++j) {
      companyOwnerSource.addCompanyOwner(companySource[i],
        personSource[rand() % personSource.getSize()]);
    }
  }
  
  // вывод на экран
  for (size_t i = 0; i < companyOwnerSource.getSize(); ++i) {
    std::cout << *companyOwnerSource[i] << std::endl;
  }
 
  std::cin.get();
  return 0;
}
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
29.03.2013, 18:00  [ТС]     Связь списков #11
Спасибо. И все же разве оператор delete будучи использован по пустому указателю не пораждает ошибок ?
Tulosba
:)
Эксперт С++
4384 / 3227 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
29.03.2013, 18:04     Связь списков #12
Цитата Сообщение от awpe Посмотреть сообщение
разве оператор delete будучи использован по пустому указателю не пораждает ошибок
Нет.
C++
1
2
int *p = nullptr;
delete p;
Абсолютно корректный код.
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
29.03.2013, 18:16  [ТС]     Связь списков #13
у меня ваш код дает double free or coruption а valgrind выдает 5 ошибок при добавлении персоны, сейчас посмотрел еще раз, валгринд не завершает свою работу, gdb ругается на неверный указатель для free(). ошибки для Person.setname и Person.setaddress. Попробовал разобраться в чем дело, но обнаружил, что ваша программа хранит строки для каждого владельца, т.е. адрес владельца или его имя в памяти может встретиться несколько раз у разных персон, то же и для компаний, или я не прав?

Добавлено через 8 минут
P.S. Я не ленивый, благодарю за код, однако мне научится надо, можете просто словами написать какой подход использовать, я программу сам напишу, иначе потом на зачетных тестах и экзаменах, без интернета... ну вы поняли Несколько листов изрисовал схемами для решения задачи, одна сложнее другой, но чего то доконца работающего на бумаге так и не придумал.
lemegeton
 Аватар для lemegeton
2915 / 1344 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
29.03.2013, 18:26     Связь списков #14
Что за персону добавляете? У вас же дебаггер, в каком месте ошибка? что за текст ошибки?
Это... null вместо const char * не скармливайте -- будут ошибки.

Нашел одну опечатку. В сеттерах, где delete [] name; и delete [] address; должно быть delete [] this->name; и delete [] this->address;. Но эта утечка не должна так себя вести.

Добавлено через 10 минут
Цитата Сообщение от awpe Посмотреть сообщение
P.S. Я не ленивый, благодарю за код, однако мне научится надо, можете просто словами написать какой подход использовать, я программу сам напишу, иначе потом на зачетных тестах и экзаменах, без интернета... ну вы поняли Несколько листов изрисовал схемами для решения задачи, одна сложнее другой, но чего то доконца работающего на бумаге так и не придумал.
Три основных класса:
1. Person, в котором хранятся "владельцы".
2. Company, в котором хранятся "компании".
3. CompanyOwner, в котором хранится пара компания-владелец.

Класс DataSource -- источник данных, который умеет хранить в сортированном массиве любые типы данных, добавлять, искать и удалять их с логарифмической скоростью.

На основе этого класса создано три класса, -- источника данных, -- PersonSource, CompanySource и DataSource. Эти классы оперируют первыми тремя сущностями. Собственно, на основе этих трех классов можно решать разные задачи связанные с предметной областью.

Для сохранения простоты решения классы не слушают события друг-друга.
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
29.03.2013, 18:54  [ТС]     Связь списков #15
Ага, понял - заполнение всех компаний случайными владельцами зацикливается, после того как поправил где надо delete [name] на delete [] this->name / address у компаний и владельцев
lemegeton
 Аватар для lemegeton
2915 / 1344 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
29.03.2013, 18:58     Связь списков #16
Цитата Сообщение от awpe Посмотреть сообщение
Ага, понял - заполнение всех компаний случайными владельцами зацикливается, после того как поправил где надо delete [name] на delete [] this->name / address у компаний и владельцев
С чего бы ему зацикливаться?

Добавлено через 50 секунд
Попробуйте убрать последний std::cin.get(); в перед return 0;.
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
29.03.2013, 19:05  [ТС]     Связь списков #17
При dbg цикл явно длится дольше чем количество сочетаний владельцев и компаний. cin помог, но - total heap usage: 76 allocs, 73 frees, 12,613 bytes allocated.
lemegeton
 Аватар для lemegeton
2915 / 1344 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
29.03.2013, 19:13     Связь списков #18
Цитата Сообщение от awpe Посмотреть сообщение
cin помог
Вы ожидание ввода приняли за зацикливание.

Цитата Сообщение от awpe Посмотреть сообщение
При dbg цикл явно длится дольше чем количество сочетаний владельцев и компаний.
Конечно больше раз. В коде же ясно написано: для каждой компании по 10 - 14 попыток назначения.

Цитата Сообщение от awpe Посмотреть сообщение
total heap usage: 76 allocs, 73 frees, 12,613 bytes allocated.
И в чем проблема?
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
29.03.2013, 19:36  [ТС]     Связь списков #19
Вдохновившись вашей реализации придумал такую:

есть структура StringStruct которая содержит указатель на тип std::string, массив указателей на структуры владельцев и структуры компаний (к каждому массиву еще int количество элементов), т.е. у одной строки есть указатели на места где она используется.

Есть структура владельцев содержит два указателя типа предыдущей структуры а также один указатель на компанию(по условию задачи один владелец - одна компания)

Есть структура компаний содержит массив указателей на структуры владельцев, а также два указателя типа StringStruc на название и адрес. Для массива есть переменная с его размером

В базовом классе создается два массива структур владелецев, физически в памяти структура владельца в единственном экземпляре, но в каждом массиве указатели отсортированы в соответствии с расположением имени или адреса, т.е. первый массив - сортировка по имени, второй по адресу.

Также в базовом классе есть массив структур компаний.


Таким образом имеем два массива строк - все имена/названия и все адреса, множество структур владельцев с доступом черех два массива, и массив компаний.

Все элементы связаны указателями, при записи нового владельца два массива владельцев позволяют провести бинарные поиски по имени и по адресу владельца

При удалении владельца можно сразу посмотреть надо ли удалять ту или иную строку или ту или иную компанию (можно проверить размер соответствеющих массивов в этих структурах и сказать используются они где либо или нет)

При добавлении записи также память выделяется не на один элемент а на текущее (количество элементов)*1.5

Конечно много указателей каждый по 4байта, но если строки длинные то наверное этот факт окупится скоростью?

Добавлено через 2 минуты
Цитата Сообщение от lemegeton Посмотреть сообщение
Вы ожидание ввода приняли за зацикливани
Я в нетбинсах не видел конца программы, а при заупске dbg количество шагов мне показалось бесконечным

Цитата Сообщение от lemegeton Посмотреть сообщение
total heap usage: 76 allocs, 73 frees, 12,613 bytes allocated.
в том что 3 блока не были освобождены это не допустимо по условиям
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.03.2013, 20:37     Связь списков
Еще ссылки по теме:

C++ Программирование списков
C++ Обработка списков
Объединение списков C++
Конкатенация списков C++
Соединение списков C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
lemegeton
 Аватар для lemegeton
2915 / 1344 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
29.03.2013, 20:37     Связь списков #20
Посмотрите, что за три блока "не были освобождены".
Yandex
Объявления
29.03.2013, 20:37     Связь списков
Ответ Создать тему
Опции темы

Текущее время: 12:32. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru