文字列の前端後端に指定文字列を追加する関数
2 IncludeFirstStr 動作確認 Delphi2007 更新日 2007/08/25(土)


フォルダパス名の終端に[\]記号が付属しているかしていないかに関わらず
IncludeTrailingPathDelimiter(フォルダパス)
を実行すると、終端に[\]記号を付属させてくれますが

これを発展させて
文字列の両端に対して、任意の文字列を付属させる事のできる関数を作りました。


────────────────────
{------------------------------- 
// 文字列の先頭(First)と終端(Last)に文字列を含ませたり取り除く関数 
機能: 
備考:       IncludeBothEndsStrは 
            AnsiQuotedStrと同じような仕様かもしれない 
履歴:       2007/07/25(水) 17:14 
//------------------------------} 
function IncludeFirstStr(const S: WideString; const SubStr: WideString): WideString; 
begin 
  if WideStringPartsCompare(SubStr, S, 1) then 
  begin 
    Result := S; 
  end else 
  begin 
    Result := SubStr + S; 
  end; 
end; 

function IncludeLastStr(const S: WideString; const SubStr: WideString): WideString; 
begin 
  if WideStringPartsCompare(SubStr, S, Length(S)-Length(SubStr)+1) then 
  begin 
    Result := S; 
  end else 
  begin 
    Result := S + SubStr; 
  end; 
end; 

function IncludeBothEndsStr(const S: WideString; const SubStr: WideString): WideString; 
begin 
  Result := IncludeLastStr(IncludeFirstStr(S, SubStr), SubStr); 
end; 

procedure testIncludeBothEndsStr; 
begin 
  Check('"テスト"', IncludeBothEndsStr('テスト', '"')); 
  Check('"テスト"', IncludeBothEndsStr('"テスト', '"')); 
  Check('"テスト"', IncludeBothEndsStr('テスト"', '"')); 
  Check('"テスト"', IncludeBothEndsStr('"テスト"', '"')); 
  Check('テスト', IncludeBothEndsStr('テスト', '')); 
  Check('テスト', IncludeBothEndsStr('テスト', '')); 
  Check('テスト', IncludeBothEndsStr('テスト', '')); 
  Check('テスト', IncludeBothEndsStr('テスト', '')); 
end; 

function ExcludeFirstStr(const S: WideString; const SubStr: WideString): WideString; 
begin 
  if WideStringPartsCompare(SubStr, S, 1) then 
  begin 
    Result := DeleteStr(S, 1, Length(SubStr)); 
  end else 
  begin 
    Result := S; 
  end; 
end; 

function ExcludeLastStr(const S: WideString; const SubStr: WideString): WideString; 
begin 
  if WideStringPartsCompare(SubStr, S, Length(S)-Length(SubStr)+1) then 
  begin 
    Result := DeleteStr(S, Length(S)-Length(SubStr)+1, Length(SubStr)); 
  end else 
  begin 
    Result := S; 
  end; 
end; 

function ExcludeBothEndsStr(const S: WideString; const SubStr: WideString): WideString; 
begin 
  Result := ExcludeLastStr(ExcludeFirstStr(S, SubStr), SubStr); 
end; 

procedure testExcludeBothEndsStr; 
begin 
  Check('テスト', ExcludeBothEndsStr('"テスト"', '"')); 
  Check('テスト', ExcludeBothEndsStr('"テスト', '"')); 
  Check('テスト', ExcludeBothEndsStr('テスト"', '"')); 
  Check('テスト', ExcludeBothEndsStr('テスト', '"')); 
  Check('テスト', ExcludeBothEndsStr('テスト', '')); 
  Check('テスト', ExcludeBothEndsStr('テスト', '')); 
  Check('テスト', ExcludeBothEndsStr('テスト', '')); 
  Check('テスト', ExcludeBothEndsStr('テスト', '')); 
end; 
//------------------------------ 

{------------------------------- 
// 文字列終端に\記号が追加されたり取り除かれたりする関数 
機能:       Include/ExcludeTrailingPathDelimiter()互換(たぶん) 
            関数名が長すぎて嫌だからこっちを使う事にした。 
備考: 
履歴:       2007/07/25(水) 17:14 
//------------------------------} 
function IncludeLastPathDelim(const Path: WideString): WideString; 
begin 
  Result := IncludeLastStr(Path, PathDelim); 
end; 

function ExcludeLastPathDelim(const Path: WideString): WideString; 
begin 
  Result := ExcludeLastStr(Path, PathDelim); 
end; 
//------------------------------ 
────────────────────

コマンドライン系の処理で必要と思われる
ダブルクウォートやシングルクウォートで文字を囲ませる機能や
HTMLの<B>タグを付属させるような処理もやりやすくなるでしょう。

メール本文に引用符記号[> ]を追加させてみたり取り除いたりも
簡単になりますね。


※補足
ところで、NiftyFDelphiのテクニックでは
PutYenMark関数というものが出てきます。
検索したところ、これだけ出てきます。
fdelphi/faq/00048.htm
fdelphi/faq/00052.htm
fdelphi/faq/00073.htm
fdelphi/faq/00147.htm
fdelphi/faq/00148.htm
fdelphi/samples/00879.html

実装は下記のようになっています。
────────────────────
function PutYenMark(vDir: TFilename): TFilename;
var
  Len: integer;
begin
  Len:=Length(vDir);
  if vDir[Len]<>'\' then
    Result:=vDir+'\'
  else
    Result:=vDir;
end; {PutYenMark}
────────────────────
※TFileName=String

これはマルチバイト非対応なので
2バイト文字に\と同じコードが含まれるファイルパスがきた場合
容易に誤動作するので注意しましょう。

"\"のSJIS文字コードは[5C]
"ソ"のSJIS文字コードは[835C]
なので、パス名の最後に[ソ]がくる場合誤動作します。

下記のテストでテストを行うと誤作動することが確認できます。
────────────────────
procedure testPutYenMark;
begin
  Check('C:\', PutYenMark('C:'));
  Check('C:\test\', PutYenMark('C:\test'));
  Check('C:\test\', PutYenMark('C:\test\'));
  Check('C:\test\あ\', PutYenMark('C:\test\あ'));
  Check('C:\test\あ\', PutYenMark('C:\test\あ\'));
  Check('C:\test\ソ\', PutYenMark('C:\test\ソ'));	//★
  Check('C:\test\ソ\', PutYenMark('C:\test\ソ\'));
end;
────────────────────

必要なユニット────────────────────
StringUnitLight.pas