Pages

Monday, March 8, 2010

Parse the text with integer values

Simply a kind of an interesting task: retrieve all integer values from a string like "10 223 21 67"
#include <stdio.h>
#include <string.h>

int main (int argc, const char * argv[])
{
char strInts[] = "10 223 21 67";
char delim[] = " ";
char *token;
int i;
token = strtok(strInts, delim);
while( token != NULL )
{
sscanf(token, "%d", &i);
printf("%d\n",i);

token = strtok( NULL, delim );
}

return 0;
}

Sunday, March 7, 2010

Postfix ++. Prefix++

Class Digit in the following program has operator++ implemented in the prefix and postfix forms:
#include <iostream>
using namespace std;

class Digit {
int value;

public:
Digit() : value(0) {}
Digit(const Digit& digit)
{
value = digit.value;
}

//prefix ++
Digit& operator++ ()
{
if (value > 8)
value = 0;
else
value++;
return *this;
}

//postfix ++
Digit operator++(int)
{
Digit digit = *this;
++*this;
return digit;
}

int Value() { return value; }
};

int main (int argc, char * const argv[])
{
Digit digit;
cout << "initially: digit = " << digit.Value() << endl;
digit++;
cout << "postfix ++: digit = " << digit.Value() << endl;
++digit;
cout << "prefix ++: digit = " << digit.Value() << endl;

return 0;
}
The program output is:

[Session started at 2010-03-07 21:38:52 +0200.]
initially:  digit = 0
postfix ++: digit = 1
prefix ++:  digit = 2
The Debugger has exited with status 0.

The following program shows the return values from these operators:
int main (int argc, char * const argv[]) 
{
Digit digit1, digit2;
cout << "initially digit1 = " << digit1.Value() << endl;
cout << " digit2 = " << digit2.Value() << endl;
digit2 = digit1++;
cout << "postfix ++: digit1 = " << digit1.Value() << endl;
cout << " digit2 = " << digit2.Value() << endl;
digit2 = ++digit1;
cout << "prefix ++: digit1 = " << digit1.Value() << endl;
cout << " digit2 = " << digit2.Value() << endl;

return 0;
}

[Session started at 2010-03-08 23:48:15 +0200.]
initially  digit1 = 0
           digit2 = 0
postfix ++: digit1 = 1
            digit2 = 0
prefix ++:  digit1 = 2
            digit2 = 2

The Debugger has exited with status 0.

It behaves exactly as the built-in types:
#include <iostream>

int main (int argc, char * const argv[]) {

int x = 0;
int y = x++;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;

return 0;
}


run
[Switching to process 813]
Running…
x = 1
y = 0

Debugger stopped.
Program exited with status value:0.


This code (with minor changes) was taken from:
Overloading the increment and decrement operators

The main trick is a fake integer parameter for the postfix operator - it allows to distinguish the postfix and prefix versions. The postfix and prefix operators return different values - the prefix operator return the object after it has been incremented. The postfix operator returns the value before it was incremented.
So it makes sense to prefer prefix operator (preincrement), because it might performs better. The preincrement operator does not have to return the old value that must be stored in a temporary object.

"C++ Std ISO IEC 9899 1990" says about the prefix and postfix operators:

5.2.6 Increment and decrement [expr.post.incr]
1 The value obtained by applying a postfix ++ is the value that the operand had before applying the operator. [Note: the value obtained is a copy of the original value ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a complete object type. After the result is noted, the value of the object is modified by adding 1 to it, unless the object is of type bool, in which case it is set to true. [Note: this use is deprecated, see annex D. ] The result is an rvalue. The type of the result is the cv-unqualified version of the type of the operand. See also 5.7 and 5.17.
2 The operand of postfix -- is decremented analogously to the postfix ++ operator, except that the operand shall not be of type bool. [Note: For prefix increment and decrement, see 5.3.2. ]
and below:
5.3.2 Increment and decrement [expr.pre.incr]
1 The operand of prefix ++ is modified by adding 1, or set to true if it is bool (this use is deprecated). The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a completely-defined object type. The value is the new value of the operand; it is an lvalue. If x is not of type bool, the expression ++x is equivalent to x+=1. [Note: see the discussions of addition (5.7) and assignment operators (5.17) for information on conversions. ]
2 The operand of prefix -- is modified by substracting 1. The operand shall not be of type bool. The requirements on the operand of prefix -- and the properties of its result are otherwise the same as those of prefix ++. [Note: For postfix increment and decrement, see 5.2.6. ]
The practical use of the prefix and postfix operator ++ (and maybe the most important) is the input iterators in STL. The following program finds an element in the list:
#include <iostream>
#include <list>

int main (int argc, char * const argv[]) {
int a[10] = { 15, 2, 56, 78, 89, 7, 16, 45, 7, 99 };
std::list<int> myList(&a[0], &a[10]);
std::list<int>::iterator it = std::find(myList.begin(), myList.end(), 7);
if (*it == 7)
std::cout << "7 found in the list" << std::endl;
return 0;
}
Here is the program output:

[Session started at 2010-03-08 23:37:06 +0200.]
7 found in the list

The Debugger has exited with status 0.
And here is a classical istream iterator, which is used to read values from the input stream:
#include <iostream>
#include <iterator>
using namespace std;

int main () {
double value1, value2;
cout << "Please, insert two values: ";

istream_iterator<double> eos; // end-of-stream iterator
istream_iterator<double> iit (cin); // stdin iterator

if (iit!=eos)
value1=*iit;

iit++;
if (iit!=eos)
value2=*iit;

cout << value1 << "*" << value2 << "=" << (value1*value2) << endl;

return 0;
}
Postfix ++ is allows to get the next input value.
For input iterator postfix ++ operation means to step forward and return old position, the prefix ++ also means to step forward and return new position.

Saturday, March 6, 2010

Cocoa. Date and Time

This small program detects the current date:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSDate* today = [[NSDate alloc] init];
NSLog(@"today is: %@", today);

[today release];
[pool drain];
return 0;
}
In the console you'll see:
run
[Switching to process 12401 local thread 0x3f03]
Running…
2010-03-06 17:05:45.217 DayOfToday[12401:a0f] today is: 2010-03-06 17:05:45 +0200

NSDate object (today) was created and initialized with the current date and time:
NSDate* today = [[NSDate alloc] init];
And the next line prints out this information:
NSLog(@"today is: %@", today);
Same result will be here:
NSDate *today = [[NSDate alloc] init];
NSString *text = [today description];
NSLog(text);
Method description gives a string representing the date.
The following program shows to calculate other related dates:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSDate *today = [[NSDate alloc] init];
NSLog(@"Today is: %@", today);

//Number os seconds in a day:
NSTimeInterval secondsPerDay = 24 * 60 * 60;

//Calculates the date of tomorrow:
NSDate *tomorrow = [today addTimeInterval: secondsPerDay];
NSLog(@"Tomorrow is: %@", tomorrow);

//Calculates the date of yesterday:
NSDate *yesterday = [today addTimeInterval: -secondsPerDay];
NSLog(@"Yesterday is: %@", yesterday);

NSLog(@"Verify today: %@", today);

[today release];
[pool drain];
return 0;
}
There is another very simple way to create the date objects:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSString *dateString = @"2010-03-12 14:07:00 +0200";
NSDate *today = [[NSDate alloc] initWithString: dateString];
NSLog(@"Today is: %@", today);

[today release];
[pool drain];
return 0;
}
Of course, this line:
NSString *dateString = @"2010-03-12 14:07:00 +0200";
can be shorter. For example, like that:
NSDate *today = [[NSDate alloc] initWithString: @"2010-03-12 14:07:00 +0200"];
Or simply:
NSDate *today = [NSDate dateWithString: @"2010-03-12 14:07:00 +0200"];

A special class NSDateFormatter allows to format the output:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSDate *today = [[NSDate alloc] init];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle: NSDateFormatterMediumStyle];

NSLog(@"%@", [dateFormatter stringFromDate: today]);

[dateFormatter release];
[today release];
[pool drain];
return 0;
}
The output will be:

run
[Switching to process 13097 local thread 0x4003]
Running…
2010-03-06 18:19:40.752 DayOfToday[13097:a0f] Mar 6, 2010

Method compare allows to compare two NSDate objects:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSDate *d1 = [NSDate dateWithString: @"2010-03-06 01:01:01 +0200"];
NSDate *d2 = [NSDate dateWithString: @"2010-03-12 02:02:02 +0200"];

NSComparisonResult result = [d1 compare: d2];

switch (result) {
case NSOrderedAscending:
NSLog(@"Ascending (d2 is a later date than d1)");
break;

case NSOrderedDescending:
NSLog(@"Descending (d1 is a later date than d2)");
break;

case NSOrderedSame:
NSLog(@"Same (d1 and d2 is equal)");
break;
}
[pool drain];
return 0;
}
And here is a program sorting an array of dates:
#import <Foundation/Foundation.h>

NSComparisonResult dateSort(NSDate *d1, NSDate *d2, void *context) {
return [d1 compare:d2];
}

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate *today = [[NSDate alloc] init];
NSDate *tomorrow = [today addTimeInterval:secondsPerDay];
NSDate *afterTomorrow = [today addTimeInterval: 2 * secondsPerDay];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];

NSArray *array = [NSArray arrayWithObjects: tomorrow, today, afterTomorrow, nil];
[array sortedArrayUsingFunction: dateSort context:nil];
NSLog(@"Sorted:");
for(NSDate *date in array) {
NSLog(@"%@", [dateFormatter stringFromDate:date]);
}

[dateFormatter release];
[array release];
[pool drain];
return 0;
}
References:
1. Mac OS Reference Library. NSDate Class Reference.
2. Mac OS Reference Library. NSDateFormatter Class Reference.

Wednesday, March 3, 2010

Mac. 18 years old.


I found this Mac in our office today. People say that it was bought in 1992. People say that it still works.

Monday, March 1, 2010

Objective-C. Read text file.

This small program reads the text file:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSString* fileName = @"text.txt";
NSString *fileString = [NSString stringWithContentsOfFile: fileName];

NSArray *lines = [fileString componentsSeparatedByString:@"\n"];

[pool drain];
return 0;
}

How to make this program:
1. Launch Xcode
2. Menu File -> New Project -> Command Line -> Foundation Tool.
3. Put this program into main.m file.

The text file should be near the executable file. The text will be in fileString.

Of course, the standard C will work too:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
char buffer[1024];
FILE* file = fopen("text.txt", "r");
if (file != 0)
{
while(fgets(buffer, 1024, file) != NULL)
{
NSString* string = [[NSString alloc] initWithCString: buffer];
NSLog(string);
[string release];
}
fclose(file);
}
[pool drain];
return 0;
}

Cocoa. Add the controller

1. Menu File - > New Project
2. Choose Cocoa Application
3. Set the name
4. Press Finish.
5. Choose Classes.
6. Popup menu -> Add File
7. Choose Objective-C class.
8. Set the class name (for example, Controller).
9. Open Resources.
10. Open MainMenu.nib
12. Open Library (Shift + Cmd + L).
13. Find NSObject and drag it to the MainMenu.nib document.
14. Select Controller.h file.
15. Drag the file to the open MainMenu.nib document (a plus sign in a circle will appear). Release the mouse button.
16. Select the added NSObject in the MainMenu.nib.
17. Open Inspector (Shift + Cmd + I).
18. Select last page (with "i" in a circle, in the right-up corner of the Inspector).
19. In the Class text field type the Controller class name (Controller in this example).
20. Click on another field in the Inspector and check the the object (NSObject) in the resources changed the name - now it's named Controller (the class name added in safe 8).
Now add controls, add IBOutlet and IBAction...

In Xcode 3.1.3 and 3.1.4 tis scenario works fine. Known  tutorials do not explain the trick with NSObject dragged to the resources.

Destinator on iTune




Destinator v9.2 on iTune: 100% free trial application:
http://itunes.apple.com/us/app/destinator-9-for-north-america/id348119515?mt=8