C language homework ------ "student achievement management system" creation record

Posted by Gorf on Wed, 29 Dec 2021 08:51:46 +0100

Last semester of freshman year, the C language class was almost over, and time passed quickly (although I didn't listen much in class). After talking about the pointer, the teacher assigned a big homework. Let's get a student performance management system, as shown below:

Huh? C file? What is the C file? I haven't heard of it. The first feeling was G, but I didn't care much about it when I finished the pointer and said that there was still more than a month before the end of the term. After all, the teacher didn't talk about the chapter of C document at that time. If not, it doesn't matter. It shouldn't be too difficult. I thought: just use a structure

Good guy, after I finished the pointer, a good friend asked me some small questions about the pointer. finished, I found that I didn't seem to be very good (I didn't laugh), so I quickly read Master Tan Haoqiang's C programming. That's right! It's the red book you used. After reading it for a while, guess what? Hey? I can't understand it. Ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha That chapter. Good guy, I recognize every word, but I don't recognize it together (I didn't laugh). Inner os: it's really G after this big homework.

However, at this time, the book kings in the school began to do big homework. Looking at them, they have almost made more than two 00 lines. It's too strong and I'm too good. Inner os: No, I have to start. Then one night I was in the training room holding C programming and browsing CSDN. After one night, I found that reading was not as inspired as searching "student achievement management system" directly on CSDN (I didn't laugh). I only wrote:

#include <bits/stdc++.h>

using namespace std ;

int main(){
	
	return 0 ; 
}

Ah, no, how is C + +, what is this universal head [doge], start again:

#inlcude <stdio.h>

int main(){
	
	
	return 0 ; 
}

It's right for the stomach

I can't say I won't do anything all night. I still know fopen, fscanf and fprintf all night

OK, we won't, printf we will!! So the following main function comes out

int main() {
	int num ;
	printf("------------------------------------\n") ;
	printf("************************************\n") ;
	printf("*     Welcome to the student achievement management system     *\n") ;
	printf("*  1.Add student records;                 *\n") ;
	printf("*  2.Delete student record;                 *\n") ;
	printf("*  3.Modify student records;                 *\n") ;
	printf("*  4.Query student information;                 *\n") ;
	printf("*  5.Clear all data;                 *\n") ;
	printf("*  6.Keep student records;                 *\n") ;
	printf("*  0.sign out                          *\n") ;
	printf("************************************\n") ;
	printf("------------------------------------\n\n") ;
	printf("Please enter your action:") ;
	while (scanf("%d", &num) != EOF ) {
		if (num == 1) {				//Add student records
		} else if (num == 2) {		//Delete student record
		} else if (num == 3) {		//Modify student records
		} else if (num == 4) {		//Query student information
		} else if (num == 5) {		//wipe data 
		} else if (num == 6) {
		} else if (num == 0) {			//sign out
		} else {
			printf("****Wrong! Please enter 0 - 6 The number within!****") ;
		}
		printf("\n") ;
		printf("Please enter your action:") ;
	}
	return 0 ;
}

Don't look down on the main function. We don't know how many times we have read this code

By the way, there are some global variables

int nn ;				//Record a total of n - 1 students
int pos ;				//Record the saved data

nn here is used to record the total number of students. pos is used to assist the output function later

Let's add another structure student

const int N = 50 ; 
struct student {
	char name[N] ; //name
	char num[N] ;  // Student number
	char sex[N] ;
	char math[N], eng[N], cpp[N] ;
} stu[N];

Why do I use char type? First of all, the name and gender must be char type, so the score can use int, but this is pure C! So many types need different placeholders, so we might as well change them all to char type, so we can only use% s in the future

OK, let's first look at keeping student records. After a night's understanding, I'm sure the first choice is fprintf, which is printed directly into the document, simple, rough and clear. I mean, the previous junk code can't be found. It's probably a format of printing directly into the file

//Wei Yuxiang, male, 202111181234 100 

The output is also very simple

FILE *fp ;
	char ch ;
	fp = fopen("data.txt", "r") ;
while ((ch = fgetc(fp)) != EOF) {
			putchar(ch) ;
		}

In this way, the content in the document can be directly output, which is very rough. But! Did you find a problem? Yes! This output is too ugly! Can you stand it? I can't stand it anyway, so it's like this after my output changes

 ----------------------------------
|Wei Yuxiang|male|202111181234|100|100|100|
 ----------------------------------

How did I change it? You can't imagine that I saved the content directly into the document for the convenience of output, Then there is another problem: some people's names are three words, some people's names are two words, some people's grades are three digits, and some people's grades are two digits (although it's almost impossible to be a single digit, we still consider it). How to ensure the output list specification when there are several horizontal bars on the top and there are several spaces in the content? This is a simple output format, which must not be difficult for us, right? I'm also a person who has passed the mid-term exam [doge] . So! How to write the code? Since there are so few cases, we might as well discuss the classification directly! So there is the following stupid Code:

FILE *fp ;
	fp = fopen("data.txt", "a") ;
	for (int i = 0 ; i < nn ; i ++) {
		int t = 52 ;
		fprintf(fp, " ") ;
		while (t --) {
			fprintf(fp, "-") ;
		}
		fprintf(fp, "\n") ;
		if (strlen(stu[i].name ) == 4) {
			fprintf(fp, "| %s |", stu[i].name ) ;
		} else
			fprintf(fp, "|%s|", stu[i].name) ;
		fprintf(fp, " %s |%s", stu[i].sex, stu[i].num ) ;
		if (strlen(stu[i].math ) == 1) {												// mathematics
			fprintf(fp, "|   %s    |", stu[i].math ) ;
		} else if (strlen(stu[i].math ) == 2) {
			fprintf(fp, "|  %s    |", stu[i].math ) ;
		} else if (strlen(stu[i].math ) == 3) {
			fprintf(fp, "|  %s   |", stu[i].math);
		}
		if (strlen(stu[i].eng ) == 1) {													//English
			fprintf(fp, "   %s    |", stu[i].eng ) ;
		} else if (strlen(stu[i].eng ) == 2) {
			fprintf(fp, "  %s    |", stu[i].eng ) ;
		} else if (strlen(stu[i].eng ) == 3) {
			fprintf(fp, "  %s   |", stu[i].eng);
		}
		if (strlen(stu[i].cpp ) == 1) {													//C language
			fprintf(fp, "    %s    |", stu[i].cpp ) ;
		} else if (strlen(stu[i].cpp ) == 2) {
			fprintf(fp, "   %s    |", stu[i].cpp ) ;
		} else if (strlen(stu[i].cpp ) == 3) {
			fprintf(fp, "   %s   |", stu[i].cpp);
		}
		fprintf(fp, "\n") ;
	}

Are you finished? After reading or lazy to see, it's OK to know that I'm a stupid ratio.

Then there is another problem. If you want the user to select a number operation in 1 or 2, if the user enters another number, if it is not processed, it may run successfully, but in more cases, we still need to use while

Adding student records is very simple. It's OK to operate directly with the structure. Saving data is nothing more than outputting the content to the C file, so adding some details of human-computer interaction becomes like this:

void insert() {		//Add student records
	char ch ;
	printf("Please enter the number of students you want to add(Enter zero to exit):") ;
	int t ;
	scanf("%d", &t) ;
	while (t < 0) {					//Ensure that the number entered is the correct number
		printf("****Please enter a number greater than zero or enter 0 to return to the previous operation!****\n") ;
		scanf("%d", &t) ;
	}
	int op ;
	if (t > 0) {
		while (t --) {
			int flag = 0;
			printf("Please enter the student's name gender student number math score English score    C language achievement\n") ;
			scanf("%s%s%s%s%s%s", stu[nn].name, stu[nn].sex, stu[nn].num, stu[nn].math, stu[nn].eng, stu[nn].cpp ) ;
			for (int i = 0 ; i < nn ; i ++) {			//Determine whether there is duplicate data
				int tmp = strcmp(stu[i].num, stu[nn].num ) ;
				if (tmp == 0) {
					printf("  *****Tips! The student already exists!*****  \n") ;
					printf("------>Continue to enter student information?<------\n") ;
					printf("     1.continue             2.sign out \n") ;
					scanf("%d", &op) ;
					-- nn ;
					if (op == 2) {
						flag = 1 ;
					} else if (op == 1)
						t ++ ;
				}
			}
			nn ++ ;
			if (flag == 1)
				break ;
		}
		printf("-------------Successfully added!------------\n") ;
		vis = 0 ;
	}
}

So how to refresh the data? There is a "w" operation in the C file fopen, which means to write the file. Writing the file will clear the existing data, so we only need fopen to clear the data

void fresh() {			//wipe data 
	printf("****Are you sure to clear all current data?****\n") ;
	printf("  1.determine                  2.cancel \n") ;
	int t ;
	scanf("%d", &t) ;
	if (t == 1) {
		FILE *fp ;
		char ch ;
		fp = fopen("data.txt", "w") ;
		printf("-------------Cleared successfully!------------\n") ;

	}
	nn = 0 ;      //initialization
	vis = 0 ;
}

So about the launch part, let's just simply ask users whether they want to quit? Then select 1 to confirm and 2 to cancel? Of course, it can't be so simple. We've all experienced word documents. When you want to close the current document, if you've done it before, this page will pop up:

Such a small detail that has helped me so many times, we have to add it to our management system! The processing method is also very simple, that is, define a global variable first

int vis ; // Used to determine whether the current data has been manipulated

In this way, we only need to add vis = 1 after all operations that may modify the data before saving (in fact, I added vis directly because I was lazy in the previous code segment), and then paste the code segment of the exit part

if (vis == 0) {
				printf("************Are you sure you want to exit?*************\n") ;
				printf("        1.determine            2.cancel\n") ;
				int op ;
				scanf("%d", &op) ;

				while (op != 1 && op != 2) {		//Ensure that the input data is legal
					printf("*********Tips! Please enter a valid operation!*********\n") ;
					scanf("%d", &op) ;
				}
				if (op == 1) {
					printf("*********Quit successfully, welcome to continue using next time!*********\n") ;
					break ;
				}
			} else {
				printf("*******Tips! The current data has not been saved. Do you want to save the data in the document?*******\n") ;
				printf("         1.preservation          2.Do not save           3.cancel      \n") ;
				int tmp ;
				scanf("%d", &tmp) ;
				while (tmp != 1 && tmp != 2 && tmp != 3) {
					printf("***********Wrong! Please enter a valid operation!***********\n") ;
					scanf("%d", &tmp) ;
				}
				if (tmp == 1) {
					save() ;
					printf("************Quit successfully, welcome to continue using next time!************\n") ;
					break ;
				} else if (tmp == 2) {
					printf("**********Quit successfully, welcome to continue using next time!*********\n") ;
					break ;
				}
			}

Well, I found a problem when running. When I add student records and save them, then I immediately access the student records. It has no output, that is, I didn't save them at that time. But when I close the program running box and click the program for access operation, it has output again! Seeing this, maybe the big guys understand. Remember what I said before? I didn't learn fclose! I didn't expect it! I didn't expect that, that is to say, when I saved the student records without fclose, it was equivalent to not saving, so I didn't output the content when I immediately accessed the content. For this problem, I asked elder martial brother

 

PS: this elder martial brother interned in a large factory, tql. Then it's almost OK to add fclose

In fact, by this point, our basic framework has been almost completed. However, one day I was walking on the road and thought again, if I had to complete the query and sorting, wouldn't it be particularly troublesome if I used fprintf and putchar(). On this issue, My roommate told me about the functions fwrite and fread (sure enough, it's a big loss not to read). After I learned these two functions: I'm super! This is easy to use, which is equivalent to completing more than half of the work directly with the structure. So how can we change it? To be honest, I don't feel comfortable with the more than 200 lines of code that have been written. Hey? Let's not change it at all, let's rewrite it directly! That's right , it took me almost two hours to rewrite the code again, add some small details such as "ensure that the input operation is legal", improve the output format, and add some return operations to improve the fault tolerance rate used by users, and the basic structure is completed. We won't post the code for modification and query, just find the structure location and output or modify it. Another problem is that if I manually launch the program and run the program again for query, the value of nn is 0, that is, we can't output well, then this problem can also be solved. My idea is to save nn separately in a file and directly obtain the value of nn from another file when running the program, At the same time, we can also pass in the structure array, so that we inherit the operation before the last end of the program

Code attached:

void renovate() {				//Record the value of n
	FILE *oper, *op ;			//Refresh override
	op = fopen("record.txt", "w") ;
	fclose(op) ;
	oper = fopen("record.txt", "wb") ;
	fwrite(&nn, sizeof(int), 1, oper) ;
	fclose(oper) ;
}

The updates in the main function are as follows:

FILE *judge ;
	char ch ;
	judge = fopen("record.txt", "r") ;		//Used to determine whether there is information in the file
	if ((ch = fgetc(judge)) != EOF) {
		FILE *ori ;
		ori = fopen("record.txt", "rb") ;
		fread(&nn, sizeof(int), 1, ori ) ;				//Chuan nn
		pos = nn ;
		fclose(ori) ;
		FILE *sol ;
		sol = fopen("data.txt", "rb") ;
		for (int i = 0 ; i < nn ; i ++) {				//Transmission stu
			fread(&stu[i], sizeof(student), 1, sol) ;
		}
		fclose(sol) ;
	}

There may be a better way. If you happen to see a better way here, please tell me in private~~

So far, all the details about the basic operation I can think of have been added. Then borrow the student number of the League branch secretary and the monitor and run the program. There is no problem.

 

A good program basically runs without any problems. The next step is sorting. Of course, you can set a bubble sorting board here, But I'm going to steal a lazy and sort directly (I didn't laugh), but here I found that the original big homework asked us to do two classes, and I've only done one class up to now (suddenly irritable), which means that I may have to copy the above program again. In the face of this 500-600 line small program, I'm too lazy to copy and paste. I'm going to finish one first, and then add two classes. The workload is also very heavy. In a word, I'm too lazy to do it

well! So! An accident happened at this time!  

When I started writing sorting, I accidentally created a program file and deleted the previously written one. Yes, I couldn't find it, that is to say, my previous code was gone. Maybe God is hinting that I'll be given a chance to refactor the code. It's true that the previous code was a little too long. Alas, so I spent one night and one morning, spent a total of more than five hours, and finally completed the final code. In fact, the basic framework is no different from the previous one, that is, some print custom functions are added to make my output part simpler, improve many input parts, and deal with illegal input more finely; At the same time, many return operations are added to improve the fault tolerance rate of users; At the same time, some small details are also added. For example, when deleting or modifying a student record, the current student information will be displayed to confirm whether to delete or modify it. When entering the secondary menu, there will be a return operation to avoid errors. For each input, a "operation to ensure that the input is legal" will be carried out to avoid some unknown errors.

About the source code of the whole program, I will write it in the next blog

Summary:

It's really interesting, but I think it's also very difficult. It's interesting because you can play by yourself to complete the production of a system. It's difficult because there are many details to consider. What if the user accidentally enters the wrong access, what if the user suddenly wants to cancel the current operation, what if there is a problem with the information entered by the user, and what if the user does not understand the current operation It may be that some algorithm problems of the previous brush did not pay much attention to the part of "human-computer interaction", so I always thought that "human-computer interaction" was not a very important part. Until I did this homework, I found that "human-computer interaction" is a very important link in the actual experience. Therefore, the difficulty of thinking in the whole code is not very high. The complex thing is how to improve the user's sense of experience. From #inlcude < studio h> To the last return 0; It took nearly a week to finish it off and on. In a word:

I'm a vegetable dog. I have to keep trying!

Topics: C Back-end