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

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

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

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

Q&A

5回答

4182閲覧

計算機のプログラム

kikaiwotaku

総合スコア8

Java

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

0グッド

2クリップ

投稿2014/12/27 17:36

初めて質問投稿します。質問に対して不足している情報などあるかもしれませんが、ご容赦ください。

Javaで簡単な計算機の仕組みを作ろうとしています。
しかし、いざコンパイルしようとすると様々なエラーが起こります。
自分は正規表現が間違っているのかなと考えているのですが、
どこがどう間違っているのかわかりません。教えてください。
ちなみに、下記のプログラムはその一部です。

public class Keisan{
public static int clac(String s)throws NumberFormatException, ArrayIndexOutOfBoundsExcepion{
String[] byAry = s.split("");
int c = 0;
int a = Integer.parseInt(brAry[0]);
int b = Integer.parseInt(brAry[2]);
char[] charAry = brAry[1].toCharArray();
if("[+]".equals(charAry)){
c = a + b;
}
else if("[-]".equals(charAry)){
c = a - b;
}
else if("[*]".equals(charAry)){
c = a * b;
}
else if("[/]".equals(charAry)){
c = a / b;
}else{
c = a % b;
}
return c;
}
}

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

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

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

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

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

guest

回答5

0

与えられた "1+2" などの文字列を正規表現で処理するように書き換えました。
この方法の延長では "1 + 2 + 3" や "-1 + 2" などを扱えるようにするのは困難です。
コンパイラの初歩を勉強して、構文解析の手法を使うようにするほうが良いです。
(参考: javacc )

lang

1// See https://teratail.com/questions/4832 2 3import java.util.regex.Pattern; 4import java.util.regex.Matcher; 5 6public class Keisan { 7 8 public String[] parseExperssion(final String str) throws Exception { 9 String[] ans = {"", "", ""}; 10 Pattern p = Pattern.compile("^(?<num1>\d+) *(?<ope>[+|-|*|/|%]) *(?<num2>\d+)$"); 11 Matcher m = p.matcher(str); 12 if (m.matches()) { 13 ans[0] = m.group("num1"); 14 ans[1] = m.group("ope"); 15 ans[2] = m.group("num2"); 16 } else { 17 throw new Exception("Bad expression."); 18 } 19 return ans; 20 } 21 22 public int calc(final String str) throws Exception { 23 String[] terms = parseExperssion(str); 24 // for (String term: terms) { System.out.println(term); } 25 int ans = 0; 26 int a = Integer.parseInt(terms[0]); 27 int b = Integer.parseInt(terms[2]); 28 String ope = terms[1]; 29 30 switch(ope) { 31 default: 32 throw new Exception("bad expression:" + str); 33 case "+": 34 ans = a + b; 35 break; 36 case "*": 37 ans = a * b; 38 break; 39 case "/": 40 ans = a / b; 41 break; 42 case "%": 43 ans = a % b; 44 break; 45 } 46 return ans; 47 } 48 49 public void myTest() { 50 final String[][] TEST_CASES = { 51 {"1 + 2", "3"}, 52 {"2 * 3", "6"}, 53 {"10 / 3", "3"}, 54 {"10 % 3", "1"}, 55 56 {"1+2", "3"}, 57 {"2*3", "6"}, 58 {"10/3", "3"}, 59 {"10%3", "1"}, 60 61 {"1 +2", "3"}, 62 {"1+ 2", "3"}, 63 {"1 + 2", "3"}, 64 65 {"10 / 0", ""}, // 0 で割るとエラー 66 {"10/0", ""}, // 0 で割るとエラー 67 68 // 書式エラー 69 {"", ""}, 70 {"10" , ""}, 71 {"+", ""}, 72 {"10 +", ""}, 73 {"10 + *", ""}, 74 {"10+" , ""}, 75 {"10+*", ""}, 76 {"+ * /", ""}, 77 {"+*/", ""}, 78 {" 1+2" , ""}, 79 {null, ""} 80 }; 81 82 for (String[] test : TEST_CASES) { 83 String exp = test[0]; 84 try { 85 int ans = calc(exp); 86 System.out.println(exp + " = " + ans); 87 if (!test[1].equals("" + ans)) { 88 System.out.println("\tError calc"); 89 } 90 } catch (Exception ex) { 91 System.out.println("'" + exp + "'" + "\n\t" + ex); 92 } 93 } 94 } 95 96 public static void main(String[] args) { 97 Keisan k = new Keisan(); 98 k.myTest(); 99 } 100}

投稿2014/12/28 08:16

編集2018/02/25 12:10
katoy

総合スコア22324

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

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

ShinpeiYamamoto

2014/12/28 08:31

素晴らしい回答ですね。 少し思ったのは、この程度の実装にjavaccやYacc/Lexを登場させるのは大げさすぎるのでは? 自分で最低限のパーサを書く程度で十分ですし、その場合正規表現を駆使する、という手もあります。URLデスパッチャのように処理を引き当てるようなパターンもあるでしょう。 いろいろな実装の方法があり、一長一短ある、ということですよね。 ちょっと気になったので参考までに。
katoy

2014/12/28 12:02

質問文での入力の式の処理には構文解析のことをもちだすのは大げさすぎるのは同感です。 でも、プログラムが動作しだせば、演算子の優先度、単行演算、カッコの利用など、 正規表現での処理では壁にぶつかるのが見えています。 将来的には 次のようなページにたどりついていただければと考えました。 - Androidで簡易な電卓 [http://hiroom2.jimdo.com/2014/04/09/javacc%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B/] - 多忙な Java 開発者のための Scala ガイド: 電卓を作る [http://www.ibm.com/developerworks/jp/java/library/j-scala08268.html] - JavaCCでスクリプト言語を作成する [http://codezine.jp/article/detail/367]
guest

0

お邪魔します。

ええと、そもそもなのですが、正規表現が誤っていてもコンパイルエラーは発生しませんよ。
実行時にExceptionが発生する可能性はあると思いますが。

それから、calc()メソッド内の引数の扱いも謎です。
Stringで受け取っていますが、期待する入力はどういったものなのでしょうか?
足し算の場合、"1+2"なのか、"1 + 2"なのか。

katoyさんがしれっと直されていますが、String.split()に空文字(="")をregexとして渡しても、
期待したようにbyAry[]には値が入らないと思われます。
その結果

lang

1 int a = Integer.parseInt(brAry[0]); 2 int b = Integer.parseInt(brAry[2]); 3 char[] charAry = brAry[1].toCharArray();

上記のあたりでNullPointerExceptionやNumberFormatExceptionなどが起こると予想されますね。

正規表現といわれていますが、正規表現を使用する箇所はsplitのみで(それには空文字を指定されています)、その他には使用されていませんがどの部分のことをおっしゃっていらっしゃるのでしょうか?

lang

1 if("[\+]".equals(charAry)){ 2 c = a + b; 3 }

と四則演算子と照合をしている部分は単純な比較を行っているに過ぎず、正規表現を使用はしていません。
もし、正規表現を使用するのであれば

lang

1//以下のインポート宣言を追加 2import java.util.regex.Pattern; 3import java.util.regex.Matcher; 4import org.apache.commons.lang.math.NumberUtils; 5 6//クラス内のメソッドで正規表現を扱うサンプル 7String s = "1+2"; 8String regex = "(\d+)(.)(\d+)"; 9Pattern p = Pattern.compile(regex); 10 11Matcher m = p.matcher(s); 12if (m.find()){ 13 int item1 = NumberUtils.toInt(m.group(0)); 14 String operator = m.group(1); 15 int item2 = NumberUtils.toInt(m.group(2)); 16}

こんな感じでしょうか。

自分の趣味でapache commonsのNumberUtilsを使っていますが、使わなくてもいいです。
(NumberUtilsを使う場合はcommons langのjarが必要になるので要注意!)
期待値以外の入力が行われた場合のエラーチェックはちゃんとしてくださいね。

参考まで。

投稿2014/12/28 04:13

ShinpeiYamamoto

総合スコア540

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

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

0

コンパイルと簡単な動作チェックができるように書き換えてみました。
(変数名の変更、if での分岐 -> switch での分岐への変更 などをしています。
ここでは exception は細かくは制御していません。すべて Excption にまとめてしまっています。
これは好ましい事ではありません。ぜひ、Excepiton の切り分けを追加してみてください。)

lang

1// See https://teratail.com/questions/4832 2 3public class Keisan { 4 5 public static int calc(final String str) throws Exception { 6 String[] brAry = str.split(" "); 7 // for (String word: brAry) { System.out.println(word); } 8 9 int ans = 0; 10 int a = Integer.parseInt(brAry[0]); 11 int b = Integer.parseInt(brAry[2]); 12 String ope = brAry[1]; 13 14 switch(ope) { 15 default: 16 throw new Exception("bad expression:" + str); 17 case "+": 18 ans = a + b; 19 break; 20 case "*": 21 ans = a * b; 22 break; 23 case "/": 24 ans = a / b; 25 break; 26 case "%": 27 ans = a % b; 28 break; 29 } 30 return ans; 31 } 32 33 public static void myTest() { 34 final String EXPRESSIONS[] = { 35 "1 + 2", // 3 36 "2 * 3", // 6 37 "10 / 3", // 3 38 "10 % 3", // 1 39 40 "10 / 0", // 0 で割るとエラー 41 42 // 書式エラー 43 "", 44 "10", 45 "+", 46 "10 +", 47 "10 + *", 48 null, 49 }; 50 51 for (String exp : EXPRESSIONS) { 52 try { 53 System.out.println(exp + " = " + Keisan.calc(exp)); 54 } catch (Exception ex) { 55 System.out.println("'" + exp + "'" + "\n\t" + ex); 56 } 57 } 58 } 59 60 public static void main(String[] args) { 61 myTest(); 62 } 63}

投稿2014/12/27 23:33

katoy

総合スコア22324

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

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

0

以下の2つにエラーが出ますね。原因は綴りミスです。

  1. ArrayIndexOutOfBoundsExcepion

-> ArrayIndexOutOfBoundsException
2. brAry
-> byAry


蛇足のようなもの:千里の道も一歩から。文法を覚え、コンパイルエラーの原因をつかみ、期待どおり動かなければデバッグして間違いの原因をつかみ、色々なアルゴリズムや設計パターンを学ぶ・・・プログラミングは一歩一歩進めていけばよいと思います。

投稿2016/11/03 00:43

KSwordOfHaste

総合スコア18394

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

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

0

正規表現は使わない上長いですが
恐らくはこういうものを作ろうとしたのではないでしょうか
1.2+3.5
2.5-6.7
3.4*5.6
2.1/7.2
などの書き方で入力すると結果を返すソースです

java

1import java.io.Console; 2 3public class San2{ 4 5public static void main(String[] args){ 6 7Console console=System.console(); 8 9String s=console.readLine("計算式:"); 10 11System.out.println(Keisan2.calc(s)); 12 13} 14 15} 16 17 18class Keisan2{ 19 20public static double calc(String s){ 21 22 23double c1=0; 24double c2=0; 25 26double res=0; 27 28if(s.contains("+")){ 29int ind=s.lastIndexOf("+"); 30 31String s1=s.substring(0,ind); 32String s2=s.substring(ind+1,s.length()); 33 34try{ 35c1=Double.parseDouble(s1); 36c2=Double.parseDouble(s2); 37}catch(Exception e){} 38 39res=c1+c2; 40 41} 42if(s.contains("-")){ 43int ind=s.lastIndexOf("-"); 44 45String s1=s.substring(0,ind); 46String s2=s.substring(ind+1,s.length()); 47 48try{ 49c1=Double.parseDouble(s1); 50c2=Double.parseDouble(s2); 51}catch(Exception e){} 52 53res=c1-c2; 54 55} 56if(s.contains("*")){ 57int ind=s.lastIndexOf("*"); 58 59String s1=s.substring(0,ind); 60String s2=s.substring(ind+1,s.length()); 61 62try{ 63c1=Double.parseDouble(s1); 64c2=Double.parseDouble(s2); 65}catch(Exception e){} 66 67res=c1*c2; 68 69} 70if(s.contains("/")){ 71int ind=s.lastIndexOf("/"); 72 73String s1=s.substring(0,ind); 74String s2=s.substring(ind+1,s.length()); 75 76try{ 77c1=Double.parseDouble(s1); 78c2=Double.parseDouble(s2); 79}catch(Exception e){} 80 81res=c1/c2; 82 83} 84 85 86return res; 87} 88 89 90}

投稿2016/11/02 23:41

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問