Created
February 8, 2013 10:54
-
-
Save nagisa/4738115 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <inttypes.h> | |
#include <time.h> | |
#define USER_ACTIVE 1 | |
#define USER_SUSPENDED 0 | |
typedef struct book { | |
uint32_t id; | |
char author[250]; | |
char title[250]; | |
uint64_t published; | |
uint32_t pages; | |
uint32_t available; | |
uint32_t total; | |
} book_t; | |
typedef struct lent { | |
time_t lent; | |
time_t returning; | |
uint32_t user_id; | |
uint32_t book_id; | |
} lending_t; | |
typedef struct user { | |
uint32_t id; | |
char name[250]; | |
char lname[250]; | |
uint32_t status; | |
} user_t; | |
typedef struct library { | |
uint32_t user_cnt; | |
uint32_t user_size; | |
user_t *users; | |
uint32_t lends_cnt; | |
uint32_t lends_size; | |
lending_t *lends; | |
uint32_t book_cnt; | |
uint32_t book_size; | |
book_t *books; | |
} lib_t; | |
char *strchrnul(char *str, const int c){ | |
for(; *str != '\0' && *str != c; str++); | |
return str; | |
} | |
int load_data(lib_t *library){ | |
FILE *in; | |
char input[1024]; | |
// Load users | |
in = fopen("users", "r"); | |
if(!in) return 0; | |
fgets(input, 1024, in); | |
sscanf(input, "%d", &library->user_cnt); | |
library->users = malloc(sizeof(user_t) * | |
(library->user_size = library->user_cnt + 100)); | |
for(uint32_t i = 0; i < library->user_cnt; i += 1){ | |
fgets(input, 1024, in); | |
sscanf(strtok(input, "\t"), "%"SCNu32, &library->users[i].id); | |
strncpy(library->users[i].name, strtok(NULL, "\t"), 249); | |
strncpy(library->users[i].lname, strtok(NULL, "\t"), 249); | |
sscanf(strtok(NULL, "\n"), "%"SCNu32, &library->users[i].status); | |
} | |
fclose(in); | |
// Load books | |
in = fopen("books", "r"); | |
if(!in) return 0; | |
fgets(input, 1024, in); | |
sscanf(input, "%d", &library->book_cnt); | |
library->books = malloc(sizeof(book_t) * | |
(library->book_size = library->book_cnt + 100)); | |
for(uint32_t i = 0; i < library->book_cnt; i += 1){ | |
fgets(input, 1024, in); | |
sscanf(strtok(input, "\t"), "%"SCNu32, &library->books[i].id); | |
strncpy(library->books[i].author, strtok(NULL, "\t"), 249); | |
strncpy(library->books[i].title, strtok(NULL, "\t"), 249); | |
sscanf(strtok(NULL, "\t"), "%"SCNu64, &library->books[i].published); | |
sscanf(strtok(NULL, "\t"), "%"SCNu32, &library->books[i].pages); | |
sscanf(strtok(NULL, "\t"), "%"SCNu32, &library->books[i].available); | |
sscanf(strtok(NULL, "\n"), "%"SCNu32, &library->books[i].total); | |
} | |
fclose(in); | |
// Load lends | |
in = fopen("lends", "r"); | |
if(!in) return 0; | |
fgets(input, 1024, in); | |
sscanf(input, "%d", &library->lends_cnt); | |
library->lends = malloc(sizeof(lending_t) * | |
(library->lends_size = library->lends_cnt + 100)); | |
for(uint32_t i = 0; i < library->lends_cnt; i += 1){ | |
fgets(input, 1024, in); | |
sscanf(input, "%"SCNu64" %"SCNu64" %"SCNu32" %"SCNu32, | |
&library->lends[i].lent, &library->lends[i].returning, | |
&library->lends[i].user_id, &library->lends[i].book_id); | |
} | |
fclose(in); | |
// Success! | |
return 1; | |
} | |
int dump_data(lib_t *library){ | |
FILE *out; | |
// Dump lends | |
out = fopen("lends", "w"); | |
fprintf(out, "%"PRIu32"\n", library->lends_cnt); | |
for(uint32_t i = 0; i < library->lends_cnt; i += 1) | |
fprintf(out, "%"SCNu64" %"SCNu64" %"SCNu32" %"SCNu32"\n", | |
library->lends[i].lent, library->lends[i].returning, | |
library->lends[i].user_id, library->lends[i].book_id); | |
fclose(out); | |
// Dump books | |
out = fopen("books", "w"); | |
fprintf(out, "%"PRIu32"\n", library->book_cnt); | |
for(uint32_t i = 0; i < library->book_cnt; i += 1) | |
fprintf(out, "%"PRIu32"\t%s\t%s\t%"PRIu64"\t%"PRIu32"\t%"PRIu32"\t%"PRIu32"\n", | |
library->books[i].id, library->books[i].author, | |
library->books[i].title, library->books[i].published, | |
library->books[i].pages, library->books[i].available, | |
library->books[i].total); | |
fclose(out); | |
// Dump users | |
out = fopen("users", "w"); | |
fprintf(out, "%"PRIu32"\n", library->user_cnt); | |
for(uint32_t i = 0; i < library->user_cnt; i += 1) | |
fprintf(out, "%"PRIu32"\t%s\t%s\t%"PRIu32"\n", library->users[i].id, | |
library->users[i].name, library->users[i].lname, | |
library->users[i].status); | |
fclose(out); | |
return 0; | |
} | |
uint32_t get_numb(uint32_t min, uint32_t max, const char *lbl){ | |
uint32_t item = 0; | |
char input[20]; | |
while(item < min || item > max){ | |
if(lbl){ | |
printf("%s>> ", lbl); | |
}else{ | |
printf(">> "); | |
} | |
fgets(input, 20, stdin); | |
sscanf(input, "%"scnu32, &item); | |
} | |
return item; | |
} | |
uint32_t menu(void){ | |
printf("–– Pasirinkite skyrių ––\n" | |
"1: Inventorius\n" | |
"2: Vartotojai\n" | |
"3: Pranešimai\n" | |
"4: Išduoti knygą\n" | |
"5: Išeiti\n"); | |
return get_numb(1, 5, "PASIRINKIMAS "); | |
} | |
uint32_t user_menu(void){ | |
printf("–– Vartotojų meniu ––\n" | |
"1: Vartotojų lentelė\n" | |
"2: Peržiūrėti vartotoją\n" | |
"3: Sukurti vartotoją\n" | |
"4: Keisti vartotoją\n" | |
"Bet kuris kitas pasirinkimas jus sugrąžins į skyrių parinktį\n"); | |
return get_numb(1, UINT32_MAX, "PASIRINKIMAS "); | |
} | |
uint32_t book_menu(void){ | |
printf("–– Knygų meniu ––\n" | |
"1: Knygų lentelė\n" | |
"2: Peržiūrėti knygą\n" | |
"3: Sukurti knygą\n" | |
"4: Keisti knygą\n" | |
"Bet kuris kitas pasirinkimas jus sugrąžins į skyrių parinktį\n"); | |
return get_numb(1, UINT32_MAX, "PASIRINKIMAS "); | |
} | |
void print_table_hr(uint32_t *cw){ | |
for(uint32_t y = 0; cw[y] != 0; y += 1){ | |
printf("+"); | |
for(uint32_t i = 0; i < cw[y]; i += 1) printf("-"); | |
} | |
printf("+\n"); | |
} | |
void print_user_table(lib_t *library){ | |
uint32_t cnt = library->user_cnt, tmp, ws[5] = {5, 8, 9, 5, 0}; | |
char line_fmt[50]; | |
// Get width of columns | |
for(uint32_t i = 0; i < cnt; i += 1){ | |
tmp = strlen(library->users[i].name) + 2; | |
ws[1] = ws[1] >= tmp ? ws[1] : tmp; | |
tmp = strlen(library->users[i].lname) + 2; | |
ws[2] = ws[2] >= tmp ? ws[2] : tmp; | |
} | |
print_table_hr(ws); | |
sprintf(line_fmt, "| ID | %%%ds | %%%ds | BŪS |\n", ws[1] - 2, | |
ws[2] - 2); | |
printf(line_fmt, "VARDAS", "PAVARDĖ"); | |
sprintf(line_fmt, "| %%3d | %%%ds | %%%ds | %%3s |\n", ws[1] - 2, | |
ws[2] - 2); | |
print_table_hr(ws); | |
for(uint32_t i = 0; i < cnt; i += 1) | |
printf(line_fmt, library->users[i].id, library->users[i].name, | |
library->users[i].lname, | |
library->users[i].status == USER_SUSPENDED ? "SUS" : "AKT"); | |
print_table_hr(ws); | |
} | |
void prev_user(lib_t *library){ | |
uint32_t id = get_numb(1, UINT32_MAX, "ĮVESKITE ID "); | |
for(uint32_t i = 0; i < library->user_cnt; i += 1){ | |
if(library->users[i].id == id){ | |
printf("ID\t%"PRIu32"\nVARDAS\t%s\nPAVARDĖ\t%s\nBŪSENA\t%s\n", | |
library->users[i].id, library->users[i].name, | |
library->users[i].lname, | |
library->users[i].status == USER_SUSPENDED ? "Suspenduotas" : | |
"Aktyvus"); | |
return; | |
} | |
} | |
printf("Vartotojas nerastas\n"); | |
} | |
void new_user(lib_t *library){ | |
if(library->user_cnt >= library->user_size){ | |
printf("Pilna atmintis, perkraute programą\n"); | |
return; | |
} | |
user_t *user = library->users + library->user_cnt; | |
if(!library->user_cnt) user->id = 1; | |
else user->id = library->users[library->user_cnt - 1].id + 1; | |
printf("ID\t%d\nVARDAS\t", user->id); | |
fgets(user->name, 249, stdin); | |
*strchrnul(user->name, '\n') = '\0'; | |
printf("PAVARDĖ\t"); | |
fgets(user->lname, 249, stdin); | |
*strchrnul(user->lname, '\n') = '\0'; | |
user->status = USER_ACTIVE; | |
library->user_cnt += 1; | |
} | |
void change_user(lib_t *library){ | |
uint32_t id = get_numb(1, UINT32_MAX, "KEIČIAMO VARTOTOJO ID "); | |
user_t *user = NULL; | |
for(uint i = 0; i < library->user_cnt; i += 1) | |
if(library->users[i].id == id){ | |
user = library->users + i; | |
break; | |
} | |
if(!user){ | |
printf("Vartotojo tokiu ID nėra\n"); | |
return; | |
} | |
printf("1: Keisti vardą\n" "2: Keisti pavardę\n" "3: %s\n" | |
"Bet kuris kitas pasirinkimas jus sugrąžins į skyrių parinktį\n", | |
user->status == USER_ACTIVE ? "Suspenduoti" : "Aktyvuoti"); | |
switch(get_numb(1, UINT32_MAX, "PASIRINKIMAS ")){ | |
case 1: | |
printf("VARDAS\t"); | |
fgets(user->name, 249, stdin); | |
*strchrnul(user->name, '\n') = '\0'; | |
break; | |
case 2: | |
printf("PAVARDĖ\t"); | |
fgets(user->lname, 249, stdin); | |
*strchrnul(user->lname, '\n') = '\0'; | |
break; | |
case 3: | |
user->status = user->status == USER_ACTIVE ? USER_SUSPENDED : USER_ACTIVE; | |
break; | |
default: | |
break; | |
} | |
} | |
void new_book(lib_t *library){ | |
char tmp[100]; | |
if(library->book_cnt >= library->book_size){ | |
printf("Pilna atmintis, perkraute programą\n"); | |
return; | |
} | |
book_t *book = library->books + library->book_cnt; | |
if(!library->book_cnt) book->id = 1; | |
else book->id = library->books[library->book_cnt - 1].id + 1; | |
printf("ID\t%d\nAUTORIUS\t", book->id); | |
fgets(book->author, 249, stdin); | |
*strchrnul(book->author, '\n') = '\0'; | |
printf("PAVADINIMAS\t"); | |
fgets(book->title, 249, stdin); | |
*strchrnul(book->title, '\n') = '\0'; | |
printf("VISO KNYGŲ\t"); | |
fgets(tmp, 99, stdin); | |
sscanf(tmp, "%d", &book->available); | |
book->total = book->available; | |
book->published = 0; | |
book->pages = 0; | |
library->book_cnt += 1; | |
} | |
void print_book_table(lib_t *library){ | |
uint32_t cnt = library->book_cnt, tmp, ws[7] = {5, 13, 9, 7, 5, 0}; | |
char line_fmt[50]; | |
for(uint32_t i = 0; i < cnt; i += 1){ | |
tmp = strlen(library->books[i].title) + 2; | |
ws[1] = ws[1] >= tmp ? ws[1] : tmp; | |
tmp = strlen(library->books[i].author) + 2; | |
ws[2] = ws[2] >= tmp ? ws[2] : tmp; | |
} | |
print_table_hr(ws); | |
sprintf(line_fmt, "| ID | %%%ds | %%%ds | KNYGŲ | PSL |\n", ws[1] - 2, | |
ws[2] - 2); | |
printf(line_fmt, "PAVADINIMAS", "AUTORIUS"); | |
print_table_hr(ws); | |
sprintf(line_fmt, "| %%3d | %%%ds | %%%ds | %%5d | %%3d |\n", ws[1] - 2, | |
ws[2] - 2); | |
for(uint32_t i = 0; i < cnt; i += 1) | |
printf(line_fmt, library->books[i].id, library->books[i].title, | |
library->books[i].author, library->books[i].available, | |
library->books[i].pages); | |
print_table_hr(ws); | |
} | |
void prev_book(lib_t *library){ | |
uint32_t id = get_numb(1, UINT32_MAX, "ĮVESKITE ID "); | |
for(uint32_t i = 0; i < library->user_cnt; i += 1){ | |
if(library->books[i].id == id){ | |
printf("ID\t\t%"PRIu32"\nPAVADINIMAS\t%s\nAUTORIUS\t%s\n" | |
"PUSLAPIŲ\t%"PRIu32"\nBIBLIOTEKOJE\t%"PRIu32" (iš %d)\n", | |
library->books[i].id, library->books[i].title, | |
library->books[i].author, library->books[i].pages, | |
library->books[i].available, library->books[i].total); | |
return; | |
} | |
} | |
printf("Knyga nerasta\n"); | |
} | |
void change_book(lib_t *library){ | |
char tmp[20]; | |
uint32_t id = get_numb(1, UINT32_MAX, "KEIČIAMOS KNYGOS ID "); | |
book_t *book = NULL; | |
for(uint i = 0; i < library->book_cnt; i += 1) | |
if(library->books[i].id == id){ | |
book = library->books + i; | |
break; | |
} | |
if(!book){ | |
printf("Knygos tokiu ID nėra\n"); | |
return; | |
} | |
printf("1: Keisti pavadinimą\n" "2: Keisti autorių\n" | |
"3: Pridėti arba atstatydinti knygas\n" | |
"4: Keisti puslapių skaičių\n" "5: Keisti išleidimo datą\n" | |
"Bet kuris kitas pasirinkimas jus sugrąžins į skyrių parinktį\n"); | |
switch(get_numb(1, UINT32_MAX, "PASIRINKIMAS ")){ | |
case 1: | |
printf("PAVADINIMAS\t"); | |
fgets(book->title, 249, stdin); | |
*strchrnul(book->title, '\n') = '\0'; | |
break; | |
case 2: | |
printf("AUTORIUS\t"); | |
fgets(book->author, 249, stdin); | |
*strchrnul(book->author, '\n') = '\0'; | |
break; | |
case 3: | |
printf("KIEK KNYGŲ PRIDĖTI (PRIDĖKITE - KAD PAŠALINTUMĖTE) >> "); | |
fgets(tmp, 19, stdin); | |
int64_t val; | |
sscanf(tmp, "%"SCNd64, &val); | |
book->available += val; | |
book->total += val; | |
break; | |
case 4: | |
printf("PUSLAPIŲ\t"); | |
fgets(tmp, 19, stdin); | |
sscanf(tmp, "%"SCNu32, &book->pages); | |
break; | |
case 5: | |
printf("Not implemented"); | |
default: | |
break; | |
} | |
} | |
void give_a_book(lib_t *library){ | |
if(library->lends_cnt >= library->lends_size){ | |
printf("Pilna atmintis, perkraute programą\n"); | |
return; | |
} | |
uint32_t user_id = get_numb(1, UINT32_MAX, "VARTOTOJO ID "); | |
user_t *user = NULL; | |
for(uint i = 0; i < library->user_cnt; i += 1) | |
if(library->users[i].id == user_id){ | |
user = library->users + i; | |
break; | |
} | |
if(!user){ | |
printf("Vartotojo tokiu ID nėra\n"); | |
return; | |
} | |
uint32_t book_id = get_numb(1, UINT32_MAX, "KEIČIAMOS KNYGOS ID "); | |
book_t *book = NULL; | |
for(uint i = 0; i < library->book_cnt; i += 1) | |
if(library->books[i].id == book_id){ | |
book = library->books + i; | |
break; | |
} | |
if(!book){ | |
printf("Knygos tokiu ID nėra\n"); | |
return; | |
} | |
library->lends[library->lends_cnt].user_id = user_id; | |
library->lends[library->lends_cnt].book_id = book_id; | |
library->lends[library->lends_cnt].returning =\ | |
library->lends[library->lends_cnt].lent = time(NULL); | |
printf("KNYGA GRĄŽINAMA PO\t"); | |
char tmp[20]; | |
uint32_t d; | |
fgets(tmp, 19, stdin); | |
sscanf(tmp, "%"SCNu32, &d); | |
library->lends[library->lends_cnt].returning += d * 86400; | |
library->lends_cnt += 1; | |
} | |
void notifications(lib_t *library){ | |
time_t curr_time = time(NULL); | |
for(uint32_t i = 0; i < library->lends_cnt; i += 1){ | |
if((intmax_t)library->lends[i].returning - (intmax_t)curr_time < 0) | |
printf("Vartotojo %d pasiskolinta %d knyga jau turėjo būti " | |
"grąžinta\n", library->lends[i].user_id, | |
library->lends[i].book_id); | |
else if((intmax_t)library->lends[i].returning - (intmax_t)curr_time < 86400) | |
printf("Vartotojo %d pasiskolinta %d knyga turi būti grąžinta " | |
"šiandien\n", library->lends[i].user_id, | |
library->lends[i].book_id); | |
} | |
printf("Visi pranešimai išspausdinti\n"); | |
} | |
int try_init(int32_t argc, char **argv){ | |
if(argc < 2) return 0; | |
for(uint32_t i = 0; i < argc; i += 1) | |
if(strcmp("init", argv[i]) == 0){ | |
FILE *in; | |
in = fopen("users", "w"); | |
fprintf(in, "0\n"); | |
fclose(in); | |
in = fopen("books", "w"); | |
fprintf(in, "0\n"); | |
fclose(in); | |
in = fopen("lends", "w"); | |
fprintf(in, "0\n"); | |
fclose(in); | |
return 1; | |
} | |
return 0; | |
} | |
int main(int32_t argc, char **argv){ | |
if(try_init(argc, argv)) return 0; | |
lib_t library; | |
if(!load_data(&library)){ | |
printf("Nepavyko įkelti bibliotekos duomenų, paleiskite " | |
"`./biblioteka init`.\n"); | |
return 1; | |
} | |
int running = 1; | |
while(running){ | |
switch(menu()){ | |
case 1: | |
switch(book_menu()){ | |
case 1: | |
print_book_table(&library); | |
break; | |
case 2: | |
prev_book(&library); | |
break; | |
case 3: | |
new_book(&library); | |
dump_data(&library); | |
break; | |
default: | |
change_book(&library); | |
dump_data(&library); | |
break; | |
} | |
break; | |
case 2: | |
switch(user_menu()){ | |
case 1: | |
print_user_table(&library); | |
break; | |
case 2: | |
prev_user(&library); | |
break; | |
case 3: | |
new_user(&library); | |
dump_data(&library); | |
break; | |
case 4: | |
change_user(&library); | |
dump_data(&library); | |
break; | |
default: | |
break; | |
} | |
break; | |
case 3: | |
notifications(&library); | |
break; | |
case 4: | |
give_a_book(&library); | |
break; | |
case 5: | |
running = 0; | |
break; | |
default: | |
break; | |
} | |
} | |
// Save data | |
dump_data(&library); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <inttypes.h> | |
#include <ctype.h> | |
typedef struct quest { | |
char question[256]; | |
char answers[26][256]; | |
uint32_t answ_count; | |
uint32_t correct; | |
} quest_t; | |
typedef struct answer { | |
uint32_t answ; | |
quest_t *question; | |
} answer_t; | |
typedef struct game { | |
quest_t questions[256]; | |
uint32_t quest_cnt; | |
uint32_t wrong_answer_cnt; | |
answer_t wrong_answers[256]; | |
} game_t; | |
uint32_t read_questions(quest_t *questions){ | |
FILE *in = fopen("data", "r"); | |
char tmp[1024]; | |
uint32_t data_size = 0; | |
for(uint32_t i = 0; !feof(in); i += 1){ | |
data_size = i; | |
// Read how much answers we have and which one is correct | |
fgets(tmp, 1023, in); | |
sscanf(tmp, "%d %d", &questions[i].answ_count, &questions[i].correct); | |
// Read the question | |
fgets(questions[i].question, 1023, in); | |
// Read the answers | |
for(uint32_t y = 0; y < questions[i].answ_count; y += 1) | |
fgets(questions[i].answers[y], 1023, in); | |
} | |
fclose(in); | |
return data_size; | |
} | |
uint32_t get_numb(uint32_t min, uint32_t max, const char *lbl){ | |
uint32_t item = 0; | |
char input[20]; | |
while(item < min || item > max){ | |
if(lbl){ | |
printf("%s>> ", lbl); | |
}else{ | |
printf(">> "); | |
} | |
fgets(input, 20, stdin); | |
sscanf(input, "%"SCNu32, &item); | |
} | |
return item; | |
} | |
int main(void){ | |
game_t game; | |
game.quest_cnt = read_questions(game.questions); | |
for(uint32_t i = 0; i < game.quest_cnt; i += 1){ | |
quest_t *question = game.questions + i; | |
printf("%s", question->question); | |
for(uint32_t i = 0; i < question->answ_count; i += 1){ | |
printf("%"PRIu32": %s", i + 1, question->answers[i]); | |
} | |
uint32_t answ = get_numb(1, question->answ_count, NULL); | |
if(answ != question->correct){ | |
game.wrong_answers[game.wrong_answer_cnt].answ = answ; | |
game.wrong_answers[game.wrong_answer_cnt].question = question; | |
game.wrong_answer_cnt += 1; | |
} | |
} | |
// Quit if all answers were correct | |
if(!game.wrong_answer_cnt){ | |
printf("Sveikiname! Į visus klausimus atsakėte teisingai!\n"); | |
return 0; | |
} | |
printf("Iš %"PRIu32" duotų klausimų %"PRIu32" atsakyti neteisingai\n" | |
"Ar norite peržiūrėti blogus atsakymus? [t/n]>> ", | |
game.quest_cnt, game.wrong_answer_cnt); | |
char choice; | |
while((choice = toupper(fgetc(stdin)))) | |
if(choice == 'T' || choice == 'N') break; | |
if(choice == 'T'){ | |
for(uint32_t i = 0; i < game.wrong_answer_cnt; i += 1){ | |
quest_t *question = game.wrong_answers[i].question; | |
printf("--------------------\n"); | |
printf("%s", question->question); | |
printf("Jūsų atsakymas buvo %"PRIu32": %s" | |
"Teisingas atsakymas yra %"PRIu32": %s", | |
game.wrong_answers[i].answ, | |
question->answers[game.wrong_answers[i].answ - 1], | |
question->correct, | |
question->answers[question->correct - 1]); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment