Amazon.com Widgets Fraction Calculator operators aren't working
Welcome, Guest. Please login or register.
Did you miss your activation email?
May 24, 2013, 03:35:47 PM
Home Help Search chat Login Register   
News: Read this please.The Great Kangaroo Escape Looking for reviews of the 4th ed on Amazon!   Twitter:  @skochan
                     

+  Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
|-+  Programming in Objective-C, 4th edition
| |-+  Chapter 21
| | |-+  Fraction Calculator operators aren't working
Pages: [1]   Go Down
Print
Author Topic: Fraction Calculator operators aren't working  (Read 732 times)
es7
Newbie
*
Posts: 3


Email




« on: August 04, 2012, 07:05:46 PM »

Hello, I do not receive any errors beforehand, but when I try to press an operator the app crashes and it takes me to a screen which i have attached below. Help would be greatly appreciated I just can't seem to catch the mistake!  Smiley

ViewController.h
Code: (Objective-C)
#import <UIKit/UIKit.h>
#import "Calculator.h"

@interface ViewController : UIViewController

@property (strong, nonatomic) IBOutlet UILabel *display;

-(void) processDigit: (int) digit;
-(void) processOP: (char) theOp;
-(void) storeFracPart;

//Numeric keys

-(IBAction) clickDigit: (UIButton *) sender;

//Arithmetic operation keys

-(IBAction) clickPlus;
-(IBAction) clickMinus;
-(IBAction) clickMultiply;
-(IBAction) clickDivide;

//Misc keys

-(IBAction) clickOver;
-(IBAction) clickEquals;
-(IBAction) clickClear;

@end

ViewController.m
Code: (Objective-C)
#import "ViewController.h"

@implementation ViewController
{  
    char op;
    int currentNumber;
    BOOL firstOperand, isNumerator;
    Calculator *myCalculator;
    NSMutableString *displayString;
}  

@synthesize display;

- (void)viewDidLoad
{
    firstOperand = YES;
    isNumerator = YES;
    displayString = [NSMutableString stringWithCapacity:40];
    myCalculator = [[Calculator alloc] init];
}


-(void) processDigit: (int) digit
{
    currentNumber = currentNumber * 10 + digit;
    
    [displayString appendString: [NSString stringWithFormat:@"%i", digit]];
    display.text = displayString;
}

-(IBAction)clickDigit:(UIButton *)sender
{
    int digit = sender.tag;
    
    [self processDigit:digit];
}

-(void) processOP:(char)theOp
{
    NSString *opStr;
    
    op = theOp;
    
    switch (theOp) {
        case '+':
            opStr = @" + ";
            break;
            
        case '-':  
            opStr = @" - ";
            break;
            
        case '*':
            opStr = @" x ";
            break;
            
        case '/':
            opStr = @" ÷ ";
            break;
    }
    
    [self storeFracPart];
    firstOperand = NO;
    isNumerator = YES;
    
    [displayString appendString: opStr];
    display.text = displayString;
}

-(void) storeFracPart
{
    if (firstOperand){
        
        if (isNumerator) {
            myCalculator.operand1.numerator = currentNumber;
            myCalculator.operand1.denominator = 1;
        }
        
        else {
            myCalculator.operand1.denominator = currentNumber;
        }
    }
    
    else if (isNumerator){
        myCalculator.operand2.numerator = currentNumber;
        myCalculator.operand2.denominator = 1;
            
    }
    
    else{
        myCalculator.operand2.numerator = currentNumber;
        firstOperand = YES;
    }
    
    currentNumber = 0;    
}

-(IBAction) clickOver
{
    [self storeFracPart];
    isNumerator = NO;
    [displayString appendString: @"/"];
    display.text = displayString;
}

//Arithmetic operation keys
 
-(IBAction) clickPlus
{
    [self processOP:'+'];
}

-(IBAction) clickMinus
{
    [self processOP:'-'];
}

-(IBAction) clickMultiply
{
    [self processOP:'*'];
}

-(IBAction) clickDivide
{
    [self processOP:'/'];
}

// Misc keys

-(IBAction) clickEquals
{
    if(firstOperand == NO)
    {
        [self storeFracPart];
        [myCalculator performOperation: op];
        
        [displayString appendString:@" = "];
        [displayString appendString:[myCalculator.accumulator convertToString]];
        display.text = displayString;
        
        currentNumber = 0;
        isNumerator = YES;
        firstOperand = YES;
        [displayString setString: @""];
    }
}

-(IBAction) clickClear
{
    isNumerator = YES;
    firstOperand = YES;
    currentNumber = 0;
    [myCalculator clear];
    
    [displayString setString:@""];
    display.text = displayString;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end


Fraction.h
Code: (Objective-C)
#import <UIKit/UIKit.h>

@interface Fraction : NSObject

@property int numerator, denominator;

-(void) print;
-(void) setTo: (int) n over: (int) d;
-(Fraction *) add: (Fraction *) f;
-(Fraction *) subtract: (Fraction *) f;
-(Fraction *) multiply: (Fraction *) f;
-(Fraction *) divide: (Fraction *) f;
-(void) reduce;
-(double) convertToNum;
-(NSString *) convertToString;

@end

Fraction.m
Code: (Objective-C)
#import "Fraction.h"

@implementation Fraction

@synthesize numerator, denominator;

-(void) setTo:(int)n over:(int)d
{
    numerator = n;
    denominator = d;
}

-(void) print
{
    NSLog(@"%i/%i", numerator, denominator);
}

-(double) convertToNum
{
    if (denominator != 0)
    {
        return (double) numerator/denominator;
    }
    else
    {
        return NAN;
    }
}

-(NSString *) convertToString
{
    if (numerator == denominator)
    {
        if (numerator == 0)
        {
            return @"0";
        }
        
        else
        {
            return @"1";
        }
    }
    
    else if (denominator == 1)
    {
        return [NSString stringWithFormat: @"%i", numerator];
    }

    else
    {
        return [NSString stringWithFormat: @"%i/%i", numerator, denominator];
    }
}


// add a fraction to the receiver

-(Fraction *) add: (Fraction *) f
{
    // To add two fractions
    // a/b + c/d = ((a*d) + (b*c)) / (b*d)
    
    //result will store the result of the addition
    Fraction *result = [[Fraction alloc] init];
    
    result.numerator = numerator * f.denominator + denominator * f.numerator;
    
    result.denominator = denominator * f.denominator;
    
    [result reduce];
    return result;
}

-(Fraction *) subtract:(Fraction *)f
{
    // a/b - c/d = ((a*d) - (b*c)) / (b*d)
    
    Fraction *result = [[Fraction alloc] init];
    
    result.numerator = numerator * f.denominator - denominator * f.numerator;
    
    result.denominator = denominator * f.denominator;
    
    [result reduce];
    return result;
}

-(Fraction *) multiply:(Fraction *)f
{
    Fraction *result = [[Fraction alloc] init];
    
    result.numerator = numerator * f.numerator;
    
    result.denominator = denominator * f.denominator;
    
    [result reduce];
    return result;
}

-(Fraction *) divide:(Fraction *)f
{
    Fraction *result = [[Fraction alloc] init];
    
    result.numerator = numerator * f.denominator;
    
    result.denominator = denominator * f.numerator;
    
    [result reduce];
    return result;
}

-(void) reduce
{
    int u = numerator;
    int v = denominator;
    int temp;
    
    if (u == 0)
    {
        return;
    }
    
    else if (u < 0)
    {
        u = -u;
    }

    while (v != 0)
    {
        temp = u % v;
        u = v;
        v = temp;
    }

    numerator /= u;
    denominator /= u;
}


Calculator.h
Code: (Objective-C)
#import <UIKit/UIKit.h>
#import "Fraction.h"

@interface Calculator : NSObject

@property (strong, nonatomic) Fraction *operand1, *operand2, *accumulator;

-(Fraction *) performOperation: (char) op;
-(void) clear;

@end

Calculator.m
Code: (Objective-C)
#import "Calculator.h"

@implementation Calculator

@synthesize operand1, operand2, accumulator;

-(id) init
{
    self = [super init];
    
    if(self)
    {
        operand1 = [[Fraction alloc] init];
        operand2 = [[Fraction alloc] init];
        accumulator = [[Fraction alloc] init];
    }
    
    return self;
}

-(void) clear
{
    accumulator.numerator = 0;
    accumulator.denominator = 0;
}

-(Fraction *) performOperation:(char)op
{
    Fraction *result;
    
    switch (op) {
        case '+':
            result = [operand1 add: operand2];
            break;
            
        case '-':
            result = [operand1 subtract: operand2];
            break;
            
        case '*':
            result = [operand1 multiply: operand2];
            break;
            
        case '/':
            result = [operand1 divide: operand2];
            break;
    }
    
    accumulator.numerator = result.numerator;
    accumulator.denominator = result.denominator;
    
    return accumulator;
}

@end
« Last Edit: August 05, 2012, 02:52:32 AM by es7 » Logged
fujilla
Global Moderator
Sr. Member
*****
Posts: 270


WWW




« Reply #1 on: August 05, 2012, 08:26:33 AM »

Unfortunately your screenshot does not help, with regards to exactly what is wrong.

Do not not get any messages in the error console?

Seeing as the app crashes on tapping on a button, I would say that it is trying to invoke a method which does not exist (which will probably be shown in the error console).

Nick
http://myfirstiphoneapp.co.uk
http://easyintervalsapp.co.uk
Logged
es7
Newbie
*
Posts: 3


Email




« Reply #2 on: August 05, 2012, 01:25:45 PM »

Yes, it displays this message:

2012-08-05 12:50:25.536 Fraction_Calculator[603:f803] -[ViewController clickPlus:]: unrecognized selector sent to instance 0x6d4fd30
2012-08-05 12:50:25.538 Fraction_Calculator[603:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ViewController clickPlus:]: unrecognized selector sent to instance 0x6d4fd30'
*** First throw call stack:
(0x13cc022 0x155dcd6 0x13cdcbd 0x1332ed0 0x1332cb2 0x13cde99 0x1914e 0x190e6 0xbfade 0xbffa7 0xbf266 0x3e3c0 0x3e5e6 0x24dc4 0x18634 0x12b6ef5 0x13a0195 0x1304ff2 0x13038da 0x1302d84 0x1302c9b 0x12b57d8 0x12b588a 0x16626 0x283d 0x27a5)
terminate called throwing an exception(lldb)

I still can't seem to figure out the problem there must be something I'm just not seeing.
Logged
fujilla
Global Moderator
Sr. Member
*****
Posts: 270


WWW




« Reply #3 on: August 06, 2012, 12:28:30 AM »

Most of the time when you get error similar to -[ViewController clickPlus:]: unrecognized selector sent to instance, it would mean that you are trying to invoke a method which does not exist.

Now, I appear to have missed something when looking at your code previously, however to be honest didn't pay too much attention to it as I wanted to see the error.

Although you may think by looking at your code that you do have the method clickPlus:, it is not quite correct.  For IBActions you need to say "who" is sending the message.  If you look at your method -(IBAction) clickDigit: (UIButton *) sender;, you will see that you are saying that an instance of a UIButton will be the sender.

So, for your operator methods you will need to add either
(UIButton *)sender
or
(id)sender
to the method names.  This will of course need to be done in both the interface and implementation files.  Also, in the XIB file, you will need to deselect the old methods for each of these buttons, then reselect the new method names, or you will still get an unrecognized selector sent to instance error.

Hope this helps,
Nick
http://myfirstiphoneapp.co.uk
http://easyintervalsapp.co.uk
Logged
es7
Newbie
*
Posts: 3


Email




« Reply #4 on: August 06, 2012, 12:55:59 AM »

Wow thank you so much. I actually wasn't quite clear of the whole self process method but I understand now. Thank you again  Smiley

Logged
Pages: [1]   Go Up
Print
Jump to:  



Login with username, password and session length

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents (c) 2009 classroomM.com. All rights reserved.