一个很好用的调试辅助类,使用需要一定C++基础
2008-09-15 21:45
369 查看
很多时候我们需要把程序运行过程中的一些临时变量显示出来,一般我们可以通过wcout或cout类将调式信息输出到控制台。但有时我们需要将调试信息输出到别的地方,比如VS.net的“输出”窗口就比较麻烦了,可能需要频繁的在字符串和数字间相互转换,这对于C++程序员来说可真是一场恶梦。下面提出一种方案,可以很好的解决这个问题。即利用替换wcout或cout的内部字符串缓存的方法,使写入到wcout或cout的字符串转写到其它的设备中。
第一步:在你整个工程的头文件,比如stdafx.h里的下面加入以下代码。这是用于wcout或cout的字符串缓存类。
C/C++ code
第二步:在包含(#include)第一步所选头文件的任意一个代码文件(*.cpp)顶部,包含头文件说明的下面加入如下代码。在这里我们对字符串缓存类的对象进行了初始化,并自己定义了一个回调函数。该回调函数将接受来自缓存类的调式自符串,然后将它输出到VS.net的“输出”窗口。当然,你也可以自己定义这样一个回调函数使字符串写入磁盘映像或SOCKET之类更复杂的设备。
C/C++ code
第三步:在任意一个类的初始化里加入如下代码(两行任选其一):
C/C++ code
之后就可以方便的使用wcout或cout进行GDI程序的调式了,写入wcout或cout的字符串将全部显示在VS.net的“输出”窗口中。
使用举例:
C/C++ code
第一步:在你整个工程的头文件,比如stdafx.h里的下面加入以下代码。这是用于wcout或cout的字符串缓存类。
C/C++ code
#include <iostream> #include <algorithm> #include <sstream> #include <tchar.h> using namespace std; template<class _Elem, class _Traits = char_traits<_Elem> > class CDebugStreamBuf : public basic_stringbuf<_Elem, _Traits > { // 回调函数接受一个准备输出到设备的字符串参数。 public: // 如果回调函数返回false,缓存对象的_Mystate将被设为BAD,并不再继续写入。 typedef bool (__stdcall *_Myof)( const _Elem* ); explicit inline CDebugStreamBuf( _Myof _Outfunc ) : _Myoutfunc( _Outfunc ){} // 初始化回调函数 virtual ~CDebugStreamBuf( void ){} // 虚析构函数 protected: // 每次同步都会刷新缓存中的所有内容 virtual int sync( void ) // 重载sync函数,将在需要输入到设备(同步)时被调用 { // 如果无回调函数或缓冲未初始化,返回错误。_Mystate将被设为BAD if ( _Myoutfunc == 0 || pptr() == 0 ) return -1; else if ( _Mysb::pbase() >= _Mysb::epptr() ) return 0; else // 确保缓存可以写入 { // 将当前写指针的后一位改写为0,如果缓存长度不足将调用overflow执行添加 sputc( _Traits::to_char_type( 0 ) ); setg( pbase(), pbase(), pptr() ); // 将读指针设为缓存起点 seekpos( 0, ios_base::out ); // 将写指针置0以备下次从起点写入 for ( ; gptr() < egptr(); ) // 遍例 { //忽略包括当前指针在内后面的所有0值 for ( ; !sbumpc(); ); if ( !_Myoutfunc( gptr() - 1 ) ) return -1; // 输出字符串 gbump( (int)( find( gptr(), egptr(), // 找到下一个0值 _Traits::to_char_type( 0 ) ) - gptr() + 1 ) ); } } return 0; } protected: _Myof _Myoutfunc; // 回调函数成员,必须在构造时初始化 };
第二步:在包含(#include)第一步所选头文件的任意一个代码文件(*.cpp)顶部,包含头文件说明的下面加入如下代码。在这里我们对字符串缓存类的对象进行了初始化,并自己定义了一个回调函数。该回调函数将接受来自缓存类的调式自符串,然后将它输出到VS.net的“输出”窗口。当然,你也可以自己定义这样一个回调函数使字符串写入磁盘映像或SOCKET之类更复杂的设备。
C/C++ code
bool CALLBACK MyOutputDebugString( LPCTSTR lpText ) { OutputDebugString( lpText ); return true; } CDebugStreamBuf<TCHAR> g_DbgBuf( MyOutputDebugString );
第三步:在任意一个类的初始化里加入如下代码(两行任选其一):
C/C++ code
wcout.rdbuf( &g_DbgBuf ); // Unicode版本 cout.rdbuf( &g_DbgBuf ); // 非Unicode版本
之后就可以方便的使用wcout或cout进行GDI程序的调式了,写入wcout或cout的字符串将全部显示在VS.net的“输出”窗口中。
使用举例:
C/C++ code
// CRect rc; GetWindowRect( &rc ); wcout << _T("窗口的宽度是:") << rc.Width() << _T(",高度是:") << rc.Height() << endl;
相关文章推荐
- (转帖)使用OpenFileDialog对话框打开文本文件(写此代码的人应该是有一定功力的程序员,因为代码写的很规范,很容易阅读,很好理解,很好调试)
- 使用ctr+c无法终止一个bash脚本,此脚本在循环执行一个需要运行一定时间的命令
- 调试使用了函数模块的程序时需要注意的一个小问题
- 调试使用了函数模块的程序时需要注意的一个小问题
- 使用反射动态调用类成员,需要Type类的一个方法:InvokeMember。对该方法的声明如下(摘抄于MSDN):
- 使用jQuery Ajax功能的时候需要注意的一个问题
- 使用NBear设计一个新的实体类时需要进行的操作
- 关于一个sql语句需要使用约等于的问题
- 需要这样一个记事本-17 VS 2010 远程调试
- gdb调试需要使用到的一些知识(心得)
- 使用Anthem.NET框架的一个调试经历
- 使用libdwraf写的一个读取GCC -g参数编译生成的调试信息的例子
- 封装一个素数方法,在使用散列表时需要预置大小,需要用到这个方法
- 今天需要获取一个网站的web服务反馈回来的数据,找到份不错的帖子关于WebClient类的使用,记录下来·
- 使用bitmap对一个大小在一定范围内的无重复数据排序(比如电话号码)|在一个大小在一定范围内的数据集中查找重复数据
- 编写一个聊天程序:有接收数据部分,和发数据的部分, 这两部分需要同时执行,使用多线程实现,一个控制接收,一个控制发送
- 使用 Anthem.NET 框架的一个调试经历
- 1 开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你。 本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的原则已经被许多现有的JDBC应用程序编译运行并验证过。 这些指导原则包括: 正确的使用数据库MetaData方法 只获取需要的数据 选用最佳性能的功能 管理连
- 不能使用ASP.NET验证控件---WebForms UnobtrusiveValidationMode 需要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptRes
- Android解决使用findViewById时需要对返回值进行类型转换问题的辅助类