Currently I have this code, and it works.
#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);
}
}
However, if I take out the unnecessary line with the printf in main(), it fails to produce any numbers.... Possible causes?!
Variable sum
in function isPerfect
is not initialized.
You had two problems with that code, the first is that sum
is not initialised and will generally be set to whatever rubbish happened to be on the stack at the time the function was called. Automatic variables are not guaranteed to be initialised to zero (or anything, for that matter) so, if you need them to start with a specific value, you have to initialise them yourself.
The second problem (now fixed with your edit) was that isFactor
is missing. Although you probably want it as a function, the following code works, producing the two perfect numbers less than 100, 6
and 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;
}
And, looking into why it might be working with that extra printf
, here's a viable explanation.
When calling a function, the local variables are allocated on the stack simply by reducing the stack pointer. Your isPerfect
asembly code probably just has a prolog like:
sub %esp,8
and then you use the memory at %esp for counter
and %esp + 4
for sum. Without initialising sum
, it starts with whatever happened to be at that memory location, which is probably not zero.
Now think about what happens when you call printf
first. It no doubt has its own local variables so it uses the part of the stack that you will later be relying on to be initialised to zero. When the printf
returns, it doesn't set those memory locations back to their previous values, it just increments the stack pointer to skip over them.
Then, when you call isPerfect
, there's a good chance that those memory locations will be different to what they were before you called printf
, simply because printf
has been using them for its own purposes.
If you're lucky (or unlucky, depending on your viewpoint), the memory location where sum
will be may even be zero. But it's undefined behaviour nonetheless and you should not rely on it - initialise sum
explicitly and your (immediate) problems will be over.
If this is homework, feel free to ignore this bit (in fact, actively ignore it since you may get caught out for plagiarism). This is how I would implement the isPerfect
function as a first cut. It doesn't call functions to work out factors since, while they're generally quite fast, they're not without cost, and something that simple can be done in a single line of C anyway.
int isPerfect (int num) {
int i, left;
for (i = 1, left = num; i < num; i++)
if ((num % i) == 0)
left -= i;
return (left == 0);
}
There's no doubt it could be made faster but the return on investment drops away pretty quickly after a certain point.
精彩评论