[Windows]_[C/C++]_[避免使用wsprintf函数]
Posted infoworld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Windows]_[C/C++]_[避免使用wsprintf函数]相关的知识,希望对你有一定的参考价值。
常景
-
之前在写
WTL
程序时,想在进度条里显示浮点数的百分比,但是百分比数字显示是错误的,用的sprintf
的宽字节版本wsprintf
。怎么回事? -
在
Windows
开发时,由于std::string
并没有格式化字符串的方法,因此我们只能使用sprintf
。但是这个C
标准库并不支持UNICODE
字符串. 因此我们只能使用Windows
提供的宽字节版本wsprintf
。但是这个方法不能用,有什么问题?
说明
- 发现问题1,
wsprintf
[1]不支持对float
类型的格式化,但是sprintf
是支持的. 即便vs2017
也不支持。比如以下显示百分比,精确到小数点后一位, 原本期望的值是50.0%
. 但是wsprintf
得到的值是f%
。
auto number = 50.000000f;
wchar_t buf[8] = { 0 };
wsprintf(buf, L"%.1f%%", number);
wcout << "wsprintf: " << buf << endl;
-
Windows系统软件的是
StringCbPrintf
[2]格式化安全函数,它的特点:- 它针对内存溢出做了安全处理。
- 它的
cbDest
有最大值限定. - 输出保证
pszDest
字符串一定是NULL
结尾, 不会超出pszDest
的范围.
-
所以在
Windows
上,如果要使用宽字节的格式化字符串,最好还是使用StringCbPrintf
系统Win32
函数。
STRSAFEAPI StringCbPrintfA(
STRSAFE_LPSTR pszDest,
size_t cbDest,
STRSAFE_LPCSTR pszFormat,
...
);
例子
#include <string.h>
#include <Windows.h>
#include <Shlwapi.h>
#include <iostream>
#include <Strsafe.h>
using namespace std;
int main()
{
auto number = 50.000000f;
wchar_t buf[8] = { 0 };
wsprintf(buf, L"%.1f%%", number);
wcout << "wsprintf: " << buf << endl;
StringCbPrintf(buf, sizeof(buf), L"%.1lf%%", number);
wcout << "StringCbPrintf: " << buf << endl;
char buf2[8] = { 0 };
sprintf(buf2, "%.1f%%", number);
cout << "sprintf: " << buf2 << endl;
}
输出
wsprintf: f%
StringCbPrintf: 50.0%
sprintf: 50.0%
参考
以上是关于[Windows]_[C/C++]_[避免使用wsprintf函数]的主要内容,如果未能解决你的问题,请参考以下文章
在哪里下载 ws2_32.dll 2.2 版的运行函数 WSPRegisterMemory?