📄 addandsubtacttomultiplybyinadditiontocalculatorvcsourcecode.txt
字号:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
/* 顺序栈的动态分配存储结构 */
#define STACK_INIT_SIZE 100 //栈初始容量
#define STACKINCREMENT 10 //栈容量增量
#undef SElemType //取消宏SElemType
#undef SqStack //取消宏SqStack
#if OPRSTACK == 1 //编译常数OPRSTACK为1表示运算符栈,为其他数表示操作数栈
#define SElemType char //栈元素类型SElemType为char
typedef struct{
SElemType *base; //栈底指针
SElemType *top; //栈顶指针
int stacksize; //当前容量
}OprStack;
#define SqStack OprStack
#else //编译常数OPRSTACK不为1表示操作数栈
#define SElemType double //栈元素类型SElemType为double
typedef struct{
SElemType *base; //栈底指针
SElemType *top; //栈顶指针
int stacksize; //当前容量
}NumStack;
#define SqStack NumStack
#endif
/* 初始化:构造一个空栈S */
void InitStack(SqStack *S)
{unsigned int nSize;
nSize = STACK_INIT_SIZE * sizeof(SElemType); //欲分配空间字节数
S->base = (SElemType *)malloc(nSize); //分配初始的存储空间
S->top = S->base; //初始栈顶
S->stacksize = STACK_INIT_SIZE; //初始容量
}//InitStack
/* 判栈空:
若S是空栈则返回TRUE,否则返回FALSE
*/
int StackEmpty(SqStack *S)
{
return (S->top == S->base);
}//StackEmpty
/* 销毁:释放顺序栈S所占的存储空间 */
void DestroyStack(SqStack *S)
{
free(S->base); //释放顺序栈S所占的存储空间
}//DestroyStack
/* 入栈:插入元素e为新的栈顶元素
*/
void Push(SqStack *S, SElemType e)
{unsigned int nSize;
//若容量不够则扩展:
if ((S->top - S->base) == S->stacksize) //若满容,
{ //则扩容:
nSize = S->stacksize + STACKINCREMENT; //新容量
S->base = (SElemType *)realloc(S->base, nSize * sizeof(SElemType)); //重新分配空间
S->top = S->base + S->stacksize; //新栈顶=新栈底+原容量
S->stacksize = nSize; //新容量
}//end if
*(S->top) = e; //e置栈顶
S->top++; //栈顶指针加1
}//Push
/* 出栈:删除栈顶元素,并用e返回
若删除失败则置全局量Error为1。
*/
void Pop(SqStack *S, SElemType *e)
{
if (StackEmpty(S)) //若栈空,
Error = 1; //置Error为1
else
{
S->top--; //栈顶指针减1
*e = *(S->top); //栈顶元素置于e
}
}//Pop
/* 取栈顶:用e返回栈顶元素
若失败则置全局量Error为1。。
*/
void GetTop(SqStack *S, SElemType *e)
{
if (StackEmpty(S)) //若栈空,
Error = 1; //置Error为1
else
*e = *(S->top - 1); //栈顶元素置于e
}//GetTop
/* Eval.cpp */
#include <string.h>
#include <math.h>
#define ERRVAL HUGE_VAL //错误值
int Error; //为1表出错,0无错
int position; //当前符号位置
double numval; //当前操作数的值
//编译常数OPRSTACK设为1,Stack.cc将构造出运算符栈OprStack:
#define OPRSTACK 1
#include "Stack.cpp" //栈类型定义及基本运算
#undef OPRSTACK //取消宏OPRSTACK:
//编译常数OPRSTACK不为1,Stack.cc将构造出操作数栈NumStack:
#define OPRSTACK 0
#include "Stack.cpp" //栈类型定义及基本运算
/* 运算:根据操作数及运算符作相应运算并返回结果
*/
double Operate(double a, char op, double b)
{double x;
switch (op) {
case '+': x = a + b; break;
case '-': x = a - b; break;
case '*': x = a * b; break;
case '/': if (b == 0)
{ x = ERRVAL; Error = 1;}
else
x = a / b;
break;
default: x = ERRVAL;
}//end switch
return(x);
}//end Operate
/* 算符优先级比较:返回比较结果
对相继出现的算符L和R:
若L<R,返回"<"
若L=R,返回"="
若L>R,返回">"
若不许L和R相继出现,返回"x"
若L或R为非法算符,返回"x"
*/
char Precede(char L, char R)
{
char p[8][9] = {
" +-*/();",
"+>><<<>>",
"->><<<>>",
"*>>>><>>",
"/>>>><>>",
"(<<<<<=x",
")>>>>x>>",
";<<<<<x=" };
/*优先矩阵p的第0行第0列闲置不用,第0列从p[1][0]开始是先出现的算符(L),第0行从p[0][1]开始是后出现的算符(R),从p[1][1]开始右下角内容是L与R的优先关系。实际上,第0列可去掉,但为了直观,仍保留。
*/
char *ptr;
int row, col;
//确定L所在的行row:
ptr = strchr(p[0], L); //在第0行查找L(本应在第0列查找,因第0列和第0行的元素位置一样,固效果同)
if (ptr == NULL) return 'x'; //未找到,非法算符
row = ptr - p[0];
//row已确定。
//确定R所在的列col:
ptr = strchr(p[0], R); //在第0行查找R
if (ptr == NULL) return 'x'; //未找到,非法算符
col = ptr - p[0];
//col已确定。
return p[row][col];
}//end Precede
void GetNumber(char *s) //取"数"
//position在调用前已指向一个数字,调用后指向非数字
//数值存于全局量numval
{
double v, radix;
numval = 0.0;
do { //拼整数
v = s[position] - '0';
numval = 10 * numval + v;
position++;
}while (('0' <= s[position]) && (s[position] <= '9'));
//
if (s[position] == '.')
{
position++;
radix = 0.1;
while (('0' <= s[position]) && (s[position] <= '9'))
{//拼小数
v = radix * (s[position] - '0');
numval = numval + v;
radix = radix * 0.1;
position++;
}//end while
}//end if
}//GetNumber
/* 取符号: 取当前位置position开始的第1个非空格符号(过滤空格)
*/
char GetToken(char *s)
{char c;
c = s[position];
while (c == ' ') //过滤空格
{
position++;
c = s[position];
}//end while
//
if (('0' <= c) && (c <= '9')) //当前字符为数字
{
GetNumber(s); //取"数"
c = '0'; //约定返回'0'代表"数"
}
else
position++;
//end if
return c;
}//end GetToken
double Eval(char *E) //返回表达式E的值
{
char s[100];
OprStack OPTR; //运算符栈
NumStack OPND; //操作数栈
double x, y, ret;
char c, CC, CT;
strcpy(s, E); //复制表达式E到s
strcat(s, ";"); //表达式末尾添加结束符";"
InitStack(&OPTR); //初始化运算符栈
Push(&OPTR, ';'); //结束符";"进运算符栈
InitStack(&OPND); //初始化操作数栈
position = 0; //当前符号位置初始为0
Error = 0; //错误标记初始为0(无错)
CC = GetToken(s); //取当前符号
GetTop(&OPTR, &CT); //取栈顶运算符置于CT
while ((CC != ';') || (CT != ';'))
{//只要当前符号和栈顶运算符不都是结束符";"便继续:
if (CC == '0') //若是操作数(GetToken中约定'0'代表操作数)
{
Push(&OPND, numval); //操作数进栈
CC = GetToken(s); //取下一个符号
}
else //若非操作数(看作运算符)
{
c = Precede(CT, CC); //栈顶运算符CT与当前运算符CC的优先级
switch (c)
{
case '<': //栈顶优先级小
Push(&OPTR, CC); //当前运算符CC进栈
CC = GetToken(s); //取下一个符号
break;
case '=': //'('与')'配对
Pop(&OPTR, &CT); //脱括弧
CC = GetToken(s); //取下一个符号
break;
case '>': //栈顶优先级大
Pop(&OPTR, &CT); //弹出栈顶运算符置于CT
Pop(&OPND, &y); //弹出栈顶操作数置于y(右操作数)
Pop(&OPND, &x); //弹出栈顶操作数置于x(左操作数)
ret = Operate(x, CT, y);
Push(&OPND, ret); //运算结果进操作数栈
break;
default:
Error = 1;
break;
}//end switch
}//end if
if (Error) break; //出错退出
GetTop(&OPTR, &CT); //取栈顶运算符置于CT
}//end while
//至此,若表达式无错,则运算符栈只有结束符";",而操作数栈也只有一个元素(就是表达式计算结果)
Pop(&OPTR, &CT); //弹出栈顶运算符
Pop(&OPND, &ret);//弹出栈顶操作数置于ret(即表达式计算结果)
if (!(StackEmpty(&OPTR) && StackEmpty(&OPND)))
Error = 1; //表达式有错
DestroyStack(&OPTR); //销毁运算符栈
DestroyStack(&OPND); //销毁操作数栈
return ret;
}//end Eval
void main(void)
{
char *t[] = {"0",
"3.5 + 1.4 - 3.5",
"(18 - 2 * (10 - 8.25)) / 5",
"1/0",
"5/3"};
char s[80];
double x;
int i;
printf("\n申明:要结束程序请输入;后按回车键。\n");
for (i = 0; i < 5; i++)
{
printf("表达式: %s\n", t[i]);
x = Eval(t[i]);
if (Error)
printf("表达式有错!\n");
else
printf("结果: %g\n", x);
}//end for
//
do {
printf("表达式: ");gets(s);
x = Eval(s);
if (Error)
printf("表达式有错!\n");
else
printf("结果: %g\n", x);
} while (s[0] != ';'); //输入';'退出
}//end main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -