Hatena::Groupcprogramming

C Study Diary

2008-12-15

c4ex3-6calculator.cpp

19:44

On the previous calculator:

Add commands to print the top element of the stack without popping, to duplicate it, and to swap the top two elements. Add a command to clear the stack.

Add access to library functions like sin , exp , and pow . See <math.h> in Appendix B, Section 4.

Add commands for handling variables. (It's easy to provide twenty-six variables with single-letter names.) Add a variable for the most recently printed value.

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#define MAX 100
#define NUM '#'
#define VAR '@'
#define END '|'
#define UNKNOW '&'

#define ERROR -1
#define NORMAL 0
#define LAST 1

int sp=0, i=0, errflag=NORMAL;
double stack[MAX];
double number=0.0;
char s[MAX];
double v[26]={};
char varname = NULL;

void push(double n){
	
	if(sp==MAX) {
		printf("Error: exceed max stack space!\n");
		errflag = ERROR;
	}else{
		stack[sp++]=n;
	}
}

double pop(){
	
	if(sp>0) return stack[--sp];  /* --sp ! */
	else {
		printf("Error: stack is empty!\n");
		errflag = ERROR;
		return 0.0;
	}	
}

void showtop(){

	if(sp>0) {
		printf("top element is %f\n", stack[sp-1]);
	}	
	else printf("Error: no element in stack. \n");
}

void copytop(){
	
	double temp;
	temp=pop();
	push(temp);
	push(temp);
	
}

void swaptoptwo(){

	double temp1;
	double temp2;
	
	temp1=pop();
	temp2=pop();
	
	push(temp1);
	push(temp2);	
 
}

void clear(){

	sp=0;
}

double atof(char* s){
	
	double number=0.0, ratio=1.0, ten=10.0;
	int i=0, non_num=0, point=-1, sign=1, psign=1, e=0, exp=0, digit=0;

	while(s[i]!='\0'){
		switch(s[i]){
			case ' ': non_num++; break;
			case '.': point=i; break;
			case '-': if(e) psign=-1; else {sign=-1; non_num++;} break;
			case '+': if(e) psign=1; else {sign=1; non_num++;} break;
			case 'e': e=1; break;
			case 'E': e=1; break;
			default: if(e) exp=exp*10+(s[i]-'0'); else { number=number*ten+(s[i]-'0'); digit++; }
		}
		i++;
	}
	/* negtive exp sign or exp =0 => ratio=0.1 ; positive exp sign => ratio = 10.0  */
	if(psign<0 || exp==0) ratio = 1/ten;
	else ratio = ten;
	
	/* if point appears */
	if(point!=-1){
		for(i=0;i<abs(psign*exp-(digit-(point-non_num)));i++)
			number = number * ratio; 
	}
	/* no point */	
	else {
		for(i=0;i<exp;i++)
			number = number * ratio; 
	}

	return number*sign;
	
}

/* process input - Polish notation */
int getinput(){
	
	int c, nc, sign = 1, j, k=0, flag;
	char op[5], value[MAX];
	
	while((c=s[i++])!='\0'){	

		/* - or minus */
		if(c=='-') {
			nc=s[i];
			if(isdigit(nc) || nc=='.'){
				sign=-1;
			}
			else {
				return c;
			}	
		}
		/* var gets value */
		else if(c=='='){
			if(varname!=NULL) {
				
				j=0;
				while(!isdigit(c)&&c!='.'){
					if(c=='-'){
						value[j++]=c;
					}
					c=s[i++];
				}
				while(isdigit(c)||c=='.') {
					value[j++]=c;	
					c=s[i++];
				}		
				i--;				
				value[j]='\0';		
				v[varname-'a'] = atof(value);
				varname=NULL;
			}	
			else printf("error: no variable name before '='. \n");
		}
		/* library functions or var name */
		else if(isalpha(c)){
			/* save characters to op[] */
			j=0;
			while(isalpha(c)){
				op[j++] = c;
				c=s[i++];			
			}
			op[j]='\0';
			i--;
			/* if op is var name */
			if(strlen(op)==1) {
				varname=op[0];
			/* check if there is a '=' afterwards */
				flag=1;
				for(k=i;s[k]!='\0';k++){
					if(s[k]=='=') {
						flag = 0;	 
						break;
					}		
				}
			/* if there isn't a '=' afterwards,  var is using in formular, return VAR */
				if(flag) return VAR;				
			/* library functions */	
			}else if(strcmp(op,"cos")==0){
				return 'c';
			}
			else if(strcmp(op,"sin")==0){
				return 's';
			}
			else if(strcmp(op,"exp")==0){
				return 'e';
			}
			else if(strcmp(op,"pow")==0){
				return 'p';
			} else return UNKNOW;
		}		
		/* number in formular */
		else if(isdigit(c) || c=='.') {
			j=0;
			while(isdigit(c)||c=='.') {
				value[j++]=c;	
				c=s[i++];
			}			
			value[j]='\0';			
			i--;
			number = atof(value)*sign;
			
			return NUM;
		}	
		else if(c==' ' ||c=='\t') 
			;
		else return c;
	}
	return END;

}

void clearstate(){
	number=0.0;
	i=0;
	varname = NULL;
	errflag = NORMAL;
	clear();
}

int main(){
	
	int c;
	double result, t1, t2;
	
		printf("Input formular: (enter ! to quit )\n");
		gets(s);
		
		while(s[0]!='!'){
		/* operation  */
			while((c=getinput())!=END){
				switch(c){
					case '+': 
						t1=pop(); t2=pop(); push(t1+t2); break;
					case '-': 
						t1=pop(); t2=pop(); push(t2-t1); break;
					case '*': 
						t1=pop(); t2=pop(); push(t2*t1); break;
					case '/': 
						t1=pop(); if((t2=pop())!=0) push(t2/t1); else { printf("Error: 0 cannot be divided. \n"); errflag = ERROR; } break;
					case '%': 
						t1=pop(); if((t2=pop())!=0) push((int)t2%(int)t1); else { printf("Error: 0 cannot be divided. \n"); errflag = ERROR; } break;	
					case 'c': 
						t1=pop(); push(cos(t1)); break;
					case 's': 
						t1=pop(); push(sin(t1)); break;
					case 'e': 
						t1=pop(); push(exp(t1)); break;
					case 'p': 
						t1=pop(); t2=pop(); push(pow(t2,t1)); break;	
					case '<': 
						printf("last result = %g\n",result); errflag =LAST; break;	
					case VAR: 
						if(v[varname-'a']!=NULL) { push(v[varname-'a']); } else printf("Error: no variable value found.\n"); break;
					case NUM:  
						push(number); number=0; break;
					default: 
						printf("Error: unkown command! \n"); 	errflag = ERROR;					
				}		
			}
			if(errflag == NORMAL) {
				printf("%s = ",s);
				result = pop();
				printf("%g\n",result);
			}
			if(errflag == ERROR) printf("Not calculate. Input Error.\n");
			/* clear state for new inputs */
			clearstate();				
			printf("\nInput formular: (enter ! to quit )\n");
			gets(s);
		
		}
}	

Run:

$ ./c4ex3-6calculator.exe
Input formular: (enter ! to quit )
90 cos
90 cos = -0.448074

Input formular: (enter ! to quit )
40 cose
Error: unkown command!
Not calculate. Input Error.

Input formular: (enter ! to quit )
a= -.234 b=2.14 a b + 10 *
a= -.234 b=2.14 a b + 10 * = 19.06

Input formular: (enter ! to quit )
!

ゲスト



トラックバック - http://cprogramming.g.hatena.ne.jp/annancy/20081215