2015-03-15 2 views
3

Я реализую общий двусвязный список в C, и я написал функции для прямого и обратного обхода. В рамках этих функций я хотел бы распечатать данные, содержащиеся в списке, но поскольку это общий характер, мне трудно понять, как это можно сделать. Очевидно, я не могу просто printf использовать %d или что-то, потому что список может содержать любой тип данных. Любые предложения, чтобы подойти к этому по-другому, были бы оценены, потому что я думал об этом в течение довольно долгого времени, и я в недоумении. Благодаря!Элементы печати связанного списка, содержащие void *

+0

Если вы не говорите о * очень * современных расширениях C, в C нет никаких дженериков; Прочтите определение тега (щелкните по тегу «generics») и решите, хотите ли вы сохранить тег. –

+0

@ MarcusMüller Извините, что я имел в виду, что данные передаются в список с помощью указателей void. – user2901181

+1

Функция обратного вызова, переданная (как указатель) в качестве аргумента функции перехвата списка? – wildplasser

ответ

4

Вы можете многое сделать.

Например, вы можете хранить структуры, которые не только содержат данные void *, но также указывают на возможный тип данных или даже строку формата, необходимую для объекта printf.

Вы также можете подумать о структуре, содержащей void *, к вашим данным и указателю функции, который позволит вам преобразовать ваши данные в строку. Это в основном минимально эмулирует полиморфизм C++ в C.

EDIT: Как указал wickstopher, вы просто не получаете безопасность типа компиляции. Разгрузите указатель на функцию, и у вас будет неподходящая функция, работающая с вашими данными, что может привести к тому, что ваша программа будет segfault, запустите вашего котенка, сжечь вашу квартиру, убежать с вашим младшим ребенком или дымовой трещиной на вашей кухне.

+0

Спасибо.Мне нравится ваше второе предложение, но разве я не столкнулся бы с той же проблемой при написании функции, которая преобразует и неизвестный тип данных в строку? Я не знаю, как это сделать. – user2901181

+2

вы должны написать функцию для каждого типа данных, которую вы планируете добавить в свой список, а затем использовать указатель на функцию, добавляя элементы в свой список. –

2

Вам необходимо указать поле тега в объявлении struct. Определить enum для типов данных, как

enum {INT_TYPE, FLOAT_TYPE, DOUBLE_TYPE, CHAR_TYPE} type; 

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

1

C не поддерживает проверку типов во время выполнения, поэтому это невозможно. См. runtime determine type for C (аналогичный вопрос).

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

1

Если предположить, что узел имеет void * указатель на узел содержимого, среди указателей для ссылки на следующие и предыдущие элементы в списке, обеспечить функцию для печати узла, такие как

void PrintNode (Node_t *node, void (*fprint)(void *)); 

Эта функция получит элементы узла, а затем вызвать функцию, предоставленную пользователем, чтобы фактически распечатать содержимое узла.

typedef struct stNode { 
    void *NodeContents; 
    struct stNode *prev; 
    struct stNode *next; 
} Node_t; 

void PrintNode (Node_t *node, void (*print)(void *)) 
{ 
    if (node && node->NodeContents && print) 
    print(node->NodeContents); 
} 
Смежные вопросы