ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

实验设计-利用栈实现计算器

2021-02-28 18:02:52  阅读:226  来源: 互联网

标签:利用 int top zc char 实验设计 数组 计算器 表达式


1.实现一个简单的计算器,输入一个包含圆括号、加减乘除、求余等符号组成的算术表达式字符串,输出该算术表达式的值。要求:
(1)系统至少能实现加、减、乘、除、求余等运算;
(2)利用栈实现并将表达式结果输出。

1.算法设计及算法步骤:

程序分析:计算器功能实现,利用顺序栈实现中缀表达式到后缀表达式的转变,继而进行相应的(+,-,*,/)简单运算。
中缀表达式转后缀表达式:
申请一段连续的顺序栈字符空间进行运算符存储,以便输入输出顺序控制。
通过一个数字数组和一个字符数组保存后缀表达式。两个数组同步数组下标,当数字数组存入一个数字时候,字符数组存入一个!号作为标识,且记录数组下标的int变量++;当字符数组存入一个符号时,数字数组下标位置默认为0,不用做标识,只需把记录数组下标的int变量++。
通过flag变量记录字符解析状态,如果连续解析到数字字符,则数字拼接,如果解析到字符,如果flag标识上次读取的为数字,则先将数字输出录入数组,再对字符进行分析。
字符如果是’(‘号,或者栈顶指向-1,则字符直接录入栈中;如果遇到右括号,执行出栈操作,并将出栈符号输出(录入到数组),直到左括号也出栈,左括号不输出;遇到运算符时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将运算符入栈(即如果是乘除,则乘除出栈,新符号进栈,
如果是加减,则四则运算出栈,遇到左括号停止出栈,新符号进栈。)最终(字符值为NULL)将栈中的元素依次出栈,输出。
后缀表达式运算:
申请一段连续的顺序栈数字(int)空间存储读取到的数字,以便表达式运算。
如果数字数组下标位置不为NULL则读取到数字,并将数字入栈,如果字符数组下表位置不为!号则说明后缀表达式这个位置是一个运算符,则出栈两个数字进行数学运算,运算后将结果入栈。
当读取到数组下标位置为NULL的时候则说明后缀表达式读取,读取完毕,返回最终结果。

C语言实现:

#define OK 1
#define ERROR 0
#define MAXSIZE 50
#include<stdio.h>
#include<stdlib.h> //引入库文件 
#include<string.h>
typedef int status;  //status是函数的类型,其值是函数结果状态代码,如OK等
                     //多用来当返回值用,注意这里Status是一个整型,如果return OK 则代表返回值 1,return ERROR代表 0 

                     //栈的理解:就相当于竖起来的线性表,对于顺序存储,这种概念更深,
					 //栈(Stack)是限定仅在表尾进行插入和删除操作的线性表.栈有空栈概念,会有一个跟踪栈顶的指针top,
					 //定义当top为-1时即为空栈, top总小于StackSize,当为满栈时,top=StackSize-1   
					 //延伸:总结栈和堆的概念及区别 

					 //c语言中char以及字符串:
//	表示字符型数组a中可以存放2个字符,第1个字符用a[0]访问,第2个字符用a[1]访问,最大下标可以用0~(2-1)范围的。比如a[100]合法下标范围是0~99;
//当a需要保存字符串时,需要注意,字符串必须以0值结尾,表示成字符就是'\0',而且这个0不算在字符串中的字符,那么你用a数组最多只能保存n-1个字符组成
//的数组,如果是char a[2];的话只能保存一个字符组成的字符串;如:char a[20]={ "Hello !" };或者char a[20]={ 'H','e','l','l','o','\0' };这时字符串占
//用6个数组元素,但字符串长度为5,如果你用strlen语句计算的长度也为5,你最多可在这个数组中保存长度为19的字符串,需要自己在末尾添加0或'\0',前面语句
//char a[20]={ "Hello !" };是编译器自动帮你加了结尾符0;
//  当懒得数字符串中字符个数时,也可以让编译器帮你数:char a[]={"Hello"};这与你自己写:char a[6]={ "Hello" };是一样的。
//char a[2];
//这是声明。声明变量 a 是 char 型数组,有2个元素。
//语句里  写  a[0] 表示它是 char 型数组a 里的 第一个 元素
//a[1] 是 char 型数组a 里的 第二个 元素。 
//char a[2];  
//也可以看成 是 字符串 变量 a。  由于 字符串要用1个单元存放字符串 结束符,所以只能 存放 长度为 1 的字符串。
//声明,带初始化写法:
//char a[2]={ 'A', 'x'};   初始化 a[0]='A';  a[1]='x';  -- 单引号括起的是 字符常量
//char a[2]="A";    初始化 字符串 "A"  -- 双引号括起的是 字符串,含 字符串结束符。

/*实现一个简单的计算器,输入一个包含圆括号、加减乘除、求余等符号组成的算术表达式字符串,输出该算术表达式的值。要求:
(1)系统至少能实现加、减、乘、除、求余等运算;
(2)利用栈实现并将表达式结果输出。*/

//要想让计算机具有处理我们通常的标准(中缀)表达式的能力,必须有:
//1.将中缀表达式转化成后缀表达式(栈用来进出运算的符号)
//2.将后缀表达式进行运算得出结果(栈用来进出运算的数字)


//c语言的字符串是以字符数组组成的,不能用普通运算符去运算字符串
//指针可以保存一个字符串常量,是只读不可写的 
//栈实现利用栈的顺序存储,字符串分隔,并将数字保存到数组中,将符号保存到字符数组中

//要明白一点,数据结构,注重算法思想,过程的学习,c语言是比较基础的语言,
//虽然库中也有很多方便的封装函数,但其基础的实现也是由人编写代码实现目的的,
//且可能函数实现要比我们自己写的程序更加复杂,与我们目的相比冗余更多,
//实现功能上,尽量自己去写底层代码,而减少函数的调用使用 

//中缀表达式转后缀表达式时用到的字符栈 
typedef char ElemType; 

//声明栈类型 
typedef struct SqStack{
 ElemType data[MAXSIZE];
 int top; 
}SQTA ;
typedef struct SqStack *zhanChar;//指针,保存地址的变量 
//后缀表达式计算时用到的数字栈 
typedef int ElemTypes; 
typedef struct SqStacks{
 ElemTypes data[MAXSIZE];
 int top; 
}SQTAs ;

typedef struct SqStacks *zhanInt;//指针,保存地址的变量 
//定义的结构体如果是指针,访问成员时就用->
//如果定义的是结构体变量,访问成员时就用.
 
 int begin();//主界面,根据用户输入内容执行不同操作 
 int transform(char shizi[]); //将中缀表达式转为适合计算机运算的后缀表达式 
int count(char shiziChar[],	int shiziInt[]); //对后缀表达式进行运算并将结果返回 


int transform(char shizi[]){  //数组本身是一个表达地址 
	
	char shiziChar [100]={};//用来存储符号排序后的符号 //如果位置是数字,存储! 
	int shiziInt [100]={}; //用来存储数字数组,如果是位置是字符,则存储为0 
	char *p=shizi; //shizi本身也是一个指针,但因为名字原因,这里还是用指针p代替 
	int a =0;//用来记录分隔后的数
	int index=0;//用来记录
	int flag=1;//用来记录是否正在拼数字 即(是否在拼数字状态) 
	zhanChar zc=(zhanChar)malloc(sizeof(SQTA ));//如果分配成功则返回指向被分配内存的指针
	zc->top=-1;
	
do{
	  
	if(*p>=48&& *p<=57){  //读到一个数字字符 
       a *=10;
		a+=*p-48;
		flag=1; 
	}else{               //读到一个字符,或者字符串结束 
		if(flag==1){
			shiziInt[index]=a;  //把拼接好的数字录入数组 
			shiziChar[index]='!';//把这一位置用!标识
			index++; 
			a=0;         
						     //到此,相当于一个数录入完毕 
		}
		if(*p==NULL){    
			//printf("读取完毕");
			while(zc->top!=-1){
				shiziChar[index]=zc->data[zc->top];
				index++;
				zc->top--;
			}
			
				break;
		} else if(zc->top==-1||*p=='('){   // 如果字符是(或者zc->top==-1,直接入栈 
			zc->top++;                  
			zc->data[zc->top]=*p;
		}else if(*p==')'){
			//遇到右括号,执行出栈操作,并将出栈符号输出,直到左括号也出栈,左括号不输出
			//遇到+--/ 时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将运算符入栈
			//最终将栈中的元素依次出栈,输出 
			do{
				if(zc->data[zc->top]=='('){
					zc->top--;  // 
					break;
				}else{
					
			shiziChar[index]=zc->data[zc->top];
				index++;
			zc->top--;
				} 
			}while(1);
			
		} else if(*p=='*'||*p=='/'){  //如果是乘除,则乘除出栈,新符号进栈 
			while(zc->top>=0&&zc->data[zc->top]=='*'||zc->data[zc->top]=='/'){
				shiziChar[index]=zc->data[zc->top];
				index++;
				zc->top--;
			}
			zc->top++;
			zc->data[zc->top]=*p;
			
		}else if(*p=='+'||*p=='-'){  //如果是加减,则四则运算出栈,遇到左括号停止出栈,新符号进栈 
			while(zc->top>=0&&zc->data[zc->top]!='('){
				shiziChar[index]=zc->data[zc->top];
				index++;
				zc->top--;
			}
			
			zc->top++;  
			zc->data[zc->top]=*p;
			
		}
		     
		flag=0;
		
		
	}
	 p++;
	 //如果单单输入一个纯数字 
	 
	}while(1);
	int i=0;
	printf("\n");
	while(shiziInt[i]!=NULL||shiziChar[i]!=NULL){  //数字数组默认为0 
		if(shiziInt[i]!=NULL){
			printf("%d",shiziInt[i]);
			
		}else if(shiziChar[i]!='!'){
			printf("%c",shiziChar[i]);
		}
			i++;
		}
			printf("\n");

      int counts=0;
      counts=count(shiziChar,shiziInt);
	return counts;
}
//	printf("%\n",p); 
//	printf("%s\n",shizi); 
//	printf("%c\n",shizi[0]);
//	printf("%p\n",shizi);
//	printf("%p\n",shizi[0]);
//	printf("%p\n",shizi[1]);

 int count(char shiziChar[],int shiziInt[]){
	int i=0;//用来记录
	zhanInt zi=(zhanInt)malloc(sizeof(SQTAs ));//如果分配成功则返回指向被分配内存的指针
	zi->top=-1;
	int count=0; //运算后的值,或最终结果
	int count1=0,count2=0; 
	while(shiziInt[i]!=NULL||shiziChar[i]!=NULL){
		if(shiziInt[i]!=NULL){   //读取到数字的时候进栈 
			zi->top++;
			zi->data[zi->top]=shiziInt[i];
			
		}else if(shiziChar[i]!='!'){  //遇到字符的时候进行运算 
			      count2=zi->data[zi->top];   //记录栈顶 
				      zi->top--;
					   count1=zi->data[zi->top];  //记录栈顶-1 
			 if(shiziChar[i]=='+'){
			 	count=count1+count2;
			 }else if(shiziChar[i]=='-'){
			 	count=count1-count2;
			 }else if(shiziChar[i]=='*'){
			 	count=count1 * count2;
			 }else if(shiziChar[i]=='/'){ 
			 	count=count1 / count2;
			 }
			 zi->data[zi->top]=count;
		} 
		   
			i++;
		}
		count=zi->data[zi->top];
		    zi->top--;
		
		return count;
} 


int begin(){
	printf("------麦兜给您计算计算器--------\n");
  	char shizi[100]=""; //最终的式子 
	printf("给我要计算的式子:\n"); 
	scanf("%99s",&shizi);
  	printf("麦兜努力计算中....");
  	printf("%d",transform(shizi));
  	} 
int main() {
	 
    begin();
    return 1;
}

标签:利用,int,top,zc,char,实验设计,数组,计算器,表达式
来源: https://blog.csdn.net/qq_42212501/article/details/114232838

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有