Comparer les numéros de version en tant que chaînes n'est pas si facile ...
"1.0.0.9"> "1.0.0.10", mais ce n'est pas correct.
La façon évidente de le faire correctement est d'analyser ces chaînes, de les convertir en nombres et de les comparer en nombres. Existe-t-il une autre façon de le faire plus "élégamment"? Par exemple, boost :: string_algo ...Comparer les versions en tant que chaînes
Répondre
Je ne vois pas ce qui pourrait être plus élégant que l'analyse simple - mais s'il vous plaît utiliser les installations de bibliothèque standard déjà en place. En supposant que vous n'avez pas besoin de vérification d'erreur:
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);
}
Rien de plus compliqué va être plus difficile à maintenir et ne vaut pas votre temps.
+1: Utilisation STL soignée. Typo dans 'std :: lexicographical_compare'. – Johnsyweb
L'algorithme est bon. Je suggère de l'envelopper comme une classe Version {Version (std :: string const &); opérateur bool <(const const & rhs) const; }; '. Cela vous permet d'avoir un 'std :: set
@Johnsyweb: Merci d'avoir relevé la faute de frappe. @ MSalters: Je suis d'accord. Je ne disais pas l'utiliser pour la production - je ne faisais que démontrer l'algorithme que le PO devrait utiliser. –
Je créer une classe de version.
Ensuite, il est simple de définir l'opérateur de comparaison pour la classe de version.
#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";
}
}
Vous devriez utiliser 'std :: vector
Juste une petite suggestion pour rendre la classe plus complète, en ce qui concerne l'opérateur. Si _boost_ est disponible, on pourrait [dériver de 'boost :: less_than_comparable'] (https://theboostcpplibraries.com/boost.operators) pour ajouter automatiquement' operator> ',' operator <= ', et' operator> = ' qui sont tous implémentés en termes de 'operator <'. Aussi utile serait 'operator ==' et dériver de 'boost :: equality_comparable' pour fournir' operator! = '. – zett42
@ zett42. Pas besoin de çà. Pour ajouter les opérateurs de comparaison, il suffit d'ajouter 'using namespace std :: rel_ops'. [Voir] (http://www.cplusplus.com/reference/utility/rel_ops/) –
int VersionParser(char* version1, char* version2) {
int a1,b1, ret;
int a = strlen(version1);
int b = strlen(version2);
if (b>a) a=b;
for (int i=0;i<a;i++) {
a1 += version1[i];
b1 += version2[i];
}
if (b1>a1) ret = 1 ; // second version is fresher
else if (b1==a1) ret=-1; // versions is equal
else ret = 0; // first version is fresher
return ret;
}
http://stackoverflow.com/a/34484221/1318830 répondue puis trouvé votre question –
je suggère que créer la classe de version au lieu de chaîne. vous pourriez aussi avoir besoin de '1.0.0.9 beta'. ce n'est pas un simple comparatif entier. –
Version C de cette question pour ceux qui sont intéressés: [comparer les numéros de version en c] (http://stackoverflow.com/questions/15057010) – hippietrail