记录或删除学生成绩的<链表>,但是不知道哪里出错了
/*********************************************************************** 动态记录学生成绩的链表 ************
************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define LEN sizeof(struct student) //student 结构大小
struct student* creat(); //创建链表(函数)
void print(struct student* head); //打印链表(函数)
void del(struct student* head, int dnum);//删除链表函数
void ask(int i);
struct student
{
int num;
float score;
struct student* next;
};
int n; //记录存放多少组数据
int main()
{
int i,dnum;
i = 0;
struct student* stu;
stu = creat();
print(stu);
printf("\n\n");
while (1)
{
ask(i);
scanf("%d", &i);
if (i == 1)
{
printf("\nPlease enter the number of the student:\n\tnum: ");
scanf_s("%d", &dnum);
del(stu, dnum);
print(stu);
}
else break;
}
system("pause");
}
struct student *creat()
{
struct student* head; //声明头部节点head
struct student* p1, * p2; //声明p1 p2,两个节点
p1 = p2 = (struct student*)malloc(LEN); //LEN是student结构大小
printf("Please enter the num:");
scanf_s("%d", &p1->num);
printf("Please enter the score:");
scanf_s("%f", &p1->score);
head = NULL; //head归零(不指向任意东西)
n = 0;
while (/*0!=*/p1->num) //p1不为零则循环,当输入0时停止循环
{
n++;
if (1 == n)
{
head = p1;
}
else
{
p2->next = p1;
}
p2 = p1;
p1 = (struct student*)malloc(LEN);
printf("\nPlease enter the num :");
scanf_s("%d", &p1->num);
printf("Please enter the score:");
scanf_s("%f", &p1->score);
}
p2->next = NULL;
return head;
}
void print(struct student* head) /*输出链表内容*/
{
struct student* p;
printf("\n There are %d records!\n\n", n);
p = head;
if (/*NULL!+*/head)
{
do
{
printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
p = p->next;
} while (/*NULL!=*/p);
}
}
void del(struct student *head,int dnum) //删除链表函数
{
struct student * p1, * p2;
int a = 0;
if (head == NULL) { printf("This is a empty form"); }
else
{
p1 = head;
p2 = NULL;
while (dnum != p1->num && p1!=NULL)
{
p2 = p1;
p1 = p1->next;
a++;
}
if (p1!=NULL)
{
if (p1 == head)
{
head = p1->next;
}
else
{
p2->next = p1->next;
}
printf("\nThe data of < %d > had been deleted!\n\n",dnum);
n = n - 1;
}
else if(p1==NULL)
{
printf("\nNo student withnumber %d was found.\n\n", dnum);
}
}
}
void ask(int i)
{
printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
} 本帖最后由 SHRS23 于 2020-8-3 17:55 编辑
/***********************************************************
************ 动态记录学生成绩的链表 ************
************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define LEN sizeof(struct student) //student 结构大小
struct student *creat(); //创建链表(函数)
void print(struct student *head); //打印链表(函数)
void del(struct student *head, int dnum);//删除链表函数
void ask(int i);
struct student
{
int num;
float score;
struct student *next;
};
int n; //记录存放多少组数据
int main()
{
int i, dnum;
i = 0;
struct student *stu;
stu = creat();
print(stu);
printf("\n\n");
while(1)
{
ask(i);
scanf("%d", &i);
if(i == 1)
{
printf("\nPlease enter the number of the student:\n\tnum: ");
scanf("%d", &dnum);
del(stu, dnum);
print(stu);
}
else
{
break;
}
}
system("pause");
}
struct student *creat()
{
struct student *head; //声明头部节点head
struct student *p1, * p2; //声明p1 p2,两个节点
p1 = p2 = (struct student *)malloc(LEN); //LEN是student结构大小
printf("Please enter the num:");
scanf("%d", &p1->num);
printf("Please enter the score:");
scanf("%f", &p1->score);
head = NULL; //head归零(不指向任意东西)
n = 0;
while(/*0!=*/p1->num) //p1不为零则循环,当输入0时停止循环
{
n++;
if(1 == n)
{
head = p1;
}
else
{
p2->next = p1;
}
p2 = p1;
p1 = (struct student *)malloc(LEN);
printf("\nPlease enter the num :");
scanf("%d", &p1->num);
printf("Please enter the score:");
scanf("%f", &p1->score);
}
p2->next = NULL;
return head;
}
void print(struct student *head) /*输出链表内容*/
{
struct student *p;
printf("\n There are %d records!\n\n", n);
p = head;
if(/*NULL!+*/head)
{
do
{
printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
p = p->next;
}
while(/*NULL!=*/p);
}
}
void del(struct student *head, int dnum) //删除链表函数
{
struct student *p1, * p2;
int a = 0;
if(head == NULL)
{
printf("This is a empty form");
}
else
{
p1 = head;
p2 = NULL;
while(dnum != p1->num && p1 != NULL)
{
p2 = p1;
p1 = p1->next;
a++;
}
if(p1 != NULL)
{
if(p1 == head)
{
head = p1->next;
}
else
{
p2->next = p1->next;
}
printf("\nThe data of < %d > had been deleted!\n\n", dnum);
n = n - 1;
}
else if(p1 == NULL)
{
printf("\nNo student withnumber %d was found.\n\n", dnum);
}
}
}
void ask(int i)
{
printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
}
做了个简单的小测试,程序本身问题不大
我想问一下你的调试运行环境是是什么
如果你用的visual studio并且你清楚你为什么要用scanf_s,那么修改方法就是把scanf_s缺少的参数补上;
如果你用的不是VS或者你不知道scanf_s是什么,那就像我上面的程序一样,把所有的scanf_s替换成scanf。
以下内容来自百度百科:
ANSI C中没有scanf_s(),只有scanf(),scanf()在读取时不检查边界,所以可能会造成内存访问越界,例如分配了5字节的空间但是读入了10字节
char buf={'\0'};
scanf("%s", buf);
如果输入1234567890,后面的部分会被写到别的空间上去。
以上代码如果用scanf_s,第二行应改为scanf_s("%s",buf,5),表示最多读取5-1个字符,因为buf要放'\0'
scanf_s最后一个参数是缓冲区的大小,表示最多读取n-1个字符.
vc++2005/2008中提供了scanf_s(),在最新的VS2015中也提供了scanf_s()。在调用时,必须提供一个数字以表明最多读取多少位字符。
3.读取单个字符也需要限定长度:scanf_s("%c,%c",&c1,1,&c2,1);而不能写成scanf_s("%c,%c",&c1, &c2,1, 1);否则编译器会报错 一个更详细的参考“:
https://blog.csdn.net/qq_43309823/article/details/95386759 本帖最后由 baige 于 2020-8-3 18:45 编辑
删除那里需要用二级指针, 删除时对学号的判断以及链表是否为空有bug,当p1==NULL,p1->num是未知的,产生bug;
https://blog.csdn.net/qq_39032310/article/details/81746742
#include<stdio.h>
#include<stdlib.h>
#define LEN sizeof(struct student)//student 结构大小
struct student* creat();//创建链表(函数)
void print(struct student* head);//打印链表(函数)
void del(struct student** head, int dnum);//删除链表函数
void ask(int i);// 是否需要删除结点
struct student
{
int num;
float score;
struct student* next;
};
int n;//记录存放多少组数据
int main()
{
int i = 0,dnum;
struct student* stu;
stu = creat();
print(stu);
printf("\n\n");
while (1)
{
ask(i);
scanf("%d", &i);// 输入i
if (i == 1) // 当i==1需要删除结点
{
printf("\nPlease enter the number of the student:\n\tnum: ");
scanf("%d", &dnum); //
del(&stu, dnum);
print(stu);
}
else break;
}
system("pause");
return 0;
}
struct student *creat()
{
struct student* head;//声明头部节点head
struct student* p1, * p2;//声明p1 p2,两个节点
p1 = p2 = (struct student*)malloc(LEN); //LEN是student结构大小
printf("Please enter the num:");
scanf("%d", &p1->num);
head = NULL;
p1->next = NULL; // 初始化p1指针域
printf("Please enter the score:");
scanf("%f", &p1->score);
n = 0;
while (p1->num) //p1不为零则循环,当输入0时停止循环
{
n++;
if (1 == n)
{
head = p1;
}
else
{
p2->next = p1;
}
p2 = p1;
p1 = (struct student*)malloc(LEN);
printf("\nPlease enter the num :");
scanf("%d", &p1->num);
printf("Please enter the score:");
scanf("%f", &p1->score);
}
p2->next = NULL;
return head;
}
void print(struct student* head) /*输出链表内容*/
{
struct student* p = head;
printf("\n There are %d records!\n\n", n);
if(head)
{
do
{
printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
p = p->next;
} while (p);
}
}
void del(struct student **head,int dnum) //删除链表函数
{
struct student *p1, *p2;
int a = 0;
if (*head == NULL)
{
printf("This is a empty form");
}
else
{
p1 = *head;
p2 = NULL;
while (dnum != p1->num) // 当p1->num == dumn或 p1 == NULL 退出循环 ,当p1==NULL时,p1->num位置,会导致程序发生未知错误
{
p2 = p1;
p1 = p1->next;
a++;
if(p1==NULL)break;// 所以我把p1==NULL退出循环写到这里
}
if (p1!=NULL)
{
if (p1 == *head)
{
*head = p1->next;
}
else
{
p2->next = p1->next;
}
printf("\nThe data of < %d > had been deleted!\n\n",dnum);
n = n - 1;
}
else
{
printf("\nNo student withnumber %d was found.\n\n", dnum);
}
}
}
void ask(int i)
{
printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
}
本帖最后由 baige 于 2020-8-4 08:20 编辑
{:10_277:} baige 发表于 2020-8-3 18:49
删除那里用2级指针,以及对于删除时判断p1->num和p1==NULL会产生bug,当p1==NULL,p1->num是未知的;
把scanf改回去就可以了 本帖最后由 baige 于 2020-8-3 19:40 编辑
你的代码,已修改
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define LEN sizeof(struct student) //student 结构大小
struct student* creat(); //创建链表(函数)
void print(struct student* head); //打印链表(函数)
void del(struct student** head, int dnum);//删除链表函数
void ask(int i);
struct student
{
int num;
float score;
struct student* next;
};
int n; //记录存放多少组数据
int main()
{
int i,dnum;
i = 0;
struct student* stu;
stu = creat();
print(stu);
printf("\n\n");
while (1)
{
ask(i);
scanf("%d", &i);
if (i == 1)
{
printf("\nPlease enter the number of the student:\n\tnum: ");
scanf("%d", &dnum);
del(&stu, dnum);
print(stu);
}
else break;
}
system("pause");
}
struct student *creat()
{
struct student* head; //声明头部节点head
struct student* p1, * p2; //声明p1 p2,两个节点
p1 = p2 = (struct student*)malloc(LEN); //LEN是student结构大小
printf("Please enter the num:");
scanf("%d", &p1->num);
printf("Please enter the score:");
scanf("%f", &p1->score);
head = NULL; //head归零(不指向任意东西)
n = 0;
while (/*0!=*/p1->num) //p1不为零则循环,当输入0时停止循环
{
n++;
if (1 == n)
{
head = p1;
}
else
{
p2->next = p1;
}
p2 = p1;
p1 = (struct student*)malloc(LEN);
printf("\nPlease enter the num :");
scanf("%d", &p1->num);
printf("Please enter the score:");
scanf("%f", &p1->score);
}
p2->next = NULL;
return head;
}
void print(struct student* head) /*输出链表内容*/
{
struct student* p;
printf("\n There are %d records!\n\n", n);
p = head;
if (/*NULL!+*/head)
{
do
{
printf("学号为 < %d > 的成绩是:%f\n", p->num, p->score);
p = p->next;
} while (/*NULL!=*/p);
}
}
void del(struct student **head,int dnum) //删除链表函数
{
struct student * p1, * p2;
int a = 0;
if (*head == NULL) { printf("This is a empty form"); }
else
{
p1 = *head;
p2 = NULL;
while (p1!=NULL&&dnum != p1->num)//短路
{
p2 = p1;
p1 = p1->next;
a++;
}
if (p1!=NULL)
{
if (p1 == *head)
{
*head = p1->next;
}
else
{
p2->next = p1->next;
}
printf("\nThe data of < %d > had been deleted!\n\n",dnum);
n = n - 1;
}
else if(p1==NULL)
{
printf("\nNo student withnumber %d was found.\n\n", dnum);
}
}
}
void ask(int i)
{
printf("Do you want to delete a data of student?\nif you want,please enter int'1',else enter int'0'\n\n||--->Enter:");
} baige 发表于 2020-8-3 19:15
你的代码,已修改
感谢感谢。 可以的话给个最佳,谢谢
页:
[1]