Language Objective-C
Date: | 04/20/05 |
Author: | Dan Christiansen |
URL: | n/a |
Comments: | 7 |
Info: | n/a |
Score: | ![]() |
/* * 99 Bottles of Beer written in Objective-C for Mac OS X. * Should work on most OpenStep environments as well. * * Please note that since Objective-C is a superset of C, all * C versions are valid Objective-C as well. Therefore, this * version is written in fancy OO, and using NSLog rather than * printf for optimum uglyness. * * Compiles on Mac OS X with "gcc -framework Foundation 99Bottles.m" * * (c) 2002 Dan Christiansen */ #import <Foundation/Foundation.h> @class BeerBottle; @class BeerWall; @interface BeerWall : NSObject { NSMutableArray *bottles; } + (BeerWall *)wallWithBottles:(int)nbottles; - (int)bottles; - (BeerBottle *)getBottle; - (void)throwParty; @end @interface BeerBottle : NSObject { BOOL full; } - (void)chug; @end @implementation BeerWall - (id)initWithBottles:(int)nbottles { self = [super init]; bottles = [NSMutableArray arrayWithCapacity:99]; int i; for (i = 0; i < 99; i++) { [bottles addObject:[[[BeerBottle alloc] init] retain]]; } return self; } + (BeerWall *)wallWithBottles:(int)nbottles { return [[BeerWall alloc] initWithBottles:nbottles]; } - (int)bottles { return [bottles count]; } - (BeerBottle *)getBottle { BeerBottle *bottle = [bottles lastObject]; [bottles removeLastObject]; [bottle release]; return [bottle autorelease]; } - (void)throwParty { /* Objective-C is only supposed to handle 63 recursive calls - we do 99. * Life's a bitch. */ switch([self bottles]) { case 1: NSLog(@"1 bottles of beer on the wall, 1 bottles of beer,"); NSLog(@"Take one down pass it around,"); [[self getBottle] chug]; NSLog(@"No bottles of beer on the wall.", [self bottles], [self bottles]); NSLog(@""); break; default: NSLog(@"%d bottles of beer on the wall, %d bottles of beer,", [self bottles], [self bottles]); NSLog(@"Take one down pass it around,"); [[self getBottle] chug]; NSLog(@"%d bottles of beer on the wall.", [self bottles], [self bottles]); NSLog(@""); [self throwParty]; break; } return; } @end @implementation BeerBottle - (id)init { self = [super init]; srand(time(0)); full = YES; return self; } - (void)chug { if (full) { if (rand()/(double)RAND_MAX < 0.025) NSLog(@"BUUUUUUUUURP!"); full = NO; } else { printf("WTF!? This bottle's empty!!!\n"); } } @end int main() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [[BeerWall wallWithBottles:99] throwParty]; [pool release]; }
Download Source | Write Comment
Download Source | Write Comment
Add Comment
Please provide a value for the fields Name,
Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.
Please don't post large portions of code here! Use the form to submit new examples or updates instead!
Comments
NSLog(@"No bottles of beer on the wall.",
[self bottles], [self bottles]);
there is no need for [self bottles], [self bottles] because in the string above, you do not have any %d.
Would this code complie correctly?
Yes, it would still compile. It's a variable length argument function, past the NSString* formatting argument.
http://c-faq.com/varargs/index.html
In initWithBottles, the alloc/init pair will create an object with retainCount == 1. This object is then sent a retain message (increasing the count to 2) and then stored in a container that increases the retain count on its own (now 3). This would be better with the explicit retain replaced by autorelease. Best would be to have BeerBottle offer to a factory method that returns an autoreleased bottle.
Now in getBottle, the removeLastObject message to the bottle container will reduce the retain count (to 2). Then there's an explicit release (down to 1) and the autorelease which will cause a release (down to zero and deallocation - as far as we care) at the end of the event loop. So unexpectedly it doesn't leak, but it's a fairly goofy way to go about it.
I would've gone for a loop instead of recursion and moved srand to an +initialize method.
1: NSLog(@"%d bottles of beer on the wall.",
[self bottles], [self bottles]);
1 %d, 2 arguments
2. NSLog(@"1 bottles of beer on the wall, 1 bottles of beer,"
1 bottles?
3. printf("WTF!? This bottle's empty!!!\n"
No NSLog here?