Skip to content

Instantly share code, notes, and snippets.

@nagisa
Created February 8, 2013 10:54
Show Gist options
  • Save nagisa/4738115 to your computer and use it in GitHub Desktop.
Save nagisa/4738115 to your computer and use it in GitHub Desktop.
#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;
}
#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