Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Split function in Visual C++

Status
Not open for further replies.

MDIGX

Programmer
Feb 18, 2004
7
US
I'm trying to find a split function similar to the one in Visual Basic that can take a comma delimited string and turn it into an array. My C++ is not strong, so any help would be greatfully appreciated.

Also... I'm trying to add functionality to existing DLL code that runs on a server, what is the best way to attempt to step through a DLL to debug?
 
There is no split function like you know one in VB.
Here you find a working solution for Split and more ...using CTypedPtrList<CPtrList, T*> template ;
Maybe will be hard to understand but you can use as here and review later!
Code:
#include <afxtempl.h>

template <class T>
class CMyTypedPtrList : public CTypedPtrList<CPtrList, T*>
{
public:
	// Construction
	CMyTypedPtrList (bool ownsElements = false)
	{
		bOwnsElements = ownsElements;
	}
	CMyTypedPtrList (const CMyTypedPtrList<T>& rhs)
	{
		*this = rhs;
	}
	
	// Implementation
	virtual ~CMyTypedPtrList()
	{
		RemoveAll();
	}
// Attributes
public:

// Operations
public:

// Overrides
	CMyTypedPtrList<T>& operator=(const CMyTypedPtrList<T>& rhs)
	{
		if (this != &rhs)
		{
			RemoveAll();
			bOwnsElements = rhs.bOwnsElements;

			POSITION pos_rhs = rhs.GetHeadPosition();
			while ( pos_rhs != NULL )
			{
				T* t = rhs.GetNext(pos_rhs);
				if (rhs.bOwnsElements)
					AddTail(new T(*t));	// we need to take our own copy!
				else
					AddTail(t);
			}
		}
		return *this;
	}
	void RemoveAll ()
	{
		if (bOwnsElements)
		{
			POSITION pos = GetHeadPosition();
			while (pos)
			{
				T *t = GetNext(pos);
				delete t;
				t=NULL;
			}
		}

		CTypedPtrList<CPtrList, T*>::RemoveAll();
	}

	enum eSortType { ASCENDING, DESCENDING };

	void Sort (eSortType SortType = ASCENDING)
	{
		CMyTypedPtrList<T> listTmp (*this);

		RemoveAll ();

		POSITION pos = listTmp.GetHeadPosition();
		while ( pos != NULL )
		{
			T* t = listTmp.GetNext(pos);
			if (bOwnsElements)
				AddSorted(new T(*t));
			else
				AddSorted(t);
		}

		if (SortType == DESCENDING)
		{
			for (int i=0, j=GetCount ()-1; i < j; i++, j--)
				Swap (i,j);
		}

	}

	void AddSorted(T* pNewItem)
	{
		ASSERT(AfxIsValidAddress(pNewItem, sizeof(T)));

		T*	pItem;
		POSITION pos;
		int i;
		// advance to the appropriate spot for insertion
		for(i=0,pos = GetHeadPosition(); pos != NULL; i++)
		{
			pItem = GetAt(pos);
			// don't advance pos if we're inserting
			if (*pNewItem < *pItem)
				break;

			GetNext(pos);
		}

		// this results in equal items being in reverse order of addition
		if ( pos == NULL )
			AddTail(pNewItem);
		else
		if ( i == 0 )
			AddHead(pNewItem);
		else
			InsertBefore(pos, pNewItem);
	}

	bool MoveUp(int nCurrentPosn)
	{
		if (nCurrentPosn > 0)
		{
			return Swap (nCurrentPosn-1, nCurrentPosn);
		}
		return false;
	}
	bool MoveDown(int nCurrentPosn)
	{
		if (nCurrentPosn < (GetCount()-1))
		{
			return Swap (nCurrentPosn, nCurrentPosn+1);
		}
		return false;
	}

	bool Swap (int nPosn1, int nPosn2)
	{			
		if (nPosn1 != nPosn2)
		{
			POSITION pos1 = FindIndex(nPosn1);		
			POSITION pos2 = FindIndex(nPosn2);

			if ((pos1 != NULL) && (pos2 != NULL))
			{
				T *pt1 = GetAt(pos1);
				T *pt2 = GetAt(pos2);
				SetAt (pos2, pt1);
				SetAt (pos1, pt2);
				return true;
			}
		}
		
		return false;
	}

	POSITION Find (const T* rhs)
	{
		POSITION pos = GetHeadPosition();
		while (pos)
		{
			T *t= GetAt(pos);
			if(*t == *rhs)
				return pos;

			GetNext (pos);
		}

		return NULL;
	}

	bool operator==(const CMyTypedPtrList<T>& rhs)
	{
		POSITION pos = GetHeadPosition();
		POSITION pos_rhs = GetHeadPosition();
		while ((pos != NULL) && (pos_rhs != NULL))
		{
			T *t		= GetNext(pos);
			T *t_rhs	= GetNext(pos_rhs);
			if(*t != *t_rhs)
				return false;
		}

		return true;
	}
	bool operator!=(const CMyTypedPtrList<T>& rhs)
	{
		return !(*this == rhs);
	}
	bool operator<(const CMyTypedPtrList<T>& rhs)
	{
		bool bIsLess = true;
		POSITION pos = GetHeadPosition();
		POSITION pos_rhs = GetHeadPosition();
		while ((pos != NULL) && (pos_rhs != NULL))
		{
			T *t		= GetNext(pos);
			T *t_rhs	= GetNext(pos_rhs);
			if(*t_rhs < *t)
				return false;
		}

		return true;
	}

protected:
private:
	bool bOwnsElements;

};

///////////////////////////////////////////////////////

class CMyStringPtrList : public CMyTypedPtrList<CString>
{
public:
	CMyStringPtrList (bool ownsElements = false):CMyTypedPtrList<CString>(ownsElements){}
	virtual ~CMyStringPtrList (){}

	enum { SPLIT_ALL = -1, JOIN_ALL = -1};


	// Notes:
	// If nLimit = -1 then split the whole string (default)
	// or you can get the first 'n' tokens 
	// If bKeepEmptyToken is true then an empty string will be kept
	// i.e. an empty token is encountered when there are two or more consecutive 
	// delimiters 
	// eg:	The string: &quot;GEORGE,IS,A,,,,DOOD&quot; when split with bKeepEmptyToken = true
	//		will result in a list of tokens...
	//		GEORGE
	//		IS
	//		A
	//		<empty>
	//		<empty>
	//		<empty>
	//		DOOD
	int Split (const CString& sBuf, TCHAR cDelim, int nLimit = SPLIT_ALL, bool bKeepEmptyToken=true)
	{
		CString sDelim (cDelim);
		return Split (sBuf, sDelim, nLimit, bKeepEmptyToken);
	}

	int Split (const CString& sBuf, const CString& sDelim, int nLimit = SPLIT_ALL, bool bKeepEmptyToken=true)
	{
		// if nLimit == 0 then it means that do not split!
		// Can't think why someone would want to do this
		// but func. must behave predictably!
		if (nLimit == 0)
		{
			AddTail (new CString (sBuf));
			return GetCount ();
		}

		CString sTemp (sBuf);
		int		nCount = 0;
		int		posn = sTemp.Find (sDelim);

		while (posn != -1)
		{
			CString *s = new CString (sTemp.Mid (0, posn)); 
			if (!s->IsEmpty() || bKeepEmptyToken)
				AddTail (s);
			else
				delete s;

			++nCount;
			if ((nLimit != SPLIT_ALL) && (nCount == nLimit))
			{
				return GetCount ();
			}
			
			// chop off the token (from left), & get the remainder of string
			sTemp = sTemp.Right (sTemp.GetLength() - sDelim.GetLength () - posn);
			posn = sTemp.Find (sDelim);
		}

		if (!sTemp.IsEmpty () || bKeepEmptyToken)
			AddTail (new CString (sTemp));

		return GetCount ();
	}

	int Join (CString& sRetBuf, const TCHAR cDelim, int nLimit = JOIN_ALL, bool bIncludeEmptyToken=true)
	{
		CString sDelim (cDelim);
		return (sRetBuf, sDelim, nLimit, bIncludeEmptyToken);
	}
	int Join (CString& sRetBuf, const CString& sDelim, int nLimit = JOIN_ALL, bool bIncludeEmptyToken=true)
	{
		POSITION pos = GetHeadPosition ();
		int nCount=0;
		while (pos)
		{
			// if nLimit = 0 then we do nothing!
			if ((nLimit != JOIN_ALL) && (nCount == nLimit))
				break;

			CString *s = GetNext (pos);
			if (!s->IsEmpty () || bIncludeEmptyToken)
				sRetBuf += *s;
			++nCount;

			// do not add a delim after LAST element
			if (( (nLimit == JOIN_ALL) && (nCount < GetCount()) ) || 
				( nCount < nLimit ))
				sRetBuf += sDelim;
		}

		// return the string length!
		return sRetBuf.GetLength();
	}

	// didn't want to complicate things with throwing exceptions here
	// so a simple solution is to return an empty string
	// then user can check against the func NOSTRING(...);
	const CString& operator[](int index)
	{
		ASSERT (index < GetCount ());
		if (index < GetCount ())
		{
			POSITION pos = FindIndex (index);
			if (pos)
				return *(GetAt (pos));
		}
				
		return m_sEmptyString;
	}


	bool NOSTRING(const CString& rhs) { return &m_sEmptyString == &rhs; }

private:
	CString m_sEmptyString;

};
Put above code in header file and link it with your code. 

How to use in another application which is linked with your dll?

CString sRecord;
CMyStringPtrList aStringList( TRUE );
aStringList.Split( sRecord,';');
// trim spaces
for ( int x = 0; x < aStringList.GetCount(); x++ ) {
	((CString*)&aStringList[x])->TrimLeft();
	((CString*)&aStringList[x])->TrimRight();
}
SetAccount(aStringList[0]);
SetAmmount(aStringList[1]);

No new, no delete!!!
-obislavu-





 
As I understand you need to get word by word. Use strtok.

Ion Filipski
1c.bmp
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top