• ベストアンサー

構造体メンバの個数

気になって質問させていただいたのですが、構造体のメンバが例えば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

  • 構造体メンバ及び、strncpy()について

    /* 構造体のメンバを char name[30]; にした時は実行できますが、char *name; としたときはプログラムを実行できません。 コンパイルエラーはともに出ないのですが、strncpy();の使い方が間違っているのか、先に構造体側でメモリサイズを確保しないと、使えないのか? メンバをポインタで持たせた構造体を初期化する関数の作り方を教えてください。 よろしくお願いします。 */ #include <stdio.h> #include <string.h> typedef struct{ char *name; int no; }ST; void set_name(ST *st, char *name, int no); int main(void) { ST st; set_name(&st, "テスト", 1); printf("%s No%d\n", st.name, st.no); return 0; } void set_name(ST *st, char *name, int no) { strncpy(st->name, name, 30); st->no=no; }

  • 構造体で・・・・

    構造体は配列を使用せずメモリ領域を獲得する関数を使用すること、 *構造体内部のメンバ名には配列を用いて良い。  という、条件があるのですが場合はどのようにすればよろしいでしょうか? どなたか教えてください。 構造体は以下のようになってます。 /*構造体の定義*/ struct seiseki{   char name[20];   int eig;   int suu;   int kok;   char rank[3]; };

  • 構造体について

    凄く初歩的な質問で申し訳ありませんが… 入門書の構造体のところで 以下のようなプログラムの例がありました。 #include <stdio.h> struct seiseki { /* 構造体の宣言 */ int no; char name[20]; double average; }; int main(void) { int i; struct seiseki seito1, seito2[20]; /* 構造体変数と構造体配列の宣言 */ >char name[20] というのは、NAMEの領域を20文字 確保すると言うことですよね? >struct seiseki seito1, seito2[20] ここの箇所が分からないのですが seito2[20]の20というのは どうして20なのですか? NAMEだけではないので もっと大きな数字になるような気がするのですが… またseito1の方は どうして数字が何もないんですか? 考え違いをしているところを ご指摘して頂ければ幸いです。

  • 異なる構造体のデータのコピー

    (1)で受け取った構造体のメンバのデータを (2)の構造体のメンバにコピーしたいと考えています。 (1) typedef struct _recvData{ int data01; int data02; char data03; char data 04; char data05; char data 06; char data07; char data08; char data09; char data10; char array01[16]; char array02[16]; } recvData; (2) typedef struct _sendData{ int header; int data01; int data02; char data03; char data 04; char data05; char data 06; char data07; char data08; char data09; char data10; int array01[4]; int array02[4]; } sendData; そこで2点ほどおしえていただきたく、お願い致します。 (1)構造体が微妙に異なるため、各メンバ変数に値をそれぞれ代入していくしか方法がないのでしょうか? (2)array01, array02はデータの型が異なる場合、データのコピーはどのようにしたらよいでしょうか?

  • 文字列配列をメンバにもつ構造体の,メモリ動的確保

    下に同様の質問があるのですが,やはり理解できません. 文字列配列をメンバにもつ構造体の,メモリを動的に確保をしたいのですが,うまくいきません. 具体的には以下のようです. 正しくはどのようにすればよいでしょうか.よろしくお願いします. typedef struct { char **boy; char **girl; } Name_class; int init_name_class(Name_class name_class, int n_boy, int n_girl) { int i; name_class.boy = (char**) malloc( n_boy * sizeof(char**) ); for(i=0; i<n_boy; i++) name_class.boy[i] = (char*) malloc( 32 * sizeof(char*) ); name_class.girl = (char**) malloc( n_girl * sizeof(char**) ); for(i=0; i<n_girl; i++) name_class.girl[i] = (char*) malloc( 32 * sizeof(char*) ); } main(int argc, char *argv[]) { int i, j, n_boy=3, n_girl=2; Name_class name_class; init_name_class(name_class, n_boy, n_girl); name_class.boy[0] = "yukio"; name_class.boy[1] = "hideaki"; name_class.boy[2] = "mitsuru"; name_class.girl[0] = "youko"; name_class.girl[1] = "chiharu"; printf("%s, %s, %s, %s, %s\n", name_class.boy[0], name_class.boy[1], name_class.boy[2], name_class.girl[0], name_class.girl[1]); }

  • C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成して

    C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成しています。 一応目的の動作はするのですが、プログラミングとして正しいか教えて頂ければと 思います。 <test.c> int main() { /* ---------------------------------------- */ /* 構造体のメンバ(NULL保障無し)がNULLか */ /* 比較するサンプル */ /* ---------------------------------------- */ char buf[50]; /* サンプル構造体 */ struct ST_test { int cd; char name[10]; int no; }; struct ST_test st_test; /* 構造体定義 */ memset(&st_test,0x00,sizeof(st_test)); /* 構造体初期化 */ memset(&buf[0],0x00,sizeof(buf)); /* 構造体初期化 */ /* 構造体に値セット */ st_test.cd = 12; memcpy(&st_test.name[0],"aabbccddee",sizeof(st_test.name)); st_test.no = 999; /* NULL判定 */ if(*st_test.name == 0x00) { printf("NULLです\n"); } else { printf("NULLではないです\n"); } return (0); }

  • [C] 構造体メンバーのカンマ区切り出力

    構造体メンバーのカンマ区切り出力をしたいと思っています。 たとえば struct XXX { char name[20]; char address[40]; char tel[12]; ... 100メンバーくらいある } のような構造体があったとします。 printf("%s,%s,%s\n", s_ptr->name, s_ptr->address, s_ptr->tel); などのようにメンバー名(変数名)を参照せずに、構造体のメンバーへのポインタを順次取得しループして出力するなどして、実現することは可能でしょうか?

  • 構造体のメンバへのアクセスについて

    お世話になります。 構造体testがあり そのメンバにchar a1[10],a2[20]・・・a100[20]まであるとします。 (配列サイズは不定) このときtest.an (nは任意の数値)にアクセスしたいのですが どう記述したらいいでしょうか? どなたかご指南お願いします。

  • ファイルから読みこんで構造体に格納する、

    shohinというファイルに RX-100 odango_tsumeawase 3000という のが 五行ならんでいるのですが、 これを読み込んで struct shohin{ char code[10]: char name[40]; int price; } にファイルから読みこんで構造体配列に 格納したいのですが、構造体配列に格納する やりかたがわかりません。 構造体配列は struct shohin list[];というのを宣言しています。 ファイルから一行読み込んで fprintf()を使おうと思うのですが、 それはできますか? メンバ毎に格納したいのですが、 それがわかりません お願いします。

  • C言語の文字列を含んだ構造体

    下記のサイトに構造体のことが書かれています。 http://www.isl.ne.jp/pcsp/beginC/C_Language_14.html その中の (3)構造体の初期化 の記述で  //構造体の型宣言  struct student{   int no; // 学籍番号   char name[256]; // 氏名   int year; // 学年   char student_class[256]; // クラス  }; と書かれています。 次の(4)構造体のデータ参照では、  //構造体の型宣言  struct OLD{   int no; //番号   char *name; //名前   int s_year; //年   char s_class; //クラス  }; と書かれています。 ここで質問です。 前者の名前は char name[256] ですが、 後者の名前は char *name になっています。 name[256] と *name では何が違うのでしょうか? どういうときに使い分けるのでしょうか?