Archive

Posts Tagged ‘std::string’

std::string caveat

Never access an std::string‘s buffer with an intent to increase/decrease it’s length nor pass such a buffer to functions which takes a char*. I did this mistake sometime back and got trapped in a strange bug with operator +=. This is how my code looked.

std::string str( ' ', MAX_PATH );
GetFolderName( pFullPath, &str[0] ); // Oop

Problem with above code is that you won’t get an immediate crash since it’s a properly allocated buffer with MAX_PATH chars. But if you do further operations on such string expect plenty of inconsistencies. This is how my code looked after above piece of code…

str += "\\"; // Append backslash

I was expecting a valid path with backslash appended towards it’s end, but this never happened and debugging with debugger too didn’t help.

So now let me tell you what the exact problem is! When you do &str[0] you pass the address to the first char in std::string‘s buffer. So when function GetFolderName fills in this buffer with folder path the length of std::string is not updated since it’s a C style function and it’s neither expected to do so. So the function terminates given buffer with a ” with std::string‘s length way high (MAX_PATH). So now when I do a += std::string internally fails some condition leading to unexpected results, note that this piece of code never caused a crash but I was quite lucky and watchful enough to fix this stupid bug. Sigh!

So watchout, there is no CString::GetBuffer or CString::GetBufferSetLength type of function for std::string, well at least for now.

How to trim white space before and after a string?

September 5, 2008 4 comments

I will describe in this post three ways to trim a string of given characters…

  1. Using custom function for std::string
  2. Using CString
  3. Using StrTrim shell API function.

Using custom function for std::string

Its bit strange that std::string doesn’t provide a Trim function 😕 , but hey since we’ve got head upon our shoulders we’re gonna write one. :P. Here is a simple function which removes white space before and after a string. We’ll call it Trim! 😛

void Trim( const std::string& StrToTrim, std::string& TrimmedString )
{
  // Find first non whitespace char in StrToTrim
  std::string::size_type First = StrToTrim.find_first_not_of( ' ' );
  // Check whether something went wrong?
  if( First == std::string::npos )
  {
    First = 0;
  }

  // Find last non whitespace char from StrToTrim
  std::string::size_type Last = StrToTrim.find_last_not_of( ' ' );
  // If something didn't go wrong, Last will be recomputed to get real length of substring
  if( Last != std::string::npos )
  {
    Last = ( Last + 1 ) - First;
  }

  // Copy such a string to TrimmedString
  TrimmedString = StrToTrim.substr( First, Last );
}

int main()
{
  std::string StrToTrim = " 32 Nibu babu thomas 2342 2 23 3 ";
  std::string TrimmedString = "On return will hold trimmed string";
  Trim( StrToTrim, TrimmedString );

  return 0;
}
//Output is: 32 Nibu babu thomas 2342 2 23 3

Using CString

Also CString has a Trim function, if you have the liberty to use CString then that’s another option.

Using StrTrim shell API function

Another option is to use StrTrim shell API function. Here is a demo from MSDN.

#include
#include
#include “Shlwapi.h”

void main(void)
{
//String one
TCHAR buffer[ ] = TEXT(“_!ABCDEFG#”);
TCHAR trim[ ] = TEXT(“#A!_”);

cout << "The string before calling StrTrim: "; cout << buffer; cout << "\n"; StrTrim(buffer, trim); cout << "The string after calling StrTrim: "; cout << buffer; cout << "\n"; } OUTPUT: - - - - - - The string before calling StrTrim: _!ABCDEFG# The string after calling StrTrim: BCDEFG[/sourcecode]

A TCHAR version of std stream and string classes

Quite simple…

// A TCHAR based std::string
typedef std::basic_string<tchar> tstring;
// A TCHAR based std::ifstream;
typedef std::basic_ifstream</tchar><tchar , std::char_traits<TCHAR> > tstream;
// A TCHAR based std::stringstream
typedef std::basic_stringstream</tchar><tchar , std::char_traits<TCHAR>, std::allocator</tchar><tchar> > tstringstream;

So now no need to worry about UNICODE and ANSI, should work as CString, since TCHAR becomes char/wchar_t based on _UNICODE macro definition.

Also note that stl has provided UNICODE versions of these classes for e.g. wstring, wstringstream, wifstream, but since windows has a type that switches automagically between char/wchar_t, we are making use of it.

So the idea behind this is that stl classes are mostly template based, so this means you can add your own version of an stl class for a custom type just like I’ve done. As a conclusion we can say that std::string can be called a vector<char> but with dedicated string operations.

%d bloggers like this: