CBStr: a BSTR wrapper-class with string manipulation members | CodeGuru

CBStr: a BSTR wrapper-class with string manipulation members

The MFC CString class, has some really nice string manipulation routines. However, if you are trying to avoid the MFC for size/deployment issues, and having to do string manipulation of BSTRs I’m sure that you will be finding the _bstr_t class frustratingly basic. After doing a great deal of frustrated hair-pulling I finally got around […]

Written By
CodeGuru Staff
CodeGuru Staff
Oct 20, 1998
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

The MFC CString class, has some really nice string manipulation routines.
However, if you are trying to avoid the MFC for size/deployment issues, and having to do string manipulation
of BSTRs I’m sure that you will be finding the _bstr_t class frustratingly basic.

After doing a great deal of frustrated hair-pulling I finally got around to implementing this class, CBstr.
It is a C++ class derived from the MS VC++ _bstr_t COM support class with the added benefit of
a barrow-load of string manipulation methods. The original idea came after seeing Alex Stockton’s
NoMFC::CString class at www.WorldofATL.com. This class was used
as the template for the public interface.

The class uses the same public “interface” as the NoMFC::CString Class with a couple of minor
differences and as a result has all the functionality of the “real” (MFC) CString class with a few
extra’s. And because it is derived from _bstr_t

Because the class is derived from _bstr_t it is very easy to use instead of that class,
especially where string manipulation of any kind is required. If you are not planning on
using the string-manipulation functionality I would suggest sticking with the _bstr_t class
for reduced class size.

To use the class simply #include the CBstrImpl.h header file supplied in the Zip, and have
this and CBStr.h in your include path.

A demo program (and my test rig) follows and is included in the zip file. This exercises
all of the functionality of of the class, but for more information I would suggest looking
at the documentation of the MFC CString class – it doesn’t seem woth copying it out 😉

This code has been tested with Visual C++ 5.0 Service Pack 3, it has not been tested
with Visual C++ 6.0

Example code

// Main.cpp
//
// Test harness to execise the CBstr class
// derived from _bstr_t and based on the 
// NoMFC::CString class from www.worldofatl.com
//
// If anyone can figure out why the ostream::operator<< refuses to
// use the implicit cast to const char* or char* then please email me 
// at gary.olliffe@parallax.co.uk
// 
//
#include “CBstrImpl.h”
#include <iostream>
using std::cout;
const TCHAR* Test(const TCHAR* psz);
// This test only works in ANSI (not UNICODE) builds
// due to lack of _T() and stream insertion operator
int main()
{
	// Create a proper BSTR 
	BSTR bstr = ::SysAllocString(L“Hello World”);
	// Create two objects of out new class
	CBstr newstr(bstr, true);    //Take a copy of bstr
	CBstr newstr2(bstr, false);  //attach to bstr
	// test the MakeUpper method
	newstr2.MakeUpper();
	// Extract the BSTR (this gives a reference 
	// to the encapulated BSTR, not a copy)
	BSTR ptrcopy = newstr2;
	// Take a copy of the encapsulated BSTR 
	BSTR deepcopy = newstr2.copy();
	// Test cast to char *
	char * ansistr = newstr2;
	// Test cast to const char *
	const char* ansicstr = newstr2;
	// output results 	
	cout << ansistr << “n” << ansicstr;
	cout << newstr2;
	// Create another string for testing
	CBstr str(“twenty”);
	// Call a method that takes a const char* parameter
	Test(str);
	// create another CBstr from the first
	CBstr str2(str);
	// output results
	cout << (const char*)str << “n”;
	cout << (const char*)str2 << “n”;
	// test the format method  
	str.Format(“sder %d %s”, 1, “ss”);
	cout << (const char*)str << “n”;
	// test the length() method
	CBstr s(“abcdef”);
	cout << s.length() << “n”; // == 6 
	// test the isempty() method
	CBstr s2;
	cout << s2.IsEmpty() << “n”; // == true
	// test the Empty method
	CBstr s3(“abc”);
	s3.Empty();
	cout << s3.length() << “n”; // == 0
	// Test GetAt() method
	CBstr s4(“abcdef”);
	cout << s4.GetAt(2) << “n”; //  == ‘c’
	// Test the operator[]
	CBstr s5(“abc”);
	cout << s5[1] << “n”; // == ‘b’
	s5.SetAt(1, ‘X’);
	cout << s5[1] << “n”; // == ‘X’
	// test assignment operators
	CBstr s6, s7;        // Empty CBstr objects
	s6 = “cat”;            // s6 == “cat”
	cout << (const char*)s6 << “n”;
	s7 = s6;               // s6 and s7 each == “cat”
	cout << (const char*)s7 << “n”;
	// test operator+()
	s6 = “the “ + s6;      // Or expressions
	cout << (const char*)s6 << “n”;
	// example for CBstr::operator +
	CBstr s8(“abc”);
	CBstr s9(“def”);
	cout << (const char*)(s8 + s9 ) << “n”; // == “abcdef”
	CBstr s10;
	s10 = CBstr(“abc”) + “def” ; // == “abcdef”
	cout << (const char*)s10 << “n”;
	// example for CBstr::operator +=
	CBstr s11(“abc”);
	cout << (const char*)( s11 += “def”) << “n”; // == “abcdef”
	// example for CBstr Comparison Operators
	CBstr s12(“abc”);
	CBstr s13(“abd”);
	if (s12 < s13)
		cout << “s12 < 13” << “n”; // == true Operator is overloaded for both.
	if (“ABC” < s12)
		cout << “ABC < s12” << “n”; // == true CBstr and char*
	if (s13 > “abe”)
		cout << “s13 > abe” << “n”; // == false 
	if (s13 == “abd”)
		cout << “s13 == abd” << “n”; // == true
	// example for CBstr::Compare
	CBstr s14( “abc” );
	CBstr s15( “abd” );
	cout << s14.Compare(s15) << “n”; // == -1 // Compare with another CBstr.
	cout << s14.Compare(“abe”) << “n”; // == -1 // Compare with LPTSTR string.
	// example for CBstr::CompareNoCase
	CBstr s16( “abc” );
	CBstr s17( “ABD” );
	cout << s16.CompareNoCase( s17 ) << “n”; // == -1 // Compare with a CBstr.
	cout << s16.Compare( “ABE” )  << “n”; // == 1 // Compare with LPTSTR string.
	// example for CBstr::Mid
	CBstr s18(“abcdef”);
	cout << (const char*)s18.Mid(2, 3) << “n”; //  == _T(“cde”)
	// example for CBstr::Left
	CBstr s19( _T(“abcdef”) );
	cout << (const char*)s19.Left(2) << “n”; //  == _T(“ab”)
	// example for CBstr::Right
	CBstr s20( _T(“abcdef”) );
	cout << (const char*)s20.Right(2) << “n”; //  == _T(“ef”)
	// example for CBstr::SpanIncluding
	CBstr s21( “cabbage” );
	CBstr s22 = s21.SpanIncluding( “abc” );
	cout << (const char*)s22 << “n”; //  == “cabba”
	s22 = s21.SpanIncluding( “xyz” );
	cout << s22.IsEmpty( ) << “n”; // == true
	// example for CBstr::MakeUpper
	CBstr s23( “abc” );
	s23.MakeUpper();
	cout << (const char*)s23 << “n”; //  == “ABC”
	// example for CBstr::MakeLower
	CBstr s24( “ABC” );
	s24.MakeLower();
	cout << (const char*)s24 << “n”; //  == “abc”
	// example for CBstr::MakeReverse
	CBstr s25( “abc” );
	s25.MakeReverse();
	cout << (const char*)s25 << “n”; //  == “cba”
	// example for CBstr::Find
	CBstr s26( “abcdef” );
	cout << s26.Find( ‘c’ ) << “n”; //  == 2
	cout << s26.Find( “de” ) << “n”; //  == 3
	// example for CBstr::ReverseFind
	CBstr s27( “abcabc” );
	cout << s27.ReverseFind( ‘b’ ) << “n”; //  == 4
	// example for CBstr::FindOneOf
	CBstr s28( “abcdef” );
	cout << s28.FindOneOf( “xd” ) << “n”; //  == 3 // ‘d’ is first match
	return 0;
}

Download demo project – 7 KB

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.