Microsoft & .NETVisual C#Search Strings for Patterns with the Match Classes

Search Strings for Patterns with the Match Classes

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The previous article illustrated how to use the .NET Regex class to split strings, such as when you need to break a comma-delimited string into its separate components (or columns). This article covers how to search strings for patterns, where the found matches are returned via the MatchCollection and Match classes. The basic steps to using these classes are as follows:

  1. Construct a Regex object with the pattern for which you are searching.
  2. Call the Regex::Match method, passing the input value to be scanned. This method returns a boolean value indicating whether or not any matches were found.
  3. Retrieve the matches via the Regex::Matches property.
  4. Iterate the matches.

Searching for a Single Pattern Occurrence

In the following example, the code is searching a string for the first occurrence of a literal and then printing the found value (Match::Value) along with the position within the input string where that value was located (Match::Index). I’ve bolded the salient code for emphasis:

// Example of searching for a single literal or pattern occurrence
using namespace System::Text::RegularExpressions;
...
String* input = S"Tim, sometimes you have to accept that times are changing.";
String* pattern = S"tim";

Console::WriteLine(S"Searching '{0}' for '{1}'", input, pattern);

Regex* rex = new Regex(pattern);
Match* match = rex->Match(input);
if (match->Success)
{
  Console::WriteLine(S"Found '{0}' at position {1}",
                     match->Value, 
                     __box(match->Index));

}

Searching for Multiple Matches with the MatchCollection Class

In the previous example, while the literal “tim” occurred several times in the input text, the code was designed to find only the first occurrence. Let’s see how the code can be modified to use the MatchCollection class in order to enumerate all matches within a string.

In the following code, I’ve made several changes:

  • The Regex constructor takes a second argument of type RegexOptions that enables you to specify things, such as whether the search is case-sensitive or not. (For this example, I’m specifying RegexOptions::IgnoreCase so that the code locates all occurrences of “tim” regardless of case.)
  • The code is using the Regex::IsMatch method to first verify whether any matches are found enumerating the MatchCollection. You can also check the count of the MatchCollection object so using either form is a subjective choice.
  • The MatchCollection object is retrieved via the Regex::Matches property. The MatchCollection object can be enumerated as any other .NET collection where the Count property indicates the number of objects held and individual objects are extracted via the collection’s Item property.
String* input = S"Tim, sometimes you have to accept that times are changing.";
String* pattern = S"tim";

Console::WriteLine(S"Searching '{0}' for '{1}'", input, pattern);

Regex* rex = new Regex(pattern, RegexOptions::IgnoreCase);
if (rex->IsMatch(input))
{
  MatchCollection* matches = rex->Matches(input);		
  for (int i = 0; i  <matches->Count; i++)
  {
    Match* match = matches->Item[i];
    Console::WriteLine(S"Found '{0}' at position {1}",
                       match->Value, 
                       __box(match->Index));
  }
}

Enumerating Matches with the NextMatch Method

Did you know you can enumerate matches without the MatchCollection class? This is accomplished by using the Match::NextMatch method to enumerate through the matches of an input string. Here’s an example that once again searches the same input string for occurrences of the literal “tim”:

String* input = S"Tim, sometimes you have to accept that times are changing.";
String* pattern = S"tim";

Console::WriteLine(S"Searching '{0}' for '{1}'", input, pattern);

Regex* rex = new Regex(pattern, RegexOptions::IgnoreCase);
for (Match* match = rex->Match(input);
     match->Success;
     match = match->NextMatch())
{
  Console::WriteLine(S"Found '{0}' at position {1}",
                     match->Value, 
                     __box(match->Index));
}

Looking Ahead

So far, we’ve covered the basics of splitting strings and using the Match/MatchCollection classes. Future articles continue in the .NET implementation of regular expressions by delving into how to form regular expression patterns to find what you’re looking for and the topics of groups and captures.

About the Author

Tom Archer owns his own training company, Archer Consulting Group, which specializes in educating and mentoring .NET programmers and providing project management consulting. If you would like to find out how the Archer Consulting Group can help you reduce development costs, get your software to market faster, and increase product revenue, contact Tom through his Web site.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories