views:

205

answers:

3

Hello;

I am new to Objective C, and am trying to write a class that defines a complex number. The code seems fine but when I print to the console, my values for instance variables are 0.

Here is the code:

//
//  ComplexNumber.h
//  Mandelbrot Set
//
//  Created by Brett on 10-06-02.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <stdio.h>


@interface ComplexNumber : NSObject {

 double real;
 double imaginary;

}

// Getters
-(double) real;
-(double) imaginary;



// Setters
-(void)setReal: (double) a andImaginary: (double) b;

//Function
-(ComplexNumber *)squared;

@end


//
//  ComplexNumber.m
//  Mandelbrot Set
//
//  Created by Brett on 10-06-02.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "ComplexNumber.h"
#import <math.h>
#import <stdio.h>

@implementation ComplexNumber

-(double)real{
 return self->real;
}

-(double)imaginary{
 return self->imaginary;
}


-(void)setReal: (double) a andImaginary: (double) b{

 self->real=a;
 self->imaginary=b;

}

-(ComplexNumber *)squared{

 double a = pow(real,2);
 double b = pow(imaginary, 2);
 double c = 2*real*imaginary;

 ComplexNumber *d;
 [d setReal:(a-b) andImaginary: c];

 return d;
}

@end

In the App Delegate for debugging purposes I added:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {   

 ComplexNumber *testNumber = [[ComplexNumber alloc] init];
 [testNumber setReal:55.0 andImaginary:30.0];
 NSLog(@"%d", testNumber.real);

    // Override point for customization after app launch    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

 return YES;
}

But the console returns 0 everytime. Help?

+3  A: 

Instead of %d, use %f. D is for integers, F is for floating point ("real").

mcandre
Good point, but not the problem here
mustISignUp
Won't that just output garbage values instead of 0? Try NSLog(@"%d", 0.0001); and you don't get 0 on the console :)
deanWombourne
@mustISignUp, yes it is. @deanWombourne, it depends. Double is 8 bytes and int is 4 bytes. The implementation will grab either the first 4 bytes or the last 4 bytes of the real number, depending on how arguments are passed and the endianness of the processor. It's quite feasible that the 4 bytes in question just happen to be 0.
JeremyP
@jeremyP thanks for the explanation about casting testNumber.real to an int - very enlightening but you don't mention what influence testNumber being nil has? Which of these byte thingies could that effect?
mustISignUp
+1  A: 

The problem is that you don't allocate the return value of your -(ComplexNumber *)squared method.

You do it correctly when you create testNumber. You have..

ComplexNumber *d;

and

ComplexNumber *testNumber = [[ComplexNumber alloc] init];

they should follow the same pattern (It's the general pattern for creating a new instance of an object).

You might want to define a custom initializer:-

- (id)initWithReal:(double)a andImaginary:(double)b { 
  self = [super init];
  if(self){
    real = a;
    imaginary = b;
  }
  return self;
}

and then instead of

ComplexNumber *testNumber = [[ComplexNumber alloc] init];
[testNumber setReal:55.0 andImaginary:30.0];

You could use

ComplexNumber *testNumber = [[ComplexNumber alloc] initWithReal:55.0 andImaginary:30.0];

As a sidenote:

self->real=a; is the same as real=a. As there is no need for -> you should not use it. If you need to access the variables from another onject you use the getter and setter methods.

Oh yeah, and as the other have pointed out. The format specifier in the NSLog is wrong as well.

mustISignUp
Thanks. All of this worked great!
Brett
A: 

A couple things. In your getters/setters why are you using self->real specifically the -> syntax. I've only seen/used self.real. You way may work (?) but the convention is to use a peroid. Also why are you manually creating the geters/seters. Unless you need to do more logic then just return and assign in them I'd suggest changing to this.

//.h
#import <Foundation/Foundation.h>
#import <stdio.h>

@interface ComplexNumber : NSObject {

      double real;
      double imaginary;
}
   @property (nonatomic) double real;
   @property (nonatomic) double imaginary;

   //Function
   -(ComplexNumber *)squared;
@end



//.m
#import "ComplexNumber.h"
#import <math.h>
#import <stdio.h>

@implementation ComplexNumber

-(ComplexNumber *)squared{

 double a = pow(real,2);
 double b = pow(imaginary, 2);
 double c = 2*real*imaginary;

 ComplexNumber *d = [[ComplexNumber alloc] init];
 d.real = a-b;
 d.imaginary = c;
 return d;
}

@end

Let objective-c create your basic getters/setters for you via the @property line. You can then access/set them the following ways.

ComplexNumber *d = [[ComplexNumber alloc] init];
d.real = 55; //or
[d setReal:55];
//with reading as easy
double real = d.real; //or
double real = [d real];
jamone
lower case r in `d.Real;` to comply with Apple guidelines. Also `self->real` just accesses the ivar directly which is the correct thing to do if you are implementing your own accessors as Brett is doing. The only thing is that `self->` is implied anyway, so it just wastes keystrokes. i.e. `real = foo;` is identical to `self->real = foo;` inside a method.
JeremyP
Your squared method is missing alloc/init for the result...
Eiko
fixed those issues.
jamone