構造体の値がうまく表示されません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ひこまろ

構造体の値がうまく表示されません

#1

投稿記事 by ひこまろ » 4年前

C言語歴3ヶ月ほどの初心者です。

画像ファイルを作成する関数を製作していたところ、
C言語の構造体について分からないことが発生しため質問させていただきました。

1. main関数内で構造体のポインタを宣言して、そのポインタを関数に渡す。
2. ポインタを渡された関数内でそのポインタが示す構造体に値を代入する。
3. さらに別の 2. の関数で処理された構造体の値を表示する。

というアルゴリズムのソースコードです。この処理を実行すると 3. で構造体の値が適切に表示されません。
このソースコードのmain関数内を書き換えることなく構造体の値を適切に表示する方法を教えてください。

コード:

#include<stdio.h>
#include<stddef.h>
#include<stdlib.h>
#include<string.h>

struct GAME {
	char *name;	/* プレーヤー名 */
	int score;	/* スコア */
	int max;	/* 最高スコア */
};

int main(void) {
	struct GAME *shooting;

	func1(shooting,"Hiroshi");
	func2(shooting);
	return 0;
}

int func1(struct GAME *game,const char *name) {

	game=(struct GAME *)malloc(sizeof(struct GAME));	/* 構造体ポインタが示す構造体を実体化する */

	game->name=malloc( sizeof(char) * strlen(name) +1 );

	strcpy(game->name,name);

	game->score=100;
	game->max=200;

	return 0;
}

int func2(struct GAME *game) {

	puts(game->name);
	printf("Score:%d\n",game->score);
	printf("Max Score:%d\n",game->max);

	return 0;
}
stdio.h におけるファイル操作の関数群では main関数内で FILE 構造体のポインタを宣言して、fopen関数やfputs関数などの引数として
FILE構造体を扱えるので、このソースコードのmain関数内の処理を上記のように記述しました。

コンパイル&実行環境はLinuxのgccです。コンパイルエラーはありません。よろしくお願いします

アバター
へにっくす
記事: 630
登録日時: 8年前
住所: 東京都

Re: 構造体の値がうまく表示されません

#2

投稿記事 by へにっくす » 4年前

ひこまろ さんが書きました:stdio.h におけるファイル操作の関数群では main関数内で FILE 構造体のポインタを宣言して、fopen関数やfputs関数などの引数として
FILE構造体を扱えるので、このソースコードのmain関数内の処理を上記のように記述しました。
fopenの戻り値がFILE*であるように、
func1も戻り値をintでなくstruct GAME*にすればよいです。
※残念ながらmain関数を変えることなく、というのは無理ですね。

コード:

#include<stdio.h>
#include<stddef.h>
#include<stdlib.h>
#include<string.h>
 
struct GAME {
    char *name; /* プレーヤー名 */
    int score;  /* スコア */
    int max;    /* 最高スコア */
};

/* プロトタイプ宣言 */
struct GAME * func1(const char *name); 
int func2(struct GAME *game);
void func3(struct GAME *game); // 追加
 
int main(void) {
    struct GAME *shooting;
 
    shooting = func1("Hiroshi"); // 変更
    func2(shooting);
    func3(shooting); // 追加:mallocしたらfreeは必ずする
    return 0;
}
 
// 変更
struct GAME * func1(const char *name) {
    struct GAME *game=(struct GAME *)malloc(sizeof(struct GAME));    /* 構造体ポインタが示す構造体を実体化する */
 
    game->name=malloc( sizeof(char) * strlen(name) +1 );
 
    strcpy(game->name,name);
 
    game->score=100;
    game->max=200;
 
    return game; // 変更
}
 
int func2(struct GAME *game) {
 
    puts(game->name);
    printf("Score:%d\n",game->score);
    printf("Max Score:%d\n",game->max);
 
    return 0;
}

// 追加
void func3(struct GAME *game) {
    free(game->name);
    free(game);
}
【編集:3/25 5:00】func3を追加
最後に編集したユーザー へにっくす on 2016年3月25日(金) 04:58 [ 編集 1 回目 ]
written by へにっくす

アバター
みけCAT
記事: 6273
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 構造体の値がうまく表示されません

#3

投稿記事 by みけCAT » 4年前

ひこまろ さんが書きました: stdio.h におけるファイル操作の関数群では main関数内で FILE 構造体のポインタを宣言して、fopen関数やfputs関数などの引数として
FILE構造体を扱えるので、このソースコードのmain関数内の処理を上記のように記述しました。
C言語の標準ライブラリのfopen関数では、引数としてFILE構造体もそれへのポインタも扱えません。
ひこまろ さんが書きました:このソースコードのmain関数内を書き換えることなく構造体の値を適切に表示する方法を教えてください。
このソースコードは適当な場所に保存して、新しいソースコードを書き、コンパイルし、実行するのがいいでしょう。
なぜなら、このソースコードのmain関数内で宣言された唯一のポインタであるshootingは未初期化の自動変数なので、値は不定であり、
2の「そのポインタが示す構造体」がナンセンス (未初期化の自動変数の値を使うとundefined behaviorになる)であるからです。

新しいソースコードでは、
  • ポインタを有効な領域で初期化する
  • 引数を無駄にぶっ壊したり無駄な領域を確保したりせず、素直にアルゴリズムとして書かれたことをやる
といいでしょう。

実装例

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct game_t {
	char *name;
	int score;
	int max;
};

void assign(struct game_t* game, const char *name);
void display(const struct game_t* game);

int main(void) {
	struct game_t g;
	/* 1. main関数内で構造体のポインタを宣言して、 */
	struct game_t *pointer_to_structure = &g;
	/* そのポインタを関数に渡す。 */
	assign(pointer_to_structure, "Hoge");
	display(&g);

	free(g.name);
	return 0;
}

void assign(struct game_t* game, const char *name) {
	/* 2. ポインタを渡された関数内でそのポインタが示す構造体に値を代入する。 */
	game->name = malloc(strlen(name) + 1);
	if (game->name == NULL) {
		perror("malloc");
		exit(1);
	}
	strcpy(game->name, name);
	game->score = 123;
	game->max = 456;
}

void display(const struct game_t* game) {
	/* 2. の関数で処理された構造体の値を表示する。 */
	printf("name = %s\nscore = %d\nmax = %d\n", game->name, game->score, game->max);
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る