概要 2015/07/22
C言語, C++ | 単なるバイト配列。長さの情報がないので終端文字 \x00 が必要 |
Java | UTF-16での16ビットの配列と長さ情報のあるオブジェクト |
Scala | UTF-16での16ビットの配列と長さ情報のあるオブジェクト |
PHP | 単なるバイト配列。長さ情報を一応は持っている |
Python | バイト配列またはUnicodeコードポイントの配列と長さ情報のあるオブジェクト |
Ruby | バイト配列と長さと文字符号化方式(文字コード)の情報をもったオブジェクト |
Perl | UTF-8での8ビットの配列または単なるバイト配列と長さ情報のあるオブジェクト |
C言語, C++ 2014/03/21
C言語における文字列は、char
型の配列であるか、配列の先頭へのポインタである。
配列自身には長さの情報がないため、文字列にも長さの情報がなく、終端文字として \x00
を置く習慣になっている。
メモリ上に配置された長さよりも長い文字列を保存してしまうと、バッファオーバーフローを起こしてしまう。
マルチバイトの文字はそのまま2バイト以上を使って保存する。文字符号化方式(文字コード)に関する情報は文字列自身は持っていないので、使うごとに文字列がなんの文字コードなのかを意識しないといけない。
ソースコード中に文字列リテラルを書くには、"
で囲む。これで \x00
で終わる char[]
型になる。
'
で囲むと文字列ではなく文字(char
型)になる。
Java 2014/10/31
Javaにおける文字列は、java.lang.String
クラスのインスタンスで、長さの情報とchar
型の配列を持った不変オブジェクトである。長さの情報を持っているため、終端文字を考えなくてよい。
char
型は文字列ではなく1文字だけを表すプリミティブ型で2バイトの整数である。
文字符号化方式(文字コード)は常にUTF-16である。Unicodeの \uFFFF
より大きい文字はサロゲートペアを使う。サロゲートペアの機能はJava5以降である。
サロゲートペアで表現する文字は4バイト必要なので、char
型2つ使って
\uFFFF
より大きい文字を表現する。従って、char
型が単純に単一の文字とは限らず、長さの情報として char
の数を返す String#length
も実際の文字数と一致するとは限らない。
Javaの最初の頃は、Unicodeは2バイトの範囲に収まっていたので、単一の文字を表すchar
は2バイトという仕様だった。あとからそれを拡張する必要に迫られて、char
を4バイトに変更するわけにはいかなかったので、
Java5からはサロゲートペアによってchar
2つで拡張された文字を表現することになった。
IO処理などの際は、文字符号化方式(文字コード)を指定することで任意の文字コードを扱うことができる。指定を省略した場合のデフォルトの文字符号化方式(文字コード)は環境などによって決められ、最近の環境ではほとんどがUTF-8になる。内部がUTF-16だと意識することはほとんどない。
任意の文字符号化方式のバイナリを外部から読み込んで内部のUTF-16に変換する際には、不正なバイナリは除外してくれる。例えばShift-JISやEUC-JPなどのマルチバイトの符号化の場合で、
2バイト目が2バイト目の範囲でないなどバイト列が不正な部分は、'?'
などに置き換えられる。なので、内部で文字列の中に不正なバイナリが混ざってしまう心配をしなくてもよい。
java.lang.String
は不変(immutable)であるが、可変(mutable)文字列としては、java.lang.StringBuilder
,
java.lang.StringBuffer
がある。
ソースコード中に文字列リテラル(String
型)を書くには、"
で囲む。
'
で囲むと文字列ではなく文字(char
型)になる。
Scala 2014/11/30
Scalaにおける文字列は、Javaのjava.lang.String
クラスそのままなので、Javaと同じく、内部ではUTF-16で、不変オブジェクトである。
java.lang.String
は scala.Predef
で scala.collection.immutable.StringOps
への暗黙の変換を定義しているので、文字列に対して scala.collection.immutable.StringOps
にあるメソッドもそのまま使うことができる。
ソースコード中に文字列リテラル(String
型)を書くには、Javaと同じく "
で囲む。
'
で囲むと文字列ではなく文字(scala.Char
型)になる。
PHP 2014/11/30
PHPでは文字列は長さの情報と単なるバイト配列であり、可変である。
長さの情報を持っているため、本来は終端文字を考えなくてよく、文字列の途中に \x00
を含めることもできる。ただし、文字列の途中に \x00
を含めた文字列は、バイナリセーフでない関数に渡すとおかしなことになるかもしれないので、やめたほうがよい。
ソースコード中に文字列リテラルを書くには、
'
または "
で囲む。またはヒアドキュメントを使う。
-> 文字列リテラル
文字列リテラルは、ソースコードで使われている文字符号化方式(文字コード)でバイナリに変換されて処理される。
単なるバイト配列であり可変オブジェクトであるので、 C言語のようにインデックスで指定して文字を変更してしまうことが可能。
$str = "abc\n";
echo $str;
// => abc
$str[1] = 'B';
echo $str;
// => aBc
Python 2014/11/29
Pythonの文字列は不変オブジェクトで、単なるバイト列とUnicode文字列(Unicodeコードポイントの列)の2種類の文字列がある。
長さの情報を持っているため、終端文字を考えなくてよく、文字列の途中に \x00
を含めることもできる。
Python2ではデフォルトはバイト列になる。u"..."
と書くとUnicode文字列になる。
Python3ではデフォルトはUnicode文字列になる。b"..."
と書くとバイト列になる。
Python2では、バイト列とUnicode文字列を混ぜて連結しようとすると、バイト列がASCIIの範囲内であればASCIIコードとみなしてUnicodeに変換してから連結する。範囲外のバイトが含まれていれば実行時にエラーになる。
Python3では、2種類を混ぜて連結しようとすると、内容によらずエラーになる。
Unicode文字列はencode
メソッドでバイト列に変換でき、バイト列はdecode
メソッドでUnicode文字列に変換できる。
文字列をリテラルとしてソースコード中に書くには
'
または "
で囲む。または三重引用符(トリプルクオート) '''
または """
で囲む。
トリプルクオートの中には改行をそのまま含めることもでき、複数行のコメントをトリプルクオートの文字列で書くことがよくある。
-> 文字列リテラル
Ruby 2014/12/30
Ruby 1.8以前と1.9以降とでは文字列の扱いが大きく異なる。
1.9以降では、1バイトの整数の配列と長さと文字コードの情報を持ったオブジェクトである。内部の文字コードがUnicodeで統一されているわけではなく、例えば入力・出力ともEUC-JPであれば、内部でもEUC-JPのままにすることで、変換する必要がなくなる。
文字列のencoding
メソッドで文字コードを取得できる。また、encode
メソッドで文字コードを変更することができ、そのときバイト列の内容もその文字コードに変換される。
force_encoding
メソッドは、文字コードの情報のみを書き換えて、バイト列は書き換えない。
ソースコード中の文字列リテラルは、このソースコードの文字コードと同じ形式でエンコードされた文字列になる。-> マジックコメント
例
# -*- coding: utf-8 -*-
src = "あいうえお"
p src.encoding
# => #<Encoding:UTF-8>
src = src.encode('EUC-JP')
p src
# => "\x{A4A2}\x{A4A4}\x{A4A6}\x{A4A8}\x{A4AA}"
p src.encoding
# => #<Encoding:EUC-JP>
長さの情報を持っているため、終端文字を考えなくてよく、文字列の途中に \x00
を含めることもできる。ただし、文字列の途中に \x00
を含めた文字列をCで実装された拡張に渡すとおかしなことになるかもしれないので、やめたほうがよい。
文字列のメソッドの中には文字列自身を変更するものがあるため、文字列はmutableなオブジェクトである。これはJavaなどのimmutableな文字列に慣れている人にとってはとても気持ち悪い。
ソースコード中に文字列リテラルを書くには、
'
または "
で囲む。またはヒアドキュメントを使う。
-> 文字列リテラル
Perl 2014/11/29
Javaに似ていて、内部ではUnicodeで処理していて、外界との入出力時に必要とする文字符号化方式で変換するのが原則。
use Encode qw/decode encode/;
# 入力時(外界が UTF-8 の場合)
$input = decode('utf-8', $input);
# 出力時(外界が UTF-8 の場合)
print encode('utf-8', $str);
または
use Encode qw/decode_utf8 encode_utf8/;
# 入力時(外界が UTF-8 の場合)
$input = decode_utf8($input);
# 出力時(外界が UTF-8 の場合)
print encode_utf8($str);
以下がわかりやすい。
図解: Perl と Unicode 文字列
http://d.hatena.ne.jp/dayflower/20080620/1213925271
Javaと違うのは、内部のUnicodeはPerlではUTF-8になっている点。それから、内部では必ずしもUnicodeである必要はなく、無理やり別の文字符号化方式のバイナリのまま処理し続けることもできる。
UTF-8になっている文字列には文字列オブジェクトにUTF8フラグがついている。そうでない文字列はすべてシングルバイトの文字だとみなされ、
UTF8フラグがオフになっている。外界からの入力時に decode
を呼び出せば、UTF8フラグがオンになり、なにも考えなくても文字列として処理できるが、
decode
を呼び出さないと、UTF8フラグがオフのままになり、文字符号化方式を常に意識しないといけない。
Perl Unicode の手引き | perldoc.jp
http://perldoc.jp/docs/perl/5.10.0/perluniintro.pod
Perl における Unicode サポート | perldoc.jp
http://perldoc.jp/docs/perl/5.12.1/perlunicode.pod
Encode
| search.cpan.org
http://search.cpan.org/dist/Encode/Encode.pm
ソースコード中に文字列リテラルを書くには、
'
または "
で囲む。
-> 文字列リテラル
Gauche (Scheme) 2014/07/18
Gaucheの文字列は、内部ではUTF-8でバイト列を保持しており、バイト数と文字数の情報も持っている。バイト数の情報があるため内部に終端文字を持っているとは限らず、文字列の途中に \x00
を含めることもできる。文字列はJavaなどと同じく不変であり、文字列を書き換える際にはいったんメモリ上でコピーされる。部分文字列を取得する際には内部でバイト列を共有する。
内部の文字符号化方式(エンコーディング)はGauche自身のコンパイル時のconfigureオプションで UTF-8以外を選択することもできる。
文字列について | Gaushe
http://practical-scheme.net/gauche/memo-str-j.html
sh (シェルスクリプト) 2014/05/27
変数に入れる値やコマンドに渡すパラメータなどはすべて文字列で、数値も文字列で表され、区別がない。
JavaScript 2014/01/13
ソースコード中に文字列リテラルを書くには、
'
または "
で囲む。
CoffeeScript 2013/09/10
ソースコード中に文字列リテラルを書くには、
'
または "
で囲む。
"
で囲んだ文字列は、中に式を埋め込むことができる。