Reputation: 439
I'm asked to accept both a number and a unit, where a unit can be cm, m, in or ft.
For this I have a loop as such
cout << "Please put in a number and its unit.\n";
while (cin >> val >> unit) {
if (val == '|') { break; }
cout << "Please put in a number and its unit.\n";
}
My question is, what is the best way to check the unit string, when it comes to code efficiency as well as readability? Does it make more sense to put a large if statement
if (unit != "cm" && unit != "m" && unit != "in" && unit != "ft") {
cout << "Unit " << unit << " not accepted.\n";
}
Or is it better to have a vector which I initialise with all the units, and then check if it matches any of the units.
if (find(units.begin(), units.end(), unit) == units.end()) {
cout << "Unit " << unit << " not accepted.\n";
}
... where vector<string> units = {"cm", "m", "in", "ft"};
Or is there another way which is much better in terms of efficiency and readability?
I hope this is the right place to ask this question. I thought about code review but it doesn't seem to fit a small question like this.. or does it?
Upvotes: 1
Views: 109
Reputation: 32847
Does it make more sense to put a large if statement?
The only four entries, I would say that you do not need to use std::vector
(and the allocation cost comes up with it) and an algorithm to test the case. If the length of the if the condition is bothering you, pack the condition to a lambda function and call with the user input.
Proper naming of lambda would give much readability than checking the variable directly inside the if
statement.
const auto isMatchingUnit = [](const std::string& unit) noexcept -> bool {
return unit == "cm" || unit == "m" || unit == "in" || unit == "ft";
};
if (isMatchingUnit(unit)) {
// do something
} else {
// do something else
}
That being said, if the number of possible input s are large, you might wanna pack the possible inputs to std::array
or std::vector
and apply the standard algorithms as per choice:
If the collection to be checked is sorted and unique you can
true
, if item is found.std::lower_bound(container.cbegin(), container.cend(), input) != container.cend()
, for true
case.If the collection to be checked is not sorted
std::find(container.cbegin(), container.cend(), input) != container.cend()
, for true
case.Upvotes: 1
Reputation: 40679
Your "if" statement is not only more efficient, but efficiency doesn't matter because no matter how you do it, the IO will take about a billion times longer.
It's also the most maintainable because if you format the "if" statement as one line per unit string, then adding, removing, or renaming a unit is only a 1-line edit, and you can easily comment them out or in if you change your mind.
The time to use a vector is if you don't know what the units are until run time.
Upvotes: 1
Reputation: 11168
The most efficient would be using std::lower_bound on a sorted array of strings, so it doesn't search all of them. If you use direct comparison or std::find, then all will be searched.
For a small vector, it might not be important (it might even be slower than a direct comparison), but for larger sets it will.
Upvotes: 0