Chapter 21: Strings

Chapter 21 deals with the C++ strings library (a welcome relief).


Contents


MFC's CString

Blah.

Return to top of page or to the FAQ.


A case-insensitive string class

The well-known-and-if-it-isn't-well-known-it-ought-to-be Guru of the Week discussions held on Usenet covered this topic in January of 1998. Briefly, the challenge was, "write a 'ci_string' class which is identical to the standard 'string' class, but is case-insensitive in the same way as the (common but nonstandard) C function stricmp():"

   ci_string s( "AbCdE" );

   // case insensitive
   assert( s == "abcde" );
   assert( s == "ABCDE" );

   // still case-preserving, of course
   assert( strcmp( s.c_str(), "AbCdE" ) == 0 );
   assert( strcmp( s.c_str(), "abcde" ) != 0 );
   

The solution is surprisingly easy. To avoid useless repitition, it is not presented here. Go to the original answer page for solutions and discussion.

CRUMBS! It's been removed into cold storage! I'll have to rewrite it here....

Return to top of page or to the FAQ.


Breaking a C++ string into tokens

The Standard C (and C++) function strtok() leaves a lot to be desired in terms of user-friendliness. It's unintuitive, it destroys the character string on which it operates, and it requires you to handle all the memory problems. But it does let the client code decide what to use to break the string into pieces; it allows you to choose the "whitespace," so to speak.

A C++ implementation lets us keep the good things and fix those annoyances. The implementation here is more intuitive (you only call it once, not in a loop with varying argument), it does not affect the original string at all, and all the memory allocation is handled for you.

It's called stringtok, and it's a template function. It's given in this file in a less-portable form than it could be, to keep this example simple (for example, see the comments on what kind of string it will accept here). If you compiled and ran this code using it:

   std::list  ls;
   stringtok (ls, " this  \t is\t\n  a test  ");
   for (std::list::const_iterator i = ls.begin();
        i != ls.end(); ++i)
   {
       std::cerr << ':' << (*i) << ":\n";
   }
You would see this as output:
   :this:
   :is:
   :a:
   :test:
with all the whitespace removed. The original s is still available for use, ls will clean up after itself, and ls.size() will return how many tokens there were.

As always, there is a price paid here, in that stringtok is not as fast as strtok. The other benefits usually outweight that, however.

Return to top of page or to the FAQ.


Simple transformations

Here are completely Standard, completely portable ways to perform common transformations on a string instance, such as "convert to all upper case." The word transformations is especially apt, because the standard template function transform<> is used. Each example assumes this small block of code:

   #include <string>
   #include <algorithm>
   #include <cctype>      // old <ctype.h>
   std::string  s ("Some Kind Of Initial Input Goes Here");
   

The example are broken up by dashed lines and are not meant to be contiguous, or flow from one to the next.

   // 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);

   // -----------------------------
   // What other simple things are there?
   

Return to top of page or to the FAQ.


Comments and suggestions are welcome, and may be sent to Phil Edwards or Gabriel Dos Reis.