Khal
Khal

Reputation: 820

Weird NSString behavior with formatString

I ran into a pretty weird issue today. I have this static method (part of a CommonUtilities source file that I've been just created that gathers all the small common methods I'd like to access anywhere in my code, like I usually do btw...)

I just want to convert a number into its scientific value using the international system notation (k, M, G, etc.)

Here is the code:

+ (NSString*)scientificFormatedStringForValue:(NSNumber*)value andUnits:(NSString*)_units
{
    NSMutableString* retStr = [NSMutableString string];
    long long longValue = [value longLongValue];
    if (longValue > 1000000000)
    {
        [retStr appendFormat:@"%d Md%@", longValue / 1000000000, _units];
    }
    else if (longValue > 1000000)
    {
        [retStr appendFormat:@"%d M%@", longValue / 1000000, _units];
    }
    else if (longValue > 1000)
    {
        [retStr appendFormat:@"%d k%@", longValue / 1000, _units];
    }
    else
    {
        [retStr appendFormat:@"%d %@", longValue, _units];
    }
    return retStr;
}

This is pretty easy right? Ok, here's the deal: the _units is not converted properly.

In my example, I use this:

[CommonUtilities scientificFormatedStringForValue:[NSNumber numberWithLongLong:longValue] andUnits:@"€"];

I get (null) as _units for the formatted string. If I print the value of _units, it's a dot. So, to try to debug this, I just replaced:

[retStr appendFormat:@"%d M%@", longValue / 1000000, _units];

with

[retStr appendFormat:@"%d M%@", longValue / 1000000, @"€"];

Still doesn't work. It tried passing a single character (thinking the maybe the € must be converted to some UTF8 stuff or whatever. So I changed the calling method to :

[CommonUtilities scientificFormatedStringForValue:[NSNumber numberWithLongLong:longValue] andUnits:@"e"];

Still crappy stuff. I even changed @"€" to [NSString stringWithString:@"€"], but still the same output! I can't figure out what's wrong here, I'm stuck.

I thought of a problem in the encoding of the source file, so I deleted it and recreated it, but still the same issue....

If any one has even the tiniest clue, that would be most helpful. Thank you guys...

Upvotes: 4

Views: 134

Answers (1)

Joe
Joe

Reputation: 57169

The problem is you are attempting to write an int (32 bits) but you are passing a long long (64 bits) and it is reading the first 4 bytes of your longValue for the value and the last 4 bytes for the _units. It just so happens that the value in low bytes of your long long is nil and did not cause a crash. You need to use %lld instead of %d to print the long value correctly.

    longValue       NSString*
/---------------\ /---------\
|   8 bytes     | | 4 bytes |
\---------------/ \---------/
^^^^^^^^ ^^^^^^^^  ^^^^^^^^^
   %d       %@        This gets ignored.
(reads 4) (reads this 4 bytes which happen to be nil)

Upvotes: 3

Related Questions