文字列を判定基準にwhile文を使うには?

解決


tonma  2005-02-21 12:06:43  No: 13345

文字列を判定基準にしてwhile文を使うときはどうしたらいいのでしょう。
例えば、、

txt := 'abcdefg';
while txt <> ''  do
    begin
      delete(txt, 1, 1);
    end;
end;

と、このようにやったのですが、無限ループに陥ってしまいます。whileの条件のところを length(txt) <> 0  としても、無限ループに陥ってしまうのですが。。
どうすればうまく終了できるのか、アドバイスおねがいします。


Syake  2005-02-21 17:34:41  No: 13346

私は、For文を使います。
何かで、繰り返す回数が既に明確ならFor文を使うほうが
処理が早いと聞きましたので。

For i := 0 to Length('abcde') -1 do
begin
  ・・・・・;
end;
ループ中は判断を入れてBreakとかContinueで制御してます。

全然、答えになってません。
(^^ゞ


Syake  2005-02-21 17:59:14  No: 13347

ちなみに
procedure TForm1.Button1Click(Sender: TObject);
var
   strTest :String;
begin
   strTest := 'abv';
   while strTest <> ''  do
   begin
      Delete(strTest,1,1);
   end;
   ShowMessage('終了しました');
end;
で、無限ループにはならなかったのですが・・・

多分、処理内容が投稿内容と違う処理でそこに問題が
ありませんか?


ほー  2005-02-21 18:48:59  No: 13348

> 例えば、、
> .....
> どうすればうまく終了できるのか、アドバイスおねがいします。
その例では無限ループにはなりません。


にしの  2005-02-21 20:00:14  No: 13349

Deleteメソッドを自前で用意している場合は、その中を疑ってみるとよいかもしれません。


tonma  2005-02-21 21:03:47  No: 13350

みなさん、ありがとうございます。でも、なぜかうまくいきません。。
確かに投稿内容と違うプログラムですが。。。
>>Syake  さん
>何かで、繰り返す回数が既に明確ならFor文を使うほうが処理が早いと聞きましたので。
繰り返す回数は明確といえば明確です。文字列の中で、','(カンマ)の個数だけ繰り返すようにしたいのですが、例えば  'abc,123.0,xyz,,’の場合だと4回繰り返すことになります。文字列中の','カンマの数は決まっていません。文字列中にある単語が何個含まれているかを返す関数などは用意されていないのでしょうか?


りおりお  2005-02-21 23:21:44  No: 13351

標準の関数はないようです。簡単につくれます。

function EnumSubStr(const Str, SubStr:string):integer;
var
  p:PChar;
begin
  result := 0;
  p := AnsiStrPos(PChar(Str),PChar(SubStr));
  while p <> nil do
  begin
    Inc(result);
    p := AnsiStrPos(p+Length(SubStr),PChar(SubStr));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Label1.Caption := IntToStr(EnumSubStr('abc,123.0,xyz,,',','));
end;


にしの  2005-02-21 23:23:46  No: 13352

投稿内容と違うのであれば、間違っている箇所が別にあるものと思います。
デバッグして、何故終了しないか追ってみてはどうでしょう。
結構単純なことだったりしますよ。
# 私はよく、while i > n do としているのにinc(i)を忘れたりします^^;

以下、余談です。
> 何かで、繰り返す回数が既に明確ならFor文を使うほうが
> 処理が早いと聞きましたので。
> For i := 0 to Length('abcde') -1 do
> begin

場合によっては、遅くなります。
Length('abcde')は、5ですが、Length関数を使うことによって、終了条件で、Length関数を毎回呼ぶことになる場合があります。
# Lengthは組み込み関数ですので、Delphiが自動判別してくれると思いますが

「明確」にするのであれば、変数に入れて使った方がよろしいかと。


りおりお  2005-02-21 23:44:33  No: 13353

ちゃちゃですが

# 私はよく、while i > n do としているのにinc(i)を忘れたりします^^;

dec(i) じゃないですか? あるいは while i < n do か?


にしの  2005-02-22 00:02:49  No: 13354

そでした^^;
いや、こういうケアレスミスは結構多く・・・


Syake  2005-02-22 03:05:20  No: 13355

にしのさん  ありがとうございます。

>Length('abcde')は、5ですが、Length関数を使うことによって、終了条件.
>で、Length関数を毎回呼ぶことになる場合があります。
># Lengthは組み込み関数ですので、Delphiが自動判別してくれると思います>が「明確」にするのであれば、変数に入れて使った方がよろしいかと。
確かに以前は変数に代入してたのですが、時の流れで横着になったよう
です。

While Loop は、その都度条件に合致しているかどうかの判定を行うため
明確化しない場合だけ・・・と認識してました。
>場合によっては、遅くなります。
ちなみに、どの様な場合でしょうか?
よろしければ、教えてください。

と、他の方からの投稿を利用する私 m(__)m


にしの  2005-02-22 04:51:51  No: 13356

今試してみると・・・Length使った方が早かったです^^;
アセンブリコードを見ると、Length('abcde')は、5に置き換えられていました。
これだと、逆に変数に入れると遅くなりますね。

Length埋め込みの場合
・レジスターの値と固定値を比較
・フラグZが0ならループ先頭に戻る
・・・

変数に入れた場合
・レジスターに変数の値を格納
・レジスターに入れた値と(別の)レジスターの値を比較
・値が小さければループを抜ける
・フラグをクリア
・・・

変数を使えば使うほど遅くなりそうです。

自前でLength関数を使うとわかりやすいです。
何度もLength(...)を呼ぶことになるので、遅くなります。
条件に関数を参照するようなコーディングは良くないと(大昔に)教わったのですが、今はもう古い考え方なのでしょうかね。

コーディングに細工するよりも、アルゴリズムに力を入れるか、それでも遅いならasmで書くしかなさそうです。

親記事と趣旨がずれてしまい、すみませんでした。


tonma  2005-02-22 08:46:22  No: 13357

いろいろありがとうございました。ちゃんと動作確認しました。
少し質問が変わりますが、関数やメソッドを1つのユニットに書き続けて行くと、どこにどの関数があるのか分らなくなってしまうのですが、皆さんはどのようにしてプログラムをまとめているのでしょう?よかったら教えてください。


Mr.XRAY  URL  2005-02-22 09:09:43  No: 13358

>関数やメソッドを1つのユニットに書き続けて行くと、どこにどの関数があ
>るのか分らなくなってしまうのですが

コードエクスプローラを使用しています.
ダブルクリックすると,その箇所にカーソルが移動します.

後以下のページもコーディングの参考になるのでは.

http://kakinotane.s7.xrea.com/delphi/faq/f003.html
http://kakinotane.s7.xrea.com/delphi/faq/f004.html


Syake  2005-02-24 02:18:18  No: 13359

>少し質問が変わりますが、関数やメソッドを1つのユニットに書き続けて行
>くと、どこにどの関数があるのか分らなくなってしまうのですが、皆さんは
>どのようにしてプログラムをまとめているのでしょう?よかったら教えてく>ださい。

既に投稿から3日経過・・・
解決されたら、面倒でも別にSubjectをつけて投稿されたほうが、色々返答が
あるのでは?
結構皆さんSubjectを見て判断されるようですから。
(私もです(^_^)、分野外は興味が無い)

で、本題っと。
良い方法なのかどうか判りませんが
他のアプリでも利用可能な手続きや関数は目的別に別のユニットに記述して
ます。
この場合ユニットの保存先も共通で使えるユニット群をまとめたフォルダー
に保存して再利用しています。
このアプリのみで使用する場合も、フォームが複数あり多用するかもしれな
いと判断される場合も別ユニットにまとめて記述しています。
この場合は開発アプリと同じフォルダーに保存しますが・・・
また、手続きや関数へのデータ受け渡しにグローバル変数や他のユニットの
Publicな変数を使ったりせず、パラメータのみでやり取りを行うようにして
います。(意味が無くなってしまうので)

また私は、データベース関連を扱うアプリが多いのでformにはインターフェ
ースのみの処理だけ、dataモジュールにはデータベース操作関連のみを記述
しています。

別件ですが:
ある方から(本)、ビジネスロジックとインターフェース、データ
ベース操作関連はそれぞれ別にしたほうが良いと紹介されていました。
つまり、インターフェース(Formや各コントロールの制御)はFormの
ユニットに。
データ操作関連はデータモジュールに。
ビジネスロジックは更に別のデータモジュールに。
となっていました。
何で、ビジネスロジックがデータモジュールなの?と思いまして、
実践してません。
確かに、手軽でしかもグローバル関数・手続きにならないし、
どのユニットの関数・手続きなのかすぐにわかるので良いの
かな????

私もプログラム自体始めてから間が無いので、他の方がどの様にされている
のか、興味があります。


tonma  2005-02-24 02:29:56  No: 13360

いろいろ方法があるんですね〜。
用途別にユニットをわけるというのは、いい方法だと思います。
長いプログラムを書くと、ぐちゃぐちゃになるので、きれいにまとめることができれば、効率も上がりますよね。


Fusa  2005-02-24 04:14:53  No: 13361

> 他のアプリでも利用可能な手続きや関数は目的別に別のユニットに記述して
> ます。
> この場合ユニットの保存先も共通で使えるユニット群をまとめたフォルダー
> に保存して再利用しています。
> このアプリのみで使用する場合も、フォームが複数あり多用するかもしれな
> いと判断される場合も別ユニットにまとめて記述しています。
> この場合は開発アプリと同じフォルダーに保存しますが・・・

全く同じようにしています。

> ある方から(本)、ビジネスロジックとインターフェース、データ
> ベース操作関連はそれぞれ別にしたほうが良いと紹介されていました。

ケースケースによるかと思いますが
インターフェースとビジネスロジックを完全に分ける方法論は
私は理想論な机上の空論、ナンセンスで古いやりかただと思います。

特にWindowsでクライアントのGUIを作っていると無理ですし意味ないでしょう。

"した方がよい"かもしれないな程度のアドバイスで
理解していてよいのではないでしょうか。

例えばActionManagerみたいな
ツールボタンのカスタマイズ可能なツールバーの実装が
内部でインターフェース部とビジネスロジック部が
完全に分かれている必要性がないでしょうし。

ブラウザコンポーネントのIEやGeckoエンジン自体や
タブブラウザ、メーラーの実装に関して思い巡らしたとしても

理想論で物事が落ち着くほど単純ではないと感じます。

自分が自然で、シンプルだと思うように
プログラムを記述して
変だと思ったらリファクタリングを心がけてはいかがでしょう。


Syake  2005-02-24 18:31:57  No: 13362

おはようございます。

>全く同じようにしています。

よかった、同じようにやっておられる方がいて(^_^)
身近に開発関係者がいないので、NETと書籍を頼りに
無い頭をこねくり回して、現状これが一番効率的かな
などと、考えやっておりました。

>"した方がよい"かもしれないな程度のアドバイスで
>理解していてよいのではないでしょうか。

はい。
-----------------------

愚レスm(__)m


tonma  2005-02-25 05:53:11  No: 13363

みなさん、いろいろ知っているのですね。私も、どんどんプログラムを書いてdelphiのプログラミング技術を身に付けたいと思います。
本当にアドバイスありがとうございました。


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

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






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