Confused

I know I’m a long way from a solution (and I’m trying to avoid looking at others answers so I can get there on my own), but I’m having a problem understanding what’s going wrong here:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    int matches;
    @autoreleasepool {
        
        NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
        NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words" encoding:NSUTF8StringEncoding error:NULL];
        
        NSArray *names = [nameString componentsSeparatedByString:@"\n"]; NSLog(@"%lu", (unsigned long)[names count]);
        NSArray *words = [wordString componentsSeparatedByString:@"\n"]; NSLog(@"%lu", (unsigned long)[words count]);
        
        for (NSString *n in names) {
            for (NSString *w in words){
                if ( w == n ) {
                    matches++;
                    NSLog(@"%@ - %@", w, n);
                }
            }
        }
        
    }
    NSLog(@"%d", matches);
    return 0;
}

My thought was this would match all the proper names that are in the words file (which should be all of them(1309) according to the challenge); what I get instead is the following:

2014-03-20 16:01:11.101 Chapter17-Challenge2-InterestingNames[2819:303] 1309
2014-03-20 16:01:11.304 Chapter17-Challenge2-InterestingNames[2819:303] 235887
2014-03-20 16:01:11.408 Chapter17-Challenge2-InterestingNames[2819:303] Art - Art
2014-03-20 16:01:12.261 Chapter17-Challenge2-InterestingNames[2819:303] Nadeem - Nadeem
2014-03-20 16:01:12.282 Chapter17-Challenge2-InterestingNames[2819:303] No - No
2014-03-20 16:01:13.134 Chapter17-Challenge2-InterestingNames[2819:303]  - 
2014-03-20 16:01:13.192 Chapter17-Challenge2-InterestingNames[2819:303] 4

I tried putting in several breakpoints (and even added a copy of the NSLog(@"%@ - %@", w, n); before the if statement to make sure it was doing what I expected (it was). I even stepped through and watched Aaron == Aaron fail the if statement. There must be some hidden character making it fail somewhere? I can’t figure out why it’s failing or what other troubleshooting technique to try.

Thanks for any help.

Try looking at what

Is doing and think about what you are comparing. Another hint is that you are now working in Objective-C, not C…

I must have a fundamental misunderstanding then. What I think it’s doing is for each name(n) in the names array, checking it against every word(w) in the words array and if they match logging it. Is it actually comparing pointer addresses?

== does a comparison in C of two variables.

You are working with NSString objects, you need to compare them. Have a read of the reference material here https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/doc/uid/20000154-DontLinkElementID_1

Look at the task you are trying to do, and see how you can achieve it.

I got it. Thanks for the assist. To be honest though I find the Apple documentation next to worthless. I don’t think it’s Apple’s fault mind you; I think I’m just not getting the concepts. I tried every iteration of the NSString/NSLiteralSearch I could think of and ended up using isEqualToString (which I only found through Google) instead (and it worked on my first try) .

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {

        int matches;

        NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
        NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words" encoding:NSUTF8StringEncoding error:NULL];
        
        NSArray *names = [nameString componentsSeparatedByString:@"\n"]; NSLog(@"%lu", (unsigned long)[names count]);
        NSMutableArray *lowercaseNames =[NSMutableArray array];
        NSArray *words = [wordString componentsSeparatedByString:@"\n"]; NSLog(@"%lu", (unsigned long)[words count]);
        NSMutableArray *coolNames =[NSMutableArray array];
        
//      Lowercase all the proper names
        NSUInteger namesCount = [names count];
        for (int i = 0; i < namesCount; i++) {
            [lowercaseNames insertObject:[names[i] lowercaseString] atIndex:i];
        }
        
        
//      List any "words" that are *exact matches to "lowercaseNames"
        for (NSString *n in lowercaseNames) {
            for (NSString *w in words){
                if ( [w isEqualToString:n] ) {
                    [coolNames insertObject:w atIndex:matches];
                    matches++;
                }
            }
        }
//      Output findings
        for (NSString *c in coolNames ) {
            NSLog(@"%@", c);
        }
        NSLog(@"%d", matches);
    }
    return 0;
}

I’m going to look at how everyone else did it and then probably re-read the book from the beginning of Part III.

I know how you feel, I bought the first edition of this book late last year and whizzed through it till I got to the point of objects and then got completely confused.

I then bought this new edition and as I read through it, I make tons of notes for my own understanding and I am finding this time through I am getting the concepts better.

The Apple documentation is good, you just need to learn how to read it (which I am still doing as well, I am no expert on it yet either!). For example, if you look in the Tasks option on the left there is a task for Identifying and Comparing strings which is where you will find -isEqualToString:

Here is the bookmark to the subsection https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/doc/uid/20000154-SW29

Google is also your friend and my other favourite site is Stackoverflow. The community here seems to be really nice and helpful as well.

Good luck!

The loop variables n and w above are being used to hold the addresses of NSString objects. Therefore, when you compare the values of those variables, you are comparing the addresses of the corresponding objects, which is not desirable in the given context.

What you really want to do is compare not the addresses but compare the values of the NSString objects.

Comparing Addresses

NSString * n = ...
NSString * w = ...

if (n == w) {
   ....
}

Comparing Values

NSString * n = ...
NSString * w = ...

if ([n isEqualToString: w]) {
   ....
}