• ベストアンサー

構造体メンバの個数

気になって質問させていただいたのですが、構造体のメンバが例えば10個とかあったりしたら、何かプログラムに異常が起きたりするものでしょうか? 現在作っているプログラム中で、本来入っているはずの数値(文字列)が、微妙にでたらめなものに変わってしまいます。(実際に起きたのが、int aの値は10なのに、46543とか。char name[20] = "ジタン" が、"ジタnp"とか) たまに、こういったことがプログラムを組んでいると起こるので、何が起こっているのか分かる方、御教授お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.26

後編: // 味方の攻撃番号を取得 static int turnInput( int check[] ) {  int turn;    for ( ; ; ){   printf( "誰が攻撃しますか(1.人物A 2.人物B 3.人物C 4.人物D)--->" );   scanf( "%d", &turn );   // 1~4以外ならプログラムの終了   if ( (turn < 1) || (turn > MAX_MEMBER) ){    exit( 1 );  // 強制終了   }   // 0~3に変換   turn--;   // 戦闘不能のチェック   if ( Member[turn].hp <= 0 ){    printf( "戦闘不能です。\n" );    continue;   }   // 攻撃済みのチェック   if ( check[turn] ){    printf( "/*-----%sのターンは終了しています-----*/\n", Member[turn].name );    continue;   }   // 攻撃番号を返す   check[ turn ] = 1;  // 攻撃済みフラグのセット   printf( "\n" );   return turn;  } } // 味方の攻撃ルーチン extern int attackMember( int members ) {  int check[ MAX_MEMBER ] = { 0 };  int loop;    dispStatus();  for ( loop = 1 ; loop <= members ; loop++ ){   printf( "味方の攻撃ターン(%d/%d)\n", loop, members );      switch ( turnInput(check) ){    case 0:     chaAB( &Member[0], &Enemy[0] );     printf( "/*-----------------人物Aのターン終了------------------*/\n\n" );     break;    case 1:     chaAB( &Member[1], &Enemy[0] );     printf( "/*-----------------人物Bのターン終了------------------*/\n\n" );     break;    case 2:     chaCD( &Member[2], &Enemy[0] );     printf( "/*-----------------人物Cのターン終了------------------*/\n\n" );     break;    case 3:     chaCD( &Member[3], &Enemy[0] );     printf( "/*-----------------人物Dのターン終了------------------*/\n\n" );     break;    default:     loop = members;  // 抜ける設定     break;   }  }  return checkEnemy();  // 1:生きている 0:死す } // 敵の攻撃ルーチン extern int attackEnemy( void ) {  int i, n1, s1, s2, s3, s4;    dispStatus();  printf( "敵の攻撃ターン\n" );  for ( i = 0 ; i < MAX_MEMBER ; i++ ){   status *p = &Member[i];      srand( (unsigned)time(NULL) + rand() );   n1 = RAND( 1000, 1000 ); // ダメージ量(1000~1999)   s1 = RAND( 100, 1 );  // [毒]状態(1-100)   s2 = RAND( 100, 1 );  // [沈黙]状態(1-100)   s3 = RAND( 100, 1 );  // [暗闇]状態(1-100)   s4 = RAND( 100, 1 );  // [混乱]状態(1-100)      if ( (p->hp -= n1) < 0 ){    p->hp = 0;   }   p->st[ 0 ] |= s1 % 2; // [毒]状態の設定   p->st[ 1 ] |= s2 % 2; // [沈黙]状態の設定   p->st[ 2 ] |= s3 % 2; // [暗闇]状態の設定   p->st[ 3 ] |= s4 % 2; // [混乱]状態の設定   printf( "%sの攻撃--->%sに%dのダメージを与えた。\n", Enemy[0].name, p->name, n1 );  }  printf( "\n" );  return checkMember();  // 1:生きている 0:全滅 } // 人物A/Bの攻撃(勇者,戦士) extern void chaAB( status *member, status *enemy ) {  int n1;    // 初期化  srand( (unsigned)time(NULL) + rand() );  n1 = RAND( 1000, 1000 ); // ダメージ量(1000~1999)    if ( (enemy->hp -= n1) < 0 ){   enemy->hp = 0;  }  printf( "%sの攻撃--->%sに%dのダメージを与えた。\n\n", member->name, enemy->name, n1 ); } // 人物C/Dの攻撃(魔法使い) extern void chaCD( status *member, status *enemy ) {  int n1, select;    // 初期化  srand( (unsigned)time(NULL) + rand() );    do {   printf( "1.魔法1 2.魔法2--->" );   scanf( "%d", &select );      switch ( select ){    case 1:     if ( member->mp < 20 ){      printf( "MPが足りません。\n" );      select = -1;      break;     }     n1 = RAND( 1000, 1000 ); // ダメージ量(1000~1999)          if ( (enemy->hp -= n1) < 0 ){      enemy->hp = 0;     }     member->mp -= 20;     printf( "%sの魔法攻撃--->%sに%dのダメージを与えた。\n\n", member->name, enemy->name, n1 );     break;    case 2:     n1 = RAND( 50, 50 );  // MP吸収量(50~99)          if ( enemy->mp < n1 ){      n1 = enemy->mp;     }     member->mp += n1;     enemy->mp -= n1;     printf( "%sの魔法吸収--->%sから%dのMPを吸収した。\n\n", member->name, enemy->name, n1 );     break;    default:     select = -1;     break;   }  } while ( select == -1 ); } 以上。

sikimori
質問者

お礼

わざわざ考えていただいてありがとうございますm(_ _)m これを参考に、改良できる部分はしていきたいと思います。 いきなり直ったので、出来る限り原因追求していきます。

その他の回答 (25)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.5

Oh-Orangeさんではありませんが、見てみました。 mainの*pの初期化が謎ですが、それ以外は問題がなさそうです。 どちらかと言うとhuman関数の方が危険そうですね。human関数の中身が見たいです。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.4

構造体の問題ではなさそうです。 プログラムの何処かでメモリ破壊をしている箇所があり、たまたま構造体の内容が壊れているだけだと思います。 よくある失敗として、 1.ポインタの扱いが間違っていて、本来の場所以外を指している。 2.配列の添え字の数値が、配列の宣言時の値を超えていて配列外を壊している。 3.malloc、freeで管理しているメモリ領域が解放されているにもかかわらず。解放されていること確認しないで使ってしまっている。そのため後からmallocで同じ場所に構造体を割り当ててしまってメモリが破壊される。 などが考えられます。 たまに、このような事が起こるとすれば、いつも同じ様なプログラムのミスをしている可能性が高いです。放置しておかずに、その悪いプログラミングのクセを直したほうがよいでしょう。そのためには破壊する箇所を探しだすことです、なぜこうなるのかを追求しないといつもでも謎の破壊は直りませんよ。

sikimori
質問者

お礼

回答、そして忠告ありがとうございます。 失敗例を元に、もう一度プログラムを見直してみます。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.3

単にプログラムミスの可能性が大ですよね^^ ふーん、そうなのか。。。仕様で、構造体のメンバの個数に最低保証数みたいなものを規定してあるのというのは、初めて知りました。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★アドバイス >構造体のメンバが例えば10個とかあったりしたら、 >何かプログラムに異常が起きたりするものでしょうか?  ↑  どんな異常が起きますか?  メモリが足りていれば問題はないと思います。 >本来入っているはずの数値(文字列)が、微妙にでたらめなものに変わってしまいます。 >(実際に起きたのが、int aの値は10なのに、46543とか。 >char name[20] = "ジタン" が、"ジタnp"とか)  ↑  構造体データをちゃんと初期化していますか? >たまに、こういったことがプログラムを組んでいると起こるので、 >何が起こっているのか分かる方、御教授お願いします。  ↑  構造体の扱い方が正しくないのでは?  これぐらいしか分かりません。 ・その他、構造体をファイルに保存してそこから読み込むときに位置がずれている事はありませんか?  また構造体の境界(パディング)を変更してコンパイルしたのにファイル内容は変更前のままとか?  構造体とか、その操作する処理を見ないと分かりませんね。  いろいろと補足して下さい。 ・以上。

sikimori
質問者

補足

回答ありがとうございます。 長くなりそうなので、簡単に補足させていただきます。分割コンパイルです。 /*-----myhead.h-----*/ typedef struct status{ char name[20]; int a,b,c,st[4]; }Status; void human(status *p); /*-----main.c-----*/ Status dt[5] = {{"人物A",10,20,30,{0,0,0,0},~{"人物E",10,20,30,{0,0,0,0}}}; int i,j; for(i=0;i<5;i++){ printf("%-10s %d %d",(p+i)->name,(p+i)->a,(p+i)->b); for(j=0;j<4;j++) printf("%d ",(p+i)->st[j]); printf("\n"); } //初期化後に、別関数に渡す human(dt); for(i=0;i<5;i++){ printf("%-10s %d %d",(p+i)->name,(p+i)->a,(p+i)->b); for(j=0;j<4;j++) printf("%d ",(p+i)->st[j]); printf("\n"); } //この表示するときに、値がでたらめになっていることがある /*-----human.c-----*/ void human(status *p){ /*この関数でメンバの値(name以外)を変化させる処理を行っている*/ }

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

構造体のメンバの数ですが、最も制約の厳しいC90でも、少なくとも127個までは保証されます。 というわけで、今回の不具合は構造体のメンバ数とは関係ないと思います。ただし、処理系のバグであれば、この限りではありません。

関連するQ&A