Возможность создания дампов в C ++, таких как var_dump () в PHP? - PullRequest
22 голосов
/ 06 мая 2009

Когда я учился в колледже, я немного занимался C / C ++, но в ближайшем будущем я работал на PHP, и теперь я хочу уделить больше времени изучению C / C ++.

В PHP я использовал print_r () или var_dump () для отображения данных из структур или массивов. У меня есть такая функциональность по умолчанию в C, чтобы увидеть, что у меня есть в структуре или массиве?

Ответы [ 6 ]

16 голосов
/ 06 мая 2009

Нет такой функциональности в C ++. Конечно, вы можете написать свои собственные функции Dump (). Причина, по которой такая возможность обычно не может быть предоставлена, заключается в том, что процесс компиляции C ++ удаляет метаданные объекта, необходимые для структурирования вывода дампа. Конечно, вы можете отображать содержимое структуры в отладчике, где такие метаданные хранятся в отладочной информации.

Кстати, вы спрашиваете о C или C ++? Эти два языка довольно разные, как по функциям, так и по подходу, хотя ни один из них не имеет var_dump () или похожих.

6 голосов
/ 18 февраля 2015

C ++ сам по себе не предоставляет что-то вроде var_dump, но с такими библиотеками, как Boost.Fusion и средствами ADAPT_STRUCT и ADAPT_ADT, это легко выполнимо.

Действительно, как сказано в другом ответе, компилятор C ++ не генерирует метаданные, необходимые для генерации такого вывода. Однако возможно генерировать эти метаданные и использовать немного шаблонного метапрограммирования для их использования.

Таким образом, я реализовал здесь adapted_struct_printer, который может печатать std :: container, любые классы или структуры, boost :: option и boost :: tuple.

Новое решение

Теперь вы можете легко сделать следующее:

#include <iostream>
#include <pre/json/to_json.hpp>

struct customer {
  std::string name;
  size_t money_spent;
  std::vector<std::string> interests;
};

BOOST_FUSION_ADAPT_STRUCT(customer,
  name,
  money_spent,
  interests)

...

customer my_customer{
  "Mr. Dupond",
  1000,
  {"sport articles", "food", "tools"}
};

std::cout << pre::json::to_json(my_customer) << std::endl;

Вы можете использовать эту библиотеку в обратном порядке, а также сделать из_json заполнение структур из json.

Документация доступна здесь: http://daminetreg.github.io/lib-cpp-pre/html/namespacepre_1_1json.html#a4325d2cdd64a7e321303fd4428f298b9

СТАРЫЙ Ответ

Единственное требование - вы должны вызывать BOOST_FUSION_ADAPT_STRUCT / BOOST_FUSION_ADAPT_ADT для своих классов (см. http://www.boost.org/doc/libs/1_57_0/libs/fusion/doc/html/fusion/adapted.html)

Так вот этот пример:

#include <iostream>

#include <swissarmyknife/boost/fusion/adapted_struct_printer.hpp>

#include <boost/fusion/include/define_struct.hpp>
#include <boost/variant.hpp>
#include <boost/tuple/tuple.hpp>


namespace bla {

  struct someclass {
     int i = 12;
     int j = 15;
  };

  using boost::fusion::detail::operator <<;
}

BOOST_FUSION_ADAPT_STRUCT(bla::someclass,
  (int, i)
  (int, j)
)

BOOST_FUSION_DEFINE_STRUCT((bla), innerbim,
    (std::string, mystring)
    )

BOOST_FUSION_DEFINE_STRUCT((bla), bimbim,
    (int, boom)
    (int, bam)
    (bla::innerbim, my_inner_bim)
    )


typedef boost::variant<int, double, bla::innerbim> myvariant_t;
typedef boost::tuple<std::string, int, bla::innerbim, myvariant_t> my_tuple_t;


BOOST_FUSION_DEFINE_STRUCT((bla), blabla,
    (bla::bimbim, bim)
    (int, i)
    (int, j)
    (std::vector<double>, list)
    (std::list<bla::bimbim>, list_of_bimbim)
    (my_tuple_t, mytuple)
    (myvariant_t, myvariant)
    )

int main(int argc, char** argv) {
  using namespace swak;

  bla::blabla instance{
    {22, 12, bla::innerbim{"COOL"} }, 
    23,
    43, 
    {2.00, 39.07, 24.05},
    { 
      {24, 9, bla::innerbim{"FEEL GOOD"} },
      {26, 14, bla::innerbim{"SO BAD"} },
    },
    {"Hey that's not an int", 1, bla::innerbim{"hello"}, 12},
    bla::innerbim("I'm in the variant")
  };
  std::cout << instance << std::endl;

  bla::someclass otherinstance{};
  std::cout << "Other instance : " << otherinstance << std::endl;

  return 0;
}

Распечатывает следующее:

{
    bim :
        {
            boom : 22,
            bam : 12,
            my_inner_bim :
                {
                    mystring : COOL,
                }
        }
    i : 23,
    j : 43,
    list : [2, 39.07, 24.05],
    list_of_bimbim : [    
        {
            boom : 24,
            bam : 9,
            my_inner_bim :
                {
                    mystring : FEEL GOOD,
                }
        }
    ,     
        {
            boom : 26,
            bam : 14,
            my_inner_bim :
                {
                    mystring : SO BAD,
                }
        }
    ],
    mytuple :
        {
            0 (Ss) : Hey that's not an int,
            1 (i) : 1,
            2 (N3bla8innerbimE) :
                {
                    mystring : hello,
                }
            3 (N5boost7variantIidN3bla8innerbimENS_6detail7variant5void_ES5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_EE) : 

                {
                    12}
        }
    myvariant : 

        {

            {
                mystring : I'm in the variant,
            }
        }
}

Other instance :     
    {
        i : 12,
        j : 15,
    }

Я улучшаю реализацию, чтобы в какой-то момент получить ее как возможную новую функцию в Boost Fusion, но ее уже можно использовать, как показано там:

https://github.com/daminetreg/lib-cpp-swissarmyknife/blob/feature/adapted_struct_printer_improved/test/adapted_struct_printer.cpp

1 голос
/ 08 сентября 2015

В статье о Microsoft есть какое-то решение:

вектор :: push_back

https://msdn.microsoft.com/pt-br/library/7fthz5xd.aspx

template <typename T> void print_elem(const T& t) {
    cout << "(" << t << ") ";
}

template <typename T> void print_collection(const T& t) {
    cout << "  " << t.size() << " elements: ";
    for (const auto& p : t) {
        print_elem(p);
    }
    cout << endl;
}

и призыв к этому:

cout << "vector data: " << endl;
print_collection(v);
1 голос
/ 05 марта 2015

Возможно, но потребовалось бы много работы, если бы были включены символы отладки и все оптимизации были отключены. Также это будет медленно и, возможно, не очень надежно [* 1].

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

Некоторые отладчики могут быть автоматизированы, поэтому, возможно, сама функция дампа будет записана в отладчике.

* 1, например отладчики иногда дают сбой при работе с некоторыми точками останова. например Программа должна иметь точку останова и остановить все потоки, прежде чем пытаться сбросить данные. например программы, которые должны иметь дело с прерываниями в реальном времени, вероятно, не будут работать. например отладчик должен быть достаточно надежным, чтобы справляться с множеством точек останова и не создавать других проблем.

0 голосов
/ 06 мая 2009

Нет, нет. Используйте отладчик, например ddd . У большинства интегрированных сред разработки одна интегрированная.

0 голосов
/ 06 мая 2009

Нет, вы должны свернуть свою собственную, используя одну из семейства функций вывода cout или C printf для пользовательских структур данных. Точно так же для массивов (кроме строк в стиле C) вам придется перебирать все элементы и печатать каждый из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...