栈的一些应用
1.数制转换
2.括号匹配
3.表达式求值
#include <stdio.h> #include <malloc.h> #include <string.h> #include <stdlib.h> #include <windows.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 char JJ[]={"0123456789ABCDEF"}; typedef struct tagWTNumber { int intbits; /* 整数数位*/ int floatbits; /* 小数有效数位*/ char infinite; /* 无穷大*/ char sign; /* 符号*/ char intpart[1000]; /* 整数部分*/ char floatpart[1000]; /* 小数部分*/ } WTNumber; typedef struct node { struct node *next; char c; double k; char str[100]; }stack; int IsEmpty(stack *s); void Creatstack(stack **s); void PushChar(stack **s,char c); char PopChar(stack **s); char GetTop(stack *s); void Creatstack(stack **s); void Push(stack **s,char *str); char * Pop(stack **s); char * Opera(char x, char *src1, char *src2); int Precede(char src1,char src2); void DisplayMenu(); void Convey(); void Calculate(); void MatchingCheck(); /* 算术函数指针类型.*/ typedef void (*PFNCALC)(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes); /* 初始化WTNumber为0.*/ void InitWTNumberToZero(WTNumber *pNum); /* 判断需要多少个字符空间存储WTNumber转换的字符串.*/ int CharArrLenByWTNumber(const WTNumber* pNum); /* 从字符串转换到WTNumber.*/ void CharArrToWTNumber(const char *arr,WTNumber *pNum); /* 从WTNumber转换到字符串.*/ void WTNumberToCharArr(char *szBuf,const WTNumber *pNum); /* 调节数位,删除最高整数位是0的和最低小数位是0的数位.*/ void AdjustBits(WTNumber *pNum); /* 移动小数点,deta=0不移动,deta<0往左移动,deta>0往右移动.*/ void MoveFloatPoint(WTNumber *pNum,int deta); /* 使无穷大 */ void MakeInfinite(WTNumber *pNum); /* 根据算术函数返回结果 */ char *Result(const char *val1,const char *val2,PFNCALC pfnCalc); /* 比较2个数大小 */ int WTCompare(const WTNumber* pn1,const WTNumber* pn2); /* 判断是否为0 */ int IsZero(const WTNumber *pNum); /* 加法*/ void WTAdd(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes); /* 乘法*/ void WTMultiply(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes); /* 减法*/ void WTSubtract(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes); /* 除法*/ void WTDivide(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes); ///*///////////////////////////////////////////////////////////////////// ///*///////////////////////////////////////////////////////////////////// ///*///////////////////////////////////////////////////////////////////// int main() { int choice; while(1) { DisplayMenu(); scanf("%d",&choice); switch(choice) { case 1: Convey(); break; case 2: MatchingCheck(); break; case 3: Calculate(); break; case 4: exit (ERROR); break; default: break; } } return 0; } ///*///////////////////////////////////////////////////////////////////// ///*///////////////////////////////////////////////////////////////////// ///*///////////////////////////////////////////////////////////////////// int IsEmpty(stack *s) { return s->next == NULL; } void Creatstack(stack **s) { *s = (stack *)malloc(sizeof(stack)); if(*s == NULL) { printf("mermory error\n"); exit (0); } (*s)->next = NULL; } void Push(stack **s,char *str) { stack *temp; temp = (stack *)malloc(sizeof(stack)); if(temp == NULL) { printf("mermory error\n"); exit (0); } strcpy(temp->str,str); temp->next = (*s)->next; (*s)->next = temp; } void PushChar(stack **s,char c) { stack *temp; temp = (stack *)malloc(sizeof(stack)); if(temp == NULL) { printf("mermory error\n"); exit (0); } temp->c = c; temp->next = (*s)->next; (*s)->next = temp; } char PopChar(stack **s) { stack *temp; char x; temp = (*s)->next; x = temp->c; (*s)->next = (*s)->next->next; free(temp); return x; } char * Pop(stack **s) { stack *temp; char *str; temp = (stack *)malloc(sizeof(stack)); temp = (*s)->next; str = (char *)malloc((strlen(temp->str) + 1)*sizeof(char) ); strcpy(str,temp->str); (*s)->next = (*s)->next->next; free(temp); return str; } char GetTop(stack *s) { if(s->next == NULL) { printf("stack empty\n"); exit (0); } else { return s->next->c; } } void DisplayMenu() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE); printf("|-------------------------------|\n"); printf("|\t1.数制转换 \t\t|\n"); printf("|\t2.括弧匹配\t\t|\n"); printf("|\t3.表达式求值\t\t|\n"); printf("|\t4.退出\t\t\t|\n"); printf("|-------------------------------|\n"); } ///*///////////////////////////////////////////////////////////////////// ///*///////////////////////////////////////////////////////////////////// ///*///////////////////////////////////////////////////////////////////// ///*///////////////////////////////////////////////////////////////////// void Convey() { int src,dest; stack *s; int temp, flag = 0; char t; Creatstack(&s); printf("请输入一个数字和要转换的进制(2-16): "); scanf("%d %d",&src,&dest); if(src == 0) { PushChar(&s,'0'); } else { if(src < 0) { flag = 1; src = - src; } while(src != 0) { temp = src % dest; t = JJ[temp]; PushChar(&s,t); src /= dest; } } if(flag == 1) { printf("-"); } while( !IsEmpty(s)) { t = PopChar(&s); printf("%c",t); } printf("\n\n"); } void MatchingCheck() { char str[100], *p; stack *s; Creatstack(&s); printf("请输入要检验的括号串,以#结束 \n"); scanf("%s",str); p = str; while(*p != '#') { switch(*p) { case '(': case '{': case '[': PushChar(&s,*p); break; case ')': if( GetTop(s) != '(' || IsEmpty(s)) { printf("括号不匹配\n\n"); return ; } else { PopChar(&s); } break; case ']': if( GetTop(s) != '[' || IsEmpty(s)) { printf("括号不匹配\n\n"); return ; } else { PopChar(&s); } break; case '}': if( GetTop(s) != '{' || IsEmpty(s)) { printf("括号不匹配\n\n"); return ; } else { PopChar(&s); } break; default : break; } p++; } IsEmpty(s) ? printf("括号匹配! \n\n") : printf("括号不匹配\n\n") ; } void Calculate() { stack *oped; stack *oper; Creatstack(&oper); Creatstack(&oped); char str[1000],temp[1000], *a, *b, c,*p,s1[2]; PushChar(&oper,'#'); printf("请输入一段计算表达式,支持1000位大数和四则运算,以#结束\n"); scanf("%s", &str); p = str; strcpy(temp,"\0"); while( *p != '#' || GetTop(oper) != '#') { if( (*p <= '9' && *p >= '0' ) || *p == '.' ) { s1[0] = *p; s1[1] = '\0'; strcat(temp,s1); p++; if( !((*p <= '9' && *p >= '0' ) || *p == '.' ) ) { Push(&oped,temp); strcpy(temp,"\0"); } } else { switch(Precede(GetTop(oper),*p)) { case -1: PushChar(&oper, *p); p++; break; case 0: PopChar(&oper); p++; break; case 1: c = PopChar(&oper); a = Pop(&oped); b = Pop(&oped); Push(&oped, Opera(c, b, a)); break; } } } printf("%s\n", Pop(&oped)); } ///#////////////////////////////////////////////////////////////// ///#////////////////////////////////////////////////////////////// char * Opera(char x, char *src1, char *src2) { if(x == '+') return Result(src1,src2,WTAdd); else if(x == '-') return Result(src1,src2,WTSubtract); else if(x == '*') return Result(src1,src2,WTMultiply); else if(x == '/') return Result(src1,src2,WTDivide); } int Precede(char src1,char src2) { int ret = 0; switch(src1) { case '*': case '/': if(src2 == '(' ) ret = -1; else ret = 1; break; case '+': case '-': if(src2 == '(' || src2 == '*' || src2 =='/') ret = -1; else ret = 1; break; case '(': if(src2 == ')') ret = 0; else ret = -1; break; case ')': ret = 1; break; case'#': if(src2 == '#') ret = 0; else ret = -1; break; default: break; } return ret; } ///#////////////////////////////////////////////////////////////// ///#////////////////////////////////////////////////////////////// ///#////////////////////////////////////////////////////////////// ///#////////////////////////////////////////////////////////////// ///#////////////////////////////////////////////////////////////// ///#////////////////////////////////////////////////////////////// void InitWTNumberToZero(WTNumber *pNum) { memset(pNum,0,sizeof(WTNumber)); } void AdjustBits(WTNumber *pNum) { while(pNum->intbits>1&&pNum->intpart[pNum->intbits-1]==0) pNum->intbits--; while(pNum->floatbits&&pNum->floatpart[pNum->floatbits-1]==0) pNum->floatbits--; } void MoveFloatPoint(WTNumber *pNum,int deta) { /* deta<0则往左移动小数点,deta>0则向右移动小数点 */ if(deta) { WTNumber n=*pNum; InitWTNumberToZero(pNum); pNum->sign=n.sign; if(deta<0) { int i; deta=-deta; for(i=deta;i<n.intbits;i++) { pNum->intpart[pNum->intbits++]=n.intpart[i]; } for(i=deta-1;i>=0;i--) { pNum->floatpart[pNum->floatbits++]=n.intpart[i]; } for(i=0;i<n.floatbits;i++) { pNum->floatpart[pNum->floatbits++]=n.floatpart[i]; } } else { int i; for(i=deta;i<n.floatbits;i++) /* 处理小数部分*/ { pNum->floatpart[pNum->floatbits++]=n.floatpart[i]; } for(i=deta-1;i>=0;i--) /* 小数到整数的部分*/ { pNum->intpart[pNum->intbits++]=n.floatpart[i]; } for(i=0;i<n.intbits;i++) /* 整数部分*/ { pNum->intpart[pNum->intbits++]=n.intpart[i]; } } } AdjustBits(pNum); } int CharArrLenByWTNumber(const WTNumber* pNum) { int len = pNum->floatbits+pNum->intbits+1; if(pNum->intbits==0) len++; /* .1 --> 0.1*/ if(pNum->floatbits) len++; /* '.'*/ if(pNum->sign) len++; /* '-'*/ if(pNum->infinite) return 11; /* #INFINITE */ return len; } void CharArrToWTNumber(const char *arr,WTNumber *pNum) { char *point; InitWTNumberToZero(pNum); if(*arr=='-') /* 如果是负数*/ { arr++; pNum->sign=1; } point=strchr(arr,'.'); if(point) /* 找到小数点 */ { int n=pNum->intbits=point-arr; /* 计算出整数数位 */ while(n) /* 整数数位不==0则循环 */ { pNum->intpart[pNum->intbits-n]=arr[n-1]-'0'; /* 将数字低位存在低下标元素*/ n--; } while(*++point) { pNum->floatpart[pNum->floatbits]=*point-'0'; pNum->floatbits++; } } else /* 说明没写小数点,全是整数.*/ { int n=pNum->intbits=strlen(arr); while(n) { pNum->intpart[pNum->intbits-n]=arr[n-1]-'0'; n--; } } AdjustBits(pNum); /* 处理-0 和0的情况*/ if(pNum->floatbits==0) { if(pNum->intbits==0 || pNum->intbits==1&&pNum->intpart[0]==0) pNum->sign=0; } } void WTNumberToCharArr(char *szBuf,const WTNumber* pNum) { int n=pNum->intbits,c; memset(szBuf,0,CharArrLenByWTNumber(pNum)); if(pNum->sign) /* 如果是负数*/ { *szBuf++='-'; } if(pNum->infinite) { strcat(szBuf,"#INFINITE"); return; } while(n) { szBuf[pNum->intbits-n]=pNum->intpart[n-1]+'0'; n--; } c=0; /* 是否加了0*/ if(pNum->intbits==0) { strcat(szBuf,"0"); c=1; } if(pNum->floatbits) strcat(szBuf,"."); n=0; while(n<pNum->floatbits) { szBuf[pNum->intbits+1+n+c]=pNum->floatpart[n]+'0'; n++; } } char *Result(const char *val1,const char *val2,PFNCALC pfnCalc) { static char *s_szRes=NULL; WTNumber n1,n2,res; if(s_szRes) { /*delete [] s_szRes;*/ free(s_szRes); s_szRes=NULL; } CharArrToWTNumber(val1,&n1); CharArrToWTNumber(val2,&n2); pfnCalc(&n1,&n2,&res); /* s_szRes = new char[CharArrLenByWTNumber(&res)];*/ s_szRes=(char*)malloc(CharArrLenByWTNumber(&res)*sizeof(char)); WTNumberToCharArr(s_szRes,&res); return s_szRes; } int WTCompare(const WTNumber* pn1,const WTNumber* pn2) { /* 首先是比较符号*/ if(pn1->sign==0&&pn2->sign!=0) /* pn1是正数,pn2是负数*/ return 1; /* >*/ else if(pn1->sign!=0&&pn2->sign==0) /* pn1是负数,pn2是正数*/ return -1; /* <*/ else /* 同号状态*/ { /* 比较整数部分*/ if(pn1->intbits>pn2->intbits) /* pn1整数数位多*/ return pn1->sign?-1:1; else if(pn1->intbits<pn2->intbits) return pn1->sign?1:-1; else /* 整数数位相同*/ { int i=pn1->intbits-1; /*指到最高位*/ while(i>=0) { if(pn1->intpart[i]>pn2->intpart[i]) return pn1->sign?-1:1; else if(pn1->intpart[i]<pn2->intpart[i]) return pn1->sign?1:-1; else i--; } /* 整数部分相同,比较小数部分*/ for(i=0;i<pn1->floatbits&&i<pn2->floatbits;) { if(pn1->floatpart[i]>pn2->floatpart[i]) return pn1->sign?-1:1; else if(pn1->floatpart[i]<pn2->floatpart[i]) return pn1->sign?1:-1; else i++; } if(i<pn1->floatbits) return pn1->sign?-1:1; if(i<pn2->floatbits) return pn1->sign?1:-1; return 0; /* 相等*/ } } } void MakeInfinite(WTNumber *pNum) { pNum->infinite=1; } int IsZero(const WTNumber* pNum) { if(pNum->floatbits==0&&pNum->intbits==0) return 1; if(pNum->floatbits==0&&pNum->intbits==1&&pNum->intpart[0]==0) return 1; return 0; } void WTAdd(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes) { InitWTNumberToZero(pRes); if(pn1->sign^pn2->sign) /*异号*/ { WTNumber n2=*pn2; n2.sign=pn1->sign; WTSubtract(pn1,&n2,pRes); } else /*同号*/ { int maxfloatbits=pn1->floatbits>pn2->floatbits?pn1->floatbits:pn2->floatbits; int addbit=0; /* 进位值*/ int i,j; for(i=maxfloatbits-1;i>=0;i--) { int value=pn1->floatpart[i]+pn2->floatpart[i]+addbit; addbit=value/10; /* 看看是否超过10. 设置进位值*/ pRes->floatpart[i]=value%10; } pRes->floatbits=maxfloatbits; /* 到此,小数部分计算完毕.*/ for(j=0;j<pn1->intbits||j<pn2->intbits;j++) { int value=pn1->intpart[j]+pn2->intpart[j]+addbit; addbit=value/10; pRes->intpart[j]=value%10; pRes->intbits++; } if(addbit>0) { pRes->intpart[j]=addbit; pRes->intbits++; } pRes->sign=pn1->sign; /*决定符号*/ AdjustBits(pRes); } } void WTMultiply(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes) { WTNumber z1=*pn1,z2=*pn2; WTNumber sum={0}; int i,j; InitWTNumberToZero(pRes); MoveFloatPoint(&z1,z1.floatbits); MoveFloatPoint(&z2,z2.floatbits); /* 计算z1*z2 */ for(i=0;i<z2.intbits;i++) { WTNumber tmp={0}; /* 存放临时乘积*/ int addbit=0; tmp.intbits=z1.intbits+i; for(j=0;j<z1.intbits;j++) { int value = z2.intpart[i]*z1.intpart[j]+addbit; addbit=value/10; tmp.intpart[j+i]=value%10; } if(addbit) { tmp.intpart[j+i]=addbit; tmp.intbits++; } WTAdd(&sum,&tmp,pRes); sum=*pRes; } *pRes=sum; MoveFloatPoint(pRes,-(pn1->floatbits+pn2->floatbits)); /* 判断符号,异号为负*/ if(pn1->sign^pn2->sign) pRes->sign=1; } void WTSubtract(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes) { InitWTNumberToZero(pRes); if(pn1->sign^pn2->sign) /* 异号情况*/ { WTNumber n2=*pn2; n2.sign=pn1->sign; WTAdd(pn1,&n2,pRes); } else /* 同号情况*/ { int cmp=WTCompare(pn1,pn2); int swapflag,i,maxfloatbits,subtractbit; if(cmp==0) return; /* 相等就没必要再减了.*/ swapflag=pn1->sign==0?cmp==-1:cmp==1; if(swapflag) { const WTNumber* p=pn1; pn1=pn2; pn2=p; } maxfloatbits=pn1->floatbits>pn2->floatbits?pn1->floatbits:pn2->floatbits; subtractbit=0; /* 退位值*/ /* 先计算小数部分*/ for(i=maxfloatbits-1;i>=0;i--) { if(pn1->floatpart[i]-subtractbit<pn2->floatpart[i]) { int value=pn1->floatpart[i]-pn2->floatpart[i]-subtractbit+10; subtractbit=1; pRes->floatpart[i]=value; } else { int value=pn1->floatpart[i]-pn2->floatpart[i]-subtractbit; subtractbit=0; pRes->floatpart[i]=value; } } pRes->floatbits=maxfloatbits; /* 至此小数部分计算完毕.*/ for(i=0;i<pn1->intbits||i<pn2->intbits;i++) { if(pn1->intpart[i]-subtractbit<pn2->intpart[i]) { int value=pn1->intpart[i]-pn2->intpart[i]-subtractbit+10; subtractbit=1; pRes->intpart[i]=value; } else { int value=pn1->intpart[i]-pn2->intpart[i]-subtractbit; subtractbit=0; pRes->intpart[i]=value; } pRes->intbits++; } pRes->sign=swapflag?!pn1->sign:pn1->sign; /*决定符号*/ AdjustBits(pRes); } } void WTDivide(const WTNumber* pn1,const WTNumber* pn2,WTNumber* pRes) { WTNumber z1=*pn1,z2=*pn2; int deta=z2.floatbits-z1.floatbits; MoveFloatPoint(&z1,z1.floatbits); MoveFloatPoint(&z2,z2.floatbits); InitWTNumberToZero(pRes); if(IsZero(pn1)) return ; if(IsZero(pn2)) { pRes->sign=pn1->sign; MakeInfinite(pRes); return ; } z1.sign=z2.sign=0; /*统一符号,便于比较大小*/ while(z1.intbits!=z2.intbits) { /*确保数位相等,这步耗费很多时间*/ if(z1.intbits<z2.intbits) { MoveFloatPoint(&z1,1); deta--; } else { MoveFloatPoint(&z2,1); deta++; } } while(pRes->floatbits<(1000/2)) { int cmp=WTCompare(&z1,&z2); int n=10; WTNumber mulres={0},subres={0}; if(cmp==-1) { /*z1<z2*/ MoveFloatPoint(&z1,1); pRes->floatpart[pRes->floatbits++]=0; continue; } else if(cmp==0) { /*z1==z2*/ pRes->floatpart[pRes->floatbits++]=1; break; } do { /*找商*/ WTNumber tmp={0}; tmp.intpart[0]=--n; tmp.intbits=1; WTMultiply(&z2,&tmp,&mulres); } while((cmp=WTCompare(&mulres,&z1))==1); pRes->floatpart[pRes->floatbits++]=n; if(cmp==0) break; WTSubtract(&z1,&mulres,&subres); MoveFloatPoint(&subres,1); z1=subres; } MoveFloatPoint(pRes,1); MoveFloatPoint(pRes,deta); /* 判断符号,异号为负*/ if(pn1->sign^pn2->sign) pRes->sign=1; }