@rempei

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Javaの配列の中に複数のデータ型の値を入れることはできる?

Q&A

Closed

解決したいこと

計算のプログラムを作ってみようと思いました。 
演算子が=になるまで数値→演算子→数値…と配列に入れ続けて演算子が=になったら計算結果を表示するように考えていたのですが、作ってるうちにタイトルのようなことができなくて困ってしまいました。
分かる方がいらっしゃいましたら教えてほしいです。

発生している問題・エラー


例)

該当するソースコード

  public static void main(String[] args){
    String equ = ".";
    int first_cul = 000;
    String cul = "";
    int num1 = 0;
    int num2 = 0;
    int result = first_cul;


### 自分で試したこと
コードはまだ途中なのですがやりたいことをくみ取ってもらえればと思います
0 likes

4Answer

演算子順序考えなくてよくて単純に手前から順に計算していいのでしたら、演算子の情報は変数に一旦保存して次の数値受け取ったときに都度計算するのはどうでしょうか?

1Like

Comments

  1. @rempei

    Questioner

    ご回答ありがとうございます。
    やりたいことはできたのですが2つほど質問があります。

    一つ目はタイトルのJavaの配列の中に複数のデータ型の値を入れることはできる?はどうなのでしょうか?

    二つ目はソースコードを更新したので見てもらいたいのですが、最初の変数定義のところで equ や first_cul の初期値を " " としたらうまく動かなかったのですがなぜでしょうか?
  • エラーチェックはしていない
  • 足し算と引き算にしか対応していない

という条件付きですが、ざっと書いてみました(一応動作確認済み)。

見ての通り、数値、演算子それぞれでバッファリングする方式です。
やはり、2回ループするのは美しくないですね。。。

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner scan = new Scanner(System.in);
        ArrayList<Integer> nums = new ArrayList<Integer>();
        ArrayList<String> ops = new ArrayList<String>();
        while (true) {
            String num = scan.nextLine();
            nums.add(Integer.parseInt(num));
            String op = scan.nextLine();
            if (op.equals("="))
                break;
            ops.add(op);
        }
        Integer result = nums.get(0);
        for (int i = 0; i < ops.size(); i++) {
            if (ops.get(i).equals("+"))
                result += nums.get(i + 1);
            else
                result -= nums.get(i + 1);
        }
        System.out.println("---- Result ----");
        System.out.println(result);
    }
}
1Like

コメントの返信にマークダウン使用できないので新規コメントに記載します。

Javaの配列の中に複数のデータ型の値を入れることはできる?はどうなのでしょうか?

教科書的な回答をすると配列は同一の型じゃないといけませんね。
ただ共通の型だといいってことは同一の基底クラスだといいってことで、Objectクラスの配列(基本型はラッパクラスを使用)にすればできなくはないですよ。
取り出すときに型を見ないといけないのでそのままだとほとんど意味ないですが。
これやるくらいでしたら @imagou さんの書かれているようにStringそのまま保持したほうが遥かにマシな気がします。

個人的にはどうしてもリストに積むような処理にしたい場合は下記のように演算子と数値をひとまとめにした構造にするかなと思います。

enum Operator {
  Add,
  Sub,
  Mul,
  Div,
}

class Data {
  public Operator op;
  public int value;
}

1つ目の値以外は正しい式だと演算子と数値は順番ずつ入力されるはずなので例えば 1+2-3 だと

{ (null, 1), (Operator::Add, 2), (Operator::Sub, 3)}

みたいに入るようにするかなーって気がします。
1字句ごとに意味(字句の種類)を保持せずに値を積むのはその後の処理的に辛いのではと思いました。

字句ごとに処理するなら木構造にしたいですが、そこらへん考え始めるとParser実装の話になってきますので……

ソースコードを更新したので見てもらいたいのですが、最初の変数定義のところで equ や first_cul の初期値を " " としたらうまく動かなかったのですがなぜでしょうか?

変数定義の部分までしか書かれておらず何もわかりません。

1Like

Comments

  1. あと、こういった処理をするときに文法をいつチェックするのか、どうエラー処理をしたいのかといったことのほうが重要な気がします。
    それによって実装する戦略も決まってくるのでは?
  2. @rempei

    Questioner

    なるほど、新たな考え方を学べた気がします。
    ありがとうございました。

数値変換は後回しにして、すべて文字列として受け取ってはいかがでしょう。

0Like

Comments

  1. @rempei

    Questioner

    ご回答ありがとうございます。
    なるほど、しかし、どのように数値変換するのかが思い浮かびません
  2. (回答が今一つだったので修正します)

    自分で提案しておいてアレなのですが、与えられた条件からすると、「すべて文字列として受け取る」ことに無理がありそうです。。。すみません。

    一番エレガントなのは、@ligun 様の方式かと思いますが、時間あったら私も(私の方式で)コード書いてみますね。

Your answer might help someone💌