zoukankan      html  css  js  c++  java
  • [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(' '));

    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 "), 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
    "), i);
        }
        zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[0])-1);
        zltoutc(sout, _T('
    '));
    
        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(' '));

    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 "), 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
    "), i);
        }
        zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[0])-1);
        zltoutc(sout, _T('
    '));
    }
    
    /// 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

  • 相关阅读:
    SpringBoot---关于 WebMvcConfigurerAdapter 过时问题及解决方法
    计算机网络要点---Http
    SpringBoot---SpringMVC关于拦截器的一些问题总结
    操作系统要点---2、并发,锁
    关于初次使用Thymeleaf遇到的问题 2020-08-11
    计算机网络要点---TCP
    pytorch深度学习:线性回归
    tarjian求LCA
    tarjian求强联通分量
    查询区间里有多少个小于k的数
  • 原文地址:https://www.cnblogs.com/zyl910/p/zltabout.html
Copyright © 2011-2022 走看看