C автоматически расширяемый массив указателей - PullRequest
4 голосов
/ 26 января 2011

ВОПРОС, ОТВЕТНЫЙ НА КОНЕЦ СТРАНИЦЫ. ПОЛНОСТЬЮ РАБОЧИЙ КОД.

Здравствуйте, я хотел бы сделать в C то, что я просил в названии, однако я не знаю, как это сделать. Я сделал это на C ++ благодаря шаблонам, но а-ля C . Вот полнофункциональный код C ++: List.h (простая база данных)

* Интересно, смогу ли я эмулировать код с помощью указателей void? Проблема в том, что я видел ссылку, в которой говорится, что void * следует избегать, потому что это может вызвать больше проблем, чем решить.

По сути, это «умный массив», в котором хранятся указатели на сами переменные. Если я знаю размер каждого указателя и размер каждой структуры, на которую указывают, простые malloc и reallocs должны работать правильно?

typedef struct
{
  void **list;

  // internal
  int last_item_index;
  size_t element_size; // size of each pointer
  int elements;        // number of currently allocated elements
  int total_size;      // >= #elements so that we don't have to always call malloc
  int tweak_request_size; // each time the list grows we add this # of elements

} List;
// a shot at an addCopy function
// it deepcopies the object you pass in
List_addCopy(List *db, void *ptr_to_new_element)
{
  ... // grow **list
  // alloc and copy new element
  db->list[db->last_item_index+1] = malloc(element_size); // WORKS?
  // HOW TO COPY THE ELEMENT TO HERE IF IT IS A STRUCTURE FOR INSTANCE???
  ...
}

or
// a shot at an assign function 
// (allocate the elements yourself then pass the pointer to the List)
List_assign(List *db, void *ptr_to_new_element)
{
  db->List = realloc(db->List, element_size*(elements+tweak_request_size));
  db->List[db->last_item_index+1] = ptr_to_new_element;
}

// Usage example

List db; // our database
struct funky *now = (funky*)malloc(sizeof(funky));

funky->soul = JamesBrown;

List_addCopy(db, funky);

if (list[0]->soul == JamesBrown)
  puts("We did It! :D");

Если я выделю все снаружи и просто передам указатели в Список, я думаю, единственная проблема - пустота **.

Возможен ли List_add? Только с обратными вызовами, которые делают alloc элемента и / или копируют его?

Возможен ли List_assign? Я не хочу много работать и в конечном итоге получить ненадежное программное обеспечение.

Большое спасибо и извините за свертку в письменной форме: p

Ответы [ 2 ]

1 голос
/ 27 января 2011

Я использовал метод Тринидада, так как я не был уверен, void ** сработает, и это довольно приятно xD

Он работает отлично, но сложно избежать циклических зависимостей (включая заголовок в другом, который приводит кв «множественных ссылках»), не перегружая интерфейс, поэтому я отказался от этого подхода, хотя я тоже загрузил его @SourceForge, затем я сделал все снова, на этот раз с пустыми указателями, и он работает отлично;) Не беспокойтесь о включениизаголовок дважды и т. д. Просто работает.

Кстати, вот ссылка, используйте ее на свое усмотрение: Список - универсальный && универсальный контейнер

В любом случае используйтена форумах помощи, когда у меня будет время, я документирую это, но сейчас я использую его для своих проектов.

1 голос
/ 26 января 2011

Вы можете избежать void* примерно так:

#include <stdio.h>
#include <stdlib.h>

#define List(T) \
    typedef struct { \
        T** items; \
        int count;  \
    } List_ ## T ;\
    \
    List_ ## T * List_ ## T ## _New() { \
        List_ ## T * list = (List_ ## T *) malloc(sizeof(List_ ## T)); \
        list->count = 0; \
        return list; \
    } \
    \
    void List_ ## T ## _Add(List_ ## T *list, T * data) { \
        printf("%d\n", ++list->count); \
    } \
    void List_ ## T ## _Del(List_ ## T *list, int index) { \
        printf("%d\n", --list->count); \
    }

/* define just one list per type */
List(int);
List(double);

int main()
{
    int a, b, c;
    double d, e;
    List_int *l1;
    List_double *l2;

    l1 = List_int_New();
    List_int_Add(l1, &a);
    List_int_Add(l1, &b);
    List_int_Add(l1, &c);
    List_int_Del(l1, 0);
    List_int_Del(l1, 0);
    List_int_Del(l1, 0);
    free(l1);

    l2 = List_double_New();
    List_double_Add(l2, &d);
    List_double_Add(l2, &e);
    List_double_Del(l2, 0);
    List_double_Del(l2, 0);
    free(l2);

    return 0;
}

Это шаблон бедняка =)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...