• ベストアンサー

構造体メンバの個数

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

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

★似たものを作ってみました。 >実は、No16さん以降、ソースを追加したり修正しているうちに、文字化けやバグが無くなりました(汗)  ↑  これ本当に直った?不思議ですね。たまたま文字化けしなくなった気が…。 ・私も『戦闘シミュレーション』を作ってみました。→sikimori さんのソースを元に。  main() 関数を複数のサブ関数に分割してみました。今後の参考にしてみて下さい。  ※1つのソースで作成しました。→前編、後編で貼り付けておく。 前編: #include <time.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> // 構造体 typedef struct Status {  char name[ 20 ]; // キャラクタ名  int hp;   // HP量  int mp;   // MP量  int st[ 4 ];  // 特殊状態(毒,沈黙,暗闇,混乱) } status; // 記号定数 #define MAX_ENEMY  (sizeof(Enemy) / sizeof(status)) #define MAX_MEMBER  (sizeof(Member) / sizeof(status)) // マクロ関数 #define RAND(max,ofs) ((rand() % (max)) + (ofs)) // 関数のプロトタイプ宣言 extern void dispStatus( void ); extern int checkEnemy( void ); extern int checkMember( void ); extern int checkGameOver( int *members ); extern int attackMember( int members ); extern int attackEnemy( void ); extern void chaAB( status *member, status *enemy ); extern void chaCD( status *member, status *enemy ); // 敵キャラのデータ extern status Enemy[ 1 ] = {  "human", 25000, 9999, 0, 0, 0, 0, }; // 味方キャラのデータ extern status Member[ 4 ] = {  "人物A", 6000, 100, 0, 0, 0, 0,  "人物B", 4000, 300, 0, 0, 0, 0,  "人物C", 4000, 250, 0, 0, 0, 0,  "人物D", 6500, 200, 0, 0, 0, 0, }; // 戦闘シミュレーション int main( void ) {  // 生き残り人数  int members;  // 初期化  srand( (unsigned)time(NULL) );  printf( "/*-------------戦闘開始!!-------------*/\n\n" );  // 最初の1回だけ。味方or敵(0:先手,1:後手)  if ( RAND(2,0) == 0 ){  // 味方が先手   while ( !checkGameOver(&members) ){    if ( attackMember(members) ){  // 味方の攻撃     if ( attackEnemy() ){   // 敵の攻撃      Sleep( 2000 );      system( "cls" );     }    }   }  }  else{      // 敵が先手   while ( !checkGameOver(&members) ){    if ( attackEnemy() ){    // 敵の攻撃     if ( attackMember(members) ){ // 味方の攻撃      Sleep( 2000 );      system( "cls" );     }    }   }  }  return 0; } // 敵,味方ステータスの表示 static void dispStatusOne( status *data ) {  static const char *msg[] = {   "毒",   "沈黙",   "暗闇",   "混乱",  }; int i, flag = 0;    // 名前,HP,MPの表示  printf( "%-10s: HP = %6d MP = %4d 状態 :", data->name, data->hp, data->mp );  // 状態の表示  if ( data->hp == 0 ){   printf( "死亡\n" );   return;  }  for ( i = 0 ; i < 4 ; i++ ){   if ( data->st[i] ){    if ( flag ){     printf( " " );    }    printf( msg[i] ); // 毒,沈黙,暗闇,混乱の表示    flag = 1;   }  }  if ( flag == 0 ){   printf( "なし" );  }  printf( "\n" ); } // 敵,味方ステータスの表示 extern void dispStatus( void ) {  int i;    printf( "/*-----------味方のステータス---------*/\n" );  for ( i = 0 ; i < MAX_MEMBER ; i++ ){   dispStatusOne( Member + i );  }  printf( "/*-------------敵のステータス---------*/\n" );  for ( i = 0 ; i < MAX_ENEMY ; i++ ){   dispStatusOne( Enemy + i );  }  printf( "/*------------------------------------*/\n" );  printf( "\n" ); } // 敵のHPをチェック extern int checkEnemy( void ) {  return (Enemy[0].hp > 0) ? 1 : 0;  // 1:敵生きている 0:敵死す } //味方のHPをチェック extern int checkMember( void ) {  int i;    for ( i = 0 ; i < MAX_MEMBER ; i++ ){   if ( Member[i].hp > 0 ){    return 1;   }  }  return 0;  // 全滅 } // ゲームオーバーのチェック extern int checkGameOver( int *members ) {  int i, count = 0;    if ( checkEnemy() == 0 ){   dispStatus();   printf( "%sを倒しました!!\n", Enemy[0].name );   return 1; // 勝利!  }  if ( checkMember() == 0 ){   dispStatus();   printf( "/*----------ゲームオーバーです----------*/\n" );   return 1; // 全滅!  }  for ( i = 0 ; i < MAX_MEMBER ; i++ ){   if ( Member[i].hp > 0 ){    count++;   }  }  *members = count;  return 0; }

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

 enum human_t { Ahuman = 0, Bhuman, ..., Zhuman, humanNum }; か^^

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

ちらっと眺めただけで、プログラムを読んでないし、デバッグと直接関係ないですが。。茶々入れてるだけかと思われるならゴメンナサイ^^; 数字をそのまま使うより、  enum human_t { Ahuman, Bhuman, ... }; なんか定義して、列挙にしておいたほうがわかりやすいんじゃないですか? 配列の添え字として使う場合は、  enum human_t { Ahuman = 0, Bhuman, ..., Zhuman, humanNum = Zhuman }; などとして、0 を明示しておいたり、長さを別に定義しておいたり。。 あと、C++コンパイラが使えて、C99の拡張機能を使っていないなら、C++コンパイラにかけてみるのもプログラムチェックに役立つと思いますよ(文字サイズなどちょっとした違いが CとC++にはありますが)。

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

★訂正。 ・check[] 配列のチェックは  if ( check[turn-1] ){   printf( "/*-----%sのターンは終了しています-----*/\n", dt[turn-1].name );  }  else switch ( turn ){   case 1: chaAB( &dt[0], &dt[4] ); printf( … ); break;   case 2: chaAB( &dt[1], &dt[4] ); printf( … ); break;   case 3: chaCD( &dt[2], &dt[4] ); printf( … ); break;   case 4: chaCD( &dt[3], &dt[4] ); printf( … ); break;   default:break;  }  でした。  for文で4回ifチェックしなくても良かった。 ・以上。

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

★いろいろと怪しい箇所(疑問)が見つかった。 ・(1)for ( j = 0 ; j < 4 ; j++ ) if( dt[j].hp == 0 ) flg2--;//死んだキャラがいたらflg2--。   この処理は   flg2=4 してから (hp == 0) なら flg2-- よりも   flg2=0 してから (hp > 0) なら flg2++ の方が分かりやすくないか。   for ( flg2 = j = 0 ; j < 4 ; j++ ) if ( dt[j].hp > 0 ) flg2++;  (2)変数 i と check[ i++ ] = turn; の部分がきっとずれるかも。   ここのロジックが変なので chaA()~chaD() 関数が正しく呼ばれていないと思う。   よって選択した人物とは違う人物関数が処理される。   そして『MPが足りない』となる。  (3)human() 関数で人物A~人物Dの4人に対して同じダメージで攻撃しています。   この動作で良いのですか?  (4)chaA()、chaB() が構造体データ以外はすべて同じなら1つの関数に出来ます。   chaC()、chaD() も構造体データ以外はすべて同じなら1つの関数に出来ます。   処理する構造体データの部分だけが違うのなら次の2つに出来ます。   void chaAB( status *member, status *enemy );   void chaCD( status *member, status *enemy );   このような引数にすれば   switch ( turn ){    case 1: chaAB( &dt[0], &dt[4] ); printf( … ); break;    case 2: chaAB( &dt[1], &dt[4] ); printf( … ); break;    case 3: chaCD( &dt[2], &dt[4] ); printf( … ); break;    case 4: chaCD( &dt[3], &dt[4] ); printf( … ); break;    default:break;   }   と出来ます。  (5)human() 関数で戦闘するたびに毒、沈黙、暗闇、混乱の状態がセット/リセットします。   普通は一度『毒』状態になったら『毒消し』しない限りはずっと『毒』状態になる気が…。   なので代入ではなくてビットORすれば良い。   (p+i)->st_ab[0] |= s1 % 2;   (p+i)->st_ab[1] |= s2 % 2;   (p+i)->st_ab[2] |= s3 % 2;   (p+i)->st_ab[3] |= s4 % 2;   とします。→『|=』を使う。 ・上記の5つ以外にも気になる点がゴロゴロあります。  データは  人物A~人物Dまでを status member[4]; として定義して  humanという敵だけを status enemy[1]; として定義した方が分かりやすいですよ。  また構造体データ member、enemy をグローバル変数にして main() 関数の処理を  複数のサブ関数に分けたほうが見やすくなります。  これによりバグになりにくくなる。 ・下に main() 関数と分けたほうが良さそうな関数のプロトタイプ宣言を載せておきます。  作り変えるときの参考にして下さい。 // 記号定数 #define MAX_ENEMY  (sizeof(Enemy) / sizeof(status)) #define MAX_MEMBER  (sizeof(Member) / sizeof(status)) // マクロ関数 #define RAND(max,ofs) ((rand() % (max)) + (ofs)) // 関数のプロトタイプ宣言 extern void dispStatus( void ); // ステータスの表示 extern int attackEnemy( void ); // 敵の攻撃(戻り値:checkEnemy()の値) extern int attackMember( int members ); // 味方の攻撃(戻り値:checkMember()の値) extern int checkEnemy( void ); // 敵のHP=0をチェック(1=生きている,0=倒れた) extern int checkMember( void ); // 味方4人のHP=0をチェック(1=戦える,0=全滅) extern int checkGameOver( int *members ); // ゲームオーバーをチェック(1=GameOver,0=戦闘続行) extern void chaA( status *member, status *enemy ); // 人物Aの攻撃 extern void chaB( status *member, status *enemy ); // 人物Bの攻撃 extern void chaC( status *member, status *enemy ); // 人物Cの攻撃 extern void chaD( status *member, status *enemy ); // 人物Dの攻撃 // 敵キャラのデータ extern status Enemy[ 1 ] = {  "human", 100000, 9999, 0, 0, 0, 0, }; // 味方キャラのデータ extern status Member[ 4 ] = {  "人物A", 6000, 100, 0, 0, 0, 0,  "人物B", 4000, 300, 0, 0, 0, 0,  "人物C", 4000, 250, 0, 0, 0, 0,  "人物D", 6500, 200, 0, 0, 0, 0, }; // 戦闘シミュレーション int main( void ) {  // 生き残り人数  int members;  // 初期化  srand( (unsigned)time(NULL) );  printf( "/*-------------戦闘開始!!-------------*/\n" );  // 最初の1回だけ。味方or敵(0:先手,1:後手)  if ( RAND(2,0) == 0 ){  // 味方が先手   while ( !checkGameOver(&members) ){    dispStatus();      // ステータスの表示    if ( attackMember(members) ){  // 味方の攻撃     if ( attackEnemy() ){   // 敵の攻撃      Sleep( 2000 );      system( "cls" );     }    }   }  }  else{      // 敵が先手   while ( !checkGameOver(&members) ){    dispStatus();      // ステータスの表示    if ( attackEnemy() ){    // 敵の攻撃     if ( attackMember(members) ){ // 味方の攻撃      Sleep( 2000 );      system( "cls" );     }    }   }  }  return 0; } 最後に: ・今回の原因は check[] 配列のロジックが正しくないようです。  『check[ i++ ] = turn;』ではなくて『check[ turn - 1 ] = 1;』にした方が良いでしょう。  それからチェックは  for ( flg = j = 0 ; j < 4 ; j++ ){   if ( check[j] ){    printf( "/*-----%sのターンは終了しています-----*/\n", dt[turn-1].name );    flg = 1;    break;   }  }  とします。flg は変なところで初期化しないようにして下さい。見づらいよ。 ・check[] 配列のロジックを直せばおかしな構造体データを操作しなくなります。  これにより >(1)dtを初期化しているのに、魔法を使おうとすると、mpが足りないと出る >(2)お互いにダメージを与えているのに敵だけhpが減らない  の2つが解決するはずです。 ・以上。サブ関数に分けて作り直した方がデバッグするより早い気がします。

sikimori
質問者

お礼

まず疑問点について私がいうのも変なのですが、回答します。 (1)これは先に思いついた方のやり方を書いてました。 (2)このプログラムで、状態異常をまだ付けていないソースがあったのですが、その時実行した時には何もバクや文字化けなく動きました。 (3)一応全体攻撃として考えているので^^ (4)確かにchaAとchaB、chaCとchaDは殆ど同じ処理内容ですが、まだ追加処理を入れるつもりだったので、一人一人別々に作っていたのですm(_ _)m (5)状態異常のときの処理は、まだ手付かずなので・・・。ごめんなさい。 ビットOR、これは使ったことがなかったので参考にさせていただきます。 実は、No16さん以降、ソースを追加したり修正しているうちに、文字化けやバグが無くなりました(汗)

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

部分部分ばらばらに貼り付けずに、全部一緒に貼り付けちゃえばいいのに。。そんなに長くなさそうだし。 そのほうが、見てくれる方々も見やすいし、まぎれがなくていいでしょ^^

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

★アドバイス >基本的に文字化けしたり、値か変わったりするのは、ダメージを受けたあとになっているようです。 >本題ですが、nameのNULL文字以降調べようとしたのですが、調べ方が分からなくて;;  ↑  次のダンプ関数を作成して下さい。  そしてダンプ表示したい場所で呼び出して下さい。 // 構造体の16進ダンプ表示 void printDump( status data[], size_t max, const char msg[] ) {  FILE *fp;    if ( (fp = fopen("dump16.txt","a")) != NULL ){   fprintf( fp, "---- ↓[%s] ----\n", msg );      for ( size_t n = 0 ; n < max ; n++ ){    unsigned char *p = (unsigned char *)&data[n];    unsigned char *end = (unsigned char *)&data[n + 1];        fprintf( fp, "\n★status dt[%d]:%s\n", n, data[n].name );    for ( int y = 0x00 ; p < end ; y += 0x10 ){     fprintf( fp, "%08X: ", y );          for ( int x = 0 ; (p < end) && (x < 0x10) ; x++ ){      if ( x == 0x07 ){       fprintf( fp, "%02X-", *p++ );      }      else{       fprintf( fp, "%02X ", *p++ );      }     }     fprintf( fp, "\n" );    }   }   fprintf( fp, "---- ↑[%s] ----\n\n", msg );   fclose( fp );  } } // 使い方 printDump( dt, 5, "test(1)" ); printDump( dt, 5, "test(2)" ); ←ダンプ時のメッセージを指定可能 その他: ・上記の printDump() 関数をソースに組み込んで下さい。  インデント部が全角空白文字なのでエディタでタブ文字に一括変換して下さい。  それから dump16.txt というファイルに追加書き込みされていきます。  メモ帳などで開いて確認して下さい。 ・あと else 部分のソースもすべて貼り付けてくれますか。  その他 human()、chaA()、chaB()、chaC()、chaD() 関数のソースもすべて貼り付けて欲しいです。  ANo.19 の回答への補足、ANo.19 の回答へのお礼、  ANo.18 の回答への補足、ANo.18 の回答へのお礼  の順に else 部分、human()、chaA()、chaB()、chaC()、chaD() 関数を貼り付けて。 ・以上。

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

あっ、何度も申し訳ない! 単なる書き間違いでした。C言語で書いてますよ。 x0xfじゃなくて0x0fです。 すごい打ち間違いだな自分。

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

あっ、さらに修正です。たびたび申し訳ない!。 for( int di=0 ; di<5 ; di++ ) { unsigned char *pDump = (unsigned char*)&dt[di]; printf( "--- dump dt[%d] struct ---",di ); for( int dj=0 ; dj<sizeof(status) ; dj++,pDump++ ) { if( (dj&x0xf)==0 ) printf("\n%04X",dj); printf( "%02X ", *pDump ); } printf("\n"); } printf( "--- dump dt end ---\n" );

sikimori
質問者

補足

これはC++で書かれていますか?残念ながら私Cで書いてまして・・・。 取り合えず、ファイル名を「.cpp」に変えてやってみましたが、 エラー E2451 main.cpp 25: 未定義のシンボル x0xf(関数 main() ) っていうのが発生しました(汗)

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

ダンプは、それでOKです。俗にダンプというとメモリ内容を16進数で表示させたものをいいます。 でも、ごめんなさい、ちょっと見づらかったですね(^^ゞ 今後のことを考えて修正しました。 for( int di=0 ; di<5 ; di++ ) { unsigned char *pDump = (unsigned char*)&dt[di]; printf( "--- dump dt[%d] struct ---\n",di ); for( int dj=0 ; dj<sizeof(status) ; dj++,pDump++ ) { printf( "%02X ", *pDump ); if( (dj&x0xf)==0xf ) printf("\n"); } printf("\n"); } printf( "--- dump dt end ---\n" ); これを正常な場合と異常な場合の2パターンお願いします。

関連する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 では何が違うのでしょうか? どういうときに使い分けるのでしょうか?

専門家に質問してみよう