【问题标题】:Boolean Function to Check Validity of Expression Recursively?递归检查表达式有效性的布尔函数?
【发布时间】:2012-02-13 02:01:24
【问题描述】:

我想创建一种形式的解析器:

#include <iostream>
#include <string>
#include <sstream>
#include <cctype>

using namespace std;

bool isValid(istringstream& is)
{
  char ch;
  is.get(ch); //I know get(ch) is a good start but this is as for as I got :)
  .......
  ....
}

int main()
{
  string s;
  while(getline(cin,s))
  {
    istringstream is(s);
    cout<<(isValid(is)? "Expression OK" : "Not OK")<<endl;
  }
}

一个布尔函数,如果 char 的序列为“5”或“(5+3)”或“((5+3)+6)”或“”形式,则返回 TRUE (((4+2)+1)+6)" ...等其他情况为 FALSE

基本上,如果表达式为单个数字或“开括号-单个数字-加号-单个数字-闭括号”形式,则表达式将被视为有效

  • 有效表达式 = 一位数

  • 有效表达式 = (有效表达式 + 有效表达式)

鉴于上述表格的大小没有限制(左括号和右括号的数量等),我想使用递归来做到这一点

作为我的新手..感谢您提供任何有用的意见!

【问题讨论】:

    标签: c++ parsing recursion boolean


    【解决方案1】:

    要执行递归解决方案,您需要先将字符串读入缓冲区,然后执行以下操作:

    int expression(char* str) {
        if (*str == '(') {
            int e1 = expression(str + 1);
            if (e1 == -1 || *(str + 1 + e) != '+') {
                return -1;
            }
            int e2 = expression(str + 1 + e + 1);
            if (e2 == -1 || *(str + 1 + e + 1 + e2) != ')') {
                return -1;
            }
            return 1 + e1 + 1 + e2 + 1;
        }
    
        if (*str >= '0' || *str <= '9') {
            return 1;
        }
    
        return -1;
    }
    
    bool isvalid(char* str) {
        int e1 = expression(str);
        if (e1 < 0) {
            return false;
        }
        if (e1 == strlen(str)) {
            return true;
        }
        if (*(str + e1) != '+') {
            return false;
        }
        int e2 = expression(str + e1 + 1);
        if (e2 < 0) {
            return false;
        }
        return (e1 + 1 + e2 == strlen(str));
    }
    

    基本上,表达式函数在其参数处返回有效表达式的长度。如果它的参数以括号开头,则获取之后表达式的长度,然后验证加号,然后验证下一个表达式之后的右括号。如果参数以数字开头,则返回 1。如果有问题,则返回 -1。然后使用该函数,我们可以通过一些总和和字符串的长度来确定字符串是否有效。

    我根本没有测试过这个函数,但我能想到的唯一可能失败的情况是括号过多:例如 ((5))。

    递归的替代方法可能是某种词法解析,例如:

    enum {
        ExpectingLeftExpression,
        ExpectingRightExpression,
        ExpectingPlus,
        ExpectingEnd,
    } ParseState;
    
    // returns true if str is valid
    bool check(char* str) {
        ParseState state = ExpectingLeftExpression;
    
        do {
            switch (state) {
                case ExpectingLeftExpression:
                    if (*str == '(') {
                    } else if (*str >= '0' && *str <= '9') {
                        state = ExpectingPlus;
                    } else {
                        printf("Error: Expected left hand expression.");
                        return false;
                    }
                break;
                case ExpectingPlus:
                    if (*str == '+') {
                        state = ExpectingRightExpression;
                    } else {
                        printf("Error: Expected plus.");
                        return false;
                    }
                break;
                case ExpectingRightExpression:
                    if (*str == '(') {
                        state = ExpectingLeftExpression;
                    } else if (*str >= '0' && *str <= '9') {
                        state = ExpectingEnd;
                    } else {
                        printf("Error: Expected right hand expression.");
                        return false;
                    }
                break;
            }
        } while (*(++str));
    
        return true;
    }
    

    该功能根本不完整,但您应该能够看到它的去向。无论如何,我认为递归在这种情况下效果更好。

    【讨论】:

    • 感谢您提供有用的输入 Daxnitro,尽管我正在尝试提出一些限制自己仅使用布尔函数的方法: bool isValid(istringstream& is) 我在原帖中提到,与里面的递归。不过,我肯定也会看看你的建议..!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 2018-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多