我继续得到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: " " %d\n", 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, %d\n",a,b,c);
17
18 }
19 return 0;
20 }
我认为这更像是一个面试问题,而不是一个初学者问题。
答案 0 :(得分:5)
原始代码中存在一些错误。一些与三角形为三角形的原因有关,有些是基本逻辑出错。
for (a = 1; a < p; a++)
错误,因为三角形的一边不能超过周长的一半。即使在周长的一半,也会产生2条线,而不是三角形。
for (b = 1; b < (p - a); b++)
错误,因为a+b
将小于开头的一半。
c
根据p
,a
和b
的值计算。
c = p - (a + b);
计算b
和a
b = p - (a + c);
a = p - (b + c);
正如Jonathan Leffler指出的那样,代码应该只打印唯一的三角形。这可以通过在a<=b && b<=c
语句之前添加条件printf
来轻松完成。
感谢@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: " " %d\n", 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, %d\n", 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
答案 1 :(得分:1)
当前接受的answer 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: %d\n", 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, %d\n", a, b, c);
}
}
}
return 0;
}
结果if (a <=b && b <= c)
之前的条件printf()
旨在确保您只生成一次长度的每个组合。我注意到,例如,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: %d\n", 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\n", a, b, c);
}
}
}
return 0;
}
比较diff -u
和tp13
输出的tp17
输出的一部分是:
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, %d\n", 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, %d\n", p, a, b, c);
}
}
}
return 0;
}
(除了打印,这与tp13.c
相同。)
现在可以对输出进行排序和比较。 -u
的{{1}}选项是多余的,但却是对称的。
tp43
因此,唯一的输出是相同的,但是当你计算差异时,$ tp43 | sort -u -k1n -k2n -k3n -k4n > tp43.out
$ tp47 | sort -u -k1n -k2n -k3n -k4n > tp47.out
$ diff tp43.out tp47.out
$
的输出中有390个额外的行:
tp47
仅供记录,文件$ 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