闲暇的产物:用boost::spirit写的sprintf-like函数

qingcairousi qingcairousi 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
最近有点时间,看了下boost::spirit,这个库很有趣,可以直接用c++写EBNF。试着用它写了一个sprintf,内部是利用stringstream格式化,效率什么的都没有考虑,主要目的就是用boost::spirit写printf格式化字符串的EBNF。函数粗略的测试过,并没有支持全部的功能(hh,l之类的长度操作就没有支持,嫌麻烦),EBNF也不是那么严谨,但普通的格式化还是可以的:)


#include <string>
#include <sstream>
#include <iomanip>
#include <stdarg.h>
#include "boost/spirit.hpp"
#include "boost/function.hpp"
#include "boost/bind.hpp"

using namespace std;
using namespace boost;
using namespace boost::spirit;

struct Formatter
{
enum Flags
{
SHARP,
MINUS,
SPACE,
PLUS,
NONE
};
stringstream formatStream;
ios::fmtflags oldFlags;
Flags flag;
va_list& argsList;
Formatter(va_list& args):argsList(args)
{
oldFlags=formatStream.flags();
}
void onChar(const char& ch)
{
formatStream<<ch;
}
void onPINT(const char* const begin,const char* const end)
{
int* pi=va_arg(argsList,int*);
formatStream<<*pi;
}
void onPOINTER(const char* const begin,const char* const end)
{
void* ui=va_arg(argsList,void*);
formatStream<<hex<<ui;
}
void onCSTRING(const char* const begin,const char* const end)
{
char* str=va_arg(argsList,char*);
formatStream<<str;
}
void onCHARACTER(const char* const begin,const char* const end)
{
formatStream.setf(ios::fixed);
int k=va_arg(argsList,int);
formatStream<<(char)k;
}
void onDOUBLE_HEX(const char* const begin,const char* const end)
{
formatStream.setf(ios::fixed);
double k=va_arg(argsList,double);
formatStream<<hex<<k;
}
void onDOUBLE_FIX(const char* const begin,const char* const end)
{
formatStream.setf(ios::fixed);
double k=va_arg(argsList,double);
formatStream<<k;
}
void onDOUBLE(const char* const begin,const char* const end)
{
formatStream.setf(ios::fixed);
double k=va_arg(argsList,double);
formatStream<<k;
}
void onDOUBLE_E(const char* const begin,const char* const end)
{
formatStream.setf(ios::scientific);
double k=va_arg(argsList,double);
formatStream<<k;
}
void onUINT_OCT(const char* const begin,const char* const end)
{
unsigned int k=va_arg(argsList,unsigned int);
formatStream<<oct<<k;
}
void onUINT_HEX(const char* const begin,const char* const end)
{
unsigned int k=va_arg(argsList,unsigned int);
formatStream<<hex<<k;
}
void onUINT_DEC(const char* const begin,const char* const end)
{
unsigned int k=va_arg(argsList,unsigned int);
formatStream<<dec<<k;
}
void onINTEGER(const char* const begin,const char* const end)
{
int k=va_arg(argsList,int);
formatStream<<dec<<k;
}
void onLENGTH(const char* const begin,const char* const end)
{
string len(begin,end);
///@todo implement me
}
void onPRECETION(int val)
{
formatStream.precision(val);
}
void onWIDTH(int val)
{
formatStream.width(val);
}
void onFLAG(const char* const begin,const char* const end)
{
switch(*begin)
{
case '#':
flag=SHARP;
formatStream.setf(ios::showbase);
break;
case '-':
flag=MINUS;
break;
case ' ':
flag=SPACE;
break;
case '+':
flag=PLUS;
break;
case '0':
formatStream<<setfill('0');
default:
break;
}
}
void onCONTENT(const char* const begin,const char* const end)
{
flag=NONE;
}
void onFMT_STR(const char* const begin,const char* const end)
{
}
void onFMTStart(const char ch)
{
flag=NONE;
formatStream.flags(oldFlags);
formatStream.width(0);
formatStream.precision(6);
formatStream<<setfill(' ');
}
};

inline string sprintf(const char* fmt,...)
{
//EBNF of sprintf's format
va_list arg_ptr;
va_start(arg_ptr,fmt);
Formatter fo(arg_ptr);
rule<> PINT=ch_p('n');
rule<> POINTER=ch_p('p');
rule<> CSTRING=ch_p('s');
rule<> CHARACTER=ch_p('c');
rule<> DOUBLE_HEX=ch_p('a')|'A';
rule<> DOUBLE_FIX=ch_p('g')|'G';
rule<> DOUBLE=ch_p('f')|'F';
rule<> DOUBLE_E=ch_p('e')|'E';
rule<> UINT_OCT=ch_p('o');
rule<> UINT_HEX=ch_p('x')|'X';
rule<> UINT_DEC=ch_p('u');
rule<> UINT=
UINT_DEC[bind(&Formatter::onUINT_DEC,ref(fo),_1,_2)] |
UINT_HEX[bind(&Formatter::onUINT_HEX,ref(fo),_1,_2)] |
UINT_OCT[bind(&Formatter::onUINT_OCT,ref(fo),_1,_2)];
rule<> INTEGER=ch_p('d')|'i';
rule<> TYPE_SPEC =
INTEGER[bind(&Formatter::onINTEGER,ref(fo),_1,_2)] |
UINT |
DOUBLE_HEX[bind(&Formatter::onDOUBLE_HEX,ref(fo),_1,_2)] |
DOUBLE_FIX[bind(&Formatter::onDOUBLE_FIX,ref(fo),_1,_2)] |
DOUBLE[bind(&Formatter::onDOUBLE,ref(fo),_1,_2)] |
DOUBLE_E[bind(&Formatter::onDOUBLE_E,ref(fo),_1,_2)] |
CHARACTER[bind(&Formatter::onCHARACTER,ref(fo),_1,_2)] |
CSTRING[bind(&Formatter::onCSTRING,ref(fo),_1,_2)] |
POINTER[bind(&Formatter::onPOINTER,ref(fo),_1,_2)] |
PINT[bind(&Formatter::onPINT,ref(fo),_1,_2)];
rule<> LENGTH=longest_d[chseq_p("hh")|"h"|"ll"|"l"|"L"|"q"|"j"|"z"|"t"];
rule<> PRECITION='.'>>int_p[bind(&Formatter::onPRECETION,ref(fo),_1)];
rule<> WIDTH=int_p[bind(&Formatter::onWIDTH,ref(fo),_1)];
rule<> FLAG=ch_p('#')|'-'|space_p|'+'|'0';
rule<> CONTENT=ch_p('%')[bind(&Formatter::onFMTStart,ref(fo),_1)]>>
*FLAG[bind(&Formatter::onFLAG,ref(fo),_1,_2)]>>
*WIDTH>>
*PRECITION>>
*LENGTH[bind(&Formatter::onLENGTH,ref(fo),_1,_2)]>>
TYPE_SPEC;
rule<> FMT_STR=*((~ch_p('%'))[bind(&Formatter::onChar,ref(fo),_1)]|CONTENT[bind(&Formatter::onCONTENT,ref(fo),_1,_2)]);
//parse string
parse(fmt,FMT_STR[bind(&Formatter::onFMT_STR,ref(fo),_1,_2)]);
va_end(arg_ptr);
return fo.formatStream.str();
}
...全文

相关推荐

libdb-cxx-5.3.21-25.el7.x64-86.rpm.tar.gz

1、文件内容:libdb-cxx-5.3.21-25.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/libdb-cxx-5.3.21-25.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装

比特魔法师

libdb-cxx-devel-5.3.21-25.el7.x64-86.rpm.tar.gz

1、文件内容:libdb-cxx-devel-5.3.21-25.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/libdb-cxx-devel-5.3.21-25.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装

比特魔法师

果宝特攻同人创作:寒冰西瓜尊角色设计与IP扩展实践

角色设计是动漫创作的核心环节,它通过视觉元素和设定构建来塑造独特的人物形象。其原理在于平衡原创性与IP一致性,既要体现个人创意,又要尊重原作世界观。在技术价值上,优秀的角色设计能提升作品辨识度,为IP扩展提供基础。在动漫同人创作、游戏角色开发等应用场景中,角色设计都需要考虑色彩搭配、能力体系等要素。以果宝特攻为例,寒冰西瓜尊的创作就融合了冰系元素和机甲设计,通过分层创作流程和数字绘画工具实现了风格统一。这种二次创作不仅展现了同人创作的创新性,也为IP宇宙的扩展提供了实用参考。

weixin_34199405

Qwen2高考全卷评测:大模型如何通过教育认知操作系统落地教学

大语言模型正从通用文本生成迈向垂直领域深度认知,其中教育场景因其强规则性、高逻辑性与文化敏感性,成为检验AI真实能力的关键试金石。高考作为中国基础教育最严苛的标准化评估体系,天然涵盖信息提取、多步推理、语义理解、规则遵循等核心AI能力维度。阿里通义Qwen2在语数外全卷评测中总分第一,关键在于其突破‘文本模仿’,构建起融合长程逻辑链强化、中文语义颗粒度压缩、考试规则硬约束注入的教育认知操作系统。该技术路径不仅支撑精准解题与合规输出,更赋能教师开展思维显影、错因归因与能力图谱分析,已在语文思辨训练、数学病理诊

weixin_34228387

『n8n』初识界面

在首页(Overview),我们和 n8n 最常打交道的是“Workflows”、“Credentials”、“Executions”这几个面板(其实后面2个也会用到,但初学阶段可以先不管)。Workflows 面板可以看到我们创建的所有工作流,所以要给工作流起一个一眼看上去就知道是干嘛的名字。

德育处主任Pro
评论 2
收藏 已收藏
分享
返回顶部