Previous review
Custom precon h,kernel_list.h. sysbrowse has three header files, which complete the pre configuration of the core header file, the operation of the core header file and the functions of the information browsing system.
1, This goal
Build the relevant operations of file data stream reading and writing, so as to save the student information table and system settings (storage path, console color, etc.)
GitHub: https://github.com/ITchujian/StudentManagementSystem_2022_C
Note: in order to share the experience of this development, I will put the analysis process and code writing process in the development record in the form of words and pictures, but I will not explain or explain some very basic actions.
Current position: [1.4 C case] please write a thousand line student management system with me in C language
Jump:
- [1C case] please write a thousand line student management system with me in C language
- [1.1 case C] please write a thousand lines student management system with me in C language
- [1.2 case C] please write a thousand lines student management system with me in C language
- [1.3 case C] please write a thousand line student management system with me in C language
- [1.5 C case] please write a thousand lines student management system with me in C language
- [1.6 case C] please write a thousand line student management system with me in C language
2, Development record
Step 1
The old rule is to create a file called sysdoc H header file, and contains the following custom header file kernel_list.h.
#include "kernel_list.h"
Then, we will create a folder named SMSdir under the currently running folder to store student information table and system settings.
Step 2
Create a function called createFolder. Its function is to create multi-level directories.
Status createFolder(char* path) { char folder_path[128]; sprintf(folder_path, "mkdir %s", path); if (_access(path, 0) == -1) { system(folder_path); } return OK; }
Step 3
One of the major problems we face is how to store our data and structures. We might as well use data stream binary.
Write binary stream:
Status writeFile(char* path, void* struct_s, int s_size, int length) { FILE* fp; fopen_s(&fp, path, "wb+"); if (fp != 0) { fwrite(struct_s, s_size, length, fp); fclose(fp); return OK; } else return INFEASIBLE; }
Read binary stream:
Status readFile(char* path, void* struct_s, int s_size, int length) { FILE* fp; fopen_s(&fp, path, "rb+"); if (fp != 0) { fread(struct_s, s_size, length, fp); fclose(fp); return OK; } else return INFEASIBLE; }
Step 4
What we need, the students are in the ElemType structure, so we should store this structure. We might as well name this file: students bin. The system settings are placed in: config Bin, which is loaded first, will load students Bin storage path, backup path, and console color value, some people wonder. I'm in preconf H is clearly defined as follows:
typedef struct { char file_path[128]; char backup_path[128]; char list_path[128]; char sys_color[32]; } SysConfig; SysConfig config_bin = {};
backup_ The path is understandable. The backup path is the list_ What the hell is path?
list_ Of course, path is the storage path for storing the SqList structure. Explain why you need this storage path:
If our project runs like this: load config Bin → load students Bin → console output menu, and then according to the user's operation, suppose we do the operation of browsing all student information. This function is defined as follows:
Status putAllList(SqList* L) { int i = 0; printf("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"); printf("┃ full name Student number Gender Age language mathematics English average Total score ┃\n"); printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n"); while (i < L->length) { printf("┃ %-9s%-16d%-12s%-11d%-12.2f%-12.2f%-12.2f%-13.2f%-8.2f┃\n", (L->elem[i]).name, (L->elem[i]).num, (L->elem[i]).sex, (L->elem[i]).age, (L->elem[i]).score_literature, (L->elem[i]).score_math, (L->elem[i]).score_english, (L->elem[i]).average_score, (L->elem[i]).sum_score); ++i; } printf("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n"); return OK; }
In other words, if we run in the above way, our L - > length is only initialized by InitList(SqList* L), and its corresponding value is 0, and our subsequent behavior, operation and function implementation are based on this value, no matter how you load it, even though students The bin file stores tens of thousands of student information, but still can't print out one. Remember, our core is the linear table SqList, and it's not feasible to separate from the variables in it. So let's optimize our operation logic:
Load config Bin → load list_path.bin → load students Bin → console output menu → user operation
Now is the correct logic, otherwise you will always operate a linear table with a length of 0, which is meaningless.
These are the problems I ignored when developing the project. After I hit the breakpoint, I found that l - > length has always been 0. It's really careless 😒.
Step 5
Write the above loading methods in turn.
Status loadConfig(void) { char dir_path[] = ".\\SMSdir"; createFolder(dir_path); char config_path[128]; sprintf(config_path, "%s\\config.bin", dir_path); readFile(config_path, &config_bin, sizeof(SysConfig), 4); system(config_bin.sys_color); return OK; }
Then load the list_path.bin
Status loadList(SqList* L) { readFile(config_bin.list_path, L, sizeof(SqList), 3); return OK; }
Finally, load students bin
Status loadStu(SqList* L) { readFile(config_bin.file_path, L->elem, sizeof(ElemType), L->length); return OK; }
sysdoc.h の complete code:
#pragma once /********************************************************************* * Reprint please indicate the source * @FileName sysdoc.h * @Description File read and write operations related files * @History * version author data introduction and operations * 1.0 Initial view: create on January 23, 2022 * *** *** ****-**-** ******* */ #include "kernel_list.h" /********************************************************************* * @chujian(cn) Import custom header file * @chujian(en) Import custom header files */ Status setMenu(void) { printf("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"); printf("┃ [[Auxiliary] system setting ┃\n"); printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n"); printf("┃ Warning in general, I do not recommend that you change settings other than 3 ┃\n"); printf("┃Please select an action: ┃\n"); printf("┃ 1 > Change storage path ┃\n"); printf("┃ 2 > Change backup path ┃\n"); printf("┃ 3 > Set front background color ┃\n"); printf("┃ 4 > [dangerous]Kernel list path ┃\n"); printf("┃ 0 > Return to main system ┃\n"); printf("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n"); printf("\nINPUT:"); return OK; } /********************************************************************* * @chujian(cn) System setting interface * @chujian(en) System setting interface */ Status colorMenu(void) { printf("Color reference table:\n"); printf("0 = black 8 = grey\n"); printf("1 = blue 9 = Light blue\n"); printf("2 = green A = Light green\n"); printf("3 = Light green B = Light green\n"); printf("4 = gules C = Light red\n"); printf("5 = purple D = lavender\n"); printf("6 = yellow E = canary yellow\n"); printf("7 = white F = Bright white\n"); return OK; } /********************************************************************* * @chujian(cn) Corresponding to the third item in system settings * @chujian(en) Corresponds to the third item in the system settings */ Status createFolder(char* path) { char folder_path[128]; sprintf(folder_path, "mkdir %s", path); if (_access(path, 0) == -1) { system(folder_path); } return OK; } /********************************************************************* * @chujian(cn) Create directory * @chujian(en) Create a directory */ Status writeFile(char* path, void* struct_s, int s_size, int length) { FILE* fp; fopen_s(&fp, path, "wb+"); if (fp != 0) { fwrite(struct_s, s_size, length, fp); fclose(fp); return OK; } else return INFEASIBLE; } /********************************************************************* * @chujian(cn) Write data stream to bin file * @chujian(en) Write data stream to .bin file */ Status readFile(char* path, void* struct_s, int s_size, int length) { FILE* fp; fopen_s(&fp, path, "rb+"); if (fp != 0) { fread(struct_s, s_size, length, fp); fclose(fp); return OK; } else return INFEASIBLE; } /********************************************************************* * @chujian(cn) From Read data stream from bin file * @chujian(en) Read data stream from .bin file */ Status loadConfig(void) { char dir_path[] = ".\\SMSdir"; createFolder(dir_path); char config_path[128]; sprintf(config_path, "%s\\config.bin", dir_path); readFile(config_path, &config_bin, sizeof(SysConfig), 4); system(config_bin.sys_color); return OK; } /********************************************************************* * @chujian(cn) Initialize config Bin file * @chujian(en) Initialize the configuration config.bin file */ Status loadList(SqList* L) { readFile(config_bin.list_path, L, sizeof(SqList), 3); return OK; } /********************************************************************* * @chujian(cn) Load the data except the corresponding elem in the kernel linear table * @chujian(en) Load the data in the kernel linear table except the student structure */ Status loadStu(SqList* L) { readFile(config_bin.file_path, L->elem, sizeof(ElemType), L->length); return OK; } /********************************************************************* * @chujian(cn) Load the last saved student information table * @chujian(en) Load the last saved student information sheet */