As I said in the previous section, there is a better way of implementing strings. Why didn't I show you what it was straight away? Because I am nasty and horrid and shouldn't be trusted!
Strings aren't built into C++ in the same way that integer variables are, but there is a header file <string.h> which contains everything you need to handle strings. I have never come across a version of C++ that didn't have access to this header file.
#include <iostream.h>
#include <string.h>
void main ()
{ string title = "The Wit and Wisdom of Bill Clinton";
string contents = " ";
cout << "My favourite book is " << title << endl;
cout << "Here it is : " << contents << endl;
cout << "There are " << strlen(title)
<< " letters in the title.";
}
That's a bit more like it! Suddenly you have a built-in string type, with functions for manipulating strings coming out of your ears! In some version of C++ (for instance, Borland C++ version 4.55), the string type is in the header file called <cstring.h>.
You can manipulate individual bits of the strings just as though they were arrays of characters. The first character of the string has index 0, the second has index 1 etc. Remember, there is an invisible \0 character at the end of the string, which also has an index. For instance:
string t = "I am in the mood for love!"; t[12] = 'n'; cout << t << endl;
You've already seen one function in the <string.h> header, that of strlen(). You put the string in the brackets and just put the entire function in some mathematical expression wherever you would use the number.
#include <iostream.h>
#include <string.h>
void main ()
{ string t = "Testing, testing , 1, 2, 3";
cout << (2 + strlen(t)) * 9.1 << endl;
}
You can see strlen(t) taking the place of a number in the mathematical expression. The length of the string is 26 (including the \0 at the end), so the mathematical expression is equivalent to (2 + 26) * 9.1, which is, urm, well, it's a big number!
There are other functions in <string.h>. This one produces a character rather than a simple number.
#include <iostream.h>
#include <string.h>
void main ()
{ string t =
"There once was a mouse, who lived in a house.";
int i;
cout << t << endl;
for (i = 0; i <= strlen(t), i++)
t[i] = toupper(t[i]);
cout << t << endl;
}
There once was a mouse, who lived in a house.
THERE ONCE WAS A MOUSE, WHO LIVED IN A HOUSE.
There is another function called tolower(). You don't need to be Einstein to work out what it does! Several functions are built into the string type itself. These are accessed by by putting a full stop after the variable name and then the function you want. Here are some of them:
This gives the length of the string. Here is an example:
string proverb = "A rolling stone gathers much speed."; cout << "The proverb contains " << proverb.length(); cout << " characters." << endl;
This gives the length of the string (not including the invisible termination character). In this example it produces
The proverb contains 35 characters.
The function requires you to put a pair of brackets after the word length even though you shouldn't put anything in them.
This gives a substring from the main string, i.e. copies some of the characters from it. Inside the brackets you have to give two numbers. The first number is the starting position of the substring to extract, the second number is the number of characters to copy. Here's an example.
string name = "Richard Friedman"; cout << name.substr(3,5) << name.substr(13,3);
This produces the string hard man on the screen. The first use of name.substr starts at index 3 in the string, which is the letter h (remember, the index starts at 0) and counts the next 5 characters, which include the space. Similarly, the 3 characters from index 13 are displayed. If the second number in brackets would take the index point beyond the end of the string, then it simply includes at the characters up to the end of the string and no further, so a slight change in the example above ...
string name = "Richard Friedman"; cout << name.substr(3,5) << name.substr(13,300);
produces the same string. You could miss out the second number altogether, and again, all the characters from the specified position are selected:
string x = "ABCDEFGH"; cout << x.substr(2,150);
This produces the string CDEFGH, but does not produce an error when you try to go beyond the end of the string. You would get the same result if you just used name.substr(2).
This is useful little function. It finds one string inside another. Inside the brackets you pass the substring that you want to find, and it returns the index position of the substring inside the main one or some other number if it isn't there (my compiler produces the number 65,535).
string ditty = "The owl and the pussy cat went to sea";
cout << ditty.find("owl");
This produces the number 4 (which is where the substring owl starts). However,
string ditty = "The owl and the pussy cat went to sea";
cout << ditty.find("hawk");
would produce the number 65,535 (at least using my compiler - yours may be completely different!) because the substring hawk isn't present in the main string. You can specify a position in string at which to start searching. This is put in as an (optional) second number after the substring to find:
string ditty = "The owl and the pussy cat went to sea";
cout << ditty.find(" ") << endl;
cout << ditty.find(" ",5) << endl;
The first find operation searches from the start of the string and produces the number 3 (the index position of the first space). The second find operation starts searching from position 5 and produces the number 7, the index position of the first space after position 5 in the string.
This is a variation on string.find, except it starts the search from the rear end of the string and works backwards.
string ditty = "The owl and the pussy cat went to sea";
cout << ditty.find("owl") << endl;
cout << ditty.rfind("owl") << endl;
In this case, both versions of the strings produce the same number as the substring "owl" only occurs once in the string, so it doesn't matter which direction you search in.
string ditty = "The owl and the pussy cat went to sea";
cout << ditty.find(" ") << endl;
cout << ditty.rfind(" ") << endl;
In this case, find produces the number 3, and rfind produces the number 33. Find finds the space before the word "owl" and rfind finds the space before the word "sea".
string ditty = "The owl and the pussy cat went to sea";
cout << ditty.find("sparrow") << endl;
cout << ditty.rfind("sparrow") << endl;
In this case, both finds produce the same number, 65,535 using my compiler, as the substring "sparrow" is not present in the string.
Of course, the number may not be 65,535 using your compiler, so C++ has a constant built-in to the string header file (or the cstring header file possibly? See my earlier comment!) which gives the "substring not found" number:
string::npos
If you wanted to test whether a string is present or not, use something like this:
if (quotation.find("Hello") == string::npos)
cout << "The substring Hello is not present."
<< endl;
else
cout << "The substring Hello is present."
<< endl;
The string part of string::npos idicates the header file that the number npos is in, so you may need to change it to cstring::npos or whatever header file you find it in.
Concatenation means putting strings together end to end to
make one large string. It is done using the + sign.
string first_name = "Richard",
surname = "Bowles";
string name;
name = first_name + surname;
cout << name << endl;
This displays the string RichardBowles on the screen. Whoops! Forgot to put a space in there .....
name = first_name + " " + surname;
That's better! You can concatenate strings, mixing variables with string constants between double quotation marks. However, the compiler can occasionally get confused. This concatenation of strings will confuse it:
name = "Bill " + "Clinton";
The compiler won't like this. My compiler gives me an "Invalid pointer addition" error. This is because it doesn't realise that it is string concatenation that is being done. You can persuade it that you are dealing with strings by making one of the operands a string variable:
string last_name = "Clinton"; name = "Bill " + last_name;
This would work, as the presence of a string variable makes the situation clear. All string concatenations work from the back towards the front (unless you put in brackets to alter the order). This means that if you want to concatenate several strings, you should make the last one in the list a string variable. This is the concatenation done first, so the compiler then knows that it is string concatenation that is taken place.
string s; string full_stop = "."; s = "The cat " + "sat on " + "the mat" + full_stop;
This won't cause an error in the compiler.