如何更改函数内数组的大小?

How can I change the size of an array inside a function?

提问人:Prio216 提问时间:9/26/2022 最后编辑:Vlad from MoscowPrio216 更新时间:9/26/2022 访问量:69

问:

我最近参加了一个关于C语言的测试,有一个练习我想请你帮忙,因为我做得不好。整个测试围绕着两个结构,“点”和“多边形”:point 有两个双精度值表示 x 和 y 坐标,而 polygon 有一个 int 值表示它拥有的点数,一个指向点的指针表示它的点列表。

typedef struct Punto{
double x;
double y;
}punto;
punto origine = {.x =0, .y =0};

typedef struct Poligono{
int numeroPunti;   //numbers of points
punto *punti;
}poligono;
poligono poligonoNullo = {.numeroPunti = 0, .punti = NULL};

然后我被要求创建各种函数来解决不同的任务,其中一个是“aggiungiPunto”(添加一个点),它以一个点和一个多边形作为输入,并将给定的点添加到“polygon.punti”中。我创建此函数的尝试如下

void aggiungipunto(punto p, poligono poli){

punto *prova;
prova = calloc(poli.numeroPunti +1, sizeof(punto));
for(int i=0; i<poli.numeroPunti;i++){
    prova[i]=poli.punti[i];
}
poli.numeroPunti++;
prova[poli.numeroPunti -1] = p;
poli.punti = &prova[0];
}

...女巫不起作用:如果我尝试在函数内打印多边形(我有一个“stampapoligono”,printPolygon 函数,它只是列出所有点并正常工作)我看到 代码做了我想要的,但是如果我尝试在我的主函数中打印多边形,它就像没有附加一样。我认为这与 c 中的函数如何获取参数的副本有关,但我不知道如何解决它。

只是为了获得更多上下文,这里是主要功能以及我如何测试:

int main(){

punto a = {.x =1, .y = 2};  
punto b = {.x = -1, .y = 2};

punto arraystatico[] = {origine, a, b}; 

poligono prova = poligonoNullo;
    prova.numeroPunti = 3;
    prova.punti = (punto *)calloc(prova.numeroPunti, sizeof(punto));

    for(int i=0;i < prova.numeroPunti ;i++){
        prova.punti[i] = arraystatico[i];
    }

printf("Poligono iniziale:\n");
stampapoligono(prova);

punto c = {.x = 12, .y =3};
aggiungipunto(c, prova);

printf("Stampa esterna: \n");
stampapoligono(prova);
free(prova.punti);
return 0;
}

这就是 stampapoligono 的工作原理

void stampapunto(punto p){
   printf("Coordinata x: %lf\tCoordinata y: %lf\n", p.x, p.y);
}

void stampapoligono(poligono poli){
   if (poli.numeroPunti ==0){
       printf("Il poligono non ha punti\n");
   }
   else{
      for(int i=0; i<poli.numeroPunti;i++){
        stampapunto((poli.punti)[i]);
        printf("\n");
      }
   }
}

编辑:我也尝试了这个代码,它使用realloc进行aggiungipunto,但结果是一样的:

void aggiungipunto(punto p, poligono poli){

punto *prova;
prova = calloc(poli.numeroPunti, sizeof(punto));
for(int i=0; i<poli.numeroPunti;i++){
    prova[i]=poli.punti[i];
}

poli.punti = (punto *)realloc(poli.punti, poli.numeroPunti+1);
for(int i=0; i<poli.numeroPunti;i++){
    poli.punti[i]=prova[i];
}

(poli.punti)[poli.numeroPunti] = p;
poli.numeroPunti++;
}
C 结构 Pass-By-Reference dynamic-memory-allocation realloc

评论

1赞 tstanisl 9/26/2022
请不要从 // 强制转换结果。这是毫无意义的,它只会增加代码的混乱。malloccallocrealloc
1赞 phuclv 9/26/2022
我是否投射 malloc 的结果?
0赞 Prio216 9/27/2022
对不起,我通常不使用分配函数来执行此操作,但是我看到一些代码已经完成,我正在乱搞,看看是否会有变化,我忘了在通过它之前将其删除。
0赞 chux - Reinstate Monica 9/27/2022
Prio216,在 C 语言中,数组大小一旦定义就无法更改。然而,with 不是一个数组,而是一个指针。内存分配可以更改大小,但不能更改数组。指针不是数组。数组不是指针。poli.punti

答:

2赞 Vlad from Moscow 9/26/2022 #1

该函数应通过指向原始对象的指针通过引用访问原始对象。否则,该函数将处理原始对象的副本并更改副本。原始对象将保持不变。aggiungipuntoprova

此外,该函数应向调用方报告成功添加新点的位置。

第一个参数的类型应为 .poligono *

所以函数声明应该看起来像

int aggiungipunto( poligono *poli, punto p );

由于点的内存是动态分配的,因此您应该使用函数 。realloc

该函数可能如下所示

int aggiungipunto( poligono *poli, punto p )
{
    punto *tmp = realloc( poli->punti, ( poli->numeroPunti + 1 ) * sizeof( punto ) );

    int success = tmp != NULL;

    if ( success )
    {
        poli->punti = tmp;
        poli->punti[poli->numeroPunti++] = p;
    }

    return success;
}

该函数的调用方式如下

aggiungipunto( &prova, c );

if ( !aggiungipunto( &prova, c ) )
{
    puts( "Error. No enough memory." );
}

此外,该函数应声明如下stampapoligono

void stampapoligono( const poligono *poli );

也就是说,原始对象应通过指向它的指针作为常量对象通过引用传递。

我的建议使用英语单词作为标识符名称。

评论

0赞 Prio216 9/27/2022
谢谢你的回答,对不起,非英文名字,考试是意大利语,所以我使用了考试要求的名字,我不认为我会在网上问,也没有想过改变它们。我能问一下你对stampapoligono所做的改变吗?测试要求我使用 poligono 作为参数,所以我做到了,但我很好奇给它一个常量指针:只是一个好习惯还是这个函数不使用它有问题?归根结底,该特定函数只是一个美化的 printf 函数,不使用 const 指针有问题吗?
0赞 Vlad from Moscow 9/27/2022
@Prio216 这不是一个问题,但函数声明是函数调用者和函数之间的约定。限定符 const 表示函数不会更改传递的对象。