Random code generator - is it written alright?

Discussion in 'Mac Programming' started by JonnyThunder, Sep 10, 2008.

  1. macrumors member

    Joined:
    Aug 16, 2008
    #1
    Hello,

    I'm just starting out with Obj-C / Cocoa (from having done no previous C or C++ programming). I wrote this to generate a random number in a window and wondered if it was a tidy enough way to achieve the goal....


    {See next post with code}


    This objective-C thing is hard work man! Seriously.

    This code does work, but wondered if it is better written another way? Also, if you click the button twice quickly - the random number isn't random (I think because the seed is from 'time'). Is there a better way to generate a better seed (perhaps using Milliseconds?)


    EDIT: I changed the seed line to the following, which gives better results when updating fast...

    Code:
    srandom(time(NULL)+(random()%100)+1);
    
     
  2. thread starter macrumors member

    Joined:
    Aug 16, 2008
    #2
    OK, I slightly modified it to have an additional output box and checkbox. Can anyone tell me if this is the right approach? I don't want to learn bad habits at this early stage!

    [MyAppClass.h]
    Code:
    #import <Cocoa/Cocoa.h>
    
    @interface MyAppClass : NSObject {
    
    	IBOutlet NSTextField *myTextField;
    	IBOutlet NSTextField *myTextField_Reverse;
    	IBOutlet NSButton *showInReverse;
    	int outputLength;
    	
    }
    
    -(IBAction)randomword:(id)sender;
    
    @end
    
    [MyAppClass.m]
    Code:
    #import "MyAppClass.h"
    
    @implementation MyAppClass
    
    -(void)init
    {
    	// Length of string output
    	outputLength = 16;
    }
    
    -(void)awakeFromNib
    {
    	[myTextField setStringValue:@"Click button to generate"];
    	[myTextField_Reverse setStringValue:@""];
    }
    
    -(void)randomword:(id)sender
    {
    	
    	// Define an array for string
    	NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:outputLength];
    	
    	// Define an array for reverse string
    	NSMutableString *outputString_Reverse = [[NSMutableString alloc] initWithCapacity:outputLength];
    	
    	// Seed generator
    	srandom(time(NULL)+(random()%time(NULL))+1);
    	
    	// Generate string
    	for (int i=0; i < outputLength; i++)
    	{
    	
    		// Append to string
    		[outputString appendFormat:@"%c",(random()%26)+65];
    		
    	}
    
    	// Check if we want to display reversed string
    	if ([showInReverse state]) {
    
    		for (int i=0; i < outputLength; i++)
    		{
    			
    			// Character by character addition of string (in reverse)
    			[outputString_Reverse appendFormat:@"%C", [outputString characterAtIndex:((outputLength-1)-i)]];
    		
    		}
    		
    	} else {
    
    		// Set string blank for display
    		[outputString_Reverse setString:@""];
    		
    	}
    	
    	// Populate output boxes here
    	[myTextField setStringValue:outputString];
    	[myTextField_Reverse setStringValue:outputString_Reverse];
    	
    }
    	
    @end
    
     
  3. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #3
    Your original seed was correct. But you do it in the wrong place. You seed once: on application startup, not everytime you ask for a random number.
     
  4. thread starter macrumors member

    Joined:
    Aug 16, 2008
    #4
    I did originally have it in the init method, but it causes a compile time error. Where should I be placing it?

    I notice that placing it in awakeFromNib works fine, but thought init method would be a better place...
     
  5. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #5
    What error? There is no difference to the exact same code (to the compiler) being in init or where you have it. You must have made a mistake.
     
  6. thread starter macrumors member

    Joined:
    Aug 16, 2008
    #6
    When I have my code like this....

    Code:
    -(void)init
    {
    	// Length of string output
    	outputLength = 16;
    	
    	// Seed generator
    	srandom(time(NULL));
    }
    
    I get the following in the debugger console...

     
  7. thread starter macrumors member

    Joined:
    Aug 16, 2008
    #7
    Just noticed that if I call the superclass init AFTER my srandom statement, it works fine.

    But my question now is, if I didn't need to call super init before - why is it required like this now....

    [this code works]
    Code:
    -(void)init
    {
    	// Length of string output
    	outputLength = 16;
    	
    	// Seed generator
    	srandom(time(NULL));
    
    	[super init];
    }
    
     
  8. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #8
    You should always call super init first. Without that your object will not be correctly setup.
     
  9. thread starter macrumors member

    Joined:
    Aug 16, 2008
    #9
    Yes, that's what I thought (and read). But when I put [super init] to the top of the init method, it causes the same issue as I posted before.

    I tried to attach the project (2.2mb) but uploads only allow just over 1mb.

    Code:
    -(void)init
    {
    	// Call superclass init method
    	[super init];	
    	
    	// Length of string output
    	outputLength = 16;
    	
    	// Seed generator
    	srandom(time(NULL));
    }
    
    The code above, causes the same compile issue as I posted earlier. However, the code that follows compiles and works no probem. I don't understand why!

    Code:
    -(void)init
    {
    	// Length of string output
    	outputLength = 16;
    	
    	// Seed generator
    	srandom(time(NULL));
    
    	// Call superclass init method
    	[super init];	
    }
    
     
  10. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #10
    1) That's not a compiler error: that's a runtime error. It's important to know the difference.

    2) Your init function is declared as void. This is wrong.

    Code:
    // Basic init
    -(id) init
    {
    if ([super init])
    {
    // Do your initialisation here
    return self;
    }
    return nil;
    }
    
    This is such a basic, fundamental error I suggest you need to go back to the beginning and read the Objective-C language guide.
     
  11. thread starter macrumors member

    Joined:
    Aug 16, 2008
    #11
    This was a basic, fundamental mistake - not a lack of understanding. I just didn't see where my mistake was. Considering I never wrote a line of C, Obj-C or anything else object related prior to this script - I think I did alright... no need to be horrible about it!
     
  12. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #12
    It shows a fundamental lack of conceptual understanding about what the init method does and how it works. If you haven't read the document I linked you should: it teaches you about the language you are using and explains it's features and usage. If you don't understand what you are doing you'll never do it right...
     
  13. thread starter macrumors member

    Joined:
    Aug 16, 2008
    #13
    No... it shows a silly mistake, NOT a misunderstanding of return types, init methods, inheritance or anything else that apparently I'm deemed to be clueless about.

    Can we kiss and make up now??? :D
     
  14. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #14
    The pattern that you should always use (unless there is a very good reason to do otherwise):
    Code:
    if (self = [super init]) { ... }
    [super init] does not necessarily return self; it could return a different value, and you should use that value instead of self.
     
  15. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #15
    Very true. I was typing from memory on a PC :eek:
     

Share This Page