2

I recently toke a test about the C language and there was an exercise for which I would like to ask for your help since I didn't do well. The entire test revolved around two struct, "point" and "polygon": point had two double values for the x and y coordinate, and polygon had a int value for the number of point it has and a pointer to point for the list of its points.

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};

I was then asked to create various functions to solve different tasks, one of witch was "aggiungiPunto" (add a point), that took a point and a polygon as input and added the given point to "polygon.punti". My attempt to create this function is the following

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];
}

...witch didn't work: if I try to print the polygon inside the function (I have a "stampapoligono", printPolygon function that just list all the point and work correctly)i see that the code did what i wanted, but if i try to print the polygon inside my main function it is like nothing append. I belive it has to do with how a function in c takes a copy of the parameters, but i don't know how to work around it.

Just for more context here is the main function and how i tested:

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;
}

And here is how stampapoligono work

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");
      }
   }
}

EDIT: I also tried this code which use realloc for aggiungipunto, but the result is the same:

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++;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Prio216
  • 35
  • 3
  • 1
    please don't cast results from `malloc`/`calloc`/`realloc`. It is pointless and it only adds clutter to the code. – tstanisl Sep 26 '22 at 15:44
  • 1
    [Do I cast the result of malloc?](https://stackoverflow.com/q/605845/995714) – phuclv Sep 26 '22 at 15:58
  • Sorry for the cast, i usually don't do it with allocation function but i saw some code were it was done and i was messing around to see if something would change, i forgot to remove it before past it here. – Prio216 Sep 26 '22 at 16:39
  • Prio216, In C, an array size cannot change once it is defined. Yet with `poli.punti` is not an array, but a pointer. Memory allocations can change size, but not arrays. Pointers are not arrays. Arrays are not pointers. – chux - Reinstate Monica Sep 26 '22 at 19:04

1 Answers1

2

The function aggiungipunto shall access the original object prova by reference through a pointer to it. Otherwise the function will deal with a copy of the original object and change the copy. The original object will stay unchanged.

Also the function should report for the caller where a new point was added successfully.

And the first parameter should have the type poligono *.

So the function declaration should look like

int aggiungipunto( poligono *poli, punto p );

As the memory for points is allocated dynamically then you should use the function realloc.

The function can look like

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;
}

And the function is called like

aggiungipunto( &prova, c );

or

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

Also the function stampapoligono should be declared like

void stampapoligono( const poligono *poli );

that is the original object should be passed by reference as a constant object through a pointer to it.

And my advice use English words for identifier names.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thank you for your answer, and sorry for the non-English name, the test was in Italian and so i used the name that test asked for, i didn't thought i would have asked online and didn't think about changing them. Can I ask you about the change you made to stampapoligono? The test asked me to use poligono as a parameter and so i did, but i'm curious about giving a const pointer to it: is just a good habit to have or there was a problem in this function in not using it? At the end of the day that particular function is just a glorified printf function, is it a problem to not using const pointer? – Prio216 Sep 26 '22 at 16:37
  • @Prio216 It is not a problem but a function declaration is a contract between the caller of the function and the function. The qualifier const means that the function does not change the passed object. – Vlad from Moscow Sep 26 '22 at 16:39