assert(first.compare(1, 7, second, 22, 7) == 0);
// Compare "his is a" to "his is w":
assert(first.compare(1, 9, second, 22, 9) < 0);
} ///:~
In the examples so far, we have used C-style array indexing syntax to refer to an individual character in a string. C++ strings provide an alternative to the s[n] notation: the at( ) member. These two indexing mechanisms produce the same result in C++ if all goes well:.
//: C03:StringIndexing.cpp
#include
#include
using namespace std;
int main(){
string s("1234");
assert(s[1] == '2');
assert(s.at(1) == '2');
} ///:~
There is one important difference, however, between [ ] and at( ). When you try to reference an array element that is out of bounds, at( ) will do you the kindness of throwing an exception, while ordinary [ ] subscripting syntax will leave you to your own devices:.
//: C03:BadStringIndexing.cpp
#include
#include
#include
using namespace std;
int main(){
string s("1234");
// at() saves you by throwing an exception:
try {
s.at(5);
} catch(exception& e) {
cerr << e.what() << endl;
}
} ///:~
Responsible programmers will not use errant indexes, but should you want to benefits of automatic index checking, using at( ) in place of [ ] will give you a chance to gracefully recover from references to array elements that don’t exist. Execution of this program on one of our test compilers gave the following output:
invalid string position
The at( ) member throws an object of class out_of_range, which derives (ultimately) from std::exception. By catching this object in an exception handler, you can take appropriate remedial actions such as recalculating the offending subscript or growing the array. Using string::operator[]( ) gives no such protection and is as dangerous as char array processing in C.[34]
Strings and character traits
The program Find.cpp earlier in this chapter leads us to ask the obvious question: Why isn’t case-insensitive comparison part of the standard string class? The answer provides interesting background on the true nature of C++ string objects.
Consider what it means for a character to have "case." Written Hebrew, Farsi, and Kanji don’t use the concept of upper- and lowercase, so for those languages this idea has no meaning. It would seem that if there were a way to designate some languages as "all uppercase" or "all lowercase," we could design a generalized solution. However, some languages that employ the concept of "case"
Although we usually treat the C++ string as a class, this is really not the case. The string type is actually a specialization of a more general constituent, the basic_string< > template. Observe how string is declared in the standard C++ header file:[35]
typedef basic_string
To really understand the nature of the string class, it’s helpful to delve a bit deeper and look at the template on which it is based. Here’s the declaration of the basic_string< > template:.