观察:可变参数的格式化输出
本文描述了将可变参数(variadic)按照格式化字符串的方式输出至标准输出(stdout)或文件流(ofstream)的一种实现方案,并加以了验证。
◆ 解法
通过可变参数函数(variadic function)和可变参数模板(variadic template),能够接受个数不定的参数。两种接受参数方式与两种输出目的地的组合,可以得到四种情况,
(资料图)
- 可变参数函数输出至标准输出(A)
- 可变参数模板输出至标准输出(B)
- 可变参数函数输出至文件流(C)
- 可变参数模板输出至文件流(D)
结合 *printf 系列输出函数以及变参标准库(
◆ 示例
以下代码片段(variadic_printf.cpp)展示了此实现方案,
可变参数函数输出至标准输出(A),
static void A(const char* fmt, ...){ std::va_list args; // #1 va_start(args, fmt); std::vfprintf(stdout, fmt, args); // #2 // or // std::vprintf(fmt, args); va_end(args);}
使用 std::va_list 对象与 va_start (#1)访问可变参数;然后由 std::vfprintf() 或 std::vprintf() 函数将可变参数输出(#2)至标准输出;最后用 va_end 宏结束对可变参数的访问。
可变参数模板输出至标准输出(B),
template static void C(const char* fmt, const Types&... args){ std::fprintf(stdout, fmt, args...); // #3 // or // std::printf(fmt, args...);}
直接由 std::fprintf() 或 std::printf() 函数输出(#3)。
可变参数函数输出至文件流(C),
static void C(const char* fmt, ...){ std::va_list args, copied; va_start(args, fmt); va_copy(copied, args); // #4 char* buffer = new char[std::vsnprintf(nullptr, 0, fmt, copied) + 1]; // +1 for "\0" std::vsprintf(buffer, fmt, args); // #5 stream << buffer; delete[] buffer; va_end(copied); va_end(args);}
使用 std::va_list 对象与 va_start 访问可变参数;可变参数的一份拷贝用于 std::vsnprintf() 函数计算待输出字符串的长度,并依此长度开辟存放字符串的临时空间(#4);再由 std::vsprintf() 函数将可变参数输出至临时空间中(#5),紧接着输出至文件流;最后释放临时空间并结束对可变参数的访问。
可变参数模板输出至文件流(D),
template static void D(const char* fmt, const Types&... args){ char* buffer = new char[std::snprintf(nullptr, 0, fmt, args...) + 1]; // +1 for "\0" std::sprintf(buffer, fmt, args...); // #6 stream << buffer; delete[] buffer;}
std::snprintf() 函数计算待输出字符串的长度,并依此长度开辟存放字符串的临时空间;然后由 std::sprintf() 函数将可变参数输出至临时空间中(#6),紧接着输出至文件流;最后释放临时空间。
以下是这四个函数的测试用例,
... A("\n%s won the %2dth FIFA World Cup!\n", "Argentina", 22);B("\n%s uses %13s to shoot the %d eagles.\n", "Bower", "Hoyt Highline", 2);C("\n%s is easy as pie!\n", "Cxx");D("\n%s counted the money again. %4.2f dollars. That was all.\n\n", "Della", 1.87);...
◆ 验证
在命令行中编译代码(-std=c++11),运行可执行文件并检查输出结果。以下是输出结果的部分内容,
$ g++ -std=c++11 variadic_printf.cpp$ ./a.outArgentina won the 22th FIFA World Cup!Bower uses Hoyt Highline to shoot the 2 eagles.$ cat variadic.outputCxx is easy as pie!Della counted the money again. 1.87 dollars. That was all.$
◆ 最后
完整的代码请参考 [gitee] cnblogs/17390064 。
写作过程中,笔者参考了 获取va_list格式化长度。致作者 sdhongjun 。
关键词:
相关新闻
- 观察:可变参数的格式化输出
- 刑事案件谅解书怎样写|全球球精选
- 当前热文:驻站作品专属作品和授权作品_独家作品 首发作品 驻站作品 分别是什么意思 谁能解释一下
- 今日讯!华创证券:维持锦欣生殖“推荐”评级 目标价6.54港元
- 上海市商务委:着力恢复和扩大消费,4月全市线下累计消费超2342亿元|环球滚动
- “大嫂”为张颂文庆生:祝颂文哥福如东海寿比南山_播资讯
- 儿童读物现错误插图!这段历史,你必须知晓! 看热讯
- 世界食品(深圳)博览会开幕 发酵食品成为展会亮点 世界动态
- 5月11日陕西地区硝酸铵价格暂稳 重点聚焦
- 金观平:传统产业“简单退出”不可取
- 替补得分对比:热火42分&邓罗17分 尼克斯替补合计8分 天天要闻
- 14.5万元/吨!硅料价格大幅下跌!
- 解决优先购买权争议问题的建议以及优先购买权纠纷的诉讼程序处理
- 重庆姐弟坠亡案开庭宣判 网友:这两个人居然活了两年多,维持原判_天天快报
- 新进展!日本科学家发现“血管清道夫”,8周74名志愿者血栓改善
- 说案|员工未完成超负荷工作能被解雇吗?
- 世界热议:微软(MSFT.US)今年不加薪!CEO称高管绩效奖金将较去年下降
- 卫宫士郎立于泰拉大陆_卫宫士郎英灵化在哪一集知道自己是卫宫_观察
- 跨境支付板块5月10日涨3.64%,中油资本领涨,主力资金净流出2.38亿元
- 关于赞美老师的句子古诗|实时
- 应急管理部:今年一季度全国受理安全生产举报量同比上升25.1%
- 长春外援祖伊:下半场比较糟糕&运气不佳,但我们实力强于对手 环球观速讯
- 有能力在今年买房,就不要等到明年!因为你不知道明天的房价是跌还是涨!早买早供,不买首付优惠也没了!_全球最新
- 近年来,骂清北已然成了一种时尚