2010-05-31 40 views
6

So sánh các số phiên bản dưới dạng chuỗi không phải là dễ dàng ...
"1.0.0.9"> "1.0.0.10", nhưng không chính xác.
Cách rõ ràng để làm điều đó đúng là phân tích các chuỗi này, chuyển đổi thành các số và so sánh dưới dạng số. Có cách nào khác để làm điều đó "thanh lịch" hơn không? Ví dụ: boost :: string_algo ...So sánh các phiên bản dưới dạng chuỗi

+1

http://stackoverflow.com/a/34484221/1318830 trả lời đó và sau đó tìm thấy câu hỏi của bạn –

+0

tôi đề nghị tạo lớp phiên bản thay vì chuỗi. bạn có thể cần '1.0.0.9 beta'. đó không phải là một số nguyên đơn giản so sánh. –

+2

Phiên bản C của câu hỏi này cho những người quan tâm: [so sánh số phiên bản trong c] (http://stackoverflow.com/questions/15057010) – hippietrail

Trả lời

23

Tôi không thấy những gì có thể thanh lịch hơn là chỉ phân tích cú pháp - nhưng hãy tận dụng tiện nghi thư viện chuẩn đã có sẵn. Giả sử bạn không cần kiểm tra lỗi:

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

Mọi thứ phức tạp hơn sẽ khó duy trì và không đáng để bạn dành thời gian.

+2

+1: Sử dụng gọn gàng STL. Typo trong 'std :: lexicographical_compare'. – Johnsyweb

+2

Thuật toán là tốt. Tôi muốn đề nghị gói nó như là một 'phiên bản lớp {Phiên bản (std :: string const &); toán tử bool <(Phiên bản const & rhs) const; }; '. Điều này cho phép bạn có một 'std :: set ' chẳng hạn. – MSalters

+0

@Johnsyweb: Cảm ơn bạn đã chọn lỗi đánh máy. @MSalters: Tôi đồng ý. Tôi đã không nói sử dụng này cho sản xuất - Tôi đã chỉ chứng minh các thuật toán tôi nghĩ rằng OP nên sử dụng. –

6

Tôi sẽ tạo lớp phiên bản.
Sau đó, đơn giản để xác định toán tử so sánh cho lớp phiên bản.

#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

Bạn nên sử dụng 'std :: vector :: assign' thay vì' std :: copy';) Nếu không +1. –

+0

Chỉ cần một gợi ý nhỏ để làm cho lớp học hoàn thiện hơn, điều hành khôn ngoan. Nếu _boost_ có sẵn, người ta có thể [lấy từ 'boost :: less_than_comparable'] (https://theboostcpplibraries.com/boost.operators) để tự động thêm' toán tử> ',' toán tử <= 'và' toán tử> = ' tất cả được thực hiện dưới dạng 'toán tử <'. Cũng hữu ích sẽ là 'operator ==' và lấy được từ 'boost :: equality_comparable' để cung cấp' toán tử! = '. – zett42

+0

@ zett42. Không cần điều đó. Để thêm các toán tử so sánh, tất cả những gì bạn cần làm là thêm 'using namespace std :: rel_ops'. [xem] (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; 
} 
Các vấn đề liên quan