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

回复:
user: user-1
content: 引用 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楼所说。

user: user-2
content: 引用 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,如此循环遍历完整个字符串，就取出来变量的值

user: user-2
content: 引用 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是正，这明显错了吧。还是我理解错了啊？

user: user-0
content: 引用 9 楼 misakamm 的回复:来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b，初始都是0 要确定f的符号，从f向前一个一个字符扫描，如果遇到-号，同时b为0，那么s = 1 - s 如果遇到)号，那么b++ 遇到(号，那么b-- 扫描完以后，s为0就是正，s为1就是负  我现在做的程序解析带1个括号的是没问题的，基本也是按这种方法的，但是多层的，怎么确定括号的范围，怎么保留每层括号外面的符号，怎么判断变量在那个括号范围内，没有理清楚里面的思路

user: user-0
content: 引用 5 楼 derekrose 的回复:使用递归  我也知道用递归，就是不知道怎么去写，方法之类的我也很清楚。。。

user: user-0
content: 引用 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),这个通过你程序正常解析出来了没？解析出来就万分感谢，分数就送上了

user: user-3
content: 来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b，初始都是0 要确定f的符号，从f向前一个一个字符扫描，如果遇到-号，同时b为0，那么s = 1 - s 如果遇到)号，那么b++ 遇到(号，那么b-- 扫描完以后，s为0就是正，s为1就是负

user: user-4
content: http://www.codeproject.com/Articles/286121/Compiler-Patterns

user: user-3
content: 你确定只有+-号和括号？如果是的话那灰常容易，一遍分析就出结果了

user: user-5
content: 编译原理中的波兰树语法分析树问题，呵呵

user: user-6
content: 使用递归

user: user-1
content: 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; // 出错了 }  这样，生成的一定是一个二叉树，内部结点是+或-，叶子结点是变量。 从根到叶子结点的路径上会有若干个+或-，可以计算出变量前的符号。   显然，可以引入一个参数来描述这若干个+或-，不用生成语法树就可以完成解析。

user: user-0
content: 或者说如何把这里面所有括号去除，变成正常的表达式

user: user-0
content: 引用 1 楼 user-7 的回复:http://wenku.baidu.com/view/3ef2f26b25c52cc58bd6be97.html 版主大哥，他这个有局限啊：中缀表达式（可以带括号，但不允许冗余括）或后缀表达式（不带括号）  。 我要的是任意，可能多层括号，有可能诸如 a+b-(c+(a-(d+e+(f-a))+m),就有冗余的括号啊，他这个实现不了吧

user: user-7
content: http://wenku.baidu.com/view/3ef2f26b25c52cc58bd6be97.html