tags:

views:

846

answers:

2

Hi, I need to create an NSString that has a single random uppercase letter.

I can get random int's fine, and I could construct a C string from it and then make the NSString, but I imagine there has to be a better and more cocoa-ish way.

Thanks!

+4  A: 

You can just make an NSString containing what you consider to be letters and pull a random character from it. Here's an example category:

@implementation NSString(RandomLetter)
- (NSString *)randomLetter {
    return [self substringWithRange:[self rangeOfComposedCharacterSequenceAtIndex:random()%[self length]]];
}
@end

(You'll need to srandom(time()) at some point, obviously. Maybe include an initialize method in your category.)

Chuck
With A-Z, this approach will work great.If you're not going to limit your domain to something like A-Z, you need to be careful with this technique. What the user thinks of as a single character might not be a single unichar.
Jon Hess
There comes a point where the idea of a character is ambiguous. I've changed it so that it explicitly uses Cocoa's support for composed character sequences.
Chuck
That looks much better.
Jon Hess
Thanks! This is what I went with.
jblocksom
+3  A: 

I think the best way is to use a c string so that you can use an explicit encoding. Here's an example of that:

NSInteger MyRandomIntegerBetween(NSInteger min, NSInteger max) {
    return (random() % (max - min + 1)) + min;
}

NSString *MyStringWithRandomUppercaseLetter(void) {
    char string[2] = {0, 0};
    string[0] = MyRandomIntegerBetween(65, 90); /// 'A' -> 'Z' in ASCII.
    return [[[NSString alloc] initWithCString:string encoding:NSASCIIStringEncoding] autorelease];
}

Here's an alternative, that's really pretty much the same thing, but avoids the C string.

NSString *MyStringWithRandomUppercaseLetter(void) {
    unichar letter = MyRandomIntegerBetween(65, 90);
    return [[[NSString alloc] initWithCharacters:&letter length:1] autorelease];
}

I prefer the explicit character encodings in the first approach, but they're both correct.

Jon Hess
This doesn't handle character sequences at all, so I'm not sure why you feel this is superior.
Chuck
Oh, I agree Chuck. The difference is that this code is explicitly limited to 'A'->'Z'. With the other approach, the caller needs to be aware of that problem in advance. Here, there's no opportunity of a caller of this function to make a mistake having to do with "characters" that need more than one code point.
Jon Hess
Good ideas, Jon, thanks for the answer!
jblocksom