#0を含む文字列の処理
96 CtrlCodeZeroString 動作確認 Delphi2007 更新日 2010/06/24(木)

時々、制御文字、コントロールコードの#0を含んだ文字列を
処理する機会があります。

ネットワークからダウンロードした文字列を扱う時などです。

#0はC/C++などではヌル終端文字列と呼ばれます。
先頭からこの制御文字がある所までを文字列として認識したりする仕様です。

Delphiの文字列、String型はこれを扱う事もでき、
文字列の比較や代入などでは#0を含んでいても正しく行なわれていますが、

例えばTLabel.Captionに代入しようとしたり
ShowMessageで文字列を表示させようとすると
このヌル文字の前までしか認識しません。


そこで、#0を含む文字列から#0を取り除いたり
#0の前までを取り出す方法を調べました。

────────────────────
//文字列から#0を消す関数
function ZeroCodeDelete(const S: String): String;
begin
  Result := S;
  if Result = '' then Exit;
  while 1 <= Pos(#0, Result) do 
  //AnsiPosは#0に対して動作しないので使ってはいけない。
  begin
    Delete(Result, Pos(#0, Result), 1);
    if Result='' then break;
  end;
end;

//文字列を比較する手続き
procedure VariantCheck(A, B: Variant);
begin
  if not(A = B) then
  begin
    Assert(False,
      Format('Error A!=B'#13#10'A=%s'#13#10'B=%s'#13#10,
        [String(A), String(B)]));
  end;
end;

procedure Check(A, B: String); overload;
begin
  VariantCheck(A, B);
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  S1, S2: String;
begin
  S1 := 'ABC' + #0 + '123';
  S2 := S1;
  Check(S1, S2);

  {↓#0を削除}
  S2 := ZeroCodeDelete(S1);
  Check('ABC123', S2);

  {↓#0より前の文字だけ取り出し}
  S2 := String(PChar(S1));
  Check('ABC', S2);
end;
────────────────────
一度 PChar にキャストしてから String に変換すると
C/C++スタイルの文字列と判断されて
#0より前の文字列だけ取り出すことが簡単に出来ます。