User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

    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 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


    IT Offers


    Top Authors