Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

carvalho2707

Lista nula em c :s

Recommended Posts

carvalho2707

boas, este programa recebe como imput isto:

p 000011 4.32 5.32 bananas

p 000122 3.12 4.32 macas

c

000122

t

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

typedef struct{
int codigoProduto;
double preco;
double IVA;
char descricao[21];
}Produto; /* estrutura de um produto */

typedef struct node{
Produto* p_dados;
struct node *p_prox;
}no; /* estrutura de um no, que ira constituir uma lista */

void criaLista(no* inicio){
inicio=NULL;
}  /* funcao que cria uma lista vazia */

void Insere(Produto* _produto, no *inicio){
no* p;
p = (no*) malloc(sizeof(no));
p->p_dados = _produto;
p->p_prox = NULL;
if (inicio == NULL)
	inicio = p;
else {
	p->p_prox = inicio;
	inicio = p; 
}
}/* insere um elemento no inicio da lista */

void Imprime(no* inicio){
no *ptr;
if (inicio == NULL){
	printf("---fim da lista---\n");
}
/*caso lista nao esteja vazia*/
ptr = inicio;
while (ptr != NULL){
	printf("codigoProduto: %d, preco: %f, IVA: %f, descricao: %s", ptr->p_dados->codigoProduto, ptr->p_dados->preco, ptr->p_dados->IVA, ptr->p_dados->descricao);
	ptr = ptr->p_prox;
}
printf("---fim da lista---\n");
}

Produto* leProduto(Produto* _produto){	
getchar();	          /* "salta" os espaços em branco */
scanf("%d ", &(_produto->codigoProduto)); 
scanf("%lf ", &(_produto->preco));
scanf("%lf ", &(_produto->IVA));  
scanf("%s ", (_produto->descricao));
return _produto;

}

no *inicio = NULL; /* cria o inicio da lista (inicialmente tava fora)*/

int main(){
Produto* _produto;

_produto = (Produto*) malloc(sizeof(Produto));	
criaLista(inicio);
while (getchar() == 'p'){
	_produto = leProduto(_produto);
	Insere(_produto, inicio);
}
Imprime(inicio);	
return 0;
}




resumindo, ele insere o 1º produto na lista na funcao insere.. mas quando saio dessa funcao a lista perde-se e toda a lista nula :/

porque? e como mudar isso?

obrigado pela ajuda :(

Share this post


Link to post
Share on other sites
KTachyon

Basicamente estás a colocar os novos nós no início da lista, correcto? Podes retornar o nó na função e atribuir exteriormente ao início. Mas a forma correcta seria mesmo adicionares novos nós ao final da lista, não ao início.


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
pmg

Porque, em C, todos os argumentos de uma funcao sao passados por valor.

Quando chamas a funcao Insere com

                Insere(_produto, inicio);

o inicio dentro da funcao propriamente dita nao tem nada a ver com o inicio que estavas a usar no main. Sao objectos diferentes. Quando alteras o objecto visivel dentro da funcao nao ha alteracoes ao objecto visivel dentro da funcao main.

Para as alteracoes dentro da funcao se reflectirem na main, tens de passar um ponteiro para o ponteiro

void Insere(Produto *_produto, no **inicio); // prototipo

Dentro da funcao podes alterar o objecto da main com, por exemplo

                *inicio = p;

Notas:

1) o cast ao resultado da funcao malloc nao e necessario e pode esconder um erro que o compilador achava se nao houvesse cast

2) evita identificadores comecados por _: estes estao reservados pela linguagem (as regras sao ligeiramente mais complicadas e _produto é valido).

3) cada malloc tem de ter um free associado para evitar "memory leaks"

4) o comentario com a descricao do que uma funcao faz fica melhor, a meu ver, no principio da dita funcao em vez do no fim

5) evita variaveis globais


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
carvalho2707

Porque, em C, todos os argumentos de uma funcao sao passados por valor.

Quando chamas a funcao Insere com

                Insere(_produto, inicio);

o inicio dentro da funcao propriamente dita nao tem nada a ver com o inicio que estavas a usar no main. Sao objectos diferentes. Quando alteras o objecto visivel dentro da funcao nao ha alteracoes ao objecto visivel dentro da funcao main.

Para as alteracoes dentro da funcao se reflectirem na main, tens de passar um ponteiro para o ponteiro

void Insere(Produto *_produto, no **inicio); // prototipo

Dentro da funcao podes alterar o objecto da main com, por exemplo

                *inicio = p;

Notas:

1) o cast ao resultado da funcao malloc nao e necessario e pode esconder um erro que o compilador achava se nao houvesse cast

2) evita identificadores comecados por _: estes estao reservados pela linguagem (as regras sao ligeiramente mais complicadas e _produto é valido).

3) cada malloc tem de ter um free associado para evitar "memory leaks"

4) o comentario com a descricao do que uma funcao faz fica melhor, a meu ver, no principio da dita funcao em vez do no fim

5) evita variaveis globais

tens toda a razao, os comentarios foi a outra pessoa do grupo que fez.. eu aco mais intuitivo por no inicio..

o que é o cast? eu tenho ainda dificuldade em perceber os termos

Share this post


Link to post
Share on other sites
pmg

o que é o cast? eu tenho ainda dificuldade em perceber os termos

O cast é uma conversao explicita de tipo de dados.

O C faz muitas conversoes automaticamente, incluindo do tipo void * para qualquer outro tipo de ponteiros.

int a = 8.3; // conversao implicita de double para int
double x = 10000; // conversao implicita de int para double
struct qualquercoisa *ponteiro = malloc(sizeof *ponteiro); // conversao implicita de void * para struct qualquercoisa *

int a = (int)8.3; // conversao explicita desnecessaria
double x = (double)10000; // conversao explicita desnecessaria
struct qualquercoisa *ponteiro = (struct qualquercoisa *)malloc(sizeof *ponteiro); // conversao explicita desnecessaria

printf("%d\n", 3.1416); // erro: o printf nao faz ajustes entre o formato ("%d" para int) e os argumentos
printf("%d\n", (int)3.1416); // conversao explicita necessaria


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

ja fiz a função a adicionar no fim agora é complicado mudar XD ja descobri o erro, estava a fazer uma copia do ponteiro ,e quando a funcao void acabava a lista perdia-se porque era so uma copia..

aproveito agora para perguntar outra coisa,

C:\Users\Tiago\Desktop\agora\final\main.c||In function 'Insere6':|

C:\Users\Tiago\Desktop\agora\final\main.c|121|warning: comparison between pointer and integer|

C:\Users\Tiago\Desktop\agora\final\main.c|123|warning: assignment makes pointer from integer without a cast|

C:\Users\Tiago\Desktop\agora\final\main.c|127|warning: comparison between pointer and integer|

quais são estas linhas ???

o que significa isso?

a funcao insere 6 é



no6* Insere6(_codigo, list6, codigotemp){

    no6* p;
p = (no6*) malloc(sizeof(no6));

    if  ( procuraRepetidos6 (codigotemp , list6 ) != 1 )
    {
        p->info = _codigo;
        p->next = NULL;
    }

if (list6 == NULL)
	list6 = p;
else {
	p->next = list6;
	list6 = p;
	}

return list6;
}

sem saber quais as linhas é impossivel responder porque existe chamadas a funções que não se sabe a definição destas alem de não saber os tipos de dados de algumas variaveis


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
pmg

então porque deu erro no meu codigo? nao fiz isso :/

A situacao dos casts deveu-se unicamente as notas da minha resposta. Essas notas nao eram necessariamente erros do codigo, mas antes notas gerais sobre programacao em C (as conversoes explicitas ao valor de retorno do malloc nao geram erro mesmo que haja: por isso mesmo é que é de evitar fazer a conversao explicita --- para o compilar mostrar o erro caso haja. O teu codigo nao tem o erro que o cast esconde, por isso a presenca do cast, embora de mau gosto, é irrelevante).


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

no6* procuraRepetidos6(codigotemp, list6 ){

if  ( procuraRepetidos6 (codigotemp , list6 ) != 1 )

respondido : C:\Users\Tiago\Desktop\agora\final\main.c|121|warning: comparison between pointer and integer|

no6* Insere6(_codigo, list6, codigotemp){

(não tenho a certeza mas acho sem declaração de tipos os argumentos da função são considerados como int)

typedef struct nodeaux{
    Lista* info;
    struct nodeaux *next;
} no6, no13, no23;

p->info = _codigo;

respondido : C:\Users\Tiago\Desktop\agora\final\main.c|123|warning: assignment makes pointer from integer without a cast|

o 127 é igual ao de cima


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
pmg

Codigo anterior relevante

no6* procuraRepetidos6(codigotemp, list6 )

Codigo com erro

linha 121 : if  ( procuraRepetidos6 (codigotemp , list6 ) != 1 )

Razao do erro:

no if estas a comparar um no6* (o resultado da funcao) com um int (o 1)

-------------------------------------------------------------------------------------

Codigo anterior relevante

typedef struct nodeaux { Lista* info; struct nodeaux *next; } no6;
no6* p;
no6* Insere6(_codigo, list6, codigotemp);

Codigo com erro

lina 123 :         p->info = _codigo;

Razao do erro

O _codigo esta declarado na definicao da funcao sem tipo, portanto a linguagem da-lhe o tipo int.

o p->info é um apontador para um objecto do tipo Lista.

Nao é possivel atribuir um int a um apontador

-------------------------------------------------------

Nota:

1) aumenta o nivel de warnings do teu compilador e preocupa-te em fazer "compilacoes limpas": sem erros (claro!) nem warnings.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
carvalho2707

Codigo anterior relevante

no6* procuraRepetidos6(codigotemp, list6 )

Codigo com erro

linha 121 : if  ( procuraRepetidos6 (codigotemp , list6 ) != 1 )

Razao do erro:

no if estas a comparar um no6* (o resultado da funcao) com um int (o 1)

a ideia é o resultado da funcao ser 1 se o produto ja existir na lista. nao foi isso que eu escrevi?

-------------------------------------------------------

Nota:

1) aumenta o nivel de warnings do teu compilador e preocupa-te em fazer "compilacoes limpas": sem erros (claro!) nem warnings.

aumento como?

eu estava preocupado em avançar e dps corrigir tudo.. mas nao, agora so avanço quando nao houver erros nem warnings

Share this post


Link to post
Share on other sites
HappyHippyHippo

a ideia é o resultado da funcao ser 1 se o produto ja existir na lista. nao foi isso que eu escrevi?

nop.

Olha bem para o tipo de dados que a função retorna ...

aumento como?

adiciona o parâmetro -Wall ao compilador

eu estava preocupado em avançar e dps corrigir tudo.. mas nao, agora so avanço quando nao houver erros nem warnings

Estamos sempre a aprender !!!


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
carvalho2707

adicionei ja e os warnings foram iguais  :( mas fica ja para quando aparecer :P

a funcao diz que enquanto o p->next for diferente de null ele faz o que esta la dentro.. la dentro diz que se o cpAux = codigo temp ele faz p->next = NULL e torna c=1.. p->next = nulll faz terminar o ciclo .. se nao for ele aponta para o proximo.. quando o ciclo acabar ele retorna 0... mas eu nao consigo retornar c :/

Share this post


Link to post
Share on other sites
carvalho2707

Codigo anterior relevante

typedef struct nodeaux { Lista* info; struct nodeaux *next; } no6;
no6* p;
no6* Insere6(_codigo, list6, codigotemp);

Codigo com erro

lina 123 :         p->info = _codigo;

Razao do erro

O _codigo esta declarado na definicao da funcao sem tipo, portanto a linguagem da-lhe o tipo int.

o p->info é um apontador para um objecto do tipo Lista.

Nao é possivel atribuir um int a um apontador

então vou declarar o _codigo no main, e passo-o para a funcao onde estava  a declarar anteriormente

quanto ao p->info    , tenho que acrescentar ->cpAux?

Share this post


Link to post
Share on other sites
pmg

O zero e um caso especial de apontador NULL.

Ao definires uma funcao que devolve um apontador

no6 *procuraRepetidos6(codigotemp, list6) {
    return 0;
}

e ao fazeres return 0; o compilador converte automagicamente (sem se queixar) o 0 para NULL.

O que interessa nao e o que esta no return. O que interessa e o que esta na definicao da funcao.

-----------------------------------------------------------------------------

Nota: especifica sempre o tipo dos argumentos para as funcoes; nao te baseies nos defaults da linguagem (que passaram a ser erro em 1999).

no6 *procuraRepetidos6(int codigotemp, int list6);


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
jpaulino

delete

Deixa-me desde já dizer que isto é uma atitute lamentável. Depois de te ajudarem, resolves apagar o tópico original impedindo outros utilizadores de saber qual a origem das soluções apresentadas.

O tópico irá ser recuperado e trancado!

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.