Putchar和Getchar在C中

时间:2013-10-14 19:26:20

标签: c getchar kernighan-and-ritchie putchar

我正在阅读K& R的The C Programming Language,并对putchar和getchar感到困惑。我制作了一个程序,你输入10个字符,程序将它们打印回屏幕。

#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;
}

我希望得到这样的输出:

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

......等等10次,但这是我得到的输出:(我在输入2个字符后停止了)

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

不确定为什么我的输入字符与固定字符串组合并被输出。

另外,我不太清楚为什么使用int来存储字符。

8 个答案:

答案 0 :(得分:5)

putchar(ch);

只打印单个字符,并且以下printf在同一行内继续。只需添加:

putchar('\n');

putchar(ch);之后,它将在执行printf之前显式启动新行。此外,您还应该从输入字符后的输入中取'\n'

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
}

答案 1 :(得分:4)

您没有打印新行。在putchar(ch);之后,您应该使用putchar('\n');来打印新行。

答案 2 :(得分:3)

用户终端可以在规范和非规范模式下运行。默认情况下,它以规范模式运行,这意味着标准输入可逐行(不是符号逐行)地用于程序。有问题的用户输入一些东西(让它是字母'a',十六进制的0x61)并按下输入(换行符中的新行字符'0x0A')。 Ascii表是here。因此,此操作为程序提供了两个符号。正如man getchar()中提到的那样,逐个符号地读取它。因此循环对一个字符迭代两次。要查看发生了什么,请使用以下程序(+循环计数器输出,+字符代码输出):

#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;
}

输出:

┌─(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

所以程序得到两个符号并打印出来。并且新的线符号不可见。所以在问题用户看到一个奇怪的额外线。 有关不同终端模式以及如何进行调整的详细说明,请参见here

使用终端选项时,stty实用程序也很有用(“icanon”告诉终端是否使用规范模式)。

关于在getchar()输出中将字符存储为int - 请参阅我的answer以获取类似主题。

答案 3 :(得分:1)

我们应该关注的术语是“流”

“流”就像桥一样,以顺序方式负责数据流。 (由程序库/头文件(例如stdio.h)管理程序内外的流畅流式传输)

回到您的问题:

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*/

注意/重要事项/注意事项,然后继续::直到流没有完全变空为止,您无法从控制台将新字符写入流中。 (这种情况仅暗示使用getchar和putchar,如下所示)

您的代码在这里:

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

通行证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

第二关: 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 >>

第三关:   与循环1相似,这次仅输入为'b'。

第四关:   与循环2相似

,依此类推,直到10遍为止。 (因此,您可以输入的最后一个字符是'e'。)

推断/结论:

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.

谢谢。 让我知道您的想法是否不同。

答案 4 :(得分:0)

在偶数个时间循环,getchar()没有从键盘输入,但它取自之前输入的命中,所以你也会注意到循环只执行了5次。因此,您必须清除缓冲区,即按下输入,以便可以在ch中输入新字符。

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

答案 5 :(得分:0)

不确定是否理想,但这有效:

    #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;
       }

答案 6 :(得分:0)

我是初学者。我尝试了这个版本的代码,它提供了所需的输出。

#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;
}

答案 7 :(得分:0)

尽管 getchar()获得单个字符,但是直到用户按下Enter键,控件才返回给程序。 getchar()函数实际上指示C将输入接受到缓冲区中,该缓冲区是为输入保留的存储区。直到用户按下Enter键,缓冲区才会释放,然后缓冲区的内容一次释放一个字符。这意味着两件事。第一,只要用户未按Enter键,就可以按Backspace键纠正错误的字符输入。第二,如果您不希望将Enter键保留在输入缓冲区上。要取消Enter键,请插入一个额外的 getchar()输入,但不执行任何操作。因此,在ch = getchar()之后,您只需要一个额外的 getchar();像这样

#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;
}