目前我有这段代码,而且有效。
#include <stdio.h>
int isFactor(long number1, long number2)
{
int isitFactor = (number2 % number1 == 0)?1:0;
return isitFactor;
}
int isPerfect(int number)
{
int counter;
int sum;
for (counter = 1; counter < number; counter++)
if (isFactor(counter, number))
sum += counter;
return (sum == number);
}
int main()
{
int counter = 1;
for (counter = 1; counter <= 100; counter++)
{
printf("", isPerfect(counter));
if (isPerfect(counter))
printf("%d\n", counter);
}
}
但是,如果我在main()中使用printf取出不必要的行,则无法生成任何数字....可能的原因?!
答案 0 :(得分:12)
函数sum
中的变量isPerfect
未初始化。
答案 1 :(得分:6)
这个代码有两个问题,第一个问题是sum
没有初始化,通常会设置为调用函数时堆栈上发生的垃圾。自动变量不保证初始化为零(或任何事情,因此),因此,如果您需要它们以特定值开头,则必须自己初始化它们。
第二个问题(现在已修复了您的编辑)是缺少isFactor
。虽然您可能希望它作为一个函数,但以下代码可以正常工作,产生两个小于100的完美数字6
和28
:
#include "stdio.h"
#define isFactor(c,n) ((n % c) == 0)
int isPerfect (int number) {
int counter;
int sum = 0; // <-- note initialisation here.
for (counter = 1; counter < number; counter++)
if (isFactor(counter, number)) sum += counter;
return (sum == number);
}
int main (void) { // try to use one of the two canonical forms.
int counter = 1;
for (counter = 1; counter <= 100; counter++)
if (isPerfect(counter)) printf("%d\n", counter);
return 0;
}
并且,调查为什么它可以使用额外的printf
,这是一个可行的解释。
调用函数时,只需减少堆栈指针即可在堆栈上分配局部变量。你的isPerfect
组装代码可能只有一个序言:
sub %esp,8
然后使用%esp中的内存counter
和%esp + 4
来获取总和。如果没有初始化sum
,它会从发生在该内存位置的任何内容开始,这可能不是零。
现在想想当你先致电printf
时会发生什么。毫无疑问它有自己的局部变量,所以它使用了后来依赖的堆栈部分初始化为零。当printf
返回时,它不会将这些内存位置设置回以前的值,它只是递增堆栈指针以跳过它们。
然后,当您致电isPerfect
时,很有可能这些记忆位置与您拨打printf
之前的记忆位置不同,只是因为printf
一直在使用它们它自己的目的。
如果你很幸运(或不幸,取决于你的观点),sum
所在的记忆位置甚至可能为零。但是它仍然是未定义的行为,你应该不依赖它 - 明确地初始化sum
并且你的(直接)问题将会结束。
如果这是作业,请随意忽略这一点(事实上,主动忽略它,因为你可能会因为剽窃而被抓住)。这就是我将isPerfect
函数实现为第一次剪切的方法。它并没有调用函数来计算因子,因为它们通常非常快,它们并非没有成本,而且无论如何都可以在单行C中完成。
int isPerfect (int num) {
int i, left;
for (i = 1, left = num; i < num; i++)
if ((num % i) == 0)
left -= i;
return (left == 0);
}
毫无疑问,可以加快速度,但投资回报率会在一定程度上迅速下降。