Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

comparing version numbers in c

I am seeing a lot of answers for this problem in other languages but I am trying to find out a way to compare 2 version numbers given as strings. For example

str1 = "141.1.23"
str2 = "141.1.22"

I am trying to find a way to compare the integer values in the strings to see which one is larger. (In this case str1 would be larger). I thought about using sometime of combination with atoi and strtok but I know I wont be able to tokenize 2 strings at once. Any advice?

like image 516
bardockyo Avatar asked Feb 24 '13 21:02

bardockyo


People also ask

How do I compare two versions of numbers?

To compare version numbers, compare their revisions in left-to-right order. Revisions are compared using their integer value ignoring any leading zeros. This means that revisions 1 and 001 are considered equal. If a version number does not specify a revision at an index, then treat the revision as 0 .

How do I compare two versions of strings?

compareVersions(String v1, String v2) compares two version strings. It returns 0 if the versions are equal, 1 if version v1 is before version v2, -1 if version v1 is after version v2, -2 if version format is invalid.

How do I compare versions in C++?

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.


2 Answers

I really wonder why people strive for such complicated solutions when there is sscanf in C. Here is a very simple solution to that problem that will work for 99% of all use cases:

int compVersions ( const char * version1, const char * version2 ) {
    unsigned major1 = 0, minor1 = 0, bugfix1 = 0;
    unsigned major2 = 0, minor2 = 0, bugfix2 = 0;
    sscanf(version1, "%u.%u.%u", &major1, &minor1, &bugfix1);
    sscanf(version2, "%u.%u.%u", &major2, &minor2, &bugfix2);
    if (major1 < major2) return -1;
    if (major1 > major2) return 1;
    if (minor1 < minor2) return -1;
    if (minor1 > minor2) return 1;
    if (bugfix1 < bugfix2) return -1;
    if (bugfix1 > bugfix2) return 1;
    return 0;
}

Here, give it a try: https://ideone.com/bxCjsb

like image 164
Mecki Avatar answered Sep 23 '22 11:09

Mecki


I know I wont be able to tokenize 2 strings at once.

Fortunately, you do not need to: make a function that takes a string, and parses it for three integer numbers using strtok_r (use a reentrant version, it's a lot safer).

strunct version_t {
    int major;
    int minor;
    int build;
};

version_t parse_ver(const char* version_str) {
    version_t res;
    // Use strtok_r to split the string, and atoi to convert tokens to ints
    return res;
}

Now you can call parse_ver twice, get two version_t values, and compare them side-by-side.

P.S. If you adopt a convention to always pad the numbers with leading zeros to a specific length, i.e. make sure that you write "141.1.03" and not "141.1.3", you could substitute integer comparison with lexicographic one.

like image 35
Sergey Kalinichenko Avatar answered Sep 24 '22 11:09

Sergey Kalinichenko