преобразование имени переменной в строку в C ++ - PullRequest
22 голосов
/ 02 августа 2010

Я хотел бы вывести некоторые данные в файл.Например, предположим, что у меня есть два вектора значений типа double:

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

. Есть ли простой способ вывести это в файл, чтобы первая строка содержала заголовки «data1» и «data2», за которыми следовало бы фактическое содержимое,Функция, которая выводит данные, будет передаваться в различные массивы, поэтому жесткое кодирование имени заголовка невозможно - в идеале я хотел бы преобразовать имя переменной в некоторую строку, а затем вывести эту строку, за которой следует содержимое векторного массива.Однако я не уверен, как преобразовать имя переменной «data1» в строку, или, действительно, если это легко сделать (читая форумы, я думаю, что это невозможно). Если это невозможно, альтернативой может бытьиспользовать ассоциативный контейнер, такой как map или, возможно, более просто контейнер 'pair'.

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

Любые предложения приветствуются!

Ответы [ 7 ]

39 голосов
/ 02 августа 2010

Вы можете использовать препроцессор "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>. Но этого должно быть достаточно.)

8 голосов
/ 29 сентября 2016

попробуйте это:

#define GET_VARIABLE_NAME(Variable) (#Variable)

// в функциях

int var=0;    
char* var_name= GET_VARIABLE_NAME(var);
2 голосов
/ 06 сентября 2016

У меня была такая же проблема. После небольшого эксперимента я создал следующие макросы, которые преобразуют имена переменных, полей, функций, методов и типов в строки.

#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 голосов
/ 06 апреля 2015

Немного адаптировано из ответа @ sarnold для C ++:

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

Пример программы, которая использует это:

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

    return 0;
}
2 голосов
/ 02 августа 2010

Вы можете использовать препроцессор, есть токен stringify, но он доступен только из источника, а не функции (вы получите имя аргумента).

1 голос
/ 02 августа 2010

Я бы подумал, что очевидный ответ - заставить функцию, которая выполняет вывод, принимать текст заголовка в качестве строкового параметра.

0 голосов
/ 05 февраля 2018

Для этого случая я сделал макрос nameof () . Возвращает std :: string имя переменной, типа или члена. Это работает как nameof () в C #.

Например:

#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
...