文字列

この章では Curl® 言語の文字列について説明します。
文字列に関連する情報は以下の章でも解説されています。

文字列入門

文字列とは一続きの文字のことです。たとえば、次の例は文字列です。
Hello World
文字列を指定するには、文字列の文字を二重引用符 (") で囲みます。次に例を示します。
"Hello World"
この章では、Curl® 言語の文字列について解説します。この章は以下のセクションで構成されています。
文字列の個々の文字を参照するには、その文字のインデックスを指定します。インデックスは文字列内の文字の位置を示します。Curl 言語では、1 番目の文字はインデックス (0) で、後続の各文字ではインデックスが 1 ずつ増えていきます。次の例では、上記の文字列の各文字のインデックスを表示して、文字列がどのように表わされるかを示しています。


この例では、W はインデックス 6r はインデックス 8 に位置します。

文字列のタイプ

要約
  • 文字列には、読み取り専用と、読み取り / 書き込み可能の 2 種類があります。

読み取り専用の文字列

読み取り専用の文字列を初期化すると、その文字列内の個々の文字は変更できません。読み取り専用の文字列は不変文字列とも呼ばれます。読み取り専用の文字列には、1つ固有の(標準の)クラスがあります:String。このクラスは読み取り専用のユニコード文字(char)の文字列を実装します。
String に対して、Curl言語は自動的に文字ごとのビット( 8、16、または 32 )を選択します。例えば、Stringchar 値( \u0000-\u00FF)である場合は、そのStringは、自動的に1 char 当たり、8 ビットをメモリで使用します。

読み取り / 書き込み可能な文字列

読み取り / 書き込み可能文字列では、個々の文字を変更できます。読み取り / 書き込み可能文字列は、可変文字列としても知られています。読み取り / 書き込み可能文字列には、1 つの組み込みのクラス、StringBuf があり、これは Unicode 文字 (char) の読み取り / 書き込み可能文字列を実装します。

クラス階層

Curl 言語の文字列クラスの階層を次に示します。
StringInterface
ReadOnlyString
String
WritableStringTextOutputStream
StringBuf
SubString
StringInterface は、Curl 言語のすべての文字列クラスのインターフェイスを提供する抽象クラスです。
ReadOnlyString は、Curl 言語の読み取り専用文字列のインターフェイスを提供する抽象クラスです。String のスーパークラスです。Stringfinal クラスとして実装されることに注意してください。したがって、これらのクラスは文字列オブジェクトの作成には使用できますが、サブクラスの作成には使用できません。
WritableString は、Curl 言語の読み取り / 書き込み可能文字列のインターフェイスを提供する抽象クラスです。StringBuf のスーパークラスになります。

文字列の作成

要約
  • 該当する文字列クラスのデータ型を使用して変数を宣言します。
  • 適切な文字列オブジェクトを変数に代入します。
  • 二重引用符 (") で囲まれた文字は、文字列リテラルとして解釈されます。
  • size を指定する場合は、内容を定義せずに StringBuf を作成することができます。
Curl 言語には、多数の組み込みの文字列クラスがあります。文字列を作成するには、該当する文字列クラスのデータ型を使用して変数を宣言します。次に例を示します。
{value
    let s1:#String            || A read-only string of characters
    let sb1:#StringBuf        || A read-write string of characters
}
注意: 上記の宣言で、# は変数が null (値を持たないこと) または文字列になることを指定しています。変数が null 値になる場合は、宣言で # を指定する必要があります。それ以外の場合、コンパイラは NullDereferenceException を返します。
次に、適切な文字列オブジェクト (つまり、対応する文字列クラスのインスタンス) を変数に代入します。変数を宣言するときに、文字列オブジェクトの値を初期化することもできます。文字列オブジェクトの値を初期化するには、対応するクラスのインスタンスを作成し、引数として文字列を渡します。次に例を示します。
{value
    let s1:#String = {String "Hello World"}
    let sb1:#StringBuf = {StringBuf "Hello World"}
}
ただし、変数を宣言するときに文字列を初期化する必要はありません。後で set ステートメントを使用して、文字列オブジェクトを変数に代入することができます。次に例を示します。
{value
    set s1 = {String "Hello World"}
    set sb1 = {StringBuf "Hello World"}
}
既定では、実行時に二重引用符 (") で囲まれた文字に対して文字列リテラルが作成されます。文字列リテラルは String オブジェクトのインスタンスです。これは、文字列オブジェクトを変数に代入する場合に String クラスのインスタンスを明示的に指定する必要がないことを意味します。ただし、他の文字列クラス (たとえばStringBuf) については、すべてインスタンスの指定が必要です。次に例を示します。
{value
    let s1:String = "Hello World"
}
ただし、他の文字列クラス (StringBuf) については、すべてインスタンスの指定が必要です。
文字列演算子 (&) を使用して、String の内容を指定することができます。文字列演算子は 2 つの文字列を連結します。たとえば、次のコードでは s1s4 および s5 は同じ文字が含まれることになります。
{value
    let s1:String = "Hello World"
    let s2:String = "Hello"
    let s3:String = " World"
    let s4:String = s2 & s3
    let s5:String = "Hello" & s3
}
StringBuf クラスでも同様の結果が得られます。たとえば次のコードでは、StringBuf の各インスタンスは引数を 1 つ取っています (文字列演算子を含む式は文字列リテラルを返します)。
{value
    let sb1:StringBuf = {StringBuf "Hello World"}
    let sb2:StringBuf = {StringBuf "Hello"}
    let sb3:StringBuf = {StringBuf " World"}
    let sb4:StringBuf = {StringBuf sb2 & sb3}
    let sb5:StringBuf = {StringBuf "Hello" & sb3}
}
ただし、文字列の各インスタンスに引数として文字列を定義しても同じ結果が得られます。文字列クラスはすべて、引数の印字表現を連結して文字列を形成します。したがって、次のコードでは文字列演算子を使用していませんが、同じ結果を生成します。
{value
    let sb1:StringBuf = {StringBuf "Hello World"}
    let sb2:StringBuf = {StringBuf "Hello"}
    let sb3:StringBuf = {StringBuf " World"}
    let sb4:StringBuf = {StringBuf sb2, sb3}
    let sb5:StringBuf = {StringBuf "Hello", sb3}
}
size を指定する場合は、内容を定義せずに StringBuf を作成することができます。次に例を示します。
{value
    let sb1:StringBuf = {StringBuf size=10}
}
この例では、読み取り /書き込み可能文字列 sb1 は 10 文字で、それぞれに既定の文字値が含まれています。既定の文字値は、Unicode 文字の値 \u0000 (Curl 言語で null 文字と呼ばれます) です。文字列の size については、この章の後半で説明します。

文字列と null

null の印字表現は <null> です。文字列オブジェクトのインスタンスを作成するときに引数として null を指定すると、文字列には null の印字表現 (つまり <null>) が格納されます。次に例を示します。

例: 文字列の引数として null を使用 (パート 1 )
|| Declare a String variable and assign a string object to it, with null
|| as a parameter to the object instantiation.
{let s:String = {String null}}

|| Display s.
{value s}
もう 1 つの例を次に示します。

例: 文字列の引数として null を使用 (パート 2)
|| Declare a StringBuf variable and assign a string object to it, with
|| null as a parameter to the object instantiation.
{let sb:StringBuf = {StringBuf 99, null, "red balloons"}}

|| Display sb
{value sb}

文字クラス

CharClass は、非常に効率的に実装できる文字のセットです。Curl 言語では、多くのプロシージャおよびメソッドが CharClass の引数を使用して、文字セットをプロシージャまたはメソッドに渡します。たとえば、StringBuf.trim メソッドでは、トリム文字を指定する CharClass 引数を渡すことができます。
CharClass オブジェクトを取得するには、文字列からオブジェクトをキャストする、ロケール定義から読み込む、または他の文字クラスと文字列の組み合せから構築するという方法が一般的です。文字クラスの主な特性は member? メソッドの速度にあります。member? メソッドは文字を引数として取り、bool を返してその文字が文字クラスのメンバであるかどうかを示します。
次の例では、文字クラスを宣言して操作する方法を示しています。

例: 文字クラスの宣言と操作
{value
    || Create a character class from a string of characters.
    let vowels:CharClass = "AaEeIiOoUu"

    || Create a character class from a combination of
    || the earlier declared character class and a string
    || of characters.
    let sort-of-vowels:CharClass = {CharClass vowels, "Yy"}

    || Declare and initialize some counter variables that
    || will be used to show some possible uses of character
    || classes.
    let vowels-count:int = 0
    let sort-of-vowels-count:int = 0

    || Declare and initialize a string.
    let the-string:String = "Hello World!  Here comes that curly language!"

    || For each character in the string, check whether it is
    || a member of the declared character classes and update the
    || relevant counter variable.
    {for ch:char in the-string do
        {if {vowels.member? ch} then
            {inc vowels-count}
        }
        {if {sort-of-vowels.member? ch} then
            {inc sort-of-vowels-count}
        }
    }

    || Display a message indicating the values of the counter
    || variables for the string.
    {paragraph
        I saw {value vowels-count} vowels and
        {value sort-of-vowels-count} sort-of vowels.
    }
}