C ++ case sensitivity conversion and Performance
Case-sensitive conversion and Performance
Preface
This article mainly discusses some of the most basic case conversion functions and APIs, and does not discuss some common case conversion interfaces in the string library, in addition, This article focuses on the performance of these conversion functions and some problems encountered in daily development.
Scope not considered
In fact, ctype. h has defined a set of macro, is not to consider whether the character falls in the A-Z, a-z range, directly calculated (directly using addition and subtraction or using bitwise AND or calculation, the difference is not very large ). Obviously, this is the most efficient, but it may be a problem to use it. If you encounter Chinese characters or other youbang characters, the conversion may be wrong, of course, if you have already confirmed that the input will fall into the A-Z, a-z range, you can use this method to calculate.
# Define _ tolower (_ Char)-'A' + 'A ')
# Define _ toupper (_ Char)-'A' + 'A ')
C library (MS)
Lowercase
Tolower
Towlower
_ Tolower_l
_ Towlower_l
Convert to uppercase
Toupper
Towupper
_ Toupper_l
_ Towupper_l
Library C does not provide a function to directly convert the entire string. It can only convert a single character. In addition, it should be noted that the provided towlower and towupper functions are surprisingly inefficient. Why is the efficiency low? I did not go into details. The tolower and toupper parameters are int, it can also be used for the wide character version. I don't know why the towlower and towupper functions are provided.
C ++ Library (MS)
Lowercase
Errno_t _ strlwr_s (char * str, size_t numberOfElements );
Errno_t _ wcslwr_s (wchar_t * str, size_t numberOfElements );
Convert to uppercase
Errno_t _ strupr_s (char * str, size_t numberOfElements );
Errno_t _ wcsupr_s (wchar_t * str, size_t numberOfElements );
At the same time, a set of template functions with the same name can be directly converted by passing only the character array name. The principle is to use array references to export the array size and then call the original conversion function, microsoft uses many similar tips (crtdefs. h ).
Note: The suffix _ s indicates secure conversion.
_ DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_0 (errno_t, _ wcslwr_s, _ inout_ecount (_ Size) wchar_t, _ String)
# Define _ DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_0 (_ ReturnType, _ FuncName, _ DstType, _ Dst )\
Extern "C ++ "\
{\
Template \
Inline \
_ ReturnType _ CRTDECL _ FuncName (_ DstType (& _ Dst) [_ Size]) \
{\
Return _ FuncName (_ Dst, _ Size );\
}\
}
Windows API
Lowercase
CharLower
CharLowerBuff
Convert to uppercase
CharUpper
CharUpperBuff
Windows APIs are mostly macros. The corresponding multi-byte and wide character versions are appended with A and W.
STL Library
The string in STL does not provide a special conversion interface, but the algorithm in STL is implemented using a method similar to the following (conversion functions can be customized or used by the system ), this is not to mention.
Transform (strCostInfo2.begin (), strCostInfo2.end (), strCostInfo2.begin (),: tolower );
Transform (strCostInfo2.begin (), strCostInfo2.end (), strCostInfo2.begin (),: toupper );
Self-implementation (Scope of consideration)
//////////////////////////////////////// //////////////////////////////////
Static const char s_ch_a_minus_A = 'a'-'A ';
Inline char ConvToUpperA (char chConv)
{
Return (chConv> = 'A' & chConv <= 'Z ')? (ChConv & 0xdf): chConv;
}
Inline wchar_t ConvToUpperW (wchar_t wchConv)
{
Return (wchConv> = L 'A' & wchConv <= L 'Z ')? (WchConv & 0x00df): wchConv;
}
Inline char ConvToLowerA (char chConv)
{
Return (chConv> = 'A' & chConv <= 'Z ')? (ChConv | 0x20): chConv;
}
Inline wchar_t ConvToLowerW (wchar_t wchConv)
{
Return (wchConv> = L 'A' & wchConv <= L 'Z ')? (WchConv | 0x0020): wchConv;
}
Inline void ConvStrToUpperA (char * strConv)
{
For (size_t I = 0; strConv [I]! = '\ 0'; ++ I)
{
// If (strConv [I]> = 'A' & strConv [I] <= 'Z ')
// StrConv [I] & = 0xdf;
StrConv [I] = ConvToUpperA (strConv [I]);
}
}
Inline void ConvStrToUpperW (wchar_t * strConv)
{
For (size_t I = 0; strConv [I]! = L' \ 0'; ++ I)
{
// If (strConv [I]> = L 'A' & strConv [I] <= L 'Z ')
// StrConv [I] & = 0x00df;
StrConv [I] = ConvToUpperW (strConv [I]);
}
}
Inline void ConvStrToLowerA (char * strConv)
{
For (size_t I = 0; strConv [I]! = '\ 0'; ++ I)
{
// If (strConv [I]> = 'A' & strConv [I] <= 'Z ')
// StrConv [I] | = 0x20;
StrConv [I] = ConvToLowerA (strConv [I]);
}
}
Inline void ConvStrToLowerW (wchar_t * strConv)
{
For (size_t I = 0; strConv [I]! = L' \ 0'; ++ I)
{
// If (strConv [I]> = L 'A' & strConv [I] <= L 'Z ')
// StrConv [I] | = 0x0020;
StrConv [I] = ConvToLowerW (strConv [I]);
}
}
The difference with direct conversion is that only the A-Z, a-z range of characters conversion, there are some limitations, but in most scenarios is available, and the efficiency is good enough.
Performance
After talking about so many conversion methods, I am most concerned about the method with the highest efficiency. Let's test the program and test environment directly and let the data speak.
Test Environment
Windows 7 x64 SP1
AMD Phenom (tm) II X4 840 T (4 cores)
10 Gb memory
Test Methods
Rotate and convert strings of 1024 bytes (excluding the end 0) in case, cyclically for millions of times, and count the time.
Test Results
====> Time consumption of case-insensitive conversion functions (1000000 cycles) <====
Direct Calculation (excluding the range): [1077] milliseconds
C-database function: [6193] milliseconds
C ++ library function: [5912] milliseconds
STL Algorithm Library template function (custom conversion): [3557] milliseconds
STL Algorithm Library template function (System Conversion): [6146] milliseconds
Custom function: [3791] milliseconds
Windows API: [13884] milliseconds
====> Time consumption of case-insensitive conversion functions (1000000 cycles) <====
Direct Calculation (excluding the range): [1076] milliseconds
C-database function: [6272] milliseconds
C ++ library function: [5865] milliseconds
STL Algorithm Library template function (custom conversion): [3292] milliseconds
STL Algorithm Library template function (System Conversion): [6053] milliseconds
Custom function: [3666] milliseconds
Windows API: [13790] milliseconds
The results of Multiple tests show that the range is obviously the fastest, but there are too few available scenarios. The second is the custom case-sensitive Conversion Function (such as Chinese characters are not case-sensitive, you only need to consider the limited ascii characters), and use STL containers and algorithms to maximize efficiency. The efficiency of WindowsAPI is relatively low. Of course, the reason for the low efficiency is not an algorithm problem, but a lot of situations. For example, you need to consider localization and special case-sensitivity conversion for some languages.
In a suitable scenario, the use of custom case-sensitivity conversions is sufficient. It takes about half a day to study the problem. The problem is due to the performance problem of a URL Processing function, A large amount of computing of this function is consumed by converting the URL to lowercase. After transformation, the performance can be easily improved by 60%.