求问用C语言去解析公式,提取所有变量的运算符号,例如a-(b+(d-e)+f)

hollin1988 2014-02-19 08:31:02
例如a-(b+(d-e)+f),,,那么a的符号是+号,b的符号是-号,e的符号是+号,给任意公式,都能自动解析出所有符号,求大神,本菜鸟想了3天都没想出方法。。。。
...全文
659 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
baihacker 2014-02-23
  • 打赏
  • 举报
回复
引用 10 楼 hollin1988 的回复:
[quote=引用 4 楼 baihacker 的回复:] 1.递归下降生成语法树。 2.遍历语法树。 或者 在递归下降生成语法树的同时维护符号信息,然后遇到一个结点就根据从上而下维护的符号信息知道 对应的符号了。 用一个struct Node来表示语法树的结点,Node可以表示一个变量,比如a,b,c。 另外Node还可以是一个运算符:加法运算或减法运算,这个时候Node有两个指针Node* l, *r, 表示参运算的结点。
char buff[1024]; // 需要解析的表达式
int curr; // 当前解析位置
Node* parse1();
Node* parse0()
{
  Node* ret = parse1(curr);
  while (buff[curr] == '+' || buff[curr] == '-')
  {
    根据buff[curr]生成结点x,x的左子树是ret,右结点通过调用parse1()生成。
    ret = x;
  }
  return ret;
}
Node* parse1()
{
  if (buff[curr] == '(')
  {
    Node* ret = parse0();
    ++curr;
    return ret;
  }
  else if (buff[curr] 是字母)
  {
   生成一个变量结点并返回
  }
  return NULL; // 出错了
}
这样,生成的一定是一个二叉树,内部结点是+或-,叶子结点是变量。 从根到叶子结点的路径上会有若干个+或-,可以计算出变量前的符号。 显然,可以引入一个参数来描述这若干个+或-,不用生成语法树就可以完成解析。
你这程序略复杂啊,没看懂 a+b-(c+(a-(d+e+(f-a))+m),这个通过你程序正常解析出来了没?解析出来就万分感谢,分数就送上了[/quote] 这个是一般的递归下降解析,即使有乘除法,甚至很多一般的语法都没有问题。 但是应用于你的问题还有很多更简单的方法,如9楼所说。
hollin1987 2014-02-23
  • 打赏
  • 举报
回复
引用 9 楼 misakamm 的回复:
来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b,初始都是0 要确定f的符号,从f向前一个一个字符扫描,如果遇到-号,同时b为0,那么s = 1 - s 如果遇到)号,那么b++ 遇到(号,那么b-- 扫描完以后,s为0就是正,s为1就是负
你这个思路我明白了,确实可以实现,我懂了:应该是变量的符号决定s的值,正是0,负数是1,然后每到一个(号判断,他跟前面遍历的)号是否匹配,如果匹配,那么(号前面的值不影响的s值,如果(号的数目>)号的数目,每到(号,并且(号前面的符号是负号,那么s=1-s,如此循环遍历完整个字符串,就取出来变量的值
hollin1987 2014-02-22
  • 打赏
  • 举报
回复
引用 9 楼 misakamm 的回复:
来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b,初始都是0 要确定f的符号,从f向前一个一个字符扫描,如果遇到-号,同时b为0,那么s = 1 - s 如果遇到)号,那么b++ 遇到(号,那么b-- 扫描完以后,s为0就是正,s为1就是负
而且根据你这个判断。f是正吧,第一个负号的时候,b=1,s=0不变,第二个-号,b=-1,s=0不变,所以s=0的值始终没变,判断出来f是正,这明显错了吧。还是我理解错了啊?
hollin1988 2014-02-22
  • 打赏
  • 举报
回复
引用 9 楼 misakamm 的回复:
来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b,初始都是0 要确定f的符号,从f向前一个一个字符扫描,如果遇到-号,同时b为0,那么s = 1 - s 如果遇到)号,那么b++ 遇到(号,那么b-- 扫描完以后,s为0就是正,s为1就是负
我现在做的程序解析带1个括号的是没问题的,基本也是按这种方法的,但是多层的,怎么确定括号的范围,怎么保留每层括号外面的符号,怎么判断变量在那个括号范围内,没有理清楚里面的思路
hollin1988 2014-02-22
  • 打赏
  • 举报
回复
引用 5 楼 derekrose 的回复:
使用递归
我也知道用递归,就是不知道怎么去写,方法之类的我也很清楚。。。
hollin1988 2014-02-22
  • 打赏
  • 举报
回复
引用 4 楼 baihacker 的回复:
1.递归下降生成语法树。 2.遍历语法树。 或者 在递归下降生成语法树的同时维护符号信息,然后遇到一个结点就根据从上而下维护的符号信息知道 对应的符号了。 用一个struct Node来表示语法树的结点,Node可以表示一个变量,比如a,b,c。 另外Node还可以是一个运算符:加法运算或减法运算,这个时候Node有两个指针Node* l, *r, 表示参运算的结点。
char buff[1024]; // 需要解析的表达式
int curr; // 当前解析位置
Node* parse1();
Node* parse0()
{
  Node* ret = parse1(curr);
  while (buff[curr] == '+' || buff[curr] == '-')
  {
    根据buff[curr]生成结点x,x的左子树是ret,右结点通过调用parse1()生成。
    ret = x;
  }
  return ret;
}
Node* parse1()
{
  if (buff[curr] == '(')
  {
    Node* ret = parse0();
    ++curr;
    return ret;
  }
  else if (buff[curr] 是字母)
  {
   生成一个变量结点并返回
  }
  return NULL; // 出错了
}
这样,生成的一定是一个二叉树,内部结点是+或-,叶子结点是变量。 从根到叶子结点的路径上会有若干个+或-,可以计算出变量前的符号。 显然,可以引入一个参数来描述这若干个+或-,不用生成语法树就可以完成解析。
你这程序略复杂啊,没看懂 a+b-(c+(a-(d+e+(f-a))+m),这个通过你程序正常解析出来了没?解析出来就万分感谢,分数就送上了
  • 打赏
  • 举报
回复
来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b,初始都是0 要确定f的符号,从f向前一个一个字符扫描,如果遇到-号,同时b为0,那么s = 1 - s 如果遇到)号,那么b++ 遇到(号,那么b-- 扫描完以后,s为0就是正,s为1就是负
  • 打赏
  • 举报
回复
你确定只有+-号和括号?如果是的话那灰常容易,一遍分析就出结果了
CyberLogix 2014-02-20
  • 打赏
  • 举报
回复
编译原理中的波兰树语法分析树问题,呵呵
derekrose 2014-02-19
  • 打赏
  • 举报
回复
使用递归
baihacker 2014-02-19
  • 打赏
  • 举报
回复
1.递归下降生成语法树。 2.遍历语法树。 或者 在递归下降生成语法树的同时维护符号信息,然后遇到一个结点就根据从上而下维护的符号信息知道 对应的符号了。 用一个struct Node来表示语法树的结点,Node可以表示一个变量,比如a,b,c。 另外Node还可以是一个运算符:加法运算或减法运算,这个时候Node有两个指针Node* l, *r, 表示参运算的结点。
char buff[1024]; // 需要解析的表达式
int curr; // 当前解析位置
Node* parse1();
Node* parse0()
{
  Node* ret = parse1(curr);
  while (buff[curr] == '+' || buff[curr] == '-')
  {
    根据buff[curr]生成结点x,x的左子树是ret,右结点通过调用parse1()生成。
    ret = x;
  }
  return ret;
}
Node* parse1()
{
  if (buff[curr] == '(')
  {
    Node* ret = parse0();
    ++curr;
    return ret;
  }
  else if (buff[curr] 是字母)
  {
   生成一个变量结点并返回
  }
  return NULL; // 出错了
}
这样,生成的一定是一个二叉树,内部结点是+或-,叶子结点是变量。 从根到叶子结点的路径上会有若干个+或-,可以计算出变量前的符号。 显然,可以引入一个参数来描述这若干个+或-,不用生成语法树就可以完成解析。
hollin1988 2014-02-19
  • 打赏
  • 举报
回复
或者说如何把这里面所有括号去除,变成正常的表达式
hollin1988 2014-02-19
  • 打赏
  • 举报
回复
引用 1 楼 zyq5945 的回复:
http://wenku.baidu.com/view/3ef2f26b25c52cc58bd6be97.html
版主大哥,他这个有局限啊:中缀表达式(可以带括号,但不允许冗余括)或后缀表达式(不带括号) 。 我要的是任意,可能多层括号,有可能诸如 a+b-(c+(a-(d+e+(f-a))+m),就有冗余的括号啊,他这个实现不了吧

70,023

社区成员

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

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