如何在 C 中动态地在数组的最后位置插入一个元素?

How to insert an element at the last position in an array dynamically in C?

我是 C 语言的新手,我试图在 C 语言的最后一个位置插入一个数字,这样数组的大小会随着时间的推移而改变。

第一个数组是这样的:

temp[10] = {1, 2, 0, 0, 5, 6, 0, 8, 0, 0};

现在我们如何将 temp!= 0 的值插入到定义长度为 5 的新数组中:tmp

这是我正在尝试的:

void push(int arr[], int value, int current){
  arr[current] = value;
}

int main(void) { 

  int temp[10] = {1, 2, 0, 0, 5, 6, 0, 8, 0, 0};
  int tmp[5];

  for(int i=0;;i++){
    if(temp[i]) push(tmp, temp[i],sizeof(tmp)/sizeof(tmp[0]));
    // I don't put i < 10 int the loop initialization. Since the tmp's length is just 5

  }
  // I put sizeof(tmp)/sizeof(tmp[0]) there because we want at every time the tmp is inserted a new value,
  // it's length will change (increase by 1). 
  // So next loop round, the new value will be added to the last position
  // But I failed to do so

} 

当前输出:

exited segmentation fault
// I'd be very grateful if someone can also explain for me why this error happens

期望输出:

tmp[5] = {1, 2, 5, 6, 8}

您对 push 的定义要求第 3 个参数是放置元素的位置。但是,表达式 sizeof(tmp)/sizeof(tmp[0]) 提供了数组的 大小 ,因此它的索引将超过数组的最后一个元素(因为 C 中的索引来自 0..n-1)。这本身会导致分段错误。

您也没有为循环提供终止条件。它将永远持续下去。

您的解决方案可以是:

for(int i=0, j=0; i<10; i++)
   if(temp[i]) push(tmp, temp[i], j++);

问题是您正在访问 temp 的范围之外,因为您没有指定何时停止循环。

对于动态数组,当你事先不知道元素个数时,可以使用realloc:

#include <stdio.h>
#include <stdlib.h>

void push(int **arr, size_t *size, int value)
{
    int *ptr = realloc(*arr, sizeof(*ptr) * (*size + 1));

    if (ptr == NULL)
    {
        free(*arr);
        perror("push");
        exit(EXIT_FAILURE);
    }
    ptr[*size] = value;
    *size += 1;
    *arr = ptr;
}

int main(void)
{ 
    int temp[10] = {1, 2, 0, 0, 5, 6, 0, 8, 0, 0};
    int *arr = NULL;
    size_t size = 0;

    for (size_t i = 0; i < sizeof temp / sizeof temp[0]; i++)
    {
        if (temp[i])
        {
            push(&arr, &size, temp[i]);
        }
    }
    for (size_t i = 0; i < size; i++)
    {
        printf("%d\n", arr[i]);
    }
    free(arr);
} 

请注意,即使它说明了可增长数组的使用,这个示例也被认为是糟糕的代码,更健壮的设计将处理大小并能够自行管理分配和释放:

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int *data;
    size_t size;
}  dyn_array;

dyn_array *create_dyn_array(void)
{
    dyn_array *arr = calloc(1, sizeof *arr);

    if (arr == NULL)
    {
        perror("create_dyn_array");
        exit(EXIT_FAILURE);
    }
    return arr;
}

void destroy_dyn_array(dyn_array *arr)
{
    free(arr->data);
    free(arr);
}

void push_dyn_array(dyn_array *arr, int value)
{
    int *ptr = realloc(arr->data, sizeof(*ptr) * (arr->size + 1));

    if (ptr == NULL)
    {
        destroy_dyn_array(arr);
        perror("push_dyn_array");
        exit(EXIT_FAILURE);
    }
    ptr[arr->size++] = value;
    arr->data = ptr;
}

int main(void)
{ 
    int temp[10] = {1, 2, 0, 0, 5, 6, 0, 8, 0, 0};
    dyn_array *arr = create_dyn_array();

    for (size_t i = 0; i < sizeof temp / sizeof temp[0]; i++)
    {
        if (temp[i])
        {
            push_dyn_array(arr, temp[i]);
        }
    }
    for (size_t i = 0; i < arr->size; i++)
    {
        printf("%d\n", arr->data[i]);
    }
    destroy_dyn_array(arr);
}

这样更好,但仍然不完美,因为我们仅限于固定类型 (int),通过一些额外的内存,我们可以调整我们的代码以支持任何类型(使用通用类型 void *),作为优化,动态数组增长了 2 倍,而不是在每次迭代时调用 realloc

#include <stdio.h>
#include <stdlib.h>

/* Begin - This API is supposed to be in a header */

typedef struct
{
    void **data;
    size_t room;
    size_t size;
}  dynarray;

dynarray *dynarray_create(void)
{
    dynarray *array = calloc(1, sizeof *array);

    if (array == NULL)
    {
        return NULL;
    }
    array->data = malloc(sizeof(void *));
    if (array->data == NULL)
    {
        free(array);
        return NULL;
    }
    array->room = 1;
    return array;
}

void *dynarray_push(dynarray *array, void *data)
{
    if (data == NULL)
    {
        return NULL;
    }
    if (array->size == array->room)
    {
        array->room *= 2;

        void *ptr = realloc(array->data, array->room * sizeof(void *));

        if (ptr == NULL)
        {
            return NULL;
        }
        array->data = ptr;
    }
    array->data[array->size++] = data;
    return data;
}

void *dynarray_get(dynarray *array, size_t index)
{
    return array->data[index];
}

size_t dynarray_size(dynarray *array)
{
    return array->size;
}

void dynarray_destroy(dynarray *array, void (*func)(void *data))
{
    if (func != NULL)
    {
        for (size_t i = 0; i < array->size; i++)
        {
            func(array->data[i]);
        }
    }
    free(array->data);
    free(array);
}

/* End API */

int main(void)
{ 
    int temp[10] = {1, 2, 0, 0, 5, 6, 0, 8, 0, 0};
    dynarray *array = dynarray_create();

    if (array == NULL)
    {
        perror("dynarray_create");
        exit(EXIT_FAILURE);
    }
    for (size_t i = 0; i < sizeof temp / sizeof temp[0]; i++)
    {
        if (temp[i])
        {
            if (dynarray_push(array, &temp[i]) == NULL)
            {
                perror("dynarray_push");
                exit(EXIT_FAILURE);
            }
        }
    }

    size_t size = dynarray_size(array);

    for (size_t i = 0; i < size; i++)
    {
        int *data = dynarray_get(array, i);

        printf("%d\n", *data);
    }
    dynarray_destroy(array, NULL);
}

什么是

trying to insert a number at the last position in C

虽然您得到了 David Ranieri 的解释性答案,但我想展示最简单的方法,同时记住您是新手。看这段代码:-

代码:

#include <stdio.h>
#include <stdlib.h>
#define SIZE 10

void push(int arr[], int value, int current){
  arr[current] = value;
}

int main(void) {

  int temp[SIZE] = {1, 2, 0, 0, 5, 6, 0, 8, 0, 0};
  int *tmp = NULL, count = 0, i, j;

  // Loop for counting non-zero values in temp array.
  for (i = 0; i < SIZE; ++i)
    if (temp[i])
        count++;

  // Dynamically allocating space for tmp along with checking errors if any.
  if((tmp = (int *)malloc(count * sizeof(int))) == NULL)
     {
         printf("Memory Not Available.\n");
         exit(-1);
     }

  for(i = 0, j = 0; i < SIZE; i++){
    if(temp[i])
        push(tmp, temp[i], j++);
  }

  // Printing your desired output.
  for(i = 0; i < count; ++i)
    printf("%d\t", tmp[i]);

    free(tmp);
}

这里tmp的大小会根据temp的非零元素变化。 现在,如果你想使 temp 数组成为动态数组,使用与 tmp 相同的方法,只需在 运行 时要求用户输入 temp 的大小和然后是 elements/values。

C 没有动态数组。数组具有根据其定义确定的固定大小。您可以分配具有 malloc() 的对象,其行为类似于数组,但您必须单独跟踪它们的分配大小。添加一个元素需要重新分配数组,因此它在内存中的地址可能会改变。

在您的代码中,tmp 具有 5 个元素的固定大小。您可以维护一个索引,指定使用了多少元素并在 push 函数中更新它:

#include <stdio.h>

int push(int arr[], int value, size_t size, size_t *current) {
    if (*current < size) {
        arr[(*current)++] = value;
        return 0;
    } else {
        /* array is full */
        return -1;
    }
}

int main(void) { 
    int temp[10] = { 1, 2, 0, 0, 5, 6, 0, 8, 0, 0 };
    int tmp[5];
    size_t pos = 0;

    for (size_t i = 0; i < sizeof(temp) / sizeof(temp[0]); i++) {
        if (temp[i])
            push(tmp, temp[i], sizeof(tmp) / sizeof(tmp[0]), &pos);
    }

    printf("tmp:");
    for (size_t i = 0; i < pos; i++) {
        printf(" %d", tmp[i]);
    }
    printf("\n");
    return 0;
}