stackoverflow when try to pass variable to bool function - objective-c

i create a counting timer(on a label) and a variable that contain the label integer value(named count). also i create a function that check if my number is 7, divided by 7 or contain 7. when i try to pass my count value to the check function my app is stack. i try for a long time to find why the stack overflow is occur but i didn't success. how can i solve it?
here is my code:
-(IBAction)start:(id)sender
{
timer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(updateTimer:) userInfo:nil repeats:YES];
MainInt = 0;
numbersTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(countup) userInfo:nil repeats:YES];
}
-(void)countup
{
MainInt += 1;
numbersLabel.text = [NSString stringWithFormat:#"%i", MainInt];
count = numbersLabel.text.intValue;
NSLog(#"num: %d", count);
if ([self checknum:(count) == false]) {
NSLog(#"BOOM");
}
}
-(BOOL)checknum:(int)number
{
while (number<10)
{
if(number ==7)
{
NSLog(#"boom, i=%d", number);
return true;
}
}
while (number>=10 && number<1000)
{
if(number % 7 == 0)
{
NSLog(#"boom i=%d", number);
return true;
}
if([self revese:(number)])
{
NSLog(#"boom reverse num = %d", number);
return true;
}
}
return false;
}
-(BOOL) revese:(int)number
{
if(number < 10 && number != 7)
return false;
if(((number % 10) == 7) || ((number / 10) == 7))
return true;
else {
[self revese:(number / 10)];
}
return false;
}
thanks!

The statement
if ([self checknum:(count) == false]) {
NSLog(#"BOOM");
}
is nonsense. You are effective asking
BOOL isLessThanOne = (count < 1);
if ([self checksum:isLessThanOne]) {
NSLog(#"BOOM");
}
change this for
if ([self checksum:count] == NO) {
NSLog(#"BOOM");
}

There are lots of issues but the first ones are these:
while (number<10)
//
while (number>=10 && number<1000)
You want an if/else type conditional statement here. The way you have it now, since you never adjust the value of number, you will get caught in an infinite loop if the strict conditions you are testing later in the code are not met. Something more like:
if(number<10){
// do some tests
} else if (number<1000){
// do some other tests
}
There are other issues but those are a start.

It is very hard to tell as I cannot really see what you are doing, but if you have stack overflow, it is very likely that your problem is the function revese which is recursive. I would bet that you have a certain value being passed to revese that is causing it to be called over and over again based on some of the unusual logic you are using in your conditional statements. You should really step through this function carefully with your debugger to identify why this is happening.

Related

Recursive function with block in Objective C

I've got a function with completion block, and which in some cases calls itself recursively until has the expected result.
I'm getting errors in release, probably because it has different memory management in release.
Anyway I'm asking what should I do to make it work in release as in debug.
I've found some links about declaring a block variable weak, and another one strong, and then assign the block to both of them. However I'm in difficulty to understand well how to apply it to my code.
Here's the code:
-(void) getBitmapFromXObject: (OCPdfXObject *) xobj completion:(void(^)(NSData * data))completion{
__block BOOL hasAlreadyCompleted = false;
if (xobj.type == OCPdfXObjectType_Form) {
OCPdfXObjectForm * formxboj = (OCPdfXObjectForm *)xobj;
OCPdfDictionary * res = formxboj.resources.xObject;
if (res != nil) {
for (CBKeyValuePair * key in res) {
OCPdfXObject* childXObjc = [OCPdfXObject createFromObject:key.value];
if (!childXObjc) {
continue;
}
[self getBitmapFromXObject:childXObjc completion:^(NSData *data) {
if (data != nil) {
hasAlreadyCompleted = true;
}
}];
}
}
}
if (xobj.type == OCPdfXObjectType_Image) {
OCPdfImage* imagexobj = (OCPdfImage *)xobj;
if (imagexobj.colorSpace != OCPdfColorSpace_DeviceRGB) {
completion(nil);
hasAlreadyCompleted = true;
}
[self getBitmapFromImage:imagexobj withCompletion:^(NSData *data) {
NSData *uiImage = data;
completion(uiImage);
hasAlreadyCompleted = true;
}];
}
if (!hasAlreadyCompleted) {
completion(nil);
}
}

Annoying "expression result unused" warning

This is for a stupidly simple animation but I keep getting this annoying "expression result unused" warning. Code is as follows:
-(IBAction)thingOneTapped:(UIGestureRecognizer *)sender{
if ((isLevel = YES)) {
thingOneEnded = YES;
goingToThingOne = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(otherThingToOne) userInfo:nil repeats:YES];
x = 11;
y = 118;
}
else (isLevel = NO); {
[self viewDidLoad];
}
}
-(void)otherThingToOne{
if ((isLevel = YES) && (isLevelOne = YES)) {
if ((x > 0) && (y > 0)) {
otherThing.center = CGPointMake(otherThing.center.x - .5, otherThing.center.y - 5.35);
x = x - .5;
y = y - 5.35;
}
else ((x < 0) && (y < 0)); {
[self levelOneDefault];
// EVIL WARNING IS RIGHT HERE IN THE ELSE PART
}
}
For checking equality you need to use == (i.e. Two equals signs) that's why you're getting the error. Also, your code will not work as you expect at the moment.
As mentioned by others.
Instead of using if(someBool == YES) just use if(someBool). And instead of if(someBool == NO) just use if(!someBool).
The reason it will not work at the moment is because (I think but not 100% on this) if(someBool = NO) will first set someBool to NO and then evaluate the condition which will always be if(NO) which will never enter the of block.
I think. But not sure about this as I haven't tested it.
You can also use like that without checking == operator, also it will be more faster:-
if ((isLevel) && (isLevelOne))

`resolve_dtor() `Parentheses Algorithm

I'm running into a frustrating problem with a parentheses completion algorithm. The math library I'm using, DDMathParser, only processes trigonometric functions in radians. If one wishes to use degrees, they must call dtor(deg_value). The problem is that this adds an additional parenthesis that must be accounted for at the end.
For example, the math expression sin(cos(sin(x))) would translate to sin(dtor(cos(dtor(sin(dtor(x))) in my code. However, notice that I need two additional parentheses in order for it to be a complete math expression. Hence, the creation of resolve_dtor().
Here is my attempted solution, the idea was to have 0 signify a left-paren, 1 signify a left-paren with dtor(, and 2 signify a right-paren thus completing either 0 or 1.
- (NSMutableString *)resolve_dtor:(NSMutableString *)exp
{
NSInteger mutable_length = [exp length];
NSMutableArray *paren_complete = [[NSMutableArray alloc] init]; // NO/YES
for (NSInteger index = 0; index < mutable_length; index++) {
if ([exp characterAtIndex:index] == '(') {
// Check if it is "dtor()"
if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:#"dtor"]) {
//dtor_array_index = [self find_incomplete_paren:paren_complete];
[paren_complete addObject:#1];
}
else
[paren_complete addObject:#0]; // 0 signifies an incomplete parenthetical expression
}
else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {
// Check if "dtor("
if (![self elem_is_zero:paren_complete]) {
// Add right-paren for "dtor("
[paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:#2];
[exp insertString:#")" atIndex:index + 1];
mutable_length++;
index++;
}
else
[paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:#2];
}
else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:#2]) {
// We know that everything is complete
[paren_complete removeAllObjects];
}
}
return exp;
}
- (bool)check_dtor:(NSMutableString *)exp
{
NSMutableArray *paren_complete = [[NSMutableArray alloc] init]; // NO/YES
for (NSInteger index = 0; index < [exp length]; index++) {
if ([exp characterAtIndex:index] == '(') {
// Check if it is "dtor()"
if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:#"dtor"]) {
//dtor_array_index = [self find_incomplete_paren:paren_complete];
[paren_complete addObject:#1];
}
else
[paren_complete addObject:#0]; // 0 signifies an incomplete parenthetical expression
}
else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {
// Check if "dtor("
if (![self elem_is_zero:paren_complete]) {
// Indicate "dtor(" at index is now complete
[paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:#2];
}
else
[paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:#2];
}
else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:#2]) {
// We know that everything is complete
[paren_complete removeAllObjects];
}
}
// Now step back and see if all the "dtor(" expressions are complete
for (NSInteger index = 0; index < [paren_complete count]; index++) {
if ([[paren_complete objectAtIndex:index] isEqualToValue:#0] || [[paren_complete objectAtIndex:index] isEqualToValue:#1]) {
return NO;
}
}
return YES;
}
It seems the algorithm works for sin((3 + 3) + (6 - 3)) (translating to sin(dtor((3 + 3) x (6 - 3))) but not sin((3 + 3) + cos(3)) (translating to sin(dtor((3 + 3) + cos(dtor(3)).
Bottom Line
This semi-solution is most likely overcomplicated (one of my common problems, it seems), so I was wondering if there might be an easier way to do this?
Solution
Here is my solution to #j_random_hacker's pseudo code he provided:
- (NSMutableString *)resolve_dtor:(NSString *)exp
{
uint depth = 0;
NSMutableArray *stack = [[NSMutableArray alloc] init];
NSRegularExpression *regex_trig = [NSRegularExpression regularExpressionWithPattern:#"(sin|cos|tan|csc|sec|cot)" options:0 error:0];
NSRegularExpression *regex_trig2nd = [NSRegularExpression regularExpressionWithPattern:#"(asin|acos|atan|acsc|asec|acot)" options:0 error:0];
// need another regex for checking asin, etc. (because of differing index size)
NSMutableString *exp_copy = [NSMutableString stringWithString:exp];
for (NSInteger i = 0; i < [exp_copy length]; i++) {
// Check for it!
if ([exp_copy characterAtIndex:i] == '(') {
if (i >= 4) {
// check if i - 4
if ([regex_trig2nd numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 4, 4)] == 1) {
[stack addObject:#(depth)];
[exp_copy insertString:#"dtor(" atIndex:i + 1];
depth++;
}
}
else if (i >= 3) {
// check if i - 3
if ([regex_trig numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 3, 3)] == 1) {
[stack addObject:#(depth)];
[exp_copy insertString:#"dtor(" atIndex:i + 1];
depth++;
}
}
}
else if ([exp_copy characterAtIndex:i] == ')') {
depth--;
if ([stack count] > 0 && [[stack objectAtIndex:[stack count] - 1] isEqual: #(depth)]) {
[stack removeObjectAtIndex:[stack count] - 1];
[exp_copy insertString:#")" atIndex:i + 1];
}
}
}
return exp_copy;
}
It works! Let me know if there are any minor corrections that would be good to add or if there is a more efficient approach.
Haven't tried reading your code, but I would use a simple approach in which we scan forward through the input string writing out a second string as we go while maintaining a variable called depth that records the current nesting level of parentheses, as well as a stack that remembers the nesting levels that need an extra ) because we added a dtor( when we entered them:
Set depth to 0.
For each character c in the input string:
Write it to the output.
Is c a (? If so:
Was the preceding token sin, cos etc.? If so, push the current value of depth on a stack, and write out dtor(.
Increment depth.
Is c a )? If so:
Decrement depth.
Is the top of the stack equal to depth? If so, pop it and write out ).
DDMathParser natively supports using degrees for trigonometric functions and will insert the relevant dtor functions for you. It'll even automatically insert it by doing:
#"sin(42°)"
You can do this by setting the angleMeasurementMode on the relevant DDMathEvaluator object.

Efficient way of checking the content of every NSDictionary in NSArray

In my app I'me getting responses from the server and I have to check that I don't create duplicate objects in the NSArray which contains NSDictionaries. Now to check if the objects exists I do this:
for (int i = 0; i < appDelegate.currentUser.userSiteDetailsArray.count; i++){
NSDictionary *tmpDictionary = [appDelegate.currentUser.userSiteDetailsArray objectAtIndex:i];
if ([[tmpDictionary valueForKey:#"webpropID"] isEqualToString:tmpWebproperty.identifier]){
needToCheck = NO;
}
if (i == appDelegate.currentUser.userSiteDetailsArray.count - 1 && ![[tmpDictionary valueForKey:#"webpropID"] isEqualToString:tmpWebproperty.identifier] && needToCheck){
// It means it's the last object we've iterated through and needToCheck is still = YES;
//Doing stuff here
}
}
I set up a BOOL value because this iteration goes numerous times inside a method and I can't use return to stop it. I think there is a better way to perform this check and I would like to hear your suggestions about it.
BOOL needToCheck = YES;
for (int i = 0; i < appDelegate.currentUser.userSiteDetailsArray.count; i++){
NSDictionary *tmpDictionary = [appDelegate.currentUser.userSiteDetailsArray objectAtIndex:i];
if ([[tmpDictionary valueForKey:#"webpropID"] isEqualToString:tmpWebproperty.identifier]){
needToCheck = NO;
break;
}
}
if (needToCheck) {
//Doing stuff here
}
But, as others have said, you can maybe keep a "summary" in a separate NSSet that you check first, vs spinning through all the dictionaries.
NSDictionary *previousThing = nil;
for (NSDictionary *thing in appDelegate.currentUser.userSiteDetailsArray) {
if ([thing[#"webpropID"] isEqualToString:newWebPropertyIdentifier]) {
previousThing = thing;
break;
}
}
if (previousThing == nil) {
// no previous thing
} else {
// duplicate
}

Problem with recursive objective-c void-method

thats my first question here and i hope someone can help me.
I´m new at the iPhone programming and want to try an easy app...
It´s an SudokuSolver which is working with an recursive Method. In JAVA this code is making no problems, but in Objective-C the code isn´t stopping when Sudoku is solved. It´s still trying to solve the Sudoku and stops later.
Anyone an idea?!
Here´s the code.
- (SudokuSolver *) initWithField: (int[9][9]) field {
self = [super init];
if(self) {
for (int i=0; i<9; i++) {
for (int j=0; j<9; j++) {
sudokuField[i][j] = field[i][j];
if (field[i][j]) {
sudokuFieldStatic[i][j] = 1;
} else {
sudokuFieldStatic[i][j] = 0;
}
}
}
}
return self;
}
- (void) solve {
[self solveFieldAtRow:0 andCol:0];
}
- (void) solveFieldAtRow: (int) row andCol: (int) col {
if (row > 8) {
return;
} else {
while (sudokuField[row][col] != 0) {
if (++col > 8) {
col = 0;
row++;
if (row > 8) {
return;
}
}
}
for (int num=1; num<10; num++) {
if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
sudokuField[row][col] = num;
[self showFieldInConsole:0];
if (col < 8) {
[self solveFieldAtRow:row andCol:col+1];
} else {
[self solveFieldAtRow:row+1 andCol:0];
}
}
}
sudokuField[row][col] = 0;
}
}
The code isn't stopping when the puzzle is solved because you don't check whether the puzzle is solved after the recursive call. So even if the recursive call found a solution, the code just continues on even after finding a solution until it has tried every possibility.
Since you say you have Java code that works, I suggest you compare the logic of the Java program versus this code. You'll probably find the Java code does include such a test.
Edit From your comment above, I see that you won't find such a test in your Java code, because there you are abusing exceptions to "return" from the recursion when a solution is found. The proper way is to have each recursive call return a true value if it found a solution and false if it didn't. And then each step should check if its child call succeeded, and itself return success if so. Something like this:
- (BOOL) solveFieldAtRow: (int) row andCol: (int) col {
if (row > 8) {
// reached the end, so it must have succeeded
return YES;
} else {
while (sudokuField[row][col] != 0) {
if (++col > 8) {
col = 0;
row++;
if (row > 8) {
// reached the end, so it must have succeeded
return YES;
}
}
}
for (int num=1; num<10; num++) {
if ([self checkRow:row forNumber:num] && [self checkCol:col forNumber:num] && [self checkFieldAtRow:row andCol:col forNumber:num]) {
sudokuField[row][col] = num;
[self showFieldInConsole:0];
BOOL result;
if (col < 8) {
result = [self solveFieldAtRow:row andCol:col+1];
} else {
result = [self solveFieldAtRow:row+1 andCol:0];
}
if (result) {
// Our child call succeeded, so we pass that back up
// the stack.
return YES;
}
}
}
sudokuField[row][col] = 0;
// If we get here, we could not find a solution. Return failure
// back up the stack.
return NO;
}
}