アプリ版:「スタンプのみでお礼する」機能のリリースについて

シューティングゲームのサンプルを勉強しています。
下記のこの部分のコードが二つあります。

memset(buf,0,sizeof(buf));

気になっています。
なぜ二つあるのかを意味を知りたいです。
よろしくお願いします。

コードは以下に記述します。
CONTROL::CONTROL()
{
player = new PLAYER;
back = new BACK;
FILE *fp;
ENEMYDATA data[ENEMY_NUM];
char buf[100];
int c;
int col=1;
int row=0;

memset(buf,0,sizeof(buf));

fp = fopen("enemydata1.csv","r");
while(fgetc(fp)!='\n');
while(1){
while(1){
c=fgetc(fp);
if(c==EOF)
goto out;
if(c!=','&& c!='\n')
strcat(buf,(const char*)&c);
else
break;
}
switch(col){
case 1: data[row].type=atoi(buf); break;
case 2: data[row].stype=atoi(buf); break;
case 3: data[row].m_pattern=atoi(buf); break;
case 4: data[row].s_pattern=atoi(buf); break;
case 5: data[row].in_time=atoi(buf); break;
case 6: data[row].stop_time=atoi(buf); break;
case 7: data[row].shot_time=atoi(buf); break;
case 8: data[row].out_time=atoi(buf); break;
case 9: data[row].x=atoi(buf); break;
case 10: data[row].y=atoi(buf); break;
case 11: data[row].speed=atoi(buf); break;
case 12: data[row].hp=atoi(buf); break;
}

memset(buf,0,sizeof(buf));

++col;
if(c=='\n'){
col=1;
++row;
}
}
out:
for(int i=0;i<ENEMY_NUM;++i){
enemy[i]=new ENEMY(
data[i].type,
data[i].stype,
data[i].m_pattern,
data[i].s_pattern,
data[i].in_time,
data[i].stop_time,
data[i].shot_time,
data[i].out_time,
data[i].x,
data[i].y,
data[i].speed,
data[i].hp,
data[i].item);
}
}

A 回答 (5件)

strcat については前の


http://oshiete.goo.ne.jp/qa/8460028.html
で指摘したんだけどねぇ>#3&#4.

memset 自体は, 既に回答があるようにループのどこかに入れれば 1個で済むはず.

しかし... 前のときにはあえて書かなかったんだけど, ENEMY のコンストラクタがすっごくバカに見える.
    • good
    • 0
この回答へのお礼

お世話になっています。
理解不足ですいません。
失礼します。

お礼日時:2014/03/02 08:41

参加するつもりはありませんので書き逃げになりますかねぇ…



csv読む込むのにfgetc()で読むよりは、1行読み込んで処理した方が…というは前回も指摘したところですが。
読もうとしているcsvにShift-JISで日本語とか書いてあったときに誤動作する可能性があります。

fgetc()で読むならすでに指摘されているようにstrcat()でつなげるのは正しくないです。
どこまで読み込んだのか…のカウンタでも持って
buf[cnt++] = (char)c;
buf[cnt] = '\0';
として追加していくべきでしょう。
# strcatする度にbufの先頭から'\0'を探す処理が走ってCPUが仕事シテマスをアッピールとか?

memset()が2つあるのはすでに回答あるとおりですね。
実施する場所をちゃんと厳選すれば1つで充分です。
というか「strcat()で繋げる」ならbuf[0] = '\0'でもいいでしょう。
# デバッガでメモリの状態見るなら向きませんけどね。
    • good
    • 0
この回答へのお礼

お世話になります。
memset(buf,0,sizeof(buf));
の部分は一つでも出来ることがわかってよかったです。
ありがとうございました。
失礼します。

お礼日時:2014/03/02 08:56

No.2です。



書き漏らしました。このソースコードには潜在的なバグが
あると思います。

strcat(buf,(const char*)&c);

ですが、strcatの第2パラメータは0終端文字列を指定しなければ
ならないのに、int型のcのアドレスを指定しています。

リトルエンディアンのintel系CPUで動作させるなら
これでもたまたまうまく動作すると思いますが、
bufクリア箇所といい、あまり勉強のお手本には
しない方がいい下手なコーディングだと思います。
なぜリトルエンディアンのintel系CPUなら動作するのか、
ビッグエンディアンだとどうなるのか調べて、
反面教師として利用すればいいのかもしれません。
    • good
    • 0

このソースコードは、fgetc(fp)で読み込んだ文字を1文字ずつ


bufにstrcatで追記し、カンマで区切られた単語を読み込む
処理になっています。

例えば「1234,5678, ....」という入力があった場合、
bufに「1234」まで文字を追記した後、「,」の出現を検出して
bufに入っている値(1234)をdata[row].typeに取り出します。
それを取り出した後
memset(buf,0,sizeof(buf));
でbufの内容をクリアしてから、またループの先頭に戻って
次の単語の処理に入りますが、もしこのクリアがないと
次の入力を読み込んだ時、現在bufに入っている「1234」に
追記して「12345678」という単語を作ってしまいます。
このため、この後半のbufクリアが必要です。bufをクリアして、
また先頭から追記し「5678」として読み込む必要があります。

ただ、こういうふうにループに入る前にクリアして、
ループの先頭に戻る前にクリアするような2度手間するよりも、
1個目のwhile(1)の直後にbufをクリアすればクリア処理は
1箇所で済む話で、その方がすっきりしていると思います。
bufを初期化するポイントが整理されていない印象です。
    • good
    • 0

ざっと見ただけできちんと確認してないけど


bufの内容としては CSV ファイルの1行分のデータを格納・処理のループをしているようです

他の行のデータ残骸が残らないようにクリアしているだけではないかと思われます

残骸が残っても支障がないように作ってあるならクリア必須というわけではありませんが
デバッグ等行う場合にはクリアしていた方がわかりやすい(確認しやすい)
といった事はあるかもしれません
    • good
    • 0
この回答へのお礼

貴重な意見ありがとうございます。
ここの部分が気になったのですが

デバッグ等行う場合にはクリアしていた方がわかりやすい(確認しやすい)

他の場合はクリアしなくてもいいと言うことですか。
出来ればこの部分の事を教えて
もらえるとありがたいです。

失礼します。

お礼日時:2014/03/02 09:40

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