[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理IIIA(Javaプログラミング入門)第11回

目次 索引
11.1 識別子とキーワード
11.2 論理型とブール式
11.3 文字と文字列
11.3.1 文字
11.3.2 文字列
11.3.3 整数と文字列
11.4 演習11
11.5 レポート課題

11.1 識別子とキーワード

これまで、変数名、メソッド名、クラス名、フィールド名など、色々なものに名前をつけてきました。 これらの名前をまとめて 識別子identifier )とよびます。

識別子の約束は、変数名のときに説明した約束と同じです。 識別子は、アルファベットから始まり、アルファベットか数字かアンダースコア( _ )が並んだ単語です。 また、 newthis などのキーワードは識別子としては使えません。 キーワードをもう一度リストアップします。

abstract , boolean , break , byte , byvalue , case , cast , catch , char , class , const , continue , default , do , double , else , extends , final , finally , float , for , future , generic , goto , if , implements , import , inner , instanceof , int , interface , long , native , new , operator , outer , package , private , protected , public , rest , return , short , static , super , switch , synchronized , this , throw , throws , transient , try , var , void , volatile , while

識別子は、そのものをよく表す分かりやすい名前にしてください。 プログラムが理解しやすくなります。 また、慣習も利用してください。 例えば、 for 文のループ変数は、 ij がよく用いられます。 識別子の大文字小文字は、次のように使い分ける場合が多いです。

表 11.1  識別子の大文字小文字の使い分け
種類 使い分け
定数名 全て大文字 PI,MAX_VALUE
クラス名 先頭が大文字 Time,MyWallet
その他 先頭が小文字 hour,clearAll

11.2 論理型とブール式

論理型logical type )とは、真理値を表わすデータ型です。 ここで 真理値truth-value )とは、真を表わす記号 true と偽を表わす記号 false のことだと思ってください。 Java では、型名 boolean で論理型を表わします。 値が論理型である式を、 ブール式Boolean expression )とよびます。 これまで「条件が成り立つ」、「条件が成り立たない」と言ってきたことは、正確にはブール式の値が true になること、false になることです。


11.3 文字と文字列

11.3.1 文字

変数には、整数の他に 文字character )を格納するすることもできます。 次のプログラムは、変数を宣言し、そこに文字を格納し、それを画面に出力するものです。

/* 1*/ class CharacterTest {
/* 2*/     public static void main (String[] args) {
/* 3*/         char x;
/* 4*/         x = 'A';
/* 5*/         System.out.println(x);
/* 6*/     }
/* 7*/ }
b00a001@Ampere:~/java% java CharacterTest
A
b00a001@Ampere:~/java%

整数のときには int 型と宣言しました。 文字のときには char 型と宣言します。 また、整数を表す場合は数字を並べました。 文字を表す場合はその文字をシングルクオート( ' )で囲みます。 ただし、シングルクオート自身、およびダブルクオート( " )、バックスラッシュ( \ )については、それぞれ '\'' , '\"' , '\\' とします。

文字どうしが等しいかどうかは、 == で比較します。 例えば、変数 x が文字 a と等しいかどうかは、条件 x == 'a' で確かめられます。 Javaでは大文字と小文字は区別されますので、 x に文字 A が格納されていましたら、この条件は成り立たない(false)となります。

文字に関するメソッドは、組み込みのクラスである Character クラスで提供されています。 この中で重要なものは以下の通りです。

static boolean isDigit (char c)
文字 c が数字ならば true を返す。 そうでなければ false を返す。
static boolean isLowerCase (char c)
文字 c がアルファベットの小文字ならば true を返す。 そうでなければ false を返す。
static boolean isSpace (char c)
文字 c がホワイトスペース(スペース、水平タブ、改行など)ならば true を返す。 そうでなければ false を返す。
static boolean isUpperCase (char c)
文字 c がアルファベットの大文字ならば true を返す。 そうでなければ false を返す。
static char toLowerCase (char c)
文字 c がアルファベットの大文字ならば、それを小文字に変換して返す。 そうでなければそのまま返す。
static char toUpperCase (char c)
文字 c がアルファベットの小文字ならば、それを大文字に変換して返す。 そうでなければそのまま返す。

例えば、変数 x の値がアルファベットの大文字ならば、…という if 文でしたら、

...
char x;
...
if (Character.isUpperCase(x)) {
    ...
}
...

と書きます。

11.3.2 文字列

これまで文字列は、

int result = 12345679 * 9;
System.out.println("result: " + result);

のように画面出力のときのみ使ってきました。 実は、文字列は組み込みのクラスである String クラスのインスタンスです。 文字列はよく使われますので、便利な機能がいくつか用意されています。

まず、コンストラクタを使わなくてもインスタンスが生成できます。 コンストラクタを用いて

String s = new String();
s = "Good";

String s = new String("Good");

などと書かなくても、

String s = "Good";

でよいのです。

また、演算子 + が使えます。 これは、文字列を連接します。

String s1 = "Good";
String s2 = "morning!";
String s3 = s1 + " " + s2;

としますと、 s3 には文字列 "Good morning!" が格納されます。

文字列と数を演算子 + で結びますと、数が文字列に変換されてから連接されます。

int result = 12345679 * 9;
String s1 = "result = ";
String s2 = s1 + result;

としますと、 s2 には文字列 "result = 111111111" が格納されます。

文字列、すなわち String クラスのインスタンスは、一度生成されますとその内容は変更できません。 文字列 "Good morning!" の mor を eve に置き換えることができないのです。 内容を変更するには、文字列ではなく文字列バッファというものを用います。 文字列バッファとは、組み込みのクラス StringBuffer のインスタンスのことです。 文字列バッファに対しては、文字の置き換え、追加、挿入などができます。 文字列を加工するには、いったん文字列バッファに変換し、処理のあと再び文字列に変換すればよいのです。

文字列を文字列バッファに変換するには、 StringBuffer クラスのコンストラクタを用います。 逆に、文字列バッファを文字列に変換するには、インスタンスメソッド toString() を呼び出します。

String s1 = "Good morning!";
StringBuffer s2 = new StringBuffer(s1);
s2.setCharAt(5, 'e');
s2.setCharAt(6, 'v');
s2.setCharAt(7, 'e');
String s3 = s2.toString();

としますと、 s3 には文字列 "Good evening!" が格納されます。 ここで、メソッド

void setCharAt (int i , char c )

は、そのインスタンスの i 番目の文字を c に置き換えるものです。

String クラスのメソッドで重要なものは以下の通りです。

char charAt (int i)
そのインスタンスの i 番目の文字を返す。
boolean equals (String s)
そのインスタンスと文字列 s の内容が同じならば true を返す。 そうでなければ false を返す。
int length ()
そのインスタンスの文字数を返す。
static String valueOf (boolean b)
真理値 b を文字列に変換して返す。
static String valueOf (char c)
文字 c を文字列に変換して返す。
static String valueOf (int i)
整数 i を文字列に変換して返す。

また、 StringBuffer クラスについては以下の通りです。

StringBuffer append (String s)
そのインスタンスに文字列 s を追加する。
StringBuffer append (char c)
そのインスタンスに文字 c を追加する。
char charAt (int i)
そのインスタンスの i 番目の文字を返す。
StringBuffer insert (int i, String s)
そのインスタンスの i 番目の位置に文字列 s を挿入する。
StringBuffer insert (int i, char c)
そのインスタンスの i 番目の位置に文字 c を挿入する。
int length ()
そのインスタンスの文字数を返す。
void setCharAt (int i, char c)
そのインスタンスの i 番目の文字を文字 c に置き換える。
String toString ()
そのインスタンスを文字列に変換して返す。

11.3.3 整数と文字列

Integer クラスでは、整数( int 型)の変換に関するメソッドがいくつか提供されています。 その中では、以下のものが重要です。

static int parseInt (String s)
文字列 s を整数( int 型)に変換して返す。
static String toString (int i)
整数( int 型)を文字列に変換して返す。

ここで、コマンドライン引数から整数を一つ取り出すプログラム

/* 1*/ class FirstArgument
/* 2*/     public static void main (String[] args) {
/* 3*/         int x = Integer.parseInt(args[0]);
/* 4*/         System.out.println(x);
/* 5*/     }
/* 6*/ }
b00a001@Ampere:~/java% java FirstArgument 100
100
b00a001@Ampere:~/java%

を思い出してください。 このプログラムの3行目の意味が、ここでやっと明らかになります。

このプログラムを実行しますと、変数 args には文字列の配列が格納されます。 この配列は、添字0の要素がはじめのコマンドライン引数、添字1の要素が次のコマンドライン引数、…となるものです。 上記の場合では、 args[0] に文字列 "100" が格納されます。 そして、クラスメソッド parseInt によって文字列 "100" が整数 100 に変換されます。 最後に、この整数 100 が変数 x に格納されるのです。


11.4 演習11

ランレングス符号を復号して、もとのイメージを画面に出力するJavaアプリケーションを作成してください。 ここで、 ランレングス符号run-length coding )とはデータ圧縮の一手法です。 また、 復号decode )するとは 符号化encode )されたデータを元に戻すことです。 ランレングス符号は、ファックス伝送の基本にもなっています。 ファックス伝送の仕組みを簡単に紹介し、その中でランレングス符号について説明します。

ファックス伝送は、はじめに送信側が紙面イメージを読み込みます。 このとき、紙面イメージを75分の1インチ程度の単位で格子状に分割します。 そして、光学的な方法でそれぞれの升を白か黒かに決定します。 升を横にたどっていき、右端に達したら左端に戻るということを、紙面がつきるまで繰り返し、白黒の列を作ります。 最後に、この白黒データを受信側に送信します。

受信側では、まずこの白黒データを受け取ります。 そして、白黒データと一緒に紙面の升をたどっていき、データが黒ならばその部分を黒く記録します。 これを繰り返しますと、もとの紙面イメージができあがるのです。

ここで、白と黒をそれぞれ WB で表わすことにしまして、送信側が白黒データ

WWWWWBBBBBBBWWWWWWWWWWWWWWWWWWWWWWWWWWWBBBBBWWWWWW

を構成したとします。 白黒データが長ければ長いほど、伝送に時間がかかりますので、なるべく短くしたいです。 そこで、5個の W 、7個の B 、27個の W 、…、すなわち

5W7B27W5B6W

という符号化データを送ることにします。 これがランレングス符号です。 受信側では、 5WWWWWW に置き換え、 7BBBBBBBB に置き換え、…という復号操作を行ないますと、データを元に戻すことができます。

ランレングス符号は、同じ文字が何度も繰り返されるデータほど効果を発揮します。 なお、実際に圧縮する場合には、数の表現に工夫が必要です。

今、受信側がランレングス符号

64WE64WE33W3B28WE33W6B25WE33W9B2
2WE33W12B19WE33W15B16WE33W18B13W
E1W53B10WE1W56B7WE1W59B4WE1W62B1
WE1W59B4WE1W56B7WE1W53B10WE33W18
B13WE33W15B16WE33W12B19WE33W9B22
WE33W6B25WE33W3B28WE64WE64WE64WE

を受け取ったとします。 これを復号して、元の紙面イメージを画面に出力するのがこの演習の目的です。 画面では、例えば白を . で、黒を * で表してください。 なお、符号が6行なのは印刷の都合によるもので、実際は1行につながっています。 また、文字 E は紙の右端を表しています。 画面では改行してください。

プログラミングの方針は特に指定しません。 方針が思いつかない人は、以下のプログラムの穴埋めを行なってください。 このプログラムの System.err.println は、エラーメッセージを画面出力するときに使うものです。 なお、 3E などの誤った符号はないものと仮定してください。

class RunLength {
    public static void main (String[] args) {
        int i;
        char c;
        String s;
        StringBuffer number = new StringBuffer("");
        String code = "64WE64WE33W3B28WE33W6B25WE33W9B2"
                      + "2WE33W12B19WE33W15B16WE33W18B13W"
                      + "E1W53B10WE1W56B7WE1W59B4WE1W62B1"
                      + "WE1W59B4WE1W56B7WE1W53B10WE33W18"
                      + "B13WE33W15B16WE33W12B19WE33W9B22"
                      + "WE33W6B25WE33W3B28WE64WE64WE64WE";
        for (i = 0; i < code.length(); i++) {
            ??? // ランレングス符号 code の i 番目の文字を
            ??? // c とおく。もし c が数字ならば、整数を表
            ??? // す文字列バッファ number にその数字を追加
            ??? // する。そうでなくて c が文字 W ならば、
            ??? // number を文字列に変換し、整数に変換し、
            ??? // その数だけ文字 . が並ぶ文字列をクラスメ
            ??? // ソッド charTimes を用いて構成し、その文
            ??? // 字列を画面に出力する。number は数字のな
            ??? // い状態に戻す。c が文字 B ならば、同様に
            ??? // 文字 * が並ぶ文字列を構成する。c が文字
            ??? // E ならば、画面で改行を行なう。c がどれで
            ??? // もなければ、エラーメッセージを画面出力す
            ??? // る。
        }
        System.out.println();
    }
    static String charTimes (char c, int times) {
        if (times < 0) {
            System.err.println("Under zero characters.");
            return "";
        } else if (times > 100) {
            System.err.println("Too many characters.");
            return "";
        } else {
            int i;
            StringBuffer s = new StringBuffer("");
            for (i = 0; i < times; i++) {
                s = s.append(c);
            }
            return s.toString();
        }
    }
}

11.5 レポート課題

今日の演習11に従ってJavaプログラムを作成し、そのプログラムをkonishi@twcu.ac.jpあてにメールで提出してください。 メールには、学生番号、氏名、科目名、授業日(11/29)を明記してください。


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2001年11月29日更新
konishi@twcu.ac.jp
Copyright (C) 2001 Zenjiro Konishi. All rights reserved.