Stanford CS193P Assignment 1 Calculator Solution

I got to be honest, this Stanford CS193P RPN Calculator Assignment is not exciting me one bit. I am working through it to understand the basics, and I’ve completed it without the Extra Credit. I’m also not sure about part 6, since my calculator says “inf” if I divide by 0 already, so I’m not sure what else I need to do.

Anyways, here is my solution to at least the “meat” of this assignment:

CalculatorViewController.h

//
//  CalculatorViewController.h
//  Calculator
//
//  Created by Natalia Murashev on 12/4/11.
//  Copyright (c) 2011 Holler. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface CalculatorViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *display;
@property (weak, nonatomic) IBOutlet UILabel *history;

@end

CalculatorViewController.m

//
//  CalculatorViewController.m
//  Calculator
//
//  Created by Natalia Murashev on 12/4/11.
//  Copyright (c) 2011 Holler. All rights reserved.
//

#import "CalculatorViewController.h"
#import "CalculatorBrain.h"

@interface CalculatorViewController()
@property (nonatomic) BOOL userIsInTheMiddleOfEnteringANumber;
@property (nonatomic, strong) CalculatorBrain *brain;
@property (nonatomic, strong) NSMutableArray *periodPressed;
@end

@implementation CalculatorViewController

@synthesize display = _display;
@synthesize history = _history;
@synthesize userIsInTheMiddleOfEnteringANumber = _userIsInTheMiddleOfEnteringANumber;
@synthesize brain = _brain;
@synthesize periodPressed = _periodPressed;

- (CalculatorBrain *) brain
{
    if(!_brain) _brain = [[CalculatorBrain alloc] init];
    return _brain;
}

- (NSMutableArray *) periodPressed
{
    if(_periodPressed == nil)_periodPressed = [[NSMutableArray alloc] init];
    return _periodPressed;
}

- (IBAction)digitPressed:(UIButton *)sender 
{
    NSString *digit = [sender currentTitle];
    
    if(self.userIsInTheMiddleOfEnteringANumber) {
        
        //when the period is entered, it is stored in the periodPressed array.
        //if the user entered more than 1 period, it does not get added to the outlets
        if([digit isEqualToString:@"."]) {
            [self.periodPressed addObject:digit];
            if([self.periodPressed count] == 1) {
                //adds the digit to the main calculator display
                self.display.text = [self.display.text stringByAppendingString:digit]; 
                //adds the digit to the history display
                self.history.text = [self.history.text stringByAppendingString:digit]; 
            }
            
        //when the user clicks on a digit (not a period), it is added to the outlets
        } else {
            self.display.text = [self.display.text stringByAppendingString:digit];
            self.history.text = [self.history.text stringByAppendingString:digit];
        }
        
    }
    
    //when the user is not in the middle of entering a number...
    else {
        //when a period is added first, it is added to the period pressed array
        if([digit isEqualToString:@"."]) {
            [self.periodPressed addObject:digit];
        }
        //adds the initial digit to the main calculator display
        self.display.text = digit;
        //adds the digit to the history display
        if(self.history.text == nil) {
            self.history.text = digit;
        } else {
            self.history.text = [self.history.text stringByAppendingString:digit];
        }
        self.userIsInTheMiddleOfEnteringANumber = YES;
    }
    
        
}

- (IBAction)enterPressed 
{
    [self.brain pushOperand:[self.display.text doubleValue]];
    self.userIsInTheMiddleOfEnteringANumber = NO;
    [self.periodPressed removeAllObjects];
    self.history.text = [self.history.text stringByAppendingString:@" "];
    
}

- (IBAction)operationPressed:(UIButton *)sender 
{   
    if(self.userIsInTheMiddleOfEnteringANumber) [self enterPressed];  
    double result = [self.brain performOperation:sender.currentTitle];
    
    NSString *resultString = [NSString stringWithFormat:@"%g", result];
    self.display.text = resultString;
    
    self.history.text = [self.history.text stringByAppendingString:sender.currentTitle];
    self.history.text = [self.history.text stringByAppendingString:@" "];
}

- (IBAction)clearPressed:(UIButton *)sender {
    self.userIsInTheMiddleOfEnteringANumber = NO;
    self.display.text = nil; 
    self.history.text = nil; 
    [self.periodPressed removeAllObjects];
    self.brain = nil;
}

- (void)viewDidUnload {
    [self setHistory:nil];
    [super viewDidUnload];
}
@end

CalculatorBrain.h

//
//  CalculatorBrain.h
//  Calculator
//
//  Created by Natalia Murashev on 12/4/11.
//  Copyright (c) 2011 Holler. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface CalculatorBrain : NSObject

- (void)pushOperand:(double)operand;
- (double)performOperation:(NSString *)operation;

@end

CalculatorBrain.m

//
//  CalculatorBrain.m
//  Calculator
//
//  Created by Natalia Murashev on 12/4/11.
//  Copyright (c) 2011 Holler. All rights reserved.
//

#import "CalculatorBrain.h"

@interface CalculatorBrain()

@property (nonatomic, strong) NSMutableArray *operandStack;
 
@end

@implementation CalculatorBrain

@synthesize operandStack = _operandStack;

- (NSMutableArray *)operandStack
{
    if(_operandStack == nil) _operandStack = [[NSMutableArray alloc] init];
    return _operandStack;
}

- (void)pushOperand:(double)operand
{
    [self.operandStack addObject:[NSNumber numberWithDouble:operand]];
}

- (double) popOperand
{
    NSNumber *operandObject = [self.operandStack lastObject];
    if(operandObject != nil) [self.operandStack removeLastObject];
    return [operandObject doubleValue];
    
}


- (double)performOperation:(NSString *)operation
{
    double result = 0;
    
    if([operation isEqualToString:@"+"]) {
        result = [self popOperand] + [self popOperand];
    } else if([@"*" isEqualToString:operation]) {
        result = [self popOperand] * [self popOperand];
    } else if ([operation isEqualToString:@"-"]) {
        double subtrahend = [self popOperand];
        result = [self popOperand] - subtrahend;
    } else if ([operation isEqualToString:@"/"]) {
        double divisor = [self popOperand];
        result = [self popOperand] / divisor;
    } else if([operation isEqualToString:@"sin"]) {
        result = sin([self popOperand]);
    } else if([operation isEqualToString:@"cos"]) {
        result = cos([self popOperand]);
    } else if([operation isEqualToString:@"sqrt"]) {
        result = sqrt([self popOperand]);
    } else if([operation isEqualToString:@"π"]) {
        result = M_PI;
    } else if([operation isEqualToString:@"log"]) {
        result = log([self popOperand]);
    } 
    
    
    [self pushOperand:result];
    
    return result;
}


@end

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.