#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; }