DEKOの掲示板

何でも好きに書いてもらっていいのですが、URL投稿はできません。
どうしてもURLを晒したい場合には"ttp://〜"形式でお願いします。

投稿の際"ホームページのURL"の欄はお手数ですが空白にして下さい。
URLの投稿を禁止しているため、そのままではエラーになってしまいます。

投稿時にメールアドレスは必須ではありませんが、レスに困る事があるので同じ名前で投稿するようにして下さい。
旧掲示板と違い、管理者はREMOTE_HOSTが見えますのでくれぐれも発言にはご注意を。

スレッド全件表示

MECSUtilsのUTF32ToUTF16で文字数が変わります

  • 山本
  • 投稿日:2010/03/07 13:43

C++Builder2010でMECSUtilsのUTF32ToUTF16関数を使うと、文字数が変わります。
Delphiでは問題ありませんか?
使用しているバージョンは、MECS Utilities Unit ver1.41です。

UnicodeString us = "テスト";
UCS4String ucs4 = UnicodeStringToUCS4String(us);
WideString ws = Mecsutils::UTF32ToUTF16(ucs4);
cout << us.Length() << endl; //=>3
cout << ucs4.High << endl; //=>3
cout << ws.Length() << endl; //=>4

  • 1.DEKO
  • 投稿日:2010/03/07 14:12

こんにちは。

var
us: UnicodeString;
ucs4: UCS4String;
ws: WideString;
begin
us := 'テスト';
ucs4 := Mecsutils.UTF16ToUTF32(us);
ws := Mecsutils.UTF32ToUTF16(ucs4);
ShowMessage(IntToStr(Length(us)));
ShowMessage(IntToStr(Length(ucs4)));
ShowMessage(IntToStr(Length(ws)));
end;

Delphi では、上記コードは

3
4
4

を返しますので正常だと思います。

MECSUtils では、文字列ポインタへのキャストを容易にするため、WideString / UCS4String / TBytes のような中身が動的配列な変数については、配列の最後の要素にヌルを含むようになっています。
# Lengthは動的配列に対して
# 配列のサイズを返すので+1になります。

RTL の UnicodeStringToUCS4String はヌル終端で
処理しないので 3 になります。

  • 2.DEKO
  • 投稿日:2010/03/07 14:30

補足しておきますと...

動的配列は確保した動的配列の後ろに暗黙的にヌルが存在するため、文字列ポインタでキャストしても正しくヌル終端になるのですが、

'ABC' 配列要素数は 3

[0] = 'A'
[1] = 'B'
[2] = 'C'
[2+1] = NULL

古い Delphi では、この暗黙的なヌルが保証されません。このため、動的配列の最初の要素を文字列ポインタに渡して処理しようとすると、'ABC'の後に不正な文字が続く事になってしまいます。

# 実はこれもデブキャンネタの一つです。

  • 3.山本
  • 投稿日:2010/03/07 16:43

了解しました。
ありがとうございました。

  • 4.山本
  • 投稿日:2010/03/08 11:45

UnicodeString s1 = "テスト";
UnicodeString s2 = MecsMappingFix_JISX0208ToUnicode(s1);

ShowMessage(IntToStr(s1.Length())); //=> 3
ShowMessage(IntToStr(s2.Length())); //=> 4

bool equal = (s1 == s2); //=> false
if (equal) {
ShowMessage("一致する");
} else {
ShowMessage("一致しない");
}

s1とs2には"テスト"という文字が入りますが、長さが異なります。
そのため (s1==s2) は false になります。

MecsMappingFix_JISX0213ToJISX0208の中でUTF16ToUTF32/UTF32ToUTF16を使用しているために、文字列の長さが変わっているのだと思います。

これは想定通りの動作でしょうか。
よろしくお願いします。

  • 5.DEKO
  • 投稿日:2010/03/08 14:41

難しい問題なのですよねぇ...。

procedure TForm1.Button1Click(Sender: TObject);
var
 UCS4: UCS4String;
begin
 UCS4 := WideStringToUCS4String('あああ');
 ShowMessage(IntToStr(Length(UCS4)));
end;

同じ(?)動的配列である UCS4String は RTL の関数もヌル終端で処理するんです。WideString は BSTR 互換なので暗黙のヌル終端が保証されるのでしょうが...。

なんか一貫性がないような気もしますが、WideString だけはヌル終端しないようにしてみますかねぇ...。

# でもそうすると Length(UCS4) と Length(WideString) が
# 辻褄合わない事になっちゃうんですよ...悩ましい。

  • 6.DEKO
  • 投稿日:2010/03/08 14:43

上記のコードは '4' を返します。

  • 7.DEKO
  • 投稿日:2010/03/08 15:40

MECSUtils 1.42 をリリースしました。

  • 8.DEKO
  • 投稿日:2010/03/08 15:49

function foo(ucs4: UCS4String): WideString; overload;
function foo(ucs4: UCS4String): UnicodeString; overload;
ができれば、もっと気の利いた事ができるのですが...。

# でっかい文字列変換クラス作るのも
# アレだしなぁ...。

タグ:

おすすめサービス

InterPot(インターポット) ドメイン@nifty @niftyホームページサービス