C++でforループがうまくいきません
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 1,976
前提・実現したいこと
C++で簡単なタイピングゲームを作っています。
ファイルからランダムな行を読み込んで、","で分割して分割した2番目の単語を入力させるものです。
発生している問題・エラーメッセージ
ループ中、時々p_word_afterの指す値がNULLになります。この時、p_word_beforeの指す文字列は一つ前のループのときと同じになっています。
ちなみに、rand()%55の値が同じである場合はp_word_afterに値が入っているので、これは原因ではないと思います。これはどういった現象なんでしょうか。
該当のソースコード
int key=0,count,score=0,mistake=0,ran=0,line,add,word_num;
int level=0;
char *advise;
unsigned i;
char line_text[256];
char word_before[50][128];
char word_after[50][128];
char *p_word_before;
char *p_word_after;
FILE *fp;
fp=fopen(<<filename>>,"r");
for(count=50;count>0;count--){
rewind(fp);
p_word_before=word_before[count];
p_word_after=word_after[count];
int len;
srand((unsigned)time(NULL));
line=0;
for(line=rand()%55;line>0;line--){
fgets(line_text,256,fp);
}
p_word_before=strtok(line_text,",");
p_word_after=strtok(NULL,",");
system("cls");
add=0;
while(*(p_word_after+add)!='\n'){
add++;
}
*(p_word_after+add)='\0';
printf("%s (%s) 残り%d単語\n",p_word_before,p_word_after,count);
i=0;
len=strlen(p_word_after);
while(i<len){
if(_kbhit()){
key=_getch();
if(key==0||key==224)key=_getch();
if(key==p_word_after[i]){
printf("checked %c\n",key);
i++;
score++;
}else{
mistake++;
}
fflush(stdin);
}
}
}
補足情報(言語/FW/ツール等のバージョンなど)
IDE : VisualStudio2012 for Desktop
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
こんにちは。
ざっと見る限り、yasunori_bamさんが記載されている現象が起こるソースのようには見えません。
rand()%55
が0の時はfgets(line_text,256,fp);
が実行されませんので、p_word_beforeに「前回」のfor(count)ループ時の値が入ることはありえますが、その時、p_word_afterにも前回と同じ値が入る筈なのでNULLにはならない筈です。
また、rand()%55
が例えば5の時、p_word_afterに値が入ったり、NULLが入ったりするのですね?
それもちょっと考えにくいです。・・・①
ただ、もし、サブ・スレッドを使っていてサブ・スレッドでもstrtok()を使っていたら、何が起こるか分かりませんので、ご説明されたような事象が起きる可能性はあります。strtok()はスレッド安全ではありませんので。
しかし、ご提示された内容からサブ・スレッドを使っているとは思えません。
試しに、下記の直後で、line_text、p_word_before、p_word_afterを表示してみては如何でしょうか?
何か掴めそうな気がします。
p_word_before=strtok(line_text,",");
p_word_after=strtok(NULL,",");
ところで、①の現象はどのようにして確認されましたか? どうもその確認にミスがありそうな予感がします。
また、ファイルは55行以上存在し、その全ての行にはp_word_afterがNULLになることはない文字列が入っていることは確認できていますか? 例えば、p_word_afterがNULLにならない行を55行コピペしておけば簡単に条件を作れると思います。
因みに下記はミスですね?(特に影響はないと思いますが。)
p_word_before=word_before[count];
p_word_after=word_after[count];
countは50から始まりますが、 word_before[50][128], word_after[50][128]ですので、word_before[49][], word_after[49][]までしかありません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
ぱっと見て気になったことが一点。
for(count=50;count>0;count--){
この記述だと、ループの中ではcountが50から始まって最後に1になります。
p_word_before=word_before[count];
p_word_after=word_after[count];
それぞれの配列は[50]
で確保されているため、添え字に指定可能な範囲は0~49
です。ループ初回でcountに50が入っているので、配列の範囲を超えています。
しっかり見て気になった点を。
for(line=rand()%55;line>0;line--){
fgets(line_text,256,fp);
}
rand()%55
は0になる可能性があります。その場合、条件判定でいきなりループ終了になるため、ループ内のfgetsが実行されません。
そうなると、line_text
に正しい文字列が入らず、strtok
関数が正しい結果を返さないのだと思います。
line=rand()%55 + 1
とすれば良いと思います。
補足
strtok
関数は、返すべき文字列がないとNULLを返します。前述のループでfgetsを実行しないまま抜けると、前回のバッファの内容が残っているわけですが、区切り文字が消されてしまっているので最初のstrtokで文字列全体を返してしまい、次のstrtokでは返すべき文字列がないという状況になったのだと思われます。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
HogeAnimalLover
2016/05/08 21:38
それはどこの行です発生していますか?strtokで発生しているならばこの仕様を調べれば良いと思います。(検索対象が見つからない場合にNULLが返る)