[C/C++] zltabout(带缩进的格式化输出)v1.0。能以相同的代码绑定到 C FILE 或 C++流

作者:zyl910

一、缘由

  在写一些生成文本的程序时,经常需要使用带缩进的格式化输出的功能。以前为此写过不少类似的函数,可惜它们的可重用性很差。
  这是因为——
1) C语言的FILE*不支持重定向到自己的缓冲区。
2) C++的流机制允许重定向到自己的流缓冲区。可惜这依赖了C++的专有语法,纯C无法用上。

  因为上述原因,以前至少得为C与C++编写两套函数集。如果考虑到char/wchat_t/TCHAR,函数集会变得更加臃肿。

  于是我决定编写一套“能以相同的代码绑定到 C FILE 或 C++流”的带缩进的格式化输出库。zltabout就是该想法的成果。


二、C范例

Step 1 定义 ZLTABOUTMODE 宏 与 引入 zltabout.h:

 #define ZLTABOUTMODE 1 // ZLTABOUTMODE_C
 #include "zltabout.h"

Step2 定义 ZLTOUTTYPE 类型的变量并赋值为stdout:

 ZLTOUTTYPE sout;
 sout = (ZLTOUTTYPE)stdout;

Step3 使用 zltoutc 输出一个字符:

 zltoutc(sout, _T('\n'));

Step4 使用 zltouts 输出字符串:

 static const TCHAR strEnd[] = _T("(END)");
 zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[0])-1);

Step5 使用 zltoutf 进行带缩进的格式化输出:

 for(i=0; i<3; ++i) {
  zltoutf(sout, i, _T("indent %d\n"), i);
 }


完整代码:

#include <stdio.h>
#include <wchar.h>

#include "auto_tchar.h"
#include "auto_tmain.h"

#define ZLTABOUTMODE    1    // ZLTABOUTMODE_C
#include "zltabout.h"


/// main .
int _tmain(int argc, TCHAR* argv[])
{
    ZLTOUTTYPE sout;
    static const TCHAR strEnd[] = _T("(END)");
    int i;

    // show.
    sout = (ZLTOUTTYPE)stdout;
    for(i=0; i<3; ++i) {
        zltoutf(sout, i, _T("indent %d\n"), i);
    }
    zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[0])-1);
    zltoutc(sout, _T('\n'));

    return 0;
}

 

 

输出结果:

indent 0
    indent 1
        indent 2
(END)

 


三、C++范例

Step 1 定义 ZLTABOUTMODE 宏 与 引入 zltabout.h:

 #define ZLTABOUTMODE 2 // ZLTABOUTMODE_CPP
 #include "zltabout.h"

Step2 定义 ZLTOUTTYPE 类型的变量并赋值为cout/wcout:

 ZLTOUTTYPE sout;
 #ifdef UNICODE
  sout = dynamic_cast<ZLTOUTTYPEW>(&wcout);
 #else
  sout = dynamic_cast<ZLTOUTTYPEA>(&cout);
 #endif

Step3 使用 zltoutc 输出一个字符:

 zltoutc(sout, _T('\n'));

Step4 使用 zltouts 输出字符串:

 static const TCHAR strEnd[] = _T("(END)");
 zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[0])-1);

Step5 使用 zltoutf 进行带缩进的格式化输出:

 for(i=0; i<3; ++i) {
  zltoutf(sout, i, _T("indent %d\n"), i);
 }


完整代码:

#include <iostream>
#include <sstream>

#include <stdio.h>
#include <wchar.h>

#include "auto_tchar.h"
#include "auto_tmain.h"

//#define ZLTABOUTMODE    1    // ZLTABOUTMODE_C
#define ZLTABOUTMODE    2    // ZLTABOUTMODE_CPP
#include "zltabout.h"

using namespace std;

/** test mode (测试模式).
 *
 * values:
 * * 1: Test cout/wcout .
 * * 2: Test stringstream/wstringstream .
 *
 */
#define MYTESTMODE    2


/// Do Test.
void dotest(ZLTOUTTYPE sout, int indent) {
    static const TCHAR strEnd[] = _T("(END)");
    int i;
    for(i=0; i<3; ++i) {
        zltoutf(sout, indent+i, _T("indent %d\n"), i);
    }
    zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[0])-1);
    zltoutc(sout, _T('\n'));
}

/// main .
int _tmain(int argc, TCHAR* argv[])
{
    ZLTOUTTYPE sout;

    // show.
#if ZLTABOUTMODE==ZLTABOUTMODE_DUMMY
    sout = (ZLTOUTTYPE)NULL;
#elif ZLTABOUTMODE==ZLTABOUTMODE_C
    sout = (ZLTOUTTYPE)stdout;
#elif ZLTABOUTMODE==ZLTABOUTMODE_CPP
    #if (MYTESTMODE==1)
        // test cout/wcout .
        #ifdef UNICODE
            sout = dynamic_cast<ZLTOUTTYPEW>(&wcout);
        #else
            sout = dynamic_cast<ZLTOUTTYPEA>(&cout);
        #endif
    #elif (MYTESTMODE==2)
        // test stringstream/wstringstream .
        basic_stringstream<TCHAR> ss;
        sout = dynamic_cast<ZLTOUTTYPE>(&ss);
    #endif
#else
    #error Error ZLTABOUTMODE !
#endif
    dotest(sout, 0);

    #if (ZLTABOUTMODE==ZLTABOUTMODE_CPP) && (MYTESTMODE==2)
        // test stringstream/wstringstream part 2.
        basic_string<TCHAR> str = ss.str();
        #ifdef UNICODE
            wcout << str;
        #else
            cout << str;
        #endif
    #endif

    return 0;
}

 

注:还可以将ZLTOUTTYPE绑定到 stringstream,例如——

    ZLTOUTTYPE sout;
    basic_stringstream<TCHAR> ss;
    sout = dynamic_cast<ZLTOUTTYPE>(&ss);
    dotest(sout, 0);
    basic_string<TCHAR> str = ss.str();
    #ifdef UNICODE
        wcout << str;
    #else
        cout << str;
    #endif

 

 

四、快速参考

常用函数:

// Output stream's type (输出流的类型).
#define ZLTOUTTYPE    // C FILE* or C++ basic_ostream .

// Writes a character to a stream (向流输出一个字符).
int zltoutc(ZLTOUTTYPE sout, TCHAR ch);

// Write a string to a stream (向流输出字符串).
void zltouts(ZLTOUTTYPE sout, const TCHAR* str, size_t cch);

// Formatted output with indentation using a pointer to a list of arguments (参数列表指针形式的带缩进格式化输出).
void zltoutvf(ZLTOUTTYPE sout, int indent, const TCHAR* fmt, va_list argptr);

//Formatted output with indentation (带缩进格式化输出).
void zltoutf(ZLTOUTTYPE sout, int indent, const TCHAR* fmt, ...);

 

输入配置性宏:

* ZL_NOWIDE: 不定义宽字符版函数 . 用于提高兼容性, 例如bcb6.
* ZLTABOUTMODE: 输出模式. 值可以为 0(ZLTABOUTMODE_DUMMY), 1(ZLTABOUTMODE_C), 2(ZLTABOUTMODE_CPP) .

 

源码下载——
https://github.com/zyl910/zltabout

你可能感兴趣的:([C/C++] zltabout(带缩进的格式化输出)v1.0。能以相同的代码绑定到 C FILE 或 C++流)