-1

Trying to find the starting positions of the smiley in c++. But once it found the first smiley, it stops finding the next smiley.

Code I was trying with regex (":\)|:\-\]")

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

int main ()
{
  std::string s ("Best :) bookseller :) today. :-]");
  std::smatch m;
  std::regex e (":\\)|:\\-\\]");

  if (std::regex_search(s, m, e))
  {
     std::cout << "matched" << std::endl;
     std::cout << m[0] << " -> " << m.position(0) << std::endl;
     std::cout << m[1] << " -> " << m.position(1) << std::endl;
     std::cout << m[2] << " -> " << m.position(2) << std::endl;
  }
  else
     std::cout << "not matched" << std::endl;

  return 0;
}

Expected output is:

matched
:) -> 5
:) -> 19
:-] -> 29

But getting output as:

matched
:) -> 5
-> 32
-> 32

It would be great if someone suggest how to find the smiley symbols position in multiple places in a test using c++ (or) suggest a right regex to use.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
jack sparow
  • 339
  • 3
  • 9
  • You can test your regex out in a text editor, easily play with it and get it right. – Taekahn Sep 07 '22 at 23:17
  • You can read the documentation too : https://en.cppreference.com/w/cpp/regex/regex_search. Obviously from the examples, you need a loop to get multiple matches. – Phil1970 Sep 07 '22 at 23:37

1 Answers1

1

A regex_search only returns a single match. As the documentation notes:

In order to examine all matches within the target sequence, std::regex_search may be called in a loop, restarting each time from m[0].second of the previous call. std::regex_iterator offers an easy interface to this iteration.

Simple loop construction:

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

int main()
{
  std::string s ("Best :) bookseller :) today. :-]");
  std::smatch m;
  std::regex e (":\\)|:-\\]");

  for (auto it = s.cbegin();
       std::regex_search(it, s.cend(), m, e);
       it = m[0].second)
  {
    std::cout << "matched" << std::endl;
    std::cout << m[0] << " -> " << m.position(0) << std::endl;
  }
}

Using regex_iterator:

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

int main()
{
  std::string s ("Best :) bookseller :) today. :-]");
  std::regex e (":\\)|:-\\]");

  for (auto it = std::sregex_iterator(s.begin(), s.end(), e);
       it != std::sregex_iterator();
       ++it)
  {
    const auto& m = *it;
    std::cout << "matched" << std::endl;
    std::cout << m.str() << " -> " << m.position(0) << std::endl;
  }
}

Note that you do not need to escape the - character in a regular expression. I have corrected that in my examples.

paddy
  • 60,864
  • 6
  • 61
  • 103