Data types

In this tutorial we cover the following topics


Data types sources of informations



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)
    • You may also add your own data types
  • 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
        NSString *filepath = @"/Users/fulmanp/Desktop/iOS/tutorials/ReadFileTest/data.txt";
        //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)
            NSLog(@"Error reading file: %@", error.localizedDescription);
        
        // 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){
                        [myArray add: data[1] index: index];
                    }
                }
            }
            
            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.635 ReadFileTest[14412:1484597] Use path: /Users/fulmanp/Desktop/iOS/tutorials/ReadFileTest/data.txt
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{
  
}

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

@end
#import "klasa.h"

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

-(void) setDataDate:(NSString *)dateValue
       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]];
                    
                    [runningData addObject: record];
                }
            }
            
            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.