自动大括号插入算法[关闭]

问题描述 投票:-2回答:1

有关更多信息,请参阅this issue on GitHub

我想编写一个算法,当用户在左括号后按Enter键时调用该算法。预期的行为详述如下。

1.假设我们有一个空文件。如果我们键入一个左括号并按Enter键,则预期的行为如下:

Enter image description here

这可以描述为以下简单算法:

  1. 如果在左括号后按下Enter,则将光标移动到下一行,并在开括号缩进之外再缩进一个级别。
  2. 如果开口支架未配对,则在与开口支架相同的压痕水平的下一条线上插入一个闭合支架。否则,如果已配对,则在1之后不执行任何操作。

换句话说,如果我们在已经配对的左大括号后按Enter键,我们不想要的是插入另一个右大括号。相反,我们只想保持缩进一致:

Enter image description here

2.现在假设我们在第2行键入另一个左括号,光标位于,然后按Enter键。我们期望按照上述相同的算法生成一对新对:

Enter image description here

3.如果我们转到第1行,按Enter键几次强制支撑,然后尝试在顶部创建一个新的块,我们希望它也配对:

Enter image description here

问题

我在实现这种行为时遇到了麻烦。我正在使用Qt在C ++中开发文本编辑器,但您不必担心框架细节。它只是一个实用函数,它接受一个名为context的给定字符串和有问题的左括号的索引,并决定是否应该插入一个右括号。

我的current implementation满足场景#1和#2,但不满足#3。它不满足#3的原因是因为我正在使用队列来打开大括号。

我也尝试过使用堆栈来打开支架。有趣的是,这最终满足#1和#3,但不满足#2。

我如何根据上述预期行为编写一个算法来确定给定的括号是否已经有匹配的对?请注意,我在网站上研究了这个,并且知道如何确定给定的开括号是否具有匹配的右括号。但是,我当前的算法(上面链接的)不能按预期工作(请参阅上面的说明,了解失败的位置)。

澄清:你不必担心整个“缩进”的事情。这是照顾和按预期工作。什么不能按预期工作是决定一个特定的大括号是否需要匹配对。

c++ algorithm qt text-editor curly-braces
1个回答
1
投票

这不是一个复杂的问题,以确定是否有一个闭合支撑,这是困难的缩进。如果在操作支架后面有任何不匹配的右支撑,则表示您有匹配。关键在于支撑是否跟随您的支撑。您可以通过以下方式确定:

  1. 存储所有不匹配的闭合支架的位置;如果你跟随你的光标,你不需要插入一个右括号
  2. 与光标后不匹配的括号数相比,动态评估光标前不匹配的括号数(不计算不匹配的关闭数);如果你的光标后有多余的关闭括号,那么你不需要插入一个右括号

如果您选择2号,我会将this answer扩展到您需要的前后计数括号:

bool foo(const string& context, const size_t pos) {
    const auto it = next(cbegin(context), pos);
    const auto before = accumulate(cbegin(context), it, 0, [](const auto output, const auto input) {
        if(input == '{') {
            return output + 1;
        }
        else if(input == '}' && output > 0) {
            return output - 1;
        }
        else {
            return output;
        }
    });
    const auto after = accumulate(it, cend(context), 0, [](const auto output, const auto input) {
        if(input == '{') {
            return output + 1;
        }
        else if(input == '}') {
            return output - 1;
        }
        else {
            return output;
        }
    });

    return before + after >= 0;
}

这可以被调用,有问题的文本(不包括插入的开放式大括号),以及将要插入大括号的字符串中的位置。鉴于您的文本包含在const string bar中,并且您的光标位置位于const size_t baz,您可以将此函数称为:foo(bar, baz)如果返回true,则需要添加右括号。

Live Example

© www.soinside.com 2019 - 2024. All rights reserved.