Delphi初心者のための ..
[2ch|▼Menu]
39:デフォルトの名無しさん
05/12/01 10:42:02
お題
「このスレの1−38までを Memo1 にコピーして、「Delphi」という文字列が何度
現れたか数えなさい。

40:デフォルトの名無しさん
05/12/01 14:08:14
>>34の1
begin
    str_src:=Edit1.Text;
    StartTime:=Now;

    len:=Length(str_src);
    eq_pos:=pos('=', str_src);

    if len=0 then
    begin
        ShowMessage('なにか文字を入力してください');
        exit;
    end;
    if eq_pos=0 then
    begin
        ShowMessage('=が見つかりませんでした');
        Exit;
    end;

    str_dest:=copy(str_src, 1, eq_pos-1);
    str_dest:=str_dest+'は';
    str_dest:=str_dest+copy(str_src, eq_pos+1, High(Integer));
    str_dest:=str_dest+'です';

    EndTime:=Now;
    DecodeTime(EndTime-StartTime, Hour, Min, Sec, MSec);
    Memo1.Lines.BeginUpdate;
    Memo1.Lines.Add(str_dest);
    Memo1.Lines.Add(Format('%u時間 %u分 %u秒 %u', [Hour,Min,Sec,MSec]));
    Memo1.Lines.EndUpdate;
end;

41:デフォルトの名無しさん
05/12/01 14:26:49
>>34の2

回答1.DeleteとInsertを使う
Delete(str_src, eq_pos, 1);
Insert('は', str_src, eq_pos);
str_dest:=Concat(str_src, 'です');

回答2.出来合いの関数を使う
Borland - Delphi Q&A 文字列を一括置換するには
URLリンク(www.borland.co.jp)

回答3.正規表現を使う
TRegExpr - PukiWiki
URLリンク(onigiri.s3.xrea.com:8080)

※2と3は標準関数ではないですが見つけたので添えておきます

42:デフォルトの名無しさん
05/12/01 17:43:03
D5 以降だと StringReplace があるけど

43:デフォルトの名無しさん
05/12/01 18:24:52
>>42
天才あらわる

44:デフォルトの名無しさん
05/12/01 22:23:51
>>34の3
    PSrc:=AllocMem(len+1);
    PSrcCopy:=PSrc;
    ZeroMemory(PSrc, len+1);

    for i:=1 to len do
    begin
        PSrc[i-1]:=str_src[i];
    end;

    while PSrc^ <> #0 do
    begin
        if PSrc^ = '=' then
        begin
            str_dest:=str_dest+'は';
        end
        else
        begin
                str_dest:=str_dest+PSrc^;
        end;
        Inc(PSrc);
    end;
    str_dest:=str_dest+'です';
    FreeMem(PSrcCopy, len+1);

45:デフォルトの名無しさん
05/12/01 22:41:39
メモリ割り当ててコピーは無駄。ポインタ使う意義が半減。

PSrc := PChar(str_src);

でいいんでない?

46:デフォルトの名無しさん
05/12/01 23:10:52
>>45
了解です。修正しました。
PCharとStringの変換が意外と楽で感激
    PSrc:=PChar(str_src);
    while PSrc^ <> #0 do
    begin
        if PSrc^ = '=' then
        begin
            str_dest:=str_dest+'は';
        end
        else
        begin
                str_dest:=str_dest+PSrc^;
        end;
        Inc(PSrc);
    end;
    str_dest:=str_dest+'です';

47:デフォルトの名無しさん
05/12/01 23:13:41
>>39
    p:=0;
    cnt:=0;
    str:=Memo1.Text;
    len:=length(sword);

    repeat
        ap:=Pos(sword, copy(str, p, High(Integer)));
        if ap>0 then
        begin
            p:=p+ap;
            Inc(cnt);
            Inc(p, len);
        end;
    until ap=0;
    ShowMessage(IntToStr(cnt));

48:デフォルトの名無しさん
05/12/01 23:32:47
>>39をPCharを使って解きました
文字列の添え字に間違って0を使ってしまってハマってしまいました
PCharのときは0から、それ以外(constやstring)は1からでいいんですよね?
    p:=1;
    cnt:=0;
    str:=Memo1.Text;
    PStr:=PChar(str);
    len:=length(sword);

    while PStr^ <> #0 do
    begin
        if PStr^ = sword[p] then
        begin
            Inc(p);
            if (p=len) then
            begin
                Inc(cnt);
                p:=1;
            end;
        end
        else
        begin
            p:=1;
        end;
        Inc(PStr);
    end;
    ShowMessage(IntToStr(cnt));

49:デフォルトの名無しさん
05/12/01 23:32:52
>>47
パチパチパチ、すばらしい
◎-3

減点は、この場合は問題ないだろうけど、日本語処理では Pos じゃなく AnsiPos
を使うこと。

いろいろ改良点があるけど

ap:=Pos(sword, copy(str, p, High(Integer)));

これがこの処理のキモ。でも、文字列コピーは最も効率悪い方法。
1MByte のテキストで検索文字列が1000回現れたら、1000回コピーする
ことになる。PChar をつかってなるべくコピーをしないで処理する方法を
考えるのが次のお題。



50:デフォルトの名無しさん
05/12/01 23:34:57
> PCharのときは0から、それ以外(constやstring)は1からでいいんですよね?

そう。string 型は、パルカルのときの実装を引きずっていますので例外的に1から、と覚える


51:デフォルトの名無しさん
05/12/02 00:00:42
×パルカル
○パスカル

52:デフォルトの名無しさん
05/12/02 00:06:33
49 のヒント AnsiStrPos

53:デフォルトの名無しさん
05/12/02 09:07:30
TEditに英文字のみ入るようにする方法教えて下さい。

54:53
05/12/02 09:19:30
イベントハンドラでキー入力をカット出来ないかなぁ?

55:デフォルトの名無しさん
05/12/02 09:35:55
>39にも誰か答えてやれよ

56:デフォルトの名無しさん
05/12/02 09:38:03
×39
○31

57:デフォルトの名無しさん
05/12/02 09:58:38
> Delphi初心者が問題をコツコツと解きながらレベルアップするためのスレです。

単発質問はくだすれへ

58:デフォルトの名無しさん
05/12/02 16:42:41
>>48

Inc(p);
if (p=len) then

これじゃ、比較が一バイト少ないよ。それから、2バイト文字を考慮してないので
ダメです。「Delphi」ならまず問題ないけど「D」だったら、2バイト文字の2バイト目も
数えてしまう可能性がある。


59:デフォルトの名無しさん
05/12/05 21:38:25
>>49
日本語処理にも気をつけました
よろしくお願いします。

const
    sword='Delphi';
var
    str:    AnsiString;
    cnt:    Integer;
    PStr: PChar;
begin
    cnt:=0;
    str:=Memo1.Text;
    PStr:=PChar(str);

    repeat
        PStr:=AnsiStrPos(PStr, sword);
        if (PStr<>nil) then
        begin
            if (StrByteType(PStr, 0)=mbSingleByte) then
            begin
                Inc(cnt);
            end;
            Inc(PStr);
        end;
    until PStr=nil;

    ShowMessage(IntToStr(cnt));

end;


60:デフォルトの名無しさん
05/12/06 00:37:50
>>59
AnsiStrPosを使ってる時点で2バイト文字として意味のある位置で
結果が返ってる筈なんでStrByteTypeいらない。

というか前からスキャン方式でStrByteTypeは使っちゃだめ。
途中の位置をいきなり指定してそれがどこにあたるか調べるのは
前後の文字を辿るしかなく、
逆にそういった機能を持つ関数を使うことは
その次点に到達するまで前からスキャンしてきたこと自体を
無駄にしてる。
前から辿るならAnsi〜系を使わずに自力でマルチバイト処理をするとしても
LeadBytesで充分。

61:デフォルトの名無しさん
05/12/06 00:46:30
>>59

惜しい。あと一歩。78点くらい。
たぶん結果は正しい。冗長なのが減点の原因。

AnsiStrPos は二バイト文字をサポートしていますので、検索の先頭を間違わなければStrByteType による確認は不要です。

それから、見つかったら、PStr は検索文字列の長さ分だけ Inc() してから再度検索します。

    repeat
        PStr:=AnsiStrPos(PStr, sword);
        if (PStr<>nil) then
        begin
          Inc(cnt);
          Inc(PStr, Length(sword));
        end;
    until PStr=nil;

このようにすると検索文字列が 「Delphi」であっても「デルファイ」であっても問題なく検索できます。
>>59 の回答は検索文字列の最初が一バイト文字であることを仮定しているので正しくないです。

しかし、かなりな進歩で驚いています。

次のお題は、何回現れるかの他に、その位置も返すような関数をつくってください。具体的には、RichEdit に
同様にテキストを読み込んで、ボタンを押すと Delphi の部分が赤い文字列になるようにします。

赤文字にする方法、位置情報を返すための配列の定義の仕方など、分からないことがあったら個別に質問してください。

62:デフォルトの名無しさん
05/12/07 01:04:33
>>61
begin
    cnt:=0;
    spos:=0;

    str:=RichEdit1.Text;
    PStr:=PChar(str);
    len:=Length(sword);

    repeat
        p:=AnsiPos(sword, PStr+spos);

        if (p>0) then
        begin
            Inc(cnt);
            Inc(spos, p);

            with RichEdit1 do
            begin
                SelStart:=spos-1;
                SelLength:=len;
                SelAttributes.Color:=clRed;
            end;
            Inc(spos, len);

        end;

    until p=0;
    ShowMessage(IntToStr(cnt));
end;
//ここまで
よろしくお願いします。

63:デフォルトの名無しさん
05/12/07 02:35:14
>>62
AnsiPosに暗黙のPChar→String変換で引数渡してるよね…。
これは暗黙に実行されるわりにコストがメチャ高いので、
ループの中では避けたほうがいい。
上と同じでAnsiStrPosじゃダメだったの?

64:デフォルトの名無しさん
05/12/07 03:05:54
>>62

すばらしい!

つぎに、汎用的に使えるように関数にしてみてください。

type
TPosArray = array of integer;

function SearchAndPos(const SubStr, Str: string; PosArray: TPosArray): integer;

で戻り値が出現回数であるような。>>63 さんのおっしゃるとおり、AnsiStrPos をつかって
実装してみてください。

65:デフォルトの名無しさん
05/12/07 03:10:21
すみません、関数は

function SearchAndPos(const SubStr, Str: string; var PosArray: TPosArray): integer;

の形です。var をわすれました。

66:デフォルトの名無しさん
05/12/09 04:07:45
>>64-65
AnsiStrPosを使うように変更しました
よろしくお願いします

function SearchAndPos(const SubStr, Str: string; var PosArray: TPosArray): integer;
var
    PStr:     PChar;
    PBgmStr:    PChar;
    PSubStr:    PChar;
    Cnt:    Integer;
    Len:    Integer;
begin
    Cnt:=0;
    Len:=Length(SubStr);

    PBgmStr:=PChar(Str);
    PStr:=PBgmStr;
    PSubStr:=PChar(SubStr);

    repeat
        PStr:=AnsiStrPos(PStr, PSubStr);
        if (PStr<>nil) then
        begin
            Inc(Cnt);
            SetLength(PosArray, Cnt);
            PosArray[Cnt-1]:=PStr-PBgmStr;
            Inc(PStr, Len);
        end;
    until PStr=nil;

    result:=Cnt;
end;

67:デフォルトの名無しさん
05/12/09 09:57:48
>>66

すばらしい!
実際のの動作はすみませんが、時間が出来たらあとで検証してみます。
見た限りでは問題無さそうです。

>>47 から比べると格段の進歩です。検索には一度も文字列コピーをしてないのですよね。

今回の教訓は、ひとかたまりの論理が完結したら、関数や手続き、クラス内のメソッド
などで表現すべき、ということです。コードの断片より、関数などで完結した論理を
表現しておくと、たとえ他の言語や環境になったとしても論理そのものは生きるので
自分の財産にすることが出来ます。

68:デフォルトの名無しさん
05/12/09 09:58:14
次の課題。

1)Delphi には Pos や AnsiPos にように文字列の先頭から、最初の位置までを
検索する関数がありますが、途中から検索する関数がありません。それを

function AnsiPosEx(const Substr, S: string; initPos: integer): Integer;

の形で AnsiStrPos をつかって、つくってください。そして、それをつかって >>66
書き直してみてください。

2)>>66 では見つかるたびに SetLength() を使って配列を一つずつ増やしています。
これは非効率的なので、たとえば10個づつ増やすようにしてみてください。

69:デフォルトの名無しさん
05/12/09 20:18:26
>>68
function AnsiPosEx(const SubStr, S: string; initPos: integer): Integer;
var
    PSubStr:    PChar;
    PS: PChar;
    PBgn: PChar;
    PPos: PChar;
begin
    PSubStr:=PChar(SubStr);
    PS:=PChar(S);
    PBgn:=PS+initPos;

    PPos:=AnsiStrPos(PBgn, PSubStr);
    result:=PPos-PS+1;
    if result<0 then
    begin
        result:=0;
    end;
end;


70:デフォルトの名無しさん
05/12/09 20:19:15
function SearchAndPos(const SubStr, Str: string; var PosArray: TPosArray): integer;
var
    PStr:     PChar;
    Cnt:    Integer;
    NowPos: Integer;
    Len:    Integer;
begin
    Cnt:=0;
    NowPos:=0;
    Len:=Length(SubStr);
    PStr:=PChar(Str);

    repeat
        NowPos:=AnsiPosEx(SubStr, PStr, NowPos);
        if NowPos<>0 then
        begin
            if Length(PosArray)=Cnt then
            begin
                SetLength(PosArray, Cnt+10);
            end;
            PosArray[Cnt]:=NowPos-1;
            Inc(Cnt);
            Inc(NowPos, Len);
        end;
    until NowPos=0;
    SetLength(PosArray, Cnt);
    result:=Cnt;
end;
//ここまで

よろしくお願いします

71:デフォルトの名無しさん
05/12/09 22:22:06
>>69

完璧!! -2 点 =98点

減点は、AnsiPosEx の第二引数に PChar を使ったこと。const の string 型は
呼び出しても、関数内で変更できないのでコピーされることはないです。ですから
string 型のまま使ってください。AnsiPosEx をつくったことにより、SearchAndPos
から、ポインタをあらわにつかうコードが完全になくすることができたことに注目してください。

次の課題は少し難易度が上がります。

このスレの1−38までのテキストのうち、半角の数字がでてきた数を数える関数をつくってください。

いままで、テキスト内の走査は、AnsiPos や AnsiStrPos をつかったのであらわに
コードを書かなかった。この課題では、一バイト文字、二バイト文字を判別しながら
数字かどうかを判定する必要があります。自分のコードでテキストを走査してください。
出来れば、前回のように、文字列の途中から検索して、最初の数字を見つける関数を
つくり、それを使って出現数を数えてください。

72:デフォルトの名無しさん
05/12/09 22:25:23
ヒント >>60 さんのコメントが参考になります。

73:デフォルトの名無しさん
05/12/10 00:15:52
数字は全角文字の二バイト目に出てこないよ。


74:デフォルトの名無しさん
05/12/10 02:07:03
>>73
ありがとう。
ほんとうですね。いま shift-jis のコード表を見ましたら、二バイト文字の二バイト目は
$40 からなんですね。一方 0-9 は $30-$39 ですから、重複しませんね。

うーむ、それでは課題が破綻するので変えることにします。

このスレの1−38までのテキストのうち、半角のアルファベット( a-z と A-Z )文字がでてきた数を数える関数をつくってください。

とします。すみませんでした。

75:デフォルトの名無しさん
05/12/11 22:32:44
嘘か真かわからんが、QualityCentralにQC#21940で、「Delphi2006 ハング」との事です。時々、ハングアップするとの事です。んー。今まで、Qualityを無視しつづけたツケだな。 -- 2005-12-07 05:54:52 (水) New

2005なんか 最初 吹っ飛んで消滅していたじゃん。 消滅からハングに 大差ないしおどろくことではないかと  先行バグ取り隊の情報引き続きよろしく  -- 2005-12-07 09:14:09 (水) New

>「消滅からハングに 大差ないしおどろくことではない」 どっちにしろ、真面目につかうものではなさそうですね。

「どっちにしろ、真面目につかうものではなさそうですね」 しらずに2005のときせっかく数時間かけて書いたコードが消滅して悲しい思いしたよ -- 2005-12-07 15:22:52 (水) New

76:デフォルトの名無しさん
05/12/15 07:29:16
>>74
function CountAlpha(var str:    AnsiString):    Integer;
var
    i:    Integer;
    cnt:    Integer;
begin
    cnt:=0;
    i:=0;

    while (i <= Length(str)) do
    begin
        if ( (str[i] in LeadBytes)) then
        begin
            Inc(i,2);
        end
        else
        begin
            if (str[i] in ['a'..'z']) or (str[i] in ['A'..'Z']) then
            begin
                Inc(cnt);
            end;
            Inc(i);
        end;

    end;
    result:=cnt;
end;
//ここまで
よろしくお願いします

77:デフォルトの名無しさん
05/12/15 10:26:25
>>76
すばらしい! 94点

減点は
CountAlpha(var str: AnsiString): → CountAlpha(const str: AnsiString):

const にして、関数内で変更しない(コピーされない)ことを保証し、
IntToStr(CountAlpha(Memo1.Text)) などと、変数を確保しなくても使えるように
することは重要です。var だと str := Memo1.Text; IntToStr(CountAlpha(str))
などとしなければ使えませんね。

減点ではないけど

if (str[i] in ['a'..'z']) or (str[i] in ['A'..'Z']) then

の部分は

if (str[i] in ['A'..'Z','a'..'z']) then

とすることもできます。

文字列のインデックスは1から始まります。ですから

i:=0; ではなく、 i:=1;

で初期化してください。次の課題は少し事前に検証してから出します。




78:デフォルトの名無しさん
05/12/15 10:42:34
>>76

つぎの課題は、もうちょっと難易度が上がります。
前回同様、アルファベットの文字を見つけるのは同じですが、塊として数えてください。

例えば

This is a pen.

の場合は4を返すような関数をつくってください。アルファベット以外の文字(空白も含む)で
区切られたアルファベットだけで出来ている語句の数を数えます。

「...ことを保証し、IntToStr(CountAlpha(Memo1.Text)) などと、変数を確保しなくても使えるように」

の場合は、「IntToStr」「CountAlpha」「Memo」「Text」の4つです。

79:デフォルトの名無しさん
05/12/15 11:52:06
ヒント
新幹線で東京から名古屋まで行くときのトンネルの数を数えるのと同等です。
トンネルの入り口を数えるといいですね。でも入り口を認識するためには
出口を認識する必要があります。出口を認識するためには、「いまトンネルの
なかにいる」という<状態>を変数に保存しておかなければなりません。また、
トンネルの中にも駅があることを考慮しなければなりません。ですから、名古屋
は違いますが終点がトンネルの中の場合もありえます。

80:デフォルトの名無しさん
05/12/15 12:22:11
すみません(こればっかり)、ヒントの最後の2行は、見つかった語句の長さを
記録するときのものです。今回は無視してください。入り口の数だけで十分です。

81:デフォルトの名無しさん
05/12/16 13:56:59
●問題2
エディットボックス(Edit1)に入力した数字までの合計値を、ボタン(Button1)を押したら、表示(Label1に表示)させよ。
なお変数は、エディットボックスの入力値(a)、合計値(Sum)、ループのカウンタ(i)とする。

procedure TForm1.Button1Click(Sender: TObject);
var
i,Sum:□□□□□□□;
a:integer;
begin
a:=StrToInt(Edit1.text);
Sum:=0;

for i:= □ to □ do
begin
Sum:= □□□+□
end;

Label1.Caption:=IntToStr(Sum);
end;

教えて!↑

82:デフォルトの名無しさん
05/12/16 15:44:01
Integer
0
a
Sum
i

83:デフォルトの名無しさん
05/12/18 04:51:49
すんません、教えてください。

TPopupMenuに動的にメニューを追加する方法なんですが、サブメニューも追加したくて・・・
例えば

A
 -SubA
 -SubB
B
 -SubA
 -SubB
 -SubC

こんな感じでサブメニュー含めて動的に追加するにはどうしたらいいですかね?

84:デフォルトの名無しさん
05/12/18 09:33:06
>>83
>>57

85:デフォルトの名無しさん
05/12/20 06:50:34
>>78-80
function CountAlphaWord(const str:    AnsiString):    Integer;
var
    i:    Integer;
    cnt:    Integer;
    isAlphaNow:    Boolean;
    isAlphaPrev:    Boolean;
begin
    isAlphaPrev:=False;

    cnt:=0;
    i:=1;

    while (i <= Length(str)) do
    begin
        isAlphaNow:=False;

        if ( (str[i] in LeadBytes)) then
        begin
            Inc(i,2);
        end
        else
        begin
            if (str[i] in ['a'..'z', 'A'..'Z']) then
            begin
                isAlphaNow:=True;
            end;
            Inc(i);
        end;


86:デフォルトの名無しさん
05/12/20 06:54:35
        if (not isAlphaPrev) and isAlphaNow then
        begin
            Inc(cnt);
        end;
        isAlphaPrev:=isAlphaNow;

    end;

    result:=cnt;
end;

//ここまで
よろしくお願いします

87:デフォルトの名無しさん
05/12/20 14:36:57
>>85-86

100点。

キモは、

if (not isAlphaPrev) and isAlphaNow then

ですね。これでトンネルの入り口を認識しているのだね。Boolean の変数を二つ
つかって、論理が分かりやすくなっています。わたしの実装だと、IsTunnel という
Boolean の変数をひとつだけ使っているので、今回の実装より簡単ですが、コードは
読みにくいです。他人の実装をみると、自分との違いが分かって勉強になります。

さて、次の課題は、多分予想できていると思いますが、トンネルの出口も認識して
数だけでなく、位置と長さも返すような関数を作ってください。

type
TPosLength = record
Position: integer;
Length : integer;
end;

TPosLenArr = array of TPosLength;

function SearchAlphaWord(const str: string; var pl: TPosLenArr): integer;

>>79 の全文をヒントとしてください。

88:デフォルトの名無しさん
05/12/23 05:34:45
>>87
function SearchAlphaWord(const str: string; var pl: TPosLenArr): integer;
var
    i:    Integer;
    cnt:    Integer;
    isAlphaPrev:    Boolean;
    isAlphaNow :    Boolean;
    iPrev:    Integer;
begin
    isAlphaPrev:=False;

    cnt:=0;
    i:=1;

    while (i <= Length(str)) do
    begin
        isAlphaNow:=False;
        iPrev:=i;

        if ( (str[i] in LeadBytes)) then
        begin
            Inc(i,2);
        end
        else
        begin
            if (str[i] in ['a'..'z', 'A'..'Z']) then
            begin
                isAlphaNow:=True;
            end;
            Inc(i);
        end;

89:デフォルトの名無しさん
05/12/23 05:35:25
        if (not isAlphaPrev) and isAlphaNow then
        begin
            Inc(cnt);

            if cnt>Length(pl) then
            begin
                SetLength(pl, cnt+10);
            end;
            pl[cnt-1].Position:=iPrev;
        end
        else    if isAlphaPrev and (not isAlphaNow) then
        begin
            pl[cnt-1].Length:=iPrev-pl[cnt-1].Position;
        end;

        isAlphaPrev:=isAlphaNow;
    end;

    SetLength(pl, cnt);
    result:=cnt;
end;
//ここまで
よろしくお願いします

90:デフォルトの名無しさん
05/12/23 11:51:19
>>88-89

90点。

ヒントの

> トンネルの中にも駅があることを考慮しなければなりません。ですから、名古屋
> は違いますが終点がトンネルの中の場合もありえます。

を忘れています。アルファベットでテキストが終わる場合を考慮してください。

...
isAlphaPrev:=isAlphaNow;
end;

if isAlphaNow then pl[cnt-1].Length:=iPrev+1-pl[cnt-1].Position; // これを追加

SetLength(pl, cnt);
result:=cnt;
end;

あと、一つも見つからない場合もありますので、while の前に

isAlphaNow := false;
iPrev := 1;

で初期化しておくとコンパイラの警告が出ませんね。

文字列操作は列挙や置換、抽出、パースなどいろいろありますが、少々当方も飽きてきた
ので次はリストクラスから出題します。すこし時間をください。

91:デフォルトの名無しさん
05/12/23 12:10:18
>>88-89

リストクラスはもっとも簡単そうな文字列のリスト TStringList から始めます。
最初はソートの練習です。

procedure TForm1.Button1Click(Sender: TObject);
var
  sl: TStringList;
  i: integer;
begin
  Randomize;
  sl := TStringList.Create;
  try
    for i := 1 to 20 do sl.Add(IntToStr(Random(1000)));
    Memo1.Lines.Assign(sl);
  finally
    sl.Free;
  end;
end;

にすると、0-999 のランダムな数値に対応する文字列が sl に20個保持され、その内容が Memo1 に
表示されます。コードを継ぎ足して、数値の小さい方から(昇順)並べ直して見てください。

TStringList.CustomSort を使います。

92:ささ ◆6KVcpBNXy.
06/01/26 15:45:51
みなさん。こんにちゎ。経済学部のささと申します。
パスカル(Delphi)の授業での課題がわかりません。。教えてください!
3科目、10人分のデータを入力して各人の合計点と科目毎の平均点を作れ!
という課題が出ました。。。

先生に下記を改変するとやりやすいといわれました。repeatとwhileとforまでしか習っていません。
Score :array[0..1000] of integer; 
begin
writeln('入力得点の平均と偏差値を計算します'); writeln('入力後、負の数を入力すると…終了します。');
kazu :=0;
repeat
write('点数は?'); readln(data);
if data >= 0 then
begin 
kazu := kazu + 1;
score[kazu] := data
end
until data < 0;
goukei := 0;  for i := 1 to kazu do goukei := goukei + score[i];  heikin :=goukei / kazu;
goukei :=0;  for i := 1 to kazu do  goukei := goukei + Sqr(score[i]); hensa := sqrt(goukei /kazu - sqr(heikin));
writeln('点数  偏差値');
for i := 1 to kazu do  writeln(score[i]:4, 50 +10 * (score[i]-heikin)/ hensa:10:1);
writeln(' 平 均 =',heikin:5:1);  writeln('標準偏差=',hensa:5:1);
readln;
end.

93:棄民党党首 ◆8slekwWKD6
06/01/26 17:00:39
やひゃひゃひゃ。おまいら。

AssignFile(f, s); Reset(f);

で s にアクセント記号と漢字交じりのファイル名をWideStringでぶちこんでみたら
開かんぞ。

TntのUnicode Componentsをいぢってみたが、AssignFileのUnicode版がみつからん。

でしかたないから
WideRenameFileで名前を'safe.bin'とかに変更しちゃって。
フツ〜にAssignFileで開いて処理してからまた
WideRenameFileで名前をUnicodeの名前へもどしますた。

わたしってなんて天才♪

94:デフォルトの名無しさん
06/02/10 02:28:56
Delphiってなくなるの?
Turbo Pascal時代からずっと使って来ただけに、
手に馴染んだ開発環境がなくなると困る。

95:デフォルトの名無しさん
06/02/10 04:04:10
>>94
ボーランドが手放すだけでDelphiがなくなるわけじゃないから安心しる。

96:デフォルトの名無しさん
06/02/10 08:15:16
買い手が無ければなくなるんじゃね?

97:デフォルトの名無しさん
06/02/10 14:45:48
で、MDIでWM_COPYDATAを子フォームで受け取るにはどーすんの?


98:デフォルトの名無しさん
06/02/10 16:58:38
受け取るのは簡単だろ

99:デフォルトの名無しさん
06/02/10 17:29:53
>>98
え?マジすか?kwsk!
とあるスレッドからMDI子フォームにSendMessageしたいんです。
そのスレッドでは、MDI子フォームのウィンドウハンドルを取得する事は
出来るのですが、SendMessageしてもMDI子フォームにメッセージが来ないです。
もう泣きそうです。
もちろん、MDI子フォームではメッセージを受け取れるようにしているのですけども・・・。


100:デフォルトの名無しさん
06/02/10 17:49:34
どうやってハンドルをみつけたの?

101:デフォルトの名無しさん
06/02/10 18:13:45
改行が多いと怒られたので、かなりハショってます。
メッセージを送る側では
procedure Thread.SendMsg(sClassName: String; nKind: Cardinal; pInfo: Pointer; nInfoSize: Integer);
var
begin
Wnd := FindWindow(PChar(sClassName), nil);
if (Wnd <> 0) then begin
:
SendMessage(Wnd, WM_COPYDATA, WPARAM(Wnd), LPARAM(@Cd));
end;

とし、SendMsg('TForm', ....); と、使っています。で、
受け取る側(MDI子フォーム)では
procedure WMCopyData( var sMsg: TWMCopyData ); message WM_COPYDATA;
を、privateに宣言して
procedure TForm.WMCopyData(var sMsg: TWMCopyData);
:
begin
pMessage := nil;
if (sMsg.CopyDataStruct.dwData = ID_TEST) then begin
:
:
:
end;
としています。


102:デフォルトの名無しさん
06/02/10 19:22:04
それでほんとに、目的 MDI 子ウィンドウが見つかってる?
一度 Spy++ か WinInsight で確かめたら?

103:デフォルトの名無しさん
06/02/10 19:45:00
取れてるようですが・・・ダメなんでしょうか?
通常どうやるのかわからないもので・・・。
とりあえず実行させて、FindWindowの戻り値を見たら0x604A6でした。
Spy++の検索ウィンドウで0x604A6を検索したら、目的のウィンドウが
検索されました。一応ウィンドウハンドルは取れているようでした。
うーん・・・困りました・・・。


104:デフォルトの名無しさん
06/02/14 02:57:20
部分範囲型って、実際バリバリ使ってる人います?
便利なようでいまいち、使いどころが…。
動作中チェックありにして、速度とか問題ないですか?

105:デフォルトの名無しさん
06/02/14 15:13:33
そもそも Delphi を実際バリバリ使ってる人なんか、そんなにいないからね

106:デフォルトの名無しさん
06/02/14 21:37:45
バリバリじゃない。さり気なく使うんだ。

107:デフォルトの名無しさん
06/02/15 10:29:36
さりげなく、こっそりと、ひそかに・・・な。

108:デフォルトの名無しさん
06/02/15 11:11:39
いや、ペタペタと使う。

109:デフォルトの名無しさん
06/02/21 23:53:44
>>101
ヘルプに有るように、FindWindowは子ウィンドウは探してくれないよ。
同じクラス名を持つ別のウィンドウのハンドルを返していると思われ。

110:デフォルトの名無しさん
06/02/22 23:07:35
質問です。色付きのボタンを作ることはできますか?
パネルを色つきにしてOnClickという事もできますが
それだとクリックされたときにボタンのように
凹んだりしないのでわかりづらいし・・・
なにかいい方法はありますでしょうか?
どなたか、よろしくお願いします。


111:デフォルトの名無しさん
06/02/22 23:14:06
>>110
まさか本当に凹んでるとか思ってないよな?

112:デフォルトの名無しさん
06/02/23 00:27:17
Paintメソッドをoverrideして自分で描画するとか。


113:Delフサギコ ◆A6VzDeLphI
06/02/23 00:51:33

           (´⌒;;
;⌒`)   ∧,,∧   そういうのだいたい
 ;; `)./ミ,,゚Д゚彡  誰か作ってるよ。
   //\ ̄ ̄旦~   (´(´⌒)
  // ※.\___\
 \\※ ※ ※ ※ ※ヽ
   \`ー───ヽ
    ────

URLリンク(homepage1.nifty.com)

URLリンク(homepage2.nifty.com)

114:デフォルトの名無しさん
06/03/02 22:41:07
152 :  :2006/03/01(水) 06:16:00 HOST:ed251.opt2.point.ne.jp
削除対象アドレス:
 スレリンク(tech板)
 スレリンク(tech板)
 スレリンク(tech板)
削除理由・詳細・その他:
 6. 連続投稿・重複

115:デフォルトの名無しさん
06/03/03 01:13:30
Dr.Dのマシン語寺子屋

116:デフォルトの名無しさん
06/03/31 11:14:10
TBitmap→TJpegImage→Jpegファイル、とやってますが、
DDBからDIBにするとメモリ減りますか?

コーディングも簡単でつか?

117:デフォルトの名無しさん
06/03/31 12:06:28
やってることと、質問の内容が噛み合ってない

118:116
06/03/31 13:30:05
いやだから、

TBitmap(DDB)→TJpegImage→Jpegファイル
から
TBitmap(DIB)→TJpegImage→Jpegファイル
に変更。

今は意識してないけど、TBitmapってデフォはDDBだおね?

119:デフォルトの名無しさん
06/03/31 13:50:09
大差ないよ。

120:デフォルトの名無しさん
06/05/29 00:58:17
feeddemonってRSSリーダーがあるんですが
v1のときにhtaのような使い方をしている
部分(左のチャンネルリスト)をどう実装してるのか
わからないんですが、誰か教えてください詳しい人


121:デフォルトの名無しさん
06/05/29 13:16:35
> Delphi初心者が問題をコツコツと解きながらレベルアップするためのスレです。

すれ違い

122:デフォルトの名無しさん
06/06/09 17:59:34
マウスカーソルをアルファベット文字、もしくは単語にしたいのですが、
簡単にできますか?

アルファベット毎にカーソルファイルを作るのでなく、
コーディングでやりたいです。

123:デフォルトの名無しさん
06/06/09 18:47:12
簡単にはできないでしょ。すなくとも動的にアルファベットの画像をつくらなきゃならないし。

124:デフォルトの名無しさん
06/06/09 19:15:11
>>122
URLリンク(forum.nifty.com)

TBitmapを作成して そこに文字を書いて、
それからCreateCursor

125:122
06/06/12 08:41:29
>>123 >>124

サンクス。
ちょっとひねればコーディングできそうですね。

126:デフォルトの名無しさん
06/09/03 09:14:12
どうぞよろしくお願いします

Delphi7.0上で、3層の情報系の業務アプリケーションを構築しています
データベースはOracle9iです
UIでは、ADOレコードセットを入力データソースするMicrosoftのActiveXコンポーネント
を使用しています
BDE、DBExpressやBizSnapを利用すれば3層のデータアプリケーションは作成できる
ことは分かりました
データセットプロバイダ経由でデータを取得しようとすると、クライアント側はClientDataSet
として受け取ることになるのですが、どこかでADOレコードセット形式に変換しなければなりません

試しにClientDataSetをまわしながらADOレコードセットにフィールド定義とデータ値をコピーする
方法を試してみましたが、処理時間とCPU負荷が半端ではなく、とても採用できませんでした
他には、BizSoapを利用した形式では、サーバー側でADOレコードセットとしてデータ取得後に
Saveメソッドを利用してXML形式で一旦データ出力し、Soap経由でテキスト送信し、クライアント
側では受信内容をファイルとして出力しADOレコードセットのLoadメソッドをCallしてXMLファイル
から復元する方法を試したみましたが、これも採用できるものではありませんでした
素直にクライアント側でADOレコードセットとして取得可能な方法としては、リモートデータセット
(Microsoft RDS)を利用したDComアプリケーションとして構築する方法もあるので試してみました
これは、非常に高速で20万件程度のデータもほぼ一瞬でクライアント処理でき驚いたものですが、
MicrosoftのサポートページではRDS自体が今後は非推奨の技術として明記されており、その点
が引っかかっております

どうしてもクライアント側で扱うデータ量が数十万件程度あることでパフォーマンスが重要になって
しまいます。
オーバーヘッドがなるべく最小の形でClientDataSetからADOレコードセット形式に変換する方法は
ないものでしょうか
もしくは、素直にADOレコードセットとしてクライアント側で一発でデータ取得できれば嬉しいです

長文になってしまい申し訳ありません
どうぞよろしくお願いいたします


127:126
06/09/03 09:22:44
126です
大変失礼しました
[ くだすれdELPHI(超初心者用) ] のスレの方に移動します

128:デフォルトの名無しさん
06/09/11 00:03:00
>>1
問題だしておくれ
初心者でも10分ぐらいで解けて、面白味のあるものがいい

129:デフォルトの名無しさん
06/09/11 08:47:19
じゃ、俺から問題

ボタンを二つ用意し、片方を非表示とする。
表示されているボタンを押すと、非表示だったボタンを表示し、押されたボタンを非表示に。
これを交互に繰り返せるものを作れ。

130:デフォルトの名無しさん
06/09/11 10:14:48
くだらね┐(´〜`;)┌

131:デフォルトの名無しさん
06/09/11 11:34:13
>>130
ならおまえがだせ。
と、いいたいところだが、これはどうだ?
コントロールのオーナーをTForm1からTForm2に変える。

132:デフォルトの名無しさん
06/09/11 12:30:13
他のスレでTPrinterの話題が出てたんで。

用紙の左上から右に5cm、下に5cmの位置に
「はろーわーるど」と印字せよ
フォントは何でもいい

133:デフォルトの名無しさん
06/09/11 15:51:09
初心者の基準を考えよ

134:デフォルトの名無しさん
06/09/12 16:57:18
iniファイル作って
初期データ読み込み書き込みはどうだ?

135:デフォルトの名無しさん
06/09/12 17:10:37
初心者の基準を考えよ

136:デフォルトの名無しさん
06/09/12 20:17:27
procedure TForm2.Button1Click(Sender: TObject);
begin
  Button1.Visible:=not Button1.Visible;
  Button2.Visible:=not Button2.Visible;

end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  Button2.OnEnter:=Button1Click;
  Button2.Visible:=False;
end;


137:デフォルトの名無しさん
06/09/12 20:18:58
あ、途中で書き込み押しちゃった
>>136>>129への回答です
短くなるように工夫しました
採点お願いします

138:デフォルトの名無しさん
06/09/12 20:25:08
わざわざコードで
  Button2.OnEnter:=Button1Click;
  Button2.Visible:=False;
をする必要が無い。
0点。

139:デフォルトの名無しさん
06/09/12 20:30:07
そりゃプロパティでも出来るけどあえて明示してるんでしょうが。

140:デフォルトの名無しさん
06/09/12 20:42:49
ほかにもフォームの位置とかサイズとか、明示しろよ。

141:デフォルトの名無しさん
06/09/12 20:54:32
こりゃいかん。

142:デフォルトの名無しさん
06/09/12 21:10:23
てゆうか先生!なんでOnEnterやねん!Clickや!!
と突っ込むところではないの?


143:デフォルトの名無しさん
06/09/12 21:12:52
ほんとだwwww

144:デフォルトの名無しさん
06/09/12 22:23:37
TD2006ってコンポにフォーカスさせてF1押してもヘルプでないよね

145:デフォルトの名無しさん
06/09/12 23:28:50
しらねぇよ。Del6per の方がましだし、そんなの使うヤツの気が知れん

146:デフォルトの名無しさん
06/09/13 03:30:32
procedure TForm1.Button1Click(Sender: TObject);
const
FILE_URL = 'URLリンク(203.131.199.131:8060)';
FILE_PATH = 'test.mp3';
var
fs: TFileStream;
begin
fs := TFileStream.Create(FILE_PATH, fmCreate);
try
with IdHTTP1 do begin
Get(FILE_URL, fs);
end;
finally
fs.Free;
end;
end;

147:デフォルトの名無しさん
06/09/13 08:14:13
>>145
可哀そうに

148:デフォルトの名無しさん
06/09/13 11:33:34
TDって略すとTurbo Debuggerかと思ってしまう俺。
(さすがにTokyo Disnylandとは思わないが)

149:デフォルトの名無しさん
06/09/13 19:35:33
>>144
可哀そうに

150:デフォルトの名無しさん
06/09/13 21:21:06
>>134
iniファイル読み書きの習作をつくってみました
普通にファイルの読み書きするより簡単かもしれない
ちょっと感動!!
procedure TForm1.Button1Click(Sender: TObject);
var
  iniFile:  TInifile;
begin
  iniFile:=TIniFile.Create('ook.ini');
  try
    count:=iniFile.ReadInteger('CounterApp', 'Count', 0);
    Inc(count);
    iniFile.WriteInteger('CounterApp', 'Count', count);
  finally
    iniFile.Free;
  end;
  ShowMessage(IntToStr(count));
end;



151:デフォルトの名無しさん
06/09/13 21:30:06
フルパスつかっとけ

152:デフォルトの名無しさん
06/09/13 22:06:31
EXEファイルと同じフォルダが前提ならそのままがいいと思うが。

153:デフォルトの名無しさん
06/09/13 22:39:21
>>152
お前はそのままでいいよw

154:デフォルトの名無しさん
06/09/13 23:24:42
>>152 は、今後大変だな・・・

155:デフォルトの名無しさん
06/09/14 00:35:54
>>150
お主、俺を超えたな!?

156:デフォルトの名無しさん
06/09/14 04:04:15
カレントディレクトリが変わるたびに、あちこちにいっぱい ini をつくるけどね

157:デフォルトの名無しさん
06/09/14 05:19:24
TIniFile って相対パス渡すとプロファイルフォルダに作られなかったっけ?

158:デフォルトの名無しさん
06/09/14 07:56:03
なんにせよそういう不安定要素は削除しないとな

159:デフォルトの名無しさん
06/09/14 10:09:08
>Delphiで無料でプログラミングしてみるお
スレリンク(tech板:239番)
>ソースと実行ファイル
URLリンク(vipperup.orz.hm)

これって、もう手に入らないの?

160:デフォルトの名無しさん
06/09/14 16:02:35
 

161:デフォルトの名無しさん
06/09/29 18:21:31
授業を受けに来たのに先生がいませんよ。有給ですか?

162:デフォルトの名無しさん
06/09/29 18:37:24
>>132


163:デフォルトの名無しさん
06/10/06 22:25:29
別のアプリケーションにエンターキーを送りたいのですが、アプリケーション側でなにか
対策をしているらしく、keybd_event ではエンターキーだけが認識されません。
(そのアプリ上でエンターキーを直接押せば認識される)

こういった場合、どのようにすればいいのでしょうか?

164:163
06/10/06 22:49:19
>>163
すみません、、、スレ間違えました。別スレに行ってきます。

165:デフォルトの名無しさん
06/10/16 03:02:58
Delphiで
Vbでいうところの Validate イベントを実現したい。
どうすればいい?

Procedure TXXXXX.OnValidate(Sender : TObject;Cancel : Boolean);

Cancel := True;

とすれば、フォーカスが抜けないようにする。
どうやったらできるんだろう?

TEdit を継承して、
WndProc を オーバーライドして
CM_EXIT をフックしてみた。

TEdit ではうまくいったが
TComboBox ではうまくいかなかった(DropDownList では おk で DropDown ではNg だった)。

誰か経験者か、うまいやり方知ってるひと教えてください。

166:デフォルトの名無しさん
06/10/16 09:10:19
やったことないけどOnEnterでValidateすべきかどうか(どこかで)設定しといて
WM_KILLFOCUS受け取ったときに上記状態なら指定されたところにチェックしにいくとか

167:デフォルトの名無しさん
06/10/16 09:25:28
OnChangeかOnExitの時に、
Cancel=Falseなら、Combobox.setfocus


168:デフォルトの名無しさん
06/10/16 10:42:34
procedure TForm1.hogeExit(Sender: TObject);
begin
  チェック処理
  if エラー then
  begin
    Enabled := False;
    Application.ProcessMessages;
    Enabled := True;
    hoge.SetFocus;
  end;
end;

169:デフォルトの名無しさん
06/10/16 16:57:31
TPrinterで印刷の集約指定等の設定変更できますか?

170:デフォルトの名無しさん
06/10/16 17:36:53
印刷設定ダイアログ結果をWindowsに反映する方法教えて下さいでつ。

171:デフォルトの名無しさん
06/10/17 01:33:57
>>166
ありがとうございます。
WM_KILLFOCUSでも同じでした。

>>167,168
ありがとうございます。

TComboBox の派生クラスに OnValidate イベントを実装したいのです。

172:デフォルトの名無しさん
06/10/19 10:09:05
DoExitをオーバーライドするのはどうですか?

procedure TMyCombo.DoExit;
var
  Cancel: Boolean;
begin
  if Assigned(FOnValidate) then begin
    Cancel := False;
    FOnValidate(Self, Cancel);
    if Cancel then begin
      SetFocus;
      Exit;
    end;
  end;

  inherited;
end;


173:デフォルトの名無しさん
06/10/19 10:47:13
Delphi7
SQLServer2000 使用です。

exceptにて、EDatabaseErrorが発生した場合に、
そのエラーNoを取得したいのですが、どのように書けばよいのでしょうか?
現時点では下のように書くところまでやりました。

except
on E: EDatabaseError do
begin
Result := False;
end;
end;

174:デフォルトの名無しさん
06/10/19 11:09:58
>>173
いろいろ考えられるね。
・E.MessageにエラーNoが入ってるならそこから抽出する。
・E.ErrorNoみたいのがあるならそれを使う。
・SQLServer2000にGetLastDBError見たいな関数があるならそれを利用する。

175:デフォルトの名無しさん
06/10/19 11:19:34
>>173
BDE使ってるならEDBEngineErrorでcatchすれば
エラーの詳細が取れるけど。
どうやって接続してるの?

176:173
06/10/19 11:24:15
>>174
すみません、もっと根本的な問題だったようです。
やりたいことは、レコードロックによるタイムアウトエラーを取得したいのですが、
タイムアウトはEDatabaseErrorではないようです。

タイムアウトはEDatabaseError以外のどのExxxErrorでとれるのでしょうか?


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5102日前に更新/190 KB
担当:undef