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
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
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
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. –