Урок: разбираем списки, часть 1 : Эльфостроение : Форум |
arban: |
09.11.09, 19:22 |
И так, цель нашего урока - понять зачем нужны списки объектов (LIST'ы, листы). Допустим, нам надо сделать эльф, который будет читать из файла какие-то данные и выводить их удобным образом, например в виде пунктов, или выводить список файлов в папке - примеров можно придумать кучу. Таким образом - листы помагают удобно и быстро распределять объекты в памяти. Это удобство достигается специальными функциями для работы со списками: Код: LIST *List_New(void); void List_Free(LIST *lst); void ListElement_AddtoTop(LIST *lst,void *newElement); void * ListElement_Remove(LIST *lst,int index); int ListElement_Prt2NumElement(LIST *lst,void *ptr); int ListElement_Find(LIST *lst,void *element, int (*cmp_proc)(void *,void *)); void * ListElement_GetByIndex(LIST * , int index); void ListElement_Add(LIST *lst,void *newElement); void List_FreeElements(LIST *,int (*cmp_proc)(void * elem_from_list),void (*freefunc)(void * elem_from_list)); void ListElement_Insert(LIST *lst, int i, void *new_item); Сейчас все функции мы разбирать не будем, а рассмотрим основные моменты. Для начала необходимо создать список. Он будет находится в переменной list. Перед этим расскажу немного о структуре LIST: Код: typedef struct { u16 unk;//неизвестно u16 FirstFree;//кол-во пунктов void **listdata;//массив с данными }LIST; Теперь приступим! 1. Объявляем list как указатель: Код: LIST * list; 2. Создаем свою структуру, содержащую какое-то число и строку, и называем её ITEM: Код: typedef struct { int number;// число wchar_t * string;//строка }ITEM; 3. Пишем функцию для создания списка, она не будет возвращать никакого значения, поэтому её тип - void, также она не содержит параметров. Я делаю для этого отдельную функцию только для оптимизации при использовании её в нескольких местах, да и код выглядит красивее. Ещё советую давать понятные имена функциям, например: List_Create, List_Destroy, List_Save и т.д. Код: void List_Create() { list=List_New();//выделяем память под список for(int i=0;i<10;i++)//запускаем цикл для добавления 10-ти пунктов { ITEM *item=new ITEM; //создаем новую переменную типа ITEM memset(item,0,sizeof(ITEM));// выделяем для неё память item->number=i;//присваиваем переменной number в структуре ITEM текущего пункта значение i wchar_t buf[1];//создаем так называемый буффер, для хранения временной строчки //тип wchar_t - строка в кодировке Unicode snwprintf(buf, 2, L"%d", i);//функцией записываем в буффер число как строку item->string=new wchar_t[wstrlen(buf)+1];// выделяем память под строку //string в структуре ITEM в размере буффера buf //единицу прибавлять в таком случае обязательно! //иначе символ L'\0' не запишется в строку wstrcpy(item->string, buf); //наконец, копируем в item->string строку buf ListElement_Add(list, item);//добавляем всё это дело в список } } Вроде бы всё расписал тут, что не понятно - не стесняйтесь спрашивать. Эту функцию очень легко отредактировать под свои нужды. 4. Теперь пришло время функции уничтожения списка, назовем её List_Destroy, также для удобства напишем простенький макрос: Код: #define DELETE(a) if (a) {delete(a);a=0;} //если объект a не равен 0, то очищаем память, занятую им Код: void List_Destroy() { if (list)//если список list существует { while (list->FirstFree)//если есть ещё пункты в списке { ITEM* it=(ITEM*)ListElement_Remove(menu->list,0);//удаляем пункт с индексом(номером) 0 //из списка и присваиваем его указатель переменной it. //Можно удалять и последний пункт, но так удобней. DELETE(it->string);// очищаем память, выделенную под строку it->string DELETE(it);//очищаем память, выделенную под сам пункт it } List_Free(list);//удаляем список } } Если вы не поняли зачем List_Destroy - при создании списка вы выделяли память под список, пункты, строки в пунктах, если это всё не "убивать" то происходит утечка памяти, тоесть нужно очистить память, занятую этими объектами. 5. Располагаем функции где нам необходимо, например: - List_Create помещаем в main - List_Destroy в onMyBookClose (в ту функцию, где обрабатывается ивент закрытия книги) Лучше всего уничтожать лист, когда он уже не используется. Вот, собственно, на сегодня и всё. Что не так, не понятно и т.д. - отписывайтесь :) (c)arban |
den_po: |
09.11.09, 19:33 |
arban пишет: - List_Destroy обязательно (!!!) помещать при закрытии книги смущает это заявление куча списковых функций, тех, что есть в либе, и что нету, описана тут http://supertrubka.org/wiki/doku.php?id=index&idx=firmware |
mmcorp: |
30.09.10, 21:31 |
я бы рекомендовал в функции List_Destroy() удалять последний элемент из списка, так как при его "выемки" из списка сдвига элементов происходить не будет, работать очищение листа будет в разы быстрее, особенно для листов с количеством элементов >>5000 |
URL этой темы: https://mobilefree.justdanpo.ru/newbb_plus/viewtopic.php?topic_id=4462 © 2005-2018 supertrubka.org |