Manipualção de arquivos em C [RESOLVIDO]

1. Manipualção de arquivos em C [RESOLVIDO]

Marcos
marcos@marcos

(usa Ubuntu)

Enviado em 08/09/2012 - 18:04h

Pessoal estou com uns problemas no meu código que não estou conseguindo entender...

1-o arquivo é criado ou aberto no modo "a+b" por uma função que é responsável pela gravação neste arquivo. Pelo que entendi esse modo de abertura faz com que seja adicionado ao final do arquivo o novo registro. Aí é que começam meus problemas... quando adiciono novos registros parece que são inseridos vários registros vazios e após é que acontece a gravação dos novos registros... só que por causa destes registros vazios (vou dizer assim) quanto tento consultar até o final do arquivo não consigo encontrar esses registros.

Poderiam me dar algumas dicas de como resolver isso?

/*aqui o arquivo é criado ou aberto,recebendo os parametros da função que a chamou*/
if((arqNotas=fopen(caminho,"a+b"))==NULL){
printf("\nErro ao tentar abrir o arquivo %s",caminho);
system("pause");
exit(1);
}


/*aqui faço a captura das informações*/
printf("\nEstrutura de Dados I\n");
printf("\nDigite o nome do aluno ou 'ENTER' para encerrar: ");
fflush(stdin);//limpa buffer do teclado
gets(aluno.nome);
while(strlen(aluno.nome)!=0){
printf("\nDigite o numero da matricula: ");
scanf("%d",&aluno.matricula);
for(int i=0;i<3;i++){
printf("\tInforme a nota da prova %d: ",i+1);
scanf("%f",&aluno.notProvaEstrutura[i]);
}
puts(" ");
for(int i=0;i<8;i++){
printf("\tInforme a nota do trabalho %d: ",i+1);
scanf("%f",&aluno.notTrabEstrutura[i]);
}
aluno.disciplina=1;//significa que está matriculado em estrutura de dados
aluno.excluido=0;//está ativo para consulta
system("cls");

if(fwrite(&aluno,sizeof(cadastro),1,arqNotas)!=1){
printf("\nErro ao tentar gravar dados no arquivo!\n");
system("pause");
}

fflush(stdin);
printf("\nDigite o nome do aluno ou 'ENTER' para encerrar: ");
gets(aluno.nome);
}
fecharArquivo(arqNotas);//fecho o arquivo


/*aqui minha função de pesquisa*/

if((arqNotas=fopen(caminho,"rb"))==NULL){
printf("\nErro ao tentar abrir o arquivo %s",caminho);
system("pause");
exit(1);
}

printf("\n\nEntre com o nome do aluno ou pressione 'Enter' para sair: ");
fflush(stdin);
gets(nome);

while(strlen(nome)!=0){
voltarComeco(arqNotas);/*antes de cada leitura o cursor é posicionado no início do arquivo*/
while(!feof(arqNotas)){
while(fread(&aluno,sizeof(cadastro),1,arqNotas)==1){
if(strcmpi(aluno.nome,nome)==0){
if(aluno.excluido==0){
printf("\nNome: %s",aluno.nome);
printf("\nMatricula: %d",aluno.matricula);

if(aluno.disciplina==1){
printf("\nCursa Disciplina de: Estrutura de Dados I\n");
for(int i=0;i<3;i++){
printf("\n\tNota prova %d: %.2f",i+1,aluno.notProvaEstrutura[i]);
}
for(int i=0;i<8;i++){
printf("\n\tNota trabalho %d: %.2f",i+1,aluno.notTrabEstrutura[i]);
}
}
else if(aluno.disciplina==2){
printf("\nCursa Disciplina de: Banco de Dados I\n");
for(int i=0;i<3;i++){
printf("\n\tNota prova %d: %.2f",i+1,aluno.notProvaBD[i]);
}
printf("\n\tNota Trabalho Pratico: %.2f",aluno.notTrabPraticoBD);
printf("\n\tNota Seminario: %.2f",aluno.notSeminarioBD);
printf("\n\tNota da Lista de Exercicios: %.2f\n\n",aluno.notListaExercBD);
}
else{
printf("\nCursa Disciplina(s) de: Estrutura de Dados I e Banco de Dados I\n");
printf("\nEstrutura de Dados\n");
for(int i=0;i<3;i++)
printf("\n\tNota prova %d: %.2f",i+1,aluno.notProvaEstrutura[i]);
for(int i=0;i<8;i++)
printf("\n\tNota trabalho %d: %.2f",i+1,aluno.notTrabEstrutura[i]);
for(int i=0;i<3;i++)
printf("\n\tNota prova %d: %.2f",i+1,aluno.notProvaBD[i]);
puts(" ");
printf("\nBanco de Dados\n");
for(int i=0;i<3;i++)
printf("\n\tNota prova %d: %.2f",i+1,aluno.notProvaBD[i]);
printf("\n\tNota Trabalho Pratico: %.2f",aluno.notTrabPraticoBD);
puts(" ");
printf("\n\tNota Seminario: %.2f",aluno.notSeminarioBD);
puts(" ");
printf("\n\tNota da Lista de Exercicios: %.2f\n\n",aluno.notListaExercBD);
}
encontrou=true;
}
}
}



Enfim, está aí o código que estou fazendo, mas acontece o problema citado.

Se alguém puder dar uma dica agradeço desde já.





  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/09/2012 - 12:18h

Seu programa faz exatamente o que você manda que ele faça.

Leia o seu algoritmo. Perceba que, ao identificar o registro que você quer apagar, você guarda a posição posterior a esse, mas continua lendo todos os demais registros até o fim do arquivo, preenchendo, nessas leituras possivelmente redundantes, todos os demais campos da variável que você vai usar, logo em seguida, para sobrescrever o registro a ser removido. É natural, portanto, que o registro removido tenha todos esses outros campos indênticos ao do último registro do arquivo.

Cabe a você, agora, modificar o algoritmo para que isso não aconteça, mas que os valores de todos os campos, exceto o que marca a exclusão, não sejam modificados.

3. Re: Manipualção de arquivos em C [RESOLVIDO]

Reginaldo de Matias
saitam

(usa Slackware)

Enviado em 08/09/2012 - 18:12h

esta faltando a declaração da struct no início do código...

e depois alocar essa estrutura



4. Re: Manipualção de arquivos em C [RESOLVIDO]

Marcos
marcos@marcos

(usa Ubuntu)

Enviado em 08/09/2012 - 18:20h

Apesar de não ter aparecido nesse fragmento que colei, tenho a declaração da struct sim.

inicio da funçao

void notasEstrutura(FILE *&arqNotas,char caminho[]){
cadastro aluno;
if((arqNotas=fopen(caminho,"a+b"))==NULL){
printf("\nErro ao tentar abrir o arquivo %s",caminho);
system("pause");
exit(1);
}


no código abaixo está a função que fiz que vai permitir a alteração dos registros. Notem que manipulei o cursor, cheguei a pensar que talvez seja um problema nessa função que está causando isso. Mas já revi todo o código e não consegui encontrar erro.

void atualizaRegistro(FILE *&arqNotas,char caminho[]){
bool encontrou=false;
cadastro aluno;
char nome[100];
int opcao=0,posicao=0;

if((arqNotas=fopen(caminho,"r+b"))==NULL){
printf("\n\nErro ao tentar abrir o arquivo %s",caminho);
system("pause");
exit(1);
}

voltarComeco(arqNotas);
printf("\nDigite o nome do aluno ou 'ENTER' para encerrar: ");
fflush(stdin);
gets(nome);
while(strlen(nome)!=0){
voltarComeco(arqNotas);
while(fread(&aluno,sizeof(cadastro),1,arqNotas)==1){
if(strcmpi(aluno.nome,nome)==0){
posicao=ftell(arqNotas);
printf("\nAluno: %s",aluno.nome);
printf("\nMatricula: %d",aluno.matricula);
printf("\n\nDeseja alterar este registro: [1-SIM] [2-NAO] : ");
scanf("%d",&opcao);
if(opcao==1){
fseek(arqNotas,(posicao-sizeof(cadastro)),SEEK_SET);
printf("\nNome: ");
fflush(stdin);
gets(aluno.nome);
printf("\nMatricula: "); scanf("%d",&aluno.matricula);
if(fwrite(&aluno,sizeof(cadastro),1,arqNotas)!=1){
printf("\nNao foi possivel gravar os dados!\n");
system("pause");
exit(1);
}//fim do fwrite
else
printf("\n\nRegistro alterado com sucesso!!!\n");
}//fim if opcao =1
encontrou=true;
}//fim comparação registro com valor digitado
}//fim do while leitura
if(!encontrou)
printf("\n\n\nRegistro nao encontrado!\n");

encontrou=false;

fflush(stdin);
printf("\nDigite o nome do aluno ou 'ENTER' para encerrar: ");
gets(nome);
}//fim do while
fecharArquivo(arqNotas);

}



5. Re: Manipualção de arquivos em C [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 09/09/2012 - 00:58h

[/i]Cara, está muito difícil de ler seu código, pois coisas como [i] acabam sendo interpretadas pelo software que implementa o fórum como marcadores para texto em itálico. Por conta da pouca legibilidade, eu nem consegui ver se a sua definição ficou correta.

Para contornar esse problema, eu recomendo que você coloque o código entre as tags [code] e [/code], ou então que use um site especializado em postagem de código (tal como codepad.org ou pastebin.com).

Tirando isso, eu acho importante você saber que o modo "a" (com ou sem os sufixos "+", que permite também ler, e "b", para forçar modo binário em sistemas como o Windows, que implementam traduções ao manipular arquivos de texto -- coisa que não existe no Unix ou no Linux) na função fopen() faz com que todas as operações de escrita sejam feitas no final do arquivo, mesmo que você eventualmente tente apontar o ponteiro de escrita para outra posição. Se você não quiser ficar com registros antigos e/ou errados no arquivo, ou deverá removê-lo, ou terá de usar outro modo de abertura. Uma forma de certificar-se de que o arquivo será criado, caso não exista, sem perder os dados preexistentes se já existir, e sem ter todas as operações de escrita obrigatoriamente realizadas no final do arquivo, é fazer o seguinte.

const char my_file_name[]="teste.dat";
FILE *fp;

if(
(fp=fopen(my_file_name, "r+")) != NULL ||
(fp=fopen(my_file_name, "w+")) != NULL
){
/* Abriu com sucesso */
}
else {
/* Abertura falhou completamente. */
}


(EXPLICAÇÃO: Primeiro eu tento abrir com o modo "r+", que significa "abrir um arquivo já existente para leitura, permitindo também modificações"; se a operação for bem sucedida, a função vai retornar um ponteiro não-nulo e salvá-lo em fp, que, não sendo nulo, fará com o que vai no lado direito (que eu coloquei na linha de baixo) do operador lógico || não seja executado, pulando diretamente para o código executado se a abertura for bem sucedida. Se, porém, essa primeira operação não for bem-sucedida, fp será nulo, e é realizada uma segunda tentativa de abertura, usando "w+", que significa "criar um arquivo novo (apagando o conteúdo anterior, se ele já existir) para escrita, permitindo também leituras". Se essa operação for bem sucedida, fp será não-nulo, e o código de abertura bem sucedido será executado. Mas se essa segunda operação falhar (por exemplo, por causa de disco cheio, falta de permissão etc.), então o programa vai pular para o código do bloco else.)


6. Re: Manipualção de arquivos em C [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/09/2012 - 00:07h

Não encontrei erro algum que salte aos olhos, mas você deve saber que faltam pedaços relevantes do código. Por exemplo, seria interessante saber como está a declaração do seu registro do tipo cadastro.

Você poderia ser um pouco mais específico com relação ao comportamento do programa? Ele apresenta alguma das mensagens de erro que você mesmo colocou no código, dá alguma mensagem de outra natureza ou simplesmente falha? Em qual (ou quais) das operações? Você tem como, antes de executar o programa, fazer uma cópia do arquivo, e, depois de executá-lo, comparar os dois arquivos? Você já examinou o conteúdo do arquivo gerado após cada execução, para inferir se os dados ali dispostos estão pelo menos íntegros dentro do arquivo, mesmo que o programa se enrole na hora de os tratar?

Os problemas que eu vi no seu código são mais uma questão de estilo e de prática de programação. Por exemplo, coisas como fflush(stdin), system("pause") e system("cls") são gambiarras grosseiras, que não funcionam universalmente (para você ter uma ideia, não funcionam no Linux, que é o assunto principal deste site, e podem nem mesmo funcionar no Windows, principalmente o primeiro exemplo, se for utilizado um outro compilador diferente do seu compilador atual). Por mais que saiba -- e eu garanto que sei, pois durante muitos anos usei C sem ter firmes alguns conceitos que só aprendi meio tardiamente -- que as funções de entrada e saída do C (e particularmente scanf()) sejam complexas e pouco adequadas a entrada e saída feita diretamente num terminal ou no console, acredito que gambiarras devem ser evitadas ao máximo.

Por conta do que eu disse acima, seu programa daria erro durante a execução na minha máquina, já que fflush(stdin) corretamente, de acordo com o padrão, não faz coisa alguma de útil no Linux, e as duas chamadas a system() simplesmente não encontrariam os comandos que você lhes passou.

Outra gambiarra é gets(). Não use, pois ela é um risco de segurança, tendo sida marcada para morrer na revisão do padrão do C de 1999 e finalmente removida no padrão do C de 2011.

Por causa do que disse acima, seu programa daria erro de compilação com as opções que eu costumo usar normalmente para compilar com o GCC; eu teria de retroceder a versão da linguagem e relaxar opções de segurança e alertas sobre o código.


7. Re: Manipualção de arquivos em C [RESOLVIDO]

Marcos
marcos@marcos

(usa Ubuntu)

Enviado em 10/09/2012 - 18:08h

Obrigado pelas dicas! Vou colocá-las em prática. Só agora estou tendo contato com a linguagem C e não sabia (ainda) que algumas funções não funcionam no Linux. Este código trata-se de parte de um projeto da faculdade.

Mas voltando as suas indagações... não é apresentando erro algum quando compilo e executo. Todas as operações de inserção são processadas normalmente com sucesso (se é que posso dizer assim).

Nesse meio tempo observei outro detalhe, quando vou alterar determinado registro estou abrindo o arquivo no modo "r+b" essa alteração é feita sem nenhuma mensagem de erro, porém é como se estivesse sendo feita uma cópia daquele registro, ou seja, mantém o registro antigo e cria-se um novo com a alteração feita.

Tenho usado o seguite raciocínio: não posso perder as informações que estão no arquivo, logo sempre que se tratar de operações de inserção tenho que abrí-lo no modo "a+b". E quando se trata de alterações, abro no modo "r+b" e manipulo o cursor até o campo de determinado registro que preciso alterar.

A propósito, segue abaixo o código da estrutura que estou utilizando.


struct cadastro{
char nome[101];
int matricula;
float notProvaEstrutura[3];
float notTrabEstrutura[7];
float notProvaBD[3];
float notSeminarioBD;
float notTrabPraticoBD;
float notListaExercBD;
int excluido;//habilitará ou nao a exibição de determinado registro na hora da consulta [0 = ativo || 1 = inativo]
int disciplina;/*recebe os valores 1,2 ou 3 e representam: 1-estrutura dados || 2-banco de dados|| 3-ambas disciplinas*/
};



Obrigado pela atenção.


8. Re: Manipualção de arquivos em C [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/09/2012 - 00:39h

Agora saltou uma coisa estranha aos olhos: na declaração das funções, você colocou um argumento do tipo FILE *&. Se fosse C++, isso seria uma "referência de ponteiro para FILE". Só que referências não existem em C. E mesmo que você esteja usando C++ (ao contrário do que disse no título do tópico), por que está com esse tipo estranho, se você aparentemente faz todas as operações com o arquivo dentro da função?

O que faz a função fecharArquivo()? O nome parece óbvio, mas custa-me pensar que você criou um simples sinônimo para fclose(). Mas, no fundo, eu pergunto por causa do sintoma que você descreveu, de que mesmo com o arquivo sendo aberto com modo "r+b" e com um fseek() antes da escrita, os dados estão indo para o final, como se o modo tivesse sido "a+b". Algo me diz que você pode estar tentando reabrir o mesmo arquivo mais de uma vez, sem fechar devidamente aberturas anteriores, o que tem algumas restrições no Windows.

De todo modo, uma aplicação de cadastro típica abriria o arquivo apenas uma vez, no começo da execução (com "r+b" se o arquivo já existir ou com "w+b" se ele tiver de ser criado, como mostrei em mensagem anterior), fazendo operações de seek para o final do arquivo se quisesse adicionar registros novos sem sobrescrever os anteriores, e as demais consultas e alterações seriam feitas com seek para as posições devidas no arquivo.

Qual compilador você está usando? E quais opções de compilação e de diagnóstico de código?

Em tempo, a declaração da estrutura parece OK, mas você possivelmente fará melhor uso de memória se declarar o array de caracteres como último campo, por questões de alinhamento. Ou então você poderia manter onde está, mas tornar o tamanho do array um múltiplo do tamanho ocupado por um valor inteiro. (Mas é claro que se fizer alguma dessas alterações no formato constituinte da estrutura não poderá usar mais o arquivo gerado anteriormente).


9. Re: Manipualção de arquivos em C [RESOLVIDO]

Marcos
marcos@marcos

(usa Ubuntu)

Enviado em 15/09/2012 - 22:03h

Boa noite!
Suas dica têm sido de grande valor, desde já obrigado!
Consegui resolver boa parte dos problemas que vinham acontecendo.

Estou com uma nova situação, espero que você ou algum outro colega possa me dar algumas dicas de como resolver...veja só, na estrutura que utilizo criei um campo chamado "excluido" do tipo booleano que serve como uma marca de exclusão. No momento do cadastro esse campo recebe automaticamente o valor "false" e na rotina de consulta, defino que apenas os registros onde o campo excluido seja igual a false sejam mostrados.

Assim quando é necessário fazer uma exclusão, o usuário localiza o registro que deseja, confirma a exclusão e o sistema muda o campo excluido para "true", dessa forma quando aquele registro for pesquisado o sistema informa que não foi encontrado.

No momento em que o sistema encontra o registro, utilizo a função ftell para saber onde foi lido.
posicao=ftell(arqdados); 


Depois, sabendo que aquela posição lida representa exatamente o início registro subsequente ao lido, posiciono o cursor no devido registro:

fseek(arqdados,(posicao-sizeof(cadastro),SEEK_SET);


onde:
posicao= é a posição onde o cursor estava quando encontrou o registro

Se estou certo, com isso posiciono o cursor exatamente no registro desejado. Então faço:
aluno.excluido=true; 


Na sequencia faço o fwrite para gravar as alterações.
E é exatamente agora que surgiu um problema... o campo excluido realmente está recebendo o valor "true", mas os outros membros da estrutura recebem todos os valores do último registro gravado.

Não estou conseguindo resolver este problema.

Agradeço pelas dicas desde já.


10. Re: Manipualção de arquivos em C [RESOLVIDO]

Marcos
marcos@marcos

(usa Ubuntu)

Enviado em 16/09/2012 - 08:51h

Consigo avaliar o que acabei de escrever, pois fiz uma rotina de consulta que deve exibir todos os registros do arquivo, não usei nenhum tipo filtro.

Vou tentar exemplificar melhor o que falei:

conteúdo antes da exclusão:

aluno: jose
matricula: 1
excluido: false;
------------------
aluno: marcio
matricula: 2
excluido: false;
------------------
aluno: joao
matricula: 3
excluido: false;
-----------------------------

conteúdo após exclusão:

aluno: joao
matricula: 3
excluido: true;
------------------
aluno: marcio
matricula: 2
excluido: false;
------------------
aluno: joao
matricula: 3
excluido: false;


A princípio poderia pensar que não causará problema, uma vez que a consulta é feita com base numa marca de exclusão. Agora e quando for necessário listar todos aqueles que foram excluídos? Jamais serão encontrados já que estão sendo sobrescritos.

Rotina de exclusão:

void excluirRegistro(FILE *&arqdados,char caminho[]){
cadastro aluno;
int modo=0,opcao, posicao,matricula;
char nome[101];

rewind(arqdados);//posicona cursor no inicio do arquivo
printf("\nDigite o nome do aluno: ");
setbuf(stdin,NULL);
gets(nome);
while(fread(&aluno,sizeof(cadastro),1,arqdados)==1){
if(strcmpi(aluno.nome,nome)==0){
posicao=ftell(arqdados);
if(aluno.excluido==false){
printf("\nAluno: %s",aluno.nome);
printf("\nMatricula: %d",aluno.matricula);
if(aluno.disciplina==1)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I");
else if(aluno.disciplina==2)
printf("\n\tCursa Disciplina(s): Banco de Dados I");
else if(aluno.disciplina==3)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I e Banco de Dados I");
puts(" ");
}
}
}
fseek(arqdados,(posicao-sizeof(cadastro)),SEEK_SET);
aluno.excluido=true;
if(fwrite(&aluno,sizeof(cadastro),1,arqdados)!=1){
printf("\nErro ao gravar dados");
system("pause");
exit(1);
}
else
printf("\n\nRegistro excluido com sucesso!!!\n");

}


Rotina de consulta considerando todos os registros

void listaGeral(FILE *&arqdados,char caminho[]){
cadastro aluno;
printf("\n\n\nRelacao de alunos matriculados: \n");
fseek(arqdados,0,SEEK_SET);
while(fread(&aluno,sizeof(cadastro),1,arqdados)==1){
printf("\n\tAluno: %s",aluno.nome);
printf("\n\tMatricula: %d",aluno.matricula);
if(aluno.disciplina==1)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I");
else if(aluno.disciplina==2)
printf("\n\tCursa Disciplina(s): Banco de Dados I");
else if(aluno.disciplina==3)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I e Banco de Dados I");
puts(" ");
}
puts(" ");
}


Rotina de consulta considerando apenas os ativos

void listaGeral(FILE *&arqdados,char caminho[]){
cadastro aluno;
printf("\n\n\nRelacao de alunos matriculados: \n");
fseek(arqdados,0,SEEK_SET);
while(fread(&aluno,sizeof(cadastro),1,arqdados)==1){
if(aluno.excluido==false){//filtra pela marca de exclusão
printf("\n\tAluno: %s",aluno.nome);
printf("\n\tMatricula: %d",aluno.matricula);
if(aluno.disciplina==1)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I");
else if(aluno.disciplina==2)
printf("\n\tCursa Disciplina(s): Banco de Dados I");
else if(aluno.disciplina==3)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I e Banco de Dados I");
puts(" ");
}
}
puts(" ");
}






11. Re: Manipualção de arquivos em C [RESOLVIDO]

Marcos
marcos@marcos

(usa Ubuntu)

Enviado em 16/09/2012 - 20:26h

Caro Paulo, muito obrigado pelas dicas!

Principalmente em relação a sua última dica ("leia seu algoritmo"), impressionante como não havia percebido...

Na minha percepção (de aspirante a programador) encontrei como saída, imagino que logicamente não seria a saída que programadores profissionais utilizariam, fazer um break assim que o registro concidir com a chave da busca, antes de efetuá-lo de fato confirmo a exclusão, caso a resposta do usuário seja sim, habilito uma espécie de flag e após o break, testo o valor desta flag.

Segue o código:

void excluirRegistro(FILE *&arqdados,char caminho[]){
cadastro aluno,aluno1;
int modo=0,opcao, posicao,matricula;
char nome[101];

rewind(arqdados);//posicona cursor no inicio do arquivo
printf("\nDigite o nome do aluno: ");
setbuf(stdin,NULL);
gets(nome);
while(fread(&aluno,sizeof(cadastro),1,arqdados)==1){
if(strcmpi(aluno.nome,nome)==0){
posicao=ftell(arqdados);
if(aluno.excluido==false){
printf("\nAluno: %s",aluno.nome);
printf("\nMatricula: %d",aluno.matricula);
if(aluno.disciplina==1)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I");
else if(aluno.disciplina==2)
printf("\n\tCursa Disciplina(s): Banco de Dados I");
else if(aluno.disciplina==3)
printf("\n\tCursa Disciplina(s): Estrutura de Dados I e Banco de Dados I");
puts(" ");
printf("\nConfirma exclusao? [1-sim 2-nao] >>> ");
scanf("%d",&opcao);
break;
}
}
}
if(opcao==1){
fseek(arqdados,(posicao-sizeof(cadastro)),SEEK_SET);
aluno.excluido=true;

if(fwrite(&aluno,sizeof(cadastro),1,arqdados)!=1){
printf("\nErro ao gravar dados");
system("pause");
exit(1);
}
else
printf("\n\nRegistro excluido com sucesso!!!\n");
}
}



12. Re: Manipualção de arquivos em C [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/09/2012 - 22:13h

Ainda tem um erro. Digamos que você percorra todos os registros sem encontrar o nome desejado. Você vai sair do loop, e está na linha que testa o valor da variável opcao. Que valor você acha que ela terá?

Eu recomendo sempre ligar o máximo de opções de diagnóstico de código oferecidas pelo compilador. Como eu uso GCC, trabalho quase sempre com pelo menos "-Wall -Werror -O2" (que significa "ligue todas as mensagens de aviso, considere avisos como erros, e faça otimização de código "nível 2" (que, entre outras coisas, faz com que o compilador faça uma análise mais profunda dos possíveis fluxos de execução do código, levando loops e ifs em consideração). Essas opções fariam com que fosse exibida uma mensagem dizendo que a variável opcao pode ter sido usada sem ter sido inicializada anteriormente pela função.

Mais interessante ainda, no caso de um arquivo vazio e na azarada hipótese de opcao receber aleatoriamente o valor 1, você vai entrar por um fluxo de execução que usará um valor indeterminado de posicao numa chamada a fseek(), e vai escrever nesse local indeterminado uma estrutura de cadastro com todos os campos indefinidos.

Corrija isso, meu caro!

Se quiser ir um pouco além (já pelo lado de estilo e eficiência), você poderia ter algum benefício se guardasse o valor de posicao antes de ler o registro candidato a apagamento. Dessa forma, você não teria de fazer uma subtração na hora de chamar fseek() para efetivar a exclusão.

Qual a finalidade do parâmetro caminho? E por que você continua declarando arqdados como referência de ponteiro para FILE? Eu sugiro que você use apenas ponteiro para FILE (i.e.: mude de FILE *& para FILE *).



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts