使用 std::regex 查找函数的内容

use std::regex to find contents of a function

本文关键字:函数 查找 std regex 使用      更新时间:2023-10-16

假设我有一个带有任意代码的主函数:

void main(){
    //Some random code    
    int a = 5;
    int b = a + 7;
}

并且此函数的文本存储在 std::string 中:

std::string mystring("void main(){ //Some random code  int a = 5; int b = a + 7;}");

我想使用 std::regex 来提取函数的主体。所以我会得到的结果是:

"//Some random code int a= 5; int b = a + 7;"

我的问题是我不知道如何格式化正则表达式以获得我想要的。这是我现在的代码:

std::string text("void main(){ //Some random code  int a = 5; int b = a + 7;}");
std::regex expr ("void main()\{(.*?)\}");
std::smatch matches;
if (std::regex_match(text, matches, expr)) {
    for (int i = 1; i < matches.size(); i++) {
        std::string match (matches[i].first, matches[i].second);
        std::cout << "matches[" << i << "] = " << match << std::endl;
    }
}

我的正则表达式完全关闭,不返回任何匹配项。我需要什么来制作我的正则表达式才能使其工作?

正如注释中所讨论的,OP 只想"提取函数体内的文本,而不管该文本是什么"。

@OP:您的正则表达式是错误的,因为您没有转义main()的括号。将正则表达式更改为"void main\(\)\{(.*?)\}"将起作用。

我还建议在 for 循环中使用 size_t for i,这样您就不会将有符号与无符号进行比较(std::smatch::size()返回size_t)。

#include <iostream>
#include <regex>
int main()
{
    std::string text("void main(){ //Some random code  int a = 5; int b = a + 7;}");
    std::regex expr("void main\(\)\{(.*?)\}");
    std::smatch matches;
    if (std::regex_match(text, matches, expr)) {
        for (size_t i = 1; i < matches.size(); i++) {
            std::string match(matches[i].first, matches[i].second);
            std::cout << "matches[" << i << "] = " << match << std::endl;
        }
    }
}

输出:

matches[1] =  //Some random code  int a = 5; int b = a + 7;

对于输入"void main(){ while(true){ //Some random code int a = 5; int b = a + 7; } }",此解决方案失败

最简单的解决方案是将正则表达式更改为 "^void main\(\)\{(.*?)\}$"但这需要输入以 "void main(){" 开头并以 "}" 结尾

正如Revolver_Ocelot所建议的那样,您还可以在正则表达式中添加一些空格匹配,以使其更加灵活。

正如您的用例中所建议的那样,最好只依靠字符串搜索和大括号匹配。

#include <iostream>
#include <regex>

std::string getBody(const std::string& functionDef, const std::string& text)
{
    size_t pos = 0;
    do
    {
        if ((pos = text.find(functionDef, pos)) == std::string::npos)
            continue;
        pos += functionDef.length();
        size_t firstSemicolon = text.find(";", pos);
        size_t firstOpen = text.find("{", pos);
        size_t firstClose = text.find("}", pos);
        if (firstSemicolon != std::string::npos && firstSemicolon < firstOpen) //Only function declaration
            continue;
        if (firstOpen == std::string::npos || firstClose == std::string::npos || firstClose < firstOpen) //Mismatch
            continue;
        size_t bodyStart = pos = firstOpen + 1;
        size_t bracesCount = 1;
        do
        {
            firstOpen = text.find("{", pos);
            firstClose = text.find("}", pos);
            if (firstOpen == std::string::npos && firstClose == std::string::npos)//Mismatch
            {
                pos = std::string::npos;
                continue;
            }
            //npos is always larger
            if (firstOpen < firstClose)
            {
                bracesCount++;
                pos = firstOpen + 1;
            }
            else if (firstOpen > firstClose)
            {
                bracesCount--;
                if (bracesCount == 0)
                {
                    size_t bodySize = firstClose - bodyStart;
                    return text.substr(bodyStart, bodySize);
                }
                pos = firstClose + 1;
            }
            else
            {
                //Something went terribly wrong...
                pos = std::string::npos;
                continue;
            }
        } while (pos != std::string::npos);
    }
    while (pos != std::string::npos);
    return std::string();
}
int main()
{
    std::string text("void main(); int test(); void main(){ while(true){ //Some {random} code int a = 5; int b = a + 7; } } int test(){ return hello; } ");
    std::cout << getBody("void main()", text) << std::endl;
    std::cout << getBody("int test()", text) << std::endl;
}

输出:

 while(true){ //Some {random} code int a = 5; int b = a + 7; }
 return hello;

该代码还可以处理换行符和跳过函数声明。我试图把它写得尽可能清楚。

如果还有问题,请随时提问。