括号,括号和括号

时间:2015-11-18 15:02:31

标签: c++ regex algorithm

任务是检查给定的字符串是否包含{}[]()的平衡集。

例如,check("{[}]")必须返回falsecheck("{[]()}")必须返回true等。

解决方案:

bool check(const std::string & s)
{
    constexpr auto brackets1 = "()";
    constexpr auto brackets2 = "[]";
    constexpr auto brackets3 = "{}";
    constexpr size_t brackets_pair_size = 2;
    constexpr auto brackets = "()[]{}";

    std::string s2;

    for (auto & c : s) 
    {
        if (strchr(brackets, c) != nullptr) 
        {
            s2 += c;
        }
    }

    auto brackets1_pos{ std::string::npos };
    auto brackets2_pos{ std::string::npos };
    auto brackets3_pos{ std::string::npos };

    while ((brackets1_pos = s2.find(brackets1)) != std::string::npos ||
           (brackets2_pos = s2.find(brackets2)) != std::string::npos ||
           (brackets3_pos = s2.find(brackets3)) != std::string::npos
           ) 
    {
        if (brackets1_pos != std::string::npos) {
            s2.erase(brackets1_pos, brackets_pair_size);
            continue;
        }

        if (brackets2_pos != std::string::npos) {
            s2.erase(brackets2_pos, brackets_pair_size);
            continue;
        }

        if (brackets3_pos != std::string::npos) {
            s2.erase(brackets3_pos, brackets_pair_size);
            continue;
        }
    }

    return s2.empty();
}

想法是: - 将所有的句子,括号和大括号复制到另一个字符串, - 从第二个字符串中删除一对括号, - 检查第二个字符串是否为空。

有没有办法改进算法?

可能是一些普遍的正则表达式吗?

5 个答案:

答案 0 :(得分:3)

检查嵌套大括号似乎是std::stack的自然情况。在迭代输入时将大括号推入堆栈,并在看到右大括号时测试正确的匹配。

bool check(const std::string &expression) // balanced and nested?
{
    std::stack<char> stack;

    for (auto ch : expression) {
        switch (ch) {
        case '(': // open parenthesis
        case '<': // open angle
        case '[': // open bracket
        case '{': // open brace
            stack.push(ch);
            break;
        case ')': // close parenthesis
            if (stack.empty() || stack.top() != '(') return false;
            stack.pop();
            break;
        case '>': // close angle
            if (stack.empty() || stack.top() != '<') return false;
            stack.pop();
            break;
        case ']': // close bracket
            if (stack.empty() || stack.top() != '[') return false;
            stack.pop();
            break;
        case '}': // close brace
            if (stack.empty() || stack.top() != '{') return false;
            stack.pop();
            break;
        }
    }
    return stack.empty(); // no unmatched braces left?
}

答案 1 :(得分:1)

这个任务不适用于正则表达式,因为它们没有记忆,也记不起括号的深度。

您应该使用解析器(可能是recursive descent parser)来完成任务。

语法看起来像这样(未经测试):

input: /* empty */
     | expr input

expr: paren-expr
    | bracket-expr
    | curly-bracket-expr

paren-expr: '(' input ')'

bracket-expr: '[' input ']'

curly-bracket-expr: '{' input '}'

示例代码:

#include <iostream>
#include <iterator>
#include <string>


class parenthesis_checker {

  template <class It>
  It parse_open_close(It first, It last, char op, char cl) const {
    if(op != *first) return first;

    It r = parse_input(first+1, last);
    if(last == r) return first;
    if(cl != *r)  return first;

    return r+1;
  }

  template <class It>
  It parse_expr(It first, It last) const {
    It r = parse_open_close(first, last, '(', ')');
    if(r != first) return r;

    r = parse_open_close(first, last, '[', ']');
    if(r != first) return r;

    r = parse_open_close(first, last, '{', '}');
    if(r != first) return r;

    return first;
  }

  template <class It>
  It parse_input(It first, It last) const {
    while(first != last) {
      It r = parse_expr(first, last);
      if(r == first) return r;
      first = r;
    }
    return first;
  }

public:
  template <class It>
  bool operator()(It first, It last) const {
    return last==parse_input(first, last);
  }

  template <class Cont>
  bool operator()(Cont value) const {
    return (*this)(value.begin(), value.end());
  }

  bool operator()(const char* str) const {
    return (*this)(std::string(str));
  }
};


int main() {
  parenthesis_checker check;

  std::cout << check("{[}]") << std::endl;
  std::cout << check("{[]()}") << std::endl;
}

答案 2 :(得分:1)

你的解决方案看起来过于复杂,我不得不承认我并没有太努力去理解它,但对我来说这是不正确的,甚至是正确的。 这个问题的一个非常简单的解决方案是创建一个堆栈并通过字符串将开括号推到堆栈并在关闭括号时从堆栈弹出(当你弹出时,你必须检查开始括号和右括号是否匹配)。 p>

遗憾的是,用正则表达式解决这个问题是不可能的,因为平衡括号的语言不是regular

答案 3 :(得分:1)

您可以通过以下简单的代码检查匹配的括号。

int bracketMatcher(string s)
{
    list<int> *countsList = new list<int>();
    string expression = s;
    int correctBrackets = 1;

    for (int index = 0; index < expression.size(); index++) {
        char ch = expression[index];
        if (ch == '(')
        {
            countsList->push_back(index);
        }
        else if (ch == ')')
        {
            if (countsList->size() == 0)
            {
                correctBrackets = 0;
                break;
            }
            countsList->pop_back();
        }
    }
    if (countsList->size() != 0)
    {
        correctBrackets = 0;
    }
    return correctBrackets;
}

或者如果要查找特定的括号类型,也可以使用以下功能。

bool bracketMatcher(string s , char c)
{
    list<int> *countsList = new list<int>();
    string expression = s;
    bool correctBrackets = true;

    char secondCh =' ';
    switch (c) {
        case '(': // open parenthesis
            secondCh = ')';
            break;
        case '<': // open angle
            secondCh = '>';
            break;
        case '[': // open bracket
            secondCh = ']';
            break;
        case '{': // open brace
            secondCh = '}';
            break;
        default:

            break;
    }
    for (int index = 0; index < expression.size(); index++) {
        char ch = expression[index];
        if (ch == c)
        {
            countsList->push_back(index);
        }
        else if (ch == secondCh)
        {
            if (countsList->size() == 0)
            {
                correctBrackets = false;
                break;
            }
            countsList->pop_back();
        }
    }
    if (countsList->size() != 0)
    {
        correctBrackets = false;
    }
    return correctBrackets;
}
int main() {

    string s  = " ((hello ) (()) llll {}word <aaa>(aad))";
    //always specify the opening bracket here

    bool parenthesisMatch = bracketMatcher(s,'(');
    bool angleBracketsMatch = bracketMatcher(s,'<');
    bool bracketMatch = bracketMatcher(s,'[');
    bool bracesMatch = bracketMatcher(s, '{');

    if(parenthesisMatch && angleBracketsMatch && bracketMatch && bracesMatch) {
        cout << "found all matching brackets" << endl;
    }
    else{
        cout << "could not find all matching brackets" << endl;
    }
    return 0;
}

答案 4 :(得分:0)

请告诉我我的代码有什么问题,它总是不提供

string isBalanced(string s) {
stack<char> comp;
char temp;
int i;
for(i=s.size()-1;(s[i]=='}' ) || (s[i]==')' ) || (s[i]==']');i--)
{
    comp.push(s[i]);
}

if(comp.size()!=i+1)
return ("NO");

while(!comp.empty() && i>=0)
{
    temp=comp.top();
    if(temp!=s[i])
    return ("NO");
    comp.pop();
    i--;
}

return("YES");
}