-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimple.c
505 lines (445 loc) · 13.9 KB
/
imple.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct livros{
int id, publicacao, exemplares;
char titulo[100];
char autor[50];
char genero[30];
char editora[50];
};
int contar(struct livros inv[]){
int cont = -1;
int i = 0;
while(inv[i].autor[0] != '\0'){
cont++;
i++;
}
return cont;
}
//função que substitui o uso de fflush(stdin), que pode não funcionar dependendo do compilador
void clean_stdin(void){
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
//escreve os dados do struct para o arquivo
void write(struct livros *inv){
FILE *fp;
fp = fopen("db.txt","w+");
if(fp != NULL){
//conta o numero de elementos no struct do heap (memória virtual) e define o i
int contagem = contar(inv)+1, i;
//itera sobre os elementos do struct gravando cada entrada em uma linha e cada propriedade separada por um pipe (|)
for(i = 0; i < contagem; i++){
fprintf(fp, "%i|", inv[i].id);
fprintf(fp, "%s|", inv[i].titulo);
fprintf(fp, "%s|", inv[i].autor);
fprintf(fp, "%s|", inv[i].genero);
fprintf(fp, "%i|", inv[i].publicacao);
fprintf(fp, "%s|", inv[i].editora);
fprintf(fp, "%i\n", inv[i].exemplares);
}
} else {
printf("Não foi possível abrir a base de dados.\n");
}
fclose(fp);
}
//salva o numero do contador em um arquivo em separado
void saveCount(int *cont){
FILE *fp;
fp = fopen("contador.txt","w+");
fprintf(fp,"%i", *cont);
fclose(fp);
}
//loga os dados do arquivo para o struct
void load(struct livros *inv, int *cont){
FILE *fp;
fp = fopen("db.txt", "a+");
if(fp != NULL){
//quebra uma linha do arquivo pelo |
void tokenize(char* entry, char response[7][80]){
int i = 0;
char *token;
//função strtok le todos o caracteres até o pipe
token = strtok(entry, "|");
//le as outras propriedades entre os pipes até o retorno ser nulo
while(token != NULL ) {
//copia a propriedade lida para o array response
strcpy(response[i], token);
//quando a strtok é chamada com NULL ela continua a ler do stream de sua ultima chamada, asism lendo todas as propriedades entre os pipes
token = strtok(NULL, "|");
//aumenta o iterador
i++;
}
}
//iteradores
int i = 0, j;
//array de strings auxiliares
char a[30][200];
//volta ao inicio do arquivo
rewind(fp);
//se o final do arquivo NÃO foi atingido
while(feof(fp) == 0){
//usa o fscanf para ler do arquivo, com a diletiva %[^\n] ele para a leitura quando achar um \n
fscanf(fp,"%[^\n]", a[i]);
//checa novamente se é o fim do arquivo. Isso é feito pois se o stream estiver no final do arquivo, move-lo para frente ira voltar ao inicio do arquivo
if(feof(fp) == 0){
//move o stream 1 caractere da posição atual.
fseek( fp, sizeof(char), SEEK_CUR);
}
//iterador
i++;
}
//itera sobre a contagem de linhas/entradas do arquivo
for(j = 0; j < i-1; j++){
//array de strings auxiliar
char response[7][80];
//chama a função tokenize para cada uma das linhas, que irá retornar as propriedades individuais da entrada
tokenize(a[j], response);
//conversões de char para int usando a função strtol(string, ponteiro, base).
//pos é o id da entrada
int pos = strtol(response[0], NULL, 10);
//pub é o ano de publicação da entrada
int pub = strtol(response[4], NULL, 10);
//exp é o numero de exemplares da entrada
int exp = strtol(response[6], NULL, 10);
// escreve o id, ano de publicação e número de exemplares da entrada no struct
inv[j].id = pos;
inv[j].publicacao = pub;
inv[j].exemplares = exp;
//copia titulo, autor, editora e genero para o heap
strcpy(inv[j].titulo, response[1]);
strcpy(inv[j].autor, response[2]);
strcpy(inv[j].genero, response[3]);
strcpy(inv[j].editora, response[5]);
}
//===== essa parte do código garante que os ID's sejam únicos =======
//abre o arquivo do contador para leitura
FILE *ident;
ident = fopen("contador.txt", "r");
//se ele não existir:
if(ident == NULL){
//move o stream para o final do arquivo
fseek(fp, 0, SEEK_END);
//se o db.txt NÃO estiver vazio, altera o contador para o ultimo id do struct +1
if(ftell(fp) != 0){
//o contador retornado será o numero de entradas do struct +1
*cont = inv[contar(inv)].id+1;
}
} else {
//caso contrário:
//cria string auxiliar num
char num[2];
//le até o fim da linha
fscanf(ident,"%[^\n]", num);
//converte a string lida para int
int leitura = strtol(num, NULL, 10);
//o valor do contador agora será o valor lido do arquivo.
*cont = leitura;
//fecha o arquivo
fclose(ident);
}
fclose(fp);
} else {
printf("Não foi possível abrir a base de dados.\n");
}
}
void cabecalho(int aux){
if(aux == 1){
printf("ID |Título |Autor |Gênero |Publicação |Editora |Exemplares\n");
printf("---+------------------------------+--------------------+--------------------+-----------+--------------------------+----------\n");
}
}
//função interna que remove o '\n' de uma string.
void clear(char str[]){
char *p;
p = strchr(str, '\n');
*p = '\0';
};
void printar(struct livros inv[30], int pos){
if(inv[pos].id < 10){
printf("%i |", inv[pos].id);
} else {
printf("%i |", inv[pos].id);
}
//Autor
int j;
//Cria uma int leng que recebe o tamanho do título do livro
int leng = strlen(inv[pos].titulo);
//Printa o nome do livro
printf("%s", inv[pos].titulo);
//Usa-se um for para printar o número de espaços até o fim da coluna, neste caso (30 - leng)
for(j = 0; j < (30 - leng) ; j++){
printf(" ");
}
//Printa a barra separadora de colunas
printf("|");
//Autor
//Cria uma int leng que recebe o tamanho do nome do autor
leng = strlen(inv[pos].autor);
//Printa o nome do autor
printf("%s", inv[pos].autor);
//Usa-se um for para printar o número de espaços até o fim da coluna, neste caso (20 - leng)
for(j = 0; j < (20 - leng) ; j++){
printf(" ");
}
//Printa a barra separadora de colunas
printf("|");
//Gênero
//Cria uma int leng que recebe o tamanho do gênero
leng = strlen(inv[pos].genero);
//Printa o gênero
printf("%s", inv[pos].genero);
//Usa-se um for para printar o número de espaços até o fim da coluna, neste caso (20 - leng)
for(j = 0; j < (20 - leng) ; j++){
printf(" ");
}
//Printa a barra separadora de colunas
printf("|");
//Ano de publicação
//Printa o ano de publicação
printf("%i", inv[pos].publicacao);
//Usa-se um for para printar o número de espaços até o fim da coluna, neste caso 7
for(j = 0; j < 7 ; j++){
printf(" ");
}
//Printa a barra separadora de colunas
printf("|");
//Editora
//Cria uma int leng que recebe o tamanho da editora
leng = strlen(inv[pos].editora);
//Printa a editora
printf("%s", inv[pos].editora);
//Usa-se um for para printar o número de espaços até o fim da coluna, neste caso (26 - leng)
for(j = 0; j < (26-leng) ; j++){
printf(" ");
}
//Printa a barra separadora de colunas
printf("|");
//Nº de exemplares
//Printa o número de exemplares
printf("%i\n", inv[pos].exemplares);
}
void listar(struct livros inv[30]){
int i;
int tamanho = contar(inv)+1;
if(tamanho != 0){
cabecalho(1);
} else {
printf("::::.Sem registros.::::\n");
}
for(i = 0; i < tamanho; i++){
printar(inv, i);
}
}
int remover(struct livros *inv, int id){
//Cria uma variavel que receve o tamanho do array
int tamanho = contar(inv)+1;
int i, j, ret = 1;
//itera sobre os elementos do array
for(i = 0; i < tamanho; i++){
//se encontrar o elemento que o usuário digitou:
if(id == inv[i].id){
ret = 0;
//começa a iterar a partir do elemento do usuário até o fim do array
for(j = i; j < tamanho; j++){
//copia o elemento seguinte para a posição do elemento a ser apagado e assim por diante
inv[j].id = inv[j+1].id;
inv[j].publicacao = inv[j+1].publicacao;
inv[j].exemplares = inv[j+1].exemplares;
strcpy(inv[j].autor, inv[j+1].autor);
strcpy(inv[j].titulo, inv[j+1].titulo);
strcpy(inv[j].editora, inv[j+1].editora);
strcpy(inv[j].genero, inv[j+1].genero);
}
//retorna 0 depois de apagar o registro
return ret;
}
}
}
void inserir(struct livros *inv, int *cont){
int valida(char str[]){
int size = strlen(str), i, cont = 0;
for(i = 0; i < size; i++){
if(str[i] == ' '){
cont++;
}
}
if(cont == size){
printf("Entrada não pode ser vazia\n");
return 1;
} else {
return 0;
}
};
//recebe o tamanho do array
int tamanho = contar(inv)+1, ano;
//string auxiliar
char aux[100];
//o novo id será o contador +1
inv[tamanho].id = *cont;
//limpa o stdin para remover bugs entre scanf e fgets
clean_stdin();
//Le o titulo
do{
printf("Título: ");
fgets(aux, 100, stdin);
clear(aux);
} while(valida(aux) == 1);
strcpy(inv[tamanho].titulo, aux);
//Le o autor
do{
printf("Autor: ");
fgets(aux, 100, stdin);
clear(aux);
}while(valida(aux) == 1);
strcpy(inv[tamanho].autor, aux);
//le a editora
do{
printf("Editora: ");
fgets(aux, 100, stdin);
clear(aux);
}while(valida(aux) == 1);
strcpy(inv[tamanho].editora, aux);
//le o genero
do{
printf("Gênero: ");
fgets(aux, 100, stdin);
clear(aux);
}while(valida(aux) == 1);
strcpy(inv[tamanho].genero, aux);
//le o ano de publicação
printf("Ano de Publicação: ");
scanf("%i", &inv[tamanho].publicacao);
//le o número de exemplares
printf("Nº Exemplares: ");
scanf("%i", &inv[tamanho].exemplares);
*cont = *cont + 1;
saveCount(cont);
}
int consulta(struct livros *inv, int id){
int i, tamanho = contar(inv)+1, ret = 1;
for (i = 0; i < tamanho; i++){
if(inv[i].id == id){
ret = 0;
printf("-----------------------\n");
printf("ID: %i\n", inv[i].id);
printf("Título: %s\n", inv[i].titulo);
printf("Autor: %s\n", inv[i].autor);
printf("Gênero: %s\n", inv[i].genero);
printf("Editora: %s\n", inv[i].editora);
printf("Publicação: %i\n", inv[i].publicacao);
printf("Exemplares: %i\n", inv[i].exemplares);
return ret;
}
}
return ret;
}
int buscaAutor(struct livros *inv, char *chave){
int i, tamanho = contar(inv)+1, aux = 0;
for(i = 0; i < tamanho; i++){
if( (strcmp(inv[i].autor, chave) ) == 0){
aux++;
cabecalho(aux);
printar(inv, i);
}
}
return aux;
}
int mudaEx(struct livros *inv, int chave){
int i, tamanho = contar(inv)+1, ret = 1;
for(i = 0; i < tamanho; i++){
if(inv[i].id == chave){
ret = 0;
printf("Insira a quantidade de exemplares atualizadas de \"%s\": ", inv[i].titulo);
scanf("%i", &inv[i].exemplares);
}
}
return ret;
}
int main(){
int i, ops = -1, aux, retorno, cont = 0;
char autor[100];
struct livros inv[30] = {};
load(inv, &cont);
while(ops != 0){
printf("------------------------\n0: Sair\n1: Listar\n2: Inserir\n3: Remover\n4: Consulta\n5: Buscar por Autor\n6: Mudar Nº de exemplares\n7: Limpar base de dados\n\n:::Escolha uma opção: ");
scanf("%i", &ops);
switch (ops){
case 0:{
write(inv);
saveCount(&cont);
break;
}
case 1:{
listar(inv);
break;
}
case 2:{
inserir(inv, &cont);
write(inv);
break;
}
case 3:{
printf("Insira o ID que deseja remover: ");
scanf("%i", &aux );
retorno = remover(inv, aux);
if(retorno == 0){
printf(":::::.Registro removido com sucesso.:::::\n");
write(inv);
} else{
printf(":::::.Registro não encontrado.:::::\n");
}
break;
}
case 4:{
printf("Insira um ID: ");
scanf("%i", &aux);
retorno = consulta(inv, aux);
if(retorno == 1){
printf(":::::.Registro não encontrado.:::::\n");
}
break;
}
case 5:{
printf("Insira um autor: ");
clean_stdin();
fgets(autor, 100, stdin);
clear(autor);
retorno = buscaAutor(inv, autor);
if(retorno == 0){
printf(":::::.Registro não encontrado.:::::\n");
}
break;
}
case 6:{
printf("Digite o ID que deseja modificar: ");
scanf("%i", &aux);
retorno = mudaEx(inv, aux);
if(retorno == 0){
printf(":::::.Registro alterado com sucesso.:::::\n");
write(inv);
} else{
printf(":::::.Registro não encontrado.:::::\n");
}
break;
}
case 7: {
FILE *fp;
fp = fopen("db.txt","w+");
fclose(fp);
fp = fopen("contador.txt","w+");
fclose(fp);
memset(inv, 0, sizeof(inv));
cont = 0;
break;
}
default:{
printf("Opção não listada\n");
break;
}
}
}
}