C语言链表删除问题求解!
void shanchu(stu *p){
int i;
printf("请输入删除学生的学号\n");
scanf("%d",&i);
stu * temp =p;
p=p->pnext;
while (p != NULL)
{
if(p->num==i)
{
temp->pnext= p->pnext;
free(p);
p=temp->pnext;//上面的P已经被free掉了,再赋值是不是需要重新定义类型??
}
temp=temp->pnext;
p=p->pnext;
}
p已经被free相当于p的函数已经释放,下面这一步是不是有问题 free掉的是p中的内容。p本身还是存在的。p就是一个地址的代号。这个是不会删掉的。 本帖最后由 jackz007 于 2019-9-22 15:49 编辑
p 只是一个指针,free(p) 所释放的只是 p 所指向的一片内存区域,这片区域,之前是用 p = (stu *)malloc(sizeof(stu)) 从系统中分配得到的。执行完 free(p) ,作为指针本身,p 仍然是存在和可以继续使用的一个 stu * 型的指针。
p 被释放后,在被重新指向其它节点之前,不可以被继续作为一个 stu 型的节点来使用和访问。
如果想创建一个新节点,可以使用 malloc() 先分配内存:
p = (stu *)malloc(sizeof(stu))
然后,就可以通过指针 p 来把数据保存在新节点里面了。 本帖最后由 seglex 于 2019-9-22 17:01 编辑
jackz007 发表于 2019-9-22 15:39
p 只是一个指针,free(p) 所释放的只是 p 所指向的一片内存区域,这片区域,之前是用 p = (stu *)m ...
我试了加了p=(stu *)malloc(sizeof (stu));得出的结果是一样的。
还想请问一下,我发图片回复,您帮我看看
https://raw.githubusercontent.com/alexnijd/test/master/tianruo_2019-9-22-637047677620765921.png
https://raw.githubusercontent.com/alexnijd/test/master/26.png seglex 发表于 2019-9-22 16:58
我试了加了p=(stu *)malloc(sizeof (stu));得出的结果是一样的。
还想请问一下,我发图片回复,您帮我 ...
楼主,贴代码文本要比贴图片简单容易的多,找到文本输入区上方的快捷工具栏,按下标有 "<>" 的按钮,把代码文本贴到新弹出的代码框里就得了。 jackz007 发表于 2019-9-22 17:18
楼主,贴代码文本要比贴图片简单容易的多,找到文本输入区上方的快捷工具栏,按下标有 "" 的按钮, ...
好的,您看看
# include <stdio.h>
# include <stdlib.h>
typedef struct student
{
int num;
char name;
struct student *pnext;
}stu;
//添加一个新节点
void addnode (stu *p)
{
int n;
printf("input\n");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
stu* pnew;
pnew =(stu*)malloc(sizeof(stu));
printf("请输入学员的信息\n");
printf("姓名");
scanf("%s",pnew->name);
printf("学号");
scanf("%d",&pnew->num);
p->pnext = pnew;
p=p->pnext;
}
}
void print(stu *q)
{
q=q->pnext;
printf("\n==================\n");
while(q!= NULL)
{
printf("%d\t%s\n",q->num,q->name);
q=q->pnext;
}
}
void shanchu(stu *p)
{
int i;
printf("请输入删除学生的学号\n");
scanf("%d",&i);
stu * temp =p;//p(头地址)的值赋值给临时变量temp
p=p->pnext;//首地址第一个有效数字地址赋值给p
while (p != NULL)
{
if(p->num==i)
{
temp->pnext= p->pnext;
free(p);//释放当前结构体下的p
p=(stu *)malloc(sizeof (stu));
p =temp->pnext;//指向下一个结构体的p
printf("指针的值:%d",p->num);
}
temp=temp->pnext;// 头地址自增
p=p->pnext;//首地址自增 ,
}
int main()
{
stu *p;
p =(stu *)malloc(sizeof(stu));
p->pnext ;
addnode(p);
print(p);
shanchu(p);
print(p);
return 0;
} 本帖最后由 jackz007 于 2019-9-22 17:58 编辑
stu * shanchu(stu *p)
{
stu * q , temp ;
int i;
q = NULL ;
printf("请输入删除学生的学号\n");
scanf("%d",&i);
if (p -> num == i) {
q = p ;
p = p -> pnext ;
} else {
while (p -> pnext != NULL) {
if(p -> pnext -> num == i) {
q = p -> pnext ;
p -> pnext = p -> pnext -> pnext
break ;
}
p = p -> pnext ;
}
}
if(q) {
free(q) ;
} else {
printf("没有找到节点!\n")
}
return(p) ;
} jackz007 发表于 2019-9-22 17:36
这一段中我输入三个数,分别是11 22 22
得到的结果并不是我想象的那样,只删除第一个值,后面的值并没有删除
https://raw.githubusercontent.com/alexnijd/test/master/tianruo_2019-9-22-637047677620765921.png 本帖最后由 jackz007 于 2019-9-23 00:17 编辑
seglex 发表于 2019-9-22 17:46
这一段中我输入三个数,分别是11 22 22
得到的结果并不是我想象的那样,只删除第一个值,后面的值并没有 ...
这是我系统地为你修改的代码,新增加了几个函数,你测试一下,看看能否解决你的问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
int num ;
char name ;
struct student * pnext ;
} stu ;
int strip(char * s)
{
int b , k , m ;
m = strlen(s) ;
while(m > 0 && (s == 0x07 || s == 0x0a || s == 0x0d || s == 0x20)) {
s = 0x00 ;
m -- ;
}
if(m > 0) {
b = 0 ;
while(b < m && (s == 0x07 || s == 0x0a || s == 0x0d || s == 0x20)) b ++ ;
if(b > 0 && b < m) {
for(k = b ; k < m ; k ++) s = s ;
s = 0x00 ;
m -= b ;
}
}
return m ;
}
int getnum(int * num)
{
int m , ret ;
char s ;
ret = 0 ;
* num = ret ;
for(;;) {
printf("输入学号 : ") ;
fgets(s , 256 , stdin) ;
if(strip(s)) {
if(sscanf(s , "%d" , & m) == 1) {
ret = m ;
* num = ret ;
break ;
} else {
fprintf(stderr , "输入错误!\n\n") ;
}
} else {
break ;
}
}
return ret ;
}
char * getname(char * name)
{
char s , * ret ;
name = '\0' ;
ret = name ;
printf("输入姓名 : ") ;
fgets(s , 256 , stdin) ;
if(strip(s)) strcpy(name , s) ;
return ret ;
}
stu * findnode(int num , stu * p)
{
stu * ret ;
ret = NULL ;
while(p) {
if(p -> num == num) {
ret = p ;
break ;
} else {
p = p -> pnext ;
}
}
return ret ;
}
stu * addnode(stu * p)
{
int num ;
stu * h , * q ;
char name ;
bool f ;
f = true ;
h = p ;
printf("\n") ;
printf("*** 录入学员信息 ***\n") ;
for(; f ;) {
p = h ;
printf("\n") ;
if(getnum(& num)) {
if(! findnode(num , p)) {
if(strlen(getname(name))) {
q = (stu *) malloc(sizeof(stu)) ;
q -> num = num ;
strcpy(q -> name , name) ;
q -> pnext = NULL ;
if(p) {
while(p -> pnext) p = p -> pnext ;
p -> pnext = q ;
} else {
p = q ;
h = p ;
}
} else {
f = false ;
}
} else {
fprintf(stderr , "错误:节点已经存在!\n\n") ;
}
} else {
f = false ;
}
}
return h ;
}
stu * delnode(stu * p)
{
int num ;
stu * h , * q ;
bool f ;
f = true ;
printf("\n") ;
printf("*** 删除学员信息 ***\n") ;
h = p ;
if(p) {
for(; f ;) {
if(h) {
p = h ;
printf("\n") ;
if(getnum(& num)) {
if((q = findnode(num , p))) {
while(p != q && p -> pnext && p -> pnext != q) p = p -> pnext ;
if(p == q || p -> pnext == q) {
if(p == q) h = p -> pnext ;
else p -> pnext = q -> pnext ;
free(q) ;
}
} else {
fprintf(stderr , "错误:节点未找到!\n\n") ;
}
} else {
f = false ;
}
} else {
printf("\n") ;
printf("链表节点已经全部删除!\n\n") ;
f = false ;
}
}
} else {
fprintf(stderr , "错误:链表为空!\n\n") ;
}
return h ;
}
void print(stu * p)
{
printf("\n") ;
printf("*** 显示学员信息 ***\n") ;
if(p) {
while(p) {
printf("%d\t%s\n" , p -> num , p -> name) ;
p = p -> pnext ;
}
} else {
fprintf(stderr , "错误:链表为空!\n\n") ;
}
}
int main(void)
{
stu * p ;
p = NULL ;
p = addnode(p) ;
print(p) ;
p = delnode(p) ;
print(p) ;
}
这个代码花了比较大的力气在键盘输入检测方面,任何时候,如果从键盘获取的参数是空回车,则随时结束输入。 jackz007 发表于 2019-9-22 23:30
这是我系统地为你修改的代码,新增加了几个函数,你测试一下,看看能否解决你的问题。
非常感谢,我会仔细阅读参考的
页:
[1]