Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从结构的动态数组中删除元素时的未定义行为_C_Arrays_Struct_Dynamic Memory Allocation - Fatal编程技术网

C 从结构的动态数组中删除元素时的未定义行为

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

我动态分配了一个n大小的结构数组,数组的每个位置也是一个数组,每个位置的大小不同(一个数组数组)

我创建了一个函数来删除给定的数组[index],但我面临一些未定义的行为,例如: 如果数组大小为3,如果删除数组[0],则无法访问数组[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*));
以及每条铁路: 头轨[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;iOch你是对的,我忘了sizeof。基本上,删除元素编号
j
。但是,
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;
}