利用链表实现学生信息管理系统(实现单向链表的:增、删、查、改、清空;以及文件的创建和信息的录入与读取)

代码

app.c

#include "app.h"
#include <stdlib.h>

union person{		//定义一个共用体,保存常用的name及id,来节省空间
	char name[20];
	int id;
};
union person stu;	//共用体变量stu

//申请新节点的函数
Node * Create_Node(void)
{
	Node * new = (Node *)malloc(sizeof(Node));	//定义Node*类型的指针,接收所申请节点空间的地址
	if(new == NULL)
	{
		printf("申请空间失败!\n");
		return NULL;
	}
	memset(new,0, sizeof(Node));	//对申请的节点初始化,置0
	return new;	//返回申请节点空间的地址
}

void input(Node * head)	//新增全部信息	//值传参
{
	int num=0;
	printf("请输入你要创建信息的个数:\n");
	scanf("%d",&num);
	while(getchar()!= '\n');
	
	for(int i=num;i>0;i--)
	{
		//新增信息
		Node * NewNode = Create_Node();//申请新节点
		if(NewNode == NULL)
		{
			printf("申请新节点失败!\n");
			return ;
		}
		
		//尾插法(输出正序)
		/*
		Node * p =head;
		while(p->next!=NULL)	//确定p为最后一个节点
		{
			p=p->next;
		}
		p->next=NewNode;	//新节点放在最后
		*/
		
		//头插法(输出倒序)
		Node * p =head;
		NewNode->next= p->next;	//先断开,再连接头节点 	// 指针域 = 常量地址
		p->next= NewNode;		//连接头节点 
		
		printf("请输入姓名:\n");
		scanf("%s",NewNode->inf.name);
		while(getchar()!= '\n');
		printf("请输入id:\n");
		scanf("%d",&NewNode->inf.id);
		while(getchar()!= '\n');
	}

}
void output(Node * head)	//输出全部信息
{
	Node * p= head;
	if(p->next == NULL)	//如果该连表只有一个头节点
    {
        printf("该连表为空!\n");
        return ;
    }
    
	printf("下面输出所与人的信息:\n");
	printf("*****************begin********************\n");
	printf("姓名\tid\n");
	while(p->next!=NULL)
	{
		p=p->next;	//因为头节点一般无值,所以让其指向下一个节点,输出其中的值
		printf("%s\t%d\n",p->inf.name,p->inf.id);
	}
	printf("******************end*********************\n");
}

Node * search(Node * head)	//查询信息
{	
	Node * p= head;
	if(p->next == NULL)	//如果该连表只有一个头节点
    {
        printf("该连表为空!\n");
        return NULL;
    }
	
	char val=0;
	printf("输入你要查询的条件:1.姓名、2.学号、3.退出\n");
	scanf("%c",&val);
	while(getchar()!='\n');

	switch(val)
	{
		case '1':
			printf("请输入姓名:\n");
			scanf("%s",stu.name);
			while(getchar()!='\n');
			
			while(p->next!=NULL)
			{
				p=p->next;
				if( strcmp(p->inf.name,stu.name)==0 )
					return p;
			}
			break;
		case '2':
			printf("请输入学号:\n");
			scanf("%d",&stu.id);
			while(getchar()!='\n');
			
			while(p->next!=NULL)
			{
				p=p->next;
				if(p->inf.id == stu.id)
					return p;
			}
			break;
		case '3':
			return NULL;
		default:
				printf("input err\n");
				break;
	}
}
void delete(Node * head)	//信息删除
{
	Node * p = head;
    Node * tmp = NULL;
    if(p->next == NULL)
    {
    	printf("该链表为空!\n");
        return ;
    }
    printf("输入学号:\n");
    scanf("%d",&stu.id);
    while(getchar()!='\n');
    
    while(p->next != NULL) // 判断当前节点后面是否有节点
    {
        if(p->next->inf.id == stu.id) // 比较当前节点p的,下一节点的信息
        {
 			printf("这个人的信息是:\n");
 			printf("%s %d\n",p->next->inf.name,p->next->inf.id);
            tmp = p->next;	//保存当前节点的下一节点的地址
            p->next = tmp->next;				//将当前节点的,下一节点的,下一个节点的地址,给到当前节点的指针域
            free(tmp);	//释放符合信息的地址空间	//即:使当前节点的指针域,指向下一个节点的下一个节点(删除当前节点的下一个节点)
            break;
        }
        p=p->next;	//让指针往下走
    }
    output(head);
}

void revise(Node * head)	//信息修改
{
	Node * p = search(head);	//定义指针,接收search()函数返回的查询到的数据的地址
	
	printf("下面重新输入这个人的: 姓名、学号:\n");
	scanf("%s %d",p->inf.name,&p->inf.id);	//重新在该位置输入信息,将原信息覆盖
	while(getchar()!='\n');

	output(head);
}

void sort(Node * head)	//信息排序
{
    printf("下面按id,从小到大排序\n");
    
    Node * p= head;
    Node * q= head;
    INF tmp = {0};	//保存相应节点数据域中的信息
    while(p->next!=NULL)
    {   
        q=head;	//使q每次循环时,都指向头节点,即下面的每次循环都从链表的头开始,把值全部比较一遍
        while(q->next->next!=NULL)
        {
            if(q->next->inf.id > q->next->next->inf.id)
            {
                tmp = q->next->inf;
                q->next->inf = q->next->next->inf;
                q->next->next->inf = tmp;
            }
            q=q->next;
        }
        p=p->next;	//p指针往下走
    }
    output(head);
}

void save(Node * head)    //保存信息于一个excel文件中
{
	FILE * fp=NULL;
	fp = fopen("stu.xlsx","w+");
	if(fp == NULL)
	{
		printf("打开文件失败!\n");
		return ;
	}
	
	Node * p= head;
	if(p->next==NULL)
	{
		printf("该链表为空!\n");
		return ;
	}
	fprintf(fp,"姓名\t学号\n");
	while(p->next!=NULL)
	{
		p= p->next;
		fprintf(fp,"%s\t%d\n",p->inf.name,p->inf.id);
	}
	fclose(fp);

}
void read_t(Node * head)	//将存储在 stu.xlsx 文件中的学生信息读出
{
	Node * p= head;
	
	FILE * fp=NULL;
	fp = fopen("stu.xlsx","r");
	if(fp == NULL)
	{
		printf("打开文件失败!\n");
		return ;
	}
	
	fscanf(fp,"姓名\t学号\n");	//先读取头,让光标后移
	while(feof(fp)==0)
	{
		Node * new= Create_Node();	//申请新节点
		fscanf(fp,"%s\t%d\n",new->inf.name,&new->inf.id);
		//头插法建立链表
		new->next= p->next;
		p->next= new;
	}
	fclose(fp);
	output(head);
}

void clear_t(Node * head)    //清空链表
{
	Node *p=head;
	if(p->next==NULL)
	{
		printf("该链表为空!\n");
		return ;
	}
	
	while(p->next!=NULL)
	{
		Node * tmp= p->next;
		p->next=p->next->next;
		free(tmp);
	}
	printf("清除链表成功!\n");
}



app.h

#ifndef	_APP_H_
#define _APP_H_

#include <stdio.h>
#include <string.h>

//定义节点类型
typedef struct info{
	char name[20];
	int id;
}INF;

typedef struct node{
	INF inf;
	struct node * next;
}Node;
/*
//构建节点的内容
typedef struct node{	//节点
	struct info{	//数据域
	char name[20];
	int id;
	} inf;
	struct node * next;	//指针域
}Node;	//节点名称
*/

Node * Create_Node(void);
void input(Node * head);
void output(Node * head);
Node * search(Node * head);
void delete(Node * head);
void revise(Node * head);	//信息修改
void sort(Node * head);
void save(Node * head);
void read_t(Node * head);	//将存储在 stu.xlsx 文件中的学生信息读出
void clear_t(Node * head);


#endif

mian.c

#include "app.h"

int main()
{
	//定义头指针指向头节点
	Node * head=NULL; // 头指针head置0
	head=Create_Node(); // 申请头节点
	if(head == NULL)
	{
		printf("申请头节点失败!\n");
		return 0;
	}
	Node *p= NULL;	//定义Node *类型的指针,接受search()的返回值
	while(1)
	{
		char val=0;
		printf("输入:0.退出、1.信息输入、2.信息查找、3.删除、\n\t4、修改、5、排序、6.信息输出、7.保存、8.提取信息、9.清除链表\n");
		scanf("%c",&val);
		while(getchar()!= '\n');
		
		switch(val)
		{
			case '0': 
				return 0;
			case '1':
				input(head);	//1.信息输入
				break;
			case '2':
				p= search(head);//2.信息查找
				printf("%s\t%d\n",p->inf.name,p->inf.id);
				break;
			case '3':
				delete(head);	//3.删除
				break;
			case '4':
				revise(head);	//4、修改
				break;
			case '5':
				sort(head);		//5、排序
				break;
			case '6':
				output(head);	//6.信息输出
				break;
			case '7':
				save(head);		//7.保存信息
				break;
			case '8':
				read_t(head);	//8.加载信息
				break;
			case '9':
				clear_t(head);	//9.清除链表
				break;
			default:	
				printf("input err\n");
				break;
		}
	}

	return 0;
}

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值