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

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

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

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

Q&A

解決済

3回答

677閲覧

ぶじかいけつしました

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

1クリップ

投稿2021/12/25 07:03

編集2022/03/03 10:30

前提・実現したいこと

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

該当のソースコード

補足

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

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

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

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

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

m.ts10806

2021/12/25 08:26

再現するコードを提示してください。 あと、出ているエラーメッセージからすると「String型配列とchar型配列の違い」ではないですよね。
Crimson_Tide

2021/12/25 08:33

コードを、提示してください。 質問者さんの考える手順に基づいて、実際にどのような実装したかは他の人にはわかりません。 手順の問題ではなく、実装の問題ではないかと想像しています。
退会済みユーザー

退会済みユーザー

2021/12/25 08:45

回答ありがとうございます。 大変失礼しました。 コードを記載しましたので、もしよろしければアドバイスのほどよろしくお願いいたします。
jimbe

2021/12/25 10:11

各配列要素には 1 文字しか入っていないのに, charAt(i) , charAt(j) している所為でしょう。
Crimson_Tide

2021/12/25 14:12

・当該コードでは1文字の文字列比較ですが、"a","aa","ab","abc"など長さが異なる文字列、1文字以上の文字列を想定していますか? > string→charに変換し、文字列コードで比較 「文字列コード」とは何でしょうか? 1文字の文字列の比較であれば、「string→charに変換し、(適切に)"文字コード"を比較」でいいですが、適切に文字コードが比較できてない実装上の問題ですね。 以下、問題点を最低限修正した上で、 asc()メソッドの二重for ループ内の 変数i 、 j と 配列変化の推移を表示したものです。 並べ替えの処理で無駄な処理をしていることがわかるでしょうか。 i:0 j:0 b a c i:0 j:1 b a c i:0 j:2 b a c -> c a b i:1 j:0 c a b -> a c b i:1 j:1 a c b i:1 j:2 a c b i:2 j:0 a c b i:2 j:1 a c b -> a b c i:2 j:2 a b c ソートアルゴリズムを学習するか、そうでもなくとも適切な並べ替えの方法がないか考慮すべきです。 ・あまり指摘するとデバッグ代行になるので控えたいですが asc()メソッド内の「return;」はどういう意図で記述したのでしょうか? sampleクラスの5行目の「 s.getAry();」はどういう意図で記述したのでしょうか? エラーが起きたときは、ざっくり以下のような流れで対応するものかと思いますがどこまでできていますか? 1)エラーメッセージの意味を把握 2)エラー箇所の特定 3)エラー発生原因の特定 4)原因箇所の修正 5)動作確認 6)エラーが解消されなければ2)に、新たなエラーが出たら1)に戻る せいぜい1)2)ぐらいしかやってるようには見受けられないので、低評価が付いてるのだと思います。
YT0014

2021/12/26 00:55

import仕様禁止以外の制限はないのでしょうか? あるのなら、ご提示ください。ないのなら、java.lang.Stringの仕様を詳細にご確認ください。
kazuma-s

2021/12/26 07:13

完全修飾名を使えば import は要りません。 java.util.Arrays.sort(ary);
guest

回答3

0

ベストアンサー

質問のコードが変更されて、配列の要素数が 5 になり、各文字列の長さが 3 に
なりました。ary.length は 5 です。i も j も 0~4 になります。
.charAt(j-j) ってなんですか? .charAt(0) ですか?
.charAt(i) で i が 3 になると、それは文字列の最後の文字を超えています。

String ではなく、int で正しくソートできるようにしてみてください。

java

1class Main { 2 public static void main(String[] args) { 3 int[] a = { 456, 546, 645, 123, 231 }; 4 for (int i = 0; i < a.length; i++) 5 for (int j = i+1; j < a.length; j++) 6 if (a[i] > a[j]) { 7 int t = a[i]; a[i] = a[j]; a[j] = t; 8 } 9 for (int i = 0; i < a.length; i++) System.out.println(a[i]); 10 } 11}

a[i] が int ではなく、String の場合、a[i] > a[j] とは書けないので、
a[i].compareTo(a[j]) > 0 にします。

追記
compareTo を使うと簡単なんですが、面倒な charAt でやってみました。

java

1class Sort { 2 protected String[] ary = { "abc", "bac", "cab", "123", "231" }; 3 4 public int getIdx() { return ary.length; } 5 6 public String[] getAry() { return ary; } 7 8 public void asc() { 9 for (int i = 0; i < ary.length; i++) 10 for (int j = i+1; j < ary.length; j++) { 11 int k, n = ary[i].length(), m = ary[j].length(); 12 if (n < m) m = n; 13 for (k = 0; k < m && ary[i].charAt(k) == ary[j].charAt(k); k++) ; 14 if (k < m ? ary[i].charAt(k) > ary[j].charAt(k) : n > m) { 15 String t = ary[i]; ary[i] = ary[j]; ary[j] = t; 16 } 17 } 18 } 19} 20 21class Sample { 22 public static void main(String[] args) { 23 Sort s = new Sort(); 24 s.asc(); 25 for (int i = 0; i < s.getIdx(); i++) 26 System.out.println(s.getAry()[i]); 27 } 28}

if文の式に三項演算子(?:)を使う変態プログラムです。
もっと分かりやすいのを書いてくださいね。
ところで、asc ってどういう意味ですか?

投稿2021/12/26 09:25

編集2021/12/27 13:52
kazuma-s

総合スコア8224

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

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

退会済みユーザー

退会済みユーザー

2021/12/26 09:35

kazuma-sさん、アドバイスありがとうございます! そうですね、一つずつしっかりとこなしていきます!
退会済みユーザー

退会済みユーザー

2021/12/27 13:43

ぱっと見私の実力ではまだ分からないので、ゆっくり解読、理解してみます! 本当にありがとうございます! ascはascending orderで昇順の略です! ちなみに降順はdescending orderでdescです。
guest

0

「文字列配列の添え字」と、「文字列を文字配列として見た時の添え字」を混在してしまっています。

asc メソッド内の 2 つの for 文は

java

1for (int i = 0; i < ary.length; i++) { 2 for (int j = 0; j < ary.length; j++) {

i, j どちらも「文字列配列の添え字」を表すためのものです。

内部の if 文の条件式では

java

1ary[j].charAt(j) 2ary[i].charAt(i)

のどちらも ary の添え字と charAt メソッドのパラメータに同じ変数を使用しています。
この為、文字列配列 ary の各要素を順に見る為に i や j が 0 → 1 → 2 と変化すると、同時に charAt のパラメータも 0 → 1 → 2 と変化することになり、
ary の 0 番目の文字列 "a" の 0 文字目 → 'a'
ary の 1 番目の文字列 "b" の 1 文字目 → 無いのでエラー
となってしまいます。

charAt に指定すべきは「文字列を文字配列として見た時の添え字」であり i でも j でもありませんので、 対象の文字列の長さに合わせてもう 1 つループを入れる等が必要でしょう。

まぁ・・・このままアルゴリズムの理解も乏しく闇雲にコードを弄り続けるよりは、「バブルソート」といったキーワードでアルゴリズム・サンプルコードを探したほうが良いようには思いますが。

投稿2021/12/26 08:23

編集2021/12/26 08:28
jimbe

総合スコア13209

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

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

退会済みユーザー

退会済みユーザー

2021/12/26 08:40

jimbeさん、アドバイスありがとうございます! 現在デバッグ中でjimbeさんから頂いたアドバイスの部分が抜けているのでは仮説を立てていた最中だったので、仮説が一応正しかったと自信を持てました。 誠にありがとうございます!
guest

0

思考停止するならプログラミングやめた方がいいです。

まず、エラーメッセージぐらいは読みましょう。

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3 [訳] mainメソッドにて例外発生っす。 java.lang.StringIndexOutOfBoundsException ってやつっす。 文字列のインデックス(添え字)が範囲外を指しているっす。3番目っすね…

っていう感じでしょうか。

このjava.lang.StringIndexOutOfBoundsExceptionは公式リファレンスで調べると、

String メソッドによりスローされ、インデックスが負または文字列のサイズより大きいことを示します。charAt などのいくつかのメソッドでは、インデックスが文字列のサイズと等しい場合にも、この例外がスローされます。

とあります。つまり、簡単に言えば、『範囲外系例外』ってところです。

文字列はプログラマ的にはJavaを使っている場合は単なる変数に入れているように見えますが、おそらく内部では配列として保持しているはずです。C言語みたいに。ただ、わかりづらいのであえて意識させない作りになっているのだと思います。

つまり、要素数10の配列を arr[100]のようにアクセスしたりしているような状態です。

5階建ての建物に15階に行こうとしているような状態です。無理ですから。

つまり、『アクセスできないところを参照している』みたいな感じです。

[今後気をつけるべきこと] 1. エラーメッセージを読もう 2. 情報を省くな 3. 思考停止するな 4. 自分なりに調べよ 5. 試したことを書くべき

ーーー
[追記1]

当たり前でしょ…

そもそもプログラミングってのは『すでにあるコードを切り貼りして作ること』ではありません
ロジックを書くのです。数学の証明を自力で考えるようなものです。

とりあえず、コードを読みましょう

コードを読むコツは『一行レベルで、その行が何をしているかを考えながら読む』です。

まずはmainメソッドから読んでみましょう。

Java

1class Sample { 2 public static void main(String[] args) { 3 // Sortクラスをインスタンス化 4 Sort s = new Sort(); 5 // 生成したオブジェクトのAACメソッドを呼び出す 6 s.asc(); 7 // sが持つgetAryメソッドを呼び出す 8 s.getAry(); 9 // iの初期値: 0, i が sのgetIdxメソッドが返すものより大きい間, 増加しながら繰り返す 10 for (int i = 0; i < s.getIdx(); i++) { 11 // sのgetAryメソッドを呼び出してその返ってきたやつのi番目にアクセスして出力 12 System.out.println(s.getAry()[i]); 13 } 14 } 15}

これを手作業でやると考えてみてください。数学の手順とかでもいいです。とにかくシミュレーションしてください。
そうすると、三行目の『sが持つgetAryメソッドを呼び出す』がちょっと意味わかりませんね。
名前から察するに『オブジェクトが持つ配列を取得する』ってところでしょうけど、何も受け取っていません。
だったら呼び出す必要なくない?

さらに、今までに呼び出されたメソッドやコンストラクタ内も同様にやる。

コンストラクタはデフォルトのやつ(デフォルトコンストラクタ)のようなのでスルー。

getAryメソッドは名前通り、単にフィールドとして持っている配列を取得するだけ。getIdxメソッドは意味不明(名前と処理が合っていない)ですが、処理内容を見ると単に要素数を返しているだけですね。

なので ascメソッドを読んでみましょう。

Java

1 public void asc() { 2 // iについて、要素数分ループ(先端から末端へ) 3 for (int i = 0; i < ary.length; i++) { 4 // jについて、同上 5 for (int j = 0; j < ary.length; j++) { 6 // (j,j)の位置データと(i,i)の位置のデータを比較し、(j,j)が大きければ 7 if ((int) ary[j].charAt(j) > (int) ary[i].charAt(i)) { 8 // 交換アルゴリズムによる交換 9 String tmp = ary[i]; 10 ary[i] = ary[j]; 11 ary[j] = tmp; 12 // メソッド終了! 13 return; 14 } 15 } 16 } 17 }

これを疑似コードとして書きだす。

pseudo

1[疑似コード] 2 31. iについて、要素数分、以下をループ(先端から末端へ) ( i = 1, 2, 3, ... ) 4 1.1. jについて、要素数分、以下をループ(先端から末端へ) ( j = 1, 2, 3, ... ) 5 1.1.1. (j,j)の位置データと(i,i)の位置のデータを比較し、(j,j)が大きければ 6 1.1.1.1. 交換アルゴリズムによる交換 7 1.1.1.2. メソッドの終了!

これを実際にシミュレーションしてみてください。実際にi,j,ary等にデータを入れて計算してみるとか。

そうすると、まず (1)で i = 0 となります。(1.1)では j = 0 となり、i = 0, j = 0 となる。
(1.1.1)で (0,0) と (0,0) を比較。つまり、Excelの表みたいに見て、0行0列のデータを比較するのです。
同じ場所を比較しているので大きいも小さいもありません。なので(1.1)に戻る。

(1.1)で j を進ませる。つまり、i = 0, j = 1 となる。そのまま(j,j) > (i,i)を比較。

(1,1) > (0,0) なのですが、対象となっている配列はString[] ary = { "b", "a", "c" };のようです。要素数はそれぞれ1で、配列は0番目から始まるので 0~(n-1)番目 までしかアクセスできません。

つまり、1行目は "a"ですが、1列目は無いです。'a' が 0番目なので。

そうなると、「んなもんねーよ!!!」となってしまいますね。

101番目までしかないコインロッカーを『109番目から取り出して来い』と言われているようなものです。無理でしょ…

そもそも無理なので、「おーーーい、そんな場所ないぞ?」という例外が投げられているだけです。

それと他の方も仰っているように、デバッグしましょう

大雑把なやり方は上記での「コードを読む」と大体一緒です。単にデバッガを使うのか、いわゆるprintfデバッグでやるのか、コードのみでやるのかとかの違いだけです。

投稿2021/12/25 07:53

編集2021/12/27 00:21
BeatStar

総合スコア4962

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

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

退会済みユーザー

退会済みユーザー

2021/12/25 08:52

BeatStarさん、回答ありがとうございます。 コードを省略し申し訳ありませんでした。 また、情報を省いてしまったのにも関わらず、アドバイスをしてくださりありがとうございます。 コードを記載しましたので、もしよろしければ改めてアドバイスを頂けると幸いです。
退会済みユーザー

退会済みユーザー

2021/12/26 08:36 編集

BeatStarさん、たくさんのアドバイスありがとうございます! BeatStarさんをはじめ皆様からのアドバイスをもとに現在デバッグ中です。 アドバイスをいただいた、1文ずつ確実に理解していく方法で少しずつではありますが、自分のコードに何が足りないのかが見えてきました。 誠にありがとうございます。 引き続きデバッグ頑張ります!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問