ヘッダファイルの中に構造体が3つ

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

ヘッダファイルの中に構造体が3つ

#1

投稿記事 by 大根おろし » 18年前

課題で3つの構造体を用意し、それにデータを入力、保存するかを選択させる関数を作成しています。
普通に構造体を宣言して格納して表示すればよいのですが、制限がありまして、

・構造体の型は実際にプログラム内で実態定義するのは一つだけ。
・構造体・数値はすべてヘッダファイルに定義すること。
・externは使用しない。

という制限があり、この構造体を3つ使うところに苦戦しています。

とりあえず構造体は関係ない部分だけ作ってみたのですが、ここからどうしていいかわかりません。
おそらくだいぶ間違ってると思うのですがご指導よろしくお願いします。
使用しているソフトはVC++6.0です。
C言語は参考書を見ながら作れるレベルです。
ヘッダファイルの作り方は習ってないのですが、教師に質問したら読めばわかると言われ教えてもらえないまま連休に入ってしまったので手探りなせいでだいぶおかしいと思います。

/* ヘッダファイル */
typedef struct namae
{
	char name[80];
}onamae;

typedef struct data
{
	int nenrei;
	int hgt;
	int wgt;
}sts;

typedef struct ken
{
	char ken[80];
	char si[80];
	char tyou[80];
}syusin;

/* 人間パラメータ設定表示処理 */
void human(void)
{
	onamae profil;
	int no;					/* 入力された処理番号を格納する変数no */

	printf("処理を選択して下さい\n");
	printf("1:情報入力\n2:情報表示");
	scanf("%d", &no);
	switch (no)
	{
	case 1:
		for(j = 1; j <= 4; j++)
		{
			printf("%d人目入力", j);
			printf("名前:");
			scanf("%s", );
			printf("年齢:");
			scanf("%d", );
			printf("身長:");
			scanf("%d", );
			printf("体重:");
			scanf("%d", );
			printf("在住している県:");
			scanf("%s", );
			printf("在住している市:");
			scanf("%s", );
			printf("在住している町:");
			scanf("%s", );

		}
		break;
	case 2:
		for(j = 1; j <= 4; j++)
		{
		}
		break;
	default:
		printf("エラー\n");
	}
	return;
}

しっぽ

Re:ヘッダファイルの中に構造体が3つ

#2

投稿記事 by しっぽ » 18年前

逆質問です。


>課題で3つの構造体を用意し、それにデータを入力、保存するかを選択させる関数を作成しています。
>普通に構造体を宣言して格納して表示すればよいのですが、制限がありまして、

>・構造体の型は実際にプログラム内で実態定義するのは一つだけ。
>・構造体・数値はすべてヘッダファイルに定義すること。
>・externは使用しない。


上記の文章は課題を正確に表現していますか?私にはモヤモヤして、理解できません。

最初の1行から、躓いてしまいます。
「3つの構造体を用意」 3種類の構造体? 実体を3つ? コードは3種類の構造体になってますが、
  3種類と解釈してよいですか?

クイズっぽくて面白そうな課題ですので、正確な間違えようのない表現でお願いします。

あとvoid human(void)は「選択させる関数」とは全く別物の関数です。不正確な表現が一部に
あると全体の表現が疑わしく見えてしまいます。

大根おろし

Re:ヘッダファイルの中に構造体が3つ

#3

投稿記事 by 大根おろし » 18年前

うまく説明できていなくて申し訳ありません。
問題をそのまま引用します。

数種類の処理を行うプログラムを作成してください。
これらの処理は完了しても処理を終了させず、何度も選択して処理を行えるようにすること。

処理1
 数値を10進数で入力し、16進数で出力。
処理2
 半角文字列(アルファベット限定)を入力し、文字列内の小文字を大文字に、大文字を小文字に変換し出力。
処理3
 1~255までの数値を入力し、0xffと論理関・論理和・排他的論理和を行い表示。
処理4

3つの構造体の型を用意しそれぞれに[名前]、[年齢・身長・体重]、[県・市・町]を定義する(4人分)。
それぞれのデータは入力で設定するようにし、入力するか表示するかを選択するメニューを用意して処理を実行する。

特定制限:
構造体の型は3つ用意するが、実際にプログラム内で実態定義を行うのは1種類だけとする。
また、構造体や変数はヘッダファイルにすべて定義し、そのヘッダファイルを読み込んで処理を行うこと。
(プログラム内に直接数値を入れてはいけません。)
externは使用しないこと。(これは口頭での制限)


(pre)
struct AA{
};

struct BB{
};

struct CC{
};

void main()
{
struct CC cc; ←AA、BBは定義してはいけない
}
(/pre)


処理3までは既に出来上がっています。
添付にテキストに貼り付けたソースを載せておきましたので処理1~3とメインの動きはそちらを参照してください。
>あとvoid human(void)は「選択させる関数」とは全く別物の関数です。
これはメインでswich文を使用して関数に飛んで関数内で出力しているためにこういう形式にしています。

よろしくお願いします。

大根おろし

Re:ヘッダファイルの中に構造体が3つ

#4

投稿記事 by 大根おろし » 18年前

試行錯誤した結果ここまで作りました。
しかし、error C2275: 'syusin' : typedef 識別子に、クラス メンバ アクセス演算子 (->) を使用しました。
'syusin' の宣言を確認してください。
というエラーとerror C2059: 構文エラー : 'type'がでてしまい、
どうも入出力どちらも格納先の指定が間違ってるのでは?というところまでは調べられたのですが、
具体的にどう直してよいのかわかりません。
/* ヘッダファイル */
typedef struct namae
{
	char name[3][80];
}onamae;

typedef struct data
{
	int nenrei[3];
	int hgt[3];
	int wgt[3];
}sts;

typedef struct ken
{
	char ken[3][80];
	char si[3][80];
	char tyou[3][80];
	onamae hito;
	sts para;
}syusin;

/* main */
#include <stdio.h>
#include <ctype.h>									/* toupper tulower isupper islower用*/
#include "gwh.h"									/* 人間パラメータ設定表示処理用の自作ヘッダー */

void henkan16(void);								/* 数値16進数変換表示処理 */
void henkanmoji(void);								/* 文字列変換表示処理 */
void suti(void);									/* 数値演算表示処理 */
void human(void);									/* 人間パラメータ設定表示処理 */	

int main()
{
	int i;											/* 処理番号 */

	/* 処理はループさせる */
	while(1)
	{
		printf("処理を選択して下さい\n");
		printf("1:数値16進数変換表示処理\n");
		printf("2:文字列変換表示処理\n");
		printf("3:数値演算表示処理\n");
		printf("4:人間パラメータ設定表示処理\n");
		printf("処理番号:");
		scanf(" %d", &i);
		
		switch(i){
		case 1:
			/* 数値16進数変換表示処理を行う */
			henkan16();
			break;
		case 2:
			/* 文字列変換表示処理を行う */
			henkanmoji();
			break;
		case 3:
			/* 数値演算表示処理を行う */
			suti();
			break;
		case 4:
			/* 人間パラメータ設定表示処理を行う */
			human();
			break;
		default:
			printf("\nエラー\n\n\n\n");
		}
	}
}

/* 数値16進数変換表示処理 */
void henkan16(void)
{
	int atai;										/* 変換したい数値を格納する変数atai */

	printf("数値を入力して下さい:");
	scanf(" %d", &atai);
	printf("\n16進数表示:%x\n\n\n\n", atai);

	return;
}

/* 文字列変換表示処理 */
void henkanmoji(void)
{
	int c;											/* 配列hakoの要素数用の変数c */
	int s;											/* 変換した文字の値を格納する変数s */
	char hako[80];									/* 入力された文字列を格納する変数hako */

	/* 配列hakoに変換する文字列を入力する */
	printf("文字列を入力して下さい\n");
	printf("文字列:");
	scanf("%s", hako);

	/* 80文字分ループし、配列hakoの中の文字列を各々大文字、小文字に変換する。 */
	for(c = 0; c < 80; c++)
	{
		/* 参照した文字が大文字だったとき */
		if(isupper(hako[c]) != 0)
		{
			/* tolowerはint型の値を返すため、int型変数sに格納して出力する */
			s = tolower(hako[c]);
			printf("%c", s);
			
		}
		/* 参照した文字が小文字だったとき */
		else if(islower(hako[c]) != 0)
		{
			/* toupperはint型の値を返すため、int型変数sに格納して出力する */
			s = toupper(hako[c]);
			printf("%c", s);
		}
		/* 参照した文字がアルファベット以外だったとき */
		else
		{
			/* 参照した文字がヌルだった場合は、文字列が終了しているのでループから抜ける */
			if(hako[c] == '\0')
			{
				break;
			}
			/* 参照した文字がアルファベット以外だったときはエラーを出力してループを抜ける */
			printf("\nエラー");
			break;
		}
	}
	printf("\n\n\n");

	return;
}

/* 数値演算表示処理 */
void suti(void)
{
	int su;														/* 入力された値を格納する変数su */

	/* 数値を変数suに入力する */
	printf("数値を入力して下さい\n");
	printf("数値:");
	scanf(" %d", &su);

	/* 入力された値を0x0fで論理関した結果を出力 */
	printf("%d\n\n\n", su & 0x0f);
	/* 入力された値を0x0fで論理和した結果を出力 */
	printf("%d\n\n\n", su | 0x0f);
	/* 入力された値を0x0fで排他的論理和した結果を出力 */
	printf("%d\n\n\n", su ^ 0x0f);

	return;
}

/* 人間パラメータ設定表示処理 */
void human(void)
{
	syusin plofir;
	int j;
	int no;												/* 入力された処理番号を格納する変数no */

	printf("処理を選択して下さい\n");
	printf("1:情報入力\n2:情報表示");
	scanf("%d", &no);
	switch (no)
	{
	case 1:
		for(j = 0; j < 4; j++)
		{
			printf("%d人目入力", j + 1);
			printf("名前:");
			scanf("%s", &syusin.hito.name[j]);
			printf("年齢:");
			scanf("%d", &syusin.para.nenrei[j]);
			printf("身長:");
			scanf("%d", &syusin.para.hgt[j]);
			printf("体重:");
			scanf("%d", &syusin.para.wgt[j]);
			printf("在住している県:");
			scanf("%s", syusin.ken[j]);
			printf("在住している市:");
			scanf("%s", syusin.si[j]);
			printf("在住している町:");
			scanf("%s", syusin.tyou[j]);
			printf("\n\n");

		}
		break;
	case 2:
		for(j = 0; j < 4; j++)
		{
			printf("名前:%s\n", syusin.hito.name[j]);
			printf("年齢:%d\n", syusin.para.nenrei[j]);
			printf("身長:%d\n", syusin.para.hgt[j]);
			printf("体重:%d\n", syusin.para.wgt[j]);
			printf("在住している県:%s\n", syusin.ken[j]);
			printf("在住している市:%s\n", syusin.si[j]);
			printf("在住している町:%s\n\n\n", syusin.tyou[j]);
		}
		break;
	default:
		printf("エラー\n");
	}
	return;
}

miyaza

Re:ヘッダファイルの中に構造体が3つ

#5

投稿記事 by miyaza » 18年前

human()関数のsyusinの部分をplofirに直せばとりあえずsyusinのエラーはなくなると思いますが・・・・・・

miyaza

Re:ヘッダファイルの中に構造体が3つ

#6

投稿記事 by miyaza » 18年前

4人分のデータを入力しなければならないのに構造体を見ると3人分しか入らないようになってます。
配列変数や構造体についてもう一度勉強してみたらどうでしょう。
上のsyusinの話も、typedefを使用して構造体を宣言したときのことが良く分かってないから上のような書き方になってしまったのではないでしょうか

miyaza

Re:ヘッダファイルの中に構造体が3つ

#7

投稿記事 by miyaza » 18年前

連続投稿すみません。

human()関数で入力後main()関数に戻ってますよね。そのときのplofirの扱いがどうなると思いますか?
おそらく入力後表示させようと思っても正しく表示されることは無いでしょう。
ローカル変数は関数の終わりに破棄されます。
そのため表示させようと思っても正しく表示されません。これを回避するにはどうしたらいいでしょう。

大根おろし

Re:ヘッダファイルの中に構造体が3つ

#8

投稿記事 by 大根おろし » 18年前

完全にただの自分のうっかりミスでした。
もっとちゃんとデバッグしていれば対処できたものばかりで質問するまでもなかったですね。
本当にすみませんでした。


>human()関数で入力後main()関数に戻ってますよね。そのときのplofirの扱いがどうなると思いますか?
>おそらく入力後表示させようと思っても正しく表示されることは無いでしょう。
>ローカル変数は関数の終わりに破棄されます。
>そのため表示させようと思っても正しく表示されません。これを回避するにはどうしたらいいでしょう。

最初はグローバル関数にすればいいと考えたのですが、課題の制限にexternが使えないことを思い出して
参考書を見たらstaticがある事を思い出し、それを使用して対処できました。

無事実行することができました。
同じミスをしないように今後も精進していきます。
ありがとうございました。

しっぽ

Re:ヘッダファイルの中に構造体が3つ

#9

投稿記事 by しっぽ » 18年前

課題の原文掲載ありがとうございました。
私には、処理4を出題した意図がさっぱり判りません。
union を使わせたいのかなぁ?それともキャストを多用し汚いコード例を
書いてみろってこと?
出題者より解答が出たら是非教えてください。
//////////////////////////////////
// ヘッダー

#include <stdio.h>

//-------------------------------------------
//(プログラム内に直接数値を入れてはいけません。) 
#define NAME 1
#define DATA 2
#define ADDRESS  3

//-------------------------------------------
// 3つの構造体の型を用意しそれぞれに[名前]、[年齢・身長・体重]、[県・市・町]を定義する(4人分)。 

#define PERSONS  4

typedef struct tagNamae
{
	char name[PERSONS][80];
} Name;

typedef struct tagData
{
	int nenrei[PERSONS];
	int hgt[PERSONS];
	int wgt[PERSONS];
} Data;

typedef struct tagAddress
{
	char ken[PERSONS][80];
	char si[PERSONS][80];
	char tyou[PERSONS][80];
} Address;

union Person
{
	Name name;
	Data data;
	Address address;
};

//-------------------------------------------
// また、構造体や変数はヘッダファイルにすべて定義し、そのヘッダファイルを読み込んで処理を行うこと。 

int flag;

//////////////////////////////////
// 実装
#include <string.h>
#include "test.h"

int main()
{
	union Person person; // 実際にプログラム内で実態定義を行うのは1種類だけとする。 
	flag = NAME; // 標準入力から、名前の入出力を指定されたと仮定。

	switch(flag){
	case NAME:
		strcpy(person.name.name[0], "Mr.A");
		printf(person.name.name[0]);
		break;
	case DATA:
		// 省略
		break;
	case Address:
		// 省略
		break;
	default:
		break;
	}

	return 0;
}

大根おろし

Re:ヘッダファイルの中に構造体が3つ

#10

投稿記事 by 大根おろし » 18年前

>私には、処理4を出題した意図がさっぱり判りません。
>union を使わせたいのかなぁ?それともキャストを多用し汚いコード例を
>書いてみろってこと?
>出題者より解答が出たら是非教えてください。


本日提出したのですが、なんと私の解釈が間違っていて、
処理4は構造体変数を配列にし、ポインタでアドレス渡しして格納するということでした。

つまり

syusin plofir

syusin plofir[4]にして、
human()を
human(&plofir)
という風にアドレス渡しで、
ヘッダファイルの構造体は二次元配列は使わないで処理するとのことでした。

さらに、情報入力と情報表示の処理はそれぞれ関数にして、
例えばinput()・output()というようにしてそこへ構造体のアドレスを移動させて格納するということでした。
修正したデータを置いてきてしまったので後日ソースを貼り付けます。

この問題は友人がGWは暇だとか余計なことを言ったばかりに暇つぶしで出された問題だったので深い意味はないのだと思います。おそらくヘッダファイルやアドレス渡しの練習ができればいいという程度の認識だと思います。
プログラムが得意な人はさらに分割プログラムにしろといわれて修正していましたし。

大根おろし

Re:ヘッダファイルの中に構造体が3つ

#11

投稿記事 by 大根おろし » 18年前

私の作ったものですが、解答です。
長くて入りきらないのでzipで圧縮して添付にのせました。

フリオ

Re:ヘッダファイルの中に構造体が3つ

#12

投稿記事 by フリオ » 18年前

 
 長くなったので、添付ファイルで。
 

しっぽ

Re:ヘッダファイルの中に構造体が3つ

#13

投稿記事 by しっぽ » 18年前

大根おろしさん、受け取りました。
わざわざありがとうございます。

閉鎖

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