我有一个动态分配的n大小的结构数组,该数组的每个位置也是一个数组,每个位置(数组的数组)的大小不同。
我创建了一个删除给定数组[索引]的函数,但是我面临一些未定义的行为,例如: 如果数组的大小为3,则删除array [0]时将无法访问array [1]。其他索引组合也会发生这种情况。完美无瑕的唯一方法是从头到尾删除。
这是我的代码: 结构:
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*));
以及每个Rail: headRail [i] =(railway *)calloc(pointsNum,sizeof(railway));
这些是删除滑轨的功能:
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;
}
这是我调用上一个函数的地方:
railway **removeRail(railway **headRail)
{
char userID[20];
int index = 0;
// Quit if no rails
if (!headRail)
{
backToMenu("No rails available!");
return NULL;
}
// Get user input
getString("\nRail ID: ",userID,MINLEN,MAXLEN); // MINLEN = 2 MAXLEN = 4
// get index of the asked rail
getRailIndex(headRail,userID,&index);
if (index != NOTFOUND)
{
headRail = delRail(headRail, index);
// Update number of rails in the array (global var)
NUMOFRAILS--;
backToMenu("Rail deleted!\n");
}
else
backToMenu("Rail not found!");
return headRail;
}
所以我的问题是我该如何修改我的代码,以便在消除位置i时,将所有其他索引向左移,最后一个空的位置将被丢弃(类似于realloc,但用于缩小)
我要的是在不更改数组结构的情况下可行吗?
答案 0 :(得分:1)
删除元素i
时,将memmove
到i+1
的所有数据i
到数组的末尾,然后realloc
的大小减小通过1。
请注意,C语言中的数组不会以任何方式跟踪其大小,因此您需要通过外部方式传递大小。
您的数据抽象很奇怪。我希望使用headRail[j][0].data.nPoints
来存储headRail[j][0].data
结构内部的点数,但是在那里您将headRails的计数存储在j行headRail[j][<this count>]
中。我建议重写一下抽象,为铁路提供一个“对象”,为整个方向上动态尺寸的二维铁路阵列添加一个“对象”。
赞:
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;
}
一些封装和更多的结构而不是二维数组呢? 2d数组确实让C感到有些痛苦,那呢:
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;
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;
}