Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.21.41.219] |
|
Сообщ.
#1
,
|
|
|
Не могу придумать, чем реализовать следущюю задачу:
Нужно создать некотурую структуру формата int type | dword h1 | dword h2 кол-во элементов нужно динамически увеличивать. + от чего возникают проблемы - нужно удалять некоторые элементы, при этом нужно иметь возможность искать по элементу структуры. чем бы это реализовать? |
Сообщ.
#2
,
|
|
|
typedef struct _Type { int type DWORD h1 DWORD h2 _Type( int _type, DWORD _h1, DWORD _h2 ): type(_type), h1( _h1 ), h2( _h2 ) {} } StructType; typedef std::vector<StructType> MyVector; typedef MyVector::iterator MyVectorIterator; MyVector m_stlVector; /*добавляем элемент*/ m_stlVector.push_back( StructType( 0,12,12 ) ); m_stlVector.push_back( StructType( 3,10,11 ) ); /*удаляем элемент*/ MyVectorIterator i = std::find(m_stlVector.begin(), m_stlVector.end(), StructType( 0,12,12 )); if( i != m_stlVector.end() ) m_stlVector.erase( i ); |
Сообщ.
#3
,
|
|
|
Спасибо, а можно таким образом добавлять в определённую позицию определённый элемент?
Например сначала помещаем type и h1 потом по h1 находим элемент и добавляем значение h2? И удалять не по маске всех элементов сразу, а по какому-то одному, к примеру h2? Можно ответить просто "можно" и я уйду разбираться с vector =) |
Сообщ.
#4
,
|
|
|
Цитата freecod @ Спасибо, а можно таким образом добавлять в определённую позицию определённый элемент? добавлять/удалять элементы из середины вектора можно, но не рекомендуется - при этом будет произведено копирование всего содержимого вектора, и это будет медленно работать на больших массивах данных. Лучше для этого использовать связанные списки типа std::list<>. А вообще ознакомься со всем STL - разнообразными контейнерами, алгоритмами и проч. |
Сообщ.
#5
,
|
|
|
Цитата добавлять/удалять элементы из середины вектора можно, но не рекомендуется - при этом будет произведено копирование всего содержимого вектора, и это будет медленно работать на больших массивах данных. Лучше для этого использовать связанные списки типа std::list<>. А вообще ознакомься со всем STL - разнообразными контейнерами, алгоритмами и проч. если парядок не важен, то можно так: MyVectorIterator i = std::find(m_stlVector.begin(), m_stlVector.end(), StructType( 0,12,12 )); if( i != m_stlVector.end() ) { std::swap( i, m_stlVector.end() ); m_stlVector.erase( m_stlVector.end() ); } |
Сообщ.
#6
,
|
|
|
freecod
Честно я стандартную библиотеку не знаю . Но для решения этого у меня есть пара заготовок . инклуде файл с классом . информация ложится в динамическую память . надо расширяю надо сужаю . Но это не шаблон , поэтому подгонка занимает время . Но тупиков в работе поменьше . Надо эту инфру кидаю в файл , надо извлекаю . так что если полуфабрикат нужен скажи . Если нет то пользуйся тем что предложили. |
Сообщ.
#7
,
|
|
|
Вообще разбираюсь уже с list, но если не жалко - зааттачь, хорошие сорсы лишними не бывают =)
|
Сообщ.
#8
,
|
|
|
ну это так для ознакомления структура
см по ссылке только вместо массива твоя структура http://www.cyberforum.ru/post55082.html еще вопрос dword это что char или unsigned short . |
Сообщ.
#9
,
|
|
|
dword это 4 байта (double word, word - это слово == 2 байта)
char это 1 байт unsigned short это 2 байта. |
Сообщ.
#10
,
|
|
|
Цитата Dem_max @ dword это 4 байта (double word, word - это слово == 2 байта) char это 1 байт unsigned short это 2 байта. Может он имел ввиду char * ? Да, dword это 4 байта, define к unsigned long Добавлено Я вот смотрю в STL все контейнеры оерентированны на единичные элементы. То есть даже структура помещается как единичный элемент. Но у меня такая задача: вот у меня 3 связанных переменных - int и два dword. их - массив. То есть если бы мне было известно необходимое кол-во элементов я бы задал struct base{ int type; DWORD h1; DWORD h2; }; base some_base[100]; и использовал бы. Но у меня есть такой нюанс - по первых мне нужно по любому элементу этой "тройки" (один элемент структуры, "строчка" из [type, h1, h2]) в соотв. "ряду" найти например где h1 == 12345678 и получить позицию этой "тройки". То есть мне это воображается как-то вроде int pos = find(some_base.h1, 12345678); DWORD need = some_base[pos].h2; то есть обращаться к каждому подэлементу и упрявляться с этим. плюс ещё сколько у меня будет этих "троек" - хз, и они регулярно обновляются - одни удаляю, другие записываю, так что классический struct не подходит... как можно догадаться - это связаные хендлы, которые группируются в реальном времени. То есть list в макро-плане удовлетворяет, но как при этом искать по всем h1, а не по тройкам, найти его позицию, обратится к другим переменным "строки" - не представляю. |
Сообщ.
#11
,
|
|
|
это main.cpp
#include <iostream> using namespace std; #include "struk.h" int main (){ truk ST; struk A[10]; for (int i=0;i<10;i++){ A[i].h1=i; A[i].h2=2*i; A[i].type=3*i; ST.add(A[i]); } cout << ST; cout <<"type=3 N="<<ST.find_type(3)<<endl; cout <<"h1=7 N="<<ST.find_h1(7)<<endl; cout <<"h2=10 N="<<ST.find_h2(10)<<endl; ST.del (5);cout << " del n=5"<<endl; cout << ST; return 0; }; Добавлено это struk.h class struk { public: int h1; int type; int h2; }; class truk { private: char Name[20]; struk * pT; // указатель буфера int Len; public: truk(); ~truk(); void clear(); // очиска буфера void add(struk & St); // добавить элемент struk get(int i); // получить элемент void del(int i); // удалить элемент int find_type(int i); int find_h1 (int i); int find_h2 (int i); friend ostream& operator<< (ostream& theStream,truk & theString); }; truk::truk(){ pT = new struk[0]; Len=0; } truk::~truk(){ delete []pT; Len=0; } void truk::clear(){ delete []pT; pT = new struk[0]; Len=0; } void truk::add(struk & St){ struk *pT2= new struk[Len+1]; int i; for(i=0;i<Len;i++) pT2[i]=pT[i]; pT2[i]=St; delete []pT; pT=pT2; Len++; } struk truk::get(int i){ if (i > Len) i=Len; struk St=pT[i-1]; return St; } void truk::del(int i){ if ((i<=Len)&&(i!=0)){ i--; struk *pT2= new struk[Len-1]; int j,k; for(j=k=0;k<Len;j++,k++){ if (i==j) k++; pT2[j]=pT[k]; } delete []pT; pT=pT2; Len--; } } int truk::find_type(int i){ // k - это найденый номер ; k=0 - такого элемента нет int j,k=0; for(j=0;j<Len;j++) if (pT[j].type==i) k=j+1; return k; } int truk::find_h1(int i){ int j,k=0; for(j=0;j<Len;j++) if (pT[j].h1==i) k=j+1; return k; } int truk::find_h2(int i){ int j,k=0; for(j=0;j<Len;j++) if (pT[j].h2==i) k=j+1; return k; } ostream & operator << (ostream & theStream,truk & AAA ){ theStream <<"N"<<"\t"<<"type"<<"\t"<<"h1"<<"\t"<<"h2 "<< endl; for (int i=0;i<AAA.Len;i++) theStream <<(i+1)<<"\t"<< AAA.pT[i].type <<"\t"<< AAA.pT[i].h1 <<"\t"<< AAA.pT[i].h2 << endl; return theStream; } Добавлено даю тебе словно все int - но если разберешься с кодом то слепишь все завтра если тебе надо кину как этот блок записать или считать с винта . |
Сообщ.
#12
,
|
|
|
насчет поиска:
если че не понятно спрашивай. typedef struct _BaseStruct { int type; unsigned long h1; unsigned long h2; _BaseStruct(){} _BaseStruct( int _type, unsigned long _h1, unsigned long _h2) : type(_type), h1(_h1), h2(_h2) {} } BaseStruct; /* */ static bool _f( const BaseStruct& _val, const unsigned long& _f_value ) { return ( _val.h1 == _f_value ); } /* */ template<class TFValue, class container> typename container::iterator& Find(typename container::iterator& _begin, typename container::iterator& _end, const TFValue& _FindValue, bool (*fun)(const typename container::value_type& _Val, const TFValue& _f_value) ) { typename container::iterator& i = _begin; while ( i != _end ) { if( fun( *i, _FindValue ) ) return i; ++i; } return _end; } typedef std::vector<BaseStruct> MyVector; typedef MyVector::iterator MyVectorIterator; typedef MyVector::const_iterator MyVectorConstIterator; int _tmain(int argc, _TCHAR* argv[]) { MyVector g_stlVector; g_stlVector.push_back( BaseStruct(0,1231321,4564654) ); g_stlVector.push_back( BaseStruct(1,128771,459894) ); g_stlVector.push_back( BaseStruct(2,1266651,46989894) ); MyVectorIterator i = Find<unsigned long, MyVector>(g_stlVector.begin(), g_stlVector.end(), 1266651, &_f ); if( i != g_stlVector.end() ) { printf("type = %d\n" "h1 = %d\n" "h2 = %d\n" ,(*i).type,(*i).h1,(*i).h2); } return 0; } |
Сообщ.
#13
,
|
|
|
Кстати, вопрос про STL. C подключением чего-либо из STL, например #include <string>, как это влияет на размер и работоспособность на разных win-площадках? как я понимаю класс работы целиком прекомпилируется в бинарник и не требует внешних либ? Как конкретно std::string ведёт себя с большими размерами данных, никаких проблем использовать string как хранилище пары сотен кб данных? И когда я сделаю string = ""; память высвободится?
|
Сообщ.
#14
,
|
|
|
это main cpp
#include <iostream> #include <fstream> using namespace std; #include "struk.h" int main (){ truk ST; struk A[10]; for (int i=0;i<10;i++){ A[i].h1=i; A[i].h2=2*i; A[i].type=3*i; ST.add(A[i]); } cout << ST; cout <<"type=3 N="<<ST.find_type(3)<<endl; cout <<"h1=7 N="<<ST.find_h1(7)<<endl; cout <<"h2=10 N="<<ST.find_h2(10)<<endl; ST.del (5);cout << " del n=5"<<endl; cout << ST; save("file.dn",ST); truk D; load("file.dn",D); cout << D; return 0; }; Добавлено это struk.h class struk { public: int type; unsigned long h1; unsigned long h2; }; class truk { private: char Name[20]; struk * pT; // указатель буфера int Len; public: truk(); ~truk(); void clear(); // очиска буфера void add(struk & St); // добавить элемент struk get(int i); // получить элемент void del(int i); // удалить элемент int find_type(int i); int find_h1 (unsigned long i); int find_h2 (unsigned long i); friend ostream& operator<< (ostream& theStream,truk & theString); friend void save(char *NameFile,truk & AA); friend void load(char *NameFile,truk & AA); }; truk::truk(){ pT = new struk[0]; Len=0; } truk::~truk(){ delete []pT; Len=0; } void truk::clear(){ delete []pT; pT = new struk[0]; Len=0; } void truk::add(struk & St){ struk *pT2= new struk[Len+1]; int i; for(i=0;i<Len;i++) pT2[i]=pT[i]; pT2[i]=St; delete []pT; pT=pT2; Len++; } struk truk::get(int i){ if (i > Len) i=Len; struk St=pT[i-1]; return St; } void truk::del(int i){ if ((i<=Len)&&(i!=0)){ i--; struk *pT2= new struk[Len-1]; int j,k; for(j=k=0;k<Len;j++,k++){ if (i==j) k++; pT2[j]=pT[k]; } delete []pT; pT=pT2; Len--; } } int truk::find_type(int i){ // k - это найденый номер ; k=0 - такого элемента нет int j,k=0; for(j=0;j<Len;j++) if (pT[j].type==i) k=j+1; return k; } int truk::find_h1(unsigned long i){ int j,k=0; for(j=0;j<Len;j++) if (pT[j].h1==i) k=j+1; return k; } int truk::find_h2(unsigned long i){ int j,k=0; for(j=0;j<Len;j++) if (pT[j].h2==i) k=j+1; return k; } ostream & operator << (ostream & theStream,truk & AAA ){ theStream <<"N"<<"\t"<<"type"<<"\t"<<"h1"<<"\t"<<"h2 "<< endl; for (int i=0;i<AAA.Len;i++) theStream <<(i+1)<<"\t"<< AAA.pT[i].type <<"\t"<< AAA.pT[i].h1 <<"\t"<< AAA.pT[i].h2 << endl; return theStream; } void save(char *NameFile,truk & AA){ ofstream out(NameFile,ios::out |ios::binary); if(!out) cout <<"files don't open "<<endl; else{ out.write((char*)&AA.Len,sizeof(int)); out.write((char*)AA.pT,(sizeof(struk)*AA.Len)); out.close(); } }; void load(char *NameFile,truk & AA){ ifstream in(NameFile,ios::in |ios::binary); if(!in) cout <<"files don't open "<<endl; else { in.read((char*)&AA.Len,sizeof(int)); AA.pT = new struk[AA.Len]; in.read((char*)AA.pT,(sizeof(struk)*AA.Len)); cout<<"READ OK" <<endl; in.close(); } }; Добавлено freecod хоть спасибо скажет ? ведь в метапрограмировании в шаблонах ему втыкать и не перевтыкать А тут рабочий код с примером как его запускать Удачи!!!! Добавлено freecod использовать char если надо обрабатывать побайтно - тупиковый вариант лучше использовать unsigned short и делить его-побайтно . тогда можно считать файл целиком и поинтером или масивом к нему добраться #include <iostream> using namespace std; int main (){ cout << sizeof(unsigned short)<<" bytes"<< endl; unsigned short A=5; unsigned short B=A/256; unsigned short C=A%256; cout <<A<<"\t"<<B <<"\t"<<C<< endl; return 0; } ладно я умолкаю и отваливаю подальше . |
Сообщ.
#15
,
|
|
|
Изобретаем велосипеды, господа) Причем еще и одноразового использования...
Цитата freecod @ То есть list в макро-плане удовлетворяет, но как при этом искать по всем h1, а не по тройкам, найти его позицию, обратится к другим переменным "строки" - не представляю. Для поиска в контейнерах существуют как минимум 2 стандартных алгоритма: find и find_if. Во втором можно задавать условие для поиска - те искать по одному элементу структуры. К сожалению, при использовании чистого STL это условие должно быть оформлено в виде отдельной функции или класса: bool findFunc(const base& elem) { if (условие) return true; return false; } ... iterator elem = std::find_if(mylist.begin(), mylist.end(), &findFunc); Используя boost, можно уложится и в одну строчку(см boost::bind, boost::lambda) Например, вызов find_if может выглядеть примерно так: find_if(mylist.begin(), mylist.end(), bind(&base::getHandle1, _1) == valueISeek); Цитата qwone @ struk.h Когда делаешь велосипед, большая вероятность напороться на грабли. Вот и здесь, я бы отметил для начала следующее: 1. Отсутствие конструктора копирования - может привести к ошибкам защиты памяти(типа Segmentation Fault) в некоторых случаях(при копировании объекта, например, при передаче его в качестве аргумента в функцию). 2. Неоптимально реализована функция add(), что будет заметно на более-менее больших объемах данных - каждый раз полностью копируется всё содержимое массива, производится вызовы new[] и delete[]. То же с функцией del(). 3. Не шаблон, хотя не так уж и сложно его сделать. 4. Обычно в таких классах перегружается operator[] Цитата freecod @ Кстати, вопрос про STL. C подключением чего-либо из STL, например #include <string>, как это влияет на размер и работоспособность на разных win-площадках? как я понимаю класс работы целиком прекомпилируется в бинарник и не требует внешних либ? В STL используются шаблоны, отсюда она полностью header only, те не требует всяких .lib файлов(исключая разве что потоки cin/cout etc), все функции встраиваемые(inline), что положительно влияет на скорость, и отрицательно - на размер. Что касается std::string, то проблем или тормозов при работе с большими файлами не замечал, хотя особенности реализации тут уже зависят от конкретной версии STL. |
Сообщ.
#16
,
|
|
|
iterator elem = std::find_if(mylist.begin(), mylist.end(), &findFunc); pan2004, да, точно...совсем забыл про нее...ну смысл тот же |
Сообщ.
#17
,
|
|
|
pan2004 ну а теперь перечисли недостатки шаблонов ?
когда ходишь на ходулях . можно с них быстрее слететь. шаблоны требуют еще большего знания и опыта. поэтому не надо спешить лезть на ходули . грабли могут и там тебя достать. |
Сообщ.
#18
,
|
|
|
Цитата pan2004 ну а теперь перечисли недостатки шаблонов ? когда ходишь на ходулях . можно с них быстрее слететь. шаблоны требуют еще большего знания и опыта. поэтому не надо спешить лезть на ходули . грабли могут и там тебя достать. углубление в мето-программирование и конструкцию языка еще ни кому не помешали... в твоих словах я вижу только нежелание... |
Сообщ.
#19
,
|
|
|
Цитата qwone @ pan2004 ну а теперь перечисли недостатки шаблонов ? Недостатки? Полно, не спорю. Например, в большинстве компиляторов до сих пор не реализован экспорт шаблонов, так что они - вещи из категории "header only". В смысле кусок шаблона в библиотеку не скомпилируешь, чтобы он там шаблоном и остался. А если серьезно - нужно бы сравнивать с аналогичными средствами других языков. Таковых я не знаю(очень часто их сравнивают с generics, но это все равно что классы C++ с сишными структурами сравнивать). Цитата qwone @ когда ходишь на ходулях . можно с них быстрее слететь. шаблоны требуют еще большего знания и опыта. Требуют, но начинать то когда-то надо? А то и будете для каждого нового типа данных свой "вектор" изобретать. Кстати, чтобы из этого класса сделать нормальный шаблон, нужно 5 минут(и еще 5 минут потратить на то, чтобы прочитать в учебнике статью - правильно говорят, у страха глаза велики). Для начала уже ничего. Потом присмотритесь к STL, всяких векторов и проч. Цитата qwone @ поэтому не надо спешить лезть на ходули . грабли могут и там тебя достать. Дело не в том, что они могут достать, а в том, сколько раз на одни и те же наступишь. Допустим, у тебя в программе пяток подобных классов(как массив к разным типам). Понадобилось добавить конструктор копирования, и придется править каждый, считай 5 раз на грабли наступил(а то и больше, простого копипаста может быть мало). Был бы шаблон - то почуствовал бы всего один удар деревяшкой по лбу). Юзал бы STL - и не пришлось бы вовсе суетится) |
Сообщ.
#20
,
|
|
|
pan2004
почему я не птица - почему не летаю . Если бы юзал STL то и код был другой . Mожет через месяц будет иначе . И код изменится .Но пока это то что я имею . И то что я собрал . А это неплохая заготовка для идущих следом . Добавлено А я пытался сделать шаблон из этого - не получилось . Сможешь сделай . Да и как запустить .с mail тест файлом. |
Сообщ.
#21
,
|
|
|
Пожалуйста.
template <typename T> //Раз class truk { private: T* pT; //Два int Len; public: truk() { pT = 0;//new T; ?Зачем тут new вообще? Len=0; } truk(truk<T>& const rhs)//Вот этого не было { if (rhs.pT){ pT = new T[rhs.Len]; for (int i = 0; i < rhs.Len; ++i) pT[i] = rhs.pT[i];} else pT = 0; Len = rhs.Len; } ~truk() { delete []pT; Len=0; } void clear() { delete []pT; pT = 0;//new struk[0]; Тоже - к черту new Len=0; } void add(T & const St)// Про указатели константности не забываем, когда полезно { T *pT2= new T[Len+1]; for(int i=0;i<Len;++i)//Вот это может занимать до 99% времени работы программы. Изменять тут ничего не буду - лучше сразу юзать std::vector<> pT2[i]=pT[i]; pT2[Len++]=St; delete []pT; pT=pT2; } T get(int i)const//Ха, тут даже не получится элемент контейнера извне изменить! { if (i > Len) i=Len; if (i <= 0) i = 1; return pT[i-1]; } void del(int i) { // А если мало элементов? if (Len == 0 || (Len == 1 && i == 1)) { Len = 0; delete []pT; pT = 0; return; } if ((i<=Len)&&(i>0)) { i--; T *pT2= new T[Len-1]; int j,k; for(j=k=0;k<Len;j++,k++){ if (i==j) k++; pT2[j]=pT[k]; } delete []pT; pT=pT2; Len--; } } }; сложно? |
Сообщ.
#22
,
|
|
|
спасибо.
где то подобное я переставлял себе . может бы пару моментов бы упустил .Или не пару. только не думаю что vector быстрее будет . хотя С++ не ассемблер и компилятор не идеальный код сделает . только вот не пойму как vector это обойдет . |
Сообщ.
#23
,
|
|
|
Цитата только вот не пойму как vector это обойдет . дело в том что вестор выделяет память на много элементов вперед. т.е. релокация памяти происходит не каждое добавление, а только тогда, когда место поджмает. и когда удаляются элементы, память не особождается. т.е. если был вектор на 10 элементов, а добавили 100, то после удаления размер заризервированной памяти так и остантся для 100 элементов. |
Сообщ.
#24
,
|
|
|
qwone: не заметил, отписал последний вопрос и завалился спать. Так что торжественное спасибо, it's work =)
Добавлено Но все таки, если мне нужно быстрое решение по добавлению и удалению элементов - лучше использовать list? Плюс - как искать по конкретному "столбцу" части элемента понятно, очень прошу объяснить как к конкретному элеенту обратиться. Я сейчас мечусь между готовым классом от qwone и потенциально быстрым list... И <base_class><list_class>::<..._...> ... и ещё много такого в объявлении list честно говоря пугают =) |
Сообщ.
#25
,
|
|
|
вожусь с list. по примеру из книжки не хочет работать
struct base { int type; HANDLE h1; HANDLE h2; std::string mem_page; DWORD page_size; }; std::list <base> hold; main{ // не пашет добавление =( hold.push_back(base(i, 0,0,"",0)); // мне при создании элемента нужно записать type и h1, остальные элементы не определенны ... find // теперь найти по h1? // и сразу записать в этот элемент значение h2 и mem_page // а теперь по h2 найти элемент и удалить его |
Сообщ.
#26
,
|
|
|
конструктор определи для структуры.
А еще лучше - почитай что-нибудь умное по C++ |
Сообщ.
#27
,
|
|
|
Цитата freecod @ вожусь с list. по примеру из книжки не хочет работать struct base { int type; HANDLE h1; HANDLE h2; std::string mem_page; DWORD page_size; }; std::list <base> hold; main{ // не пашет добавление =( hold.push_back(base(i, 0,0,"",0)); // мне при создании элемента нужно записать type и h1, остальные элементы не определенны ... find // теперь найти по h1? // и сразу записать в этот элемент значение h2 и mem_page // а теперь по h2 найти элемент и удалить его Что за книжка такая, в которой такую чушь пишут ? Как уже сказал trainer, определи конструктор, который вызываешь при помещении элемента в список. Вот тут, ты вызываешь конструктор base( i, 0, 0, "", 0 ): hold.push_back(base(i, 0,0,"",0)); Но определние этого конструктора в описании класса отсутствует. struct base { int type; HANDLE h1; HANDLE h2; std::string mem_page; DWORD page_size; // добавляем конструктор: base( int, HANDLE, HANDLE, const std::string &, DWORD ); }; Ну и естественно, нужно реализовать этот конструктор Может быть еще дефолтовый конструктор тоже понадобится. |
Сообщ.
#28
,
|
|
|
Цитата Может быть еще дефолтовый конструктор тоже понадобится. понадобится... |
Сообщ.
#29
,
|
|
|
Цитата maxim84_ @ Цитата Может быть еще дефолтовый конструктор тоже понадобится. понадобится... Теоретически - необязательно. |
Сообщ.
#30
,
|
|
|
freecod можно бы и и сделать вектороподобным - алгоритм <vector> я понял как он работает . там надо просто с запасом брать память и просто двигать , а не создавать заново.
или даже <deque> . <list> тоже можно эмулировать .Hо действительно , как сказал pan2004 надо расти дальше . Вот и буду расти. |