⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 addandsubtacttomultiplybyinadditiontocalculatorvcsourcecode.txt

📁 Add and subtract to multiply by in addition to calculator VC source code
💻 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 + -