如何在 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;
}
我是 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;
}