持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情
在之前的文章中,我也拙略的实现了一个简单得不像话的cout,现在,我们对已有的基础上,为cout这样的输出流加上一个format格式的功能!
为什么要这样做呢?
C++的输出用cout的话,我觉得并不算很好用,你要输出精度、十六进制、八进制等内容时,就非常痛苦面具了
那么,我们是不是可以给c++加一点插件呢?
比如要格式化某个东西的输出时这样做:
cout << format("this var is: %d%d", x, y) << x << " " << y << endl;
或者
cout << format("this var is: %d %d") << x << y << endl;
当然,我觉得如果这样设置还比不上直接用print
在不损失太多效率的情况下,支持一个混用的模式。
现在,让我们来看看如何实现:
首先
需要搞清楚的是,osteam的重载操作,要通过重载operator<<来做到,并且若是要访问fmt类的私有函数
则需要友元函数。
对于多个变量的传参问题,则可以使用模板可变长传参来实现参数转发问题。
然后把格式和参数交给sprintf来解决
于是,我们就可以写出第一版代码
class Fmt {
static constexpr int BUFSIZE = {32};
private:
char buf[BUFSIZE]{};
public:
template <typename... Arg> Fmt(const char *fmt, Arg... arg) {
sprintf(buf, fmt, arg...);
}
friend std::ostream &operator<<(std::ostream &os, const Fmt &fmt);
};
std::ostream &operator<<(std::ostream &os, const Fmt &fmt) {
return (os << fmt.buf);
}
其实把fmt写成一个类有一点多余的嫌疑。
因为同意一个函数也可以做到这一件事情。
用函数则可以这样写:
template <typename... Arg>
const char* format(const char *fmt, Arg... arg) {
char buf[BUFSIZ];
sprintf(buf, fmt, arg...);
return buf;
}
大概没有问题吧?
问题很大,若是这样写,局部变量就返回了!
生命周期发生变化,不要怪程序不听话~
但是,若是写出一个类的形式,其实可以在一定程度上避免这个问题(要不去试试上面那个程序有没有坑?)
当然,采用动态分配内存,这个就不存在了~
使用
下面,我们来看一看简单的使用:
int main() {
std::cout << Fmt("%d %d\n", 1, 2)
<< Fmt("%s %c\n", "222", '1')
<< Fmt("%d %c", 1, 'A')
<< std::endl;
return 0;
}
可以实现这种cout和format混用的场景,效率也不会损失太多。