6

This is a simple challenge in my introductory Objc class that is causing my a lot of grief. I've tried a few things I picked up in the X-code API to try to fix this but I'm having no luck. The challenge specifications include a restriction: I cannot change any code outside the for loop and my output cannot include a trailing comma. In its current iteration it does, and I don't know how to get rid of it!

Here is the code in its current form:

    NSString *outputString = @"";
    int loopMaximum = 10;

    for (int counter = 1; counter <= loopMaximum; counter++) {
        outputString = [NSString stringWithFormat:@"%@ %d,", outputString, counter];
        //Not sure how to get rid of trailing comma =/
    }

    NSLog(@"%@", outputString);
user3281385
  • 121
  • 1
  • 6
  • Try adding a comma in front of the new number you add, except for the case that you're on the first iteration of the loop, which you could either check by checking the value of counter, or by checking that `outputString` has length zero. – Gavin Feb 27 '14 at 21:11
  • Are you sure you want to start with a space character? ;-) – Eiko Feb 27 '14 at 22:42

4 Answers4

5

The better approach is something like this:

NSMutableString *outputString = [NSMutableString string];
int loopMaximum = 10;

for (int counter = 1; counter <= loopMaximum; counter++) {
    if (counter > 1) {
        [outputString appendString:@", "];
    }
    [outputString appendFormat:@"%d", counter];
}

NSLog(@"%@", outputString);
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • One of the countless similar solutions. Just keep in mind that this is lacking the leading space character - which probably is an excellent choice. :) – Eiko Feb 27 '14 at 22:44
  • If OP "cannot change any code outside the for loop" this solution is not correct. – Avt Feb 28 '14 at 07:23
  • I admit I didn't see that requirement. But it is a silly requirement. Why write hacky code in the loop to avoid doing it the right way? – rmaddy Feb 28 '14 at 15:04
  • Why ? because a restriction is a restriction. – Gomino Jun 06 '14 at 10:02
1

Even if rmaddy's solution is more memory efficient, OP said he is not allowed to change code outside the "for loop":

So here is a valid solution:

NSString *outputString = @"";
int loopMaximum = 10;

for (int counter = 1; counter <= loopMaximum; counter++) {
    outputString = [NSString stringWithFormat:@"%@%d%@", outputString, counter, (counter<loopMaximum)?@", ":@""];
}

NSLog(@"%@", outputString);
Gomino
  • 12,127
  • 4
  • 40
  • 49
1

Trim last character(s) simply by creating a substring.

string = [string substringToIndex:[string length] - 1];
d00dle
  • 1,276
  • 1
  • 20
  • 33
0

One of the more efficient approaches is as follows. With automatic reference counting (ARC),

NSMutableString *outputString = [[NSMutableString alloc] init];
NSUInteger loopMaximum = 10;

for (NSUInteger counter = 1; counter <= loopMaximum; counter++)  
{
    if (counter == 1)
    {
        [outputString appendFormat:@"%d", counter];
        continue;
    }

    [outputString appendFormat:@", %d", counter];
}

NSLog(@"%@", outputString);

For manual reference counting (MRC) append [outputString release]; after the NSLog();.

NSString vs. NSMutableString

In the approach given in the question there is repeated creation NSString objects as the answer is being constructed. The allocation and copying of memory is very slow, additionally since the objects begin produced are autoreleased, memory use will increase every time the loop iterates and will not be released until the next drain of an autoreleasepool. Instead, a better solution would be the use of NSMutableString which is a subclass of NSString designed to mutate/change and is much faster at appending characters to itself.

NSUInteger vs. int

In the approach given in the question there is also use of int. It is preferable to use NSInteger and NSUInteger as they avoid problems with execution on 32/64bit processors. Since there are no negative numbers the use of a unsigned variable (NSUInteger)is also perferable as it gives a greater positive range.

Message Passing

Passing messages can become expensive particularly while iterating. By limiting the number of messages passed to 1 per iteration it reduces the amount of overhead incurred.

Community
  • 1
  • 1
Atlas
  • 236
  • 1
  • 11
  • If OP "cannot change any code outside the for loop" this solution is not correct. – Avt Feb 28 '14 at 07:23