配列のポインタ渡し

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

配列のポインタ渡し

#1

投稿記事 by オラクル » 7年前

ファイル読み込みの関数を作っているのですが引数のとろこでつまづいてしまいました
環境はVC++2010とDXライブラリです

コード:

// FileHandling.h


#ifndef FE_FILEHANDLING_H
#define FE_FILEHANDLING_H

#include <stdio.h>
#include "common.h"

/********************************************************************************
*Class FileHandling

*ファイルを取り扱う

*メソッドはファイルのパスと読み込み結果を格納するものを引数としてもらい
*ファイルの読み込みと格納を行う

*********************************************************************************/
class FileHandling{

	public:
		// ファイルの読み込み
		void File_read( const char *FileName, VECTOR *Array[]  );

};

#endif // FE_FILEHANDLING_H


// FileHandling.cpp

#include "FileHandling.h"
#pragma warning( disable : 4996 )
/********************************************************************************
*FileHandling::File_read
*空白、カンマ区切りのテキストファイルを読み込む

*戻り値:なし

*引数:	const char *FileName	( ファイルのパス )
*		VECTOR	   *Array[]		( ファイルの内容を格納する配列:VECTOR型 )

*********************************************************************************/
void FileHandling::File_read( const char *FileName, VECTOR *Array[] ){
	
	FILE* fp;		// ファイルポインタ変数
	float x = 0;	// X座標格納変数
	float y = 0;	// Y座標格納変数
	float z = 0;	// Z座標格納変数
	int i = 0;		// 配列の添え字

	// ファイルを取得
	fp = fopen(FileName, "r");
	// 取得したファイルが無ければ
	if( fp == NULL ){
		// メッセージ表示
		MessageBox( NULL, "ファイル読み込み失敗", "DXライブラリ" , MB_OK );
	}
	// ファイルの終端まで調べる
	while( fscanf(fp, "%f %f %f", x, y, z) != EOF ){
		// ファイルから得た値を格納
		Array[i]->x = (float)x;
		Array[i]->y = (float)y;
		Array[i]->z = (float)z;
		// 配列の添え字を進める
		i++;
	}
	// ファイルの解放
	fclose(fp);

}


// main.cpp

int main(){
     VECTOR FileData_EnemyPos[];	 // ファイルから読み込んだデータの格納配列
     FileHandling	fileHandling;				        // FileHandlingクラス(ファイルを取り扱いを行う)

     fileHandling.File_read( "EnemyPos_Data.txt", FileData_EnemyPos ); // Error

}
error C2664: 'FileHandling::File_read' : 2 番目の引数を 'DxLib::VECTOR [1]' から 'DxLib::VECTOR *[]' に変換できません。

やりたいこととしては関数に配列のアドレスとファイルパスを渡すとファイルパスのファイルを読み込んで引数で
もらった配列のアドレスをもとに実引数の配列” VECTOR FileData_EnemyPos[];”に値が格納されるという
仕組みです

同じVECTOR型の変数では出来たのですがやはり配列は勝手が違うようです

どのようにすればよいか教えていただけると助かります

nil
記事: 428
登録日時: 8年前

Re: 配列のポインタ渡し

#2

投稿記事 by nil » 7年前

Array->x = (float)x;
Array->y = (float)y;
Array->z = (float)z;
なぜxyzをfloatで宣言しているのにキャストしているんですか?
あと引数の*を消せばいいです

box
記事: 1746
登録日時: 9年前

Re: 配列のポインタ渡し

#3

投稿記事 by box » 7年前

オラクル さんが書きました:

コード:

	// 取得したファイルが無ければ
	if( fp == NULL ){
		// メッセージ表示
		MessageBox( NULL, "ファイル読み込み失敗", "DXライブラリ" , MB_OK );
	}
ダイアログでOKボタンを押した後、何ごともなかったかのように続けていいんでしょうか。
オラクル さんが書きました:

コード:

	// ファイルの終端まで調べる
	while( fscanf(fp, "%f %f %f", x, y, z) != EOF ){
fscanf()の引数として、x, y, zは本当に正しいでしょうか。何か忘れていませんか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

Re: 配列のポインタ渡し

#4

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

涼雅 さんが書きました:あと引数の*を消せばいいです
それだと呼び出し関数に渡すときは固定の配列でないといけないですよね?
質問者が聞きたいのは、読み込んだ数だけメモリを確保してそれにデータを保持したいのだと思いますが?

とりあえず引数についてご質問なので、サンプルを以下に示します。

コード:

#include "stdafx.h"

#include "stdio.h"
#include "malloc.h"

// 適当な構造体
typedef struct _tagVector
{
	int x, y;
} VECTOR;

// 読込 (ここでは単純にメモリ確保)
void FileRead(VECTOR *pvec[])
{
	VECTOR vec[9] = {{0, 1}, {2, 3}, 0};        // まあファイル読込した結果だと思いねえ
	// メモリ確保
	*pvec = (VECTOR*)calloc(9, sizeof(VECTOR));
	// 確保したところにファイルから読み込んだ結果をコピーする
	memcpy(*pvec, &vec, sizeof(VECTOR) * 9);
}

// 呼び出しサンプル
int main(){
	VECTOR *vec = NULL; // ここに読み込んだデータを入れたい
	FileRead(&vec); // ポインタにして渡す

	// ここにきたら以下のようにアクセスできる
	for ( int j = 0; j < 9; j++ )
	{
		printf("%d=%d,%d\n", j, vec[j].x, vec[j].y);
	}
	// ただしメモリ確保した以上のアクセスはしたらだめ(プログラムが落ちる)
	// printf("%d=%d,%d\n", 9, vec[9].x, vec[9].y); // NG!! FileReadで確保しているのが9なので0~8でないといけない

	free(vec); // 確保したメモリは解放すること
};
ファイルの中に個数が最初に書かれているならラクなんですけどね。
written by へにっくす

オラクル

Re: 配列のポインタ渡し

#5

投稿記事 by オラクル » 7年前

>> 涼雅
ご指摘ありがとうございます
自分でもうっかりしていたみたいです

>>box
エラー処理などメインの処理以外を後回しにしてしまうんですが
悪い癖ですね、直します。

fscanfに関しては他のサイトさんを回ってみたところ引数にアドレスを指定しているところがありましたがそうゆうことでしょうか?

コード:

 // ファイルの終端まで調べる
    while( fscanf(fp, "%f %f %f", &x, &y, &z) != EOF ){

>>へにっくす
"ファイルの中に個数が最初に書かれているならラク"とのことでしたが

コード:

// file.txt

10 // 個数
// x        // y        // z
100 100 100
200 200 200
     ・
     ・
     ・
// X Y z3つで1つ分として10個分ファイルに記載
// 実際に書かれているのは数字だけ
こういうことだと思うんですが
その場合、提示してくださったソースコードはどのように変化するのでしょうか?

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

Re: 配列のポインタ渡し

#6

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

オラクル さんが書きました:その場合、提示してくださったソースコードはどのように変化するのでしょうか?
単純に読めればいいなら、こんな感じになる。
ちなみに全角数字だと数値として読めないぞ?
なぜラクなのかというと、個数を調べる処理が要らないからだ。

コード:

// mainの変更:戻り値を使って、呼び出し元に何個作成されたかを知らせる。
// count = FileRead(&vec);
// for (int j; j < count; j++)
// というように変える
int FileRead(VECTOR *pvec[])
{
	VECTOR *pv;
	FILE *fp = fopen("file.txt", "r");
	int n=0; // 個数 (読めなかった場合を考えて初期化しておく)
	int cnt; // カウント
	if ( 1 == fscanf(fp, "%d", &n) ) // まず個数を読む
	{
		if ( n > 0 ) // 0を超えている場合、その数分読み込む
		{
			*pvec = (VECTOR*)calloc(n, sizeof(VECTOR)); // メモリ確保
			for ( cnt = 0, pv = *pvec; cnt < n; cnt++, pv++ ) // ポインタを使用する
			{
				if ( 2 > fscanf(fp, "%d%d", &pv->x, &pv->y) ) // 1行が2つぶん
				{
					printf("2項目読めませんでした");
					break;
				}
			}
		}
	}
	fclose(fp); // 後始末
	return n; // 戻す値はfile.txtにあった個数
}
サンプルのため、エラー処理を何も入れてません。
(ファイルが存在しない場合とか、メモリを確保できなかった場合とか、一行が何項目あるかとか、…)
written by へにっくす

オラクル

Re: 配列のポインタ渡し

#7

投稿記事 by オラクル » 7年前

ありがとうございます
参考にさせていただきます

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: 配列のポインタ渡し

#8

投稿記事 by YuO » 7年前

そもそもC++なら配列ではなくstd::vector<VECTOR>使えばいいのでは?
push_backしていくだけですから,それほど難しくないかと。

ちなみに,
  • ポインタ型の配列 (array of pointer type)

    コード:

    T *array[N]
  • 配列型へのポインタ (pointer to array type)

    コード:

    T (*pointer)[N]
です (Tは大元の型,Nは要素数)。

閉鎖

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