Хранение значение разных типов в связном списке (наподобие ООП) - C (СИ)
Формулировка задачи:
Я хочу написать оптимизированный интерпретатор брейнфака. Он сначала компилирует текст в некое внутреннее представление, а потом интерпретирует его. И саму программу, и ленту памяти я решил реализовать как бесконечный (растущий в обе стороны при необходимости) двусвязный список. Вопрос: как хранить два разных типа данных в списке? Один тип данных - число. Второй - структура из двух чисел и указателя. Мне приходят в голову два варианта: один тип данных на все, т.е. число будем хранить в той же структуре, просто два из трех ее полей останутся неиспользованными. Для такого маленького проекта вполне допустимое решение, гигабайты оно потреблять не будет. Но это некрасиво, неправильно и нехорошо. Второй вариант - ввести еще одну переменную, которая будет обозначать тип. В зависимости от ее значение будет вызываться тот или иной метод. Для двух типов - опять же, вполне допустимое решение. Но как сделать правильно, чтобы получилось что-то наподобие ООП? Я пытался гуглить, читал статьи, но там все слишком сложно, с наследованием и полиморфизмом. А мне всего-то надо удобно, прозрачно работать с двумя-тремя (тремя - это если сам список тоже сделать объектом) типами данных. Вот пока что только заготовку для бесконечно растущего списка написал:
typedef struct list_t {
void* data;
struct list_t* prev;
struct list_t* next;
} List;
List* List_New(void)
{
List* node = (List*)malloc(sizeof(List));
node->data = NULL;
node->prev = NULL;
node->next = NULL;
return node;
}
List* List_Prev(List* node)
{
if (node->prev == NULL) {
node->prev = List_New();
node->prev->next = node;
}
return node->prev;
}
List* List_Next(List* node)
{
if (node->next == NULL) {
node->next = List_New();
node->next->prev = node;
}
return node->next;
}
void List_Free(List* node)
{
while (node->prev != NULL) {
List_Free(node->prev);
}
while (node->next != NULL) {
List_Free(node->next);
}
free(node);
}Решение задачи: «Хранение значение разных типов в связном списке (наподобие ООП)»
textual
Листинг программы
int main(void)
{
Tape* memory = Tape_New();
Tape* even = Tape_New();
for (int i = 0; i < 10; i++) {
Number* number = Number_New(i);
memory = Tape_Write(memory, number);
if (i % 2 == 0) {
even = Tape_Write(even, number);
}
}
for (even = Tape_Rewind(even); even->data != NULL; even = Tape_Forward(even)) {
printf("%d ", ((Number*)Tape_Read(even))->value);
}
Tape_Free(even);
for (memory = Tape_Rewind(memory); memory->data != NULL; memory = Tape_Forward(memory)) {
free(Tape_Read(memory));
}
Tape_Free(memory);
return 0;
}
Объяснение кода листинга программы
В этом коде создаются два связных списка: memory и even. В цикле заполняются элементами списка memory, при этом каждый элемент списка memory содержит указатель на список even с четными числами. Затем происходит обход списка even в обратном порядке и выводятся значения его элементов. После этого обходится список memory в обратном порядке, освобождаются указатели на элементы списка even и освобождается память, выделенная под список memory. В конце программы возвращается 0, что означает успешное завершение работы программы.