软件版本号的检查和比较是我们经常要用到的一个功能,我自己写了一个函数,用起来还是挺方便的。
// 函数功能:执行字符串形式的版本比较
// 返回值:比较成功返回真,比较失败返回假
// 比较结果保存到nResult中
// lpszVer1高于lpszVer2时nResult的值为1
// lpszVer1低于lpszVer2时nResult的值为-1
// lpszVer1等于lpszVer2时nResult的值为0
// 使用说明:安全的用法应当是先对函数返回值进行判断,返回为真时再检查nResult中的比较结果
BOOL CompareVersion(__in LPCTSTR lpszVer1, __in LPCTSTR lpszVer2, __out short & nResult)
{
// 参数安全性检查
if (lpszVer1 == NULL || lpszVer1[0] == _T('\0')) return FALSE;
if (lpszVer2 == NULL || lpszVer2[0] == _T('\0')) return FALSE;
// 参数有效性检查
for (size_t i = 0; i < _tcslen(lpszVer1); i++)
{
// 如果指定版本号中的当前字符在0到9范围以外,并且不是分割点,就认为是无效的
if ((lpszVer1[i] < _T('0') || lpszVer1[i] > _T('9')) && lpszVer1[i] != _T('.'))
return FALSE;
}
for (size_t i = 0; i < _tcslen(lpszVer2); i++)
{
// 如果指定版本号中的当前字符在0到9范围以外,并且不是分割点,就认为是无效的
if ((lpszVer2[i] < _T('0') || lpszVer2[i] > _T('9')) && lpszVer2[i] != _T('.'))
return FALSE;
}
// _tcstok_s函数会修改输入,所以先把版本字符串复制一份
// 根据版本号的通常表示法,不必根据源版本字符串的大小从堆上申请空间,直接定义即可满足绝大多数需求,也能提高效率
const short nMAX_VER_LEN = 64;
TCHAR szVer1[nMAX_VER_LEN] = {0}, szVer2[nMAX_VER_LEN] = {0};
StringCchCopy(szVer1, nMAX_VER_LEN - 1, lpszVer1);
StringCchCopy(szVer2, nMAX_VER_LEN - 1, lpszVer2);
const TCHAR szSeps[] = _T(".");
LPTSTR lpszToken1 = NULL, lpszToken2 = NULL;
LPTSTR lpszNextToken1 = NULL, lpszNextToken2 = NULL;
lpszToken1 = _tcstok_s(szVer1, szSeps, &lpszNextToken1);
lpszToken2 = _tcstok_s(szVer2, szSeps, &lpszNextToken2);
// 进行逐级拆分
while ((lpszToken1 != NULL) || (lpszToken2 != NULL))
{
int nNum1 = 0, nNum2 = 0;
// 检查拆分结果
if (lpszToken1 != NULL)
{
nNum1 = _tstoi(lpszToken1);
lpszToken1 = _tcstok_s(NULL, szSeps, &lpszNextToken1);
}
if (lpszToken2 != NULL)
{
nNum2 = _tstoi(lpszToken2);
lpszToken2 = _tcstok_s(NULL, szSeps, &lpszNextToken2);
}
// 执行比较
if (nNum1 > nNum2)
{
nResult = 1;
break;
}
else if (nNum1 < nNum2)
{
nResult = -1;
break;
}
else
{
nResult = 0;
}
}
return TRUE;
}