2

I am a beginner in C and was working on a program that can output the prime numbers within the range using Eratosthenes' sieve. However, the program does not output anything and is in a loop, I believe this has to do with the repetitive use of for statements in my code but also have no idea where I may be going wrong. I tried putting break statements with if statements but it seems like it does not work. Thank you in advance.

#include <stdio.h>
#include <math.h>

int sieve(int limit);

int main() {
    int maximum = 0;
    printf("Enter the limit of prime numbers:");
    scanf_s("%d", &maximum);
    sieve(maximum);
    return 0;
}

int sieve(int limit) {
    int array[100];
    int common = 2;;

    for (int i = 0; i <= limit; i++) {
        array[i] = i + 1;
    }
    for (;;) {
        for (int j = 0; j <= limit; j++) {
            if (array[j] % common == 0 && !(array[j] == common)) {
                array[j] = 0;
                array[0] = 0;
            }
        } 
        for (int k = 0; k <= limit; k++) {
            if (!(array[k] == 0) && !(common == array[k])) {
                common = array[k];
                break;
            }
        }
        if (common >= sqrt(limit))
            break;
    }
    for (int o = 0; o < limit; o++) {
        if (!(array[o] == 0)) {
            printf("%d  ", array[o]);
        }
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Jorido
  • 25
  • 6
  • When watching in a debugger, where does it get stuck? – tadman May 10 '21 at 05:50
  • Remember: Break only busts out of one level of `for` loop. You could set a condition that breaks your outer `for` as well. – tadman May 10 '21 at 05:50
  • I actually have no clue on how to check this... It just doesn't output anything and doesn't finish the debugger. – Jorido May 10 '21 at 05:51
  • Hi tadman, wouldn't the if (common >= sqrt(limit)) break act as that condition? – Jorido May 10 '21 at 05:52
  • @Jorido, you are correct, it would. However this implies that it actually gets called. Have you tried putting a printf prior to the break statement to see whether the condition is actually met somewhere down the line? As an alternative, try setting a breakpoint on the 'break' or on the 'output' 'for', to see whether the program reaches there. – Refugnic Eternium May 10 '21 at 06:09
  • When you start your debugger, set a breakpoitn at `main` and several other "interesting" places. Or single-step through your program. There are zillions of tutorials how to use a debugger. You might like to extent on "[...] it does not work" because we have no idea what you're doing. – the busybee May 10 '21 at 06:10
  • Chances are, that your break condition is never met. Either use the debugger of your choice to verify that `common` actually gets increased in line 25 or put a `printf` telling you the current value of `common` right in front of the loop. When looking for an error, there is hardly a thing such as 'too much information'. – Refugnic Eternium May 10 '21 at 06:18
  • Does this answer your question? [How to break out of nested loops?](https://stackoverflow.com/questions/9695902/how-to-break-out-of-nested-loops) – flowit May 10 '21 at 06:19
  • 2
    Thank you guys for all the help! I watched some debugger tutorials and now I think I understand my mistake.... Again, thank you so much! – Jorido May 10 '21 at 06:59

2 Answers2

2

I hope I'm not out of my depth here since it's been a while since I have touched C.

You could set a boolean variable to false. Within the child loop you set it to true. Add an if statement within the parent loop to check if that variable is true and break the parent loop if it is.

Quick pseudo-code:

bool t = false
parent loop:
  child loop:
    if something
      t = true
  if t
    break
Dharman
  • 30,962
  • 25
  • 85
  • 135
thomas j
  • 56
  • 2
1

The outer loop runs for ever because you do not increment common inside the loop body.

Note also that you can enumerate all multiples of common with a simple addition instead of a costly % operator.

Here is a modified version:

#include <stdio.h>

int sieve(int limit);

int main() {
    int maximum = 0;
    printf("Enter the limit of prime numbers:");
    scanf_s("%d", &maximum);
    sieve(maximum);
    return 0;
}

int sieve(int limit) {
    int array[limit + 1];

    for (int i = 0; i <= limit; i++) {
        array[i] = i;
    }
    for (int common = 2; common * common <= limit; common++) {
        // remove all multiples of common. Start at common*common
        // because lesser multiples have already been removed as they
        // are multiples of a smaller number
        for (int i = common * common; i <= limit; i += common) {
            array[i] = 0;
        } 
    }
    for (int i = 1; i <= limit; i++) {
        if (array[i] != 0) {
            printf("%d  ", array[i]);
        }
    }
    printf("\n");
    return 0;
}

Note that you can use an array of unsigned char initialized to 1 and print i instead of array[i].

chqrlie
  • 131,814
  • 10
  • 121
  • 189