bebabo
|
|
« : 15-10-2007 16:22 » |
|
Столкнулся со странной проблемой. Есть класс, в нем static vector и static функция, которая работает с этим вектором, проверяя каждый объект на соответствие некому условию и если true - вырезает этот объект из вектора. vector<Transition>::iterator t = Transition::trans.begin(); while(t != Transition::trans.end()){ if(CheckShapeType((*t).GetFromShape(), sh)){ trans.erase(t++); } } Результат - все те объекты, которые должны быть удалены - удаляются за исключением одного. Он полностью соответствует условия удаления, но не вырезается. Точнее, вырезается, если запустить цикл повторно. Пробовал заменить вектор на список - еще хуже - уходит в бесконечный цикл. Что здесь может быть не так?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 15-10-2007 16:44 » |
|
Есть класс, в нем static vector и static функция
в студию класс, в нем static vector и static функцию
|
|
|
Записан
|
|
|
|
bebabo
|
|
« Ответ #2 : 15-10-2007 16:51 » |
|
class Transition : public Shape{ protected: string from_shape; string to_shape; string to_shape_text; string trigger; string body; string else_part; public: static vector <Transition> trans; public: Transition(std::string& _name, CVisioShape& shape); string GetFromShape(); string GetToShape(); string GetTrigger(); string GetBody(); static void ClearTransitions(); private: void SetBody(); bool SetTrigger(); };
код статичной функции в предыдущем посте функция для проверки условия удаления bool CheckShapeType(string& str, string& shape_type){ std::string::size_type i = str.find(shape_type); return (i != std::string::npos) ? true : false; }
|
|
« Последнее редактирование: 15-10-2007 16:53 от bebabo »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #3 : 15-10-2007 17:08 » |
|
проведи эксперимент: bool CheckShapeType(string& str, string& shape_type) { return true; }
всё ли удалится или тоже один элемент останется ?
|
|
|
Записан
|
|
|
|
bebabo
|
|
« Ответ #4 : 15-10-2007 17:23 » |
|
так работает корректно. и список и вектор. без всякой проверки тоже удаляет нормально. ну, теперь хотя бы ясно, где проблема)
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #5 : 15-10-2007 17:29 » |
|
bebabo, у меня нет уверенности, что постфиксный ++ работает корректно. Я бы сделал цикл на for - и нагляднее и надежнее.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
bebabo
|
|
« Ответ #6 : 15-10-2007 17:30 » |
|
RXL, пробовал. результат тот же
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #7 : 15-10-2007 17:47 » |
|
Кстати - "return (i != std::string::npos) ? true : false;" - масло маслянное: оператор неравенства уже возвращает логическое значение. Проверь: for (vector<Transition>::iterator t = trans.begin(); t != trans.end(); t++) if (CheckShapeType(t->GetFromShape(), sh)) trans.erase(t++); GetFromShape() - я бы и тут проверил.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
bebabo
|
|
« Ответ #8 : 15-10-2007 17:59 » |
|
Кстати - "return (i != std::string::npos) ? true : false;" - масло маслянное: оператор неравенства уже возвращает логическое значение. кстати, да) GetFromShape - просто возвращает стринг from_shape проверил. один так и не удалился
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 15-10-2007 18:06 » |
|
bebabo, а что за жестокая заморочка тут std::string::size_type i = str.find(shape_type); return (i != std::string::npos) ? true : false;
, не проще ли while(...) { if((*t).GetFromShape() == sh) { ... } }
? или нету там оператора сравнения ?
|
|
|
Записан
|
|
|
|
bebabo
|
|
« Ответ #10 : 15-10-2007 18:20 » |
|
Алексей1153++, насчет заморочки - функция CheckShapeType принимает два строковых аргумента from_shape и sh и далее определяет есть ли в from_shape вхождения sh. например, from_shape = "transition.12" или "transition.5", а sh = "transition". в данном случае будет true
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 15-10-2007 18:31 » |
|
странно, а что за циферка на конце ?
|
|
|
Записан
|
|
|
|
bebabo
|
|
« Ответ #12 : 15-10-2007 18:49 » |
|
Алексей1153++, циферка... как бы это объяснить ) циферка - это что-то вроде порядкового номера, так в visio (пишу плагин для него) именуются фигуры. например, если нарисовать условие перехода (transition), то эта фигура будет названа transition, следующая transition.1, ну и т.д.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #13 : 15-10-2007 19:00 » |
|
bebabo, в общем, поставь точку прерывания в CheckShapeType и посмотри, что там в параметрах происходит. Кстати, я бы объявил так: bool CheckShapeType(const string& str, const string& shape_type); Ты же их не изменяешь в функции, а оптимизатору в помощь и вообще надежнее.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #14 : 15-10-2007 19:08 » |
|
Для меня пока ясно лишь одно. Если один элемент остаётся, то условие, как минимум, один раз НЕ выполняется.
bebabo, попробуй, чтобы исключить подозрения на erase, убрать проверку условия и просто удалить все элементы.
зы Согласен, с мнением, что код очено запутано написан. Это уменьшает место, но резко снижает читабельность и понимание.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #15 : 15-10-2007 19:27 » |
|
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
bebabo
|
|
« Ответ #16 : 16-10-2007 18:15 » |
|
бился весь день и только что обнаружил идиотскую ошибку в первоначальном варианте цикла while(t != Transition::trans.end()){ if(CheckShapeType((*t).GetFromShape(), sh)){ trans.erase(t++); } } инкремент t происходит только когда CheckShapeType возвращает true. исправил, запустил все получилось как надо. то что я принимал в случае со списком за бесконечный цикл было просто зависанием цикла на случае false. но почему этот цикл не зависает в случае с вектором - загадка. и почему не срабатывает вариант с for(; - тоже не понимаю
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #17 : 17-10-2007 05:18 » |
|
Думаю, что с for тоже срабатывает, но там тоже притаилать ошибка.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #18 : 17-10-2007 05:21 » |
|
bebabo, перепиши всё в максимально читаемом виде для начала, а когда отладишь - сократишь. И то сильно усердствовать в уплотнении не стОит
|
|
|
Записан
|
|
|
|
blob
Гость
|
|
« Ответ #19 : 18-04-2008 14:29 » |
|
Столкнулся со странной проблемой. Есть класс, в нем static vector и static функция, которая работает с этим вектором, проверяя каждый объект на соответствие некому условию и если true - вырезает этот объект из вектора. vector<Transition>::iterator t = Transition::trans.begin(); while(t != Transition::trans.end()){ if(CheckShapeType((*t).GetFromShape(), sh)){ trans.erase(t++); } } Результат - все те объекты, которые должны быть удалены - удаляются за исключением одного. Он полностью соответствует условия удаления, но не вырезается. Точнее, вырезается, если запустить цикл повторно. Пробовал заменить вектор на список - еще хуже - уходит в бесконечный цикл. Что здесь может быть не так? Первое - а как оно вообще до конца доходит, когда if не возвращает true? Тогда же инкрементов не будет. Второе - как по мне, не удаляется элемент тогда, когда два элемента, которые необходимо удалить, идут последовательно. Я тут набросал тестовый код, если его скомпилить сl.exe от 2003 студии, то вроде бы работает, но второй элемент в векторе остаётся. В 2005 студии скомпилированный код при запуске выдаёт страшные маты по поводу того, что vector iterators incompatible. По-моему справедливо, т.к. действия выполняются в таком порядке: 1) возвращается текущая позиция t 2) инкремент 3) erase 4) после erace все итераторы вектора, указывающие на элементы, лежащие после удалённого, невалидны. Это вектор, а он располагается в памяти последовательно. У него нет указателей на next и previous, как у списка. Тестовый код: #include <vector> #include <iostream>
int main() { std::vector<int> v; v.push_back(1); v.push_back(2); std::vector<int>::iterator i = v.begin(); while(i != v.end()) v.erase(i++); for(std::vector<int>::iterator j = v.begin(); j != v.end(); ++j) std::cout << *j; } попробуй использовать алгоритм std::remove_if (из заголовочного файла <algorithm>). Он перенесёт все элементы, подлежащие удалению, в конец вектора, и вернёт указатель на первый из "удалённых" элементов. Далее вызываешь Transition::trans.erase("тот итератор, что вернул remove_if", Transition::trans.end()); и все ненужные элементы удалены.
|
|
|
Записан
|
|
|
|
blob
Гость
|
|
« Ответ #20 : 18-04-2008 14:35 » |
|
вернёт remove_if не указатель, а vector<Transition>::iterator
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #21 : 21-04-2008 05:03 » |
|
вернёт remove_if не указатель, а vector<Transition>::iterator в релизной сборке итератор вектора это указатель. согласен насчет remove_if, имхо более правильный подход
|
|
|
Записан
|
Странно всё это....
|
|
|
|