paulo1205
(usa Ubuntu)
Enviado em 07/02/2013 - 19:58h
Em tempo -- e eu não sei como não vi isso antes, sem ter de compilar o programa aqui e ter o mesmo erro -- a causa do problema é que o arquivo não é aberto, logo o ponteiro
arq é nulo, e a chamada a
fwrite() causa falha de segmentação quando a função tenta acesso ao conteúdo do ponteiro nulo.
Na verdade, há mais problemas na função cadastro. Para começar, tudo indica que
arq deveria ser uma variável local, e não um argumento da função.
A forma de abrir o arquivo para leitura com atualização (
"r+b") só funciona se o arquivo já existir, não o criando caso não exista. Usar
"w+b", por outro lado, faria com que qualquer conteúdo de um arquivo preexistente fosse perdido. Contudo, é possível tentar abrir para atualização primeiro, e depois tentar criar o arquivo, se a primeira tetativa falhar, mais ou menos como mostrado abaixo.
if(
(arq=fopen("arquivo", "r+b"))==NULL ||
(arq=fopen("arquivo", "w+b"))==NULL
){
fprintf(stderr, "Nao foi possivel abrir o arquivo: %s\n", strerror(errno));
}
Aliás, você deveria se acostumar a sempre testar o valor devolvido não só por
fopen(), mas também por todas as outras funções de entrada e saída.
Outro problema é o uso de
fflush(stdin). Embora muita implementações façam o descarte dos dados no buffer de entrada, isso não é uma regra geral (pois o padrão determina o comportamento de
fflush() apenas para
streams de saída de dados, não para aqueles de entrada de dados, como
stdin), e mesmo em sistemas em que tal comportamento é determinado, dependendo de como os caracteres da entrada forem dispostos, pode ou não haver caracteres remanescentes depois do ponto em que se cria que o buffer estaria "limpo".
Ainda outro problema é o uso de
gets(). Essa função tem um problema inato de projeto que a faz insegura para uso geral (a saber: ela não limita o tamanho da entrada fornecida pelo usuário; então, no seu caso, se alguém digitar mais do que 34 caracteres para o nome ou mais 9 caracteres para o telefone, a função vai gravar além do espaço reservado para receber a entrada). Tão ruim era a função que o padrão do C de 1999 a tornou obsoleta, e o de 2011 finalmente a removeu da biblioteca padrão. Em seu lugar, você pode usar
fgets().
A forma como você fez o
loop é sub-ótima, pois tem uma chamada a
gets() a mais do que seria necessário. Você poderia fazer algo como vai abaixo.
while(1){
/* le nome (mas sem usar gets(), por favor! ;) ) */
if(strlen(nome)==0)
break; /* sai do loop */
/* resto do loop */
}