Reputation: 2217
I am learning c++ and wondering what the best or most idiomatic way to do the following would be. I have a list of known accepted strings that will be constant for a program. I want to know if a string provided to a function is in the list of my accepted strings. I came up with:
bool match(const char* foo, const char* bar) {
return strcmp(foo, bar) == 0;
}
bool thingIsValid(const char* thing) {
return match("foo", thing) || match("bar", thing) || match("baz", thing);
}
...
thingIsValid(someArg.c_str());
...
This approach just seems to be more of the C idiom to me. In other languages I would probably just have a list and do a .contains(thing) on that list. How do people typically do this in C++?
Upvotes: 2
Views: 7556
Reputation: 706
The accepted answer uses a std::vector<std::string>
and says it is not ideal to keep this on the heap, but you don't need to use std::vector or std::string. The following should work, and the data will be stored in read only memory.
static auto banned_fnames = {
"..", ".", "AUX", "COM", "COM2", "COM3", "COM4", "COM5", "COM6",
"COM7", "COM8", "COM9", "CON", "LPT1", "LPT2", "LPT3", "LPT4",
"LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "NUL", "PRN",
};
auto stem = resolved_path.stem().string();
if (std::find(std::begin(banned_fnames), std::end(banned_fnames), fname) != std::end(banned_fnames))
{
error = fmt::format("Bad path: {} - banned filename", user_path);
return "";
}
Upvotes: 0
Reputation: 12485
Probably the best way these days is to use an unordered set:
std::unordered_set<std::string> ValidValues {"one", "two", "three"};
if( ValidValues.find( testString ) == ValidValues.end() ) {
// String is not valid...
}
The only real disadvantage here is that you can't simply lay out the valid strings in your executable image. (Setting up the set requires initialization code and heap allocations.) But that shouldn't really matter for the vast majority of applications.
Upvotes: 7
Reputation: 171127
One possible way to do it:
bool thingIsValid(const std::string &thing) {
static const std::vector<std::string> validValues {"foo", "bar", "baz"};
return std::find(validValues.begin(), validValues.end(), thing) != validValues.end();
}
The above piece of code uses C++11 list-initialisation to create the vector
. If you don't have C++11, you would have to construct the vector by using push_back()
.
Upvotes: 2