Last active
February 18, 2019 00:08
-
-
Save LionZXY/784a1e190c602dd3fcc865ea64f130ad to your computer and use it in GitHub Desktop.
This file contains 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> | |
#define __MAX_SIZE 256 // Директива прекомплятора. Что это за страшные слова? Смотри: | |
/** | |
* Компилятор си он умный. Перед тем как компилировать код он проходиться по нему и выполняет специальный код (да-да, язык внутри языка) | |
* В данном случае это означает, что везде где написанно __MAX_SIZE компилятор заменит на 256 | |
*/ | |
typedef struct Book book; // Обьявляем что структура впринципе существует. | |
struct Book // Уже подробно описываем её и рассказываем что там внутри | |
{ | |
char ISBN[14]; // Строка (массив символов). Массив максимум 14 элементов - это означает, что ничего больше 14 символов мы положить не можем | |
// => Строка "1234567890123" поместиться, а вот уже "12345678901234" нет (13 символов + ноль в конце) | |
char Author[__MAX_SIZE]; // Это строка (автор, в данном случае). Благодаря доброму (а как иначе, он же няшка) компилятору эта строчка будет выглядеть так: | |
// char Author[256]; | |
char Title[__MAX_SIZE]; // Строка (название книги) | |
// char Title[256]; | |
int All; // Целое число. Всего сколько книг | |
int Free; // Сколько книг доступно | |
}; | |
typedef struct Student student; // Обьявляем что структура впринципе существует. | |
struct Student // Уже подробно описываем её и рассказываем что там внутри | |
{ | |
char ID[7]; // ОГО! Тут уже ограничение на 7 символов! Вот это уже серьезно. Значит "1234567" уже не вместиться | |
char FamilyName[__MAX_SIZE]; | |
// Ну ты уже понял, да? | |
char Name[__MAX_SIZE]; | |
char FatherName[__MAX_SIZE]; | |
char Faculty[3]; // Тут максимум может вместиться "ИУ". "ИБМ" недостойны места в этой божественной программе. | |
char Specialist[__MAX_SIZE]; | |
}; | |
typedef struct User user; // Ну ты уже понял, да? | |
struct User // Ну ты уже понял, да? | |
{ | |
char Username[__MAX_SIZE]; | |
char Password[__MAX_SIZE]; | |
int ADbook; // Это целочисленное значение. В нем содержиться права на чтение и запись книги (доступ к меню книг) //TODO узнать значение | |
int ADstudent; // Это целочисленное значение. В нем содержиться права на чтение и запись студента (доступ к меню студента) //TODO узнать значение | |
}; | |
/** | |
* Переменные - это одна из самых важных частей в програмировании | |
* Это область в памяти, куда можно что-то складывать и доставать. | |
* От того ЧЕГО туда можно складывать зависит первая часть строки (book), а от того как переменная будет называться, вторая (Books). | |
* Итого, строка: | |
* bool Books; | |
* Обьявит переменную book с именем Books. Мы можем обращаться к этой переменной, например, так: cout << Books; | |
* Однако, ты уже заметил, что там еще есть [] вконце. Это значит, что мы обьявили массив. Это значит МНОГО переменных. Кхм, не много, а ровно __MAX_SIZE (помнишь я рассказывал тебе про прекомпилятор?) | |
* Обращаться к такой переменной можно, например, так: Books[1] - обращение ко второму элементу массива | |
* Этому | |
* Books: | BOOK1 | BOOK2 | BOOK3 | ... | |
**/ | |
book Books[__MAX_SIZE]; // Вот это уже интересно. Это ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ! Как только твоя программа загрузиться (Не запуститься! Загрузиться (до вызова метода int main()) это значение будет проинициализированна (выделиться память под неё) | |
student Students[__MAX_SIZE]; | |
user Users[__MAX_SIZE]; | |
int check; | |
//^ Ну все выше ты понял, да? | |
void swap(int *, int *); | |
void strswap(char a[], char b[]); | |
//Part: Book | |
/** | |
* Все методы про книги. Тут есть один подвох. В C нельзя делать методы с одинаковыми именами (иначе как компилятор поймет чего ты хочешь вызвать?) | |
* Поэтому имена такие длинные. | |
* Существует два типа называния переменных CamelCase (каждое слово с большой буквы) и вот эта херовина: part_1_book | |
* Оба варианта заслуживают признания, но лучше использовать какой-то один | |
**/ | |
void part_1_book(); | |
/** | |
* Мы впервые встретились с указателем! | |
* Итак, указатель - эта такая штука, которая УКАЗЫВАЕТ на область памяти в которой храниться переменная, а не на саму переменную (в отличии от переменной) | |
* int * test1; <- Указатель! | |
* int test2; <- Переменная! | |
* Еще по указателю не обязательно может быть одна переменная, может быть и больше. | |
* САМОЕ ГЛАВНОЕ ЗАПОМНИТЬ! Указатель УКАЗЫВАЕТ на область памяти | |
*/ | |
int readBook(const char *filename); | |
// WARNING! В этот метод можно положить строку меньше 14 символов | |
int comparingISBN(char a[14]); | |
void addingNewBook(const char *filename); | |
void searchingBook(const char *filename); | |
void deletingBook(const char *filename); | |
void sortingBook(const char *filename); | |
//Part: Student | |
// Ну ты понял, да? | |
void part_1_student(); | |
int readStudent(const char *filename); | |
int comparingID(char a[7]); | |
void addingNewStudent(const char *filename); | |
void deletingStudent(const char *filename); | |
void editingStudent(const char *filename); | |
void searchingStudent(const char *filename); | |
//Part: User | |
void part_2_user(); | |
int readUser(const char *filename); | |
int checkUser(const char *filename); | |
// Главная точка входа в программу! | |
int main(int argc /* количество аргументов командной строки */, | |
char **argv /* Очень запутанная структура. Указатель на указатели (на область памяти где храняться указатели) */) { | |
check = checkUser("user.csv"); | |
if (check == -1) { | |
printf("WRONG!!!"); | |
} else | |
part_2_user(); | |
return 0; | |
} | |
void part_1_book() { | |
int n = readBook("book.csv"); | |
if (n == -1) { | |
printf("ERROR #1: empty file"); | |
} else { | |
int x; | |
printf("MENU BOOK:"); | |
printf("\n0) Main Menu"); | |
printf("\n1) Add"); | |
printf("\n2) Delete"); | |
printf("\n3) Search"); | |
printf("\n4) Show"); | |
printf("\n5) Esc"); | |
printf("\nYou want:"); | |
scanf("%d", &x); // Вводим x (& - значит получить указатель на переменную) | |
fflush(stdin); | |
switch (x) { | |
case 0: { | |
part_2_user(); | |
break; | |
} | |
case 1: { | |
if (Users[check].ADbook == 1) { | |
addingNewBook("book.csv"); | |
break; | |
} else { | |
printf("You can't\n"); | |
part_2_user(); | |
} | |
} | |
case 2: { | |
if (Users[check].ADbook == 1) { | |
deletingBook("book.csv"); | |
break; | |
} else { | |
printf("You can't\n"); | |
part_2_user(); | |
} | |
} | |
case 3: { | |
searchingBook("book.csv"); | |
break; | |
} | |
case 4: { | |
sortingBook("book.csv"); | |
break; | |
} | |
case 5: { | |
break; | |
} | |
default:; | |
} | |
} | |
} | |
void part_1_student() { | |
int n = readStudent("student.csv"); | |
if (n == -1) { | |
printf("ERROR #1: empty file"); | |
} else { | |
int x; | |
printf("MENU STUDENT:"); | |
printf("\n0) Main Menu"); | |
printf("\n1) Add"); | |
printf("\n2) Delete"); | |
printf("\n3) Edit"); | |
printf("\n4) Search"); | |
printf("\n5) Esc"); | |
printf("\nYou want:"); | |
scanf("%d", &x); | |
fflush(stdin); | |
switch (x) { | |
case 0: { | |
part_2_user(); | |
break; | |
} | |
case 1: { | |
if (Users[check].ADstudent == 1) { | |
addingNewStudent("student.csv"); | |
break; | |
} else { | |
printf("You can't\n"); | |
part_2_user(); | |
} | |
} | |
case 2: { | |
if (Users[check].ADstudent == 1) { | |
deletingStudent("student.csv"); | |
break; | |
} else { | |
printf("You can't\n"); | |
part_2_user(); | |
} | |
} | |
case 4: { | |
searchingStudent("student.csv"); | |
break; | |
} | |
case 3: { | |
if (Users[check].ADstudent == 1) { | |
editingStudent("student.csv"); | |
break; | |
} else { | |
printf("You can't\n"); | |
part_2_user(); | |
} | |
} | |
case 5: { | |
break; | |
} | |
default:; | |
} | |
} | |
} | |
void part_2_user() { | |
if (check != -1) { | |
int n = readUser("user.csv"); | |
if (n == -1) { | |
printf("ERROR #1: empty file"); | |
} else { | |
int x; | |
printf("MENU:"); | |
printf("\n1) Book"); | |
printf("\n2) Student"); | |
printf("\nYou want:"); | |
scanf("%d", &x); | |
fflush(stdin); | |
switch (x) { | |
case 1: { | |
part_1_book(); | |
break; | |
} | |
case 2: { | |
part_1_student(); | |
break; | |
} | |
default:; | |
} | |
} | |
} else | |
printf("WRONG"); | |
} | |
int readBook(const char *filename) { | |
FILE *fs = fopen(filename, "r+"); // Открываем файл для чтения | |
if (!fs) | |
return -1; | |
//Read file | |
rewind(fs); // Перематываем файл назад | |
char tmp[__MAX_SIZE]; | |
int total = 0; | |
while (fgets(tmp, __MAX_SIZE, fs)) { | |
/** | |
* Тут очень интересная штука | |
* [^,] - регулярное выражение, которое ищет строку заканчивающуюся на запятую | |
* А %d - это выражение, которое указывает, что здесь мы ожидаем целове число | |
**/ | |
sscanf(tmp, "%[^,], %[^,], %[^,], %d , %d", Books[total].ISBN, Books[total].Author, Books[total].Title, | |
&Books[total].All, &Books[total].Free); | |
total++; | |
} | |
return total; | |
} | |
int comparingISBN(char a[14]) //compare which new ISBN existed or not | |
{ | |
int i; | |
int temp = -1; | |
for (i = 0; i < readBook("book.csv"); i++) { | |
if (strcmp(a, Books[i].ISBN) == 0) // Сравнение строк | |
temp = i; | |
} | |
return temp; | |
} | |
//Add | |
void addingNewBook(const char *filename) { | |
FILE *fs = fopen(filename, "a+"); | |
book newbook; | |
printf("ISBN:"); | |
gets(newbook.ISBN); | |
if (comparingISBN(newbook.ISBN) != -1) | |
fclose(fs); | |
else { | |
printf("\nAuthor's name:"); | |
gets(newbook.Author); | |
printf("\nBook's title:"); | |
gets(newbook.Title); | |
printf("\nAll:"); | |
scanf("%d", &newbook.All); | |
printf("\nFree:"); | |
scanf("%d", &newbook.Free); | |
fprintf(fs, "%s, %s, %s, %d, %d\n", newbook.ISBN, newbook.Author, newbook.Title, newbook.All, | |
newbook.Free); // Вывод в файл | |
fclose(fs); | |
} | |
} | |
//Search | |
void searchingBook(const char *filename) { | |
FILE *fs = fopen(filename, "r"); | |
char searchitem[14]; | |
rewind(fs); | |
printf("ISBN:"); | |
gets(searchitem); | |
int n = comparingISBN(searchitem); | |
if (n == -1) | |
fclose(fs); | |
else { | |
printf("%s, %s, %s, %d, %d\n", Books[n].ISBN, Books[n].Author, Books[n].Title, Books[n].All, Books[n].Free); | |
fclose(fs); | |
} | |
} | |
//Delete | |
void deletingBook(const char *filename) { | |
FILE *fs; | |
char deleteitem[__MAX_SIZE]; | |
printf("ISBN:"); | |
gets(deleteitem); | |
fs = fopen(filename, "r"); | |
rewind(fs); | |
int k = comparingISBN(deleteitem); | |
int n = readBook(filename); | |
fclose(fs); | |
if (k != -1) { | |
fs = fopen(filename, "w"); | |
int i; | |
for (i = 0; i < n; i++) { | |
if (i != k) | |
//printf("%s, %s, %s, %d, %d\n", Books[i].ISBN, Books[i].Author, Books[i].Title, Books[i].All, Books[i].Free); | |
fprintf(fs, "%s, %s, %s, %d, %d\n", Books[i].ISBN, Books[i].Author, Books[i].Title, Books[i].All, | |
Books[i].Free); | |
} | |
fclose(fs); | |
} else | |
printf(" "); | |
} | |
//Edit | |
void swap(int *a, int *b) { | |
int temp; | |
temp = *b; | |
*b = *a; | |
*a = temp; | |
} | |
void strswap(char a[], char b[]) { | |
char tmp[__MAX_SIZE]; | |
strcpy(tmp, b); | |
strcpy(b, a); | |
strcpy(a, tmp); | |
} | |
void sortingBook(const char *filename) { | |
FILE *fs = fopen(filename, "r"); | |
int i, j; | |
int n = readBook("book.csv"); | |
for (i = 0; i < n; i++) { | |
for (j = i + 1; j < n; j++) { | |
if (strcmp(Books[i].ISBN, Books[j].ISBN) < 0) { | |
strswap(Books[i].ISBN, Books[j].ISBN); | |
strswap(Books[i].Author, Books[j].Author); | |
strswap(Books[i].Title, Books[j].Title); | |
swap(&Books[i].All, &Books[j].All); | |
swap(&Books[i].Free, &Books[j].Free); | |
} | |
} | |
} | |
for (i = 0; i < n; i++) | |
printf("%s | %s | %s | %d | %d\n", Books[i].ISBN, Books[i].Author, Books[i].Title, Books[i].All, Books[i].Free); | |
} | |
//Student File | |
int readStudent(const char *filename) { | |
FILE *fs = fopen(filename, "r+"); | |
if (!fs) | |
return -1; | |
//Read file | |
rewind(fs); | |
char tmp[__MAX_SIZE]; | |
int total = 0; | |
while (fgets(tmp, __MAX_SIZE, fs)) { | |
sscanf(tmp, "%[^,], %[^,], %[^,], %[^,], %[^,], %[^\n]", Students[total].ID, Students[total].FamilyName, | |
Students[total].Name, Students[total].FatherName, Students[total].Faculty, Students[total].Specialist); | |
total++; | |
} | |
return total; | |
} | |
int comparingID(char a[7]) //compare which new ID existed or not | |
{ | |
int i; | |
int temp = -1; | |
for (i = 0; i < readStudent("student.csv"); i++) { | |
if (strcmp(a, Students[i].ID) == 0) | |
temp = i; | |
} | |
return temp; | |
} | |
//Add | |
void addingNewStudent(const char *filename) { | |
FILE *fs = fopen(filename, "a+"); | |
student newstudent; | |
printf("ID:"); | |
gets(newstudent.ID); | |
if (comparingID(newstudent.ID) != -1) | |
fclose(fs); | |
else { | |
printf("Family Name:"); | |
gets(newstudent.FamilyName); | |
printf("Name:"); | |
gets(newstudent.Name); | |
printf("Father Name:"); | |
gets(newstudent.FatherName); | |
printf("Faculty:"); | |
gets(newstudent.Faculty); | |
printf("Specialist:"); | |
gets(newstudent.Specialist); | |
fprintf(fs, "%s, %s, %s, %s, %s, %s\n", newstudent.ID, newstudent.FamilyName, newstudent.Name, | |
newstudent.FatherName, newstudent.Faculty, newstudent.Specialist); | |
fclose(fs); | |
} | |
} | |
//Delete | |
void deletingStudent(const char *filename) { | |
FILE *fs; | |
char deleteitem[__MAX_SIZE]; | |
printf("ID:"); | |
gets(deleteitem); | |
fs = fopen(filename, "r"); | |
rewind(fs); | |
int k = comparingID(deleteitem); | |
int n = readStudent(filename); | |
fclose(fs); | |
if (k != -1) { | |
fs = fopen(filename, "w"); | |
int i; | |
for (i = 0; i < n; i++) { | |
if (i != k) | |
fprintf(fs, "%s, %s, %s, %s, %s, %s\n", Students[i].ID, Students[i].FamilyName, Students[i].Name, | |
Students[i].FatherName, Students[i].Faculty, Students[i].Specialist); | |
} | |
fclose(fs); | |
} else | |
printf(" "); | |
} | |
//Edit | |
void editingStudent(const char *filename) { | |
FILE *fs; | |
student edititem; | |
printf("ID:"); | |
gets(edititem.ID); | |
fs = fopen(filename, "r"); | |
rewind(fs); | |
int k = comparingID(edititem.ID); | |
int n = readStudent(filename); | |
fclose(fs); | |
if (k != -1) { | |
printf("Family Name:"); | |
gets(edititem.FamilyName); | |
printf("Name:"); | |
gets(edititem.Name); | |
printf("Father Name:"); | |
gets(edititem.FatherName); | |
printf("Faculty:"); | |
gets(edititem.Faculty); | |
printf("Specialist:"); | |
gets(edititem.Specialist); | |
fs = fopen(filename, "w"); | |
int i; | |
for (i = 0; i < n; i++) { | |
if (i != k) | |
fprintf(fs, "%s, %s, %s, %s, %s, %s\n", Students[i].ID, Students[i].FamilyName, Students[i].Name, | |
Students[i].FatherName, Students[i].Faculty, Students[i].Specialist); | |
} | |
fprintf(fs, "%s, %s, %s, %s, %s, %s\n", edititem.ID, edititem.FamilyName, edititem.Name, edititem.FatherName, | |
edititem.Faculty, edititem.Specialist); | |
fclose(fs); | |
} else | |
printf(" "); | |
} | |
//Search | |
void searchingStudent(const char *filename) { | |
FILE *fs = fopen(filename, "r"); | |
char searchitem[7]; | |
rewind(fs); | |
printf("ID:"); | |
getchar(); | |
gets(searchitem); | |
int n = comparingID(searchitem); | |
if (n == -1) | |
fclose(fs); | |
else { | |
printf("%s, %s, %s, %s, %s, %s\n", Students[n].ID, Students[n].FamilyName, Students[n].Name, | |
Students[n].FatherName, Students[n].Faculty, Students[n].Specialist); | |
fclose(fs); | |
} | |
} | |
int readUser(const char *filename) { | |
FILE *fs = fopen(filename, "r+"); // Открыть файл для чтения | |
if (!fs) | |
return -1; | |
//Read file | |
rewind(fs); // Перемотка на начало файла | |
char tmp[__MAX_SIZE]; | |
int total = 0; | |
while (fgets(tmp, __MAX_SIZE, fs)) { | |
sscanf(tmp, "%[^,], %[^,], %d , %d", Users[total].Username, Users[total].Password, &Users[total].ADbook, | |
&Users[total].ADstudent); | |
total++; | |
} | |
return total; | |
} | |
//Check | |
int checkUser(const char *filename) { | |
FILE *fs = fopen(filename, "r"); // Открываем файл. Строка "r" говорит о том, что мы его открываем на запись. | |
char login[__MAX_SIZE]; | |
char password[__MAX_SIZE]; | |
printf("Login:"); | |
gets(login); // Читаем строку | |
printf("Password:"); | |
gets(password); // Читаем пароль | |
rewind(fs); // Перемотка на начало файла | |
int n = readUser("user.csv"); | |
int i; | |
int tp = -1; | |
for (i = 0; i < n; i++) { | |
if (strcmp(login, Users[i].Username) == 0 /* сравниваем строки */ && strcmp(password, Users[i].Password) == 0) { | |
tp = i; | |
} | |
} | |
if (tp >= 0 && tp < n) | |
return tp; | |
else | |
return -1; | |
// Он забыл закрыть файл!!! Сволочь! Растрелять! Это баг, теперь этот файл будет всегда открыт, пока живет программа | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment