2016-02-26 3 views
-1

так скажем, у меня есть основная функция с некоторым произвольным кодом:использования станда :: регулярное выражение, чтобы найти содержание функции

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

и текстом этой функции хранится внутри станд :: строка:

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; 
    } 
} 

Мое регулярное выражение полностью выключено и не возвращает совпадений. Что мне нужно для создания моего регулярного выражения, чтобы это работало?

+4

Не связано с вашей (текущей) проблемой, но с использованием регулярных выражений, чтобы попробовать синтаксический анализ кода C или C++, будет сложно, поскольку регулярные выражения не могут справиться с вложенными структурами. Для чего-то простого, как ваш пример, он будет работать, но как только вы смешаетесь с вложенными фигурными скобками, вы больше не сможете надежно использовать регулярные выражения. –

+0

Я вижу - поэтому функция «main» может иметь любое количество вложенных операторов if/else, в то время как циклы и т. Д. ... в этом случае regex не будет работать? Если нет, то каков был бы лучший способ получить данные? Я не привязан к использованию регулярного выражения, я просто решил, что это лучший способ. – Sunny724

+1

Связанные: http://stackoverflow.com/a/1732454/3410396 –

ответ

0

Как обсуждалось в комментариях, OP хочет только «извлечь текст внутри тела функции, вне зависимости от того, что это за текст».

@OP: Ваше регулярное выражение неверно, так как вы не избегаете скобок для main(). Изменение регулярного выражения до "void main\\(\\)\\{(.*?)\\}" будет работать.

Я также рекомендую использовать size_t для 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_Oc elot вы также можете добавить некоторое соответствие пробелов в регулярное выражение, чтобы сделать его немного более гибким.

+0

Спасибо за ваш ответ! К сожалению, этот подход не работает, если в тексте тела есть «}» перед окончательным «}» разделителем. – Sunny724

+0

@ cardinal724 Строка, в которой вы оказались, всегда заканчивается символом '}'? Можете ли вы привести мне еще несколько примеров? –

+0

уверен: эта строка не выполняется: "void main() {while (true) {// Некоторое случайное число int a = 5; int b = a + 7;}}" – Sunny724

0

Как было предложено в вашем случае использования, вероятно, было бы лучше всего использовать строковый поиск и сопоставление фигурных скобок.

#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; 

Код может также обрабатывать переводы строк и скачет объявления функций. Я попытался написать его как можно более ясно.

Если есть еще вопросы, не стесняйтесь спрашивать.

+0

Coliru-Link: http://coliru.stacked-crooked.com/a/749ff701622f5168 –

Смежные вопросы