scientific calculator tutorial for iPhone/ipad - ios

i have been looking for a tutorial for a scientific calculator one the web but i could not find anything. my aim is to learn how to write a calculator app similar to the one in iPhone. does any know of any tutorials that can help me learn how to add scientific functions to a calculator app. keep in mind that i have tried the various versions of the basic calculator and have been through a few of those tutorials and just want to learn and may use the methods to add scientific functions such as rad, sin, cos and some other stuff in the app. i will be great full for any help i can get.
AP
Edit:
since there are no real material on how to build a scientific calculator out there( at least i haven't found anything specific yet) here is the run down of how to build one.
first create a NSObject class to hold your operation methods. ( this is optional, you can set it on top of your getter (.m) file if you like.) call it whatever you want. then declare the following the the header file.
{
double operand;
double savedNumber;
NSString *waitingOperation;
double waitingOperand;
}
- (void)setOperand:(double)aDouble;
- (double)performOperation:(NSString *)operation;
- (void)performWaitingOperation;
#end
then in the .m file of your NSObject class declare the methods that operates your functions. something like the following:
-(void)setOperand:(double)num
{
operand=num;
}
-(double)performOperation:(NSString *)operation
{
if([operation isEqual:#"sqrt"]){
operand = sqrt(operand);
}else if ([operation isEqual:#"1/x"]){
if(operand)
operand = 1 / operand;
}else if ([operation isEqual:#"2/x"]){
if(operand)
operand = 2 / operand;
}else if ([operation isEqual:#"3/x"]){
if(operand)
operand = 3 / operand;
}else if ([operation isEqual:#"+/-"]){
if(operand)
operand = (-1) * operand;
}else if ([operation isEqual:#"sin"]){
operand = sin(operand);
}else if ([operation isEqual:#"sinh"]){//you can add more scientific functions in the same way to this list.
operand = sinh(operand);
}else if ([operation isEqual:#"cos"]){
operand = cos(operand);
}else if ([operation isEqual:#"cosh"]){
operand = cosh(operand);
}else if ([operation isEqual:#"tan"]){
operand = tan(operand);
}else if ([operation isEqual:#"tanh"]){
operand = tanh(operand);
}else if ([operation isEqual:#"M"]){
savedNumber = operand;
}else if ([operation isEqual:#"M+"] ){
savedNumber += operand;
}else if ([operation isEqual:#"M-"] ){
savedNumber -= operand;
}else if ([operation isEqual:#"Recall"]){
[self setOperand:savedNumber];
}else if ([operation isEqual:#"C"]){
savedNumber = 0;
operand = 0;
waitingOperand = 0;
savedNumber= 0;
}else {
[self performWaitingOperation];
waitingOperation = operation;
waitingOperand = operand;
}
return operand;
}
- (void) performWaitingOperation
{
if([#"+" isEqual:waitingOperation]){
operand = waitingOperand + operand ;
} else if([#"-" isEqual:waitingOperation]){
operand = waitingOperand - operand ;
}else if([#"X" isEqual:waitingOperation]){
operand = waitingOperand * operand ;
}else if([#"/" isEqual:waitingOperation]){
if(operand)
operand = waitingOperand / operand ;
}
}
now in the view controller that you are trying to display the calculator you need to access all of these functions and display them in your outlets, such as buttons and text field and so on. here is the .h file
IBOutlet UILabel *display;
SCalcAI *ai;
BOOL userIsInTheMiddleOfTypingNumber;
}
- (IBAction) digitPressed: (UIButton *)sender;
- (IBAction) operationPressed: (UIButton *) sender;
rememebr to import your NSObject class header on top of this file otherwise you get an error. then in the .m file you need to declare these functions.
-(NameofyourNSOBjectClass *) ai
{
if(!ai)
{
ai = [[SCalcAI alloc] init];
}
return ai;
}
- (IBAction) digitPressed: (UIButton *)sender
{
NSString *digit = [[sender titleLabel] text];
if(userIsInTheMiddleOfTypingNumber){
[display setText:[[display text] stringByAppendingString:digit]];
} else{
[display setText:digit];
userIsInTheMiddleOfTypingNumber = YES;
}
}
- (IBAction) operationPressed: (UIButton *) sender
{
if(userIsInTheMiddleOfTypingNumber){
[[self ai] setOperand:[[display text] doubleValue]];
userIsInTheMiddleOfTypingNumber = NO;
}
NSString *operation = [[sender titleLabel] text];
double result = [[self ai] performOperation:operation];
[display setText:[NSString stringWithFormat:#"%g", result]];
}
then hook up all the buttons to the operations they need to be connected in the storyboard or xib. thats that. the above is the skeleton version of the whole thing but I'm sure you can build on that. if you need help send me message.

The Standford iOS programming class cs193p has an example of building a simple calculator. Might be a good place to start. Great course, great videos. Paul Hagarty is a very good instructor. The scientific functions would not be hard to add once you have the core done.
Two resources:
http://www.tusharsharma.in/project/open-source/mathematical-calculator-iphone4/
http://emplementation.blogspot.com/2010/11/ios-development-tutorials-on-itune-u.html

Related

isEqual is not working properly in xcode

My code looks like proper but isEqual used to compare two object is not working. i'm new to iOS. there is no much resource to check. [box2 isEqual:box1] is always gives me No. but it supposed to give Yes. anything wrong in my code, please suggest me the correct thing. thanks in advance. expecting best suggestion .
#import <Foundation/Foundation.h>
#interface Box:NSObject
{
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
}
#property(nonatomic, readwrite) double height; // Property
-(double) volume;
//-(id)initWithLength:(double)l andBreadth:(double)b;
#end
#implementation Box
#synthesize height;
-(id)init
{
self = [super init];
if(self)
{
length = 2.0;
breadth = 3.0;
}
return self;
}
-(double) volume
{
return length*breadth*height;
}
#end
#class Box;
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Box *box1 = [[Box alloc]init]; // Create box1 object of type Box
Box *box2 = [[Box alloc]init];
NSLog (#"hello world");
box1.height = 5.0;
NSLog (#"%ld",[box1 volume]);
if([box2 isEqual:box1])
{
NSLog(#"%b",[box2 isEqual:box1]);
}
[pool drain];
return 0;
}
You have to override isEqual method in your object.
e.g. in your "#implementation Box"
- (BOOL)isEqual:(id)object
{
if ([object isKindOfClass:[Box class]]) {
Box*box = (Box*)object;
return self.height == box.height; // compare heights values
}
return [super isEqual:object];
}
isEqual: works just fine and as documented, but not as you expected.
isEqual: is a property of NSObject. It returns YES if two object pointers are the same, and NO if they are not. If you want a different result, you need to override isEqual for your Box class. Note that the argument to isEqual: could be anything, not just a Box, so you need to be careful.
Obviously you shouldn't declare instance variables put properties, so the code below assumes that. The way your code is written, you will have some confusion with an instance variable height, a property height, and an instance variable _height, which will give you headaches. It also assumes that you are not subclassing Box (for example you could have a coloured box, which should not be equal to a Box with same width, height and breadth).
- (BOOL)isEqual:(id)other
{
if (! [other isKindOfClass:[Box class]]) return NO;
Box* otherBox = other;
return _length == other.length && _breadth == other.breadth
&& _height == other.height;
}

Semantic Issue: Comparison between pointer and integer

I have researched online and couldn't find an answer. On Xcode 6 I have a error:
Semantic issue: Comparison between pointer and integer ('UILabel*' and 'int')
The code is (ViewController.m):
-(void)enemyMovement {
enemyShip.center = CGPointMake(enemyShip.center.x, enemyShip.center.y + 2);
if (CGRectIntersectsRect(enemyShip.frame, mothersShip.frame)) {
lives = lives - 1;
liveString = [NSString stringWithFormat:#"LIVES: %i", lives];
livesLabel.text = liveString;
//Stop enemy moving
[enemyMovementTimer invalidate];
if (livesLabel > 0) {
[self positionEnemy];
}
if ((livesLabel = 0)) {
[self gameOver];
}
}
}
-(void)gameOver {
[enemyMovementTimer invalidate];
[missleMovementTimer invalidate];
[self performSelector:#selector(replayGame) withObject:nil afterDelay:3];
}
- (void)replayGame {
score = 0;
lives = 3;
scoreString = [NSString stringWithFormat:#"SCORE: 0"];
liveString = [NSString stringWithFormat:#"LIVES: 3"];
scoreLabel.text = scoreString;
livesLabel.text = liveString;
startButton.hidden = YES;
friendlyShip.hidden = NO;
enemyShip.hidden = NO;
mothersShip.hidden = NO;
scoreLabel.hidden = NO;
livesLabel.hidden = NO;
[self positionEnemy];
}
The error occurs when integer is '1' but when integer is '0' the error doesn't occur and the lives goes into negative numbers, but the command doesn't occur for either number. The command is to revert back to the start of the game. I Think the problem is something to do with the way that the lives label is set out, I also think it might be something about the '=='. But i am not sure completely I have tried to solve this problem, but I have been unsuccessful, several times. I hope you can help me.
Thank You in advance
livesLabel > 0 is comparing the memory address of the livesLabel object to the number 0. What you want is to compare 0 to the text that the label shows. The comparison would look like this: [livesLabel.text intValue] > 0
You're comparing a label to a number. You might need to relearn some fundamental programming concepts, and I can't help you there, but a UILabel has a text property which can be parsed into an int with intValue.
if (livesLabel > 0) {
[self positionEnemy];
}
if ((livesLabel = 0)) {
[self gameOver];
}
I can't even tell what you're trying to achieve, you should compare lives instead, not the label to a number, its like trying to compare a sticker with a number, it makes absolutely no sense.

Clearing/Resetting all string and variables

I have a routine in xcode that calls a function and spits out a result to a UITextView element on an iPhone app.
Before the routine is started I want to reset all NSString objects/values and any variables that I used to calculate the result. Is there a quick way to do this?
So far no matter what I retype in the UITextField it just gets ignored after the initial calculation.
Code for the solve button :-
- (IBAction)Solve:(id)sender {
//
// Reset strings and variable code here
//
[_Number1 resignFirstResponder];
[_Number2 resignFirstResponder];
[_Number3 resignFirstResponder];
[_Number4 resignFirstResponder];
[_Number5 resignFirstResponder];
[_Number6 resignFirstResponder];
[_TargetNum resignFirstResponder];
// Dismiss Keyboard
int numb1,numb2,numb3,numb4,numb5,numb6,numTar;
numb1 = [self.Number1.text intValue];
numb2 = [self.Number2.text intValue];
numb3 = [self.Number3.text intValue];
numb4 = [self.Number4.text intValue];
numb5 = [self.Number5.text intValue];
numb6 = [self.Number6.text intValue];
numTar = [self.TargetNum.text intValue];
mainLoopOne(numb1,numb2,numb3,numb4,numb5,numb6,numTar);
// Start calculation with field values
readAnswers = #"Please read answers bottom-up.\n";
cantCalc = NULL;
finalResult = #"";
if (numb1 != 0) {
int ii;
for(ii = 0; ii < 6 ; ii++) {
if (allAnswers[ii] != NULL) {
finalResult = [finalResult stringByAppendingFormat:#"%#", allAnswers[ii]];
}
}
if (finalResult == NULL) {
cantCalc = #"Unfortunately, that doesn't seem to be possible, as there was no answer calculated.\n";
readAnswers = #"";
}
CompileText = [NSString stringWithFormat:#"%#\n%#\nfrom %d combination tries.", readAnswers, finalResult, countCombi];
[self.TextWin setText:CompileText];
}
countCombi = 0;
}
#end
Most of the strings and variables are set just under the #import "ViewController.h" so they are global :-
NSString *readAnswers;
NSString *cantCalc;
NSString *finalResult;
NSString *allAnswers[10];
NSString *CompileText;
NSString *readAnswers;
NSString *finalResult;
#define DIV 0
#define MUL 1
#define ADD 2
#define SUB 3
int n1,n2,n3,n4,n5,n6;
int answer_counter = 0;
int tar2 = 0;
int number[6];
int target = 0;
int used[6];
int countCombi;
Thanks.
Create a reset method that alloc inits every string in your view controller again. You can set the textview's text to "".
In theory you could write a helper class that you pass in an object (your view controller) and it uses introspection to reset everything that is a string or whatever you want. This is a good approach for modularity and reusability, however it requires knowledge of c, and introspection.
Yes whatever williams say thats correct. Implement like below:
-(IBAction)doClear:sender
{
[Yourtextview setString];
}

How to do an if statement with a button?

I'm new to Objective-C and am learning it bit by bit, and I have a question about it.
I made an iPhone app about incrementing or decreasing a number, for example, and the default number is set to 0. By pressing the Up, Down or Restart button you have different command options. I would like to put into play the if statement, for ex. when the Label number (0) equals five (5) have a popup box, or a text saying "You have reached the number 5"; this would only be to learn and be able to implement this in a future app or game.
ViewController.h
#import <UIKit/UIKit.h>
int Number;
#interface ViewController : UIViewController {
IBOutlet UILabel *Count;
}
- (IBAction)Up:(id)sender;
- (IBAction)Down:(id)sender;
- (IBAction)Restart:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (IBAction)Up:(id)sender {
Number = Number + 1;
Count.text = [NSString stringWithFormat:#"%i", Number];
}
- (IBAction)Down:(id)sender {
Number = Number - 1;
Count.text = [NSString stringWithFormat:#"%i", Number];
}
- (IBAction)Restart:(id)sender {
Number = 0;
Count.text = [NSString stringWithFormat:#"%i", Number];
}
- (void)viewDidLoad {
Number = 0;
Count.text = [NSString stringWithFormat:#"%i", Number];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
You can add a method:
- (void)checkNumber {
if (Number == 5) {
// show the alert
}
}
And then in your code:
-(IBAction)Up:(id)sender {
Number = Number + 1;
Count.text = [NSString stringWithFormat:#"%i", Number];
[self checkNumber];
}
-(IBAction)Down:(id)sender {
Number = Number - 1;
Count.text = [NSString stringWithFormat:#"%i", Number];
[self checkNumber];
}
Then, learn about naming conventions as your names are all wrong (letter capitalisation).
You will only hit 5 on the Up method, so check your value in there. Display a UIAlertView if someone tries to go over 5.
- (IBAction)Up:(id)sender{
if (Number >= 5) {
UIAlertView *alert = [[UIAlertView alloc ] initWithTitle:#"Sorry!" message:#"You can't go over five." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
else {
Number = Number + 1;
Count.text = [NSString stringWithFormat:#"%i", Number];
}
}
I am using UIAlertView to show the message here, but you could use UILabel, or something else.
A few pointers about Objective-C conventions:
Methods use camel case, and have descriptive names. Instead of Up, use something like incrementTestValue.
Variable names also use camel case. Instead of Number and Count, just use number and countLabel, respectively. Using a capital makes it look like a class name.
Take a look at this code. This will be a good example of how to use return values inside your methods. My method is called -(BOOL)isNumberGreaterThanOrEqualToFive;
The - indicates this is an instance method. The (BOOL) indicates this method returns a BOOL (YES/NO). isNumberGreaterThanOrEqualToFive is the name of the method. It's used like this
BOOL value = [self isNumberGreaterThanOrEqualToFive];
//value will either be YES or NO
Take a look
-(BOOL)isNumberGreaterThanOrEqualToFive {
if (Number >= 5) {
return YES;
}
return NO;
}
-(IBAction)Up:(id)sender {
if ([self isNumberGreaterThanOrEqualToFive]) {
NSLog(#"Number is greater than or equal to 5");
[self showAlertViewWithMessage:#"Number is 5 or more!"];
} else {
Number = Number + 1;
}
}
Another thing to learn about Obj-C and programming in general is something called factorization, where you split up unrelated tasks into smaller more discrete related tasks. For example, instead of having one big block of code inside a method, you can make several methods that each complete one specific task. You could split out the code that shows the AlertView this way. For example:
-(void)showAlertViewWithMessage:(NSString *)messageText {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:messageText delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}

Decimal place not displaying correctly in Xcode?

I got the decimal working now but for some reason its displaying backwards. It's probably my lack of math skills but here is the code:
-(IBAction)buttonDigitPressed:(id)sender {
currentNumber = (float)[sender tag] + currentNumber /10;
priceOne.text = [NSString stringWithFormat:#"%.2f",currentNumber];
}
Now when I type on my custom keyboard in this order: 5-2-1, it displays the number backwards: 1.25. I want it to display 5.21. Any ideas?
In your #interface add a new instance variable
float currentMultiplier;
Set it in your (re-)initialisation routine, so:
currentMultiplier = 1.0;
and recode the routine you mention in the question as:
-(IBAction)buttonDigitPressed:(id)sender
{
currentNumber += (float)[sender tag]*currentMultiplier;
currentMultiplier *= 0.1;
priceOne.text = [NSString stringWithFormat:#"%.2f",currentNumber];
}
-(IBAction)buttonDigitPressed:(id)sender {
currentNumber = currentNumber*10 + (float)[sender tag];
calculatorScreen.text = [NSString stringWithFormat:#"%2f",currentNumber];
}

Resources