Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID
Please do not post the same thing multiple times. The board software automatically flags certain posts as needing moderator attention. This happens the most often for new users. I'm pretty sure this is made clear at the time you attempt to post. Posting the same thing over and over again just makes that many more posts the moderators have to weed through later. This makes us sad. Don't make us sad. If your post/thread doesn't appear, just wait a while. Don't post it again. If it hasn't shown up by the next day, then you can try again. I normally go through posts in the mornings, and try to check a few times throughout the day, but I'm not here 24/7. There will typically be a significant delay before posts are approved. Just be patient.

Simple Help with Objective-C

(The classroomm.com forums are basically dead, so I'm reposting this here, hope no one minds).

I'm on Chapter 4 in "Programming in Objective-C".

I've spent waaay too long on this problem and ended up with a correct answer by basically copying one on classroomm.com which I'm not too proud of as I still don't know what I did wrong.

Here's what I want to work:


#import <Foundation/Foundation.h>

@interface Rectangle: NSObject

-(void) setWidth: (int) w;
-(void) setHeight: (int) h;
-(int) area;
-(int) perimeter;
-(void) print;

@end

@implementation Rectangle

{
int width;
int height;
int area;
int perimeter;
}
-(void) setWidth: (int) w;
{
width = w;
}
-(void) setHeight: (int) h;
{
height = h;
}
-(int) area;
{
area = height*width;
}
-(int) perimeter;
{
perimeter = (height*2) + (width*2);
}
-(void) print;
{
NSLog (@"area: %i, perimeter: %i", area, perimeter);

}

@end

//---- program section ----
 int main (int argc, char * argv[])
{
 @autoreleasepool {
Rectangle *myRectangle;
myRectangle =[Rectangle alloc];
myRectangle =[myRectangle init];
[myRectangle setHeight:3];
[myRectangle setWidth:2];
[myRectangle print];
}
return 0;
}



But I get a value of 0 for area and perimeter.
Please tell me what is wrong.

Also:

- When do I have to use "return"? Ch 4 in Programming in Objective-C doesn't really use it in the examples so I've avoided it until going to the classroom.com forums. I have not used it for the previous chapter 4 examples. What (simple)alternatives are there to using return(It's just now dawning on me that there are multiple ways to do things)?

- When should I use "print" vs. NSLog? As in when should I predefine the "print" method in the implementation section vs. simply using an NSLog method(it's a method, right?) in the program section?

- Can I use the "print" method to print to display more than one thing? Meaning can I have one method displays "a+b -c" and another display "a+f*h", like a print1 and a print2?

This has been very difficult for me so far and I'm still wrapping my head around the whole "method, object, argument" stuff so if in your responses you could explicitly label the thing you're talking about as a method, object, etc, that would really help me out.

One final question: When I copy/paste code that I write up in Pages, I always get an error in the "NSLog(@"...." line, when I re-write the line in Xcode, the error usually goes away, I assume this has something to do with an unrecognized font or something in Pages, what text editor do you guys use to write up code in?

Replies

  • BrianSlickBrianSlick Posts: 9,301Tutorial Authors, Registered Users
    NSLog (@"area: %i, perimeter: %i", area, perimeter); 
    You are logging the area and perimeter instance variables. Instance variables are all initialized to 0 (or nil) when the parent object is created, so they will remain 0 until something causes them to change. You only change those values when calling the methods with the same names, but you don't actually call those methods. So in this particular case, if you had done everything else correctly, then all you would need to do is make this change:
    NSLog (@"area: %i, perimeter: %i", [self area], [self perimeter]); 
    However, you have a problem with each of these methods:
    -(int) area;  
    {
    area = height*width;
    }
    -(int) perimeter;
    {
    perimeter = (height*2) + (width*2);
    }
    The (int) part at the beginning of each one means that each method should return an int. However, neither method returns anything. You should have warnings about this already. You perform the calculation, assign the result to the instance variable, and that's it. You never return a value. So each of these needs to look more like this:
    -(int) area;  
    {
    area = height*width;
    return area;
    }
    -(int) perimeter;
    {
    perimeter = (height*2) + (width*2);
    return perimeter;
    }
    So this is a partial answer to your question about return.

    The print method is just something that whoever set this up decided to do. It isn't required. You generally wouldn't create a method whose sole purpose is to log something. Even if you wanted to, you should give it a better name like printAreaAndPerimeter so that you know what it does. Otherwise you can make as many of them as you want for different purposes. It's just a method like any other method.

    Is there a reason that you aren't using Xcode all of the time? Coding in Pages would have to be truly painful.
    Spaces
  • SpacesSpaces Posts: 6New Users
    Thanks but you tell me how the value of "myFraction" is displayed in the following program without using "return" at any point?

    // Program to work with fractions – class version #import <Foundation/Foundation.h>
    //---- @interface section ----
    @interface Fraction: NSObject
    -(void) print;
    -(void) setNumerator: (int) n; -(void) setDenominator: (int) d;
    @end
    //---- @implementation section ----
    @implementation Fraction {
    int numerator;
    int denominator; }
    -(void) print {
    NSLog (@"%i/%i", numerator, denominator); }
    -(void) setNumerator: (int) n {
    numerator = n; }
    -(void) setDenominator: (int) d {
    denominator = d; }
    @end
    //---- program section ----
    int main (int argc, char * argv[]) {
    @autoreleasepool { Fraction *myFraction;
    // Create an instance of a Fraction
    myFraction = [Fraction alloc]; myFraction = [myFraction init];
    // Set fraction to 1/3
    [myFraction setNumerator: 1]; [myFraction setDenominator: 3];
    // Display the fraction using the print method
    NSLog (@"The value of myFraction is:");
    [myFraction print]; }
    return 0; }


    About Pages: I've been taking notes in Pages and copying code the pdf book into Pages so it just seemed natural to write up something in Pages and test it in Xcode, but I suppose that doesn't make much practical sense, particularly after I realized I could change the font size in Xcode.
    Post edited by Spaces on
  • BrianSlickBrianSlick Posts: 9,301Tutorial Authors, Registered Users
    First of all, stop doing this in 3 lines:
    Rectangle *myRectangle;  
    myRectangle =[Rectangle alloc];
    myRectangle =[myRectangle init];
    Should be like this:
    Rectangle *myRectangle = [[Rectangle alloc] init];
    Think of alloc/init like a pair of methods that you need to perform at the same time. You should never do alloc and stop there, and you should never do init unless the previous step was an alloc. If you are doing one, you should also do the other. Putting them on separate lines makes it too easy to forget one of the steps. There will be other situations where putting things on separate lines is probably better for readability, but this is not one of those occasions.


    Specific to your question, you create a fraction object, you set the numerator and the denominator, and then you call the print method. The setNumerator and setDenominator methods each take the input value and assign it to the corresponding instance variables. These are each void methods, so nothing needs to be returned. By the time you call the print method, the instance variables have the values previously assigned, so you get the log output. The print method is also defined as a void method, so nothing needs to be returned.

    All that return means is that you are finished with a particular method. But if the method isn't expected to return a value, then explicitly saying return isn't necessary.
    - (void)doSomeWork
    {
    // Do the work
    }
    The method is finished when you hit the last }. There is nothing else to be done here. Adding a return is not necessary. It won't hurt anything, but it isn't doing anything either.
    - (void)doSomeWork
    {
    // Do the work

    return;
    }
    There is nothing functionally different between these two code samples. Where it can make sense to specify a return is if you wish to drop out of the method early:
    - (void)doSomeWork
    {
    if (somethingBadHappened)
    return;

    // Do the work
    }
    So if something bad happened based on whatever criteria you care about, you can exit the method early.

    Void (and IBAction) methods do not return values, so that's why your program is working without the returns. This changes if you define the method to return something:
    - (float)doSomeWorkAndTellMeTheResult
    {
    // Do the work
    return theAnswer;
    }
    And you can exit early in these cases too, but you still have to return something:
    - (float)doSomeWorkAndTellMeTheResult
    {
    if (somethingBadHappened)
    return 0.0;

    // Do the work
    return theAnswer;
    }
    Post edited by BrianSlick on
    Spaces
Sign In or Register to comment.