
いつもお世話になっています。
C言語の質問です。
単体テストログを取るために、
“関数Aをコールする前後で、関数Aに引数として渡す構造体のメンバをすべて”printf(もしくはfprintf)で出力して比較確認しなければならないのですが、
構造体のメンバが250とか、150とかあり、メンバ名もxxx_01,xxx_02などのようにエクセルなどで簡単に加工して作れるものではないので、いちいちメンバ名を指定しなければならないのでとても大変です。
オブジェクト指向言語なら、for each文とかでオブジェクトのメンバを簡単に取り出せるのでしょうが(間違っているかもしれません・・・)、C言語で構造体のメンバを、for文などのループを使って簡単に出力できる方法はないでしょうか?
メンバの型は、一定ではなく、char、int、double、別の構造体のポインタ型(これは出力しなくて良い)と混在しています。メンバが全て同一の型ならポインタで構造体の先頭アドレスからsizeof(メンバの型)の分インクリメントしていけば出力できそうな気もしますが、メモリ上に連続して確保されるのかも私にはわからないので困っています。
enumで列挙して・・・というのも調べてみましたが、応用は出来ないようでした。
どなたか、地道にメンバ名を書いて出力する以外の方法をご存知の方、いらっしゃいましたらお知恵をお貸しください。
よろしくお願いいたします。
※説明不足の点がありましたら補足いたします。
No.5ベストアンサー
- 回答日時:
コードを書かないという方向性の提案を一つ。
デバッガに構造体の内容を出力させるというのはどうでしょうか。
struct {
int a;
char *b;
double c;
}
という型を持つ変数xがあったとして、gdbでは下記のような出力が得られます。
(gdb) print x
$1 = {
a = 123,
b = 0x2fd0 "ABC",
c = -9876.5
}
この回答への補足
gdbは、プロジェクト方針で「使用しない」とのことですが、インストールはされていたので使用してみました。思っていたほど難しくなく、デバッグがとても便利になりました。大変役に立つアドバイスありがとうございました。
補足日時:2008/12/19 12:07ご回答ありがとうございます。
家庭内で不慮の悲しい出来事があり御礼が遅れてしまい申し訳ありません。
gdbは導入しておらず(なぜ?)、他にメモリリーク検出のvalgrindなども導入されていないので使用できませんでした。
私自身gdbは名前を知っている程度でしたので、このような使い方が出来るとは知りませんでした。勉強してみたいと思います。
大変参考になる意見ありがとうございました。
No.4
- 回答日時:
#2です。
cvsはcsvの誤りです。
メンバ型はB列にしましたが、最右列にしておけば加工後に列削除や非表示にしなくても選択するときに除くことができます。
やりやすいようにどうぞ。
No.3
- 回答日時:
こんなのはどうでしょう?
#ifdef DUMP
# define STRUCT(name) void dump_##name(const struct name *data, FILE *stream) {
# define END_STRUCT }
# define MEMBER(type, name) print_##type(data->name);
#else
# define STRUCT(name) struct name {
# define END_STRUCT };
# define MEMBER(type, name) type name;
#endif
といったマクロを定義しておいて、
STRUCT(foo)
MEMBER(int, hoge)
MEMBER(double, bar)
...
END_STRUCT
のようにすれば、DUMPマクロの定義状態によって、構造体の定義とダンプ用の関数を生成できるはずです。
ご回答ありがとうございます。
家庭内で不慮の悲しい出来事があり御礼が遅れてしまい申し訳ありません。
マクロは確かに便利そうですね。
マネージャに相談してみたのですが「可読性が低くなる」とのことで却下されてしまいました。。
せっかくお答えいただいたのに申し訳ありません。
今後の参考にさせていただきます。
No.2
- 回答日時:
excelにメンバの型とメンバ名だけをコピーしてから加工→エディタにコピーすればそんなに手間じゃないですよ。
excel側
A列:「printf("」
B列:メンバ型をコピー
C列:メンバ名をコピー
D列:「=if(B1="char *", " %s", if(B1="double", " %lf", " %d"))」
E列:「\n", XXX.」(XXXは構造体変数名)
F列:「=C1」
G列:「);」
A、D~G列をオートフィルでメンバ行数分コピーしたらB列を削除するか非表示にして全選択し、エディタに貼り付けします。
エディタ側では列と列の間がタブで区切られているので、置換機能でタブを削除すればメンバが200でも1000でもあっと言う間に出力文完成。
こんな風。
printf("memb1 %s\n", XXX.memb1);
printf("memb2 %lf\n", XXX.memb2);
…
windowsだったらsakuraエディタのように矩形選択が使えるエディタならメンバ型、名をexcelにコピーするのも楽ですね。
矩形選択が出来ないのならcvsにしてからexcelで読み込むという手間がかかるかな。
ご回答ありがとうございます。
家庭内で不慮の悲しい出来事があり御礼が遅れてしまい申し訳ありません。
エクセルで加工するのが便利ですね。
ただ、行数が多くなってしまうのでうまくいかないものかな・・・(ループ文とかで短いコードで処理)と思い質問させていただきました。
sakuraエディタは出向先の意向により使用できない(同じく矩形選択できるemエディタなども使用できない、使用できるのは秀丸のみ)なので矩形選択ができないのがつらいところです。
No.1
- 回答日時:
そんな便利機能はないので、地道に書くしかありません。
いっそ「構造体の定義を解析してprintf()に変換する」プログラムを書いてしまうのが楽かもしれませんね。
しかしメンバーが100超えって……も少しコンパクトな単位に分けられなかったんでしょうか?
for eachにしても例外はあるかもしれませんが「配列の各要素を先頭から終端まで」なので構造体メンバーの取得には使えません。
ご回答ありがとうございます。
帰宅が遅くなってしまいましたので、とりあえず#1様の欄に返信させていただきます。
#2~#5の方につきましても、後日回答をさせていただきます。
まことに勝手で申し訳ありませんが、ご了承ください。
回答ですが、やはりそのような便利機能はありませんか。
今は、複数ある構造体ごとにそれぞれのメンバを出力する専用関数を作ろうかと考えています。
システムは金融系なのですが、DBのテーブルのカラムをコピーしてExcel2003に貼り付けたら、長すぎて貼り付けられませんでしたので、カラム数だけでExcelの横幅256項目を超えているようです。
構造体もネストの嵐で、ポインタを*、ダブルポインタを**で書くと、
引数として受け取る*構造体Aのメンバに*構造体Bと構造体Cがあり、
*構造体Bのメンバには構造体D配列があり、構造体D各々のメンバに構造体Eがある。
構造体Cのメンバには構造体Fがある。
そして関数には構造体Aの配列として**構造体A配列が渡される・・・
のような(私にはもう何がなにやら・・・の)つくりになっています。
それぞれ、メンバ数は30~250以上とさまざまです。
金融系のシステムって、こんなにデータ使うのか・・・と驚愕している次第です。。
古いシステムのようで、COBOLをC言語でラッパしているようです。
私としては、オブジェクト指向言語で作ればもっと扱いやすくなるのではないか・・・と考えているのですが、なにぶんこの金融危機でお金がないらしくコストのかかる開発はできないようです。
私は元々はVB系(の後にJava経験多少アリ)でしたので、Join関数やSplit関数、LBound関数、UBound関数、Redim関数・・・使い慣れていたものがことごとくC言語に存在しないのでマシン語に近い高級言語とはこういうものかと、良くも悪くもよい経験をさせてもらっています。
私の開発効率が低く、休日出勤になってしまいそうで皆様へのお返事は遅れてしまうかもしれませんが、必ずお返事はいたしますのでしばらくお待ちいただけますようお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 2 2022/07/21 00:02
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- JavaScript オブジェクト配列の各メンバを任意の式で評価して、その評価値が最大のオブジェクトを返す関数はありますか 2 2023/05/20 15:02
- 会社・職場 一人のメンバだけに土日出勤がある面倒な作業を丸投げ、一方で、上司とそれ以外の同僚達はそのメンバだけハ 4 2023/07/21 10:31
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語(構造体) 3 2022/07/05 20:08
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- 哲学 説得力を修辞の巧みさまたは論理の強さの2つに分析するにはどうすると良いでしょうか? 0 2022/07/20 05:46
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
このQ&Aを見た人はこんなQ&Aも見ています
-
構造体のメンバをfor文で回したい
C言語・C++・C#
-
C言語のポインターに関する警告
C言語・C++・C#
-
バッファとは何ですか
C言語・C++・C#
-
-
4
文字列の切り出し
C言語・C++・C#
-
5
GDBデバッガの使い方について
C言語・C++・C#
-
6
char*を初期化したいのですが
C言語・C++・C#
-
7
INT64対応のprintf系関数はありますか?
C言語・C++・C#
-
8
DataGridViewでセルクリックイベントを発生させるには
Visual Basic(VBA)
-
9
C言語 配列の長さの上限
C言語・C++・C#
-
10
#if 1 #elseの意味について
C言語・C++・C#
-
11
C言語初心者の質問失礼します。
C言語・C++・C#
-
12
c言語でAからZまでを表示するプログラム
C言語・C++・C#
-
13
プログラムについての質問です。 fflush(stdout)はいったいどのような時に使われているので
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VisualStudio2022でC言語プログ...
-
c言語
-
C言語のことです。写真(見にく...
-
visual studio 2022でのC#プロ...
-
C#でTreeViewのCheckBoxのサイ...
-
C# で 数式文字列処理を処理す...
-
VisualStudioでC++クラスを追加...
-
ArduinoでMouse関数を使用して...
-
VisualStudioで、コードを印刷...
-
gcc13.2のバグ?
-
スタックフレームの消滅
-
【C言語】全角文字の配列を、全...
-
Windows Formアプリからコンソ...
-
C言語の関数のextern宣言
-
プログラマー達は何故、プログ...
-
PIC12F1822でLED調光器を作りたい
-
最初に聞かれたこと
-
C言語 関数、変数の宣言について
-
C言語について(初心者)
-
プログラミングc++を全く分か...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語
-
gccを行ってもexeファイルが生...
-
大量のデータを読み込んで表示...
-
visual studio 2022でのC#プロ...
-
C++でデスクトップGUIアプリ開...
-
【C言語】全角文字の配列を、全...
-
Windows Formアプリからコンソ...
-
VisualStudio2022でC言語プログ...
-
C#でログファイルにファイルパ...
-
C#でTreeViewのCheckBoxのサイ...
-
c#のTLS1.2での通信について
-
VisualStudioでC++クラスを追加...
-
C言語について。
-
int16_t の _t は何?
-
プログラマー達は何故、プログ...
-
逆コンパイルと逆アセンブルの...
-
C言語の関数のextern宣言
-
c言語でイベントフラグを使った...
-
C言語 関数、変数の宣言について
-
[C言語]fputsとfprintfの違い
おすすめ情報