简体   繁体   中英

Pointers to structs, C

I have these two structs, everything goes well, but when I try calculating poly->scope
The output is 0.0, like nothing really happens. Also, I get some errors I cannot understand, for example - the line scanPoint(&poly->points[i]); says "Dereferencing NULL pointer"

Thanks for help.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct point
{
   int x, y;
}point;

typedef struct polygon
{
   int n;
   point* points;
   double scope;
}polygon;

void scanPoint(point*);
void scanPolygon(polygon*);
double distance(point*, point*);
void calculatePolygonScope(polygon*);
void freeMemory(polygon*);

int main()
{
   polygon poly;
   
   scanPolygon(&poly);
   calculatePolygonScope(&poly);
   freeMemory(&poly);
   
   printf("Output: Scope of polygon: %.2lf\n", poly.scope);

   return 0;
}

void scanPoint(point* p)
{
   printf("Please Enter X of your point: \n");
   scanf("%d", &p->x);
   printf("Please Enter Y of your point: \n");
   scanf("%d", &p->y);
}

void scanPolygon(polygon* poly)
{
   int i;
   printf("Please enter how many points does the polygon have? : \n");
   scanf("%d", &poly->n);
   poly->points = (point*)calloc(poly->n, sizeof(point));
   for (i = 0; i < poly->n; i++)
   {
       scanPoint(&poly->points[i]);
   }
}

double distance(point* p1, point* p2)
{
   double x = pow(((double)p2->x - (double)p1->x), 2);
   double y = pow(((double)p2->y - (double)p1->y), 2);
   double dis = sqrt(x + y);
   return dis;
}

void calculatePolygonScope(polygon* poly)
{
   int i;
   double temp = 0.0;
   for (i = 0; i < poly->n-1;)
   {
       temp += distance(&poly->points[i], &poly->points[++i]);
   }
   poly->scope = temp;
}

void freeMemory(polygon* poly)
{
   free(poly->points); 
}

The function call distance(&poly->points[i], &poly->points[++i]); in calculatePolygonScope exhibits undefined behavior because it uses the value of i in two places, one of which modifies the value of i . From C17 6.5/2:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings. 85)

85) This paragraph renders undefined statement expressions such as

 i = ++i + 1; a[i++] = i;

while allowing

 i = i + 1; a[i] = i;

To fix it, do the increment of i in the for loop control:

   for (i = 0; i < poly->n-1; i++)
   {
       temp += distance(&poly->points[i], &poly->points[i + 1]);
   }

If calculatePolygonScope is supposed to calculate the perimeter of the polygon, it is missing the edge between the first and last points. It could be changed as follows to include that edge:

void calculatePolygonScope(polygon* poly)
{
   int i;
   double temp = 0.0;
   for (i = 0; i < poly->n-1; i++)
   {
       temp += distance(&poly->points[i], &poly->points[i + 1]);
   }
   if (poly->n > 1)
   {
       /* Last edge */
       temp += distance(&poly->points[poly->n-1], &poly->points[0]);
   }
   poly->scope = temp;
}

As an aside, the distance function can be simplified by using the hypot function:

double distance(point* p1, point* p2)
{
    return hypot(p2->x - p1->x, p2->y - p1->y);
}

or to avoid any possible integer overflow:

double distance(point* p1, point* p2)
{
    return hypot((double)p2->x - p1->x, (double)p2->y - p1->y);
}

EDIT: OP is not allowed to use hypot , but the distance function can still be simplified by using simple multiplication to do the squaring, instead of using the more expensive (and potentially less accurate) pow function:

double distance(point* p1, point* p2)
{
   double x = (double)p2->x - (double)p1->x;
   double y = (double)p2->y - (double)p1->y;
   double dis = sqrt(x * x + y * y);
   return dis;
}

Note: It is not actually necessary to cast both operands of the subtraction operator to double . The other can be left as an int and will be converted to double automatically before the subtraction is performed.

You probably want this:

void calculatePolygonScope(polygon* poly)
{
  int i;
  double temp = 0.0;
  for (i = 0; i < poly->n - 1; i++)
  {
    temp += distance(&poly->points[i], &poly->points[i + 1]);
  }
  poly->scope = temp;
}

With that modification the function returns the sum the polygon's segments except the last segment.

If the function is supposed to return the perimeter of the polygon, you need obviously to add another modification. I let you findout yourself how to do this as an exercise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM