Problemas com realloc

1. Problemas com realloc

Netinho
netinhocqc

(usa Outra)

Enviado em 13/02/2012 - 17:54h

estou com dois problemas no código a seguir, na função preencher esta dando um erro na linha de realloc e na linha de lê o nome, idade, e matricula. desde já agradeço.


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

typedef struct cadastro{
char nome[30];
int idade;
int matricula;
}cadastro;

void preencher(cadastro *aluno, int cont);
void imprimir(cadastro *aluno);
void pesquisar(cadastro *aluno);
void criar();

int main(){
int op;
FILE *arquivo;
int cont=0;
cadastro *aluno;
aluno = (cadastro *)malloc(sizeof(cadastro)*cont);
criar();
printf("\t\t\t\tCadastro de Alunos\n\n");
do{
printf("--------------------------------------------------------------------------------\n\n");
printf("\t\t\t\t(1) - Cadastrar Aluno \n");
printf("\t\t\t\t(2) - Lista Alunos \n");
printf("\t\t\t\t(3) - Pesquisar Aluno \n");
printf("\t\t\t\t(4) - Ordenar Lista\n");
printf("\t\t\t\t(5) - Remover Alunos\n");
printf("\t\t\t\t(6) - Sair\n\n");
printf("--------------------------------------------------------------------------------\n\n");
printf("Digite sua opcao: ");
scanf("%d",&op);
switch(op){
case 1:
cont++;
preencher(aluno, cont);
break;
case 2:
imprimir(aluno);
break;
case 3:
pesquisar(aluno);
break;
default:
printf("Saindo!\n");
}
}while(op != 6);
system("pause");
}
void criar(){
FILE *arquivo;
if((arquivo = fopen("Windows.txt","wb")) == NULL){
exit(0);
}
fclose(arquivo);
}
void pesquisar(cadastro *aluno){
FILE *arquivo;
char Npesquisa[50];
fflush(stdin);
if((arquivo = fopen("Windows.txt","rb")) == NULL){
exit(0);
}
printf("--------------------------------------------------------------------------------\n\n");
printf("Digite do Aluno que deseja pesquisar: ");
fgets(Npesquisa,50,stdin);
printf("\n");
if(fread(&aluno,sizeof(struct cadastro),1,arquivo) != 1){
exit(0);
}
if(strcmp(Npesquisa,aluno->nome) == 0){
fread(&aluno,sizeof(struct cadastro),1,arquivo);
printf("Nome: %sIdade: %d\nMatricula %d\n",aluno->nome, aluno->idade, aluno->matricula);
}else{
printf("Nome nao encontrado\n");
}
fclose(arquivo);
printf("--------------------------------------------------------------------------------\n\n");
}


void imprimir(cadastro *aluno){
FILE *arquivo;
if((arquivo = fopen("Windows.txt","rb")) == NULL){
exit(0);
}
while (1) {
if (fread(&aluno, sizeof (struct cadastro), 1, arquivo) < 1){
break;
}
printf("Nome: %sIdade: %d\nMatricula %d\n",aluno->nome, aluno->idade, aluno->matricula);
}
fclose(arquivo);
}

void preencher(cadastro *aluno, int cont){
FILE *arquivo;
if(aluno = (cadastro *)realloc(aluno,sizeof(cadastro)*cont) == NULL){
exit(0);
}
if((arquivo = fopen("Windows.txt","ab")) == NULL){
exit(0);
}
for(int i=0; i<cont; i++){
fflush(stdin);
printf("Digite o Nome do Aluno: ");
fgets(aluno->nome,30,stdin);
printf("Digite a Idade do Aluno: ");
scanf("%d",&aluno->idade);
printf("Digite a Matricula do Aluno: ");
scanf("%d",&aluno->matricula);
fwrite(&aluno,sizeof(struct cadastro),1,arquivo);
}
fclose(arquivo);
}



  


2. Re: Problemas com realloc

Alex Fernando Ferreira
staltux

(usa Slackware)

Enviado em 15/02/2012 - 08:40h

não sei se ja resolveu o problema pois ja fazem dois dias, mas mesmo assim...

não estou em casa pra testar, mas de cara ja vi uma coisa estranha no seu codigo, na linha do realloc

if(aluno = (cadastro *)realloc(aluno,sizeof(cadastro)*cont) == NULL){


tente trocar por

if( (aluno = (cadastro *)realloc(aluno,sizeof(cadastro)*cont) ) == NULL){

quando chegar em casa olho o resto



3. Re: Problemas com realloc

Netinho
netinhocqc

(usa Outra)

Enviado em 15/02/2012 - 16:32h

Consegui resolver sim essa parte do reallo.

Era para fazer assim:

realloc(aluno,sizeof(cadastro)*cont);

pois eu estava fazendo um teste se for igual a NULL e o realloc sempre devolve um NULL.

Agora me apareceu outro problema é para a função imprimir, quando cadastro mais de um aluno ele só mostra o ultimo cadastrado, se poder me dá uma ajudinha desde já agradeço a sua boa vontade.


4. Re: Problemas com realloc

Alex Fernando Ferreira
staltux

(usa Slackware)

Enviado em 16/02/2012 - 09:39h

Bom, fiz funcionar porem mudei varias coisas, eu comentei o codigo, por isso tenha paciencia de ler...

quanto ao realloc, precisa sim pegar o resultado, ele "geralmente retorna NULL", mas nao he sempre nao...

segue o novo codigo, ele cadastra,pesquisa e lista todos os cadastrados...



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

typedef struct cadastro{
char nome[30];
int idade;
int matricula;
}cadastro;

//void preencher(cadastro *aluno, int cont);
// explico o pq da alteracao dentro da funcao

void preencher(cadastro *aluno);
void imprimir(cadastro *aluno);
void pesquisar(cadastro *aluno);

//void criar();
// devido ao modo de abertura 'ab' nao eh necessario
// criar o arquivo previamente, se nao existir o C cria ele

int main(){
int op;

//FILE *arquivo;
// nao estava sendo usada

//int cont=0;
// count nao sera mais usado, explico mais tarde

cadastro *aluno;
//aluno = (cadastro *)malloc(sizeof(cadastro)*cont);
// count eh zero, logo 'cadastro * 0 = a 0'

aluno = (cadastro *)malloc(sizeof(cadastro));

//criar();
// usando essa funcao vc apaga tudo que tinha no arquivo
// por isso mostra sempre o ultimo cadastrado

printf("\t\t\t\tCadastro de Alunos\n\n");
do{
printf("--------------------------------------------------------------------------------\n\n");
printf("\t\t\t\t(1) - Cadastrar Aluno \n");
printf("\t\t\t\t(2) - Lista Alunos \n");
printf("\t\t\t\t(3) - Pesquisar Aluno \n");
printf("\t\t\t\t(4) - Ordenar Lista\n");
printf("\t\t\t\t(5) - Remover Alunos\n");
printf("\t\t\t\t(6) - Sair\n\n");
printf("--------------------------------------------------------------------------------\n\n");
printf("Digite sua opcao: ");
scanf("%d",&op);
switch(op){
case 1:
//cont++;
//preencher(aluno, cont);
preencher(aluno);
break;
case 2:
imprimir(aluno);
break;
case 3:
pesquisar(aluno);
break;
default:
printf("Saindo!\n");
}
}while(op != 6);
system("pause");
}
/*
void criar(){
FILE *arquivo;
if((arquivo = fopen("Windows.txt","wb")) == NULL){
exit(0);
}
fclose(arquivo);
}
*/
void pesquisar(cadastro *aluno){
FILE *arquivo;
char Npesquisa[50];
fflush(stdin);
if((arquivo = fopen("Windows.txt","rb")) == NULL){
// alterado aqui, volta para o menu
printf("\nNenhum Aluno cadastrado.\n");
return;

}
printf("--------------------------------------------------------------------------------\n\n");
printf("Digite do Aluno que deseja pesquisar: ");
fgets(Npesquisa,50,stdin);
printf("\n");

// aqui fazemos um loop ate encontrar o tal aluno
// ou sair

while(1){
// frread espera um ponteiro
// aluno eh ponteiro logo nao precisa do &
if(fread(aluno,sizeof(struct cadastro),1,arquivo) != 1){
printf("Nome nao encontrado\n");
return;
}
if(strcmp(Npesquisa,aluno->nome) == 0){
// pra que ler novamente?
//fread(&aluno,sizeof(struct cadastro),1,arquivo);
printf("Nome: %sIdade: %d\nMatricula %d\n",aluno->nome, aluno->idade, aluno->matricula);
// aluno foi encontrado entao saimos...
break;
}

}
fclose(arquivo);
printf("--------------------------------------------------------------------------------\n\n");
}


void imprimir(cadastro *aluno){
FILE *arquivo;
if((arquivo = fopen("Windows.txt","rb")) == NULL){
// alterado aqui, assim nao fecha do nada
printf("\nLista Vazia.\n");
return;
}
while (1) {
// alterado aqui
// fread espera um ponteiro
// aluno ja eh ponteiro, logo o '&' nao eh necessario
if (fread(aluno, sizeof (struct cadastro), 1, arquivo) < 1){
break;
}
// alterada a identacao da saida aqui
printf("\nNome: %s\tIdade: %d\tMatricula %d\n",aluno->nome, aluno->idade, aluno->matricula);
}
fclose(arquivo);
}


//void preencher(cadastro *aluno, int cont){
void preencher(cadastro *aluno){
FILE *arquivo;
// aqui fiquei em duvida, pq esse realloc ?
// vc esta sempre aumentando o tamanho dele, mas nao entendi o motivo
// ele ja vem alocado por parametro, logo nao eh necessario mecher nisso
//if(aluno = (cadastro *)realloc(aluno,sizeof(cadastro)*cont) == NULL){
//exit(0);
//}

// lembra do cria(), com esse ab nao precisa dele aqui
if((arquivo = fopen("Windows.txt","ab")) == NULL){
exit(0);
}

// outra coisa que fiquei em duvida, pq estao em um for?
// ja que eu peco pra cadastrar direto do menu, isso nao faria
// cadastrar 1 na primeira vez, 2 na segunda e etc?
//for(int i=0; i<cont; i++){

fflush(stdin);
printf("Digite o Nome do Aluno: ");
fgets(aluno->nome,30,stdin);
printf("Digite a Idade do Aluno: ");
scanf("%d",&aluno->idade);
printf("Digite a Matricula do Aluno: ");
scanf("%d",&aluno->matricula);
// alterado aqui
// fwrite espera um ponteiro, aluno ja eh ponteiro
// logo '&' eh desnecessario
fwrite(aluno,sizeof(struct cadastro),1,arquivo);
fflush(arquivo);
// grava tudo antes de sair
fclose(arquivo);
}



Por favor, se encontrar algum erro, ou eu tiver alterado algo que nao podia, me avisa ae ^^;


5. Re: Problemas com realloc

euteste da silva
foxbit3r

(usa Solaris)

Enviado em 16/02/2012 - 10:26h

Que legal.. posso brincar disso tmb?


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

typedef struct cadastro{
char nome[30];
int idade;
int matricula;
}cadastro;


void preencher(cadastro *aluno);
void imprimir(cadastro *aluno);
void pesquisar(cadastro *aluno);

char bordas[]="------------------------------------------\
--------------------------------------\n\n";

char filename[]="Windows.txt";

int main(){
int op;


cadastro *aluno;
aluno = (cadastro *)malloc(sizeof(cadastro));


printf("\t\t\t\tCadastro de Alunos\n\n");
do{
printf(bordas);
printf("\t\t\t\t(1) - Cadastrar Aluno \n");
printf("\t\t\t\t(2) - Lista Alunos \n");
printf("\t\t\t\t(3) - Pesquisar Aluno \n");
printf("\t\t\t\t(4) - Ordenar Lista\n");
printf("\t\t\t\t(5) - Remover Alunos\n");
printf("\t\t\t\t(6) - Sair\n\n");
printf(bordas);
printf("Digite sua opcao: ");
scanf("%d",&op);
switch(op){
case 1:
//cont++;
//preencher(aluno, cont);
preencher(aluno);
break;
case 2:
imprimir(aluno);
break;
case 3:
pesquisar(aluno);
break;
default:
printf("Saindo!\n");
}
}while(op != 6);
system("pause");
}


void pesquisar(cadastro *aluno){
FILE *arquivo;
char Npesquisa[50];
fflush(stdin);
if((arquivo = fopen(filename,"rb")) == NULL){
fprintf(stderr,"\nErro de abertura do arquivo: %s\n",filename);
exit(-1);

}
printf(bordas);
printf("Digite do Aluno que deseja pesquisar: ");
fgets(Npesquisa,50,stdin);
printf("\n");


while(1){

if(fread(aluno,sizeof(struct cadastro),1,arquivo) != 1){
fprintf(stderr,"Nome nao encontrado no arquivo: %s\n");
exit(-1);
}
if(strcmp(Npesquisa,aluno->nome) == 0){
printf("Nome: %sIdade: %d\nMatricula %d\n",aluno->nome, aluno->idade, aluno->matricula);

break;
}

}
fclose(arquivo);
printf(bordas);
}


void imprimir(cadastro *aluno){
FILE *arquivo;
if((arquivo = fopen(filename,"rb")) == NULL){
fprintf(stderr,"\nErro de abertura do arquivo: %s\n",filename);
exit(-1);
}
while (1) {
if (fread(aluno, sizeof (struct cadastro), 1, arquivo) < 1){
break;
}

printf("\nNome: %s\tIdade: %d\tMatricula %d\n",aluno->nome, aluno->idade, aluno->matricula);
}

fclose(arquivo);
}



void preencher(cadastro *aluno){
FILE *arquivo;
if((arquivo = fopen(filename,"ab")) == NULL){
fprintf(stderr,"\nErro de abertura do arquivo: %s\n",filename);
exit(-1);
}


fflush(stdin);
printf("Digite o Nome do Aluno: ");
fgets(aluno->nome,30,stdin);
printf("Digite a Idade do Aluno: ");
scanf("%d",&aluno->idade);
printf("Digite a Matricula do Aluno: ");
scanf("%d",&aluno->matricula);
fwrite(aluno,sizeof(struct cadastro),1,arquivo);
fflush(arquivo);
fclose(arquivo);
}



6. Re: Problemas com realloc

Alex Fernando Ferreira
staltux

(usa Slackware)

Enviado em 16/02/2012 - 11:28h

hehehe, isso esta quase um sourceforge ala VOL...

daqui a pouco vamos ter implementado tudo + interface grafica ^^




7. Re: Problemas com realloc

Netinho
netinhocqc

(usa Outra)

Enviado em 16/02/2012 - 15:51h

vlw cara agora deu uma esclarecidada vlw mesmo por entender essa confusão hehehehe


8. Re: Problemas com realloc

Paulo
paulo1205

(usa Ubuntu)

Enviado em 24/02/2012 - 18:48h

O tópico é velho, e parece que o realloc() nem era necessário mas acho bom frisar que o que foi mostrado aqui é código que esconde bugs potencialmente muito perigosos.

A manpage dos BSDs, nesse particular, é mais rica e esclarecedora, mas o fato é que fazer algo como

ptr = realloc(ptr, new_size); 


pode falhar se o sistema não conseguir alocar new_size bytes na memória. Quando isso acontece, a função normalmente não provoca perdas no conteúdo nem no valor de ptr, mas devolve um valor nulo (NULL) para indicar o erro. O problema, então, é que, por causa da construção que faz uma atribuição do valor retornado pela função ao ponteiro, quando ocorrer um erro de alocação, o valor que havia sido preservado pela função é sobrescrito com um ponteiro nulo, deixando a memória que já estava aolcada anteriormente sem um ponteiro que a referencie.

A forma correta de fazer é semelhante ao que vai abaixo.

new_ptr = realloc(ptr, new_size);
if(new_ptr == NULL){
/* Não conseguiu realocar o ponteiro, mas manteve o
tamanho e os dados anteriores intactos.
Dá algum tratamento à falha de alocação. */
}
else{
/* Realocação bem sucedida. Pode-se, então, sobrescrever
o ponteiro com o valor devolvido. */
ptr = new_ptr;
}



9. Re: Problemas com realloc

Netinho
netinhocqc

(usa Outra)

Enviado em 24/02/2012 - 21:29h

Bem sobre o realloc vc disse que não é necessário, mais foi o meu professor que disse que era para fazer com um realloc toda vez que for cadastrar um aluno, e acho que é esse o meu problema pois eu achava que tinha resolvido pois na função a seguir toda ver que faço um novo cadastro ele sobrescreve o anterior, o que será que eu estou errando?

[code]
void preencher(cadastro *aluno){
FILE *arquivo;
if((arquivo = fopen(filename,"ab")) == NULL){
fprintf(stderr,"\nErro de abertura do arquivo: %s\n",filename);
exit(-1);
}


fflush(stdin);
printf("Digite o Nome do Aluno: ");
fgets(aluno->nome,30,stdin);
printf("Digite a Idade do Aluno: ");
scanf("%d",&aluno->idade);
printf("Digite a Matricula do Aluno: ");
scanf("%d",&aluno->matricula);
fwrite(aluno,sizeof(struct cadastro),1,arquivo);
fflush(arquivo);
fclose(arquivo);
}
[code/]


10. Re: Problemas com realloc

euteste da silva
foxbit3r

(usa Solaris)

Enviado em 25/02/2012 - 10:53h

Cara, vc só tá fazendo alocação de memória para gravar num arquivo.
Os dados não vão ficar na memória e sim no arquivo. Se vc quer manter os dados anteriores na memória vai precisar de uma lista ligada.
Eu vi o seu código e resolvi fazer umas alterações nele.


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

typedef struct cadastro{
char nome[30];
int idade;
int matricula;
}cadastro;


void preencher(cadastro *aluno);
void imprimir(cadastro *aluno);
void pesquisar(cadastro *aluno);

void removeNewLine(void){
while(getchar()!='\n');
}

char bordas[]="------------------------------------------\
--------------------------------------\n\n";

char filename[]="oracle.db";
FILE *arquivo;

int main(){
int op;


cadastro *aluno;
aluno = (cadastro *)malloc(sizeof(cadastro));
if(aluno == NULL) {
fprintf(stderr,"Erro na alocacao de memoria");
exit(-2);
}

printf("\t\t\t\tCadastro de Alunos\n\n");
do{
printf(bordas);
printf("\t\t\t\t(1) - Cadastrar Aluno \n");
printf("\t\t\t\t(2) - Lista Alunos \n");
printf("\t\t\t\t(3) - Pesquisar Aluno \n");
printf("\t\t\t\t(4) - Ordenar Lista\n");
printf("\t\t\t\t(5) - Remover Alunos\n");
printf("\t\t\t\t(6) - Sair\n\n");
printf(bordas);
printf("Digite sua opcao: ");
scanf("%d",&op);
switch(op){
case 1:
preencher(aluno);
break;
case 2:
imprimir(aluno);
break;
case 3:
pesquisar(aluno);
break;
default:
printf("Saindo!\n");
}
}while(op != 6);
free(aluno);
}


void pesquisar(cadastro *aluno){
char Npesquisa[30];
fflush(stdin);
if((arquivo = fopen(filename,"rb")) == NULL){
fprintf(stderr,"\nErro de abertura do arquivo: %s\n",filename);
exit(-1);

}
printf(bordas);
removeNewLine();
printf("Digite do Aluno que deseja pesquisar: ");
scanf("%s30[^\n]",Npesquisa);
putchar('\n');

printf("\nNome\t\tIdade\t\tMatricula ");
while(fread(aluno,sizeof(struct cadastro),1,arquivo)>0){
if(strcmp(Npesquisa,aluno->nome) == 0){
printf("\n%s\t\t%d\t\t%d",aluno->nome,\
aluno->idade, aluno->matricula);
break;
}

}
fclose(arquivo);
putchar('\n');
printf(bordas);
}


void imprimir(cadastro *aluno){
if((arquivo = fopen(filename,"rb")) == NULL){
fprintf(stderr,"\nErro de abertura do arquivo: %s\n",filename);
exit(-1);
}
printf("\nNome\t\tIdade\t\tMatricula ");
while (fread(aluno, sizeof (struct cadastro), 1, arquivo)>0){
printf("\n%s\t\t%d\t\t%d",aluno->nome,\
aluno->idade, aluno->matricula);
}
fclose(arquivo);
putchar('\n');
}



void preencher(cadastro *aluno){
if((arquivo = fopen(filename,"ab")) == NULL){
fprintf(stderr,"\nErro de abertura do arquivo: %s\n",filename);
exit(-1);
}

printf("Digite o Nome do Aluno: ");
scanf("%s30[^\n]",aluno->nome);
removeNewLine();
printf("Digite a Idade do Aluno: ");
scanf("%d",&aluno->idade);
printf("Digite a Matricula do Aluno: ");
scanf("%d",&aluno->matricula);
fwrite(aluno,sizeof(struct cadastro),1,arquivo);
fflush(arquivo);
fclose(arquivo);
}



11. Re: Problemas com realloc

Netinho
netinhocqc

(usa Outra)

Enviado em 26/02/2012 - 16:48h

Desculpe-me cara minha ignorância, mais poderiam me explicar duas função: o que a função removenewline faz, e porque vc esta fazendo o scanf para ler string e usando %s30[^\n] pois não conheço essa forma. Desde já agradeço sua resposta.


12. Re: Problemas com realloc

euteste da silva
foxbit3r

(usa Solaris)

Enviado em 03/03/2012 - 10:28h

O remoNewLine é para remover o caracter '\n' que acaba dando problemas quando vc cria um programa que a entrada é um inteiro mais um string.

Faz um teste depois criando um programa que leia um inteiro e um string sem fazer remoção do caracter new line que você vai ver o seu programa pular a leitura do string que é conhecido pela maioria por "sujeira no buffer" aonde é erroneamente usado o flush(stdin) para contornar o problema.

o scanf que eu coloquei foi para fazer leitura de string ao invés de usar o fgets.








Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts