簡単な質問だと思いますが、例えば「abcdafff」と文字列があった場合に
文字列を後ろから検索して先頭から2つ目の「a」より後ろの「fff」を
取得する便利な関数はありませんか?
先頭から2つ目の「a」の位置がPos関数等で簡単に取得出来れば良いのですが・・。
また、これに関連して「c」より前の「ab」を取得する関数はありませんか?
Copy関数のように「c」の文字位置より「ab」を取得するのではなく、
「c」という文字を基準にして「ab」を取得することは出来ませんか?
よろしくお願いします。
正規表現ユニット使ってもいいですが、Delphiで書くならこんな漢字。
//1
function getText1(SubStr,Str:string):string;
var i:integer;
begin
for i:= Length(Str)-Length(SubStr) downto 1 do
begin
if Copy(Str,i,Length(SubStr))=SubStr then
begin
Result:=Copy(Str,i+Length(SubStr),Length(Str));
exit;
end;
Result:='';
end;
end;
//日本語サポート版
function getText1W(SubStr,Str:Widestring):WideString;
var i:integer;
begin
for i:= Length(Str)-Length(SubStr) downto 1 do
begin
if Copy(Str,i,Length(SubStr))=SubStr then
begin
Result:=Copy(Str,i+Length(SubStr),Length(Str));
exit;
end;
Result:='';
end;
end;
//2
function getText2(SubStr,Str:string):string;
var i:integer;
begin
for i:= Length(Str)-Length(SubStr) downto 1 do
begin
if Copy(Str,i,Length(SubStr))=SubStr then
begin
Result:=Copy(Str,1,i-1);
exit;
end;
Result:='';
end;
end;
//日本語サポート版
function getText2W(SubStr,Str:string):string;
var i:integer;
begin
for i:= Length(Str)-Length(SubStr) downto 1 do
begin
if Copy(Str,i,Length(SubStr))=SubStr then
begin
Result:=Copy(Str,1,i-1);
exit;
end;
Result:='';
end;
end;
//サンプル
procedure TForm1.Button1Click(Sender: TObject);
begin
Caption:=getText1('a','abcdafff');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Caption:=getText2('c','abcdafff');
end;
//2
//日本語サポート版
function getText2W(SubStr,Str:Widestring):Widestring;
> 文字列を後ろから検索して先頭から2つ目の「a」より後ろの「fff」を
> 取得する便利な関数はありませんか?
後ろから検索して、前から二つ目の「a」?
前から検索した方が早いですよ。
後ろから検索して見つかった「a」が、先頭から何番目かなんてわかりませんけど?
> 取得する便利な関数はありませんか?
ありません
> 「c」という文字を基準にして「ab」を取得することは出来ませんか?
できます
やりたいことがわかっているのだから、その通りにやればいいだけです。
↓ノリで書いたので、コンパイルが通るのかも、動くのかもテストしていません。
function HogeHoge1(aSubStr, aStr: String): String;
var
i: Integer;
begin
//例: aSubStr = 'a', aStr := 'abcdafff'
Result := '';
//一個目の'a'を検索
i := Pos(aSubStr, aStr);
//i:=1
if i > 0 then begin
//一個目の'a'までを削除
//'abcdafff' -> 'bcdafff'
Delete(aStr, 1, i + Length(aSubStr) - 1);
//二個目の'a'を検索
i := Pos(aSubStr, aStr);
//i=4
if i > 0 then begin
//二個目の'a'までを削除
//'bcdafff' -> 'fff'
Delete(aStr, 1, i + Length(aSubStr) - 1);
Result := aStr;
end;
end;
end;
function HogeHoge2(aSubStr, aStr: String): String;
var
i: Integer;
begin
//例: aSubStr = 'c', aStr := 'abcdafff'
Result := '';
//'c'を検索
i := Pos(aSubStr, aStr);
//i:=3
if i > 0 then begin
//'c'以降を削除
//'abcdafff' -> 'ab'
Delete(aStr, i, Length(aStr));
Result := aStr;
end;
end;
↑
はいはい さんとは書き方が違うだけと思うが、詳しく見ていない
違うでしょ。
「にわ」「にわにはにわにわとりがいる」
で
「にわとりがいる」と「とりがいる」のどっちが欲しいのか次第。
そもそも”後ろから検索して先頭から2つ目の「a」より後ろの「fff」”が曖昧な表現だから
後ろから検索して最初に見つかった文字の後ろなのか
前から検索して二つ目に見つかった文字の後ろなのか不明。
質問の仕方が論理的にあいまいすぎるだよ。
> 文字列を後ろから検索して先頭から2つ目の「a」より後ろの「fff」を
これは、後ろから検索する意味がない。先頭から検索しないと「2つ目」で
あることが確定しない。
> これに関連して「c」より前の「ab」を取得する関数はありませんか?
これはcより前の半角2文字分なのか、cより前の文字列全部なのかわからない。
ほんとは、こんな自分規格な論理は汎用の関数を組み合わせて自分でつくる
ものなんだよ。
論理を整理すると、Pos() や AnsiPos() のように最初に見つかった位置だけ
じゃなくて2番目以降も調べられる関数をつくれば、あとは簡単。
みなさんレスありがとうございます。
返信が遅くなりすみません。
質問内容があいまいでご迷惑をおかけしました。
> 文字列を後ろから検索して先頭から2つ目の「a」より後ろの「fff」を
これは、文字列を後ろから検索して最初に見つかった「a」より後ろの「fff」をという意味です。
Notesで言うところの、「strRightBack('abcdafff', 'a')」です。
> これはcより前の半角2文字分なのか、cより前の文字列全部なのかわからない。
cより前の文字列全部の意味です。
Notesで言うところの、「strLeft('abcdafff', 'c')」です。
> ほんとは、こんな自分規格な論理は汎用の関数を組み合わせて自分でつくる
> ものなんだよ。
Delphiの標準関数であればと思い質問しましたが、やっぱり自作するしかないんですね。
面白いのでやってみました。ポインタをつかって検索にはコピーを使わないようにして
なるべく処理速度を上げています。
// 文字列の途中からでも検索できる:戻り値はポインタ
function AnsiStrPosEx(Str,SubStr:PChar; InitPos:Cardinal):PChar;
begin
result := nil;
if InitPos > StrLen(Str) then exit;
result := AnsiStrPos(Str+InitPos,SubStr);
end;
// 文字列の途中からでも検索できる:戻り値は文字インデックス
function AnsiPosEx(const Substr,S:string; InitPos:Cardinal):integer;
var
ret:PChar;
begin
ret := AnsiStrPosEx(PChar(S),PChar(Substr),InitPos-1);
if ret = nil then result := 0 else result := ret-PChar(S)+1;
end;
// 一番最後の部分文字列の位置を返す
function GetLastSubstrPos(const Substr,S:string):integer;
var
l,p,pre:integer;
begin
result := 0;
l := Length(SubStr);
p := AnsiPosEx(Substr,S,1);
while (P<>0) do begin
result := p;
p := AnsiPosEx(Substr,S,p+l);
end;
end;
// 一番最後の部分文字列より右側の文字列を返す
function strRightBack(const str, substr: string): string;
var
p: integer;
begin
result := '';
p := GetLastSubstrPos(substr, str);
if p > 0 then
result := Copy(str,p+Length(substr),Length(str));
end;
// 最初の部分文字列より左側の文字列を返す
function strLeft(const str, substr: string): string;
var
p: integer;
begin
result := '';
p := AnsiPos(substr, str);
if p > 0 then
result := Copy(str, 1, p-1);
end;
みなさんありがとうございます。
色々と方法を教えていただき、とても参考になりました。
ただ、出来たら自作の関数を作ってゴリゴリ書くのではなく、標準関数でかつ1〜2行程度で実現したかったので、私も色々と考えて以下のようにして見ました。処理速度は遅いかもしれませんが・・・。
>文字列を後ろから検索して先頭から2つ目の「a」より後ろの「fff」を
strA := ReverseString('abcdafff');
strA := ReverseString(Copy(strA, 1, Pos('a', strA) - 1));
ツイート | ![]() |