C语言实现数学表达式运算_第1页
C语言实现数学表达式运算_第2页
C语言实现数学表达式运算_第3页
C语言实现数学表达式运算_第4页
C语言实现数学表达式运算_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、开发思路:(假设有表达式2*3*(1+2))

数字要一个一个取出放在内存中,根据相邻前后2个计算符号,判断是否要取出数字进行计算,2个

数字的计算值重新放在内存中且顺序放置.<>考虑使用栈这种数据结构去保存数字和符号,用2个栈,

1个栈保存数字,一个栈保存运算符号。

2、因要使用栈这种数据结构,本代码使用纯C语言开发,故先编写栈的代码,参考:

c语言实现通用数据结构(三):通用椎栈

3、重要处理逻辑

<1)如何判断前后2个运算符的优先级关系

*3.1算符间的优先关系

7+-»/()

+>><<<>>

—>><<<>>

.>>>><>>

/>>>><>>

(<<<<<aft>

)>>>>>>

v<.<_<<@牛仔彳新广

(2)如何字符转换为数字

因键盘输入的内容为字符类型,需要判断输入的字符类型且进行必要转换

ASCII码表,表头依次为:二进制十进制「六进制字符

001010004028t

001010014129)

00101010422A金

00101011432B

00101100442C

00101101452D-

00101110462E•

00101111472F1

0011000048300

0011000149311

0011001050322

0011001151333

0011010052344

0011010153355

0011011054366

0011011155377

0011100056388

0011100157399

(3)如何判断表达式处理完毕

默认先预置一个符号#,输入内容2*3*(1+2)#,当符号栈内为#,且当前处理的字符为#。则表达

式处理完毕。

4、代码实现

Sdefine_CRT_SECURE_NO_DEPRECATE

#define_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES1

^include<stdlib.h>

^include<stdio.h>

^include"myStack.h"

//判断是否操作符

intifOp(charc){

switch(c){

case'+':

return1;

case'-':

return1;

case

return1;

case'/':

return1;

case

return1;

case'),:

return1;

case:

return1;

default:

break;

}

return0;

}

intfindOffset(char♦str,charc,intlen){

for(inti-0;i<len;i++){

if(str[i]—c){

return1;

)

)

return-1;

}

〃判断任意相继出现的2个运算符的优先级

charyxji(charopl,charop2){

charops[]="+-*/()#";

charoplist[7][7]={

">><«>>",

">><<<>>",

">>>><>>",

">>>><>>",

"<<«<=&",

">>>>&>>",

intlen-sizeof(ops)/lizeof(char);

returnoplist[findOffset(ops,opl,len)][findoffset(ops,cp2,len)];

}

〃基础运算a•第1个数b-第2人数

voidbaseOp(charop,inta,in,:b,int•value){

printf("baseOp%d%c%d",a,op,b);

//intvalue=0;

//int*p-&value;

switch(op){

case

•value=a+b;

break;

case

,value=a-b;

break;

case

,value-a*b;

break;

case'/':

•value=a/b;

break;

default:

printf("运算符不合法

exit⑴;

)

}

〃钱换字符为数字

voidtransValue(charc,int*v){

if(c>47&&c<58){

*v=(c-48);

}

}

voidprintstack(MyStack♦stackl,MyStack*stack2){

intlenl-myListGetSize*stackl);

intlen2-myListGetSize(stack2);

printf("stackl值:");

for(int1=0;1<lenl;i++)(

char*m-(char*)myListGetDataAt(stackl,i);

printf("%c",*m);

}

printf("\nstack2值:”);

for(inti=0;i<len2;i++){

int*m-(int*)myLis*GetDataAt(stack2i);

printf(HXd(Xp)\•«1,»);

}

printf(M\n");

}

//计算,该方法只能对数字0-9运算(可掌握栈、指针的使用)

//2*3*(1+2)#

voidcalculate(charbds[]){

inti=0;

charflag=;

MyStack"stackl-creatcMy3tack();//5tackl中放运算符

myStackPush(stackl,&flag);

MyStack,stack2=createMyStack();//stack2中放数字

//charc=bds[i];//等价于*(bds+i)

while(bds[i]!=||*(char*)myStackGetTop(stackl)!='#,){

printstack(stackl,stack2);

if(!ifOp(bds[i])){

/*

*这种写法不行!

intvv-0;

transValue(bds[i],&vv)

int*vu-(int*)malloc(sizeof(int));

transValue(bds[iJ,vu);

printf("isnumber:%d\n",*vu);〃打印出数字

myStackPush(stack2,vu);

i++;

)

else{

printf("isfuhao:%c\n",bds[i]);

char♦opl=(char*)myStackGetTop(stackl);

printf("topiop:Xc\n",*opl);

if(*opl->,#'){

rnyStackPush(stackl,&bds[i]);

continue;

}

charres=yxji(*opl,bds[i]);

printf("yxji:%c\n",res);

switch(res){

case'>>:{

char*curop=(char*)myStackPop(stackl);〃取出当前运算符

print-f("iop2op:%c\n",*opl);

int*b=(int*)myStackPop(stack2);〃第2个运算数

int*a-(int*)myStackPop(stack2);〃第1个运算数

/*

*这种写法不行!

intvalue■0;

baseOp(*curop,transValue(*a),transValue(*b),8value);

int*value■(int*)malloc(sizeof(int));

baseOp(*curop,*a,*b,value);

printf("=%d\n",*value);

myStackPush(stack2,value);

break;

}

case'<':

myStackPushCstackl,&bds[i]);

i++;

break;

case:{

printf(".:)-");

myStackPop(stackl);〃取出右括号(

break;

}

default:

printf("友达式错误!”);

exit(l);

}

}

}

int,valueRes=(int")myStackPop(stack2);

printf("计免结果值为:%d\n",*valueRes);

freeMyList(stackl);

freeMyList(stack2);

)

intmain(){

printf("输入表达式:\n");

charbds[50];

scanf("%s",bds);〃数组变量名,传入的相当于是数组第一个元素的地址。方法形参是个指针变显,指针变量才能存放

地址

calculate(bds);

return0;

)

5、代码开发过程总结(踩坑填坑真实记录)

将符号转为数字并把数字放入栈中,若写为如下形式不行

intw-0;

transValuefr,&vv);

myStackPush(stack2,vv);

因为临时变量地址始终不变,第2个值赋值后,等于是把已放入栈内的第一个值修改了(程序中通过

打印出指针变量值,即变量的地址,发现地址确实没变)

应该用如下方式:

int*w=(int*)malloc(sizeof(int));

transValuefl*,vv);

myStackPush(stack2,vv);

掌握指针用法很重要!此处记录如下:

再看用数组名作函数参数的情况.前已介绍,实参数组名代表该数组首元索的地址•而

形参是用来接收从实参传递过来的数组首元素地址的.因此•形参应该是一个指针变量(只

有指针变量才能存放地址).实际上.C编译都是将形参数组名作为指针变量来处理的.例

如,本小节开头给出的函数fun的形参是写成数组形式的:

fun<int•rrCJtintn)

但在程序编译时是将an按指针变僦处理的,相当于将函数fun的苜部写成

funtini•arr.intn)

以上两种写法是等价的.在诙函数被谓用时,系统会在fun函数中思*一禽财喀犬”.

用来存放从主调的数传递过来的实参数组首元素的地址.如果余忠喘柏市府象跖

«8.1以变量名和数组名作为函数参数的比较

实参类型变垃名数组名

要求形参的类型变址名数组名或指针变量

传递的信息变量的值实参数组首元素的地址

通过函数调用能否改变实参的值不能改变实参变量的值能改变实参数组的值

需要说明的是:C语言调用函数时虚实结合的方法都是采用“值传递”方式,当用变址

名作为函数参数时传递的是变量的值,当用数组名作为函数参数时,由于数组名代表的是数

组首元素地址,因此传递的值是地址,所以要求形参为指针变域.

在用数组名作为函数实参时,既然实际上相应的形参是指针变量,为什么还允许使用形

参数组的形式呢?这是因为在C语言中用下标法和指针法都可以访问一个数组(如果有一

个数组a,则a[i]和*(a+i)无条件等价)•用下标法表示比较直观,便于理解.因此许多人

愿意用数组名作形参,以便与实参数组对应。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论