今回は、テスト勉強を兼ねて制作した単語帳にてバグが見つかったので、
その解決方法をおたずねしたく投稿させていただきます。
まず、この単語帳のソースコードを以下に示します。
#define ONCE
#include "origin.h"
struct word_t{
char ques[64];
char ans[64];
struct word_t *next;
}*head;
// 領域確保
struct word_t *talloc(){
return ( struct word_t * )malloc( sizeof( struct word_t ) );
}
// 領域開放
void word_free( struct word_t *p ){
struct word_t *q;
if( p != NULL ){
q = p->next;
free( p );
word_free( q );
}
}
int main(int argv,char *argc[]){
int num, right, wrong;
char filename[256], answer[64];
struct word_t *p, *old, *pd, *oldd;
FILE *fp;
if( argv<2 ){
printf( "実行ファイル名を入力してください ≫" );
scanf( "%s", filename );
}
else{
strcpy( filename, argc[1] );
}
if( ( fp = fopen( filename, "r" ) ) == NULL ){
printf( "実行ファイルが見つかりませんでした\n" );
printf( "ファイルの確認をしてください\n" );
exit( EXIT_FAILURE );
}
head = ( struct word_t * )realloc( head, sizeof( struct word_t ) );
fscanf( fp, "%s %s", head->ques, head->ans );
head->next = NULL;
num = 1;
old = head;
while( p = talloc(), fscanf( fp, "%s %s", p->ques, p->ans ) != EOF ){
old->next = p;
p->next = NULL;
old = p;
num++;
}
fclose( fp );
p = old = head;
right = wrong = 0;
for(int i=0;p!=NULL;i++){
system( "cls" );
printf( "意味:%s\n" ,p->ques );
printf( "解答:" );
scanf( "%s", answer );
getchar();
system( "cls" );
printf( "意味:%s\n", p->ques );
printf( "解答:%s\n", answer );
printf( "正解:%s ", p->ans );
if( strcmp( p->ans, answer )==0 ){
printf( "○\n" );
right++;
old = p;
p = p->next;
}
else{
printf( "×\n" );
wrong++;
if( p!=head ){
oldd = old;
pd = p;
old = p;
p = p->next;
oldd->next = pd->next;
pd->next = head;
head = pd;
}
else{
old = p;
p = p->next;
}
}
printf( "\t\t\t正解数 %d/総問題数 %d\n", right, i+1 );
getchar();
}
if( wrong==0 ){
printf( "パーフェクトです!\n" );
printf( "この調子で頑張ってください!\n" );
}
while( wrong>0 ){
system( "cls" );
printf( "間違えた部分の復習プログラムを開始します\n" ); getchar();
p = head;
num = wrong;
right = wrong = 0;
for(int i=0;i<num;i++){
system( "cls" );
printf( "意味:%s\n" ,p->ques );
printf( "解答:" );
scanf( "%s", answer );
getchar();
system( "cls" );
printf( "意味:%s\n", p->ques );
printf( "解答:%s\n", answer );
printf( "正解:%s ", p->ans );
if( strcmp( p->ans, answer )==0 ){
printf( "○\n" );
right++;
old = p;
p = p->next;
}
else{
printf( "×\n" );
wrong++;
if( p!=head ){
oldd = old;
pd = p;
old = p;
p = p->next;
oldd->next = pd->next;
pd->next = head;
head = pd;
}
else{
old = p;
p = p->next;
}
}
printf( "\t\t\t正解数 %d/総問題数 %d\n", right, i+1 );
getchar();
}
}
fp = fopen( filename, "w" );
p = head;
while( p!=NULL ){
fprintf( fp, "%s %s\n", p->ques, p->ans );
p = p->next;
}
fclose( fp );
word_free( head );
}
ここでは、stdioだとかstdlibだとか、そういった基本的な標準ライブラリがまとまっているものとして考えてもらえればOKです。
問題のエラーなのですが、この単語帳は「間違えた問題を自己再編成し先頭に持ってくる」という仕様をしておりまして、
最後に間違えた単語のみを反復練習、さらに次回以降は「間違えやすい問題から」出題されるようにしていました。
しかし、この単語帳において3度以上間違えると、反復練習時に3度目の出題が必ず(null)と表示されてしまうのです。
試しにブレークポイントを108行目に設定し、出題用ポインタpのアドレスを見張ってみたのですが、
3問目で必ずp=NULLになっています。
恐らく再編成を行う84~96行目に何らかの不備(というかミス)が存在していると考えましたが、
恥ずかしながら、私ではそれが何なのかを見つけることができませんでした。
どうか、この問題の解決方法、考え方をご教授ください。よろしくお願いします。
開発環境:VC++2008EE
使用言語:C