Как создать гетерогенный список ссылок в C или C ++ - PullRequest
4 голосов
/ 07 декабря 2011

Список ссылок, который может содержать данные и алгоритм с плавающей запятой, целыми числами, символами и т. Д., Должен быть хорошим и не очень сложным

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

доходит до c, я должен проверить каждый введенный пользователем символ, чтобы проверить, является ли он целым, с плавающей запятой или символом или нет. Затем мы можем продолжить

предложите эффективный алгоритм / код

Ответы [ 6 ]

6 голосов
/ 07 декабря 2011

Если вы хотите сделать это самостоятельно, вы, в основном, захотите создать массив или связанный список элементов, которые кодируют как данные, так и тип данных. Вы можете использовать структуру, которая включает в себя индикатор типа и объединение различных типов, которые вы хотите обработать, и создать массив или связанный список этой структуры:

typedef struct {
    int type_indicator;
    union {
        float f;
        int i;
        double d;
        void *p;
        char c;
    }
} generic_item;

generic_item generic_array[10];

Я оставлю вам возможность придумать соответствующее перечисление для индикатора типа и добавить указатель функции для вашего алгоритма. Если вам нужен связанный список вместо массива, вам, очевидно, также необходимо добавить указатель generic_item *next.

Я не изучал варианты повышения, на которые ссылаются другие ответы, но, вероятно, я сначала заглянул туда, прежде чем пытаться развернуть свое собственное решение.

5 голосов
/ 07 декабря 2011

Использование boost :: option или boost :: any . Зависит от ваших потребностей.

4 голосов
/ 07 декабря 2011

ПРИМЕЧАНИЕ: это чисто ответ С.

Я хотел бы начать с этой структуры данных:

typedef struct heterogeneous_list
{
    enum { CHAR, STRING, FLOAT, INT } type;
    void *item;
    struct heterogeneous_list *next;
}

Когда я получал элемент от пользователя, я сохранял его в списке (при условии, что текущие точки находятся в конце списка):

current->next = malloc(sizeof(heterogeneous_list));
case (/* whether the user entered a char, string, float, or int */
{
    case /* char */:
        current->next.item = malloc(sizeof(char));
        current->next.type = CHAR;
        current->next.next = NULL;
        break;
/* and so forth, for string, int, and float */
}
current = current->next;

При переборе списка теперь легко обрабатывать то, что находится в списке, на основе типа. В следующем коде предполагается, что current является текущим элементом списка, который просматривается в итерации (цикл for, проходящий по списку):

char currentItemChar;
char * currentItemString;
float currentItemFloat;
int currentItemInt;

case (current->type)
{
    case CHAR:
        currentItemChar = *((char*) current->item);
        // process a character
        break;
    case STRING:
        currentItemString = (char*) current->item;
        // process a string
        break;
    case FLOAT: 
        currentItemFloat = *((float*) current->item);
        // process a float
        break;
    .
    .
    .
};

Я бы так и сделал.

2 голосов
/ 07 декабря 2011

http://www.boost.org/doc/libs/1_48_0/doc/html/variant.html

(который, конечно, также упоминает объединения C / C ++, прежде чем объяснять, какие варианты повышения дают вам это)

1 голос
/ 07 декабря 2011

Гетерогенный связанный список может быть создан с использованием void * в качестве указателя на элемент данных:

struct Node
{
    Node * previous;
    Node * next;
    void * p_data;
};

Перед реализацией гетерогенного контейнера можно спросить, можно ли изменить дизайн на использованиеГомогенные контейнеры вместо

0 голосов
/ 07 декабря 2011

Вы могли бы делать такие вещи, используя - как вы упомянули - некоторые пустые указатели в связи с некоторыми более или менее хитрыми макросами.

Вы можете определить struct (или класс) содержит три указателя: next, prev (для следующего и предыдущего элемента списка) и какой-то void* data.Кроме того, вы можете сохранить тип для каждой записи в списке (который может быть реализован с помощью enum или чего-то подобного).

Более того, вы можете определить макрос, который - при наличии элемента списка - извлекает данные и автоматическиприведите его к данному типу:

#define get_list_item(item, type) *(type*)(((item)->data))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...