Хранение значение разных типов в связном списке (наподобие ООП) - 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, что означает успешное завершение работы программы.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д