指针未更新

时间:2017-06-19 15:23:38

标签: c function pointers

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

int* removeNegatives(int *v, int *totv){

int i, j, aux=(*totv), t=0;

for(i=0; i<aux; i++){

    if(v[i]<0){

        t=v[i];

        for(j=i; j<=aux; j++){

            v[j]=v[j+1];
        }

        v[(*totv)-1]=t;
        aux--;
        i=-1;
    }

    else{

        continue;
    }
}

totv=&aux;

v=(int*)realloc(v,(*totv)*sizeof(int));

return(v);

}

int main(){

int *totv=NULL, *v=NULL, *z=NULL, i, j=0, a;

printf("How many numbers are you entering?\n");
scanf("%d",&i);
printf("Enter them, then:\n");

totv=&i;

do{
    if(j<(*totv)){

        scanf("%d",&a);
        v=(int*)realloc(v,++j*sizeof(int));
        v[j-1]=a;
    }

}while(j<(*totv));

printf("\n");
printf("Size before: %d\n",*totv);

z=retiraNegativos(v,totv);

printf("Size after: %d\n",*totv);
printf("\n");

printf("[ ");

for(i=0; i<(*totv); i++){

    printf("%d ",z[i]);
}

printf("]");    

printf("\n");

free(z);
return(0);
}

我根据用户输入的负数来调整矢量&#34; v&#34; 的大小。

但问题是,在我调用了函数&#34; removeNegatives&#34; 之后,指针&#34; totv&#34; 没有更新。< / p>

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

这可能看起来与您的问题无关,但事实并非如此。

考虑一下:

int foo(int bar)
{
  bar = 123;
}
...
int x = 1;
foo(x);
// What's the value of x here?
...

调用x后会foo更新吗?

答案 1 :(得分:0)

问题出在这里:

totv=&aux;

您将某些指针的本地副本分配给新地址。这在您的功能之外没有任何明显的效果。你真正想要的不是改变指针,而是它指向的值,因此你需要:

*totv=aux;

此外,您在此处遇到问题:

for(j=i; j<=aux; j++)
    v[j]=v[j+1];

在上一次迭代中,您将在位置auxaux + 1处访问阵列,这两个阵列都超出了阵列的范围,至少在第一次删除时!相反,你需要:

for(j = i; j < aux - 1; j++)

或者在我眼中更优雅:

for(j = i + 1; j < aux; j++)
    v[j - 1]= v[j];

进一步提示:

  • 如果没有任何内容可以跟随其他分支,则您不需要任何else continue;
  • 无需从一开始就重新启动循环(i = -1;),您可以继续使用刚刚复制的值(--i;)。但是,虽然技术上不正确,但是不要修改for循环的循环变量。这是人们不期望从这种循环中得到的东西。如果你真的需要,那就选择一个while循环。
  • 如果您之后将其删除,则无需将删除的值复制到最后。
  • 如果您不想保留已移除的值,请不要在每次删除一个值时复制所有后续值,而是将每个值复制为仅保留一次,请参阅下文。

一次性移动所有元素:

int* p = v;
for(unsigned int i = 0; i < aux; ++i)
{
    int tmp = v[i];
    if(tmp >= 0)
        *p++ = tmp; // copy current value to first free position
}

值为{ 1, -2, -3, 4, 5, -6, 7 }的数组现在看起来像这样: { 1, 4, 5, 7, 5, -6, 7 }。最后的值保持不变,p指向要切断的第一个位置。所以:

aux = p - v;
*totv = aux;
return (int*) realloc(v, aux * sizeof(int));

请注意,如果重新分配失败,您可以通过这种方式返回NULL。如果减小尺寸,我认为这是不太可能的,但是为了正确性:

p = realloc(v, aux * sizeof(int));
return p ? p : v;

因此,您在失败时返回未更改的数组。考虑一些更精细的错误处理......