程序输出问题

时间:2015-04-23 06:15:58

标签: c arrays loops struct polygons

下面是我的程序,它确定了给定一定量(x,y)坐标的多边形的周长和面积,但我似乎得到了错误的输出,我不明白为什么。

输入是:

  3  12867  1.0 2.0  1.0 5.0  4.0 5.0
  5  15643  1.0 2.0  4.0 5.0  7.8 3.5  5.0 0.4  1.0 0.4

第一个条目是点数(点数),第二个条目是多边形ID,之后的任何内容都是一组坐标。

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

#define MAX_PTS 100
#define MAX_POLYS 100
#define END_INPUT 0

struct Point {
    double x, y;
};

double getDistance(struct Point a, struct Point b) {
    double distance;
    distance = sqrt((a.x - b.x) * (a.x - b.x) + (a.y-b.y) *(a.y-b.y));
    return distance;
}

double polygon_area(int length, double x[], double y[]) {
    double area = 0.0;
    for (int i = 0; i < length; ++i) {
       int j = (i + 1) % length;
       area += (x[i] * y[j] - x[j] * y[i]);
    }
area = area / 2;
area = (area > 0 ? area : -1 * area);

return (area);
}

int main(int argc, char *argv[]) {
    int npoints, poly_id;
    struct Point a, b;

    if(scanf("%d %d", &npoints, &poly_id)) {
        int iteration = 0;
        scanf("%lf %lf", &a.x, &a.y);
        struct Point initialPoint = a;
        double perimeter = 0;  // i start with 0 value of parameter.     
        for (iteration = 1; iteration < npoints; ++iteration) {
            scanf("%lf %lf", &b.x, &b.y);  // take input for new-point.
            perimeter += getDistance(a, b); // add the perimeter.
        // for next iteration, new-point would be first-point in getDistance
            a = b; 
        }
        // now complete the polygon with last-edge joining the last-point
        // with initial-point.
        perimeter += getDistance(a, initialPoint);

        printf("First polygon is %d\n", poly_id);
        printf("perimeter = %2.2lf m\n", perimeter);

        scanf("%d %d", &npoints, &poly_id);
        double x[MAX_PTS], y[MAX_PTS];
        double area = 0;
        for (iteration = 0; iteration < npoints; ++iteration) {
            scanf("%lf %lf", &(x[iteration]), &(y[iteration]));
        }
        area = polygon_area(npoints, x, y); 

        printf("First polygon is %d\n", poly_id);
        printf("area = %2.2lf m^2\n", area);

    } else if(scanf("%d", &npoints)==0) {
        exit(EXIT_SUCCESS);
    }

    return 0;
}

我一直得到的输出是:

First polygon is 12867
perimeter = 10.24 m
First polygon is 15643
area = 19.59 m^2

但我想要的输出是:

First polygon is 12867
perimeter = 10.24 m
First polygon is 12867
area = 4.50 m^2 

或者:

First polygon is 12867
perimeter = 10.24 m
area = 4.50 m^2

如果有人能指出我出错的地方,我们将不胜感激。

1 个答案:

答案 0 :(得分:0)

如果你还没有整理出来,你的问题很明显。您读取第一个多边形的数据,然后计算perimeter

    perimeter += getDistance(a, initialPoint);

    printf("First polygon is %d\n", poly_id);
    printf("perimeter = %2.2lf m\n", perimeter);

然后,莫名其妙地,在计算区域之前,您会读取第二个多边形的数据:

    scanf("%d %d", &npoints, &poly_id);
    double x[MAX_PTS], y[MAX_PTS];
    double area = 0;
<snip>
    area = polygon_area(npoints, x, y); 

您希望如何使用第二个多边形的数据获取第一个多边形的区域有点令人困惑。

您需要做的是在读取下一个数据之前计算每个多边形的perimeterarea。您通常会提示输入if进行处理,然后执行以下操作,而不是您的number of polygons代码块。

for (i = 0; i < npolys; i++)
{
    <read data for poly>
    <calculate perimeter>
    <calculate area>
    <display results>
}

接下来,当您期望来自用户的数据时,请提示它。不要只是让用户看着一个闪烁的光标,想知道你的程序是否挂起等等。一个简单的printf要求点数和多边形id工作正常。然后,输入每个x / y对的类似提示很大程度上消除了混淆。考虑到上述所有因素,您的代码可以重写为:

int main (void) {

    size_t npoints, poly_id;
    size_t npolys = 0;
    size_t it = 0;
    struct Point a, b;

    printf ("\nNumber of polygons to enter: ");
    scanf (" %zu", &npolys);

    for (it = 0; it < npolys; it++)
    {
        double x[MAX_PTS], y[MAX_PTS];
        double perimeter = 0;
        double area = 0;
        size_t iter = 0;

        printf ("\nEnter npoints & poly_id    : ");
        scanf("%zu %zu", &npoints, &poly_id);

        printf ("Enter the first point X & Y: ");
        scanf("%lf %lf", &a.x, &a.y);

        x[iter] = a.x;
        y[iter] = a.y;

        struct Point initialPoint = a;

        for (iter = 1; iter < npoints; ++iter) 
        {
            printf ("           next point X & Y: ");
            scanf("%lf %lf", &b.x, &b.y);   /* input for new-point. */

            x[iter] = b.x;
            y[iter] = b.y;

            perimeter += getDistance(a, b); /* add the perimeter.   */
            a = b;                          /* new-pt is first-pt   */
        }

        /* complete polygon joining the last-point with initial-point. */
        perimeter += getDistance (b, initialPoint);
        area = polygon_area (npoints, x, y); 

        printf("\nPolygon %zu is %zu\n", it, poly_id);
        printf("perimeter = %2.2lf m\n", perimeter);
        printf("     area = %2.2lf m^2\n", area);

    }

    return 0;
}

但是为什么不为您的代码编写一个输入例程来读取您的数据文件并消除容易出错的用户输入?这需要一点时间,但并不难。这样,您就可以完全分离代码的输入和处理功能。

这使您可以实际上专注于以逻辑方式放置代码的处理部分,而不是让处理逻辑充满用户输入。以下是如何将输入与代码逻辑分开以帮助保持代码清洁和可读性的示例。它在开始第一次计算之前将所有数据读入结构数组。

当您将代码分成逻辑函数时,它会使perimeterarea这样的单个计算维护成为调整单个函数逻辑的简单问题。如果您有任何疑问,请查看以下内容并告知我们:

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

#define MAXPTS 100
#define MAXPOLYS 100

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

typedef struct polygon {
    size_t sz;
    size_t id;
    point *vertex;
} polygon;

double get_distance (point a, point b);
double poly_perim (polygon a);
double polygon_area (polygon pg);
polygon *read_data (char *fn);

int main (int argc, char **argv)
{
    if (argc < 2 ) {
        fprintf (stderr, "error: insufficient input, usage: %s filename\n", argv[0]);
        return 1;
    }

    size_t it = 0;
    size_t idx = 0;
    polygon *pg = read_data (argv[1]);

    if (!pg) return 1;

    while (pg[idx].sz)
    {
        printf ("\n id: %zu   points: %zu  perimeter: %6.2lf  area: %6.2lf\n\n", 
                pg[idx].id, pg[idx].sz, poly_perim (pg[idx]), polygon_area (pg[idx]));

        for (it = 0; it < pg[idx].sz; it++)
            printf ("  %5.2lf  %5.2lf\n", pg[idx].vertex[it].x, pg[idx].vertex[it].y);

        idx++;
    }

    return 0;
}

double get_distance (point a, point b)
{
    double distance;
    distance = sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    return distance;
}

double poly_perim (polygon a)
{
    int i = 0;
    double perim = get_distance (a.vertex[0], a.vertex[a.sz -1]);

    for (i = 1; i < a.sz; i++)
        perim += get_distance (a.vertex[i-1], a.vertex[i]);

    return perim;
}

double polygon_area (polygon pg)
{
    double area = 0.0;
    int i = 0;

    for (i = 0; i < pg.sz; ++i) 
    {
        int j = (i + 1) % pg.sz;
        area += (pg.vertex[i].x * pg.vertex[j].y - pg.vertex[j].x * pg.vertex[i].y);
    }

    area /= 2.0;
    area = area > 0 ? area : -1 * area;

    return area;
}

polygon *read_data (char *fn)
{
    char *ln = NULL;
    size_t n = 0;
    size_t it = 0;
    size_t idx = 0;
    ssize_t nchr = 0;
    FILE *fp = NULL;
    polygon *pg = NULL;

    if (!(fp = fopen (fn, "r"))) {
        fprintf (stderr, "%s() error: file open failed '%s'.\n", __func__, fn);
        exit (EXIT_FAILURE);
    }

    if (!(pg = calloc (MAXPOLYS, sizeof *pg))) {
        fprintf (stderr, "%s() error: virtual memory allocation failed.\n", __func__);
        exit (EXIT_FAILURE);
    }

    while ((nchr = getline (&ln, &n, fp)) != -1)
    {
        char *p = ln;
        char *ep = NULL;
        long lnum = 0;
        double dnum = 0;

        errno = 0;
        lnum = strtol (p, &ep, 10);
        if (errno == 0 && (p != ep && lnum != 0))
            pg[idx].sz = (size_t)lnum;
        else {
            fprintf (stderr, "%s() error: file read failure '%s'.\n", __func__, fn);
            exit (EXIT_FAILURE);
        }

        p = ep;
        errno = 0;
        lnum = strtol (p, &ep, 10);
        if (errno == 0 && (p != ep && lnum != 0))
            pg[idx].id = (size_t)lnum;
        else {
            fprintf (stderr, "%s() error: file read failure '%s'.\n", __func__, fn);
            exit (EXIT_FAILURE);
        }

        pg[idx].vertex = calloc (pg[idx].sz, sizeof *(pg[idx].vertex));
        if (!pg[idx].vertex) {
            fprintf (stderr, "%s() error: virtual memory allocation failed.\n", __func__);
            exit (EXIT_FAILURE);
        }

        for (it = 0; it < pg[idx].sz; it++)
        {
            p = ep;
            errno = 0;
            dnum = strtod (p, &ep);
            if (errno == 0 && (p != ep && lnum != 0))
                pg[idx].vertex[it].x = dnum;
            else {
                fprintf (stderr, "%s() error: file read failure '%s'.\n", __func__, fn);
                exit (EXIT_FAILURE);
            }

            p = ep;
            errno = 0;
            dnum = strtod (p, &ep);
            if (errno == 0 && (p != ep && lnum != 0))
                pg[idx].vertex[it].y = dnum;
            else {
                fprintf (stderr, "%s() error: file read failure '%s'.\n", __func__, fn);
                exit (EXIT_FAILURE);
            }
        }
        idx++;
        if (idx == MAXPOLYS) {
            fprintf (stderr, "%s() warning: MAXPOLYS reached in file '%s'.\n", __func__, fn);
            break;
        }
    }

    fclose (fp);
    if (ln) free (ln);

    return pg;
}

<强>输入

$ cat dat/poly.txt
  3  12867  1.0 2.0  1.0 5.0  4.0 5.0
  5  15643  1.0 2.0  4.0 5.0  7.8 3.5  5.0 0.4  1.0 0.4

<强>输出

$ ./bin/poly dat/poly.txt

 id: 12867   points: 3  perimeter:  10.24  area:   4.50

   1.00   2.00
   1.00   5.00
   4.00   5.00

 id: 15643   points: 5  perimeter:  18.11  area:  19.59

   1.00   2.00
   4.00   5.00
   7.80   3.50
   5.00   0.40
   1.00   0.40