Amazon.com Widgets Exercise 7.2
Welcome, Guest. Please login or register.
Did you miss your activation email?
October 21, 2014, 04:55:05 AM
Home Help Search chat Login Register 
News: Read this please.The Great Kangaroo Escape Looking for reviews of the 4th ed on Amazon!   Twitter:  @skochan
                     

+ Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
|-+ Old Stuff
| |-+ Answers to Exercises
| | |-+ Chapter 7
| | | |-+ Exercise 7.2
Pages: [1] 2 3 Go Down
Print
Author Topic: Exercise 7.2 (Read 8704 times)
amuso
Jr. Member
**
Posts: 68


Hope to make a living coding...

amuso@scw.net




on: February 12, 2009, 12:34:49 PM

Trying to modify the print method... I am having problems not changing the fraction itself.

This code (Fraction.m) works, but changes the fraction:

-(void) print: (BOOL) simplify    // call method using [aFraction print: FALSE]; or [aFraction print: TRUE];
{
   if ( simplify ) {     // We called the method with a TRUE statement
      [self reduce];
      NSLog (@"%g - WAS reduced.", numerator, denominator);
   } else {
      NSLog (@"%i/%i - NOT reduced.", numerator, denominator);
   }
}

This was verified by first calling the method with a TRUE statement, then a FALSE. Both returned a reduced fraction since the method reduce obviously reduces the fraction during the first run... (from the main code):

   resultFraction = [aFraction add: bFraction];
   [resultFraction print: FALSE];
   [resultFraction print: TRUE];

(If I swap the last two lines I see that the fraction is modified since the output then is two reduced fractions).


Then I tried to alter the code to create a new fraction which would be modified if the Simplify statement was TRUE... However I cannot get it to work properly... Here is what I got:

-(void) print: (BOOL) simplify
{
   if ( simplify ) {
      Fraction *result = [[Fraction alloc] init];
      [result setTo: numerator over: denominator];
      [result reduce];

      NSLog (@"%i/%i - WAS reduced.", numerator, denominator);
      [result release];
   } else {
      NSLog (@"%i/%i - NOT reduced.", numerator, denominator);
   }
}

The output though doesnt reduce the fraction...

2009-02-12 20:32:34.256 FractionTest[7985:10b] 1/4 - NOT reduced.
2009-02-12 20:32:34.258 FractionTest[7985:10b] +
2009-02-12 20:32:34.259 FractionTest[7985:10b] 1/2 - NOT reduced.
2009-02-12 20:32:34.259 FractionTest[7985:10b] =
2009-02-12 20:32:34.260 FractionTest[7985:10b] 6/8 - NOT reduced.
2009-02-12 20:32:34.261 FractionTest[7985:10b] 6/8 - WAS reduced.

My first code would, but of course did so by modifying the actual fraction...

2009-02-12 20:19:39.978 FractionTest[7846:10b] 6/8 - NOT reduced.
2009-02-12 20:19:39.978 FractionTest[7846:10b] 3/4 - WAS reduced.

Last Edit: February 12, 2009, 12:36:55 PM by amuso Logged

MacBook MB063 4GB OS X 10.7.3 (Xcode 4.3)
iMac MA876 3GB OS X 10.7.3
iPhone 4S 16GB 5.0.1 / iPad 2 16GB 5.0.1
Need translations to Norwegian? Happy to help.
skochan
Administrator
Hero Member
*****
Posts: 3114







Reply #1 on: February 12, 2009, 12:40:58 PM

Your approach in the second case is correct.  Note that you're reducing result but your NSLog statements are displaying the numerator and denominator of the receiver, not of result.

Cheers

Steve
Logged
amuso
Jr. Member
**
Posts: 68


Hope to make a living coding...

amuso@scw.net




Reply #2 on: February 12, 2009, 01:09:49 PM

Ah, of course... I see that now. Is this a valid way to fetch those values ?

NSLog (@"%i/%i - WAS reduced.", result.numerator, result.denominator);

Anyways, now the program does actually work as intended:

2009-02-12 21:05:45.843 FractionTest[8503:10b] 7/4 - NOT reduced.
2009-02-12 21:05:45.845 FractionTest[8503:10b] = 1 3/4 - NOT REDUCED
2009-02-12 21:05:45.845 FractionTest[8503:10b] +
2009-02-12 21:05:45.845 FractionTest[8503:10b] 1/2 - NOT reduced.
2009-02-12 21:05:45.847 FractionTest[8503:10b] =
2009-02-12 21:05:45.848 FractionTest[8503:10b] 9/4 - WAS reduced.
2009-02-12 21:05:45.848 FractionTest[8503:10b] = 2 2/8 - WAS REDUCED
2009-02-12 21:05:45.848 FractionTest[8503:10b] 18/8 - NOT reduced.
2009-02-12 21:05:45.851 FractionTest[8503:10b] = 2 2/8 - NOT REDUCED

(I moved on while waiting for a tip, and applied the necessary code from exercise 7.5 which is why it says 7/4 is 1 3/4 etc).

I have a habit of adding a bunch of comment output to see if the desired code is run which is why all the extra (WAS or NOT reduced) is output.

Logged

MacBook MB063 4GB OS X 10.7.3 (Xcode 4.3)
iMac MA876 3GB OS X 10.7.3
iPhone 4S 16GB 5.0.1 / iPad 2 16GB 5.0.1
Need translations to Norwegian? Happy to help.
skochan
Administrator
Hero Member
*****
Posts: 3114







Reply #3 on: February 12, 2009, 01:11:05 PM

Yep, looks good!

Cheers,

Steve
Logged
rock
Newbie
*
Posts: 10






Reply #4 on: April 11, 2009, 11:20:01 AM

I am having an issue with understanding the statement "Modify the print method from your Fraction class so that it takes an optional BOOL argument..." from this exercise.  The solution given here is not actually an optional argument, is it (i.e. you must supply YES or NO)?

How do you create a method that has truly optional arguments, and does that actually apply to this exercise, or was the intention to simply have a BOOL that is always populated (which is not how the exercise reads at all, btw)?

Related to that, how do you create an argument that is prepopulated with a default, as in:
Code: (Objective-C)
function(a,b=null)
so that "a" is required, but if "b" is not supplied, the default is null?  Is that something that even makes sense in Objective-C?

Thanks.
Logged
skochan
Administrator
Hero Member
*****
Posts: 3114







Reply #5 on: April 11, 2009, 11:44:44 AM

That is a typo.  It really should say to modify it to take an additional argument, not an optional one!

Cheers,

Steve Kochan
Logged
dysan819
Newbie
*
Posts: 1



Email




Reply #6 on: April 12, 2009, 03:40:51 PM

That helps, because I don't think that technique was explained yet.

Could you write a second version of the method:
Code: (Objective-C)
- (void) simplify {
    // do work here
}
- (void) print {
    // do work here
}
- (void) print: (BOOL) simplify {   
    if (simplify) {
        [self simplify];
    }
    [self print];
}
and the program will run the correct version?
Code: (Objective-C)
    [aFraction print];
    [aFraction print: TRUE];
Logged
skochan
Administrator
Hero Member
*****
Posts: 3114







Reply #7 on: April 12, 2009, 05:16:57 PM

That works but, of course, print and print: are two different methods, not one that takes an optional argument!

Cheers,

Steve
Logged
scutter7282
Newbie
*
Posts: 18






Reply #8 on: June 02, 2009, 02:38:38 PM

This question is about 7.2 but on the topic of memory release (related to the big 7.5/7.6 discussion which I've read):

I'm wondering where in my code does it indicate that the object "result" that I created in the print method is released?  In the console, it looks fine.  If I add to main.m "[result release];" before or after releasing aFraction, it says it can't release something already released. 

Comparing to 7.5, it seems to me that I was supposed to release both of them in order to not have memory leak.


Code: (Objective-C)
#import <Foundation/Foundation.h>

@interface Fraction: NSObject
{
int numerator;
int denominator;
}

@property int numerator, denominator;

-(void) print: (BOOL) simplify;
-(void) setTo: (int) n over: (int) d;
-(void) reduce;
@end

@implementation Fraction

@synthesize numerator, denominator;

-(void) print: (BOOL) simplify
{
if (denominator == 1)
NSLog(@"%i", numerator);
else if (numerator == 0)
NSLog(@"0");
else if (simplify) {
Fraction *result = [[Fraction alloc] init];
[result setTo: numerator over: denominator];
[result reduce];
NSLog(@"%i/%i", result.numerator, result.denominator);
// release result in main
}
else
NSLog(@"%i/%i", numerator, denominator);
}
-(void) setTo: (int) n over: (int) d
{
numerator = n;
denominator = d;
}
-(void) reduce
{
int u = numerator;
int v = denominator;
int temp;

while (v != 0) {
temp = u % v;
u = v;
v = temp;
}

numerator /= u;
denominator /= u;
}
@end

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Fraction *aFraction = [[Fraction alloc] init];
Fraction *result;
[aFraction setTo: 6 over: 8];

result = aFraction;
[result print: YES];
[aFraction print: NO];


[aFraction release];


    [pool drain];
    return 0;
}

/* Console Output:
[Session started at 2009-06-02 17:37:24 -0400.]
2009-06-02 17:37:24.725 Fraction[10495:10b] 3/4
2009-06-02 17:37:24.727 Fraction[10495:10b] 6/8

The Debugger has exited with status 0.
*/

Logged
skochan
Administrator
Hero Member
*****
Posts: 3114







Reply #9 on: June 02, 2009, 02:51:05 PM

You don't need to use the temporary Fraction result that you create inside your add: method after you've reduced and printed its value.   That is, its value is not returned to (or needed by) the caller (main) and so you can release it in your print method when you're done using it.

Cheers,

Steve
Logged
nhohmann
Global Moderator
Jr. Member
*****
Posts: 57







Reply #10 on: July 02, 2009, 05:06:39 AM


-(void) print: (BOOL) simplify
{
   if ( simplify ) {
      Fraction *result = [[Fraction alloc] init];
      [result setTo: numerator over: denominator];
      [result reduce];

      NSLog (@"%i/%i - WAS reduced.", numerator, denominator);
      [result release];
   } else {
      NSLog (@"%i/%i - NOT reduced.", numerator, denominator);
   }
}

I realize this was posted months ago, but I'm confused.  What does your FractionTest.m look like?  Specifically, what expression or "test" is determining whether or not the Boolean variable "simplify" (as shown above) is TRUE or FALSE? 

It seems like the test that would determine if the fraction needs to be reduced would be the reduce loop itself (found in the reduce method), so why bother?  Calling the reduce method works the same whether a fraction needs to be reduced or not.  So why waste the time and code?  (Especially if they're one and the same.)

I must be missing something.  Am I?  (I hope so.)  Please help.

Thanks,

Neil
Logged
skochan
Administrator
Hero Member
*****
Posts: 3114







Reply #11 on: July 02, 2009, 06:39:39 AM

Neil,

The purpose of this exercise was to add a print: method that takes a BOOL argument to indicate if you want to have to fraction reduced before printing.  That's not the same as specifying whether the fraction can be reduced.  So, for example, give the fraction 6/8 is stored in myFract, this call:

Code: (Objective-C)
[myFract print: YES];

should produce 3/4 as the output, whereas

Code: (Objective-C)
[myFract print: NO];

should display 6/8, since the NO means not to reduce the fraction.

Cheers,

Steve Kochan
Logged
nhohmann
Global Moderator
Jr. Member
*****
Posts: 57







Reply #12 on: July 03, 2009, 02:45:33 AM

Thanks Steve -- I think I was reading too much into the exercise.  That said, here are snippets of my code and output.  Everything seems to work (after a good 30 minutes of banging around).  Let me know if anything seems amiss.

Here is the console output, which includes the reduced and non-reduced result (to show that the original fraction was not permanently changed):
Code: (Objective-C)
[
[Session started at 2009-07-03 11:12:33 +0200.]
2009-07-03 11:12:33.082 FractionTest[1182:10b] 2/4
2009-07-03 11:12:33.092 FractionTest[1182:10b] +
2009-07-03 11:12:33.095 FractionTest[1182:10b] 1/4
2009-07-03 11:12:33.097 FractionTest[1182:10b] =
2009-07-03 11:12:33.099 FractionTest[1182:10b] 3/4
2009-07-03 11:12:33.102 FractionTest[1182:10b] Previously the fraction had been 12/16.

The Debugger has exited with status 0.

Here is part of the FractionTest.m file that calls the print method with the added Boolean variable, reduceFrac:
Code: (Objective-C)
// Print results

[aFraction print: NO];
NSLog (@"+");
[bFraction print: NO];
NSLog (@"=");

resultFraction = [aFraction add: bFraction];
[resultFraction print: YES];


And here is the print method in the Fraction.m file:
Code: (Objective-C)
-(void) print: (BOOL) reduceFrac
{
if (denominator == 1)
NSLog (@"%i", numerator);
else if (reduceFrac)
{
Fraction *reduceFraction = [[Fraction alloc] init];
[reduceFraction setTo: numerator over: denominator];
[reduceFraction reduce];
NSLog(@"%i/%i", reduceFraction.numerator, reduceFraction.denominator);
NSLog (@"Previously the fraction had been %i/%i.", numerator, denominator);
[reduceFraction release];
}
else
NSLog (@"%i/%i", numerator, denominator);
}
Last Edit: July 04, 2009, 07:13:57 AM by nhohmann Logged
TheWildJacko
Newbie
*
Posts: 2






Reply #13 on: August 27, 2009, 11:59:38 PM

Thanks for posting these answers.  This exercise confused me a bit but now I get it.  Also, once I understood out how to do this exercise, I found that if the fraction you are trying to reduce is something like 9/3, the print method will reduce it to 3/1, not 3 (because it will only check for 1 in the denominator once, before it reduces the fraction).  So you can add an extra else if statement checking whether numerator % denominator == 0, and then printing a whole number if the if statement is true.

Code: (Objective-C)
- (void) print: (BOOL) toReduce
{
if (denominator == 1) NSLog(@"%i", numerator);
else if (numerator == 0) NSLog(@"0");
else if (numerator % denominator == 0) NSLog(@"%i", numerator / denominator);
else if (denominator == 0) NSLog(@"Undefined: denominator = 0");
else if (toReduce)
{
Fraction *result = [[Fraction alloc] init];
[result setTo: numerator over: denominator];
[result reduce];

if (result.denominator == 1) NSLog(@"%i", result.numerator);
else NSLog(@"%i/%i", result.numerator, result.denominator);

[result release];
}
else NSLog(@"%i/%i", numerator, denominator);
}
Last Edit: August 28, 2009, 01:00:31 AM by TheWildJacko Logged
jocko757
Newbie
*
Posts: 12


Email




Reply #14 on: February 28, 2010, 08:49:44 AM

Hi guys, I have ZERO programming experience and am way behind all of you.  This exercise took me two days and I'm still confused about one thing...

Can anyone explain to me where you declare the Boolean variable?  I declared it in the main like this:

BOOL toReduce;

In the interface section, I declared the print method like this:

-(void) print: (BOOL) toReduce;

Then I called on the print method like this...

[aFraction print: NO]

[resultFraction print: YES]


When I run the program, I get the correct result, but I get a caution...

unused variable "toReduce"

If I comment out    //BOOL toReduce;   everything works.  So my question is, how does the program know that the boolean variable "toReduce" is in fact a boolean variable?  From the declaration in the interface section?

Any clarification would be appreciated.  Thanks, Jack







Logged
Pages: [1] 2 3 Go Up
Print
Jump to:



Login with username, password and session length

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents (c) 2009 classroomM.com. All rights reserved.