I got this exercise to work, with one small issue.
./lookup TEXT_TO_SEARCH
After giving the search information, it prints "Segmentation fault: 11" and I cannot figure out why. If someone could look over this code and assist me in figuring it out, it would be greatly appreciated.
Thanks in advance!
NOTE: There are two calls to main(); one is commented out while the other actually runs upon the ./lookup command. The reason for this is the first main() set up the archive. Long story short, I didn't feel like making another Xcode project.
AddressCard.h
#import <Foundation/Foundation.h>
@interface AddressCard : NSObject <NSCoding>
{
NSString *name;
NSString *surname;
NSString *fullName;
NSString *email;
NSString *streetAddress;
NSString *city;
NSString *state;
NSString *country;
NSString *phoneNumber;
NSString *zip;
NSString *nextField;
NSMutableArray *fields; // An array of every field in each card.
BOOL isFound; // Is the match found?
}
@property (copy, nonatomic) NSString *name, *surname, *fullName, *email, *streetAddress, *city, *state, *country, *phoneNumber, *nextField, *zip;
@property (copy, nonatomic) NSMutableArray *fields;
@property BOOL isFound;
-(void) setName: (NSString*) theName andSurname: (NSString*) theSurname;
-(void) print;
-(NSComparisonResult) compareNames: (id) element;
-(void) addFieldsToCard;
-(void) searchAll: (NSString*) theSearch;
@end
AddressCard.m
#import "AddressCard.h"
@implementation AddressCard
@synthesize name, surname, fullName, email, streetAddress, city, state, country, phoneNumber, nextField, zip;
@synthesize fields;
@synthesize isFound;
-(void) setName: (NSString*) theName andSurname: (NSString*) theSurname {
// self.name = theName;
// self.email = theEmail;
// Same thing!
[self setName: theName];
[self setSurname: theSurname];
}
-(void) print {
NSLog (@"====================================");
NSLog (@"| |");
NSLog (@"| %10s %-21s |", [name UTF8String], [surname UTF8String]);
NSLog (@"|----------------------------------|");
NSLog (@"| |");
NSLog (@"| %-32s |", [email UTF8String]);
NSLog (@"| %-32s |", [streetAddress UTF8String]);
NSLog (@"| %-10s, %-2s %-17s |",[city UTF8String],[state UTF8String],[zip UTF8String]);
NSLog (@"| %-32s |", [country UTF8String]);
NSLog (@"| %-32s |", [phoneNumber UTF8String]);
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"| O O |");
NSLog (@"====================================");
}
-(void) dealloc
{
[name release];
[surname release];
[email release];
[streetAddress release];
[city release];
[state release];
[zip release];
[country release];
[phoneNumber release];
[fields release];
[super dealloc];
}
-(NSComparisonResult) compareNames:(id)element
{
return [name compare: [element surname]];
}
-(void) addFieldsToCard
{
[fields autorelease];
fields = [[NSMutableArray alloc] initWithCapacity: 0];
[fields addObject: [self name]];
[fields addObject: [self surname]];
[fields addObject: [self fullName]];
[fields addObject: [self email]];
[fields addObject: [self streetAddress]];
[fields addObject: [self city]];
[fields addObject: [self state]];
[fields addObject: [self country]];
[fields addObject: [self phoneNumber]];
[fields addObject: [self zip]];
}
-(void) searchAll: (NSString*) theSearch
{
int numFields = [fields count];
NSRange match;
isFound = FALSE;
BOOL isDoneSearching = FALSE;
NSLog(@"\n");
NSLog(@"Lookup: %@",theSearch);
for ( int i = 0 ; i < numFields ; ++i ) {
if ( !(isFound) ) { // If it's NOT been found yet
nextField = [fields objectAtIndex: i];
match = [nextField rangeOfString: theSearch options:NSCaseInsensitiveSearch];
if(match.location != NSNotFound) {
NSLog(@"Match found in %@'s card.",[self fullName]);
isFound = TRUE;
isDoneSearching = TRUE;
}
}
}
if( (!(isFound)) )
NSLog(@"No match found in %@'s card.",[self fullName]);
}
-(void) encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject: name forKey: @"AddressCardName"];
[encoder encodeObject: surname forKey: @"AddressCardSurname"];
[encoder encodeObject: fullName forKey: @"AddressCardFullName"];
[encoder encodeObject: email forKey: @"AddressCardEmail"];
[encoder encodeObject: streetAddress forKey: @"AddressCardStreetAddress"];
[encoder encodeObject: city forKey: @"AddressCardCity"];
[encoder encodeObject: state forKey: @"AddressCardState"];
[encoder encodeObject: country forKey: @"AddressCardCountry"];
[encoder encodeObject: phoneNumber forKey: @"AddressCardPhoneNumber"];
[encoder encodeObject: zip forKey: @"AddressCardZip"];
// [encoder encodeObject: nextField forKey: @"AddressCardNextField"];
[encoder encodeObject: fields forKey: @"AddressCardFields"];
// [encoder encodeBool: isFound forKey: @"AddressCardIsFound"];
NSLog(@"Card archived.");
}
-(id) initWithCoder:(NSCoder *)decoder
{
name = [[decoder decodeObjectForKey: @"AddressCardName"] retain];
surname = [[decoder decodeObjectForKey: @"AddressCardSurname"] retain];
fullName = [[decoder decodeObjectForKey: @"AddressCardFullName"] retain];
email = [[decoder decodeObjectForKey: @"AddressCardEmail"] retain];
streetAddress = [[decoder decodeObjectForKey: @"AddressCardStreetAddress"] retain];
city = [[decoder decodeObjectForKey: @"AddressCardCity"] retain];
state = [[decoder decodeObjectForKey: @"AddressCardState"] retain];
country = [[decoder decodeObjectForKey: @"AddressCardCountry"] retain];
phoneNumber = [[decoder decodeObjectForKey: @"AddressCardPhoneNumber"] retain];
zip = [[decoder decodeObjectForKey: @"AddressCardZip"] retain];
// nextField = [[decoder decodeObjectForKey: @"AddressCardNextField"] retain];
fields = [[decoder decodeObjectForKey: @"AddressCardFields"] retain];
// isFound = [decoder decodeBoolForKey: @"AddressCardIsFound"];
NSLog(@"Card unarchived.");
return self;
}
@end
AddressBook.h
#import "AddressCard.h"
@interface AddressBook: NSObject <NSMutableCopying, NSCoding>
{
NSString *bookName;
NSMutableArray *book;
AddressCard *nextCard;
BOOL isSorted;
NSMutableArray *matches; // An array of every match found in a search.
}
@property (copy, nonatomic) NSString *bookName;
@property BOOL isSorted;
-(id) initWithName: (NSString *) name;
-(void) addCard: (AddressCard *) theCard;
-(void) removeCard: (AddressCard *) theCard;
-(void) removeAllCards;
-(int) entries;
-(void) list;
-(void) dealloc;
-(void) lookup: (NSString*) theSearch;
-(void) printMatches: (NSString*) match;
-(void) sort;
@end
AddressBook.m
#import "AddressBook.h"
@implementation AddressBook
@synthesize bookName;
@synthesize isSorted;
-(void) encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject: bookName forKey: @"AddressBookBookName"];
[encoder encodeObject: book forKey: @"AddressBookBook"];
// [encoder encodeObject: nextCard forKey: @"AddressBookNextCard"];
// [encoder encodeObject: matches forKey: @"AddressBookMatches"];
// [encoder encodeBool: isSorted forKey: @"AddressBookIsSorted"];
NSLog(@"Book archived.");
}
-(id) initWithCoder:(NSCoder *)decoder
{
bookName = [[decoder decodeObjectForKey: @"AddressBookBookName"] retain];
book = [[decoder decodeObjectForKey: @"AddressBookBook"] retain];
// nextCard = [[decoder decodeObjectForKey: @"AddressBookNextCard"] retain];
// matches = [[decoder decodeObjectForKey: @"AddressBookMatches"] retain];
// isSorted = [decoder decodeBoolForKey: @"AddressBookIsSorted"];
NSLog(@"Book unarchived.");
return self;
}
-(id) mutableCopyWithZone:(NSZone *)zone
{
AddressBook *newBook = [[[self class] allocWithZone: zone] initWithName: [self bookName]];
newBook->book = [self->book mutableCopy];
return newBook;
}
-(id) initWithName:(NSString *)name
{
isSorted = FALSE;
self = [super init];
if ( self )
{
bookName = [[NSString alloc] initWithString: name];
book = [[NSMutableArray alloc] init];
}
return self;
}
-(void) addCard:(AddressCard *)theCard
{
[book addObject: theCard];
}
-(void) removeCard:(AddressCard *)theCard
{
[book removeObjectIdenticalTo: theCard];
}
-(int) entries
{
return [book count];
}
-(void) list
{
NSLog(@"============== Contents of %-@: ==============",bookName);
NSLog(@"First name: Last name: Email:");
NSLog(@"----------- ---------- ------");
for ( nextCard in book )
NSLog(@"%-12s %-15s %-25s",[nextCard.name UTF8String],[nextCard.surname UTF8String],[nextCard.email UTF8String]);
NSLog(@"========================================================");
}
-(void) dealloc
{
[bookName release];
[book release];
[nextCard release];
[matches release];
[super dealloc];
}
-(void) lookup:(NSString *)theSearch
{
if ( [book count] == 0 ) {
NSLog(@"Cannot search an empty book. Add cards, then try searching again.");
return;
}
if( !(matches) )
matches = [[NSMutableArray alloc] initWithCapacity: 20];
int numCardsSearched = 0;
[nextCard release];
for ( nextCard in book ) {
[nextCard searchAll: theSearch];
++numCardsSearched;
if( [nextCard isFound] )
[matches addObject: nextCard];
if ( numCardsSearched == [book count] )
if ([matches count] > 0)
[self printMatches: theSearch];
else {
NSLog(@"\n");
NSLog(@"No matches found for %@ in %@.",theSearch,[self bookName]);
}
}
}
-(void) printMatches: (NSString*) match
{
NSLog(@"\n");
NSLog(@"Matches found for: \"%@\"", match);
for ( AddressCard *theMatch in matches )
[theMatch print];
}
-(void) sort // Sorts the cards in the book by last name.
{
if( [self isSorted] == FALSE ) {
NSLog(@"\n");
NSLog(@"Sorting...");
[book sortUsingSelector: @selector(compareNames:)];
[self setIsSorted: TRUE];
NSLog(@"Sorted!");
NSLog(@"\n");
}
else {
NSLog(@"Already sorted, dumbass!");
NSLog(@"\n");
}
}
-(void) removeAllCards
{
[book removeAllObjects];
}
@end
main.m
#import "AddressBook.h"
/***** This program sets up the archive-retrieval program. *****
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AddressCard *card1 = [[AddressCard alloc] init];
AddressCard *card2 = [[AddressCard alloc] init];
AddressBook *myBook = [[AddressBook alloc] initWithName: @"Justin's book"];
// NSMutableData *data;
// NSKeyedArchiver *archiver = [NSKeyedUnarchiver
NSString *aName = @"NameA";
NSString *bName = @"NameB";
NSString *aSurname = @"SurnameA";
NSString *bSurname = @"SurnameB";
NSString *aFullName = [aName stringByAppendingString: @" "];
NSString *bFullName = [bName stringByAppendingString: @" "];
aFullName = [aFullName stringByAppendingString: aSurname];
bFullName = [bFullName stringByAppendingString: bSurname];
NSString *aEmail = @"someone@somewhere.com";
NSString *bEmail = @"someoneelse@somewhere.com";
NSString *aStreetAddress = @"123 Some St.";
NSString *bStreetAddress = @"321 Someother St.";
NSString *aCity = @"Anytown";
NSString *bCity = @"Anycity";
NSString *aState = @"STATE1";
NSString *bState = @"STATE2";
NSString *aZip = @"12345";
NSString *bZip = @"54321";
NSString *aCountry = @"USA";
NSString *bCountry = @"USA";
NSString *aPhoneNumber = @"555-555-5555;
NSString *bPhoneNumber = @"555-555-5556";
[card1 setName: aName];
[card1 setSurname: aSurname];
[card1 setFullName: aFullName];
[card1 setEmail: aEmail];
[card1 setStreetAddress: aStreetAddress];
[card1 setCity: aCity];
[card1 setState: aState];
[card1 setZip: aZip];
[card1 setCountry: aCountry];
[card1 setPhoneNumber: aPhoneNumber];
[card2 setName: bName];
[card2 setSurname: bSurname];
[card2 setFullName: bFullName];
[card2 setEmail: bEmail];
[card2 setStreetAddress: bStreetAddress];
[card2 setCity: bCity];
[card2 setState: bState];
[card2 setZip: bZip];
[card2 setCountry: bCountry];
[card2 setPhoneNumber: bPhoneNumber];
[card1 addFieldsToCard];
[card2 addFieldsToCard];
[myBook addCard:card1];
[myBook addCard:card2];
// data = [NSMutableData data];
// archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: data];
// [archiver encodeObject: card1 forKey: @"Card1"];
// [archiver encodeObject: card2 forKey: @"Card2"];
// [archiver encodeObject: myBook forKey: @"myBook"];
// [archiver finishEncoding];
// if ( [data writeToFile: @"backup.archive" atomically: YES] == NO )
// NSLog(@"Backup failed.");
// else NSLog(@"Backup successful!");
if ( [NSKeyedArchiver archiveRootObject: myBook toFile: @"backup.archive"] == NO ) {
NSLog(@"Backup failed.");
return 1;
}
else NSLog(@"Backup successful.");
NSLog(@"%@",[[NSFileManager defaultManager] currentDirectoryPath]);
// [archiver release];
[card1 release];
[card2 release];
[myBook release];
[pool drain];
return 0;
}
***** *****/
/*
* 4. Write a program to read in an archived
* AddressBook and look up an entry based on a
* name supplied on the command line, like so:
* $ lookup gregory
*/
// This is what actually runs.
int main(int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSProcessInfo *proc = [NSProcessInfo processInfo];
NSArray *args = [proc arguments];
// NSMutableData *data;
// NSKeyedUnarchiver *unarchiver;
AddressBook *myBook;
// AddressCard *card1;
// AddressCard *card2;
if ( [args count] != 2 ) {
NSLog(@"Usage: ./%@ SEARCH",[proc processName]);
return 1;
}
// data = [NSMutableData dataWithContentsOfFile: @"backup.archive"];
// if (!data)
// {
// NSLog(@"File read failed.");
// return 2;
// }
// else NSLog(@"File read successful.");
// unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data];
// card1 = [unarchiver decodeObjectForKey: @"Card1"];
// card2 = [unarchiver decodeObjectForKey: @"Card2"];
// myBook = [unarchiver decodeObjectForKey: @"myBook"];
// [unarchiver finishDecoding];
myBook = [NSKeyedUnarchiver unarchiveObjectWithFile: @"backup.archive"];
if( !myBook ) {
NSLog(@"File read failed.");
return 2;
}
else NSLog(@"File read successful.");
[myBook list];
[myBook lookup: [args objectAtIndex: 1]];
[myBook release];
// [unarchiver release];
[pool drain];
return 0;
}