ページ 11

構造体とポインタについて

Posted: 2012年7月22日(日) 20:31
by taz
こんばんは。質問があります。構造体とポインタについてです。以下コードを示します。

コード:

//読み込みファイル
#include <stdio.h>
#include <stdlib.h>

#define END_FILE 0 //ファイルの終端
#define MENU 0 //メニューの表示
#define ADDR 1 //新規レコードの追加
#define UPDATER 2 //更新
#define DELR 3 //削除
#define DISPR 4 //一覧表示
#define CANCEL 5 //キャンセル
#define END 5 //キャンセル
#define NO 2 //いいえ
#define ERROR -1 //エラーの時
#define NOERROR 0 //エラーじゃない時

FILE *fp; //ファイルポインタ
char *fname = "comma.csv"; //ファイル名
int ret = 0; //関数の返り値
int choice=0; //キーボード入力値格納変数
int i_num=0; //構造体配列の番号

//会員メンバ構造体
struct member 
{
	int no;
	char name;
	char adress;
	char tel;
	char mail;
	struct member *pmember;
};

/*メイン関数*/
main()
{
	int Pno = 0;
	Pno = init_disp();
		while(Pno!=CANCEL)
		{
			switch(Pno)
			{
			case MENU:
				Pno = init_disp();
				break;
			/*case ADDR:
				Pno = add_record();
				break;*/
			/*case UPDATER:
				Pno = update_record();
				break;
			case DELR:
				Pno = del_record();
				break;*/
			case DISPR:
				Pno = disp_record();
				break;
			case END:
				break;
			}
		}
}

int init_disp()
{
	int no = 0; //数字の入力値
		
	printf("---会員管理システムメニュー---\n\n");
	printf("1.新規登録\n");
	printf("2.変更\n");
	printf("3.削除\n");
	printf("4.一覧表示\n");
	printf("5.終了\n");
	printf("No? ");
	scanf("%d",&no); //数値を入力
	
	return no;
}

//*一覧表示*/
int disp_record()
{
	struct member a, *ppmember;
	ppmember = &a;
	ret = csv_read(); //ファイルの読み出し関数
    
    //ファイル読み込み終了まで繰り返す
    while(feof(fp)==END_FILE)
    {
        //ファイルからデータを読み込み、構造体配列に格納
        if((fscanf(fp,"%d,%[^,],%[^,],%[^,],%s",ppmember->no,ppmember->name,ppmember->adress,ppmember->tel,ppmember->mail)) != EOF)
        {
               printf("\n%d",ppmember->no); //番号
               printf("\n%s",ppmember->name); //名前
               printf("\n%s",ppmember->adress); //住所
               printf("\n%s",ppmember->tel); //電話番号
               printf("\n%s",ppmember->mail); //メールアドレス
        }
    }
    printf("\n\n%s\n","メニューに戻ります。1:yes");
    scanf("%d",&choice); //メニューに戻るための入力
    //入力値が1の場合
    if(choice==1)
    {
        system("cls"); //コマンドプロンプトの表示クリア
        return MENU; //メイン関数に戻る
    }
    fclose(fp); //ファイルを閉じる
    return NOERROR;
}

int csv_read()
{
	fp = fopen(fname,"r"); //ファイルを読み込みモードで開く
	
	//ファイルポインタがNULLかどうか判定
	if(fp == NULL)
	{
		printf("%sファイルが開けません\n",fname);
		return ERROR; //エラーの返り値として-1を返す
	}
	return NOERROR;
}
上記91行目、
//ファイルからデータを読み込み、構造体配列に格納
if((fscanf(fp,"%d,%[^,],%[^,],%[^,],%s",ppmember->no,ppmember->name,ppmember->adress,ppmember->tel,ppmember->mail)) != EOF)
の部分でエラーが出ます。構造体のメンバに、不正な値が代入されているようです。
何が、問題なのか理解が出来ません。どなたかアドバイスよろしくお願いします。

Re: 構造体とポインタについて

Posted: 2012年7月22日(日) 20:36
by みけCAT
scanfの使い方はわかりますか?
ポインタを渡すべきところで値を渡しているようです。
fscanfはファイルポインタ以外scanfと同じです。
わからないようでしたら苦Cをどうぞ。
http://9cguide.appspot.com/06-01.html#S2
http://9cguide.appspot.com/15-03.html

Re: 構造体とポインタについて

Posted: 2012年7月22日(日) 20:41
by box
taz さんが書きました:

コード:

//*一覧表示*/
int disp_record()
{
	struct member a, *ppmember;
	ppmember = &a;
変数aの役割は、何ですか?
taz さんが書きました:

コード:

        //ファイルからデータを読み込み、構造体配列に格納
        if((fscanf(fp,"%d,%[^,],%[^,],%[^,],%s",ppmember->no,ppmember->name,ppmember->adress,ppmember->tel,ppmember->mail)) != EOF)
構造体の配列に相当する領域は、どこにありますか?

Re: 構造体とポインタについて

Posted: 2012年7月22日(日) 21:20
by softya(ソフト屋)
前回の後でコメントしたんですが読んでもらってますか?
「putchar について • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=11095

Re: 構造体とポインタについて

Posted: 2012年7月22日(日) 22:15
by taz
softya(ソフト屋) さんが書きました:前回の後でコメントしたんですが読んでもらってますか?
「putchar について • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=11095
読ませて頂きました。ありがとうございます。おかげで理解する事が出来ました。

Re: 構造体とポインタについて

Posted: 2012年7月22日(日) 22:19
by taz

コード:

//読み込みファイル
#include <stdio.h>
#include <stdlib.h>

#define END_FILE 0 //ファイルの終端
#define MENU 0 //メニューの表示
#define ADDR 1 //新規レコードの追加
#define UPDATER 2 //更新
#define DELR 3 //削除
#define DISPR 4 //一覧表示
#define CANCEL 5 //キャンセル
#define END 5 //キャンセル
#define NO 2 //いいえ
#define ERROR -1 //エラーの時
#define NOERROR 0 //エラーじゃない時

FILE *fp; //ファイルポインタ
char *fname = "comma.csv"; //ファイル名
int ret = 0; //関数の返り値
int choice=0; //キーボード入力値格納変数
int i_num=0; //構造体配列の番号

//会員メンバ構造体
struct member 
{
	int no;
	char name[20];
	char adress[20];
	char tel[20];
	char mail[20];
	struct member *pmember;
};

/*メイン関数*/
main()
{
	int Pno = 0;
	Pno = init_disp();
		while(Pno!=CANCEL)
		{
			switch(Pno)
			{
			case MENU:
				Pno = init_disp();
				break;
			/*case ADDR:
				Pno = add_record();
				break;*/
			/*case UPDATER:
				Pno = update_record();
				break;
			case DELR:
				Pno = del_record();
				break;*/
			case DISPR:
				Pno = disp_record();
				break;
			case END:
				break;
			}
		}
}

int init_disp()
{
	int no = 0; //数字の入力値
		
	printf("---会員管理システムメニュー---\n\n");
	printf("1.新規登録\n");
	printf("2.変更\n");
	printf("3.削除\n");
	printf("4.一覧表示\n");
	printf("5.終了\n");
	printf("No? ");
	scanf("%d",&no); //数値を入力
	
	return no;
}

//*一覧表示*/
int disp_record()
{
	struct member a, *ppmember;
	ppmember = &a;
	ret = csv_read(); //ファイルの読み出し関数
    
    //ファイル読み込み終了まで繰り返す
    while(feof(fp)==END_FILE)
    {
        //ファイルからデータを読み込み、構造体配列に格納
        if((fscanf(fp,"%d,%[^,],%[^,],%[^,],%s",&(ppmember->no),&(ppmember->name[0]),&(ppmember->adress[0]),&(ppmember->tel[0]),&(ppmember->mail[0]))) != EOF)
        {
               printf("\n%d",ppmember->no); //番号
               printf("\n%s",ppmember->name); //名前
               printf("\n%s",ppmember->adress); //住所
               printf("\n%s",ppmember->tel); //電話番号
               printf("\n%s",ppmember->mail); //メールアドレス
        }
    }
    printf("\n\n%s\n","メニューに戻ります。1:yes");
    scanf("%d",&choice); //メニューに戻るための入力
    //入力値が1の場合
    if(choice==1)
    {
        system("cls"); //コマンドプロンプトの表示クリア
        return MENU; //メイン関数に戻る
    }
    fclose(fp); //ファイルを閉じる
    return NOERROR;
}

int csv_read()
{
	fp = fopen(fname,"r"); //ファイルを読み込みモードで開く
	
	//ファイルポインタがNULLかどうか判定
	if(fp == NULL)
	{
		printf("%sファイルが開けません\n",fname);
		return ERROR; //エラーの返り値として-1を返す
	}
	return NOERROR;
}

以上のように、char型は文字列なので、配列にし、また呼び出す時に、配列の最初を指定する事で解決する事が出来ました。
アドバイスありがとうございました。

Re: 構造体とポインタについて

Posted: 2012年7月22日(日) 22:34
by box
解決したとのことですが、今のdisp_record関数は
「単に出力しているだけ」で、出力したデータはこの関数を抜けた後、
どこにも残っていないことを理解しておいてください。
他の機能を実現しようとすると、その時点で大変お困りになるような気がします。

Re: 構造体とポインタについて

Posted: 2012年7月22日(日) 22:43
by taz
box さんが書きました:解決したとのことですが、今のdisp_record関数は
「単に出力しているだけ」で、出力したデータはこの関数を抜けた後、
どこにも残っていないことを理解しておいてください。
他の機能を実現しようとすると、その時点で大変お困りになるような気がします。
アドバイスありがとうございます。他の機能についても、色々と試行錯誤して頑張りたいと思います。