他のソースファイルの操作関数を扱いたい

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

他のソースファイルの操作関数を扱いたい

#1

投稿記事 by マナ » 10年前

すみませんこちらでも聞いたことなのですが
http://oshiete.goo.ne.jp/qa/8410396.html

少し延長気味になります。

ソースA の内容

コード:

static struct{
char *name[2];
double d_data[2];
int i_data[4];
double s_data[2];
int state[2][3];
int regi[5];
}kya_data[2]={ {
  { "奈美" , "爆弾" }, 
  {
   43.0000 ,
   54.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   0.100,
   0.100,
  } , {
  { 0 , 0 , 0 } ,
  { 0 , 0 , 0 } 
  } , {
   100 , 0 , 0 , 0 , 0
  } },{
  { "由美" , "湖" }, 
  {
   23.0000 ,
   76.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   0.100,
   0.100,
  } , {
  { 0 , 0 , 0 } ,
  { 0 , 0 , 0 } 
  } , {
   0 , 0 , 0 , 0 , 100
  } }
};

void data_load( void ){ //テキストファイルからロード
  //略
}

void data_read( int num , const char **r_name , ... ){ //読み込み

	va_list args;
	va_start( args , r_name );

	int a = 0;

	if( r_name == "name"   ){ a = 0; }
	else if( r_name == "d_data" ){ a = 1; }
	else if( r_name == "i_data" ){ a = 2; }
	else if( r_name == "s_data" ){ a = 3; }
	else if( r_name == "state"  ){ a = 4; }
	else if( r_name == "resi"   ){ a = 5; }

	switch( a ){
		case 0:
			**s = kya_data[ num ].name;
			break;

		case 1:
			*d = kya_data[ num ].d_data[ *num2 ];
			break;

		case 2:
			*i = kya_data[ num ].i_data[ *num2 ];
			break;

		case 3:
			*d = kya_data[ num ].s_data[ *num2 ];
			break;

		case 4:
			*i = kya_data[ num ].state[ *num2 ][ *num3 ];
			break;

		case 5:
			*i = kya_data[ num ].resi[ *num2 ];
			break;
	}
}

void data_save( int num , const char **r_name , ... ){ //構造体の値の変更と同時にテキストファイルに書き込み
	//略
}
ソースBの内容

コード:

void data_load( void );
void data_read( int num , const char **r_name , ... );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){

	char *s;
	double i;

	data_load();//本当は必要な画面の時だけ呼び出す
	data_read( 0 , "name" , 0 , &s ); //ソースファイルAに書かれた0番目の人の0番目のnameデーターをソースファイルBのsに格納したい
	data_read( 0 , "state" , 0 , 1 , &i ); //ソースファイルAに書かれた0番目の人の0列目の1番目のstateデーターをソースファイルBのiに格納したい

	DrawString( 0 , 0 , GetColor( 0 , 0 , 0 ) , s );
	DrawString( 0 , 20 , GetColor( 0 , 0 , 0 ) , i );
}
大体このような形で構造体のデーターを扱いたいのですがソースAでは変数を用意してくださいと言われコンパイルエラーになります。

どのように書いたら別ファイルで書かれた構造体のデーターを読み取れますか?
聞いた先ではd_dataを特定の値に変えることはできても
d_data以外の値を変えるには変更したい物専用の関数を作らないといけないため不便だと思うのです。

そのため値の読み取りようと、値の変更用の関数を作れないかと思い聞いてみました。

box
記事: 2002
登録日時: 13年前

Re: 他のソースファイルの操作関数を扱いたい

#2

投稿記事 by box » 10年前

マナ さんが書きました: ソースAでは変数を用意してくださいと言われコンパイルエラーになります。
ソースAの何行目でどういうエラーが出たのか、
エラーメッセージをそのまま記載してください。
マナ さんが書きました:

コード:

	if( r_name == "name"   ){ a = 0; }
	else if( r_name == "d_data" ){ a = 1; }
	else if( r_name == "i_data" ){ a = 2; }
	else if( r_name == "s_data" ){ a = 3; }
	else if( r_name == "state"  ){ a = 4; }
	else if( r_name == "resi"   ){ a = 5; }
たぶん、strcmp()あたりを使う必要があるのではないでしょうか。
マナ さんが書きました:

コード:

static struct{
char *name[2];
double d_data[2];
int i_data[4];
double s_data[2];
int state[2][3];
int regi[5];
}kya_data[2]={ {
  { "奈美" , "爆弾" }, 
  {
   43.0000 ,
   54.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   0.100,
   0.100,
  } , {
  { 0 , 0 , 0 } ,
  { 0 , 0 , 0 } 
  } , {
   100 , 0 , 0 , 0 , 0
  } },{
  { "由美" , "湖" }, 
  {
   23.0000 ,
   76.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   0.100,
   0.100,
  } , {
  { 0 , 0 , 0 } ,
  { 0 , 0 , 0 } 
  } , {
   0 , 0 , 0 , 0 , 100
  } }
};
他の人がどういう風にソースを書いているかをよく見て、
このグチャグチャなインデントを何とかしましょう。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
Tatu
記事: 445
登録日時: 13年前
住所: 北海道

Re: 他のソースファイルの操作関数を扱いたい

#3

投稿記事 by Tatu » 10年前

関数を分けた方がよい気がします。

一つの関数に各データの処理を書くよりも
各データ専用の関数を追加する方が楽だと思うからです。

マナ

Re: 他のソースファイルの操作関数を扱いたい

#4

投稿記事 by マナ » 10年前

エラーログはこんな感じです。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(183) : error C2065: 's' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(187) : error C2065: 'd' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(187) : error C2065: 'num2' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(191) : error C2065: 'i' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(191) : error C2065: 'num2' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(195) : error C2065: 'd' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(195) : error C2065: 'num2' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(199) : error C2065: 'i' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(199) : error C2065: 'num2' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(199) : error C2065: 'num3' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(203) : error C2065: 'i' : 定義されていない識別子です。
c:\documents and settings\user\my documents\visual studio 2008\projects\kami\kyara_cd.cpp(203) : error C2065: 'num2' : 定義されていない識別子です。

普通のC言語で書いたのならstrcmp()はいると思いますがDXライブラリだとどうでしょうね?

ええ、これよりも見やすいインデントがあるんですか。
見つけたら試してみますね

マナ

Re: 他のソースファイルの操作関数を扱いたい

#5

投稿記事 by マナ » 10年前

その各データ専用の関数を作っているつもりなのですがどう違うのでしょうか?

データーのロードと読み取りとセーブ&書き込み用を扱う関数の3セットを各データー事に作る予定なのですが・・・。

アバター
Tatu
記事: 445
登録日時: 13年前
住所: 北海道

Re: 他のソースファイルの操作関数を扱いたい

#6

投稿記事 by Tatu » 10年前

>strcmp
DXライブラリの作者が
使えるC言語標準関数のページで紹介しています。
不要ならわざわざ紹介しないでしょう。

>インデント
教えて!gooの方の回答者さんがやっているくらいには分かりやすくしてほしいですね。

>違い
可変引数を使わなくていいという点が大きな違いになるでしょう。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 他のソースファイルの操作関数を扱いたい

#7

投稿記事 by softya(ソフト屋) » 10年前

C++の文法で書いたのなら文字列比較に==が使える方法もあります。C言語の知識の範囲で使うならstrcmpを使うのが無難かと思います。

**s とかは宣言なしに突然湧いているので、そんな識別子はないとエラーで怒られるのは致し方ない事ですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マナ

Re: 他のソースファイルの操作関数を扱いたい

#8

投稿記事 by マナ » 10年前

お二人の話を総合すると結局可変引数を使った関数では型の違う値を返せないって事でしょうか?

型が決まってるのでしたらreturn を使えばいいですしね

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 他のソースファイルの操作関数を扱いたい

#9

投稿記事 by みけCAT » 10年前

マナ さんが書きました:お二人の話を総合すると結局可変引数を使った関数では型の違う値を返せないって事でしょうか?
「型の違う値を返す」というのはどういう処理でしょうか?
可変長引数を使った関数で、引数のポインタにいろいろな型のデータを格納する処理は普通にscanf関数でありますね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 他のソースファイルの操作関数を扱いたい

#10

投稿記事 by みけCAT » 10年前

マナ さんが書きました:お二人の話を総合すると結局可変引数を使った関数では型の違う値を返せないって事でしょうか?
どのような推論をすると、このような結論が出るのでしょうか?私、気になります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

マナ

Re: 他のソースファイルの操作関数を扱いたい

#11

投稿記事 by マナ » 10年前

そういえばそうですね

scanf 関数と同じようなものを作ればいいんですね
試してみます。

return を使って int型なら int型を返すことが可能な関数を double型なら double型 を返すことが可能な関数をそれぞれ作って返すのです

int kan1( ~~~ ){
return //(int型の何か)
}

double kan2( ~~~ ){
return //(double型の何か)
}

このような感じで

発想はTatuさんが
可変引数を使わなくていいという点が大きな違いになるでしょう。
といわれたのと

ソフト屋さんが可変引数について言求されなかったようなので

可変引数を使わなくていい→可変引数を使った関数は存在しない→可変引数を使った関数では型の違う値を返せない

っという発想ですね

アバター
usao
記事: 1887
登録日時: 11年前

Re: 他のソースファイルの操作関数を扱いたい

#12

投稿記事 by usao » 10年前

何がしたいのか読み取りにくいので,まとめてみました.

(1)A側でデータがどういう形式で保持されているのかについて
 B側では知らなくていいようにしたい
(2)B側では操作したいデータの種類を文字列で指定したいのだが,
 ・問題点1:その種類毎に,付随するデータ指定用の引数の数(型も?)が異なる.
 ・問題点2:データ種類によって,データの型が異なる.
       (B側は,各データの型が何なのかだけは知っている)
 を許容できるデータ操作関数の書き方がわからない.
(3)操作データ毎にそれ専用の関数を用意すれば何も悩まなくていいのだが
 たくさんの関数を書かないとならないのが不便だと思う.


…というわけで,質問者様的には(3)でやるのではなくて
(2)の問題点をどうにかしたい,ということなのかな?

マナ

Re: 他のソースファイルの操作関数を扱いたい

#13

投稿記事 by マナ » 10年前

そうです2です
伝え方が悪くって申し訳ありませんね

アバター
usao
記事: 1887
登録日時: 11年前

Re: 他のソースファイルの操作関数を扱いたい

#14

投稿記事 by usao » 10年前

さて,
・問題点1
に関しては,例を見た感じだと,データ種類を指し示す文字列("name"みたいなの)以外の
「0番目」とか「0列目」とかいうデータ指定用の引数については,
個数はデータ種類に応じて変わるとしても,型は int とかに固定できそうであり,
また,個数も現実にはせいぜい1個~数個 といったところではないだろうか?

そういう話であれば,
例えば,データ指定用の引数が最大で3個あれば十分な場合,
関数の型は可変個の引数とかにしなくても,こんな形でいけないだろうか?
・問題点2
に関しては,まぁ,void* でどうにか… うん.

コード:

bool Get( void *pDstData, const std::string &rDataName, int indx1=-1, int indx2=-1, int indx3=-1 )
{
	//rDataNameと,indx1~3 に応じたデータを pDstData に入れる.
	//うまくいったらtrueを,
	//引数指定が不正な場合とかには,falseを返す.
	//※または戻り値でエラーを返すのではなく例外投げちゃうとかでもいいかも.
}
[追記]
個数がもうちょっと多くないとダメなら,デフォルト引数で解決するんじゃなくて
intの配列とかで受けてもいいんじゃないかな.
あるいは,いっそのことデータ指定文字列の中に全て含めてしまって,中でパースするとか.

・問題点2
をtemplateでどうにかするのでもいいかもしれないけど,
関数の実装は,型ごとに特殊化しないとならないような気がする.
最後に編集したユーザー usao on 2014年2月19日(水) 17:35 [ 編集 1 回目 ]

マナ

Re: 他のソースファイルの操作関数を扱いたい

#15

投稿記事 by マナ » 10年前

すみません
usaoさんの関数の引数なのですが全部疑問があります。

void *pDstData void型って引数に指定できるの? 初めて見た 使い方がよくわからん
const std::string &rDataName 全く見たことがない書き方何これ?
int indx1=-1 indx まではわかるけど =-1 って何だろこの書き方だと読み込んだ値から-1引かれると予想する

できれば解説をお願いしてもよろしいですか?

マナ

Re: 他のソースファイルの操作関数を扱いたい

#16

投稿記事 by マナ » 10年前

後、もうひとつですがusaoさんの引数について私が全て理解できたとして、疑問があるのですがindx3 に値が全くないものでもその関数は使えるものなのでしょうか?

まあ、使わない事を知らせる値を入れれば問題はないと思います。

そうするとなるほど可変引数を使わなくても結果を返してくれる関数は作れそうですね。
決まっていない型を返す方法が理解できればの話ですが。

アバター
usao
記事: 1887
登録日時: 11年前

Re: 他のソースファイルの操作関数を扱いたい

#17

投稿記事 by usao » 10年前

あれ? ひょっとしてC++ではダメなのかな?

>int indx1=-1
C++では引数のデフォルト値を必要なら指定しておける.
呼び出し側で末尾側の引数が省略された場合は,その指定しておいた値が省略された引数の値として用いられる.
例えば,↑のコードで
Get( NULL, "hello", 5 );
とかいう呼び出しは
Get( NULL, "hello", 5, -1, -1 );
と書いたのと同じことになる.

>まあ、使わない事を知らせる値を入れれば問題はないと思います。
やってることの考え方はコレですね.(「使わない」ことを表す値として-1と書いてみました.)

>const std::string &rDataName
C++です.
constなstd::string型への参照です. std::string型は,文字列用の型.
'&'で書いてるのは「参照」という機能.
(別にポインタで const std::string *pDataName って書いてもいいのですけど.)

>void *
これはCの範疇ですよ.名前はたしか「総称ポインタ」です.
型が不明なやつです.使う側で本当の型にキャストしないとならないので,あまり好んで使いたくはないやつですが,
例えば,callback関数とか書くときには割と使いますよ.


全体的に,詳細はググるなどしてください
(投げやりなのではなく,掲示板に書くよりもその方が早いし確実な情報が得られると思うので)

マナ

Re: 他のソースファイルの操作関数を扱いたい

#18

投稿記事 by マナ » 10年前

すみません私C++は全く知りません
Cで同じようなものがかけるといいのですが

int や double や char や char* あたりは知ってはいますがvoid が引数は始めてみます。
っと言うよりもvoid は何も引数を指定しませんよ っと言う意味でしか知りませんでした

少々void を使った引数について調べてみますね
時間が限られているため今日私の書き込みがなかったらまた別の日になります。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 他のソースファイルの操作関数を扱いたい

#19

投稿記事 by ISLe » 10年前

可変長引数から引数の値を取り出すにはva_argマクロを使いますが、設計から見直すべきです。
(別のトピックの話題ですが)データの改竄を気にするひとが書くコードではないですね。

アバター
usao
記事: 1887
登録日時: 11年前

Re: 他のソースファイルの操作関数を扱いたい

#20

投稿記事 by usao » 10年前

引数は void じゃなくて void* ですよ.
↑の方の書き込みに[追記]で書きましたが,デフォルト引数値じゃなくて配列で指定しちゃえばCで書けますよね.
がんばってください.

コード:

//戻り値の型はどうでもいいが,まぁ{成功したら1,失敗したら0}を返すみたいな感じでintにしてみた.
int Get(
  void *pDstData,  //データを受取場所を指すポインタ.
  const char *pDataName,  //データ名文字列
  int *pIndexes  //必要なindex群の配列先頭のポインタ.
  )
{
  //pDataNameの内容をみて,データの型と,
  //pIndexesの使い方(見るべき個数)を判断する.
  // ↓
  //pDstDataを然るべきポインタ型にキャストして,そこにデータを入れる

 //※呼び出し側が正しく引数を指定しないと簡単に吹っ飛んじゃうだろうけど
  // まぁそこは仕方ないってことで※
}

マナ

Re: 他のソースファイルの操作関数を扱いたい

#21

投稿記事 by マナ » 10年前

調べてきました
http://www.nurs.or.jp/~sug/soft/tora/tora5.htm
このサイトで大体理解できました。

引数として扱うにはよさそうですね。
引き出し元に値を返すのが

usaoさんの言う 第2引数の
const std::string &rDataName
の部分なのですね

後はどのように返すかですね

で調べてる間に返信があったので
もしかして第2引数を文字列にして返すのは、後は型変換等を使えば他の型に変更できるからって事でしょうか?

それなら任意のデーターを引き出せる感じがします。

申し訳ありませんそろそろ時間です。


<ISLeさん
途中でこれだと作れないと感じたため早めに聞きました
設計のやり直しについては知ってましたよ

アバター
usao
記事: 1887
登録日時: 11年前

Re: 他のソースファイルの操作関数を扱いたい

#22

投稿記事 by usao » 10年前

引き出し元に値を返すのが

usaoさんの言う 第2引数の
const std::string &rDataName
の部分なのですね

後はどのように返すかですね

で調べてる間に返信があったので
もしかして第2引数を文字列にして返すのは、後は型変換等を使えば他の型に変更できるからって事でしょうか?
違う.全然違う.
No.20 にCでのコード例を書いたけど,
呼び出し側が情報受け取りにつかうのが void*
第二引数の文字列は,あなたのコードで"name"とか書いてるやつですよ.

ただ,それはそれとして,「文字列で情報を返して,受け側で変換する」という方法も
浮動小数点数になってるデータへの要求精度次第ではOKなのかもしれません.

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 他のソースファイルの操作関数を扱いたい

#23

投稿記事 by ISLe » 10年前

マナ さんが書きました:<ISLeさん
途中でこれだと作れないと感じたため早めに聞きました
設計のやり直しについては知ってましたよ
設計のやり直しは何のためにするのか分かってますか?
わたしの投稿をきちんと読んでくださいよ。

できるかどうかとやってよいかどうかは別の話です。

コード:

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
void get_value(const char *type, ...)
{
	int type_id = -1;
	va_list args;
	va_start(args , type);
	if (strcmp(type, "int") == 0) type_id = 0;
	else if (strcmp(type, "double") == 0) type_id = 1;
	else if (strcmp(type, "string") == 0) type_id = 2;
	switch (type_id) {
	case 0:
		{
			int *p = va_arg(args, int*);
			*p = 123;
		} break;
	case 1:
		{
			double *p = va_arg(args, double*);
			*p = 456.78;
		} break;
	case 2:
		{
			char *p = va_arg(args, char*);
			strcpy(p, "hello!");
		} break;
	}
	va_end(args);
}
int main(void)
{
	int i = 0;
	double d = 0.0;
	char s[64];
	get_value("int", &i);
	get_value("double", &d);
	get_value("string", s);
	printf("int:%d double:%f string:%s\n", i, d, s);
	return 0;
}

アバター
usao
記事: 1887
登録日時: 11年前

Re: 他のソースファイルの操作関数を扱いたい

#24

投稿記事 by usao » 10年前

オフトピック
ところで,個人的興味ですけど
「どうして」こういう方法でデータアクセスしたいのか,というバックグラウンドというか
そこらへんの話も 差し支えなければ 知りたいところですね.
(データ種を文字列で指定したいときってどういうときなんだろう?とか.)

マナ

Re: 他のソースファイルの操作関数を扱いたい

#25

投稿記事 by マナ » 10年前

遅くなりましたができました
一部は分裂したので別の関数で扱うことになります

パターンA

コード:

static struct{
char *name[2];
double d_data[2];
int i_data[4];
int regi[5];
}kya_data[2]={ {
  { "奈美" , "爆弾" }, 
  {
   43.0000 ,
   54.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   100 , 0 , 0 , 0 , 0
  } },{
  { "由美" , "湖" }, 
  {
   23.0000 ,
   76.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   0 , 0 , 0 , 0 , 100
  } }
};
 
void data_load( void ){ //テキストファイルからロード
  //略
}
 
char *kya_read( int mode1 , int mode2 , int num , int num2 ){ //読み込み

	//mode2 は計算用
	char *read_d;
	static char read_h[128];

	switch( mode1 ){
		case 0:
			read_d = kya_data[ num ].name;
			break;

		case 1:
			read_d = kya_data[ num ].pic;
			break;

		case 2:
			sprintf_s( read_h , 100 , "%d" , (int)kya_data[ num ].d_data[ num2 ] );
			read_d = (char *)read_h;
			break;

		case 3:
			sprintf_s( read_h , 100 , "%d" , kya_data[ num ].i_data[ num2 ] );
			read_d = (char *)read_h;
			break;

		case 4:
			sprintf_s( read_h , 100 , "%d" , kya_data[ num ].resi[ num2 ] );
			read_d = (char *)read_h;
			break;

	}

	return read_d;

}
 
void kya_wright( int mode , char mode2 , int num , int num2 , void *str ){

	switch( mode ){
		case 0:
			kya_data[ num ].name = (char*)str;
			break;

		case 1:
			kya_data[ num ].pic = (char*)str;
			break;

		//case 2:
		//	kya_data[ num ].d_data[ num2 ] = (double)str;
		//	break;
		//void*型 は double型 に変換できないとか言われたどうしよ

		case 3:
			switch( mode2 ){
				case '+': kya_data[ num ].i_data[ num2 ] += (int)str; break;
				case '-': kya_data[ num ].i_data[ num2 ] -= (int)str; break;
				case '*': kya_data[ num ].i_data[ num2 ] *= (int)str; break;
				case '/': kya_data[ num ].i_data[ num2 ] /= (int)str; break;
				case '=':
				default:  kya_data[ num ].i_data[ num2 ] = (int)str; break;
			}
			break;

		case 4:
			kya_data[ num ].resi[ num2 ] = (int)str;
			break;

	}

}

マナ

Re: 他のソースファイルの操作関数を扱いたい

#26

投稿記事 by マナ » 10年前

<usaoさん
<呼び出し側が情報受け取りにつかうのが void*
って事を理解したため、読み取りようではなく書き込み用と解釈しました
私が言ったことが違うのであれば、void*型でも値を戻せるって事ですね
改めて改良してみます

<浮動小数点数になってるデータへの要求精度次第ではOKなのかもしれません.
できませんでした。
コンパイルエラーになるのでどうすればいいかが分かりませんでした

マナ

Re: 他のソースファイルの操作関数を扱いたい

#27

投稿記事 by マナ » 10年前

<ISLeさん
<可変長引数から引数の値を取り出すにはva_argマクロを使いますが、設計から見直すべきです。

え、ですから可変長引数とはもっと別の問題だと思ったので、設計の仕方からおかしい事は自覚してましたよ
何がおかしいのです?

結局、可変長引数にしろってことですか?
ソースコードはありがとうございます。

これは return の形で値を返したりできないのでしょうか?

マナ

Re: 他のソースファイルの操作関数を扱いたい

#28

投稿記事 by マナ » 10年前

<usaoさん
黒い青の背景の質問の回答ですが

一キャラデータの能力地自体が多種類に渡ったり、キャラにとどまらず拠点地、アイテムのデータ、スキルデーターなどいろんなものが多種類のデーターが必要なため、どこかにそれぞれ、固定データーと変動データーを管理する場所がないと、どこにどのデーターがあるか分からなくなる上に、セーブ&ロードすらできなくなるため非常に困ってました

そのため、固定データーは特にいじる必要がないためヘッダーの形で呼び出し、変動データーは一箇所で管理しつつつ値を読み込んだり、書き込んだり、セーブ&ロードしたほうが良いかと思いました。

そのため、こういった形の関数を作ろうとしています。
これでよろしいでしょうか?

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 他のソースファイルの操作関数を扱いたい

#29

投稿記事 by ISLe » 10年前

マナ さんが書きました:え、ですから可変長引数とはもっと別の問題だと思ったので、設計の仕方からおかしい事は自覚してましたよ
何がおかしいのです?

結局、可変長引数にしろってことですか?
ソースコードはありがとうございます。

これは return の形で値を返したりできないのでしょうか?
最後の一文が何も分かってないことを顕著に表していますね。

そもそもこんな処理を書いてはいけないのですよ。
「改竄を気にするひとが書くコードではない」というのは全否定しているということだと分からないですか?

C/C++の勉強からひととおりやり直してください。
掲示板のアドバイスで改善するレベルを遥かに超えています。
そもそも日本語がまともに通じないですし。

かずま

Re: 他のソースファイルの操作関数を扱いたい

#30

投稿記事 by かずま » 10年前

なぜ、インデントを直さないのですか?
pic というメンバはありません。regi と resi とは?
本当にコンパイルできたコードを提示していますか?
変数の型についての理解がないようです。

コード:

#include <stdio.h>

struct KYA {
    char *name[2];
    double d_data[2];
    int i_data[4];
    int regi[5];
};

static struct KYA kya_data[2] = {
    {
        { "奈美", "爆弾" }, 
        { 43.0000, 54.0000, },
        { 50, 50, 50, 50 },
        { 100, 0, 0, 0, 0 }
    },
    {
        { "由美", "湖" }, 
        { 23.0000, 76.0000 },
        { 50, 50, 50, 50 },
        { 0, 0, 0, 0, 100 }
    }
};
 
int kya_read(int mode, int num, int num2, void *p)
{
    switch (mode) {
    case 0: *(char **)p = kya_data[num].name[num2]; break;
    case 2: *(double *)p = kya_data[num].d_data[num2]; break;
    case 3: *(int *)p = kya_data[num].i_data[num2]; break;
    case 4: *(int *)p = kya_data[num].regi[num2]; break;
    default: return 1;
    }
    return 0;
}
 
int kya_write(int mode, char mode2, int num, int num2, void *p)
{ 
    switch (mode) {
    case 0: kya_data[num].name[num2] = (char *)p; break;
    case 2: kya_data[num].d_data[num2] = *(double *)p; break;
    case 3:
        switch (mode2) {
        case '+': kya_data[num].i_data[num2] += *(int *)p; break;
        case '-': kya_data[num].i_data[num2] -= *(int *)p; break;
        case '*': kya_data[num].i_data[num2] *= *(int *)p; break;
        case '/': kya_data[num].i_data[num2] /= *(int *)p; break;
        default:  kya_data[num].i_data[num2] = *(int *)p; break;
        }
        break;
    case 4: kya_data[num].regi[num2] = *(int *)p; break;
    default: return 1;
    }
    return 0;
}

int main(void)
{
    char *name;  double d_data;  int i, i_data, regi;

    kya_read(0, 0, 0, &name); printf("%s ", name);
    kya_read(0, 0, 1, &name); printf("%s ", name);
    kya_read(2, 0, 0, &d_data); printf("%.4f ", d_data);
    kya_read(2, 0, 1, &d_data); printf("%.4f ", d_data);
    for (i = 0; i < 4; i++) {
        kya_read(3, 0, i, &i_data); printf("%d ", i_data);
    }
    for (i = 0; i < 5; i++) {
        kya_read(4, 0, i, &regi); printf("%d ", regi);
    }
    printf("\n");

    kya_write(0, '=', 0, 1, "名前");
    d_data = 31.4; kya_write(2, '=', 0, 0, &d_data);
    i_data = 99,  kya_write(3, '-', 0, 2, &i_data);
    regi = 77,  kya_write(4, '=', 0, 3, &regi);

    kya_read(0, 0, 0, &name);   printf("%s ", name);
    kya_read(0, 0, 1, &name);   printf("%s ", name);
    kya_read(2, 0, 0, &d_data); printf("%.4f ", d_data);
    kya_read(2, 0, 1, &d_data); printf("%.4f ", d_data);
    for (i = 0; i < 4; i++) {
        kya_read(3, 0, i, &i_data); printf("%d ", i_data);
    }
    for (i = 0; i < 5; i++) {
        kya_read(4, 0, i, &regi); printf("%d ", regi);
    }
    printf("\n");
    return 0;
}
実行結果

コード:

奈美 爆弾 43.0000 54.0000 50 50 50 50 100 0 0 0 0 
奈美 名前 31.4000 54.0000 50 50 -49 50 100 0 0 77 0 

かずま

Re: 他のソースファイルの操作関数を扱いたい

#31

投稿記事 by かずま » 10年前

引数を void * ではなく、... (<stdarg.h> を使用) に変えてみました。
void * だと、ポインタしか渡せないので、値を渡す kya_write() が
int や double の変数のアドレスを引数にしていますが、stdarg だと、
int や double の値をそのまま渡せます。kya_read() は、引数で
値を返してもらうので、こちらはポインタのままです。

コード:

#include <stdio.h>
#include <stdarg.h>
 
struct KYA {
    char *name[2];
    double d_data[2];
    int i_data[4];
    int regi[5];
};
 
static struct KYA kya_data[2] = {
    {
        { "奈美", "爆弾" }, 
        { 43.0000, 54.0000, },
        { 50, 50, 50, 50 },
        { 100, 0, 0, 0, 0 }
    },
    {
        { "由美", "湖" }, 
        { 23.0000, 76.0000 },
        { 50, 50, 50, 50 },
        { 0, 0, 0, 0, 100 }
    }
};
 
int kya_read(int mode, int num, int num2, ...)
{
    va_list ap;
    va_start(ap, num2);
    switch (mode) {
    case 0: *va_arg(ap, char **) = kya_data[num].name[num2]; break;
    case 2: *va_arg(ap, double *) = kya_data[num].d_data[num2]; break;
    case 3: *va_arg(ap, int *) = kya_data[num].i_data[num2]; break;
    case 4: *va_arg(ap, int *) = kya_data[num].regi[num2]; break;
    default: return 1;
    }
    va_end(ap);
    return 0;
}
 
int kya_write(int mode, char mode2, int num, int num2, ...)
{ 
    va_list ap;
    va_start(ap, num2);
    switch (mode) {
    case 0: kya_data[num].name[num2] = va_arg(ap, char *); break;
    case 2: kya_data[num].d_data[num2] = va_arg(ap, double); break;
    case 3:
        switch (mode2) {
        case '+': kya_data[num].i_data[num2] += va_arg(ap, int); break;
        case '-': kya_data[num].i_data[num2] -= va_arg(ap, int); break;
        case '*': kya_data[num].i_data[num2] *= va_arg(ap, int); break;
        case '/': kya_data[num].i_data[num2] /= va_arg(ap, int); break;
        default:  kya_data[num].i_data[num2] = va_arg(ap, int); break;
        }
        break;
    case 4: kya_data[num].regi[num2] = va_arg(ap, int); break;
    default: return 1;
    }
    va_end(ap);
    return 0;
}
 
int main(void)
{
    char *name;  double d_data;  int i, i_data, regi;
 
    kya_read(0, 0, 0, &name);   printf("%s ", name);
    kya_read(0, 0, 1, &name);   printf("%s ", name);
    kya_read(2, 0, 0, &d_data); printf("%.4f ", d_data);
    kya_read(2, 0, 1, &d_data); printf("%.4f ", d_data);
    for (i = 0; i < 4; i++) {
        kya_read(3, 0, i, &i_data); printf("%d ", i_data);
    }
    for (i = 0; i < 5; i++) {
        kya_read(4, 0, i, &regi); printf("%d ", regi);
    }
    printf("\n");
 
    kya_write(0, '=', 0, 1, "名前");
    kya_write(2, '=', 0, 0, 31.4);  // double の値
    kya_write(3, '-', 0, 2, 99);    // int の値 (99 を引く)
    kya_write(4, '=', 0, 3, 77);    // int の値
 
    kya_read(0, 0, 0, &name);   printf("%s ", name);
    kya_read(0, 0, 1, &name);   printf("%s ", name);
    kya_read(2, 0, 0, &d_data); printf("%.4f ", d_data);
    kya_read(2, 0, 1, &d_data); printf("%.4f ", d_data);
    for (i = 0; i < 4; i++) {
        kya_read(3, 0, i, &i_data); printf("%d ", i_data);
    }
    for (i = 0; i < 5; i++) {
        kya_read(4, 0, i, &regi); printf("%d ", regi);
    }
    printf("\n");

    return 0;
}
実行結果は、void * のときと同じです。

かずま

Re: 他のソースファイルの操作関数を扱いたい

#32

投稿記事 by かずま » 10年前

異なる型をひとつの型として扱う方法に union があります。

コード:

#include <stdio.h>
#include <stdarg.h>
 
struct KYA {
    char *name[2];
    double d_data[2];
    int i_data[4];
    int regi[5];
};
 
static struct KYA kya_data[2] = {
    {
        { "奈美", "爆弾" }, 
        { 43.0000, 54.0000, },
        { 50, 50, 50, 50 },
        { 100, 0, 0, 0, 0 }
    },
    {
        { "由美", "湖" }, 
        { 23.0000, 76.0000 },
        { 50, 50, 50, 50 },
        { 0, 0, 0, 0, 100 }
    }
};
 
union U {
    int i;
    double d;
    char *s;
};

int kya_read(int mode, int num, int num2, union U *p)
{
    switch (mode) {
    case 0: p->s = kya_data[num].name[num2]; break;
    case 2: p->d = kya_data[num].d_data[num2]; break;
    case 3: p->i = kya_data[num].i_data[num2]; break;
    case 4: p->i = kya_data[num].regi[num2]; break;
    default: return 1;
    }
    return 0;
}
 
int kya_write(int mode, char mode2, int num, int num2, union U val)
{ 
    switch (mode) {
    case 0: kya_data[num].name[num2] = val.s; break;
    case 2: kya_data[num].d_data[num2] = val.d; break;
    case 3:
        switch (mode2) {
        case '+': kya_data[num].i_data[num2] += val.i; break;
        case '-': kya_data[num].i_data[num2] -= val.i; break;
        case '*': kya_data[num].i_data[num2] *= val.i; break;
        case '/': kya_data[num].i_data[num2] /= val.i; break;
        default:  kya_data[num].i_data[num2] = val.i; break;
        }
        break;
    case 4: kya_data[num].regi[num2] = val.i; break;
    default: return 1;
    }
    return 0;
}
 
int main(void)
{
    union U val;  int i;

    kya_read(0, 0, 0, &val); printf("%s ", val.s);
    kya_read(0, 0, 1, &val); printf("%s ", val.s);
    kya_read(2, 0, 0, &val); printf("%.4f ", val.d);
    kya_read(2, 0, 1, &val); printf("%.4f ", val.d);
    for (i = 0; i < 4; i++) {
        kya_read(3, 0, i, &val); printf("%d ", val.i);
    }
    for (i = 0; i < 5; i++) {
        kya_read(4, 0, i, &val); printf("%d ", val.i);
    }
    printf("\n");
 
    val.s = "名前"; kya_write(0, '=', 0, 1, val);
    val.d = 31.4;   kya_write(2, '=', 0, 0, val);
    val.i = 99;     kya_write(3, '-', 0, 2, val);
    val.i = 77;     kya_write(4, '=', 0, 3, val);
 
    kya_read(0, 0, 0, &val); printf("%s ", val.s);
    kya_read(0, 0, 1, &val); printf("%s ", val.s);
    kya_read(2, 0, 0, &val); printf("%.4f ", val.d);
    kya_read(2, 0, 1, &val); printf("%.4f ", val.d);
    for (i = 0; i < 4; i++) {
        kya_read(3, 0, i, &val); printf("%d ", val.i);
    }
    for (i = 0; i < 5; i++) {
        kya_read(4, 0, i, &val); printf("%d ", val.i);
    }
    printf("\n");

    return 0;
}
実行結果は、void * のときと同じです。

閉鎖

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