2010-05-31 2 views
6

Сравнение номеров версий как строк не так просто ...
«1.0.0.9"> "1.0.0.10", но это неверно.
Очевидный способ сделать это правильно - это проанализировать эти строки, преобразовать их в числа и сравнить их с числами. Есть ли другой способ сделать это более «элегантно»? Например, boost :: string_algo ...Сравнение версий как строк

+1

http://stackoverflow.com/a/34484221/1318830 Ответил там и затем нашел ваш вопрос –

+0

я предлагаю создать версию класса вместо строки. вам может понадобиться '1.0.0.9 beta'. это не просто сравнение целого числа. –

+2

C вариант этого вопроса для заинтересованных: [сравнение номеров версий в c] (http://stackoverflow.com/questions/15057010) – hippietrail

ответ

23

Я не вижу, что может быть более элегантным, чем просто синтаксический анализ - но , пожалуйста, использовать стандартные библиотечные возможности уже на месте. Если предположить, что вам не нужно проверять ошибки:

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); 
} 

Все сложнее будет труднее поддерживать и не стоит вашего времени.

+2

+1: Аккуратное использование STL. Typo в 'std :: lexicographic_compare'. – Johnsyweb

+2

Алгоритм хорош. Я бы предложил обернуть его как 'class Version {Version (std :: string const &); bool operator <(Version const & rhs) const; }; '. Это позволяет вам, например, установить 'std :: set '. – MSalters

+0

@Johnsyweb: Спасибо, что набрал опечатку. @MSalters: Я согласен. Я не говорил использовать это для производства - я просто демонстрировал алгоритм, который, как мне кажется, должен использовать OP. –

6

Я бы создал класс версии.
Тогда просто определить оператор сравнения для класса версии.

#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"; 
    } 
} 
+0

Вы должны использовать 'std :: vector :: assign' вместо' std :: copy';) В противном случае +1. –

+0

Просто небольшое предложение сделать класс более полным, оперативным. Если доступно _boost_, можно было бы [получить из 'boost :: less_than_comparable'] (https://theboostcpplibraries.com/boost.operators) автоматическое добавление' operator> ',' operator <= 'и' operator> = ' которые все реализованы в терминах 'operator <'. Также полезно было бы 'operator ==' и выводить из 'boost :: equal_comparable', чтобы обеспечить' operator! = '. – zett42

+0

@ zett42. Нет необходимости в этом. Чтобы добавить операторы сравнения, все, что вам нужно сделать, это добавить 'using namespace std :: rel_ops'. [см.] (http://www.cplusplus.com/reference/utility/rel_ops/) –

0
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; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^