Reputation: 65
I am trying to make a search function in my application. If the user inputs a substring (or the complete string) I want to know if that substring matches any of the strings or part of the strings stored in my vector.
The following code is written so far:
cout << "Input word to search for: ";
cin >> searchString;
for (multimap <string, vector<string> >::const_iterator it = contactInformationMultimap.cbegin(); it != contactInformationMultimap.cend(); ++it)
{
for (vector<string>::const_iterator iter = it->second.cbegin(); iter != it->second.cend(); ++iter)
{
if (*iter.find(searchString))
^^^^^^^^^^^^^^^^^^^^^^^ this does not work, if i cout *iter it is the correct word stored in the vector. The problem is that i can not use the find function.
}
}
Anyone having any suggestions?
Upvotes: 2
Views: 3098
Reputation: 490148
The comments have shown how to correct the syntax so your code can compile, but the result is code that I'd still (at least personally) rather avoid. The primary reason for iterators to allow their use in generic algorithms. In this case, generic algorithms can do the job quite nicely. For example, let's assume that you wanted to print out the key for every record that the value associated with that key contained whatever value was in searchString
. To do that you could write the code like this:
std::copy_if(data.begin(), data.end(), // The source "range"
std::ostream_iterator<T>(std::cout, "\n"), // the destination "range"
[&](T const &v) {
return std::any_of(v.second.begin(), v.second.end(),
[&](std::string const &s) {
return s.find(searchString) != std::string::npos;
}
);
}
);
This depends on an operator<<
for the correct type, something like this:
typedef std::pair < std::string, std::vector<std::string>> T;
namespace std {
std::ostream &operator<<(std::ostream &os, T const &t) {
return os << t.first;
}
}
A complete test program could look like this:
#include <map>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
typedef std::pair < std::string, std::vector<std::string>> T;
namespace std {
std::ostream &operator<<(std::ostream &os, T const &t) {
return os << t.first;
}
}
int main() {
std::multimap<std::string, std::vector<std::string>> data{
{ "key1", { "Able", "Bend", "Cell" } },
{ "key2", { "Are", "Dead" } },
{ "key3", { "Bad", "Call" } }
};
std::string searchString = "a";
std::copy_if(data.begin(), data.end(),
std::ostream_iterator<T>(std::cout, "\n"),
[&](T const &v) {
return std::any_of(v.second.begin(), v.second.end(),
[&](std::string const &s) {
return s.find(searchString) != std::string::npos;
}
);
}
);
}
Result:
key2
key3
Upvotes: 0
Reputation: 310990
Unary operators have less priority than postfix operators. In your if statement you need that the unary operator * would be evaluated before member access operator. So you have to write
if ( ( *iter ).find(searchString) != std::string::npos )
Or you could write
if ( iter->find(searchString) != std::string::npos )
Take into account that this record
if ( ( *iter ).find(searchString) )
makes no sense.
Also you could write
for (multimap <string, vector<string> >::const_iterator it = contactInformationMultimap.cbegin(); it != contactInformationMultimap.cend(); ++it)
{
for ( const std::string &s : it->second )
{
if ( s.find(searchString ) != std::string::npos ) /*...*/;
}
}
Upvotes: 2