Converting the Hard Way
There are numerous ways to change the case of a string. A naive implementation might look like this:
using namespace std;
for (int j=0; j<s.length(); ++j)
} // s now contains "HELLO"
Though functionally correct, this loop is a maintenance headache. To apply a different type of transformation to the string, say to convert it to lowercase or transliterate all characters to their Cyrillic equivalent, you'll have to rewrite the loop's body. To improve the design, separate the string transformation into two operations: one that iterates through the string's elements and one that actually transforms every element. You gain more flexibility by decoupling these operations and simplify future maintenance.
Step 1: Iteration
The transform() algorithm defined in <algorithm> is rather flexible. Not only does it separate between the iterations and transformation operations, it also allows you to transform only a portion of the string. In addition, you can store the result in a different destination, should you prefer to keep the original string intact. The transform() algorithm has two overloaded versions but we will use only the following one:
OutputIterator transform(InputIterator first,
You can find an explanation about the different iterator categories here
. The first and second arguments are iterators pointing to the beginning and the end of the sequence being transformed. The third argument is an iterator pointing to the beginning of the destination sequence. If you wish to overwrite the current string, result and first should have identical values.
Step 2: Transformation
The fourth argument is a unary operator. It can either be an address of a function that takes a single argument or a function object. STL algorithms don't really care whether a unary operator is a function object or an address because they merely append () to it and let the compiler takes care of the rest. This example uses the standard toupper() function declared in <cctype>:
#include <cctype> // for toupper
using namespace std;
transform(s.begin(), s.end(), s.begin(), toupper);
Alas, the program above will not compile because the name 'toupper' is ambiguous. It can refer either to:
int std::toupper(int); // from <cctype>
template <class chart>
charT std::toupper(charT, const locale&);// from
Use an explicit cast to resolve the ambiguity:
std::transform(s.begin(), s.end(), s.begin(),
This will instruct the compiler to choose the right toupper().