#include <algorithm>
#include <cctype> // old <ctype.h>
- std::string s ("Some Kind Of Initial Input Goes Here");
+ struct ToLower
+ {
+ char operator() (char c) const { return std::tolower(c); }
+ };
+
+ struct ToUpper
+ {
+ char operator() (char c) const { return std::toupper(c); }
+ };
- // Change everything into upper case
- std::transform (s.begin(), s.end(), s.begin(), toupper);
+ int main()
+ {
+ std::string s ("Some Kind Of Initial Input Goes Here");
+
+ // Change everything into upper case
+ std::transform (s.begin(), s.end(), s.begin(), ToUpper());
- // Change everything into lower case
- std::transform (s.begin(), s.end(), s.begin(), tolower);
+ // Change everything into lower case
+ std::transform (s.begin(), s.end(), s.begin(), ToLower());
- // Change everything back into upper case, but store the
- // result in a different string
- std::string capital_s;
- capital_s.reserve(s.size());
- std::transform (s.begin(), s.end(), capital_s.begin(), tolower); </pre>
+ // Change everything back into upper case, but store the
+ // result in a different string
+ std::string capital_s;
+ capital_s.resize(s.size());
+ std::transform (s.begin(), s.end(), capital_s.begin(), ToUpper());
+ } </pre>
<p><span class="larger"><strong>Note</strong></span> that these calls all
involve the global C locale through the use of the C functions
<code>toupper/tolower</code>. This is absolutely guaranteed to work --
So, if all your input forevermore consists of only those 96
characters (hahahahahaha), then you're done.
</p>
- <p>At minimum, you can write short wrappers like
+ <p><span class="larger"><strong>Note</strong></span> that the
+ <code>ToUpper</code> and <code>ToLower</code> function objects
+ are needed because <code>toupper</code> and <code>tolower</code>
+ are overloaded names (declared in <code><cctype></code> and
+ <code><locale></code>) so the template-arguments for
+ <code>transform<></code> cannot be deduced, as explained in
+ <a href="http://gcc.gnu.org/ml/libstdc++/2002-11/msg00180.html">this
+ message</a>. <!-- section 14.8.2.4 clause 16 in ISO 14882:1998
+ if you're into that sort of thing -->
+ At minimum, you can write short wrappers like
</p>
<pre>
char toLower (char c)
{
- return tolower(static_cast<unsigned char>(c));
+ return std::tolower(c);
} </pre>
<p>The correct method is to use a facet for a particular locale
and call its conversion functions. These are discussed more in
Chapter 22; the specific part is
- <a href="../22_locale/howto.html#5">here</a>, which shows the
- final version of this code. (Thanks to James Kanze for assistance
- and suggestions on all of this.)
+ <a href="../22_locale/howto.html#7">Correct Transformations</a>,
+ which shows the final version of this code. (Thanks to James Kanze
+ for assistance and suggestions on all of this.)
</p>
<p>Another common operation is trimming off excess whitespace. Much
like transformations, this task is trivial with the use of string's
#include <algorithm>
#include <cctype> // old <ctype.h>
- struct Toupper
+ struct ToUpper
{
- Toupper(std::locale const& l) : loc(l) {;}
- char operator() (char c) { return std::toupper(c,loc); }
+ ToUpper(std::locale const& l) : loc(l) {;}
+ char operator() (char c) const { return std::toupper(c,loc); }
private:
std::locale const& loc;
};
- struct Tolower
+ struct ToLower
{
- Tolower(std::locale const& l) : loc(l) {;}
- char operator() (char c) { return std::tolower(c,loc); }
+ ToLower(std::locale const& l) : loc(l) {;}
+ char operator() (char c) const { return std::tolower(c,loc); }
private:
std::locale const& loc;
};
int main ()
{
std::string s("Some Kind Of Initial Input Goes Here");
- std::locale loc_c("C");
- Toupper up(loc_c);
- Tolower down(loc_c);
+ std::locale loc_c("C");
+ ToUpper up(loc_c);
+ ToLower down(loc_c);
// Change everything into upper case.
std::transform(s.begin(), s.end(), s.begin(), up);
std::string capital_s;
std::transform(s.begin(), s.end(), std::back_inserter(capital_s), up);
}</pre>
+ <p>The <code>ToUpper</code> and <code>ToLower</code> structs can be
+ generalized for other character types by making <code>operator()</code>
+ a member function template.
+ </p>
<p>The final version of the code uses <code>bind2nd</code> to eliminate
the wrapper structs, but the resulting code is tricky. I have not
shown it here because no compilers currently available to me will