文字列から空行を削除するには?

解決


かえで  2004-02-17 03:30:16  No: 7164

改行を含んだ文字列から空行を削除したいのですが、

var
  SL: TStringList;
  i: Integer;
begin
  SL := TStringList.Create;
  try
    SL.Text := Value; // Valueに文字列が入っている
    for i := SL.Count - 1 downto 0 do
      if SL[i] = '' then
        SL.Delete(i);
    Value := SL.Text;
  finally
    SL.Free;
  end;
end;

この方法だと文字列の最後に改行が無いときうまくいきません。
どうすれば空行だけを削除できるでしょうか?
それと、TStringListを使わない方法がありましたら教えてください。


るるとん@K  2004-02-17 03:40:46  No: 7165

私は普段for文は使わないので良く分かりませんが
SL.Count-1の部分がSL.Countだけで良いような気がします
var
SL:・TStringList;
i:・Integer;
begin
SL・:=・TStringList.Create;
try
SL.Text・:=・Value;
i:=0;
while・i・<・SL.Count・do
begin
if・SL[i]・=・''・then
SL.Delete(i);
end;
Value・:=・SL.Text;
finally
SL.Free;
end;
end;
ですかな


るるとん@K  2004-02-17 03:41:54  No: 7166

何か文字化けしてますね


jok  2004-02-17 03:46:25  No: 7167

> この方法だと文字列の最後に改行が無いときうまくいきません。

そうなの? 試したところではうまくいくようですけど。


るるとん@K  2004-02-17 03:48:46  No: 7168

>・この方法だと文字列の最後に改行が無いときうまくいきません。
たぶん最後の行まで実行されて無いだけだとおもいます


るるとん@K  2004-02-17 03:56:40  No: 7169

var
s:string;
begin
while ansipos(#13#10#13#10,s) do
begin
StringReplace(s,#13#10#13#10,#13#10,[rfReplaceAll]);
end;
if s[length(s)-1]+s[length(s)] = #13#10 then
begin
s:=leftstr(s,length(s)-2);
end;
end;


るるとん@K  2004-02-17 03:59:00  No: 7170

ミッス!!
危険、無限ループ
StringReplace(s,#13#10#13#10,#13#10,[rfReplaceAll]);
ではなく
s:=StringReplace(s,#13#10#13#10,#13#10,[rfReplaceAll]);


にしの  2004-02-17 04:06:33  No: 7171

それだと、#13#10#13#10#13#10が、#13#10#13#10になり、空行が残ります。
# 無限ループにはなりませんよ。
# 処理後の場所は処理されません。

また、先頭の空行は、#13#10のみですので、別途処理が必要です。

最後の行が改行の時問題であれば、最後にダミーの行を追加してからTStringListに入れれば対処できますね。


にしの  2004-02-17 04:15:53  No: 7172

るるとん@Kさん、失礼しました。
ちゃんと処理されていましたね。
よく見ず発言してました。


にしの  2004-02-17 04:30:52  No: 7173

こんなのを作っていました。文字列が大きいと遅いと思います。細かくはチェックしていません。

function DelEmptyLine(const str: String): String;
var
  s: String;
  p: PCHAR;
  prev: Char;
begin
  s := AdjustLineBreaks(str, tlbsLF);//#$Aに変更

  p := PCHAR(s);
  Result := '';
  prev := ' ';
  while p^=#10 do Inc(p);
  while p^ <> #0 do
  begin
    if (prev=#10) and (p^=#10) then
    begin
      Inc(p);
      Continue;
    end;
    Result := Result + p^;
    prev := p^;
    Inc(p);
  end;
  Result := AdjustLineBreaks(Result);
end;

作って気がついたのですが、文字列最後の改行を、最後に空行があると見なすのでしょうか。
# 上に書いたプロシージャでは、最後の改行は空行とは見なしていません。


るるとん@K  2004-02-17 04:51:05  No: 7174

>また、先頭の空行は、#13#10のみですので、別途処理が必要です。
これでOK
var
s:string;
begin
while ansipos(#13#10#13#10,s)>0 do
begin
s:=StringReplace(s,#13#10#13#10,#13#10,[rfReplaceAll]);
end;
if s[length(s)-1]+s[length(s)] = #13#10 then
begin
s:=leftstr(s,length(s)-2);
end;
if ansipos(#13#10,s)=1 then
begin
s:=stringreplace(s,#13#10,'',[])
end;
end;


かえで  2004-02-17 07:01:07  No: 7175

> 私は普段for文は使わないので良く分かりませんが
> SL.Count-1の部分がSL.Countだけで良いような気がします
for文にしたのは一番高速だと教わったからです。
繰り返しの回数がわかっているときはfor文を使う方が良いらしいです。

> 文字列最後の改行を、最後に空行があると見なすのでしょうか。
自信は無いのですが、空行というのは「改行コードの前に文字が無い行」
ではないかと思います。

るるとん@Kさん、コードを書いてくださってありがとうございます。
ですが、同じ方法を以前試したことがあり、文字列が大きいと遅くて
実用になりませんでした。

にしのさんの方法を使わせていただきます。
どうもありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加