关于算术表达式的问题(关于栈)

ermoxin 2008-10-14 05:42:33
用单链表来求一个算术表达式:从键盘上任意输入一个算术表达式,要求得到正确的结果
例如输入:1+(3-5)*2=
要求输入这个表达式后,得到结果-3,其实就是一个进栈出栈的问题.
哪个知道,帮我用C语言代码写出来好吗?谢谢!
...全文
191 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
yayayaya123321 2010-12-13
  • 打赏
  • 举报
回复
写的好啊, 真的很受用。
xianyuxiaoqiang 2008-10-16
  • 打赏
  • 举报
回复
其实我做过一个完整的小编译器,不过在自己电脑里。现在在公司,没法给你看。
楼主还是自己动手吧,当初我也不是很会,做了大概两周。做完才发现自己能力提升很多。
楼主可以在我的基础上进行修正,相信会有很大收获。直接给你终结版怕误了你的前途……
xianyuxiaoqiang 2008-10-14
  • 打赏
  • 举报
回复
/********************************************
*文法规则集合
*E := '(' E ')' | E1
*E1:= E2 ( + E2 | - E2 |e)
*E2:= E3 ( * E3 | / E3 |e)
*E3:= '(' ( E ) ')'| NUM
*NUM := number
*为简单起见,仅仅支持正数
*********************************************/
#include <stdio.h>
#include <stdlib.h>
#define MAX 999999
#define DEBUG
struct node
{
char symbol;
int number;
node *next;
}root;
char comstr[100] = {0};
node *nextnode = NULL;
node *nextword = &root;

int E();
int E1();
int E2();
int E3();
void debug()
{
node *a = &root;
while(true)
{
if(a->next != NULL)
{
printf(" : %c\n", a->symbol);
a = a->next;
}
else break;
}
}


bool getnextword()
{
if(nextword->next!=NULL)
{
if(nextword->next->next != NULL)
{
nextword = nextword->next;
return true;
}
}
else
{
printf("End of input\n");
return false;
}
}
void deleteall(node * next)//删除链表释放内存
{
if(next->next!=NULL)
{
deleteall(next->next);
}
else
{
delete next;
}
}

/****************************
据文法规则产生函数E系列
****************************/
int E()
{
#ifdef DEBUG
printf("E\n");
#endif
int res = 0;
if(nextword->symbol == '(')
{
if(!getnextword())
{
exit(0);
}
res = E();
if(nextword->symbol == ')')
{
getnextword();
}
else
{
printf("syntax error! missing ')'\n");
exit(0);
}
}
else
{
res = E1();
}
return res;
}
int E1()
{
#ifdef DEBUG
printf("E1\n");
#endif
int res1 = 0, res2 = 0;
res1 = E2();
if(nextword->symbol == '+')
{
if(!getnextword())
{
exit(0);
}
res2 = E2();
return res1 + res2;
}
else if(nextword->symbol == '-')
{
if(!getnextword())
{
exit(0);
}
res2 = E2();
return res1 - res2;
}
else
{
return res1;
}
}
int E2()
{
#ifdef DEBUG
printf("E2\n");
#endif
int res1 = 0, res2 = 0;
res1 = E3();
if(nextword->symbol == '*')
{
if(!getnextword())
{
exit(0);
}
res2 = E3();
return res1 * res2;
}
else if(nextword->symbol == '/')
{
if(!getnextword())
{
exit(0);
}
res2 = E3();
if(res2 == 0)
{
printf("Error! devide 0 !\n");
exit(0);
}
return res1 / res2;
}
else
{
return res1;
}
}
int E3()
{
#ifdef DEBUG
printf("E3\n");
#endif
int res = 0;
if(nextword->symbol == '(')
{
if(!getnextword())
{
exit(0);
}
res = E();
if(nextword->symbol == ')')
{
getnextword();
return res;
}
else
{
printf("syntax error! missing ')'\n");
exit(0);
}
}
else if(nextword->symbol == 'n')
{
res = nextword->number;
getnextword();
return res;
}
}
/****************************
check用于产生单词链表
****************************/

int check(char * str, int len)
{
root.next = NULL;
nextnode = &root;
node *newnode = NULL;
int num = 0;
bool last_is_num = true;
for(int index = 0; index < len; ++index)
{
if(str[index] >= '0' && str[index] <= '9')
{
if(last_is_num)
{
num = 10 * num + str[index] - '0';
if(num > MAX)
{
printf("Too big number! %d\n", num);
return 0;
}
}
else
{
last_is_num = true;
num = str[index] - '0';

}
if(index == len -1)
{
newnode = new node;
nextnode->number = num;
nextnode->symbol = 'n';//数字标志
nextnode->next = newnode;
nextnode = newnode;
nextnode->next = NULL;
}
}
else
{
if(last_is_num)//检查到上次循环得到了数字
{
newnode = new node;
nextnode->number = num;
nextnode->symbol = 'n';//数字标志
num = 0;
last_is_num = false;
nextnode->next = newnode;
nextnode = newnode;
nextnode->next = NULL;
}
newnode = new node;
nextnode->symbol = str[index];
nextnode->next = newnode;
nextnode = newnode;
nextnode->next = NULL;
}
}

return 1;
}
int main()
{
printf("Please input the sentense ,end with'='(No more than 100 bytes):\n");
char input = 0;
int len = 0;
while(scanf_s("%c", &input))
{
if(input == '=')
{
break;
}
else if(input >= '0' && input <= '9' || input == '+' || input == '-' || input == '*' || input == '/' || input == '(' || input == ')')
{
comstr[len] = input;
++len;
if(len > 98)
{
printf("Too long sentense!\n");
return 0;
}
}
else if(input == 0x09 || input == ' ' || input == 0x0d || input == 0x0a)
{
}
else
{
printf("Invalid input: %d\n", input);
return 0;
}
}
if(len == 0)
{
printf("No input\n");
return 0;
}
else
{
comstr[len] = '\0';
//printf("%s", comstr);
}
if(check(comstr, len) == 0)
{
printf("Invalid sentense\n");
exit(0);
}
else
{
printf("result: %s = %d\n",comstr, E());
#ifdef DEBUG
debug();
printf("len is %d\n", len);
#endif
if(root.next != NULL)
{
deleteall(root.next);
}
}
}

还有些bug,有时间再调试了。
pingzi_1119 2008-10-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zmlovelx 的回复:]
中缀表达式到后缀表达式的转换
  要把表达式从中缀表达式的形式转换成用后缀表示法表示的等价表达式,必须了解操作符的优先级和结合性。优先级或者说操作符的强度决定求值顺序;优先级高的操作符比优先级低的操作符先求值。如果所有操作符优先级一样,那么求值顺序就取决于它们的结合性。操作符的结合性定义了相同优先级操作符组合的顺序(从右至左或从左至右)。
转换过程包括用下面的算法读入中缀表达式的操作数、操作符…
[/Quote]
这位大哥写的一看就像很有道理!
frank_ll 2008-10-14
  • 打赏
  • 举报
回复
看不懂
帮顶贴
chlaws 2008-10-14
  • 打赏
  • 举报
回复
论坛上搜搜 已经有很多了
mifeixq 2008-10-14
  • 打赏
  • 举报
回复
逆波兰表达式

1+(3-5)*2
135-2*+
帅得不敢出门 2008-10-14
  • 打赏
  • 举报
回复
中缀表达式到后缀表达式的转换
  要把表达式从中缀表达式的形式转换成用后缀表示法表示的等价表达式,必须了解操作符的优先级和结合性。优先级或者说操作符的强度决定求值顺序;优先级高的操作符比优先级低的操作符先求值。如果所有操作符优先级一样,那么求值顺序就取决于它们的结合性。操作符的结合性定义了相同优先级操作符组合的顺序(从右至左或从左至右)。
转换过程包括用下面的算法读入中缀表达式的操作数、操作符和括号:
1. 初始化一个空堆栈,将结果字符串变量置空。
2. 从左到右读入中缀表达式,每次一个字符。
3. 如果字符是操作数,将它添加到结果字符串。
4. 如果字符是个操作符,弹出(pop)操作符,直至遇见开括号(opening parenthesis)、优先级较低的操作符或者同一优先级的右结合符号。把这个操作符压入(push)堆栈。
5. 如果字符是个开括号,把它压入堆栈。
6. 如果字符是个闭括号(closing parenthesis),在遇见开括号前,弹出所有操作符,然后把它们添加到结果字符串。
7. 如果到达输入字符串的末尾,弹出所有操作符并添加到结果字符串。

后缀表达式求值
  对后缀表达式求值比直接对中缀表达式求值简单。在后缀表达式中,不需要括号,而且操作符的优先级也不再起作用了。您可以用如下算法对后缀表达式求值:
1. 初始化一个空堆栈
2. 从左到右读入后缀表达式
3. 如果字符是一个操作数,把它压入堆栈。
4. 如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
5. 到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
具体看此贴,直接有代码了
http://www.zxbc.cn/html/20070423/7312.html
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 chlaws 的回复:]
论坛上搜搜 已经有很多了
[/Quote]
up
ermoxin 2008-10-14
  • 打赏
  • 举报
回复
算法的思想我都知道
可是,问题是不会写代码?楼上的大哥,可以速度点修改你的代码吗?
我需要正确的代码,不需要调试的代码,谢谢了

69,373

社区成员

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

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