原题:在这里插入代码片
栈应用作业
已经给定了若干的表达式在附件“3周作业材料.txt”中
要求:
(1)顺序读取文件的每一行,并且打印输出
(2)计算出该行表达式结果,打印输出
(3)输出一个换行,并且进行下一行表达式的处理
思路借鉴于数据结构与算法:C语言版/程玉胜主编—合肥:中国科学技术大学出版社,2015.1——p52、p53
欢迎转载,转载请标明出处(请勿直接用于提交作业)
小声bb:小心平时分扣光
摆烂作业,初次尝试,fw一位,欢迎各位大佬指点(求轻喷)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Maxsize 100
#define H 10
typedef char signed ElemType1;//操作符
typedef struct
{ElemType1 stack[Maxsize];
int top;
}SeqStack1;
typedef double ElemType;//操作数
typedef struct
{ElemType stack[Maxsize];
int top;
}SeqStack;
void InitStack(SeqStack *s)
{
s->top =0;
}
int StackEmpt (SeqStack *s)
{
return s->top ==0;
}
void push(SeqStack *s,ElemType x)
{
if(s->top ==Maxsize)
{printf("\n 栈已满,上溢!");
exit(1);
}
s->top ++;
s->stack [s->top -1]=x;
printf("*新入栈的是%f*\n",s->stack [s->top -1]);
}
ElemType pop(SeqStack *s)
{
if(StackEmpt(s))
{printf("\n 栈已空,下溢!");
exit(1);
}
ElemType t=s->stack [s->top -1];printf("《运算数出栈是%f》\n",s->stack [s->top -1]);
s->top --;
return t;
}
ElemType GetTop(SeqStack *s)
{ if(StackEmpt(s))
{printf("\n 栈已空");
exit(1);
}
return s->stack [s->top -1];
}
//一条更伤心的分割线
void InitStack1(SeqStack1 *s)
{
s->top =0;
}
int StackEmpt1(SeqStack1 *s)
{
return s->top ==0;
}
void push1(SeqStack1 *s,ElemType1 x)
{
if(s->top ==Maxsize)
{printf("\n 栈已满,上溢!");
exit(1);
}
s->top ++;
s->stack [s->top -1]=x;
printf("(操作符入栈是'%c')\n",s->stack [s->top -1]);
}
ElemType1 pop1(SeqStack1 *s)
{
if(StackEmpt1(s))
{printf("\n 栈已空,下溢!");
exit(1);
}
ElemType1 t=s->stack [s->top -1];
printf("(操作符出栈是%c)\n",s->stack [s->top -1]);
s->top --;
return t;
}
ElemType1 GetTop1(SeqStack1 *s)
{ if(StackEmpt1(s))
{printf("\n 栈已空");
exit(1);
}
return s->stack [s->top -1];
}
//一条伤心的分割线
ElemType char2double(ElemType1 p[],int j)
{
double A=0,B=0,C=0;
A=p[j]-'0';
for(;j>=1;)
{
B=p[j-1]-'0';
--j;
//printf("[%f]",B);//B的值不对
A=A+B*pow(10,j+1);//?可能有问题 ,是否能倍数还是j、j+1
//printf("[%f]",A);
}
printf("[%f]",A);
return A;
}
ElemType1 Compare(ElemType1 X,ElemType1 Y )//X是当前,y是栈顶 ,X<=Y时x出栈参与运算
{
if (Y=='(')
{
printf("我返回>\n");
return '>';} //
if(Y==';')
{
printf("我返回>\n");
return '>';
}
if(X=='|')
{
printf("我返回e\n");
return 'e';
}//读到终止符了 仍然有问题21:08
if(X=='(')
{
printf("我返回>\n");
return '>';
}
if(X==')')
{
printf("我返回s\n");
return 's';
}
if(Y=='*'||Y=='/')
{
printf("我返回<\n");
return '<';
}
if((Y=='+'||Y=='-')&&(X=='+'||X=='-'))
{
printf("我返回=\n");
return '=';
}
if((Y=='+'||Y=='-')&&(X=='/'||X=='*'))
{
printf("我返回>\n");
return '>';
}
}
ElemType Operate(ElemType p,ElemType1 op,ElemType q)
{
ElemType JG;
switch(op)
{
case '+':JG=p+q; printf("《运算结果是%f》\n",JG);break;
case '-':JG=p-q;printf("《运算结果是%f》\n",JG);break;
case '*':JG=p*q;printf("《运算结果是%f》\n",JG);break;
case '/':JG=p/q;printf("《运算结果是%f》\n",JG);break;
}
return JG;
}
//很伤心呢
int main()
{
SeqStack1 CZF;
SeqStack YSS;
SeqStack1 *OPTR=&CZF;
SeqStack *OPND=&YSS;//optr操作符;opnd运算数
ElemType1 Bds[Maxsize],N[H],op,c,S,z;
ElemType d=0,b=0,v=0;
FILE *fp;
int i,j,t,o,m,e;
InitStack(OPND) ;
InitStack1(OPTR);
push1(OPTR,';');
if((fp=fopen("homework.txt","r"))==NULL)
{
printf("无法打开文件");
exit(0);
}
while(!feof(fp))
{
for(i=0;(Bds[i]=fgetc(fp))!='\n';i++)
{
printf("%c",Bds[i]); //可能有问题 ,赋值的问题 (已解决),一会记得恢复20:01,2022.0317
}//读入字符数组Bds[],表达式字符数组
for(j=0;Bds[j]!=' ';j++)
{
c=Bds[j];/*BDS现在存入了一个表达式,用另一个字符数组N[]存数字字符,当读到运算符时将N[]中数
字转化为 double型压入opnd,将运算符压入optr,并开始运算*/
if(c>='0'&&c<='9')//这里有问题????t没存进去 (****数存入有问题45存成了452)问题:最后一位3存不进去
{N[t]=c;
//printf("[%c]",N[t]);//除小括号识别有问题,其余都没问题
t++;//t当计数器
}
else
{
if(c!='('&&Bds[j-5]!='(')
//2022.3.17.可能有问题,存放一个临时值来替代gettop
{push(OPND,char2double(N,t-1) );
t=0;}//将N[]中字符串数字转数字 ,共有t个位数,压入optr
S=Compare(c,GetTop1(OPTR));
switch(S)//copmare函数 没进入switch?!严重问题
{
case '>':push1(OPTR,c);//之前的操作符没压入栈? 入栈仍有问题,只压入了开始的;!??!
break;
case '=':
case '<':
op=pop1(OPTR);
//a没压入栈
b=pop(OPND);//先弹 2
d=pop(OPND);//后弹 34计算34
v=Operate(d,op,b);//oprate函数
push(OPND,v);
push1(OPTR,c);
break;//将读到的操作符比较运算或入栈
case 's':op=pop1(OPTR);//-出栈
b=pop(OPND);
d=pop(OPND);
v=Operate(d,op,b);
push(OPND,v);//oprate函数
pop1(OPTR);
if(GetTop1(OPTR)=='(')
push(OPND,v);
break;
case 'e':while(GetTop1(OPTR)!=';')//栈底
{
op=pop1(OPTR);//到这一步停止了,栈已空下溢,optr的入栈问题
b=pop(OPND);//先弹 2
d=pop(OPND);//后弹 34计算34
v=Operate(d,op,b);//oprate函数
push(OPND,v);
}
push1(OPTR,';');
break;
//读完最后一个数字后,没有去计算站内存储的数字,而是读了下一个表达式,循环有误!!!!!
}
}
}
printf("\n 答案是=%f\n",pop(OPND));
// pop(OPND);
}
return 0;
}
\\学习心得:尝试手写代码,通过画图模拟运算过程,利用好调试手段,将运算流程打印输出可以事半功倍,学会建立函管理好变量名标识符用的太乱了自己理解不了2022/3/17.23:50
\学习心得:尝试手写代码,通过画图模拟运算过程,利用好调试手段,将运算流程打印输出可以事半功倍,学会建立函管理好变量名标识符用的太乱了自己理解不了2022/3/17.23:50