CStringArrayをソートする

MSDNライブラリを見ていたら「qsort_s」という関数を発見。

クイックソート関数qsortは昔からあったが、知らないうちにqsort_sができていた。これら2つは何が違うかと言うと...比較用関数に独自パラメータ(context)を渡せるかどうか。qsortはパラメータを渡せないため、単純なソートには使えるものの実際問題として使い物にならない関数だった。

そのため今まではクイックソートが必要な時はqsortのソースコードを元にパラメータが利用できる関数を作成しなければいけなかった。qsort_sのおかげでその手間が省けるようになった。ここではこのqsort_sを利用してCStringArrayの文字列をソートする。

#include "atlstr.h"
#include "atlcoll.h"

class	CDnpSortString
{
	//比較関数
	static	int	SortStringArrayCompare(void* pContext,const void* pData1,const void* pData2)
	{
		if(pContext == NULL)
			return	0;
		return	((CDnpSortString*)pContext)->SortStringArrayCompare_(pData1,pData2);
	}

	//昇順か降順か
	bool		_bABC;

	//ソート対象
	CAtlArray<CAtlString>*	_pastrText;

public:

	CDnpSortString()
	{
		_bABC = true;
		_pastrText = NULL;
	}

	//比較関数の実体
	//外部からは呼ばないこと!
	int	SortStringArrayCompare_(const void* pData1,const void* pData2)
	{
		size_t	nSize;

		if(_pastrText == NULL)
			return	0;

		nSize = _pastrText->GetCount();
		if(*(size_t*)pData1 >= nSize || *(size_t*)pData2 >= nSize)
			return	0;

		if(_bABC)
			return	::_tcscmp((*_pastrText)[*(size_t*)pData1],(*_pastrText)[*(size_t*)pData2]);
		else
			return	::_tcscmp((*_pastrText)[*(size_t*)pData2],(*_pastrText)[*(size_t*)pData1]);
	}


	//
	//	CStringArrayのソート
	//
	bool	SortStringArray(CAtlArray<CAtlString>& astrText,bool bABC)
	{
		size_t	i;
		size_t	nSize;
		size_t*	pnIndex;
		CAtlArray<CAtlString>	astrTmp;

		nSize = astrText.GetCount();
		if(nSize == 0)
			return	false;

		pnIndex = new size_t[nSize];
		if(pnIndex == NULL)
			return	false;

		astrTmp.SetCount(nSize);
		for(i = 0; i < nSize; i++)
		{
			pnIndex[i] = i;
			astrTmp[i] = astrText[i];
		}

		_bABC = bABC;
		_pastrText = &astrText;
		::qsort_s(pnIndex,nSize,sizeof(size_t),SortStringArrayCompare,this);
		_pastrText = NULL;

		for(i = 0; i < nSize; i++)
			astrText[i] = astrTmp[pnIndex[i]];

		delete	pnIndex;

		return	true;
	}

};



void	Test(void)
{
	///////////////////
	//ダミーデータ用意
	//
	CAtlArray<CAtlString>	astrFiles;

	astrFiles.Add(_T("abc"));
	astrFiles.Add(_T("aac"));
	astrFiles.Add(_T("aec"));
	astrFiles.Add(_T("bbc"));


	///////////////////
	//ソート
	//
	CDnpSortString	cSort;
	cSort.SortStringArray(astrFiles,false);


	///////////////////
	//結果表示
	//
	size_t		i;
	size_t		nSize;
	CAtlString	strMessage;

	nSize = astrFiles.GetCount();
	for(i = 0; i < nSize; i++)
	{
		strMessage += astrFiles[i];
		strMessage += _T("\n");
	}

	::MessageBox(NULL,strMessage,_T(""),MB_OK);
}

プロジェクトファイルをダウンロード


カテゴリー「文字列操作」 のエントリー