dポイントプレゼントキャンペーン実施中!

Borland C++ Builder 5 を使っています。
StringGridの内容をクリップボードにCOPYするプログラムを作っています。
Excelに貼り付けるのが目的なので、Tab区切りのデータにしています。

下に示したソースで実現できましたが、非常に遅いのです。
100行とか200行ならアッという間なのですが、2,000行、3,000行となるとかなり待たされます。
時間を食っているのは(2)の部分のようです。
もう少しスマートに、短時間でCOPYしたいのですが、方法はないものでしょうか?

◆ソースの解説
StringGridの21列分を、行数だけクリップボードにCOPYします。
(1)
StringGridの各行、各列をLOOPしてセルに格納されている文字列長の合計を求めます。
Tab区切りにするため、各セルごと1バイト加算します。
また、各行ごと改行を入れるため、これも1バイト加算します。
(2)
合計容量が計算できたら、メモリーを動的確保し、もう一度LOOPをしながら、文字列をCOPYします。
セルごとにTab、行ごとに改行も追加します。
(3)
最後にクリップボードをクリアしてCOPYします。


int cnt = StringGrid1->RowCount;
int size = 0;
//StringGridのサイズ(文字長)をカウントする ------ (1)
for(i=0;i<cnt;i++){
for(k=0;k<21;k++){
size += strlen(StringGrid1->Cells[k][i].c_str()) + 1;
}
size++;
}
//メモリーを確保して、StringGridをCOPYする -------- (2)
cb = new char[size];
strcpy(cb,"");
for(i=0;i<cnt;i++){
for(k=0;k<21;k++){
strcat(cb,StringGrid1->Cells[k][i].c_str());
strcat(cb,"\t"); //Tab区切りの文字列にする
}
strcat(cb,"\n");
}
Clipboard()->Clear(); // -------- (3)
Clipboard()->AsText = cb;

なお、サイズがintに収まるかというチェックとか、メモリーの解放をする、といったことも必要ですが、記述を省略しました。

A 回答 (1件)

strcatで毎回連結しているようですが、質問内容のソースコードでは毎回'\0'を探し出して、その後に文字列を連結しているため処理効率が落ちてしまいます。



以下のようにしてはどうでしょう。

追加宣言
int mcnt,mlp;

(2)の部分のソースコード
cb = new char[size];
cb[0] = '\0';
mcnt = 0;
for(i=0;i<cnt;i++){
for(k=0;k<21;k++){
for(mlp=0;mlp<strlen(StringGrid1->Cells[k][i].c_str());mlp++){
cb[mcnt] = StringGrid1->Cells[k][i].c_str()[mlp];
mcnt++;
}
//Tab区切りの文字列にする
cb[mcnt] = '\t';
mcnt++;
}
//行ごとに改行する。
cb[mcnt] = '\n';
mcnt++;
}
//最後に'\0'を付加。
cb[mcnt] = '\0';
mcnt++;

申し訳ありませんが、試してはいません。
    • good
    • 0
この回答へのお礼

hiro_knighさん、ありがとうございました。

>strcatで毎回連結しているようですが、質問内容のソースコードでは毎回'\0'を探し出して、その後に文字列を連結しているため処理効率が落ちてしまいます

どうもそのようです。

試しに、次のようなstrcatのテストプログラムを作ってみました。
char Tmem[400001]="";
char moji[]="0123456789";
int i;
for(i=0;i<20000;i++) strcat(Tmem,moji);

20,000回のLOOPで、約3秒かかりますが、倍の40,000回のLOOPでは、11秒もかかります。(ストップウォッチによる手動計測)
回数を倍にしただけなのに、時間は4倍弱掛かっています。
'\0'を探し出すのに時間が掛かっているようです。

アドバイスを参考に、kのLOOPを次のようにしました。
len = strlen(StringGrid1->Cells[k][i].c_str());
strncpy(&cb[st],StringGrid1->Cells[k][i].c_str(),len);
cb[st + len] = '\t';
st = st + len +1;

その結果、手動計測では測定不可能なほど早くなりました。
ありがとうございました。

お礼日時:2009/09/21 18:18

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!