4.3节 逆波兰计算器——程序理解

/*
	时间:2017/8/17
	地点:工程北629
	功能:逆波兰算法实现计算器
	思想:逆波兰算法 、全局变量,局部变量 、栈内存
	问题:特别注意:该程序对首先输入负数的情况,有待编写。

	理解:自己思考并调试程序。
*/

#include
#include

#define MAXOP 100    //全局变量MAXOP,作用范围全局。
#define NUMBER '0'

int getop(char []);	 //获取下一个运算符或数值

void push(double);	 //把f压入到值栈中
double pop(void);	 //弹出返回栈顶值

/*  主函数  */
int main(void)
{
	printf("请按照逆波兰运算,以空格分开:\n");
	int type;
	double op2;
	char s[MAXOP];	//定义局部变量, 作用范围main函数中。含100个元素的全0数组s 

	while((type = getop(s)) != EOF)  //main函数调用getop函数,向getop函数发送长度100的全0数组s
	{
		switch(type)
		{
		case NUMBER:
			push(atof(s));	//请参考atof函数,将字符串转换成数字,参考《The C Programming Language》4.3节
			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("error: zero divisor\n");
			break;
		case '\n':
			printf("\t运算结果是:%.8g\n", pop());
			break;
		default:
				printf("error: unknown command %s\n", s);
				break;
		}
	}
	return 0;
}

#include

int  getch(void);
void ungetch(int);

/*  获取下一个数值或者操作数  */
int getop(char s[])
{
	int i, c;

	while((s[0] = c = getch()) == ' ' || c == '\t')  //getop函数 纯调用getch函数,不发送任何实参。    算术> 关系> 逻辑> 赋值
		;
	s[1] = '\0';
	if(!isdigit(c) && c != '.')
		return c;
	i = 0;
	if(isdigit(c))
		while(isdigit(s[++i] = c = getch()))
			;
	if(c == '.')
		while(isdigit(s[++i] = c = getch()))
			;
	s[i] = '\0';
	if(c != EOF)
		ungetch(c);
	return NUMBER;
}

#define BUFSIZE 100   //定义缓冲区

char buf[BUFSIZE];    //  用于ungetch函数的缓冲区  
int bufp = 0;		  //  buf中给下一个空闲位置,输出缓冲的字符,bufp是全局变量,该变化的数值下一次要使用。

/*  取出一个字符(可能是压回的字符)  */
int getch(void)      
{
	return (bufp > 0) ? buf[--bufp] : getchar();  //getch函数调用getchar函数
}

/*  把字符压回到输入中*/
void ungetch(int c)  
{
	if (bufp >= BUFSIZE)
		printf("ungetch: too many characters\n");
	else
		buf[bufp++] = c;
}

#define MAXVAL 100  

int sp = 0;	  //定义全局变量,sp的值,下一次调用要使用。
double val[MAXVAL];  

/*  把f压入到值栈中  */
void push(double f)
{
	if(sp < MAXVAL)
		val[sp++] = f;
	else
		printf("error: stack full, can't push %g\n", f);
}

/*  弹出并返回栈顶的值  */
double pop(void)
{
	if (sp > 0)
		return val[--sp];
	else
	{
		printf("error: stack empty\n");
		return 0.0;
	}
}

/*
	在Vc++6.0中的输出结果是:
----------------------------
	请按照逆波兰运算,以空格分开:
	1 2 - 4 5 + *
			运算结果是:-9
	1 2 - 4 5 + /
			运算结果是:-0.11111111
	1.1 2.2 - 3.3 4.4 + *
			运算结果是:-8.47
	1.1 2.2 + 3.3 4.4 - *
			运算结果是:-3.63
	-1 2 +
	error: stack empty
	error: stack empty
			运算结果是:3
	-1 2 -
	error: stack empty
			运算结果是:-1
	-1 2 + 4 5 - *
	error: stack empty
			运算结果是:-3
	-1 2 - 4 5 + /
	error: stack empty
			运算结果是:-0.11111111
	^Z
	Press any key to continue
----------------------------
	总结:1、因为需要共享,所以需要定义全局变量。因为变量的值在内存中不断变化。
		     当下一次需要继续使用该变量时,不得不使用全局的变量,因为局部变量跳出函数后,系统将权限收回,不能再使用,
		     所以定义全局变量是必须的。
		  2、程序较长,可以从简单的逆波兰表达式  1 2 - \n  入手,将程序运行一遍,这样更有利于理解全局变量的意义。 
		  
		  3、对于 + - * /也可以不用空格分离。
		  
*/

你可能感兴趣的:(《C程序设计语言R&H》)