Comparing version numbers as strings is not so easy...
"1.0.0.9" > "1.0.0.10", but it's not correct.
Obvious way to do it properly is parse these strings, convert to numbers and compare as numbers.
Is it other way to do it more "elegant"? For example, boost::string_algo...
views:
134answers:
2
+10
A:
I don't see what could be more elegant than just parsing -- but please make use of standard library facilities already in place. Assuming you don't need error checking:
void Parse(int result[4], const std::string& input)
{
std::istringstream parser(input);
parser >> result[0];
for(int idx = 1; idx < 4; idx++)
{
parser.get(); //Skip period
parser >> result[idx];
}
}
bool LessThanVersion(const std::string& a,const std::string& b)
{
int parsedA[4], parsedB[4];
Parse(parsedA, a);
Parse(parsedB, b);
return std::lexicographical_compare(parsedA, parsedA + 4, parsedB, parsedB + 4);
}
Anything more complicated is going to be harder to maintain and isn't worth your time.
Billy ONeal
2010-05-31 05:25:47
+1: Neat STL usage. Typo in `std::lexicographical_compare`.
Johnsyweb
2010-05-31 06:17:22
The algorithm is good. I'd suggest wrapping it as a `class Version { Version(std::string const bool operator<(Version const };`. This allows you to have a `std::set<Version>` for instance.
MSalters
2010-05-31 08:37:35
@Johnsyweb: Thanks for picking up on the typo. @MSalters: I agree. I wasn't saying use this for production -- I was just demonstrating the algorithm I think the OP should use.
Billy ONeal
2010-05-31 13:32:33
+2
A:
I would create a version class.
Then it is simple to define the comparison operator for the version class.
#include <iostream>
#include <sstream>
#include <vector>
#include <iterator>
class Version
{
// An internal utility structure just used to make the std::copy in the constructor easy to write.
struct VersionDigit
{
int value;
operator int() const {return value;}
};
friend std::istream& operator>>(std::istream& str, Version::VersionDigit& digit);
public:
Version(std::string const& versionStr)
{
// To Make processing easier in VersionDigit prepend a '.'
std::stringstream versionStream(std::string(".") + versionStr);
// Copy all parts of the version number into the version Info vector.
std::copy( std::istream_iterator<VersionDigit>(versionStream),
std::istream_iterator<VersionDigit>(),
std::back_inserter(versionInfo)
);
}
// Test if two version numbers are the same.
bool operator<(Version const& rhs) const
{
return std::lexicographical_compare(versionInfo.begin(), versionInfo.end(), rhs.versionInfo.begin(), rhs.versionInfo.end());
}
private:
std::vector<int> versionInfo;
};
// Read a single digit from the version.
std::istream& operator>>(std::istream& str, Version::VersionDigit& digit)
{
str.get();
str >> digit.value;
return str;
}
int main()
{
Version v1("10.0.0.9");
Version v2("10.0.0.10");
if (v1 < v2)
{
std::cout << "Version 1 Smaller\n";
}
else
{
std::cout << "Fail\n";
}
}
Martin York
2010-05-31 07:04:18
You should use `std::vector<T>::assign` instead of `std::copy` ;) Otherwise +1.
Billy ONeal
2010-05-31 13:31:17