Counter in while within while not working - iphone

I'm having a strange problem with the following code:
int c = [whatsNewArray1 count];
int t = [dames count];
int i = 0;
int o= 0;
NSMutableArray *finalWhatsNew = [[NSMutableArray alloc]init];
while (i<c){
NSLog(#"teller array %i", i);
while(t>o){
NSLog(#"dames %i", i);
if ([[[dames objectAtIndex:o] productId] isEqualToString:[whatsNewArray1 objectAtIndex:i]]){
[finalWhatsNew addObject:[dames objectAtIndex:o]];
NSLog(#"inner dames%i", i);
}
o++;
}
i++;
}
This code retrieves al the entries from the "dames" array which are stated in the "finalWhatsNew" array. Problem with this is that the if is only get called the first time.
To make it a little bit clearer, the whole code is working fine, but as soon "i" is ++ to 1. the if statement isn't called. It looks like ios i canceling it out after the first time for performance reason or somethins like that. Anybody has any ideas?
Thnx!!!

After inner loop is finished for the first time the o counter is equal to array's count and so it won't enter the loop again. To make it work you must reset o counter on each iteration of the outer loop:
while (i<c){
o = 0;
while (t > o)
...
Edit: For clearer code (and probably better performance) you can use fast enumeration instead of usual for/while loops:
for (NSString *searchId in whatsNewArray1){
for (YourObject *obj in dames){
if ([[obj productId] isEqualToString:searchId])
[finalWhatsNew addObject: obj];
}
}
Edit2: Also you can eliminate 2nd loop by using NSPredicate to filter your array:
for (NSString *searchId in whatsNewArray1){
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"productId == %#",searchId];
[finalWhatsNew addObjectsFromArray:[dames filteredArrayUsingPredicate:predicate]];
}

As Vladimir says, you need to reset o after each iteration of the outer loop. Ideally you switch to for-statements here, as they fit what you're doing exactly:
for (int i=0; i<c; ++i) {
// ...
for (int o=0; o<t; ++o) {
// ...

Related

CS50 pset 3: Tideman sort_pairs function

I need some assistance in understanding the logic behind this function. This is my current sort_pairs function in Tideman:
// Sort pairs in decreasing order by the strength of victory
void sort_pairs(void)
{
qsort(pairs, pair_count, sizeof(pair), compare);
return;
}
// Function for sort_pairs
int compare(const void *a, const void *b)
{
const pair *p1 = (const pair *) a;
const pair *p2 = (const pair *) b;
if (p1->winner < p2->winner)
{
return -1;
}
else if (p1->winner > p2->winner)
{
return 1;
}
else
{
return 0;
}
}
This does not clear check50 and I looked online to find how to approach this problem. It seems that most functions compare the values from the preferences array instead (eg preferences[pairs[i].winner][pairs[i].loser]) . My previous functions vote, record_preferences, and add_pairs all clear check50. I have not advanced beyond sort_pairs yet.
Why can't I compare the strength of victory directly from the pairs array instead since I already have the data stored there?
You don't need to make this so complex, you can use your own sorting here. Let's try a simple insertion sort-
void sort_pairs()
{
pair temp;
for (int i = 1, j; i < pair_count; i++)
{
temp = pairs[i];
j = i - 1;
for (; j >= 0 && preferences[pairs[j].winner][pairs[j].loser] < preferences[temp.winner][temp.loser]; j--)
{
pairs[j + 1] = pairs[j];
}
pairs[j + 1] = temp;
}
}
The pair struct looks like-
typedef struct
{
int winner;
int loser;
}
pair;
Explanation:-
We go through each pair of elements inside the pairs array - starting at 1 since I'm going to compare with the previous element (j = i - 1)
Now we check all the previous elements from the current element and compare them with the key - preferences[pairs[INDEX].winner][pairs[INDEX].loser]
This is the key you should be sorting by. preferences[WINNER_ID][LOSER_ID] means the amount of people that prefer WINNER_ID over LOSER_ID.
And that's pretty much it!, it's simply a insertion sort but the key is the important part.

Atomically setting a variable without comparing first

I've been reading up on and experimenting with atomic memory access for synchronization, mainly for educational purposes. Specifically, I'm looking at Mac OS X's OSAtomic* family of functions. Here's what I don't understand: Why is there no way to atomically set a variable instead of modifying it (adding, incrementing, etc.)? OSAtomicCompareAndSwap* is as close as it gets -- but only the swap is atomic, not the whole function itself. This leads to code such as the following not working:
const int N = 100000;
void* threadFunc(void *data) {
int *num = (int *)data;
// Wait for main thread to start us so all spawned threads start
// at the same time.
while (0 == num) { }
for (int i = 0; i < N; ++i) {
OSAtomicCompareAndSwapInt(*num, *num+1, num);
}
}
// called from main thread
void test() {
int num = 0;
pthread_t threads[5];
for (int i = 0; i < 5; ++i) {
pthread_create(&threads[i], NULL, threadFunc, &num);
}
num = 1;
for (int i = 0; i < 5; ++i) {
pthread_join(threads[i], NULL);
}
printf("final value: %d\n", num);
}
When run, this example would ideally produce 500,001 as the final value. However, it doesn't; even when the comparison in OSAtomicCompareAndSwapInt in thread X succeeds, another thread Y can come in set the variable first before X has a chance to change it.
I am aware that in this trivial example I could (and should!) simply use OSAtomicAdd32, in which case the code works. But, what if, for example, I wanted to set a pointer atomically so it points to a new object that another thread can then work with?
I've looked at other APIs, and they seem to be missing this feature as well, which leads me to believe that there is a good reason for it and my confusion is just based on lack of knowledge. If somebody could enlighten me, I'd appreciate it.
I think that you have to check the OSAtomicCompareAndSwapInt result to guarantee that the int was actually set.

Using Block with objectAtIndex method of NSArray

Here is the code:
TrailLayer * layer = (TrailLayer*)[_layers objectAtIndex:(int)^{
if (_segmentNumber < [_segmentArray count]) {
return _segmentNumber;
} else {
return _segmentNumber - 1;
}
}];
what is the problem here? Here, all the _Variables are IVARs. I am first time using Blocks, can someone help me identifying this problem. Its giving EXC_BAD_INSTRUCTION here.
Thanks.
Try this code, First write block to get the index number, and use that number to retrieve value from array
int (^segmentIndex)(int) = ^(int segmentNumber){
if (segmentNumber < [_layers count]) {
return segmentNumber;
} else {
return segmentNumber - 1;
}
};
NSLog(#"Trail Layer %#", [_layers objectAtIndex:segmentIndex(_segmentNumber)]);
TrailLayer * layer = (TrailLayer*)[_layers objectAtIndex:segmentIndex(_segmentNumber)];
A block is a runnable thing like a function, basically a piece of code that you can store, pass around, and run later (or not). You want to pass an integer to objectAtIndex:, so passing a block makes absolutely no sense whatsoever.
What you could have meant to do was run the block, and then pass its result to objectAtIndex:. In that case, you would have to run the block:
TrailLayer * layer = [_layers objectAtIndex:^{
if (_segmentNumber < [_segmentArray count]) {
return _segmentNumber;
} else {
return _segmentNumber - 1;
}
}()]; // <-- run the block
However, defining a block (which is a full-fledged object, and does a lot of fancy stuff) just to run it immediately is kinda silly. If you want to just be able to use a piece of code as an expression, you could use the "statement expressions" language extension supported by both GCC and LLVM:
TrailLayer * layer = [_layers objectAtIndex:({
int result;
if (_segmentNumber < [_segmentArray count]) {
result = _segmentNumber;
} else {
result = _segmentNumber - 1;
}
result;
})];
But really you should just do a regular C conditional expression in this case:
TrailLayer * layer = [_layers objectAtIndex:
_segmentNumber < [_segmentArray count] ?
_segmentNumber : _segmentNumber - 1];

While loop not stopping with given criteria

Im having a bit of a problem with this while loop. I keep getting a crash because it continues to execute the loop even when it has found the object and supposedly increased the int.
Any ideas I have plenty of other loops set up in a similar way and they all work fine.
int possible = 0;
while (possible < [possibleAthetes count]) {
if ([[[possibleAthetes objectAtIndex:possible]valueForKey:#"ID"]intValue] == [self.athleteID intValue]) {
[possibleAthetes removeObjectAtIndex:possible];
possible = [possibleAthetes count] ;
}
possible ++;
}
You are incrementing possible even when you remove an object. Break out of the loop.
If you need to get rid of multiple athletes, leave out the break(No need to increment because of the removed object).
int possible = 0;
while (possible < [possibleAthetes count]) {
BOOL criteriaMatch = ([[[possibleAthetes objectAtIndex:possible]valueForKey:#"ID"]intValue] == [self.athleteID intValue]);
if (criteriaMatch){
[possibleAthetes removeObjectAtIndex:possible];
break;
} else {
possible++;
}
}

Where to locate srandom (time(null))

I'm using function random()%some integer in a method of one of my app's classes and I have no idea where to put srandom (time (NULL)) to generate not pseudorandom but true random numbers. I have already put it in viewDidLoad and viewWillAppear but it doesn't help.
- (NSMutableDictionary *)getUsersFromServer
{
srand(time(NULL));
//here we're getting list of users from the server
NSMutableDictionary * users = [[[NSMutableDictionary alloc] init] autorelease];
for (int i = 0;i < 19;i++)
{
int wins = rand()%100; float f_wins = (float)wins;
int losses = rand()%100; float f_losses = (float)losses;
int withdr = rand()%100; float f_withdr = (float)withdr;
float win_per = f_wins / ((f_wins + f_losses + f_withdr) / 100.0);
[userresults setArray:[NSMutableArray arrayWithObjects:[NSNumber numberWithInt:wins],
[NSNumber numberWithInt:losses],
[NSNumber numberWithInt:withdr],
[ NSNumber numberWithFloat:win_per],
nil]];
[users setObject:userresults forKey:[NSString stringWithFormat:#"Pfeffer ID %i",i]];
}
[userresults release];
return users;
}
something like this... the code looks awful but its sense is understandable. rand() produces same numbers for each loop iteration. If I use arc4random() it changes nothing. still same numbers
I don't think this is a issue about randomness or seeds at all, I don't use Objective-C, but ...
// for each loop iteration:
[userresults setArray: .... ] // <-- modify object known as userresults?
[users setObject:userresults ....] // <-- isn't that the SAME userresults object?
That is, I believe you have the same object multiple times in users: shouldn't a new result object be created each iteration?
Also, see srand() — why call it only once? -- for why using srand at the top of this method might not be ideal. Alternatively, this post recommends arc4random as it does not require a manual seeding and is a "stronger" pseudo-random generator.
Happy coding.