In this part of my C++ tutorial I finish covering C++ with Regular Expressions. If you missed the 1st part watch it first.
This time I’ll cover Back References, Substitutions, Look Ahead, Or Conditionals and 3 problems for you to solve. All of the heavily commented code follows the video below. Use it to receive the best results in your studies.
If you like videos like this consider donating $1, or simply turn off Ad Blocking software. Either helps me to continue making free tutorials.
Code from the Video
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <thread>
#include <ctime>
#include <regex>
void PrintMatches(std::string str,
std::regex reg){
// Used when your searching a string
std::smatch matches;
// Determines if there is a match and match
// results are returned in matches
while(std::regex_search(str, matches, reg)){
// Get the first match
std::cout << matches.str(1) << "\n";
// Eliminate the previous match and create
// a new string to search
str = matches.suffix().str();
}
std::cout << "\n";
}
// [ ] : Match what is in the brackets
// [^ ] : Match anything not in the brackets
// ( ) : Return surrounded submatch
// . : Match any 1 character or space
// + : Match 1 or more of what proceeds
// ? : Match 0 or 1
// * : Match 0 or More
// *? : Lazy match the smallest match
// \b : Word boundary
// ^ : Beginning of String
// $ : End of String
// \n : Newline
// \d : Any 1 number
// \D : Anything but a number
// \w : Same as [a-zA-Z0-9_]
// \W : Same as [^a-zA-Z0-9_]
// \s : Same as [\f\n\r\t\v]
// \S : Same as [^\f\n\r\t\v]
// {5} : Match 5 of what proceeds the curly brackets
// {5,7} : Match values that are between 5 and 7 in length
int main()
{
// ---------- Back References ----------
// A back reference allows you to to reuse the expression
// that proceeds it
// Grab a double word
std::string str1 = "The cat cat fell out the window";
// Match word boundary, 1 or more characters, space
// and the same word that proceeded it
// \\1 is used to refer to the 1st match surrounded
// by ()
std::regex reg1 ("(\\b\\w+)\\s+\\1");
PrintMatches(str1,reg1);
// ---------- Back Reference Substitutions ----------
// Replace the bold tags in the link with no tags
std::string str2 = "<a href='#'><b>The Link</b></a>";
// Regex matches bold tags and grabs the text between
// them to be used by the back reference
std::regex reg2 ("<b>(.*?)</b>");
// Holds the new string
std::string result;
// regex_replace makes a copy of the original
// along with the replaced parts
// back_inserter inserts the final results
// into result
// $1 references the subexpression surrounded
// with () ex. (.*?)
std::regex_replace(std::back_inserter(result),
str2.begin(), str2.end(), reg2, "$1");
std::cout << result << "\n";
// ---------- Another Back Reference Substitution ----------
// Here I want to surround all phone number
// area codes with ()
std::string str3 = "412-555-1212";
// I create 2 subexpressions
std::regex reg3 ("([\\d]{3})-([\\d]{3}-[\\d]{4})");
// Holds the new string
std::string res3;
// The output is the area code surrounded with ()
// and then the 2nd subexpression
std::regex_replace(std::back_inserter(res3),
str3.begin(), str3.end(), reg3, "($1)$2");
std::cout << res3 << "\n";
// ---------- PROBLEM ----------
// Receive a string like this
std::string str4 = "https://www.youtube.com "
"http://www.google.com";
// Grab the URL and then provide the following output
// using a back reference substitution
// <a href='https://www.youtube.com'>www.youtube.com</a>
// <a href='https://www.google.com'>www.google.com</a>
// Grab the whole URL and the web page name
std::regex reg4 ("(https?://([\\w.]+))");
// Holds the new string
std::string res4;
std::regex_replace(std::back_inserter(res4),
str4.begin(), str4.end(), reg4,
"<a href='$1'>$2</a>\n");
std::cout << res4 << "\n";
// ---------- Look Ahead ----------
// A look ahead defines a pattern to match but not
// return
// You define the expression to look for but not
// return
// like this (?=expression)
std::string str5 = " one two three four ";
// I don't want to return the word boundaries
std::regex reg5 ("(\\w+(?=\\b))");
PrintMatches(str5,reg5);
// ---------- OR Conditional ----------
// You can use | to define the matches you'll except
std::string str6 = "1. Dog 2. Cat 3. Turtle";
std::regex reg6 ("\\d\\.\\s(Dog|Cat)");
PrintMatches(str6,reg6);
// ---------- PROBLEM ----------
// Create a regex that will match for 5 digit zip
// codes or zip codes with 5 digits a dash and
// then 4 digits
std::string str7 = "12345 12345-1234 1234 12346-333";
std::regex reg7 ("(\\d{5}-\\d{4}|\\d{5}\\s)");
PrintMatches(str7,reg7);
// ---------- PROBLEM ----------
// Find all of the following phone numbers
// and then print them
std::string str8 = "14125551212 4125551212 "
"(412)5551212 412 555 1212 412-555-1212 "
"1-412-555-1212";
std::regex reg8 ("((1?)(-| ?)(\\()?(\\d{3})(\\)|-| |\\)-|\\) )?(\\d{3})(-| )?(\\d{4}|\\d{4}))");
PrintMatches(str8,reg8);
return 0;
}