How to use NSScanner or componentsSeperatedByString - iphone

I have a {"Red","Blue","Green","Yellow"} returned as string. How to process this to add to an array ?
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString* sampleString = #"{\"Red\",\"Blue\",\"Green\",\"Yellow\"}";
NSArray* components = [sampleString componentsSeperatedByString:#"\"{"];
[pool drain];
return 0;
}
Updated Code#
NSString* sampleString = #"{\"Red\",\"Blue\",\"Green\",\"Yellow\"}";
NSMutableArray *rows = [NSMutableArray array];
// Get newline character set
NSMutableCharacterSet *removeCharacterSet = (id)[NSMutableCharacterSet characterSetWithCharactersInString:#"{(,}"];
[removeCharacterSet formIntersectionWithCharacterSet:[[NSCharacterSet whitespaceCharacterSet] invertedSet]];
// Characters that are important to the parser
NSMutableCharacterSet *importantCharactersSet = (id)[NSMutableCharacterSet characterSetWithCharactersInString:#"\""];
[importantCharactersSet formUnionWithCharacterSet:removeCharacterSet];
// Create scanner, and scan string
NSScanner *scanner = [NSScanner scannerWithString:sampleString];
[scanner setCharactersToBeSkipped:nil];
while ( ![scanner isAtEnd] )
{
BOOL insideQuotes = NO;
BOOL finishedRow = NO;
NSMutableArray *columns = [NSMutableArray arrayWithCapacity:10];
NSMutableString *currentColumn = [NSMutableString string];
while ( !finishedRow )
{
NSString *tempString;
if ( [scanner scanUpToCharactersFromSet:importantCharactersSet intoString:&tempString] ) {
[currentColumn appendString:tempString];
}
if ( [scanner isAtEnd] ) {
if ( ![currentColumn isEqualToString:#""] ) [columns addObject:currentColumn];
finishedRow = YES;
}
else if ( [scanner scanCharactersFromSet:removeCharacterSet intoString:&tempString] ) {
if ( insideQuotes ) {
// Add line break to column text
[currentColumn appendString:tempString];
}
else {
// End of row
if ( ![currentColumn isEqualToString:#""] ) [columns addObject:currentColumn];
finishedRow = YES;
}
}
else if ( [scanner scanString:#"\"" intoString:NULL] ) {
if ( insideQuotes && [scanner scanString:#"\"" intoString:NULL] ) {
// Replace double quotes with a single quote in the column string.
[currentColumn appendString:#"\""];
}
else {
// Start or end of a quoted string.
insideQuotes = !insideQuotes;
}
}
else if ( [scanner scanString:#"," intoString:NULL] ) {
if ( insideQuotes ) {
[currentColumn appendString:#","];
}
else {
// This is a column separating comma
[columns addObject:currentColumn];
currentColumn = [NSMutableString string];
[scanner scanCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:NULL];
}
}
}
if ( [columns count] > 0 ) [rows addObject:columns];
}
NSLog(#"This String:%#",[rows objectAtIndex:0]);
I got code from http://www.macresearch.org/cocoa-scientists-part-xxvi-parsing-csv-data. Now the output is This String:( Red ), How to get rid of "(" ")" ?

Here's all you need to scan the sample you've provided using an instance of NSScanner:
NSScanner *scanner = [NSScanner scannerWithString:#"{\"Red\",\"Blue\",\"Green\",\"Yellow\"}"];
NSMutableCharacterSet *charactersToSkip = [NSMutableCharacterSet punctuationCharacterSet];
[scanner setCharactersToBeSkipped:charactersToSkip];
NSMutableArray *substrings = [NSMutableArray array];
NSString *substring = #"";
while (![scanner isAtEnd]) {
[scanner scanUpToCharactersFromSet:charactersToSkip intoString:&substring];
[scanner scanCharactersFromSet:charactersToSkip intoString:NULL];
[substrings addObject:substring];
}
NSLog(#"%#", substrings);
Note that if you substituted parens for curly braces, all you'd need to do to create an array of strings from the sample would be:
NSString *sampleString = #"(\"Red\",\"Blue\",\"Green\",\"Yellow\")";
NSArray *strings = [sampleString propertyList];
NSLog(#"%#", strings);
...but I'm not really clear on what you need to accomplish.

Related

Getting substring from response NSString

I need to get substring CODE's value (X2.31) from string
NSString *str = #"SHMU=\"\" CODE=\"X2.31\" XTN=\";
How could I get that particular substring?
Try the below one
NSString *str = #"SHMU=\"\" CODE=\"X2.31\" XTN=\"";
NSRange range = [str rangeOfString:#"CODE="];
NSString *substring = [[str substringFromIndex:NSMaxRange(range)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *str1 = [substring componentsSeparatedByString:#" "];
NSLog(#"the sub %#",[[str1 objectAtIndex:0] stringByTrimmingCharactersInSet[NSCharacterSet whitespaceCharacterSet]]);
And by string was "X2.31"
NSString *strOrg = [NSString stringWithFormat:#"%#",#"SHMU=\"\" CODE=\"X2.31\" XTN=\""] ;
NSString *strLeft = [NSString stringWithFormat:#"%#",#"SHMU=\"\" CODE=\""] ;
NSString *strRight = [NSString stringWithFormat:#"%#",#"\" XTN=\""] ;
NSLog(#"%#", [self getDataBetweenString:strOrg LeftString:strLeft RightString:strRight LeftOffset:13]);
- (NSString *)getDataBetweenString:(NSString *)orgString LeftString:(NSString *)leftString RightString:(NSString *)rightString LeftOffset:(NSInteger)leftPos;
{
NSInteger left, right;
NSString *foundData;
NSScanner *scanner=[NSScanner scannerWithString:orgString];
[scanner scanUpToString:leftString intoString: nil];
left = [scanner scanLocation];
[scanner setScanLocation:left + leftPos];
[scanner scanUpToString:rightString intoString: nil];
right = [scanner scanLocation] + 1;
left += leftPos;
foundData = [orgString substringWithRange: NSMakeRange(left, (right - left) - 1)]; return foundData;
}
This is only specific to the str you posted.
Your number must be followed by First X.
float f=[[str componentsSeparatedByString:#"X"][1] floatValue];

how to get digits of a integer from NSString?

I am having a string like NSString *str = #"123".I want to fill the digits of this string into UIPickerView.But how to get the digits from this string?I added the following code
- (void)pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component
{
int number = [str intValue];
if(component == 0)
{
}
else if(component == 1)
{
}
else
{
}
}
Please see this..
NSMutableArray *arrNumbers = [[NSMutableArray] alloc] initWithCapacity:[YOURSTRING length]];
for (i=0;i<[YOURSTRING length];i++)
{
  unichaar ch = [YOURSTRING characterAtIndex:i];
  NSLog(#"Processing charachter %c",ch);
  // If you really want
  [arrNumbers addObject:(id)ch];
}
Other solutions seem to be excessive, considering NSString is already an array of characters. More lightweight solution:
NSString *str = #"123";
for (int i = 0; i < [str length]; i++) {
int digit = [str characterAtIndex:i] - '0';
// do something with your digit
}
If you have it as a string you can just do
NSArray * digitStrings = [str componentsSeparatedByString:""];
And each element in the array would be a digit as a NSString.
not tested but you can give it a try, this is supposed to scan all numeric entries of your string.
-(NSArray*)getDigitsFromString:(NSString*)str{
NSMutableString *outpuString = [NSMutableString
stringWithCapacity:str.length];
NSScanner *scanner = [NSScanner scannerWithString:str];
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789"];
while ([scanner isAtEnd] == NO) {
NSString *buffer;
if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
[outpuString appendString:buffer];
} else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
}
}
NSArray * digitStr = [outpuString componentsSeparatedByString:#""];
return digitStr;
}
NSMutableArray * digit=[[NSMutableArray alloc]init];
NSString *string = #"123456";
for (int i=0;i<[string length]; i++) {
NSString * newString = [string substringWithRange:NSMakeRange(i, 1)];
[digit addObject:newString];
}
NSLog(#"String %# ", digit)
One more answer which addresses more the idea of the original question by solving the problem of separating an int into it's digits:
NSString *numberString = #"68243";
int result[numberString.length];
NSInteger number = [numberString integerValue];
int j = numberString.length - 1;
while (j >= 0)
{
int power = pow(10, j);
int rest = (number % power);
result[j] = (number - rest)/power;
number = rest;
j--;
}

iPhone - NSScanner does not parse

I'm using this method to find the first <> couple into a string (XML content) :
NSScanner* scanner = [NSScanner scannerWithString:contentToParse];
int startPos = 0;
int endPos = 0;
// Open search
if ([scanner scanString:#"<" intoString:nil]) {
startPos = [scanner scanLocation]-1;
NSLog(#"found '<' at pos %i", startPos);
// close search
if ([scanner scanString:#">" intoString:nil]) {
endPos = [scanner scanLocation]-1;
NSLog(#"found '>' at pos %i", endPos);
NSString* tag = [contentToParse substringWithRange:NSMakeRange(startPos, endPos-startPos)];
NSLog(#"Tag found : %#", tag);
}
}
but only "found '<' at pos 0" is logged.
My XML content contains many many <> items...
Why is that method not working ?
scanString:intoString: tries to scan the string parameter at the current location. If such string is not present at the current location, it simply returns NO.
You may want use scanUpToString:intoString: (reference) instead, which scans advancing the scan location until the given string is encountered.
NSScanner *scanner = [NSScanner scannerWithString:contentToParse];
// open search
[scanner scanUpToString:#"<" intoString:nil];
if (![scanner isAtEnd]) {
[scanner scanString:#"<" intoString:nil];
// close search
NSString *tag = nil;
[scanner scanUpToString:#">" intoString:&tag];
if (![scanner isAtEnd]) {
NSLog(#"Tag found : %#", tag);
}
}

How can I verify if a String has a null value?

sorry but i'm still struggling to make this code working. It works if with a 2 digits number but it crashes with a single digit number. How can I verify if the NSString *secDigit has a value or is null. I hope my question is clear. Thanks in advance.
NSString *depositOverTotalRwy = [NSString stringWithFormat:#"%#", [deposit text]];
NSArray *components = [depositOverTotalRwy
componentsSeparatedByString:#"/"];
NSString *firstThird = [components objectAtIndex:0];
char firstChar = [firstThird characterAtIndex:0];
char secChar = [firstThird characterAtIndex:1];
NSString *firstDigit = [NSString stringWithFormat:#"%c",firstChar];
NSString *secDigit = [NSString stringWithFormat:#"%c", secChar];
NSLog(#" i'm %#", firstDigit);
NSLog(#" i'm %#", secDigit);
if ([firstDigit isEqualToString: #"1"]) {
firstDigit=#"wet";
NSLog(#"wet");
}
if ([firstDigit isEqualToString: #"2"]) {
firstDigit=#"wet";
NSLog(#"snow");
}
if ([firstDigit isEqualToString: #"3"]) {
firstDigit=#"wet";
NSLog(#"ice");
}
if ([secDigit isEqualToString: #"1"]) {
secDigit=#"wet";
NSLog(#"wet");
}
if ([secDigit isEqualToString: #"2"]) {
secDigit=#"snow";
NSLog(#"snow");
}
if ([secDigit isEqualToString: #"3"]) {
secDigit=#"ice";
NSLog(#"ice");
}
thanks to all of you..... here my code (working now):
NSString *depositOverTotalRwy = [NSString stringWithFormat:#"%#", [deposit text]];
NSArray *components = [depositOverTotalRwy
componentsSeparatedByString:#"/"];
NSString *firstThird = [components objectAtIndex:0];
char firstChar = [firstThird characterAtIndex:0];
NSString *firstDigit = [NSString stringWithFormat:#"%c",firstChar];
NSLog(#" i'm %#", firstDigit);
if ([firstDigit isEqualToString: #"1"]) {
firstDigit=#"wet";
NSLog(#"wet");
}
if ([firstDigit isEqualToString: #"2"]) {
firstDigit=#"wet";
NSLog(#"snow");
}
if ([firstDigit isEqualToString: #"3"]) {
firstDigit=#"wet";
NSLog(#"ice");
}
if ([firstThird length] >1) {
char secChar = [firstThird characterAtIndex:1];
NSString *secDigit = [NSString stringWithFormat:#"%c", secChar];
if ([secDigit isEqualToString: #"1"]) {
secDigit=#"wet";
NSLog(#"wet");
}
if ([secDigit isEqualToString: #"2"]) {
secDigit=#"snow";
NSLog(#"snow");
}
if ([secDigit isEqualToString: #"3"]) {
secDigit=#"ice";
NSLog(#"ice");
}
}
I guess you code crashes in this line:
char secChar = [firstThird characterAtIndex:1];
This is because you try to access a character outside of the string bounds. You need to guard against this by checking the length of the string first:
if ([firstThird count] > 1) {
// String has 2 or more characters, do all the stuff that involves
// a second character.
char secChar = [firstThird characterAtIndex:1];
NSString *secDigit = [NSString stringWithFormat:#"%c", secChar];
if ([secDigit isEqualToString: #"1"]) {
secDigit=#"wet";
NSLog(#"wet");
}
}
But I'd also like to recommend to not use an NSString here, as you already have a char. Just do something like this:
if ([firstThird count] > 1) {
// String has 2 or more characters, do all the stuff that involves
// a second character.
char secChar = [firstThird characterAtIndex:1];
if (secChar == '1') {
secDigit=#"wet";
NSLog(#"wet");
}
}
I think this is what you are looking for:
char secChar;
if(firstThird.length > 1)
{
secChar = [firstThird characterAtIndex:1];
}
According to this
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
NSString "Raises an NSRangeException if index lies beyond the end of the receiver"
So, your code:
char secChar = [firstThird characterAtIndex:1];
Is the problem (you should see that in the debugger Console)
Check the length first with
if ([firstThird length] < 2) {
// handle the case where it is one digit
}
You can check number of characters in a string using NSString length. and modify your code
as
NSString *depositOverTotalRwy = [NSString stringWithFormat:#"%#", #"23"];
NSArray *components = [depositOverTotalRwy
componentsSeparatedByString:#"/"];
NSString *firstThird = [components objectAtIndex:0];
unichar firstChar;
unichar secChar;
if([firstThird length]>1){
firstChar = [firstThird characterAtIndex:0];
secChar = [firstThird characterAtIndex:1];
} else {
firstChar = [firstThird characterAtIndex:0];
secChar = 0;
}
switch (firstChar) {
case '1': /* Do your stuff*/break;
case '2': /* Do your stuff*/break;
case '3': /* Do your stuff*/break;
default:
break;
}
switch (secChar) {
case '1': /* Do your stuff*/break;
case '2': /* Do your stuff*/break;
case '3': /* Do your stuff*/break;
default:
break;
}
you can use unichar instead of char. And can perform check in switch statements.
If you use char, a casting is done from unichar to char and for some characters you may lose actual value. So it is safe to use unichar...
If you want to convert unichar to string simply code
NSString * stringChar = [NSString StringWithFormat:#"%C",unicharVariable];
Thats it ...

NSString range of string at occurrence

i'm trying to build a function that will tell me the range of a string at an occurrence.
For example if I had the string "hello, hello, hello", I want to know the range of hello at it's, lets say, third occurrence.
I've tried building this simple function, but it doesn't work.
Note - the top functions were constructed at an earlier date and work fine.
Any help appreciated.
- (NSString *)stringByTrimmingString:(NSString *)stringToTrim toChar:(NSUInteger)toCharacterIndex {
if (toCharacterIndex > [stringToTrim length]) return #"";
NSString *devString = [[[NSString alloc] init] autorelease];
for (int i = 0; i <= toCharacterIndex; i++) {
devString = [NSString stringWithFormat:#"%#%#", devString, [NSString stringWithFormat:#"%c", [stringToTrim characterAtIndex:(i-1)]]];
}
return devString;
[devString release];
}
- (NSString *)stringByTrimmingString:(NSString *)stringToTrim fromChar:(NSUInteger)fromCharacterIndex {
if (fromCharacterIndex > [stringToTrim length]) return #"";
NSString *devString = [[[NSString alloc] init] autorelease];
for (int i = (fromCharacterIndex+1); i <= [stringToTrim length]; i++) {
devString = [NSString stringWithFormat:#"%#%#", devString, [NSString stringWithFormat:#"%c", [stringToTrim characterAtIndex:(i-1)]]];
}
return devString;
[devString release];
}
- (NSRange)rangeOfString:(NSString *)substring inString:(NSString *)string atOccurence:(int)occurence {
NSString *trimmedString = [inString copy]; //We start with the whole string.
NSUInteger len, loc, oldLength;
len = 0;
loc = 0;
NSRange tempRange = [string rangeOfString:substring];
len = tempRange.length;
loc = tempRange.location;
for (int i = 0; i != occurence; i++) {
NSUInteger endOfWord = len+loc;
trimmedString = [self stringByTrimmingString:trimmedString fromChar:endOfWord];
oldLength += [[self stringByTrimmingString:trimmedString toChar:endOfWord] length];
NSRange tmp = [trimmedString rangeOfString:substring];
len = tmp.length;
loc = tmp.location + oldLength;
}
NSRange returnRange = NSMakeRange(loc, len);
return returnRange;
}
Instead of trimming the string a bunch of times (slow), just use rangeOfString:options:range:, which searches only within the range passed as its third argument. See Apple's documentation.
So try:
- (NSRange)rangeOfString:(NSString *)substring
inString:(NSString *)string
atOccurence:(int)occurence
{
int currentOccurence = 0;
NSRange rangeToSearchWithin = NSMakeRange(0, string.length);
while (YES)
{
currentOccurence++;
NSRange searchResult = [string rangeOfString: substring
options: NULL
range: rangeToSearchWithin];
if (searchResult.location == NSNotFound)
{
return searchResult;
}
if (currentOccurence == occurence)
{
return searchResult;
}
int newLocationToStartAt = searchResult.location + searchResult.length;
rangeToSearchWithin = NSMakeRange(newLocationToStartAt, string.length - newLocationToStartAt);
}
}
You need to rework the whole code. While it may seem to work, it's poor coding and plain wrong, like permanently reassigning the same variable, initializing but reassigning one line later, releasing after returning (which will never work).
For your question: Just use rangeOfString:options:range:, and do this the appropriate number of times while just incrementing the starting point.