質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.03%

java初心者の質問です

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,823

score 16

学校の課題で電卓?の作成をしています。
式をユーザーが入力をして実行すると答えがでる というものです。
例えば
ユーザー入力)1 + 8 - 4 * 2
       答えは10
という形のものです。ただし計算の順番は無視するものとする。  というものなのですが 僕の作ったソースだと
1 + 8 - 4 * 2
答えは2
という風になってしまします。
これを計算できるようにしていきたいのですがどうソースを書いたらいいのか教えてください。
あと 計算の順番を掛け算割り算からするとしたらどうしたらいいでしょうか?
やりたいことは入力された値を保持してあとから取り出す....ということをしたいです。
参考にソースなどを書いて下さるとわかりやすいです。
お願いします。

↓ソース

import java.io.*;

class Keisanki
{
    public static void main(String[] args) throws IOException
    {
        
        int answer = 0;
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        System.out.println("式を入力してください");    
        String siki = br.readLine();//文字列を分割する必要がある。
        String[] keisan = siki.split(" ");
        String en = "a";//演算子が入力された時に保存する場所
        String num,num1;//数字が入力された時に保存する変数の宣言
        int i = 0;
        num ="";//数字が入力された時に保存する場所(左辺)
        num1 = "";//数字が入力された時に保存する場所(右辺)
        for ( i = 0; i < keisan.length; i++) {//iの数だけ繰り返される(ループ)
            
            //System.out.println(keisan[i]);//ここで出力されるものはlengthで返ってくるもの
            if ( i % 2 == 0 ) {
                num = Integer.parseInt(keisan[i]);
        
            } else {
                en = keisan[i];//奇数の時は演算子
                //System.out.println("演算子" + en);    
            }
            if ( i == 0 ) {
                num1 = Integer.parseInt(keisan[i]);
            }
        }
        
        if (i % 2 != 0 && i != 1){
            if(en.equals("+")){
                answer = num1 + num;
            }
            else if(en.equals("-")){
                answer = num1 - num;
            }
            else if(en.equals("*")){
                answer = num1 * num;
            }
            else if(en.equals("/")){
                answer = num1 / num

            }

        }
        System.out.println("答えは" + answer + "です");
      }

}


  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

String型で宣言しているnum,num1にparseIntの結果を代入しているのが解せないのですが・・・これらはint型であると仮定して話を進めます.
このコードを順番に解釈していくと
  1.  入力をスペース区切りでString配列に変換
  2.  for文で,最初の要素をnumに,それ以降演算子はenに,数値はnum1に代入する.
  3.  forを抜けた後,enに入っている演算子によってnumとnum1を計算する
ここで問題なのは2.で,forでループする間enとnum1は更新を繰り返します.結局例の場合ではnumには最初の数字である1が,enには最後の演算子"*",num1には最後の数字2が入り,計算は
1*2 = 2
という結果になります.
電卓のような動作をさせるのですから,演算子が入力されるたびに,その前に入力された演算子に応じた計算をしないとおかしくなります.つまり,forループの中で計算をしないといけません.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/10/10 19:17

    回答頂きありがとうございます。
    1はわかりました。
    計算をするタイミングがわかっていませんでした。

    2は
    if ( i == 0 ) {
    num1 = Integer.parseInt(keisan[i]);
    }
    の箇所です。
    そもそもStringで宣言しているものをintに変換することが無意味なのでしょうか?

    キャンセル

  • 2015/10/10 21:03

    計算するのでintへの変換は必要です.しかし変換してintになった値をString型の変数に入れることは無理です.私が言いたいのはnum,num1の宣言の型が違うということです.
    ご提示のコードはコンパイルが通らないのでは?

    キャンセル

  • 2015/10/11 00:51

    回答頂きありがとうございます。
    ようやく理解ができました。
    なおしてみます。

    キャンセル

0

>計算の順番を掛け算割り算からするとしたらどうしたらいいでしょうか? 

電卓にMR,M+,M-というボタンが有るでしょ。
加減乗除しかないとしたら加算と減算はそのまま計算し、乗算除算が出てきたら
結果を一旦キープして乗除を計算してその結果とキープを計算するといいでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/10/12 15:04

    回答頂きありがとうございます!
    参考にさせていただきます。

    キャンセル

0

2つの計算メソッドを書いてみました。
1つは 質問文のものを少し変更したもので、演算の優先度は無視して計算をするものです。
もう1つは、掛け算割り算を優先的に計算するものです。
以下の往路グラムでは、式として空行入力をするまでは、繰り返し2つの計算結果を示します。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;

class Keisanki {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.println("式を入力してください。(空行を入力すると終了)");
            String siki = br.readLine().trim(); // 文字列を分割する必要がある。
            if (siki.length() == 0) { // 空行なので終了する
                break;
            }

            System.out.println("答えは " + calc0(siki) + " です。[演算の優先度は無視]");
            System.out.println("答えは " + calc(siki) + " です。[演算の優先度を考慮]");
        }
    }

    // 演算の優先度を無視して計算する。
    static int calc0(String siki) {
        String[] keisan = siki.split(" ");
        int answer = Integer.parseInt(keisan[0]);
        String op = null;
        for (int i = 1; i < keisan.length; i++) {
            if (i % 2 == 1) { // 奇数の時は演算子
                // TODO: en が +, - * / のいずれかであることをチェックすること
                op = keisan[i];
            } else { // 偶数の時は数字
                // TODO: keisan[i] が数字であることをチェックすること。
                int num = Integer.parseInt(keisan[i]);
                if (op != null) {
                    answer = calc_simple(answer, num, op);
                }
                op = null;
            }
        }
        return answer;
    }

    // 演算の優先度を考慮して計算する
    static int calc(String siki) {
        String[] keisan = siki.split(" ");
        Stack<Integer> nums = new Stack<Integer>();
        Stack<String> ops = new Stack<String>();

        for (int i = 0; i < keisan.length; i++) {
            if (i % 2 == 1) { // 奇数の時は演算子
                String op = keisan[i];
                if (ops.size() > 0 && nums.size() > 1) {
                    String op0 = ops.peek();
                    // 1つ前の演算が * か / , または 1つ前と今の演算が +か - なら, すぐに計算をする。
                    if ("*/".indexOf(op0) != -1 || ("+-".indexOf(op0) != -1 && "+-".indexOf(op) != -1)) {
                        int num1 = nums.pop();
                        int num0 = nums.pop();
                        String opx = ops.pop();
                        int result = calc_simple(num0, num1, opx);
                        nums.push(result);
                    }
                }
                ops.push(op);
            } else { // 偶数の時は数字
                nums.push(Integer.parseInt(keisan[i]));
            }
        }

        while (!ops.isEmpty()) {
            int num1 = nums.pop();
            int num0 = nums.pop();
            String op = ops.pop();
            int result = calc_simple(num0, num1, op);
            nums.push(result);
        }
        // nums.size() == 1 であることをチェックすること。
        return nums.pop();
    }

    // "num0 op num1" の式を計算する。
    static int calc_simple(int num0, int num1, String op) {
        int ans = num0;
        if ("+".equals(op)) {
            ans += num1;
        } else if ("-".equals(op)) {
            ans -= num1;
        } else if ("*".equals(op)) {
            ans *= num1;
        } else if ("/".equals(op)) {
            // TODO: num != 0 をチェックすること
            ans /= num1;
        }
        return ans;
    }
}
// 演算の優先度を考慮した時の計算例
// 2 -> 2
// 2 + 3 -> 5
// 2 * 3 -> 6
// 2 / 3 -> 0
//
// 2 + 3 * 4 * 5 -> 62
// 2 * 3 + 4 * 5 -> 26
// 2 * 3 * 4 + 5 -> 29
//
// 2 - 3 + 4 + 5 -> 8
// 2 + 3 - 4 + 5 -> 6
// 2 + 3 + 4 - 5 -> 4
//
// 2 + 3 + 4 + 5 -> 14
// 2 * 3 * 4 * 5 -> 120
// 120 / 3 / 4 / 5  -> 2
// 120 / 3 + 4 / 2  -> 42
// TODO
//    (, ), 単項演算をサポートすること。
//    空白で区切らなくても済むようにすること。
実行例
式を入力してください。(空行を入力すると終了)
2 + 3 * 4 * 5
答えは 100 です。[演算の優先度は無視]
答えは 62 です。[演算の優先度を考慮]
式を入力してください。(空行を入力すると終了)
2 * 3 + 4 * 5
答えは 50 です。[演算の優先度は無視]
答えは 26 です。[演算の優先度を考慮]
式を入力してください。(空行を入力すると終了)
2 * 3 * 4 + 5
答えは 29 です。[演算の優先度は無視]
答えは 29 です。[演算の優先度を考慮]
式を入力してください。(空行を入力すると終了)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/10/12 15:05

    とてもわかりやすく そしてコードもありがとうございます。
    優先順位なしのはできたので、優先順位ありのものをつくってみます。
    本当にありがとうございます。

    キャンセル

  • 2015/10/12 17:22

    どんな式をつかってテストしたらプログラムのバグを発見できるか? についても検討して、
    テストをするプログラムを書くことにおついても勉強をするとよいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る