EXERCÍCIOS PROPOSTOS – SOLUÇÃO
1: #include <stdio.h>
2: #include <string.h>
3: #include <stdlib.h> /* Função exit */
4: #include <ctype.h> /* Função toupper */
5:
6: #define FICH "dados.dat" /* Ficheiro com os Dados */
7:
8: #define OP_INSERIR '1'
9: #define OP_ALTERAR '2'
10: #define OP_APAGAR '3'
11: #define OP_LISTAR '4'
12: #define OP_PESQUISAR '5'
13:
14: #define OP_SAIR '0'
15:
16: #define OP_PESQ_IDADE '1'
17: #define OP_PESQ_NOME '2'
18:
19: char *mainMenu[]={
20: "1. Inserir Registo", 21: "2. Alterar Registo", 22: "3. Apagar Registo", 23: "4. Listar Registos", 24: "5. Pesquisas", 25: "0. Sair",
26: NULL /* Acabaram as Opções */
27: };
28:
29: char *searchMenu[]={
30: "1. Pesquisar por Intervalo de Idades",
31: "2. Pesquisar por Nome",
32: "0. Voltar",
33: NULL /* Acabaram as Opções */
34: };
35:
36: typedef struct
37: {
38: char nome[30+1];
39: int idade;
40: float salario;
41: char status; /* '*' Indica que o registo esta apagado */
42: } PESSOA;
43:
44: void mensagem(char *msg);
45:
46: /* Lê os dados de um registo introduzidos pelo utilizador */
47: void ler_pessoa(PESSOA *p)
48: {
49: printf("Nome : "); gets(p->nome);
50: printf("Idade : "); scanf("%d", &p->idade);
51: printf("Salario : "); scanf("%f", &p->salario); 52: p->status=' ';
53: }
54:
55: /* Mostra no ecrã, os dados existente no registo */
56:
57: void mostrar_pessoa(PESSOA p)
58: {
59: printf("%-30s %3d %10.2f\n", p.nome, p.idade, p.salario);
60: }
61:
62: /* Limpar o buffer do teclado */
63: void limpar_buffer()
64: {
65: while (scanf("%*c")==1)
66: ;
67: }
68:
69: /* Grava os dados de uma pessoa no Ficheiro */
70: void gravar_pessoa(FILE*fp, PESSOA p)
71: {
72: fseek(fp, 0L, SEEK_END);
73: if (fwrite(&p, sizeof(p), 1L, fp)!=1)
74: mensagem("Adicionar Pessoa: Falhou a escrita do Registo");
75: else
76: mensagem("Registo gravado com sucesso.");
77: }
78:
79: /* Coloca um mensagem no ecrã */
80: void mensagem(char *msg)
81: {
82: printf("%s", msg); 83: printf("Prima <ENTER> para continuar");
84: limpar_buffer();
85: getchar();
86: }
87:
88: /* Devolve a referência para o ficheiro de dados */ 89: FILE *obter_ficheiro()
90: {
91: FILE *fp=fopen(FICH, "r+b"); /* Tentar Abrir */ 92:
93: if (fp==NULL) /* Ficheiro não existe */ 94: fp=fopen(FICH, "w+b"); /* Tentar Criar */ 95:
96: if (fp==NULL)
97: {
98: fprintf(stderr, "ERRO FATAL: Ficheiro de Dados\n"); 99: exit(1); 100: }
101: return fp; 102: }
103:
104: /*
105: * Faz um Menu Simples com as opções do array de strings. 106: * Selecciona a Opção, usando o 1º caráter de cada string.
107: * Devolve o primeiro caráter da opção
108: */
109: char menu(char *opcoes[])
110: { 111: char op; 112:
113: while (1) 114: { 115:
116: printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
117: for(int i=0; opcoes[i]!=NULL; i++)
118: printf("\t\t%s\n", opcoes[i]);
119: 120: printf("\n\n\t\tOpção: ");
121: scanf(" %c", &op); 122: limpar_buffer();
123:
124: for (int i=0; opcoes[i]!=NULL; i++)
125: if (opcoes[i][0]==op)
126: return op; 127: }
128: }
129:
130: void inserir_pessoa(FILE *fp)
131: { PESSOA x; 132: ler_pessoa(&x); 133: gravar_pessoa(fp, x); 134: }
135:
136: void alterar_pessoa(FILE*fp)
137: { PESSOA x; 138: long int n_reg; 139:
140: printf("Qual o nº do registo: ");
141: scanf("%ld", &n_reg);
142: if (fseek(fp, (n_reg-1)*sizeof(PESSOA), SEEK_SET)!=0)
143: { 144: mensagem("Registo inexistente ou problemas no posicionamento!!!");
145: return;
146: }
147:
148: if (fread(&x, sizeof(PESSOA), 1L, fp)!=1)
149: { 150: mensagem("Problemas na leitura do registo!!!"); 151: return;
152: }
153:
154: if (x.status=='*')
155: { 156: mensagem("Um registo apagado não pode ser alterado!!!\n\n"); 157: return; 158: } 159:
160: printf("\n\nDados Actuais\n\n"); 161: mostrar_pessoa(x); 162: printf("\n\nNovos Dados\n\n"); 163: ler_pessoa(&x); 164:
165: // Recuar um Registo no Ficheiro
166: fseek(fp, -(long) sizeof(PESSOA), SEEK_CUR); 167: // Reescrever o Registo; 168: fwrite(&x, sizeof(PESSOA), 1L, fp); 169: fflush(fp); 170: }
171:
172: void apagar_pessoa(FILE*fp)
173: { PESSOA x; 174: long int n_reg; 175: char resp;
176:
177: printf("Qual o nº do Registo: "); 178: scanf("%ld", & n_reg);fflush(stdin); 179:
180: if (fseek(fp, (n_reg-1)*sizeof(PESSOA), SEEK_SET)!=0)
181: { 182: mensagem("Registo inexistente ou problemas no posicionamento!!!");
183: return; 184: }
185:
186: if (fread(&x, sizeof(PESSOA), 1L, fp)!=1)
187: { 188: mensagem("Problemas na leitura do registo!!!");
189: return ; 190: }
191:
192: if (x.status=='*')
193: {
194: mensagem("Registo já está apagado!!!\n\n"); 195: return; 196: }
197:
198: printf("\n\nDados Actuais\n\n"); 199: mostrar_pessoa(x);
200:
201: printf("\n\nApagar o registo (s/n)???: "); scanf(" %c", &resp); 202: if (toupper(resp)!='S') return;
203:
204: x.status='*';
205:
206: // Recuar um registo no ficheiro
207: fseek(fp, -(long) sizeof(PESSOA), SEEK_CUR);
208:
209: // Reescrever o fegisto; 210: fwrite(&x, sizeof(PESSOA), 1L, fp); 211: fflush(fp); 212: }
213:
214:
215: void listar(FILE*fp)
216: { long int n_linhas =0; 217: PESSOA reg; 218:
219: rewind(fp);
220: while(1)
221: {
222: if (fread(®, sizeof(reg), 1L, fp)!=1)
223: break;/* Sair do Ciclo */
224:
225: if (reg.status=='*')
226: continue ; /* Passa ao próximo */
227: mostrar_pessoa(reg);
228: n_linhas++;
229: if (n_linhas%20==0)
230: mensagem("");
231: }
232: mensagem("\n\nFim da listagem "); /* No fim da Listagem */ 233: }
234:
235: void pesquisar_idades(FILE*fp, int ini, int fim)
236: { PESSOA reg; 237: rewind(fp);
238:
239: while (fread(®, sizeof(PESSOA), 1L, fp))
240: if (reg.status!='*' && reg.idade>=ini && reg.idade<=fim)
241: mostrar_pessoa(reg);
242:
243: mensagem("\n\nFim da listagem "); /* No fim da Listagem */ 244: }
245:
246: void pesquisar_nome(FILE*fp, char *s)
247: { PESSOA reg; 248: rewind(fp);
249:
250: while (fread(®, sizeof(PESSOA), 1L, fp))
251: if (reg.status!='*' && strstr(reg.nome, s))
252: mostrar_pessoa(reg);
253: mensagem("\n\nFim da listagem "); /* No fim da Listagem */ 254: }
255:
256: int main(void)
11.2
257: {
258: char opcao;
259: FILE *fp = obter_ficheiro();
260:
261: while ((opcao=menu(mainMenu))!=OP_SAIR)
262: switch(opcao)
263: {
264: case OP_INSERIR: inserir_pessoa(fp); break; 265: case OP_ALTERAR: alterar_pessoa(fp); break; 266: case OP_APAGAR: apagar_pessoa(fp); break; 267: case OP_LISTAR: listar(fp); break;
268:
269: case OP_PESQUISAR:
270: while((opcao=menu(searchMenu))!=OP_SAIR)
271: switch (opcao)
272: {
273: case OP_PESQ_IDADE:
274: {
275: int n1, n2;
276: printf("Qual o intervalo de Idades: "); 277: scanf("%d%d", &n1, &n2);
278: pesquisar_idades(fp, n1, n2);
279: break;
280: }
281: case OP_PESQ_NOME:
282: { 283: char string[BUFSIZ+1];
284: printf("Qual o nome a procurar: "); 285: gets(string); 286: pesquisar_nome(fp, string);
287: }
288: }
289: }
290: return 0;
291: }
a)
#define MAX 10 #define MAX_NOME 40
typedef struct { unsigned n; char nome[MAX_NOME+1]; } REGISTO;
b)
typedef struct { REGISTO arr[MAX]; int conta; } LISTA;
c) int main(void) { LISTA lista; return 0; }
d)
void inic(LISTA * ptr)
{ ptr->conta=0; }
e)
int lista_cheia(LISTA lst)
{ return lst.conta>=MAX; }
f)
int inserir(LISTA *ptr, REGISTO reg)
{ if (lista_cheia(*ptr)) return -1; ptr->arr[ptr->conta] = reg; return ptr->conta++; }
g)
h)
int gravar(LISTA lst, char *filename) /* Versão 1 */ { FILE *fp=fopen(filename, "wb"); if (fp==NULL) return 0;
for (int i=0 ; i<lst.conta; i++) if (fwrite(&lst.arr[i], sizeof(REGISTO), 1L, fp)!=1) return 0; fclose(fp); return 1; }
int gravar_v2(LISTA lst, char *filename) /* Versão 2 */ { FILE *fp=fopen(filename, "wb"); if (fp==NULL) return 0;
if (fwrite(lst.arr, sizeof(REGISTO), (long) lst.conta, fp)!= lst.conta) return 0; fclose(fp); return 1; }
int carregar_lista(LISTA *ptr, FILE *fp) { REGISTO reg; rewind(fp); /* Ir para o principio do ficheiro */ while (fread(®, sizeof(reg), 1L, fp)==1) if (inserir(ptr, reg)==-1) return 0; return 1; }
i)
void listar(LISTA lst)
{ puts("---- LISTA (inicio) ----"); for (int i=0; i<lst.conta; i++) printf("%2d: %d %s\n", i+1, lst.arr[i].n, lst.arr[i].nome); puts("---- LISTA (fim) -------"); }
j)
1: #include <stdio.h>
2: #include <string.h>
3:
4: #define MAX 10
5: #define MAX_NOME 40
6:
7: typedef struct
8: { 9: unsigned n; 10: char nome[MAX_NOME+1];
11: } REGISTO;
12:
13: typedef struct
14: { 15: REGISTO arr[MAX];
16: int conta; 17: } LISTA;
18:
19: void inic(LISTA * ptr)
20: { 21: ptr->conta=0; 22: }
23:
24: int lista_cheia(LISTA lst)
25: { 26: return lst.conta>=MAX;
27: }
28:
29: int inserir(LISTA *ptr, REGISTO reg)
30: { 31: if (lista_cheia(*ptr))
32: return -1;
33: ptr->arr[ptr->conta] = reg; 34: return ptr->conta++;
35: }
36:
37: int gravar(LISTA lst, char *filename) /* Versão 1 */
38: {
39: FILE *fp=fopen(filename, "wb");
40: if (fp==NULL) return 0;
41:
42: for (int i=0 ; i<lst.conta; i++)
43: if (fwrite(&lst.arr[i], sizeof(REGISTO), 1L, fp)!=1)
44: return 0;
45: fclose(fp);
46: return 1;
47: }
48:
49: int gravar_v2(LISTA lst, char *filename) /* Versão 2 */
50: {
51: FILE *fp=fopen(filename, "wb");
52: if (fp==NULL) return 0;
53:
54: if (fwrite(lst.arr, sizeof(REGISTO), (long) lst.conta, fp)!= lst.conta)
55: return 0;
56: fclose(fp);
57: return 1;
58: }
59:
60: int carregar_lista(LISTA *ptr, FILE *fp)
61: { REGISTO reg; 62: rewind(fp); /* Ir para o principio do ficheiro */ 63: while (fread(®, sizeof(reg), 1L, fp)==1)
64: if (inserir(ptr, reg)==-1)
65: return 0;
66: return 1;
67: }
68:
69: void listar(LISTA lst)
70: {
71: puts("---- LISTA (inicio) ----");
72: for (int i=0; i<lst.conta; i++)
73: printf("%2d: %d %s\n", i+1, lst.arr[i].n, lst.arr[i].nome);
74: puts("---- LISTA (fim) -------\n");
75: }
76:
77:
78: int main(void)
79: {
80: REGISTO regs[] = {{50, "Rui"}, {22, "Ana"}, 81: {77, "Isabel"}, {99, "Carlos"}
82: };
83: LISTA lista;
84:
85: inic(&lista); 86: listar(lista);
87:
88: // Adicionar os registos à lista
89: for (int i=0; i<sizeof(regs)/sizeof(regs[0]); i++)
90: inserir(&lista, regs[i]);
91: listar(lista);
92:
93: if (gravar(lista, "lista.dat"))
94: puts("Registos gravados com sucesso.");
95: else
96: puts("Problemas na gravação dos registos."); 97:
98: // Carregar os registos existentes em ficheiro 99: // ja lista já existente, adicionando-os ao fim 100:
101: FILE *fp = fopen("lista.dat", "rb"); 102: if (fp==NULL)
103: { 104: printf("Não foi possível abrir o ficheiro de dados"); 105: return 1; 106: }
107:
108: carregar_lista(&lista, fp); 109: puts("Depois de adicionados os registos à lista 1x"); 110: listar(lista); 111:
112: // Voltar a carregar os registos para ver se os limites 113: // não são violados
114:
115: carregar_lista(&lista, fp); 116: fclose(fp);
117: puts("Depois de adicionados os registos à lista 2x"); 118: listar(lista); 119:
120: return 0; 121: } PROG1104.C (PROGRAMA COMPLETO)
$ pro1104 ---- LISTA (inicio) ------- LISTA (fim) -------
---- LISTA (inicio) ----
1: 50 Rui
2: 22 Ana
3: 77 Isabel
4: 99 Carlos ---- LISTA (fim) -------
Registos gravados com sucesso.
Depois de adicionados os registos à lista 1x
---- LISTA (inicio) ----
1: 50 Rui
2: 22 Ana
3: 77 Isabel
4: 99 Carlos
5: 50 Rui
6: 22 Ana
7: 77 Isabel
8: 99 Carlos ---- LISTA (fim) -------
Depois de adicionados os registos à lista 2x
---- LISTA (inicio) ----
1: 50 Rui
2: 22 Ana
3: 77 Isabel
4: 99 Carlos
5: 50 Rui
6: 22 Ana
7: 77 Isabel
8: 99 Carlos
9: 50 Rui
10: 22 Ana ---- LISTA (fim) -------