9.6. strings Revisited9.6. 再谈 string 类型We introduced the string type in Section 3.2 (p. 80). Table 9.12 (p. 337) recaps the string operations covered in that section. 第 3.2 节介绍了 string 类型,表 9.12 扼要重述了在该节中介绍的 string 操作。 Table 9.12. string Operations Introduced in Section 3.2表 9.12 第 3.2 节介绍的 string 操作
In addition to the operations we've already used, strings also supports most of the sequential container operations. In some ways, we can think of a string as a container of characters. With some exceptions, strings support the same operations that vectors support: The exceptions are that string does not support the operations to use the container like a stack: We cannot use the front, back, and pop_back operations on strings. 除了已经使用过的操作外,string 类型还支持大多数顺序容器操作。在某些方面,可将 string 类型视为字符容器。除了一些特殊操作,string 类型提供与 vector 容器相同的操作。string 类型与 vector 容器不同的是,它不支持以栈方式操纵容器:在 string 类型中不能使用 front、back 和 pop_back 操作。 The container operations that string supports are: string 支持的容器操作有:
When we say that string supports the container operations, we mean that we could take a program that manipulates a vector and rewrite that same program to operate on strings. For example, we could use iterators to print the characters of a string a line at a time to the standard output: string 类型提供容器操作意味着可将操纵 vector 对象的程序改写为操纵 string 对象。例如,以下程序使用迭代器将一个 string 对象的字符以每次一行的方式输出到标准输出设备:
string s("Hiya!");
string::iterator iter = s.begin();
while (iter != s.end())
cout << *iter++ << endl; // postfix increment: print old value
Not surprisingly, this code looks almost identical to the code from page 163 that printed the elements of a vector<int>. 不要奇怪,这段代码看上去几乎与第 5.5 节中输出 vector In addition to the operations that string shares with the containers, string supports other operations that are specific to strings. We will review these string-specific operations in the remainder of this section. These operations include additional versions of container-related operations as well as other, completely new functions. The additional functions that string provides are covered starting on page 341. 除了共享容器的操作外,string 类型还支持其他本类型特有的操作。在本节剩下的篇幅吕,我们将回顾这些 string 类型特有的操作,包括与其他容器相关操作的补充版本,以及全新的函数。string 类型的补充函数将在第 9.6.2 节介绍。 The additional versions of the container operations that string provides are defined to support attributes that are unique to strings and not shared by the containers. For example, several operations permit us to specify arguments that are pointers to character arrays. These operations support the close interaction between library strings and character arrays, whether null-terminated or not. Other versions let us use indices rather than iterators. These versions operate positionally: We specify a starting position, and in some cases a count, to specify the element or range of elements which we want to manipulate. string 类型为某些容器操作提供补充版本,以支持 string 特有的、不为其他容器共享的属性。例如,好几种操作允许指定指向字符数组的指针参数。无论字符串是否以空字符结束,这些操作都支持标准库 string 对象与字符数组之间的紧密交互作用。其他版本则使用程序员只能使用下标而不能使用迭代器。这些版本只能通过位置操纵元素:指定起始位置,在某些情况下还需指定一个计数器,由此指定要操纵的某个元素或一段元素。
Readers might want to skim the remainder of Section 9.6. Once you know what kinds of operations are available, you can return for the details when writing programs that need to use a given operation. 读者可跳过第 9.6 节剩下的内容。一旦知道了有哪些操作可以使用,就可以在编写需要使用这种操作的程序时,才回来阅读其细节。 9.6.1. Other Ways to Construct strings9.6.1. 构造 string 对象的其他方法The string class supports all but one of the constructors in Table 9.2 (p. 307). The constructor that takes a single size parameter is not supported for string. We can create a string: as the empty string, by providing no argument; as a copy of another string; from a pair of iterators; or from a count and a character: string 类支持表 9.2 所列出的几乎所有构造函数,只有一个例外:string 不支持带有单个容器长度作为参数的构造函数。创建 string 对象时:不提供任何参数,则得到空的 string 对象;也可将新对象初始化为另一个 string 对象的副本;或用一对迭代器初始化:或者使用一个计数器和一个字符初始化: string s1; // s1 is the empty string string s2(5, 'a'); // s2 == "aaaaa" string s3(s2); // s3 is a copy of s2 string s4(s3.begin(), s3.begin() + s3.size() / 2); // s4 == "aa" In addition to these constructors, the string type supports three other ways to create a string. We have already used the constructor that takes a pointer to the first character in a null-terminated, character array. There is another constructor that takes a pointer to an element in a character array and a count of how many characters to copy. Because the constructor takes a count, the array does not have to be null-terminated: 除了上述构造函数之外,string 类型还提供了三种其他的方式创建类对象(表 9.13)。在前面的章节中,已经使用过只有一个指针参数的构造函数,该指针指向以空字符结束的字符数组中的第一个元素。另一种构造函数需要一个指向字符数组元素的指针和一个标记要复制多少个字符的计数器作参数。由于该构造函数带有一个计数器,因此数组不必以空字符结束: char *cp = "Hiya"; // null-terminated array char c_array[] = "World!!!!"; // null-terminated char no_null[] = {'H', 'i'}; // not null-terminated string s1(cp); // s1 == "Hiya" string s2(c_array, 5); // s2 == "World" string s3(c_array + 5, 4); // s3 == "!!!!" string s4(no_null); // runtime error: no_null not null-terminated string s5(no_null, 2); // ok: s5 == "Hi" We define s1 using the constructor that takes a pointer to the first character of a null-terminated array. All the characters in that array, up to but not including the terminating null, are copied into the newly created string. 使用只有一个指针参数的构造函数定义 s1,该指针指向以空字符结束的数组中的第一字符。这个数组的所有字符,但不包括结束符 null,都被复制到新创建的 string 对象中。 The initializer for s2 uses the second constructor, taking a pointer and a count. In this case, we start at the character denoted by the pointer and copy as many characters as indicated in the second argument. s2, therefore, is a copy of the first five characters from the array c_array. Remember that when we pass an array as an argument, it is automatically converted to a pointer to its first element. Of course, we are not restricted to passing a pointer to the beginning of the array. We initialize s3 to hold four exclamation points by passing a pointer to the first exclamation point in c_array. 而 s2 的初始化式则通过第二种构造函数实现,它的参数包括一个指针和一个计数器。在这个例子中,从参数指针指向的那个字符开始,连续复制第二个参数指定数目的字符。因此,s2 是 c_array 数组前 5 个字符的副本。记住,将数组作为参数传递时,数组将自动转换为指向其第一个元素的指针。当然,并没有限制非得传递指向数组起点的指针不可。通过给 s3 的构造函数传递指向 c_array 数组中第一个感叹号字符的指针,s3 被初始化为存储 4 个感叹号字符的 string 对象。 The initializers for s4 and s5 are not C-style strings. The definition of s4 is an error. This form of initialization may be called only with a null-terminated array. Passing an array that does not contain a null is a serious error (Section 4.3, p. 130), although it is an error that the compiler cannot detect. What happens at run time is undefined. s4 和 s5 的初始化式并不是 C 风格字符串。其中,s4 的定义是错误的。调用这种形式的初始化,其参数必须是以空字符结束的数组。将不包含 null 的数组传递给构造函数将导致编译器无法检测的严重错误(第 4.3 节),此类错误在运行时将支发生什么状况并未定义。 The initialization of s5 is fine: That initializer includes a count that says how many characters to copy. As long as the count is within the size of the array, it doesn't matter whether the array is null-terminated. s5 的初始化则是正确的:初始化式包含了一个计数器,以说明要复制多少个字符用于初始化。该计数器的值必须小于数组的长度,此时,无论数组是否以空字符结束,都没什么关系。 Table 9.13. Additional Ways to Construct strings9.13. 构造 string 对象的其他方法
Using a Substring as the Initializer用子串做初始化式The other pair of constructors allow us to create a string as a copy of a substring of the characters in another string: 另一对构造函数使用程序员可以在创建 string 对象时将其初始化为另一个 string 对象的子串。 string s6(s1, 2); // s6 == "ya" string s7(s1, 0, 2); // s7 == "Hi" string s8(s1, 0, 8); // s8 == "Hiya" The first two arguments are the string from which we want to copy and a starting position. In the two-argument version, the newly created string is initialized with the characters from that position to the end of the string argument. We can also provide a third argument that specifies how many characters to copy. In this case, we copy as many characters as indicated (up to the size of the string), starting at the specified position. For example, when we create s7, we copy two characters from s1, starting at position zero. When we create s8, we copy only four characters, not the requested nine. Regardless of how many characters we ask to copy, the library copies up to the size of the string, but not more. 第一个语句的两个参数指定了要复制的 string 对象及其复制的起点。在两个参数的构造函数版本中,复制 string 对象实参中从指定位置到其末尾的所有字符,用于初始化新创建的 string 对象。还可以为此类构造函数提供第三个参数,用于指定复制字符的个数。在本例中,我们从指定位置开始复制指定数目(最多为 string 对象的长度)的字符数。例如,创建 s7 时,从 s1 中下标为 0 的位置开始复制两个字符;而创建 s8 时,只复制了 4 个字符,而并不是要求的 8 个字符。无论要求复制多少个字符,标准库最多只能复制数目与 string 对象长度相等的字符。 9.6.2. 修改 string 对象的其他方法Many of the container operations that string supports operate in terms of iterators. For example, erase takes an iterator or iterator range to specify which element(s) to remove from the container. Similarly, the first argument to each version of insert takes an iterator to indicate the position before which to insert the values represented by the other arguments. Although string supports these iterator-based operations, it also supplies operations that work in terms of an index. The index is used to indicate the starting element to erase or the position before which to insert the appropriate values. Table 9.14 lists the operations that are common to both string and the containers; Table 9.15 on the facing page lists the string-only operations. string 类型支持的许多容器操作在操作时都以迭代器为基础。例如,erase 操作需要一个迭代器或一段迭代器范围作其参数,用于指定从容器中删除的元素。类似地,所有版本的 insert 函数的第一参数都是一个指向插入位置之后的迭代器,而新插入的元素值则由其他参数指定。尽管 string 类型支持这些基于迭代器的操作,它同样也提供以下标为基础的操作。下标用于指定 erase 操作的起始元素,或在其前面 insert 适当值的元素。表 9.14 列出了 string 类型和容器类型共有的操作;而表 9.15 则列出了 string 类型特有的操作。 Table 9.14. string Operations in Common with the Containers表 9.14 与容器共有的 string 操作
Table 9.15. string-Specific Versions表 9.15 string 类型特有的版本
Position-Based Arguments基于位置的实参The string-specific versions of these operations take arguments similar to those of the additional constructors covered in the previous section. These operations let us deal with strings positionally and/or let us use arguments that are pointers to character arrays rather than strings. string 类型为这些操作提供本类型特有的版本,它们接受的实参类似于在前一节介绍的补充构造函数。程序员可通过这些操作基于位置处理 string 对象,并/或使用指向字符数组的指针而不是 string 对象作实参。 For example, all containers let us specify a pair of iterators that denote a range of elements to erase. For strings, we can also specify the range by passing a starting position and count of the number of elements to erase. Assuming s is at least five characters long, we could erase the last five characters as follows: 例如,所有容器都允许程序员指定一对迭代器,用于标记删除(erase)的元素范围。对于 string 类型,还允许通过为 erase 函数传递一个起点位置和删除元素的数目,来指定删除的范围。假设 s 至少有 5 个元素,下面的语句用于删除 s 的最后 5 个字符: s.erase(s.size() - 5, 5); // erase last five characters from s Similarly, we can insert a given number of values in a container before the element referred to by an iterator. In the case of strings, we can specify the insertion point as an index rather than using an iterator: 类似地,对于容器类型,可在迭代器指向的元素之前插入(insert)指定数目的新值。而对于 string 类型,系统还允许使用下标而不是迭代器指定插入位置: s.insert(s.size(), 5, '!'); // insert five exclamation points at end of s Specifying the New Contents指定新的内容The characters to insert or assign into the string can be taken from a character array or another string. For example, we can use a null-terminated character array as the value to insert or assign into a string: 在 string 对象中 insert 或 assign 的字符可来自于字符数组或另一个 string 对象。例如,以空字符结束的字符数组可以用作 insert 或 assign 到 string 对象的内容: char *cp = "Stately plump Buck"; string s; s.assign(cp, 7); // s == "Stately" s.insert(s.size(), cp + 7); // s == "Stately plump Buck" Similarly, we can insert a copy of one string into another as follows: 类似地,可如下所示将一个 string 对象的副本插入到另一个 string 对象中: s = "some string"; s2 = "some other string"; // 3 equivalent ways to insert all the characters from s2 at beginning of s // insert iterator range before s.begin() s.insert(s.begin(), s2.begin(), s2.end()); // insert copy of s2 before position 0 in s s.insert(0, s2); // insert s2.size() characters from s2 starting at s2[0] before s[0] s.insert(0, s2, 0, s2.size()); 9.6.3. string-Only Operations9.6.3. 只适用于 string 类型的操作The string type provides several other operations that the containers do not: string 类型提供了容器类型不支持其他几种操作,如表 9.16 所示:
The substr Operationsubstr 操作The substr operation lets us retrieve a substring from a given string. We can pass substr a starting position and a count. It creates a new string that has that many characters, (up to the end of the string) from the target string, starting at the given position: 使用 substr 操作可在指定 string 对象中检索需要的子串。我们可以给 substr 函数传递查找的起点和一个计数器。该函数将生成一个新的 string 对象,包含原目标 string 对象从指定位置开始的若干个字符(字符数目由计数器决定,但最多只能到原 string 对象的最后一个字符): string s("hello world"); // return substring of 5 characters starting at position 6 string s2 = s.substr(6, 5); // s2 = world Alternatively, we could obtain the same result by writing: 可选择另一种方法实现相同的功能: // return substring from position 6 to the end of s string s3 = s.substr(6); // s3 = world Table 9.16. Substring Operation表 9.16 子串操作
The append and replace Functionsappend 和 replace 函数There are six overloaded versions of append and ten versions of replace. The append and replace functions are overloaded using the same set of arguments, which are listed in Table 9.18 on the next page. These arguments specify the characters to add to the string. In the case of append, the characters are added at the end of the string. In the replace function, these characters are inserted in place a specified range of existing characters in the string. string 类型提供了 6 个 append 重载函数版本和 10 个 replace 版本(见表 9.17)。append 和 replace 函数使用了相同的参数集合实现重载。这些参数如表 9.18 所示,用于指定在 string 对象中添加的字符。对于 append 操作,字符将添加在 string 对象的末尾。而 replace 函数则将这些字符插入到指定位置,从而替换 string 对象中一段已存在的字符。 The append operation is a shorthand way of inserting at the end: string s("C++ Primer"); // initialize s to "C++ Primer" s.append(" 3rd Ed."); // s == "C++ Primer 3rd Ed." // equivalent to s.append(" 3rd Ed.") s.insert(s.size(), " 3rd Ed."); The replace operations remove an indicated range of characters and insert a new set of characters in their place. The replace operations have the same effect as calling erase and insert. The ten different versions of replace differ from each other in how we specify the characters to remove and in how we specify the characters to insert in their place. The first two arguments specify the range of elements to remove. We can specify the range either with an iterator pair or an index and a count. The remaining arguments specify what new characters to insert. string 类型为 replace 操作提供了 10 个不同版本,其差别在于以不同的方式指定要删除的字符和要插入的新字符。前两个参数应指定删除的元素范围,可用迭代器对实现,也可用一个下标和一个计数器实现。其他的参数则用于指定插入的新字符。 We can think of replace as a shorthand way of erasing some characters and inserting others in their place: 可将 replace 视为删除一些字符然后在同一位置插入其他内容的捷径: Table 9.17. Operations to Modify strings (args defined in Table 9.18)表 9.17 修改 string 对象的操作(args 在表 9.18 中定义)
// starting at position 11, erase 3 characters and then insert "4th" s.replace(11, 3, "4th"); // s == "C++ Primer 4th Ed." // equivalent way to replace "3rd" by "4th" s.erase(11, 3); // s == "C++ Primer Ed." s.insert(11, "4th"); // s == "C++ Primer 4th Ed."
In the previous call to replace, the text we inserted happens to be the same size as the text we removed. We could insert a larger or smaller string: replace 操作用于删除一段指定范围的字符,然后在删除位置插入一组新字符,等效于调用 erase 和 insert 函数。
s.replace(11, 3, "Fourth"); // s == "C++ Primer Fourth Ed."
In this call we remove three characters but insert six in their place. 在这个例子中,删除了 3 个字符,但在同一个位置却插入了 6 个字符。 Table 9.18. Arguments to append and replace表 9.18 append 和 replace 操作的参数:args
9.6.4. string Search Operations9.6.4. string 类型的查找操作The string class provides six search functions, each named as a variant of find. The operations all return a string::size_type value that is the index of where the match occurred, or a special value named string::npos if there is no match. The string class defines npos as a value that is guaranteed to be greater than any valid index. string 类提供了 6 种查找函数(表 9.19),每种函数以不同形式的 find 命名。这些操作全都返回 string::size_type 类型的值,以下标形式标记查找匹配所发生的位置;或者返回一个名为 string::npos 的特殊值,说明查找没有匹配。string 类将 npos 定义为保证大于任何有效下标的值。 There are four versions of each of the search operations, each of which takes a different set of arguments. The arguments to the search operations are listed in Table 9.20. Basically, these operations differ as to whether they are looking for a single character, another string, a C-style, null-terminated string, or a given number of characters from a character array. 每种查找操作都有 4 个重载版本,每个版本使用不同的参数集合。表 9.20 列出了查找操作使用的不同参数形式。基本上,这些操作的不同之处在于查找的到底是单个字符、另一个 string 字符串、C 风格的以空字符结束的字符串,还是用字符数组给出的特定数目的字符集合。 Table 9.19. string Search Operations (Arguments in Table 9.20)
Table 9.20. Arguments to string find Operationsstring 类型提供的 find 操作的参数
Finding an Exact Match精确匹配的查找The simplest of the search operations is the find function. It looks for its argument and returns the index of the first match that is found, or npos if there is no match: 最简单的查找操作是 find 函数,用于寻找实参指定的内容。如果找到的话,则返回第一次匹配的下标值;如果找不到,则返回 npos:
string name("AnnaBelle");
string::size_type pos1 = name.find("Anna"); // pos1 == 0
Returns 0, the index at which the substring "Anna" is found in "AnnaBelle". 返回 0,这是子串“Anna”位于字符串“AnnaBelle”中的下标。
When we look for a value in the string, case matters: 以下程序寻找 string 对象中的某个值,字母的大小写影响了程序结果:
string lowercase("annabelle");
pos1 = lowercase.find("Anna"); // pos1 == npos
This code will set pos2 to nposthe string Anna does not match anna. 这段代码使 pos1 的值为 npos ——字符串 Anna 与 anna 不匹配
Find Any Character查找任意字符A slightly more complicated problem would be if we wanted to match any character in our search string. For example, the following locates the first digit within name: 如果在查找字符串时希望匹配任意指定的字符,则实现起来稍微复杂一点。例如,下面的程序要在 name 中寻找并定位第一个数字: string numerics("0123456789"); string name("r2d2"); string::size_type pos = name.find_first_of(numerics); cout << "found number at index: " << pos << " element is " << name[pos] << endl; In this example, pos is set to a value of 1 (the elements of a string, remember, are indexed beginning at 0). 在这个例子中,pos 的值被设置为 1(记住,string 对象的元素下标从 0 开始计数)。 Specifying Where to Start the Search指定查找的起点We can pass an optional starting position to the find operations. This optional argument indicates the index position from which to start the search. By default, that position is set to zero. One common programming pattern uses this optional argument to loop through a string finding all occurrences. We could rewrite our search of "r2d2" to find all the numbers in name: 程序员可以给 find 操作传递一个可选的起点位置实参,用于指定开始查找的下标位置,该位置实参的默认值为 0。通常的编程模式是使用这个可选的实参循环查找 string 对象中所有的匹配。下面的程序重写了查找“r2d2”的程序,以便找出 name 字符串中出现的所有数字: string::size_type pos = 0; // each trip reset pos to the next instance in name while ((pos = name.find_first_of(numerics, pos)) != string::npos) { cout << "found number at index: " << pos << " element is " << name[pos] << endl; ++pos; // move to the next character } In this case, we initialize pos to zero so that on the first trip through the while name is searched, beginning at position 0. The condition in the while resets pos to the index of the first number encountered, starting from the current value of pos. As long as the return from find_first_of is a valid index, we print our result and increment pos. 在这个例子中,首先将 pos 初始化为 0,使第一次循环从 0 号元素开始查找 name。while 的循环条件实现两个功能:从当前 pos 位置开始查找,并将找到的第一个数字出现的下标值赋给 pos。当 find_first_of 函数返回有效的下标值时,输出此次查找的结果,并且让 pos 加 1。 Had we neglected to increment pos at the end of this loop, then it would never terminate. To see why, consider what would happen if we didn't. On the second trip through the loop. we start looking at the character indexed by pos. That character would be a number, so find_first_of would (repeatedly) returns pos! 如果漏掉了循环体末尾让 pos 加 1 的语句,那么循环永远都不会结束。考虑没有该操作时,会发生什么情况?第二次循环时,从 pos 标记的位置开始查找,而此时 pos 标记的就是一个数字,于是 find_first_of 函数将(不断重复地)返回同一个 pos 值。
Looking for a Nonmatch寻找不匹配点Instead of looking for a match, we might call find_first_not_of to find the first position that is not in the search argument. For example, to find the first non-numeric character of a string, we can write 除了寻找匹配的位置外,还可以调用 find_first_not_of 函数查找第一个与实参不匹配的位置。例如,如果要在 string 对象中寻找第一个非数字字符,可以如下编写程序: string numbers("0123456789"); string dept("03714p3"); // returns 5, which is the index to the character 'p' string::size_type pos = dept.find_first_not_of(numbers); Searching Backward反向查找Each of the find operations that we've seen so far executes left to right. The library provides an analogous set of operations that look through the string from right to left. The rfind member searches for the lastthat is, rightmostoccurrence of the indicated substring: 迄今为止,我们使用的所有 find 操作都是从左向右查找的。除此之外,标准库还提供了一组类似的从右向左查找 string 对象的操作。rfind 成员函数用于寻找最后一个——也就是是最右边的——指定子串出现的位置: string river("Mississippi"); string::size_type first_pos = river.find("is"); // returns 1 string::size_type last_pos = river.rfind("is"); // returns 4 find returns an index of 1, indicating the start of the first "is", while rfind returns an index of 4, indicating the start of the last occurrence of "is". find 函数返回下标 1,标记 river 字符串中第一个“is”的出现位置;而 rfind 函数返回最后一个匹配的位置,而并不是第一个。 The find_last FunctionsThe find_last functions operate like the corresponding find_first functions, except that they return the last match rather than the first:
Each of these operations takes an optional second argument indicating the position within the string to begin searching. 这两个操作都提供第二个参数,这个参数是可选的,用于指定在 string 对象中开始查找的位置。 9.6.5. Comparing strings9.6.5.As we saw in Section 3.2.3 (p. 85), the string type defines all the relational operators so that we can compare two strings for equality (==), inequality (!=), and the less- or greater-than operations (<, <=, >, >=). Comparison between strings is lexicographicalthat is, string comparison is the same as a case-sensitive, dictionary ordering: 正如在第 3.2.3 节所看到的,string 类型定义了所有关系操作符,使程序员可以比较两个 string 对象是否相等(==)、不等(!=),以及实现小于或大于(<、<=、>、>=)运算。string 对象采用字典顺序比较,也就是说,string 对象的比较与大小写敏感的字典顺序比较相同: string cobol_program_crash("abend"); string cplus_program_crash("abort");
Here cobol_program_crash is less than the cplus_program_crash. The relational operators compare two strings character by character until reaching a position where the two strings differ. The overall comparison of the strings depends on the comparison between these unequal characters. In this case, the first unequal characters are 'e' and 'o'. The letter 'e' occurs before (is less than) 'o' in the English alphabet and so "abend" is less than "abort". If the strings are of different length, and one string is a substring of the other, then the shorter string is less than the longer. 操作符逐个字符地进行比较,直到比较到某个位置上,两个 string 对象对应的字符不相同为止。string 对象的整个比较依赖于不相同字符之间的比较。在本例中,第一个不相等的字符是‘e’和‘o’。由于在英文字母表中,‘e’出现得比‘o’早(即‘e’小于‘o’),于是“abend”小于“abort”。如果要比较的两个 string 对象长度不相同,而且一个 string 对象是另一个 string 对象的子串,则较短的 string 对象小于较长的 string 对象。 The compare Functionscompare 函数In addition to the relational operators, string provides a set of compare operations that perform lexicographical comparions. The results of these operations are similar to the C library strcmp function (Section 4.3, p. 132). Given 除了关系操作符,string 类型还提供了一组 compare 操作(表 9.21),用于实现字典顺序的比较。这些操作的结果类似于 C 语言中的库函数 strcmp(第 4.3 节)。假设有语句:
s1.compare (args);
compare returns one of three possible values: compare 函数返回下面列出的三种可能值之一:
For example 例如: // returns a negative value cobol_program_crash.compare(cplus_program_crash); // returns a positive value cplus_program_crash.compare(cobol_program_crash); Table 9.21. string compare Operations表 9.21 string 类型 compare 操作
The overloaded set of six compare operations allows us to compare a substring of either one or both strings for comparison. They also let us compare a string to a character array or portion thereof: compare 操作提供了 6 种重载函数版本,以方便程序员实现一个或两个 string 对象的子串的比较,以及 string 对象与字符数组或其中某一部分的比较: char second_ed[] = "C++ Primer, 2nd Edition"; string third_ed("C++ Primer, 3rd Edition"); string fourth_ed("C++ Primer, 4th Edition"); // compares C++ library string to C-style string fourth_ed.compare(second_ed); // ok, second_ed is null-terminated // compare substrings of fourth_ed and third_ed fourth_ed.compare(fourth_ed.find("4th"), 3, third_ed, third_ed.find("3rd"), 3); The second call to compare is the most interesting. This call uses the version of compare that takes five arguments. We use find to locate the position of the beginning of the substring "4th". We compare three characters starting at that position to a substring from third_ed. That substring begins at the position returned from find when looking for "3rd" and again we compare three characters. Essentially, this call compares "4th" to "3rd". 我们对第二个 compare 函数的调用更感兴趣。这个调用使用了具有 5 个参数的 compare 函数版本。先调用 find 函数找到子串“4th”的起点。让从此起点开始的 3 个字符与 third_ed 的子串做比较。而 third_ed 的子串起始于 find 函数找到的“3rd”的起点,同样取其随后的 3 个字符参加比较。可见这个语句本质上比较的是“4th”和“3rd”。 ![]() |
Exercises Section 9.6.5
|