#include <stdio.h>
#include <stdlib.h>
#include "leituras.h"
/* Macros relacionadas com as categorias admissiveis: */
#define CATEG_MIN 0
#define CATEG_MAX 2
/* Macro que define um valor possivel para marcar posicoes vazias: */
#define VAZIO -1
/* Numero maximo de caracteres num nome: */
#define NOME_MAX 40
/* Definicao da estrutura que guarda informacao acerca de um utente: */
typedef struct Utente
{
char nome[NOME_MAX+1];
int categoria;
int codigo;
} Utente;
/* Definicao de um tipo para assinalar o resultado das funcoes: */
typedef enum {mau, bom} resultado;
/* Registo vazio tipo: */
const Utente vazio = {"", 0, VAZIO};
resultado insereUtente(FILE *f)
{
long pos, posvazia;
Utente utente, novo;
/* Le dados do novo utente do teclado, sem verificacao de repeticoes: */
LEnome("Nome: ", novo.nome, NOME_MAX);
novo.categoria = LEvalor("Categoria: [%d a %d] ", CATEG_MIN, CATEG_MAX);
novo.codigo = LEvalor("Codigo: [>=%d] ", 0, 0);
rewind(f);
/* Procura posicao vazia e verifica repeticoes: */
posvazia = -1;
while(pos = ftell(f), fread(&utente, sizeof(Utente), 1, f) == 1)
if(utente.codigo == VAZIO)
posvazia = pos;
else
if(utente.codigo == novo.codigo)
{
printf("O codigo %d ja' existe!\n", novo.codigo);
return mau;
}
else if(strcmp(utente.nome, novo.nome) == 0)
{
printf("O nome \"%s\" ja' existe!\n", novo.nome);
return mau;
}
/* Se houver alguma posicao livre coloca posicao escrita: */
if(posvazia != -1)
fseek(f, posvazia, SEEK_SET);
/* Escreve o novo utente: */
if(fwrite(&novo, sizeof(Utente), 1, f) != 1)
{
fputs("Erro: guardando novo utente!\n", stderr);
exit(EXIT_FAILURE);
}
return bom;
}
int removeUtente(FILE *f)
{
char nome[NOME_MAX+1];
Utente utente;
long pos;
/* Pede nome do utente a remover: */
LEnome("Nome a remover: ", nome, NOME_MAX);
rewind(f);
/* Procura o utente: */
while(pos = ftell(f), fread(&utente, sizeof(Utente), 1, f) == 1)
if(utente.codigo != VAZIO && strcmp(utente.nome, nome) == 0)
break;
if(feof(f))
{
fprintf(stderr, "Erro: utente \"%s\" nao exite!\n", nome);
return mau;
}
fseek(f, pos, SEEK_SET);
/* Sobrepoe utente "vazio": */
if(fwrite(&vazio, sizeof(Utente), 1, f) != 1)
{
fputs("Erro: escrevendo vazio!\n", stderr);
exit(EXIT_FAILURE);
}
return bom;
}
void listaUtentes(FILE *f)
{
Utente utente;
rewind(f);
/* Procura o utente: */
while(fread(&utente, sizeof(Utente), 1, f) == 1)
if(utente.codigo != VAZIO)
printf("Nome: %s\nCategoria: %d\nCodigo: %d\n\n",
utente.nome, utente.categoria, utente.codigo);
}
resultado leUtentes(FILE *f)
{
FILE *entrada;
char nome[FILENAME_MAX+1];
Utente utente;
long pos;
/* Pede nome do ficheiro a ler: */
LEcadeia("De que ficheiro pretende ler? ", nome, FILENAME_MAX);
/* Abre ficheiro: */
if((entrada = fopen(nome, "r")) == NULL)
{
fprintf(stderr, "Erro: abrindo ficheiro \"%s\"!\n", nome);
return mau;
}
rewind(f);
/* Le tudo o que for possivel e escreve no ficheiro de registos: */
while(fgets(utente.nome, NOME_MAX+1, entrada) != NULL &&
fscanf(entrada, "%d %d ", &utente.categoria, &utente.codigo) == 2)
{
if(utente.nome[strlen(utente.nome)-1] == '\n')
utente.nome[strlen(utente.nome)-1] = '\0';
fwrite(&utente, sizeof(Utente), 1, f);
}
/* Fecha ficheiro de entrada: */
fclose(entrada);
/* Limpa todas as posicoes que faltam no ficheiro de registos: */
while(pos = ftell(f), fread(&utente, sizeof(Utente), 1, f) == 1)
if(utente.codigo != VAZIO)
{
fseek(f, pos, SEEK_SET);
fwrite(&vazio, sizeof(Utente), 1, f);
}
if(ferror(f))
{
fputs("Erro: escrevendo no ficheiro de registos!\n", stderr);
exit(EXIT_FAILURE);
}
return bom;
}
resultado guardaUtentes(FILE *f)
{
FILE *saida;
char nome[FILENAME_MAX+1];
Utente utente;
/* Pede nome do ficheiro onde guardar: */
LEcadeia("Em que ficheiro pretende guardar? ", nome, FILENAME_MAX);
/* Abre ficheiro: */
if((saida = fopen(nome, "w")) == NULL)
{
fprintf(stderr, "Erro: criando ficheiro \"%s\"!\n", nome);
return mau;
}
rewind(f);
/* Escreve utentes: */
while(fread(&utente, sizeof(Utente), 1, f) == 1)
if(utente.codigo != VAZIO)
fprintf(saida, "%s\n%d\n%d\n",
utente.nome, utente.categoria, utente.codigo);
if(ferror(saida))
{
fprintf(stderr, "Erro: escrevendo no ficheiro de texto!\n");
fclose(saida);
return mau;
}
fclose(saida);
return bom;
}
int main(int argc, const char * const *argv)
{
FILE *f; /* ficheiro de registos. */
int opcao;
const char *nome;
nome = argc == 1? "utentes.db" : argv[1];
/* Tenta abrir ficheiro de registos ja' existente, se nao existir tenta
criar um novo: */
if((f = fopen(nome, "r+b")) == 0 && (f = fopen(nome, "w+b")) == 0)
{
fprintf(stderr, "Erro: nao consegui abrir nem criar \"%s\"!",nome);
return EXIT_FAILURE;
}
do
{
/* Perguntar opcao ao utilizador: */
printf("\n1 - Inserir novo utente\n2 - Remover utente\n"
"3 - Listar utentes\n4 - Ler de ficheiro\n"
"5 - Guardar em ficheiro\n0 - Sair\n\n");
switch(opcao = LEvalor("Opcao: [%d a %d] ", 0, 5))
{
case 1:
insereUtente(f);
break;
case 2:
removeUtente(f);
break;
case 3:
listaUtentes(f);
break;
case 4:
leUtentes(f);
break;
case 5:
guardaUtentes(f);
break;
case 0:
break;
default:
/* Aqui nunca se pode chegar! */
break;
}
}
while(opcao != 0);
fclose(f);
return EXIT_SUCCESS;
}