Student.h
#ifndef QY_STUDENT_H
#define QY_STUDENT_H
#define NAMELEN 32
#define MINAGE 4
#define MAXAGE 100
#define MINSTUDYID 20140001
#define MAXSTUDYID 20149999
typedef struct student {
char name[NAMELEN];
int age;
int studyID;
int useFlag; /*0:unuse 1:using*/
} STU;
enum command {
kListStudents,
kAddStudent,
kDelStudent,
kSearchStudent,
kQuitCMD,
};
extern STU*allocStudentRecords(int number);
extern voidprintStudents(STU *stu);
extern int addStudent(STU*stu, char *name, int age, int studyID);
extern int delStudent(STU*stu, int studyID);
extern intsearchStudent(STU *stu, int studyID);
extern voiddeallocStudentRecords(STU *);
#endif
student.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "student.h"
static intnumberOfStudents;
STU *allocStudentRecords(int number)
{
STU *stu = NULL;
int size = number * sizeof(STU);
stu =malloc(size);
if (stu == NULL) {
perror("malloc");
return NULL;
}
memset(stu, 0, size);
numberOfStudents = number;
return stu;
}
static void printStudent(STU*stu, int index)
{
printf("Student's Name is [%s]\n", stu[index].name);
printf("Student's Age is [%d]\n", stu[index].age);
printf("Student's StudyID is [%d]\n", stu[index].studyID);
printf("====================================\n");
}
voidprintStudents(STU *stu)
{
for (int i = 0; i <numberOfStudents; i++) {
if (stu[i].useFlag){
printStudent(stu, i);
}
}
}
// 检查学生学号是否冲突,冲突返回-1,不冲突返回0
static int checkStudyID(STU *stu, int studyID)
{
for (int i = 0; i < numberOfStudents;i++) {
if (studyID == stu[i].studyID
&& stu[i].useFlag == 1) {
return -1;
}
}
return 0;
}
// 获取空闲位置索引
static int getFreePosition(STU *stu)
{
for (int i = 0; i < numberOfStudents;i++) {
if (stu[i].useFlag == 0) {
return i;
}
}
return -1;
}
int addStudent(STU *stu, char *name, int age, int studyID)
{
int index = -1;
// 1. 检查学号是否冲突
if (checkStudyID(stu, studyID) < 0) {
fprintf(stderr, "Student <%d>Already Exsist!\n", studyID);
return -1;
}
// 2. 找到空闲位置索引
index = getFreePosition(stu);
if (index < 0) {
fprintf(stderr, "No Free Position toAdd New Student!\n");
return -1;
}
// 3. 根据传入的数据,进行相应赋值
strncpy(stu[index].name, name, NAMELEN-1);
stu[index].age = age;
stu[index].studyID = studyID;
stu[index].useFlag = 1;
printf("AddedSuccessfully!\n");
return 0;
}
int delStudent(STU *stu, int studyID)
{
for (int i = 0; i < numberOfStudents;i++) {
if (stu[i].studyID == studyID
&& stu[i].useFlag) {
stu[i].useFlag = 0;
printf("DeletedSuccessfully!\n");
return 0;
}
}
fprintf(stderr, "Student <%d>to delete does not exsist!\n", studyID);
return -1;
}
int searchStudent(STU *stu, int studyID)
{
for (int i = 0; i < numberOfStudents;i++) {
if (stu[i].studyID == studyID
&& stu[i].useFlag) {
printStudent(stu, i);
return 0;
}
}
fprintf(stderr, "Student <%d>to search does not exsist!\n", studyID);
return -1;
}
void deallocStudentRecords(STU*stu)
{
free(stu);
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "student.h"
#define BUFSIZE 32
#define STUNUM 32
/*
* 将用户的输入转换成long类型,并返回转换结果
* 返回-1 代表转换失败
*/
static long getInput(void)
{
char buf[BUFSIZE] = {0};
long result = -1;
fgets(buf, BUFSIZE, stdin);
result = strtol(buf, NULL, 0);
if ((result == 0 && errno == EINVAL)
|| (errno == ERANGE)) {
result = -1;
errno = 0;
}
return result;
}
static int getStudyID(void)
{
int studyID = -1;
_InputStudyID:
fprintf(stdout, "Please InputStudent's Study ID:\n");
studyID = (int)getInput();
if (studyID < MINSTUDYID || studyID >MAXSTUDYID) {
fprintf(stderr, "Invalid Input!(StudyID Must in [20140001-20149999])\n");
goto _InputStudyID;
}
return studyID;
}
int main(void)
{
long cmd = -1;
char stuName[NAMELEN] = {0};
int stuAge = -1;
int studyID = -1;
STU *stu = NULL;
// 打开保存学生记录的文件
system("touch records");
FILE *fp = fopen("records", "r+");
if (fp == NULL) {
perror("fopen");
goto _Fail1;
}
// 为学生记录申请内存并初始化
stu = allocStudentRecords(STUNUM);
if (NULL == stu) {
goto _Fail2;
}
// 从保存学生记录的文件中读取记录到内存里
fread(stu, sizeof(STU), STUNUM, fp);
rewind(fp);
while (1) {
// 1. 提示用户输入命令
fprintf(stdout, "Please Input CommandNumber:\n0 - List\t1 - Add \t2 - Delete\t3 - Search\t4 - Quit\n");
// 2. 接收用户输入的命令:(怀疑用户的输入,也就是对用户输入进行检查)
cmd = getInput();
fpurge(stdin);
if (cmd == -1 || cmd > kQuitCMD || cmd< kListStudents) {
fprintf(stderr, "InvalidCommand!\n");
continue;
}
// 3. 匹配用户输入的命令,执行相应的操作
switch (cmd) {
case kListStudents:
printStudents(stu);
break;
case kAddStudent:
fprintf(stdout, "Please InputStudent's Name:\n");
fgets(stuName, NAMELEN, stdin);
stuName[strlen(stuName)-1] = '\0';
_InputAge:
fprintf(stdout, "Please InputStudent's Age:\n");
stuAge = (int)getInput();
if (stuAge < MINAGE ||stuAge > MAXAGE) {
fprintf(stderr, "Invalid Input!(AgeMust in [4-100])\n");
goto _InputAge;
}
studyID = getStudyID();
addStudent(stu, stuName,stuAge, studyID);
break;
case kDelStudent:
studyID = getStudyID();
delStudent(stu, studyID);
break;
case kSearchStudent:
studyID = getStudyID();
searchStudent(stu, studyID);
break;
case kQuitCMD:
goto _Exit;
break;
default:
fprintf(stderr, "Can't go here!Unknown Command!\n");
break;
}
}
_Fail2:
fclose(fp);
_Fail1:
exit(1);
_Exit:
// 将学生记录写入到记录文件
fwrite(stu, sizeof(STU), STUNUM, fp);
fclose(fp);
deallocStudentRecords(stu);
return 0;
}