Add nodes to the chained list using loop

Asked

Viewed 49 times

0

I did not find any similar question, in case you have, please indicate and I delete the post.
How to create a chained list so I can use a for loop to put the nodes in the list. I’m using two structures, one for the list itself, and one pro node. If I create a Node type variable for each node it works.

typedef struct List
{
    int size;
    struct Node *mainNode;
} list;

typedef struct Node
{
    int value;
    struct Node *next;
} node;

Loop that is not working:

list myList = newEmptyList();
node *nodeArray[10];

for (int i = 0; i < 10; i++)
{
    nodeArray[i]->value = i;
    addNode(&myList, nodeArray[i]);
}

AddNode function:

void addNode(list *targetList, node *nodeToAdd)
{
    node *lastNode;
    if (targetList->size == 0)
    {
        targetList->size++;
        targetList->mainNode = nodeToAdd;
    }
    else
    {
        lastNode = getNode(*targetList, targetList->size - 1);
        targetList->size++;
        lastNode->next = nodeToAdd;
    }

    printf("Node added.\nNew list size: %d\n", targetList->size);
    system("pause");
    
}

GetNode function:

node * getNode(list targetList, int index)
{
    Node* currentNode = NULL;

    if (index >= targetList->size || index < 0) return currentNode;

    for (int i = 0; i <= index; i++)
    {
        if (i == 0)
        {
            currentNode = targetList->mainNode;
        }
        else
        {
            currentNode = currentNode->next;
        }
    }
    return currentNode;     
}

Output:
Node Added.
New list size: 1
Press any key to continue. . .
Node Added.
New list size: 2
Press any key to continue. . .

Specifically after two, the program stops abruptly.

  • Post a complete, compileable program.

  • I added the getNode function, I wanted to summarize not to make a very large post, and the main function is just that loop same, I hope the post has improved.

  • Also there was an error in the getNode function, thank you very much for the answer.

1 answer

2


It’s hard to understand with just part of the program what’s going on.

Without reading the code of getNode() and the rest of the program becomes difficult.

From what posted, it seems very complicated.

about the structure

The convention in C is to set the first letter in upper case for the defined types, because it differentiates these types from the normal variables. You used List for example in a struct that is usually anonymous in typedef. And used list for the name, and thus lost this differentiation. Only the node needs a name because it has an internal reference to itself in the structure. Compare to the following example.

It is much more complicated to program a list with pointers to one side only. If you don’t really need this use pointers to both sides. It’s the simple one. With a single pointer to a single side at every moment you have to reposition, or else be saving pointers by the program. Using pointers to both sides and leaving in the list pointers to the beginning and to the end of the list everything is easier: to go through, remove, insert...

And in general the data is void* because it is generic and can always use the same functions.

back on the show

Consider this structure for a list of int

typedef int     Data; // can be anything

typedef struct st_node
{
    Data            value;
    struct st_node* next;

}   Node;

typedef struct
{
    int     size;
    Node*   start;

}   List;

And compare: Lista has Node and Node has Data. Like I said, it should be a pointer, and if possible void, generic.

a complete example

I’ll show you a example using these structures and functions:

    void        add_data_b(Data* data, List* l);
    void        add_data_e(Data* data, List* l);
    List*       create_list();
    void        show_list(List*, const char*);

written the common way of doing this. add_data_b() inserts at the beginning of the list and of course, add_data_e() inserts at the end. show_list() accepts an optional message as a parameter.

The example:

  • inserts 13 to 24 at the end of the list
  • inserts 12 to 1 in that order at the beginning of the list
  • uses a for() for each case and so you have examples of how to do what you want
  • so the final list should have 24 elements, from 1 to 24

out of the box

Teste: inseridos de 13 a 24 no fim da lista

        => 12 elementos

  13  14  15  16  17  18  19  20  21  22
  23  24

Teste: inseridos de 12 a 1 no inicio da lista

        => 24 elementos

   1   2   3   4   5   6   7   8   9  10
  11  12  13  14  15  16  17  18  19  20
  21  22  23  24

The complete program

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

typedef int     Data; // can be anything

typedef struct st_node
{
    Data            value;
    struct st_node* next;

}   Node;

typedef struct
{
    int     size;
    Node*   start;

}   List;

    void        add_data_b(Data* data, List* l);
    void        add_data_e(Data* data, List* l);
    List*       create_list();
    void        show_list(List*, const char*);

int main(void)
{
    List* l = create_list();

    // insere no fim
    for (int i = 13; i <= 24; i+=1) add_data_e(&i, l);
    show_list(l, "Teste: inseridos de 13 a 24 no fim da lista");

    // insere no inicio
    for (int i = 12; i >= 1; i-=1) add_data_b(&i, l);
    show_list(l, "Teste: inseridos de 12 a 1 no inicio da lista");
    return 0;
}


void add_data_b(Data* data, List* l)
{  // insert at list start
    // we need a new node, anyway...
    Node* new  = (Node*)malloc(sizeof(Node));
    new->value = *data;
    new->next  = NULL;
    // list may be empty
    if (l->size == 0)
    {
        l->start = new;
        l->size  = 1;
        return;
    }
    new->next = l->start;
    l->start = new;
    l->size += 1;
}


void add_data_e(Data* data, List* l)
{  // insert at the end
    // we need a new node, anyway...
    Node* new  = (Node*)malloc(sizeof(Node));
    new->value = *data;
    new->next  = NULL;
    // list may be empty
    if (l->size == 0)
    {
        l->start = new;
        l->size  = 1;
        return;
    }
    Node* p = l->start;
    while (p->next != NULL) p = p->next;
    p->next = new;
    l->size += 1;
}

List* create_list()
{ 
    List* new = (List*)malloc(sizeof(List));
    new->size = 0;
    new->start = NULL;
    return new;
}

void show_list(List* l, const char* message)
{
    if (message != NULL) printf("%s\n\n", message);
    printf("\t=> %d elementos\n\n", l->size);
    int nc = 0;
    Node* n  = l->start;
    for (int i = 0; i < l->size; i += 1)
    {   // mostra um por um
        printf("%4d", n->value);
        n = n->next;
        nc += 1;
        if (nc == 10)
        {   // mostra 10 por coluna
            printf("\n");
            nc = 0;
        }
    }
    printf("\n\n");
    return;
}
  • I thought I had how to do without using the dynamic allocation functions, but it seems I was wrong, thank you very much.

  • can write without using free()/malloc(). Use an array and use the indexes as pointers. Only you will have to declare all at once, of course: It will be a node vector. Want to see an example? It is the same thing. It is only much faster and much less convenient, especially when removing some knot.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.