getch()和getchar()有什么区别?

24

getchgetchar 函数之间的确切区别是什么?

4个回答

37

getchar()是一个标准函数,用于从stdin中获取一个字符。

getch()是非标准的。它从键盘获取一个字符(可能与stdin不同),并且不回显该字符。


先生,您能指向资源或举个例子来解释一下“可能与标准输入不同”的语句吗?谢谢! - Rishi Shukla
3
这意味着stdin可以是键盘,也可以是另一个输入流。 - Roy Dictus

10
标准C函数是getchar(),声明在<stdio.h>中。自从人类历史的黎明时期以来,它基本上一直存在。它从标准输入(stdin)中读取一个字符,通常是用户的键盘,除非它已被重定向(例如通过shell输入重定向字符<或管道)。 getch()getche()是旧的MS-DOS函数,声明在<conio.h>中,在Windows系统上仍然很流行。它们不是标准C函数;它们并不存在于所有系统中。getch立即从键盘读取一个按键,而不等待用户按下回车键,并且不回显按键。getche也是如此,只是它回显按键。据我所知,getchgetche总是从键盘读取;它们不受输入重定向的影响。
问题自然而然地出现,如果getchar是标准函数,如何使用它读取一个字符而不需要等待回车键或者不回显?对于这些问题的答案至少有一点复杂。(事实上,它们足够复杂,以至于我怀疑它们解释了getchgetche持久的流行,因为它们非常容易使用。)
答案是getchar没有控制回显和输入缓冲等细节问题的能力。就C语言而言,这些都是更低级别、依赖于系统的问题。
但是理解getchar所假设的基本输入模型是有用的。令人困惑的是,通常有两个不同的缓冲层次。
  1. 当用户在键盘上输入按键时,它们被操作系统的 终端驱动程序 读取。通常,在默认模式下,终端驱动程序会立即回显按键(以便用户可以看到自己正在输入什么)。通常,在默认模式下,终端驱动程序还支持一定量的行编辑——例如,用户可以按 Delete 或 Backspace 键删除不小心输入的字符。为了支持行编辑,终端驱动程序通常在一个 输入缓冲区 中收集字符。只有当用户按下 Return 键时,该缓冲区的内容才会对调用程序可用。(仅当标准输入实际上是键盘或其他串行设备时,才存在此级别的缓冲。如果将标准输入重定向到文件或管道,则终端驱动程序无效,并且此级别的缓冲不适用。)
  2. stdio 包从操作系统中读取字符并将它们存入自己的输入缓冲区。getchar 只需从该缓冲区获取下一个字符。当缓冲区为空时,stdio 包尝试通过读取更多字符来重新填充它。
因此,如果我们追溯从程序第一次调用getchar开始发生的事情:stdio发现其输入缓冲区为空,因此它试图从操作系统读取一些字符,但是目前没有可用的字符,因此read调用被阻塞。同时,用户可能正在键入一些字符,这些字符在终端驱动程序的输入缓冲区中累积,但用户尚未按下Return键。最后,用户按下Return键,被阻塞的read调用返回,将整行字符返回给stdio,后者使用它们填充其输入缓冲区,然后将其返回给最初调用getchar的地方,该调用一直耐心等待。 (然后,如果程序第二次或第三次调用getchar,则可能在stdio的输入缓冲区中有更多字符 - 用户键入的下一行字符 - 可供getchar立即返回。有关此内容的更多信息,请参见这些C course notes第6.2节。)
但是,正如你所看到的,getchar和stdio包无法控制回显或输入行编辑等细节,因为这些在步骤1中早在终端驱动程序的较低级别上处理。

因此,在类Unix操作系统下,如果您想读取字符而不等待Return键,或者控制字符是否回显,可以通过调整终端驱动程序的行为来实现。细节有所不同,但有一种方法可以打开和关闭回显,并且有一种(实际上有几种)方法可以打开和关闭输入行编辑。 (至少对于其中一些细节,请参见this SO question,或旧版C FAQ list中的question 19.1。)

当关闭输入行编辑时,操作系统可以立即返回字符(无需等待回车键),因为在这种情况下,它不必担心用户可能会输入错误的按键,需要使用删除或退格键“撤消”。但同样地,当程序关闭终端驱动程序中的输入行编辑时,如果要让用户纠正错误,则必须实现自己的编辑,因为它将看到用户的错误字符和删除或退格键的字符代码。

有什么指导可以调整终端驱动程序的行为吗? - This isn't my real name
@这不是我的真名 所有血腥的细节:不。指针:好建议;已添加。 - Steve Summit

1
  • getchar是标准C函数,位于stdio.h中。它从标准输入流(stdin,在大多数系统上是控制台输入)中读取一个字符。由于需要用户输入字符并按下回车键,因此它是一个阻塞调用。它将用户的输入回显到屏幕上。

  • getc(stdin)getchar完全等效,除了它还可以用于其他输入流。

  • getch是非标准的,通常在旧的废弃的MS DOS头文件conio.h中找到。它的工作方式与getchar相同,只是在第一次按键后不会阻塞,允许程序在用户按下回车键之前继续执行。它不会将输入回显到屏幕上。

  • getchegetch相同,也是非标准的,但它会将输入回显到屏幕上。


我相信 getch 会阻塞直到按下一个键,它只是不会在行末等待按下回车键。 - Steve Summit
@SteveSummit 啊,是的,我把它和另一个古老的函数 kbhit 搞混了。已经修复了。 - Lundin

0

getch() 只获取输入,但不会在屏幕上显示输出,即使我们按下回车键。

getchar() 获取输入并在我们按下回车键时将其显示在屏幕上。


2
getchar() 返回字符但不显示它,这由程序员决定。如果输入未被处理,getchar() 可以在按下回车键之前从 stdin 读取。 - Ryan Haining

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接