C++循环链表,插入函数,读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突(猜测是指针
本帖最后由 菜鸟小乔 于 2019-5-31 21:53 编辑循环链表,目前只写了插入函数,调用时出问题。
初始化一个空循环环链表,调用插入函数,插入第一个结点。
编译可以通过,运行时异常中断。
异常中断报错:
0x00007FFF74A8135A (vcruntime140d.dll)处(位于 ch2_3.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。
中断同时弹出一个xstring文件。
.h文件--------------------------------
#ifndef CircularLinkList_h_include
#define CircularLinkList_h_include
/* 《循环链表》
*/
#include<iostream>
using namespace std;
//定义一种数据类型
typedef struct {
int id;
string name;
}EleType;
//循环链表节点,
typedef struct Node {
EleType data;
struct Node* next;
}Node;
//定义 循环链表的结构
typedef struct C_LinkList {
Node* next; //头指针(有头节点,)
int length; //链表长度,初始值为0.
}C_LinkList;
//插入元素
void Insert(C_LinkList* list_c, int pos, EleType element);
//打印
void Print(C_LinkList* list_c);
#endif
------.cpp文件----------------
#include<iostream>
#include"C_list.h"
using namespace std;
//初始化
void Init(C_LinkList* list_c, EleType* dataArray, int len)
{
}
//插入元素
void Insert(C_LinkList* list_c, int pos, EleType element)
{
//定义空节点
Node* node = (Node*)malloc(sizeof(struct Node));
node->data = element; //如果注释掉这一行就可以运行,但是就没办法给data赋值了!!!
node->next = NULL;
if (pos == 1)
{
node->next = list_c->next;
if (!node->next) //如果链表长度为零
{
cout<<"长度为零"<<endl;
node->next = node;
}
else//长度不为零,找到最后一个节点,并改变其指针域
{
cout << "长度不为零" << endl;
Node* lastnode = list_c->next;
for (int i = 1; i < list_c->length; i++)
{
lastnode = lastnode->next;
}
lastnode->next = node;
}
list_c->next = node;
list_c->length++;
return;
}//
cout << "pos不等于1" << endl;
//插入pos不是第一个:从第一个开始遍历
Node* currNode = list_c->next;
for (int i = 1; currNode && i < pos - 1; i++)
{
currNode = currNode->next;
}
if (currNode)
{
cout << "pos不等于1" << endl;
node->next = currNode->next;
currNode->next = node;
list_c->length++;
if (pos == list_c->length)//如果是最后一个结点
{
node->next = list_c->next;//改变最后一个节点的指针域为指向第一个结点
}
}
}
///////////////////////////////////
void Print(C_LinkList *list_c)
{
if (list_c->length == 0 || list_c->next == NULL)
{
cout << "链表为空,无内容可打印!" << endl;
list_c->length = 0;
return;
}
//链表不为空时打印:
Node* node = list_c->next; //创建临时结点为第一个结点开始遍历
for (int i = 0; i < list_c->length; i++)
{
cout << node->data.id << ":" << node->data.name << endl;
node = node->next;
}
}
--------main函数--------
#include<iostream>
#include"C_list.h"
using namespace std;
//测试数据
EleType dataArray[]{
{1,"香蕉"},
{2,"樱桃"},
{3,"菠萝"},
{4,"苹果"}
};
//测试函数
void test();
int main()
{
test();
return 0;
}
////////////////
void test()
{
C_LinkList* clist = (C_LinkList*)malloc(sizeof(C_LinkList));//初始化空的循环链表
clist->next = NULL;
clist->length = 0;
Insert(clist, 1, dataArray);//在第一个位置插入元素
Print(clist);//打印
free(clist);
}
我想问一个问题,如果循环列表只有一个元素时,是不是list->next = &list ? 我就是个弟弟 发表于 2019-5-31 21:54
我想问一个问题,如果循环列表只有一个元素时,是不是list->next = &list ?
嗯 我就是个弟弟 发表于 2019-5-31 21:54
我想问一个问题,如果循环列表只有一个元素时,是不是list->next = &list ?
{:5_99:}你把我问住了。。。
你这个问题是不是等价于“第一个元素的地址”==“头结点的地址”?
如果是这样的话,我觉得是不等的,“第一个元素的地址”==“头结点->next指向的地址” !="头结点的地址"
以上只是我的个人理解,我刚开始学编程,很多东西都不懂。。。。。还想求大神赐教呢~ 我就是个弟弟 发表于 2019-5-31 21:54
我想问一个问题,如果循环列表只有一个元素时,是不是list->next = &list ?
不对,他这个是
在没有元素时list->next = NULL;
只有一个元素时
list->next指向第一个元素,第一个元素的next是自己的地址
我就是个弟弟 发表于 2019-5-31 21:54
我想问一个问题,如果循环列表只有一个元素时,是不是list->next = &list ?
(gdb) print clist
$1 = (C_LinkList *) 0x601000000000
(gdb) print *clist
$2 = {next = 0x603000000000, length = 1}
(gdb) print clist->next
$3 = (Node *) 0x603000000000
(gdb) print *clist->next
$4 = {data = {id = 3, name = "菠萝"}, next = 0x603000000000}
(gdb)
人造人 发表于 2019-5-31 22:17
不对,他这个是
在没有元素时list->next = NULL;
只有一个元素时
所以大神能帮我看看代码的问题出在哪里吗? 猜测是野指针,可是我检查代码没看到有没初始化的指针。。。
菜鸟小乔 发表于 2019-5-31 22:17
你把我问住了。。。
你这个问题是不是等价于“第一个元素的地址”==“头结点的地址”?
C_LinkList 我觉得这个没有必要,而且当你向堆申请内存的时候一定哟记得释放掉,可以写一个释放内存的函数。
还有很神奇的时我用我的编译器编译出来的程序居然会一直卡住。。。 我就是个弟弟 发表于 2019-5-31 22:22
C_LinkList 我觉得这个没有必要,而且当你向堆申请内存的时候一定哟记得释放掉,可以写一个释放内存的函 ...
我试了free,但是还是会出同样的问题。 菜鸟小乔 发表于 2019-5-31 22:20
所以大神能帮我看看代码的问题出在哪里吗? 猜测是野指针,可是我检查代码没看到有没初始化的指针。。。
...
既然pos == 1,那还找什么?一定就是它指向它自己呀
还有,node->next 在21行明确赋值为NULL,25行一定成立
“既然pos == 1,那还找什么?一定就是它指向它自己呀
还有,node->next 在21行明确赋值为NULL,25行一定成立”
嗯,“既然pos == 1,那还找什么?一定就是它指向它自己呀”
这个是我理解错了
但是 “还有,node->next 在21行明确赋值为NULL,25行一定成立”
这个的确不对
人造人 发表于 2019-5-31 22:29
“既然pos == 1,那还找什么?一定就是它指向它自己呀
还有,node->next 在21行明确赋值为NULL,25行一定 ...
pos==1,时,有两种情况,一种是链表为空和链表不为空,所以要分情况讨论。
19行node->next=NULL;是给node指针域赋初值,避免野指针。在23行,node->next被重新赋值了,所以后面25行需要判断它是否为空。 菜鸟小乔 发表于 2019-5-31 22:39
pos==1,时,有两种情况,一种是链表为空和链表不为空,所以要分情况讨论。
19行node->next=NULL;是 ...
等一等,我研究研究 在C_list.h中加一个
#include <string>
#ifndef CircularLinkList_h_include
#define CircularLinkList_h_include
/* 《循环链表》
*/
#include <iostream>
#include <string>
using namespace std;
//定义一种数据类型
typedef struct {
int id;
string name;
}EleType;
//循环链表节点,
typedef struct Node {
EleType data;
struct Node* next;
}Node;
//定义 循环链表的结构
typedef struct C_LinkList {
Node* next; //头指针(有头节点,)
int length; //链表长度,初始值为0.
}C_LinkList;
//插入元素
void Insert(C_LinkList* list_c, int pos, EleType element);
//打印
void Print(C_LinkList* list_c);
#endif
人造人 发表于 2019-5-31 22:47
在C_list.h中加一个
#include
试了#include<string>,不行。。。问题复现。 菜鸟小乔 发表于 2019-5-31 22:52
试了#include,不行。。。问题复现。
你用哪个ide ?
vs ? 人造人 发表于 2019-5-31 22:53
你用哪个ide ?
vs ?
VS2019 菜鸟小乔 发表于 2019-5-31 22:55
VS2019
malloc没有调用string的构造函数,EleType中的name这个string对象不存在,不能调用这个name对象的拷贝构造函数
有两个修改方案
1.用new替换malloc
2.在指定地址构造对象
我对于当前这个问题,不推荐第二种解决方案
/* 《循环链表》
*/
#include<iostream>
#include <string>
using namespace std;
//定义一种数据类型
typedef struct
{
int id;
string name;
}EleType;
//循环链表节点,
typedef struct Node
{
EleType data;
struct Node* next;
}Node;
//定义 循环链表的结构
typedef struct C_LinkList
{
Node* next; //头指针(有头节点,)
int length; //链表长度,初始值为0.
}C_LinkList;
//插入元素
void Insert(C_LinkList* list_c, int pos, EleType element);
//打印
void Print(C_LinkList* list_c);
//初始化
void Init(C_LinkList* list_c, EleType* dataArray, int len)
{
}
//插入元素
void Insert(C_LinkList* list_c, int pos, EleType element)
{
//定义空节点
//Node* node = (Node*)malloc(sizeof(struct Node));
//node->data = element; //如果注释掉这一行就可以运行,但是就没办法给data赋值了!!!
//node->next = NULL;
Node* node = new Node;
node->data = element; //如果注释掉这一行就可以运行,但是就没办法给data赋值了!!!
node->next = NULL;
if(pos == 1)
{
node->next = list_c->next;
if(!node->next) //如果链表长度为零
{
cout << "长度为零" << endl;
node->next = node;
}
else//长度不为零,找到最后一个节点,并改变其指针域
{
cout << "长度不为零" << endl;
Node* lastnode = list_c->next;
for(int i = 1; i < list_c->length; i++)
{
lastnode = lastnode->next;
}
lastnode->next = node;
}
list_c->next = node;
list_c->length++;
return;
}//
cout << "pos不等于1" << endl;
//插入pos不是第一个:从第一个开始遍历
Node* currNode = list_c->next;
for(int i = 1; currNode && i < pos - 1; i++)
{
currNode = currNode->next;
}
if(currNode)
{
cout << "pos不等于1" << endl;
node->next = currNode->next;
currNode->next = node;
list_c->length++;
if(pos == list_c->length)//如果是最后一个结点
{
node->next = list_c->next;//改变最后一个节点的指针域为指向第一个结点
}
}
}
///////////////////////////////////
void Print(C_LinkList *list_c)
{
if(list_c->length == 0 || list_c->next == NULL)
{
cout << "链表为空,无内容可打印!" << endl;
list_c->length = 0;
return;
}
//链表不为空时打印:
Node* node = list_c->next; //创建临时结点为第一个结点开始遍历
for(int i = 0; i < list_c->length; i++)
{
cout << node->data.id << ":" << node->data.name << endl;
node = node->next;
}
}
//测试数据
EleType dataArray[]{
{1, "香蕉"},
{2, "樱桃"},
{3, "菠萝"},
{4, "苹果"}
};
//测试函数
void test();
int main()
{
test();
return 0;
}
////////////////
void test()
{
C_LinkList* clist = (C_LinkList*)malloc(sizeof(C_LinkList));//初始化空的循环链表
clist->next = NULL;
clist->length = 0;
Insert(clist, 1, dataArray);//在第一个位置插入元素
Print(clist);//打印
free(clist);
}
本帖最后由 菜鸟小乔 于 2019-6-1 00:33 编辑
人造人 发表于 2019-5-31 23:02
malloc没有调用string的构造函数,EleType中的name这个string对象不存在,不能调用这个name对象的拷贝构 ...
感谢大神指教,学到了~~{:5_106:} 菜鸟小乔 发表于 2019-5-31 23:49
你修改的内容是:用54-56行替换 48-50行,我试了像你这样把malloc换成new,然后test函数里用栈内存如下, ...
把代码贴完整
页:
[1]
2