0

this code creates a "loop", where the first element point back to nothing and points to the next element (if there is one), if not, it points to nothing

typedef struct noeud
{
    struct noeud* point_suivant;
    struct noeud* point_precedent;
    int valeur;
    int n;

}t_noeud;
typedef struct anneau
{
    
    t_noeud* noeud;
    int nb_points;

}t_anneau;

this is t_noeud_init

t_noeud* t_noeud_init(const int valeur) {
    t_noeud* nouveau_noeud = (t_noeud*)malloc(sizeof(t_noeud));

    if (nouveau_noeud == NULL) {
        printf("EXIT_FAILURE");
        return NULL;
    }

    nouveau_noeud->valeur = valeur;
    nouveau_noeud->point_suivant = NULL;
    nouveau_noeud->point_precedent = NULL;
    return nouveau_noeud;
}

this is t_noeud_add

t_noeud* t_noeud_add(const int valeur, t_noeud* noeud_precedent) {
    t_noeud* nouveau_noeud = (t_noeud*)malloc(sizeof(t_noeud));
    if (nouveau_noeud == NULL) {
        printf("EXIT_FAILURE");
        return NULL;
    }
    noeud_precedent->point_suivant = nouveau_noeud;
    nouveau_noeud->valeur = valeur;
    nouveau_noeud->point_suivant = NULL;
    nouveau_noeud->point_precedent = noeud_precedent;
    return nouveau_noeud;
}

this is t_anneau_init

t_anneau* t_anneau_init() {//remplie de zero
    t_anneau* nouveau_anneau = (t_anneau*)malloc(sizeof(t_anneau));
    if (nouveau_anneau == NULL) {
        printf("EXIT_FAILURE");
        return NULL;
    }
    
    
    nouveau_anneau->noeud = t_noeud_init(zero);     
        nouveau_anneau->noeud->n = 0;
        nouveau_anneau->nb_points = 0;
        
        nouveau_anneau->noeud->point_suivant =
        t_noeud_add(zero, nouveau_anneau->noeud); 
            nouveau_anneau->noeud->point_suivant->n = 1;
            nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
    nouveau_anneau->noeud->point_suivant->point_suivant = 
        t_noeud_add(zero, nouveau_anneau->noeud->point_suivant); 
            nouveau_anneau->noeud->point_suivant->point_suivant->n = 2;
            nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
    nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant = 
        t_noeud_add(zero, nouveau_anneau->noeud->point_suivant->point_suivant); 
            nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->n = 3;
            nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
    nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant = 
        t_noeud_add(zero, nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant); 
            nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant->n = 4;
            nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
    nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant->point_suivant = 
        t_noeud_add(zero, nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant); 
            nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant->point_suivant->n = 5;
            nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
    nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant->point_suivant->point_suivant = 
        t_noeud_add(zero, nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant->point_suivant); 
            nouveau_anneau->noeud->point_suivant->point_suivant->point_suivant->point_suivant->point_suivant->point_suivant->n = 6;
            nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
    
    
    return nouveau_anneau;
}

this is a giant piece of code and that is why i would like to automate it but what i've tried does'nt work.

i tried someething like this:

for (int i = 0; i < 6; i++) {
        nouveau_anneau->noeud->point_suivant = t_noeud_add(zero, nouveau_anneau->noeud);
        nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
        nouveau_anneau->noeud = nouveau_anneau->noeud->point_suivant;
    }

where it would build upon itself but cant quite seem to make it work.

any suggestions?

displayer
  • 1
  • 4
  • 2
    You want to build and maintain a [linked list](https://stackoverflow.com/q/11173480/1707353)? – Jeff Holt Jul 28 '21 at 20:20
  • yes, i can already manipulate it, only not very well – displayer Jul 28 '21 at 20:23
  • 1
    The *elegant* way to accomplish this uses a pointer-to-pointer-to node. – wildplasser Jul 28 '21 at 21:00
  • i thought i was using pointer to pointer to node already – displayer Jul 28 '21 at 21:13
  • I assume that this adds a number of nodes to your doubly-linked list. `anneau` suggests that it will loop around? Instead of repeatedly using `point_suivant` like Schlemiel the Painter, why don't you use `point_precedent`, which is the head? (Also, `=0` in `C` `struct` doesn't work.) – Neil Jul 28 '21 at 21:24
  • as i understand it, and im a student thats been working with this for a week now, each node has 3 things, a value, a pointer to the next node, and a pointer the the node before it. the very first node has its `point_suivant` set to nullptr and its `point_precedent` also set to nullptr, instead of going forward in the loop i should go backwards? also you are correct, this adds a number of nodes to a doubly-linked list – displayer Jul 28 '21 at 21:30
  • then what's the fourth thing `n`? – rici Jul 28 '21 at 21:43
  • And where's the definition of `t_noeud_add`? – rici Jul 28 '21 at 21:46
  • `n` is the nodes number: if you want to access node number 3, look for the node with `n = 3` – displayer Jul 28 '21 at 21:46
  • to post a more simple version of the code i removed `t_noeud_add` and `t_noeud_init` but i added it now. – displayer Jul 28 '21 at 21:50
  • This is a linked-list `liste->null<-1-><-2-><-3->null`; I would say that `...3<-anneux->1-><-2-><-3-><-1...`. In `liste` case, keep the previous entry instead of starting over. – Neil Jul 28 '21 at 22:25
  • What is the purpose of a node number inside the node? One advantage of a linked list is that you can easily add or remove nodes in the middle of the list. This would break your node number. Also unless you have pointers into the middle of the list you must start from the head anyway and in that case you can simply count until you get the desired node number. – Gerhardh Jul 29 '21 at 07:24

2 Answers2

1

I think you just need a bit of work on your for idea, maybe try this code below. I just added two auxiliary variables to hold the current and previous point_suivant.

t_anneau* t_anneau_init() {//remplie de zero
    t_anneau* nouveau_anneau = (t_anneau*)malloc(sizeof(t_anneau));
    if (nouveau_anneau == NULL) {
        printf("EXIT_FAILURE");
        return NULL;
    }
        
    nouveau_anneau->noeud = t_noeud_init(zero);     
    nouveau_anneau->noeud->n = 0;
    nouveau_anneau->nb_points = 0;
        
    struct noeud* prev_point_suivant = nouveu_anneau->noeud;
    struct noeud* cur_point_suivant = prev_point_suivant->point_suivant;

    for (int i = 1; i <= 6; ++i) {
        cur_point_suivant = t_noeud_add(zero, prev_point_suivant);
        cur_point_suivant->n = i;
        ++nouveau_anneau->nb_points;

        prev_point_suivant = cur_point_suivant;
        cur_point_suivant = cur_point_suivant->point_suivant;
    }

    return nouveau_anneau;
}
gscgomes
  • 91
  • 4
  • 1
    you are a god, it works! i did not think to use variables to hold the current and previous positions. thank you! – displayer Jul 28 '21 at 22:00
0

It is not a complete program, but I will show you a minimum thing you can run and see if it helps. I can expand it with more of the usual functions, if you find it useful. Just let me know in the comments.

About your code

If possible, always provide a complete code, something one could copy and try.

The way you wrote is somewhat complicated, but it was great you did not tried to write the list as a single node, as is normal for beginners.

About the code, my suggestions (below is an excerpt of your code, just for comment):


nouveau_anneau->noeud = t_noeud_init(zero);     
        nouveau_anneau->noeud->n = 0;
        nouveau_anneau->nb_points = 0;
        
        nouveau_anneau->noeud->point_suivant =
        t_noeud_add(zero, nouveau_anneau->noeud); 
            nouveau_anneau->noeud->point_suivant->n = 1;
            nouveau_anneau->nb_points = nouveau_anneau->nb_points + 1;
    nouveau_anneau->noeud->point_suivant->point_suivant = 
        t_noeud_add(zero, nouveau_anneau->noeud->point_suivant); 
            nouveau_anneau->noeud->point_suivant->point_suivant->n = 2;
            nouveau_anneau->nb_points = nouveau
  • It seems really complex and hard to read.

  • It seems not to help you prefixing the pointers in the list by point_. You know you will write this many many times in the code, and the code for the list is a tool. When the code is ready you will not change it or even read it often: just use it to build and manage your linked lists. Same is true for the very long name for the list itself. In the example I used A ;)

An example

I will use your code, plus a few changes, and write 3 functions, as

typedef struct str_noeud
{
    struct str_noeud* suivant;
    struct str_noeud* precedent;
    int               valeur;

}   Noeud;

typedef struct
{
    Noeud*  debut;
    Noeud*  fin;
    int     size; // actual size
    int     maximum; // limit, or 0

}   Anneau;

Anneau* anneau_init(unsigned);
int     anneau_add(int, Anneau*);
int     anneau_list(Anneau*,const char*);

As you may expect:

  • _init() creates a list and returns a pointer to it. The parameter is an unsigned that sets the maximum number of nodes that can be inserted in the list. Returns NULL in case of error

  • _add() add an element to the start of the list. The parameters are the value and of course the pointer to the list. Returns 0 for success or a negative error code

  • _list() just list the elements. The parameters are the address of the list and an optional message, just to help in testin if you have many lists.

The test program

int main(void)
{
    // fills up a list until error
    Anneau* one = anneau_init(28);
    int     value = 28;
    while (anneau_add(value--, one) == 0) {};
    anneau_list(one, "A simple test list");
    anneau_list(one, "");
    return 0;
}

This is simple:

  • a list is created with a limit of 28 nodes.

  • a loop adds a value to the list, starting at 28, counting down. As the limit is precisely 28, it is expected that anneau_add() return an error when the limit is reached. Since the elements are added to the start of the list we expect to see elements 1 to 28 (inclusive) inserted in the list.

  • since the list writes down 10 elements for line it is easy to check. anneau_list() is called twice to show the message thing.

Example output

A simple test list

28 [of 28 elements MAX]

    debut :    1
    fin   :   28

Elements

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


28 [of 28 elements MAX]

    debut :    1
    fin   :   28

Elements

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

Complete test code

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

typedef struct str_noeud
{
    struct str_noeud* suivant;
    struct str_noeud* precedent;
    int               valeur;

}   Noeud;

typedef struct
{
    Noeud*  debut;
    Noeud*  fin;
    int     size; // actual size
    int     maximum; // limit, or 0

}   Anneau;

Anneau* anneau_init(unsigned);
int     anneau_add(int, Anneau*);
int     anneau_list(Anneau*,const char*);


int main(void)
{
    // fills up a list until error
    Anneau* one = anneau_init(28);
    int     value = 28;
    while (anneau_add(value--, one) == 0) {};
    anneau_list(one, "A simple test list");
    anneau_list(one, "");
    return 0;
}


int         anneau_add(int v, Anneau* A)
{   // insert 'v' at the start of the list
    if (A == NULL) return -1;  // no list
    if ((A->maximum > 0) && (A->size == A->maximum)) return -2; // no space
    // ok: fits
    Noeud* one     = (Noeud*)malloc(sizeof(Noeud));
    one->valeur = v;
    one->suivant = A->debut; 
    one->precedent  = NULL; 
    A->debut       = one; // 
    A->size       += 1;
    if (A->size == 1) A->fin = one;
    return 0;
};


Anneau*     anneau_init(unsigned lim)
{ 
    Anneau* nouveau = (Anneau*)malloc(sizeof(Anneau));
    if (nouveau == NULL)
    {
        printf("EXIT_FAILURE");
        return NULL;
    }
    nouveau->debut            = NULL;
    nouveau->fin              = NULL;
    nouveau->maximum          = lim;
    nouveau->size             = 0;
    return nouveau;
};


int anneau_list(Anneau* A, const char* message)
{
    if (A == NULL) return -1;
    if (message != NULL) printf("%s\n", message);
    if (A->maximum > 0)
    {
        printf("\n%d [of %d elements MAX]\n", 
               A->size, A->maximum);
    }
    else
    {
        printf("\n%d elements [MAX not defined]\n",
               A->size);
    }
    if (A->size < 1) return 0; // empty

    Noeud* p = A->debut;
    printf("\n    debut : %4d\n", A->debut->valeur );
    printf("    fin   : %4d\n", A->fin->valeur );
    printf("\nElements\n\n");
    int nc = 1;
    do
    {
        printf("%4d  ", p->valeur);
        p = p->suivant;
        if (nc == 10)
        {
            nc = 1;
            printf("\n");
        }
        else
            nc += 1;
    } while (p != NULL);
    printf("\nEnd\n");
    return 0;
};

/*
https://stackoverflow.com/questions/68566872/
is-there-a-way-to-automate-creation
-of-a-struct-within-a-struct
*/

Write back if you need to see sample implementation of other functions, like ones to remove nodes or delete a whole list.

arfneto
  • 1,227
  • 1
  • 6
  • 13