1. 程式人生 > >C++實現軟體版本號比較

C++實現軟體版本號比較

軟體版本號的檢查和比較是我們經常要用到的一個功能,我自己寫了一個函式,用起來還是挺方便的。

// 函式功能:執行字串形式的版本比較
// 返回值:比較成功返回真,比較失敗返回假
//         比較結果儲存到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;
}