Thread: Check if the area and perimeter is the expected result

  1. #1
    Registered User
    Join Date
    Dec 2016
    Posts
    7

    Check if the area and perimeter is the expected result

    I have a program to calculate area and perimeter of a polygon. It reads each line of a text file, each line has some coordinates, and with that coordinates it calculates the area and the perimeter of the polygn.

    To check if the output of the program corresponds to the correct area and perimeter I have 2 char arrays, each array corresponds to the correct result of each line of the file. The result array is to store the result values.

    Code:
    char expected[] = "80.0036.00";  // area = 80.00 perimeter = 36.00
    char expected1[] = "48.0032.00"; // area = 48.00 perimeter = 32.00
    char result[] = "";              // its purpose is to store the result values
    The file coordinates.txt has two lines for now, the calculation result of the first line corresponds to the expected[] and the result of the other line corresponds to the expected1[]:
    2 10 12 10 12 2 2 2
    4 8 16 8 16 4 4 4

    Im getting a problem that is altough the correct result "80.0036.00" is icual to the expected result "80.0036.00" the comparison result is always "Arrays are different". The same happens to the other lines. I also tried with sprintf but get same issue.


    Code:
    while (fgets(line, sizeof (line), data)){
        xycount = 0;
        polygon_area = 0;
        a = *(triangle*)malloc(sizeof (triangle));
        memset(polygon_vertices, 0, sizeof (polygon_vertices));
        line[strlen(line) - 1] = 0;
        token = strtok(line, " ");
        while (token != NULL){
            xy = atof(token);
            token = strtok(NULL, " ");
            polygon_vertices[xycount++] = xy;
        }
        idx = 0;
        triangles = (xycount / 2) - 2;
        for (index = 2, idx = 0;idx < triangles;index += 2, ++idx){
            a.v1[x] = polygon_vertices[0];
            a.v1[y] = polygon_vertices[1];
            a.v2[x] = polygon_vertices[index + 0];
            a.v2[y] = polygon_vertices[index + 1];
            a.v3[x] = polygon_vertices[index + 2];
            a.v3[y] = polygon_vertices[index + 3];
            triangle_area = area(a);
            polygon_area += triangle_area;
    
        }
        printf("area=%.2f\t", polygon_area);
        perim = perimeter(polygon_vertices, xycount);
        printf("perimeter=%.2f\n", perim);
    
        result[xycount] = printf("%.2f", polygon_area);
        result[xycount] += printf("%.2f", perim);
    
        if(strcmp(expected, result) == 0) {
            printf("Arrays match.");
        }
        else{
            printf("Arrays different\n");
        };
    
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > result[xycount] = printf("%.2f", polygon_area);
    > result[xycount] += printf("%.2f", perim);
    What do you expect this to do?

    What it isn't doing is building a string you can use with strcmp.

    printf returns a int, which is the number of chars printed.

    Maybe
    sprintf(result,"%.2f%.2f",polygon_area, perim);


    > a = *(triangle*)malloc(sizeof (triangle));
    What's this?
    The * right at the front is very suspect.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    You should post a simplified complete program that can be compiled and that exhibits the problem. A sample of the input file would also help.

    Code:
    result[xycount] = printf("%.2f", polygon_area);
    result[xycount] += printf("%.2f", perim);
    If you're trying to build a string in "result" using the assignment operator, that won't work. "printf()" simply returns the number of characters written.

    If you want to build strings with the value of variables, look into sprintf().

  4. #4
    Registered User
    Join Date
    Dec 2016
    Posts
    7
    You can see the other part below, it is working and its showing always "Arrays diferent".

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    enum { x, y};
    typedef struct triangle{
        double v1[2];
        double v2[2];
        double v3[2];
    } triangle;
    double area(triangle a);
    double perimeter(double* vertices, int size);
    double side(double* p1, double* p2);
    char expected[] = "80.0036.00";
    char expected1[] = "48.0032.00";
    char expected2[] = "61.5034.87";
    
    char result[] = "";
    
    int main()
    {
        int n, idx;
        int triangles;
        int index;
        int xycount;
        double xy;
        double triangle_area;
        double polygon_area;
        double perim;
        double polygon_vertices[50] = {0.0};
        triangle a;
        FILE* data;
        char line[256];
        char* token;
        if ((data = fopen("C:\\Users\\CHK\\Desktop\\coordinates.txt", "r")) == NULL) {
            fprintf(stderr, "can't open data file\n");
            exit (EXIT_FAILURE);
        }
        while (fgets(line, sizeof (line), data)){
            xycount = 0;
            polygon_area = 0;
            a = *(triangle*)malloc(sizeof (triangle));
            memset(polygon_vertices, 0, sizeof (polygon_vertices));
            line[strlen(line) - 1] = 0;
            token = strtok(line, " ");
            while (token != NULL){
                xy = atof(token);
                token = strtok(NULL, " ");
                polygon_vertices[xycount++] = xy;
            }
            idx = 0;
            triangles = (xycount / 2) - 2;
            for (index = 2, idx = 0;idx < triangles;index += 2, ++idx){
                a.v1[x] = polygon_vertices[0];
                a.v1[y] = polygon_vertices[1];
                a.v2[x] = polygon_vertices[index + 0];
                a.v2[y] = polygon_vertices[index + 1];
                a.v3[x] = polygon_vertices[index + 2];
                a.v3[y] = polygon_vertices[index + 3];
                triangle_area = area(a);
                polygon_area += triangle_area;
    
            }
            printf("area=%.2f\t", polygon_area);
            perim = perimeter(polygon_vertices, xycount);
            printf("perimeter=%.2f\n", perim);
    
            result[xycount] = printf("%.2f", polygon_area);
            result[xycount] += printf("%.2f", perim);
    
            if(strcmp(expected, result) == 0) {
                printf("Arrays match.");
            }
            else{
                printf("Arrays different\n");
            };
    
        }
        fclose(data);
        return 0;
    }
    
    /* calculate triangle area with Heron's formula */
    double area(triangle a)
    {
        double s1, s2, s3, S, area;
    
        s1 = side(a.v1, a.v2);
        s2 = side(a.v2, a.v3);
        s3 = side(a.v3, a.v1);
        S = (s1 + s2 + s3) / 2;
        area = sqrt(S*(S - s1)*(S - s2)*(S - s3));
    
        return area;
    }
    
    /* calculate polygon perimeter */
    double perimeter(double *vertices, int size)
    {
        int idx, jdx;
        double p1[2], p2[2], pfirst[2], plast[2];
        double perimeter;
    
        perimeter = 0.0;
        /* 1st vertex of the polygon */
        pfirst[x] = vertices[0];
        pfirst[y] = vertices[1];
        /* last vertex of polygon */
        plast[x] = vertices[size-2];
        plast[y] = vertices[size-1];
        /* calculate perimeter minus last side */
        for(idx = 0; idx <= size-3; idx += 2)
        {
            for(jdx = 0; jdx < 4; ++jdx)
            {
                p1[x] = vertices[idx];
                p1[y] = vertices[idx+1];
                p2[x] = vertices[idx+2];
                p2[y] = vertices[idx+3];
            }
            perimeter += side(p1, p2);
        }
        /* add last side */
        perimeter += side(plast, pfirst);
    
        return perimeter;
    }
    
    /* calculate length of side */
    double side(double *p1, double *p2)
    {
        double s1, s2, s3;
    
        s1 = (p1[x] - p2[x]);
        s2 = (p1[y] - p2[y]);
        s3 = (s1 * s1) + (s2 * s2);
    
        return sqrt(s3);
    }

  5. #5
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by chenb View Post
    You can see the other part below, it is working and its showing always "Arrays diferent".
    Did you read the advice Salem and I posted?

  6. #6
    Registered User
    Join Date
    Dec 2016
    Posts
    7
    yes, thanks for your help. Im trying to fix this with that advice. But its strange, using sprintf, now I have 4 lines in the file and for the first two lines it is working now I get "Arrays match", but for the other two I get "Arrays diferent", Im trying to understand why, because they are equal too.

  7. #7
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    If you want more help, post your updated code.

  8. #8
    Registered User
    Join Date
    Dec 2016
    Posts
    7
    I just change to sprintf(result,"%.2f%.2f",polygon_area, perim); The actual code is now this:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    enum { x, y};
    typedef struct triangle{
        double v1[2];
        double v2[2];
        double v3[2];
    } triangle;
    double area(triangle a);
    double perimeter(double* vertices, int size);
    double side(double* p1, double* p2);
    char expected[] = "80.0036.00";
    char expected1[] = "48.0032.00";
    char expected2[] = "61.5034.87";
     
    char result[] = "";
     
    int main()
    {
        int n, idx;
        int triangles;
        int index;
        int xycount;
        double xy;
        double triangle_area;
        double polygon_area;
        double perim;
        double polygon_vertices[50] = {0.0};
        triangle a;
        FILE* data;
        char line[256];
        char* token;
        if ((data = fopen("C:\\Users\\CHK\\Desktop\\coordinates.txt", "r")) == NULL) {
            fprintf(stderr, "can't open data file\n");
            exit (EXIT_FAILURE);
        }
        while (fgets(line, sizeof (line), data)){
            xycount = 0;
            polygon_area = 0;
            a = *(triangle*)malloc(sizeof (triangle));
            memset(polygon_vertices, 0, sizeof (polygon_vertices));
            line[strlen(line) - 1] = 0;
            token = strtok(line, " ");
            while (token != NULL){
                xy = atof(token);
                token = strtok(NULL, " ");
                polygon_vertices[xycount++] = xy;
            }
            idx = 0;
            triangles = (xycount / 2) - 2;
            for (index = 2, idx = 0;idx < triangles;index += 2, ++idx){
                a.v1[x] = polygon_vertices[0];
                a.v1[y] = polygon_vertices[1];
                a.v2[x] = polygon_vertices[index + 0];
                a.v2[y] = polygon_vertices[index + 1];
                a.v3[x] = polygon_vertices[index + 2];
                a.v3[y] = polygon_vertices[index + 3];
                triangle_area = area(a);
                polygon_area += triangle_area;
     
            }
            printf("area=%.2f\t", polygon_area);
            perim = perimeter(polygon_vertices, xycount);
            printf("perimeter=%.2f\n", perim);
     
            sprintf(result,"%.2f%.2f",polygon_area, perim);
     
            if(strcmp(expected, result) == 0) {
                printf("Arrays match.");
            }
            else{
                printf("Arrays different\n");
            };
     
        }
        fclose(data);
        return 0;
    }
     
    /* calculate triangle area with Heron's formula */
    double area(triangle a)
    {
        double s1, s2, s3, S, area;
     
        s1 = side(a.v1, a.v2);
        s2 = side(a.v2, a.v3);
        s3 = side(a.v3, a.v1);
        S = (s1 + s2 + s3) / 2;
        area = sqrt(S*(S - s1)*(S - s2)*(S - s3));
     
        return area;
    }
     
    /* calculate polygon perimeter */
    double perimeter(double *vertices, int size)
    {
        int idx, jdx;
        double p1[2], p2[2], pfirst[2], plast[2];
        double perimeter;
     
        perimeter = 0.0;
        /* 1st vertex of the polygon */
        pfirst[x] = vertices[0];
        pfirst[y] = vertices[1];
        /* last vertex of polygon */
        plast[x] = vertices[size-2];
        plast[y] = vertices[size-1];
        /* calculate perimeter minus last side */
        for(idx = 0; idx <= size-3; idx += 2)
        {
            for(jdx = 0; jdx < 4; ++jdx)
            {
                p1[x] = vertices[idx];
                p1[y] = vertices[idx+1];
                p2[x] = vertices[idx+2];
                p2[y] = vertices[idx+3];
            }
            perimeter += side(p1, p2);
        }
        /* add last side */
        perimeter += side(plast, pfirst);
     
        return perimeter;
    }
     
    /* calculate length of side */
    double side(double *p1, double *p2)
    {
        double s1, s2, s3;
     
        s1 = (p1[x] - p2[x]);
        s2 = (p1[y] - p2[y]);
        s3 = (s1 * s1) + (s2 * s2);
     
        return sqrt(s3);
    }

  9. #9
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Can you post the contents of your coordinates file as well?

  10. #10
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Something I just noticed:

    Code:
    line[strlen(line) - 1] = 0;
    This is generally not a safe approach. If the length is zero, you access elements out of bound.

    See here for some alternatives.

  11. #11
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Here's a strange piece of code:
    Code:
    a = *(triangle*)malloc(sizeof (triangle));
    Consider what that does. It allocates an uninitialized chunk of memory big enough to hold a triangle, then copies it's uninitialized contents to a, then leaks the memory.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > char result[] = "";
    This doesn't allocate enough space to store your result.
    Specifically, it's only one byte containing \0.

    Make this a longer string.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    Dec 2016
    Posts
    7
    Thanks for your help. Do you know a alternative to that part?

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Which part?

    You can simply delete this line
    a = *(triangle*)malloc(sizeof (triangle));

    And maybe
    char result[50];
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 9
    Last Post: 11-28-2016, 05:51 PM
  2. 3DES ECB MODE IN OPENSSL Can't get expected Result
    By homoon in forum C Programming
    Replies: 11
    Last Post: 05-21-2012, 02:32 PM
  3. Replies: 6
    Last Post: 09-29-2011, 04:23 AM
  4. check thread timers result
    By evariste in forum C Programming
    Replies: 2
    Last Post: 01-16-2011, 05:07 PM
  5. Area Perimeter
    By rossipoo in forum C Programming
    Replies: 5
    Last Post: 11-09-2010, 09:20 PM

Tags for this Thread