alminacck
alminacck

Reputation: 37

how to create a linked list with this struct as data?

I am trying to print out a table, namely the first ten elements in the periodic table as a linked list with a struct as data. The struct holds the elements' data like so:

typedef struct element{
    char *name;
    char *symbol;
    float weight; 
}element;

and then creating the list itself likeso:

typedef struct list{
    struct element elements[]; //an array holding element types?
    struct list *next; 
}list;

so because I need to print out the first 10 elements, I tried using arrays to declare the names, symbols and weights, but I couldn't make the connection of which way to use that in the linked list as data:

char *names[10] = {"Hydrogen", "Helium", "Lithium", "Beryllium", "Boron", "Carbon", "Nitrogen", "Oxygen", "Fluorine", "Neon"};
char *symbols[10] = {"H","He","Li","Be","B","C","N","O","F","Ne"};
float weights[10] = {1.008,4.003,6.941,9.012,10.811,12.011,14.007,15.999,18.998,20.180};

Upvotes: 0

Views: 80

Answers (3)

0___________
0___________

Reputation: 68013

Just add the pointer the the next element. You do not need a new structure for it. Here is some example code (only adding to the list and printing implemented)

There is some code populating the list form the arrays.

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

typedef struct element{
    char *name;
    char *symbol;
    float weight;
    struct element *next;
}element;

element *addToList(element *head, const char *name, const char *symbol, float weight)
{
    element *current, tmp;
    if(!head)
    {
        head = realloc(head, sizeof(*head));
        current = head;
    }
    else
    {
        element *wrk;
        current = head;
        while(current -> next) current = current ->next;
        wrk = malloc(sizeof(*head));
        if(wrk)
        {
            current -> next = wrk;
            current = wrk;
        }
    }
    if(current)
    {
        current -> name = malloc(strlen(name) + 1);
        current -> symbol = malloc(strlen(symbol) + 1);
        //add memory checks here
        strcpy(current -> name, name);
        strcpy(current -> symbol, symbol);
        current -> weight = weight;
        current -> next = NULL;
    }
    return head;
}

size_t printLinst(const element *head)
{
    size_t nelems = 0;
    while(head)
    {
        printf("%zu element = {\"%s\", \"%s\", %f}\n", ++nelems, head -> name, head -> symbol, head -> weight);
        head = head -> next;
    }
    return nelems;
}

/* another list functions */

char *names[10] = {"Hydrogen", "Helium", "Lithium", "Beryllium", "Boron", "Carbon", "Nitrogen", "Oxygen", "Fluorine", "Neon"};
char *symbols[10] = {"H","He","Li","Be","B","C","N","O","F","Ne"};
float weights[10] = {1.008,4.003,6.941,9.012,10.811,12.011,14.007,15.999,18.998,20.180};

#define ARRSIZE(arr) (sizeof((arr))/sizeof((arr)[0])) 

int main(void)
{
    element *head = NULL;

    for(size_t index = 0; index < ARRSIZE(weights); index++)
    {
        head = addToList(head, names[index], symbols[index], weights[index]);
    }

    printf("List is %zu elements long\n", printLinst(head));
    /* another code */
}

https://godbolt.org/z/ddEzTx

Upvotes: 1

John Bollinger
John Bollinger

Reputation: 181689

You have two main options for linked list structure:

  1. The items contain the links, and so constitute linked list nodes in their own right:

    struct element {
        char *name;
        char *symbol;
        float weight; 
        struct element *next;   // <--- here
    };
    
  2. List nodes and data are separate(-ish). For example:

    struct element {
        char *name;
        char *symbol;
        float weight; 
    };
    
    struct node {
        struct element *element;  // points to the item
        struct node *next;
    };
    

    or maybe

    struct node {
        struct element element;   // contains the item
        struct node *next;
    };
    

There can be a separate structure for the list itself, but there doesn't have to be. The minimal representation of the list is simply a pointer to the head node:

struct node *head;

It is not usual for there to be a structure containing the nodes directly, as you propose, because requiring the nodes to be drawn from such a pool would limit the maximum size of the list. There are other reasons why it can be useful to have a structure type representing the overall list, but that's probably more complexity than you need to worry about for your present task.

Whether you want to declare typedef aliases for your structure types is an entirely separate question, by the way. I rarely do so, myself. It is largely a style question, but I bring it up because some people have the mistaken impression that typedef is an essential element of the definition of a structure type.

Upvotes: 1

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

It is unusual for a linked list to have an array of elements, though there are cases where it can be useful. In your case I think a linked list where each list element has one element is more appropriate:

typedef struct list{
    struct element element;
    struct list *next; 
}list;

As a matter of style, we end up with the name element used in the structure name, as the typedef'd name and as a structure member. I suggest to rename them to struct ELEMENT and tElement. The same with the list structure. This will make it like:

typedef struct ELEMENT {
    char *name;
    char *symbol;
    float weight; 
} tElement;

typedef struct LIST {
    tElement element;
    struct LIST *next; 
} tList;

I leave it to you to develop the functions to create and add to the list and to print it.

Upvotes: 2

Related Questions