2004 -0305 ver 0.10 草稿開始 -1013 ver 0.20 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃.&&&& **** %%%%.  JavaScript&Javaで目指そう!基本情報技術者試験  ┃ ┃&&&&&&******%%%%%%  http://www.yscon.co.jp/j/java/jmaga/      ┃ ┃'&┃&''*┃*''%┃%'      (C)2004 斎藤末広 jmaga@yscon.co.jp  ┃ ┗━┻━━┻━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓  通巻47号 2004/04/16  基本情報技術者午後平成15年秋問8 解説 ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛  プログラムを作成する上での注意事項:  WindowsXP, SDK(JDK) 1.4.2,IE 6.0 を前提としています。  「ファイルの拡張子を表示する」に設定してください。 ========================================================================= ▼基本情報技術者試験 Java プログラム研究シリーズ開始  頭をJavaの試験にならすために,今回は,過去の基本情報技術者試験のJavaの過 去問題を解説します。  問題をどう解くかという視点ではなく,サンプルそのものを研究していきます。  今回は,平成15年秋問8です。この問題をどう解くかは,宿題メール会員限 定教材にて公開中です。そちらもあわせて参考にして下さい。 宿題メール会員とは http://www.yscon.co.jp/j/homework/index.htm#kaihi ------------------------------------------------------------------------ ▼基本情報技術者午後平成15年秋問8プログラム  問題は,過去問題集を参考にするか,東京理科大のサイトで公開されている 問題を参考にして下さい。  なお,プログラムソースは,空欄を埋めてすでに完成してあります。また, 見やすくするために,改行を加え,行番号をつけました。 基本情報技術者午後平成15年秋問8 http://www.rs.kagu.sut.ac.jp/~infoserv/j-siken/H15b2/pm08.html 〔プログラムの説明〕  プログラムは,バイナリデータのバイト列をあるアルゴリズムに従って変換し, その結果を文字の列として取得するためのクラス Encoder とそのテスト用クラス からなる。変換アルゴリズムは次のとおりである。 (1) バイト列の先頭から順に 6 ビットずつ取り出し,変換表の対応する文字に 変換する。ただし,バイト数が 3 の倍数でないときは,ビット数が 6 の倍数に なるように,最後に 4 ビット又は 2 ビットの 0 があるものとする。 (2) 変換後の文字数が,与えられたバイト数の 4/3 倍以上で最も小さい 4 の 倍数になるように,文字の列の最後に必要な個数だけ“=”を付加する。 (3) 変換例を図1 に示す。   (図1 変換例 省略) (4) クラス Encoder は,next と hasNext の二つのメソッドをもつ。 next は, 変換アルゴリズムに従って変換された文字を 1 文字ずつ順に返すメソッドである。 返すべき文字がなくなった後に呼ばれると,java.util.NoSuchElementException を投げる。 hasNext は,次の next 呼出しの際に,例外が発生せずに文字を返す ことができるとき真となる。 (5) 変数 CHARS は,6 ビットの数値を 1 文字に変換するための表で,配列の大 きさは 64 である。変数 n は,次に next が呼ばれたときに返すべき文字が何番 目の文字であるかを保持する(先頭の文字は 0 番目とする)。変数 bin は,変 換するバイナリデータの列を保持する。 (6) 図1 のバイト列を用いたテスト用クラス EncoderTest の実行結果を図2 に示す。 +----------+ | EjRFZw== | +----------+ 図2 実行結果 例 j47-01 Encoder.java ソース http://www.yscon.co.jp/j/java/jmaga/jsmp/j47/Encoder.java 1: /* 基本情報技術者午後平成15年秋問8 2: バイナリーデータをテキストデータに変換 3: */ 4: 5: public class Encoder { 6: static final char[] CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + 7: "abcdefghijklmnopqrstuvwxyz0123456789+/").toCharArray(); 8: private int n = 0; 9: private byte[] bin; 10: 11: public Encoder(byte[] bin) { 12: if (bin == null) this.bin = new byte[0]; 13: else this.bin = bin; 14: } 15: 16: public boolean hasNext() { 17: return n < (bin.length + 2) / 3 * 4; 18: } 19: 20: public char next() { 21: char letter; 22: int pos = (int)(n * 0.75); 23: // 変換対象の 6 ビットのデータが含まれる 2 バイトのデータを取得 24: if (pos < bin.length) { 25: int cell = bin[pos++] << 8; 26: if (pos < bin.length) cell += bin[pos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: letter = CHARS[(cell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else { 30: if (!hasNext()) 31: throw new java.util.NoSuchElementException(); 32: else letter = '='; 33: } 34: n++; 35: return letter; 36: } 37: } 38: 39: class EncoderTest { 40: public static void main(String[] args) { 41: byte[] bin = {0x12, 0x34, 0x45, 0x67}; 42: Encoder encoder = new Encoder(bin); 43: while (encoder.hasNext()) { 44: System.out.print(encoder.next()); 45: } 46: System.out.println(); 47: } 48: } ------------------------------------------------------------------------ ▼実行と確認  Encoder.java をコンパイルし,実行してみましょう。 "jv"は,なお,jv.bat で, java -classpath . %1 %2 %3 が書いてあります。 DOSプロンプト画面 ┏------------------------------------------------------------┓ J:\j47>javac Encoder.java J:\j47>jv EncoderTest J:\j47>java -classpath . EncoderTest EjRFZw== ┗------------------------------------------------------------┛ となります。 ------------------------------------------------------------------------ ▼ Encoder.java の構造  Encoder.java のファイル内には,EncoderクラスとEncoderTestクラスが定義 されています。  全体の構造は,以下のようになっています。 Encoder.java ファイル内  Encoder クラス   hasNest() メソッド   next() メソッド  EncoderTest クラス   Encoder encoder = new Encoder(bin); です。  EncoderTest が,Encoder のインスタンス encoder に仕事をさせるという構造 です。  EncoderTest クラスは,Encoder クラスが正常に動作するかのテストの役目を します。このようなテストプログラムを,テストドライバといいます。 ------------------------------------------------------------------------ ▼ Java 初心者の方にお奨め,x付き書き換え  サンプルプログラムを学習する方法で,x付き書き換えがあります。変更できる 名前のところを,ことごとく,頭にxを付けます。  たとえば,  int suuji;  のプログラムを  xint xsuuji;  とすると,xint は,コンパイルエラーになりますが,xsuuji の方は,x付き でもコンパイルエラーとはなりません。  このx付き書換によって,プログラムの枝と葉が色分けされるような感じにな ります。  ご自分でぜひ,x付き書換をして見て下さい。  x付き書換をすると,次のようになります。ただし,一文字だけの変数名等は, x付きにしないということにします。  プログラム名をxEncoder01 としました。 例 j47-02 xEncoder01.java ソース http://www.yscon.co.jp/j/java/jmaga/jsmp/j47/xEncoder01.java 1: /* 基本情報技術者午後平成15年秋問8 x付き書換 2: バイナリーデータをテキストデータに変換 3: */ 4: 5: public class xEncoder01 { 6: static final char[] xCHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + 7: "abcdefghijklmnopqrstuvwxyz0123456789+/").toCharArray(); 8: private int n = 0; 9: private byte[] xbin; 10: 11: public xEncoder01(byte[] xbin) { 12: if (xbin == null) this.xbin = new byte[0]; 13: else this.xbin = xbin; 14: } 15: 16: public boolean xhasNext() { 17: return n < (xbin.length + 2) / 3 * 4; 18: } 19: 20: public char xnext() { 21: char xletter; 22: int xpos = (int)(n * 0.75); 23: // 変換対象の 6 ビットのデータが含まれる 2 バイトのデータを取得 24: if (xpos < xbin.length) { 25: int xcell = xbin[xpos++] << 8; 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else { 30: if (!xhasNext()) 31: throw new java.util.NoSuchElementException(); 32: else xletter = '='; 33: } 34: n++; 35: return xletter; 36: } 37: } 38: 39: class xEncoderTest { 40: public static void main(String[] xargs) { 41: byte[] xbin = {0x12, 0x34, 0x45, 0x67}; 42: xEncoder01 xencoder = new xEncoder01(xbin); 43: while (xencoder.xhasNext()) { 44: System.out.print(xencoder.xnext()); 45: } 46: System.out.println(); 47: } 48: } ------------------------------------------------------------------------ ▼ xEnoderTest説明  xEnoderTestクラスから説明をしましょう。この役割は,xEncoderクラスのテス トをすることです。テストドライバといいます。 39: class xEncoderTest { 40: public static void main(String[] xargs) { 41: byte[] xbin = {0x12, 0x34, 0x45, 0x67}; 42: xEncoder01 xencoder = new xEncoder01(xbin); 43: while (xencoder.xhasNext()) { 44: System.out.print(xencoder.xnext()); 45: } 46: System.out.println(); 47: } 48: }  まずは,main() メソッドをみましょう。 40: public static void main(String[] xargs) {  main()メソッドは,特別なメソッドで,このクラスを実行させると,最初に自 動的に実行されるメソッドです。 J:\j47>java -classpath . xEncoderTest と実行をすると,main()メソッドが実行されます。main()メソッドの中をみましょ う。 41: byte[] xbin = {0x12, 0x34, 0x45, 0x67};  テストデータを用意しています。xbin を byte型配列として用意し,そこの中に, 0x12, 0x34, 0x45, 0x67を代入しています。  0x で始める書き方は,それが,16進数の数字であることを意味します。 42: xEncoder01 xencoder = new xEncoder01(xbin);  xEncoder01 クラスのインスタンスを,xendoer という名前で作成しています。 そのときに,先ほどの用意したテストデータ xbin を渡しています。 43: while (xencoder.xhasNext()) { 44: System.out.print(xencoder.xnext()); 45: } 先ほど,生成した,xencoder インスタンスに仕事をさせます。xhasNext()で, 次があるかどうかを調べさせ,次がある限り,44行で,画面に表示させます。 表示するものは,xnext() で探しています。 実行すると J:\j47>java -classpath . xEncoderTest EjRFZw== です。xbinのテストデータが,変換され,それが表示されました。 ------------------------------------------------------------------------ ▼ xEncoder01 解説  xEncoder01 クラスの解説をします。 5: public class xEncoder01 { 6: static final char[] xCHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + 7: "abcdefghijklmnopqrstuvwxyz0123456789+/").toCharArray(); 8: private int n = 0; 9: private byte[] xbin; 10: 11: public xEncoder01(byte[] xbin) { 12: if (xbin == null) this.xbin = new byte[0]; 13: else this.xbin = xbin; 14: } 15: 16: public boolean xhasNext() { 17: return n < (xbin.length + 2) / 3 * 4; 18: } 19: 20: public char xnext() { 21: char xletter; 22: int xpos = (int)(n * 0.75); 23: // 変換対象の 6 ビットのデータが含まれる 2 バイトのデータを取得 24: if (xpos < xbin.length) { 25: int xcell = xbin[xpos++] << 8; 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else { 30: if (!xhasNext()) 31: throw new java.util.NoSuchElementException(); 32: else xletter = '='; 33: } 34: n++; 35: return xletter; 36: } 37: } の主な構造は, xEncoder01 クラス  変換テーブル用意  コンストラクタ  xhasNext() メソッド  xNext() メソッド です。 順に解説しましょう。 変換テーブル用意 6: static final char[] xCHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + 7: "abcdefghijklmnopqrstuvwxyz0123456789+/").toCharArray();  変換するときの変換テーブル(対応表)を作っています。  xCHARS[0] = 'A';  xCHARS[1] = 'B';   (省略)  xCHARS[63] = '/'; と同等です。  変換するときは,6ビットの信号を入力しますので,変換テーブルは,要素数 が,2^6=64 の配列としています。  static は,xCHARS 文字型の配列は,インスタンスが持つものでなく,クラス xEncoderが持つことを示しています。クラスが持つことで,このクラスから作ら れるのインスタンスは,共通で,このxCHARS を利用できます。  final は,xCHARS 文字列の配列の中身が,この後,変更できないことを示して います。ファイナルアンサーのファイナルです。  char[] xCHARS で,要素がchar型の配列,xCHARS を用意しました。配列の名 前が,xCHARS とx以外が大文字なのは,final で値が変更できないということを 暗示しています。よくやるテクニックです。  値が変更できないので,定数といいます。他の言語(VBなど)では,CONST とい う予約語が使われます。Java の場合は,final が使われます。 6: static final char[] xCHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + 7: "abcdefghijklmnopqrstuvwxyz0123456789+/").toCharArray(); の = の後ろは,   ("…" + "…").toCharArray() と  文字列.toCharArray() という形です。  文字列は,Java の場合,Stringクラスのインスタンスとして表されます。  文字列.toCharArray() は,この文字列インスタンスに,toCharArray() メソッド の仕事をさせます。自分自身の内容(文字列)を,文字型配列に変換しています。  これで,xCHARS 配列に,値が代入されました。 8: private int n = 0; 9: private byte[] xbin;  private は,これが,このクラスより作られたインスタンスの内部だけで利用 されるということを表しています。 ------------------------------------------------------------------------ ▼ xEncoder01 コンストラクタ(構築子)解説 11: public xEncoder01(byte[] xbin) { 12: if (xbin == null) this.xbin = new byte[0]; 13: else this.xbin = xbin; 14: } は,xEncoder クラスからインスタンスが作られるときに使われる特殊なメソッド です。コンストラクタ(構築子)と呼ばれます。  このコンストラクタを実行しているのは,テストドライバの中の 42: xEncoder01 xencoder = new xEncoder01(xbin);  です。42行目の意味は,xEncoder01クラスのインスタンス xencoder を,引数 xbin を渡して,生成(こんすとらくと)するという意味です。 11: public xEncoder01(byte[] xbin) { 12: if (xbin == null) this.xbin = new byte[0]; 13: else this.xbin = xbin; 14: }  13行目に現れる   this.xbin = xbin は,コンストラクタで生成されるときにもらった,xbin を,インスタンス内部の this.xbin に代入しています。同じ,xbin という名前を使ったため,このような 記述になりました。もし,11行目で, public xEncoder01(byte[] ybin){  と,xbin の代わりに,ybinとしたら, 11 行目から 14行目は public xEncoder01(byte[] ybin) { if (ybin == null) xbin = new byte[0]; else xbin = ybin; } と書くことができます。 ------------------------------------------------------------------------ ▼ xEncoder01 xhasNext()メソッド解説 16: public boolean xhasNext() { 17: return n < (xbin.length + 2) / 3 * 4; 18: }  この xhasNext()メソッドは,返値の型が,boolean(真偽型)です。まだ次が あるか? と判断してあれば,真,無ければ,偽を返します。  次があるかどうかは,与えられたバイナリデータのバイト列の長さをもとに それを変換したあとの文字数を超えていないかどうかを調べています。 問題文の(1)と(2)から,  xbin.length と 変換後の文字数の対応は,次の通りです。 xbin.length bit数 変換後文字数  変換後文字数(4の倍数) ============================================================ 1 8 2        4 2 16 3 4 3 24 4 4 ------------------------------------------ 4 32 6 8 5 40 7 8 6 48 8 8 ------------------------------------------ 7 56 10 12 8 64 11 12 9 72 12 12 ------------------------------------------ この関係を式で表すと  変換後文字数(4の倍数) = (int)((xbin.length + 2) / 3) * 4 となります。  ここで,変換後文字数(4の倍数)の配列の添え字は,0 から始まりますので, 添え字nの配列の要素があるかどうかは,  n < 変換後文字数(4の倍数) が成立していればよいことになります。 ------------------------------------------------------------------------ ▼ xEncoder01 xnext()メソッド解説 20: public char xnext() { 21: char xletter; 22: int xpos = (int)(n * 0.75); 23: // 変換対象の 6 ビットのデータが含まれる 2 バイトのデータを取得 24: if (xpos < xbin.length) { 25: int xcell = xbin[xpos++] << 8; 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else { 30: if (!xhasNext()) 31: throw new java.util.NoSuchElementException(); 32: else xletter = '='; 33: } 34: n++; 35: return xletter; 36: }  xnext() メソッドは,変換後の文字を返します。   20: public char xnext() {  public は,xnext()メソッドが,このクラスの外から利用されることを示して います。  char は,xnext() の仕事の結果は,char 型で帰ってくることを示します。 21: char xletter;  文字型の変数,xletter を用意しました。これは後のプログラムを読むと分かり ますが,変換後の文字を保管するために使います。xnext()メソッドは,この xletter を返します。 22: int xpos = (int)(n * 0.75);  n は,変換後の文字の順番を表す変数です。これから求める文字が,最初から 数えて何文字目にあたるかを保持しています。0 から数えています。  (int)(n * 0.75) で,整数に強制的に型変換をします。小数分を切り捨てしま す。n * 0.75 小数分を切りすることで返還前のビット列での対応する位置を求め ています。 24: if (xpos < xbin.length) { 25: int xcell = xbin[xpos++] << 8; 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else { 30: if (!xhasNext()) 31: throw new java.util.NoSuchElementException(); 32: else xletter = '='; 33: }  この if の条件式,xpos < xbin.length で,n 番目の文字になるはずのもと のビットが存在しているかをチェックしています。  元のビットが存在すればそれを取り出し,xletter に代入しています。  元のビットが存在しなければ,さらに,xhasNext() が偽であれば, エラーとしています。  元のビットが存在しなく,文字出力の対象となっている所であれば,"="を返 しています。  このアルゴリズムでは,2段階の長さあわせをして,それぞれの埋め草を入れて います。  最初の埋め草は,最初の長さあわせは,ビット列を6ビット単位に区切るため, 6ビットに足らない場合に,ビットの0を使っています。  次の埋め草は,できあがった文字列の長さが,4の倍数でない場合に,"="を使っ います。 24: if (xpos < xbin.length) { 25: int xcell = xbin[xpos++] << 8; 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else {  ここは,n 番目の文字が,埋め草の"="でないときの処理です。 25: int xcell = xbin[xpos++] << 8;  これを分解すると int xcell; xcell = xbin[xpos] << 8; xpos++; と同等です。分解したもので,説明します。  int xcell; 整数型変数 xcell を用意します。  xcell = xbin[xpos] << 8;  xbin[xpos]mの値を8ビット,左算術シフトをしています。256 倍しています。  xpos++;  で,xpos の次ぎの値にしています。  ここで,25行目を再度確認しましょう。 25: int xcell = xbin[xpos++] << 8;  xcell に,xbin から値を取り出して,それを256倍ということになります。本来 は,6ビット分のみを取り出したいので,このあと,さらに工夫があるはずです。 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63];  xpos < xbin.length は,先ほど取り出して位置の後にまだ対象となるビット列 があるかどうかの判断です。後にあるときに,  xcell += xbin[xpos] & 255; をしています。  これは,先ほど取り出した8ビットの値に後の値を取り出しをして,それと, &255しています。下8ビットを xcell 足し込むことになります。  xcell には,xbin[] から2バイト分取り出しことになります。 さらに, 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63];  を実行しています。  ここで,シフト演算子の >> は,%, * , + と比べて弱いため,先に,  (n + 3) % 4 * 2 + 4  が計算されます。 "どれくらいシフトするの計算"  n = 0 のとき,(0 + 3) % 4 * 2 + 4 = 10  n = 1 のとき,(1 + 3) % 4 * 2 + 4 = 4  n = 2 のとき,(2 + 3) % 4 * 2 + 4 = 6  n = 3 のとき,(3 + 3) % 4 * 2 + 4 = 8  n が4以上のときは,上のパターンを繰り返すことになります。  xcell >> (n + 3) % 4 * 2 + 4  で,n の値にあわせて,右シフトします。  それに,&63 をすることで,ビット列の下6桁を取り出すことになります。 n, pos と(xcell >> (n + 3) % 4 * 2 + 4) & 63 の関係を 22: int xpos = (int)(n * 0.75); 23: // 変換対象の 6 ビットのデータが含まれる 2 バイトのデータを取得 24: if (xpos < xbin.length) { 25: int xcell = xbin[xpos++] << 8; 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else { で,確認しましょう。 最初のビット列を,ひらがなの文字がそれぞれビットとして xbin の内容 あいうえおかきく けこさしすせそた ちつてとなにぬね のはひふへほまみ とします。 n = 0 のとき "あいうえおか" n = 1 のとき "きくけこさし" n = 2 のとき "すせそたちつ" n = 3 のとき "てとなにぬね" が取り出せるはずです。シフトは,上の"どれくらいシフトするの計算"から n = 0 のときは,xpos = 0, シフトが 10 n = 1 のときは,xpos = 0, シフトが 4 n = 2 のときは,xpos = 1, シフトが 6 n = 3 のときは,xpos = 2, シフトが 8 n = 0 ととき xpos = 0 から2バイト取り出し,整数型(32ビット)に代入しますので  ○○○○○○○○ ○○○○○○○○ あいうえおかきく けこさしすせそた >> 10 とすると  ○○○○○○○○ ○○○○○○○○ ○○○○○○○○ ○○あいうえおか &63 をすると,下6桁取り出し  ○○○○○○○○ ○○○○○○○○ ○○○○○○○○ ○○あいうえおか n = 1 のとき xpos = 0 から2バイト取り出し,整数型(32ビット)に代入しますので  ○○○○○○○○ ○○○○○○○○ あいうえおかきく けこさしすせそた >> 4  ○○○○○○○○ ○○○○○○○○ ○○○○あいうえ おかきくけこさし &63 をすると,下6桁取り出し  ○○○○○○○○ ○○○○○○○○ ○○○○○○○○ ○○きくけこさし n = 2 のとき xpos = 1 から2バイト取り出し,整数型(32ビット)に代入しますので  ○○○○○○○○ ○○○○○○○○ けこさしすせそた ちつてとなにぬね >>6  ○○○○○○○○ ○○○○○○○○ ○○○○○○○○ さしすせそたちつ &63 をすると,下6桁取り出し  ○○○○○○○○ ○○○○○○○○ ○○○○○○○○ ○○すせそたちつ n = 3 のとき xpos = 2 から2バイト取り出し,整数型(32ビット)に代入しますので  ○○○○○○○○ ○○○○○○○○ ちつてとなにぬね のはひふへほまみ >> 8  ○○○○○○○○ ○○○○○○○○ ○○○○○○○○ ちつてとなにぬね &63 をすると,下6桁取り出し  ○○○○○○○○ ○○○○○○○○ ○○○○○○○○ ○○てとなにぬね よって n = 0 のとき "あいうえおか" n = 1 のとき "きくけこさし" n = 2 のとき "すせそたちつ" n = 3 のとき "てとなにぬね" が取り出せました。 次ぎ 24: if (xpos < xbin.length) { 25: int xcell = xbin[xpos++] << 8; 26: if (xpos < xbin.length) xcell += xbin[xpos] & 255; 27: // 変換すべき 6 ビットを抽出し, 対応する 1 文字に変換 28: xletter = xCHARS[(xcell >> (n + 3) % 4 * 2 + 4) & 63]; 29: } else { 30: if (!xhasNext()) 31: throw new java.util.NoSuchElementException(); 32: else xletter = '='; 33: } の 29 行目のelseのところをみましょう。 これは,24行目から,これから取り出す文字に対応するものが,ビット列にない 場合の処理です。  次ぎ(xhasNest)がないなら,31行目で,論理的におかしいということで,例外 としています。  次ぎがあれば,対応の規則より,'='を入れました。32 行目のとおりです。 34: n++; 35: return xletter; 36: }  ここで,次の,xnext() のために,n++ をやっています。  return xletter は,28行目で決まった文字を返しています。 ------------------------------------------------------------------------ ▼基本パターン  平成15年秋問8のプログラムは,ひとつのファイルに2つのクラス Encoderクラス EncoderTestクラス がありました。これは,目的とするクラスとそれのテストプログラムをいっしょ に書いておくというやり方です。  Encoderクラスは,与えられたもの,ビット列,を文字に変換します。やり方と して,  次があるか,あればそれを出す,次のために値を更新しておく というパターンでした。  両方とも,よくあるパターンですので,覚えておくといいでしょう。 ------------------------------------------------------------------------ ▼ 著作権について  このメールマガジンで公開している,プログラムソースは,著作権を当方スタッ フが所有しますが,プログラムソースの利用は,原則,商用を含めて,再利用, 改変,発表を制限しません。どんどんご利用下さい。  質問コーナのプログラムソースは,著作権に問題がある場合があるかもしれま せん。原則を適用しません。再利用の許可をしません。  画像や音などの素材は,それぞれ著作権があります。著作者に承諾なしに再利 用はできません。  本文に関しては,斎藤末広が著作権を所有します。再利用に関しては,承諾を 必要とします。お問い合わせ下さい。 ------------------------------------------------------------------------ ▼アンケート(以下を返信してください)  この号のJマガに対するご意見をお待ちしています。ぜひ,ご返信下さい。 この号の内容 1 良かった 2 普通 3 良くなかった コメント,リクエスト,質問もお待ちしています。遠慮せずにどうぞ。