3

Can some one explain me why I see a double input of the printf() function the while loop:

#include <ctype.h>
#include <stdio.h>

int main(){
    int x = 0;

    while ( x != 'q'){

    printf("\nEnter a letter:");

    x=getchar();
    printf("%c\n", x);
    if( isalpha(x) )
      printf( "You entered a letter of the alphabet\n" );
    if( isdigit(x) )
      printf( "You entered the digit %c\n", x);
    }   
    return 0;
}

The output of the code in Debian Squeeze (gcc version 4.4.5 (Debian 4.4.5-8)) is:

Enter a letter:1
1
You entered the digit 1

Enter a letter: // why is the first one appearing ???


Enter a letter:2
2
You entered the digit 2
oz123
  • 27,559
  • 27
  • 125
  • 187
  • The "enter" key produces another character. Make your loop print the char values unconditionally and you'll see. Why did you assume that "printf was behaving strange"? – Kerrek SB Dec 04 '11 at 02:26

4 Answers4

5

The first one reads the line terminator character you entered when hitting Enter after 1 (the line terminator will remain in the input buffer).

You can verify this by adding an else branch:

#include <ctype.h>
#include <stdio.h>

int main()
{
  int x = 0;
  while ( x != 'q')
  {
    printf("\nEnter a letter:");
    x = getchar();
    printf("%c\n", x);
    if( isalpha(x) )
      printf( "You entered a letter of the alphabet\n" );
    else if( isdigit(x) )
      printf( "You entered the digit %c\n", x);
    else
      printf("Neither letter, nor digit: %02X\n", x);
  }
  return 0;
}

The output:

Enter a letter:1
1
You entered the digit 1

Enter a letter:

Neither letter, nor digit: 0A

Enter a letter:2

The byte 0A is the line-feed character.

kol
  • 27,881
  • 12
  • 83
  • 120
  • OK, I understand. So, how is one supposed to read a single char from std ? scanf("%s", x) does not control more than one letter... – oz123 Dec 04 '11 at 02:31
  • I would use scanf, and analyze the string I got. If it's not a single character (strlen(x) != 1), then I would print an error message, and give the "Enter a letter:" again. This approach also works if you want to read an integer. In this case the safe way is to read a string, and try to convert it to an integer (atoi). – kol Dec 04 '11 at 02:36
1

The second time through the loop, getchar() is getting the Enter after the first char you entered.

You could do something like

while ((c = getchar()) != EOF && c != '\n') {} /* eat the rest of the line */

to get rid of everything up to and including the next Enter after getting a char and before asking for another.

cHao
  • 84,970
  • 20
  • 145
  • 172
  • hmmm... I don't understand you solution. I does eat the "\n" caused by typing Enter, but it then causes the program to exit the loop. – oz123 Dec 04 '11 at 03:09
  • this works, paraphrasing your suggestion: while ( c != 'q'){ printf("\nEnter a letter:"); while ((c = getchar()) != EOF && c != '\n' && c != 'q') {} /* eat the rest of the line */ } – oz123 Dec 04 '11 at 03:14
0

If you want to check characters as you enter a slightly advanced technique would be to change stdin's behavior to raw mode.Then as soon as the user hits a char you get that in your variable. Check this for some start

Community
  • 1
  • 1
bashrc
  • 4,725
  • 1
  • 22
  • 49
0

Use CTRL + D to get the functionality of the newline character without its side effect.

arnkore
  • 425
  • 5
  • 14