Alphanumeric and Month-Name Ordering
Copyright © 2026 by David Wincelberg

Demo Program

I revised the implementation of alphanumeric ordering by removing the handling of decimal and negative numbers so that the period, dash, and underscore characters may be used as separators in numeric text. In addition, numeric text may contain a thousands separator, such as a comma or a space.

English month names may now also be sorted in their natural order when they are enclosed in braces. Other sets of month names can be added to the program. See the image for an example.

This program can be downloaded from TextANSort.zip (1,019 KB). Right click on this link, select "Save link as," choose a location, and click on the Save button.

Program image: Alphanumeric Ordering Test Bed

back to top

Simple Alphanumeric Ordering Source Code

Alphanumeric ordering is now in several classes. Here is part of it.

// Actions:	Limits comparison results to -1, 0 or 1 since
//		some sorting functions may expect these values.
int CStringOrder::LimitResult (int nTest) const
{
	if (nTest < 0) {
		return -1;
	}
	else if (nTest == 0) {
		return 0;
	}
	else {
		return 1;
	}
}	// LimitResult

// Actions:	Simple alphanumeric comparisons.
// Notes:	Requires that there be a digit in the same starting place in
//		each filename.	Limited to numbers smaller than 2^31,
//		about two billion (2,147,483,647).
int CStringSANOrder::CompareStrings (LPCTSTR pszItem1, LPCTSTR pszItem2) const
{
	if (pszItem1 == nullptr || pszItem2 == nullptr) return 0;

	register LPCTSTR psz1{ pszItem1 };
	register LPCTSTR psz2{ pszItem2 };
	int nTest{};

	while (*psz1 != _T('\0') && *psz2 != _T('\0')) {
		if (::_istdigit (*psz1) && ::_istdigit (*psz2)) {	// generic for isdigit
			nTest = ::_ttoi (psz1) - ::_ttoi (psz2);	// generic for atoi

			if (nTest != 0) {
				return LimitResult (nTest);
			}

			// Moves past the numbers.
			while (::_istdigit (*psz1)) ++psz1;
			while (::_istdigit (*psz2)) ++psz2;
		}
		else {
#if defined(LOCALEORDER)
			// locale caseless match
			nTest = ::_tcsnicoll (psz1, psz2, 1);			// generic for _strnicoll
#else
			// caseless match
			nTest = ::_totlower (*psz1) - ::_totlower (*psz2);	// generic for tolower
#endif

			if (nTest != 0) {
				return LimitResult (nTest);
			}

			++psz1;
			++psz2;
		}
	}

	nTest = *psz1 - *psz2;	// At least one string has ended.
	return LimitResult (nTest);
}	// CompareStrings

The zip file for alphabetic and simple alphanumeric ordering can be downloaded from StringSANOrder.zip (3 KB). Right click on this link, select "Save link as," choose a location, and click on the Save button.

This source code may be used in any program, including commercial ones. Please credit me in your program's documentation.

back to top

Alphanumeric Ordering with the STL

Alphanumeric ordering can be used with Standard Template Library containers. The following image is of a program that uses an STL multiset for sorting. ANO is connected to a multiset with

std::multiset<CString, CSANOCompare> strSet;

where CSANOCompare s defined in SANOCompare.*. It includes

bool CSANOCompare::operator() (LPCTSTR pszItem1, LPCTSTR pszItem2) const
{
	return SimpleANCompare (pszItem1, pszItem2) < 0;
}

for comparing LPCTSTR strings. It also contains functions for comparing std::strings.  See ANOwithSTL.zip (1,972 KB) for details. Right click on this link, select "Save link as," choose a location, and click on the Save button.

Program image: Alphanumeric Ordering with the Standard Template Library

back to top



Last updated: 13-July-2026