学生管理系统(链表)

#include <stdio.h>
#include<stdlib.h>
#include<dos.h>
#include<string.h>//使用到strcpy()字符串拷贝函数和比较函数
#include<conio.h>
#include<iostream>
#include <malloc.h>//使用到malloc()
 
using namespace std;
 
 
struct Student   //定义Student结构体,含有两个属性10个长度的字符串name[10]和下一个地址的指针*next
{		
	char name[10];
	char nu[10];
	struct Student *next;
};
 
 
class Operate  //把函数进行封装,在使用前需要先创建对象*********************************************************************
{
/*	int option;		//这个可以起到一个类似switch()的作用
	Operate(int _option)
	{
		this->option = _option;//用到了this指针
	}*/
public:
		
	int repeat(struct Student *p,int i,const char *str)//i为0/1,0为判断学号,1为判断姓名
		{
			int flag = 0;//返回1为重复,0为不重复
			struct Student *current;

			current = p;
			
			while(1) //注意要用这样的循环方式,否则之间循环判断current->next != NULL会漏掉最后一个
			{
				if(i == 0)
				{
					if(strcmp(current->nu,str) == 0 )//判断字符串是否相等
					{
						flag = 1;
						break;
					}
				}else
				{
					if(strcmp(current->name,str) == 0 )//判断字符串是否相等
					{
						flag = 1;
						break;
					}
				}
				if(current->next != NULL)
				{
					current = current->next;
				}else
				{
					flag = 0;
					break;
				}
			}
			return flag;
		}

	void input( struct Student *p)  //创建学生数据
	{
		struct Student *head,*current,*next; //Student的头部地址和当前地址和下一个地址(区别Student类中的next)
		char str[10];//用于存储学生的名字
		char nu[10];//用于存储学生学号
		char flag;//用于判断是否继续扫描
 
		head = p;
		current = head;
	
		printf("请输入学生名字:\n");
		scanf("%s", str);//扫描键盘
		getchar();//注意在前一次进行过扫描后要加getchar(),否则下次扫描会读取回车
		strcpy(head->name,str);//strcpy()将str数组中字符串拷贝到head所指的name中,其中head为结构体指针,故要写为head->name
	
		printf("请输入学生学号:\n");
		scanf("%s", nu);//扫描键盘
		getchar();//注意在前一次进行过扫描后要加getchar(),否则下次扫描会读取回车
		strcpy(head->nu,nu);
 
		printf("是否继续输入:Y/N?");
		scanf("%c",&flag);//flag为普通数字,用scanf要它的地址,故为&flag
		getchar();				  //但注意在前一次进行过扫描后要加getchar(),否则这次扫描会读取回车
		if((flag != 'N')&&(flag != 'Y'))
		{
			printf("\t\n输入出错\n");
			getchar();
			return;
		}
	
	
		while( flag != 'N' )
		{
			next = (struct Student *)malloc( sizeof(struct Student) );
			next->next = NULL;
			
			printf("请输入学生名字:\n");
			scanf("%s", str);//扫描键盘
			getchar();//注意在前一次进行过扫描后要加getchar(),否则下次扫描会读取回车
			if(repeat(head,1,str) == 1)
			{
				printf("输入姓名重复,按任意键返回\n");
				getchar();
				return;
			}
			printf("请输入学生学号:\n");
			scanf("%s", nu);//扫描键盘
			getchar();//注意在前一次进行过扫描后要加getchar(),否则下次扫描会读取回车
			if(repeat(head,0,nu) == 1)
			{
				printf("输入学号重复,按任意键返回\n");
				getchar();
				return;
			}
 
		//	next = (struct Student *)malloc( sizeof(struct Student) );
			strcpy(next->name,str);//将str的字符复制给next所指的Student类中的name
			strcpy(next->nu,nu);
		
			current->next = next;//注意:current->next为当前指针所指的Student类中的next指针,而后一个next是刚使用malloc申请到内存的地址
								 //故此处为把下一个的地址next赋值给当前current所指的Student类的next地址
								 //****即上一个元素的指针指向下一个元素
			current = next;//这是更新当前指针,和上面的current=head作用类似
						   //****即当前指针指向下一个元素
	
			printf("是否继续输入:Y/N?");
			scanf("%c",&flag);
			getchar();
		}
		current->next = NULL;//循环结束,当前指针指向最后一个元素,最后一个指针要赋值为NULL
	}
 
 
	struct Student * del(struct Student *p) //删除学生数据
	{
		struct Student *current,*last,*head;
		char nu[10];
	
		head = p;
		current = p;                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
 
		printf("\n请输入需要删除学生的学号:\n");
		scanf("%s",&nu);
		getchar();
	//	printf("%s \n",nu);
 
		while(1) //注意要用这样的循环方式,否则之间循环判断current->next != NULL会漏掉最后一个
		{
			if(strcmp(current->nu,nu) == 0 )//判断字符串是否相等
			{
				if(current == p) head = current->next;//如果删除的是第一个元素,就把p->next变为头部
				else	last->next = current->next;     //还可以用free()来释放文件
				printf("删除后当前表为\n");
				list(head);
				return(head);
				break;
			}
			if(current->next != NULL)
			{
				last = current;
				current = current->next;
			}else
			{
				printf("没有找到该学生数据\n");
				printf("按任意键返回\n");
				getchar();     //**********************************
				return(head);
				break;
			}
		}
	}	
	
	void list(struct Student *p)//这称为链表的遍历
	{
		int i=0;
		while(1)
		{
			printf("%d \n",i);
			printf("学生学号为:");
			printf("%s \n", p->nu);
			printf("学生姓名为:");
			printf("%s \n", p->name);
			printf("\n");
	
			if(p->next != NULL)//这里的next指Student结构体中的属性next,即判断当前P所指的Student类中的next地址是否为空(NULL)
			{
				p = p->next;
				i++;
			}else
			{
				printf("按任意键返回\n");
				getchar();
				break;
			}
		}
	}
 
 
	void find( struct Student *p)  //查找函数,根据姓名查找
	{	
		struct Student *current;
		char nu[10];
		char flag;

		current = p;
 
		printf("\n请输入需要查找的学生学号:\n");
		scanf("%s",&nu);
		getchar();
//		printf("%s \n",nu); //查看输入值是否正确
	
		while(1) //注意要用这样的循环方式,否则之间循环判断current->next != NULL会漏掉最后一个
		{
			if(strcmp(current->nu,nu) == 0 )//判断字符串是否相等
			{
				printf("查找的学生姓名为:\n");
				printf("%s \n",current->name);
				printf("查找的学生学号为:\n");
				printf("%s \n",current->nu);
				printf("按任意键返回\n");
				getchar();
				break;
			}
			if(current->next != NULL)
			{
				current = current->next;
			}else
			{
				printf("没有找到该学生数据\n");
				printf("按任意键返回\n");
				getchar();
				break;
			}
		}
		
	}
 
 
	struct Student * insert(struct Student *p)//链表的插入
	{
		struct Student *insert,*current,*head;
		char str[10];
		char nu[10];
		int position;
 
		current = p;
		head = p;
	
		printf("请输入学生名字:\n");
		scanf("%s", str);//扫描键盘
		getchar();//注意在前一次进行过扫描后要加getchar(),否则下次扫描会读取回车
		if(repeat(current,1,str) == 1)
		{
			printf("输入姓名重复,按任意键返回\n");
			getchar();
			return head;
		}
		
		printf("请输入学生学号:\n");
		scanf("%s", nu);//扫描键盘
		getchar();//注意在前一次进行过扫描后要加getchar(),否则下次扫描会读取回车
		if(repeat(current,0,nu) == 1)
		{
			printf("输入学号重复,按任意键返回\n");
			getchar();
			return head;
		}
 
		insert = (struct Student *)malloc( sizeof(struct Student) );
		strcpy(insert->name,str);
		strcpy(insert->nu,nu);
 
		printf("需要插入到序号第几位之后:\n");
		scanf("%d",&position);
 
		if( position > 0 )              //*****此为查找链表的第position位*****
		{
			//需要插入到position+1的位置
			while( position > 1 )  //移动指针的位置,移动到第position位,即循环之后current指向的为第position位
			{
				current = current->next;
				position--;
			}
			insert->next = current->next; //insert要插入到current指向地址和current下一位指向地址之间,故先把insert的next地址指向current的下一位
			current->next = insert;//再把current的next指向insert
 
		}else if( position == 0)
		{
			head = insert;
			insert->next = current;
		}
	
	
		return head;//若插入的第一位则返回新的头部的地址,否则主函数中仍然为原来的地址
	}
 
 
	void modify(struct Student *p)  //修改函数
	{
		struct Student *current;
		char nu[10];
		char str[10];
 
		current = p;
 
		printf("\n请输入需要修改的学生学号:\n");
	//	getchar();//此处加了会影响,具体原因不明。。。
		scanf("%s",&nu);
		getchar();
	//	printf("%s \n",nu); //查看输入值是否正确
		
		while(1) //注意要用这样的循环方式,否则之间循环判断current->next != NULL会漏掉最后一个
		{
			if(strcmp(current->nu,nu) == 0 )//判断字符串是否相等
			{
				printf("该学生姓名为:\n");
				printf("%s \n",current->name);
				printf("该学生学号为:\n");
				printf("%s \n",current->nu);
				
				printf("学生名字修改为:\n");
				scanf("%s", str);//扫描键盘
				getchar();//注意在前一次进行过扫描后要加getchar(),否则下次扫描会读取回车
	
				printf("学生学号修改为:\n");
				scanf("%s", nu);//扫描键盘
				getchar();
 
 	
				strcpy(current->name,str);
				strcpy(current->nu,nu);
 

				printf("按任意键返回\n");
				getchar();
				break;
			}
			if(current->next != NULL)
			{
				current = current->next;
			}else
			{
				printf("没有找到该学生数据\n");
				printf("按任意键返回\n");
				getchar();
				break;
			}
		}	
	}
 
 
	
};
 
 
 
 
 
 
 
int menu_select()
{
	int i;
	printf("\n\n\t ****************************学生管理系统****************************\n");
	printf("\t}*                       1.创建学生信息                 *|\n");
	printf("\t}*                       2.删除学生信息                 *|\n");
	printf("\t}*                       3.查看全部学生信息             *|\n");
	printf("\t}*                       4.查找学生信息                 *|\n");
	printf("\t}*                       5.插入学生信息                 *|\n");
	printf("\t}*                       6.修改学生信息                 *|\n");
	printf("\t}*                       7.离开                         *|\n");
	printf("\n\n\t ********************************************************************\n");
	do
	{
		printf("\n\t请输入您的选择:");
		scanf("%d",&i);//扫描函数,将扫描的值存入i中
		getchar();
		if(i<=0||i>7)
		{
			printf("\n\t输入出错,请重新输入\n");
		}
	}while(i<=0||i>7);//判断i值是否在1~7之间,否则继续要求输入
	return i;
}
 
void main()
{
	struct Student *p;//数据链表的头部
	p=(struct Student *)malloc( sizeof(struct Student) );
/*	if(p!)
	{
		printf("\n allocate memory failure!");
		return;
	}*/
	p->next=NULL; 
	Operate op1;//新创建的对象**************************************************************************************************
	while(1)
	{
		system("cls");
		switch(menu_select())
		{
			case 1:
				op1.input(p);
				break;
			case 2:
				p=op1.del(p);
				break;
			case 3:
				op1.list(p);
				break;
			case 4:
				op1.find(p);
				break;
			case 5:
				p=op1.insert(p);
				break;
			case 6:
				op1.modify(p);
				break;
			case 7:
				exit(0);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_37358422/article/details/81069724