2015-04-23 2 views
-3

Ci-dessous est mon programme qui détermine le périmètre et la zone d'un polygone donné un certain nombre de coordonnées (x, y) mais je semble obtenir la mauvaise sortie et je ne vois pas pourquoi.Problème avec la sortie du programme

L'entrée est la suivante:

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 

Avec la première entrée étant le nombre de points (points) et la seconde entrée étant l'ID de polygone, tout ce qui suit est un ensemble de coordonnées.

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

Ma sortie Je continue à recevoir est:

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

Mais la sortie que je veux est:

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

Ou bien:

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

serait apprécié si quelqu'un pourrait juste signaler où je vais mal.

+4

Je suggère d'apprendre à utiliser un débogueur. L'idée est de parcourir votre code ligne par ligne et d'examiner les variables jusqu'à ce que vous trouviez l'erreur. Une alternative consiste à afficher les valeurs avec 'printf' à des points stratégiques. – dandan78

+0

Vous lisez dans le deuxième polygone avant d'avoir calculé la zone du premier polygone. Lire les coordonnées du premier polygone dans un tableau afin que vous puissiez faire à la fois le périmètre et la zone. – JS1

+0

Le titre de votre question indique qu'il y a un problème avec la sortie, quand ce n'est pas le problème réel. Le problème est clairement avec le code et pas un problème de sortie. Quand quelqu'un lit le titre de la question, ce n'est pas ce à quoi il s'attendrait. –

Répondre

0

Si vous ne l'avez pas encore résolu, votre problème est évident. Vous lisez les données pour le premier polygone, puis vous calculez le perimeter:

perimeter += getDistance(a, initialPoint); 

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

Puis, inexplicablement, vous lisez des données pour votre deuxième polygone avant de calculer la zone:

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

Comment comptez-vous obtenir la zone pour le premier polygone utilisant les données pour le deuxième polygone est un peu déconcertante.

Ce que vous devez faire est de calculer à la fois le perimeter et le area pour chaque polygone avant de lire les données pour le suivant. Plutôt que de votre bloc if de code, vous habituellement invite à entrer dans le number of polygons à traiter et à faire quelque chose comme:

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

Ensuite, lorsque vous attendez des données d'un utilisateur, il demandera. Ne laissez pas simplement l'utilisateur regardant un curseur clignotant se demandant si votre programme accroché, etc. Un simple printf demandant le nombre de points et l'ID de polygone fonctionne bien. Ensuite, une invite similaire à entrer chaque paire x/y va un long chemin à éliminer la confusion. En prenant tout ce qui précède en considération, votre code pourrait être réécrite comme:

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

Mais pourquoi ne pas écrire une routine d'entrée pour votre code pour lire votre fichier de données et d'éliminer l'erreur d'entrée utilisateur sujette? Cela prend un peu de temps, mais ce n'est pas difficile. De cette façon, vous pouvez séparer complètement les fonctions d'entrée et de traitement de votre code.

Cela vous libère de vous concentrer sur la mise en place logique de la partie traitement de votre code, au lieu de saupoudrer la logique de traitement avec l'entrée utilisateur. Voici un exemple de la façon dont la séparation des entrées de la logique de votre code peut aider à garder votre code propre et lisible. Il lit toutes les données dans un tableau de structures avant de commencer le premier calcul.Lorsque vous conservez votre code séparé en fonction logique, il est nécessaire de maintenir n'importe quel calcul individuel comme perimeter ou area pour régler simplement la logique d'une seule fonction. Jetez un oeil à ce qui suit et laissez-moi savoir si vous avez des questions:

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

Entrée

$ 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 

Sortie

$ ./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