-3

I'm quite new to NSString manipulation and don't have much experience at all of manipulating strings in any language really.

My problem is that I have a string that contains a lot of data, within this data is a name that I need to extract into a new NSString. EG:

NSString* dataString =@"randomdata12359123888585/name_john_randomdatawadapoawdk"

"/name_" always precede the data I need and "_" always follows it.

I have looked into things such as NSScanner but I'm not quite sure what the correct approach is or how to implement NSScanner.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Biggs
  • 267
  • 3
  • 9

3 Answers3

3

Your string format is very well-defined (as you say, the name you are after is always preceded by "/name_" and always followed by "_"), and I suppose that the name ("john") hence cannot contain an underscore.

I'd therefore consider a simple regular expression, which is perfectly suited for this sort of problem:

NSString *regexPattern = @"^.*/name_(.*?)_.*$";

NSString *name = [dataString stringByReplacingOccurrencesOfString: regexPattern 
                                                       withString: @"$1"
                                                          options: NSRegularExpressionSearch
                                                            range: NSMakeRange(0, dataString.length)];

In case you are not familiar with regular expressions, what is going on here is:

  1. Begin at the beginning of the string (the "^")
  2. Allow anything (".*") followed by "/name_"
  3. Capture what follows (the parenthesis means "capture this")
  4. In the parenthesis, allow anything (".*"), but make it as short as possible (the "?" after the "*")
  5. It must be followed by an underscore and then allow anything that happens to be there up to the end of the string (the "$")

This will match the whole string, and when substituting the match (i.e., all of the string) with "$1", it will substitute the match with the substring included in the first (and only) parenthesis.

Result: It will produce a string that contains only the name. If the string does not have the correct format (i.e., no name between two underscores), then it will not change anything and return the full, original string.

It is a matter of coding style whether you prefer one approach over the other, but if you like regular expressions, then this approach is both clean, easy to understand and simple to maintain.

As I see it, any fragility in this is due to the data format, which looks suspiciously like something that depends on other "random" pieces of data, so whichever method you choose to parse that string, make sure you add some defensive tests to check the data format and alert you if unexpected strings begin to enter your data. This could be years from now, when you have forgotten everything about underscores, regexes and NSScanner.

Monolo
  • 18,205
  • 17
  • 69
  • 103
1
-(void)separateString{
NSString* dataString =@"randomdata12359123888585/name_john_randomdatawadapoawdk";
NSArray *arr1 = [dataString componentsSeparatedByString:@"/"];
NSArray *arr2 = [[arr1 objectAtIndex:1] componentsSeparatedByString:@"_"];
NSLog(@"%@ %@",arr1,arr2);
}

The output you get is

arr1=  (
randomdata12359123888585,
"name_john_randomdatawadapoawdk"
) 
arr2 = (
name,
john,
randomdatawadapoawdk
)

now you can access the name or whatever from the array index.

Manish Agrawal
  • 10,958
  • 6
  • 44
  • 76
1

I managed to do this with NSScanner, however the array answer would work too so I've upvoted it.

The NSScanner code I used for anyone else facing a similar problem is:

-(void)formatName{
NSString *stringToSearch = _URLString; //url string is the long string we wish to search.

NSScanner *scanner = [NSScanner scannerWithString:stringToSearch];
[scanner scanUpToString:@"name_" intoString:nil]; // Scan all characters before name_
while(![scanner isAtEnd]) {
    NSString *substring = nil;
    [scanner scanString:@"name_" intoString:nil]; // Scan the # character
    if([scanner scanUpToString:@"_" intoString:&substring]) {
        // If the space immediately followed the _, this will be skipped

        _nameIwant = substring; //nameIwant is a property to store the name I scanned for
        return;
    }

}

}

Biggs
  • 267
  • 3
  • 9