#include <stdio.h>
#include <stdlib.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
/* Macros relacionadas com o numero maximo de caracteres num nome e com o
tamanho das matrizes de char necessarias para os guardar: */
#define NOME_MAX 40
#define NOMEMAT_MAX (NOME_MAX + 1)
/* Macro que define o numero maximo de utentes: */
#define UTENTES_MAX 50
/* Definicao da estrutura que guarda informacao acerca de um utente: */
typedef struct Utente
{
char nome[NOMEMAT_MAX];
int categoria;
int codigo;
} Utente;
/* Elimina tudo ate' ao proximo fim-de-linha (como a chamada fflush(stdin),
so' que esta ultima nao corresponde `a norma ANSI-C, nao funcionando, por
isso senao em DOS e com alguns compiladores): */
void mataLinha(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF)
/* Nada. */;
}
/* Insere mais um utente na matriz, devolve verdadeiro se a matriz sofreu
alteracoes: */
int insereUtente(Utente utentes[])
{
int i;
/* Procura posicao vazia: */
for(i = 0; i < UTENTES_MAX; i++)
if(utentes[i].codigo < 0)
break;
/* Se nao ha' qualquer posicao livre sair: */
if(i == UTENTES_MAX)
{
fprintf(stderr, "Erro: base de dados cheia!\n");
return 0;
}
/* Introducao dos dados do utente, sem verificacao de repeticoes: */
do
{
printf("Nome: ");
if(fgets(utentes[i].nome, NOMEMAT_MAX, stdin) == NULL)
{
fprintf(stderr, "Erro: lendo nome!\n");
exit(EXIT_FAILURE);
}
if(utentes[i].nome[strlen(utentes[i].nome)-1] == '\n')
utentes[i].nome[strlen(utentes[i].nome)-1] = '\0';
else
mataLinha(); /* para eliminar resto da linha. */
}
while(utentes[i].nome[0] == '\0');
do
{
printf("Categoria: ");
if(scanf("%d", &utentes[i].categoria) != 1)
{
fprintf(stderr, "Erro: lendo categoria!\n");
exit(EXIT_FAILURE);
}
}
while(utentes[i].categoria < CATEG_MIN || utentes[i].categoria >
CATEG_MAX);
mataLinha();
do
{
printf("Codigo: ");
if(scanf("%d", &utentes[i].codigo) != 1)
{
fprintf(stderr, "Erro: lendo codigo!\n");
exit(EXIT_FAILURE);
}
}
while(utentes[i].codigo < 0);
mataLinha();
return 1;
}
/* Remove um utente da matriz, devolve verdadeiro se a matriz sofreu
alteracoes: */
int removeUtente(Utente utentes[])
{
int i;
char nome[NOMEMAT_MAX];
/* Pede nome do utente a remover: */
printf("Nome a remover: ");
if(fgets(nome, NOMEMAT_MAX, stdin) == NULL)
{
fprintf(stderr, "Erro: lendo nome!\n");
exit(EXIT_FAILURE);
}
if(nome[strlen(nome)-1] == '\n')
nome[strlen(nome)-1] = '\0';
/* Procura utente: */
for(i = 0; i < UTENTES_MAX; i++)
if(strcmp(utentes[i].nome, nome) == 0)
break;
if(i == UTENTES_MAX)
{
fprintf(stderr, "Erro: nao encontrei \"%s\"!\n", nome);
return 0;
}
/* Elimina utente: */
utentes[i].codigo = VAZIO;
return 1;
}
/* Mostra a lista dos utentes: */
void listaUtentes(Utente utentes[])
{
int i;
for(i = 0; i < UTENTES_MAX; i++)
if(utentes[i].codigo >= 0)
{
printf("Nome: %s\n", utentes[i].nome);
printf("Categoria: %d\n", utentes[i].categoria);
printf("Codigo: %d\n\n", utentes[i].codigo);
}
}
/* Le os utentes dum ficheiro, apagando todos os utentes anteriormente
guardados na matriz, devolve verdadeiro se conseguiu ler: */
int leUtentes(Utente utentes[])
{
int i;
FILE *entrada;
char nome[FILENAME_MAX+1];
/* Pede nome do ficheiro a ler: */
printf("De que ficheiro pretende ler? ");
if(fgets(nome, FILENAME_MAX+1, stdin) == NULL)
{
fprintf(stderr, "Erro: lendo nome do ficheiro!\n");
exit(EXIT_FAILURE);
}
if(nome[strlen(nome)-1] == '\n')
nome[strlen(nome)-1] = '\0';
/* Abre ficheiro: */
if((entrada = fopen(nome, "r")) == NULL)
{
fprintf(stderr, "Erro: abrindo ficheiro!\n");
return 0;
}
/* Le tudo o que for possivel: */
for(i = 0; i < UTENTES_MAX; i++)
{
/* Repare-se no formato "%d ", no ultimo fscanf, que diz `a funcao
para eliminar todos os espacos brancos, incluindo fins-de-linha,
depois de ler o codigo: */
if(fgets(utentes[i].nome, NOMEMAT_MAX, entrada) == NULL ||
fscanf(entrada, "%d", &utentes[i].categoria) != 1 ||
fscanf(entrada, "%d ", &utentes[i].codigo) != 1)
break;
if(utentes[i].nome[strlen(utentes[i].nome)-1] == '\n')
utentes[i].nome[strlen(utentes[i].nome)-1] = '\0';
}
/* Limpa todas as posicoes que nao se conseguiu ler: */
for(; i < UTENTES_MAX; i++)
utentes[i].codigo = VAZIO;
/* Fecha ficheiro: */
fclose(entrada);
return 1;
}
/* Guarda lista de utentes num ficheiro (a informacao que existia no
ficheiro e' descartada), devolve verdadeiro se consegui guardar: */
int guardaUtentes(Utente utentes[])
{
int i;
FILE *saida;
char nome[FILENAME_MAX+1];
/* Pede nome do ficheiro onde guardar: */
printf("Em que ficheiro pretende guardar? ");
if(fgets(nome, FILENAME_MAX+1, stdin) == NULL)
{
fprintf(stderr, "Erro: lendo nome do ficheiro!\n");
exit(EXIT_FAILURE);
}
if(nome[strlen(nome)-1] == '\n')
nome[strlen(nome)-1] = '\0';
/* Abre ficheiro: */
if((saida = fopen(nome, "w")) == NULL)
{
fprintf(stderr, "Erro: abrindo ficheiro!\n");
return 0;
}
/* Escreve utentes: */
for(i = 0; i < UTENTES_MAX; i++)
/* So' se escrevem as posicoes preenchidas! */
if(utentes[i].codigo >= 0)
{
fprintf(saida, "%s\n", utentes[i].nome);
fprintf(saida, "%d\n", utentes[i].categoria);
fprintf(saida, "%d\n", utentes[i].codigo);
}
/* Verifica se houve erros de escrita e fecha ficheiro: */
if(ferror(saida))
{
fprintf(stderr, "Erro: escrevendo no ficheiro!\n");
fclose(saida);
return 0;
}
fclose(saida);
return 1;
}
/* Limpa matriz de utentes: */
void limpaUtentes(Utente utentes[])
{
int i;
for(i = 0; i < UTENTES_MAX; i++)
utentes[i].codigo = VAZIO;
}
/* Funcao de leitura de opcoes: */
int leOpcao(int min, int max)
{
int n, res;
do
if((res = scanf("%d", &n)) == EOF)
{
fprintf(stderr, "Erro: lendo opcao!\n");
exit(EXIT_FAILURE);
}
while(res != 1 || n < min || n > max);
mataLinha();
return n;
}
/* Programa principal: */
int main(void)
{
Utente utentes[UTENTES_MAX];
int opcao, alterado = 0;
/* Limpar a matriz de utentes: */
limpaUtentes(utentes);
/* No inicio perguntar se quer ler a base de dados de um ficheiro: */
printf("Deseja abrir um ficheiro? [1 - sim, 0 - nao] ");
if(leOpcao(0, 1) == 1)
leUtentes(utentes);
do
{
/* Perguntar opcao ao utilizador: */
printf("1 - Inserir novo utente\n2 - Remover utente\n"
"3 - Listar utentes\n4 - Ler de ficheiro\n"
"5 - Guardar em ficheiro\n0 - Sair\nOpcao: ");
switch(opcao = leOpcao(0, 5))
{
case 1:
if(insereUtente(utentes))
alterado = 1;
break;
case 2:
if(removeUtente(utentes))
alterado = 1;
break;
case 3:
listaUtentes(utentes);
break;
case 4:
if(alterado)
{
printf("Deseja guardar antes de ler? [1 - sim, 0 - nao] ");
if(leOpcao(0, 1) == 1)
{
if(guardaUtentes(utentes))
alterado = 0;
}
else
alterado = 0;
}
if(!alterado) /* so' se le se se conseguiu guardar! */
if(leUtentes(utentes))
alterado = 0;
break;
case 5:
if(guardaUtentes(utentes))
alterado = 0;
break;
case 0:
break;
default:
/* Aqui nunca se pode chegar! */
break;
}
}
while(opcao != 0);
/* Se houve alteracoes perguntar se se quer guardar: */
if(alterado)
{
printf("Deseja guardar antes de sair? [1 - sim, 0 - nao] ");
if(leOpcao(0, 1) == 1)
guardaUtentes(utentes);
}
return EXIT_SUCCESS;
}