Thursday, February 16, 2012

cs193p fall 2011 Assignment 1 - Extra credit solution - iPhone Application Developnment

Continuing with the Assignment1 of the Stanford's CS 193P iPhone Application Development.  Fall2011 edition. This time I have solved Extra Credit part of the Assignment 1. I didn't manage to find a solution to these assignments so I am not sure if they are correct. I would appreciate your ideas and thoughts in comments below. If you have missed be sure to read my previous post that solves the non Extra Credits part of the Assignment 1:

cs193p fall 2011 iPhone Application Developnment Assignment 1 solution
Once again big thank you goes to Stanford and Paul Hegarty for creating this great video tutorials.
Nuff' talking. Lets get to work.

TASK 1.
1. Implement a “backspace” button for the user to press if  they hit the wrong digit button. 
This is not intended to be “undo,” so if  they hit the wrong operation button, they are
out of  luck!  It’s up to you to decided how to handle the case where they backspace
away the entire number they are in the middle of  entering, but having the display go
completely blank is probably not very user-friendly.
My Solution:
My idea here is to create a new string that contains everything but the last character from the display UILable. The hardest thing here is to dig into the documentation to find a method that you can call upon NSString to create a subString from original string. I have found substringToIndex: method. It creates a new string from the original string. It takes original string from the beginning and to the index you provide. Find more on substringToIndex:


- (IBAction)backspacePressrd {
    if (self.display.text.length){
        self.display.text=
               [self.display.text substringToIndex:(self.display.text.length - 1)];
}

TASK 2.
2. When the user hits an operation button, put an = on the end of  the text label that is
showing what was sent to the brain (required task #4). Thus the user will be able to tell
whether the number in the Calculator’s display is the result of  a calculation or a
number that the user has just entered.
My Solution: I am not sure if I understood this assignment correctly. It is not hard to add = to the end of brainHistory UILable every time someone hits enter. The trick is to remove it after something other than enter is pressed. So I introduced new Boolean variable which is true if the = is shown and false if it is not. If someone has a better solution to this let me know.

Iniside the interface of the ViewControler.m file I have declared property
 @property (nonatomic) BOOL equalsIsShown;
inside of the interface of the same file I have synthesized getter and setter for the same property.
 @synthesize equalsIsShown=_equalsIsShown;
 
I have added check if a = is already on the screen when user starts to enter the number. If it is app will remove it.
 
- (IBAction)digitPressed:(UIButton *)sender {
    NSString *digit =[sender currentTitle];
    NSLog(@"Digit pressed %@", digit);
    NSRange isNumberDecimal = [self.display.text rangeOfString:@"."];
    if ((self.brainHistory.text.length)&&(self.equalsIsShown)){
        self.brainHistory.text= [self.brainHistory.text
                            substringToIndex:(self.brainHistory.text.length - 1)];
        self.equalsIsShown=NO;
    }
    if (self.userIsInTheMiddleOfEnteringANumber){
    //the rest of the method stays unchanged


I have also modified operationPressed: method. The last two lines are new.

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

TASK 3.
3. Add a +/- operation which changes the sign of  the number in the display.  Be careful
with this one.  If  the user is in the middle of  entering a number, you probably want to
change the sign of  that number and let them continue entering it, not force an
enterPressed like other operations do.  But if  they are not in the middle of  entering a
number, then it would work just like any other single-operand operation (e.g. sqrt).
My Solution: I am not sure if I am doing this right. I don't understand what does if user is in the middle of entering a nuber have to do with plus/minus change? I have created a separate button (new button) for this. Created a new method pusMinus for my new button. When I hit the button I convert the string from display UILabel to a double, then multiply the number with -1 and then again convert it back to string.

- (IBAction)plusMinus {
    self.display.text= 
            [NSString stringWithFormat:@"%g",([self.display.text doubleValue]*-1)];
}

This is not ideal solution because if users decides to change sign in front of the number right after typing decimal point the point will be lost. A better solution could be by manipulating strings. First you check first character of the display UILabel if it is minus or a nuber. If it is a minus then remove the fist character. If it is not create a new string with minus in front. Think that would work.

13 comments:

  1. I hope so. I was looking at assignment 2 but I don't quite understand it, so it could take some time before I understand it and solve it.

    ReplyDelete
  2. Yes, it's a bit confusing. Thanks for the reply:)

    ReplyDelete
  3. re- Task 3
    If the user is a typing number then he should be able to continue extending the number. (just as you did).
    However it would also be possible to change the sign of an answer (result). I that case you need to change the stack as well.

    ReplyDelete
    Replies
    1. Good point Arnaud.
      Maybe solution would be:
      Check if the user is in the middle of entering the number. If he is then pop operand and push new number on the stack. I am too lazy to implement that in the code, so if you decide to try it let us know the result...

      Delete
    2. I fact that is what I implemented.

      Delete
  4. For Task 1 this solution is able to reset the display when the last digit is deleted with backspace:

    - (IBAction)backspacePressed {

    if (self.display.text.length > 1){

    self.display.text = [self.display.text substringToIndex:(self.display.text.length -1)];

    } else { self.display.text = @"0"; self.userIsInTheMiddleOfEnteringANumber = NO; }
    }

    ReplyDelete
    Replies
    1. Hi Salvatore,

      I first did the substring, and then depending on the result I set the display to 0. This seemed to make it neater for catering for negative numbers too...

      - (IBAction)backspacePressed {
      self.display.text =[self.display.text substringToIndex:
      [self.display.text length] - 1];

      if ( [self.display.text isEqualToString:@""]
      || [self.display.text isEqualToString:@"-"]) {

      self.display.text = @"0";
      self.userIsInTheMiddleOfEnteringNumber = NO;
      }
      }

      Full solution at http://www.i4-apps.com

      Delete
  5. For Task 2 there is no need to track if equal is shown or not.
    You can update the Brain History display (log) after an operation with the text resulting from this string manipulation:
    self.log.text = [[self.log.text stringByReplacingOccurrencesOfString:@"= " withString:@""] stringByAppendingString:@"= "];

    ReplyDelete
  6. I've posted my solution to the extra credit tasks at http://www.i4-apps.com

    ReplyDelete
  7. FOR TASK 2:


    if ([self.userInputHistory.text rangeOfString:@"="].location == NSNotFound) {
    self.userInputHistory.text = [self.userInputHistory.text stringByAppendingString:@" ="];
    }else {
    self.userInputHistory.text = [[self.userInputHistory.text stringByReplacingOccurrencesOfString:@" =" withString:@""]stringByAppendingString:@" ="];
    }

    ReplyDelete
  8. This is how I implemented Task 1. If the last character after backspacing is a point, the point gets removed, too.

    - (IBAction)backspace {
    NSUInteger length = self.display.text.length;
    if(length > 1) {
    self.display.text = [self.display.text substringToIndex:length-1];
    if([self.display.text hasSuffix:@"."]) {
    self.display.text = [self.display.text substringToIndex:length-2];
    }
    } else {
    self.display.text = @"0";
    self.userIsInTheMiddleOfEnteringANumber = NO;
    }
    }

    ReplyDelete