The string class is extremely useful, in that it makes it easy for programmers to write efficient and safe code. In contrast, traditional C style ``character array'' strings are a never ending source of headaches and bugs. We explore the string class, as well as dicussing its advantages over character array strings.
One of the nice things about strings is that they store the string in automatically managed dynamic storage. This means that the programmer doesn't need to manage a strings memory. The programmer can use it just like they would use an integer or a double. The string grows when it needs to. This is an enormous advantage when reading data from an external source. For example, consider the following code;:
char x[10]; std::cin >> x;
The C string, x only has enough room for 9 characters, so if the user types ``supercalifragilisticexpialidocious'', then the program could crash. On the other hand, the following code is safe:
std::string x; std::cin >> x;Because the string x can grow to a sufficient size to accomodate the use input. The size of x does not have to be decided at compile time.
For strings to be useful, they must support appropriate operations. The string class has the following methods:
string(); string ( const string& ); // copy constructor string ( const char* ); // c-style string // creates a string of length length // and fills it with the character c string ( int length, char c);
std::string s = "hello"; std::cout << s[0] << std::endl; // prints "h" s[0]='H'; // s = "Hello".
string& operator+ ( string& )
One may catenate strings using the operator +. For example, this gives rise to a new implementation of the popular program known as Hello World
#include <string> #include <iostream> int main() { std::string s = "Hello "; std::string t = "World"; std::cout << (s+t) << std::endl; return 0; }
One may also use the operator +=. Both operators are overloaded so that one may append type char.
ONe may compare two strings for equality using the usual comparison operator ==. The operators <, <= and >, >= are also defined -- they use lexical ordering for the comparisons.
string::size_type find_first_of(const string&),
string::size_type find_last_of(const string &),
string::size_type find_first_not_of(const string&),
string::size_type find_last_not_of(const string &)
#include <iostream> #include <string> int main() { using std::string; using std::cout; using std::endl; string s = "Hello"; string::size_type idx; idx = s.find_first_of ("el"); // 1 cout << idx << endl; idx = s.find_first_not_of ("el"); // 0 cout << idx << endl; idx = s.find_last_of ( "el" ); // 3 cout << idx << endl; idx = s.find_last_not_of ("el"); // 4 cout << idx << endl; idx = s.find_first_of ("X"); // string::npos cout << idx << endl; idx = s.find_first_of (s); // 0 cout << idx << endl; return 0; }
Do not confuse string::size_type with int. In particular, string::size_type is usually unsigned, int is signed.
string s; ifstream(s);Does not work, but
string s; ifstream(s.c_str());does.
string substr(size_type idx1, size_type idx2 )
Returns the substring beginning at idx1 and finishing at idx2. If the argument idx2 is not provided, it returns the substring starting at idx1 and ending at the end of the string.
#include <string> #include <iostream> using namespace std; int main() { string s; cout << "Enter a string" << endl; cin >> s; string::size_type idx = s.find_last_of ( '.' ); if ( idx == string::npos ) cout << "No file extension"; else cout << "The file extension is " << s.substr ( idx ) << endl; return 0; }
#include <vector> #include <string> using namespace std; int main() { string s; vector<string> v; cout << "Enter a word, 'q' to quit:" << endl; while ( getline(cin, s) && s != "q" ) { v.push_back(s); cout << "Enter a word, 'q' to quit:" << endl; } int sz = v.size(); string min=v[0]; for ( int i = 0; i < sz; ++i ) if ( v[i] < min ) { min = v[i]; } cout << "The minimum word is '" << min << "'" << endl; }
#include <cstdlib> #include <fstream> #include <ctime> #include <stdexcept> // these two constants are system dependent. const char DICTIONARY[] = "/usr/dict/words"; const int NUM_WORDS = 45402; using namespace std; // see the tutorial on random numbers int int_rand(int n) { if ( n <= 0 || n > RAND_MAX ) throw domain_error("Argument out of range"); const int bucket_size = RAND_MAX / n; int a; do { a = rand() / bucket_size; } while ( a >= n ); return a; } int main() { srand(time(0)); string word; ifstream fin(DICTIONARY); int r = int_rand ( NUM_WORDS ); if (!fin) exit(EXIT_FAILURE); for ( int i = 0; i < r; ++i ) getline(fin, word); // now we're ready to play. string current ( word.size(), '_' ); int guesses = 0; char ch; while ( current != word ) { cout << "The word is :\n" << current << endl; cout << "Choose a letter" << endl; cin >> ch; for ( int i = 0; i<word.size(); ++i ) if ( word[i] == ch ) current[i] = ch; ++guesses; cout << "You've had " << guesses << " guesses" << endl; } return 0; }