C语言链表写入冲突
调试的显示是:心好累啊.exe 中的 0x0115173b 处有未经处理的异常: 0xC0000005: 读取位置 0xfeeefef2 时发生访问冲突
指向出问题的地方:
int length_list (NODE *pHead)
{
int len = 0;
NODE *p = pHead->pNext;
while (p != NULL)
{
len++;
printf("%d",len);
p = p->pNext;//这里显示有问题
}
printf("%d",len);
return len;
}
但是为什么会这样啊?
下附整个程序:(用动态链表实现报数报到3踢出局)
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//函数声明
struct NODE1
{
int data;
struct NODE1 * pNext;
};
typedef struct NODE1 NODE;
//typedef struct NODE1 * PNODE;
NODE * creat_list();
int length_list (NODE *pHead);
void delete_list(NODE *pHead, NODE *p);
int main()
{
NODE *pHead = creat_list();
int count = 0;
NODE *p = pHead;
while (length_list(pHead)>1)
{
p = p->pNext;
++ count;
if (count == 3 && p != NULL)
{
delete_list (pHead, p);
count = 0;
}
if (p == NULL)
{
p = pHead;
}
}
printf ("剩余的人的编号是:%d", pHead->pNext->data);
while (1);
return 0 ;
}
NODE *creat_list()
{
NODE *pHead = (NODE * )malloc(sizeof(NODE));
int len, data, i;
NODE * pTail;
printf("一共多少人玩(请输入人数):\n");
scanf_s ("%d", &len);
if (pHead == NULL)
{
printf ("分配内存失败,程序结束!");
exit(-1);
}
pHead->pNext = NULL;
pTail = pHead;
for (i=0; i<len; i++)
{
NODE *pNew = (NODE * )malloc(sizeof(NODE));
if (pNew == NULL)
{
printf ("分配内存失败,程序结束!");
exit(-1);
}
pNew->pNext = NULL;
pNew->data = i+1;
printf("%d",pNew->data);
pTail->pNext = pNew;
pTail = pNew;
}
printf("\n%d",pHead->pNext->data);
return pHead;
}
int length_list (NODE *pHead)
{
int len = 0;
NODE *p = pHead->pNext;
while (p != NULL)
{
len++;
printf("%d",len);
p = p->pNext;
}
printf("%d",len);
return len;
}
void delete_list(NODE *pHead, NODE *p)
{
//if (pHead->pNext == NULL)
// return false;
NODE *pTag = pHead->pNext; NODE *pFore = pHead;
while (pTag != p)
{
pFore = pTag;
pTag = pTag->pNext;
}
if (p->pNext != NULL)
{
pTag->pNext = p->pNext;
}
else pTag->pNext = NULL;
free (p);
p = NULL;
//return true;
} p = p->pNext 出错 肯定是因为p->pNext是一个无法访问的地址
动态调试看看 单步到崩溃的时候 看看此时p->pNext的值是什么 NODE *p = pHead->pNext;
这个你只是声明了一个NODE*类型的指针,但是没有在内存中给p开辟空间呀
改成
NODE *p = (NODE*)malloc(sizeof(NODE))
p = pHead->pNext;
再试试 地址错误 本帖最后由 mingcxx 于 2016-9-12 20:41 编辑
感觉你的代码思路有点乱,
创建节点时从第2个节点开始录入数据,整个程序运行中头结点数据一直是不定内存,浪费内存。
删除节点时却只释放了节点所占用的内存(而没有把待删除节点的前一个节点中指向该节点的Next指针更新NULL或指向目标节点的下一节点),那你的链表中依然链接了这个节点,只不过释放内存之后,这个节点的内存不可读。p = p->pNext;自然要出错。
以及没有释放链表占用的内存。
下面是仅仅无bug的修改代码,输出的数据意义不清晰(尤其第3行),依赖具体功能和代码思路需要进一步修改:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//函数声明
struct NODE1
{
int data;
struct NODE1 * pNext;
};
typedef struct NODE1 NODE;
//typedef struct NODE1 * PNODE;
NODE * creat_list();
int length_list(NODE *pHead);
void delete_list(NODE *pHead, NODE **p);
int main()
{
NODE *pHead = creat_list();
int count = 0;
NODE *p = pHead;
while (length_list(pHead)>1)
{
p = p->pNext;
++count;
if (count == 3 && p != NULL)
{
delete_list(pHead, &p);
count = 0;
}
if (p == NULL)
{
p = pHead;
}
if (count < 3)
break;
}
printf("剩余的人的编号是:%d", pHead->pNext->data);
while (1);
return 0;
}
NODE *creat_list()
{
NODE *pHead = (NODE *)malloc(sizeof(NODE));
int len, data, i;
NODE * pTail;
printf("一共多少人玩(请输入人数):\n");
scanf_s("%d", &len);
if (pHead == NULL)
{
printf("分配内存失败,程序结束!");
exit(-1);
}
pHead->pNext = NULL;
pTail = pHead;
for (i = 0; i<len; i++)
{
NODE *pNew = (NODE *)malloc(sizeof(NODE));
if (pNew == NULL)
{
printf("分配内存失败,程序结束!");
exit(-1);
}
pNew->pNext = NULL;
pNew->data = i + 1;
printf("%d", pNew->data);
pTail->pNext = pNew;
pTail = pNew;
}
printf("\n%d", pHead->pNext->data);
return pHead;
}
int length_list(NODE *pHead)
{
int len = 0;
NODE *p = pHead->pNext;
while (p != NULL)
{
len++;
printf("%d", len);
p = p->pNext;
}
printf("%d", len);
return len;
}
void delete_list(NODE *pHead, NODE **p)
{
//if (pHead->pNext == NULL)
// return false;
NODE *pTag = pHead; NODE *pFore = pHead;
while (pTag->pNext != *p)
{
pFore = pTag;
pTag = pTag->pNext;
}
if ((*p)->pNext != NULL)
{
pTag->pNext= (*p)->pNext;
}
else
pTag->pNext = NULL;
free((*p));
*p = NULL;
//return true;
} 本帖最后由 SingleLove 于 2016-9-12 21:25 编辑
问题就在你这个函数void delete_list(NODE *pHead, NODE *p)释放掉被选中的节点后;
main函数里的辅助指针找不到这个已经被释放掉的节点的地址了;所以就报错了
可以在void delete_list(NODE *pHead, NODE *p) 这个函数返回下一个节点的地址;
再用main函数里的辅助指针接一下:p = delete(pHead, p);
下面是我自己写的代码
#define _CRT_SECURE_NO_WARNINGS//我是在vs2013做的所以加了这句宏定义 防止 scanf 带来的error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//malloc() 等
#include <Windows.h>//Sleep()
//定义节点
typedef struct Node
{ //数据域
int data;
//指针域
struct Node *next;
}Node;
//创建链表
Node *creatList()
{
printf("请问有多少人玩游戏:");
int data;
scanf("%d", &data);
if (data <= 0)//判断输入的数字是否合法
{
printf("请输入大于0的玩家个数\n");
return NULL;
}
//创建头节点
Node * head = (Node *)malloc(sizeof(Node));
if (head == NULL)//判断是否成功分配内存
{
return NULL;
}
head->next = NULL;//头结点的指针域指向空
Node *cur = NULL;//保存尾结点
Node *pNew = NULL;//创建新节点
int i = 0;//用于给节点赋值
cur = head;//在没创建数据节点前头结点就是尾结点
while (cur != NULL)
{
i++;
if (cur->data == data)//当节点的值为data时跳出循环
{
break;
}
pNew = (Node *)malloc(sizeof(Node));//创建新节点
pNew->data = i;//给新节点赋值
cur->next = pNew;//使当前节点的next指向新节点
cur = pNew;//保存尾结点
pNew->next = NULL;//尾结点的next指向NULL
}
return head;//把头节点的地址返回
}
//释放被选中的节点
Node *DelList(Node *head, Node *delNode)
{
if (head == NULL)
{
return NULL;
}
//定义两个变量来查找这个节点和它上一个节点所在位置
Node *pre = head;//靠前的
Node *cur = head->next;
while (cur != NULL)
{
if (cur->data == delNode->data)//找到要释放的节点
{
break;
}
pre = pre->next;
cur = cur->next;
}
//跳出循环时 cur指向delNode这个节点, pre指向delNode的上一个节点
pre->next = cur->next;
free(cur);
cur = pre->next;
return cur;//这个很重要;楼主的段错误就是因为没有把这个地址返回造成的;
//当你把节点释放之后main函数里的辅助指针( tmp )再也找不到这个节点的地址,
//所以就报错了
//我返回的是被释放节点的下一个节点的地址
}
//获取剩余有效节点的个数(即剩余玩家的个数)
int listLength(Node *head)
{
if (head == NULL)//判断传入的地址是否有效
{
return -1;
}
int i = 0;//用于计算剩余玩家的个数
Node *tmp = head->next;//指向首节点
printf("尚未退出游戏的玩家编号分别是:\n");
while (tmp != NULL)
{
i++;
printf("%d,", tmp->data);//打印剩余玩家的编号
tmp = tmp->next;//跳向下一个数据节点
}
printf("\n");
return i;//返回剩余玩家的个数
}
int main()
{
while (1)//循环输入
{
Node *head = NULL;
head = creatList();//接返回的地址
if (head == NULL)//创建链表失败
{
return -1;
}
int count = 0;//用于数数;数到3则踢出一个玩家
Node *tmp = head->next;
int i = listLength(head);//有多少个玩家
while (i > 1)
{
if (tmp == NULL)
{
tmp = head->next;
}
count++;
if (count == 3 && tmp != NULL)
{
printf("被踢出局的玩家是 %d 号玩家\n", tmp->data);
tmp = DelList(head, tmp);
i = listLength(head);
count = 0;
continue;
}
tmp = tmp->next;
}
//最后跳出循环肯定只剩下一个玩家没有被踢出游戏的
tmp = head->next;//跳出循环时很可能tmp的值是NULL;
//例如 4 的时候
//那样就会造成段错误;所以需要重新指定下
printf("游戏结束尚未退出游戏的玩家的编号%d\n", tmp->data);
Sleep(3000);//让程序睡眠3秒;linux系统则是 3
system("cls");//清屏
}
printf("\n");
system("pause");
return 0;
}
{:10_249:}{:10_249:}感觉完全看不懂你到底想要实现什么功能{:10_249:}{:10_249:}
页:
[1]