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

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

ただいまの
回答率

87.90%

数字を含んだ文字列の数字の範囲が適正か調べたい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,158

score 37

Javaの質問です。

boolean TRUE = false;
String S = 1111s334s124s214s124;


というプログラムで、数字を含んだ文字列があった場合、sで区切られた文字列の中の数字が、すべて0以上1999以下の数字である、ということを調べたいです。

String[] S2 = S.split("s");


として、配列に分配後に

for(String s_2 : S2){
  if(s_2.equals([0-1999]){
    TRUE = true;
  }else{
    TRUE = false;
  }
}


という感じでするのですが、(s_2.equals([0-1999])ではうまくいきません。
やはり、s_2の中の数値を表す文字をあらたなint型の配列に変換しておさめていき、その数字が0から1999の範囲内である、という調べ方しかないのでしょうか?
よろしくお願いします。

---追記---

正規表現を使って、上の問題のプログラムを作ってみました。

import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class main{
    public static void main(String[] args){
        String S = "1111s0123s0124s0214s0124";

        Pattern p = Pattern.compile("[0-1]{1}[0-9]{3}s[0-1]{1}[0-9]{3}s[0-1]{1}[0-9]{3}s[0-1]{1}[0-9]{3}s[0-1]{1}[0-9]{3}");
        Matcher m = p.matcher(S);

        System.out.println(m.find());
    }
}


というようになりました。

String S = "1111s0123s0124s0214s0124";


のところなのですが、すべての数字の部分を4桁表示にしないとうまくいきませんでした。
(Pattern p = Pattern.compileの正規表現チェックで、すべて0000~1999を調べているので)

String S = "1111s123s124s214s124";


上のような4桁と3桁の数字の混ざった文字列の場合、
一旦、sで区切った文字をsplit("s")してから、何桁か調べて、その桁数によって、

Pattern p = Pattern.compile


で調べる方法を複数用意するのが良いのかなと思いました。

質問時には、数値変換してからチェックする、以外の方法は思いつきませんでしたが、知識の深い方からのアドバイスにより、正規表現でのチェックという方法があると知り、上のようなプログラムを作り、一応、ここに念のため、記させていただきました。
以上となります。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

(s_2.equals([0-1999])ではうまくいきません。

すみません、逆になんでそう書けると思ったのかお聞きしたいです。
言語は文法が厳格に決まっているのであって、なんとなく書いて動かすものでは無いです。

やはり、s_2の中の数値を表す文字をあらたなint型の配列に変換しておさめていき、その数字が0から1999の範囲内である、という調べ方しかないのでしょうか?

他の方法もあるかもしれませんが、数値に直していくのが一番自然で書きやすいかと。
もちろん実装はいろいろ考えられますから、int[]型の変数が必須というわけではないです。

こんなふうにも書けますし。

static boolean isValid(String src) {
    return Arrays.stream(src.split("s"))
        .mapToInt(Integer::parseInt)
        .allMatch(n -> 0 <= n && n <= 1999)
    ;
}

あと、変数名はもうちょっと考えて付けましょう。

boolean TRUE = false;

『TRUEの値がfalse』って、禅問答のような状況になっています。
真偽値であることは見れば誰でも分かるんですから、『何のための』真偽値か分かるようにしましょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/23 18:08

    ありがとうございました!
    booleanの変数名をきちんと気をつけるようにします!
    自分では気づかなかったです。。
    ご指摘をしていただき、ありがとうございました!
    なにかあれば、また教えていただければありがたいです。
    また、なにかありましたら、よろしくお願いします!
    ありがとうございました!

    キャンセル

+1

split("s") してから処理をする方針で書いてみました。

import java.util.regex.Pattern;

public class Parse {
    public static void main(String[] args) {
        String STRS[] = { 
                "abcsABC",
                "123",
                "1111s334s124s214s124",
                "12ss3",
                "1.2sabc",
                "99999999999999999999999999999999999999999999999999s1"
               };

        Pattern pattern = Pattern.compile("\\d");
        for (String str : STRS) {
            if (pattern.matcher(str).find()) {
                System.out.println(check(str) + ":\t'" + str + "'");
            }
        }
    }

    static boolean check(String str) {
        for (String num_str : str.split("s")) {
            try {
                int x = Integer.parseInt(num_str);
                if ((x < 0) || (1999 < x)) {
                    return false;
                }
            } catch (NumberFormatException e) {
                return false;
            }
        }
        return true;
    }
}

小数点があったり、int の範囲外の大きな数値のチェックもできています。
実行例:
イメージ説明

追記:
split() を使わずに正規表現で数字部分を取り出す方法で書いてみました。
0 - 1999 の値の範囲の数値であることも正規表現でチェックすることは可能ですが、
範囲が 3 - 1998 なんてふうになったときに対応が困難です。
数値範囲については、parseInt() してチェックするようにしています。
(正規表現で 4 桁以内の数字列しか渡らないはずなので parse 時の Format 不正例外は発生しないはず)

package teratail;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Parse {
    // 数字を含んでいるか?
    private final static Pattern pattern_0 = Pattern.compile("\\d");
    // "数値s数値s ... 数値" のパターンか?
    private final static Pattern pattern_1 = Pattern.compile("^((\\d{1,4})s)+(\\d{1,4})$");

    public static void main(String[] args) {
        String STRS[] = { 
                "abcsABC",
                "123",
                "1111s334",
                "1s2s3s4s5s6s7s8s9",
                "1111s334s124s215s126",
                "1111s334s124s215s1999",
                "1111s334s124s215s2000",
                "12ss3",
                "1.2sabc",
                "99999999999999999999999999999999999999999999999999s1"
               };
        for (String str : STRS) {
            if (pattern_0.matcher(str).find()) {
                System.out.println(check(str, pattern_1) + ":\t'" + str + "'");
            }
        }
    }

    static boolean check(String str, Pattern pattern) {
        Matcher m = pattern.matcher(str);
        if (!m.find()) {
            return false;
        }
        int count = m.groupCount();
        for (int i = 1; i <= count; i++) {
            int x = Integer.parseInt(m.group(i).replace("s", ""));
            if ((x < 0) || (1999 < x)) {
                return false;
            }
        }
        return true;
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/23 21:42

    ありがとうございました!
    関数で判定を返すという手法に気づかなかったです! こういう使い方もあるのですね。
    拡張forの宣言のときに"s"で区切った文字をnum_strに入れて、それからすぐに数値に変換して、ifで判定する、という無駄のない流れが、本当に勉強になりました!
    自分でやると、拡張forは思いつかず、関数も思いつかず、なかなかうまくいかなかったので、参考にさせてもらいたく思います!
    この度は親切に教えて頂きまして、ありがとうございました!

    キャンセル

  • 2018/09/23 23:38

    split() なく、正規表現をつかって書式チェック・数字文字列の取り出しをすることもできる気がしています。try してみることをおすすめします。

    参考情報
    - Matchesメソッドで一致したすべての部分を抽出する方法
    https://www.sejuku.net/blog/54264#Matches

    キャンセル

  • 2018/09/24 09:59

    ご返信をいただき、ありがとうございました!
    さっそく、調べながら、split()なしの正規表現でのプログラムに挑戦してみました。
    プログラムをコメント欄に載せてはいけないかと思いまして、上の投稿欄にプログラムを追記として記させていただきました。
    正規表現でのチェックは数字を4桁にすればうまくいくのですが、3桁が混じるとうまくいきませんでした。(正規表現での調べ方を文字列の中の数字の桁数と合わせるか、数字の桁数を正規表現の調べ方の桁数に合わせる必要がありました)
    また、プログラムを作る流れでPatternやMatcherというものがあることが知れて、勉強になりました!
    今回はいろいろと教えてくださって、ありがとうございました!
    それでは、失礼します。

    キャンセル

  • 2018/09/24 15:14 編集

    追記を書いていただき、ありがとうございます!
    書いていただいたプログラムを調べつつ、勉強させて貰いました!
    正規表現に対する知識やPatternの使い方、Matcherの使用方法に対する知識が増えたので、とても勉強になりました!
    この度は教えてくださって、ありがとうございました!

    キャンセル

+1

追記に回答
splitせずにPattern1パターンでできます。

Pattern p = Pattern.compile("^(([01][0-9]{3}|[0-9]{1,3})s)*([01][0-9]{3}|[0-9]{1,3})$")


[01][0-9]{3}で「千の位が0か1の4桁の数」を、[0-9]{1,3}で「3桁の数」を表現できます。
ただ先頭に0を許すのなら、"0000032"なども受け入れられるようにするべきなのでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/24 15:22 編集

    ご返信いただき、ありがとうございました!
    [01][0-9]{3}|[0-9]{1,3})という|という書き方がとても勉強になりました!

    >ただ先頭に0を許すのなら、"0000032"なども受け入れられるようにするべきなのでしょうか?
    私の投稿欄に追記したプログラムでは、先頭に0を許すとしてしまったのですが、[1][0-9]{3}|[0-9]{1,3}とすれば、良いようですよね。。
    次からはこういう点になるべく気をつけて、プログラムが書けるようにしたいです。
    この度は教えてくださって、ありがとうございました!

    キャンセル

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

  • ただいまの回答率 87.90%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る