Objective-C compile error: Invalid operands to binary expression - objective-c

-(void)updateCharacterStatsForArmor:(RKArmor *)armor withWeapons:(RKWeapon *)weapon withHealthEffect:(int)healtheffect
{
if (armor != nil){
self.character.health = self.character.health - self.character.armor.health + armor.health;
self.character.armor = armor;
}
else if (weapon != nil){
// The problematic line:
self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;
self.character.weapon = weapon;
}
else if (healtheffect != 0){
self.character.health = self.character.health + healtheffect;
}
else {
self.character.health = self.character.health + self.character.armor.health;
self.character.damage = *(self.character.damage + self.character.weapon.damage);
}
}
#end
The line with the error is marked in the code snippet. The error says invalid operand to binary expression int int*.
Would It be best to restart the whole thing?

You probably defined one of the damage properties you're using as an int* instead of int. Check your character and weapon classes for that. I'd suspect self.character.damage.

If the line you indicated really is the problem, it looks like you've probably declared the damage property of the character class to return int * instead of int. It's easy to make that mistake because properties that point to objects are always pointers. int, however, is not an object type, so there's usually not need to store a pointer to one in a property.
The line you say is a problem is:
self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;
But later on you have:
self.character.damage = *(self.character.damage + self.character.weapon.damage);
It looks like this second line is some kind of attempt to avoid a compiler error, but it doesn't seem to make a lot of sense. You'd only dereference the result of the addition if you were doing pointer arithmetic, but that doesn't make much sense for a property called damage.
To fix all this, take a look at your character class declaration. You'll probably see something like:
#property(...) int *damage;
Remove that * and make sure the attribute is assign, like this:
#property(assign) int damage;
Also, it's not clear how pirates are involved. Perhaps ye have been a mite hasty in makin' yer query? Arrr!

Related

Obj-c EXC_BAD_ECCESS error

I'm having a strange crash, at the 4th line below.
{
...
int exp = [[resourceCompletionReward objectAtIndex:experienceD] integerValue];
int xx = mySprite.x;
int yy = mySprite.y;
[self setupRisingText:exp withX:xx withY:yy];
...
}
-(void)setupRisingText:(int)risingValue withX:xx withY:yy {
...
}
When it tries to run the setupRising Text method it just crashes. Can't see anything wrong though?
What ever you do with xx and yy in setupRisingText::: they are treated as id (something like NSObject *, not exactly like that but similar)
So instead of int variables pointers to objects (any object, not just subclasses of NSObject) are accessed and dealt with. That is the default for any parameter without a type.
Use
-(void)setupRisingText:(int)risingValue withX:(int)xx withY:(int)yy {
...
}
instead.
BTW, if you used NSNumber you would have less of a problem here.
I am wondering, shouldn't your method look like this?
-(void)setupRisingText:(int)risingValue withX:(int)xx withY:(int)yy {
//NSLog(#"%d",risingValue+xx+yy);
}

if statement comparing integers not working in objective c

I am trying to perform logic based on the values of two integers. Here I am defining my integers, and I also have NSLog so I can see if the values are correct when I run the code:
int theHikeFlag = (int)[theNewHikeFlag objectAtIndex:(theID-1)];
NSLog(#"theHikeFlag: %#",theHikeFlag);
int fromTheDB = [self.detailItem hikeFlag];
NSLog(#"fromTheDB: %d",fromTheDB);
And here is the logic:
if (theHikeFlag==1) {
hikeString=#"You have";
}
else if (theHikeFlag==0) {
hikeString=#"You have not";
}
else {
if (fromTheDB==1) {
hikeString=#"You have";
}
else {
hikeString=#"You have not";
}
}
As an example of how this code is working. When theHikeFlag=1 and fromTheDB=0, the code bypasses the if and the else if and goes straight to the else and sets hikeString="You have not". This means that my result is irrelevant of theHikeFlag and is based on the fromTheDB integer.
Since you cannot store ints in an array, the line
(int)[theNewHikeFlag objectAtIndex:(theID-1)];
is not doing what you think it should. You need to pull the data from NSNumber, not cast to int.
int theHikeFlag = [[theNewHikeFlag objectAtIndex:(theID-1)] intValue];
The reason why the log output is correct is a bit funny: you made two mistakes in a row! First, you re-interpreted a pointer as an int, and then you let NSLog re-interpret it as an object again by adding a format specifier %# that is incompatible with int, but works fine with pointers! Since the int value contains a pointer to NSNumber, NSLog produces the "correct" output.

How to find parsing error with ParseKit framework

I was wondering if there were a way to get back how far into an assembly a PKParser has parsed before encountering a syntax error.
reference: http://parsekit.com/
I'm using a grammar that basically describes a prefix notation expression language.
For example:
given your standard prefix notation expression grammar and a string "(+ a - b c))"
I'd like to retrieve that [(,+,a] where matched, so I can give the user some idea of where to look to fix their error, but the completeMatchFor and bestMatchFor don't return anything I can use to find this info.
Ideally I'd like to say that a '(' was expected, but it's not necessary for a grammar as simple as what I'm using.
From the book mentioned as the user manual, it seemed as if I would need to create a custom parser for this, but I was hoping that maybe I'd simply missed something in the framework.
Thoughts?
Developer of ParseKit here.
There are two features in ParseKit which can be used to help provide user-readable hints describing parse errors encountered in input.
-[PKParser bestMatchFor:]
The PKTrack class
It sounds like you're aware of the -bestMatchFor: method even if it's not doing what you expect in this case.
I think the PKTrack class will be more helpful here. As described in Metsker's book, PKTrack is exactly like PKSequence except that its subparsers are required, and an error is thrown (with a helpful error message) when all of its subparsers are not matched.
So here's a grammar for your example input:
#start = '(' expr ')' | expr;
expr = ('+' | '-') term term;
term = '(' expr ')' | Word;
Any productions listed contiguously are a Sequence -- but could instead be a Track.
The benefit of changing these Sequences to be Tracks is that an NSException will be thrown with a human-readable parse error message if the input doesn't match. The downside is that you must now wrap all usages of your factory-generated parser in a try/catch block to catch these Track exceptions.
The problem currently (or before now, at least) is that the PKParserFactory never produced a parser using Tracks. Instead, it would always use Sequences.
So I've just added a new option in head of trunk at Google Code (you'll need to udpate).
#define USE_TRACK 0
in
PKParserFactory.m
It's 0 by default. If you change this define to 1, Tracks will be used instead of Sequences. So given the grammar above and invalid input like this:
(+ a - b c))
and this client code:
NSString *g = // fetch grammar above
PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
NSString *s = #"(+ a - b c))";
#try {
PKAssembly *res = [p parse:s];
NSLog(#"res %#", res);
}
#catch (NSException *exception) {
NSLog(#"Parse Error:%#", exception);
}
you will get a nice-ish human-readable error:
Parse Error:
After : ( + a
Expected : Alternation (term)
Found : -
Hope that helps.
I'm wrestling with this issue too. In order for -bestMatchFor: to be useful in identifying error conditions, there should be methods in PKAssembly's public interface indicating if there are more tokens/characters to be parsed. -completeMatchFor: is able to determine error state because it has access to the private -hasMore method. Perhaps PKAssembly's -hasMore method should be public.
I looked at PKTrack but since I want to handle errors programmatically, it wasn't useful to me.
My conclusion is I either write my own custom Track parser or I alter the framework and expose -hasMore. Are there other ways to handle errors?
Until I figure out a better way to detect errors, I've added the following to the file containing the implementation of my custom parser:
#interface PKAssembly ()
- (BOOL)hasMore;
- (id)peek;
#end
#implementation PMParser
...
#end
In my parse method:
PKAssembly* a = [PKTokenAssembly assemblyWithString:s];
PKAssembly* best = [self bestMatchFor:a];
PMParseNode* node = nil;
BOOL error = NO;
NSUInteger errorOffset = 0;
if (best == nil) // Anything recognized?
{
error = YES;
}
else
{
if ([best hasMore]) // Partial recognition?
{
PKToken* t = [best peek];
error = YES;
errorOffset = t.offset;
}
node = [best pop];
}
If an error occurred, errorOffset will contained the location of the unrecognized token.

"used struct type value where scalar is required" at .layer.position

I want to make a selection before apply one of two animations,
what I thought is: make a Point one, if my myImageView is at the Point one, then apply animationNo1, else apply animationNo2, but I got this:"used struct type value where scalar is required", at line if (myImageView.layer.position = one)
What I do? how can I fix this?
Does anyone know exactly what makes the problem happen?
CGPoint one = CGPointMake(myImageView.layer.position.x, 100);
if (myImageView.layer.position = one)
{
animationNo1
}
else
{
animationNo2
}
First of all, your if-statement will not do what you think. If you want to compare something you have to use == (ie 2 =)
and you can't compare CGPoints like this.
use
if (CGPointEqualToPoint(one, self.view.layer.position))
if (myImageView.layer.position = one) { animationNo1 }
should be
if (CGPointIsEqualToPoint(myImageView.layer.position, one)) { animationNo1 }
You used a single = meaning assignment, rather than a == for comparison. But the == wouldn't do what you wanted here anyway.
You are passing a struct (int this case position) instead of a scalar. To do what you want you need to use CGPointIsEqualToPoint:
if (CGPointEqualToPoint(one, self.view.layer.position))
Full code with corrections:
CGPoint one = CGPointMake(myImageView.layer.position.x, 100);
if (CGPointEqualToPoint(one, self.view.layer.position))
{
animationNo1
}
else
{
animationNo2
}
Also, as others have pointed out: Be careful about = vs ==. They are different. In this case you don't use == for comparison fortunately, but if you use = for other stuff it will make it true instead of checking to see if it is true.

NSArray in if statement strange behaviour

i have the following two pieces of code which i think should be identical
int temp = [[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state];
if (temp > 0)
{
NSLog(#"TEST: %d",temp);
}
if ([[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state] > 0)
{
NSLog(#"TEST: %d",temp);
}
state is just an int in the objects in the array with accessor like:
#property (assign)int state;
but when state is negative, the first version works (no output), but the second version outputs (for example) "TEST: -4" (?!)
is there any obvious reason why they might be different?
Since -objectAtIndex: returns an id, the compiler will not be able to know what -state should return. If you did not import the header that declares state first, or if the property state has ambiguous declaration (e.g. another class has declared #property(retain) id state before your class is imported), then the compiler may infer a wrong type for -state.
If it infers id, for instance, as all pointers are nonnegative, -4 will be implicitly viewed as 0xFFFFFFFC, thus the > 0 condition passes.
But for code 1, you have specified that temp is an int, so even if the return value of the call is 0xFFFFFFFC, it will be cast back to a signed value (-4), hence the condition fails.
The safest approach is to specify the type of -objectAtIndex:, i.e.
Foo* obj = [[myArray objectAtIndex:iIndex] objectAtIndex:jIndex];
if (obj.state > 0) {
...
I I understand it right, and the two if's are NOT in the same method, then the second one prints an unassigned variable. the fix should go like this:
if ((temp = [[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state]) > 0)
{
NSLog(#"TEST: %d",temp);
}