C++封装存储数据单位转换, 方便将输入数据以指定方式输出
main.cpp
#include <wtypesbase.h>
#include <string>
#include <vector>
#include <tchar.h>
#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif
// 数据单位
enum eUnitType
{
eUT_Auto, // 自动
eUT_b, // (2 ^ 000) * 8 Bit
eUT_Kb, // (2 ^ 010) * 8 Bit
eUT_Mb, // (2 ^ 020) * 8 Bit
eUT_Gb, // (2 ^ 030) * 8 Bit
eUT_Tb, // (2 ^ 040) * 8 Bit
eUT_Pb, // (2 ^ 050) * 8 Bit
eUT_Eb, // (2 ^ 060) * 8 Bit
eUT_Zb, // (2 ^ 070) * 8 Bit
eUT_Yb, // (2 ^ 080) * 8 Bit
eUT_Bb, // (2 ^ 090) * 8 Bit
eUT_Nb, // (2 ^ 100) * 8 Bit
eUT_Db, // (2 ^ 110) * 8 Bit
eUT_Cb, // (2 ^ 120) * 8 Bit
eUT_Xb, // (2 ^ 130) * 8 Bit
eUT_B, // Byte 2 ^ 000 Byte
eUT_KB, // Kilobyte 2 ^ 010 Byte
eUT_MB, // Megabyte 2 ^ 020 Byte
eUT_GB, // Gigabyte 2 ^ 030 Byte
eUT_TB, // Terabyte 2 ^ 040 Byte
eUT_PB, // Petabyte 2 ^ 050 Byte
eUT_EB, // Exabyte 2 ^ 060 Byte
eUT_ZB, // Zettabyte 2 ^ 070 Byte
eUT_YB, // Yottabyte 2 ^ 080 Byte
eUT_BB, // Brontobyte 2 ^ 090 Byte
eUT_NB, // NonaByte 2 ^ 100 Byte
eUT_DB, // DoggaByte 2 ^ 110 Byte
eUT_CB, // corydonbyte 2 ^ 120 Byte
eUT_XB, // Xerobyte 2 ^ 130 Byte
eUT_Max
};
typedef struct _DATA_UNIT_INFO
{
double value; // 数值
eUnitType eUnit; // 单位
_tstring strUnitStr; // 单位字符串
_tstring strOutput; // 内容(数值 + 单位字符串)
}DATA_UNIT_INFO;
DATA_UNIT_INFO FormatByteSize(
double nBytesSize, // 输入值
eUnitType eSrcUnit = eUnitType::eUT_Auto, // 原始单位
eUnitType eDestUnit = eUnitType::eUT_Auto, // 目标单位
bool fHasUnits = true, // 结果字符串数值添加单位
bool fSpace = true, // 结果字符串数值与单位之间添加空格
int nInteger = 1, // 整数部分长度
int nPrecision = 3 // 小数部分长度
);
void ConsoleOutput(LPCTSTR pFormat, ...);
int main()
{
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_B, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_KB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_MB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_GB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_TB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_PB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_EB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_ZB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_YB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_BB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_NB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_DB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_CB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
ConsoleOutput(_T("%s\r\n"), FormatByteSize(1, eUnitType::eUT_XB, eUnitType::eUT_Auto, true, true, 0, 1).strOutput.c_str());
return 0;
}
DATA_UNIT_INFO FormatByteSize(
double nBytesSize,
eUnitType eSrcUnit/* = eUnitType::eUT_Auto*/,
eUnitType eDestUnit/* = eUnitType::eUT_Auto*/,
bool fHasUnits/* = true*/,
bool fSpace/* = true*/,
int nInteger/* = 1*/,
int nPrecision/* = 3*/
)
{
TCHAR szFormatBuf[MAX_PATH] = { 0 };
TCHAR szResultBuf[MAX_PATH] = { 0 };
DATA_UNIT_INFO dataUnitInfo;
bool fSrcBit = false;
bool fDestBit = false;
LPCTSTR strUnitByteName[] = {
_T("B"),
_T("KB"),
_T("MB"),
_T("GB"),
_T("TB"),
_T("PB"),
_T("EB"),
_T("ZB"),
_T("YB"),
_T("BB"),
_T("NB"),
_T("DB"),
_T("CB"),
_T("XB"),
};
LPCTSTR strUnitBitName[] = {
_T("b"),
_T("Kb"),
_T("Mb"),
_T("Gb"),
_T("Tb"),
_T("Pb"),
_T("Eb"),
_T("Zb"),
_T("Yb"),
_T("Bb"),
_T("Nb"),
_T("Db"),
_T("Cb"),
_T("Xb"),
};
// 原始单位 比特 -> 字节
if (eSrcUnit >= eUnitType::eUT_b && eSrcUnit < eUnitType::eUT_B)
{
fSrcBit = true;
eSrcUnit = (eUnitType)(eSrcUnit + (eUnitType::eUT_B - eUnitType::eUT_b));
}
// 目标单位 比特 -> 字节
if (eDestUnit >= eUnitType::eUT_b && eDestUnit < eUnitType::eUT_B)
{
fDestBit = true;
eDestUnit = (eUnitType)(eDestUnit + (eUnitType::eUT_B - eUnitType::eUT_b));
}
// 原始单位转换
for (int i = eUnitType::eUT_B; i < eSrcUnit; i++)
{
nBytesSize *= 1024.0f;
}
// 自动
int nUnitTypeIndex = eUnitType::eUT_B;
if (eUnitType::eUT_Auto == eDestUnit)
{
double nCurUnitSize = 1.0f;
double nNextUnitSize = 1024.0f;
int nUnitTypeMaxIndex = eUnitType::eUT_Max - 1;
for (int i = 0; i < _countof(strUnitByteName) && nUnitTypeIndex < nUnitTypeMaxIndex; i++)
{
if ((nBytesSize >= nCurUnitSize && nBytesSize < nNextUnitSize) || 0 == nNextUnitSize || 0 == nBytesSize)
{
break;
}
nCurUnitSize *= 1024.0f;
nNextUnitSize *= 1024.0f;
nUnitTypeIndex++;
}
eDestUnit = (eUnitType)nUnitTypeIndex;
}
{
::_stprintf_s(szFormatBuf, _countof(szFormatBuf), _T("%%%d.%dlf"), nInteger + nPrecision + 1, nPrecision);
double fUnitSize = 1.0f;
for (int i = eUnitType::eUT_B; i < eDestUnit; i++)
{
fUnitSize *= 1024.0f;
}
if (fSrcBit)
{
fUnitSize *= 8.0f;
}
if (fDestBit)
{
nBytesSize *= 8.0f;
}
double lfResult = nBytesSize / fUnitSize;
::_stprintf_s(szResultBuf, _countof(szResultBuf), szFormatBuf, lfResult);
dataUnitInfo.strOutput = szResultBuf;
dataUnitInfo.value = lfResult;
if (fHasUnits)
{
if (fSpace)
{
dataUnitInfo.strOutput += _T(" ");
}
if (fDestBit)
{
dataUnitInfo.strOutput += strUnitBitName[eDestUnit - eUnitType::eUT_B];
dataUnitInfo.strUnitStr = strUnitBitName[eDestUnit - eUnitType::eUT_B];
dataUnitInfo.eUnit = (eUnitType)(eDestUnit + (eUnitType::eUT_B - eUnitType::eUT_b));
}
else
{
dataUnitInfo.strOutput += strUnitByteName[eDestUnit - eUnitType::eUT_B];
dataUnitInfo.strUnitStr = strUnitByteName[eDestUnit - eUnitType::eUT_B];
dataUnitInfo.eUnit = eDestUnit;
}
}
}
return dataUnitInfo;
}
void ConsoleOutput(LPCTSTR pFormat, ...)
{
size_t nCchCount = MAX_PATH;
_tstring strResult(nCchCount, 0);
va_list args;
va_start(args, pFormat);
do
{
//格式化输出字符串
int nSize = _vsntprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
if (-1 != nSize)
{
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
::WriteConsole(console, strResult.c_str(), nSize, NULL, NULL);
break;
}
//缓冲大小超限终止
if (nCchCount >= INT32_MAX)
{
break;
}
//重新分配缓冲
nCchCount *= 2;
strResult.resize(nCchCount);
} while (true);
va_end(args);
}