栈的一些应用

 

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;
}

  

 

 

  

posted on 2012-03-26 00:14  genslow  阅读(305)  评论(0编辑  收藏  举报