-1

I'm relatively new to C and I am trying to get a program to run. It's a program that lists all primes from 1 - 1000. The way I compile it is by typing gcc Primes.c into the command line and running it in NppExec.

Code:

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

int x;
int bool = 1;
int y;

main() {

    for (x = 2; x <= 100; x++) {
        bool = 1;
        for (y = 0; y <= floor(x/2); y++) {
            if (x % y == 0) {
               bool = 0;    
            }
        }

        if (bool == 1) {
            printf("%d\n", x);  
        }
    }
}

I type:

NPP_SAVE
CD $(CURRENT_DIRECTORY)
C:\MinGW32\bin\gcc.exe -g "$(FILE_NAME)" 
a

into the box and then execute. A window will pop up and say a.exe has stopped working. Any idea's on how to fix this?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Hunter VL
  • 101
  • 1
  • 2
  • 2
    Don't use `bool` as a variable name, it can actually be a defined type in C. – Some programmer dude Jan 30 '16 at 06:56
  • Don't attempt to evaluate `x % y` when `y` is `0`. That's a divide-by-zero error. You also don't need to use `floor(x/2)`. Just `x/2` will suffice, since `x` is an integer. Calling `floor` serves no purpose other than to convert it to `double` for no useful reason. – Tom Karzes Jan 30 '16 at 07:21
  • Compile with all warnings and debug info `gcc -Wall -Wextra -g` then **use the debugger** (`gdb`) so learn how to use it. – Basile Starynkevitch Jan 30 '16 at 07:27
  • FYI, dependently types languages aim to solve this sort of problem. You can write your program in such a language so that it does not compile if you cannot prove that `y != 0`. See this [gist](https://gist.github.com/edwinb/0047a2aff46a0f49c881) for an example. – Hugo O. Rivera Jan 30 '16 at 08:41
  • The key part in that gist is: `safe_div : (x : Int) -> (y : Int) -> {auto p : so (y /= 0)} -> Int` It takes two integers `x, y` and a proof that `y != 0`. If you give it non-integers, or if you can't show that `y != 0`, the program will not compile. – Hugo O. Rivera Jan 30 '16 at 08:42

3 Answers3

3

There is a bug and many smaller issues in your code:

  • You should not define x, bool and y as global variables, define these variables inside the body of the main function.
  • The prototype for main is int main(void) or int main(int argc, char *argv[]). main() is an obsolete form that is no longer supported by the C standard. gcc will accept it but clang will not by default. You should also add return 0; at the end of main: although it was made implicit in C99, it is better style and more portable to older compilers.

  • You should not use bool as a variable name, bool is usually used as a type name, name your flag prime.

  • You should loop until 1000 as instructed.

  • y <= floor(x / 2) does not work as expected: x / 2 is an integer expression, it already has the value you expect, passing it to floor will convert it as a double and return the same value, y will be automatically converted to double for the comparison. All this is unnecessary, y <= x / 2 suffices. floor is the only function used from <math.h>, you can remove this include file too.

  • Note that your condition will let the program perform way too many iterations, you should instead use y * y <= x.

  • Initializing y to 0 will cause a division by zero when you compute x % y, invoking undefined behavior, the crash you observe. You must initialize y to 2 because all numbers are divisible by 1.

  • You should exit the loop when you detect that x is composite, avoiding unnecessary iterations.

Here is a corrected version:

#include <stdio.h>

int main(void) {
    int x, y, prime;

    for (x = 2; x <= 1000; x++) {
        prime = 1;
        for (y = 2; y * y <= x; y++) {
            if (x % y == 0) {
                prime = 0;
                break;
            }
        }
        if (prime == 1) {
            printf("%d\n", x);  
        }
    }
    return 0;
} 
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I think that about covers it. Only nit was the missed formatting `return 0` at the end of bulleted paragraph No. 2 (I'll let you fix it, I don't like edits to my answers over minutia) – David C. Rankin Jan 30 '16 at 07:21
  • @DavidC.Rankin: good point, I added extra precisions regarding the `return 0;` – chqrlie Jan 30 '16 at 07:27
  • `floor(x/2)` will not be converted back to `int`, silently or otherwise, as you claim. What will happen is `y` will be converted to `double` and the comparison will be done as `double`. – Tom Karzes Jan 30 '16 at 07:35
1

You have

for (y = 0; y <= floor(x/2); y++) {
    if (x % y == 0) {

You initialize y to zero, then you directly divide by y (i.e. zero). Division by zero doesn't work, it will crash your program.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

The problem are these 2 lines:

for (y = 0; y <= floor(x/2); y++) {
    if (x % y == 0) {

What do you expect to get with 2 % 0?

As per the standard:

C99 6.5.5p5 - The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.

The crash is because of the Modulo operator when y is 0.

how to check if there is a division by zero in c

Community
  • 1
  • 1
Sadique
  • 22,572
  • 7
  • 65
  • 91