NO

Author Topic: Weird scanf behaviour  (Read 4947 times)

andre104

  • Guest
Weird scanf behaviour
« on: July 28, 2009, 08:07:55 PM »
This is a simple calculator program I made

Code: [Select]
#include <stdio.h>

int main (){
int x,y,h;
char z;

x=0;
y=0;
h=0;

printf ("x: ");
scanf ("%d", &x);
printf ("y: ");
scanf ("%d", &y);
//while ((z = getchar()) != '\n' && z != EOF);
printf ("z: ");
scanf("%c",&z);
if (z == '+') {
h=x+y; printf ("%d", h);
getch();
}
else if (z == '-') {
h=x-y; printf ("%d", h);
getch();
}
else if (z == '*') {
h=x*y; printf ("%d", h);
getch();
}
else if (z == '/') {
h=x/y; printf ("%d", h);
getch();
}
return 0;
}

The strange part is, after z: printed, then the program suddenly quits.
I don't understand why. It's supposed to ask input for z.

But when I add this line before printf("z: ") :
Code: [Select]
while ((z = getchar()) != '\n' && z != EOF);
Then the program runs correctly. Any idea why?

Offline AlexN

  • Global Moderator
  • Member
  • *****
  • Posts: 394
    • Alex's Link Sammlung
Re: Weird scanf behaviour
« Reply #1 on: July 29, 2009, 07:35:26 AM »
But when I add this line before printf("z: ") :
Code: [Select]
while ((z = getchar()) != '\n' && z != EOF);
Then the program runs correctly. Any idea why?

scanf("%d", &y); reads from the input-stream only to the end of the number. The end of line stays in the input stream. Without the line above scanf("%c",&z); reads as character '0x0A' from the end of line. This is wheter '+', '-', '*' nor '/' so the program runs to the end. ;)
best regards
 Alex ;)

andre104

  • Guest
Re: Weird scanf behaviour
« Reply #2 on: July 29, 2009, 08:02:56 AM »
scanf("%d", &y); reads from the input-stream only to the end of the number. The end of line stays in the input stream. Without the line above scanf("%c",&z); reads as character '0x0A' from the end of line. This is wheter '+', '-', '*' nor '/' so the program runs to the end. ;)

Uhm I still don't get it... 
scanf("%c",&z); is supposed to wait for Enter to be pressed, right?
if not, then how can it read the newline character?

???

Paolo_R

  • Guest
Re: Weird scanf behaviour
« Reply #3 on: July 29, 2009, 08:35:42 AM »
Try adding fflush(stdin); immediately before scanf("%c", &z);

Paolo_R

  • Guest
Re: Weird scanf behaviour
« Reply #4 on: July 29, 2009, 08:38:11 AM »
... and you probably need to add #include <conio.h> and change getch() to _getch().

Offline AlexN

  • Global Moderator
  • Member
  • *****
  • Posts: 394
    • Alex's Link Sammlung
Re: Weird scanf behaviour
« Reply #5 on: July 29, 2009, 09:15:15 AM »
hm I still don't get it...  
scanf("%c",&z); is supposed to wait for Enter to be pressed, right?
if not, then how can it read the newline character?

???
Yes, but the RETURN-key produces a CR/LF (0x0D/0x0A). The scanf before read to the CR and LF stands still in the input-stream. When you hit the RETURN-key again, scanf() start reading from the input stream and there is the first char the LF (0x0A) from the previous line.

fflush(stdin); from Paolo_R will empty the input stream, before you start reading a single char.
best regards
 Alex ;)

andre104

  • Guest
Re: Weird scanf behaviour
« Reply #6 on: July 29, 2009, 02:18:54 PM »
Try adding fflush(stdin); immediately before scanf("%c", &z);

yes... i know that
but according to this article, fflush(stdin) should be avoided

mmm...

nicolas.sitbon

  • Guest
Re: Weird scanf behaviour
« Reply #7 on: July 29, 2009, 03:23:22 PM »
Code: [Select]
#include <stdio.h>
#include <stdbool.h>

static inline int get_int(char const * const message)
{
   int found  = 0;
   int result = 0;

   do
   {
      puts(message);
      found = scanf("%d", &result);
      scanf("%*[^\n]"), getchar();
   }
   while(found != 1);

   return result;
}

static inline char get_char(char const * const message)
{
   int character = EOF;

   do
   {
      puts(message);
      character = getchar();

      if(character != '\n'  &&  character != EOF)
      {
         scanf("%*[^\n]"), getchar();
      }
   }
   while(character == EOF);

   return (char) character;
}

static inline bool is_valid_operator(char operator)
{
   return (operator == '+'  ||  operator == '-'  ||  operator == '*'  ||  operator == '/');
}

static inline char get_operator(char const * const message)
{
   char operator = 0;

   do
   {
      operator = get_char(message);
   }
   while(is_valid_operator(operator) == false);

   return operator;
}

int main(void)
{
   int x = get_int("enter first operand :");
   int y = get_int("enter second operand :");
   int result = 0;

   switch(get_operator("enter operator :"))
   {
      case '+': result = x + y; break; /* TODO : check overflow */
      case '-': result = x - y; break; /* TODO : check overflow */
      case '*': result = x * y; break; /* TODO : check overflow */
      case '/': result = x / y; break; /* TODO : check overflow */
   }

   printf ("result = %d\n", result);

   return 0;
}

Paolo_R

  • Guest
Re: Weird scanf behaviour
« Reply #8 on: July 30, 2009, 06:17:57 AM »
Quote
but according to this article, fflush(stdin) should be avoided

... and according to that article so should scanf()!