1

私は既存のコードをゆっくりとDelphi2010に変換し、EmbarcaedroWebサイトのいくつかの記事とMarcoCantúホワイトペーパーを読んでいます。

私が理解していないことがまだいくつかあるので、ここに私の質問を例示するための2つの関数があります。

function RemoveSpace(InStr: string): string;
var
  Ans     : string;
  I       : Word;
  L       : Word;
  TestChar: string[1];
begin
  Ans := '';
  L := Length(InStr);
  if L > 0 then
  begin
    for I := 1 to L do
    begin
      TestChar := Copy(InStr, I, 1);
      if TestChar <> ' ' then Ans := Ans + TestChar;
    end;
  end;
  RemoveSpace := Ans;
end;

function ReplaceStr(const S, Srch, Replace: string): string;
var
  I: Integer;
  Source: string;
begin
  Source := S;
  Result := '';
  repeat
    I := Pos(Srch, Source);
    if I > 0 then begin
      Result := Result + Copy(Source, 1, I - 1) + Replace;
      Source := Copy(Source, I + Length(Srch), MaxInt);
    end
    else Result := Result + Source;
  until I <= 0;
end;

RemoveSpace関数の場合、Unicode文字が渡されなければ(たとえば、「aa bb」)、すべて問題ありません。ここで、テキスト「ab cd」を渡すと、関数は期待どおりに機能しません(出力としてab ?? cdを取得します)。

文字列で可能なUnicode文字をどのように説明できますか?Length(InStr)の使用は、Copy(InStr、I、1)と同様に明らかに正しくありません。

このコードをUnicode文字を考慮して変換する最良の方法は何ですか?

ありがとう!

4

5 に答える 5

14

それらがあなたのREAL関数であり、emを機能させようとしているだけの場合:

function RemoveSpace(const InStr: string): string;
begin
  Result := StringReplace(InStr, ' ', '', [rfReplaceAll]); 
end;

function ReplaceStr(const S, Srch, Replace: string): string;
begin
  Result := StringReplace(S, Srch, Replace, [rfReplaceAll, rfIgnoreCase]); 
end;
于 2009-10-07T12:46:24.457 に答える
1

(現時点ではD10を使用していませんので、注意してください!)

Delphiの問題は、基本的なASCII範囲外の文字を含む文字列リテラルにあります。それらが文字列ルーチンに渡されると、非ASCII文字は疑問符に置き換えられます。

これを回避するには、テキストリテラルをパラメータとして関数に渡す前に、テキストリテラルをWideStringsにキャストします。

StringReplaceルーチンに適用されるかどうかはわかりませんが、Delphiの検索ルーチンPos/PosexはUnicodeを正しく処理しません。これらのルーチンを独自のバリアントに置き換える必要がありました。この改善されたルーチンでは、パラメーターが通常の文字列型ではなく、WideString型であることを確認することが重要です。

Unicodeを処理するときにD7でこれを実行しましたが、すべて正常に機能します。

于 2009-10-07T14:59:16.080 に答える
1

現在はUnicodeタイプですがstring、長さを指定すると、非UnicodeShortStringタイプが取得されます。関数内のTestChar変数は、RemoveSpaceUnicode以外の1文字の文字列です。ずっと使っていたはずの実Char変数です。1文字の文字列が1文字と同じVBの世界から来たと思います。Delphiでは、文字列は文字と同じではないため、を呼び出すCopyと文字列が取得されます。

Unicode Delphiでは、その1文字の文字列は非Unicode文字列に縮小され、現在のコードページにその文字の表現がない場合は、代わりに疑問符が表示されます。次のように修正します。

function RemoveSpace(const InStr: string): string;
var
  I: Integer;
  TestChar: Char;
begin
  Result := '';
  for I := 1 to Length(InStr) do
  begin
    TestChar := InStr[I];
    if TestChar <> ' ' then
      Result := Result + TestChar;
  end;
end;

私はを取り除きましたAnsResultTurbo Pascal 7以降では、独自の変数を宣言してから関数名に割り当てる代わりに、暗黙的に宣言された変数を使用できます。Result読み取りと書き込みが可能です。また、長さゼロの入力について心配する必要はありません。「for-to」ループの上限が下限よりも小さい場合、ループは単に実行されないため、事前に確認する必要はありません。最後に、1文字の長さの文字列を取得する代わりに、ブラケット演算子を使用して、指定されたインデックスの文字InStrを抽出しました。

Lengthとの使用法は明らかに間違っているとあなたは言いますCopyが、あなたは間違っています。これらの関数は、Unicodeでも引き続き正常に機能します。彼らはそれCharが現在2バイト幅であることを知っているので、UnicodeString変数でそれらを呼び出すと、正しい文字が得られます。彼らはまた変数に取り組み続けAnsiStringます。実際、WideString古いDelphiバージョンでも、変数の検索も機能します。

コードの主な問題は、Unicode文字を非Unicode文字列型に格納する場所でした。

于 2009-10-07T15:09:17.340 に答える
0

String[1]にはUnicodeバージョンがありません

代わりにCharを試してください。

于 2010-02-03T06:58:25.277 に答える
0

問題の説明から推測すると、UTF8でエンコードされた文字列を処理しているようです。それはほとんどの場合悪い考えです。最初にそれらをより適切な表現にデコードしてから、それらを操作します。完了したら、すべてをUTF-8として再度エンコードできます。

ワイド文字列のデータ型はDelphiでは「WString」だと思います。今は調べられません。

于 2009-10-07T12:27:36.027 に答える