#include <string> using namespace std; int main() { string s; ... // string has a constructor: string(const char *); string s = "Hello, world!"; s = string("Bye");
// operator>> and operator<< can be used with string // variables. // As usual, operator>> skips leading white space and stops // reading at first trailing white space or end of input. string s; cin >> s; cout << s; // There is a non-member getline function: // istream& getline(istream&, string& s, const char delim = '\n'); // This example reads input lines until end of file (or input error) // changes the state of cin which is the return value of getline. // The lines read are stored in the vector v. The getline function // reads all characters (e.g., blanks, tabs, normal characters, // etc.) up to the delimiter character. The default delimiter // character is the newline character that terminates an input // line. The delimiter can be changed by passing a new delimiter // character as the third parameter to getline. // // Note: This function does not work correctly for some // versions of Visual C++ version 6 when using it with cin, although // it does work for input file streams, i.e., ifstream objects. // There is a fix. vector<string> v; string s; ... while( getline(cin, s) ) { v.push_back(s); }
C++ strings can also be assigned using the = operator, or concatenated using the + operator:
string s1 = "first string"; string s2 = "second string"; string s3 = s1 + ", " + s2; cout << s3 << endl; Output: first string, second string // Note that the + operator does NOT work unless one of the arguments // is a c++ string. If both are c-style strings an error occurs. string s; s = "abc" + "cdef"; // ERROR: No + operator defined for operands of // type char[4] and char[5]. // The previous example doesn't work because neither operand // of + is a c++ string. You can convert a c-style string // to a c++ string using the string constructor: string s; s = "abc" + string("cdef"); // This is ok. Since one of the operands is a c++-string, the // other operand, "abc", will also be automatically converted // to a c++ string. // operands can be char * as well as c-string constants, but // one of the operands still needs to be a c++ string. So // you sill need to convert at least one of the operands // if both are c-strings: char w[] = "abc"; s = string(w) + "cdef"; The += operator is also defined and works as you would expect.
One obstacle to using c-style strings with the STL general purpose algorithms such as sorting is that c-strings are compared differently (using the function strcmp) than using the < operator and you can't overload operator< for c-strings. (The < operator is already defined for char * type, but unfortunately it is just comparing the pointer value, not the characters pointed to.)
For C++ strings, all of the typical relational operators work as expected to compare either C++ strings or a C++ string and either a C string or a static string (i.e., "one in quotes"). That is, as for concatenation, as long as one of the operands of a comparison is a c++-string, the other operand will be converted if necessary from a c-string to c++-string.
#include <string> string passwd; getline(cin, passwd); // Compare c++-string to a c-string, "fred or barney" is converted if(passwd == "fred or barney") // equality comparison { cout << "Access allowed." << endl } else { cout << "Access denied!" << endl } #include <cstring> char passwd[50]; cin.getline(passwd, 50); // Comparing char * type c-strings requires using strcmp if(strcmp(passwd,"fred or barney") == 0 ) // c-string equality comparison { cout << "Access allowed." << endl } else { cout << "Access denied!" << endl }
There are two member functions to get the number of characters in a c++ string: size() and length(). They are functionally the same. The 'size' name is the one used by all the STL containers, but 'length' may be more intuitive in the case of strings. Take your pick.
The operator[] is a member function of the string class. It returns a reference to the char stored at the given position in the c++-string. The subscript should be >= 0 and < size().
string s = "abc"; unsigned int len = s.size(); // len is 3 for(unsigned int i = 0; i < s.size(); i++) { cout << s[i] << endl; } Output: a b c
Another similarity between the string class and the STL container classes is the use of iterators. The following example code to enumerate the characters in a string is exactly like enumerating the elements of any of the STL containers.
string s = "Twas brillig"; string::iterator p; for(p = s.begin(); p != s.end(); ++p) { cout << *p << endl; } Note: If characters are added or removed from a string, any iterators associated to the string are invalidated and should be reinitialized.
The c++ string class has the following members to search the string for a specified search character or string in the instance string:
In all cases the return value is the beginning position of the searched for character or string if it is present. If the searched for char or string is not in the string, the return value is the constant string::npos.
static unsigned int string::pos = ... // The largest possible // unsigned int; all bits are 1's.
This sample code searches for every instance of the string "an" in a given string and counts the total number of instances: string s = "banana"; int cnt = 0; unsigned pos = s.find("an", 0); while ( pos != string::npos ) { cnt++; pos = s.find("an", pos); } cout << "an occurred " <<cnt << times << endl;
There are also corresponding member functions to search backwards in the string.
string string::substr(unsigned int starpos = 0, unsigned int length = string::npos)
string s = "abcdefghijklmnop"; string first5 = s.substr(0,5); // startpos = 0, 5 chars (at pos 0 - 4) string second5 = s.substr(5,5); // startpos = 5, 5 chars (at pos 5 - 9) string r10 = s.substr(10); // startpos = 10, all remaining chars cout << first5 << endl; cout << second5 << endl; cout << r10 << endl; cout << s.substr(10) << endl; Output: abcde fghij klmnop abcdefghijklmnop
Two additional member functions similar to find can be very useful in breaking a string into "tokens" that are delimited by delimiter characters such as spaces or punctuation. Each of these two functions is overloaded so that it can be used either with delimiters specified by c-strings or c++-strings.
string s = "fred; barney, wilma-betty! "; string delims = " ,;:.!?"; unsigned int startpos, delimpos; Exercise: Write the code using find_first_not_of, find_first_of, and substr to print the substrings of s delimited by the characters in the string delims. The output should be as indicated here: Output: fred barney wilma betty
The erase member function takes a position and a character count and removes that many characters starting from the given position. The position is zero-indexed, as usual. If the position is greater or equal to the size, then an out_of_range exception is thrown.
The insert member function takes a starting position and a char, c-string, or c++-string, which is inserted into the string at the given position. All following characters are "moved over". The starting position can be any value from 0 up to and including the size of the string. This is different than for erase which does not allow the position to equal to size since there is no character at that position. For insert if position is equal to size, the new string is just inserted at the end. However, if position is > size, then again, an out_of_range exception is thrown.
string s = "fred barney wilma"; s.erase(5, 6); // removes "barney"; s is now "fred wilma" (2 spaces) s.erase(0, s.size()); // removes all chars; s is now "" string s = "fred wilma"; s.insert(5, "barney "); // now s is "fred barney wilma" s.insert(s.size(), " betty"); // now s is "fred barney wilma betty"; string s = "abc"; try { s.insert(4, "d"); } catch(out_of_range e) { cout << "insert(4, ...) out of range" << endl; cout << e.what() << endl; } Output: insert(4,...) out of range basic_string::insert
Many standard C-libarary and several standard c++-libary functions expect c-strings (char *) rather than c++ string objects. This is easily handled by using the member function c_str:
cont char * c_str() const; Note that the returned char* is a const value so you cannot modify this string. If you need to modify the returned value, you should create a second string and use the strcpy function to copy the returned value from c_str().
#include <fstream> int main() { ifstream ifs; string fname; cout << "Enter input file name: "; cin >> fname; // The open function expects a char * (a c-string) // Use c_str() to return a c-style version of fname's value. ifs.open(fname.c_str()); ... }