2014-11-02 4 views
19

Ниже программа была записана для получения информации «День» с использованием C++ 11 std::regex_match & std::regex_search. Однако использование первого метода возвращает false, а второй метод возвращает true (ожидается). Я прочитал документацию и уже существующий вопрос SO, связанный с этим, но я не понимаю разницу между этими двумя методами и когда мы должны использовать любой из них? Могут ли они использоваться как взаимозаменяемые для любой общей проблемы?Разница между std :: regex_match и std :: regex_search?

Difference between regex_match and regex_search?

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

int main() 
{ 
    std::string input{ "Mon Nov 25 20:54:36 2013" }; 
    //Day:: Exactly Two Number surrounded by spaces in both side 
    std::regex r{R"(\s\d{2}\s)"}; 
    //std::regex r{"\\s\\d{2}\\s"}; 
    std::smatch match; 

if (std::regex_match(input,match,r)) { 
     std::cout << "Found" << "\n"; 
    } else { 
     std::cout << "Did Not Found" << "\n"; 
    } 

    if (std::regex_search(input, match,r)) { 
     std::cout << "Found" << "\n"; 
     if (match.ready()){ 
      std::string out = match[0]; 
      std::cout << out << "\n"; 
     } 
    } 
    else { 
     std::cout << "Did Not Found" << "\n"; 
    } 
} 

Выход

Did Not Found 

Found 

25 

Почему первый метод возвращает регулярное выражение false в этом случае ?. regex кажется правильным, поэтому в идеале оба должны были быть возвращены true. Я выполнил вышеуказанную программу, изменив std::regex_match(input,match,r) на std::regex_match(input,r) и обнаружил, что он все еще возвращает false.

Может ли кто-нибудь объяснить приведенный выше пример и, в общем, использовать случаи этих методов?

ответ

18

regex_match возвращает только true, когда вся входная последовательность была совпадают, в то время как regex_search удастся, даже если только суб-последовательность соответствует regex.

Цитируя N3337,

§28.11.2/2regex_match[re.alg.match]

Эффекты: Определяет, есть ли совпадение между регулярным выражением e , и все последовательности символов [first,last). ... Возвращает true, если такой матч существует, false в противном случае.

Вышеприведенное описание предназначено для перегрузки regex_match, которая принимает пару итераторов в последовательность, подлежащую согласованию. Оставшиеся перегрузки определены в терминах этой перегрузки.

Соответствующий regex_search перегрузки описывается как

§28.11.3/2regex_search[re.alg.search]

Effects: Определяет, есть ли некоторые суб- последовательность в пределах [first,last), которая соответствует регулярному выражению e. ... Возвращает true, если такая последовательность существует, false в противном случае.


В вашем примере, если изменить regex к r{R"(.*?\s\d{2}\s.*)"}; как regex_match и regex_search удастся (но результат матча не только день, но и вся строка даты).

Live demo измененной версии вашего примера, где день фиксируется и отображается как regex_match, так и regex_search.

+0

Спасибо за объяснение. Не могли бы вы объяснить, почему нам нужно было изменить из соответствия [0] в соответствии с [1], чтобы получить точный результат в обоих случаях ?. Я имею в виду, что это касается std :: smatch использует понимание. –

+1

@MantoshKumar Я добавил круглые скобки вокруг поля даты '(\ d {2})' для создания группы захвата. Из 'match_results' [документации] (http://en.cppreference.com/w/cpp/regex/match_results/operator_at)' match [0] 'всегда возвращает все согласованное выражение, а' match [1] ' возвращает первый подзаголовок и так далее. В этом случае у нас была только одна группа захвата за день и поэтому она хранится в первом подзаголовке. – Praetorian

12

Это очень просто. regex_search просматривает строку, чтобы найти, соответствует ли какая-либо часть строки регулярному выражению. regex_match проверяет, соответствует ли целая строка регулярному выражению. В качестве простого примера рассмотрим следующую строку:

"one two three four" 

Если я использую regex_search на эту строку с выражением "three", это будет успех, потому что "three" можно найти в "one two three four"

Однако, если я использую regex_match вместо этого он потерпит неудачу, потому что "three" - это не вся строка, а только ее часть.