主题:有优先级的计算器(供大家参考)
/*
last modification time:
3.25.2004
ver 2.0
*/
#include "conio.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define SIZE 100
#define ARRAYSIZE 10
int checkexp(char*);
int checkparen(char* cp1 );
char* findpunc(char* cp1 );
int checkpunc(char* cp1 );
double asc2num(char* cp1, char* cp2);
double seperatewords( char* expression );
char* finddot(char* cp1, char* cp2);
char* findmatch(char* cp1 );
double calculate(double expcp[ARRAYSIZE], char puncs[ARRAYSIZE], char punc );
main(){
char expression[SIZE+1];
double results=0;
window(1,1,80,25 );
textbackground(BLUE);
textcolor(WHITE);
clrscr();
window(1,1,80,5);
textbackground(WHITE);
textcolor(BLACK);
clrscr();
gotoxy(1,1);
cprintf("this programme can solve an expression including ( ) + - * / ^ ;\r\n" );
cprintf("if you wana use minus, use(0-xxx) or (.-xxx) to take place of it;\r\n" );
cprintf("please enter your expressions; no space is expected;\r\n" );
cprintf("key in 'q' to quit the programme;" );
window(1,7,80,8);
textbackground(BLUE);
textcolor(WHITE);
while(1){
while(bioskey(1)==0);
clrscr();
gotoxy(22,7 );
gets(expression );
/*check if quit;*/
if( *expression=='q' ){
break;
}
/*check if expression is legal;*/
if( !checkexp(expression) ){
continue;
}
/*recursion*/
results=seperatewords(expression);
gotoxy(20,8);
cprintf(" the result is: %lf\r ",results);
gotoxy(22,5);
} /*end while*/
}
/*codes below used to seperate words and use recursion to
solve each expression in "(" and ")" ;*/
double seperatewords(char* expression ){
double expcp[ARRAYSIZE];
char puncs[ARRAYSIZE]="";
char* cp1=expression;
char* cp2=expression;
int i=0;
double* results=NULL;
while( i<ARRAYSIZE ){
cp2=findpunc(cp1);
if(*cp2=='(' ){
expcp[i]=seperatewords(cp2+1 );
cp2=findmatch(cp2)+1;
}else if(*cp2==')' ){
expcp[i]=asc2num(cp1,cp2);
puncs[i]='\0';
results=&expcp[i];
break;
}else{
expcp[i]=asc2num(cp1,cp2);
}
if(*cp2!='\0'){
if(*cp2==')' ){
results=&expcp[i];
break;
}
/*store punctuations;*/
puncs[i]=*cp2++;
i++;
cp1=cp2;
}else{
/*end of expression;*/
puncs[i]='\0';
results=&expcp[i];
break;
}
}
if (i>=ARRAYSIZE ) {
cprintf("operands are too many...\nonly calculate the front %d operands\n", ARRAYSIZE);
puncs[i-1]='\0';
}
calculate(expcp, puncs, '^' );
/* '*' and '/' have the same PRI
* so they are associative, so it doesn't matter which is calculated first;
* '+' and '-' is the same;
*/
calculate(expcp, puncs, '/' );
calculate(expcp, puncs, '*' );
calculate(expcp, puncs, '+' );
calculate(expcp, puncs, '-' );
return *results;
}
char* findpunc(char* cp1){
while( (*cp1>='0'&&*cp1<='9') || *cp1=='.' ){
cp1++;
}
return cp1;
}
char* findmatch(char* cp1 ){
int i=0;
while(1 ){
if(*cp1=='(' ) i++;
else if(*cp1==')' ){
i--;
if(i==0) break;
}
cp1++;
}
return cp1;
}
/*codes below used to convert nums;*/
double asc2num(char* cp1, char* cp2){
double num=0;
double power=10,powernum=1;
char* cptemp=NULL;
char* cprem=NULL;
/*because cp2 points to a punc , -- to point to a number;*/
cprem=cptemp=finddot( cp1, cp2 );
/*if exist,digitals in front of dot;*/
if(cprem>cp1){
cptemp--;
for(;cp1<=cptemp;cptemp--){
num+=(*cptemp-'0')*powernum;
powernum*=power;
}
}
/*if exist,digitals behind the dot;*/
if(cprem<cp2){
cptemp=cprem;
power=.1;
powernum=.1;
cptemp++;
for(;cptemp<cp2;cptemp++){
num+=(*cptemp-'0')*powernum;
powernum*=power;
}
}
return num;
}
char* finddot(char* cp1, char* cp2){
while( *cp1!='.' && cp1<cp2 ){
cp1++;
}
return cp1;
}
/*punc is the punc you wana to calcute with;*/
double calculate(double expcp[ARRAYSIZE], char puncs[ARRAYSIZE], char punc ){
/*compute multiplying and dividing;*/
double* p_operandl=NULL;
double* p_operandr=NULL;
double numtemp=0;
int i=0;
int j=0;
char* cp1=puncs;
char* cp2;
while(*cp1!='\0'){
i=j;
p_operandl=&expcp[i];
p_operandr=&expcp[i];
cp2=cp1+1;
if(*cp1!='x'){
p_operandr=&expcp[++i];
while(*cp2=='x'){
cp2++;
i++;
p_operandr=&expcp[i];
}
if(*cp1==punc){
if (punc=='^' ) {
numtemp=pow(*p_operandl, *p_operandr );
}else if(punc=='/' ){
if(*p_operandr==0){
cprintf("sign divider's right operand must not be 0!\n");
numtemp=0;
break;
}
numtemp= *p_operandl / *p_operandr;
}else if (punc=='*' ) {
numtemp= *p_operandl * *p_operandr;
}else if (punc=='+' ) {
numtemp= *p_operandl + *p_operandr;
}else if (punc=='-' ) {
numtemp= *p_operandl - *p_operandr;
}
*cp1='x';
*p_operandr=numtemp;
}
}
cp1++;
j++;
}/*end while*/
return numtemp;
}
/*codes below used to check exps;*/
int checkexp(char* expression){
/*check if expression is legal;*/
char* cp1=expression;
/*first character must be one of the below;*/
if( (*cp1<'0'||*cp1>'9')&&*cp1!='.'&&*cp1!='(' ){
cprintf("the first figer must be digital!\n");
return 0;
}
if(!checkparen(expression) ){
cprintf("wrong expression.please check parenthesis.\n" );
return 0;
}
for(; *cp1!='\0'; cp1++ ){
if( (*cp1<'0'||*cp1>'9')&&*cp1!='.' ){
if( *cp1!='+' && *cp1!='-' && *cp1!='/' && *cp1!='*' &&
*cp1!='(' && *cp1!=')' && *cp1!='^' ){
cprintf( "error figers...\n" );
return 0;
}
if( !checkpunc(cp1) ){
cprintf( "there must be digitals on both side of the punctuation\n" );
return 0;
}
}
}
return 1;
}
/*check punctuations, including + - * / ;*/
int checkpunc(char* cp1){
/*check if there is digital at both side of punctuations;*/
if(*cp1!='(' && *cp1!=')' ){
if( (*(cp1-1)<'0'||*(cp1-1)>'9')&&*(cp1-1)!='.'&&*(cp1-1)!='('&&*(cp1-1)!=')' ||
(*(cp1+1)<'0'||*(cp1+1)>'9')&&*(cp1+1)!='.'&&*(cp1+1)!='('&&*(cp1+1)!=')' ){
return 0;
}
}
return 1;
}
/*check parentheses. those are '(' and ')' ;*/
int checkparen(char* cp1 ){
int i=0;
char* cp2=cp1;
/*make sure '(' and ')' matches;and there's no ')' before '(' ;*/
for(;*cp1!='\0';cp1++ ){
if(*cp1=='(' ){
i++;
}
else if(*cp1==')' ){
i--;
}
if(i<0){
return 0;
}
}
if(i!=0) return 0;
for(cp1=cp2;*cp1!='\0';cp1++ ){
if(*cp1=='(' ){
if( (*(cp1+1)<'0'||*(cp1+1)>'9')&&*(cp1+1)!='.'&&*(cp1+1)!='(' ) return 0;
if(cp1==cp2 ) continue;
if(*(cp1-1)!='+' && *(cp1-1)!='-' && *(cp1-1)!='^' &&
*(cp1-1)!='*' && *(cp1-1)!='/'&&*(cp1-1)!='.'&&*(cp1-1)!='(' ) return 0;
}
else if(*cp1==')' ){
if( (*(cp1-1)<'0'||*(cp1-1)>'9')&&*(cp1-1)!='.'&&*(cp1-1)!=')' ) return 0;
if(*(cp1+1)=='\0' ) continue;
if(*(cp1+1)!='+' && *(cp1+1)!='-' && *(cp1+1)!='^' &&
*(cp1+1)!='*' && *(cp1+1)!='/'&&*(cp1+1)!=')' ) return 0;
}
}
return 1;
}
last modification time:
3.25.2004
ver 2.0
*/
#include "conio.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define SIZE 100
#define ARRAYSIZE 10
int checkexp(char*);
int checkparen(char* cp1 );
char* findpunc(char* cp1 );
int checkpunc(char* cp1 );
double asc2num(char* cp1, char* cp2);
double seperatewords( char* expression );
char* finddot(char* cp1, char* cp2);
char* findmatch(char* cp1 );
double calculate(double expcp[ARRAYSIZE], char puncs[ARRAYSIZE], char punc );
main(){
char expression[SIZE+1];
double results=0;
window(1,1,80,25 );
textbackground(BLUE);
textcolor(WHITE);
clrscr();
window(1,1,80,5);
textbackground(WHITE);
textcolor(BLACK);
clrscr();
gotoxy(1,1);
cprintf("this programme can solve an expression including ( ) + - * / ^ ;\r\n" );
cprintf("if you wana use minus, use(0-xxx) or (.-xxx) to take place of it;\r\n" );
cprintf("please enter your expressions; no space is expected;\r\n" );
cprintf("key in 'q' to quit the programme;" );
window(1,7,80,8);
textbackground(BLUE);
textcolor(WHITE);
while(1){
while(bioskey(1)==0);
clrscr();
gotoxy(22,7 );
gets(expression );
/*check if quit;*/
if( *expression=='q' ){
break;
}
/*check if expression is legal;*/
if( !checkexp(expression) ){
continue;
}
/*recursion*/
results=seperatewords(expression);
gotoxy(20,8);
cprintf(" the result is: %lf\r ",results);
gotoxy(22,5);
} /*end while*/
}
/*codes below used to seperate words and use recursion to
solve each expression in "(" and ")" ;*/
double seperatewords(char* expression ){
double expcp[ARRAYSIZE];
char puncs[ARRAYSIZE]="";
char* cp1=expression;
char* cp2=expression;
int i=0;
double* results=NULL;
while( i<ARRAYSIZE ){
cp2=findpunc(cp1);
if(*cp2=='(' ){
expcp[i]=seperatewords(cp2+1 );
cp2=findmatch(cp2)+1;
}else if(*cp2==')' ){
expcp[i]=asc2num(cp1,cp2);
puncs[i]='\0';
results=&expcp[i];
break;
}else{
expcp[i]=asc2num(cp1,cp2);
}
if(*cp2!='\0'){
if(*cp2==')' ){
results=&expcp[i];
break;
}
/*store punctuations;*/
puncs[i]=*cp2++;
i++;
cp1=cp2;
}else{
/*end of expression;*/
puncs[i]='\0';
results=&expcp[i];
break;
}
}
if (i>=ARRAYSIZE ) {
cprintf("operands are too many...\nonly calculate the front %d operands\n", ARRAYSIZE);
puncs[i-1]='\0';
}
calculate(expcp, puncs, '^' );
/* '*' and '/' have the same PRI
* so they are associative, so it doesn't matter which is calculated first;
* '+' and '-' is the same;
*/
calculate(expcp, puncs, '/' );
calculate(expcp, puncs, '*' );
calculate(expcp, puncs, '+' );
calculate(expcp, puncs, '-' );
return *results;
}
char* findpunc(char* cp1){
while( (*cp1>='0'&&*cp1<='9') || *cp1=='.' ){
cp1++;
}
return cp1;
}
char* findmatch(char* cp1 ){
int i=0;
while(1 ){
if(*cp1=='(' ) i++;
else if(*cp1==')' ){
i--;
if(i==0) break;
}
cp1++;
}
return cp1;
}
/*codes below used to convert nums;*/
double asc2num(char* cp1, char* cp2){
double num=0;
double power=10,powernum=1;
char* cptemp=NULL;
char* cprem=NULL;
/*because cp2 points to a punc , -- to point to a number;*/
cprem=cptemp=finddot( cp1, cp2 );
/*if exist,digitals in front of dot;*/
if(cprem>cp1){
cptemp--;
for(;cp1<=cptemp;cptemp--){
num+=(*cptemp-'0')*powernum;
powernum*=power;
}
}
/*if exist,digitals behind the dot;*/
if(cprem<cp2){
cptemp=cprem;
power=.1;
powernum=.1;
cptemp++;
for(;cptemp<cp2;cptemp++){
num+=(*cptemp-'0')*powernum;
powernum*=power;
}
}
return num;
}
char* finddot(char* cp1, char* cp2){
while( *cp1!='.' && cp1<cp2 ){
cp1++;
}
return cp1;
}
/*punc is the punc you wana to calcute with;*/
double calculate(double expcp[ARRAYSIZE], char puncs[ARRAYSIZE], char punc ){
/*compute multiplying and dividing;*/
double* p_operandl=NULL;
double* p_operandr=NULL;
double numtemp=0;
int i=0;
int j=0;
char* cp1=puncs;
char* cp2;
while(*cp1!='\0'){
i=j;
p_operandl=&expcp[i];
p_operandr=&expcp[i];
cp2=cp1+1;
if(*cp1!='x'){
p_operandr=&expcp[++i];
while(*cp2=='x'){
cp2++;
i++;
p_operandr=&expcp[i];
}
if(*cp1==punc){
if (punc=='^' ) {
numtemp=pow(*p_operandl, *p_operandr );
}else if(punc=='/' ){
if(*p_operandr==0){
cprintf("sign divider's right operand must not be 0!\n");
numtemp=0;
break;
}
numtemp= *p_operandl / *p_operandr;
}else if (punc=='*' ) {
numtemp= *p_operandl * *p_operandr;
}else if (punc=='+' ) {
numtemp= *p_operandl + *p_operandr;
}else if (punc=='-' ) {
numtemp= *p_operandl - *p_operandr;
}
*cp1='x';
*p_operandr=numtemp;
}
}
cp1++;
j++;
}/*end while*/
return numtemp;
}
/*codes below used to check exps;*/
int checkexp(char* expression){
/*check if expression is legal;*/
char* cp1=expression;
/*first character must be one of the below;*/
if( (*cp1<'0'||*cp1>'9')&&*cp1!='.'&&*cp1!='(' ){
cprintf("the first figer must be digital!\n");
return 0;
}
if(!checkparen(expression) ){
cprintf("wrong expression.please check parenthesis.\n" );
return 0;
}
for(; *cp1!='\0'; cp1++ ){
if( (*cp1<'0'||*cp1>'9')&&*cp1!='.' ){
if( *cp1!='+' && *cp1!='-' && *cp1!='/' && *cp1!='*' &&
*cp1!='(' && *cp1!=')' && *cp1!='^' ){
cprintf( "error figers...\n" );
return 0;
}
if( !checkpunc(cp1) ){
cprintf( "there must be digitals on both side of the punctuation\n" );
return 0;
}
}
}
return 1;
}
/*check punctuations, including + - * / ;*/
int checkpunc(char* cp1){
/*check if there is digital at both side of punctuations;*/
if(*cp1!='(' && *cp1!=')' ){
if( (*(cp1-1)<'0'||*(cp1-1)>'9')&&*(cp1-1)!='.'&&*(cp1-1)!='('&&*(cp1-1)!=')' ||
(*(cp1+1)<'0'||*(cp1+1)>'9')&&*(cp1+1)!='.'&&*(cp1+1)!='('&&*(cp1+1)!=')' ){
return 0;
}
}
return 1;
}
/*check parentheses. those are '(' and ')' ;*/
int checkparen(char* cp1 ){
int i=0;
char* cp2=cp1;
/*make sure '(' and ')' matches;and there's no ')' before '(' ;*/
for(;*cp1!='\0';cp1++ ){
if(*cp1=='(' ){
i++;
}
else if(*cp1==')' ){
i--;
}
if(i<0){
return 0;
}
}
if(i!=0) return 0;
for(cp1=cp2;*cp1!='\0';cp1++ ){
if(*cp1=='(' ){
if( (*(cp1+1)<'0'||*(cp1+1)>'9')&&*(cp1+1)!='.'&&*(cp1+1)!='(' ) return 0;
if(cp1==cp2 ) continue;
if(*(cp1-1)!='+' && *(cp1-1)!='-' && *(cp1-1)!='^' &&
*(cp1-1)!='*' && *(cp1-1)!='/'&&*(cp1-1)!='.'&&*(cp1-1)!='(' ) return 0;
}
else if(*cp1==')' ){
if( (*(cp1-1)<'0'||*(cp1-1)>'9')&&*(cp1-1)!='.'&&*(cp1-1)!=')' ) return 0;
if(*(cp1+1)=='\0' ) continue;
if(*(cp1+1)!='+' && *(cp1+1)!='-' && *(cp1+1)!='^' &&
*(cp1+1)!='*' && *(cp1+1)!='/'&&*(cp1+1)!=')' ) return 0;
}
}
return 1;
}