https://groups.google.com/d/msg/microsoft.public.pocketpc.developer/oaAgvrjgl8k/Q0rlSzU4wL4J
nor...@googlegroups.com
12/27/05
Hi.
I have "ported" an app from eVC4 to VS2005, and everything compiles and works somewhat OK. But there seems to be some changes in the CString::Format method.
1. It is limited to 1025 characters. Any longer, and it truncates. If I just add several strings to eachother using '+', the resulting string can be far larger than 1025, so it must be the Format function itself. This is a major problem, is there a fix?
2. Some Format statements that worked in eVC4 no longer works. I have a statement with 13 %'s and the first 10 are inserted OK, but number 11 is just wrong, and 12 and 13 seems offset by one.
Does anyone know about this? I guess I have to make my own CString-based class and override the Format function if there is no way to fix this.
Best regards,
Ole-Johan Ellingsen
Click here to Reply
buzz
12/28/05
We just got done fighting the problem with Format in our port from eVC4
to WM5. It appears that MFC8 is using the "safe" versions of sprintf,
and there is no apparent way of disabling this (compiler switches).
Here is the class that I wrote to get around the problem. (BTW....I
haven't noticed your item #2...yet).
HERE IS THE HEADER FILE
//------------------------------------------------------------------------------
#pragma once
#include "strsafe.h"
class CPCString
{
public:
CPCString(void);
virtual ~CPCString(void);
bool Format(const TCHAR* format, ...);
TCHAR* GetBuffer() { return _buf; }
private:
TCHAR* _buf;
int getBufferSize(const TCHAR* format, va_list args);
};
HERE IS THE CPP FILE
//------------------------------------------------------------------------------
#include "StdAfx.h"
#include "PCString.h"
//------------------------------------------------------------------------------
//
// Constructor
//
//------------------------------------------------------------------------------
CPCString::CPCString(void): _buf(NULL)
{
}
//------------------------------------------------------------------------------
//
// Destructor
// Destroy the internal string buffer as we go out of scope
//
//------------------------------------------------------------------------------
CPCString::~CPCString(void)
{
if(_buf)
{
delete _buf;
_buf = NULL;
}
}
//------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------
bool CPCString::Format(const TCHAR* format, ...)
{
bool res = true;
size_t bufLength = 0;
LPTSTR pEnd = NULL;
size_t chRemaining = 0;
DWORD flags = STRSAFE_NULL_ON_FAILURE | STRSAFE_IGNORE_NULLS;
HRESULT hr = S_OK;
// Create the variable arguement list and initialize
va_list args;
va_start(args, format);
// Calculate how much buffer we will need based on the length of the
// format string and the size of the arguements
bufLength = getBufferSize(format, args);
// Reset the arguement pointer back to the beginning
va_start(args, format);
// Create a buffer large enough to hold our formatted string
_buf = new TCHAR[bufLength];
if(_buf == NULL)
{
// Something bad happened....bail
return false;
}
// Clear the buffer
memset((void*)_buf, 0, bufLength);
// Call the safe sprintf for format the string into the given buffer
hr = StringCchVPrintfEx(_buf, bufLength, &pEnd, &chRemaining, flags,
format, args);
// Make sure everything is ok
if(FAILED(hr))
{
res = false;
}
return res;
}
//------------------------------------------------------------------------------
//
// Calculates the size of the buffer (in TCHAR) that is needed to hold the
// formatted string based on arguement types (lengths).
//
//------------------------------------------------------------------------------
int CPCString::getBufferSize(const TCHAR* format, va_list args)
{
const int NON_STRING_LENGTH = 32;
const int ROUNDING_LENGTH = 256;
TCHAR ch;
// Initialize the length to the length of the format string. We know we
will
// need at least that much buffer.
int length = _tcslen(format);
// Set pointers to the beginning and end of the format string
TCHAR* p = (TCHAR*)format;
TCHAR* pEnd = p + length;
// Loop thru the format string
while(p < pEnd)
{
// If we find a formatter...
if(*p == _T('%'))
{
// Get the format type
ch = *(p + 1);
// Make sure the user is not just printer a percent ('%%')
if(ch != _T('%'))
{
// Check for string format types
if((ch == _T('s')) || (ch == _T('S')))
{
// We found a string type, so get the string length of the
// corresponding arguement and add it to the overall length
length += _tcslen(va_arg(args, TCHAR*));
}
else if((ch == _T('e')) || (ch == _T('E')) || (ch == _T('f')) ||
(ch == _T('g')) || (ch == _T('G')))
{
// We found a real type, so grab its arguement and throw it away.
// Add a fixed amount for this type to the overall length
va_arg(args, double);
length += NON_STRING_LENGTH;
}
else
{
// We found an integer type, so grab its arguement and throw it away.
// Add a fixed amount for this type to the overall length
va_arg(args, int);
length += NON_STRING_LENGTH;
}
}
// Skip of the format type
p++;
}
// Examine the next character in the format string
p++;
}
// Make the overall length a nice multiple of ROUNDING_LENGTH
length = length + (ROUNDING_LENGTH - (length % ROUNDING_LENGTH));
return length;
}
USE WITH CAUTION....
- show quoted text -