Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Formatting a string containing a number with comma separation

I have a number stored in an NSMutableString instance which I want to auto format with comma delimiters and then display the result in a UITextField.

I've tried using NSNumberFormatter to format as currency, but I don't want it to show decimals if the original NSMutableString doesn't contain a decimal place.

For example:

  • If the NSMutableString contains "1234567", it should format as "1,234,567".
  • If the NSMutableString contains "1234567.1", it should format as "1,234,567.1"
  • If the NSMutableString contains "1234567.12", it should format as "1,234,567.12"

The maximum decimals that the NSMutableString will contain is 2.

Any help is greatly appreciated.

Thanks!

like image 357
staticnz Avatar asked Jan 17 '23 02:01

staticnz


2 Answers

Keep in mind that you should really be localizing this if you are interacting with users on this, however here is one way to do it:

- (NSString *)formatString:(NSString *)string {
    // Strip out the commas that may already be here:
    NSString *newString = [string stringByReplacingOccurrencesOfString:@"," withString:@""];
    if ([newString length] == 0) {
        return nil;
    }

    // Check for illegal characters
    NSCharacterSet *disallowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet];
    NSRange charRange = [newString rangeOfCharacterFromSet:disallowedCharacters];
    if ( charRange.location != NSNotFound) {
        return nil;
    }

    // Split the string into the integer and decimal portions
    NSArray *numberArray = [newString componentsSeparatedByString:@"."];
    if ([numberArray count] > 2) {
        // There is more than one decimal point
        return nil;
    }

    // Get the integer
    NSString *integer           = [numberArray objectAtIndex:0];
    NSUInteger integerDigits    = [integer length];
    if (integerDigits == 0) {
        return nil;
    }

    // Format the integer.
    // You can do this by first converting to a number and then back to a string,
    // but I would rather keep it as a string instead of doing the double conversion.
    // If performance is critical, I would convert this to a C string to do the formatting.
    NSMutableString *formattedString = [[NSMutableString alloc] init];
    if (integerDigits < 4) {
        [formattedString appendString:integer];
    } else {
        // integer is 4 or more digits
        NSUInteger startingDigits = integerDigits % 3;
        if (startingDigits == 0) {
            startingDigits = 3;
        }
        [formattedString setString:[integer substringToIndex:startingDigits]];
        for (NSUInteger index = startingDigits; index < integerDigits; index = index + 3) {
            [formattedString appendFormat:@",%@", [integer substringWithRange:NSMakeRange(index, 3)]];
        }
    }

    // Add the decimal portion if there
    if ([numberArray count] == 2) {
        [formattedString appendString:@"."];
        NSString *decimal = [numberArray objectAtIndex:1];
        if ([decimal length] > 0) {
            [formattedString appendString:decimal];
        }
    }

    return formattedString;
}

// Test cases:
NSLog(@"%@", [self formatString:@"123456"]);
NSLog(@"%@", [self formatString:@"1234567."]);
NSLog(@"%@", [self formatString:@"12345678.1"]);
NSLog(@"%@", [self formatString:@"123456789.12"]);

// Output:
123,456
1,234,567.
12,345,678.1
123,456,789.12
like image 133
lnafziger Avatar answered Feb 07 '23 01:02

lnafziger


I think this should do it -- I added an if statement to check if there is a decimal point in the typed in value. "Output" in this example is a property that I have bound to the value of a text field to show the result.

-(IBAction)doConversion:(id)sender{
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
    [formatter setMaximumFractionDigits:2];
    [formatter setUsesGroupingSeparator:YES];
    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];

    double entryFieldFloat = [entryField doubleValue]; 
    if ([entryField.stringValue rangeOfString:@"."].length == 1) {
        formatter.alwaysShowsDecimalSeparator = YES;
        self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
    }else{
        formatter.alwaysShowsDecimalSeparator = NO;
        self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
    }
}
like image 35
rdelmar Avatar answered Feb 07 '23 01:02

rdelmar