Using std::search to find multiple occurrence of pattern - c++

I want to use function search or other similar function to find multiple occurrence of given pattern.
This is my code:
#include <cstring>
#include <iostream>
#include <iomanip>
#include <set>
#include <list>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>
using namespace std;
int main () {
std::vector<int> haystack;
string a = "abcabcabc";
string b = "abc";
string::iterator it;
it = search(a.begin(),a.end(),b.begin(),b.end());
if(it!=a.end()){
cout << it-a.begin()<<endl;
}
return 0;
}
This code return 0 as the first occurrence of pattern "abc" , would like to return 0, 3, 6. That would be all of the indexes in the original string where pattern begins.
Thank you for any help.

for(size_t pos=a.find(b,0); pos!=std::string::npos; pos=a.find(b,pos+1)) {
std::cout << pos << std::endl;
}
This uses std::basic_string::find (ref) directly to find the starting position of the substring.

The search function searches the first string a for any occurence of the elements of the second string b. As Your second string contains the elements a, b and c the code would return an iterator to the first position, then to the second, the third one,...
What You what to use is the find function. It returns an iterator to the element that equals the one that You were searching for. In Your case You're search the string a for the element abc. So You would have to call
string::iterator it = std::find(a.begin(), a.end(), "abc");
while (it != a.end()) {
// Do whatever you want to do...
++it;
it = std::find(it, a.end(), "abc");
}

//find first result index
auto find_index = str.find("st");
while(string::npos != find_index) {
cout << "found at: " << find_index << endl;
//find next
find_index = str.find("st",find_index+1);
}

Related

How to use a vector to pass multiple strings into a function

I have a function that reads a file to find a certain word. The system I currently have however searched for a specific word and isn't case sensitive. I can't simply use .find("word" && "Word")
As far as I can tell, the easiest way to do this would be with a vector with both versions of the word inside for the function to look for both however I can't figure out how to pass the vector into the function.
Any help would be appreciated. Thanks
You may just call find for every possible word in your vector. But i would suggest to use only lowercase if possible
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
int main()
{
std::string str = "HeLlo WorLd";
std::vector<std::string> vec{ "HELLO","HeLlo","hEllO","WORLD","WorLd" };
std::for_each(vec.begin(), vec.end(), [&](const std::string& comp)
{
auto found = str.find(comp);
if (found != std::string::npos)
std::cout << "Found World " << comp << " in str at " << std::distance(str.begin(), str.begin() + found) << std::endl;
});
return 0;
}
In c++ you can pass the vector to a function as a reference or absolute value. To pass as the reference, You can follow this approach.
int fun(std::vector<std::string>& arr) {
int value = 0;
// your operation
return value;
}
int main() {
std::vector<std::string> arr;
// your logic
int value = fun(arr);
return 0;
}

sort in lexicographic order in map C++

I am using STL map in C++ for counting the frequency of words in a text file and words must be sort in lexicographic order. Input data is given as a text file. Ive already read and added them in map but i got a problem with sorting.
Example, i have { "Abc", "abc", "bag", "Boom", "great"}. When i added them in map, i got
Abc 1 Boom 1 abc 1 bag 1 great 1
but expected result is
Abc 1 abc 1 Boom 1 bag 1 great 1
#include <iostream>
#include <cstring>
#include <map>
#include <fstream>
using namespace std;
typedef map<string, int> word_count;
int main(){
word_count wc;
fstream f_in;
f_in.open("test.in");
string x;
while( !f_in.eof()){
f_in >> x;
wc[x]++;
}
f_in.close();
return 0;
}
Here is my code for reading input. Any help for my problem? Thanks
The OP wants a custom sort order that's subtly different from the standard lexicographical order. A map with a custom sort order can be achieved by passing in a custom Compare (Compare is the third template parameter of map):
#include <algorithm>
#include <cctype>
#include <cstring>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <vector>
using std::string;
using std::transform;
using std::map;
using std::cout;
struct Compare {
bool operator() (const string& s0, const string& s1) const {
// construct all lowercase versions of s0 and s1
string str0(s0.length(),' ');
string str1(s1.length(),' ');
transform(s0.begin(), s0.end(), str0.begin(), tolower);
transform(s1.begin(), s1.end(), str1.begin(), tolower);
if (!str0.empty() and !str1.empty() and str0.front()==str1.front()) {
// do a standard lexicographic sort if the first character is the same
return s0 < s1;
}
else {
// otherwise, do a case-insensitive lexicographic sort using the lowercased strings
return str0 < str1;
}
}
};
typedef map<string, int, Compare> word_count;
int main(){
word_count wc;
auto words = { "Abc", "abc", "bag", "Boom", "great"};
for (auto word : words)
wc[word]++;
for(auto elem : wc)
cout << elem.first << " " << elem.second << '\n';
return 0;
}
This indeed produces the desired output:
Abc 1
abc 1
Boom 1
bag 1
great 1
Try out a live version of the code online
By default, the third template parameter of a map is less<key> (in this case, less<string>), which will sort strings in the standard lexicographical A-z order.
Here is a complete example with file reading included, and using the base sorting functionality of std::map.
#include <iostream>
#include <cstring>
#include <map>
#include <fstream>
typedef std::map<std::string, int> word_count;
int main(int argc, char** argv){
if(argc < 2){
std::cout << "Please provide a file name." << std::endl;
return 1;
}
word_count wc;
std::ifstream inputfile(argv[1]);
if (inputfile.is_open()){
std::string x;
while(inputfile >> x){
wc[x]++;
}
inputfile.close();
}else {std::cout << "Program aborted: unable to open input file" << std::endl; return 1;}
for(auto word: wc){
std::cout << word.first << "\t" << word.second << std::endl;
}
return 0;
}

How to check if a string contains punctuation c++

I am attempting to iterate over a string to check for punctuation. I've tried to use ispunct() but am receiving an error that there is no matching fucntion for call to ispunct. Is there a better way to implement this?
for(std::string::iterator it = oneWord.begin(); it != oneWord.end(); it++)
{
if(ispunct(it))
{
}
}
Is there a better way to implement this?
Use std::any_of:
#include <algorithm>
#include <cctype>
#include <iostream>
int main()
{
std::string s = "Contains punctuation!!";
std::string s2 = "No puncuation";
std::cout << std::any_of(s.begin(), s.end(), ::ispunct) << '\n';
std::cout << std::any_of(s2.begin(), s2.end(), ::ispunct) << '\n';
}
Live Example
it is an iterator; it points to a character in a string. You have to dereference it to get the thing it points to.
if(ispunct(static_cast<unsigned char>(*it)))

std::set_Differences Not working with read files

I have a strange issue with the set_differences function from the <algorithm> header. I am attempting to read two text files line by line and each line is put into a corresponding set. For some reason set-difference does not detect any difference between the two sets though there most certainly are. When I hardcode populate two sets it works just fine. It must be something with the content of the strings read from the files but I can't figure out what.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <set>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
std::set<std::string> listOfFiles(std::string fileName) {
std::ifstream tempFile;
tempFile.open(fileName.c_str());
std::string X;
std::set<std::string> fileNameSet;
if (tempFile.is_open()) {
while (std::getline(tempFile, X)) {
fileNameSet.insert(X);
}
}
else {
std::cerr << "Failed to open " + fileName + "\n";
exit(0);
}
return fileNameSet;
}
std::set<std::string> setDifferences(std::set<std::string> a, std::set<std::string> b) {
using namespace std;
set<string> result;
set_difference( a.begin(), a.end(), b.begin(), b.end(), inserter(result, result.begin()));
cout << "Difference" << endl << "-------------" << endl;
for (set<string>::const_iterator i = result.begin(); i != result.end(); ++i) {
cout << *i << endl;
}
return result;
}
int main()
{
std::set<std::string> initialSet = listOfFiles("test1.txt");
std::set<std::string> afterNGD = listOfFiles("test2.txt");
std::set<std::string> result, result2;
std::set<std::string> a, b;
a.insert("one");
a.insert("two");
a.insert("three");
b.insert("a");
b.insert("b");
b.insert("three");
//Fails: result is empty
result = setDifferences(initialSet, afterNGD);
//Pass: result2 constains strings "one" and "two"
result2 = setDifferences(a,b);
return 0;
}
My text files contain:
test1.txt
.Xil
fileNames.txt
hostlistfile.txt
ipcore_dir
iseconfig
item.prj
item.sch
item.sym
item.syr
item.ucf
item.vhf
item.xdl
item.xst
item_bitgen.xwbt
item_guide.ncd
item_summary.html
pa.fromNcd.tcl
planAhead.ngc2edif.log
planAhead_pid11956.debug
planAhead_pid1272.debug
planAhead_pid16492.debug
planAhead_pid19040.debug
planAhead_pid7804.debug
planAhead_pid9888.debug
planAhead_run_1
planAhead_run_2
sch2HdlBatchFile
SingleItemTest.gise
SingleItemTest.tcl
SingleItemTest.xise
template files
templates
xst
_xmsgs
text2.txt:
.Xil
fileNames.txt
hostlistfile.txt
ipcore_dir
iseconfig
item.bld
item.lso
item.ngc
item.ngd
item.ngr
item.prj
item.sch
item.sym
item.syr
item.ucf
item.vhf
item.xdl
item.xst
item_bitgen.xwbt
item_guide.ncd
item_ngdbuild.xrpt
item_summary.html
item_vhdl.prj
item_xst.xrpt
pa.fromNcd.tcl
planAhead.ngc2edif.log
planAhead_pid11956.debug
planAhead_pid1272.debug
planAhead_pid16492.debug
planAhead_pid19040.debug
planAhead_pid7804.debug
planAhead_pid9888.debug
planAhead_run_1
planAhead_run_2
sch2HdlBatchFile
SingleItemTest.gise
SingleItemTest.tcl
SingleItemTest.xise
template files
templates
xlnx_auto_0_xdb
xst
_ngo
_xmsgs
From the reference:
Copies the elements from the sorted range [first1, last1) which are
not found in the sorted range [first2, last2) to the range beginning
at d_first.
From your example files, all the elements in text1.txt can be found in text2.txt, so the output is as expected.

C++ substring contained between 2 specific characters

In c++ would like to extract all substrings in a string contained between specific characters, as example:
std::string str = "XPOINT:D#{MON 3};S#{1}"
std::vector<std:string> subsplit = my_needed_magic_function(str,"{}");
std::vector<int>::iterator it = subsplit.begin();
for(;it!=subsplit.end(),it++) std::cout<<*it<<endl;
result of this call should be:
MON 3
1
also using boost if needed.
You could try Regex:
#include <iostream>
#include <iterator>
#include <string>
#include <regex>
int main()
{
std::string s = "XPOINT:D#{MON 3};S#{1}.";
std::regex word_regex(R"(\{(.*?)\})");
auto first = std::sregex_iterator(s.begin(), s.end(), word_regex),
last = std::sregex_iterator();;
while (first != last)
std::cout << first++->str() << ' ';
}
Prints
{MON 3} {1}
Demo.