d的printf元编程,适用于betterC

使用:

 int i;
    dprintf!"hello %s %s %s %s betty\n"(3, 4.0, &i, "abc".ptr);

重写为:

    printf("hello %d %g %p %s betty\n", 3, 4.0, &i, "abc".ptr);

import core.stdc.stdio : printf;

template Seq(A ...) { alias Seq = A; }

int dprintf(string f, A ...)(A args)
{
    enum Fmts = Formats!(A);
    enum string s = formatString(f, Fmts);
    __gshared const(char)* s2 = s.ptr;
    return printf(Seq!(s2, args[0..2], args[2..4]));
}

template Formats(T ...)
{
    static if (T.length == 0)
	enum Formats = [ ];
    else static if (T.length == 1)
	enum Formats = [Spec!(T[0])];
    else
	enum Formats = [Spec!(T[0])] ~ Formats!(T[1 .. T.length]);
}

template Spec(T : byte)    { enum Spec = "%d"; }
template Spec(T : short)   { enum Spec = "%d"; }
template Spec(T : int)     { enum Spec = "%d"; }
template Spec(T : long)    { enum Spec = "%lld"; }

template Spec(T : ubyte)   { enum Spec = "%u"; }
template Spec(T : ushort)  { enum Spec = "%u"; }
template Spec(T : uint)    { enum Spec = "%u"; }
template Spec(T : ulong)   { enum Spec = "%llu"; }

template Spec(T : float)   { enum Spec = "%g"; }
template Spec(T : double)  { enum Spec = "%g"; }
template Spec(T : real)    { enum Spec = "%Lg"; }

template Spec(T : char)    { enum Spec = "%c"; }
template Spec(T : wchar)   { enum Spec = "%c"; }
template Spec(T : dchar)   { enum Spec = "%c"; }

template Spec(T : immutable(char)*)   { enum Spec = "%s"; }
template Spec(T : const(char)*)       { enum Spec = "%s"; }
template Spec(T : T*)                 { enum Spec = "%p"; }

/******************************************
 * Replace %s format specifiers in f with corresponding specifiers in A[].
 * Other format specifiers are left as is.
 * Number of format specifiers must match A.length.
 * Params:
 *	f = printf format string
 *	A = replacement format specifiers
 * Returns:
 *	replacement printf format string
 */
string formatString(string f, string[] A ...)
{
    string r;
    size_t i;
    size_t ai;
    while (i < f.length)
    {
	if (f[i] != '%' || i + 1 == f.length)
	{
	    r ~= f[i];
	    ++i;
	    continue;
	}
	char c = f[i + 1];
	if (c == '%')
	{
	    r ~= "%%";
	    i += 2;
	    continue;
	}
	assert(ai < A.length, "not enough arguments");
	string fmt = A[ai];
	++ai;
	if (c == 's')
	{
	    r ~= fmt;
	    i += 2;
	    continue;
	}
	r ~= '%';
	++i;
	continue;
    }
    assert(ai == A.length, "not enough formats");
    return r;
}
posted @   zjh6  阅读(18)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示