Следующая процедура сравнивает строки номера версии, которые состоят из подлинных чисел. Преимущество заключается в том, что разделитель не имеет значения; он будет работать, например, с 141.01.03, 141: 1: 3 или даже 141A1P3. Он также обрабатывает несоответствующие хвосты, чтобы 141.1.3 приходилось до 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;
}
Заменить strtoul
с с strcspn
с и strncmp
, и вы можете использовать его для сравнения нечисловых версии «номера» - но разделитель должен быть точка. Например, 141.3A.1 сортирует до 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')
...
Для этого примера 'strcmp' будет делать :-) – cnicutar
Mmm, stcmp, вероятно, поставит Linux 2.14 перед Linux 2.4. –
@David Grayson: strcmp возвращает значение больше нуля, когда первый символ, который не соответствует, имеет большее значение в str1, чем в str2, а сравнение останавливается на первом нуле, поэтому оно все равно будет работать даже для 2.1 и 2.14 , 2.1 и 2.10 могут быть неоднозначными, но это так или иначе. В этом случае отнюдь не ясно, что представляет собой допустимую строку версии. Он будет работать до тех пор, пока все группы цифр, кроме последней, имеют одинаковую длину, поэтому вы не сравниваете цифру с точкой. – Clifford