DelFusa Blog 総本山

プログラミングの話題とかです。

NEW | PAGE-SELECT | NEXT

≫ EDIT

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

| スポンサー広告 | --:-- | comments(-) | trackbacks(-) | TOP↑

≫ EDIT

インクルードトライリングパスデリミター


   δ δ  
 δ 
  ∧△、  / ̄ ̄ ̄ ̄ ̄ ̄ ̄
  ミ,,゚Д゚彡<  あつめしや~
  ミU U   \_______
  ミ  ミ
   )/   
  ν    ドロロロロロロロ♪


いやあ、どーもどーも。こんばんは。
みなさん、元気してますかい?

黒バックにしたのは、いかがです?

なつですので、ちょっと怖い雰囲気コスプレってみますた。


さて。今日のネタは

文字列の最終文字にパスが含ませる為の関数
IncludeTrailingBackslash(D5以降)/IncludeTrailingPathDelimiter(D6以降)が、あまりにも使いにくい件についてです。

この関数の詳細内容は、ヘルプをみてください。

この標準関数、命名則もどーかと思いますが
機能がもんのすごい、中途半端なんですよ。
『パス区切り文字だけ』『文字列後端だけ』
しか指定できない。という仕様です。

お客さん!仕様ですよ!仕様!


こういう風に汎用的に考えられてない関数は、
様々な場面で、"惜しい"ってことになるわけですよ。

文字列をシングルクウォーテーションで前後で囲む形に整形したいんだけど.....という場面ではIncludeTrailingBackslashは使えるわけがありません。やっている動作はほとんど一緒のくせしてね。

ということで、自作してしまいましょう。


つまり、汎用的になるように、Include○△□(AAA, 任意文字, 前方/後方/どっちも);
という関数を作りたいわけです。AAAに任意文字を前後に追加できたりするような、のが欲しい。

まあ、前方後方両方のスイッチは引数じゃなくて各関数名として独立させたとして
IncludeFirstStr/IncludeLastStr/IncludeBothEndsStr
ExcludeFirstStr/ExcludeLastStr/ExcludeBothEndsStr
こんな命名にしてみましょう。

テスト関数は次のようになります。
テスト関数であるCheckは、2つの引数が一致してなかったら、『ブー』と、警告が出る関数です。

 Check('テスト', IncludeFirstStr('テスト', ''));
  これが最も基本。IncludeFirstStr関数がどういう動作をして欲しいのか、一発でわかりますね。
  これがテストコード=関数の仕様書。となりうるという事なのです。
  だから、テストを先に書け。というテストファーストなのです。

 Check('テスト', IncludeFirstStr('テスト', ''));
  これがすでに文字が含まれている事を判別するテスト

 Check('<>テスト', IncludeFirstStr('<>テスト', ''));
  少し変則的なテスト

 Check('スト', IncludeFirstStr('テスト', ''));
 Check('スト', IncludeFirstStr('スト', ''));
 Check('スト', IncludeFirstStr('スト', ''));
 Check('
スト', IncludeFirstStr('テスト', ''));
  より変則的なテスト、『ブー』と鳴りやすい状況を作り出すテスト

さて、簡単にIncludeFirstStrのテストコードが書けました。
IncludeTrailingPathDelimiter関数と比べて、俺が何をしたいのか伝わりましたか?
日本語でヘルプ記述するよりも、テストコード書く方が早いでしょ。
俺らのコミュニケーションの伝達。

というわけで、
このテストコード中のを前方ではなく、後方にして、\記号に置き換えてしまってもいいでしょう。
全角に含まれている半角記号に対してちゃんと動作するかどうかも
テストとして書いておくのも手です。

 Check('\テスト', IncludeFirstStr('テスト', '\')); ①
 Check('\テスト', IncludeFirstStr('\テスト', '\')); ②
 Check('\\テスト', IncludeFirstStr('\\テスト', '\')); ③
 Check('\\\テスト', IncludeFirstStr('\\\テスト', '\')); ④
  こういうテストコードも作れます。正直言うと、②と③のテストコードは
  ①と④と比べて誤動作する可能性が低いので不要ですが、
  書いておいてもいいでしょう。

このテストで『ブーーー』と、鳴らないようにコードを書いていくわけです。

前方一致は、Posで戻り値が1になればいいけど
後方一致の、IncludeEndStrのほうは少し計算がめんどくさいかな。
バグが出るかもね。
挑戦してみてはいかがかな?

でも、このテストコードを通過すれば
ノンバグコーディングができて、安心なのです。

漏れは、WideString対応の部分文字列一致関数や
Delete関数の、文字列戻り値出力版も自作してるので手早くつくれてしまいます。


{-------------------------------
// 文字列の先頭(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;
//------------------------------

これで、IncludeTrailingPathDelim互換機能や
これでダブルクウォートやシングルクウォートで文字を囲ませるとか
(コマンドライン系の処理でいるでしょ?)

メールの引用符記号[> ]を追加させてみたり、簡単かな。


{-------------------------------
// 文字列終端に\記号が追加されたり取り除かれたりする関数
機能: 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;
//------------------------------

もっと昔から作っておけばよかったぜ。


同様の処理でTrim関数に関しても任意文字指定でのトリムも用意してます。
全角スペースに対するトリムとか。
前方のタブだけトリムしたい。みたいな処理にもすぐ対応してしまいましょう。

StringUnitLight.pas
TrimLeftとかTrimRightにしたけど
TrimFirst/TrimLastに名前変更しちゃおうかな...

自作ライブラリは自分でつくっていけるから、楽しいです。

皆さんも作ったり、漏れんとこから、ぱくっていいものをつくっていってくださいね。
スポンサーサイト

| 未分類 | 00:45 | comments:2 | trackbacks:0 | TOP↑

COMMENT

SysUtils の AnsiQuotedStr 関数じゃダメですか?

| pik | 2007/09/03 14:10 | URL | ≫ EDIT

AnsiQuotedStr では、一気に両端に対してしか処理できないですし、
["AAA"]という文字列を渡すと
[""AAA""]と返ってきますので、これじゃ、役に立たない。って感じなのですよ。

ダブルクウォートで囲まれているか囲まれていないか、わからない文字列に対して囲まれている事を保証させるという使い方ができます。

| ミ・д・彡 | 2007/09/04 07:32 | URL | ≫ EDIT















非公開コメント

TRACKBACK URL

http://delfusa.blog65.fc2.com/tb.php/75-22060f0a

TRACKBACK

PREV | PAGE-SELECT | NEXT

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。