ページ 11

ファイル読み書きについて(再)

Posted: 2016年5月24日(火) 16:21
by kloud

コード:

////////////////////////
//                    //
//   ヘッダファイル   //
//                    //
////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//////////////////////
//                  //
//   構造体の定義   //
//                  //
//////////////////////
typedef enum
{
	MODE_FINISH = 0 ,     // 終了
	MODE_INPUT ,          // 入力
	MODE_OUTPUT ,         // 出力
	MODE_SAVE ,           // セーブ
	MODE_LOAD ,           // ロード
	MODE_MAX ,            // 最大数
}MODE;

typedef struct
{
    char aName[256];     // 名前
    int nAge;            // 年齢
    float fHeight;       // 身長
    float fWeight;       // 体重
}PersonalData;

///////////////////////////
//                       //
//   プロトタイプ宣言    //
//                       //
///////////////////////////
void SelectMode ( void );
int Input ( PersonalData* pData );
void Output ( PersonalData* pData , int nNumHuman );
void Save ( PersonalData* pData , int nNumHuman );
void Load ( PersonalData* pData , int* nNumHuman );

////////////////////
//                //
//   マクロ定義   //
//                //
////////////////////
#define MinCount (1)
#define MaxCount (5)

////////////////////
//                //
//   メイン関数   //
//                //
////////////////////
void main ( void )
{
	// モード選択
	SelectMode ();

	// キー入力待ち
    rewind (stdin);
    getchar();

    return;
}

void SelectMode ( void )
{
	PersonalData aData[MaxCount];
    int nNumHuman;
	memset ( aData , 0 , sizeof ( aData ) );
	MODE mode;

	do
	{
		// 番号入力
		printf ( "\nMENU\n" );

		printf ( "以下の番号から処理を選んでください\n" );

		printf ( "1. 入力\n" );
		printf ( "2. 出力\n" );
		printf ( "3. セーブ\n" );
		printf ( "4. ロード\n" );
		printf ( "0. 終了\n" );
		printf ( "> " );

		scanf ( "%d" , &mode );

		// 各番号の処理
		switch ( mode )
		{
			// 終了処理
			case 0:
				   printf ( "プログラムを終了します\n" );

				   break;

			// 入力処理
		    case 1:
				   nNumHuman = Input ( &aData[0] );

				   break;

			// 出力処理
			case 2:
				   Output ( &aData[0] , nNumHuman );

				   break;

			// セーブ処理
			case 3:
				   Save ( &aData[0] , nNumHuman );

				   break;

			// ロード処理
			case 4:
				   Load ( &aData[0] , &nNumHuman );

				   break;

		}
	}while ( mode != MODE_FINISH );     // 終了処理が呼ばれるまでループ
}

//////////////////
//              //
//   入力関数   //
//              //
//////////////////
int Input ( PersonalData* pData )
{
    int Name_Count;
	int nNumHuman;

	if ( pData == NULL )
	{
		printf ( "データ入力に失敗しました\n" );
		return 0;
	}

	do
	{
	    printf ( " 何人分のデータを入力しますか?(%d~%d人) > " , MinCount , MaxCount );
	    scanf ( "%d" , &nNumHuman );
	}while ( nNumHuman < MinCount | nNumHuman > MaxCount );

	printf ( "\n %d人分のデータを入力します\n" , nNumHuman );

	// 人数分入力
    for ( int InputNum = 1; InputNum <= nNumHuman; InputNum++ )
    {
        printf ( " %d人目のデータ入力 \n" , InputNum );
 
        printf ( " 姓(全角5文字以内) > " );                      // 苗字入力
        scanf ( "%s" , &pData -> aName[0] );
 
        Name_Count = strlen ( &pData -> aName[0] );
 
        printf ( " 名(全角5文字以内) > " );                      // 名前入力
        scanf ( "%s" , &pData -> aName[Name_Count] );
 
        printf ( " 年齢(半角2ケタ) > " );                        // 年齢入力
        scanf ( "%d" , &pData -> nAge );
 
        printf ( " 身長(cm) (半角数字・少数第1位まで) > " );     // 身長入力
        scanf ( "%f" , &pData -> fHeight );
 
        printf ( " 体重(kg) (半角数字・少数第1位まで) > " );     // 体重入力
        scanf ( "%f" , &pData -> fWeight );
 
        pData++;
    }

    return nNumHuman;
}
 
////////////////////
//                //
//   セーブ関数   //
//                //
////////////////////
void Save ( PersonalData* pData , int nNumHuman )
{
    FILE* fp;

	if ( nNumHuman < MinCount | nNumHuman > MaxCount )      // エラーの原因がすぐわかる
	{
		printf ( "データがありません\n" );
		return;
	}

    if ( pData != NULL )
    {
		// ファイルを開く
	    fp = fopen ( "savedata.bin", "wb" );

	    if ( fp == NULL )
	    {
		   printf ( "FILE OPEN ERROR\n" );
		   rewind ( stdin );
		   getchar ();
        }
		else
		{
		   // ファイル書き込み
           fwrite ( &nNumHuman , sizeof ( int ) , 1 , fp );
           fwrite ( pData , sizeof ( pData ) , nNumHuman , fp );

		   // ファイルを閉じる
           fclose ( fp );
		}

		if ( fclose ( fp ) != EOF )
		{
			printf ( "FILE CLOSE ERROR" \n );
			rewind ( stdin );
			getchar ();
		}
		else
		{
            printf ( "\nセーブしました\n" );
			rewind ( stdin );
			getchar ();
		}
    }
	else
	{
		printf ( "セーブ失敗\n" );
		rewind ( stdin );
		getchar ();
	}
}
 
////////////////////
//                //
//   ロード関数   //
//                //
////////////////////
void Load ( PersonalData* pData , int* nNumHuman )
{
    FILE* fp;
 
	// ファイルを開く
    fp = fopen ( "savedata.bin" , "rb" );

    if ( fp == NULL )
    {
        printf ( "FILE OPEN ERROR\n" );

		rewind ( stdin );
		getchar ();
    }
	else
	{
		if ( pData != NULL )
		{
			if ( nNumHuman < MinCount | nNumHuman > MaxCount )
			{
				printf ( "データがありません\n" );

				rewind ( stdin );
				getchar ();
			}
			else
			{
				// ファイル読み込み
                fread ( nNumHuman , sizeof ( int ) , 1 , fp );
                fread ( pData , sizeof ( *pData ) , *nNumHuman , fp );

		        // ファイルを閉じる
                fclose ( fp );

			    printf ( "ロードしました\n" );
				rewind ( stdin );
				getchar ();
			}
		}
		else
		{
			printf ( "データがありません\n" );
			rewind ( stdin );
			getchar ();
		}
	}
}

//////////////////
//              //
//   出力関数   //
//              //
//////////////////
void Output ( PersonalData* pData , int nNumHuman )
{
	if ( nNumHuman == 0 )
	{
		printf ( "データがありません\n" );
		return;
	}

	if ( pData == NULL )
	{
		printf ( "出力に失敗しました\n" );
		return;
	}

	// 人数分出力
    for ( int nCount_2 = 0; nCount_2 < nNumHuman; nCount_2++ )
    {
        printf ( " %d人目のデータ出力 \n" , nCount_2 + 1 );

        printf ( " 姓名 : %s\n" , pData -> aName[0] );        // 姓名出力
        
        printf ( "年齢 : %d 才\n" , pData -> nAge );           // 年齢出力

        printf ( "身長: %1.0f cm\n" , pData -> fHeight );      // 身長出力

        printf ( " 体重: %1.0f kg\n" , pData -> fWeight );     // 体重出力

		pData++;
	}
}

///////////////   EOF    ///////////////

前回のプログラムを変えて、セーブ、ロードなどを任意の順序でできるようにしました。
そこで、一つ問題が発生したのですが、一回目のデータをセーブしてからウィンドウを閉じて、再び開き、ロードして出力すると名前以外が変に出力されます。
どこがおかしいのでしょうか?

Re: ファイル読み書きについて(再)

Posted: 2016年5月24日(火) 17:37
by kloud

コード:

//////////////////////////////////
//                              //
//        MENU[main.cpp]        //
//    AT-12A-248-20 鈴木 大成   //
//                              //
//////////////////////////////////

////////////////////////
//                    //
//   ヘッダファイル   //
//                    //
////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//////////////////////
//                  //
//   構造体の定義   //
//                  //
//////////////////////
typedef enum
{
	MODE_FINISH = 0 ,     // 終了
	MODE_INPUT ,          // 入力
	MODE_OUTPUT ,         // 出力
	MODE_SAVE ,           // セーブ
	MODE_LOAD ,           // ロード
	MODE_MAX ,            // 最大数
}MODE;

typedef struct
{
    char aName[256];     // 名前
    int nAge;            // 年齢
    float fHeight;       // 身長
    float fWeight;       // 体重
}PersonalData;

///////////////////////////
//                       //
//   プロトタイプ宣言    //
//                       //
///////////////////////////
void SelectMode ( void );
int Input ( PersonalData* pData );
void Output ( PersonalData* pData , int );
void Save ( PersonalData* pData , int );
void Load ( PersonalData* pData , int* );

////////////////////
//                //
//   マクロ定義   //
//                //
////////////////////
#define MinCount (1)
#define MaxCount (5)

////////////////////
//                //
//   メイン関数   //
//                //
////////////////////
void main ( void )
{
	// モード選択
	SelectMode ();

	// キー入力待ち
    rewind (stdin);
    getchar();

    return;
}

void SelectMode ( void )
{
	PersonalData aData[MaxCount];
    int nNumHuman = 0;
    memset ( aData , 0 , sizeof ( aData ) );
	MODE mode;

	do
	{
		// 番号入力
		printf ( "\nMENU\n" );

		printf ( "以下の番号から処理を選んでください\n" );

		printf ( "1. 入力\n" );
		printf ( "2. 出力\n" );
		printf ( "3. セーブ\n" );
		printf ( "4. ロード\n" );
		printf ( "0. 終了\n" );
		printf ( "> " );

		scanf ( "%d" , &mode );

		printf ( "\n" );

		// 各番号の処理
		switch ( mode )
		{
			// 終了処理
			case 0:
				   printf ( "プログラムを終了します\n" );

				   break;

			// 入力処理
		    case 1:
				   nNumHuman = Input ( &aData[0] );

				   break;

			// 出力処理
			case 2:
				   Output ( &aData[0] , nNumHuman );

				   break;

			// セーブ処理
			case 3:
				   Save ( &aData[0] , nNumHuman );

				   break;

			// ロード処理
			case 4:
				   Load ( &aData[0] , &nNumHuman );

				   break;

		}
	}while ( mode != MODE_FINISH );     // 終了処理が呼ばれるまでループ
}

//////////////////
//              //
//   入力関数   //
//              //
//////////////////
int Input ( PersonalData* pData )
{
    int Name_Count;
	int Data_Count;

	if ( pData == NULL )
	{
		printf ( "データ入力に失敗しました\n" );
		return 0;
	}

	do
	{
	    printf ( " 何人分のデータを入力しますか?(%d~%d人) > " , MinCount , MaxCount );
	    scanf ( "%d" , &Data_Count );
	}while ( Data_Count < MinCount || Data_Count > MaxCount );

	printf ( "\n %d人分のデータを入力します\n" , Data_Count );

	// 人数分入力
    for ( int InputNum = 1; InputNum < Data_Count + 1; InputNum++ )
    {
		printf ( "\n" );

        printf ( " %d人目のデータ入力 \n" , InputNum );
 
        printf ( " 姓(全角5文字以内) > " );                      // 苗字入力
        scanf ( "%s" , &pData -> aName[0] );
 
        Name_Count = strlen ( &pData -> aName[0] );
 
        printf ( " 名(全角5文字以内) > " );                      // 名前入力
        scanf ( "%s" , &pData -> aName[Name_Count] );
 
        printf ( " 年齢(半角2ケタ) > " );                        // 年齢入力
        scanf ( "%d" , &pData -> nAge );
 
        printf ( " 身長(cm) (半角数字・少数第1位まで) > " );     // 身長入力
        scanf ( "%f" , &pData -> fHeight );
 
        printf ( " 体重(kg) (半角数字・少数第1位まで) > " );     // 体重入力
        scanf ( "%f" , &pData -> fWeight );
 
        pData++;
    }

    return Data_Count;
}
 
////////////////////
//                //
//   セーブ関数   //
//                //
////////////////////
void Save ( PersonalData* pData , int nNumHuman )
{
    FILE* fp;

	if ( nNumHuman < MinCount | nNumHuman > MaxCount )      // エラーの原因がすぐわかる
	{
		printf ( "データがありません\n" );
		return;
	}

    if ( pData != NULL )
    {
		// ファイルを開く
	    fp = fopen ( "savedata.bin", "wb" );

	    if ( fp == NULL )
	    {
		   printf ( "FILE OPEN ERROR\n" );
           return;
        }

		// ファイル書き込み
        fwrite ( &nNumHuman , sizeof ( int ) , 1 , fp );
        fwrite ( pData , sizeof ( *pData ) , nNumHuman , fp );

		// ファイルを閉じる
        fclose ( fp );

		if ( fclose ( fp ) != EOF )
		{
			fputs ( "FILE CLOSE ERROR" , stderr );
			return;
		}
		else
		{
            printf ( "\nセーブしました\n" );
		}
    }
	else
	{
		printf ( "セーブ失敗\n" );
	}
}
 
////////////////////
//                //
//   ロード関数   //
//                //
////////////////////
void Load ( PersonalData* pData , int* nNumHuman )
{
    FILE* fp;
 
    if ( pData != NULL )
    {
		// ファイルを開く
        fp = fopen ( "savedata.bin" , "rb" );

        if ( fp == NULL )
        {
            fputs ( "FILE OPEN ERROR\n" , stderr );
            return;
        }
        
		// ファイル読み込み
        fread ( nNumHuman , sizeof ( int ) , 1 , fp );
        fread ( pData , sizeof ( *pData ) , *nNumHuman , fp );

		// ファイルを閉じる
        fclose ( fp );

		if ( fclose ( fp ) != EOF )
		{
			fputs ( "FILE CLOSE ERROR" , stderr );
			return;
		}
		else
		{
            printf ( " ロードしました\n" );
		}
    }
	else
	{
		printf ( "ロード失敗\n" );
	}
}

//////////////////
//              //
//   出力関数   //
//              //
//////////////////
void Output ( PersonalData* pData , int nNumHuman )
{
	if ( nNumHuman == 0 )
	{
		printf ( "データがありません\n" );
		return;
	}

	if ( pData == NULL )
	{
		printf ( "出力に失敗しました\n" );
		return;
	}

	// 人数分出力
    for ( int nCount_2 = 0; nCount_2 < nNumHuman; nCount_2++ )
    {
        printf ( " %d人目のデータ出力 \n" , nCount_2 + 1 );

        printf ( " 姓名 : %s\n" , &pData -> aName[0] );        // 姓名出力
        
        printf ( "年齢 : %d 才\n" , pData -> nAge );           // 年齢出力

        printf ( "身長: %0.1f cm\n" , pData -> fHeight );      // 身長出力

        printf ( " 体重: %0.1f kg\n" , pData -> fWeight );     // 体重出力

		printf ( "\n" );

		pData++;
	}
}

///////////////   EOF    ///////////////
自力で解決できました。
お騒がせしてすみません。