我想在c中动态地向数组添加数字。我的想法是只分配一个大小为+ 1的新数组,添加数字,释放根数组并将指针从temp更改为根数组。像这样:
void addNumber(int* a, int* size, int number)
{
*size = *size + 1;
int* temp = (int*)(calloc(*size, sizeof(int)));
int i, j = 0;
for(i = 0; i < *size-1; i++) {
if(a[i] < number) {
printf("add ai");
temp[j] = a[i];
j++;
} else {
printf("add number");
temp[j] = number;
}
}
if(j != *size) {
printf("add new number");
temp[j] = number;
}
free(a);
a = temp;
}
int main(int argc, char* argv[])
{
int n = 10;
int* a;
int size = 1;
a = (int*) (calloc(1, sizeof(int)));
a[0] = 1;
if(!contains(a, size, 2)) {
addNumber(a, &size, 2);
}
printArray(a,size);
return 0;
}
问题是在addNumber函数中代码有效,而* a具有新数组的正确值。但在main函数中,数组* a的值为1,0。因此不添加新的插入值2。为什么?无法理解。
答案 0 :(得分:2)
要动态更改数组大小,可以使用realloc()例程。除了使用eaiser之外,它可以比顺序调用free()
和malloc()
的方法更快。
保证重新分配的块将填充旧内存块的内容。
问题是在addNumber函数中代码有效,而* a具有新数组的正确值
您的代码中存在两个主要缺陷。第一个是你的addNumber()
例程没有返回新分配的内存块(因此它被泄漏),你应该使用双指针或者将新块作为函数结果返回。
第二个是第一个结果 - 在a
被释放后,你继续写信给它。
如果您更愿意坚持使用当前的方法,则此修改后的代码应该有效:
void addNumber(int** a, int* size, int number)
{
*size = *size + 1;
int* temp = (int*)(calloc(*size, sizeof(int)));
int i, j = 0;
for(i = 0; i < *size-1; i++) {
if((*a)[i] < number) {
printf("add ai");
temp[j] = (*a)[i];
j++;
} else {
printf("add number");
temp[j] = number;
}
}
if(j != *size) {
printf("add new number");
temp[j] = number;
}
free(*a);
*a = temp;
}
int main(int argc, char* argv[])
{
int n = 10;
int* a;
int size = 1;
a = (int*) (calloc(1, sizeof(int)));
a[0] = 1;
if(!contains(a, size, 2)) {
addNumber(&a, &size, 2);
}
printArray(a,size);
return 0;
}
答案 1 :(得分:1)
为什么呢?无法理解。
那是因为您要在a
中本地修改addNumber
的值。这不会改变a
中main
的值。
为了让main
能够访问新分配的内存,您需要更改addNumber
以返回新分配的指针。
int* addNumber(int* a, int* size, int number){
...
return a;
}
然后将main
更改为:
if(!contains(a, size, 2)){
a = addNumber(a, &size, 2);
// Assign to a the new pointer value.
}
答案 2 :(得分:0)
你的'a'在main中已经是一个指针,将它传递给一个函数传递它的副本。你需要做的是 - 传递地址'&amp; a'并以函数形式接收它作为双指针'** a'并在函数内部,使用dereference获取数组内的值(如* a [i]和free( *一个)。 将最后一行更改为'return temp'并将其作为a = addnumber(&amp; a,&amp; size,2)收集在main中;
顺便说一下,为什么不使用realloc()函数,而不是经历所有这些麻烦。它动态增加了数组的大小。使用realloc后,您只需在最后一个索引处添加新号码。
答案 3 :(得分:0)
您正在寻找的是realloc()
。它可用于在保留内容的同时增长或缩小内存。
/* array is now sizeof(int) * new_size bytes */
array = realloc(array, sizeof(int) * new_size);
realloc()
可能会更改现有的内存分配,或者可能会分配一个全新的内存块。这就是为什么将结果重新分配给重新分配的东西很重要。
但是如果addNumber()
通过创建新内存来重新分配数组,main()
就不会知道它。出于同样的原因,这是行不通的。
void incrementNumber(int num) {
num = num + 1;
}
int num
是一个按值传递的数字。如果希望它在调用者中反映出来,则需要将其作为指针传递。
void incrementNumber(int *num) {
*num = *num + 1;
}
指针是一样的。他们仍然是数字。 int *a
按值传递指针。如果您更改a
中的addNumber
,则来电者无法看到它。就像以前一样,你需要将它作为指针传递。指向像这样使用的指针的指针称为double pointer。
void addNumber( int **array_ptr, size_t *array_size, size_t type_size, int number ) {
/* Increment the size and make sure that bubbles up */
*array_size = *array_size + 1;
/* realloc might grow the memory, or it might allocate new memory
either way, assign the result back to its original variable
by dereferencing the double pointer.
*/
*array_ptr = realloc(*array_ptr, *array_size * type_size);
/* Since it's a double pointer, we have to first dereference it before using
it as an array */
(*array_ptr)[*array_size - 1] = number;
}
(请注意,我也传递了数组中元素的大小,不能假设)。
通过将指针传递给数组来调用它。
addNumber(&a, &size, sizeof(int), 5);
之后,一切都是一样的。
for( int i = 0; i < size; i++ ) {
printf("%d ", a[i]);
}
puts("");
最终,您希望通过在结构中包含数组,大小和类型来改进这一点,以便您可以在整齐的包中传递它。
typedef struct {
int *array;
size_t size;
} IntArray;
作为一项练习,这很棒,你会学到很多东西,并且会对静态记忆产生许多坏习惯。但是正确有效地进行动态数据结构很困难(例如,一次分配一个额外的插槽效率非常低)。
有很多很多的库提供了这样的动态结构。因此,请继续将其作为练习,但对于实际代码,请使用Gnome Lib等库。