100 Days of Code-day18

K&R exercise 4-11

Modify getop so that it doesn’t need to use ungetch. Hint: use an internal static variable.
反思:
the point of illustration of this program is static variable,lastc.It get initialized once (only once because it’s static variable)and maintain its state in every innovation unless assign to lastc value.Every time the program want to certain if the number or string is complete,it’ll read one more character.So we can use lastc to store this character.
Furthermore, as the following program shows, there is no use to innovate getch in this program.We can use getchar function to replace it.Becaue when the program don’t need ungetch function, there are no characters pushed into buf character array.So the next free position in buf is 0 all the time.Justifying bufp will waste too much time.

#define bufsize 100
char buf[bufsize];//buffer for ungetch
int bufp = 0;//next position in buf
int getch(void)
{
	return bufp > 0 ? buf[--bufp] : getchar();
}
void ungetch(int ch)
{
	if (bufp >= bufsize)
		printf("too many characters in buf\n");
	else
		buf[bufp++] = ch;
}

Improve program:

//逆波兰计算器 reverse Polish calculator,simple "RPN"
#define number '0'  //在输入中找到一个数的标志
#define Name 'n'	//在输入中找到"名字"的标志
#define maxop 100	//操作数或运算符的最大长度

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

int main()
{
	int type, i, var=0;
	double op, op2, v;//操作数operand
	char s[maxop];
	double variable[26];

	for (i = 0; i < 26; i++)
		variable[i] = 0.0;
	while ((type=getop(s))!=EOF)
	{
		switch (type)
		{
			case number://char类型的数据可以自动转换为int类型的数据
				//当getop函数想要返回一个数值操作数时,并不能像返回运算符一样
				//直接将字符串s中的内容赋值给type,所以需要一个标志来表示返回数值操作数的情况
				//本程序选择'0'为这种情况的标志,随后将字符串s转化为浮点数
				push(atof(s));
				break;
			case '+':
				push(pop() + pop());
				break;
			case '-':
				//变量op2用处:
				//'+','*'运算满足交换律,所以操作数的弹出无先后顺序。
				//而'-''/'则相反,运算符的左右操作数应该加以区分
				op2 = pop();
				push(pop() - op2);
				break;
			case '*':
				push(pop() * pop());
				break;
			case '/':
				op2 = pop();
				if (op2 != 0.0)
					push(pop() / op2);
				else
					printf("error:zero divisor\n");
				break;
			case'%':
				op2 = pop();
				if (op2 != 0)
					push(fmod(pop(), op2));
				else
					printf("error: zero disvisor\n");
				break;
			case'c'://clear the stack
				ClearStack();
				break;
			case'p'://print top element
				op2 = pop();
				printf("\t%.8g\n", op2);
				push(op2);
				break;
			case'd'://duplicate top element of the stack
				op2 = pop();
				push(op2);
				push(op2);
				break;
			//case'e':
			//	push(exp(pop()));
			//	break;
			
			case Name:
				mathfunc(s);
				break;
			case's'://swap the top two characters
				op = pop();
				op2 = pop();
				push(op);
				push(op2);
				break;
			case '\n'://每次输入运算符和操作数后都会以换行符做结尾,所以'\n'的出现
				//表示一次运算的结束,此时就可以打印计算结果
				v = pop();
				printf("\t%.8g\n", v);
				break;
			case'='://RPN notation for assigning to variables
				pop();//先弹出变量原先的值
				if (var >= 'A' && var <= 'Z')
					variable[var - 'A'] = pop();//将需要更新的值弹出,并赋值到输入变量对应的索引处
				else
					printf("error: no variable\n");
				break;
			default:
				if (type >= 'A' && type <= 'Z')//A-Z作为数组变量的索引,同时也代表输入的变量
					push(variable[type - 'A']);//将变量对应位置的值压入到栈中,所压入的值是该变量执行赋值操作前的值
				else if (type == 'v')
					push(v);
				else
					printf("error:unknown command %s\n", s);
				break;
		}
		var = type;
	}
	return 0;
}

//mathfunc:check if string s is one of supported math functions for "math.h"
void mathfunc(char s[])
{
	double op2;
	if (strcmp(s, "sin") == 0)
		push(sin(pop()));
	else if (strcmp(s, "cos") == 0)
		push(cos(pop()));
	else if (strcmp(s, "exp") == 0)
		push(exp(pop()));
	else if (strcmp(s, "pow") == 0)
	{
		op2 = pop();
		pow(pop(), op2);
	}
	else
		printf("%s is wrong math function!!! Not supported!!!",s);
}

#define maxval 100
int strplace = 0;//栈中下一个空闲的位置(栈顶指针)
double val[maxval];//栈用顺序表来存放

void push(double f)
{
	if (strplace < maxval)
	{
		val[strplace++] = f;
	}
	else
		printf("error:stack has been full,can't push\n");
}

double pop(void)
{
	if (strplace > 0)
	{
		return val[--strplace];//example:1 2 +
		//'+'不需要进行pop操作,所以先进行自减操作,然后再返回
	}
	else
	{
		printf("error:stack empty,can't pop\n");
		return 0.0;
	}
}

void ClearStack(void)
{
	strplace = 0;
}



//getop函数用来获取下一个运算符或数值操作数
int getop(char s[])
{
	int c , i;
	static int lastch = 0;

	if (!lastch)
		c = getchar();
	else
	{
		c = lastch;
		lastch = 0;
	}		
	while ((s[0] = c) == ' ' || c == '\t')
		c = getchar();
	s[1] = '\0';
	i = 0;
	if (!isdigit(c) && c != '.' && c != '-' && !islower(c))//遵循从左到右的顺序进行判断
		return c;
	if (c == '-')
	{
		if (isdigit(c = getchar()) || c == '.')
			s[++i] = c;
		else 
		{//程序要确定读取数字的完整性,所以需要多读一个字符
			if (c != EOF)
				lastch = c;
			return '-';//返回输入的结尾
		}
	}
	if (islower(c))//如果c为小写字母
	{
		while (islower(s[++i] = c = getchar()))
			;
		s[i] = '\0';
		if (c != EOF)
			lastch = c;
		if (strlen(s) > 1)
			return Name;
		else
			return s[--i];//return c;是不正确的,因为此时c是程序为了确定字符串完整性所多读取的字符
						//而在其之前的那个字符才是执行相应操作的字符标志
	}
	
	if (isdigit(c))//收集整数部分
		while (isdigit(s[++i] = c = getchar()));
	if(c=='.')//收集小数部分
		while (isdigit(s[++i] = c = getchar()));
	s[i] = '\0';
	if (c != EOF)
		lastch = c;
	return number;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值