Reading in .CSV individual values - ios

I have a .CSV File below that is already put into a nice format rather than a solid list of values.
How would i be able to read individual values from this list … for example 'Time of 5 & 6" and return the number?
I know how would retrieve this from a normal .csv file that is listed, however not from one that has a weird layout like this one. Any ideas?
Thank

If the column titles (such as "Time 4" and "Time of 5 & 6") are consistent, you could separate each line and then by commas, look for the index of the column title, and then grab the same column in the next line.
I haven't tested this, but I think it should work. Assuming your file is read in as a string:
NSArray *componentsByLine = [myFile componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
int firstIndex = 0;
int secondIndex = 0;
BOOL found = NO;
for(firstIndex = 0; firstIndex < componentsByLine.count; firstIndex++)
{
NSArray *componentsByComma = [[componentsByLine objectAtIndex:firstIndex] componentsSeparatedByString:#","];
for(secondIndex = 0; secondIndex < componentsByComma.count; secondIndex++)
{
if([[componentsByComma objectAtIndex:secondIndex] isEqualToString:#"Time of 5 & 6"])
{
found = YES;
break;
}
}
if(found)
break;
}
float requestedTime = [[[[componentsByLine objectAtIndex:firstIndex+1] componentsSeparatedByString:#","] objectAtIndex:secondIndex] floatValue];

Related

How to create a centre align Nsstring

I have NSString strings that represent Product name Quantity Price
I need to align columns of these values like this
Productname Qty Price
PLAIN T-SHIRT 5 50.00
BLACK DENIM 1 29.99
BLUE DENIM 3 29.99
STRIPED DRESS 1 49.99
BLACK BOOTS 2 35.99
How ever I try using
+(NSString *) get_TOT:(NSString *)tot_STR : (int) length_range
{
NSString *tmp_TT;
NSUInteger length = tot_STR.length;
NSRange range;
tmp_TT = [NSString stringWithFormat:#" %d %f",Qty,pricc];
if (length <= 33)
{
range = NSMakeRange(33-length, length);
tmp_TT = [tmp_TT stringByReplacingCharactersInRange:range withString:tot_STR];
}
else
{
tmp_TT = [tmp_TT substringToIndex:33];
}
return tmp_TT;
}
I am not sure what is going wrong here
Thanks in advance
Woah! Adding hardcoded blank spaces to get the desired UI would be a very bad way of doing it.
You should use NSAttributedStrings to get the center-alignment.

How to Read CSV with comma placed within double quotes

I am implementing csv splitting in my project . can I know how to implement CSV splitting in ios. say for example i have a string #"one,\"two,three\",four" . I need output as below in an array format which containts 3 element
one
two,three
four
You can use this code but, it is not proper way:
NSString *StrDataOfCSV=#"one,\"two,three\",four";
NSMutableArray * csvArray= [[NSMutableArray alloc]init];
NSArray * firstSeparated=[StrDataOfCSV componentsSeparatedByString: #"\","];
for (NSString * strCom in firstSeparated) {
NSArray * arrCom=[strCom componentsSeparatedByString:#",\""];
[csvArray addObjectsFromArray:arrCom];
}
Something like this to "normalize" your input string, replacing the commas with a new separator character, one that you can guarantee won't appear in your input (e.g. a |), and removing the quotes from the quoted fields:
char *cbCSVRecord = "one,\"two,three\",four";
bool bQuotedField = false;
// normalize
for (int i = 0,j = 0;i < (int)strlen(cbCSVRecord);i++)
{
if ((cbCSVRecord[i] == '\n') || (cbCSVRecord[i] == '\r'))
cbCSVRecord[i] = '\0';
// Not a double quote?
if (cbCSVRecord[i] != '"')
{
// if a comma NOT within a quoted field, replace with a new separator
if ((cbCSVRecord[i] == ',') && (!bQuotedField))
cbCSVRecord[i] = '|';
// new output
cbCSVRecord[j] = cbCSVRecord[i];
j++;
}
// Is a double quote, toggle bQuotedField
else
{
if (!bQuotedField)
bQuotedField = true;
else
bQuotedField = false;
}
}
cbCSVRecord[j] = '\0';
please note that I roughed out this code, and it is plain C code. It should either work or have you pretty close.
An input of #"one,\"two,three\",four" should become #"one|two,three|four", and you can then use:
NSArray *listItems = [list componentsSeparatedByString:#"|"];
Use NSString's componentsSeparatedByString:
NSString *list = #"Karin, Carrie, David";
NSArray *listItems = [list componentsSeparatedByString:#", "];

Will this unicode encryption fail?

I'm not needing any serious security, I just need to stop 11 year olds with plist editors from editing their number of coins in my game with ease.
I created a function that takes a string, for each unicode value of a character it raises this unicode value by 220 plus 14 times the character number that it is in the string.
Obviously this will fail (I think) if the string was like a million characters long because eventually you run out of unicode characters, but for all intents and purposes, this will only be used on strings of 20 characters and less.
Are there any unicode characters in this range that will not be stored to a plist or will be ignored by Apple's underlying code when I save the plist so that when I retrieve it and decrypt the character will be gone and I can't decrypt it?
+(NSString*)encryptString:(NSString*)theString {
NSMutableString *encryptedFinal = [[NSMutableString alloc] init];
for (int i = 0; i < theString.length; i++) {
unichar uniCharacter = [theString characterAtIndex:i];
uniCharacter += +220+(14*i);
[encryptedFinal appendFormat:#"%C", uniCharacter];
}
return encryptedFinal;
}
+(NSString*)decryptString:(NSString*)theString {
NSMutableString *decryptedFinal = [[NSMutableString alloc] init];
for (int i = 0; i < theString.length; i++) {
unichar uniCharacter = [theString characterAtIndex:i];
uniCharacter += +220+(14*i);
[decryptedFinal appendFormat:#"%C", uniCharacter];
}
return decryptedFinal;
}
It works for a range of a string of length 20 characters or less if you are encrypting one of the first 26+26+10+30 characters in the unicode index at any given point along the 20 character line. It probably works higher, I just didn't test it any higher.
This is the code I created to test it, all unicode characters were stored in an NSString and stayed valid for counting later.
int i = 0;
NSMutableString *encryptedFinal = [[NSMutableString alloc] init];
NSString *theString = #"a";
int j = 26+26+10+30;//letters + capital letters + numbers + 30 extra things like ?><.\]!#$
int f = 0;
int z = 0;
while (f < j) {
while (i < 220+220+(14*20)) {
unichar uniCharacter = [theString characterAtIndex:0];
uniCharacter += +f;
uniCharacter += +220+(14*i);
[encryptedFinal appendFormat:#"%C", uniCharacter];
i++;
}
z += i;
f++;
i = 0;
}
NSLog(#"%#", encryptedFinal);
NSLog(#"%i == %i?", z, encryptedFinal.length);
There are two thing that you can do:
Save the number of coins using NSData rather than using
NSNumber. Then use
NSData+AES
to encrypt it. You can even encrypt your entire .plist file to
ensure that no other fields are changed.
Security through obscurity. Just save the number of coins as an important sounding field. e.g.:Security Token Number. You can also create a bogus number of coins field whose value is ignored. Or maybe save the same value in both the fields and flag the user for cheating if the two values don't match.

how to include index number in a class name

I am making a program where I need to loop through an array with a list of letters. I want the letters to be shown on their specific label. I have therefore created an outlet of each (about 38) and given them the name "alif01", "alif02", etc.
for (int i = 0; i < [arabicLetters count]; i++) {
int num = i;
NSString *letterString = [arabicLetters objectAtIndex:i];
NSLog(#"alif0%d is %#", num, letterString);
alif0**[i]**.text = arabicLetters[i];
}
is it possible to use the index [i] instead of writing it all manually?
You should not have 38 IBOutlet properties for this. You should have an array (possibly an IBOutletCollection) so that you can loop over the array / index into the array.
While technically you can create a key name and use KVC valueForKey: (appending strings / string format), the array approach is a much better solution.
Indeed, as you already have a loop, you would be better served by creating the labels in the loop directly, then you know you have the correct number. This is particularly beneficial later, when you change the contents of arabicLetters (though that sounds like it isn't a concern in this particular case).
Try with below code:
for (int i = 0; i < [arabicLetters count]; i++) {
NSString *letterString = [arabicLetters objectAtIndex:i];
NSString *propertyName = [NSString stringWithFormat:#"alif0%d.text",i];
[self setValue:letterString forKeyPath:propertyName];
}

Sequentially ordered NSMutableArray - replacing breaks in order

I've been having a mind blank over this problem, so I thought maybe some of you could shed a light on the situation.
To cut a long story short, I am building an app that fetches a school student's timetable from a server, parses it, and displays it in a table view. Each student has 7 periods per day, and there are 10 days in the timetable spanning across a fortnight (5 days in Week A, 5 days in Week B).
However the problem lies where some students have free periods - that is, they do not have a class during that period. Because the server does not take free periods into account, some students might return 70 total periods in the fortnight, whereas another might return 66.
Cutting to the chase here...
I have an ordered NSMutableArray full of NSDictionaries. A typical object in the array would look like this when outputted to the console:
{
weekday = 12;
period = 1;
room = "Room D404";
title = "English Extension";
},
I need to figure out where there is a break in the order, and if so, insert an object into it to fill the blank. Let me give you an example:
{
dayweek = 12;
period = 1;
room = "Room D404";
title = "English Extension";
},
{
dayweek = 12;
period = 2;
room = "Room W285";
title = "Modern History";
},
{
dayweek = 12;
period = 3;
room = "Room W187";
title = "Maths Extension 1";
},
{
dayweek = 12;
period = 4;
room = "Room W370";
title = Economics;
},
{
dayweek = 12;
period = 6;
room = "Room D301";
title = "English Advanced";
},
{
dayweek = 12;
period = 7;
room = "Room W282";
title = "Studies of Religion";
},
{
dayweek = 13;
period = 1;
room = "Room W370";
title = Economics;
},
There is no object where period = 5, so I need to add one. Is what I'm saying hard to understand? Sorry if it is.
Thanks in advance!
This fills in missing periods from 1 to the last existing on a day. It does not fill days to a given minimum of periods.
NSMutableArray periods; // from somewhere else
NSUInteger count = [periods count];
NSUInteger currentPeriod = 0;
NSUInteger currentDayweek = 0;
for (NSUInteger i = 0; i < count; ++i)
{
NSDictionary *periodDescription = periods[i];
NSUInteger dayweek = [periodDescription[#"dayweek"] unsignedIntegerValue];
if (dayweek != currentDayweek) {
// another day
currentPeriod = 0;
currentDayweek = dayweek;
}
NSUInteger period = [periodDescription[#"period"] unsignedIntegerValue];
currentPeriod += 1;
while (period > currentPeriod) {
NSDictionary *fillIn = #{ #"dayweek" : #(dayweek), #"period" : #(currentPeriod), #"room" : #"cafeteria", #"title" = "taking a break" };
[periods insertObject:fillIn atIndex:i];
currentPeriod += 1;
i += 1;
count += 1;
}
}
If you do not want to fill morning hours before the first existing period, add this directly before the while loop:
if (currentPeriod == 1)
currentPeriod = period;
Note: Typed in browser, errors are probable.
Try this and let me know if you are getting any issues
for (int i = 1; i<=self.arrayForRows.count; i++)
{
if ([[[self.arrayForRows objectAtIndex:i]valueForKey:#"period"] intValue] == i)
{
}
else
{
// Insert Here as [self.arrayForRows insertObject:yourObject atIndex:i];
i=i-1;
}
}
This is only a partial answer, but too long to post as a comment.
The purpose of this snippet is only to identify missing periods with a minimal amount of code. You would need to do it in a loop for all days of the fortnight, of course.
To do this you can use predicates:
// For each day create a list of all periods.
// This is just a hard coded example
NSArray *allPeriodsForDay = #[#(1),#(2),#(3),#(4),#(5),#(6)];
// Get an array of the periods actually in the list
// It will look like this: #[#(1),#(2),#(4),#(5),#(6)]; // Period 3 missing
NSArray *studentsPeriods = [periodRecords valueForKey: #"period"];
// Build a predicate to identify period(s) not in list
NSPredicate *freePredicate = [NSPredicate predicateWithFormat:#"not self in %#", studentsPeriods];
NSArray *freePeriods = [allPeriodsForDay filteredArrayUsingPredicate:freePredicate];
freePeriods now contains a list of the "missing" periods in the students' schedule for that day.
You can then create a new NSDictionary and add it to the list. Then sort it all by the period field.

Resources