黑马程序员技术交流社区
标题: 链表编写一个学生管理系统程序遇到问题,请大神解决 [打印本页]
作者: 魔主 时间: 2015-4-22 21:39
标题: 链表编写一个学生管理系统程序遇到问题,请大神解决
编写一个学生管理系统程序,用来记录学生的信息(包括姓名、年龄、性别、学号、分数),提供增加、删除、查询学生信息的入口。(C语言)
//链表编写一个学生管理系统程序遇到问题,请大神解决。main函数好像不对,然后只能添加1个学生信息,怎么解决?或者大神改进代码,谢谢。
#include <stdio.h>
#include <stdlib.h>
//创建节点结构,记录学生的信息
struct student{
char name[20]; //姓名
int age; //年龄
char sex; //性别
int no; //学号
int score; //分数
struct student*next; //指向下一个节点的指针
};
int count; //链表长度,作用是表示链表中节点数量
//create函数创建列表,该函数将会返回链表头指针
struct student *create()
{
struct student *head=NULL; //初始化链表,头指针为空
struct student *end,*new; //end指向原来尾节点,new指向新创建节点
int count=0; //初始化链表长度
end=new=(struct student*)malloc(sizeof(struct student));
/*使用malloc函数分配内存,end与new都指向第一个分配的内存。malloc函数原型: void*malloc(unsigned int size);功能:是在内存中动态地分配一块size大小的内存空间,返回一个指针,该指针指向分配的内存空间,如果出现错误则返回NULL;
类似函数:calloc函数,其原型:void*calloc(unsigned n,unsigned size),功能:在内存中动态分配n个长度size的连续空间数组,会返回一个指针,该指针指向动态分配的连续内存空间地址, 如果出现错误则返回NULL; */
printf("请输入学生信息(包括姓名、年龄、性别、学号、分数):\n");
scanf("%s",new->name); //姓名
scanf("%d",&new->age); //年龄
scanf("%c",&new->sex); //性别
scanf("%d",&new->no); //学号
scanf("%d",&new->score); //分数
while(new->no!=0){
count++; //表示链表节点增加
//判断新加入节点是否第一次加入节点
if(count==1)
{ //第一次加入节点时,新节点为首节点也为最后一个节点
new->next=head; //先将新节点指向为空
end=new; //跟踪新加入的节点
head=new; //头指针指向首节点
}
else
{//加入新节点时链表中已有节点
new->next=NULL; //新节点的指针为空
end->next=new; //原来尾节点指向新节点
end=new; //end指向新节点
}
new=(struct student*)malloc(sizeof(struct student));
/*再次分配节点内存空间,然后再次向其中输入数据,通过while循环再次判断输入的数据是否符合节点的要求。当要求不适合时,执行下面的代码,调用free函数将不符合要求的节点空间进行释放*/
scanf("%s",new->name);
scanf("%d",&new->age);
scanf("%c",&new->sex);
scanf("%d",&new->no);
scanf("%d",&new->score);
}
free(new); //释放没有用到的空间
/*free函数原型:void free(void*ptr); 功能:使用由指针ptr指向的内存区,使部分内存区能被其他变量使用。ptr是最近一次调用calloc或malloc函数返回的值。free函数无返回值。*/
return head;
}
//以上通过动态分配内存空间的方式创建完成链表
void print(struct student*head) //输出链表,查询信息
{
struct student*temp; //循环使用临时指针
int n=1; //表示链表中节点的序号
printf("学生管理系统共有%d人\n",count);
printf("\n");
temp=head; //指针得到首节点的地址
while(temp!=NULL)
{
printf("学号%d的学生信息如下:\n",n); //输出学号
printf("姓名:%s\n",temp->name); //输出姓名
printf("年龄:%d\n",temp->age); //输出年龄
printf("性别:%c\n",temp->sex); //输出性别
printf("分数:%d\n",temp->score); //输出分数
printf("\n");
temp=temp->next; //移动临时节点到下一个节点
n++;
}
}
/*print函数将链表数据输出,其参数head表示链表头节点。函数中定义一个临时指针temp用来循环操作,定义整型变量i表示链表节点序号,然后将临时指针temp保存首节点地址。
while语句将所有节点中保存的数据都显示输出,其中每输出一个节点内容后,就移动temp指针指向下一个节点地址,当为最后一个节点时,所拥有的指针指向NULL,循环结束*/
//在链表头节点位置插入节点[有三种插入操作(链表头节点位置插入节点,某个节点位置进行,像创建结构时在链表后面添加节点),思路一样]
//向链表中添加节点
struct student *insert(struct student*head)
{
struct student*new; //指向新分配空间
printf("增加学生信息(包括姓名、年龄、性别、学号、分数):\n");
new=(struct student*)malloc(sizeof(struct student)); //分配内存空间,并返回指向该内存空间的指针
scanf("%s",new->name);
scanf("%d",&new->age);
scanf("%c",&new->sex);
scanf("%d",&new->no);
scanf("%d",&new->score);
new->next=head; //新节点指针指向原来首节点
head=new; //头指针指向新节点
count++; //增加链表节点数量
return head; //返回头指针
}
/*链表的插入需要为插入的链表分配内存,然后向新节点输入数据,这样一个新节点就创建完成了。如果需要将这个节点插入链表中,首先需要将新节点的指针指向原来的首节点,保存首节点的地址,然后将头指针指向新节点,这样就完成节点的连接操作,最后增加链表的节点数量*/
//删除链表节点
void delete(struct student*head,int n) //head表示头节点,n表示要删除节点序号或下标
{
int i; //控制循环次数
struct student*temp; //临时指针
struct student*p; //表示要删除节点前的节点
temp=head; //得到头节点
p=temp;
printf("删除学号为%d的学生\n",n);
for(i=1;i<n;i++) //for循环使temp指向要删除的节点
{
p=temp;
temp=temp->next;
}
p->next=temp->next; //连接删除节点两边节点
free(temp); //释放要删除节点的内存空间
count--; //减少链表中节点的元素个数
}
/*delete函数传递两个参数,head表示链表头指针,n表示要删除的节点在链表中位置。定义变量i用来控制循环次数,然后定义两个指针,分别表示要删除的节点和这个节点之前的节点。输出一行提示信息表示要进行删除操作,之后利用for语句进行循环操作找到要删除的节点,连接删除节点两边的节点,并使用free函数将temp指向的内存空间进行释放。之后在main函数中添加代码执行删除操作,将链表中第二个节点进行删除*/
int main(){
struct student*head; //定义头节点
head=creaead); //创建节点
head=insert(head); //增加学生信息
delete(head,1); //删除学生信息,例如删除第二个节点操作
print(head); //输出链表
return 0;
}
作者: dgrlucky 时间: 2015-4-22 21:39
#include <stdio.h>
int menu();
void init();
void listStu();
int insertNewStu(int row);
int deleteByNo();
void analyse();
int queryByNo();
int modifyInfoByNo();
int getStuRowByNo(char no[]);
char students[50][300] ;
int stu_num = 2;
void main()
{
int opt;
int result=1;
init();
while(result)
{
if(result==0)
{
break;
}
opt = menu();
switch(opt){
case 1:
//printf("\t执行操作:输入学员资料\n");
result = insertNewStu(stu_num);
stu_num=stu_num+1;
break;
case 2:
// printf("\t执行操作:删除学员资料\n");
result=deleteByNo();
stu_num=stu_num-1;
break;
case 3:
//printf("\t执行操作:查找学员资料\n");
result=queryByNo();
break;
case 4:
//printf("\t执行操作:修改学员资料\n");
result=modifyInfoByNo();
break;
case 5:
//printf("\t执行操作:输出学员信息数据\n");
listStu();
break;
case 0:
printf("\n\t谢谢使用!\n");
result=0;
break;
default:
printf("\t您的选择有误。\n");
}
}
}
int menu()
{
int option;
printf("\n\t--------------------------------------------------\n");
printf("\t|\t\t学员信息管理系统\t\t|\n");
printf("\t--------------------------------------------------\n\n");
printf("\t1.输入学员资料\n");
printf("\t2.删除学员资料\n");
printf("\t3.查找学员资料\n");
printf("\t4.修改学员资料\n");
printf("\t5.输出学员信息数据\n");
printf("\t0.退出\n\n");
printf("\t请选择您要进行的操作:");
scanf("%d",&option);
return option;
}
void init(){
strcpy(students[0], "2010-$-张学友-$-男-$-香港-$-13601234567-$-98-$-89-$-");
strcpy(students[1], "2011-$-王菲-$-女-$-北京-$-15887654321-$-99-$-100-$-");
}
void listStu()
{
char temp[300]="";
int i;
printf("\n\t****现存的学员信息****\n");
printf("学号\t");
printf("姓名\t");
printf("性别\t");
printf("地址\t");
printf("手机\t\t");
printf("Java\t");
printf(".Net\n");
//针对每一行,进行解析
for(i=0;i<stu_num;i++)
{
strcpy(temp,students[i]);
//打印每一行的每个信息项
while(strlen(temp)!=0)
{
analyse(temp);
}
printf("\n");
}
}
void analyse(char c[])
{
int i,j;
int token;
char p_temp[100]="";
//该行第一个分隔符前的信息项解析出来
for(j=0;j<strcspn(c, "-$-");j++)
{
p_temp[j]=c[j];
}
printf("%s\t",p_temp);
//去掉已经解析出的项,即把每项信息向前前移动位置
token=strcspn(c, "-$-");
for(j=0;j<strlen(c)-token;j++)
{
c[j]=c[token+3+j];
}
}
int insertNewStu(int row)
{
int flag=0;//标识前项信息是否录入正确
int i;
char stu_temp[1][300];//用于存储该学员的信息
int i_temp;
char n_temp[30];
char a_temp[10];
char c_temp[10];
//输入学号
while(flag==0)
{
printf("\n\t请输入学员学号:");
scanf("%d",&i_temp);
if(i_temp<1000 ||i_temp>9999)
{
printf("\t学号必须是4位数字!");
continue;
}else
{
sprintf(c_temp,"%d",i_temp);
strcpy(stu_temp[0], c_temp);
strcat(stu_temp[0], "-$-");
flag=1;
}
}
//输入姓名
while(flag==1)
{
printf("\n\t请输入学员姓名:");
scanf("%s",&n_temp);
if(strlen(n_temp) >= 20)
{
printf("\t姓名长度过长!\n");
continue;
}else
{
strcat(stu_temp[0], n_temp);
strcat(stu_temp[0], "-$-");
flag=2;
}
}
//输入性别
while(flag==2)
{
printf("\n\t请输入性别(1.男 2.女):");
scanf("%d",&i_temp);
if(i_temp!=1 && i_temp!=2)
{
printf("\t性别选择错误,请重新选择!\n");
continue;
}else
{
if(i_temp==1)
{
strcat(stu_temp[0], "男");
}else
{
strcat(stu_temp[0], "女");
}
strcat(stu_temp[0], "-$-");
flag=3;
}
}
//输入地址
while(flag==3)
{
printf("\n\t请输入学员地址:");
scanf("%s",&a_temp);
if(strlen(a_temp) >30)
{
printf("\t地址长度过长\n");
continue;
}else
{
strcat(stu_temp[0], a_temp);
strcat(stu_temp[0], "-$-");
flag=4;
}
}
//输入手机号
while(flag==4)
{
printf("\n\t请输入手机号码:");
scanf("%s",&c_temp);
//判断手机号码合法性
for(i = 0; i < strlen(c_temp); i++){
if(c_temp[i] < '0' || c_temp[i] > '9'){
printf("\t手机中包含非数字字符\n");
break;;
}
}
if(strlen(c_temp)!=11)
{
printf("\t手机位数不正确!");
continue;
}else
{
strcat(stu_temp[0], c_temp);
strcat(stu_temp[0], "-$-");
flag=5;
}
}
//输入成绩
while(flag==5)
{
printf("\n\t请输入Java成绩:");
scanf("%d",&i_temp);
if(i_temp<0 ||i_temp>100)
{
printf("\t成绩非法!");
continue;
}else
{
sprintf(c_temp,"%d",i_temp);
strcat(stu_temp[0], c_temp);
strcat(stu_temp[0], "-$-");
flag=6;
}
}
while(flag==6)
{
printf("\n\t请输入.Net成绩:");
scanf("%d",&i_temp);
if(i_temp<0 ||i_temp>100)
{
printf("\t成绩非法!");
continue;
}else
{
sprintf(c_temp,"%d",i_temp);
strcat(stu_temp[0], c_temp);
strcat(stu_temp[0], "-$-");
flag=7;
}
}
//确认新信息增加是否正确
printf("\n\t********确认学员信息如下********\n");
printf("\t%s",stu_temp);
printf("\n\n\t确认信息输入是否正确(Y/N):");
scanf("%s",&c_temp);
if(strcmp(c_temp,"y")==0 ||strcmp(c_temp,"Y")==0 )
{
strcpy(students[row],stu_temp[0]); //写入students的第row行
}else
{
insertNewStu(row);
}
return flag;
}
int getStuRowByNo(char no[])
{
int i,j;
int pos=-1;
char temp[5]="";
//按行搜索
for(i=0;i<stu_num;i++)
{
//搜索该行的列
for(j=0;j<strcspn(students[i],"-$-");j++)
{
temp[j]=students[i][j];
}
//如果找到,返回所在行i
if(strcmp(no,temp) == 0)
{
pos=i;
break;
}
}
return pos;
}
int deleteByNo()
{
char no[5];
int row;
int i,j;
printf("\n\t请输入要删除的学号:");
scanf("%s",no);
row=getStuRowByNo(no);//获取学员所在行
if(row==-1)
{
printf("\t\n********没有该学号学员的信息,请核实学号********\n");
return -1;
}else
{
for(i=row;i<50;i++)
{
for(j = 0; j < 300; j++)
students[i][j]=students[i+1][j];
}
printf("\n\t********删除成功********\n");
return 1;
}
}
int queryByNo()
{
char no[5];
int row;
char temp[300]="";
printf("\n\t请输入要查找的学号:");
scanf("%s",no);
row=getStuRowByNo(no);//获取学员所在行
if(row==-1)
{
printf("\t\n********没有该学号学员的信息,请核实学号********\n");
return -1;
}else
{
strcpy(temp,students[row]);
printf("\n********查找到学员信息如下********\n");
printf("学号\t");
printf("姓名\t");
printf("性别\t");
printf("地址\t");
printf("手机\t\t");
printf("Java\t");
printf(".Net\n");
while(strlen(temp)!=0)
{
analyse(temp);
}
printf("\n");
return 1;
}
}
int modifyInfoByNo()
{
char no[5];
int row;
char temp[300]="";
printf("\n\t请输入要修改的学号:");
scanf("%s",no);
row=getStuRowByNo(no);//获取学员所在行
if(row==-1)
{
printf("\t\n********没有该学号学员的信息,请核实学号********\n");
return -1;
}else
{
return insertNewStu(row);
//return 1;
}
}
作者: dgrlucky 时间: 2015-4-24 17:18
因代码受限,注释被我删除,你应该看得懂,请自行添加吧!功能完善:)
作者: 魔主 时间: 2015-4-24 19:29
既然没人解答,黑马币就给你了。
我的题目没改一个字就把代码提交了,得了9.5分
作者: 魔主 时间: 2015-4-24 19:36
不好意思,24小时评分超出限制,明天再评分吧。
作者: 魔主 时间: 2015-4-24 20:30
strcopy,strcat函数要加头文件#include<string.h>
void main()改为int main()
while中输入姓名、输入地址、输入手机号代码中scanf("%s",&a_temp);把取地址符去掉scanf("%s",a_temp);
确认新信息增加是否正确代码中 printf("\t%s",stu_temp);改为 printf(“\t%s”,*stu_temp)
有个问题,增加学生信息输完后,问是否正确(y\no),我故意输no,编译器报错,死循环了:请输入学号 四位数
编译器崩溃了,我晕;其他的功能没看
作者: dgrlucky 时间: 2015-4-24 22:52
好的!谢谢:P
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |