Как управлять различными видами данных в связанном списке? - PullRequest
1 голос
/ 09 мая 2019

У меня есть проект, который учитель просит нас выполнить в связном списке.Хорошо, их довольно легко реализовать, но у меня проблемы с управлением данными в моем списке.Они могут быть любыми из них: int, char, float или string (char массив).Я знаю, как связать любое из них по отдельности, но когда они перепутаны, вещи начинают становиться грязными.

Я не очень старался, я застрял.Вот некоторые мысли, которые пришли мне в голову: создать 4 структуры, по 1 для каждого типа данных (но я никогда не видел связанного списка различных структур, возможно, это не список по определению, потому что они не одного и того же типа структуры)или создайте 1 структуру с объявлением для каждого типа данных.Важно сказать, что у меня есть переменная, которая сообщает мне, каким типом данных я управляю в данный момент (но когда я передаю аргументы для своей функции, у меня не все из них, если я не придумаю некоторые флагино это кажется довольно глупым, и проект не определил никаких ограничений для моих переменных).

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

Учитывая данные (первое число говорит мне, сколько узлов в моем списке):

5

f 3.14

d 100

cx

s gardenal

d 300

Я ожидаю, что мой результат будет:

3.1400 100 x gardenal 300

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

1 Ответ

5 голосов
/ 09 мая 2019

Как правило, вам нужно добавить тег типа к struct Node, чтобы вы могли отслеживать тип данных, хранящихся в отдельных узлах.

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

Вот простой пример с использованием пустого указателя :

#include <stdio.h>
#include <stdlib.h>

enum ListType 
{
    INT = 0,
    FLOAT,
    CHAR,
    STRING,
};

struct Node
{
    struct Node *next;
    enum ListType type;
    void *data;
};

void printNode(struct Node *p)
{
    switch (p->type)
    {
        case INT:
            printf("%d ", *((int*)p->data));
            break;
        case FLOAT:
            printf("%f ", *((float*)p->data));
            break;
        case CHAR:
            printf("%c ", *((char*)p->data));
            break;
        case STRING:
            printf("%s ", (char*)p->data);
            break;
        default:
            printf("ERROR ");
            break;
    }
}

void printList(struct Node *p)
{
    while(p)
    {
        printNode(p);
        p = p->next;
    }
}

void freeListData(struct Node *p)
{
    while(p)
    {
        free(p->data);
        p = p->next;
    }
}

int main(void) {
    // Build the list manually to illustrate the printing
    struct Node N1;
    struct Node N2;

    N1.type = FLOAT;
    N1.data = malloc(sizeof(float));
    *((float*)N1.data) = 3.14;
    N1.next = &N2;

    N2.type = INT;
    N2.data = malloc(sizeof(int));
    *((int*)N2.data) = 100;
    N2.next = NULL;

    // .. more nodes

    printList(&N1);

    freeListData(&N1);

    return 0;
}

Вывод:

3.140000 100

А вот пример с использованием объединения :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum ListType 
{
    INT = 0,
    FLOAT,
    CHAR,
    STRING,
};

union ListData
{
    int d;
    float f;
    char c;
    char *str;  // Memory for the string must be malloc'ed
};

struct Node
{
    struct Node *next;
    enum ListType type;
    union ListData data;
};

void printNode(struct Node *p)
{
    switch (p->type)
    {
        case INT:
            printf("%d ", p->data.d);
            break;
        case FLOAT:
            printf("%f ", p->data.f);
            break;
        case CHAR:
            printf("%c ", p->data.c);
            break;
        case STRING:
            printf("%s ", p->data.str);
            break;
        default:
            printf("ERROR ");
            break;
    }
}

void printList(struct Node *p)
{
    while(p)
    {
        printNode(p);
        p = p->next;
    }
}

void freeListStrings(struct Node *p)
{
    while(p)
    {
        if (p->type == STRING) free(p->data.str);
        p = p->next;
    }
}

int main(void) {
    // Build the list manually to illustrate the printing
    struct Node N1;
    struct Node N2;
    struct Node N3;

    N1.type = FLOAT;
    N1.data.f = 3.14;
    N1.next = &N2;

    N2.type = INT;
    N2.data.d = 100;
    N2.next = &N3;

    N3.type = STRING;
    N3.data.str = malloc(sizeof "Hello World");
    strcpy(N3.data.str, "Hello World");
    N3.next = NULL;

    // .. more nodes

    printList(&N1);

    freeListStrings(&N1);

    return 0;
}

Вывод:

3.140000 100 Hello World 
...