#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);
}
}
}