La seguente routine confronta le stringhe di numeri di versione costituite da numeri originali. Il vantaggio è che il delimitatore non ha importanza; funzionerà con, ad esempio, 141.01.03, 141: 1: 3 o addirittura 141A1P3. Gestisce anche code non corrispondenti in modo che 141.1.3 venga prima di 141.1.3.1.
#include <assert.h>
#include <stdlib.h>
int versionCmp(char *pc1, char *pc2)
{
int result = 0;
/* loop through each level of the version string */
while (result == 0) {
/* extract leading version numbers */
char* tail1;
char* tail2;
unsigned long ver1 = strtoul(pc1, &tail1, 10);
unsigned long ver2 = strtoul(pc2, &tail2, 10);
/* if numbers differ, then set the result */
if (ver1 < ver2)
result = -1;
else if (ver1 > ver2)
result = +1;
else {
/* if numbers are the same, go to next level */
pc1 = tail1;
pc2 = tail2;
/* if we reach the end of both, then they are identical */
if (*pc1 == '\0' && *pc2 == '\0')
break;
/* if we reach the end of one only, it is the smaller */
else if (*pc1 == '\0')
result = -1;
else if (*pc2 == '\0')
result = +1;
/* not at end ... so far they match so keep going */
else {
pc1++;
pc2++;
}
}
}
return result;
}
int main(void)
{
assert(versionCmp("1.2.3" , "1.2.3") == 0);
assert(versionCmp("1.2.3" , "1.2.4") < 0);
assert(versionCmp("1.2.4" , "1.2.3") > 0);
assert(versionCmp("10.2.4", "9.2.3") > 0);
assert(versionCmp("9.2.4", "10.2.3") < 0);
/* Trailing 0 ignored. */
assert(versionCmp("01", "1") == 0);
/* Any single space delimiter is OK. */
assert(versionCmp("1a2", "1b2") == 0);
return EXIT_SUCCESS;
}
Sostituire i strtoul
s con strcspn
s ed un strncmp
, e si può usare per confrontare la versione non numerici "numeri" - ma il delimitatore deve essere un punto. Ad esempio, 141.3A.1 ordina prima di 141.3B.
...
while (result == 0) {
/* ignore leading zeroes */
pc1 += strspn(pc1, "0");
pc2 += strspn(pc2, "0");
/* extract leading version strings */
int len1 = strcspn(pc1, ".");
int len2 = strcspn(pc2, ".");
/* if one is shorter than the other, it is the smaller version */
result = len1 - len2;
/* if the same length then compare as strings */
if (result == 0)
result = strncmp(pc1, pc2, len1);
if (result == 0) {
pc1 += len1;
pc2 += len2;
if (*pc1 == '\0' && *pc == '\0')
...
fonte
2013-02-25 02:57:37
Per questo esempio, 'strcmp' farebbe :-) – cnicutar
Mmm, stcmp probabilmente inserirà Linux 2.14 prima di Linux 2.4. –
@David Grayson: strcmp restituisce un valore maggiore di zero quando il primo carattere che non corrisponde ha un valore maggiore in str1 che in str2, e il confronto si ferma sul primo nul, quindi funzionerà ancora, anche per 2.1 e 2.14 . 2.1 e 2.10 potrebbero essere ambigui, ma poi è in ogni modo. In questo caso non è affatto chiaro dagli esempi cosa costituisce una stringa di versione valida. Funzionerà finché tutti i gruppi di cifre tranne l'ultimo avranno la stessa lunghezza, quindi non si finirà per confrontare una cifra con un punto. – Clifford