.NODE

Joining a Sequence of Strings

Problem

Given a sequence of strings, such as output from Example 4-10, you want to join them together into a single, long string, perhaps with a delimiter.

Solution

Loop through the sequence and append each string to the output string. You can handle any standard sequence as input; Example 4-13 uses a vector of strings.

Example 4-13. Join a sequence of strings

#include 
#include 
#include 

using namespace std;

void join(const vector& v, char c, string& s) {

 s.clear( );

 for (vector::const_iterator p = v.begin( );
 p != v.end( ); ++p) {
 s += *p;
 if (p != v.end( ) - 1)
 s += c;
 }
}

int main( ) {

 vector v;
 vector v2;
 string s;

 v.push_back(string("fee"));
 v.push_back(string("fi"));
 v.push_back(string("foe"));
 v.push_back(string("fum"));

 join(v, '/', s);

 cout << s << '
';
}

 

Discussion

Example 4-13 has one technique that is slightly different from previous examples. Look at this line:

for (vector::const_iterator p = v.begin( );

The previous string examples simply used iterators, without the "const" part, but you can't get away with that here because v is declared as a reference to a const object. If you have a const container object, you can only use a const_iterator to access its elements. This is because a plain iterator allows writes to the object it refers to, which, of course, you can't do if your container object is const.

I declared v const for two reasons. First, I know I'm not going to be modifying its contents, so I want the compiler to give me an error if I do. The compiler is much better at spotting that kind of thing than I am, especially since a subtle syntactic or semantic error can cause an unwanted assignment. Second, I want to advertise to consumers of this function that I won't do anything to their container, and const is the perfect way to do that. Now, I just have to create a generic version that works on multiple character types.

Just as in Recipe 4.6, making join generic with a function template is easy. All you have to do is change the header to be parameterized on the type of character, like this:

template
void joing(const std::vector >& v, T c,
 std::basic_string& s)

But vectors may not be your only input. You may be saddled with the task of joining an array of C-style strings. C++ strings are preferable to C-style strings, so if you have to do this, join them into a C++ string. Once you've done that, you can always retrieve a C-style version by calling string's c_str member function, which returns a const pointer to a null-terminated character array.

Example 4-14 offers a generic version of join that joins an array of character arrays into a string. Since the new, generic version is parameterized on the character type, it will work for narrow or wide character arrays.

Example 4-14. Joining C-style strings

#include 
#include 

const static int MAGIC_NUMBER = 4;

template
void join(T* arr[], size_t n, T c, std::basic_string& s) {
 s.clear( );

 for (int i = 0; i < n; ++i) {
 if (arr[i] != NULL)
 s += arr[i];
 if (i < n-1)
 s += c;
 }
}

int main( ) {
 std::wstring ws;

 wchar_t* arr[MAGIC_NUMBER];

 arr[0] = L"you";
 arr[1] = L"ate";
 arr[2] = L"my";
 arr[3] = L"breakfast";

 join(arr, MAGIC_NUMBER, L'/', ws);


}


Building C++ Applications

Code Organization

Numbers

Strings and Text

Dates and Times

Managing Data with Containers

Algorithms

Classes

Exceptions and Safety

Streams and Files

Science and Mathematics

Multithreading

Internationalization

XML

Miscellaneous

Index

show all menu





C++ Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2006
Pages: 241
Similar book on Amazon

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net