ページ 11

自作関数をまたいだ際の動的構造体について

Posted: 2015年12月09日(水) 21:32
by たかひろ
自作関数で動的構造体を扱いたいのですが、下記のコードにした場合エラーが出てしまいます。
よろしければ、エラーとなっている原因とどのように修正をすればよいか、また修正したものをお見せしていただけないでしょうか。
また、もし読みにくいと思いましたら好きなように変更しても構わないです。
使用コンパイラはborland社のものです。

エラー文
エラー E2034 test.cpp 35: 'int' 型は 'struct' 型に変換できない(関数 keisan(struct *,int) )

コード:

#include <stdio.h>
#include <stdlib.h>
 
 /* 構造体宣言 */
typedef struct
{
     int a;
     double b;
}*test_t;

int keisan( test_t , int);
 
 /* メイン */
 int main()
{
 	 test_t test;
     int n;
 
     /* 配列サイズの入力 */
     printf( "n = " );
     scanf( "%d", &n );
	 
	 keisan( test , n );

     free(test);
}

int keisan( test_t test , int n )
{
	test = (test_t)calloc( n , sizeof(test_t) );
	if(test == NULL) return 1;
	
	for(int i = 0 ; i < n ; i++ )
	{
		test[ i ] = i * 10;
		
		printf("test[%d] = %d", test[i] , i);
	}
	return 0;
}

Re: 自作関数をまたいだ際の動的構造体について

Posted: 2015年12月09日(水) 22:00
by みけCAT
●致命的な間違い
  • デフォルトでは構造体に整数は直接代入できません。 (エラーとなっている原因)
  • printfの%dに構造体を渡してはいけません。
  • 未初期化のtestをfree関数に渡してはいけません。
●その他不自然な点
  • scanfが正しく値を読み込めたか確認するべきです。
  • printfに渡しているtestとiが逆のようです。
  • callocとfreeより、newとdeleteを使うべきです。

修正したコード

コード:

#include <stdio.h>
/* stdlib.hのincludeは使わなくなったので削除 */
#include <string> /* std::stringを使うために追加 */

/* 構造体宣言 */
typedef struct test_t_data /* =演算子やnew、コンストラクタで困らないように名前をつける */
{
	int a;
	double b;

	test_t_data(): a(0), b(0.0) {} /* デフォルトコンストラクタで初期化されるようにする */

	/* int型のデータを受け取る=演算子を定義する */
	test_t_data& operator=(int n)
	{
		a = n;
		b = n;
		return *this;
	}

	/* printf関数に渡すために文字列に変換する関数を定義する */
	std::string to_string() const
	{
		char buffer[10240];
		sprintf(buffer, "{%d, %f}", a, b);
		return buffer;
	}
}*test_t;

int keisan( test_t& , int); /* main関数のtestを書き換えられるように参照を用いる */

/* メイン */
int main()
{
	test_t test;
	int n;

	/* 配列サイズの入力 */
	printf( "n = " );
	if(scanf( "%d", &n ) != 1) return 1; /* きちんと読み込めたかチェックし、読み込めていなければ終了する */

	keisan( test , n );

	delete[] test; /* new[]で確保したのでdelete[]で解放する */
}

int keisan( test_t& test , int n ) /* main関数のtestを書き換えられるように参照を用いる */
{
	test = new test_t_data[n]; /* callocではなくnew[]で確保する */
	if(test == NULL) return 1;
	
	for(int i = 0 ; i < n ; i++ )
	{
		test[ i ] = i * 10;
		
		printf("test[%d] = %s\n", i , test[i].to_string().c_str()); /* データと書式を修正する */
	}
	return 0;
}

Re: 自作関数をまたいだ際の動的構造体について

Posted: 2015年12月09日(水) 22:30
by たかひろ
ご丁寧に教えてくれましてありがとうございます。
それと本当に申し訳ないのですが、私はc言語を主軸にやっておりc++のコンパイラを使っているので
c++の機能も一部使っているような形にしています。

それゆえにc++の機能、オブジェクト指向などは理解しておらずc言語の機能しか使っていません。
ですのでこれで解決ができましたが本当によろしければでよいのでc言語仕様に直したコードも教えてもらってもよろしいでしょうか。

Re: 自作関数をまたいだ際の動的構造体について

Posted: 2015年12月09日(水) 22:46
by みけCAT
こうですか、わかりません。

コード:

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

/* 構造体宣言 */
typedef struct
{
	int a;
	double b;
}*test_t;

int keisan( test_t* , int);

/* メイン */
int main(void)
{
	test_t test;
	int n;

	/* 配列サイズの入力 */
	printf( "n = " );
	if(scanf( "%d", &n ) != 1) return 1;

	keisan( &test , n );

	free(test);

	return 0;
}

int keisan( test_t* test , int n )
{
	int i;
	*test = calloc( n , sizeof(test_t) );
	if(*test == NULL) return 1;
	
	for(i = 0 ; i < n ; i++ )
	{
		(*test)[ i ].a = i * 10;
		
		printf("test[%d] = %d\n", i, (*test)[i].a);
	}
	return 0;
}

Re: 自作関数をまたいだ際の動的構造体について

Posted: 2015年12月09日(水) 23:40
by たかひろ
わがままにつあっていただきありがとうございます!おかげさまで解決いたしました