C言語を学習中。
ポインタを学習後、今度は構造体について学習している。
scanf()
関数でユーザー入力を受け付けて構造体のメンバーに代入するという処理をやりたいのだけど、複雑になってきてよくわからなくなってきたので、一通り整理する。
ポイント整理
(1)構造体の宣言
何はともあれ、最初に宣言しておかなければ構造体を使えない。
グローバル領域で宣言しておく。
// 構造体の宣言 struct STATUS{ char name[21]; int hp; int ap; };
(2)構造体を定義・初期化してprintf()で出力する
構造体変数の定義と初期化を行い、各メンバーへアクセスしてprintf()
出力するやり方。
構造体変数を使用したい関数内で記述する。
// 構造体の定義・初期化 struct STATUS yuusha = {"ゆうしゃ", 8, 2}; // 構造体yuushaのメンバーをprintfで出力 // 出力結果 -> ゆうしゃ:最大HP = 8, 攻撃力 = 2 printf("%s:最大HP = %d, 攻撃力 = %d\n", yuusha.name, yuusha.hp, yuusha.ap);
(3)定義・初期化した構造体の値を書き換える
構造体変数の定義と初期化を行い、各メンバーのにアクセスして値を再代入するやり方。
int型はそのまま代入が可能。
string型はstrcpy()
を使うためstring.h
のインクルードが必要。#include <string.h>
の一文をグローバル領域の先頭に記述する。
// 構造体の定義・初期化 struct STATUS monster = {"モンスター", 10, 1}; // 構造体(初期化済み)の各メンバーへ個別に再代入 strcpy(monster.name, "スライム"); // string.hのインクルードが必要 monster.hp = 3; monster.ap = 1; // 構造体monsterのメンバーをprintfで出力 // 出力結果 -> スライム:最大HP = 3, 攻撃力 = 1 printf("%s:最大HP = %d, 攻撃力 = %d\n", monster.name, monster.hp, monster.ap);
(4)構造体(定義のみ)の各メンバーに代入する
定義のみで初期化していない場合でも、やり方は先程の再代入と変わらない。
こちらもstring型はstrcpy()
を使うためstring.h
のインクルードが必要。
// 構造体の定義 struct STATUS enemy; // 構造体(定義のみ)enemyの各メンバーへ個別に代入 strcpy(enemy.name, "カンダタ"); // string.hのインクルードが必要 enemy.hp = 18; enemy.ap = 1; // 構造体enemyのメンバーをprintfで出力 // 出力結果 -> カンダタ:最大HP = 18, 攻撃力 = 1 printf("%s:最大HP = %d, 攻撃力 = %d\n", enemy.name, enemy.hp, enemy.ap);
(5)構造体の各メンバーにscanf()関数で入力を受け付けて代入する
今回目標としてた処理。
前提として、scanf()
はユーザー入力を受け付けて指定した変数に格納する、というような事が行われる。
その時にscanf()
関数には変数のアドレスを渡してやる必要がある。
// 構造体の定義 struct STATUS member; // 構造体の各メンバーへscanfで代入 printf("名前を入力 > "); scanf("%s", member.name); // 第2引数はアドレスを指定。str型配列は変数名そのものがアドレスを示す printf("最大HPを入力 > "); scanf("%d", &member.hp); // 第2引数はアドレスを指定。int型は変数名にアドレス演算子&をつける printf("攻撃力を入力 > "); scanf("%d", &member.ap); // 構造体memberのメンバーをprintfで出力 // 出力結果 -> (ユーザー入力値) printf("%s:最大HP = %d, 攻撃力 = %d\n", member.name, member.hp, member.ap);
サンプルコード
/* 構造体の宣言、定義・初期化 構造体のメンバーへアクセスしてprintfで表示 構造体のメンバー(int, char)にscanfで代入 */ #include <stdio.h> #include <string.h> // 構造体の宣言 struct STATUS{ char name[21]; int hp; int ap; }; int main() { // 構造体の定義・初期化 struct STATUS yuusha = {"ゆうしゃ", 8, 2}; struct STATUS monster = {"モンスター", 10, 1}; struct STATUS enemy; struct STATUS member; // 構造体yuushaのメンバーをprintfで出力 // 出力結果 -> ゆうしゃ:最大HP = 8, 攻撃力 = 2 printf("%s:最大HP = %d, 攻撃力 = %d\n", yuusha.name, yuusha.hp, yuusha.ap); // 構造体(初期化済み)の各メンバーへ個別に再代入 strcpy(monster.name, "スライム"); // string.hのインクルードが必要 monster.hp = 3; monster.ap = 1; // 構造体monsterのメンバーをprintfで出力 // 出力結果 -> スライム:最大HP = 3, 攻撃力 = 1 printf("%s:最大HP = %d, 攻撃力 = %d\n", monster.name, monster.hp, monster.ap); // 構造体(定義のみ)enemyの各メンバーへ個別に代入 strcpy(enemy.name, "カンダタ"); // string.hのインクルードが必要 enemy.hp = 18; enemy.ap = 1; // 構造体enemyのメンバーをprintfで出力 // 出力結果 -> カンダタ:最大HP = 18, 攻撃力 = 1 printf("%s:最大HP = %d, 攻撃力 = %d\n", enemy.name, enemy.hp, enemy.ap); // 構造体の各メンバーへscanfで代入 printf("名前を入力 > "); scanf("%s", member.name); // 文字列配列は変数名そのものがアドレスを示す printf("最大HPを入力 > "); scanf("%d", &member.hp); printf("攻撃力を入力 > "); scanf("%d", &member.ap); // 構造体senshiのメンバーをprintfで出力 // 出力結果 -> (ユーザー入力値) printf("%s:最大HP = %d, 攻撃力 = %d\n", member.name, member.hp, member.ap); return 0; }