C语言学生管理系统(最终版本)

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define FILE_NAME "student.csv"

#define RD_ID      (1<<0)
#define RD_NAME     (1<<1)
#define RD_SCORE    (1<<2)

//描述1个学生的属性
struct student
{
    int ID;
    char name[20];
    float score;
};
//创建链表的节点数据结构
struct node
{
    struct student data;//该节点的数据域
    struct node *next;//该节点的指针域
};

void GetInfo(struct student *p,unsigned char flag);
int menu(void);                     //菜单函数声明
int add(struct node *p);           //添加
int  del(struct node *p);         //删除
int change(struct node *p);      //修改
int find(struct node *p);       //查找
void all_pri(struct node *p);  //打印所有
//int quit(void);             //退出
int save(struct node *p);    //保存
void read(struct node *p);  //读取保存的文件 
struct node *head = NULL;   //指向头节点的指针变量
static int Add1(struct node *p,struct student temp);
int close(struct node *p1);

int main()
{
    int num=0;
    read(head);
	while(1)
	{
		num = menu();
		switch(num)
		{
		    case 1:add(head);break;
		    case 2:del(head);break;
		    case 3:change(head);break;
		    case 4:find(head);break;
		    case 5:all_pri(head);break;
            case 6:save(head);return 0;
		}
	}
}


int menu(void)
{
    int num;
    printf("\t\t*****欢迎进入学生管理系统*****\n");
    printf("\t\t*****    1 添加学生    *****  \n");
    printf("\t\t*****    2 删除学生    ***** \n");
    printf("\t\t*****    3 修改学生    ***** \n");
    printf("\t\t*****    4 查找学生    ***** \n");
    printf("\t\t*****   5 打印所有信息  ***** \n");
    printf("\t\t*****   6 保存并退出学生系统  ***** \n");
    printf("请输入选项:");
    scanf("%d",&num);
    return num;
}
/******************************************
int add(struct node *p)
{
    //1.开辟新的节点,使用new指向该新的节点
    struct node *new = malloc(sizeof(struct node));
     //2.1给节点的数据域赋值
     GetInfo(&new->data,RD_ID|RD_NAME|RD_SCORE);
     //2.2给节点的指针域赋值
     new->next = NULL;
    //3.把新的节点添加到链表中去
    //3.1 链表为空
    if(head == NULL)
    {
        head = new;
        return 0;
    }
    else//尾插法
    {
       while(p->next != NULL)
       {
            p = p->next;
       }
        //把新节点添加到链表最后节点的后面
       p->next = new;
       return 0;
    }
}
******************************************/


int add(struct node *p)
{
    //1.开辟新的节点,使用new指向该新的节点
    struct node *new = malloc(sizeof(struct node));
     //2.1给节点的数据域赋值
     GetInfo(&new->data,RD_ID|RD_NAME|RD_SCORE);
     //2.2给节点的指针域赋值
     new->next = NULL;
    //3.把新的节点添加到链表中去 -- 中间插入
    //3.1 链表为空
    if(head == NULL)
    {
        head = new;
        return 0;
    }
    //3.2 查找位置,进行插入
       while(p != NULL)
       {
            if(p->data.ID < new->data.ID)
            {
                //后续节点为空,直接插入后面
                if(p->next == NULL)
                {
                    p->next = new;
                    return 0;
                }
                else if(p->next->data.ID > new->data.ID)
                {
                    new->next = p->next;
                    p->next = new;
                    return 0;
                }
            }
            else if(p == head)
            {
                new->next = head;
                head = new;
                return 0;
            }
            p = p->next;
       }
        
}

/*
删除链表中某个节点
p1 -- 链表头
返回值: 0 -- 成功
      >0 -- 失败
       1 -- 链表为空
       2 -- 链表中查询不到
*/
int del(struct node *p)
{
    if(p == NULL)  //空链表
    {
        return 1;
    }
    struct student temp={0};   //定义一个结构体数组
    GetInfo(&temp,RD_ID);     //输入要删除的ID
    struct node *del = NULL;
     //定义一个结构体指针,用来保存要删除节点的首地址

    //1.判断是否是第一个节点
    if(p->data.ID == temp.ID)
    {
        del = p;
        head = del->next;
        free(del);
        return 0;
    }
    //第2个节点开始
    while(p->next != NULL)  //寻找到最后一个结点
    {
        if(p->next->data.ID == temp.ID)
        {
            del = p->next;         //将被删结点的地址给del
            p->next = del->next;  //被删结点的下个地址给p的next
            free(del);           //释放被删结点
            return 0;
        }
        p = p->next;
    }
    printf("无名之辈,不足挂齿\n");
    return 2;
}

int change(struct node *p)
{
    struct student temp = {0}; //初始化结构体数组
    GetInfo(&temp,RD_ID|RD_NAME);//输入你想要修改的学生信息的学号
    while(p != NULL)
    {
        if(p->data.ID == temp.ID)
        {
            if(strcmp(p->data.name,temp.name)==0)
            {
                GetInfo(&temp,RD_ID|RD_NAME|RD_SCORE);
                //输入想要修改的信息
                p->data = temp;
                return 0;
            }

        }
        p = p->next;
    }
        printf("查无此人\n");
        return 1;
}

int find(struct node *p)
{
    struct student temp = {0};  //保存要查找的信息
    GetInfo(&temp,RD_ID);      //输入要查找学生的学号
    while(p != NULL)          //循环比较学号
    {
        if(p->data.ID == temp.ID)
        {
            printf("找到该学生,信息如下:\n");
            printf("%d\t",p->data.ID);
            printf("%s\t",p->data.name);
            printf("%f\n",p->data.score);
            return 0;
        }
        p = p->next;
    }
        printf("查无此人\n");
        return 1;
}

void all_pri(struct node *p)
{
    printf("打印所有学生信息操作……\n");
    printf("学号\t姓名\t成绩\n");
    while(p != NULL)
    {
        printf("%d\t",p->data.ID);
        printf("%s\t",p->data.name);
        printf("%f\n",p->data.score);
        p = p->next;
    }
}


/*
flag = 相应的选项是否允许输入
[0]位 -- no_flag    1--允许输入 0 -- 不允许输入
[1]位 -- name_flag  1--允许输入 0 -- 不允许输入
[2]位 -- sex_flag   1--允许输入 0 -- 不允许输入
*/
void GetInfo(struct student *p,unsigned char flag)
{
    if(flag & (1<<0))
    {
        printf("请输入学号:");
        scanf("%d",&p->ID);
    }
    if(flag & (1<<1))
    {
        printf("请输入姓名:");
        scanf("%s",p->name);
    }
    if(flag &(1<<2))
    {
        printf("请输入成绩:");
        scanf("%f",&p->score);
    }
}




int save(struct node *p)     //保存
{
    FILE *fp = fopen(FILE_NAME,"w");
    fprintf(fp,"学号,姓名,分数\n");
    if(p == NULL)  //链表为空
    {
        perror("文件打开失败");
		return 1;
    }
    while(p != NULL)
    {
        fprintf(fp,"%d,",p->data.ID);
        fprintf(fp,"%s ,",p->data.name);
        fprintf(fp,"%.2f\n",p->data.score);
        p = p->next;
    }
    fclose(fp);
    return 0;
}

/**************************************************
void read(struct node *p)
{
    FILE *fp = fopen("data.txt","a+");
    if (fp == NULL)
	{
		perror("fopen");
		return ;
	}
    	struct node *new = NULL,*end = p;
	while (fgetc(fp) != -1)
	{
		fseek(fp,-1,1);//光标位置
		new = malloc(sizeof(struct node));
		fscanf(fp,"ID: %d\t 姓名: %s\t\t成绩: %f\t\n",&new->data.ID,new->data.name,&new->data.score);
		new->next = NULL;
		end->next = new;
		end = new;
	}
	fclose(fp);
	//return ;
}
*************************************************/

void read(struct node *p)
{
        //1.打开 FILE_NAME r
    FILE *fp = fopen(FILE_NAME,"r");
    //2.往链表中添加新的数据
    //2.1 偏移文件指针 -- 跳过列名
    fseek(fp,sizeof("学号,姓名,性别,分数"),SEEK_SET);
    //2.2 读取文件信息 -- 判断文件是否到最后
    struct student temp={0};
    int res = 0;
    while(1){
        memset(&temp,0,sizeof(temp));
        res = fscanf(fp,"%d,",&temp.ID);
        res = fscanf(fp,"%s",temp.name);
        res = fscanf(fp,"%f",&temp.score);
        if(res == EOF){
            break;
        }
        //2.3 往链表中添加
        Add1(p,temp);
        p = head;//p1从新值指向链表头
    }
    //3.关闭文件
    fclose(fp);
}

static int Add1(struct node *p,struct student temp)
{
     //1.开辟新的节点,使用pnew指向该新的节点
    struct node *new = malloc(sizeof(struct node));
    //2.1给节点的数据域赋值
    new->data = temp;
    //2.2给节点的指针域赋值
    new->next = NULL;
    //3.把新的节点添加到链表中去 -- 中间插入
    //3.1 是否为空链表
    if(head == NULL){
        head = new;
        return 0;
    }
    //3.2 查找位置,进行插入
    while(p != NULL){
        if(p->data.ID < new->data.ID)
        {
            //后续节点为空,直接插入后面
            if(p->next == NULL){
                p->next = new;
                return 0;
            }else if(p->next->data.ID > new->data.ID){
                new->next = p->next;
                p->next = new;
                return 0;
            }
        }else if(p == head){
            new->next = head;
            head =  new;
            return 0;
        }
        p = p->next;
    }
}
int close(struct node *p1)
{
    printf("系统正在关闭\n");
    save(p1);
    printf("系统关闭完成\n");
    return 0;
}

相关推荐

  1. C语言学生管理系统

    2024-01-17 21:46:01       32 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-17 21:46:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-17 21:46:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-17 21:46:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-17 21:46:01       20 阅读

热门阅读

  1. 第十四届蓝桥杯省赛PythonB组

    2024-01-17 21:46:01       31 阅读
  2. 电脑DIY-显卡

    2024-01-17 21:46:01       37 阅读
  3. 前端每次发版提示用户

    2024-01-17 21:46:01       34 阅读
  4. webassembly003 whisper.cpp的项目结构CMakeLists.txt

    2024-01-17 21:46:01       26 阅读
  5. 初来乍到!做一个个人介绍!

    2024-01-17 21:46:01       35 阅读
  6. SpringMVC controller方法返回值见解3

    2024-01-17 21:46:01       29 阅读
  7. Docker-Dockerfile

    2024-01-17 21:46:01       34 阅读
  8. docker 学习命令整理

    2024-01-17 21:46:01       30 阅读
  9. 设计模式-原型模式

    2024-01-17 21:46:01       36 阅读