Doubt: dynamic list chained inside another, in C

Asked

Viewed 396 times

5

I’m having a huge difficulty to be able to create a dynamically chained list within another using data structure and manipulation, because I haven’t found anything that exemplifies how to create a list within another one. I can create a single dynamic list, but I can’t create another one inside it.

What my program should do:

I have a list of Bands; each band is a list of albuns; and each album is a list of music. And in the program the user can manipulate music, albums and bands as he wants.

My code is below, but it doesn’t work. Someone could give me a light?

File . C

#include "biblioteca.h"

ElemM *lm;
ElemA *la;
ElemB *lb;
//---------------------------MAIN--------------------------------->

int main()
{
  lb = cria_lista_banda();
  la =  cria_lista_album();
  lm = cria_lista_musica();


  system("PAUSE");  
  return 0;
} 
//----------------------------------------------------------------->

ElemB *cria_lista_banda(){
        ElemB *lb;
        lb =  malloc(sizeof(ElemB));
        lb->prox_banda = NULL;
        return lb;


}

ElemA *cria_lista_album(){
        ElemA *la;
        la =  malloc(sizeof(ElemA));
        la->prox_album= NULL;
        return la;


}

ElemM *cria_lista_musica(){
        ElemM *lm;
        lm =  malloc(sizeof(ElemM));
        lm->prox_musica= NULL;
        return lm;


}

int incluir_musica(ElemM *lm, ElemA *la, ElemB *lb, int id_m, int tempo, char *nome_m, int id_a, int id_b){
        int valor1, valor2, valor3, i;

        valor1 = busca_banda(id_b, lb);
        valor2 = busca_album(id_b, id_a, lb, la);
        valor3 = busca_musica(id_b, id_a, id_m, lb, la, lm);
        if(valor3 == -1) return -1;

        ElemB *q;
        q = lb->prox_banda;
        for(i = 0; i <= valor1; i++){
              q = q->prox_banda;
        }
        ElemA *p;
        p = q->albuns_da_banda->prox_album;
        for(i = 0; i <= valor2; i++){
             p = p->prox_album;         
        }

        ElemM *novo, *novocpy;
        p->musicas_do_album->novo = malloc( sizeof(ElemM));
        novocpy = p->musica_do_album->novo;
        if(novo == NULL) return 0;
        novocpy->id_musica = id_m;
        novocpy->tempo_da_musica = tempo;
        strcpy(novocpy->nome_musica, nome_m);
        novocpy->prox_musica = lc->prox_musica;
        lm->prox_musica = novocpy;
        return 1;
}

int busca_banda(int id, ElemB *lb){
        int cont = 0;
        ElemB *p;
        p = lb->prox_banda;
        while(p != NULL && p->id_banda != id){
                p = p->prox_banda;
                cont++;
        }
        if(p == NULL) return -1;
        return cont;
}

int buscar_album(int id_b, int id_a, ElemB *lb, ElemR *la){
        int valor_busca = busca_banda(id_b, lb); 
        int i;
        int cont = 0;

        if(valor_busca == -1) return -1;
        ElemB *q;
        q = lb->prox_banda;
        for(i = 0; i <= valor_busca; i++){
              q = q->prox_banda;
        }
        ElemA *p;
        p = q->albuns_da_banda->prox_album;
        while(p != NULL && p->id_album != id_a){
             p = p->prox_album;
             cont++;         
        }      

        if(p != NULL) return -1;
        return cont;   

}


int buscar_musica(int id_b, int id_a, int id_m, ElemB *lb, ElemA *la, ElemM *lm){
        int valor_busca1 = busca_banda(id_b, lb);
        int valor_busca2 = busca_album(id_b, id_a, lb, la); 
        int i;
        int cont = 0;

        if(valor_busca1 == -1) return -1;
        if(valor_busca2 == -1) return -1;
        ElemB *q;
        q = lb->prox_banda;
        for(i = 0; i <= valor_busca1; i++){
              q = q->prox_banda;
        }
        ElemA *p;
        p = q->albuns_da_banda->prox_album;
        for(i = 0; i <= valor_busca2; i++){
             p = p->prox_album;         
        }
        ElemM *k;
        k = p->musica_do_album->prox_musica;
        while(k != NULL && k->id_musica != id_m){
             k = k->prox_musica;
             cont++;         
        }       

        if(k != NULL) return -1;
        return cont;   

}

File . h

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

struct musica{
       int id_musica;
       int tempo_musica;
       char nome_musica[30];
       struct musica *prox_musica;
       };      

typedef struct musica ElemM;

struct album{
       int id_album;
       char nome_album[30];
       struct musica *musica_do_album;
       struct album *prox_album;
       };

typedef struct album ElemA;

struct banda{
       int id_banda;
       char nome_banda[30];
       struct album *albuns_da_banda;
       struct banda *prox_banda;
       };       

typedef struct banda ElemB;


ElemB *cria_lista_banda();
ElemR *cria_lista_album();
ElemC *cria_lista_musica();
int incluir_musica(ElemM *lm, ElemA *la, ElemB *lb, int id_m, int tempo, char *nome_m, int id_a, int id_b)
int busca_banda(int id, ElemB *lb);
int buscar_album(int id_b, int id_a, ElemB *lb, ElemR *la);
int buscar_musica(int id_b, int id_a, int id_m, ElemB *lb, ElemA *la, ElemM *lm);
  • The includes of the headers normal are not necessary in the Arquivo .h. They look better in the Arquivo .C. You can add pinclude Guards](https://en.wikipedia.org/wiki/Include_guard) to Arquivo .h

  • If you want a program to use, and not make a program to learn C, you should definately be using a language that abstracts basic things like data structures. You can use Python, Javascript, Ruby, PHP, and even Java and worry more about your problem than how to do the basic things that C doesn’t do.

  • What do you mean, "doesn’t work" ? You compiled the program ? The compilation ended without errors ? You ran the program ? It gave a different result than you expected ? What result did you expect and what result did it give ? The program gave crash ? I’m a doctor Jim, not a Psychic!

3 answers

0

Look, you declared three pointers, one for each type of list. I didn’t understand the logic in that.

What you want is probably just a pointer to Band (I’m guessing whenever you register a Album you need to already have one Band to bind you and similarly, when you register a Music there should already be a Album to insert it, I’m sure I assume that?).

Based on this above assumption, the function to create a new Band should first check if there is already any band in this bandlist, and if there is, in what position would you like to insert it in this list?

How about starting your program with the bandlist NULL and change the function to add bands as shown below?

You’d initialize the pointer to bandlist thus:

 ElemB *bandas = NULL;

I would declare the function to register a new band like this:

ElemB *adiciona_banda(Elemb *lista_de_bandas, int id, char* nome){
    ElemB *nova_banda;
    nova_banda =  (ElemB*) malloc(sizeof(ElemB));
    nova_banda->id_banda = id;
    strcpy(nova_banda->nome_banda, nome);
    nova_banda->prox_banda = lista_de_bandas; //Aqui eu tou inserindo a nova banda no inicio da lista
    nova_banda->albuns_da_banda = NULL; //supondo que toda banda é cadastrada antes dos albuns.
    return nova_banda;
}

and at the time to call on the main:

  bandas = adiciona_banda(bandas, 1, "Ivete Sangalo");
  bandas = adiciona_banda(bandas, 2, "Papa Roach");

Note that no ID and NAME checks were done before adding (it will depend on your logic ai...)

Now how to add an album? The function would be very similar:

ElemA *adiciona_album(ElemA* lista_de_albuns, int id, char * nome){
    ElemA *novo_album;
    novo_album = (ElemA*) malloc(sizeof(ElemA));
    novo_album->id_album = id;
    strcpy(novo_album->nome_album, nome);
    novo_album->prox_album = lista_de_albuns; // também adicionando o novo album no inicio da lista
    novo_album->musica_do_album = NULL; //SUpondo que o álbum deve ser cadastrado antes das músicas e portanto ele é criado vazio.
    return novo_album;
}

Suppose you want to add the Album Infest and the Album Lovehatetragedy in the band Papa Roach (which is the first in the list of bands in the example):

  bandas->albuns_da_banda = cria_lista_album(bandas->albuns_da_banda, 1, "Infest");
  bandas->albuns_da_banda = cria_lista_album(bandas->albuns_da_banda, 2, "LoveHateTragedy");

In case you wanted to add the Album The world will in the band Ivete...

  ElemB *p = bandas->prox_banda; //*p vai conter o endereço do Nó da Banda Ivete
  p->albuns_da_banda = cria_lista_album(p->albuns_da_banda, 1, "O mundo vai");

Again, I’m not checking to see if id or name the album already exists.

The way you’re going to do with music is very similar:

  ElemM *adiciona_musica(ElemM* lista_de_musicas, int id, int tempo, char * nome){
       ElemM nova_musica* = (ElemM*) malloc (sizeof(ElemM));
       nova_musica->id_musica = id;
       nova_musica->tempo_musica = tempo;
       strcpy(nova_musica->nome_musica, nome);
       nova_musica->prox_musica = lista_de_musicas;
       return nova_musica;

  }

And assuming you want to add the Lovehatetragedy song to Papa Roach’s Lovehatetragedy album, the name would be:

 ElemM *p = bandas->albuns_da_banda->musicas; //já sei que Papa Roach ta no inicio da lista e que LoveHateTragedy é o primeiro álbum...
 p = adiciona_musica(p, 1, "LoveHateTragedy");

Doing so... I recommend changing the search functions to return a pointer (or NULL if not found). In this example I used the positions of the bands and albums I already knew to shorten the example. I will leave only the header of the search functions I would use and the implementation is for you:

 //pra buscar a banda você pode passar tanto a variável bandas como parâmetro ou 
 //deixar sem passar por parâmetro, já que ela foi declarada como variável global.
 ElemB* busca_banda_por_id(int id);
 ElemB* busca_banda_por_nome(char *nome);

 //Aqui você precisa passar a lista de Álbuns que da banda que
 //encontrou na chamada de uma das buscas de banda como parâmetro.
 //Tome cuidado que a busca_banda pode retornar NULL, verifique isso antes de chamar
 //uma das 2 funções abaixo.
 ElemA* busca_album_por_id(ElemA* albuns_da_banda, int id); 
 ElemA* busca_album_por_id(ElemA* albuns_da_banda, char *nome);

 //E, de forma análoga, estariam as funções de buscar a musica
 ElemM* busca_musica_por_id(ElemM* musicas_do_album, int id);
 ElemM* busca_musica_por_id(ElemM* musicas_do_album, char *nome);

0

Apparently there’s an error in your library. Where there is "struct casa" it should be "struct musica".

This error occurs in 3 different places.

  • I fixed that, but this giving error in the function include music. I’m not able to include any music, I’m not sure if what I did is logically correct.

  • A does not seem to exist the new struct does not exist, and besides I do not know if it was created the lists of correct way.

-2

Okay, let’s go in parts! If you want to create a library . h, you must have a file . c without main function, where you will have all the functions that exist in that . h . That way, main should be in a separate file for it, where you will include the library . h that you created.

Also, in C, if you want to call function A from within function B, make sure that function A is positioned somewhere in the code above function B. That’s why main should always stay below all other functions ;)

Finally, you should put the proper includes (<stdio.h>, <stdlib.h>,<string.h> etc.) in all files . c, both in main and . c for . h.

After I put these things away, I believe that if I make one more mistake, it will just be little problems of code or logic! Good luck, qqr thing we’re there

Browser other questions tagged

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