- ベストアンサー
スペースを空けて端を揃えて表示する方法
- スペースを空けて表示したとき、縦に綺麗に揃えて表示する方法について質問です。
- 各行の左側に英単語を表示し、右側にその単語の座標を表示したいですが、文字の長さによって揃わないことがあります。
- スペースの数を調整することで、綺麗に揃えて表示することができます。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
5分遅れで同じ回答をしてしまった(^^; ついでなので、もう少し文字種の範囲を広げても大丈夫なものを作成してみた。 public static void main(String[] args) { String[] word = {"りんご", "おranじ", "犬", "fortunately"}; String[] coord = {"(2,8) (3,6)", "(3,7) (9,8) (2,10)", "(3,0)", "(6,6)"}; java.nio.charset.Charset charset = java.nio.charset.Charset.forName("Shift_JIS"); int width = word[0].getBytes(charset).length + 15; for (int i = 0; i < word.length; i++) { String format = "%-" + (width - word[i].getBytes(charset).length + word[i].length()) + "s%s%n"; System.out.printf(format, word[i], coord[i]); } } 前提として、 与えられた文字がシフトJISで表せるようなもので、 シフトJISで1バイトコードになるものがいわゆる半角(1桁幅)、 2バイトコードになるものがいわゆる全角(2桁幅)となるのなら、 上のようにすることで対処できる。 要点は文字数でなく文字を構成するコードが何バイトかを数えて、 2バイトなら2桁分のスペースを用意する。 これには、getBytesでStringからバイト配列を得てlengthでバイト数を得る。 今度は書式文字列は各行ごとに変わる可能性がある。 widthはword[0]の文字列幅に15スペース分を加えたもの。 "apple"でなく"りんご"なので21になる。 つまり座標の表示は22桁目からということになる。 各行の書式文字列での、 (width - word[i].getBytes(charset).length + word[i].length()) で、バイト数と文字数との差を求めて表示幅から引くことで、 1文字が2桁になる場合に対処している。 書式は使いどころによって便利なもので、 printfで書式出力するところを、 StringクラスのformatメソッドでStringインスタンスにすることもできたりする。
その他の回答 (6)
- magicalpass
- ベストアンサー率58% (378/648)
#1です プログラミングの学習等で固定ピッチだという前提があれば、スペースでの位置合わせというのは有効ですが、現実にアプリ等を作っていく上では通用しないことがあるということです。 また、実用的なアプリの多くはGUI環境で作られますから、コンソールに文字を表示する感覚とは違ってきます。GUIの画面上で文字を表示するならAWT等を使って、 g.drawString("文字列", x, y); みたいなやり方で座標指定して文字を表示します。 こういう方法を使えば、厳密に位置合わせができるというわけです。(表示の開始位置だけだけど) 英単語の開始位置をx1、座標の開始位置をx2で揃え、縦の位置yを1行の幅ずつ増やしていけばきちっと揃った状態で表示できるようになるわけです。
- Takuya0615
- ベストアンサー率21% (329/1502)
エクセル使えば早くない?
- vaguechat
- ベストアンサー率85% (47/55)
固定ピッチ端末で使用することは大前提であるとして、 シンプルにやるのならC言語でおなじみの書式付き出力を利用する方法がある。 public static void main(String[] args) { String[] word = {"apple", "orange", "dog", "fortunately"}; String[] coord = {"(2,8) (3,6)", "(3,7) (9,8) (2,10)", "(3,0)", "(6,6)"}; String format = "%-" + (word[0].length() + 15) + "s%s%n"; for (int i = 0; i < word.length; i++) System.out.printf(format, word[i], coord[i]); } printfメソッドが書式による出力を行うメソッドであり、 formatがその書式を定める文字列になる。 formatは上のサンプルであれば "%-20s%s%n" という文字列になる。 前半部の"%-20s"はprintfメソッドの書式文字列を除いた最初の引数、つまりword[i]に対する書式、 次の"%s"はその次の引数coord[i]に対する書式を表す。 最後の"%n"は改行を表す。 "%s"というのは丁度必要な幅を確保した文字列という意味であり、 "%20s"のようにすると20桁分の幅を確保し、その中で文字列は右寄せという意味になる。 "%-20s"のように"-"をつけることで左寄せの意味になる。 つまり、"%-20s%s%n"をprintfメソッドに与えることは、 20桁分の出力欄を確保してその欄の中で左寄せでword[i]を出力し、 その次の桁、つまり21桁目からcoord[i]を出力し、 最後に改行を出力することの意となる。 この書式文字列"%-20s%s%n"をプログラム自身が動的に作っているのが、 "%-" + (word[0].length() + 15) + "s%s%n" の部分。 > 最初の単語(apple)で15個のスペースを置き座標を表示するので、以下の単語はそれにあわせて表示する とのことなので、 (word[0].length() + 15) はword配列の最初の要素"apple"の文字数を数え、 さらにスペース分の15を加えた20という値を計算し、 その前後に残りの書式文字列のパーツを足して、書式文字列としている。 ただし、上のサンプルでは解決の難しい問題、unicode文字の表示幅判定の問題を抱えている。 例えば、word[i]が英単語だけならいいが、どれかを漢字などのいわゆる全角文字にすると表示が崩れる。 文字種を限っていけば簡単な判定の方法があるがunicode全般での判定は難しい。 word[i]を普通の英単語に限るなら判定しなくて済むので一番簡単になる。 これは質問者の問題領域次第なので、とりあえず一番簡単でいいもの前提にした。 もう一つ、サンプルでは補助文字に対応していないが、 こちらも質問者の問題領域次第なのであまり気にしなくていいかもしれない。 文字数数えを (word[0].codePointCount(0, word[0].length()) + 15) にすれば補助文字に対応するが、文字幅判定の方が実用上は大きい問題なのであまり意味がない気がする。 printfメソッドの書式の仕様についてはjava.util.Formatterクラスの文書に詳細がある。 C言語のprintf関数について検索してみても参考になると思う。 特にサンプルは文字列前提だったが数値を出力したい場合などは自分で調べてほしい。 また、たとえば、座標を複数個の数値などを要素とする配列やコレクションで持っている時に、 一行に複数の座標を出力する場合は、書式付きでword[i]だけを先に出力して、 さらに座標を個数分出力した後、改行するなどすればいいと思う。
- ketuago65
- ベストアンサー率50% (13/26)
すいません思い出しました。 printfをつかって簡単にできました。 main()のループの中身を↓に変えると簡単にできます。 System.out.printf("%-20s%s\n",words[i],coo[i]);
- ketuago65
- ベストアンサー率50% (13/26)
もっと簡単な方法があった気もしますが、ぱっと思いついたのでとりあえず。 public static void main(String[] args){ String[] words = {"apple","orange","dog"}; String[] coo = {"(2,8) (3,6)","(3,7) (9,8) (2,10)","(3,0)"}; for(int i = 0; i < words.length;i++){ System.out.print( words[i] ); printSpace(words[i]); System.out.println( coo[i] ); } } public static void printSpace(String word){ String space = " "; for(int i = 0; i < 15 - word.length(); i++){ System.out.print(space); } } こんな感じに英単語の長さにあわせて毎回ループでスペースを表示させれば上手くいく と思います。 まぁもっといい方法があると思うので他の方のでいい方法があればそちらでお願いします^^;
- magicalpass
- ベストアンサー率58% (378/648)
どういう環境で動作するものなのかによって違ってくるので一概には言えませんが…… とりあえず、一律に15個のスペースじゃ位置が揃わないのは理解されてますよね? MS-DOSマシンのような完全なフォントピッチ固定の環境ならスペースを調整することで位置を揃えることは出来ますが、昨今のPC環境はそんな単純なものではないので、たとえ固定ピッチのフォントを使ったとしてもスペースの幅が文字幅と違ったりするので、この方法は良いとは言えないでしょう。 各行を行単位で一括に処理するのではなく、英単語の項目と座標の項目は分け、それぞれ独自に座標を指定して表示するのが適切な方法だと思われます。
補足
すみません、間違えました。すべての場合に15個分のスペースでは揃うわけないですよね・・・。 最初の単語(apple)で15個のスペースを置き座標を表示するので、以下の単語はそれにあわせて表示する、でした。 magicalpassさんの言うように、単語と座標をわけて表示するというのは、どのように書けばいいのでしょうか? 初めに英単語の表示で、 System.out.print("apple"); としたあとで System.out.print("(2,8)"); System.out.print("(3,6)"); というように別けるということでしょうか?これだと単語の後すぐに座標が来てしまいやはり同じ結果になってしまいます。 すみません。どのように独自に指定して表示すればよいでしょうか?
お礼
皆さま本当にありがとうございました! printf、非常に勉強になりました! Javaにこういうのがあったんですね^^すごく参考になりました!