getch和ungetch的使用

getch与ungetch函数详解及应用
本文介绍了getch()和ungetch()函数的使用,getch()允许用户无需回车即可输入,ungetch()则能将字符退回键盘缓冲区。在无法预知输入长度的情况下,它们能辅助读取并处理输入。文中还提到了逆波兰计算器的一个应用场景,展示getch()和ungetch()如何在处理不需要的输入字符时发挥作用。

函数说明

  1. getch()
    这个函数可以让用户按下任意键而不需要回车就可以接受到用户的输入。可以用来作为“press any key to continue”的实现。

  2. ungetch()
    把一个字符退回到键盘缓冲区中

  3. 工作原理
    ungetch( )函数是把要压回的字符放到一个共享缓冲区(字符数组)中,
    当该缓冲区不空时,getch函数就从缓冲区中读取字符;当缓冲区为空时,getch函数调用getchar函数直接从输入中读取字符。
    注意:这里还要增加一个下标变量来标记缓冲区中当前字符的位置。

由于缓冲区与下标变量是提供getch与ungetch函数共享的,并且在两次调用之前必须保持值不变,
因此他们必须是这两个函数的外部变量。
可以按照下列方式编写getch和ungetch函数及其共享变量:

#include<ctype.h>
#define BUFSIZE 100
 
char buf[BUFSIZE]; 	/* 用于ungetch函数的缓冲区 */
int bufp = 0;  		/* buf中下一个空闲位置 */
 
int getch(void)		/* 取一个字符(可能是压回的字符)*/
{
	return (bufp > 0) ? buf[--bufp]:getchar();
}
 
void ungetch(int c)	/* 把字符c压回到输入中*/
{
	if (bufp >= BUFSIZE)
		printf("ungetch: too many charachters\n");
	else
		buf[bufp++] = c;
} 

应用场景

当程序不能确定读取的输入是否足够,就得超前读取。但最后读取的可能是我们不需要的字符,这就需要“反读”,我很不理解这个说法,简单点就是需要将这个不需要的字符再给它写回键盘缓冲区。如下面的获取数字函数中。

/* getop函数:获取下一个运算符或数字操作数 */
int getop(char s[])  //这个s[]就是要存放的操作数
{
	int i,c;
	
	while((s[0] = c = getch() == ' '|| c == '\t')) // 跳过空格或制表符 
		;
	s[1] = '\0';
	if(!isdigit(c) && c != '.')  
		return c;    /* 进一步判断,不是数,c是上面赋值的,C是运算符或‘\n’,返回运算符 */
	i = 0;
	if(isdigit(c))      /* 收集整数部分 */
		while((isdigit(s[i++] = c = getch()))) //继续读取下一个从键盘输入的字符,
		//这时有可能输入的是123空格,那么最后一个c就是我们不需要的,但是已经给了s
			;
	if(c == '.')        /* 收集小数部分 */
		while((isdigit(s[i++] = c = getch()))) //同整数部分
			;
	s[i] = '\0'; //这里其实已经将那个我们不需要的字符从s的末尾给变成了结束符 “\0”
	
	if(c != EOF)
		ungetch(c);   /* 反读不需要的字符 ,即写回缓冲区,个人理解对于这个函数觉得没必要*/
	return NUMBER;  //主程序里定义好的符号常量
}

附加——逆波兰计算器

#include<stdio.h>
#include<stdlib.h>  //为了使用atof()函数

#define MAX  100 //操作数或运算符最大长度
#define NUMBER '0' //标识找到一个数

int getop(char []);
void push(double);
double pop(void)

//逆波兰计算器
main()
{
  int type;
  double op2;
  char s[MAX];
 while((type = getop(s)) != EOF){
 
     switch(type){
      case NUMBER:
          push(atof(s));
          break;
      case '+':
          push(pop()+pop());  //加乘操作数次序无所谓
          break;
      case '*':
          push(pop()*pop());
          break;
      case '-':      //减除操作数注意次序
          op2 = pop();
          push(pop()-op2);
          break;
      case '/':
          op2 = pop();
          if(op2 != 0.0)
            push(pop()/op2);
          else
            printf("divisor can't be zero");
          break;
      case '\n':
        printf("the result is:%f" pop());
        break;
   }
  }
  return 0;
}
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值