作者: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=; i<; ++i) {
zltoutf(sout, i, _T("indent %d\n"), i);
}
zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[])-);
zltoutc(sout, _T('\n')); return ;
}

输出结果:

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=; i<; ++i) {
zltoutf(sout, indent+i, _T("indent %d\n"), i);
}
zltouts(sout, strEnd, sizeof(strEnd)/sizeof(strEnd[])-);
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, ); #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 ;
}

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

    ZLTOUTTYPE sout;
basic_stringstream<TCHAR> ss;
sout = dynamic_cast<ZLTOUTTYPE>(&ss);
dotest(sout, );
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++流的更多相关文章

  1. Python学习教程(learning Python)--1.2.2 Python格式化输出基础

    本节讨论为何要格式化输出数据? 先看一段代码吧,本程序的功能是计算月支付金额. amount_due = 5000.0 #年支付金额 monthly_payment = amount_due / 12 ...

  2. 凯撒密码、GDP格式化输出、99乘法表

    1.恺撒密码的编码 s=input('明文:') print('密文:',end='') for i in s: print(chr(ord(i)+3),end='') 附加: print('字符串的 ...

  3. Python进行JSON格式化输出,以及汉字显示问题

    格式化输出 转载地址  https://blog.csdn.net/real_tino/article/details/76422634 问题分析: Python下json手法的json在打印查看时, ...

  4. C++ cout格式化输出(转)

    C++ cout格式化输出(转) 这篇文章主要讲解如何在C++中使用cout进行高级的格式化输出操作,包括数字的各种计数法(精度)输出,左或右对齐,大小写等等.通过本文,您可以完全脱离scanf/pr ...

  5. python学习笔记(基础二:注释、用户输入、格式化输出)

    注释 单行:# 多行:上下各用3个连续单引号或双引号 3个引号除了多行注释,还可以打印多行 举例: msg = ''' name = "Alex Li" name2 = name ...

  6. Linux下date命令,格式化输出,时间设置

    date命令的帮助信息 [root@localhost source]# date --help用法:date [选项]... [+格式] 或:date [-u|--utc|--universal] ...

  7. Python自动化运维之4、格式化输出、文件对象

    Python格式化输出: Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[P ...

  8. 浅谈format格式化输出

    什么是format? 相对于基本格式化输出采用"%"的方法,format的功能强大,该函数把字符串当一个模板,通过传入的参数进行格式化,并且使用大括号"{}"作 ...

  9. python 格式化输出日志记录

    # 格式化打印提示输出示例已logging模块为例. service_name = "Booking" logger.error('%s service is down!' % s ...

随机推荐

  1. MongoDB介绍与windows下安装

    MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类 似json的bjson格式,因此可以存储比较复杂的数据类型. ...

  2. 【Visual Lisp】变体与安全数组

    (vlax-make-variant) ;;创建一个未初始化的变体 ;;01.整型值变体(setq myvar (vlax-make-variant 10)) ;;创建整型值变体,返回 #<va ...

  3. How to configure windows machine to allow file sharing with dns alias (CNAME)

    Source: http://serverfault.com/questions/23823/how-to-configure-windows-machine-to-allow-file-sharin ...

  4. 拉格朗日乘子法和KKT条件

    拉格朗日乘子法(Lagrange Multiplier)和KKT(Karush-Kuhn-Tucker)条件是求解约束优化问题的重要方法,在有等式约束时使用拉格朗日乘子法,在有不等约束时使用KKT条件 ...

  5. 作死遇到的坑--view向下偏移

    好大一个坑.--谈谈view偏移问题: 先上张图, 图中白色部分.上面的是从网上找的资源.将导航栏隐藏之后用collectionView加上去而实现的滑动标签功能.开始以为是代码中的问题.然后仔细推敲 ...

  6. C常用数据类型长度

    1.整型数据类型 2.无符号整型数据类型 3.字符型数据类型 char  字节数  1: 4.浮点型数据类型

  7. 【转载】关于Linux Shell 特殊字符

    一.通配符     1.一般通配符       ① * (星号):匹配字符的0次或多次出现       举例:f*可以匹配f.fa.fls.a     注意:“.”和“/”必须显示匹配         ...

  8. 入门级:怎么使用C#进行套接字编程(二)

    入门级:怎么使用C#进行套接字编程(一) 原文地址如下: C# Server Socket program C# Client Socket program 代码环境:VS2010+Win8.1企业评 ...

  9. 用c#开发微信 (10) JS-SDK 基本用法- 分享接口“发送到朋友”

    微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包.通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享. ...

  10. MySql和SQL Server数据类型 对比

    My Sql 数据类型 SQL Server 数据类型 Yes/No bit Smallint(字节型) tinyint Integer(长整型) int Real(单精度浮点型)    real F ...