altyouth@mac:~/MATERIAL FACULDADE/ESTRUTURA DE DADOS/LISTA$ g++ insere_inicio.cpp -oinsere_inicio.exe
insere_inicio.cpp: In function ‘void insereh(celula**, int)’:
insere_inicio.cpp:14:16: error: invalid conversion from ‘void*’ to ‘celula* {aka lista*}’ [-fpermissive]
novo = malloc(sizeof(celula));
to estudando p EStrutura de Dados , ai peguei um código e joguei no compilador , mas tá dando erro e eu to tentando entender o código na verdade
#include<iostream>#include<cstdlib>usingnamespace std;typedefstruct lista{int elemento ;struct lista *prox;}celula;
Um primeiro problema é que você está misturando estilos de C++ com C.
Em C++ é redundante atribuir um nome de tipo a algo que já foi declarado como estrutura. O jeito C++ de reescrever a declaração acima seria o seguinte.
struct celula {int elemento;
celula *prox;};
void insereh(celula **topo ,int ele){
celula *novo;
novo = malloc(sizeof(celula));
Aqui o erro principal, que também é consequência da mistura de estilos entre C e C++.
Em C++, a maneira usual de alocar e desalocar memória é através dos operadores new e delete. Esses operadores são melhores do que as funções malloc() e free() do C porque são seguros quanto a tipos de dados envolvidos.
A maneira correta de reescrever a linha acima em C++ é a seguinte.
novo=new celula;
Se você tiver de usar malloc(), tem de se adaptar ao fato que que ele devolve um ponteiro para um tipo diferente daquele que recebe o endereço da alocação, de modo que você é forçado a fazer explicitamente uma conversão de tipos (essa conversão de tipos é automática e feita implicitamente em C, mas não o é em C++ porque poderia levar conversões de tipo inseguras).
Uma forma correta, MAS NÃO RECOMENDADA, de fazer isso seria a seguinte.
Há razões para preferir usar “decltype(novo)” e “sizeof *novo” a, respectivamente, “cliente *” e “sizeof(cliente)”. O mais eloquente, para mim, é que você só precisa fazer a correspondência entre a variável e o seu tipo apenas umas vez, na hora da declaração, e não ficar reexpressando tal associação em outras partes do código. Isso facilita inclusive a manutenção do código: se amanhã você decidir trocar o tipo do ponteiro, não vai precisar mudar também a linha que faz a alocação.
Outro jeito de fazer é AINDA PIOR: usar malloc() e conversão de tipos ao estilo de C. Não vou nem mostrar, para você não achar que eu a chancelei. Essa conversão é ruim até em C, já que é redundante, e pior ainda em C++, por passar por cima do sistema de tipos sem nenhuma chance de deixar o compilador detectar se a conversão é segura ou não.
novo -> elemento = ele;if(*topo==NULL){
Em C++ geralmente não se usa “NULL”. Se você usar uma versão antiga do C++ (antes do padrão de 2011), o usual era comparar com o valor 0 mesmo (ou não comparar com nada, pois um ponteiro nulo é automaticamente entendido como falso num contexto de valor booleano, e qualquer outro valor de ponteiro é entendido como verdadeiro). A partir do padrão de 2011, existe o valor específico nullptr, que é mais seguro quanto a tipo de dados do que a antiga macro NULL do C.
novo -> prox=NULL;*topo = novo;}else{
novo-> prox=*topo;*topo = novo;}}void printar(celula *topo){
celula *aux;
aux = topo;if(aux==NULL){}else{
Por que essa construção assim, com um bloco de condição verdadeira vazio, e tudo o que existe para fazer ser executado apenas quando a condição é falsa? Seria melhor você inverter o teste, e omitir completamente o bloco else.
do{
cout<<aux->elemento;
aux = aux->prox;}while(aux!=NULL);}
Bom, agora ainda piorou. Na verdade, todo o bloco “if(!aux){ /*nada!*/ } else { do { /*imprime e avança aux*/ } while(aux); }” pode ser escrito de modo mais sucinto do seguinte modo.