0
#include <stdio.h>
#include <conio.h>
void main()
{
    int x=0,y=0,z=0;
    printf("Enter a number:");
    scanf("%d", &x);
    z=x/2;
    for(y=2; y<=z; y++)
    {
        if(x%y==0)
        {
            printf("%d is not prime", x);
            break;
        }
    }

    if(y==z+1)
    { 
        printf("%d is prime", x);
    }

    getch();

}

Simple program to find a prime number, a school project, the code should work just fine but after making a .exe file through cmd using MWGin, the executable program closes soon after entering the number even though getch is implemented.

P.S- Ignore conio, its required in school.

Edit:- Solved now.

  • What's left in the input buffer after `scanf("%d, &x");`? (*hint:* `'\n'`) Wonder if `getch()` takes that as your input.... (avoid `getch()` it is 100% non-portable to anything other than DOS/windows -- `getchar()` works fine) Your biggest issue is you should do `char buf[1024]; printf("Enter a number:"); if (!fgets (buf, sizeof buf, stdin)) { return 1; } if (sscanf (buf, "%d, &x") != 1)) { return 1; } ...` That way you read a line at a time (including the trailing `'\n'`) and don't have to worry about what `scanf()` leaves in the input buffer.... – David C. Rankin Jul 07 '23 at 09:27
  • 1
    Note: that should be `if (sscanf (buf, "%d", &x) != 1)` -- you have a quote in the wrong place. Hold on and I'll add an answer. – David C. Rankin Jul 07 '23 at 09:43
  • There is absolutely no need for `scanf` at all here. Reading parameters from stdin instead of from command line parameters is a horrible anti-pattern when learning the language. Reading input is hard to get right, and there's no need for the extra confusion. Instead of reading `x` from the input stream, you ought to parse `argv[1]` (where main has been defined as `int main(int argc, char **argv)`. And don't ever write `void main() { ... }`. – William Pursell Jul 07 '23 at 14:09
  • @WilliamPursell I am barely a beginner so the answer seems more than a little confusing to me, but the problem seems to be because of the textbook I follow, I will look up new ones to correct whatever I was doing wrong. If you have any suggestions please list them, so. – Adyansh Mishra Jul 07 '23 at 16:19
  • If your textbook tells you to use `void main()` and `#include `, definitely get a better one. Try https://gustedt.gitlabpages.inria.fr/modern-c/ – n. m. could be an AI Jul 07 '23 at 19:33
  • @AdyanshMishra I am suggesting you do something like `int main(int argc, char **argv) { int x = argc > 1 ? strtol(argv[1], NULL, 0) : 10; ...` and invoke the function with the parameter passed as the first argument. Reading from `stdin` is unnecessary, and doing so with `scanf` is going to cause needless confusion. – William Pursell Jul 08 '23 at 13:12
  • @WilliamPursell Ah got it, thanks – Adyansh Mishra Jul 08 '23 at 13:47
  • @n.m.willseey'allonReddit Thanks, I will check it out – Adyansh Mishra Jul 08 '23 at 13:48

2 Answers2

1

Your primary problem is when you use scanf() to read an integer from stdin, you also input '\n' as a result of pressing [Enter]. scanf() using the "%d" conversion specifier does not read the '\n' and leaves it in the input buffer (stdin here) waiting to be read by the next input. When getch() encounters the '\n' in the input buffer -- it takes that as your input and happily exits -- nothing to wait for.

This is one of many reasons why you should use fgets() for all user-input. fgets() will read an entire line of data (into a sufficiently sized buffer/character array) including the trailing '\n'. scanf() is so full of pitfalls for the new programmer -- just like this one, you should learn how to handle input in a way that what remains in the input buffer does not depend on the scanf() conversion specifier used or whether a matching-failure occurs.

fgets() is recommended for all new (and seasoned) programmers.

How do I get my Number out from what fgets() reads?

Answer: sscanf(). Simply parse the string filled by fgets() using sscanf() instead or attempting to read directly from the input stream with scanf(). There are many benefits to this approach, including solving the problem you have run into. Just pass your buffer as the first parameter to sscanf(). It's just like using scanf() from the conversion there on. Don't forget to VALIDATE every input and every conversion...

What else is Wrong in Your Code?

void main() is not defined for a standards conforming program. (it is an anachronism - a holdover from an ancient time) Unless you are programming in a freestanding environment (without the benefit of any OS), in a conforming implementation, the allowable declarations for main for are int main (void) and int main (int argc, char *argv[]) (which you will see written with the equivalent char **argv). See: C11 Standard - §5.1.2.2.1 Program startup(p1). See also: What should main() return in C and C++? In a freestanding environment, the name and type of the function called at program startup are implementation-defined. See: 5.1.2.1 Freestanding environment

Space your code adequately. Errors are harder to find (and your old professor will go blind trying to read) code with all characters crammed together. The compiler doesn't care -- but humans do.

Lastly, always ensure you output a '\n' as the final output from your program to make your program POSIX compliant. Otherwise, it will mess up the command-line prompt for any user not using windows.

Putting it altogether, you can do something similar to:

#include <stdio.h>

#if defined (_WIN32) || defined (__MINGW32__)
#include <conio.h>
#endif

int main(void)
{
  char buf[1024];                 /* buffer to hold entire line of input */
  int x = 0, y = 0, z = 0;
  
  fputs ("Enter a number: ", stdout);
  
  /* read entire line of input into buf - validate EVERY input */
  if (fgets (buf, sizeof buf, stdin) == NULL) {
    return 1;
  }
  
  /* parse number from line using sscanf()  - validate EVERY conversion */
  if (sscanf (buf, "%d", &x) != 1) {
    fprintf (stderr, "error: invalid integer input '%s'.\n", buf);
    return 1;
  }
  
  z = x / 2;              /* WARNING - integer division! */
  
  for (y = 2; y <= z; y++) {
    if (x % y == 0) {
      printf ("%d is not prime\n", x);
      break;
    }
  }
  
  if (y == z + 1) { 
    printf ("%d is prime\n", x);
  }

#if defined (_WIN32) || defined (__MINGW32__)
  getch();
#endif
}

(note: the preprocessor macros just conditionaly include conio.h and call getch() if they are available -- otherwise they just skip that code)

Note the warning about integer division -- while intentional in this case, make sure you understand what it is. Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thanks for the answer, the main problems with my code seem to be because of the textbook I am following which seems to be outdated by your answer, if you don't mind, could you recommend a textbook to study C from the beginning? – Adyansh Mishra Jul 07 '23 at 16:16
  • @AdyanshMishra - Happy to. Just drop by [The Definitive C Book Guide and List](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) – David C. Rankin Jul 07 '23 at 18:28
0

The problem is in the scanf() function.

You wrote it:

scanf("%d, &x");

That's wrong. The variable "x"'s address, which will store the user input, is separate argument, it should be outside the string argument. Like this:

scanf("%d", &x);

Then your program works.

I guess it's just a typo mistake.

Sandrious
  • 118
  • 8