APUE作业之一,记录备查(未实现全部要求功能)
//************************
//实现四则运算,可以使用()改变运算顺序,支持sin、cos、exp、log函数(可以扩充)
//在gcc下调试通过
//后续修该备忘:
//1、增加函数(单操作数):同时修该functions变量、is_func()/is_func2()/cal_func()等含数;
//2、增加精度设置:增加指定输出精度命令。。。。
//2009.6.23
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<math.h>
#define MAX_LINE 1024
#define MAX_OPERATOR 512
typedef int bool;
#define true 1
#define false 0
struct stack_num
{
double num[MAX_OPERATOR];
int cur;
};
struct stack_op
{
char op[MAX_OPERATOR];
int cur;
};
bool num_push(struct stack_num *stack, double n);
bool num_pop(struct stack_num *stack, double *ptr);
double num_top(struct stack_num *stack);
bool op_push(struct stack_op *stack, char ch);
bool op_pop(struct stack_op *stack, char *ptr);
inline char op_top(struct stack_op *stack);
char get_pri(char a, char b);
inline char* get_key(char *ptr);
inline bool is_opera(char ch);
inline bool is_num(char ch);
double operate(double a, char op, double b);
double cal_func(char op, double a);
//*****操作符优先级表 ***************************
//由于目前所有函数的优先级相同,因此表中只包含了一个(sin函数)
//其他函数执行优先级查询时,由于边界限制,实际查询的和sin相同
char priority[8][8] =
{
// + - * / ( ) # s
{ '>','>','<','<','<','>','>','<'},//+
{ '>','>','<','<','<','>','>','<'},//-
{ '>','>','>','>','<','>','>','<'},//*
{ '>','>','>','>','<','>','>','<'},///
{ '<','<','<','<','<','=','N','<'},//(
{ '>','>','>','>','N','>','>','N'},//)
{ '<','<','<','<','<','N','=','<'},//#
{ '>','>','>','>','<','>','>','<'},//s
};
char* operators = "+-*/()#";
char* functions = "scelf";
char* numbers = "1234567890.";
char cmd[MAX_LINE];
char *key[MAX_OPERATOR];
//******堆栈操作函数定义*******
bool num_push(struct stack_num *stack, double n)
{
if(stack->cur >= MAX_OPERATOR)
return -1;
stack->num[stack->cur++] = n;
return 0;
}
bool num_pop(struct stack_num *stack, double *ptr)
{
if(stack->cur <= 0)
return -1;
*ptr = stack->num[--stack->cur];
return 0;
}
double num_top(struct stack_num *stack)
{
return stack->num[stack->cur-1];
}
bool op_push(struct stack_op *stack, char ch)
{
if(stack->cur >= MAX_OPERATOR)
return -1;
stack->op[stack->cur++] = ch;
return 0;
}
bool op_pop(struct stack_op *stack, char *ptr)
{
if(stack->cur <= 0)
return -1;
*ptr = stack->op[--stack->cur];
return 0;
}
inline char op_top(struct stack_op *stack)
{
return stack->op[stack->cur-1];
}
//****** 查询a、b的优先级*********
//a 在 b的前面输入(即:a为表中的行,b为表中的列)
char get_pri(char a, char b)
{
int i,j;
int lenth = strlen(operators);
for(i=0; i<lenth && operators[i]!=a; i++) ;
for(j=0; j<lenth && operators[j]!=b; j++) ;
return priority[i][j];
}
//***** 获取下一个关键字(非空格的字符)*******
//返回下一关键字的指针
//主要用于消除空格的影响
inline char* get_key(char *ptr)
{
while(*ptr==' ')
ptr++;
return ptr;
}
//****查询是否为操作符********
bool is_opera(char ch)
{
int i;
int len = strlen(operators);
for(i=0; i<len; i++)
{
if(operators[i] == ch)
break;
}
if(i==(len))
{
return false;
}
else
return true;
}
//****查询是否为数字*****
bool is_num(char ch)
{
int i;
int len = strlen(numbers);
for(i=0; i<len; i++)
{
if(numbers[i] == ch)
break;
}
if(i==len)
return false;
else
return true;
}
//****查询是否为函数****
//若是函数 则只保留首字母当作操作符
bool is_func(char *ptr)
{
switch(*ptr)
{
case 's':
{
if(ptr[1]=='i' && ptr[2]=='n')
{
ptr[1] = ' ';
ptr[2] = ' ';
return true;
}
else
return false; //syntax error;
}
case 'c':
{
if(ptr[1]=='o' && ptr[2]=='s')
{
ptr[1] = ' ';
ptr[2] = ' ';
return true;
}
else
return false; //syntax error;
}
case 'l':
{
if(ptr[1]=='n')
{
ptr[1] = ' ';
return true;
}
else
return false; //syntax error;
}
case 'e':
{
if(ptr[1]=='x' && ptr[2]=='p')
{
ptr[1] = ' ';
ptr[2] = ' ';
return true;
}
else
return false; //syntax error;
}
default:
return false;
}
return false;
}
//******查询是否为函数2*******
//简单的查询 函数与否,用于函数名称规一化之后
bool is_func2(char ch)
{
int i;
int len = strlen(functions);
for(i=0; i<len; i++)
{
if(functions[i] == ch)
break;
}
if(i==len)
return false;
else
return true;
}
int main(int argc, char *argv[])
{
char *ptr;
char old_oper;
char prio;
int lenth;
bool err = false;
double n;
double na,nb;
struct stack_op s_oper;
struct stack_num s_num;
while( fgets(cmd, MAX_LINE, stdin) != NULL)
{
lenth = strlen(cmd);
if(cmd[lenth-1] != '/n')
{
printf("line too long /n");
exit(0);
}
//初始化堆栈等
cmd[lenth-1] = '#';
ptr = cmd;
s_oper.cur = 0;
s_num.cur = 0;
op_push(&s_oper,'#');
err = false;
ptr=get_key(ptr);
while(1)
{
old_oper = op_top(&s_oper);
if( *ptr=='#' && old_oper=='#')
break; //两端的#相遇,说明计算完毕
if(is_opera(*ptr)||is_func(ptr)) //当前字符为操作符或函数(在这里执行函数名的归一化)
{
prio = get_pri(old_oper,*ptr);
switch(prio)
{
case '>': //上一个操作符优先级高,则计算上一个操作
{
op_pop(&s_oper,&old_oper); //pop the old operator
if(is_func2(old_oper)) //函数运算(单目操作)
{
num_pop(&s_num,&na);
num_push(&s_num, cal_func(old_oper,na));
break;
}
else //运算符操作(双目操作)
{
num_pop(&s_num,&nb);
num_pop(&s_num,&na); // pop the two numbers na,nb
if( old_oper=='/' && nb==0.0)
{
printf("divided by 0/n");
err = true;
break;
}
num_push(&s_num,operate(na,old_oper,nb)); //operate them and push the result
break;
}
}
case '<': //当前操作符优先级高
{
op_push(&s_oper,*ptr); //当前操作符入栈
ptr = get_key(++ptr);
break;
}
case '=': //()相遇
{
op_pop(&s_oper,&old_oper);
ptr = get_key(++ptr);
break;
}
default:
{
printf("syntax error/n");
err = true;
break;
}
}
}
else if(is_num(*ptr))
{
n = strtod(ptr,&ptr);
num_push(&s_num,n); //num 入栈
ptr = get_key(ptr);
}
else
err = true;
if(err == true)
{
break;
}
}
if(err==true)
continue;
else
{
printf("%lf/n",num_top(&s_num));
}
}
exit(0);
}
//*****运算符操作**********
double operate(double a, char op, double b)
{
switch(op)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
case '/':
return a/b;
default:
return 0;
}
}
//**********函数操作**************
#define PI 3.1415926
double cal_func(char op, double a)
{
switch(op)
{
case 's':
return sin(a*PI/180);
case 'c':
return cos(a*PI/180);
case 'l':
return log(a);
case 'e':
return exp(a);
default:
return 0;
}
}