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

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

新規登録して質問してみよう
ただいま回答率
85.48%
標準入力

標準入力(stdin)は、プログラムが標準的に用いるデータ入力元。リダイレクトしない限り、プログラムを起動した端末のキーボードが標準入力になります。UNIX系OSやC言語に実装されて普及した概念ですが、他のOSや言語も含めた総称としても使われます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

2回答

1528閲覧

Java言語で標準入力で受け取った中置記法の数式を逆ポーランド記法に変換したい。

takayuki1107

総合スコア28

標準入力

標準入力(stdin)は、プログラムが標準的に用いるデータ入力元。リダイレクトしない限り、プログラムを起動した端末のキーボードが標準入力になります。UNIX系OSやC言語に実装されて普及した概念ですが、他のOSや言語も含めた総称としても使われます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

0グッド

0クリップ

投稿2023/02/10 04:38

実現したいこと→Java言語で標準入力で受け取った中置記法の数式を逆ポーランド記法に変換したい。

以前、https://teratail.com/questions/5jykl6q0ug5xmf の質問をさせていただきましたが、それを踏まえて質問させていただいております。まずは、こちらの質問をご覧いただければ幸いです。
こちらの質問を踏まえて逆ポーランド記法に変換したものをスタックを用いる方法で解きたいと考えております。

  • 標準入力からString型の数式を受け取って(2×3+1、とか、100×50/20、(20+30)×5、2(3+5)/4、1+(2(3+((5÷2)-2)))みたいな、=はつかない、×や÷が来たら乗算・除算にする)それを四則演算の原則に則って計算(*や/は+や-に優先する、とか、()内の計算が優先とか)したいです。

↑上の文章で乗算を表そうとしてアスタリスクを書くと表示されないので×としています。

ここで標準入力で受け取る数式が中置記法なので、これをまず逆ポーランド記法に直したいです。
↑のURLでの質問でいただいた回答の中には様々ライブラリをインポートしていらっしゃる方もいましたし、ライブラリを使えば簡単に解けるのかもしれませんが、現時点で私はScanner以外のライブラリはほぼ触ったことがなく、Javaの経験も浅いので、コードを提示いただく際にはそういったものを用いないものをいただけると幸いです。

前提

開発環境はeclipse、OSはwindows11、ちなみにiniファイルを編集して文字コードをUTF-8にしました。

私のJavaスキル→勉強し始めて3週間たたない程度。変数宣言、算術演算子、if文での条件分岐、forやwhileなどの繰り返し処理、メソッドの使い方、クラスを分けての開発の仕方などを学びました。
Scanner以外のライブラリに関してはほぼ使ったことがないので、できればソースコードを提示いただく際には使用しないでいただけると非常にありがたいです。
ちなみに、独学ですがPHPは約1年、Pythonは半年ほど勉強しており、基本的な文法は抑えており、PHPはスクラッチで各種バリデーションやログイン機能を備えたアプリを開発したり、Laravelを用いて簡単なアプリを開発したことがあり、PythonはフレームワークにStreamlit、ライブラリにpandasやnumpy、altairなどを使っての簡単なwebアプリ開発の経験があります。
基本情報技術者は保持しており、逆ポーランド記法への変換自体は机上ではできます。(プログラムでの実装方法が分からない状態。)

該当のソースコード

いろいろコードを書いて試してみたのですが、思った通りの挙動に全くならないし、そもそも記述量も少ない段階なので、載せないでおきます。申し訳ございません。

問題を解く手順として自分で考えているもの

標準入力で中置記法(String型)の数式(formulaとする。)を受け取る→
splitで1文字ずつに分割し、配列(formulaArrayとする。)に格納→
formulaArrayを逆ポーランド記法に変換して別の配列に格納(rpnListとする。長さはformulaArray.lengthとする。)→
rpnListからfor文で1要素ずつ取り出して1~9の数字(String型)だったら、スタック(stackという名の配列とする。)に格納。演算子(i番目)が渡ってきたらstackに格納された2つの数字(i-2番目と、i-1番目)をint型に変換後、演算を行い、この結果を変数に格納(int tmpとする)し、再び配列に格納。、、、みたいな感じで解こうと思っています。
まず、最初の中置記法の数式を逆ポーランド記法に変換する段階でどうすればいいのかわからな過ぎて詰まっています。これを標準入力の数式を受け取る際に用いるScanner以外のライブラリは極力使わない形でアルゴリズムを実現したいです。ご協力いただければ幸いです、よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2023/02/10 04:43

ライブラリを使っちゃいけないのは課題だからですよね? そうでなければ使いましょう。
takayuki1107

2023/02/10 04:47

課題ではありますが、私のJava経験が非常に浅いのが一番の理由です。
ozwk

2023/02/10 05:03

> 最初の中置記法の数式を逆ポーランド記法に変換する段階でどうすればいいのかわからな過ぎて詰まっています。 1. 調べましたか? 2. (調べた場合)それらしき方法を見つけましたか? 3. (見つけた場合)どこがわかりませんでしたか?
Zuishin

2023/02/10 05:13

浅い経験を何とかするためにもっと簡単なことから始めましょう。 ライブラリを使わなければ難易度が下がるということはありません。
dodox86

2023/02/10 05:51

> まず、最初の中置記法の数式を逆ポーランド記法に変換する段階でどうすればいいのかわからな過ぎて詰まっています。 Javaの経験値に限った話ではないように思います。まずは頭の中でできて、その手順を紙にでも書けるか、ではないでしょうか。
jimbe

2023/02/11 04:32 編集

分からない、経験が浅いと言われながら、何故そこを埋めずに先へ行こうとするのでしょうか。 課題として時間が無いのかもしれませんが、それならただの作成依頼にしかなりません。 先の質問への回答にコードを書きましたが、使っているのは今 java をインストールすれば使える機能だけです。 リスト・スタック等は複数のデータを管理する構造としては言語問わず使われるからこそ 標準であるのであって、それを『配列しか使わないで』と言われて では配列でリスト等の実装も書いて付け足せば良いのかといえば、車輪の再発明どころか時間とコード量の無駄でしかありません。 他の言語が出来るなら、まずそちらで動くものを作ってから java に書き換えて見るというのは如何でしょうか。 >逆ポーランド記法への変換自体は机上ではできます ということなら、それをフローチャートにしてご提示頂くとかのほうが、それに沿ったコードが回答し易いと思います。
kazuma-s

2023/02/10 06:54

> ↑上の文章で乗算を表そうとしてアスタリスクを書くと表示されないので×としています。 `2*3+1` と書いてください。「'」ではなくて「`」です。 2(3+5)/4 は「*」を省略していますが、それは意図したものですか?
xebme

2023/02/11 06:58 編集

操車場アルゴリズムは見たことありますか https://ja.wikipedia.org/wiki/%E6%93%8D%E8%BB%8A%E5%A0%B4%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0 スタックを知らなければ、配列でスタックを自作しましょう。 カーニハン&リッチーのC言語の教科書は、ワンステップずつ計算器を作る内容だったと思います。これなんか、Javaに置き換えてみるのも良いでしょう。 カンニングしたければ、https://www.freecodecamp.org/learn/coding-interview-prep/rosetta-code/ でも実力がなければいつか去らなければなりません。 ちょと言いすぎました。実力というのは、自力で、数行のコードからなんとか動作するコードを作る、粘り強さ、しつこさのことです。時間をかけてください。
guest

回答2

0

リストを配列で定義し、スタックはそのリストを利用するように定義、正規表現をコード化、内部クラスの殆どを展開しました。
簡単になったとは思えませんが…。

係数優先モード指定追加。 6/2(1+2) の結果を選べます。(true なら 1、 false なら 9)

java

1class List { 2 private String[] values = new String[0]; 3 private int size = 0; 4 List() {} 5 List(List org) { 6 size = org.size; 7 values = new String[org.values.length]; 8 for(int i=0; i<size; i++) values[i] = org.values[i]; 9 } 10 /** 最後に追加 11 * @param v 追加するデータ */ 12 void add(String v) { 13 if(size == values.length) { 14 String[] newValues = new String[values.length + 10]; 15 for(int i=0; i<size; i++) newValues[i] = values[i]; 16 values = newValues; 17 } 18 values[size++] = v; 19 } 20 /** i 番目を削除 21 * @param i インデックス(0 ~ size()-1) 22 * @return 削除したデータ */ 23 String remove(int i) { 24 String v = values[i]; 25 for(size--; i<size; i++) values[i] = values[i+1]; 26 return v; 27 } 28 /** i 番目を取得 29 * @param i インデックス(0 ~ size()-1) 30 * @return データ */ 31 String get(int i) { return values[i]; } 32 /** i 番目を変更 33 * @param i インデックス(0 ~ size()-1) 34 * @param v データ */ 35 void set(int i, String v) { values[i] = v; } 36 /** 件数 37 * @return 件数 */ 38 int size() { return size; } 39 @Override 40 public String toString() { 41 String s = "["; 42 for(int i=0; i<size; i++) s += (i>0?", ":"") + values[i]; 43 s += "]"; 44 return s; 45 } 46} 47 48class Stack { 49 private List list = new List(); 50 /** トップに追加 51 * @param v 追加するデータ */ 52 void push(String v) { list.add(v); } 53 /** トップから取り出し 54 * @return データ */ 55 String pop() { return list.remove(list.size()-1); } 56 /** トップを確認 57 * @return データ */ 58 String peek() { return list.get(list.size()-1); } 59 /** 空判定 60 * @return 空なら true */ 61 boolean isEmpty() { return list.size() == 0; } 62} 63 64public class Main { 65 public static void main(String[] args) { 66 String[] testdata = { "1+2.5*-3", "100*50/20", "(20+30)*5", "2(3+5)/4", "1+(2(3+((5/2)-2)))", "6/2(1+2)" }; 67 for(String formula : testdata) { 68 RPN rpn = new RPN(formula, true); 69 System.out.println(rpn + "=" + rpn.calc()); 70 } 71 } 72 73 private static class RPN { 74 private static class Translator { 75 private final String formula; 76 private int index; 77 private Stack stack = new Stack(); 78 private List list = new List(); 79 80 Translator(String formula) { 81 this.formula = formula; 82 } 83 84 List translate(boolean coefficientPriorityMode) { 85 int mode = 0; 86 while(!isEnd()) { 87 if(mode == 0) { 88 if(getChar() == '(') { 89 putOp(nextOperator()); 90 } else { 91 putValue(nextNumber()); 92 mode = 1; 93 } 94 } else { 95 String op = nextOperator(); 96 if(op.equals(")")) { 97 putOp(op); 98 } else { 99 if(op.equals("(")) putOp(coefficientPriorityMode ? "**" : "*"); 100 putOp(op); 101 mode = 0; 102 } 103 } 104 } 105 return complete(); 106 } 107 108 private boolean isEnd() { return index >= formula.length(); } 109 private char getChar() { return formula.charAt(index); } 110 private String nextOperator() { 111 String op = "" + formula.charAt(index++); 112 if("+-*/()".indexOf(op.charAt(0)) < 0) throw new IllegalArgumentException("Operator Error: index=" + index); 113 return op; 114 } 115 private String nextNumber() { 116 int j, i = index + (formula.charAt(index)=='-'?1:0); 117 for(j=0; i<formula.length() && ('0'<=formula.charAt(i) && formula.charAt(i)<='9'); i++, j++); 118 if(j > 0 && i < formula.length() && formula.charAt(i) == '.') { 119 for(i++, j=0; i<formula.length() && ('0'<=formula.charAt(i) && formula.charAt(i)<='9'); i++, j++); 120 } 121 if(j == 0) throw new IllegalArgumentException("Number Error: index=" + index); 122 String v = formula.substring(index, i); 123 index = i; 124 return v; 125 } 126 127 private void putOp(String op) { 128 if(op.equals(")")) { 129 while(!stack.isEmpty() && !(op=stack.pop()).equals("(")) list.add(op.toString()); 130 if(!op.equals("(")) throw new IllegalStateException("Formula Error: Unmatched parentheses."); 131 return; 132 } 133 if(!op.equals("(")) { 134 while(!stack.isEmpty() && getPri(stack.peek()) >= getPri(op)) list.add(stack.pop()); 135 } 136 stack.push(op); 137 } 138 private int getPri(String op) { 139 if(op.equals("**")) return 3; 140 if(op.equals("*") || op.equals("/")) return 2; 141 if(op.equals("+") || op.equals("-")) return 1; 142 return 0; 143 } 144 private void putValue(String v) { 145 list.add(v); 146 } 147 private List complete() { 148 while(!stack.isEmpty()) list.add(stack.pop()); 149 for(int i=0; i<list.size(); i++) if(list.get(i).equals("**")) list.set(i, "*"); 150 return new List(list); 151 } 152 } 153 154 private final String formula; 155 private List list; 156 157 RPN(String formula, boolean coefficientPriorityMode) { 158 this.formula = formula; 159 list = new Translator(formula).translate(coefficientPriorityMode); 160 } 161 162 String calc() { 163 Stack stack = new Stack(); 164 for(int i=0; i<list.size(); i++) { 165 String s = list.get(i); 166 if(s.equals("+")) { 167 double b = Double.parseDouble(stack.pop()); 168 double a = Double.parseDouble(stack.pop()); 169 stack.push("" + (a + b)); 170 } else if(s.equals("-")) { 171 double b = Double.parseDouble(stack.pop()); 172 double a = Double.parseDouble(stack.pop()); 173 stack.push("" + (a - b)); 174 } else if(s.equals("*")) { 175 double b = Double.parseDouble(stack.pop()); 176 double a = Double.parseDouble(stack.pop()); 177 stack.push("" + (a * b)); 178 } else if(s.equals("/")) { 179 double b = Double.parseDouble(stack.pop()); 180 double a = Double.parseDouble(stack.pop()); 181 stack.push("" + (a / b)); 182 } else { 183 stack.push(s); 184 } 185 } 186 return stack.pop(); 187 } 188 189 @Override 190 public String toString() { 191 return formula + "=" + list; 192 } 193 } 194}
1+2.5*-3=[1, 2.5, -3, *, +]=-6.5 100*50/20=[100, 50, *, 20, /]=250.0 (20+30)*5=[20, 30, +, 5, *]=250.0 2(3+5)/4=[2, 3, 5, +, *, 4, /]=4.0 1+(2(3+((5/2)-2)))=[1, 2, 3, 5, 2, /, 2, -, +, *, +]=8.0 6/2(1+2)=[6, 2, 1, 2, +, *, /]=1.0

投稿2023/02/10 18:59

編集2023/02/12 19:38
jimbe

総合スコア12646

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

このコードは参考になりますか?

Java

1import java.util.Scanner; 2 3class Main { 4 public static void main(String[] args) { 5 System.out.println("数式を入力してください"); 6 Scanner scanner = new Scanner(System.in); 7 String formula = scanner.nextLine(); 8 Expr e = new Expr(formula); 9 e.syn(0); 10 if (e.tok != 0) System.out.println("syntax error"); 11 else System.out.println(e.rpn); 12 } 13} 14 15class Expr { // 数式クラス (expression) 16 String str, rpn; int len, pos, val; char tok; 17 18 Expr(String s) { str = s; len = s.length(); pos = 0; rpn = ""; } 19 20 char lex() { // 字句解析 (lexical analyzer) 21 while (pos < len) 22 if ((tok = str.charAt(pos++))>='0' && tok<='9') { 23 for (val = tok - '0'; pos < len && 24 (tok = str.charAt(pos))>='0' && tok<='9'; pos++) 25 val = val * 10 + (tok - '0'); 26 return tok = '0'; 27 } 28 else if (tok != ' ') return tok; 29 return tok = 0; // end of string 30 } 31 32 final static char[] op = { '+', '-', '*', '/' }; 33 34 void syn(int i) { // 構文解析 (syntax analyzer) 35 if (i < 4) 36 for (syn(i+2); tok == op[i] || tok == op[i+1]; ) { 37 char t = tok; 38 syn(i+2); 39 rpn += t + " "; 40 } 41 else if (lex() == '0') { 42 rpn += val + " "; 43 lex(); 44 } 45 else if (tok == '(') { 46 syn(0); 47 if (tok == ')') lex(); 48 else tok = 1; 49 } 50 else tok = 1; 51 } 52}

Scanner 以外の特別なクラスは使っていません。
理解できないのはどこですか?

投稿2023/02/10 07:01

編集2023/02/10 08:45
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問