Programming in Objective-C

Updated Resources
Download Program Examples
Answers to Odd-Numbered Exercises
Errata

I hope you are enjoying Programming in Objective-C. I welcome your feedback! Feel free to email your comments to me. Of course, your feedback on Amazon.com would also be appreciated!
 
Regards,
 

 
Steve Kochan

Updated Resources

Updated resources are listed here to supplement those listed in Appendix E of Programming in Objective-C. Please email me with any resources you think should be listed here. Thanks!
1. This is from Alex Perez, who is a co-maintainer of the GNUstep.org website:

As co-maintainer of the GNUstep.org website, I noticed that in the Resources section of your book, there are three URLs to the GNUstep website, one on page 535 and two on 536. Due to a recent redesign of the website (check it out, if you haven't, it looks quite nice :), two of the three URLs are no longer valid. I am working with our server maintainer to get pernament HTTP redirects set up so they continue to be valid in light of the fact that it's not very easy to update URLs in books ;-) On another note, I wanted to let you know that there is a very handy GNUstep development environment installer for Windows which is available at

ftp://ftp.gnustep.org/pub/gnustep/windows/Install-GNUstep-Development-Environment-0.5.1-1.9.0.exe


(There's a link on the front page of our site, as well as our download section). This significantly simplifies the building of GNUstep on Win32.
2. This is from André Brière:

The latest versions (1.5.X) of Cygwin support Objective-C. Their FAQ states the opposite, but it seems outdated. I have 1.5.7 and gcc compiles Objective-C code just fine.

Download Program Examples

Return to top
The program examples are archived in tar format. To extract the archive, first download the file to your disk, then run tar on the archive. Note that some browsers will automatically extract the archive into a folder for you. Otherwise, you can run tar like this

tar xvf examples.tar

Click here to download examples

Please let me know if you need the examples in some other format.


Errata

Return to top
Following is errata from the first and second printings of Programming in Objective-C. If you spot any other errors, please send me an email and let me know. Thanks!
Page Errata
-- The following applies to readers using Xcode for the first part of the book: "If you use Xcode instead of the command-line tools, you will need to delete the contents of the automatically-generated ..._Prefix.pch file as well as the #import line at the top of main.m each time you start a project (the book only specifies the latter)." [Thanks to KIeth Blount]
1 The statement about GCC being in the public domain is false. The copyrights for all Free Software Foundation products are owned by the FSF. It is released under the GNU General Public License. [Thanks to Alex Perez]
9 In the first gcc example, the comment "Compile main.c and call it prog1" should be in italics and not bold [Thanks to David Bayendor]
56 In line 10, change "Objective-C (25) would take place." to read "c (25) would take place." [Thanks to John Flanigan]
68 There are two extra lines of output shown for Program 4.7. [Thanks to Ryan Govostes]
88 For Program 5.7, the greatest common divisor of 1026 and 540 is 54 (not 27). [Thanks to Alex Eagar]
89 In lines 6 and 7, change the ÷ character to a % character. [Thanks to Ryan Govostes]
92 Exercise 4 should refer to Program 5.3A. [Thanks to John Flanigan]
145 Exercises 6 and 7 should refer to Exercise 7 from Chapter 4. [Thanks to John Flanigan]
145 Exercise 6: add: method should read -(Complex *) add: (Complex *) complexNum;
Also, the sum for the example shoud be 8.0 + 11i [Thanks to John Flanigan]
159 Program 8.6: In -(void) setX: (int) xVal; andY: (int) yVal remove the embedded semicolon to read -(void) setX: (int) xVal andY: (int) yVal
174 Exercise 6: In the example, the origin of the intersecting rectangle should be (400, 420) and not (400, 380). [Thanks to Matthew Woolums]
233 The brackets are wrong in the MakeFract macro definition. Change it to read


  #define MakeFract(x,y)    ([[Fraction alloc] initWith: x over: y])

[Thanks to Ingo Paulsen]

355 (2nd printing only) Program 15.14: Add a semicolon to the end of the line that reads AddressCard *myCard
367 Program 15.18: Change the line that reads
    if ([set1 isEqualToSet: set2] == NO)
to read
    if ([set1 isEqualToSet: set2] == YES)

[Thanks to Alex Eagar]

390 (2nd printing only) Program 16.6: Add a declaration to the program: BOOL fileExists;
533 My email address is incorrect. It should be steve@kochan-wood.com
Below is listed errata from the first printing of the book.
Page Errata
-- There are many examples that were not formatted correctly due to a problem with the publisher's typsetting software. The programs will still run correctly and the formatting will be corrected in the next printing. I'm sorry about that.
92 Exercise 3: 5! is 120, not 1 as shown
120, 123, 339 In all three places the number 2 should be displayed as the first prime number (the publisher hasn't been able to explain this one to me!)
141 Delete the third line of output from Program 7.5. [Thanks to Ingo Paulsen]
149 Figure 8.3: There should be a directed line from the first x to the second x; There should be a directed line from the first initVar to the second initVar
152 Correct method name is -(void) setWidth: (int) w andHeight: (int) h in two places. [Thanks to Francisco Garuti]
158 In Program 8.6, change the first line from #include "Point.h" to #import "Point.h"
180 Program 9.2: remove the line [dataValue free]; from the end of main
198 Inside method allocF the statement should read ++gCounter; and not ++counter;
202 Program 10.3: Change the line enum month aMonth; to read enum month amonth;
214 Program 11.1: Inside method mul: a [ is missing at the beginning of the line that starts
result setTo: numerator * ...
225 Exercise 5: The initWithside: method should return a Square object and the setSide: method no value (that is, type void)
229 Change the line that reads return TWO_PI * r; to read return TWO_PI * radius; [Thanks to Ingo Paulsen]
248 Change the line about Fibonacci numbers to read:
Thereafter, each successive Fibonacci number Fi is defined to be the sum of the two preceding Fibonacci numbers Fi-2 and Fi-1.
278 Program 13.10: In the line that reads printf ("Today's date is %i/%i/.2%i.\n", change .2%i to %.2i
342 Program 15.9: Change NSAutoreleasepool to NSAutoreleasePool
345 Program 15.10: Insert #import <Foundation/NSAutoreleasePool.h> at the beginning of the program. Change NSAutoreleasepool to NSAutoreleasePool in the program.
347 Insert a closing } at the end of the list method.
354 (BOOL) isEqual should be -(BOOL) isEqual
355 Program 15.14: Change the line that reads
    AddressCard *myCard = [AddressBook alloc];
to read
    AddressCard *myCard;
370 Exercise 7 is really part of Exercise 6.
383 Program 16.4: Add a closing > after #import <NSAutoreleasePool.h
390 Program 16.6: Change the line
     NSArray *args = [NSProcessInfo arguments];
to read
    NSArray *args = [proc arguments];

In the statement [NSFm fileExistsAtPath: dest isDirectory: &isDir]; the result returned from the method should also be tested in the if that follows to see if the file exists and is a directory (the value of isDir is meaningless if the file does not exist)

402 Program 17.1: Remove the [ from in front of the printf.
410-411 Change the "Foo dealloc" message in the dealloc method to "ClassA dealloc". The output from Program 17.5 should then be changed acordingly, as well as the reference in the text on page 411.
448 Program 19.12: Insert the line
    #import <Foundation/NSArray.h>
after the line
    #import <Foundation/NSArchiver.h>

Answers to Odd-Numbered Exercises

Return to top
As a result of the feedback I received, I am posting the answers to the odd-numbered exercises. So far I have posted all but one answer (from Chapter 15).
Chapter 2
Chapter 3
Chapter 4
Chapter 5
Chapter 6
Chapter 7
Chapter 8
Chapter 9
Chapter 10
Chapter 11
Chapter 12
Chapter 13
Chapter 14
Chapter 15
Chapter 16
Chapter 17
Chapter 18
Chapter 19


Chapter 2

2-3
Testing.......1...2..3

2-5
1. Semicolon should not appear at the end of the first line
2. Code for main should start with a { and not a (
3. Keyword INT should be int
4. Comment /* COMPUTE RESULT  should be terminated with a */
5. Missing semicolon at end of statement sum = 25 + 37 - 19
6. Comment for DISPLAY RESULTS is wrong; either use a /* .. */ pair or being the line with //
7. String inside printf should be enclosed in double quotes, not single quotes
8. Missing a comma before the second argument to printf


Chapter 3

3-1
6_05 is invalid because it starts with a number
A$ is invalid because it contains an invalid character (the $)

3-5
The advantages are that you can apply the same method name to verhicles 
from different classes.  In other words, you can send the "prep" message 
to a vehicle, and that vehicle could be a Car, a Motorcycle, or a Boat.  
You don't have to figure out what vehicle type is first. This feature is 
known as polymorphism, and is discussed in greater detail in Chapter 9.

3-7
#include <objc/Object.h>

@interface Point: Object
{
        int  x;
        int  y;
}

-(void) setX: (int) xVal;
-(void) setY: (int) yVal;

-(int) x;
-(int) y;
@end

@implementation Point;
-(void) setX: (int) xVal
{
        x = xVal;
}

-(void) setY: (int) yVal
{
        y = yVal;
}

-(int) x
{
        return x;
}

-(int) y
{
        return y;
}
@end

int main (int argc, char *argv[])
{
        Point *pt1, *pt2;

        pt1 = [[Point alloc] init];
        pt2 = [[Point alloc] init];

        // set first point to (100, 200)

        [pt1 setX: 100];
        [pt1 setY: 200];

        // set second point to (-20, 55)

        [pt2 setX: -20];
        [pt2 setY: 55];

        // retrieve and display values

        printf ("Pt1 = (%i, %i)\n", [pt1 x], [pt1 y]);
        printf ("Pt2 = (%i, %i)\n", [pt2 x], [pt2 y]);

        // release their memory
        [pt1 free];
        [pt2 free];

        return 0;
}


Chapter 4

4-1
0996        '9' is not a valid octal digit
0x10.5      An exponent is required for a hexadecimal floating constant
1.2Fe-7     Can't use 'F' and 'e' together
98.7U       'U' is not a valid suffix for a floating constant
0X0G1       'G' is not a valid hexadecimal digit
17777s      's' is not a valid qualifier
15,000      Commas are not permitted in numbers

4-3
d = d

4-5
#import <stdio.h>

int main (int argc, char *argv[])
{
    double result;

    result = (3.31e-8 * +2.01e-7) / (7.16e-6 + 2.01e-8);
    printf ("result = %g\n", result);

    return 0;
}
 

4-7
#import <objc/Object.h>
#import <stdio.h>

@interface  Rectangle: Object
{
        int     width;
        int     height;
}

-(void)   setWidth: (int) w;
-(void)   setHeight: (int) h;
-(int)    width;
-(int)    height;
-(int)    area;
-(int)    perimeter;
@end

@implementation Rectangle;

-(void) setWidth: (int) w
{
        width = w;
}

-(void) setHeight: (int) h
{
        height = h;
}

-(int) width
{
        return width;
}

-(int) height
{
        return height;
}

-(int) area
{
        return width * height;
}

-(int) perimeter
{
        return (width + height) * 2;
}
@end


int main (int argc,  char *argv[])
{
   Rectangle  *myRect = [[Rectangle alloc]  init];

   [myRect setWidth: 5];
   [myRect setHeight: 8];

   printf ("Rectangle: w = %i, h = %i\n", [myRect width], [myRect height]);
   printf ("Area = %i, Perimeter = %i\n", [myRect area], [myRect perimeter]);

   [myRect free];

   return 0;
}

4-9
#import <objc/Object.h>
#import <stdio.h>

@interface  Calculator: Object
{
    double  accumulator;
}   

// accumulator methods
-(void)   setAccumulator: (double) value;
-(void)   clear;
-(double) accumulator;       

// arithmetic methods
-(double)   add: (double) value;
-(double)   subtract: (double) value;
-(double)   multiply: (double) value;
-(double)   divide: (double) value;      
-(double)   changeSign;
-(double)   reciprocal;
-(double)   xSquared;
@end

@implementation Calculator;     
-(void) setAccumulator: (double) value
{
        accumulator = value;
}

-(void) clear
{
        accumulator = 0;
}

-(double) accumulator
{
        return accumulator;
}

-(double) add: (double) value
{
        accumulator += value;
        return accumulator;
}

-(double) subtract: (double) value
{
        accumulator -= value;
        return accumulator;
}

-(double) multiply: (double) value
{
        accumulator *= value;
        return accumulator;
}

-(double) divide: (double) value
{
        accumulator /= value;
        return accumulator;
}

-(double)   changeSign
{
        accumulator = -accumulator;
        return accumulator;
}

-(double)   reciprocal
{
        accumulator = 1 / accumulator;
        return accumulator;
}

-(double)   xSquared
{
        accumulator *= accumulator;
        return accumulator;
}
@end

int main (int argc, char *argv[])
{
        Calculator   *myCalc;

        myCalc = [[Calculator alloc]  init];

        [myCalc clear];
        [myCalc setAccumulator: 10.0];    // acc = 10.
        [myCalc xSquared];                // acc = 100.
        [myCalc reciprocal];              // acc = 1/100.
        [myCalc changeSign];              // acc = -1/100

        printf ("The result is %g\n", [myCalc accumulator]);

        [myCalc free];
        return 0;
}


Chapter 5

5-1
// Program to generate a table of triangular numbers 

#import <stdio.h>

int main (int argc, char *argv[])
{
     int  n, nSquared;

     printf ("TABLE OF SQUARESn\n");
     printf (" n       n squared\n");
     printf ("---   ---------------\n");

     nSquared = 1;

     for ( n = 1;  n <= 10;  ++n ) {
        nSquared = n * n;
        printf ("%2i          %i\n", n, nSquared);
     }

    return 0;
}


5-3
// Program to generate a table of factorials 

#import <stdio.h>

int main (int argc, char *argv[])
{
     int  n, nFactorial;

     printf ("TABLE OF FACTORIALS\n");
     printf (" n          n!\n");
     printf ("---   ---------------\n");

     nFactorial = 1;

     for ( n = 1;  n <= 10;  ++n ) {
        nFactorial *= n;
        printf ("%2i      %8i\n", n, nFactorial);
     }

    return 0;
}


5-5
#import <stdio.h>

int main (int argc, char *argv[])
{
        int n, number, triangularNumber, counter, numReps;

        printf ("How many triangular numbers do you want? ");
        scanf ("%i", &numReps);

        for ( counter = 1; counter <= numReps; ++counter ) {
                printf ("What triangular number do you want? ");
                scanf ("%i", &number);

                triangularNumber = 0;

                for ( n = 1; n <= number; ++n )
                        triangularNumber += n;

                printf ("Triangular number %i is %i\n\n", number, triangularNumber);
        }

        return 0;
}

5-7
Each digit would be preceded by a minus sign.
A number like -123 would display as -3-2-1.



Chapter 6

6-1
#import <stdio.h>

int main (int argv, char *argc[])
{
        int     n1, n2;

        printf ("Enter your two integers: ");
        scanf ("%i %i", &n1, &n2);

        if ( n1 % n2 == 0 )
                printf ("%i is evenly divisible by %i\n", n1, n2);
        else
                printf ("%i is not evenly divisible by %i\n", n1, n2);

        return 0;
}

6-3
// This goes a little further than the exercise
// called for by also display fractions like 10/2 as 5.

-(void) print
{
        if (numerator == 0)
                printf (" 0 ");
        else if (numerator % denominator == 0)
                printf (" %i ", numerator / denominator);
        else
                printf (" %i/%i ", numerator, denominator);
}

6-5
// Program to reverse the digits of a number
// Modified to handle negative numbers

#import <objc/Object.h>
#import <stdio.h>

int main (int argc, char *argv[])
{
        int   number, right_digit;
        BOOL  isNeg;

        printf ("Enter your number: ");
        scanf ("%i", &number);

        // set flag and negate number if negative

        if (number < 0 ) {
                isNeg = YES;
                number = -number;
        }
        else
                isNeg = NO;

        do {
                right_digit = number % 10;
                printf ("%i", right_digit);
                number /= 10;
        }
        while ( number != 0 );

        // display minus sign if number was negative

        if (isNeg == YES)
                printf ("-");

        printf ("\n");

        return 0;
}

6-7
// Program to generate a table of prime numbers

#import <stdio.h>
#import <objc/Object.h>

int main (int argc, char *argv[])
{
      int       p, d;
      BOOL      isPrime;
        
      printf (" 2  ");  // first prime is 2

      for ( p = 3;  p <= 50;  p += 2 ) {
                isPrime = YES;

                for ( d = 3;  d < p && isPrime == YES;  ++d )
                        if ( p % d  ==  0 )
                                isPrime = NO;

                if ( isPrime == YES )
                        printf ("%i  ", p);
      }

      printf ("\n");
      return 0;
}


Chapter 7

7-1
-(Fraction *) subtract: (Fraction *) f
{
        // To sub two fractions:
        // a/b - c/d = ((a*d) - (b*c)) / (b * d)

        Fraction  *result = [[Fraction alloc] init];
        int         resultNum, resultDenom;

        resultNum = (numerator * [f denominator]) -
                (denominator * [f  numerator]);
        resultDenom = denominator * [f denominator];

        [result setTo: resultNum  over: resultDenom];
        [result reduce];

        return result;
}

-(Fraction *) multiply: (Fraction *) f
{
        Fraction    *result = [[Fraction alloc] init];

        [result setTo: numerator * [f numerator]
                 over: denominator * [f denominator]];
        [result reduce];

        return result;
}

-(Fraction *) divide: (Fraction *) f
{
        Fraction    *result = [[Fraction alloc] init];

        [result setTo: numerator * [f denominator]
                 over: denominator * [f numerator]];
        [result reduce];

        return result;
}

7-3
Just add the message expression

  [sum print];

to the program after the sum has been calculated

7-5
-(void) print 
{
        if (numerator >= denominator)  
                printf (" %i", numerator / denominator);
        
        if (numerator % denominator != 0)
                printf (" %i/%i ", numerator % denominator, denominator);
}


Chapter 8

8-1
// Simple example to illustrate inheritance

#import <objc/Object.h>
#import <stdio.h>

// ClassA declaration and definition

@interface ClassA: Object
{
        int     x;
}

-(void) initVar;
@end

@implementation ClassA;
-(void) initVar
{
        x = 100;
}
@end

// Class B declaration and definition

@interface ClassB : ClassA
-(void) printVar;
@end

@implementation ClassB;
-(void) printVar
{
        printf ("x = %i\n", x);
}
@end

// Class C declaration and definition

@interface ClassC : ClassB
-(void) initVar;
@end

@implementation ClassC;
-(void) initVar
{
        x = 300;
}
@end

int main (int argc, char *argv[])
{
        ClassA   *a = [[ClassA alloc] init];
        ClassB   *b = [[ClassB alloc] init];
        ClassC   *c = [[ClassC alloc] init];

        [a initVar];   // sets a's instance var to 100
        [b initVar];   // sets b's instance var to 100
        [c initVar];   // sets c's instance var to 300

                       // Note ClassA has no printVar method
        [b printVar];  // displays 100
        [c printVar];  // displays 300

        [a free];       
        [b free];       
        [c free];       

        return 0;
}

8-3
// Class B2 declaration and definition

@interface ClassB2: ClassA
-(void) printVar;
@end

@implementation ClassB;
-(void) printVar
{
        printf ("x = %i\n", x);
}
@end

1. ClassB and ClassB2 are both subclasses of Class A
2.           Object  (root)
               |
             ClassA
               |
           ___________
           |          |
         ClassB     ClassB2

3. The superclass of ClassB is ClassA
4. The superclass of ClassB2 is ClassA
5. A class can have any number of subclasses, but only one 
   superclass

8-5
// Note that this exercise uses the sqrt function from the standard
// math library <math.h> to calculate the area of a triangle.  
// To link this routine with gcc, you may need to use the following 
// command line:
//
//  gcc prog.m -lobjc -lm
//
// I apologize for not supplying the formula to calculate the area of
// of a triangle.
//

#import <objc/Object.h>
#import <math.h>

// ************ GraphicObject Class

@interface GraphicObject : Object
{
        int  fillColor;  // 32-bit color
        BOOL filled;     // Is the object filled?
        int  lineColor;  // 32-bit line color
}

-(void) setFillColor: (int) theColor;
-(void) setFilled: (int) isFilled;
-(void) setLineColor: (int) theLineColor;
-(int)  fillColor;
-(BOOL) filled;
-(int)  lineColor;
@end

@implementation GraphicObject;
-(void) setFillColor: (int) theColor
{
        fillColor = theColor;
}

-(void) setFilled: (int) isFilled
{
        filled = isFilled;
}

-(void) setLineColor: (int) theLineColor
{
        lineColor = theLineColor;
}

-(int)  fillColor
{
        return fillColor;
}

-(BOOL) filled
{
        return filled;
}

-(int)  lineColor
{
        return lineColor;
}
@end

// ************ Point class

@interface  Point: Object
{
        int     x;
        int     y;
}

-(void) setX: (int) xVal;
-(void) setY: (int) yVal;
-(void) setX: (int) xVal andY: (int) yVal;
-(int)  x;
-(int)  y;
@end

@implementation Point;

-(void) setX: (int) xVal
{
        x = xVal;
}

-(void) setY: (int) yVal
{
        y = yVal;
}

-(void) setX: (int) xVal andY: (int) yVal
{
        x = xVal;
        y = yVal;
}

-(int) x;
{
        return x;
}

-(int) y;
{
        return y;
}
@end

// ************   Rectangle subclass

@interface Rectangle : GraphicObject
{
        int width;
        int height;
        Point *origin;
}

-(void)    setWidth: (int) w;
-(void)    setHeight: (int) h;
-(void)    setWidth: (int) w andHeight: (int) h;
-(void)    setOrigin: (Point *) pt;
-(Point *) origin;
-(int)     width;
-(int)     height;
-(int)     area;
-(int)     perimeter;
@end

@implementation Rectangle;

-(void) setWidth: (int) w
{
        width = w;
}

-(void) setHeight: (int) h
{
        height = h;
}

-(void) setWidth: (int) w andHeight: (int) h
{
        width = w;
        height = h;
}

-(void) setOrigin: (Point *) pt
{
        origin = pt;
}

-(int) width
{
        return width;
}

-(int) height
{
        return height;
}

-(int) area
{
        return width * height;
}

-(int) perimeter
{
        return (width + height) * 2;
}

-(Point *) origin
{
        return origin;
}
@end

// ************ Circle subclass

@interface Circle : GraphicObject
{
        int   radius;  // this can be stored as a float if you like
        Point *center;
}

-(void) setRadius: (int) r;
-(int)  radius;    
-(float) area;
-(float) circumference;
@end

@implementation Circle;
-(void) setRadius: (int) r
{
        radius = r;
}

-(int) radius
{
        return radius;
}

-(float) area
{
        return 3.141592654 * radius * radius;
}

-(float) circumference
{
        return 2 * 3.141592654 * radius;
}
@end

// ************ Triangle class

@interface Triangle : GraphicObject
{
        int side1;
        int side2;
        int side3;
}

-(void) setSide1: (int) s1 andSide2: (int) s2 andSide3: (int) s3;
-(int) side1;
-(int) side2;
-(int) side3;
-(float) area;
-(int) perimeter;
@end

@implementation Triangle;
-(void) setSide1: (int) s1 andSide2: (int) s2 andSide3: (int) s3
{
        side1 = s1;
        side2 = s2;
        side3 = s3;
}

-(int) side1
{
        return side1;
}

-(int) side2
{
        return side2;
}

-(int) side3
{
        return side3;
}

-(float) area
{
        float s;
        
        s = (side1 + side2 + side3) / 2.0;
        return sqrt (s * (s - side1) * (s - side2) * (s - side3));
}

-(int) perimeter
{
        return side1 + side2 + side3;
}
@end

// Small test program follows

int main (int argc, char *argv[])
{
        Rectangle *rect = [[Rectangle alloc] init];
        Circle    *circ = [[Circle alloc] init];
        Triangle  *tri = [[Triangle alloc] init];
        
        [rect setWidth: 15 andHeight: 12];
        [circ setRadius: 5];
        [tri  setSide1: 6 andSide2: 8 andSide3: 10];

        // You could also take advantage of any of
        // the inherited methods from the GraphicObject
        // class, for example:

        [rect setFilled: YES];
        [circ setLineColor: 0];
        [tri  setFillColor: 0xFFFFFF];

        printf ("Area of rectangle, width = %i, height = %i is %i\n\n", 
                [rect width], [rect height], [rect area]);

        printf ("Circumference of circle with radius %i is %g\n",
                [circ radius], [circ circumference]);
        printf ("Area is %g\n\n", [circ area]);

        printf ("Perimeter of triangle with sides %i, %i, and %i is %i\n",
                [tri side1], [tri side2], [tri side3], [tri perimeter]);
        printf ("Area is %g\n", [tri area]);

        [rect free];
        [circ free];
        [tri free];

        return 0;
}

8-7
-(void) draw
{
        int w, h;


        if (height == 0)
                return;

        // top line

        for (w = 1; w <= width; ++w)
                printf ("-");

        printf ("\n");

        // draw the sides

        for (h = 1; h <= height; ++h) {
                for (w = 1; w <= width; ++w)
                        if (w == 1 || w == width)
                                printf ("|");
                        else
                                printf (" ");

                printf ("\n");
        }

        // bottom line

        for (w = 1; w <= width; ++w)
                printf ("-");

        printf ("\n");
}


Chapter 9

9-1
The Complex class does not have a "reduce" method.  So the compiler will
give you a warning message.  If you run the program anyway, you will also
get a runtime error when the system tries to find the method at runtime.

9-3
// Added print method for Point class

-(void) print 
{
        printf (" (%i, %i) ", x, y);
}

// Test program

#import "Fraction.h"
#import "Complex.h"
#import "Point.h"

int main (int argc, char *argv[])
{
     id       dataValue;
     Fraction *f1 = [[Fraction alloc] init];
     Complex  *c1 = [[Complex alloc] init];
     Point    *p1 = [[Point alloc] init];

     [f1 setTo: 2 over: 5];
     [c1 setReal: 10.0 andImaginary: 2.5];
     [p1 setX: 100 andY: 200];

     // first dataValue gets a fraction

     dataValue = f1;
     [dataValue print];
     printf ("\n");

     // now dataValue gets a complex number

     dataValue = c1;
     [dataValue print];
     printf ("\n");

     // now dataValue gets a point

     dataValue = p1;
     [dataValue print];
     printf ("\n");

     [c1 free];
     [f1 free];
     [p1 free];

     return 0;
}

9-5
The first two results are "NO" and the remaining are "YES"



Chapter 10

10-3
static int gFractionAdds;

-(Fraction *) add: (Fraction *) f
{
        // To add two fractions:
        // a/b + c/d = ((a*d) + (b*c)) / (b * d)

        // result will store the result of the addition
        Fraction        *result = [[Fraction alloc] init];
        int             resultNum, resultDenom;

        resultNum = (numerator * [f denominator]) + 
                (denominator * [f numerator]);
        resultDenom = denominator * [f denominator];

        [result setTo: resultNum over: resultDenom];
        [result reduce];

        ++gFractionAdds;  // Number of fractions added

        return result;
}

// Method to return the number of additions

-(int) numAdditions
{       
        return gFractionAdds;
}

10-5
typedef  Fraction *FractionObj;

10-7
// See if sign extension occurs
// Assumes an 8-bit char

int main (int argc, char *argv[])
{
        char  c1 = 255;  // all 8 bits on
        int   i1;

        // See if sign extension occurs 
        i1 = c1;

        // Will print 255 if no sign extension,
        //             -1 otherwise

        printf ("%i\n", i1);

        return 0;
}


Chapter 11

11-1
#import "Fraction.h"

@interface Fraction (MathOps)
-(Fraction *) add: (Fraction *) f;
-(Fraction *) mul: (Fraction *) f;
-(Fraction *) sub: (Fraction *) f;
-(Fraction *) div: (Fraction *) f;
-(Fraction *) invert;
@end

@implementation Fraction (MathOps)
// include previous add:, mul:, sub:, and div: methods

-(Fraction *) invert
{
        Fraction *result = [[Fraction alloc] init];

        [result setTo: denominator over: numerator];

        return result;
}
@end

11-3
#import "Calculator.h"
#import <math.h>

// Note: These methods really should not take arguments but instead
// should work on the contents of the accumulator.  But here is the
// solution as the problem was stated in the text.

@interface Calculator (Trig)
-(void) sin: (double) angle;
-(void) cos: (double) angle;
-(void) tan: (double) angle;
@end

@implementation Calculator (Trig)
-(void) sin: (double) angle
{
        accumulator = sin (angle);
}

-(void) cos: (double) angle
{
        accumulator = cos (angle);
}

-(void) tan: (double) angle
{
        accumulator = tan (angle);
}
@end

11-5
#import "Square.h"

@implementation Square
{
        Rectangle *rect;
}

-(Square *) initWithSide: (int) s 
{
        self = [super init];

        if (self) {
                rect = [[Rectangle alloc] init];
                [rect setWidth: s andHeight: s];
        }

        return self;
}
        
-(void) setSide: (int) s
{
        [rect setWidth: s andHeight: s];
}

-(int) side
{
        return [rect width];
}

-(int) area
{
        return  [rect area];
}

-(int) perimeter
{
        return  [rect perimeter];
}

-(id)  free
{
        [rect free];
        return [super free];
}
@end

// Simple test program follows


#import <stdio.h>

int main (int argc, char *argv[])
{
        Square *mySquare = [[Square alloc] initWithSide: 7];

        printf ("Square with side: %i, perimeter = %i, area = %i\n",
                [mySquare side], [mySquare perimeter], [mySquare area]);

        [mySquare free];
        return 0;
}


Chapter 12

12-3
#define  MAX(a,b,c)  ( ((a) > (b)) ? \
                        ((a) > (c) ?  (a) : (c)) : \
                       ((b) > (c) ? (b) : (c)) )

int main (int argc, char *argv[])
{
        printf ("%i %i %i %i %i %i\n", MAX (1,2,3), MAX(1,3,2), 
                MAX(3,1,2), MAX(3,2,1), MAX(2,1,3), MAX(2,3,1));

        return 0;
}

12-5
#define IS_ALPHABETIC(c) (IS_LOWER_CASE(c) || IS_UPPER_CASE(c))

12-7
#define ABSOLUTE_VALUE(x)  ((x) < 0 ? -(x) : (x))


Chapter 13

13-1
float average (float data[])
{
        int  i;
        float sum, average;

        for (i = 0; i < 10; ++i)
                sum += data[i];

        average = sum / 10;

        return average;
}

13-3
// Prime numbers generated with Sieve of Erasthothenes

int main (int argc, char *argv[])
{
        int  P[151], i, j;
        int  n = 150;

        for (i = 2; i <= n; ++i)
                P[i] = 0;

        i = 2;
        
        while (i <= n) {
                if (P[i] == 0)
                        printf ("%i  ", i);

                j = 1;

                while (i * j <= n) {
                        P[i * j] = 1;
                        ++j;    
                }

                ++i;
        }

        return 0;
}

13-5
typedef  struct date  {
        int month;
        int day;
        int year;
} Date;

13-7
They are all valid and each printf from a set produces the same output.


Chapter 14

14-3
Just make sure that the parent of the Fraction class is NSObject
and not Object, and that the header file <Foundation/NSObject.h> is
imported instead of <objc/Object.h>.


Chapter 15

15-1
// I apologize!  This exercise is harder than I realized when I wrote it!
//

#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSCalendarDate.h>

@interface NSCalendarDate (ElapsedDays)
-(unsigned long) numberOfElapsedDays: (NSCalendarDate *) theDate;
@end

@implementation NSCalendarDate (ElapsedDays)
-(unsigned long) numberOfElapsedDays: (NSCalendarDate *) theDate
{
        int elapsedDays;

        [self years: 0 months: 0 days: &elapsedDays hours: 0 
                minutes: 0 seconds: 0 sinceDate: theDate];

        if (elapsedDays >= 0)
                return (unsigned long) elapsedDays;
        else
                return (unsigned long) -elapsedDays;
}
@end

int main (int argc, char *argv[])
{
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSCalendarDate *today = [NSCalendarDate calendarDate];
        NSCalendarDate *threeWeeksAgo;

        threeWeeksAgo = [today dateByAddingYears: 0 months: 0 
                days: -21 hours: 0 minutes: 0 seconds: 0];

        NSLog (@"%@\n", today);
        NSLog (@"%@\n", threeWeeksAgo);

        printf ("elapsed days is %i\n", 
                [today numberOfElapsedDays: threeWeeksAgo]);

        [pool release];
        return 0;
}

15-3
// lookup address card by name -- assumes an exact match

-(NSMutableArray *) lookup: (NSString *) theName
{
        AddressCard  *nextCard;
        NSMutableArray *matches = nil;     // to hold the matches

        int     i, elements;

        elements = [book count];

        for ( i = 0; i < elements; ++i) {
                nextCard = [book  objectAtIndex: i];

                // if we find a match, add it to the array matches

                if ( [[nextCard name] caseInsensitiveCompare: theName]
                   == NSOrderedSame ) {
                        if (matches == nil) // create the array if its nil
                                matches = [NSMutableArray arrayWithCapacity: 10];
                        [matches addObject: nextCard];
                }
        }

        return matches;
}

15-5
// lookup any string contained in any field of all address cards

-(NSMutableArray *) lookup: (NSString *) search
{
        AddressCard  *nextCard;
        NSMutableArray *matches = nil;     // to hold the matches

        int     i, elements;

        elements = [book count];

        for ( i = 0; i < elements; ++i) {
                nextCard = [book objectAtIndex: i];

                // search both fields for a match and add to the array
                // matches if found

                // note: if you completed ex. 3, then you would also
                // add tests here for the new fields you added

                if ( [[nextCard name] caseInsensitiveCompare: search]
                   == NSOrderedSame || [[nextCard email] 
                      caseInsensitiveCompare: search] == NSOrderedSame) {
                        if (matches == nil) // create the array if its nil
                                matches = [NSMutableArray arrayWithCapacity: 10];
                        [matches addObject: nextCard];
                }
        }

        return matches;
}


For the last part of the question, one approach is to redesign your 
AddressCard so the fields are stored inside a dictionary.  In that way, 
an AddressBook method like "lookup" can sequence through all of the 
fields in an AddressCard by enumerating the dictionary.

15-7
// Note: This is labeled as Exercise 8 in the book, but is really 7 (see errata)

#import "Fraction.h"
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSArray.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool  *pool = [[NSAutoreleasePool alloc] init];
        
        Fraction *f1 =  [[Fraction alloc] init];
        Fraction *f2 =  [[Fraction alloc] init];
        Fraction *f3 =  [[Fraction alloc] init];
        Fraction *f4 =  [[Fraction alloc] init];
        NSArray  *fractions = [NSArray arrayWithObjects: f1, f2, f3, f4, nil];
        Fraction *sum, *sum2;
        int     i, nFracts;

        [f1 setTo: 1 over: 4];
        [f2 setTo: 1 over: 2];
        [f3 setTo: 1 over: 8];
        [f4 setTo: 1 over: 16];

        nFracts = [fractions count];

        // set the sum to the first fraction

        sum = [fractions objectAtIndex: 0]; 

        // add up the remaining fractions

        for (i = 1; i < nFracts; ++i) {
                sum2 = [sum add: [fractions objectAtIndex: i]];
                [sum  release];  
                sum = sum2;  // we use sum2 to avoid memory leakage
        }

        // Display the final sum                

        printf ("The sum is ");  [sum print];  printf ("\n");

        [sum release];

        // f1-f4 get released from the array when the autorelease pool
        // gets released
        [pool release];

        return 0;
}

15-9
//
// Answer to this exercise is forthcoming!!
//


Chapter 16

16-1
// Implement a copy command for multiple file copying

#import <Foundation/NSString.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSPathUtilities.h>
#import <Foundation/NSProcessInfo.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool  *pool = [[NSAutoreleasePool alloc] init];
        NSFileManager      *NSFm;
        NSString           *source, *dest;
        BOOL               destExists, isDir;
        NSProcessInfo      *proc = [NSProcessInfo processInfo];
        NSArray            *args = [proc arguments];
        int                numArgs = [args count];
        int                i;

        NSFm = [NSFileManager  defaultManager];

        // Check for at least two arguments on the command line

        if (numArgs < 2 || numArgs < 3) {   
                printf ("Usage: %s s1 [s2 ...] dest\n", [[proc processName] cString]);
                return 1;
        }

        dest = [args objectAtIndex: numArgs - 1];

        // See if the destination file is a directory and make 
        // sure it already exists (note that copyPath:toPath:handler
        // will create directories in a path if they don't exist

        destExists = [NSFm fileExistsAtPath: dest isDirectory: &isDir];

        if (numArgs > 3 && (destExists == NO || isDir == NO)) {
                printf ("A destination dir is needed for multiple files\n");
                return 2;
        }

        // Now copy the files

        for (i = 1; i < numArgs - 1; ++i) {
                source = [args objectAtIndex: i];
        
                // Make sure the source file can be read
        
                if ([NSFm  isReadableFileAtPath: source] == NO)  {
                        printf ("Can't read %s\n", [source cString]);
                        continue;       // try the next file
                }
        
                dest = [args objectAtIndex: numArgs - 1];
                destExists = [NSFm fileExistsAtPath: dest isDirectory: &isDir];

                // If destination is a directory, add the source name to the 
                // end of the destination

                if (destExists == YES && isDir == YES)
                        dest = [dest stringByAppendingPathComponent: 
                                [source lastPathComponent]];


                [NSFm removeFileAtPath: dest handler: nil];

                // Okay, time to perform the copy 
        
                if ([NSFm copyPath: source toPath: dest handler: nil] == NO) 
                        printf ("%s: copy failed!\n", [source cString]);
                else 
                        printf ("%s: copy succeeeded\n", [source cString]);
        }

        [pool release];
        return 0;
}

16-3
// Duplicate basic function of Unix basename command
// Note: this does not handle the optional suffix argument


#import <Foundation/NSString.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSPathUtilities.h>
#import <Foundation/NSProcessInfo.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool  *pool = [[NSAutoreleasePool alloc] init];
        NSFileManager      *NSFm;
        NSString           *path;
        NSProcessInfo      *proc = [NSProcessInfo processInfo];
        NSArray            *args = [proc arguments];
        int                numArgs = [args count];

        NSFm = [NSFileManager  defaultManager];

        // Check for one argument on the command line

        if (numArgs != 2) {   
                printf ("Usage: %s path\n", [[proc processName] cString]);
                return 1;
        }

        path = [args objectAtIndex: numArgs - 1];

        printf ("%s\n", [[path lastPathComponent] cString]);

        [pool release];
        return 0;
}



// Duplicate basic function of Unix dirname command


#import <Foundation/NSString.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSPathUtilities.h>
#import <Foundation/NSProcessInfo.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool  *pool = [[NSAutoreleasePool alloc] init];
        NSFileManager      *NSFm;
        NSString           *path;
        NSProcessInfo      *proc = [NSProcessInfo processInfo];
        NSArray            *args = [proc arguments];
        NSMutableArray     *components;
        int                numArgs = [args count];

        NSFm = [NSFileManager  defaultManager];

        // Check for one argument on the command line

        if (numArgs != 2) {   
                printf ("Usage: %s path\n", [[proc processName] cString]);
                return 1;
        }

        path = [args objectAtIndex: numArgs - 1];

        // pathComponents returns an NSArray object, so we'll copy
        // it into an NSMutableArray so we can remove its last element

        components =  [NSMutableArray arrayWithArray: [path pathComponents]];

        // remove the last component of the array if more than one entry

        if ([components count] > 1)
                [components removeObjectAtIndex: [components count] - 1];

        // now reconstruct it back into a path

        path = [NSString pathWithComponents: components]; 

        printf ("%s\n", [path cString]);

        [pool release];
        return 0;
}

16-5
#include <Foundation/NSString.h>
#include <Foundation/NSProcessInfo.h>
#include <Foundation/NSPathUtilities.h>

@interface NSString (TempFiles)
+(NSString *) temporaryFileName;
@end

@implementation NSString (TempFiles)
+(NSString *) temporaryFileName
{
        NSProcessInfo   *proc = [NSProcessInfo processInfo];
        NSString        *tempdir = NSTemporaryDirectory ();

        return [tempdir stringByAppendingPathComponent: 
                        [proc globallyUniqueString]];
}

16-7

// Copy the contents of file typed on command line to terminal

#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSFileHandle.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSData.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool  *pool = [[NSAutoreleasePool alloc] init];
        NSFileHandle       *inFile, *outFile;
        NSData             *buffer;
        NSString           *path;
        NSProcessInfo      *proc = [NSProcessInfo processInfo];
        NSArray            *args = [proc arguments];
        int                numArgs = [args count];
        BOOL               endOfFile;

        // Check for one argument on the command line

        if (numArgs != 2) {   
                printf ("Please specify a file name!\n");
                return 1;
        }

        path = [args objectAtIndex: 1];

        // Open the file for reading

        inFile = [NSFileHandle  fileHandleForReadingAtPath: path];

        if (inFile == nil) {
                NSLog (@"Open of file for reading failed\n");
                return 2;
        }

        // Open the terminal as standard output

        outFile = [NSFileHandle fileHandleWithStandardOutput];

        // Read inFile and write its contents to outFile 128 bytes at a time

        endOfFile = NO;

        while (endOfFile == NO) {
                buffer = [inFile readDataOfLength: 128];
                if ([buffer length] != 0)
                        [outFile writeData: buffer];
                else
                        endOfFile = YES;
        }

        // Close files

        [inFile closeFile];
        [outFile closeFile];

        [pool release];
        return 0;
}



Chapter 17

17-1
// Small test program to see the effects on the retain count of
// adding and removing entries to a dictionary
//
// As you will see (and as the documentation for NSMutableDictionary explains)
//
//  1. Adding an object increases the object's retain count
//  2. Deleting an object decreases the object's retain count
//  3. Adding a key does not affect the key's retain count, because the key 
//     is copied into the dictionary and not retained.
//  4. Deleting a key does not affect the original key's retain count for the
//     reason previously described.
//

#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSValue.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        NSMutableDictionary *dict;
        NSMutableString  *str1 = [NSMutableString stringWithString: @"test"];
        NSMutableArray   *arr1 = [NSMutableArray arrayWithCapacity: 100];
        NSString         *key1 = [NSString stringWithString: @"myKey"];
        NSNumber         *int1 = [NSNumber numberWithInt: 100];


        dict = [NSMutableDictionary dictionary];

        printf ("Retain counts: str1 = %i, arr1 = %i, key1 = %i, int1= %i\n",
                [str1 retainCount], [arr1 retainCount], [key1 retainCount],
                [int1 retainCount]);

        [dict setObject: int1 forKey: key1];
        [dict setObject: arr1 forKey: @"Array"];
        [dict setObject: @"case" forKey: str1];

        printf ("Retain counts: str1 = %i, arr1 = %i, key1 = %i, int1= %i\n",
                [str1 retainCount], [arr1 retainCount], [key1 retainCount],
                [int1 retainCount]);

        [dict removeObjectForKey: key1];
        [dict removeObjectForKey: @"Array"];
        [dict removeObjectForKey: str1];

        printf ("Retain counts: str1 = %i, arr1 = %i, key1 = %i, int1= %i\n",
                [str1 retainCount], [arr1 retainCount], [key1 retainCount],
                [int1 retainCount]);

        [pool release];
}

        

        

17-3
Just add an autorelease message to the result fraction in each method
before the return is made.  In the simplest way, this can be done by 
changing the line

        return result;

at the end of each method to

        return [result autorelease];

given that autorelease returns the object (which I realize I overlooked
mentioning that in the text...oh well, next printing!)

And yes, expressions such as 

        [[fractionA  add: fractionB] print];

could then be written without memory leakage because the fraction returned
by the add: method would have been added to the autorelease pool and 
therefore will get released when the pool is released.


Chapter 18

18-1
See Page 531 for the answer to this exercise.
You don't need a mutableCopy method, since it probably doesn't
make sense to distinguish mutable vs. immutable address books.  You 
generally want to add and remove entries from an address book, so you'll
likely always want a mutable copy. 

18-3
// This program stores an array as an object into a dictionary
// It then makes immutable and mutable copies.  Next, the first
// element of the original array is changed and the output
// verifies whether a shallow or deep copy was performed

#import <Foundation/NSObject.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSAutoreleasePool.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool    *pool = [[NSAutoreleasePool alloc] init];
        NSMutableArray       *dataArray = [NSMutableArray arrayWithObjects:
                                @"one", @"two", @"three", @"four", nil];
        NSDictionary         *dict; 
        NSDictionary         *imdict;
        NSMutableDictionary  *mdict;
        NSMutableArray       *arr;
        int                  i;

        // Create the dictionary with one entry

        dict = [NSDictionary dictionaryWithObject: dataArray
                   forKey: @"array"];
        // make immutable and mutable copies of the dictionary

        arr = [dict objectForKey: @"array"];

        printf ("\nArray in original dictionary before change: ");

        for (i = 0; i < [arr count]; ++i)
                printf ("%s  ", [[arr objectAtIndex: i] cString]);


        // Make copies

        imdict = [dict copy];  
        mdict = [dict mutableCopy];

        // change the first element of the array in dataArray
        
        [dataArray replaceObjectAtIndex: 0 withObject: @"zero"];
        
        // see the effects on the three dictionaries now 
        // (the original and the two copies

        arr = [dict objectForKey: @"array"];

        printf ("\nArray in original dictionary after change: ");

        for (i = 0; i < [arr count]; ++i)
                printf ("%s  ", [[arr objectAtIndex: i] cString]);

        printf ("\nArray in immutable copy of dictionary: ");

        arr = [imdict objectForKey: @"array"];

        for (i = 0; i < [arr count]; ++i)
                printf ("%s  ", [[arr objectAtIndex: i] cString]);

        printf ("\nArray in mutable copy of dictionary: ");

        arr = [mdict objectForKey: @"array"];

        for (i = 0; i < [arr count]; ++i)
                printf ("%s  ", [[arr objectAtIndex: i] cString]);

        printf ("\n");

        [pool release];
        return 0;
}



Chapter 19

19-1
Simply insert the line

        [primes writeToFile: @"primes.pl" atomically: YES];

at the end of the program after all the prime numbers have been generated
(but before the pool gets released).

19-3
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSArchiver.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSURL.h>

int main (int argc, char *argv[])
{
        NSAutoreleasePool    *pool = [[NSAutoreleasePool alloc] init];
        NSDictionary  *glossary;
        NSEnumerator  *keyEnum;
        NSString      *url = @"http://www.kochan-wood.com/examples/glossary.pl";
        id            key;

        glossary = [NSDictionary dictionaryWithContentsOfURL: 
                         [NSURL URLWithString: url]];

        keyEnum = [glossary  keyEnumerator];

        while ( (key = [keyEnum  nextObject]) != nil ) 
                printf ("%s: %s\n", [key cString], 
                                [[glossary objectForKey: key] cString]);
        
        [pool release];
        return 0;
}

19-5
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSData.h>
#import <Foundation/NSProcessInfo.h>
#import "AddressBook.h"

int main (int argc, char *argv[])
{
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSData            *dataArea;
        NSKeyedUnarchiver *unarchiver;
        AddressBook       *myBook;
        NSProcessInfo      *proc = [NSProcessInfo processInfo];
        NSArray            *args = [proc arguments];
        int                numArgs = [args count];
        NSString           *search;
        AddressCard        *match;

        // Check for an argument on the command line

        if (numArgs != 2) {
                printf ("Usage: %s name\n", [[proc processName] cString]);
                return 1;
        }

        search = [args objectAtIndex: 1];

        // Read in the archive and connect an
        // NSKeyedUnarchiver object to it

        dataArea = [NSData dataWithContentsOfFile: @"myArchive"];
        unarchiver = [[NSKeyedUnarchiver alloc]
                          initForReadingWithData: dataArea];

        // Decode the address book  we previously stored in the archive

        myBook = [unarchiver decodeObjectForKey: @"myaddrbook"];
        
        [unarchiver finishDecoding];
        [unarchiver release];
                
        // Now lookup the entry

        match  = [myBook lookup: search];

        if (match == nil)
                printf ("%s not found!\n", [search cString]);
        else
                [match print];

        [pool release];
        return 0;
}


pleural mesothelioma

© 2003-2004 by Kochan-Wood.com, Inc. All rights reserved