1

Possible Duplicate:
Why doesn't getchar() wait for me to press enter?

I continue to learn C, and at this stage I have something that is not clear to me. When I write a program, that has several printf();, at the end, where I ask a user to press Enter key to finish the program, I have to write getchar(); twice, because when I write it once it does not work. I use getchar(); only at the end of the program, nowhere else.

I work on Ubuntu. I write in C.

here is my latest work:

#include<stdio.h>
main()
{
int m,n,r,k,q,l;
printf("This program will help you to find GCD & LCM of 2 non-negative integers\n");
printf("Now, you'll be asked to enter your integers, press Enter to continue");
getchar();
printf("Enter first integer:");
scanf("%i", &m);
printf("Enter second integer:");
scanf("%i", &n);
while(m<0 || n<0)
{
printf("The integers cannot be negative! You'll be asked to enter integers again.\n");
printf("Enter first integer:");
scanf("%i", &m);
printf("Enter second integer:");
scanf("%i", &n);
}
while(m==0 && n==0)
{
printf("Both of the integers cannot be zero at the same time! You'll be asked to enter integers again.\n");
printf("Enter first integer:");
scanf("%i", &m);
printf("Enter second integer:");
scanf("%i", &n);
}
if(n>m)
{
int b;
b=n;
n=m;
m=b;
}
r=m%n;
if(r==0)
{
printf("The GCD of these integers is %i\n", n);
printf("The LCM of these integers is %i\n", m);
printf("Press Enter to finish");
getchar();
getchar();
return 0;
}
k=n%r;
while(k>0)
{
r=k;
k=q;
}
l=(m*n)/r;
printf("The GCD of these integers is %i\n", r);
printf("The LCM of these integers is %i\n", l);
printf("Press Enter to finish");
getchar();
getchar();
return 0;
}
Community
  • 1
  • 1
454b
  • 133
  • 2
  • 6
  • 12
  • 1
    "Also, I have another question" -- then have it in *another question*. –  Aug 04 '12 at 14:12
  • `scanf` leaves the ENTER waiting in the buffer. The first `getchar` "eats" that ENTER; the second `getchar` waits for input. – pmg Aug 04 '12 at 14:17
  • @H2CO3, if you've got an answer - so please, answer. – 454b Aug 04 '12 at 14:17
  • @pmg, thanks. I understood. I found that fflush clears the buffer, but I did not find a way to creectly use it. can u help me? – 454b Aug 04 '12 at 14:18
  • @EmiLazE: try to use `fgets` (and `sscanf`) instead of `scanf`. `fgets` "eats" all of the input up to and including the ENTER. `scanf` wasn't designed for dealing with input from humans. – pmg Aug 04 '12 at 14:19
  • @pmg, will try it. so I have to write at the end something like this? fgets(); – 454b Aug 04 '12 at 14:21
  • 1
    No. Replace your `scanf("%d", ...)` calls with the pair `fgets(buffer, sizeof buffer, stdin); sscanf(buffer, "%d", ...);`. Don't forget to define buffer before using it, for example: `char buffer[1000];` – pmg Aug 04 '12 at 14:22
  • @EmiLazE No, you use `fgets` and `sscanf` _instead of_ `scanf`. – Some programmer dude Aug 04 '12 at 14:23
  • 2
    Oh! **don't use `fflush` on input streams**: that operation (`fflush` on input streams) is undefined in the C89 Standard (many C implementations today are still C89). – pmg Aug 04 '12 at 14:25
  • but one more thing - what is the difference in size of buffer? – 454b Aug 04 '12 at 14:29
  • 1
    `fgets` needs to know how much space it can use (to avoid buffer overflows). That's why it is passed the size of the buffer (it automatically takes into account the string terminator). – pmg Aug 04 '12 at 14:33
  • @pmg not only C89. It is UB in any C Standard (the latest Standard being C17 as of now). – alx - recommends codidact Apr 02 '19 at 22:59

1 Answers1

2

The reason you need 2 getchar() is because

  1. the last scanf() call left the ENTER waiting in the buffer
  2. the 1st getchar() "ate" that ENTER
  3. the 2nd getchar() waits for input.

To properly deal with user input, use fgets() and sscanf() instaed of the simpler scanf(). Define a buffer for these functions, for example

char buffer[1000];

and then replace your scanf() calls with the pair

fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, "%d", &n);

In the future you might want to also check the return value of sscanf() to detect invalid inputs, like foo42ENTER

if (sscanf(buffer, "%d", &n) != 1) /* invalid input */;

Edit (using strtol() rather than sscanf() is even better -- thanks to @Scooter)

char buffer[1000];
char *err;
/* ... */
fgets(buffer, sizeof buffer, stdin); /* error checking ommited */
n = strtol(buffer, &err, 10);
/* error checking ommited */
/* ... */
pmg
  • 106,608
  • 13
  • 126
  • 198
  • 1
    atoi() and strtol() can also be used to get a C string into an int. – Scooter Aug 04 '12 at 14:52
  • `atoi()` is not a good choice because there is no way to detect errors. **`strtol()` is even better than `sscanf()`**, thanks! – pmg Aug 04 '12 at 14:55
  • +1 for discouraging scanf(). C books should start using fgets()+sscanf() instead of scanf(). unbuffered IO is always dangerous – Aftnix Aug 04 '12 at 15:15