zoukankan      html  css  js  c++  java
  • 打印完整的递归调用栈

    之前在写0-1背包问题的递归解法时,想要弄出完整的递归栈。尝试了使用debug工具手工追踪并画出调用栈,发现太麻烦了,又试了一下使用visual studio的code map功能,发现对于递归,它只会显示递归函数不断调用自己,并不会自动展开成为树的形式。所以我就使用了最简陋的办法,就是自己写了一个类,依赖C++的constructor和destructor来自动将栈输入到一个vector中,并且在main函数结束的地方添加一个语句将其内容输出到文件中。

    这里使用了一些C++11的特性,我使用mingw和msvc2015编译通过了,其它的编译器就不知道了。

    下面是这个类的代码,写的很不完善:

    //stacktrace.h
    1. #ifndef STACKTRACE_H
    2. #define STACKTRACE_H
    3. #include <iostream>
    4. #include <string>
    5. #include <vector>
    6. /**
    7. * 这个类还比较简单粗暴,没有实现字符串格式化参数的软编码(如果需要可以使用boost::format()来像sprintf()一样格式化),
    8. * 也没有作为模板类实现以完成可变形参构造函数(注意不要使用C语言的va_arg)。
    9. * 使用的时候需要根据需求进行修改。
    10. *
    11. * 使用方法:
    12. * 在main函数中setSpaceLength(unsigned length)来控制格式,如果不做这一步,则默认spaceLength = 4
    13. * 在需要进行stack trace的函数所在的文件中include "stacktrace.h"
    14. * 在需要进行stack trace的函数开头加上一句 StackTrace(capacity, itemNum); capacity和itemNum是需要打印到stack trace的数据
    15. * 在main函数的结尾加上一句writeToFile(std::ostream &os, StackTrace::outputType type = reformat);
    16. *
    17. * 如果需要修改这个类的显示效果,只需要修改 StackTrace(double capacity, int itemNum);
    18. * 注意:每一行的结束需要写入一个换行符
    19. *
    20. */
    21. class StackTrace
    22. {
    23. private: //private data field
    24. static int depth;
    25. static std::vector<std::string> content;
    26. static unsigned spaceLength;
    27. static std::vector<unsigned> firstNotSpace;
    28. public: //public data field
    29. enum outputType{raw,reformat};
    30. public: //constructor and copy control
    31. StackTrace(double capacity, int itemNum);
    32. virtual ~StackTrace()
    33. {
    34. --depth;
    35. }
    36. public: //public member function
    37. static void setSpaceLength(unsigned length);
    38. static void writeToFile(std::ostream &os, outputType type = reformat);
    39. private: //private member function
    40. static void clear();
    41. static void outputResult(std::ostream &os);
    42. static void generateFirstNotSpace();
    43. static void textReplace();
    44. };
    45. #endif // RECURSIONSTACKTRACE_H

    //stacktrace.cpp
    1. #include "stacktrace.h"
    2. #include <sstream>
    3. #include <iostream>
    4. #include <vector>
    5. #include <string>
    6. #include <fstream>
    7. #include <cstdlib>
    8. using namespace std;
    9. int StackTrace::depth = 0;
    10. std::vector<std::string> StackTrace::content;
    11. unsigned StackTrace::spaceLength = 4;
    12. std::vector<unsigned> StackTrace::firstNotSpace;
    13. void StackTrace::clear()
    14. {
    15. content.clear();
    16. firstNotSpace.clear();
    17. }
    18. void StackTrace::setSpaceLength(unsigned length)
    19. {
    20. spaceLength = length;
    21. }
    22. StackTrace::StackTrace(double capacity, int itemNum)
    23. {
    24. ++depth;
    25. ostringstream temp;
    26. int i;
    27. for(i = 0;i<depth-1;++i)
    28. {
    29. for(unsigned j= 0;j<spaceLength;++j)
    30. temp << " ";
    31. //cout << " ";
    32. }
    33. if(i<depth)
    34. {
    35. if(spaceLength==0)
    36. ; //null statement
    37. else
    38. {
    39. temp << "└";
    40. for(unsigned j=0; j<spaceLength-1; ++j)
    41. temp << "-";
    42. }
    43. }
    44. temp << "(" << itemNum << ", " << capacity << ")" << endl;
    45. content.push_back(temp.str());
    46. }
    47. void StackTrace::writeToFile(std::ostream &os, outputType type)
    48. {
    49. if(type == reformat)
    50. {
    51. generateFirstNotSpace();
    52. textReplace();
    53. }
    54. outputResult(os);
    55. clear();
    56. }
    57. void StackTrace::outputResult(ostream &os)
    58. {
    59. for(const string &temp:content)
    60. os << temp;
    61. os << flush;
    62. }
    63. void StackTrace::generateFirstNotSpace()
    64. {
    65. for(size_t i= 0; i<content.size();++i)
    66. firstNotSpace.push_back(content[i].find_first_not_of(' '));
    67. }
    68. void StackTrace::textReplace()
    69. {
    70. for(size_t i=1; i<content.size();++i)
    71. {
    72. size_t pos = 0;
    73. while((pos = content[i].find("└",pos)) != string::npos)
    74. {
    75. for(int j = i-1;j>=0;--j)
    76. {
    77. if(firstNotSpace[j]==string::npos)
    78. continue;
    79. if(firstNotSpace[j] <= pos )
    80. goto END2LOOP;
    81. else
    82. {
    83. content[j][pos] = '|';
    84. continue;
    85. }
    86. }
    87. }
    88. END2LOOP: ;
    89. }
    90. }

    以下是结果范例:
    1. └---(5, 3)
    2. └---(4, 1)
    3. | └---(3, 0)
    4. | └---(3, 1)
    5. | └---(2, 1)
    6. | └---(1, 0)
    7. | └---(1, 1)
    8. | └---(0, 0.9)
    9. | | └---(-1, 0.6)
    10. | | └---(-1, 0.9)
    11. | └---(0, 1)
    12. | └---(-1, 0.7)
    13. | └---(-1, 1)
    14. └---(4, 3)
    15. └---(3, 2)
    16. | └---(2, 2)
    17. | └---(1, 1)
    18. | | └---(0, 0.9)
    19. | | | └---(-1, 0.6)
    20. | | | └---(-1, 0.9)
    21. | | └---(0, 1)
    22. | | └---(-1, 0.7)
    23. | | └---(-1, 1)
    24. | └---(1, 2)
    25. | └---(0, 1.9)
    26. | | └---(-1, 1.6)
    27. | | └---(-1, 1.9)
    28. | └---(0, 2)
    29. | └---(-1, 1.7)
    30. | └---(-1, 2)
    31. └---(3, 3)
    32. └---(2, 3)
    33. └---(1, 2)
    34. | └---(0, 1.9)
    35. | | └---(-1, 1.6)
    36. | | └---(-1, 1.9)
    37. | └---(0, 2)
    38. | └---(-1, 1.7)
    39. | └---(-1, 2)
    40. └---(1, 3)
    41. └---(0, 2.9)
    42. | └---(-1, 2.6)
    43. | └---(-1, 2.9)
    44. └---(0, 3)
    45. └---(-1, 2.7)
    46. └---(-1, 3)



    这里有别人写的类似的类:





  • 相关阅读:
    Java中关系操作符==的学习以及与equals的对比
    关于alibaba.fastjson的使用
    给有C或C++基础的Python入门 :Python Crash Course 1
    快速幂基本模板
    断言封装及应用(有难度)
    断言封装之key检查及kv实战示例
    正则取值及断言实战示例
    关联实现下-jsonpath取值(有难度!!耗时长)
    关联实现上-jsonpath取值
    requests顺序执行实现
  • 原文地址:https://www.cnblogs.com/cmicat/p/4596409.html
Copyright © 2011-2022 走看看