Newb question at Objective-C

Discussion in 'Mac Programming' started by TheLee, Aug 5, 2006.

  1. macrumors member

    Joined:
    Aug 5, 2006
    #1
    Heyo, recent switcher from Windows, and I've been trying my hand at ObjC to see if it's worth porting my C# (and heavy System.Console Library use) to ObjC + SDL.

    I've basically been writing more and more complex "Hello, world" programs to get more and more familiar with dynamic typing/binding and some aspects of the Foundation.

    so, this is my problem - I'm basically trying to get user input and have the user input define what the object the message is being sent to. Sorry for the ugly code - I was lazy since this was just a test app.
    Code:
    #import <Foundation/Foundation.h>
    #import "hello.h"
    
    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
        id helper = NULL;
        SEL selector = NULL;
        
        helper = NSClassFromString(@"Hello");
        selector = NSSelectorFromString(@"print");
    
        // tests 1 and 2 omitted because, you know, they work
    
        // this part is for inputting the string without any whitespace
        int bytes;
        char *string;
        
        scanf("%i", &bytes );
        string = (char *) malloc( sizeof(char *) * bytes );
        scanf("%s", string );
        
        printf( "The string was entered with %i bytes.\n", bytes );
        
        // test ot make sure it was inputted correctly
        int i;
        for ( i = 0 ; i < bytes ; i++ )
        {
            printf( "%c.\n", string[i] );
        }
    
        // test 3
        NSString *nsstring = [[ NSString alloc ] initWithCString:string encoding:NSASCIIStringEncoding ];
        helper = NSClassFromString( nsstring );
        
        if ( helper = nil )
        {
            printf ( "Custom helper failed!\n" );
        }
        
        [ helper performSelector:selector ];
        
        free( string );
        
        [nsstring release];
        [class release];    
        [pool release];
        return 0;
    }
    
    The problem is that I'm not getting output... [ Hello print ] is suppossed to output "Hello World" (and is a class method). I've tried printing and testing every single variable, and as far as I can tell, they're all valid and correct. "selector" has not changed from tests 1 and 2, where it correctly was used to send the message of "print." "helper" is non-nil, and the only possible class it can be set to is Hello (unless Apple documentation is wrong... but I also experimented in tests 1 and 2 with @"Hello " and it would give me run-time errors. I also tried doing [ helper print ] but i'm getting no output, so something is clearly wrong with helper... but it's non-nil!

    Help!

    EDIT - Hmm.. I just noticed that I was inputting "5" and entering Hello, which I expect would give me a segmentation fault of some kind since it has to be null terminated, right? So I tried mallocing to bytes + 1 (to account for the null byte), but the problem persists... I feel C# has something to do with this as it has corrupted my memory of C.
     
  2. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    I know this is just a test/example, but it might help to forget about malloc() and just declare your string as
    Code:
    char string[256];
    Also, posting your hello class would help a lot. You're using print as if it's a class method, so make sure it's declared like:
    Code:
    + (void)print;
    in your .h file.
     
  3. Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #3
    Here's you problem. When this statement is executed, you're setting helper to nil. As nil is equivalent to false, the expression will never evaluate to true so you'll never get the "Custom helper failed" message. Furthermore, you'll never get the "Hello world" message since helper is set to nil.

    Change it to this and it should work:

    Code:
    if ( helper == nil )
    Yes, C strings should be allocated 1 byte more than the length of the string. Your program won't always crash if you go past the end of a buffer, but it can cause some quite serious problems. I'll assume you'd never use code like this for anything other than personal use, since it provides no protection against buffer overflows.

    As an aside, it's not affecting the behaviour of your program but you're allocating sizeof(char *) for each character in your string. This should be sizeof(char).
     
  4. thread starter macrumors member

    Joined:
    Aug 5, 2006
    #4
    ZOMG.

    I'm such a moron.

    yeah, helper = nil was the problem.

    C# definitely has spoiled me into laziness as "helper = nil" woudl never have compiled in C# (in case you're not familiar, C# only accepts explicit boolean results (true and false), and not implicit ones like in C where 0 = false and anything else = true).

    On another note... if I had done char string[256] and inputted a 5 byte string, would the null termination happen at string[5]? So I don't even need this clumsy construct to prevent whitespace?
     
  5. Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #5
    Correct. The only change you might want to make to your code is when you print the string character by character; you'd want to stop outputting characters once you reached a null terminator.

    ie:
    Code:
        int i;
        for ( i = 0 ; i < bytes ; i++ )
        {
    		if (string[i]=='\0')
    			break;
            printf( "%c.\n", string[i] );
        }
     
  6. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #6
    That's one thing that annoys me with C#. In Objective-C, you can do if (obj) and it will return true if obj is not nil, and false if it is. But in C# you have to type it out fully, like if (obj == null).. so much extra effort ;)

    scanf() should put in the null character for you.
     
  7. macrumors 6502

    Joined:
    Jul 25, 2006
    #7
    To try to offset this issue, some people try to get in the habit of writing
    Code:
    if( nil == helper )
    so that if you ever do type
    Code:
    if( nil = helper)
    you will get an error.
     
  8. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #8
    Better method is to figure out what warnings to enable in the compiler, and then make sure that you don't use code that gives any warnings. That way you don't sacrifice readability of your code.
     

Share This Page