Dynamic stack - C
I am studying dynamic stack from the code below:
#include <stdio.h>
#include <stdlib.h>
#define tam 50
// ---- Estruturas para os tipos -------------------------------------------------------------------------------
typedef struct // Definicao da estrutura do registro
{ // Com definição do tipo (typedef)
int Chave;
// Outros campos
}REGISTRO;
// ---- Funções ligadas aos REGISTROs --------------------------------------------------------------------------
REGISTRO LerRegistro() // Ler os dados de um registro
{
REGISTRO r;
printf("\n\n Digite a chave da pessoa : ");
scanf("%d", &r.Chave);
// Outros campos
return r;
}
void ImprimeRegistro(REGISTRO r) // Imprimir um registro
{
printf(" Chave : %d \n", r.Chave);
// Outros campos
}
// --- Tipo PILHA ---------------------------------------------
struct TNo{
REGISTRO reg;
struct TNo *prox;
};
typedef struct TNo *TPILHA; //não entendi o motivo da criação dessa //struct
void InicializarPilha(TPILHA *pPilha)
{
(*pPilha) = NULL;
}
int PilhaCheia(TPILHA pPilha)
{
return 0;
}
int PilhaVazia(TPILHA pPilha)
{
return (pPilha == NULL);
}
void Empilhar(TPILHA *pPilha, REGISTRO pReg )
{
struct TNo *novo;// pq essa struct foi criada?
novo = (struct TNo *) malloc(sizeof (struct TNo));
novo->reg = pReg;
novo->prox = NULL;// pq o valor do próximo é nulo?
if (*pPilha == NULL)
{
(*pPilha) = novo;//o que essa linha quer dizer?
}
else
{
novo->prox = (*pPilha); //o que essa linha quer dizer?
(*pPilha) = novo; //o que essa linha quer dizer?
}
}
REGISTRO Desempilhar(TPILHA *pPilha)
{
REGISTRO aux;
if (*pPilha == NULL)
{
aux.Chave = -1;
}
else
{
aux = (*pPilha)->reg;
(*pPilha) = (*pPilha)->prox;
}
return aux;
}
void Visualizar(TPILHA pPilha)
{
TPILHA aux1 = pPilha;
printf("\n\n");
while (aux1 != NULL)
{
printf(" %d \n", aux1->reg.Chave);
aux1 = aux1->prox;
}
printf(" ------- ");
printf("\n\n");
}
// ---- Funções Uteis --------------------------------------------------------------------------
char Menu2() // Menu com retorno da
// opcao selecionada
{
char o;
printf(" -- Menu -- \n");
printf(" ( A ) Adicionar ao Estoque \n");
printf(" ( R ) Retirar do estoque \n");
printf(" ( > ) Transferir da Pilha 1 para a Pilha 2 \n");
printf(" ( < ) Transferir da Pilha 2 para a Pilha 1 \n");
printf(" ( V ) Visualizar Estoque \n");
printf(" ( S ) Sair \n");
printf("\n Opcao : ");
fflush(stdin);
scanf("%c", &o);
return o;
}
main()
{
TPILHA p1, p2;
char opcao;
InicializarPilha(&p1);
InicializarPilha(&p2);
do
{ opcao = Menu2();
switch(opcao)
{
case 'A': case 'a':
{
// Solicitar qual pilha
printf(" Digite qual pilha : ");
int p;
scanf("%d", &p);
// Qual registro
REGISTRO aux;
printf(" Digite qual codigo : ");
scanf("%d", &aux.Chave);
// Empilhar
if (p==1)
Empilhar(&p1, aux);
else
Empilhar(&p2, aux);
} break;
case 'R': case 'r': {
// Solicitar qual pilha
printf(" Digite qual pilha : ");
int p;
scanf("%d", &p);
// Desempilhar
if (p==1)
Desempilhar(&p1);
else
Desempilhar(&p2);
}break;
case '<': {
REGISTRO raux;
raux = Desempilhar(&p2);
Empilhar(&p1, raux);
}break;
case '>': {// Mover de Pilha 1 para Pilha 2
REGISTRO raux;
raux = Desempilhar(&p1);//Desemp de P1
Empilhar(&p2, raux); //Emp em P2
}break;
case 'V': case 'v': {
printf("pilha 1 :\n ");
Visualizar(p1);
printf("\n ----- \n ");
printf("pilha 2 :\n ");
Visualizar(p2);
printf("\n\n\n ");
}break;
case 's':
case 'S': printf(" Opcao SAIR escolhida \n"); break;
default : printf(" Opcao invalida. \n");
}
system("pause");
system("cls");
}
while( (opcao != 'S') && (opcao != 's') );
}
I know how to assemble the structure, but I am in doubt in some parts that are commented in the code, in case what the specific lines do
1 answers
typedef struct TNo *TPILHA; //não entendi o motivo da criação dessa //struct
This does not create a struct
. It's just a typedef
that says a pointer to the structure TNo
is called TPILHA
. In fact this type of typedefs are disconcerted because they make it difficult to read because they hide the pointer. Something similar yet simpler to realize would be:
typedef int inteiro;
Which means that inteiro
becomes a type equivalent to int
and then allows you to do something like inteiro x = 10;
As for comments in function Empilhar
:
void Empilhar(TPILHA *pPilha, REGISTRO pReg )
{
struct TNo *novo;// pq essa struct foi criada? (1)
novo = (struct TNo *) malloc(sizeof (struct TNo));
novo->reg = pReg;
novo->prox = NULL;// pq o valor do próximo é nulo? (2)
if (*pPilha == NULL)
{
(*pPilha) = novo;//o que essa linha quer dizer? (3)
}
else
{
novo->prox = (*pPilha); //o que essa linha quer dizer? (4)
(*pPilha) = novo; //o que essa linha quer dizer? (5)
}
}
1) Again this line also doesn't create a struct
, it just declares a pointer to a TNo
structure. The creation just comes in the next line with malloc
.
2) the value of the next is null because it is useful to start the new element with something, and when it is empty the necessary is NULL
which symbolizes that it has no more elements ahead. In cases where it is not empty the prox
will again be changed, in the line I marked as (4). I could make it otherwise clear but this tends to be simpler, for the rest of the code the function has.
3) here is changing the stack you received as a pointer. If the stack is empty because it is NULL
then it will become the new node that was created. How you received the stack as a pointer you have to change with the *
using the syntax *ptr = valor;
.
4) if the stack is not empty then the new element created has to point to the last one that was in the stack, given by *pPilha
, i.e. the value pointed by pPilha
.
5) this statement is the same as 3).
Now I personally think it got pretty complicated in terms of syntax and logic. Much simpler would be:
void Empilhar(TPILHA *pPilha, REGISTRO pReg )
{
struct TNo *novo = malloc(sizeof (struct TNo));
novo->reg = pReg;
novo->prox = *pPilha;
*pPilha = novo;
}
So few lines to do the same! Ideas behind this transformation:
Doing
*pPilha =
or(*pPilha) =
is the same as parentheses are redundant in this case.-
(*pPilha) = novo;
it was inif
and inelse
so it does not depend onif
and should come after novo->prox = *pPilha;
- if you putprox
toNULL
when*pilha
isNULL
and you putprox
to*pilha
when it is not then you always put*pilha
which is much simpler.= malloc(sizeof (struct TNo));
the cast in themalloc
is not necessary and ends up simplifying reading among other things without it.