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.
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.
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.
Last updated: 13-July-2026