paulo1205
(usa Ubuntu)
Enviado em 17/09/2012 - 16:29h
marcos@marcos escreveu:
Em relação a variável opcao, posso minimizar o problema citado por você inicializando-a com valor zero, e dentro do if que faz a chamada ao fseek, após a chamada, eu a carrego novamente com valor zero.
Esse modo de agir poderia ser considerado como uma medida paliativa nesse caso?
Sim, seria
somente um paliativo, pois não seria consertar um fluxo indevido, mas somente contornar um erro de execução. E você teria de definir valores válidos também para as outras variáveis que eu mencionei, mesmo que não as utilize de modo algum (e isso tem um custo, tanto em tamanho de código como em tempo de execução).
A solução filosoficamente correta é repensar o algoritmo de modo a evitar esses paliativos.
No seu caso, você pode caminhar para essa solução correta sem fazer mudanças muito profundas. A forma mais lógica de começar é olhando o que está dentro do loop, no momento em que você localiza o registro candidato a alteração. É ali que você pede a confirmação sobre a alteração. Por que, então, não o altera imediatamente nesse mesmo ponto, e então encerra o loop, em lugar de encerrar o loop e fazer a alteração fora dele?
Vou lhe dar uma ideia superficial de como eu faria, sem dialogar com o usuário e usando um código de retorno e a variável global
errno (de <errno.h> ou <cerrno>) para indicar a causa de eventuais falhas (e com um perceptível sotaque de UNIX). Veja até que, se você desprezar os comentários e linhas em branco, o código fica bem curto, e mesmo assim pega todos os possíveis casos de erro e os reporta para quem tiver chamado a função.
int mark_as_deleted(FILE *data_file, const char *unique_id) {
off_t found_rec_offset;
record_t rec;
if(data_file==NULL){
errno=EBADF; /* Código de erro de arquivo inválido. */
return 0;
}
rewind(data_file);
found_rec_offset=0;
while(fread(data_file, sizeof rec, 1, &rec)==1){
if(strcmp(rec.unique_id, unique_id)==0 && !rec.deleted){
/* Só exclui registro se bate com unique_id e se não estiver já marcado como *
* excluído (considere o caso de a chave ter sido removida um dia, e depois *
* reinserida noutra posição!). */
rec.deleted=1; /* Altera apenas o campo que marca a exclusão. */
/* Como o registro a ser removido foi encontrado, o loop será interrompido *
* pelo retorno da função. Observe que o valor retornado só será verdadeiro *
* se as duas operações forem bem sucedidas; se qualquer uma delas falhar, o *
* programa usará o valor de errno definido internamente pela que falhar. */
return
fseeko(data_file, found_rec_offset, SEEK_SET)==0 &&
fwrite(data_file, sizeof rec, 1, &rec)==1
;
}
found_rec_offset+=sizeof rec; /* Não preciso de ftell(). ;) */
}
/* Só chega neste ponto se tiver ocorrido erro ou fim de arquivo (EOF). */
if(feof(data_file)){
/* Atingiu EOF sem achar o registro correspondente a unique_id. */
clearerr(data_file); /* Remove flag de EOF, para que futuras operações no arquivo não falhem. */
errno=ENOENT; /* Código de erro de entrada não existente. */
}
/* Note que se tiver sido erro, e não EOF, o valor de errno permanece intocado. */
return 0; /* Devolve falso para indicar que não removeu coisa alguma. */
}