KotlinでAndroid-No.09(文字列)

対象バージョン:Android Studio v4.1, Kotlin v1.4

文字列

今回はKotlinの文字列(クラス)について、主に文字列の作成方法について確認していきます。

前置き

毎度の事ですが、ここで紹介している内容は、僕自身がKotlinでプログラミングする上で必要と思う事を記載しています。(ほぼ備忘録です)

間違いや、不足部分、正しくない使い方も多々あると思いますので、記載内容に疑問がある場合はKotlinの正式なサイトや、他の方の記事も参考にしてみてください。

文字列の長さ

文字列の長さを取得するには、「length」メンバで取得します。

val str : String = "あいうABCDEFG!"
dispMsg("str len = " + str.length)

実行結果は以下になります。

str len = 11

半角文字も全角文字も1文字と数えられます。

また、lengthメンバは「val」扱いなので、このメンバに値を指定して文字列の長さを変える事は出来ません^^。

文字列の作成

ログや画面上に変数の値を表示させようとする場合、文字列と変数の値を組み合わせた文字列を作成します。

例えば以下の様なクラスの名前とIDを表示したい場合を考えます。

data class Member(var name : String, var id : Int)
Member : name = Nanashi, id = 1

toString()の利用

ほとんどのクラスには「.toString()」クラスが実装されているので、それを利用します。

val member = Member("Nanashi", 1)

// .toString()を省略 
val msg1_1 = "Member : name = " + member.name + ", id = " + member.id
dispMsg(msg1_1)

// .toString()を明示
val msg1_2 = "Member : name = " + member.name + ", id = " + member.id.toString()
dispMsg(msg1_2)

これまでの記事で良く利用してきた書き方です。ただし、実際には「.toString()」は省略して書いていましたが…^^;

toString()を省略できるのは「最初に文字列が来る」という条件がある場合のみです。下記の様な書き方をするとエラーになります。

val msg1_3 = member.id + " : " + member.name // 「1 : Nanashi」を期待するがエラー

いきなり文字列以外を持ってくる場合は、toString()を明示する必要があります。

 val msg1_4 = member.id.toString() + " : " + member.name // 「1 : Nanashi」

${}の利用

他のサイトで良くみる書き方です。

val msg2 = "Member : name = ${member.name}, id = ${member.id}"

メンバを含まない変数の場合は「{}」を省略できます。

// カウントダウン
for(index in 10 downTo 1)
{
    val msg = "Count : $index" // ${iindex}でもOK
    dispMsg(msg)
}

実行すると以下の様になります。

Count : 10
Count : 9
Count : 8
Count : 7
Count : 6
Count : 5
Count : 4
Count : 3
Count : 2
Count : 1

さて、「$」の後に、変数でない文字列(半角英字)が来るとエラーになります。

「$」を単なる文字として表示したい場合は、バックスラッシュを付けて「\$」の様にします。

String.format()の利用

書式指定文字列を作成したい場合は、format()メソッドを利用します。

// 文字列の後に.format()を付ける
val msg3_1 = "Member : name = %%8s, id = %%4d".format(member.name, member.id)
dispMsg(msg3_1)

// String.format()メソッドを利用
val msg3_2 = String.format("Member : name = %%8s, id = %%4d", member.name, member.id)
dispMsg(msg3_2)

書式指定の際は、書式指定文字「%*」と変数の型を一致させていないと、実行時に例外が発生するので注意が必要です。

// Int型の「member.id」に対して「%%f」(不動小数点)を指定
msg = "Member id = %%f".format(member.id)

実行時下記の様な例外を発生して、アプリが落ちます。

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sample.sampleapp, PID: 10224
    java.util.IllegalFormatConversionException: f != java.lang.Integer
        at java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4403)

少し厄介なのが、符号無し整数(UInt, ULong, UByteなど)です。

UIntなどの書式指定文字は「%u」ではありません(例外が発生して落ちます)。

以下のいずれかでの対応になると思います。

① toInt()やtoLong()メソッドを利用して、符号有整数として扱う。

val uval : UInt = 100u

// 符号有整数(Int)に変換して出力
var msg = "uval = 0x%%08x".format(uval.toInt())
dispMsg(msg)

この場合、マイナス値として表示されてしまう場合もある事に注意が必要です。(最上位ビットが1になっている場合など)

② toString(radix = 基数)メソッドを使って文字列として扱う。

「radix(基数)」は何進数として文字列にするかを指定します。(省略したら10進数扱いになります)

val uval : UInt = 100u

msg = "[ 2進数]   %%16s".format(uval.toString(2))
dispMsg(msg)
msg = "[ 8進数]   %%16s".format(uval.toString(6))
dispMsg(msg)
msg = "[10進数]   %%16s".format(uval.toString(10))
dispMsg(msg)
msg = "[16進数] 0x%%16s".format(uval.toString(16))
dispMsg(msg)

これを実行すると下記の様になります。

[ 2進数]            1100100
[ 8進数]                244
[10進数]                100
[16進数] 0x              64

さて、文字列の場合「%16s」の様に長さは指定できますが、数字の場合の様に0埋めをしたいからと言って「%016s」の様には指定できません(実行時に例外が発生します…^^;)

文字列で0埋めを実現したい場合は、下記の様な拡張関数を用意する事が出来ます。(拡張関数でなくてもいいですが…)

// 指定の基数(進数)、指定長で0埋めした文字列を返す
@ExperimentalUnsignedTypes
fun UInt.toString(radix:Int, length:Int) : String
{
    val strLen = this.toString(radix).length
    return if(strLen < length){ "0".repeat(length - strLen) }else{ "" } + this.toString(radix)
}

// 拡張関数を実行
msg = "[16進数] 0x%%s".format(uval.toString(16, 16))
dispMsg(msg)

これを実行すると下記の様に、0埋めが実現できます。

[16進数] 0x0000000000000064

文字列操作関数

文字列操作関数について記載しようと思いましたが、大量にあるのと、今すぐ自分に必要となるものは、もう上記で記載しているので、Kotlin本家のマニュアルのURLを貼っておきます。

[String – Kotlin Programming language]
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/


次回予告

現状、次回のネタが決まっていません…^^;

今回までは、Kotlinの基本的な部分を見てきたので、そろそろAndroidアプリに特有な部分について見て行きたいなとは思っています。


前の記事次の記事
No.08(クラス)(編集中)