Git - это система контроля версий, используемая для отслеживания изменений в компьютерных файлах. Это инструмент для управления вашим кодом & amp; История файлов при координации работы удаленно над этими файлами с другими. Просто установите git и начинайте. Вы можете скачать его на www.git-scm.com. В версии laravel 5.7 вам понадобится git
.Универсальный список, вероятно, будет отдельно связан и вероятно предполагает, что объекты в списке имеют структуру как это:
typedef struct list_item list_item;
struct list_item
{
list_item *next;
...data for node...
};
Используя это расположение, можно записать функции для управления списками, использующими просто прямые указатели.
Иногда,'...data for node...
'будет простое'void *
'; то есть, элементы списка будут содержать указатели на следующий узел в списке (или ПУСТОЙ УКАЗАТЕЛЬ, если будет никакой следующий узел), и указатели на данные.
typedef struct list list;
struct list
{
list *next;
void *data;
};
Так как можно бросить любой указатель на'void *
', у Вас может быть любое соединение типов данных в списке - но Ваш код должен знать, как обработать их.
Вы спрашиваете об универсальной функции списка, но вероятно, нет единственного дизайна one-function-does-all и конечно не простого. Существует много возможных наборов функций, которые могли сделать универсальные функции списка. Один набор, вдохновленный Lisp, состоял бы из:
void *car(list *lp); // Return the data for the first item on the list
list *cdr(list *lp); // Return the tail of the list
list *cons(list *lp1, list *lp2); // Construct a list from lists lp1 and lp2
list *cond(list *lp, void *data); // Append data item to list
Вы, вероятно, хотите обеспечить способность протестировать, пуст ли список, и несколько других объектов.
Одна хорошая выставка, по общему признанию в C++, найдена в "Размышлениях Koenig на C++". Идеи могут быть адаптированы в C довольно легко - это не ужасно твердо (хотя управление хранением в C более трудно, чем в C++).
C не имеет никакого понятия "универсальных" указателей или объектов - самое близкое, которое можно получить, использует a void*
указатель. Если Вы хотите, чтобы одна часть кода смогла обработать какой-либо тип данных, в значительной степени необходимо использовать void*
указатели. Для типов данных с размерами, не больше, чем указатель, можно бросить между типом и void*
; для больших типов данных необходимо будет использовать динамическую память и иметь void*
членская точка к динамической памяти. Просто не упустите утечки памяти!
typedef struct list_node {
struct list_node *next;
void *data;
} list_node;
void list_insert(list_node *node, void *data) {
// ...
}
С другой стороны, если Вы хотите сгенерировать код для каждого возможного типа данных, необходимо будет сделать это с макросами и затем инстанцировать макросов для каждого типа данных, который Вы могли бы использовать. Например:
#define DEFINE_LIST(type) \
typedef struct list_node_##type { \
struct list_node_##type *next; \
type data; \
}
#define IMPLEMENT_LIST_INSERT(type) \
void list_##type##_insert(list_node_##type *node, type data) { \
... \
}
DEFINE_LIST(int); // defines struct list_node_int
DEFINE_LIST(double); // defines struct list_node_double
IMPLEMENT_LIST_INSERT(int); // defines list_int_insert
IMPLEMENT_LIST_INSERT(double); // defines list_double_insert
Ядро Linux имеет интересную реализацию универсального связанного списка в C на его linux/list.h заголовке. Это - двунаправленный связанный список с главным узлом, используемым как это:
struct mystruct {
...
/* Contains the next and prev pointers */
struct list_head mylist;
...
/* A single struct can be in several lists */
struct list_head another_list;
...
};
struct list_head mylist_head;
struct list_head another_list_head;
Некоторые интересные вещи в этом небольшом примере:
struct list_head
, не к целевой структуре (на примере выше, они указывают на &(foo->mylist)
для первого списка и &(foo->another_list)
для второго списка).Все функции управления списком берут указатели на struct list_head
(и большинство не заботится вообще, является ли это отдельным главным узлом или одним из встроенных узлов). Добираться от struct list_head
к целевой структуре Вы используете list_entry
макрос (который совпадает с containter_of
макрос от linux/kernel.h заголовка), который расширяется в простое вычитание указателя.
Так как это - двунаправленный связанный список с главным узлом, Вы можете в O(1)
:
C и его стандартная библиотека не предлагают никакому списку определенных функций.
Но существуют библиотеки со многими полезными функциями для C, которые поддерживают типы данных, известные с других языков программирования: http://library.gnome.org/devel/glib/2.18/glib-data-types.html