Data types

In this tutorial we cover the following topics

Excercise 4.0.1: class for multidimensional (2D) array

Assumptions

• Class should allow to store objects in a dynamic 2D array.

Excercise 4.0.2: runners log application

Assumptions

• Application should read data from a text file.
• Each line describes one training.
• Training data are expressed in the form
• Not all training data are obligatory – some of them may be missing.
• The following data are defined
• Training date
• Training time
• Distance
• Time
• Equipment (for example shoes)
• The user should have a menu with options like
• Print total distance
• Print total training time
• Print an average speed
• Print total distence per week
• etc

Hint 1 for the exercises

Simple application which reads some data from a file, creates an array and puts this data into array.

```#import <Foundation/Foundation.h>

@interface Array2D : NSObject{
NSMutableArray * array;
}

- (id)initWithCapacity: (int) capacity;
-(void) add: (NSObject*) element index:(int) index;
- (NSObject *) get: (int) index;
@end
```
```#import "Array2D.h"

@implementation Array2D

- (id)initWithCapacity: (int) capacity{
self = [super init];
if (self) {
array = [[NSMutableArray alloc] initWithCapacity: capacity];

for (int i=0; i<capacity; i++) {
[array setObject:[NSNull null] atIndexedSubscript: i];
}

}
return self;
}

-(void) add: (NSObject*) element index:(int) index{
[array replaceObjectAtIndex: index withObject: element];
}

- (NSObject *) get: (int) index{
return array[index];
}

@end
```
```/*
This application reads a file of the format
10
0 foo_0
2 foo_2
7 foo_7

where
line 0: max number of elements
line 1: number of columns
line x: <index><space><string_without_space>
*/

#import <Foundation/Foundation.h>
#import "Array2D.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {
int capacity = 0;
int numberOfDataLines;
int index;

// Reading data from a file
//Don't know how to use the follwing on OS X
//NSString *filepath = [[NSBundle mainBundle] pathForResource:@"running_data" ofType:@"strings"];
NSError *error;
NSLog(@"Use path: %@", filepath);
NSString *fileContents = [NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:&error];

if (error)

// Process this data
NSArray *dataLines = [fileContents componentsSeparatedByString:@"\n"];

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *number = [numberFormatter numberFromString: dataLines[0]];
if (number){
capacity = [number intValue];

Array2D * myArray = [[Array2D alloc] initWithCapacity: capacity];

numberOfDataLines = (int)([dataLines count]);

for(int i = 1; i < numberOfDataLines; ++i){
NSArray *data = [dataLines[i] componentsSeparatedByString:@" "];
number = [numberFormatter numberFromString: data[0]];
if (number){
index = [number intValue];
if (index < capacity){
}
}
}

NSObject * obj;
for(int i=0; i<capacity; ++i){
obj = [myArray get: i];
if ([obj isKindOfClass:[NSNull class]]){
NSLog(@"At index %d we have: ---", i);
} else {
NSLog(@"At index %d we have: %@", i, [myArray get: i]);
}
}
}
}
return 0;
}
```

Tested with a file

```10
0 foo_0
2 foo_2
7 foo_7
```

should return something similar to
[fulmanp type=”terminal”]
2016-03-18 16:55:34.643 ReadFileTest[14412:1484597] At index 0 we have: foo_0
2016-03-18 16:55:34.643 ReadFileTest[14412:1484597] At index 1 we have: —
2016-03-18 16:55:34.643 ReadFileTest[14412:1484597] At index 2 we have: foo_2
2016-03-18 16:55:34.644 ReadFileTest[14412:1484597] At index 3 we have: —
2016-03-18 16:55:34.644 ReadFileTest[14412:1484597] At index 4 we have: —
2016-03-18 16:55:34.644 ReadFileTest[14412:1484597] At index 5 we have: —
2016-03-18 16:55:34.644 ReadFileTest[14412:1484597] At index 6 we have: —
2016-03-18 16:55:34.644 ReadFileTest[14412:1484597] At index 7 we have: foo_7
2016-03-18 16:55:34.644 ReadFileTest[14412:1484597] At index 8 we have: —
2016-03-18 16:55:34.645 ReadFileTest[14412:1484597] At index 9 we have: —
Program ended with exit code: 0
[/fulmanp]

Hint 2 for the exercises

Assumptions

• Application should read data from a text file.
• Each line describes one training.
• Training data are expressed in the form
• One training data should be represented in application as an object.
• All training data (object) should be collected in an array.
```#import <Foundation/Foundation.h>

@interface Record : NSObject{

}

withDuration: (NSString *) durationValue
withDistance: (NSString *) distanceValue;
-(NSString *) getAllDataAsString;

@end
```
```#import "klasa.h"

@implementation Record
{
NSDate * date;
int duration;
int distance;
}

withDuration: (NSString *) durationValue
withDistance: (NSString *) distanceValue {
int tmp;

// Deal with integer values
NSNumber *number;
NSNumberFormatter *numberFormatter= [[NSNumberFormatter alloc]init];
numberFormatter.numberStyle=NSNumberFormatterDecimalStyle;
number = [numberFormatter numberFromString: durationValue];
duration = [number intValue];
number = [numberFormatter numberFromString: distanceValue];
distance = [number intValue];

// Deal with time
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [[NSDateComponents alloc] init];

NSArray *dateComponentsAsString = [dateValue componentsSeparatedByString: @"-"];

tmp = [[numberFormatter numberFromString: dateComponentsAsString[0]] intValue];
[components setYear:tmp];
tmp = [[numberFormatter numberFromString: dateComponentsAsString[1]] intValue];
[components setMonth:tmp];
tmp = [[numberFormatter numberFromString: dateComponentsAsString[2]] intValue];
[components setDay:tmp];

date = [calendar dateFromComponents:components];
}

-(NSString *) getAllDataAsString
{
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *components = [calendar components:units fromDate:date];

NSString * dateAsString = [NSString stringWithFormat:@"%4ld-%02ld-%02ld",
[components year],
[components month],
[components day]];

return [NSString stringWithFormat:@"%@ %d %d", dateAsString, duration, distance];
}

@end
```
```#import "klasa.h"

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableArray * runningData = [[NSMutableArray alloc] init];
NSString * filepath = @"/Users/fulmanp/Desktop/iOS/app_data/projekcik/run.txt";
NSError *error;
NSString* fileContents = [NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error: &error];
if (error)
{
NSLog(@"%@",error.localizedDescription);
}
else
{
NSArray *dataLines = [fileContents componentsSeparatedByString: @"\n"];
int numberOfLines =(int)[dataLines count];
NSArray *line;

for(int i=0; i<numberOfLines; i++){
line = [dataLines[i] componentsSeparatedByString: @" "];

if ((int)[line count] == 3){
Record * record = [[Record alloc] init];

[record setDataDate: line[0] withDuration: line[1] withDistance: line[2]];

}
}

int numberOfRecords =(int)[runningData count];
for(int i=0; i<numberOfRecords; i++){
NSLog(@"%@", [runningData[i] getAllDataAsString]);
}
}
}
return 0;
}
```

[fulmanp type=”terminal”]
2016-03-31 18:48:21.108 projekcik[1428:104176] 2016-03-13 1000 5
2016-03-31 18:48:21.109 projekcik[1428:104176] 2016-03-15 1500 7
2016-03-31 18:48:21.109 projekcik[1428:104176] 2016-03-22 2000 9
Program ended with exit code: 0
[/fulmanp]
If you want you can use `argc` and `argv` arguments to pass file name to the application. To test it in Xcode please visit Scheme Editor settings page (you can use `command` + `shift` + `<`)

1. From the Scheme toolbar menu, choose a scheme.
2. From the same menu, choose Edit Scheme to display the scheme dialog.
3. In the left column, select Run.
4. To specify runtime arguments, click Arguments and then click the Add button.
5. Click Close.
6. Click the Run button or choose Product > Run.