⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stdstring.cpp

📁 字符串处理源代码:StdString
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ===================================================================================================
// FILE: StdString.cpp
// AUTHOR: Joe O'Leary (with help -- see comments in StdString.h)
// REMARKS:
//		This file implements the CStdString class which was declared in
//		StdString.h.  It also implements some helper functions used for
//		our own UNICODE/ANSI conversion macros.
//
// COPYRIGHT:
//		1999 Joseph M. O'Leary.  This code is free.  Use it anywhere you want.  Rewrite
//		it, restructure it, whatever you want.  Please don't blame me if it causes your
//		$30 billion dollar satellite to explode.  If you redistribute it in any form, I
//		would appreciate it if you would leave this notice here.
//
//		If you find any bugs, please let me know:
//
//				jmoleary@earthlink.net
// ===================================================================================================

#include "StdAfx.h"
#include "StdString.h"
#include <xutility>
#if defined (max)
	#undef max
	#undef min
#endif
#define max(a,b) std::_cpp_max(a,b)
#define min(a,b)std::_cpp_min(a,b)

#include <algorithm>
#include <functional>
#include <locale>


// If conversion has not been explicitly turned off...
#ifndef _NO_STDCONVERSION
	
	// Global MBCS-to-UNICODE helper function
	PWSTR  StdA2WHelper(PWSTR pw, PCSTR pa, int nChars)
	{
		if (pa == NULL)
			return NULL;
		ASSERT(pw != NULL);
		pw[0] = '\0';
		VERIFY(MultiByteToWideChar(CP_ACP, 0, pa, -1, pw, nChars));
		return pw;
	}

	// Global UNICODE-to_MBCS helper function
	PSTR  StdW2AHelper(PSTR pa, PCWSTR pw, int nChars)
	{
		if (pw == NULL)
			return NULL;
		ASSERT(pa != NULL);
		pa[0] = '\0';
		VERIFY(WideCharToMultiByte(CP_ACP, 0, pw, -1, pa, nChars, NULL, NULL));
		return pa;
	}

#endif // _NO_STDCONVERSION

#if !defined(_MFC_VER)
	HINSTANCE CStdString::hInstResource = ::GetModuleHandle(NULL);
#endif

// ---------------------------------------------------------------------------------------
// CONSTRUCTOR:  CStdString::CStdString
//		CStdString(PCTSTR pT)
//           
// DESCRIPTION:
//		This particular overload of the CStdString constructor takes either a real
//		string or a resource ID which has been converted with the MAKEINTRESOURCE()
//		macro
//
// PARAMETERS: 
//		pT	- a NULL-terminated raw string with which the CStdString object should be
//			  initialized or a resource ID converted with MAKEINTRESOURCE (or NULL)
//
// RETURN VALUE: none -- it's a constructor
// ---------------------------------------------------------------------------------------
CStdString::CStdString(PCTSTR pT) : STRBASE(szTNull)	// constructor for either a literal string or a resource ID
{ 
	if ( pT == NULL )
		;
	else if ( HIWORD(pT) == NULL ) 
	{ 
		if ( !Load(_TRES(pT)) ) 
			TRACE(_T("Can't load string %u\n"), _TRES(pT));
	} 
	else
		*this = pT;
}
// ---------------------------------------------------------------------------------------
// FUNCTION:  CStdString::Load
//		bool Load(UINT nId)
//           
// DESCRIPTION:
//		This function attempts to load the specified string resource from application's
//		resource table.
//
// PARAMETERS: 
//		nId - the resource Identifier from the string table.
//
// RETURN VALUE: 
//		true if the function succeeds, false otherwise
// ---------------------------------------------------------------------------------------
#define MAX_LOAD_TRIES	5			// max # of times we'll attempt to load a string
#define LOAD_BUF_SIZE	256			// 256 characters should be more than enough for most strings
bool CStdString::Load(UINT nId)
{
#ifdef _MFC_VER
	CString strRes(MAKEINTRESOURCE(nId));
	*this = strRes;
	return !empty();

#else
	
	// Get the resource name via MAKEINTRESOURCE.  This line is pretty much lifted from CString

	PCTSTR szName = MAKEINTRESOURCE((nId>>4)+1);
	HINSTANCE hModule = CStdString::GetResourceHandle();

	// No sense continuing if we can't find the string resource.

	if ( ::FindResource(hModule, szName, RT_STRING) == NULL )
		return false;
	
	int nMaxLen = 0;
	int nRetLen = 0;
	int nTries = 0;
	PTSTR pBuf = NULL;

	// Keep looping until:
	//		we have a buffer big enough to hold the string,
	//		or we exceed the maximum number of tries,
	//		or there is an error

	do
	{
		nMaxLen += LOAD_BUF_SIZE;
		pBuf = reinterpret_cast<PTSTR>(_alloca((nMaxLen) * sizeof(TCHAR)));
		nRetLen = ::LoadString(hModule, nId, pBuf, nMaxLen);
		if ( nRetLen == 0 )
			TRACE(_T("Resource ID %d does not exist -- cannot load\n"), nId);
		else if ( nRetLen < 1 )
			TRACE(_T("Error 0x%X attempting to load resource %d\n"), ::GetLastError(), nId);
		else if ( nRetLen+1 < nMaxLen )
			*this = pBuf;

	} while ( nRetLen+1 == nMaxLen && nTries++ < MAX_LOAD_TRIES );

	return true;

#endif
}

//  JMO -- not tested yet.  Uncomment at your own risk

// ---------------------------------------------------------------------
//  Wildstrcmp() - compares strings using DOS wildcards
//              'mask' may contain '*' and '?'
//              returns true if 's' matches 'mask', otherwise false
// ---------------------------------------------------------------------
//bool CStdString::Wildstrcmp (PCTSTR c_s, PCTSTR c_mask)
//{
//	PTSTR mask=(PTSTR)c_mask;
//	PTSTR s=(PTSTR)c_s;
//	  
//	while (*mask)
//	{
//		switch (*mask)
//		{
//		case _T('?'):
//			if (!*s)
//				return false;
//			s++;
//			mask++;
//			break;
//
//		case _T('*'):
//			while (*mask == _T('*'))
//				mask++;
//			if (!*mask)
//				return true;
//			if (*mask == _T('?'))
//				break;
//			while (*s != *mask)
//			{
//				if (!*s)
//					return false;
//				s++;
//			}
//			s++;
//			mask++;
//			break;
//
//		default:
//			if ( *s != *mask )
//				return false;
//			s++;
//			mask++;
//		}
//	}
//
//	if ( !*s && *mask )
//		return false;
//
//	return true;
//}





// ---------------------------------------------------------------------------------------
// FUNCTION:  CStdString::Format
//		void _cdecl Formst(CStdString& PCTSTR szFormat, ...)
//		void _cdecl Format(PCTSTR szFormat);
//           
// DESCRIPTION:
//		This function does sprintf/wsprintf style formatting on CStdString objects.  It
//		is very much a copy of the MFC CString::Format function.  Some people might even
//		call this identical.  However all these people are now dead.
//
// PARAMETERS: 
//		nId - ID of string resource holding the format string
//		szFormat - a PCTSTR holding the format specifiers
//		argList - a va_list holding the arguments for the format specifiers.
//
// RETURN VALUE:  None.
// ---------------------------------------------------------------------------------------
// formatting (using wsprintf style formatting)
void CStdString::Format(UINT nId, ...)
{
	va_list argList;
	va_start(argList, nId);

	CStdString strFmt;
	if ( strFmt.Load(nId) )
		FormatV(strFmt, argList);

	va_end(argList);
}
void CStdString::Format(PCTSTR szFormat, ...)
{
	va_list argList;
	va_start(argList, szFormat);
	FormatV(szFormat, argList);
	va_end(argList);
}

// ---------------------------------------------------------------------------------------
// FUNCTION:  CStdString::FormatV
//		void FormatV(PCTSTR szFormat, va_list, argList);
//           
// DESCRIPTION:
//		This function formats the string with sprintf style format-specifications.  It
//		makes a general guess at required buffer size and then tries successively larger
//		buffers until it finds one big enough or a threshold (MAX_FMT_TRIES) is exceeded.
//
// PARAMETERS: 
//		szFormat - a PCTSTR holding the format of the output
//		argList - a Microsoft specific va_list for variable argument lists
//
// RETURN VALUE: 
// ---------------------------------------------------------------------------------------
#define MAX_FMT_TRIES	5
#define FMT_BLOCK_SIZE	256
void CStdString::FormatV(PCTSTR szFormat, va_list argList)
{
	va_list argListSave = argList;

	// We're just going to use the normal _vsntprintf function, assuming FMT_BLOCK_SIZE characters.
	// However, if FMT_BLOCK_SIZE characters is not be enough, we will try 2 * FMT_BLOCK_SIZE, then
	// 3 * FMT_BLOCK_SIZE, up to MAX_FMT_TRIES * FMT_BLOCK_SIZE characters.

	int nTriesLeft = MAX_FMT_TRIES-1;
	int nCharsUsed = - 1;
	int nTChars = 0;

	// Keep looping until either we succeed or we have exhausted the number of tries

	do
	
	{
		nTChars += FMT_BLOCK_SIZE;		// number of TCHARS in the string

		// Allocate a buffer on the stack to hold the characters and NULL terminate it

		TCHAR* szBuf = reinterpret_cast<TCHAR*>(_alloca((nTChars+1) * sizeof(TCHAR)));
		szBuf[nTChars+1] = '\0';

		// Now try the actual formatting.  The docs say even the wide version takes the
		// number of BYTES as the second argument, not the number of characters (TCHARs).
		// However the docs are wrong.  I checked the actual implementation of 
		// _vsnprintf and _vsnwprintf and they multiply count by sizeof TCHAR. 

		nCharsUsed = _vsntprintf(szBuf, nTChars+1, szFormat, argListSave);
		if ( nCharsUsed >= 0 )
			*this = szBuf;

	} while ( nCharsUsed < 0 && nTriesLeft > 0);

	va_end(argListSave);
}

// This class is used for TrimRight() and TrimLeft() function implementations.
// Thanks to Dave Plummer for catching a bug here (it's fixed now).
class NotSpace : public std::unary_function<TCHAR, bool>
{
public:
	// The fast, unportable method of doing this is to simply call _istspace().  The
	// slow, portable way is to use the Standard C++ library.  Uncomment whichever
	// one you need.
	bool operator() (TCHAR tchar) { return !_istspace(tchar); }
//	bool operator() (TCHAR tchar) { return !std::isspace(tchar, std::locale::classic());}
};


// ---------------------------------------------------------------------------------------
// FUNCTION:  CStdString::TrimRight
//		CStdString& TrimRight();
//
// DESCRIPTION:
//		This function removes any whitespace characters from the right end of the string.
//
// PARAMETERS: none
// RETURN VALUE:
//		a reference to this object (*this) -- allows chaining together of
//		these calls, eg. strTest.TrimRight().TrimLeft().ToUpper();
// ---------------------------------------------------------------------------------------
CStdString& CStdString::TrimRight()
{
	CStdString::reverse_iterator iter = std::find_if(rbegin(), rend(), NotSpace());
	if ( iter != rend() )
	{
		CStdString::size_type nNewSize = find_last_of(*iter);
		erase(nNewSize+1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -