链表的删除操作中得到被删除指针的前一个节点时候的指针异常
今天在联系链表的删除操作,该工程包括list.h,list.c,main.c源代码分别如下:list.h
- C/C++ code
#ifndef _LIST_H#define _LIST_Htypedef struct _node{ void * data; struct _node *next;}NODE;typedef struct{ NODE *head; NODE *last; int length;}LIST;LIST * initList();int insertList(LIST *l,void *data,int size);NODE * findNodeByKey(LIST *l,void *key,int (*compare)(void *,void *));NODE * findNode(LIST *l,void *key,int (*compare)(void *,void *),NODE **pre);int deleteList(LIST *l,void *key,int (*compare)(void *,void *));#endif
list.c:我单步执行时到红色部分就异常了
- C/C++ code
#include"list.h"#include<stdio.h>NODE * findNode(LIST *l,void *key,int (*compare)(void *,void *),NODE **pre){ NODE *p = NULL; int s = 0; if(l == NULL || key == NULL || compare == NULL || pre == NULL){ return NULL; } p=l->head; pre = NULL; while(p){ if(compare(p->data,key) == 1){ printf("findNode-->find!"); return p; } [color=#FF0000]//报错 *pre = p;[/color] p = p->next; } return NULL;}int deleteList(LIST *l,void *key,int (*compare)(void *,void *)){ NODE *q=NULL,*p=NULL; /*这是一个很巧妙的编码方式 1.p指向findNode的返回值,也就是查找到的目标节点 2.q指向目标节点的前一个节点,是一个指向指针的指针 3.通过对p的非空判断可以知道是否存在目标节点 4.通过对q的非空判断可以知道目标节点是否是第一个节点 这是一个很灵活的编码方式! */ p = findNode(l,key,compare,&q); if(p == NULL){ //说明目标节点在链表中不存在 return 0; } if(q == NULL){ //说明目标节点是第一个节点,前面就是头结点 l->head = p->next; }else{ //目标节点不是第一个节点,把指针越过删除的节点 q->next = p->next; } //如果目标节点是最后一个节点呢 if(p == l->last){ l->last = q; } //先释放p的数据域,再释放p free(p->data); free(p); l->length --; return 1;}
main.c
在deleteList处开始函数的调用:
- C/C++ code
#include<stdio.h>#include<string.h>#include<stdlib.h>#include"list.h"struct STU{ char sno[5]; char sname[10]; int age; int scroe;}stu[3]={ {"100","avin",12,299}, {"101","tgip",52,239}, {"102","inca",23,439},};//专门比较姓名的函数int compareByName(void *info,void *key){ //强制类型转换 struct STU *stu = (struct STU *)info; char *name = (char *)key; return strcmp(stu->sname,name) == 0 ? 1 : 0;}//专门比较学号的函数int compareBySno(void *info,void *key){ //强制类型转换 struct STU *stu = (struct STU *)info; char *no = (char *)key; return strcmp(stu->sno,no) == 0 ? 1 : 0;}void main(){ NODE *res = NULL;//查找时候的返回结果 char name[] = "inca"; char no[]="101"; LIST *list = initList(); int i=0; for(;i<3;i++){ insertList(list,&stu[i],sizeof(stu[i])); } res = findNodeByKey(list,name,compareByName);//注意,这里compareByName的名字就代表该函数的地址 if(res == NULL){ printf("not found!\n"); }else{ //强制类型转换 struct STU *st = (struct STU *)res->data; printf("found! %d\n",st->scroe ); } /*注意这里的compareBySno 如果携程compareBySno()就表示是方法调用,将会以该方法的返回值传递进入deleteList中。 compareBySno表示将该函数的地址传递进去。 */ //这里开始删除函数的调用 [color=#FF0000]if(deleteList(list,no,compareBySno) == 1){ printf("delete Success!\n"); }else{ printf("delete failed!\n"); }[/color]}
希望各位帮忙看看,到底是哪错了……
[解决办法]
。。。早知道不看了。
------解决方案--------------------
我来帮你顶一下吧,我可以从头到尾好好看了一遍的,连那句“这是一个很巧妙的编程方式”也看了