我一直得到c的负数,b只打印23,a像应该的那样循环。当我把它放在外围时,至少输出加起来是24。我觉得我差一点就是一些愚蠢的逻辑错误。我的代码在下面。
编写一个程序来查找所有边长为整数的三角形和一个用户指定的周长。您的程序应该找到所有的三元组a、b和c,其中a+b+c是用户指定的周长值。
1 #include <stdio.h>
2
3 int main() {
4 int p, a, b, c;
5 printf("Enter a perimeter: ");
6 scanf("%d", &p);
7
8 printf("Triangles with a perimeter: " " %dn", p);
9
10 for(a = 1; a < p; a++) {
11 for(b = a; b < p; b++)
12 c = p - (a + b);
13 b = p - (a + c);
14 a = p - (b + c);
15
16 printf("%d, %d, %dn",a,b,c);
17
18 }
19 return 0;
20 }
我认为这更像是一个面试问题,而不是一个初学者的问题。
原始代码中有几处错误。有些与三角形是什么有关,有些则是基本逻辑出错。
for (a = 1; a < p; a++)
是错误的,因为三角形的一侧不能长于周长的一半。即使在周长的一半,也会形成两条线,而不是一个三角形。
CCD_ 2是错误的,因为CCD_。
基于p
、a
和b
的值来计算c
。
c = p - (a + b);
计算b
和a
有什么意义?
b = p - (a + c);
a = p - (b + c);
正如Jonathan Leffler所指出的,代码应该只打印唯一的三角形。这可以通过在printf
语句之前添加条件a<=b && b<=c
来容易地实现。
感谢@JonathanLeffler花时间调试这段短代码。发现了一个错误,该错误导致代码跳过某些输出,因为b
被初始化为更高的值,并且内部for循环条件提前终止了循环。
这是代码的更正版本。
#include <stdio.h>
int main() {
int p, a, b, c;
printf("Enter a perimeter: ");
scanf("%d", &p);
printf("Triangles with a perimeter: " " %dn", p);
for (a = 1; 2*a < p; a++) {
for (b = 1; a+b < p; b++)
if ((p-2*a) > 0 && (p-2*b) > 0 && (2*a+2*b-p) > 0) {
c = p - (a + b);
if(a<=b && b<=c)
printf("%d, %d, %dn", a ,b, c);
}
}
return 0;
}
现在让我们试试。
Enter a perimeter: 6
Triangles with a perimeter: 6
2, 2, 2
没错。周长为6
的三角形只有1
的可能组合。1, 1, 4
单位长的边不会是三角形,除非您愿意弯曲4
单位长的面。
Enter a perimeter: 12
Triangles with a perimeter: 12
2, 5, 5
3, 4, 5
4, 4, 4
输出中的重复信息
alvits目前接受的答案产生了许多重复的输出,其中组合是边的相同组合的排列。我修改了代码以打印3到29周长的所有三角形,并在打印操作之前添加了建议的条件if (a <= b && b <= c)
。
tp17.c
注意:代码不正确
#include <stdio.h>
int main(void)
{
int p, a, b, c;
// printf("Enter a perimeter: ");
// scanf("%d", &p);
for (p = 3; p < 30; p++)
{
printf("Triangles with perimeter: %dn", p);
for (a = 1; 2 * a < p; a++)
{
for (b = (p - a) / 2; (p - 2 * a) > 0 && (p - 2 * b) > 0 && (2 * a + 2 * b - p) > 0; b++)
{
c = p - (a + b);
if (a <= b && b <= c)
printf("%d, %d, %dn", a, b, c);
}
}
}
return 0;
}
结果的for (b = 1; b < (p - a); b++)
0之前的条件if (a <=b && b <= c)
旨在确保每个长度组合只生成一次。例如,我注意到,在p=12的情况下,可以得到:(2, 5, 5)
、(3, 4, 5)
、(4, 4, 4)
作为输出。不过,我错过的是,对于p = 11
,添加条件会省略(3, 5, 3)
(因为代码没有生成(3, 3, 5)
,原因我无法理解)。因此,这个条件还不够好——它确实消除了很多重复条目(好),但也丢弃了一些不重复的条目(坏)。
因此,代码应该消除这种情况,因为这种情况会使程序生成大量冗余输出,从而使输出比较非常复杂。
tp13.c
我还创建了一个密切相关的程序,从同一个基础开始:
#include <stdio.h>
int main(void)
{
for (int p = 3; p < 30; p++)
{
printf("Triangles with perimeter: %dn", p);
for (int a = 1; a <= p / 2; a++)
{
for (int b = 1; b + a < p; b++)
{
int c = p - (a + b);
if (a + b <= c || a + c <= b || b + c <= a)
continue;
if (a <= b && b <= c)
printf("%d, %d, %dn", a, b, c);
}
}
}
return 0;
}
输出比较
比较tp13
和a+b
0输出的部分diff -u
输出为:
Triangles with perimeter: 11
1, 5, 5
2, 4, 5
-3, 3, 5
+2, 5, 4
3, 4, 4
+3, 5, 3
+4, 3, 4
+4, 4, 3
+4, 5, 2
+5, 3, 3
+5, 4, 2
+5, 5, 1
Triangles with perimeter: 12
2, 5, 5
3, 4, 5
+3, 5, 4
4, 4, 4
+4, 5, 3
+5, 3, 4
+5, 4, 3
+5, 5, 2
Triangles with perimeter: 13
看看周长为12的结果,很明显tp17
只是生成不同的排列。然而,观察周长为11的结果表明,tp17
生成(3, 5, 3)
和(5, 3, 3)
,但不生成(3, 3, 5)
,而tp13
生成(3, 3, 5)
,而不生成其他两个排列。然而,所示输出片段中tp17
的输出中的所有其他额外行都是其他行的排列。
需要不同的输出格式
上面的输出格式不适合自动比较,所以我修改了输出,以打印周长,然后按非递减顺序列出三个边。因此,我在tp17.c
中添加了代码,以便在打印前按非递减顺序对边进行排序。对于三个元素,可能有更简单的方法可以做到这一点,但这很有效。
tp47.c
/* SO 4203-5818 - Calculate all triangles with given perimeter */
#include <stdio.h>
#include <stdlib.h>
static int int_cmp(const void *va, const void *vb)
{
int a = *(int *)va;
int b = *(int *)vb;
return (a > b) - (a < b);
}
int main(void)
{
int p, a, b, c;
for (p = 3; p < 30; p++)
{
for (a = 1; 2 * a < p; a++)
{
for (b = (p - a) / 2; (p - 2 * a) > 0 && (p - 2 * b) > 0 && (2 * a + 2 * b - p) > 0; b++)
{
c = p - (a + b);
{
int d[] = { a, b, c };
qsort(d, 3, sizeof(d[0]), int_cmp);
printf("%d: %d, %d, %dn", p, d[0], d[1], d[2]);
}
}
}
}
return 0;
}
tp43.c
/* SO 4203-5818 - Calculate all triangles with given perimeter */
#include <stdio.h>
int main(void)
{
for (int p = 3; p < 30; p++)
{
for (int a = 1; a <= p / 2; a++)
{
for (int b = 1; b + a < p; b++)
{
int c = p - (a + b);
if (a + b <= c || a + c <= b || b + c <= a)
continue;
if (a <= b && b <= c)
printf("%d: %d, %d, %dn", p, a, b, c);
}
}
}
return 0;
}
(除了打印,这与tp13.c
相同。)
比较
现在可以对输出进行排序和比较。tp43
的-u
选项是多余的,但却是对称的。
$ tp43 | sort -u -k1n -k2n -k3n -k4n > tp43.out
$ tp47 | sort -u -k1n -k2n -k3n -k4n > tp47.out
$ diff tp43.out tp47.out
$
因此,唯一的输出是相同的,但当你计算差异时,tp47
:的输出中有390行额外的行
$ tp43 | sort -k1n -k2n -k3n -k4n > tp43-all.out
$ tp47 | sort -k1n -k2n -k3n -k4n > tp47-all.out
$ diff tp43-all.out tp47-all.out | diffcount
deleted 0, inserted 390
$ wc -l tp4?.out tp4?-all.out
206 tp43.out
206 tp47.out
206 tp43-all.out
596 tp47-all.out
1214 total
$
仅为了记录,文件tp43.out
、tp47.out
、tp43-all.out
是相同的。它们的内容是:
3: 1, 1, 1
5: 1, 2, 2
6: 2, 2, 2
7: 1, 3, 3
7: 2, 2, 3
8: 2, 3, 3
9: 1, 4, 4
9: 2, 3, 4
9: 3, 3, 3
10: 2, 4, 4
10: 3, 3, 4
11: 1, 5, 5
11: 2, 4, 5
11: 3, 3, 5
11: 3, 4, 4
12: 2, 5, 5
12: 3, 4, 5
12: 4, 4, 4
13: 1, 6, 6
13: 2, 5, 6
13: 3, 4, 6
13: 3, 5, 5
13: 4, 4, 5
14: 2, 6, 6
14: 3, 5, 6
14: 4, 4, 6
14: 4, 5, 5
15: 1, 7, 7
15: 2, 6, 7
15: 3, 5, 7
15: 3, 6, 6
15: 4, 4, 7
15: 4, 5, 6
15: 5, 5, 5
16: 2, 7, 7
16: 3, 6, 7
16: 4, 5, 7
16: 4, 6, 6
16: 5, 5, 6
17: 1, 8, 8
17: 2, 7, 8
17: 3, 6, 8
17: 3, 7, 7
17: 4, 5, 8
17: 4, 6, 7
17: 5, 5, 7
17: 5, 6, 6
18: 2, 8, 8
18: 3, 7, 8
18: 4, 6, 8
18: 4, 7, 7
18: 5, 5, 8
18: 5, 6, 7
18: 6, 6, 6
19: 1, 9, 9
19: 2, 8, 9
19: 3, 7, 9
19: 3, 8, 8
19: 4, 6, 9
19: 4, 7, 8
19: 5, 5, 9
19: 5, 6, 8
19: 5, 7, 7
19: 6, 6, 7
20: 2, 9, 9
20: 3, 8, 9
20: 4, 7, 9
20: 4, 8, 8
20: 5, 6, 9
20: 5, 7, 8
20: 6, 6, 8
20: 6, 7, 7
21: 1, 10, 10
21: 2, 9, 10
21: 3, 8, 10
21: 3, 9, 9
21: 4, 7, 10
21: 4, 8, 9
21: 5, 6, 10
21: 5, 7, 9
21: 5, 8, 8
21: 6, 6, 9
21: 6, 7, 8
21: 7, 7, 7
22: 2, 10, 10
22: 3, 9, 10
22: 4, 8, 10
22: 4, 9, 9
22: 5, 7, 10
22: 5, 8, 9
22: 6, 6, 10
22: 6, 7, 9
22: 6, 8, 8
22: 7, 7, 8
23: 1, 11, 11
23: 2, 10, 11
23: 3, 9, 11
23: 3, 10, 10
23: 4, 8, 11
23: 4, 9, 10
23: 5, 7, 11
23: 5, 8, 10
23: 5, 9, 9
23: 6, 6, 11
23: 6, 7, 10
23: 6, 8, 9
23: 7, 7, 9
23: 7, 8, 8
24: 2, 11, 11
24: 3, 10, 11
24: 4, 9, 11
24: 4, 10, 10
24: 5, 8, 11
24: 5, 9, 10
24: 6, 7, 11
24: 6, 8, 10
24: 6, 9, 9
24: 7, 7, 10
24: 7, 8, 9
24: 8, 8, 8
25: 1, 12, 12
25: 2, 11, 12
25: 3, 10, 12
25: 3, 11, 11
25: 4, 9, 12
25: 4, 10, 11
25: 5, 8, 12
25: 5, 9, 11
25: 5, 10, 10
25: 6, 7, 12
25: 6, 8, 11
25: 6, 9, 10
25: 7, 7, 11
25: 7, 8, 10
25: 7, 9, 9
25: 8, 8, 9
26: 2, 12, 12
26: 3, 11, 12
26: 4, 10, 12
26: 4, 11, 11
26: 5, 9, 12
26: 5, 10, 11
26: 6, 8, 12
26: 6, 9, 11
26: 6, 10, 10
26: 7, 7, 12
26: 7, 8, 11
26: 7, 9, 10
26: 8, 8, 10
26: 8, 9, 9
27: 1, 13, 13
27: 2, 12, 13
27: 3, 11, 13
27: 3, 12, 12
27: 4, 10, 13
27: 4, 11, 12
27: 5, 9, 13
27: 5, 10, 12
27: 5, 11, 11
27: 6, 8, 13
27: 6, 9, 12
27: 6, 10, 11
27: 7, 7, 13
27: 7, 8, 12
27: 7, 9, 11
27: 7, 10, 10
27: 8, 8, 11
27: 8, 9, 10
27: 9, 9, 9
28: 2, 13, 13
28: 3, 12, 13
28: 4, 11, 13
28: 4, 12, 12
28: 5, 10, 13
28: 5, 11, 12
28: 6, 9, 13
28: 6, 10, 12
28: 6, 11, 11
28: 7, 8, 13
28: 7, 9, 12
28: 7, 10, 11
28: 8, 8, 12
28: 8, 9, 11
28: 8, 10, 10
28: 9, 9, 10
29: 1, 14, 14
29: 2, 13, 14
29: 3, 12, 14
29: 3, 13, 13
29: 4, 11, 14
29: 4, 12, 13
29: 5, 10, 14
29: 5, 11, 13
29: 5, 12, 12
29: 6, 9, 14
29: 6, 10, 13
29: 6, 11, 12
29: 7, 8, 14
29: 7, 9, 13
29: 7, 10, 12
29: 7, 11, 11
29: 8, 8, 13
29: 8, 9, 12
29: 8, 10, 11
29: 9, 9, 11
29: 9, 10, 10