Frage

I'm reading K&R's The C Programming Language and have become confused on putchar and getchar. I made a program where you enter 10 chars and the program prints them back out to the screen.

#include <stdio.h>

int main() 
{
    int i;
    int ch;
    for(i = 0; i < 10; i++)
    {
        printf("Enter a single character >> ");
        ch = getchar();
        putchar(ch);
    }

    return 0;
}

I expected to get an output like this:

Enter a single character >> a
a
Enter a single character >> b
b

...and so on 10 times but this is the output I got: (I stopped after entering 2 chars)

Enter a single character >> a
aEnter a single character >>
Enter a single character >> b
bEnter a single character >>
Enter a single character >>

not sure why my input character is being combined with the fixed string and being output.

Also, I'm not too sure why ints are used to store characters.

War es hilfreich?

Lösung

putchar(ch);

just prints single character and the following printf continues within the same line. Simply add:

putchar('\n');

right after putchar(ch);, which will explicitly start the new line before the printf is executed. Additionally you should also take '\n' from the input which stays there after you enter the character:

for(i = 0; i < 10; i++)
{
    printf("Enter a single character >> ");
    ch = getchar();
    getchar();        // <-- "eat" new-line character
    putchar(ch);
    putchar('\n');    // <-- start new line
}

Andere Tipps

You are not printing a new line. After putchar(ch); you should use putchar('\n'); to print a new line.

User terminal can operate in canonical and non-canonical modes. By default it operates in canonical mode and this means that standard input is available to a program line-by-line (not symbol-by-symbol). In question user inputs something (let it be letter 'a', 0x61 in hex) and pushes enter (new line character '0x0A' in hex). Ascii table is here. So this action gives a two symbols to a program. As mentioned in man getchar() reads it symbol-by-symbol. So loop iterates twice for one character. To see what is going on use the following program (+loop counter output, +character code output):

#include <stdio.h>
#include <unistd.h>

int main() 
{
  int i;
  char ch;
  for(i = 0; i < 10; i++)
  {
    printf("Enter a single character %d >>", i);
    ch = getchar();
    printf("Ch=0x%08X\n", ch);
    /*putchar(ch);*/
  }

  return 0;
}

Output:

┌─(02:01:16)─(michael@lorry)─(~/tmp/getchar)
└─► gcc -o main main.c; ./main 
Enter a single character 0 >>a
Ch=0x00000061
Enter a single character 1 >>Ch=0x0000000A
Enter a single character 2 >>b
Ch=0x00000062
Enter a single character 3 >>Ch=0x0000000A
Enter a single character 4 >>^C

So program gets two symbols and prints them. And new line symbol is not visible. So in the question user see one strange additional line. Detailed description on different terminal modes and how to make its adjustments can be found here.

Also stty utility can be useful while working with terminal options ("icanon" tells if terminal use canonical mode or not).

And about storing chars as int in getchar() output - see my answer for similar topic.

The term on which our focus should be on, is "Stream".

A "Stream" is a like a bridge, responsible for flow of data in a sequential way. (The harmony of smooth streaming, both in and out of a program, is managed by libraries/header files, e.g. stdio.h)

Coming back to your question :

When you type input as 'a' and hit 'enter', you supply 2 values to input stream. - a (ASCII Value : 97) - enter (ASCII Value : 13) /*This 'enter' as an input is the devil. To keep it simple, i will keep calling it as Enter below, and the enter is usually not displayed on screen*/

NOTE/IMPORTANT/CAUTION before proceeding: Till the time your stream doesn't get completely empty, you can't write new characters from the console into the stream. (This scenario only implies for the use of getchar and putchar, as shown below)

HERE IS YOUR CODE:

for(i = 0; i < 10; i++)
    {
        printf("Enter a single character >> ");
        ch = getchar();
        putchar(ch);
    }

Loop Pass 1 : a) You ask user to enter a character. // printf statement b) getchar reads only a single character from stream. c) putchar renders/displays only a single character from stream. d) At first pass you provide input as 'a' but you also hit 'Enter' e) Now, your stream is like a ***QUEUE***, at first pass, and at 1st place of the queue, you have 'a' and at 2nd place 'enter'. Queue f) Once you do putchar, the first character , i.e. 'a' from the stream/queue gets displayed. e) Loop ends. g) Output of this pass: Enter a single character >>a

Loop Pass 2 : a) You ask user to enter a character. // printf() statement b) Unfortunately your stream isn't empty. It has an "enter" value from the previous pass. c) So, getchar(), reads the next single character, i.e. 'enter' from stream. (This is where you were expecting to manually enter the next character, but the system did it for you. Read the NOTE/IMPORTANT/CAUTION section mentioned above) d) putchar() displays 'enter' on screen, but since 'enter' is no displayable thing, nothing gets displayed. e) Output of this pass: Enter a single character >>

Loop Pass 3 : Similar as loop 1, only input this time is 'b'.

Loop Pass 4: Similar as loop 2

and so on till 10 passes. (So, last character you will be able to enter is 'e'.)

INFERENCE/CONCLUSION:

So, long story short, you were expecting to enter the next character, so that getchar would pick your entered value, but since from your previous pass,'enter' value was already waiting in the stream, it got displayed first, giving you such an illusion.

Thank you. Let me know if your thoughts are different.

Loop on the even number of time, getchar() is not taking input from keyboard, but it is taken from the previous entered hit, so you would have also noticed that loop is only executed 5 times. So you have to clear the buffer, i.e. pressed entered, so that new character can be entered in the ch.

for (i = 0; i < 5; i++)
    {
        printf("\nEnter a single character >> "); // new line
        ch = getchar();
        while (getchar() != '\n'); //Clearung buffer.
        putchar(ch);
    }

Not sure if ideal, but this worked:

    #include <stdio.h>
    int main() 
    {
       int i;
       int ch;
        for(i = 0; i < 10; i++)
        {
            printf("Enter a single character >> ");
            getchar();
            ch=getchar();
            putchar(ch);
         }

         return 0;
       }

I am a beginner . I tried this version of code and it gave the desired output.

#include <stdio.h>

int main()
{
    int i;
    int ch;
    for(i = 0; i < 10; i++)
    {
        printf("Enter a single character >> ");
        fflush(stdin);
        ch = getchar();
        putchar(ch);
        printf("\n");
    }

    return 0;
}

Although getchar() gets a single character, control isn’t returned to your program until the user presses Enter. The getchar() function actually instructs C to accept input into a buffer, which is a memory area reserved for input. The buffer isn’t released until the user presses Enter, and then the buffer’s contents are released a character at a time. This means two things. One, the user can press the Backspace key to correct bad character input, as long as he or she hasn’t pressed Enter. Two, the Enter keypress is left on the input buffer if you don’t get rid of it.to Get rid of the Enter keypress insert an extra getchar() that captures the Enter but doesn’t do anything with it.so you just need an extra getchar() after ch = getchar();like this

#include <stdio.h>
#include <stdlib.h>

int main()
{    int i;
    int ch;
    for(i = 0; i < 10; i++)
    {
        printf("Enter a single character >> ");
        ch = getchar();
        getchar();
        putchar(ch);
    }
    return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top