目录
配置文件:
stuInfor.txt
stu_account.txt
学C以来,第一次写了近五百行代码,实现一个简易版的学生管理系统,把一组学生信息存入文件中,然后管理员读取信息,管理员还可以对学生信息进行增,删,改,查。除此之外,还可以对用户账号进行增,删,改,查。
头文件 list.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<conio.h>
typedef struct student {
int num;
char name[20];
char sex;
float score1;
float score2;
float score3;
float score4;
float score5;
struct student *pNext;
}Student_t, *pStudent_t;
typedef struct user_account {
char name[20];
char password[10];
int permission;
struct user_account *pNext;
}user_account_t,*puser_account_t;
#define STUINFOR "stuInfor.txt"
void listTailInsert(pStudent_t *ppHead, pStudent_t *ppTail, pStudent_t str);
void listPrint(pStudent_t pHead);
void listPrintByName(pStudent_t pHead, char *name1);
void listDelete(pStudent_t *ppHead, pStudent_t *ppTail, int num);
void listModify(pStudent_t pHead, int num, pStudent_t str);
void writeFile(FILE *fp, pStudent_t pHead);
void writeFile1(FILE *fp1, puser_account_t pHead1);
void accountTailInsert(puser_account_t *ppHead, puser_account_t *ppTail, puser_account_t str1);
void accountPrint(puser_account_t pHead);
void accountAdd(puser_account_t *ppHead, puser_account_t *ppTail, puser_account_t str1);
void accountDelete(puser_account_t *ppHead1, puser_account_t *ppTail1, char *name1);
void accountModify(puser_account_t *ppHead1, char *name1, puser_account_t str1);
void accountPrintByName(puser_account_t pHead1, char *name5);
void check(puser_account_t pHead, puser_account_t str1, char* user_name, char* user_password);
list.c
#include "list.h"
//pStudent_t phead = NULL, ptail = NULL;
//尾插法,插入节点
void listTailInsert(pStudent_t *ppHead, pStudent_t *ppTail, pStudent_t str)
{//尾插法
//pStudent_t pNew = (pStudent_t)calloc(1, sizeof(Student_t));//申请空间
//pNew->num = str;
//printf("%5d %s %c %5.2f%5.2f%5.2f%5.2f%5.2f\n", str->num, str->name, str->sex, str->score1, str->score2, str->score3, str->score4, str->score5);
if (NULL == *ppTail)//判断链表是否为空,用NULL==*ppHead也可以
{
*ppHead = str;//新节点既给头节点,又给尾节点
*ppTail = str;
}
else {
(*ppTail)->pNext = str;//对ppHead取值才是一级指针才能拿到外面的值
//二级指针拿到一级指针才可以进行成员访问
*ppTail = str;
}
//printf("%5d %s %c %5.2f%5.2f%5.2f%5.2f%5.2f\n", str->num, str->name, str->sex, str->score1, str->score2, str->score3, str->score4, str->score5);
}
//打印函数
void listPrint(pStudent_t pHead)//打印函数
{
while (pHead != NULL)//打印,遍历,while循环
{
printf(" %5d %-10s %c %5.2f %5.2f %5.2f %5.2f %5.2f\n", pHead->num, pHead->name, pHead->sex, pHead->score1, pHead->score2, pHead->score3, pHead->score4, pHead->score5);
pHead = pHead->pNext;
}
printf("\n");
}
//按学号打印
void listPrintByNum(pStudent_t pHead, int number1)//通过学号进行查找打印
{
while (pHead) {
if (pHead->num == number1)
{
printf(" %5d %-10s %c %5.2f %5.2f %5.2f %5.2f %5.2f\n", pHead->num, pHead->name, pHead->sex, pHead->score1, pHead->score2, pHead->score3, pHead->score4, pHead->score5);
}
pHead = pHead->pNext;
}
printf("\n");
printf("返回首页请输入3键:\n");
}
//按姓名打印
void listPrintByName(pStudent_t pHead, char *name1)//通过姓名进行查找打印,这里是char*,而不是char
{
while (pHead != NULL) {
int ret = strcmp(pHead->name, name1);
if (0 == ret)
{
printf(" %5d %-10s %c %5.2f %5.2f %5.2f %5.2f %5.2f\n", pHead->num, pHead->name, pHead->sex, pHead->score1, pHead->score2, pHead->score3, pHead->score4, pHead->score5);
}
pHead = pHead->pNext;
}
printf("\n");
printf("请输入3键返回首页:\n");
}
//删除节点
void listDelete(pStudent_t *ppHead, pStudent_t *ppTail, int num)
{
pStudent_t pCur, pPre;
pCur = *ppHead;
pPre = pCur;
if (pCur == NULL)
{
printf("list is empty\n");
return;
}
else if (pCur->num == num)//要删除的是头部
{
*ppHead = pCur->pNext;
if (NULL == *ppHead)//如果头部删了之后头为nULL,说明删之前就一个节点
{
*ppTail = NULL;//故此时,尾节点也为null
}
}
else {
while (pCur)//删除的是中间节点
{
if (pCur->num == num)
{
pPre->pNext = pCur->pNext;
break;
}
pPre = pCur;
pCur = pCur->pNext;
}
if (pCur == NULL)
{
printf("No such number\n");
return;
}
if (*ppTail == pCur)
{
*ppTail = pPre;
}
}
free(pCur);
pCur = NULL;
}
//修改
void listModify(pStudent_t pHead, int num, pStudent_t str)//不用改变
{
while (pHead)
{
if (pHead->num == num)
{
//pHead->name = name;
//pHead->sex = sex;
pHead->score1 = str->score1;
pHead->score2 = str->score2;
pHead->score3 = str->score3;
pHead->score4 = str->score4;
pHead->score5 = str->score5;
break;
}
pHead = pHead->pNext;
}
if (NULL == pHead)
{
printf("这个学号不存在,请重输\n");
}
}
//函数:往文件里的写函数
void writeFile(FILE *fp,pStudent_t pHead)
{
pStudent_t pCur = pHead;
int ret = 0;
while (pCur) {
ret = fprintf(fp, " %-5d %-10s %c %5.2f %5.2f %5.2f %5.2f %5.2f \n", pCur->num, pCur->name, pCur->sex, pCur->score1, pCur->score2, pCur->score3, pCur->score4, pCur->score5);
pCur = pCur->pNext;
}
fseek(fp, 0, SEEK_CUR);
//fclose(fp);
}
//函数:往文件1里写
void writeFile1(FILE *fp1,puser_account_t pHead1)
{
puser_account_t pCur1 = pHead1;
int ret = 0;
while (pCur1) {
ret = fprintf(fp1, " %-10s %-10s %10d \n", pCur1->name, pCur1->password, pCur1->permission);
pCur1 = pCur1->pNext;
}
fseek(fp1, 0, SEEK_CUR);
//fclose(fp);
}
void accountTailInsert(puser_account_t *ppHead, puser_account_t *ppTail, puser_account_t str1)
{
if (NULL == *ppTail)//判断链表是否为空,用NULL==*ppHead也可以
{
*ppHead = str1;//新节点既给头节点,又给尾节点
*ppTail = str1;
}
else {
(*ppTail)->pNext = str1;//对ppHead取值才是一级指针才能拿到外面的值
//二级指针拿到一级指针才可以进行成员访问
*ppTail = str1;
}
}
void accountPrint(puser_account_t pHead)//打印函数
{
while (pHead != NULL)//打印,遍历,while循环
{
printf("%-10s %-10s %10d\n", pHead->name, pHead->password,pHead->permission);
pHead = pHead->pNext;
}
printf("\n");
}
void accountDelete(puser_account_t *ppHead1, puser_account_t *ppTail1,char *name1)
{
puser_account_t pCur1, pPre1;
pCur1 = *ppHead1;
pPre1 = pCur1;
if (pCur1== NULL)
{
printf("list is empty\n");
return;
}
else if (strcmp(pCur1->name,name1)==0)//要删除的是头部
{
*ppHead1 = pCur1->pNext;
if (NULL == *ppHead1)//如果头部删了之后头为nULL,说明删之前就一个节点
{
*ppTail1 = NULL;//故此时,尾节点也为null
}
}
else {
while (pCur1)//删除的是中间节点
{
if (strcmp(pCur1->name,name1)==0)
{
pPre1->pNext = pCur1->pNext;
break;
}
pPre1 = pCur1;
pCur1 = pCur1->pNext;
}
if (pCur1== NULL)
{
printf("No such name!\n");
return;
}
if (*ppTail1 == pCur1)
{
*ppTail1 = pPre1;
}
}
free(pCur1);
pCur1 = NULL;
}
void accountModify(puser_account_t pHead, char *name1, puser_account_t str1)
{
while (pHead)
{
if (strcmp(pHead->name, name1) == 0)
{
//pHead->name = name;
//pHead->sex = sex;
strcpy(pHead->password, str1->password);
pHead->permission = str1->permission;
break;
}
pHead = pHead->pNext;
}
if (NULL == pHead)
{
printf("这个账号不存在,请重输\n");
}
}
void accountPrintByName(puser_account_t pHead1, char *name5)
{
while (pHead1 != NULL)
{
int ret;
ret = strcmp(pHead1->name, name5);
if (0 == ret)//如果传进来的名字等于文件,链表中指向的名字
{
printf("%-10s %-10s %10d\n", pHead1->name, pHead1->password, pHead1->permission);
break;
}
pHead1 = pHead1->pNext;
}
printf("\n");
}
void check(puser_account_t pHead,puser_account_t str1,char* user_name,char* user_password)
{
while (pHead != NULL)
{
int ret = strcmp(pHead->name, user_name);
int ret1 = strcmp(pHead->password, user_password);
int count = 0;
if (0 == ret&&0==ret1)
{
if (pHead->permission == 1) {
count = 0;
printf("管理员同志你好!\n");
}
else {
printf("学生你好!\n");
count = 1;
}
}
pHead= pHead->pNext;
}
printf("\n");
}
main.c
#include "list.h"
pStudent_t phead = NULL, ptail = NULL;
puser_account_t phead1 = NULL, ptail1 = NULL;
int main(int argc, char *argv[])
{
FILE *fp;
FILE *fp1;
int i;
int val;
int number;
int num;
if (argc != 3)
{
printf("error args\n");
goto error;
}
fp = fopen(argv[1], "r+");//这里argv[1]可以换成file.txt
if (NULL == fp)
{
perror("fopen");
goto error;
}
pStudent_t str;
str = (pStudent_t)calloc(1, sizeof(Student_t));
while (memset(str, 0, sizeof(Student_t)), fscanf(fp, "%d%s %c%f%f%f%f%f", &str->num, str->name, &str->sex, &str->score1, &str->score2, &str->score3, &str->score4, &str->score5) != EOF)
{//读进来之后,用链表插入方法,建一条链表,尾插法
listTailInsert(&phead, &ptail, str);//尾插法
str = (pStudent_t)calloc(1, sizeof(Student_t));//给每个节点申请空间
//count++;
}//串成链表成功
fp1 = fopen(argv[2], "r+");//这里argv[1]可以换成file.txt
if (NULL == fp1)
{
perror("fopen");
goto error;
}
puser_account_t str1;
str1 = (puser_account_t)calloc(1, sizeof(user_account_t));
int ret;
while (memset(str1, 0, sizeof(user_account_t)), fscanf(fp1, "%s%s%d", str1->name, str1->password, &str1->permission)!=EOF)
{
accountTailInsert(&phead1, &ptail1, str1);
str1 = (puser_account_t)calloc(1, sizeof(user_account_t));
}
//char user_name[20];
//char user_password[10];
//printf("请输入用户账户名:");
//scanf("%s", user_name);
//printf("请输入用户账户密码:");
//char user_password = getch();//scanf("%s", user_password);
//int count = 0;
//check(phead1,str1, user_name, user_password);//检查姓名,密码,权限是否正确,
//if (count==0)
//{
//
//}
//else {
// goto label3;
//}
//if (count == 0) {
//user_name==name,user_password=password,permisson=1
label1:
printf("\n----------------------------\n");
printf("1.查找学生信息\n2.添加学生信息\n3.更新学生信息.\n4.删除学生信息.\n5.添加用户账号.\n6.更新账号\n7.删除账户。\n8.查找账户\n9.退出\n"); printf("请输入一个数字进行选择:\n");
while (scanf("%d", &number) != EOF) {
//1.查找学生信息
if (number == 1) {
// printf("%5d %s %c %5.2f%5.2f%5.2f%5.2f%5.2f\n", pHead->num, pHead->name, pHead->sex, pHead->score1, pHead->score2, pHead->score3, pHead->score4, pHead->score5);
label2:
printf("0.查看全部\n1.通过名字进行查找\n2.通过学号进行查找\n3.退出当前,返回上一层页面\n");
printf("请输入一个数字进行选择:");
while (scanf("%d", &number) != EOF)
{
if (0 == number) {
listPrint(phead);
goto label2;
}
else if (1 == number) {
printf("请输入学生的姓名:");//?????
char name1[20];
scanf("%s", name1);
listPrintByName(phead, &name1);
goto label2;
}
else if (2 == number) {
printf("请输入学生的学号:");
int number1;
scanf("%d", &number1);
listPrintByNum(phead, number1);
goto label2;
}
else {
goto label1;
}
}
}
//2.添加学生信息
else if (2 == number)// 添加一个学生的信息 else
{
printf("请输入学生信息(格式为:100 张三 m 3 3 3 3 3):\n");
str = (pStudent_t)calloc(1, sizeof(Student_t));//申请新节点
scanf("%d%s %c%f%f%f%f%f", &str->num, str->name, &str->sex, &str->score1, &str->score2, &str->score3, &str->score4, &str->score5);
//printf("%5d %s %c %5.2f%5.2f%5.2f%5.2f%5.2f\n", str->num, str->name, str->sex, str->score1, str->score2, str->score3, str->score4, str->score5);
//printf("%5d %s %c %5.2f%5.2f%5.2f%5.2f%5.2f\n", phead->num, phead->name, phead->sex, phead->score1, phead->score2, phead->score3, phead->score4, phead->score5);
listTailInsert(&phead, &ptail, str);
printf("\n");
fp = fopen(argv[1], "w+");
writeFile(fp, phead);
printf("\n---------------------------\n");
listPrint(phead);
printf("添加成功!");
goto label1;
}
//3.修改学生信息
else if (3 == number)
{
int num;
char name[20];
float score1, score2, score3, score4, socre5;
printf("请输入要修改的学生学号:");
scanf("%d", &num);
printf("请输入要修改的5门课的分数,格式为( 1 2 3 4 5):\n");
scanf("%f%f%f%f%f", &str->score1, &str->score2, &str->score3, &str->score4, &str->score5);
listModify(phead, num, str);
fp = fopen(argv[1], "w+");
//printf("\n");
//fprintf(fp, " %5d %-10s %c %5.2f %5.2f %5.2f %5.2f %5.2f\n", str->num, str->name, str->sex, str->score1, str->score2, str->score3, str->score4, str->score5);
//fclose(fp);
listPrint(phead);
fp = fopen(argv[1], "w+");
writeFile(fp, phead);
printf("修改成功!");
goto label1;
}
//4.删除学生信息
else if (4 == number)
{
printf("请输入要删除的学生的学号:");//按学号
int num;
scanf("%d", &num);
//fflush(stdout);
listDelete(&phead, &ptail, num);
printf("\n");
fp = fopen(argv[1], "w+");
writeFile(fp, phead);
listPrint(phead);
printf("删除成功!");
goto label1;
}
//5.账户的增加
else if (5 == number)
{
accountPrint(phead1);
printf("请输入账户信息(格式为:admin admin 1):\n");
str1 = (puser_account_t)calloc(1, sizeof(user_account_t));//申请新节点
scanf("%s%s%d", str1->name, str1->password, &str1->permission);
accountTailInsert(&phead1, &ptail1, str1);
printf("\n");
fp1 = fopen(argv[2], "w+");//把东西写进文件fp1里面的
writeFile1(fp1, phead1);
printf("\n---------------------------\n");
accountPrint(phead1);
printf("添加成功!");
goto label1;
}
//6.账户的更新,修改
else if (6 == number)
{
accountPrint(phead1);
char name[20];
printf("请输入要修改的账号姓名:");
scanf("%s", name);
printf("请输入要修改的密码和权限,格式为(admin 1):\n");
scanf("%s%d", str1->password, &str1->permission);
accountModify(phead1, name, str1);
/*fp1 = fopen(argv[2], "w+");*/
accountPrint(phead1);
fp1 = fopen(argv[2], "w+");
writeFile1(fp1, phead1);
printf("修改成功!");
goto label1;
}
//7.账户的删除
else if (7 == number)
{
accountPrint(phead1);
printf("请输入要删除的账户的名字:");//按名字删除
char name1[20];
scanf("%s", name1);
//fflush(stdout);
accountDelete(&phead1, &ptail1, name1);
printf("\n");
fp1 = fopen(argv[2], "w+");
writeFile1(fp1, phead1);
accountPrint(phead1);
printf("账号删除成功!");
goto label1;
}
//8.账户的查找
else if (8 == number)//就是说,我输入一个名字,它立马给我显示账号信息
{
accountPrint(phead1);
char name5[20];
printf("请输入账户的名字:");
scanf("%s", name5);
printf("个人账户查找成功!\n");
accountPrintByName(phead1, name5);
goto label1;
}
//9.退出登录,返回
else if (9 == number) {
return 0;
}
else {
printf("请输入正确的数字:即1~9之间的数字\n");
goto label1;
}
free(str);
}
fclose(fp);
error:
return 0;
//label3:
}
配置文件:stuInfor.txt 和 stu_account.txt
100 lele f 4.00 4.00 4.00 4.00 4.00
103 xionger m 6.00 6.00 6.00 6.00 6.00
109 qinger m 9.00 9.00 9.00 9.00 9.00
110 liulei m 8.00 8.00 8.00 8.00 8.00
130 qiang f 1.00 1.00 1.00 1.00 1.00
188 llldskf m 1.00 1.00 1.00 1.00 1.00
122 lililili f 2.00 2.00 2.00 2.00 2.00
188 老张 m 3.00 3.00 3.00 3.00 3.00
admin admin 1
liulei 789 2
qinger 456 2
1111 2222 3
老王 111 3