C 从结构的动态数组中删除元素时的未定义行为
我动态分配了一个n大小的结构数组,数组的每个位置也是一个数组,每个位置的大小不同(一个数组数组) 我创建了一个函数来删除给定的数组[index],但我面临一些未定义的行为,例如: 如果数组大小为3,如果删除数组[0],则无法访问数组[1]。其他索引组合也会出现这种情况。它完美运行的唯一方式是从一开始就删除 以下是我的代码: 结构:C 从结构的动态数组中删除元素时的未定义行为,c,arrays,struct,dynamic-memory-allocation,C,Arrays,Struct,Dynamic Memory Allocation,我动态分配了一个n大小的结构数组,数组的每个位置也是一个数组,每个位置的大小不同(一个数组数组) 我创建了一个函数来删除给定的数组[index],但我面临一些未定义的行为,例如: 如果数组大小为3,如果删除数组[0],则无法访问数组[1]。其他索引组合也会出现这种情况。它完美运行的唯一方式是从一开始就删除 以下是我的代码: 结构: typedef struct point{ char id[5]; char type[5]; char color[10]; in
typedef struct point{
char id[5];
char type[5];
char color[10];
int x;
int y;
} Point;
typedef struct {
char lineID[5];
int nPoints;
Point *pt;
}railData;
typedef struct railway {
railData data;
}railway;
以下是创建阵列的方式:
headRail = (railway**)calloc(lineNum,sizeof(railway*));
以及每条铁路:
头轨[i]=(铁路*)calloc(pointsNum,sizeof(铁路))
以下是删除轨道的功能:
railway **delRail(railway **headRail, int j)
{
int nPts = 0;
if (!headRail)
{
puts(ERRORS[NULLPOINTER]);
return NULL;
}
// Number of rail points on jth rail
nPts = headRail[j]->data.nPoints;
// Free each rail point from jth rail
for (int i = 0; i < nPts; ++i)
{
free(headRail[j][i].data.pt);
}
// Free allocated memory for jth rail
free(headRail[j]);
return headRail;
}
所以我的问题是,我如何修改我的代码,以便在消除位置I时,所有其他索引向左移动,最后一个位置(将为空)被丢弃(类似于realloc,但用于收缩)
我所要求的在不改变数组结构的情况下可行吗?当移除元素
I
时,执行memmove
将I+1
到I
的所有数据移动到数组的末尾,然后执行realloc
,大小减小1
请注意,C中的数组不会以任何方式跟踪其大小,因此需要通过外部方式传递大小
你的数据抽象很奇怪。我希望headRail[j][0].data.nPoints
用于存储headRail[j][0].data
结构中的点数,但在这里您可以存储j行headRail[j][
中的headRail计数。我建议重写抽象,一个“对象”用于铁路,另一个“对象”用于在所有方向上动态大小的铁路二维阵列
比如:
malloc的数量将保持不变,但考虑数据将变得更简单。每个指向数据数组的指针都有自己的大小跟踪变量。分配可能如下所示:
railway *rail_new(size_t lineNum, size_t pointsNum) {
railway *r = calloc(1, sizeof(*r));
if (!r) { return NULL; }
// allocate the memory for rows of raildata
r->raildatascnt = lineNum;
r->raildatas = calloc(r->raildatascnt, sizeof(*r->raildatas));
if (!t->raildatas) { /* error hadnling */ free(r); abort(); }
// for each row of raildata
for (size_t i = 0; i < r->raildatascnt; ++i) {
struct railData_row_s * const row = &r->raildatas[i];
// allocate the memory for the column of raildata
// hah, looks similar to the above?
row->datacnt = pointsNum;
row->data = calloc(row->datacnt, sizeof(*row->data));
if (!row->data) { /* error ahdnling */ abort(); }
}
return r;
}
railway*rail\u new(大小\u t lineNum,大小\u t pointsNum){
铁路*r=calloc(1,尺寸(*r));
如果(!r){返回NULL;}
//为raildata的行分配内存
r->raildatascnt=lineNum;
r->raildatas=calloc(r->raildatascnt,sizeof(*r->raildatas));
如果(!t->raildatas){/*error hadnling*/free(r);abort();}
//对于每行raildata
对于(大小i=0;iraildatascnt;++i){
struct railData_row_s*const row=&r->raildatas[i];
//为raildata列分配内存
//哈,看起来和上面一样?
row->datacnt=pointsNum;
row->data=calloc(row->datacnt,sizeof(*row->data));
如果(!row->data){/*error ahdnling*/abort();}
}
返回r;
}
缺失太多,请发布一个。顺便说一句,它很简单,因为MAXLEN
太大了。至少,您需要发布结构定义。而且,你可能也应该发布你的代码的其余部分。我不知道memmove,但它似乎是一条路要走。但是它不起作用,memmove不应该在一个循环中吗?例如,对于(k=j+1;kmemmove
在数组中移动数据时,这只是一个简单的循环思想。它等于(size_t i=j;ij
。但是,realloc
将“删除”/去除最后一个元素。因此,您需要将大于j+1的所有元素向左移动一个元素,以便删除数组中的最后一个元素。然后realloc将缩短内存,从而删除/使最后一个元素后面的内存无效。
railway **delRail(railway **headRail, int j)
{
...
// this is strange, it's equal to
// nPts = headRail[j][0].data.nPoints;
// dunno if you mean that,
// or if [j][0].data.nPoints refers to the size of
// headRail[j][0].data.pt or to the size of the whole array
size_t nPts = headRail[j]->data.nPoints;
for (size_t i = 0; i < nPts; ++i) {
free(headRail[j][i].data.pt);
}
free(headRail[j]);
// note that arrays in C does not know how many elements are there in the array
// so you typically pass that along the arguments, like
// railway **delRail(railway **headRail, size_t railcount, int j);
size_t headRailCount = lineNum; // some external knowledge of the size
memmove(&headRail[j], &headRail[j + 1], (headRailCount - j - 1) * sizeof(*headRail));
void *pnt = realloc(headRail, (headRailCount - 1) * sizeof(*headRail));
if (pnt == NULL) return NULL; // that would be strange
headRail = pnt; // note that the previous headRail is no longer valid
--lineNum; // decrement that object where you store the size of the array
return headRail;
}
typedef struct {
// stores a single row of rail datas
struct railData_row_s {
// stores a pointer to an array of rail datas
railData *data;
// stores the count of how many datas of rails are stored here
size_t datacnt;
// stores a pointer to an array of rows of rail datas
} *raildatas;
// stores the size of the pointer of rows of rail datas
size_t raildatascnt;
} railway;
railway *rail_new(size_t lineNum, size_t pointsNum) {
railway *r = calloc(1, sizeof(*r));
if (!r) { return NULL; }
// allocate the memory for rows of raildata
r->raildatascnt = lineNum;
r->raildatas = calloc(r->raildatascnt, sizeof(*r->raildatas));
if (!t->raildatas) { /* error hadnling */ free(r); abort(); }
// for each row of raildata
for (size_t i = 0; i < r->raildatascnt; ++i) {
struct railData_row_s * const row = &r->raildatas[i];
// allocate the memory for the column of raildata
// hah, looks similar to the above?
row->datacnt = pointsNum;
row->data = calloc(row->datacnt, sizeof(*row->data));
if (!row->data) { /* error ahdnling */ abort(); }
}
return r;
}