プロが教える店舗&オフィスのセキュリティ対策術

電卓アプリを作っています。
今困っているのは
1.割り算で小数点以下の計算ができない。
2.3つ以上の計算が(2×3×4のような)足し算しかできない。
3.間違えて数値を入力した場合に使うバックスペース的なボタンの作り方。
です。
どれか一つでもいいのでアドバイスいただけたらありがたいです。

#import "myViewController.h"


@implementation myViewController

// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
startInput = YES;
currentValue = 0;
}

-(IBAction)numberButtonPressed:(id)sender
{
UIButton *b = (UIButton *)sender;

if( startInput ){
// 最初の1桁目が0なら表示しない
if( b.tag == 0 ) return;
// 新しく表示する文字列を作成
label.text = [NSString stringWithFormat:@"%d", b.tag];

startInput = NO;
} else {
// すでに表示されている文字列に連結
label.text = [NSString stringWithFormat:@"%@%d", label.text, b.tag];
}
NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audio play];

}


-(IBAction)equalButtonPressed:(id)sender
{
currentValue = sum;
sum = sum-sum;

// 直前に押された演算子で場合分け
if( operation == 0 ){
currentValue += [label.text intValue];
} else if( operation == 1 ){
currentValue -= [label.text intValue];
} else if( operation ==2){
currentValue *= [label.text intValue];
} else if (operation ==3){
currentValue /= [label.text intValue];
}
// 表示の更新
label.text = [NSString stringWithFormat:@"%d", currentValue];

startInput = YES;
label2.text =@"=";
NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audio play];

}

-(IBAction)opButtonPressed:(id)sender
{ UIButton *b = (UIButton *)sender;

// 現在値の保存
if( operation == 0 ){
currentValue= [label.text intValue];
sum +=currentValue;
label.text =[NSString stringWithFormat:@"%d", sum];
}

// 演算の保存
operation = b.tag;
startInput = YES;

if( operation == 0 ){
label2.text =@"+";
}
if( operation == 1 ){
label2.text =@"-";
}
if( operation == 2 ){
label2.text =@"×";
}
if( operation == 3 ){
label2.text =@"÷";
}
NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audio play];

}


-(IBAction)clearButtonPressed:(id)sender
{
label.text = @"0";
startInput = YES;
label2.text =@"";

NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audio play];

}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];

// Release any cached data, images, etc. that aren't in use.
}

- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}


- (void)dealloc {
[super dealloc];
}


@end

A 回答 (1件)

質問1に対してですが、数値を整数(int)で計算している以上、小数点以下は切り捨てられます。

小数点以下を計算するなら、浮動小数点数(float、double)で計算しなければなりません。

質問2、3に対しては、それ以前にプログラム全体の見直しと、再設計が必要なため、現時点で考えても意味がないことだと思います。
まず、数値を整数でなく、浮動小数点数で処理すると決まった時点で、いくつもの処理すべき項目が出てきます。画面に表示する最大桁数と、内部で計算する際の有効桁数をどうするか?具体的に説明すると、「10÷3=3.333333……」の計算をする場合、小数点何位まで表示し、有効桁数をどうするか、ということです。有効桁数を適切に決めないと、「10÷3×3」と計算した場合に、答えが「10」にならず、「9.9999999」などとなることがあります。その場合、それでもかまわないのか、10にならなければならないのか、プログラム設計の指針を、決めておかなければなりません。
有効桁数の問題に対処するために、計算過程を記憶しておくプログラムが必要でしょう。先の例でいえば、「10÷3×3」を、「10×3÷3」と計算すれば、有効桁数に起因する誤差を、最小限に抑えることができます。計算過程を記憶するということは、質問3のUndo機能を持たせることにも通じるでしょう。

単純な計算機を作るだけでも、一筋縄ではいかないことがわかると思います。

※本題と関係なく、気になったこと:

AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audio play];

ボタンを押すたびに「audio」インスタンスを生成していますが、それを開放するコードが見受けられません。インスタンスは再利用されるのではなく、そのつど新しいインスタンスが生成されます。ボタンはひんぱんに押されるわけですから、「audio」インスタンスが、そのうちメモリを食いつぶしてしまうかもしれません。
iOSでは、ガベージコレクションが無効なので、インスタンス(オブジェクト)のライフ期間をつねに意識しておく必要があります。

NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];

上のコードでは、「path」、「[NSBundle mainBundle]」、「url」と、3つのインスタンスを生成していますが、いずれもautoreleaseが暗黙にセットされているので、適宜開放されます。が、「init~」で始まる初期化メソッドでインスタンスを生成すると、「暗黙のautorelease」はきかないので、「release」か「autorelease」を呼ばないと、開放されません。

今回のプログラムでは、インターフェイス部に、インスタンス変数として、すべての音声のインスタンスを宣言しておき、「viewDidLoad」メソッド内で、すべての音声のインスタンスを生成し、「dealloc」メソッド内で開放してやるのが、適切であろうと思います。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!