|
It surely should be interesting and useful a CString-clone not using Microsoft C++ ...
So I test to compile with gcc (g++, gpp), and I get the following:
==========================================================
Compiler: Default compiler
Executing g++.exe...
g++.exe ".\TestString.cpp" -o ".\TestString.exe" -fexpensive-optimizations -O1 -I"C:\DEV-CPP\include\c++" -I"C:\DEV-CPP\include\c++\mingw32" -I"C:\Dev-Cpp\include\c++\backward" -I"C:\Dev-Cpp\include" -L"C:\DEV-CPP\lib"
In file included from ./TestString.cpp:5:
./StdString.h: In function `int ssvsprintf(WCHAR*, unsigned int, const
WCHAR*, char*)':
./StdString.h:1111: invalid conversion from `size_t' to `const wchar_t*'
./StdString.h:1111: cannot convert `const WCHAR*' to `char*' for argument
`3' to `int vswprintf(wchar_t*, const wchar_t*, char*)'
./StdString.h: At global scope:
./StdString.h:1693: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, const CStdStr<ct>&)' declares a non-template
function
./StdString.h:1693: warning: (if this is not what you intended, make sure
the function template has already been declared and add <> after the
function name here) -Wno-non-template-friend disables this warning
./StdString.h:1694: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, CT)' declares a non-template function
./StdString.h:1695: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, const CHAR*)' declares a non-template function
./StdString.h:1696: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, const WCHAR*)' declares a non-template
function
./StdString.h:1697: warning: friend declaration `CStdStr<ct>
operator+(const CHAR*, const CStdStr<ct>&)' declares a non-template function
./StdString.h:1698: warning: friend declaration `CStdStr<ct>
operator+(const WCHAR*, const CStdStr<ct>&)' declares a non-template
function
In file included from ./TestString.cpp:5:
./StdString.h:3015:31: warning: no newline at end of file
./TestString.cpp: In function `int main(int, char**)':
./TestString.cpp:15: `_bstr_t' undeclared (first use this function)
./TestString.cpp:15: (Each undeclared identifier is reported only once for
each function it appears in.)
./TestString.cpp:26: `_ASSERTE' undeclared (first use this function)
./TestString.cpp:56: no method `CStdStr<char>::SetResourceHandle'
./TestString.cpp:57: `IDS_STRING1' undeclared (first use this function)
./TestString.cpp:60: `IDS_STRING2' undeclared (first use this function)
./StdString.h: In member function `bool CStdStr<ct>::Equals(const CT*,
bool) const [with CT = char]':
./TestString.cpp:27: instantiated from here
./StdString.h:1785: no matching function for call to `ssicmp(
CStdStr<char>, const char*&)'
Execution terminated
==========================================================
How It can be handled ?
Thanks in advance
Miguel PS
|
|
|
|
|
As in the above question, it would appear you have an out-of-date version of the code. Please try to grab the latest version from this link:
http://home.earthlink.net/~jmoleary/code/StdString.zip
This should make things much better. Please let me know if you have any other problems. Clearly I have been lax in following this board but I will be more vigilant in the future.
-Joe
|
|
|
|
|
Hello,
I experienced a small problem with compiling this under linux with g++.
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-42)
Compiling:
==================================================
g++ -g -fno-rtti -O3 -c main.cpp -o main.o
In file included from main.cpp:19:
StdString.h: In function `int ssvsprintf(wchar_t*, unsigned int, const
wchar_t*, char*)':
StdString.h:1627: invalid conversion from `const wchar_t*' to `unsigned int'
StdString.h:1627: cannot convert `char*' to `const wchar_t*' for argument `3'
to `int vswprintf(wchar_t*, unsigned int, const wchar_t*, char*)'
main.cpp:48:1: warning: no newline at end of file
make: *** [main.o] Error 1
StdString.h:
-----------------------------------------------------------------------------
1623: #elif defined(__sgi)
1624:
1625: nCount;
1626: return vsprintf( (char *)pW, (char *)pFmtW, vl);
1627:
1628:#else
1629:
1630: nCount;
1631: return vswprintf(pW, pFmtW, vl);
1632:
1633: #endif
-------------
>> man vsprintf
vswprintf - formatted wide character output conversion
int vswprintf(wchar_t *wcs, size_t maxlen,
const wchar_t *format, va_list args);
Solution:
I commented line number 1615 and everything compiled and works fine, so it would be like this:
StdString.h:
#if !defined(_MSC_VER) \
&& !defined (__BORLANDC__) \
1615: //&& !defined(__GNUC__) \
&& !defined(__sgi)
return vswprintf(pW, nCount, pFmtW, vl);
// suddenly with the current SGI 7.3 compiler there is no such function as
// vswprintf and the substitute needs explicit casts to compile
#elif defined(__sgi)
-----------------------------------------------------------------------------------------
It is just a small issue, and everything else works perfectly fine.
And I would like to thank YOU, and all other people, which helped
to create that wonderful class.
I did manage to compile my class, which I wrote under VS7 with CString, using CStdString under Linux without any changes (well, concerning the using of the CString).
THANK YOU.
|
|
|
|
|
Hi,
I'm glad you've had some success with my code. The vsprintf() thing causes a lot of problems and I still have no foolproof solution for all platforms.
There is a somewhat more recent (than CodeProject's) version of the code available at the usual place:
http://home.earthlink.net/~jmoleary/code/StdString.zip.
It includes a minor performance optimization for Replace() and alerts you to possible problems that might occur if you don't have a length-checked formatting function available on your platform
-Joe
-Joe
|
|
|
|
|
I just have a question that if I can use CStdString type of variable where char* is needed. I am afraid it is going to cause crashes. Any help will be greatly appreciated.
|
|
|
|
|
Do you mean where char* is required or const char * ?
For const char* it is no problem. The class has an implicit cast operator to that or you can call c_str() to retrieve the const char* . For example:
<br />
int main(void)<br />
{<br />
<br />
FILE* file = fopen("myfile.txt", "w");<br />
CStdString sName = "Joe";<br />
<br />
<br />
fprintf(file, sName);<br />
<br />
<br />
fprintf(file, sName.c_str());<br />
<br />
return 0;<br />
}<br />
<br />
<br />
For char* you need to be a little more careful since you are effectively giving direct access to the internal buffer of the string class out to another function. To access a CStdtring as a char* you do the same thing you would do with MFC's CString: Call the GetBuffer() function. When access to that internal buffer is no longer needed, call the ReleaseBuffer() function
It is up to you to make sure that you have allocated enough space in the buffer for whatever code you pass it of to. But that's the same problem you would have if you simply allocated a flat char[] array on the stack or got a char* from heap memory. In other words, there is no greater danger using CStrString's internal buffer than there would be using a simple char buffer.
Here's a really dopey example to show how it works.
<br />
<br />
<br />
void GetNameOfCity(char* buf, int nMaxChars)<br />
{<br />
strncpy(buf, "Boston", nMaxChars)<br />
}<br />
<br />
<br />
int main(void)<br />
{<br />
CStdString str;<br />
str.FillStringBuffer(str.GetBuffer(20), 20);<br />
str.ReleaseBuffer();<br />
return 0;<br />
}<br />
<br />
-Joe
|
|
|
|
|
Just a heads up for you Joe, in VS 7.1, when you turn on the compiler option 'Detect 64 bit Portability issues' (option is under Project > Properties > C/C++ > General) StdString.h generates quite a number of warnings. Looks like quite a few static_cast<>'s are needed
|
|
|
|
|
Joe,
many thanks for this class, I've been using it for years with great success.
Right now I'm having difficulty with the SS_NO_REFCOUNT directive, is as much as turning it on prevents compilation. I was wondering if I'd missed something or if indeed there was a problem. This is the compiler error...
c:\dev\fsiv30\platform\microsoft\fsiv30lib\fsilibtest\stdstring.h(2156) : error C2352: 'std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> >::assign' : illegal call of non-static member function
c:\program files\microsoft visual studio\vc98\include\xstring(132) : see declaration of 'assign'
c:\dev\fsiv30\platform\microsoft\fsiv30lib\fsilibtest\stdstring.h(2144) : while compiling class-template member function 'class CStdStr<char> &__thiscall CStdStr<char>::assign(const char *,unsigned int)'
It occurs on line 2156 of stdstring.h...
Q172398(*this);
>>>>> MYBASE::assign(pC, nChars);
return *this;
If you can offer any feedback I'd appreciate it. I'd rather not go down the route of statically linking the CRT. Right now I'm developing a multithreaded application for Win32 but in the very near future I will need
to develop a similar app for Linux too.
Many thanks
matthew sell
|
|
|
|
|
Hi Matthew,
Sorry to take so long to get back to you.
I'll have to go build my test app tonight with SS_NO_REFCOUNT turned on. I admit it's been awhile since I've done that.
But please be aware, you only need the SS_NO_REFCOUNT setting if you are building with Visual C++ 6.0 with the original version of the Standard C++ Library that came with it. VC7 removes refcounting anyway so it is not needed.
I'll take a look at it tonight or tomorrow night and get back to you
-Joe
-Joe
|
|
|
|
|
The sample code crashes when I add the following:
<br />
CStdString s, t = "test";<br />
s.Format("%s", t);<br />
It is a known problem of va_list / vsprintf implementation of Format functions in custom string classes. If s.Format("%s", (LPCTSTR)t); is used, everything's fine - but I find it annoying to cast a string to LPCTSTR whenever I need to pass it to Format.
Does anyone know a pretty solution to this, except for the full-blown custom Format that is used by MFC's CString?
Regards,
BB
|
|
|
|
|
Well, there IS a pretty solution to it, but it only works for Format(). It does NOT work for sprintf, fprintf, or any other non-CStdString-member function.
Download the latest version here
http://home.earthlink.net/~jmoleary/code/StdString.zip
In it, you will find a version of Format that is specially written to avoid this problem. Basically what I did was overload a member template function to take anywhere from 1 to 17 arguments. Each overload will safely convert the CStdString into an LPCTSTR for you. So as long as you're not passing more than 17 objects to this function, you can avoid this crash.
So your sample code should work just fine.
CStdString s, t = "test";<br />
s.Format("%s", t);
But the following code would still crash
char buf[100];<br />
CStdStringA t = "test";<br />
sprintf(buf, "%s", t);
Is this a hack on my part? Definitely. But you know what? The fact that you are able to pass an MFC CString as a variable argument to a variadic function without casting it is hack as well. Even Microsoft recommends you explicitly cast a CString when passing it to a variadic function. They just let you get away with not doing it.
If it makes any difference, you don't have to cast to LPCTSTR. You can do the slightly less verbose call to c_str() member function. Like this
CStdString s, t = "test";<br />
s.Format("%s", t.c_str());
Still annoying. But we're all supposed to be using streams now anyway, right?
CStdString s, t = "test";<br />
std::stringstream oss<br />
oss << t;<br />
s = oss.str();
-Joe
|
|
|
|
|
Thank you for the solution hint, Joe! I will check out whether it can be simplified by using even more template tricks.
Regards,
BB
|
|
|
|
|
Thanks for this it will save me hours!
However when I add this to my MFC project I get an error in the second archive operator.
The error raised for line 3886 and is:
error C2440: 'initializing' : cannot convert from 'const CStdStringW' to 'ATL::CStringT<BaseType,StringTraits>'
I don't intend to use these operators so I just got rid of them. I just thought I would mention it, to see if there is a solution. I am using VS.Net 7.1.
After I git rid of these lines I was left with the type cast warnings that other people have mentioned. I think I have the latest version, as I have just downloaded it.
What is the best means of getting rid of these warnings.
Thanks again
AndyC
|
|
|
|
|
Hi Andy,
That's actually a minor error that someone pointed out to me a few months ago but that I still haven't fixed. It occurs when the preprocessor macro
_ATL_CSTRING_EXPLICIT_CONSTRUCTORS
is #defined.
The fix is to change this line in the CArchive operator <<:
CString strTemp = strW;
Into this line
CStdString strTemp(strW);
I keep meaning to post the update but I always forget about it. Sorry. If you change your local copy you should be able to build.
But that fix aside, there should not be any compiler warnings. If you are getting them, could you email them to me? I thought I had eliminated them all. It would appear I missed some.
-Joe
|
|
|
|
|
I am seeing this same error with VS.Net 7.1. I have the version dated 2/16/05.
"cannot convert from 'const CStdStringW' to 'ATL::CStringT<basetype,stringtraits>'"
Does anyone have an answer to this issue yet?
|
|
|
|
|
Hi Alan,
Did you try making the one-line fix I suggested in my other response to this thread?
Basically you change this line:
CString strTemp = strW;
into this line
CString strTemp(strW);
I admit I should have changed this myself already. I am unable to access my website via FTP right now so I can't do it at this moment.
-Joe
|
|
|
|
|
That worked, thanks.
Your first post showed:
CStdString strTemp(strW);
changing it to
CString strTemp(strW);
That fixes the problem.
Thanks.
|
|
|
|
|
I recently received an email with a question about CStdString from someone named "Marcus Gesing". Unfortunately the reply address did not work (The gmx.net servers did not have a usernamed "mgesing") so I am unable to reach him.
Marcus, if you see this, please respond to this post and I will attempt to answer your question. The solution should be quite simple, I think
std::locale::global(std::locale(""));
-Joe
|
|
|
|
|
Hello,
What if this is integrated as function "ReplaceNoCase" in CStdString.h, Will it work.
typedef CStdString string
string ReplaceNoCase(string InputString, string OldString,string NewString);
string CTxParser::ReplaceNoCase(string InputString, string OldString, string NewString)
{
string output( InputString );
string input_lower( InputString );
string oldone_lower( OldString );
input_lower.MakeLower();
oldone_lower.MakeLower();
int pos=0;
while ( (pos=input_lower.Find(oldone_lower,pos))!=-1 ) {
input_lower.Delete( pos, lstrlen(OldString) );
input_lower.Insert( pos, NewString );
output.Delete( pos, lstrlen(OldString) );
output.Insert( pos, NewString );
}
return output;
}
This is working code, It replaces the string without any case.
regards
Balkrishna Talele
|
|
|
|
|
Why input_lower.MakeLower() can not work, upper char still be upper char.
VC6 with sp5. Why?
|
|
|
|
|
Hi David,
If you can send me some sample code that does not work for you (i.e. that fails to make an uppercase string lowercase), I can try to figure out what the problem is.
-Joe
-Joe
|
|
|
|
|
Hi Balkrishna,
I have often thought about adding a function like this. But at this point I am unwilling to change my code unless absolutely necessary. Every time I add a function, it becomes code I must support on multiple platforms. By all means, add this function if you want and I do appreciate your submitting it. But I hope you will forgive me if I don't put it in the online version.
One thing though, your function is a little bit inefficient. There is too much string copying going on there. Try something like this:
string CTxParser::ReplaceNoCase(const string& InputString, const string& OldString, const string& NewString)
this avoids copying string objects on the stack. Or you could do this:
string CTxParser::ReplaceNoCase(PCTSTR InputString, PCTSTR OldString, PCTSTR NewString);
This avoids creating string objects when all you have is a const TCHAR*
Thanks,
-Joe
|
|
|
|
|
I have problem with StdString after converting from VC++ 6.0 to VS.Net 2003. I am using it in non MFC DLL with ATL.
The problems start at:
typedef MYBASE::const_pointer PCMYSTR; // PCSTR or PCWSTR
error C2146: syntax error : missing ';' before identifier 'PCMYSTR'
Cheers,
Stan Daymond
|
|
|
|
|
I resolved the problem by downloading the latest version from:
http://www.joeo.net/code/StdString.zip
The version I was using was last modified in year 2000.
I would advise everybody to make sure you use the latest (or at least) very recent version.
Cheers,
Stan Daymond
|
|
|
|
|
I just found a problem in my application. My application is client/server software. They communicate with eath other via socket. But when the port number of server socket is greater than or equal to 10000, socket doesn't work any more. It looks to me that it's memory problem. I wonder if any ever uses the string class with socket before and had same problem. My OS is Windows(XP, 2000, NT). And this happens only when the server executable is launched by another executable. Any help will be greatly appreicated.
|
|
|
|
|