Why can’t I print out what’s on the list?

Asked

Viewed 76 times

0

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

typedef struct cadastro {
  char nome[30];
  char matricula[30];
  char Disciplinas[30];
  char notas[30];
  struct cadastro *proxno;
} alunos;

int inserir_aluno_inicio(alunos *lista);
alunos *remover_aluno(alunos *lista);
int menu(void);
void opcoes(alunos *lista, int opc);
alunos *liberar();
int inicializar();
void imprimir(alunos *lista);

int main()
{
  int opcao;
  alunos *lista = (alunos *)malloc(sizeof(alunos));

  lista = inicializar();

  do
  {
    opcao = menu();
    opcoes(lista, opcao);
  } while (opcao != 5);

  return 0;
}

int inicializar()
{
  return NULL;
}

int inserir_aluno_inicio(alunos *lista)
{  
  alunos *novo = (alunos *)malloc(sizeof(alunos));

  if (novo == NULL)
  {
    puts("Sem memória");
    return 1;
  }

  printf("Digite o nome do aluno ou da aluna: ");
  scanf(" %s", novo->nome);

  printf("Digite a matricula do aluno ou aluna[5 numeros ou letras]:");
  scanf(" %s", novo->matricula);

  printf("Digite a disciplina do aluno ou aluna: ");
  scanf(" %s", novo->Disciplinas);

  printf("Digite a nota da aluna ou do aluno:");
  scanf(" %s", novo->notas);

  puts("");

  novo->proxno = lista;
  lista = novo;
  return 0;
}  
//  
int menu()
{
  int ale;
  puts(" M E N U___E S C O L A R___V I N G A D O R E S \n");
  puts("=============================\n");
  printf("[ 0 ] INSERIR ALUNO     =\n");
  puts("[ 1 ] REMOVER ALUNO       =\n");
  puts("[ 2 ] IMPRIMIR INFORMACOES DO ALUNO =\n");
  puts("[ 3 ] LIMPAR LISTA DE ALUNOS =\n");
  puts("[ 4 ] SAIR DA LISTA        =\n");
  puts("==============================\n");
  scanf("%d", &ale);
  return ale;
}  

void opcoes(alunos *lista, int opc)
{
  switch (opc)
  {
    case 0:
      inserir_aluno_inicio(lista);
      break;
    case 1:
      break;
    case 2:
      imprimir(lista);
      break;
    case 3:
      break;
    case 4:
      puts("Ate a proxima!");
      break;  
    default:
      puts("Nao existe essa opcao tente novamente!");
  }
}  

void imprimir(alunos *lista)
{
  alunos *aux = lista;
  while (aux != NULL)
  {  
    printf("O nome da aluna(o): %s", aux->nome);
    printf("\n");
    printf("A matricula do aluno(a) e: %s", aux->matricula);
    printf("\n");
    printf("A disciplina da aluna(o) e: %s",aux->Disciplinas);
    printf("\n");
    printf("A nota do aluno (a): %s", aux->notas);
    printf("\n");
    aux = aux->proxno;
  }  
}  

WHAT I HAVE ALREADY TRIED TO DO: What I have tried is to allocate memory to a new element that is a new registration, but when I call print function it shows number and random characters. Even when I do to the main list receive the new allocation, which is what I tried.

1 answer

2


Let’s see...

Keep in mind the following:

  • A pointer is a variable that stores an address instead of a known type value. If accessed, the saved address may contain another address or a known type value;

  • Every variable has its own address. Thus, a "traditional" variable has its own address and a pointer variable as well. Let’s work with equality - always!

  • The name of a variable is nothing more than a mnemonic to her address. That is, a synonym.

Looking closely at the problem

Consider the following generic representation code:

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

typedef struct meu { int valor; struct minha *prox; } tipo;

void incluir(tipo *lista){

    tipo *temp = (tipo *) malloc(...);

    temp->valor = 5;

    temp->prox = lista;
    lista = temp;

}

void imprimir(tipo *lista){

    while(temp != NULL){
        printf("%d ", lista->valor);
        temp = temp->prox;
    }

}

int main(){

    tipo *lista = NULL;

    incluir(lista);
    imprimir(lista);

    return(0);
}

Now let us narrate the events that follow:

  • creates a pointer called lista of a given tipo;
  • give the address pointed by the pointer lista for the inclusion function;
  • in the inclusion function, a temporary pointer is created for a new data entry;
  • stands in the prox from the new entry the address pointed by the pointer lista;
  • pointer lista point to the address of the new entry;
  • call the print function to print the contents of the list;
  • fails miserably and inquires about the craft of Dennis Ritchie’s mother;

In order to save the honor of the poor lady mother of this computer genius, we must mitigate the problem. Let’s go!

Case analysis

Consider that the pointer address lista be it 0x02. Pay attention: it is his address and not his content; that he points out! In case, lista points to NULL. then we have something like 0x02 -> NULL in memory.

Consider the memory table to assist in the explanation:

+===================================+
|         Tabela de Memória         |
+----------+------------------------+
| Endereço | Valor                  |
+===================================+
|   0x01   | 5                      |
+----------+------------------------+
|   0x02   | NULL                   |
+----------+------------------------+
|   0x03   | 0x30                   |
+----------+------------------------+
|   0x04   | livro k&r download pdf |
+----------+------------------------+
|   0x05   | NULL                   |
+----------+------------------------+
|   0x06   | ab..$5%ab asd/         |
+----------+------------------------+
+         ...                       +        

As we passed lista as an argument for incluir(), we passed the address he points to. We passed NULL. Remember that a variable always passes its value in any normal instance and not its address.

Within the function incluir(), we hope that lista is at the address 0x02 with the value NULL. OK...

THERE! Trickster of the rascal!

This is completely wrong! What we have in lista (in incluir()) is the value pointing the pointer and not the address of the pointer. The variable lista (in incluir()) is actually another variable at another address (say 0x05). Only the amount it points to lista in incluir() is the same as lista in main().

The direct consequence of this is that the reference is lost. That explains why we failed to print.

Solution

To deal with this problem, we need the value pointed out by lista and the address of lista in itself. This is easily done by passing &lista for the functions instead of lista. This way, our memory would be like this:

+===================================+
|         Tabela de Memória         |
+----------+------------------------+
| Endereço | Valor                  |
+===================================+
|   0x01   | 5                      |
+----------+------------------------+
|   0x02   | NULL                   |
+----------+------------------------+
|   0x03   | 0x30                   |
+----------+------------------------+
|   0x04   | livro k&r download pdf |
+----------+------------------------+
|   0x05   | 0x02                   |
+----------+------------------------+
|   0x06   | ab..$5%ab asd/         |
+----------+------------------------+
+         ...                       +   

Our jobs would look like this:

void incluir(tipo **lista){ ...

void imprimir(tipo **lista){ ...

Function calls would be as follows:

incluir( &lista );
imprimir( &lista );

Concluding: list within incluir() will point to the address of lista inside main() which in turn will point to the known type. Thus, you can also track lista and not only the content to which it points.

Fixing the program

Ideally, try to tidy it up yourself. If you can’t, take a look at this functional version of it.

The code below contains some visual modifications I made to better understand your program. This includes how the information is displayed. Change it as you wish.

Libraries:

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

Structures:

typedef struct cadastro {

    char nome[30];
    char matricula[30];
    char Disciplinas[30];
    char notas[30];

    struct cadastro *proxno;

} alunos;

Job statements:

int inserir_aluno_inicio(alunos **lista);
int menu(void);

void opcoes(alunos **lista, int opc);
void imprimir(alunos **lista);

alunos *remover_aluno(alunos **lista);
alunos *liberar();
alunos *inicializar();

Function main():

int main() {

    int opcao;
    alunos *lista = (alunos *)malloc(sizeof(alunos));

    lista = inicializar();

    do {
        opcao = menu();
        opcoes(&lista, opcao);
    } while (opcao < 4);

    return 0;

}

Function inicializar():

alunos *inicializar() { return NULL; }

Function menu():

int menu() {

    int ale;

    puts("\n  M E N U   E S C O L A R   V I N G A D O R E S \n");
    puts(" ===============================================\n");
    puts(" =  [ 0 ]  INSERIR ALUNO                       =\n");
    puts(" =  [ 1 ]  REMOVER ALUNO                       =\n");
    puts(" =  [ 2 ]  IMPRIMIR INFORMACOES DO ALUNO       =\n");
    puts(" =  [ 3 ]  LIMPAR LISTA DE ALUNOS              =\n");
    puts(" =  [ 4 ]  SAIR DA LISTA                       =\n");
    puts(" ===============================================\n");
    printf(" COMANDO > ");

    scanf("%d", &ale);

    return ale;

}  

Function inserir_aluno_inicio():

int inserir_aluno_inicio(alunos **lista) {  

    alunos *novo = (alunos *) malloc( sizeof( alunos ) );

    if (novo == NULL)
    {
        puts(" Sem memória!");

        return 1;
    }


    printf("\n Digite o nome do aluno ou da aluna: ");
    scanf(" %s", novo->nome);

    printf(" Digite a matricula do aluno ou aluna [5 numeros ou letras]: ");
    scanf(" %s", novo->matricula);

    printf(" Digite a disciplina do aluno ou aluna: ");
    scanf(" %s", novo->Disciplinas);

    printf(" Digite a nota da aluna ou do aluno: ");
    scanf(" %s", novo->notas);

    puts("");


    novo->proxno = *lista;
    *lista = novo;


    return 0;

}

Function opcoes():

void opcoes(alunos **lista, int opc) {

    switch (opc) {

        case 0:
            inserir_aluno_inicio(lista);
            break;

        case 1:
            break;

        case 2:
            imprimir(lista);
            break;

        case 3:
            break;

        case 4:
            puts("\n Ate a proxima!\n");
            break;  

        default:
            puts(" Nao existe essa opcao tente novamente!");

    }

} 

Function imprimir():

void imprimir(alunos **lista) {

    alunos *aux = *lista;

    while (aux != NULL){

        printf("\n\tO nome da aluna(o): %s\n", aux->nome);
        printf("\tA matricula do aluno(a) e: %s\n", aux->matricula);
        printf("\tA disciplina da aluna(o) e: %s\n",aux->Disciplinas);
        printf("\tA nota do aluno (a): %s\n", aux->notas);

        aux = aux->proxno;

    }

} 

The code is also found in Github. If you find it easier, look at it in one file there.

If you still don’t understand, find another source. I recommend this answer from Lucas Virgili.

  • 1

    Thank you. You killed the answer.

  • 1

    It worked, see! I will post the code fixed or leave the above error and your resolution comment?

  • 1

    The platform works as follows: you ask a question and one or more people answer. The best answer among those who solve the problem, you mark as correct and give a positive: the actions serve to thank those who helped you. A correct answer also serves to help others with similar problems. In cases where no one answers or solves the problem, if you find the solution you can write an answer and mark your own answer as correct. The question is only edited to be improved, never to answer. If my answer helped, you can mark as correct. :)

Browser other questions tagged

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