#include<stdio.h>
int main(void)
{
int c;
while((c=getchar())!=EOF)
{
if(c==8) // 8 is ASCII value of backspace
printf("\\b");
}
}
现在我想输入退格并希望getchar()函数将退格的ASCII返回到c(int变量)
注意 - 我不是在询问getch函数我知道getch命令能够读取退格 我只想知道getchar是否能够读取退格 如果是,怎么样?
怎么做请解释我 我是C编程的新手
答案 0 :(得分:2)
如果您的系统支持POSIX.1-2001中标准化的termios,那么您可以操作标准输入终端以不缓冲您的输入。请考虑以下示例:
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
/* SIGINT handler */
static volatile sig_atomic_t done = 0;
static void handle_done(int signum)
{
if (!done)
done = signum;
}
static int install_done(const int signum)
{
struct sigaction act;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = handle_done;
act.sa_flags = 0;
if (sigaction(signum, &act, NULL) == -1)
return errno;
return 0;
}
/* Reverting terminal back to original settings */
static struct termios terminal_config;
static void revert_terminal(void)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminal_config);
}
int main(void)
{
int c;
/* Set up INT (Ctrl+C), TERM, and HUP signal handlers. */
if (install_done(SIGINT) ||
install_done(SIGTERM) ||
install_done(SIGHUP)) {
fprintf(stderr, "Cannot install signal handlers: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
/* Make terminal input noncanonical; not line buffered. Also disable echo. */
if (isatty(STDIN_FILENO)) {
struct termios config;
if (tcgetattr(STDIN_FILENO, &terminal_config) == 0 &&
tcgetattr(STDIN_FILENO, &config) == 0) {
config.c_lflag &= ~(ICANON | ECHO);
config.c_cc[VMIN] = 1; /* Blocking input */
config.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO, TCSANOW, &config);
atexit(revert_terminal);
}
}
/* Set standard input unbuffered. */
setvbuf(stdin, NULL, _IONBF, 0);
printf("Press Ctrl+C to exit.\n");
fflush(stdout);
while (!done) {
c = fgetc(stdin);
if (c == EOF)
printf("Read EOF%s\n", ferror(stdin) ? " as an error occurred" : "");
else
printf("Read %d = 0x%02x\n", c, (unsigned int)c);
fflush(stdout);
}
return EXIT_SUCCESS;
}
#define
行告诉您的C库头文件为基于GNU的系统公开POSIX.1功能。
只要收到INT( Ctrl + C ),TERM或HUP信号,就会设置done
标志。 (如果断开与终端的连接,则会发送HUP信号,例如关闭终端窗口。)
terminal_config
结构将包含注册为退出函数的revert_terminal()
使用的原始终端设置,以将终端设置恢复为在程序启动时读取的原始设置。
如果标准输入是终端,则函数isatty(STDIN_FILENO)
返回1。如果是这样,我们获取当前终端设置,并将其修改为非规范模式,并询问每个读取块,直到至少读取一个字符。 (如果设置.c_cc[VMIN]=0
和.c_cc[VTIME]=0
,I / O函数往往会有点混乱,因此如果没有输入待处理,fgetc()
返回0.通常它看起来像EOF到stdio.h I / O函数。)
接下来,我们使用setvbuf()
告诉C库不要在内部缓冲标准输入。通常,C库使用输入缓冲区进行标准输入,以提高效率。但是,对我们来说,这意味着C库会缓冲输入的字符,我们的程序在输入时可能不会立即看到它们。
类似地,标准输出也被缓冲以提高效率。 C库应该将所有完整的行刷新到实际的标准输出,但是我们可以使用fflush(stdout)
调用来确保我们写入stdout的所有内容都被刷新到那时的实际标准输出。
在main()
中,我们有一个简单的循环,它读取按键,并以十进制和十六进制打印它们。
请注意,当输入信号时,例如INT信号,因为您输入了 Ctrl + C ,信号传递到我们的handle_done()
信号如果有一个挂起,处理程序会中断fgetc()
调用。这就是当您按 Ctrl + C 时看到Read EOF
的原因;如果之后检查ferror(stdin)
,您会看到它返回非零值(表示发生了错误)。在这种情况下,“错误”是EINTR
,“被信号打断”。
另请注意,当您按某些键(如光标或功能键)时,您会看到生成多个字符,通常以27和91开头(十进制; 0x1B 0x5B,十六进制; "\033["
如果表示为C字符串文字)。这些通常是但不总是ANSI转义序列。通常,它们是特定于终端的代码,可以使用terminfo数据库通过tigetstr()
,tigetnum()
和tigetflag()
获取。
更容易实现的方法是使用Curses库;大多数系统上的ncurses或Windows计算机上的PDCurses。它们不仅提供了更简单的界面,而且还以特定于终端的方式实现,以实现跨系统的最大兼容性。
使用Curses函数的C程序可以针对任何Curses库进行编译,因此可以在Linux,Mac和Windows机器上编译和运行相同的C源文件。但是,ncurses确实包含很多扩展,其他Curses库可能不会提供这些扩展,例如PDCurses。