2

I'm a programming newbie and I'm currently writing a conversion calc program in objective c and I'm really struggling.

I have a string representing a unsigned long long value. I need a way either when attempting to add another character to check that the new character would not go above LONG_LONG_MAX before adding it. Or deleting the last character if the value is/would be above LONG_LONG_MAX

the only possible way I could think to even try this is:

- (BOOL) isNumberStringValid:(NSString *)stringValue {
      unsigned long long uVal = strtoull(stringValue.UTF8String, NULL, 0);

      if (uVal <= ULLONG_MAX) return TRUE;
      else return FALSE;
}

I know this doesn't work because uVal would always be <= ULLONG_MAX but I can't think of any other ways to possibly check. Can anyone help me find a way to accomplish this???

3 Answers3

1

You can use the fact that strtoull() sets the value of errno to ERANGE if the given string was out of range:

- (BOOL) isNumberStringValid:(NSString *)stringValue {
    errno = 0;
    unsigned long long uVal = strtoull(stringValue.UTF8String, NULL, 0);
    return (errno == 0);
}

Some test (ULLONG_MAX = 264-1 = 18446744073709551615):

1234 : TRUE
18446744073709551615 : TRUE
18446744073709551616 : FALSE
1844674407370955161678 : FALSE
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

You can use NSNumberFormatter. Unfortunately NSNumberFormatter stores the 'maximum' value as a float, so there are some problems around the boundary of LONG_LONG_MAX. To deal with that this code checks for nil or a long long value that is negative (which means that it overflowed)

-(BOOL) isNumberStringValid:(NSString *)stringValue
{

    [NSNumberFormatter setDefaultFormatterBehavior:NSNumberFormatterBehavior10_4];
    NSNumberFormatter *f=[[NSNumberFormatter alloc]init];

    NSNumber *max=[NSNumber numberWithLongLong:LONG_LONG_MAX];

    [f setMaximum:max];

    BOOL valid=NO;

    NSNumber *num=[f numberFromString:stringValue];
    if (num != nil)       // A nil value means that input was > LONG_LONG_MAX
    {
       long long x=[num unsignedLongLongValue];  // A negative value here means that the input was > LONG_LONG_MAX
       if (x>0)
       {
        valid=YES;        
       }
    }
    return valid;
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
-1

the if statement you have is checking if uVal is less than or equal to LONG_LONG_MAX

unsigned long long uVal = (unsigned)stringValue.longLongValue;
if (uVal >= LONG_LONG_MAX) {
    return YES;
}
else {
    return NO;
}

I ran this and it works fine.

RASS
  • 61
  • 1
  • 6
  • Your logic seems to be reversed - you return yes if the number is too big and no if it isn't - the function should return YES if the number is valid, but it also doesn't work because of the overflow when you assign a number greater than LONG_LONG_MAX to uVAL. Try it with your string equal to "9223372036854775809" - you end up with a 4294967295 – Paulw11 Mar 28 '14 at 23:43
  • OK this code does seem to work for me:'code' NSString *string = @"9223372036854775807"; unsigned long long uVal = strtoull(string.UTF8String, NULL, 0); NSLog(@"%llu", uVal); if (uVal >= LONG_LONG_MAX) { NSLog(@"no"); return NO; } else { NSLog(@"yes"); return YES; } – RASS Mar 28 '14 at 23:58