Effective STL Terms 35

zhaozj2021-02-11  237

Terms 35: Compare simple cases of simple cases through Mismatch or Lexicographical comparison

The most common question of a STL rookie is "How do I use STL to make case case-sensitive strings?" This is a simple and simple question. The case where the case is not related to the string, it is easy to really, it is really difficult, depending on how you want to solve this problem. This task is simple if you ignore international issues and only focus on the type of string strcmp. If you have the ability to handle characters in the language in the language (that is, the string of the text is in addition to the language other than English) or the program uses a LOCALE instead of the default, this task is difficult.

In this clause, I will make a simple version of this issue, because that is enough to demonstrate how STL completes the task. (This problem can also be resolved with STL. Instead, it solves the problem related to the Locale you can see in Appendix A.) In order to make simple problems more challenging, I will Treated twice. Programmers who want to use case-sensitive factors typically require two different call interfaces, a similar strCMP (return a negative number, zero or positive), another similar to Operator (Return True or false). So I will demonstrate how to use the STL algorithm to implement two call interfaces.

But first, we need a way to determine if the two characters are equal except for casements. This is a complex problem when considering internationalization issues. The following characters are more apparent to a smaller solution, but it is similar to strCMP string comparison, because I only consider the string comparison similar to Strcmp, this function is enough:

INT CICHARCOMPARE (CHAR C1, CHAR C2) / / Size does not turn to compare characters

{// C1 and C2, if C1

// If C1 == C2 returns 0, if C1> C2 returns 1

INT IC1 = TOLOWER (static_cast (c1)); // Interpretation of these statements

INT IC2 = TOLOWER (static_cast (c2)); // See below

IF (IC1

IF (LC1> IC2) RETURN 1;

Return 0;

}

This function follows strCMP, which can return a negative number, zero or positive, dependent between C1 and C2. Unlike StrCMP, CICHARCompare converts two parameters to lowercase before comparing. This creates a case-sensitive character comparison.

Many functions in (also ), the parameters and return value types of TOLOWER are int, but unless this INT is EOF, its value must be able to behave as a unsigned char. In C and C , the char may or may not be a symbol (depending on the implementation). When the char is a symbol, the only confirmation of its value can be expressed as the unsigned char to convert the TOLOWER. This explains the conversion in the above code. (In the unsigned implementation, this conversion does not work.) This also explains the INT instead of saving the TOLOWER return value.

It is easy to write CICHARCompare, it is easy to write two string comparison functions that our first case-unrelated, provide an interface similar to StrCMP. CISTRINGCOURE This function returns a negative number, zero or positive, depending on the relationship between the string to compare. It is based on the Mismatch algorithm because the Mismatch determines the position of the first corresponding different value in the two intervals. Before we can call Mismatch, we must first satisfy its premise. In particular, we must determine if a string is shorter than the other short, short strings as the first range. So we can put the real work in a function called CISTRINGCompareImpl, then let CISTRINGCompare simply make sure that the passive parameter order is correct, adjust the return value if the parameter exchanges:

INT CISTRINGCOMPAREIMPL (const string & s1, // Implementation See below

Const String & S2);

Int CistringCompare (Const String & S1, Const String & S2)

{

IF (S1.SIZE () <= s2.size ()) Return CistringCompareImpl (S1, S2);

Else Return -cistringCompareImpl (S2, S1);

}

In CISTRINGCOMPAREIMPL, most of the work is done by mismatch. It returns a pair of iterators, indicating that the first corresponding character in the range is different:

INT CISTRINGCOMPAREIMPL (Const String & Si, Const Strings S2)

{

Typedef Pair

PSCI P = mismatch (// explained below

S1.BEGIN (), S1.End (), // Why do we

S2.begin (), // Need not2; see

NOT2 (PTR_FUN (CICHARCompare))); // Terms 41 explain why

// We need ptr_fun

IF (p.first == s1.end ()) {// If true, S1 is equal to

IF (p.second == s2.end ()) Return 0; // S2 or S1 is shorter than S2

Else Return -1;

}

Return Cicharcompare (* p.first, * p.second); // Two strings relationship

} // and the mismatched characters

Fortunately, the comment makes all things clear. Basically, once you know the location of the first different characters in the string, you can easily determine which string, if any, in front. The only thing that may be strange is to pass the judgment of Mismatch, that is, NOT2 (PTR_FUN (CICHARCompare)). This judgment returns TRUE when the character matches because the mismatch will stop when the judgment returns false. We cannot use CICHARCompare for this because it returns -1, 1 or 0, while it returns 0 when the character matches it, just like strCMP. If we pass CICHARCompare as a judgment to Mismatch, C will convert CICHARCompare's return type to Bool, and of course Bool's equivalent is false, just as the opposite we want! Similarly, when CICHARCompare returns 1 or -1, it will be explained as True, because, just like C, all non-zero integer values ​​are as TRUE. This will again follow the opposite we want. To correct this semantic inversion, we put on NOT2 and PTR_FUN in front of CICHARCompare, and we will always live happily. Our second method CistringCompare is a suitable STL judgment: can be used as a function of comparison functions in an associated container. This implementation is very short, because we need to do it to modify the CICHARCompare to a character comparison function with the judgment interface, and then hand over the string comparison to the second long algorithm in STL --lexicographical_compare:

Bool CICHARLESS (Char C1, Char C2) // Return to ignore the case

{// is in the case of whether C1 is

// in front of C2;

TOLOWER (static_cast (c1))

TOLOWER (static_cast (c2)); // A function object may

} // better than the function

Bool CistringCompare (Const String & S1, Const String & S2)

{

Return lexicographical_compare (s1.begin (), s1.end (), // About this

S2.BEGIN (), S2.END (), // algorithm call

CICHARLESS; // Discussion here

}

No, I will not let you have any suspense. The maximum algorithm is set_symmetric_difference.

If you are familiar with Lexicographical_compare, the above code is clear. If you don't, it may be like a concrete. Fortunately, it is not difficult to replace concrete into glass.

Lexicographical_compare is a generic version of Strcmp. Strcmp only features a character number, but Lexicographical_Compare has a role in all intervals of all any types of values. At the same time, STRCMP is always compared to two characters to see their relationship is equal, less than or greater than the other. Lexicographical_compare can be passed into a binary judgment that determines if two values ​​meet a user-defined standard.

In the call above, lexicographical_compare is used to find the first different locations of S1 and S2, based on the result of calling CICHARLESS. If you use the character of that position, CICHARLESS returns true. Lexicographical_compare is also; if, in the first character, from the first character string, the character is first in the corresponding from the second string character, first A string is in the second. Just like strcmp, lexicographical_compare believes that the interval of two phase-equivalent values ​​is equal, so it returns FALSE for such two intervals: The first interval is not in the second. Also as Strcmp, if the first interval is over before discovering different correspondence values, Lexicographical_Compare returns True: A prefix that is prior to any interval is a prefix. Talking about Mismatch and Lexicographic_Compare. Although I focused on the lightness of this book, if I didn't mention the case where the case-sensitive string comparison function was widely existed as the non-standard expansion of the standard C library, I may be a delegation. They generally have the names such as stricp or strcmpi, and they generally do not provide more support for internationalization as we developed in this Territory. If you want to sacrifice some transplantability, you know your string does not contain embedded null, and you don't care about internationalization, you can find the simplest way to implement a case where you don't do it. STL. Instead, it converts two strings to const char * pointers (see Terms 16), and then use stricp or strcmpi to the pointer:

Int CistringCompare (Const String & S1, Const String & S2)

{

Return stricp (s1.c_str (), s2.c_str ()); // on your system

} // Function name

// is not stricmp

Some people may call this HACK, but stricp / strcmpi is optimized to do only one thing, which is often more than the common algorithm for long strings mismatch and lexicographical_compare. If that is important to you, you may not care about the standard STL algorithm you use non-standard C functions. Sometimes the way to use STL most efficiently is to recognize other methods better.

转载请注明原文地址:https://www.9cbs.com/read-4801.html

New Post(0)