web-dev-qa-db-ja.com

C ++で変数名を文字列に変換する

一部のデータをファイルに出力したい。たとえば、2つのdoubleのベクトルがあるとします。

vector<double> data1(10);
vector<double> data2(10); 

これをファイルに出力して、最初の行に「data1」と「data2」という見出しが含まれ、その後に実際の内容が続くようにする簡単な方法はありますか?データを出力する関数にはさまざまな異なる配列が渡されるため、見出しの名前をハードコーディングすることはできません-理想的には、変数名を文字列に変換してから、その文字列に続いてベクトル配列の内容を出力します。ただし、変数名「data1」を文字列に変換する方法がわからない、または実際にそれが簡単に実行できるかどうかはわかりません(フォーラムを読んで、私の推測ではそうはできないと思います)。マップなどの連想コンテナ、またはおそらくより単純に「ペア」コンテナを使用します。

pair<vector<double>,string> data1(10,'data1');  

どんな提案も歓迎します!

26
Wawel100

プリプロセッサ「stringify」を使用できます#やりたいことを行うには:

#include <stdio.h>

#define PRINTER(name) printer(#name, (name))

void printer(char *name, int value) {
    printf("name: %s\tvalue: %d\n", name, value);
}

int main (int argc, char* argv[]) {
    int foo = 0;
    int bar = 1;

    PRINTER(foo);
    PRINTER(bar);

    return 0;
}


name: foo   value: 0
name: bar   value: 1

printfをごめんなさい。私は<iostream>。しかし、これで十分です。)

39
sarnold

これを試して:

#define GET_VARIABLE_NAME(Variable) (#Variable)

//関数内

int var=0;    
char* var_name= GET_VARIABLE_NAME(var);
8
SaeidMo7

プリプロセッサを使用できます。文字列化トークンがありますが、これはソースからのみ使用でき、関数には使用できません(引数名を取得します)。

2
Puppy

C++の場合、@ sarnoldの回答からわずかに変更:

#define DEBUG(x) std::cout << #x << " = " << x << std::endl;

これを使用するプログラム例:

int main() {
    int foo = 1;
    DEBUG(foo);

    return 0;
}
2
thiagowfx

私も同じ問題を抱えていました。少し実験した後、変数、フィールド、関数、メソッド、型の名前を文字列に変換する次のマクロを作成しました。

#define MACRO_VARIABLE_TO_STRING(Variable) (void(Variable),#Variable)

#define MACRO_FUNCTION_TO_STRING(Function) (void(&Function),#Function)

#define MACRO_METHOD_TO_STRING(ClassName,Method) (void(&ClassName::Method),#Method)

#define MACRO_TYPE_TO_STRING(Type) (void(sizeof(Type)),#Type)

このコードでは、コンマ演算子とvoid変換を使用して、変数や関数などが実際に存在するかどうかをコンパイラーに強制的に確認させます。良い点は、初期化されていない変数でもうまく機能することです。 VCとGCCの両方でテストしましたが、警告メッセージなしで判明したすべての詳細オプションを使用しました。

int GetAndPrintValue(const char* VariableName)
{
   std::cout << VariableName << std::endl;
   return 10;
}

int Variable=GetAndPrintValue(MACRO_VARIABLE_TO_STRING(Variable));

入力ストリームからデータを読み取るパーサーを作成するときにこのようなコードを使用し、解析された変数が範囲外の場合、妥当性チェックに失敗した変数の名前で例外をスローします。

2
Timmy_A

私は、明白な答えは、出力を実行する関数に見出しテキストを文字列パラメーターとして取るようにすることだと思っていました。

1
anon

この場合、私は nameof() マクロを作成しました。変数、型、またはメンバーのstd :: string名を返します。 C#ではnameof()のように機能します。

例えば:

#include "nameof.h"

std::vector<double> data1(10);
std::string name = nameof(data1); // "data1"

struct Foo1
{
    struct Foo2
    {
        Foo1* foo1;
    };

    Foo1* foo1;
    Foo2 foo2;
};

name = nameof(Foo1::foo1->foo2.foo1); // "foo1"

name = nameof(123); // std::logic_error exception
0
Dmitry Bravikov