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

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

新規登録して質問してみよう
ただいま回答率
85.46%
コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

1回答

682閲覧

入力された数字・空白・ひらがなが入っている文字列が、指定の型になっている場合のみ、入力文字列から数字を取り出して計算したい。

kyutaro001076k

総合スコア1

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2021/08/31 13:20

前提・実現したいこと

コマンドプロンプトに入力された文字列が「2 たす 4 は?」「6.2 わる 2 は?」のように各tokenの間が空白で区切られている時には答えを「6.0です。」や「3.1です。」のように表示させるようにしたい。「7.2ひく2.1は?」のように空白で区切られていない場合などは、「理解不能」と表示させたい。
最後の?は全角でも半角でも大丈夫なようにしたい。

発生している問題・エラーメッセージ

「2 たす 4 は?」と正しく入力しても、答えが表示されない。
入力された文字列との比較がうまくできていない。

エラーは特にないが文字列比較が正常にできていない。 下記のコードにこだわりはありませんので、文字列比較のやり方をお教えいただきたいです。

該当のソースコード

コード
if(R.matches("[1-9]+.?\d+\sたす\s[1-9]+.?\d+\sは?")){
System.out.println("a");    //うまくいけばこれが反応するはずなのに反応してない
}

java

試したこと

比較がうまくできているか上記のようなコードで確認したが、うまくいっていないようです。
Rには入力された文字列が入っています。

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

windowsを使用しています。
ここにより詳細な情報を記載してください。

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

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

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

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

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

BeatStar

2021/08/31 13:42 編集

(不適切発言に見えなくもないため削除)
guest

回答1

0

ベストアンサー

まず、2箇所に出てくる実数部分にマッチするパターンを修正する。

質問者が使っている[1-9]+.?\d+というパターンは、19の数字が1個以上連続し、その直後に.が0個か1個あり、その直後に09の数字が1個以上連続する文字列にマッチする。これだと、

  • 「0.5」や「10.5」のように、整数部に0を含み、小数部を持つ実数にマッチしない。
  • マイナスの実数にマッチしない。

という問題がある。

そこで、

  • 符号(+-)が0個または1個あり(省略可能ということ)
  • その直後に09の数字が1個以上連続し(「001」なども許容する)
  • .(小数点)1個と、それに続く09の数字の1個以上の連続」が0個または1個ある(省略可能ということ)

と考えると、このパターンは([+-]?\d+(?:.\d+)?)と書ける。これをJavaの文字列リテラルにすると、"([+-]?\\d+(?:\\.\\d+)?)"となる。

なお、全体を()で囲むのは、マッチした実数部分をキャプチャして取り出すため、内部で(?:...)を使うのは、キャプチャすることを避けるため。

備考: このパターンの整数部分の\d+を、「0が1個だけか、19の数字1個とそれに続く09の数字の0個以上の連続」を意味するパターン(?:0|[1-9]\d*)(文字列リテラルだと"(?:0|[1-9]\\d*)")に置換すれば、「001」などを除外できる。


次の問題は、区切りとなる空白2箇所を、質問文では文字列リテラル中に\sと書いていることだ。\sは正規表現パターンとしては正しいが、Javaの文字列リテラルとして書くには、\をエスケープして\\sと書く必要がある。


演算方法を示す「たす」の部分は、(たす|ひく|かける|わる)のように書ける。
末尾の「は?」または「は?」の部分は、は[??]と書ける。

なお、質問文のは?だと、?が正規表現のメタ文字として解釈されてしまうので、は\?とエスケープする必要がある(文字列リテラルだと"は\\?")。もっとも、?は文字クラス[...]の内部ではメタ文字ではないので、文字クラスを使うならエスケープする必要はない。


以上をまとめ、文字列先頭と末尾にマッチするように^$を付加すると、入力文字列を一気にパースするための正規表現パターンは、

regex

1^([+-]?\d+(?:.\d+)?)\s+(たす|ひく|かける|わる)\s+([+-]?\d+(?:.\d+)?)\s+([??])$

となり、

Java

1var pat = "^([+-]?\\d+(?:\\.\\d+)?)\\s+(たす|ひく|かける|わる)\\s+([+-]?\\d+(?:\\.\\d+)?)\\s+(は[??])$"; 2var p = Pattern.compile(pat); 3var m = p.matcher(str);

とすれば、変数strに格納済みの文字列に対するマッチを行ない、m.matches()でパースできたかどうかを調べ、m.group(1)m.group(3)で実数部分の文字列を得て、それらを実数に変換してからm.group(2)で取得できる文字列に対応した演算を行なえばいいだろう。

一から書くなら、入力文字列全体を一気にパースせず、空白文字でsplitして分割した文字列それぞれに対してマッチ処理を書いたほうが楽だろう。実数部分のパターンが重複して出てくることも避けられる。

投稿2021/09/01 01:23

編集2023/03/01 02:29
Daregada

総合スコア11990

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問