Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare version numbers in C++ [duplicate]

Our professor want us to write a program to compare two version numbers, like 0.1 < 0.2 or 1 < 1.1. Also there are some trick ones like .0.4 < .1. So, my idea is first judge if the number start as a dot, if it does, I add a 0 to it. After that I remove other dots except the first one. Then I convert string to number and compare them. Here's what I do in the first step.

string numb1,numb2;
if(numb1[0]=='.')
{
    numb1 ="0"+ numb1;
}

I do the same thing to the second number. And now I need help to show me how to remove the dots except the first one. Our professor want us to use this specific function: int compareVersions(string ver1, string ver2). If ver1 > ver2: return 1 if ver1 < ver2: return -1 otherwise return 0.

By the way, some of the vision number may very long like 2.3.2.2.3.1.1.5.3.5.6.2 or 1.1.1.1.1.1.1.

like image 603
Huang Xu Avatar asked Oct 14 '15 20:10

Huang Xu


3 Answers

Here's one approach that should work for numerical version numbers:

  • Split the input strings into pieces using getline(strstream, token, ".")
  • Convert corresponding pieces to numbers using atoi or stol and compare numerically

Basically, treat the version numbers as sequences of numbers separated by . and compare those sequences lexicographically.


Note that a practical, general version number comparison algorithm probably needs to handle extra trickiness such as letter suffixes (e.g. 1.1e, 2.4b24, 3.5rc1), etc. I'm assuming that this is outside the scope of a class exercise, but the approach is similar: split these parts into sequences of numeric and non-numeric parts and compare each part (e.g. 2.4b7 < 2.4b24 because 4, "b", 7 < 4, "b", 24).

like image 124
nneonneo Avatar answered Oct 22 '22 01:10

nneonneo


Something like this would work to do the checking and is fairly minimal. It makes use of boost to split the string and then compares the version step by step. It automatically deals with missing leading zeros.

#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <iostream>

int version_a_newer_than_b(const std::string& a, const std::string& b)
{
    // First, split the string.
    std::vector<std::string> va, vb;
    boost::split(va, a, boost::is_any_of("."));
    boost::split(vb, b, boost::is_any_of("."));

    // Compare the numbers step by step, but only as deep as the version
    // with the least elements allows.
    const int depth = std::min(va.size(), vb.size());
    int ia,ib;
    for (int i=0; i<depth; ++i)
    {
        ia = atoi(va[i].c_str());
        ib = atoi(vb[i].c_str());
        if (ia != ib)
            break;
    }

    // Return the required number.
    if (ia > ib)
        return 1;
    else if (ia < ib)
        return -1;
    else
    {
        // In case of equal versions, assumes that the version
        // with the most elements is the highest version.
        if (va.size() > vb.size())
            return 1;
        else if (va.size() < vb.size())
            return -1;
    }

    // Everything is equal, return 0.
    return 0;
}

int main()
{
    std::string a = "0.1.32.8";
    std::string b = "0.1";

    std::cout << "Is a newer than b: " << version_a_newer_than_b(a, b) << std::endl;

    return 0;
}
like image 40
Chiel Avatar answered Oct 22 '22 01:10

Chiel


What you need to do is iterate through the string, ignoring '.' and converting the char representations of numbers into ints. Then compare the two end results.

string numb1 = "4.3.2";
string numb2 = "3.4.5";
int n1 = 0;
int n2 = 0; 

for (int i = 0; i < numb1.length(); i++)
{
    if (numb1[i] != '.')
    {   
        n1 = n1 * 10;
        n2 = n2 * 10;
        n1 += (int(numb1[i]) - '0');
        n2 += (int(numb2[i]) - '0');                
    }

}

That will give you 432 and 345, comparing those would give you which is the higher version.

like image 1
Tyler Avatar answered Oct 22 '22 02:10

Tyler