c语言实现四则运算,并指出错误点

qqzj532008274 2011-03-16 02:25:14
试用C语言编写程序,实现四则运算算式的计算:
要求:
1. 键盘输入四则运算表达式,回车后自动返回计算结果
2. 四则运算表达式由数字和运算符组成,数字为实数,运算符包括+ - * / ( ),四则运算表达式总允许有空格。
3. 如果四则运算算式有错误,应指出第一个错误字符所在的位置
4. 输入任何错误的算式,不会导致程序错误

例如:
输入: 2 *(4/8+3*9*(568-234 ))+0.765
屏幕输出:=18037.765

输入: 2*(4/+3*9*(568-234)))+0.765
屏幕输出:err 21
注:以上输出err 21, 表示字符串第21个字符有错误



我能够用栈的知识实现四则运算,但是我没有什么方法实现找出错误点的第多少个字符。
...全文
1074 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
luciferisnotsatan 2011-04-08
  • 打赏
  • 举报
回复
你可以先检测下输入是否有问题,然后再用栈来做四则运算。也就是解析两次,一次差错,一次求解
liuyi_15 2011-04-08
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zhouming1318 的回复:]
一下是我的代码,用到了栈的思想,但是我 当时写的时候没 考虑错误要输出,楼主可以稍加修改
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define Size 100
#define initsize 10
typedef struct
{
char *top;
char *……
[/Quote]
左括号和右括号的优先级有错误
愤怒的熊猫007 2011-03-16
  • 打赏
  • 举报
回复
一下是我的代码,用到了栈的思想,但是我 当时写的时候没 考虑错误要输出,楼主可以稍加修改
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define Size 100
#define initsize 10
typedef struct
{
char *top;
char *base;
int size;
}Sqchar;
typedef struct
{
double *top;
double *base;
int size;
}Sqdouble;
typedef struct
{
char c;
int mark;
}oper;
void initdouble(Sqdouble &opnd);
void initchar(Sqchar &optr);
void pushchar(Sqchar &optr, char e);
void pushdouble(Sqdouble &opnd, double e);
void popchar(Sqchar &optr, char &e);
void popdouble(Sqdouble &opnd, double &e);
char gettopchar(Sqchar optr);
double gettopdouble(Sqdouble opnd);
double operate(double a1, char x, double a2);
int precde(char a, char b);
char Gchar(char *&a, char e);
double conter();
int in(char c);
void main()
{
double a;
a = conter();
printf("%f", a);
}
void initdouble(Sqdouble &opnd)
{//建立运算符的栈
opnd.base = (double *) malloc (Size * sizeof(double));
opnd.top = opnd.base;
opnd.size = Size;
}//initdouble
void initchar(Sqchar &optr)
{//建立运算符的栈
optr.base = (char *) malloc (Size * sizeof(char));
optr.top = optr.base;
optr.size = Size;
}//initchar
void pushchar(Sqchar &optr, char e)
{
if((optr.top - optr.base) >= optr.size)
{
optr.base = (char *) realloc (optr.base,(optr.size + initsize ) * sizeof(char));
optr.size += initsize;
}
*optr.top = e;
optr.top++;
}//pushchar
void pushdouble(Sqdouble &opnd, double e)
{
if((opnd.top - opnd.base) >= opnd.size)
{
opnd.base = (double *) realloc (opnd.base,(opnd.size + initsize ) * sizeof(double));
opnd.size += initsize;
}
*opnd.top = e;
opnd.top++;
}//pushdouble
void popchar(Sqchar &optr, char &e)
{//e为返回删除值
if(optr.base != optr.top)
{
optr.top--;
e = *optr.top;
}//if
}//popchar
void popdouble(Sqdouble &opnd, double &e)
{//e为返回删除值
if(opnd.base != opnd.top)
{
opnd.top--;
e = *opnd.top;
}//if
}//popdouble

char gettopchar(Sqchar optr)
{
char e;//存放top的值
if(optr.top != optr.base)
{
e = *(optr.top - 1);
return (e);
}
}//gettopchar

double gettopdouble(Sqdouble opnd)
{
double e;//存放top的值
if(opnd.top != opnd.base)
{
e = *(opnd.top - 1);
return (e);
}
}//gettopdouble

double conter()
{
Sqchar optr;//建立一个存放运算符的栈
Sqdouble opnd;//建立一个存放数的栈
char c;// 用于输入算数式
char *a;//建立一动态字符串把转化成数字
double b;//把输入的字符转化为数字用
char x;//接受 返回的运算符
double a1;//接受运算的数1
double a2;//接受运算的数2
initchar (optr);
initdouble (opnd);
pushchar(optr, '=');
c = getchar();
while(c != '=' || gettopchar(optr) != '=')
{
if(in(c))//未解决不理解书上op的意思 有问题
{
c = Gchar(a, c);
b = atof(a);
pushdouble(opnd, b);
}//if
else
{
switch(precde(gettopchar(optr), c))
{
case 1:
{
pushchar(optr, c);
c = getchar();
break;
}
case 2:
{
popchar(optr, x);
c = getchar();
break;
}
case 3:
{
popchar (optr, x);
popdouble(opnd, a2);
popdouble(opnd, a1);
pushdouble(opnd, operate(a1, x, a2));//为解决
break;
}
case 4:
{
printf("有错误请检查后重新输入\n");
}
}
}//else

}//while
return (gettopdouble(opnd));

}
int precde(char a, char b)
{//优先级a<b返回1 a=b 返回2 大于返回3 不成立返回 4
int a1;//用于保存a1运算符的优先级
int b1;//用于保存a2运算符的优先级
int i;//用于循环
oper H[7]= {{'+',3}, {'-', 3}, {'*', 2}, {'/', 2}, {'(', 5}, {')', 1}, {'=', 4}};
for(i = 0; i <= 6; i++)
{
if(a == H[i].c)
{
a1 = H[i].mark;
break;
}
}//for
for(i = 0; i <= 6; i++)
{
if(b == H[i].c)
{
b1 = H[i].mark;
break;
}
}//for
if(a=='(' && b==')')
{
return 2;
}
if(b == '(')
{
return 1;
}
if(b == ')')
{
return 3;
}
if((a == '(' && b == '=')||
(a == ')' && b == '(')||
(a == '=' && b == ')'))
{
return 4;
}//if
else
{
if(a1 >= b1)
{
return 1;
}
else if((a == '('&& b == ')')
||a == '=')
{
return 2;
}
else if(a1 < b1)
{
return 3;
}
}
}//precde
double operate(double a1, char x, double a2)
{//对式子进行计算
double cost;//存放运算结果
switch (x)
{
case '+':
{
cost = a1 + a2;
break;
}
case '-':
{
cost = a1 - a2;
break;
}
case '*':
{
cost = a1 * a2;
break;
}
case '/':
{
cost = a1 / a2;
break;
}
}
return (cost);
}//operate
int in(char c)
{//为数返回0 为运算符返回1
if(c != '+'&&
c != '-'&&
c != '*'&&
c != '/'&&
c != '('&&
c != ')'&&
c != '=')
{
return 1;
}
else
{
return 0;
}

}
char Gchar(char *&a, char e)
{//动态建立一个字符串a[n]
char *newbase;
char c;
int n;
n = 2;
a = (char *) malloc (n * sizeof(char));
a[0] = e;
c = getchar();
while((c == '0')||
(c == '1')||
(c == '2')||
(c == '3')||
(c == '4')||
(c== '5')||
(c == '6')||
(c == '7')||
(c == '8')||
(c == '9'))
{
newbase = (char *) realloc (a, (n+1) * sizeof(char));
a = newbase;
n++;
a[n-2] = c;
c = getchar();
}//while
a[n-1] = '\0';
return (c);
}
qqzj532008274 2011-03-16
  • 打赏
  • 举报
回复
我这个地方实现不了

屏幕输出:err 21
注:以上输出err 21, 表示字符串第21个字符有错误

这21怎么才能够整出来啊?
不胜感激
qqzj532008274 2011-03-16
  • 打赏
  • 举报
回复
我的源代码是这样的
#if !defined CALCULATE_H
#define CALCULATE_H

/*
FourOperations类主要用于四则运算的操作
*/
#include <stdio.h>
#include <stdlib.h>
#include <string>

struct FourOperations
{
public:
FourOperations();
//计算表达式
bool calculate(double &result, const char *s);
//得出错误点
void error(char n);
//得出相邻运算符之间运算符的优先级
char GetOrder(char a, char b);
//对数字压栈操作
bool NumPush(const char &a);
//对数字出栈操作
bool NumPop(char &a);
//对算术表达式压栈操作
bool OpePush(const char &a);
//对算术表达式出栈操作
bool OpePop(char &a);
//根据两个数字和运算符进行运算
double arithmeticaloperation(double &First,double &Second,char CluteChar);
//取出相邻的两个数
bool GetAdjacentNumber(double &First,double &Second);
//判断输入的四则运算表达式是否合法
bool JugeLegal(const char *s);
private:
int Operstore,Numstore; //用来标记数字栈和字符栈中元素的个数
char ope[100]; //算术运算符栈
char num[100]; //数字栈
int errornumber; //错误点
};
#endif






#include "calculate.h"

/***
构造函数
*/
FourOperations::FourOperations()
{
//对数据初始化
Operstore=0;
Numstore=0;
errornumber=0;
};
/***
数字压栈操作
*/
bool FourOperations::NumPush(const char &Nm)
{
/*如果栈里元素个数大于100个就返回*/
if (Numstore>=100)
{
return false;
}else{
num[Numstore++]=Nm;
return true;
}
}
/***
数字出栈操作
*/
bool FourOperations::NumPop(char &Nm)
{
/*如果栈里元素个数等于0就返回*/
if (Numstore==0)
{
return false;
}else{
Nm=num[--Numstore];
return true;
}
}
/***
算术表达式入栈操作
*/
bool FourOperations::OpePush(const char &Op)
{
/*如果栈里元素个数大于100个就返回*/
if (Operstore>=100)
{
return false;
}else{
ope[Operstore++]=Op;
return true;
}
}
/***
算术表达式出栈操作
*/
bool FourOperations::OpePop(char &Op)
{
/*如果栈里元素个数等于0就返回*/
if (Operstore==0) {
return false;
}else{
Op=ope[--Operstore];
return true;
}
}

/***
本函数根据两个相邻的数和四则运算法则进行四则运算
*/
double FourOperations::arithmeticaloperation(double &First,double &Second,char CluteChar)
{
double Result;
switch (CluteChar)
{
case '+': Result=First+Second; break;
case '-': Result=First-Second; break;
case '*': Result=First*Second; break;
case '/': Result=First/Second; break;
default :
break;
}
return Result;
}
/***
取出运算符相邻的两个元素
*/
bool FourOperations::GetAdjacentNumber(double &First,double &Second)
{
char szA[50];
int i=0;
bool PopSuccess; //用来判断出栈是否成功
if (Numstore==0)
{
error('\4'); //num栈已空
return false;
}
NumPop(szA[i]);
//获取当前数字字符
do NumPop(szA[i]);
while (szA[i++]!=',');
szA[--i]='\0';
strrev(szA);
Second=atof(szA);
//从num栈中获取第二个操作数
i=0;
if (Numstore==0)
{
error('\3'); //num栈已空
return false;
}
//获取前一数字字符
do PopSuccess=NumPop(szA[i]);
while (szA[i++]!=',' && PopSuccess);
if (PopSuccess) NumPush(',');
szA[--i]='\0';
//颠倒数字字符
strrev(szA);
First=atof(szA); //把字符串转换成浮点数
return true;
}

/***
本函数用于优先级和输入是否正确判断
*/
bool FourOperations::calculate(double &result, const char *s)
{
char CluteChar,szA[50],order;
int i;
double FirstNum, SecondNum, ResultNum;
Operstore=Numstore=0; //清空ope栈和num栈
OpePush('\0');

do
{
//如果为数字,则把数字字符压入栈中
if (*s>='0' && *s<='9' || *s=='.')
{
do
{
NumPush(*s++);
errornumber++;

}
while (*s>='0' && *s<='9' || *s=='.');
NumPush(','); //用于分隔字符串
}

//如果为算术运算操作符符,则进行优先级的运算,并压栈操作
else
{
OpePop(CluteChar);

switch (order=GetOrder(CluteChar, *s))
{
//后面的运算符级别高于前面运算符
case '0':
{
OpePush(CluteChar);
OpePush(*s++);
errornumber++;
if (*s=='+')
{
s++;
errornumber++;
}
/*如果为减号,把减号压入运算符栈。数字0压入数字栈,
并用逗号隔开,主要目的是用于减去负数*/
else if (*s=='-')
{
s++;
errornumber++;
OpePush('-');
NumPush('0');
NumPush(',');
}
break;
}


//后面的运算符级别低于前面的运算符
case '1':
{
//取出跟运算符相邻的两个元素
if(!(GetAdjacentNumber(FirstNum,SecondNum)))
{
return false;
}
//根据相邻的两个数和运算符进行运算
if(!(ResultNum=arithmeticaloperation(FirstNum,SecondNum,CluteChar)))
{
return false;
}

gcvt(ResultNum, 16, szA); //把浮点数转换成字符串
i=strlen(szA)-1;
if (szA[i]=='.') szA[i]='\0';

//把计算结果压入栈
i=0;
do NumPush(szA[i]);
while (szA[++i]!='\0');
NumPush(',');
}
break;
//‘=’表示相邻两个运算符的优先级别相同
case '=':
{
s++;
errornumber++;
}
break;
default:
{
//得出错误信息
error(order);
return false;
break;
}
}
}
}while (Operstore!=0);
result=atof(num); //字符转换成浮点类型
return true;
}
/***
得出错误信息
*/
void FourOperations::error(char n)
{
switch (n)
{
case '\1': printf("括号不匹配,%d\n",errornumber); break;
case '\2': printf("右括号与左括号间没有运算符,%d\n",errornumber); break;
case '\3': printf("运算符过多,%d\n",errornumber);
}
}
/***
用于得出优先级的顺序,a代表当前前一位的运算符,b代表当前的运算符
*/
char FourOperations::GetOrder(char a, char b)
{
/*
以下数组用来得出栈的优先顺序,'1'代表前面的运算符优先级别高,
'0'代前面的运算符表优先级别低.
'\1''\2'分别代表不同的错误
*/
static char order[7][7]={
'1','1','0','0','0','1','1',
'1','1','0','0','0','1','1',
'1','1','1','1','0','1','1',
'1','1','1','1','0','1','1',
'0','0','0','0','0','=','\1',
'1','1','1','1','\2','1','1',
'0','0','0','0','0','\1','='
};
int Ord[2], j=0;
/*得出当前运算符和前一个运算符所在数组order的行列*/
for(int i=0;i<2;i++)
{
switch (a)
{
case '+': Ord[j]=0; break;
case '-': Ord[j]=1; break;
case '*': Ord[j]=2; break;
case '/': Ord[j]=3; break;
case '(': Ord[j]=4; break;
case ')': Ord[j]=5; break;
case '\0': Ord[j]=6; break;
default: return '\0';
}
j++;
a=b;
}
//返回优先级别及错误信息
return order[Ord[0]][Ord[1]];
}

/***
判断输入法是否合格
*/
bool FourOperations::JugeLegal(const char *strinput)
{
int i=0;
for(;i<strlen(strinput);i++)
{
if(!((strinput[i]<='9'&&strinput[i]>='0')||
strinput[i]=='+'||strinput[i]=='-'||
strinput[i]=='*'||strinput[i]=='/'||
strinput[i]=='('||strinput[i]==')'))
{
printf("你输入的不符合四则运算表达式字符,请从新输入\n");
return false;
}
}
return true;

}
int main()
{
FourOperations FOper;
bool YorNSuss;
//用于存储结果
double result;
//储存输入的字符,最大能够输入一百个字符
printf("请输入算术表达式,字符不能够多于一百个\n");
char strinput[100];
while(gets(strinput))
{
//判断是否多于一百个字符
if(100<strlen(strinput))
{
printf("你输入的字符大于一百个\n");
return -1;
}
//判断输入的四则运算符是否合格
YorNSuss=FOper.JugeLegal(strinput);
if(YorNSuss)
{
//根据输入的表达式,算出结果
YorNSuss=FOper.calculate(result, strinput);
if (YorNSuss)
printf("%lg\n", result);
}
}
return 0;
}



帮我一下,

我这点实现不了

fengzhw 2011-03-16
  • 打赏
  • 举报
回复
在token解析的时候,记录下单词的位置信息,同时解析的时候就有可能报告一次错误。
表达式的错误往往出在栈不平衡的时候,例如该有数没有数,或者该有封闭括号却是个别的等等。
这时候,你就直接把栈顶单词的位置当作错误位置报告出来就行了。

这个问题一定要用栈处理,将来可以变得更强大。

用递归临时解决问题不难,以后想扩充可难了。
taohuirong 2011-03-16
  • 打赏
  • 举报
回复
这个用不着栈
lx3275852 2011-03-16
  • 打赏
  • 举报
回复
看起来挺难得。。。得来一个很犀利的递归。。。。。。
或者得用栈了。。。。。

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧