2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Связь списков27.03.2013, 18:29. Показов 1573. Ответов 22
Метки нет (Все метки)
Доброго времени суток,
В процессе решения задачи, встретилась проблема: есть структура
Что я делал: Идет запрос на добавление структуры (с указанием значений для ее элементов), тогда проверяется есть ли в
в массиве выделяется память под указатель
Далее в цикле (если конечно индекс не больше числа элементов в массиве до дополнения, иначе после выделения памяти элемент запишется в последнюю ячейку):
Это лишь малая часть программы, пока я писал остальные части я проводил тестирование (совпало) на строках идущих по порядку, соответсвенно никаких повторяющихся данных (типа std::string во всяком случае) и все в нужном порядке, но когда написав много кода, я ввел строки идущие не попорядку я удивился выводу, содержимое структур не соответсвовало ожиданиям, оно и понятно вот здесь:
Что можете предложить? Добавлено через 6 минут P.S. доступные библиотеки :
0
|
27.03.2013, 18:29 | |
Ответы с готовыми решениями:
22
Связь полей из 2(3) списков Связь выпадающих списков и календаря на форме Связь выпадающих списков в одной форме Связь таблиц управляемых списков по различным полям |
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
|
|
28.03.2013, 08:06 | 3 |
Не замутненный поток сознания.
Абзац на полторы тыщи символов в трех предложениях совершенно нечитаем. Взаимоисключающие параграфы детектед: + std::string тоже часть STL. Предлагаю сделать две вещи: 1. Кратко и емко изложить суть вопроса; 2. Выложить полностью исходный текст задания.
0
|
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
|
|
28.03.2013, 08:34 | 4 |
Ммм. А вообще, постановка задачи имеется? А то правда, то что делаете вы - слишком огромно. Что вообще требовалось - с этого и надо было начинать!
0
|
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
|||||||||||
28.03.2013, 11:59 [ТС] | 5 | ||||||||||
конструктор класса без параметров деструктор освобождает память метод 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... Везде только указатели, строки хранятся только во вспомогательном классе в единственном экземпляре... пока так: Кликните здесь для просмотра всего текста
Добавлено через 1 минуту Может у меня подход вообще не правильный...?)
0
|
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
|
28.03.2013, 14:23 [ТС] | 7 |
Почему? и как мне тогда выделять память под новый массив указателей? Единственное что приходит в голову это создавать временный массив указателей новой размерности и копировать туда содержимое старого, потом delete старый массив и копирование в ту старую переменную указатель на новый массив указателей, но разве тогда я не потеряю в скорости? Мой класс еще далек от совершенства, но там я держу два массива, в одном строки отсортированы а другой хранит ссылки на строки чтобы обеспечивать доступ к ним после сортировки (как то так), в бд mysql я бы сделал таблицу с тремя полями - содержимое строки, ее порядковый номер в таблице и ее не изменяемый адрес, т.е. со стороны можно организовать доступ к конкретной строке в не зависимости от сортировки + можно работать с индексами строк в алфавитном порядке, те строка номер(индекс) 1 соответствует той строке которая сейчас на первом месте в таблице (сортировка по алфавиту). Вопрос - как бы выглядело подобное в c++ ? И насчет подхода - может можно сделать все проще (без map, vector)?
0
|
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
|
|
28.03.2013, 20:19 | 8 |
А не проще бы было, не сортировать именно строки в первом списке, а сортировать указатели. У тебя массив указателей на строки. Сортируешь эти указатели в списке так, чтобы строки в них были отсортированы. Тогда и указатели не собьются...
0
|
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
||||||
29.03.2013, 05:47 [ТС] | 9 | |||||
nonedark2008, Либо вы невнимательны либо я плохо описал происходящее) Всю эту эквилибристику с классами и массивами я затеял, в том числе и для того, чтобы проводить операции над указателями а не над строками, т.е. по моим соображениям строки хранятся программой в единственно виде, будучи отсортированы в одном массиве, указатели на них, оданако, также содержатся и в другом массиве, но там индекс соответствует порядку их вложения, таким образом при обращении к объекту по указателю, до вложения новой строки получаем указатель на нее, и при обращении после, указатель получим тот же самый, не смотря на то, что строки были отсортированы, и у некоторых (иногда всех если строка на первом месте) изменился указатель в том отсортированом массиве, объект данного класса все равно вернет указатель на ту же самую строку, во всяком случае такая задумка. Сейчас думаю о третьем массиве булевых значений, в котором индексы будут соответствовать индексам в массиве неотсортированых строк, значния 0 или 1, много памяти не займут, зато так я обозначу те индексы в неотсортированом массиве которые ссылаются на адрес под который не выделена память, это следует из алгоритма - после удаления строки, изменяется размер того массива который содержит отсортированые строки, после delete одной строки, указатель на нее не действителен, а он есть в неотсортированом массиве и здравствуй segfault при попытке чтения, отсортировать данные там и освободить место не получится т.к. массив (поправьте если ошибаюсь) начинается на каком то адресе, а каждый следующий эдемент это просто следующая ячейка памяти (размер "ячейки" диктуется типом) так что для сохранения первоначальной ссылки на строку менять адреса там нельзя иначе потом там где была строка "строка ваня" будет "строка петя".
Еще вопрос - может вместо булевых значений использовать целые 32битные? вроде как при сравнении проессору быстрее сравнить два числа одного типа чем заниматься приведением типов? Самое плохое что осталось три дня до здачи) Добавлено через 26 минут *сдачи Добавлено через 3 часа 11 минут Кликните здесь для просмотра всего текста
Если не лень, попробуйте строковый класс, у меня вроде нормально работает, валгринд не ругается...
0
|
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
|
||||||
29.03.2013, 16:34 | 10 | |||||
Точно. Вообще не правильный. С полученным интерфейсом будет просто невозможно работать. Воспользуйтесь классами.
Вот пример по вашей задаче. Из STL только iostream. Бинарный поиск, никаких копирований, размещение сортированными массивами.
1
|
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
|
29.03.2013, 18:00 [ТС] | 11 |
Спасибо. И все же разве оператор delete будучи использован по пустому указателю не пораждает ошибок ?
0
|
2 / 2 / 1
Регистрация: 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. Я не ленивый, благодарю за код, однако мне научится надо, можете просто словами написать какой подход использовать, я программу сам напишу, иначе потом на зачетных тестах и экзаменах, без интернета... ну вы поняли Несколько листов изрисовал схемами для решения задачи, одна сложнее другой, но чего то доконца работающего на бумаге так и не придумал.
0
|
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
|
|
29.03.2013, 18:26 | 14 |
Что за персону добавляете? У вас же дебаггер, в каком месте ошибка? что за текст ошибки?
Это... null вместо const char * не скармливайте -- будут ошибки. Нашел одну опечатку. В сеттерах, где delete [] name; и delete [] address; должно быть delete [] this->name; и delete [] this->address;. Но эта утечка не должна так себя вести. Добавлено через 10 минут Три основных класса: 1. Person, в котором хранятся "владельцы". 2. Company, в котором хранятся "компании". 3. CompanyOwner, в котором хранится пара компания-владелец. Класс DataSource -- источник данных, который умеет хранить в сортированном массиве любые типы данных, добавлять, искать и удалять их с логарифмической скоростью. На основе этого класса создано три класса, -- источника данных, -- PersonSource, CompanySource и DataSource. Эти классы оперируют первыми тремя сущностями. Собственно, на основе этих трех классов можно решать разные задачи связанные с предметной областью. Для сохранения простоты решения классы не слушают события друг-друга.
0
|
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
|
29.03.2013, 18:54 [ТС] | 15 |
Ага, понял - заполнение всех компаний случайными владельцами зацикливается, после того как поправил где надо delete [name] на delete [] this->name / address у компаний и владельцев
0
|
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
|
|
29.03.2013, 18:58 | 16 |
С чего бы ему зацикливаться?
Добавлено через 50 секунд Попробуйте убрать последний std::cin.get(); в перед return 0;.
1
|
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
|
29.03.2013, 19:05 [ТС] | 17 |
При dbg цикл явно длится дольше чем количество сочетаний владельцев и компаний. cin помог, но - total heap usage: 76 allocs, 73 frees, 12,613 bytes allocated.
0
|
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
|
|
29.03.2013, 19:13 | 18 |
Вы ожидание ввода приняли за зацикливание.
Конечно больше раз. В коде же ясно написано: для каждой компании по 10 - 14 попыток назначения. И в чем проблема?
0
|
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
|
|
29.03.2013, 19:36 [ТС] | 19 |
Вдохновившись вашей реализации придумал такую:
есть структура StringStruct которая содержит указатель на тип std::string, массив указателей на структуры владельцев и структуры компаний (к каждому массиву еще int количество элементов), т.е. у одной строки есть указатели на места где она используется. Есть структура владельцев содержит два указателя типа предыдущей структуры а также один указатель на компанию(по условию задачи один владелец - одна компания) Есть структура компаний содержит массив указателей на структуры владельцев, а также два указателя типа StringStruc на название и адрес. Для массива есть переменная с его размером В базовом классе создается два массива структур владелецев, физически в памяти структура владельца в единственном экземпляре, но в каждом массиве указатели отсортированы в соответствии с расположением имени или адреса, т.е. первый массив - сортировка по имени, второй по адресу. Также в базовом классе есть массив структур компаний. Таким образом имеем два массива строк - все имена/названия и все адреса, множество структур владельцев с доступом черех два массива, и массив компаний. Все элементы связаны указателями, при записи нового владельца два массива владельцев позволяют провести бинарные поиски по имени и по адресу владельца При удалении владельца можно сразу посмотреть надо ли удалять ту или иную строку или ту или иную компанию (можно проверить размер соответствеющих массивов в этих структурах и сказать используются они где либо или нет) При добавлении записи также память выделяется не на один элемент а на текущее (количество элементов)*1.5 Конечно много указателей каждый по 4байта, но если строки длинные то наверное этот факт окупится скоростью? Добавлено через 2 минуты Я в нетбинсах не видел конца программы, а при заупске dbg количество шагов мне показалось бесконечным в том что 3 блока не были освобождены это не допустимо по условиям
0
|
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
|
|
29.03.2013, 20:37 | 20 |
Посмотрите, что за три блока "не были освобождены".
0
|
29.03.2013, 20:37 | |
29.03.2013, 20:37 | |
Помогаю со студенческими работами здесь
20
Как сделать связь выпадающих списков страна, город? Объединение 2 и более списков в список списков по индексу без использования циклов Как сложить сумму из чисел сотен списков и узнать количество списков? Перестановка списков заданных уровней, учитывая промежуточное состояние списков Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |