【问题标题】:How to remove item from array in C?如何从C中的数组中删除项目?
【发布时间】:2013-10-29 22:18:30
【问题描述】:

我想从 b->array 中删除元素,如下代码所示:removeItem 函数 我试图从 b->array = {11.11,12.12,13.13} 中删除 12.12,但它会导致分段错误而不是打印 {11.11,13.13}。有人可以帮助摆脱它吗?

typedef struct
{
  float val;
}data;

typedef struct
{
  data **array;
  int size;
}bag;
int main(int argc,char* argv[])
{

    bag *str = createBag(); 
    #ifdef DEBUG
    printf("Inital values: %p %d\n",str->array,str->size);
    #endif
    data *iptr = createData(10.10);
    data *iptr1 = createData(11.11);
    data *iptr2 = createData(12.12);
    data *iptr3 = createData(13.13);
    data *iptr4 = createData(14.14);
    #ifdef DEBUG
    printf("%f\n",iptr->val);
    #endif
    addData(str,iptr);
    addData(str,iptr1);
    addData(str,iptr2);
    addData(str,iptr3);
    addData(str,iptr4);
    printBag(str);
    data *ptr = getData(str,4);
    printf("Data item 4 is:%f\n",ptr->val);
    int b = getBagSize(str);
    printf("Size of bag: %d\n",b);
    removeBack(str);
    printBag(str);
    removeFront(str);
    printBag(str);
    //cleanBag(str);
    int s = searchBag(str,10.10);
    printf("%d\n",s);
    removeItem(str,12.12);
    printBag(str);
  return 0;
}


bag* createBag()
{
    bag *str = (bag*)malloc(sizeof(bag));
    str->array = NULL;
    str->size = 0;
    return str;
}

data* createData(float v)
{
    data *iptr = (data*)malloc(sizeof(data));
    iptr->val = v;
    return iptr;
}

void addData(bag* b, data* d)
{
    b->size++;

    data** array1 = (data**)malloc(sizeof(data*)* b->size);



    if(b->array!= NULL)
    {
        int i;
        for(i = 0; i<b->size;i++)
        {
            array1[i] = b->array[i];
        }
    }

    free(b->array);
    array1[b->size-1] = d;

    b->array = array1;

}

void printBag(bag *b)
{
    int i;
    for(i=0; i<b->size;i++)
    {
        printf("%f\n",b->array[i]->val);
    }
}

data* getData(bag *b, int pos)
{

    if(pos>5)
    {
        printf("change array position\n");
    }   
    return b->array[pos];


}

int getBagSize(bag *b)
{
    return b->size;

}

void removeBack(bag *b)
{
    b->size--;
    free(b->array[b->size]);

    data **array2 = (data**)malloc(sizeof(data*)* b->size);

    if(b->array!= NULL)
    {
        int i;
        for(i = 0; i<b->size;i++)
        {
            array2[i] = b->array[i];
            #ifdef DEBUG
            printf("%f\n",array2[i]->val);
            #endif
        }

    free(b->array);
    b->array = array2;
    }
}

void removeFront(bag *b)
{
    b->size--;
    free(b->array[0]);

    data **array2 = (data**)malloc(sizeof(data*)* b->size);

    if(b->array!= NULL)
    {
        int i;
        for(i = 0; i<b->size;i++)
        {
            array2[i] = b->array[i+1];
            #ifdef DEBUG
            printf("%f\n",array2[i]->val);
            #endif
        }

    free(b->array);
    b->array = array2;
    }

}
/*void cleanBag(bag *b)
{
    int i;
    for(i=0;i<b->size;i++)  
    {
        free(b->array[i]);
    }
    free(b->array);
    free(b);        
}*/

int searchBag(bag *b,float v)
{
    int i;
    for(i=0;i<b->size;i++)
    {

        if(b->array[i]->val==v)
        {
            return (i+1);
        }
    }
    return -1;
}

void removeItem(bag *b, float v)
{
    int flag = 0,i = 0;

    flag = searchBag(b,v); 
    if(flag != -1) 
    { 
        data **array2 = (data**)malloc(sizeof(data*)*(b->size-1));

        for(i = 0; i < (b->size); i++) 
        { 
             if(i == (flag-1))
            { 
                i = i + 1;
                continue; 
            } 

            array2[i] = b->array[i]; 
        } 
        free(b->array); 
        b->size--; 
        b->array = array2; 
    } 
    else 
    {
        printf("Element is not found\n");
    }
}

【问题讨论】:

  • 代码中的一个错误/错误:如果未找到 float,searchBag 返回“0”,但在 removeItem 中您测试 if(flag != -1)。应该是if(flag != 0)吧?
  • 您是否尝试过使用调试器单步执行代码以查看发生了什么?
  • 另外,我认为我们不能用 == 运算符比较两个浮点数,因为这不太可能是真的。
  • 另外,关于您的分段错误,请查看 removeItem 中的 for(i = 0; i &lt; (b-&gt;size); i++) 循环,以及索引变量 i 如何转换为数组访问 -您会注意到它会尝试访问超出分配内存末尾的 array2 元素。
  • return -1 也给我分段错误

标签: c arrays pointers structure


【解决方案1】:

您的代码中有两个错误。

  1. searchBag 如果在包中找不到浮点值,则返回 0。 但是,函数 removeItem 测试if(flag != -1)。它应该改为测试if(flag != 0)

  2. 段的原因。您遇到的故障也在于 removeItem 函数。 请注意为 array2 分配的内存仅用于 b->size-1 元素。此数组的有效数组索引在 0 ... b->size-2 的范围内。 现在,查看 for 循环,您会注意到索引变量 i 将从 0 运行到 b->size-1。恰好在最后一次迭代中,i 将变为 b->size-1,因此代码会尝试写入超出 array2 分配内存的位置 array2[b-&gt;size-1]


removeItem 函数的一个可能的修复方法如下所示:

void removeItem(bag *b, float v)
{
    int flag = 0;
    int oldArrayIndex = 0;
    int newArrayIndex = 0;

    flag = searchBag(b,v); 
    if(flag != 0) 
    { 
        data **array2 = (data**) malloc(sizeof(data*)*(b->size-1));

        for(oldArrayIndex = 0; oldArrayIndex < (b->size); oldArrayIndex++) 
        { 
            if(oldArrayIndex != (flag-1))
            { 
                array2[newArrayIndex] = b->array[oldArrayIndex]; 
                newArrayIndex++;
            } 
        } 
        free(b->array); 
        b->size--; 
        b->array = array2; 
    } 
    else 
    {
        printf("Element is not found\n");
    }
}

【讨论】:

  • (i!=(flag-1)) 我在这里是什么?
  • 我已经尝试过你的代码,但 der 是其中的一个问题,如果我将在数组中有 1.0 2.0 .....5.0 元素并且如果我试图删除 4.0 那么根据你的代码它会删除3.0,对于 5.0,它删除了 4.0。
  • @RHN,我的示例代码基于上述问题中实现的 searchBag 函数。你改了 searchBag 功能了吗?
  • @RHN: "(i!=(flag-1)) 我在这里是什么?糟糕,错字:) 它不应该是 'i' 而应该是 oldArrayIndex。我修正了我的答案:)
猜你喜欢
  • 2021-10-19
  • 2016-09-07
  • 1970-01-01
  • 1970-01-01
  • 2021-09-07
  • 2016-10-30
  • 2021-08-15
相关资源
最近更新 更多