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