3

I am taking a training course on "C" and running into a problem. It's hard to explain so I'll post the code. This is training syntax, so don't ask me why it's done the way it is. When both of these segment blocks are run in a main(), the second block does not behave as if it exists alone in the main(). I have tried several IDE thinking it might be a bug.

/* First Segment Block */
int c;
printf("Type a letter: ");
c = getchar();
printf("You typed '%c'\n",c);

/* OR - outputs the same, to demonstrate putchar */

printf("You typed '");
putchar(c);
printf("'\n\n");

/* Second Segment Block */
int a,b,d;
printf("Type two letters: ");
a = getchar();
b = getchar();
d = getchar();
printf("You typed '");
putchar(a);
printf("' and '");
putchar(b);
printf("' and '");
putchar(d);
printf("'\n");

In the second segment block, I added a 3rd variable to test my theory. When you type the requested 2 letters, the first getchar() picks up a new line and the second getchar() picks up the first letter. The 3rd getchar() picks up the second letter. If you comment out the entire first segment block, then it behaves correctly, picking up the first letter by the first getchar() and the second letter by the second getchar(), displaying the output as expected.

Here is the output when both run together.

Type a letter: k
You typed (k)
You typed 'k'

Type two letters: lk
You typed '
' and 'l' and 'k'

RUN SUCCESSFUL (total time: 9s)

When they are run individually, the output is below.

First Segment Output.

Type a letter: k
You typed (k)
You typed 'k'

RUN SUCCESSFUL (total time: 5s)

Second Segment Output.

Type two letters: rf
You typed 'r' and 'f' and '
'

RUN SUCCESSFUL (total time: 5s)

The 3rd getchar() is a newline and that is expected.

Can anyone explain why when both segments are run in the same main(), the behavior is different from when run seperate?

Thank you in advance, Daniel N. (C language beginner)

DNadler
  • 33
  • 1
  • 4
  • 1
    Did you press return after answering the first prompt? That newline gets read by the next `getchar()`. – Barmar Dec 15 '16 at 15:56
  • 2
    When you typed the first letter, you also hit return, which shows up as a newline. The second `getchar()` reads the newline, and then the two letters are read (and there's an unread newline in the input). This is expected behaviour. If you'd typed `abc` and return, things would behave more nearly as you expected...except the extra `getchar()` calls would return without you typing anything more. – Jonathan Leffler Dec 15 '16 at 15:56
  • 1
    Newline (`'\n'`) is a `char` too.. – chux - Reinstate Monica Dec 15 '16 at 15:57
  • Well, it's a common mistake at the beginning. People forget that newline `\n` is treated like any other char. It will be worst with `scanf` – Fefux Dec 15 '16 at 15:59
  • When you typed your character, did you press the Enter key? getchar() may only get a character at a time, but you have to terminate the line. – octopusgrabbus Dec 15 '16 at 16:00

4 Answers4

4

On the first prompt, you type something like aEnter, so your input stream contains the characters 'a', '\n'. The first getchar call reads the a and leaves the newline in the input stream.

In response to the second prompt, you type bcEnter, so your input stream now contains '\n', 'b', 'c', '\n'.

You can probably figure out what happens from here - the next getchar call reads that newline character from the input stream.

There are a couple of ways to deal with this. One is to test your input, and try again if it's a newline:

do
{
  a = getchar();
} while ( a == '\n' );  // or while( isspace( a )), if you want to reject
                        // any whitespace character.

Another is to not use getchar; instead, use scanf with the %c conversion specifier and a blank space in the format string:

scanf( " %c", &c ); // you will need to change the types of your 
...                 // variables from int to char for this.
scanf( " %c", &a );
scanf( " %c", &b );
scanf( " %c", &c );

The leading space in the format string tells scanf to ignore any leading whitespace, so you won't pick up the newline character.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • The training I am taking creates a new file for each segment it explains, I have been just adding it to the end, as long as variables are unique. I guess "C" needs to be told how to handle each and every character, even when physical "Enter" is pressed, which is completely invisible. – DNadler Dec 15 '16 at 16:29
  • 1
    @DNadler: Newlines are not invisible; they are a character like any other. They don't have a glyph associated with them, but they do affect the display. – John Bode Dec 15 '16 at 16:36
0

Both 'space' and '\n (new line)' are characters as well. So, getchar() is getting every character you enter. For example, if you press 'a (enter) b', it will read a='a',b='\n',d='b'.

awerchniak
  • 357
  • 3
  • 16
0

This happens because your terminal is line buffered, so it's waiting for you to press Enter before passing any of the characters you've typed to your program. When you do press Enter, your program will receive any characters that you've typed, including the newline character (\n) produced by the Enter key.

The actual sequence of events looks like this:

  1. Your program prints the first prompt.
  2. Your program calls getchar(), which tries to read a character from the standard input stream. Since the stream is currently empty, it pauses your program until some input arrives.
  3. You see the prompt and press a key (say, X). Since your terminal is line buffered, your program doesn't see it yet, and so remains paused.
  4. You press Enter. Your terminal now send the characters you typed (X and \n) to your program.
  5. getchar() returns the first character available to your program on the standard input, i.e. X.
  6. Your code now prints the second prompt, and calls getchar() again. getchar() sees that there's another character (\n) still waiting on the standard input, and returns it immediately.
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
  • The newline from the first response is the blank line between the two outputs, correct? Therefore there should be nothing in the buffer waiting for the second response. it's already output to the screen – DNadler Dec 15 '16 at 16:10
  • My bad... I wasn't thinking about the physical pressing "Enter" on the keyboard. – DNadler Dec 15 '16 at 16:11
0

This is how input streams are. when the first segment is running and to enter the first char, you press enter. It is basically taken as character itself in the input stream. so if you enter 'a' and press enter, its like 'a\n' in input stream. Now with getchar, you read one char from input stream to your variable which is 'a' here. On giving you 'a', input stream is left with '\n' still. next time you do getchar, you will get '\n' as char. even if you enter new chars, it will always be first in stream ie, '\nabc....'

'\n' it just to explain new line character.

Anmol
  • 123
  • 4