計算機のプログラム
受付中
回答 5
投稿
- 評価
- クリップ 2
- VIEW 3,346
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;
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+5
与えられた "1+2" などの文字列を正規表現で処理するように書き換えました。
この方法の延長では "1 + 2 + 3" や "-1 + 2" などを扱えるようにするのは困難です。
コンパイラの初歩を勉強して、構文解析の手法を使うようにするほうが良いです。
(参考: javacc )
// See https://teratail.com/questions/4832
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Keisan {
public String[] parseExperssion(final String str) throws Exception {
String[] ans = {"", "", ""};
Pattern p = Pattern.compile("^(?<num1>\\d+) *(?<ope>[+|-|*|/|%]) *(?<num2>\\d+)$");
Matcher m = p.matcher(str);
if (m.matches()) {
ans[0] = m.group("num1");
ans[1] = m.group("ope");
ans[2] = m.group("num2");
} else {
throw new Exception("Bad expression.");
}
return ans;
}
public int calc(final String str) throws Exception {
String[] terms = parseExperssion(str);
// for (String term: terms) { System.out.println(term); }
int ans = 0;
int a = Integer.parseInt(terms[0]);
int b = Integer.parseInt(terms[2]);
String ope = terms[1];
switch(ope) {
default:
throw new Exception("bad expression:" + str);
case "+":
ans = a + b;
break;
case "*":
ans = a * b;
break;
case "/":
ans = a / b;
break;
case "%":
ans = a % b;
break;
}
return ans;
}
public void myTest() {
final String[][] TEST_CASES = {
{"1 + 2", "3"},
{"2 * 3", "6"},
{"10 / 3", "3"},
{"10 % 3", "1"},
{"1+2", "3"},
{"2*3", "6"},
{"10/3", "3"},
{"10%3", "1"},
{"1 +2", "3"},
{"1+ 2", "3"},
{"1 + 2", "3"},
{"10 / 0", ""}, // 0 で割るとエラー
{"10/0", ""}, // 0 で割るとエラー
// 書式エラー
{"", ""},
{"10" , ""},
{"+", ""},
{"10 +", ""},
{"10 + *", ""},
{"10+" , ""},
{"10+*", ""},
{"+ * /", ""},
{"+*/", ""},
{" 1+2" , ""},
{null, ""}
};
for (String[] test : TEST_CASES) {
String exp = test[0];
try {
int ans = calc(exp);
System.out.println(exp + " = " + ans);
if (!test[1].equals("" + ans)) {
System.out.println("\tError calc");
}
} catch (Exception ex) {
System.out.println("'" + exp + "'" + "\n\t" + ex);
}
}
}
public static void main(String[] args) {
Keisan k = new Keisan();
k.myTest();
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
(変数名の変更、if での分岐 -> switch での分岐への変更 などをしています。
ここでは exception は細かくは制御していません。すべて Excption にまとめてしまっています。
これは好ましい事ではありません。ぜひ、Excepiton の切り分けを追加してみてください。)
// See https://teratail.com/questions/4832
public class Keisan {
public static int calc(final String str) throws Exception {
String[] brAry = str.split(" ");
// for (String word: brAry) { System.out.println(word); }
int ans = 0;
int a = Integer.parseInt(brAry[0]);
int b = Integer.parseInt(brAry[2]);
String ope = brAry[1];
switch(ope) {
default:
throw new Exception("bad expression:" + str);
case "+":
ans = a + b;
break;
case "*":
ans = a * b;
break;
case "/":
ans = a / b;
break;
case "%":
ans = a % b;
break;
}
return ans;
}
public static void myTest() {
final String EXPRESSIONS[] = {
"1 + 2", // 3
"2 * 3", // 6
"10 / 3", // 3
"10 % 3", // 1
"10 / 0", // 0 で割るとエラー
// 書式エラー
"",
"10",
"+",
"10 +",
"10 + *",
null,
};
for (String exp : EXPRESSIONS) {
try {
System.out.println(exp + " = " + Keisan.calc(exp));
} catch (Exception ex) {
System.out.println("'" + exp + "'" + "\n\t" + ex);
}
}
}
public static void main(String[] args) {
myTest();
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
ええと、そもそもなのですが、正規表現が誤っていてもコンパイルエラーは発生しませんよ。
実行時にExceptionが発生する可能性はあると思いますが。
それから、calc()メソッド内の引数の扱いも謎です。
Stringで受け取っていますが、期待する入力はどういったものなのでしょうか?
足し算の場合、"1+2"なのか、"1 + 2"なのか。
katoyさんがしれっと直されていますが、String.split()に空文字(="")をregexとして渡しても、
期待したようにbyAry[]には値が入らないと思われます。
その結果
int a = Integer.parseInt(brAry[0]);
int b = Integer.parseInt(brAry[2]);
char[] charAry = brAry[1].toCharArray();
上記のあたりでNullPointerExceptionやNumberFormatExceptionなどが起こると予想されますね。
正規表現といわれていますが、正規表現を使用する箇所はsplitのみで(それには空文字を指定されています)、その他には使用されていませんがどの部分のことをおっしゃっていらっしゃるのでしょうか?
if("[\\+]".equals(charAry)){
c = a + b;
}
と四則演算子と照合をしている部分は単純な比較を行っているに過ぎず、正規表現を使用はしていません。
もし、正規表現を使用するのであれば
//以下のインポート宣言を追加
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.apache.commons.lang.math.NumberUtils;
//クラス内のメソッドで正規表現を扱うサンプル
String s = "1+2";
String regex = "(\\d+)(.)(\\d+)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
if (m.find()){
int item1 = NumberUtils.toInt(m.group(0));
String operator = m.group(1);
int item2 = NumberUtils.toInt(m.group(2));
}
こんな感じでしょうか。
自分の趣味でapache commonsのNumberUtilsを使っていますが、使わなくてもいいです。
(NumberUtilsを使う場合はcommons langのjarが必要になるので要注意!)
期待値以外の入力が行われた場合のエラーチェックはちゃんとしてくださいね。
参考まで。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
正規表現は使わない上長いですが
恐らくはこういうものを作ろうとしたのではないでしょうか
1.2+3.5
2.5-6.7
3.4*5.6
2.1/7.2
などの書き方で入力すると結果を返すソースです
import java.io.Console;
public class San2{
public static void main(String[] args){
Console console=System.console();
String s=console.readLine("計算式:");
System.out.println(Keisan2.calc(s));
}
}
class Keisan2{
public static double calc(String s){
double c1=0;
double c2=0;
double res=0;
if(s.contains("+")){
int ind=s.lastIndexOf("+");
String s1=s.substring(0,ind);
String s2=s.substring(ind+1,s.length());
try{
c1=Double.parseDouble(s1);
c2=Double.parseDouble(s2);
}catch(Exception e){}
res=c1+c2;
}
if(s.contains("-")){
int ind=s.lastIndexOf("-");
String s1=s.substring(0,ind);
String s2=s.substring(ind+1,s.length());
try{
c1=Double.parseDouble(s1);
c2=Double.parseDouble(s2);
}catch(Exception e){}
res=c1-c2;
}
if(s.contains("*")){
int ind=s.lastIndexOf("*");
String s1=s.substring(0,ind);
String s2=s.substring(ind+1,s.length());
try{
c1=Double.parseDouble(s1);
c2=Double.parseDouble(s2);
}catch(Exception e){}
res=c1*c2;
}
if(s.contains("/")){
int ind=s.lastIndexOf("/");
String s1=s.substring(0,ind);
String s2=s.substring(ind+1,s.length());
try{
c1=Double.parseDouble(s1);
c2=Double.parseDouble(s2);
}catch(Exception e){}
res=c1/c2;
}
return res;
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
以下の2つにエラーが出ますね。原因は綴りミスです。
- ArrayIndexOutOfBoundsExcepion
-> ArrayIndexOutOfBoundsException - brAry
-> byAry
蛇足のようなもの:千里の道も一歩から。文法を覚え、コンパイルエラーの原因をつかみ、期待どおり動かなければデバッグして間違いの原因をつかみ、色々なアルゴリズムや設計パターンを学ぶ・・・プログラミングは一歩一歩進めていけばよいと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.20%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2014/12/28 17:31
少し思ったのは、この程度の実装にjavaccやYacc/Lexを登場させるのは大げさすぎるのでは?
自分で最低限のパーサを書く程度で十分ですし、その場合正規表現を駆使する、という手もあります。URLデスパッチャのように処理を引き当てるようなパターンもあるでしょう。
いろいろな実装の方法があり、一長一短ある、ということですよね。
ちょっと気になったので参考までに。
2014/12/28 21: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]