2015-11-03 2 views
8

В принципе, я хочу иметь регулярное выражение, такое как # [0-9] + и иметь возможность проверить, может ли строка соответствовать ему. Например, если я получаю пользовательский ввод, и они вводят «#», эта строка не соответствует регулярному выражению, но может быть, если пользователь также вводил некоторые номера.Проверьте, является ли строка потенциальным совпадением для regex

Я знаю, что у C++ есть функции matches(), но есть ли что-нибудь там, например, что я ищу? Или какой-то способ сделать это?

Благодаря

+1

ли вы имеете в виду частичное совпадение (когда часть строки соответствует)? Как с 'regex_search'? Проверьте [это демо] (https://ideone.com/F2Z8mQ). –

+1

Интересный вопрос! +1 @stribizhev: Я думаю, он имел в виду, что существует суффикс для ввода, который позволит ему соответствовать шаблону. –

+0

regex_search не совсем то, что я ищу. То, что я ищу, больше противоположное. Я ищу, чтобы выяснить, является ли строка частичным совпадением для регулярного выражения. В приведенном выше примере «#» не является полным совпадением для регулярного выражения, но это частичное совпадение, так как оно начинается с «#», но, что более важно, имеет потенциал для полного соответствия, если добавлено больше символов. «#a» не является частичным совпадением, так как добавление большего количества символов не сделает его полным совпадением. – Pottsiex5

ответ

4

ОТКАЗ: Ниже приводится довольно наивный подход, который не является ни быстрым, ни красивым. Тем не менее он выполняет работу для простого регулярного выражения. Я не рекомендую использовать это, не понимая, что он делает

#include <string> 
#include <iostream> 
#include <regex> 


bool is_valid_regex_string(const std::string& rgx_str) 
{ 
    bool bResult = true; 
    try 
    { 
     std::regex tmp(rgx_str); 
    } 
    catch (const std::regex_error& e) 
    { 
     (e); 
     bResult = false; 
    } 
    return bResult; 
} 

std::string create_partial_regex_string(const std::string& rgx_str) 
{ 
    std::string par_rgx_str; 
    for (int i = 1; i <= rgx_str.size(); i++) 
    { 
     std::string sub_rgx_str = rgx_str.substr(0, i); 
     if (is_valid_regex_string(sub_rgx_str)) 
     { 
      if (!par_rgx_str.empty())par_rgx_str += "|"; 
      par_rgx_str += "(" + sub_rgx_str + ")"; 
     } 
    } 
    //return par_rgx_str; 
    return "^" + par_rgx_str + "$"; 
} 


void testPartialRegex(const std::string& rgx, const std::string& str) 
{ 
    std::string partialRegexString = create_partial_regex_string(rgx); 
    std::regex partRegex(partialRegexString); 
    std::cout << "\tTESTING \"" << str << "\" against \"" << partialRegexString << "\" :" << std::endl; 

    std::smatch base_match; 
    std::cout << "\t\t-> " << (std::regex_match(str, partRegex) ? "true" : "false") << std::endl; 
} 

void test(const std::string& str) 
{ 
    std::cout << "\n###########################################\nTESTING \"" << str << "\"\n" << std::endl; 
    for (int i = 1; i <= str.size(); i++) 
    { 
     testPartialRegex("#[0-9]+", str.substr(0, i)); 
    } 
    std::cout << "\n###########################################\n" << std::endl; 

} 



int main() 
{ 

    test("#123456");  
    test("#12a3456");  
    test("#b");  
    test("123456");  
    test("##");  
    return 0; 
} 

Выход:

########################################### 
TESTING "#123456" 

     TESTING "#" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#1" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#12" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#123" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#1234" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#12345" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#123456" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 

########################################### 


########################################### 
TESTING "#12a3456" 

     TESTING "#" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#1" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#12" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#12a" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "#12a3" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "#12a34" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "#12a345" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "#12a3456" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 

########################################### 


########################################### 
TESTING "#b" 

     TESTING "#" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "#b" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 

########################################### 


########################################### 
TESTING "123456" 

     TESTING "1" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "12" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "123" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "1234" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "12345" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 
     TESTING "123456" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 

########################################### 


########################################### 
TESTING "##" 

     TESTING "#" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> true 
     TESTING "##" against "^(#)|(#[0-9])|(#[0-9]+)$" : 
       -> false 

########################################### 
+0

, идущий туда и обратно между выдержкой этого и не голосующим ... Он выполняет свою работу, но ... вы знаете ... – bolov

+0

Поскольку приблизительное, уродливое решение (но работающее по большей части) все еще лучше, чем нет решение на всех, вы получаете мой голос ... – bolov

+0

@bolov Да, я тоже не доволен этим ... –

-5

следующие проверки кода для вас, будет ли строка соответствуют выражение с «#» в начале и затем один или несколько номеров ...

#include <iostream> 
#include <regex> 

using namespace std; 

int main() 
{ 

    string str; 
    while (true) { 
     cin >> str; 
     regex pat{ "(#[[:d:]]+)" }; 
     bool match = regex_search(str, pat); 
     cout << (match ? "Matched" : "Not matched") << endl; 
    } 

    return 0; 
} 
+1

Вы неправильно поняли задачу. –

+0

Я уверен, что ты мог бы сказать мне без нисходящего потока. Если мой новый ответ - то, что ищет Pottsiex5, любезно удалите downvote, пожалуйста. – dspfnder

+0

Я не понимаю, почему здесь внизу. –

7

Вы можете использовать Boost.Regex, который уже реализует Partial Matches.

При использовании это указывает на то, что должны быть найдены частичные, а также полные совпадения. A частичное совпадение - это тот, который соответствует одному или нескольким символам в конце ввода текста, но не соответствует всем регулярным выражениям (хотя, возможно, это и имело доступ к большему количеству входных данных).

Код

#include <iostream> 
#include <boost/regex.hpp> 
using namespace std; 
using namespace boost; 


int main () { 
    string subject = "#"; 
    string pattern = "#[0-9]+"; 


    const regex e(pattern); 
    if (regex_match(subject, e, match_partial)) { 
     cout << subject << " \tMATCHES\t " << pattern << endl; 
    } else { 
     cout << subject << " \tDOESN'T MATCH\t " << pattern << endl; 
    } 


    return 0; 
} 

rextester demo

+1

** Примечание: ** PCRE также поддерживает его с помощью [PCRE_PARTIAL] (http://www.pcre.org/current/doc/html/pcre2partial.html) – Mariano

+4

Это лучше, чем принятое решение. –

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