ここから本文です

javaで文字列反転プログラムを作りたいのですが、 単純な文字列反転はできます。 ...

har********さん

2013/7/2420:08:51

javaで文字列反転プログラムを作りたいのですが、
単純な文字列反転はできます。
ですが、空白が入った場合その空白は反転後もその位置にあってほしいのです。
例:abc defg → gfe dcba

このようなプログラムを作りたいのですが中々思いつかず…。
どなたかわかる方いましたらソースを張ってもらえないでしょうか。

この質問は、活躍中のチエリアン・専門家に回答をリクエストしました。

閲覧数:
1,130
回答数:
5
お礼:
50枚

違反報告

ベストアンサーに選ばれた回答

khu********さん

2013/7/2503:59:42

ソースは貼りませんが、1つの処理案を書いておきます。

1.元の文字列から空白を全て探し出す。空白を見つけたら、その位置を配列に保存。
2.元の文字列から逆文字列を作る。ただし、その際、空白は全て無視する。結果として、空白の無い逆文字列が出来る。
3.元の空白位置を保存した配列を見て、逆文字列に空白を挿入する。配列が終端に達したら終了。

この回答は投票によってベストアンサーに選ばれました!

ベストアンサー以外の回答

1〜4件/4件中

並び替え:回答日時の
新しい順
|古い順

ii3********さん

リクエストマッチ

2013/7/3111:33:40

1.元の文字から空白を削除したものを反転。
2.元の位置に空白を挿入。
という流れにすればいいのでは?

//package haru06789.q10110771945;

public class Sample {
public static void main(String[] args) {
String src = "abc defg hijkl mnopqr stuvwxyz";

// 空白を削除したものを反転
StringBuffer buffer = new StringBuffer(src.replaceAll(" ", ""));
buffer.reverse();

// 元の位置に空白を挿入
int spaceIndex = -1;
while ((spaceIndex = src.indexOf(" ", spaceIndex + 1)) >= 0) {
buffer.insert(spaceIndex, " ");
}

System.out.println(buffer.toString());
}
}

ten********さん

編集あり2013/7/2521:59:34

haru06789さん
実は同じような質問が昔あって、その質問者様は私の回答がくるやいなや削除し、盗んでいった出来事がありました(笑)
彼はおそらく京都コンピュータ学院の生徒さんでしょうか。
この泥棒猫め!といってやりたい気持ちでいっぱいでしたので、疑っているわけではございませんが、どうかそんなことはしないでね(笑)
以下がそのときに回答した私のコードです。

----------------

やり方はたくさんありそうですね。

public class Main {

public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
String line = "";
for(String s : args) sb.append(s);
sb.reverse();
for(String s : args) {
line += sb.substring(0, s.length()) + " ";
sb.delete(0, s.length());
}
System.out.println(line.trim());
}
}

サクッと動かしたいならこんな感じでもよろしいのではないかな。
こんなのでも一応、
・1つの単語にも対応
・空白等にも対応?
くらいは満たせていますね

以下実行例です。

java Main kyoto computer gakuin

niuka gretupmo cotoyk

しかし良い問題ですな~

[追記」
コメントをつけていませんでしたので簡単に説明します。
・StringBuilder sbを用意してappend()メソッドでとにかく引数をぶち込みます。
・reverse()メソッドでひっくり返してやります。
・あとは用意した変数lineに、「sbの先頭から、ある引数の文字数番目までの文字列」と「空白" "」を加えます。
・lineへ既に加えた分はdelete()関数で削除してやります。
・最後のtrim()メソッドは愛情です。(笑)

アバター

編集日時:2013/7/19 07:43:29
回答日時:2013/7/18 11:19:11

-----------ここまで

[この質問に関する追記]
私はharuki_yawataさんのコードも遠回りしすぎて逆に分かり辛いものになって損している部分が大きいと感じますね。
さすがに私のコードは簡素化しすぎているかもしれませんし、オブジェクト指向的でもないですが、しかしながら
StringBufferクラスには最初からreverse()メソッドがあるのにそれを活かせていない点がとても残念に感じます。
http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.ht...

あと、
>空白が入った場合その空白は反転後もその位置にあってほしいのです

とのことですが、空白の位置が引数をもってして実行した時点で「絶対的」に決まっているのだから、「全部ひっくり返してから空白を挿入」すればいいのでは?
と私は思ってしまいます。(以降に1文字ずつ調べる必要があるだとか、そういうときのために設計しておくだとかなら話は別ですが。)

と、書きましたがmainメソッドの引数に指定するとは限らないですね。ですが同じ要領でできます。

public class Main {

public static void main(String[] args) {

String str = "abc defg";
String[] words = str.split(" ");
StringBuffer sb = new StringBuffer();
for(String s : words) sb.append(s);
sb.reverse();
String line = "";
for(String s : words) {
line += sb.substring(0, s.length()) + " ";
sb.delete(0, s.length());
}
line = line.trim();
System.out.println(line);
}
}

[出力]
gfe dcba

わざわざ空白を挿入してから(または挿入したままの状態で)反転するのはナンセンスだと思います。

har********さん

編集あり2013/7/3119:42:59

◇単純な文字列反転はできます
文字列反転の処理を少し応用すれば良いです。

◇空白が入った場合その空白は反転後もその位置にあってほしいのです
元の文字列から1文字読み込み、反転後の文字列には後ろから前へ、読み取った文字を書き込みます。
ここまでは普通の文字列反転と同じです。

その際、事前に反転後の文字列に元の文字列をコピーしておきます。
そして読取り処理には空白文字を読み飛ばす処理を追加し、書き込み処理では書き込み先が空白なら次の書き込み先(1つ前)に移動する処理を追加します。

反転する処理をメソッドにしたものは、以下のようになります。
private static StringBuffer reverseString(final String targetStr){
StringBuffer reversedStr = new StringBuffer(targetStr);

for (int targetIndex = targetStr.length()-1, originIndex = 0; targetIndex>=0; targetIndex--, originIndex++){
if (targetStr.charAt(originIndex)!=' '){ //空白文字は読み飛ばす
while (reversedStr.charAt(targetIndex)==' ') targetIndex--; //空白部分には書き込まない
reversedStr.setCharAt(targetIndex, targetStr.charAt(originIndex));
}
}
return reversedStr;
}

空白位置を変えずに反転した文字列を戻り値として返します(StringではなくStringBufferクラスを使用している理由は、ご自分で調べてみて下さい)

garen_mpegさんの回答には3点間違いがあります。
◆効率を考えてないんで適当ですが
このような処理では効率よりもまず読みやすさ、処理の簡潔さを考えるべきですから、余計な断り書きです。

◆例外チェックとかまったくしてないですし、
例外チェックすべきところはありません。
この処理で例外が発生するなら、それはプログラムミスしかありません。
例外を受け取っても、プログラム中では処理のしようがありませんから、さっさと例外で異常終了すべきです。

◆動かしてないのでアレですが・・・
動かせば分かるというものではありませんが、拡張for文を使って配列の要素を読み出している処理は誤用です。
拡張for文の仕様では、要素を取り出す順序が保証されません(この意味が分からないなら、回答する前に勉強し直して下さい)。
うまく処理されても、それはたまたまということです。

--- 補足その他(2013.7.31)---
ii3pvy63さん:
なぜとっくにtentekominorさんが回答されているプログラムと同じ物を、自分の回答として回答されているのでしょう。
いつもながら、意味不明です。

tentekominorさん:
◇haruki_yawataさんのコードも遠回りしすぎて逆に分かり辛いものになって損している部分が大きいと感じますね
ご指摘ありがとうございます。
haru06789さんの質問に文字列の反転はできるとあったので、そこからあまり論理が飛躍しない事を優先しました。
Stringクラスのメソッドやコレクションクラスは、まだ敷居が高いかと思います。

garen_mpegさん:
◇javaの場合、今回のような配列などなら、先頭から順に参照するようにコンパイルするのでは?
現状の実装では、その通りです。
だからうまく動作します。
けれども、拡張for文の仕様には順序が保証されないと明記されていますので、実装に頼った処理は禁じ手です。
現場でもそうですが、初学者に例示するプログラムとしては更に罪深いでしょう?

gar********さん

編集あり2013/7/2517:00:33

効率を考えてないんで適当ですが

String noSpaceTarget = target.replace(" ","");

// noSpaceTargetを反転して、noSpaceTargetに代入しておく

char[] targetArray = target.toCharArray();
char[] noSpaceTargetArray = noSpaceTarget.toCharArray();

int i = 0;
for(char c:noSpaceTargetArray){
if(targetArray[i]==' '){
i++;
}
targetArray[i++] = c;
}

return String.valueOf(targetArray);

こんな感じでどうですかね。
例外チェックとかまったくしてないですし、
動かしてないのでアレですが・・・


>追記。
上記のソースでは空白文字が2つ以上連続する場合、期待する動作になりません。
haruki_yawataさんが行っているように空白文字のスキップ処理が必要です。


以下、haruki_yawataさん宛になってしまうのですが、

>このような処理では効率よりもまず読みやすさ、処理の簡潔さを考えるべきですから、余計な断り書きです。
おっしゃる通りです。


>例外チェックすべきところはありません。
>この処理で例外が発生するなら、それはプログラムミスしかありません。
>例外を受け取っても、プログラム中では処理のしようがありませんから、さっさと例外で異常終了すべきです。
確かにArrayIndexOutOfBoundsExceptionなどは発生させること自体控えるべきですし、明らかなプログラムミスです。
ですが例外チェックだけでなく、nullチェックなども含めての表現だとご理解ください。
また最悪そういった自体が発生してしまった場合、Logなどを出力することも人によってはあると思います。
他にも、環境の面で言うなら、安易に異常終了させるべきではない環境も存在します。(Androidなど)


>動かせば分かるというものではありませんが、拡張for文を使って配列の要素を読み出している処理は誤用です。
>拡張for文の仕様では、要素を取り出す順序が保証されません(この意味が分からないなら、回答する前に勉強し直して下さい)。
>うまく処理されても、それはたまたまということです。
連想配列なら確かに不定ですが、javaの場合、今回のような配列などなら、先頭から順に参照するようにコンパイルするのでは?
と思うのですが、わざわざ指摘してくださっているということは誤認している仕様なのだと思います。
仕様を確認してみようと思います。


曖昧な表現や未熟な知識で回答をして不快な思いをされたなら、申し訳ありません。

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる