C/C++的题目:算术表达式求值

fiterby 2010-04-14 08:54:23
小米终于快小学毕业了,小米的小学毕业论文是解不含未知数的算术表达式。
老师给他的样例非常多,而且式子很长,老师还给小米 4 个规则:
1.a+b 代表a+2*b;
2.a-b 代表 a-3*b;
3.全部运算满足右结合性,如:a+b+c=a+2*(b+2*c);
4.小括号的优先级大于中括号。
小米不想把时间浪费在单调而又无趣的计算上,所以他请你帮他写一个程序,他的要
求很简单,就是他输入一组数据,就能立刻得到答案。
现给你一个算术表达式,对于每个式子输出一个数,表示该表达式的解。
★数据输入
输入只有一行,给你一个算术表达式,式子中只含有数字,‘+’、‘-’、‘(’、‘)’、‘[’、‘]’,长度不超过 10000,式子中的数均不为负,保证数据合法,输入的值以及结果都为 int型整数。
★数据输出
输出式子的运算结果!

输入示例 输出示例
(34+28+28)+[(7+8)-(9+10)] 74
...全文
530 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
fiterby 2010-04-24
  • 打赏
  • 举报
回复
谢谢啊,你还特地写了,但是我们有十个测试点。。。那个数据只是个范例而已。。。
mLee79 2010-04-15
  • 打赏
  • 举报
回复
偶在上面个帖子4楼的应该是符合要求地, 你把这个交上去, 然后跟老师一起探讨下编译原理/下推自动机/形式文法等等内容:
$ ( function x() { echo ------ $* ------- ; $* ; } ;\
x cat Xexpr.y ;x bison Xexpr.y -o Xexpr.c ; \
x gcc -o Xexpr Xexpr.c ; echo "(34+28+28)+[(7+8)-(9+10)]" | ./Xexpr ) | tee result
------ cat Xexpr.y -------
%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define YYPARSE_PARAM yyparam
#define YYLEX_PARAM yyparam

typedef struct yyparam_t yyparam_t;
struct yyparam_t
{
char* X_input;
int result;
};

int yylex( int *yylval_ , yyparam_t* param );

void yyerror( const char* msg )
{
fprintf( stderr , "[ERROR]%s\n" , msg );
}

%}
%pure_parser
%token XNUM

%right '+' '-'
%%
goal:
expr { ((yyparam_t*)YYPARSE_PARAM)->result = $$; }
;
expr:
XNUM
|
expr '+' expr { $$ = $1 + 2 * $3 ; }
|
expr '-' expr { $$ = $1 - 3 * $3 ; }
|
'(' expr ')' { $$ = $2 ; }
|
'[' expr ']' { $$ = $2 ; }
;
%%

int yylex( int *yylval_ , yyparam_t* param )
{
while( isspace( *param->X_input ) )
++param->X_input;

if( 0 == *param->X_input )
return 0;

if( !isdigit( *param->X_input ) )
return *param->X_input++;

*yylval_ = strtol( param->X_input , ¶m->X_input , 0 );
return XNUM;
}

int main()
{
yyparam_t param;
char line[1024+1] = "";
while( fgets( line , 1024 , stdin ) )
{
param.X_input = line;
if( 0 == yyparse( ¶m ) )
{
printf( "%d\n" , param.result );
}
}
return 0;
}
------ bison Xexpr.y -o Xexpr.c -------
------ gcc -o Xexpr Xexpr.c -------
74

o笨笨猪o 2010-04-15
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 fiterby 的回复:]
我还真想拒绝。。。但是这算平时成绩啊啊啊啊!大家都6分我就1分,那就亏打了。。。
[/Quote]
无语。。。。
你可以参考一下这个帖子:
http://topic.csdn.net/u/20100412/21/b39c50b9-caeb-406f-a12e-023e088c78c9.html
fiterby 2010-04-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 turntogo 的回复:]
到这里去看看吧,呵呵别笑我,这是我上传的资源,这是源代码呀:
http://d.download.csdn.net/down/315802/Turntogo
[/Quote]
谢谢啊,等我下课了再好好看看,到时候再给你评价~
星光伴月 2010-04-15
  • 打赏
  • 举报
回复
嗯,老师太黑了,也太狠了,还有点太过分了!
fiterby 2010-04-15
  • 打赏
  • 举报
回复
我还真想拒绝。。。但是这算平时成绩啊啊啊啊!大家都6分我就1分,那就亏打了。。。
o笨笨猪o 2010-04-15
  • 打赏
  • 举报
回复
这个涉及到编译技术的课程,如果没有学过,你可以拒绝做这次作业。
星光伴月 2010-04-15
  • 打赏
  • 举报
回复
到这里去看看吧,呵呵别笑我,这是我上传的资源,这是源代码呀:
http://d.download.csdn.net/down/315802/Turntogo
fiterby 2010-04-15
  • 打赏
  • 举报
回复
是一个学校的。
数据结构的作业。。。拿到我就傻了。。。
o笨笨猪o 2010-04-15
  • 打赏
  • 举报
回复
你这是作业还是什么?如果是新手的话,老师也不可能出这样难度的作业。
mLee79 2010-04-15
  • 打赏
  • 举报
回复
你们同一个学校的么:
http://topic.csdn.net/u/20100412/18/adc79bc4-7c01-4e2f-8fa0-6d44a99f651d.html
fiterby 2010-04-15
  • 打赏
  • 举报
回复
我有想过一些方法,就是不知道怎么才能实现。。。。
要把式子都变成逆波兰式么,然后再压到栈里?关键就来了。。。。怎么实现中缀式变成逆波兰式。。。?
o笨笨猪o 2010-04-15
  • 打赏
  • 举报
回复
其实这个问题没有那么复杂,将它抽象一下,其实就是求:
left + right
而且题目说明了不用考虑异常输入,所以就可以变得简单得多:
#include <iostream>
#include <string>
#include <locale>
#include <sstream>


class RightExpressionEvaluator {
public:
explicit RightExpressionEvaluator(std::istream& input) : input(input) {
}

int evaluate() {
return evaluateLeftOperand() + evaluateRightOperand();
}

private:
int evaluateLeftOperand() {
return readNextToken() ? parseLeftOperand() : 0;
}

int parseLeftOperand() {
if (isOpenBracket(token)) {
return evaluate();
}
else if (isDigit(token)) {
return readNextInteger();
}
return 0;
}

int evaluateRightOperand() {
return readNextToken() ? parseRightOperand() : 0;
}

int parseRightOperand() {
switch (token) {
case '+': return 2 * evaluate();
case '-': return -3 * evaluate();
}
return 0;
}

int readNextInteger() {
int result = 0;
input.unget();
input >> result;
return result;
}

bool readNextToken() {
return input.get(token).good();
}

bool isOpenBracket(char token) {
return token == '(' || token == '[';
}

bool isDigit(char token) {
return std::isdigit(token, std::locale());
}

private:
std::istream& input;
char token;
};


void testEvaluator(const std::string& expression) {
std::istringstream input(expression);
std::cout << "expression: " << expression << std::endl;
std::cout << "value : " << RightExpressionEvaluator(input).evaluate() << std::endl;
std::cout << std::endl;
}

int main() {
testEvaluator("2");
testEvaluator("2+2");
testEvaluator("2-2");
testEvaluator("2-(2+2)");
testEvaluator("2-[2+2]");
testEvaluator("(2-2)+(2+2)");
testEvaluator("[2-2]-(2+2)");
testEvaluator("(34+28+28)+[(7+8)-(9+10)]");
}
fiterby 2010-04-15
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 wanyouzhu 的回复:]
引用 9 楼 fiterby 的回复:
我还真想拒绝。。。但是这算平时成绩啊啊啊啊!大家都6分我就1分,那就亏打了。。。

无语。。。。
你可以参考一下这个帖子:
http://topic.csdn.net/u/20100412/21/b39c50b9-caeb-406f-a12e-023e088c78c9.html
[/Quote]
如果是(a+b+c)这样的式子要怎么处理?右结合性,也就是a+b+c=a+(b+c)
lcfan123 2010-04-14
  • 打赏
  • 举报
回复
做出这个需要时间
  • 打赏
  • 举报
回复
UP

纠结的说

33,321

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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