std::string的format一种实现

1,428 阅读1分钟
  • 由于std标准库的string没有实现类似CString的Format函数,使得我们有时候不得不使用istream、ostream来格式化字符串,然而这些类使用起来又复杂繁琐。在Windows下编程时我们还可以使用CString的Format函数,但是这里也可能会涉及到字符类型的转换等问题。而且使用CString的Format函数就意味着代码无法做到跨平台。
  • 于是我在VS下敲下了如下代码:
#include <iostream>
#include <string>
#include <stdarg.h>

int std_string_format(std::string & str, const char * format, ...) {
	std::string tmp;

	va_list marker;
	va_start(marker, format);

	size_t num = _vscprintf(format, marker);

	if (num >= tmp.capacity())
		tmp.reserve(num + 1);

	vsprintf_s((char *)tmp.data(), tmp.capacity(), format, marker);

	va_end(marker);

	str = tmp.c_str();
	return str.size();
}

int std_wstring_format(std::wstring & str, const wchar_t * format, ...) {
	std::wstring tmp;

	va_list marker;
	va_start(marker, format);

	size_t num = _vscwprintf(format, marker);

	if (num >= tmp.capacity())
		tmp.reserve(num + 1);

	vswprintf_s((wchar_t *)tmp.data(), tmp.capacity(), format, marker);

	va_end(marker);

	str = tmp.c_str();
	return str.size();
}

int main()
{
	std::string std_str;
	int len = std_string_format(std_str, "hello %s!", "world");
	std::cout << "std_str=" << std_str << ", len=" << len << std::endl;

	std::wcout.imbue(std::locale("chs"));

	std::wstring std_wstr;
	len = std_wstring_format(std_wstr, L"你好 %s!", L"世界");
	std::wcout << L"std_wstr=" << std_wstr << L", len=" << len << std::endl;

	system("pause");
}
  • 在VS下编译运行结果:
std_str=hello world!, len=12
std_wstr=你好 世界!, len=6
  • 可是这段代码在wandbox下编译不过,原来是因为_vscprintf和vsprintf_s是微软提供的函数。于是,我在wandbox下修改了一下代码:
#include <iostream>
#include <string>
#include <stdarg.h>

int format_num(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	int num = vsnprintf(0, 0, format, args);
	va_end(args);
	return num;
}

int format_num(const wchar_t *format, ...)
{
	va_list args;
	va_start(args, format);
	int num = vswprintf(0, 0, format, args);
	va_end(args);
	return num;
}

int std_string_format(std::string & str, const char * format, ...) {
	std::string tmp;

	va_list marker;
	va_start(marker, format);

	size_t num = format_num(format, marker);

	if (num >= tmp.capacity())
		tmp.reserve(num + 1);

	vsnprintf((char *)tmp.data(), tmp.capacity(), format, marker);

	va_end(marker);

	str = tmp.c_str();
	return str.size();
}

int std_wstring_format(std::wstring & str, const wchar_t * format, ...) {
	std::wstring tmp;

	va_list marker;
	va_start(marker, format);

	size_t num = format_num(format, marker);

	if (num >= tmp.capacity())
		tmp.reserve(num + 1);

	vswprintf((wchar_t *)tmp.data(), tmp.capacity(), format, marker);

	va_end(marker);

	str = tmp.c_str();
	return str.size();
}

int main()
{
	std::string std_str;
	int len = std_string_format(std_str, "hello %s!", "world");
	std::cout << "std_str=" << std_str << ", len=" << len << std::endl;

	std::wcout.imbue(std::locale("chs"));

	std::wstring std_str_ch;
	len = std_wstring_format(std_str_ch, L"你好 %s!", L"世界");
	std::wcout << L"std_str_ch=" << std_str_ch << L", len=" << len << std::endl;
}
  • 其运行结果如下:
std_str=hello world!, len=12
std_str_ch=你好 世界!, len=6
  • wandbox的中文设置有问题,运行结果是在Windows下跑出来的,应该是OK了。