Skip to main content
Use real headers; fix spelling and grammar, minimum INT_MAX is 32K, not 64k
Source Link
Toby Speight
  • 81.7k
  • 14
  • 101
  • 308

Overflow

Overflow

Using int can have trouble with integers as small as 64k32K. Consider a version using a time stamp of 14 digits as one of the fields 20220302101901. Use some unsigned type, perhaps uintmax_t. Even then I would consider detecting overflow - or see below.

What if non-digit or non-dot?

What if non-digit or non-dot?

Since separators like ,, and letters are treated pathologically like digits, how about giving those meaning as separators and not useusing them to computercompute the version value?

NULL?

NULL?

Since version compare is often done near the beginning of code and the result is very important, I'd like the comparecomparison to tolerate more of the usual mistakes like NULL or effect some error message.

Unlimited integer precession

Unlimited integer precision

Overflow

Using int can have trouble with integers as small as 64k. Consider a version using a time stamp of 14 digits as one of the fields 20220302101901. Use some unsigned type, perhaps uintmax_t. Even then I would consider detecting overflow - or see below.

What if non-digit or non-dot?

Since separators like ,, and letters are treated pathologically like digits, how about giving those meaning as separators and not use them to computer the version value?

NULL?

Since version compare is often done near the beginning of code and the result is very important, I'd like the compare to tolerate more of the usual mistakes like NULL or effect some error message.

Unlimited integer precession

Overflow

Using int can have trouble with integers as small as 32K. Consider a version using a time stamp of 14 digits as one of the fields 20220302101901. Use some unsigned type, perhaps uintmax_t. Even then I would consider detecting overflow - or see below.

What if non-digit or non-dot?

Since separators like ,, and letters are treated pathologically like digits, how about giving those meaning as separators and not using them to compute the version value?

NULL?

Since version compare is often done near the beginning of code and the result is very important, I'd like the comparison to tolerate more of the usual mistakes like NULL or effect some error message.

Unlimited integer precision

added 921 characters in body
Source Link
chux
  • 33.7k
  • 2
  • 38
  • 92

Using int can have trouble with integers as small as 64k. Consider a version using a time stamp of 14 digits as one of the fields 20220302101901. Use some unsigned type, perhaps uintmax_t. Even then I would consider detecting overflow - or see below.

int compareVersion(const char * v1, const char * v2) {
  if (v1 == NULL) v1 = "";
  if (v2 == NULL) v2 = "";
  ...

Unlimited integer precession

No multiplication, no precision limit.

// Used unsigned access.  Avoid UB with `isdigit()` and correct for non-2's complement.
const unsigned char *u1 = v1;
const unsigned char *u2 = v2;

while (*u1 || *u2) {
  // Consume leading uninformative zero digits.
  while (*u1 == '0') u1++; 
  while (*u2 == '0') u2++; 

  int compare = 0;
  while (isdigit(*u1) && isdigit(*u2)) {
    if (*u1 != *u2 && compare == 0) { 
      compare = *u1 > *u2 ? 1 : -1;
    }
    u1++;
    u2++;
  }
  // Compare meaningful here only if same number of digits in u1, u2.

  // If one string has more significant digits, it is larger
  if (isdigit(*u1)) {
    return 1;
  }
  if (isdigit(*u2)) {
    return -1;
  }

  if (compare) {
    return compare;
  }
  if (*u1) u1++;
  if (*u2) u2++;
}
return 0;

  
  

Using int can have trouble with integers as small as 64k. Consider a version using a time stamp of 14 digits as one of the fields 20220302101901. Use some unsigned type, perhaps uintmax_t. Even then I would consider detecting overflow.

int compareVersion(const char * v1, const char * v2) {
  if (v1 == NULL) v1 = "";
  if (v2 == NULL) v2 = "";
  ...

Using int can have trouble with integers as small as 64k. Consider a version using a time stamp of 14 digits as one of the fields 20220302101901. Use some unsigned type, perhaps uintmax_t. Even then I would consider detecting overflow - or see below.

int compareVersion(const char * v1, const char * v2) {
  if (v1 == NULL) v1 = "";
  if (v2 == NULL) v2 = "";
  ...

Unlimited integer precession

No multiplication, no precision limit.

// Used unsigned access.  Avoid UB with `isdigit()` and correct for non-2's complement.
const unsigned char *u1 = v1;
const unsigned char *u2 = v2;

while (*u1 || *u2) {
  // Consume leading uninformative zero digits.
  while (*u1 == '0') u1++; 
  while (*u2 == '0') u2++; 

  int compare = 0;
  while (isdigit(*u1) && isdigit(*u2)) {
    if (*u1 != *u2 && compare == 0) { 
      compare = *u1 > *u2 ? 1 : -1;
    }
    u1++;
    u2++;
  }
  // Compare meaningful here only if same number of digits in u1, u2.

  // If one string has more significant digits, it is larger
  if (isdigit(*u1)) {
    return 1;
  }
  if (isdigit(*u2)) {
    return -1;
  }

  if (compare) {
    return compare;
  }
  if (*u1) u1++;
  if (*u2) u2++;
}
return 0;

  
  
added 917 characters in body
Source Link
chux
  • 33.7k
  • 2
  • 38
  • 92

Overflow

Using int can have trouble with integers as small as 64k. Consider a version using a time stamp of 1014 digits as one of the fields 20220302101901. IMOUse some unsigned type, useperhaps uintmax_t. Even then I would consider detecting overflow.

What if non-digit or non-dot?

Since separators like ,, and letters are treated pathologically like digits, how about giving those meaning as separators and not use them to computer the version value?

// while (*v1 && *v1 != '.')  a = 10*a + (*v1++ - '0');
while (isdigit(*v1))  a = 10*a + (*v1++ - '0');

Pedantically, should use unsigned char values with is...()

while (isdigit(*(const unsigned char*)v1))  a = 10*a + (*v1++ - '0');

... or use (*v1 >= '0' && *v1 <= '9') if avoiding libraries.

NULL?

Since version compare is often done near the beginning of code and the result is very important, I'd like the compare to tolerate more of the usual mistakes like NULL or effect some error message.

int compareVersion(const char * v1, const char * v2) {
  if (v1 == NULL) v1 = "";
  if (v2 == NULL) v2 = "";
  ...

Overflow

Using int can have trouble with integers as small as 64k. Consider a version using a time stamp of 10 digits as one of the fields. IMO, use uintmax_t. Even then I would consider detecting overflow.

Overflow

Using int can have trouble with integers as small as 64k. Consider a version using a time stamp of 14 digits as one of the fields 20220302101901. Use some unsigned type, perhaps uintmax_t. Even then I would consider detecting overflow.

What if non-digit or non-dot?

Since separators like ,, and letters are treated pathologically like digits, how about giving those meaning as separators and not use them to computer the version value?

// while (*v1 && *v1 != '.')  a = 10*a + (*v1++ - '0');
while (isdigit(*v1))  a = 10*a + (*v1++ - '0');

Pedantically, should use unsigned char values with is...()

while (isdigit(*(const unsigned char*)v1))  a = 10*a + (*v1++ - '0');

... or use (*v1 >= '0' && *v1 <= '9') if avoiding libraries.

NULL?

Since version compare is often done near the beginning of code and the result is very important, I'd like the compare to tolerate more of the usual mistakes like NULL or effect some error message.

int compareVersion(const char * v1, const char * v2) {
  if (v1 == NULL) v1 = "";
  if (v2 == NULL) v2 = "";
  ...
Source Link
chux
  • 33.7k
  • 2
  • 38
  • 92
Loading