obj-c problem setting array with componentsSeperatedByString - iphone

I have a data source with about 2000 lines that look like the following:
6712,Anaktuvuk Pass Airport,Anaktuvuk Pass,United States,AKP,PAKP,68.1336,-151.743,2103,-9,A
What I am interested in is the 6th section of this string so I want to turn it into an array, then i want to check the 6th section [5] for an occurrance of that string "PAKP"
Code:
NSBundle *bundle = [NSBundle mainBundle];
NSString *airportsPath = [bundle pathForResource:#"airports" ofType:#"dat"];
NSData *data = [NSData dataWithContentsOfFile:airportsPath];
NSString *dataString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSArray *dataArray = [dataString componentsSeparatedByString:#"\n"];
NSRange locationOfAirport;
NSString *workingString = [[NSString alloc]initWithFormat:#""];
NSString *searchedAirport = [[NSString alloc]initWithFormat:#""];
NSString *airportData = [[NSString alloc]initWithFormat:#""];
int d;
for (d=0; d < [dataArray count]; d=d+1) {
workingString = [dataArray objectAtIndex:d];
testTextBox = workingString; //works correctly
NSArray *workingArray = [workingString componentsSeparatedByString:#","];
testTextBox2 = [workingArray objectAtIndex: 0]; //correctly displays the first section "6712"
testTextBox3 = [workingArray objectAtIndex:1] //throws exception index beyond bounds
locationOfAirport = [[workingArray objectAtIndex:5] rangeOfString:#"PAKP"];
}
the problem is that when the workingArray populates, it only populates with a single object (the first component of the string which is "6712". If i have it display the workingString, it correctly displays the entire string, but for some reason, it isn't correctly making the array using the commas.
i tried it without using the data file and it worked fine, so the problem comes from how I am importing the data.
ideas?

You code works. You should run it with the debugger to see what's happening. At a guess, your input data isn't what you think it is - possibly a different encoding, or different line endings.
See sample:
NSString *dataString = #"6712,Anaktuvuk Pass Airport,Anaktuvuk Pass,United States,AKP,PAKP,68.1336,-151.743,2103,-9,A";
NSArray *dataArray = [dataString componentsSeparatedByString:#"\n"];
for (NSString *workingString in dataArray) {
NSString *testTextBox = workingString; //works correctly
NSArray *workingArray = [workingString componentsSeparatedByString:#","];
NSString *testTextBox2 = [workingArray objectAtIndex: 0]; //correctly displays the first section "6712"
NSString *testTextBox3 = [workingArray objectAtIndex:1]; //throws exception index beyond bounds
NSRange locationOfAirport = [[workingArray objectAtIndex:5] rangeOfString:#"PAKP"];
}

there was a problem in the data where there were a few "\"s that caused the errors.

Related

Reading from NSMutableArray throws exception at item 2 even though it exists

I've got a file with a bunch of string in like so:
item1,01-SR,admin,Missing or broken,undefined, 16/04/2013 18:10:10;
item1,03-SR,admin,In Use,undefined, 16/04/2013 18:10:34;
item1,01-SR,admin,In Use,undefined, 16/04/2013 18:10:45;
item1,02-SR,admin,In Use,undefined, 16/04/2013 18:10:49;
item1,05,admin,In Use,undefined, 16/04/2013 18:10:56;
I'm reading the strings in and then splitting them up so I just get one string at a time. Then I want to split up the string I've got again so each CSV is it's own variable. I've tried this like so (numLines is a count of the number of lines in the file):
while (count1 < numLines) {
NSString *message = [[strings objectAtIndex: count1] copy];
NSMutableArray *items = [[fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#";"]] mutableCopy];
NSString *items1 = [[items objectAtIndex: count1] copy];
NSLog(#"items: %#", items1);
NSMutableArray *inditems = [[items1 componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]] mutableCopy];
NSString * item1 = inditems[0];
NSString * bnum1 = inditems[1];
NSString * user1 = inditems[2];
NSString * state1 = inditems[3];
NSString * gender1 = inditems[4];
NSString * tstamp1 = inditems[5];
NSLog(#"item: %#", item1);
NSLog(#"bnum: %#", bnum1);
NSLog(#"user: %#", user1);
NSLog(#"state: %#", state1);
NSLog(#"gender: %#", gender1);
NSLog(#"tstamp: %#", tstamp1);
count1++;
}
Now, this works as far as selecting one line from the file and it puts the first two items into the array and then writes the values of item1 and bnum1 to the log but then it throws an exception for some reason. Now this would usually suggest to me that item 2 doesn't exist in the array so I did a count like so:
NSLog(#"count = %d", [inditems count]);
Which correctly returns 6. I then wanted to check that it could actually read another item from the array so I did:
NSString *tstamp1 = [[inditems lastObject] copy];
Which when logged correctly returns the time stamps like so:
16/04/2013 18:10:10
So I thought "oh at least item 5 works" and tried just getting that item:
while (count1 < numLines) {
NSString *message = [[strings objectAtIndex: count1] copy];
NSMutableArray *items = [[fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#";"]] mutableCopy];
NSString *items1 = [[items objectAtIndex: count1] copy];
NSLog(#"items: %#", items1);
NSMutableArray *inditems = [[items1 componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]] mutableCopy];
NSString * item1 = inditems[0];
NSString * bnum1 = inditems[1];
NSString * tstamp1 = inditems[5];
NSLog(#"item: %#", item1);
NSLog(#"bnum: %#", bnum1);
NSLog(#"tstamp: %#", tstamp1);
count1++;
}
But that also throws an exception! I'm probably doing something stupid here, but I would appreciate any help.
Thanks!
My guess is your NSArray *strings is including empty value which is causing your error. You need to check it first and then do your logic.
//path is your file path
NSString* fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSArray *strings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (int i = 0; i < [strings count]; i++){
if (![[strings objectAtIndex:i] isEqualToString:#""]){
//Here do your code...
}
}

Memory management in appending a string?

I have an iPhone application in which i am creating an array in the didfinishlaunch in the appdelegate. Like this:
for(int i=1;i<53;i++)
{
NSString *namestring=[NSString stringWithString:#"avatar"];
NSString *string = [NSString stringWithFormat:#"%d",i];
NSString *pngstring=[NSString stringWithString:#".png"];
string = [string stringByAppendingString:pngstring];
namestring = [namestring stringByAppendingString:string];
NSLog(#"%#",namestring);
[avtararray addObject:namestring];
}
working fine.and everywhere i am doing the avatar job with my avatararray in the appdelegate.But in one case when i pop back to the previous view and try to load the string from the array again
NSString *avatarstringt=[[appDelegate.avtararray objectAtIndex:i]description];here it is crashing with a an error
-[CFString description]: message sent to deallocated instance..
when doing the profile job i know that the leak is in the above loop in the appendingstring code.Can anybody help me to remove this?
First of all, Never do this
NSString *string = [NSString stringWithFormat:#"%d",i];
NSString *pngstring=[NSString stringWithString:#".png"];
string = [string stringByAppendingString:pngstring];
The following statements, are redundant
NSString *namestring=[NSString stringWithString:#"avatar"];
NSString *pngstring=[NSString stringWithString:#".png"];
and should be written as:
NSString *namestring=#"avatar";
NSString *pngstring=#".png";
You can use as :
NSString *namestring=#"avatar";
NSString *numberString = [NSString stringWithFormat:#"%d",i];
NSString *pngstring=#"png";
namestring = [namestring stringByAppendingFormat:#"%#.%#",numberString,pngstring];
Even the shortest of code :
for(NSInteger i=1;i<5;i++){
NSString *namestring = [NSString stringWithFormat:#"avatar%#.png",#(i)];
NSLog(#"%#",namestring);
}
As suggested by rmaddy: you can use i as integer, no need of converting it into nsnumber
NSString *namestring = [NSString stringWithFormat:#"avatar%d.png",i];

NSRegularExpression to extract text

All,
I have a dictionary with two keys and values. I need to extract bits and pieces from them and place them into seperate strings.
{
IP = "192.168.17.1";
desc = "VUWI-VUWI-ABC_Dry_Cleaning-R12-01";
}
That is what the dictionary looks like when I call description.
I want the new output to be like this:
NSString *IP = #"192.168.17.1";
NSString *desc = #"ABC Dry Cleaning"; //note: I need to get rid of the underscores
NSString *type = #"R";
NSString *num = #"12";
NSString *ident = #"01";
How would I achieve this?
I've read through the Apple developer docs on NSRegularExpression but I find it hard to understand. I'm sure once I get some help once here I can figure it out in the future, I just need to get started.
Thanks in advance.
Okay, so first, you have to get the object associated with each key:
NSString *ip = [dic objectForKey:#"IP"]; //Btw, you shouldn't start a variable's name with a capital letter.
NSString *tempDesc = [dic objectForKey:#"desc"];
Then, what I would do is split the string in tempDesc, based on the character -.
NSArray *tmpArray = [tempDesc componentsSeparatedByString:#"-"];
Then you just have to get the strings or substrings you're interested in, and reformat them as needed:
NSString *desc = [[tmpArray objectAtIndex:2] stringByReplacingOccurrencesOfString:#"_" withString:#" "];
NSString *type = [[tmpArray objectAtIndex:3] substringToIndex:1];
NSString *num = [[tmpArray objectAtIndex:3] substringFromIndex:1];
NSString *ident = [tmpArray objectAtIndex:4];
As you can see, this works perfectly without using NSRegularExpression.

parsing array elements in iPhone

NSBundle *bundle = [NSBundle mainBundle];
NSString *pthpath = [bundle pathForResource:#"path" ofType:#"txt"];
NSString *content = [NSString stringWithContentsOfFile:pthpath encoding:NSUTF8StringEncoding error:nil];
array=[[NSArray alloc ]init];
array = [content componentsSeparatedByString:#"~"];
=====================================================================
here content is:
87,348~51,347~135,132~182,133~268,346~236,347~159,168~87,347#118,298~115,297~200,298~189,266~128,265~117,299#222,352~268,353~264,340~219,342~225,355#186,262~199,299~212,297~195,257~188,260
and array is:
"87,348",
"51,347",
"135,132",
"182,133",
"268,346",
"236,347",
"159,168",
"87,347#118,298",
"115,297",
"200,298",
"189,266",
"128,265",
"117,299#222,352",
"268,353",
"264,340",
"219,342",
"225,355#186,262",
"199,299",
"212,297",
"195,257",
"188,260"
But I want to again create an array by parsing with #. Please help me out...........
for (NSString *string in array) {
NSArray *subArray = [string componentsSeparatedByString:#"#"];
for (NSString *substring in subArray)
etc. etc.
(Next time try to have your question better formatted and articulated please.)
Instead of using componentsSeparatedByString:, use componentsSeparatedByCharactersInSet: and create a character set with the separators you want.
Also, you are creating an array there (array = [[NSArray alloc] init]) and when you do array = [content componentsSeparatedByString:#"#"] you are leaking the just allocated array. In general, seems like you should read more about how objects and references work.
I think from following code you may get some idea, if I understood your question correctly,
NSMutableArray *resultArray = [[NSMutableArray alloc] initWithCapacity:1];
NSArray *tempArray1 = nil;
NSArray *tempArray2 = nil;
NSString *content = #"87,348~51,347~135,132~182,133~268,346~236,347~159,168~87,347#118,298~115,297~200,298~189,266~128,265~117,299#222,352~268,353~264,340~219,342~225,355#186,262~199,299~212,297~195,257~188,260";
tempArray1 = [content componentsSeparatedByString:#"#"];
for(NSString *string in tempArray1)
{
tempArray2 = [string componentsSeparatedByString:#"~"];
[resultArray addObjectsFromArray:tempArray2];
}
NSLog(#"ResultArray :%#", resultArray);

iPhone parsing url for GET params

I have an string which is got from parsing an xml site.
http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500
I want to have an NSString function that will be able to parse the value of c.
Is there a default function or do i have to write it manually.
You could use Regular expression via RegExKit Lite:
http://regexkit.sourceforge.net/RegexKitLite/
Or you could separate the string into components (which is less nice):
NSString *url=#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray *comp1 = [url componentsSeparatedByString:#"?"];
NSString *query = [comp1 lastObject];
NSArray *queryElements = [query componentsSeparatedByString:#"&"];
for (NSString *element in queryElements) {
NSArray *keyVal = [element componentsSeparatedByString:#"="];
if (keyVal.count > 0) {
NSString *variableKey = [keyVal objectAtIndex:0];
NSString *value = (keyVal.count == 2) ? [keyVal lastObject] : nil;
}
}
I made a class that does this parsing for you using an NSScanner, as an answer to the same question a few days ago. You might find it useful.
You can easily use it like:
URLParser *parser = [[[URLParser alloc] initWithURLString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"] autorelease];
NSString *c = [parser valueForVariable:#"c"]; //c=500
Try the following:
NSURL *url = [NSURL URLWithString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"];
NSMutableString *parameterString = [NSMutableString stringWithFormat:#"{%#;}",[url parameterString]];
[parameterString replaceOccurrencesOfString:#"&" withString:#";"];
// Convert string into Dictionary
NSPropertyListFormat format;
NSString *error;
NSDictionary *paramDict = [NSPropertyListSerialization propertyListFromData:[parameterString dataUsingEncoding:NSUTF8StringEncoding] mutabilityOption: NSPropertyListImmutable format:&format errorDescription:&error];
// Now take the parameter you want
NSString *value = [paramDict valueForKey:#"c"];
Here is the native iOS approach using NSURLComponents and NSURLQueryItem classes:
NSString *theURLString = #"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray<NSURLQueryItem *> *theQueryItemsArray = [NSURLComponents componentsWithString:theURLString].queryItems;
for (NSURLQueryItem *theQueryItem in theQueryItemsArray)
{
NSLog(#"%# %#", theQueryItem.name, theQueryItem.value);
}