In this article we will discuss how to find all occurrences / Positions of a sub string in a given string in both case sensitive & case insensitive manner.
Find All Case Sensitive Occurrences of a Sub String in a given String
Logic:
Use std::string::find to search the first occurrence and then go on searching using same logic from that position onward, till you reach the end.
Complete example is as follows,
#include <iostream> #include <string> #include <algorithm> /* *Find all positions of the a SubString in given String */ void findAllOccurances(std::vector<size_t> & vec, std::string data, std::string toSearch) { // Get the first occurrence size_t pos = data.find(toSearch); // Repeat till end is reached while( pos != std::string::npos) { // Add position to the vector vec.push_back(pos); // Get the next occurrence from the current position pos =data.find(toSearch, pos + toSearch.size()); } } int main() { std::string data = "Hi this is a Sample string, 'iS' is here 3 times"; std::vector<size_t> vec; // Get All occurrences of the 'is' in the vector 'vec' findAllOccurances(vec, data , "is"); std::cout<<"All Index Position of 'is' in given string are,"<<std::endl; for(size_t pos : vec) std::cout<<pos<<std::endl; return 0; }
Output:
All Index Position of 'is' in given string are, 5 8 33
As it’s internally using std::string::find to the sub string therefore it is case sensitive and able to find 3 occurrences only.
Find All Case Sensitive occurrence of a Sub String in a given String
We will use the same logic as above i.e. keep on search the occurrences of sub string till reaches the end.
But to find an occurrence of sub string, we will use customized case insensitive version of std::string::find .
Frequently Asked:
- Implementing a Case Insensitive string::find in C++
- Find all occurrences of a sub string in a string | C++ | Both Case Sensitive & InSensitive
- Find and Replace all occurrences of a sub string in C++
Checkout the complete code as follows,
#include <iostream> #include <string> #include <algorithm> // Case Insensitive version of std::string::find size_t findCaseInsensitive(std::string data, std::string toSearch, size_t pos = 0) { // Convert String to lower case std::transform(data.begin(), data.end(), data.begin(), ::tolower); // Convert String to lower case std::transform(toSearch.begin(), toSearch.end(), toSearch.begin(), ::tolower); return data.find(toSearch, pos); } /* *Find all positions of the a Case Insensitive Sub String in given String */ void findAllOccurancesCaseInsensitive(std::vector<size_t> & vec, std::string data, std::string toSearch) { // Find First Position size_t pos = findCaseInsensitive(data,toSearch); // Iterate till end while( pos != std::string::npos) { // Push position in vector vec.push_back(pos); // Search next position pos = findCaseInsensitive(data,toSearch, pos + toSearch.size()); } } int main() { std::string data = "Hi this is a Sample string, 'iS' is here 4 times"; std::vector<size_t> vec; // Get All case insensitive occurrences of the 'is' in the vector 'vec' findAllOccurancesCaseInsensitive(vec, data , "IS"); std::cout<<"All Index Position of 'is' in given string are,"<<std::endl; for(size_t pos : vec) std::cout<<pos<<std::endl; return 0; }
Output:
All Index Position of 'is' in given string are, 5 8 29 33
Because we are using case insensitive version of std::string::find, therefore we will get 4 reparations of sub string.
Generic Find All Implementation
We don’t need to maintain 2 separate functions to find all occurrences, we can create a generic find_all function, that will accept String Finder function as callback and use it to find repeated occurrences of sub strings i.e.
typedef size_t (* FINDFUNCTOR)(std::string data, std::string toSearch, size_t pos); void findAllOccurances(std::vector<size_t> & vec, std::string data, std::string toSearch, FINDFUNCTOR finder) { // Find first occurrence size_t pos = finder(data, toSearch, 0); // Iterate till last while( pos != std::string::npos) { vec.push_back(pos); // Find next occurrence pos =finder(data, toSearch, pos + toSearch.size()); } }
Let’s use this above function to find case insensitive substrings by passing findCaseInsensitive as callback
// Find All case insensitive occurrences of the 'is' in the vector 'vec' findAllOccurances(vec, data , "iS", &findCaseInsensitive);
Let’s use this above function to find case sensitive substrings by passing std::string::find as callback i.e.
// Get All Case Sensitive occurrences of the 'is' in the vector 'vec' findAllOccurances(vec, data , "iS", [&](std::string data, std::string toSearch, size_t pos){ return data.find(toSearch, pos); });
Complete example is as follows,
#include <iostream> #include <string> #include <vector> #include <algorithm> #include <functional> // Case Insensitive version of std::string::find size_t findCaseInsensitive(std::string data, std::string toSearch, size_t pos = 0) { // Convert String to lower case std::transform(data.begin(), data.end(), data.begin(), ::tolower); // Convert String to lower case std::transform(toSearch.begin(), toSearch.end(), toSearch.begin(), ::tolower); return data.find(toSearch, pos); } typedef size_t (* FINDFUNCTOR)(std::string data, std::string toSearch, size_t pos); void findAllOccurances(std::vector<size_t> & vec, std::string data, std::string toSearch, FINDFUNCTOR finder) { // Find first occurrence size_t pos = finder(data, toSearch, 0); // Iterate till last while( pos != std::string::npos) { vec.push_back(pos); // Find next occurrence pos =finder(data, toSearch, pos + toSearch.size()); } } int main() { std::string data = "Hi this is a Sample string, iS is 3 times here"; std::vector<size_t> vec; std::cout<<"All Index Position of Case InSensitive 'is' in given string are,"<<std::endl; // Find All case insensitive occurrences of the 'is' in the vector 'vec' findAllOccurances(vec, data , "iS", &findCaseInsensitive); for(size_t pos : vec) std::cout<<pos<<std::endl; vec.clear(); std::cout<<"All Index Position of Case Sensitive 'is' in given string are,"<<std::endl; // Get All Case Sensitive occurrences of the 'is' in the vector 'vec' findAllOccurances(vec, data , "iS", [&](std::string data, std::string toSearch, size_t pos){ return data.find(toSearch, pos); }); for(size_t pos : vec) std::cout<<pos<<std::endl; return 0; }
Output
All Index Position of Case InSensitive 'is' in given string are, 5 8 28 31 All Index Position of Case Sensitive 'iS' in given string are, 28