basic question
-
Hi all!! I'm learning C++ and there I'd like somebody to tell me how to properly use the class CString. The problem is that I've a lot of problems with it, when I'm using different CString vars sometimes they screw each others' values. I've noticed that using a property called GetBuffer and ReleaseBuffer, they get fixed. Could somebody tell me the use of that properties and which is the difference between using MyCStringVar.GetBuffer(iBufferLength) and (LPTSTR)(LPCTSTR)MyCStringVar ?? As far as I know they both return a pointer to the string. I know it might be a basic question but if somebody could answer it I'd really appreciate it, thanks.
-
Hi all!! I'm learning C++ and there I'd like somebody to tell me how to properly use the class CString. The problem is that I've a lot of problems with it, when I'm using different CString vars sometimes they screw each others' values. I've noticed that using a property called GetBuffer and ReleaseBuffer, they get fixed. Could somebody tell me the use of that properties and which is the difference between using MyCStringVar.GetBuffer(iBufferLength) and (LPTSTR)(LPCTSTR)MyCStringVar ?? As far as I know they both return a pointer to the string. I know it might be a basic question but if somebody could answer it I'd really appreciate it, thanks.
-
If you don't need to modify the strings contents then use the (LPTSTR)(LPCTSTR) cast. If you want direct access to the CString buffer (so you can modify it) then use GetBuffer.
The problem I had is that If I used this code: CString MyString; mFile->Read((LPTSTR)(LPCTSTR)MyString, iMyLength); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); When reading the file, the var AnotherStringWhichIsAMemberVarOfTheClass got screwed it's value with what I wanted to read (from the file). Then, by using the Try-All-The-Methods-Of-The-Class solution I noticed that If I wrote: CString MyString; mFile->Read(MyString.GetBuffer(iMyLength), iMyLength); MyString.ReleaseBuffer(); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); Everything went right, but I still don't understand why. I'm modifying MyString's content and you've told me that then it'd be better to use GetBuffer(), but contents of AnotherString(...) get screwed when reading the file and before modifying it. Could you tell me why ???? Thanks for everything.
-
The problem I had is that If I used this code: CString MyString; mFile->Read((LPTSTR)(LPCTSTR)MyString, iMyLength); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); When reading the file, the var AnotherStringWhichIsAMemberVarOfTheClass got screwed it's value with what I wanted to read (from the file). Then, by using the Try-All-The-Methods-Of-The-Class solution I noticed that If I wrote: CString MyString; mFile->Read(MyString.GetBuffer(iMyLength), iMyLength); MyString.ReleaseBuffer(); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); Everything went right, but I still don't understand why. I'm modifying MyString's content and you've told me that then it'd be better to use GetBuffer(), but contents of AnotherString(...) get screwed when reading the file and before modifying it. Could you tell me why ???? Thanks for everything.
OK, it's very simple: CString internally holds a buffer of characters. From our standpoint (programmers using the CString class who don't know exactly how it works) CString's buffer grows/shrinks based on its contents. In the first scenario (the one that breaks) you instanciate a CString object (MyString) using its default constructor. This means that it's empty -- it's got an empty buffer. Then you read the file and try to copy its characters into the empty CString object. Since it's got an empty buffer, you end up inadvertently copying the characters to whatever memory is adjacent to it. So you basically overwrite memory which you hadn't allocated for that purpose. This is very bad, as you noticed. In the second scenario, you call GetBuffer to not only return a writable buffer (LPTSTR), but you also tell the object to allocate iMyLength bytes for you to copy into. After reading from the file, you tell the CString object that you're done using the buffer (ReleaseBuffer) and that it should clean it up (find the terminating null character) and make the object ready for use. I hope this is clear to you, but let me just say that usually if you have to do nasty casting like (LPTSTR)(LPCTSTR)MyString, it's a sign that something's not quite right. You should never do that with a CString object unless you're certain that its buffer won't be changed (ie., you're passing a CString object to poorly written code that should have used LPCTSTR instead of LPTSTR). The general rule is: if the function takes an LPCTSTR (or const char*), use the object directly (no casting needed). If the function takes an LPTSTR (or char*), use GetBuffer/ReleaseBuffer. Regards, Alvaro
-
The problem I had is that If I used this code: CString MyString; mFile->Read((LPTSTR)(LPCTSTR)MyString, iMyLength); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); When reading the file, the var AnotherStringWhichIsAMemberVarOfTheClass got screwed it's value with what I wanted to read (from the file). Then, by using the Try-All-The-Methods-Of-The-Class solution I noticed that If I wrote: CString MyString; mFile->Read(MyString.GetBuffer(iMyLength), iMyLength); MyString.ReleaseBuffer(); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); Everything went right, but I still don't understand why. I'm modifying MyString's content and you've told me that then it'd be better to use GetBuffer(), but contents of AnotherString(...) get screwed when reading the file and before modifying it. Could you tell me why ???? Thanks for everything.
Hello, the codegurus around the world.;) One rule is that you had better use MFC as much as possilbe in your code if you want to use CString. If you want to read the content of the file, you can use CStdio calss. Since you use CString value, and want to pass const char* (LPCSTR) of the function, it sometimes waste your code line (GetBuffer...) or the memory. (but, maybe not big deal). However, if we use COM or Unicode, we face this kind of problem so often.:(( The string conversion gives us so much headache. X| Have a nice day!
-Masaaki Onishi-
-
The problem I had is that If I used this code: CString MyString; mFile->Read((LPTSTR)(LPCTSTR)MyString, iMyLength); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); When reading the file, the var AnotherStringWhichIsAMemberVarOfTheClass got screwed it's value with what I wanted to read (from the file). Then, by using the Try-All-The-Methods-Of-The-Class solution I noticed that If I wrote: CString MyString; mFile->Read(MyString.GetBuffer(iMyLength), iMyLength); MyString.ReleaseBuffer(); MyString.Replace("something", AnotherStringWhichIsAMemberVarOfTheClass); Everything went right, but I still don't understand why. I'm modifying MyString's content and you've told me that then it'd be better to use GetBuffer(), but contents of AnotherString(...) get screwed when reading the file and before modifying it. Could you tell me why ???? Thanks for everything.
(edited) Alvaro's explanation points to the reason. But note that even the following won't work: CString a = "Ophelia"; CString b = a; // *1* strcpy((LPTSTR)(LPCTSTR) b, "Hamlet"); // *2* will change a and b, because: CString uses a "copy on write" mechanism. At line *1*, b will reference the same string buffer as a. Only when you change one of the strings, an actual copy is made. *2* now modifies the shared string buffer without CString having any chance of knowing it. Hence no copy, hence a shared buffer gets modified. ----------------------- CString doesn't have a cast to LPTSTR for a reason. And blindly casting to LPTSTR is definitely not a good idea. Peter
-
Hi all!! I'm learning C++ and there I'd like somebody to tell me how to properly use the class CString. The problem is that I've a lot of problems with it, when I'm using different CString vars sometimes they screw each others' values. I've noticed that using a property called GetBuffer and ReleaseBuffer, they get fixed. Could somebody tell me the use of that properties and which is the difference between using MyCStringVar.GetBuffer(iBufferLength) and (LPTSTR)(LPCTSTR)MyCStringVar ?? As far as I know they both return a pointer to the string. I know it might be a basic question but if somebody could answer it I'd really appreciate it, thanks.
Read this : http://www.codeproject.com/string/cstringmgmt.asp ---- Xian
-
(edited) Alvaro's explanation points to the reason. But note that even the following won't work: CString a = "Ophelia"; CString b = a; // *1* strcpy((LPTSTR)(LPCTSTR) b, "Hamlet"); // *2* will change a and b, because: CString uses a "copy on write" mechanism. At line *1*, b will reference the same string buffer as a. Only when you change one of the strings, an actual copy is made. *2* now modifies the shared string buffer without CString having any chance of knowing it. Hence no copy, hence a shared buffer gets modified. ----------------------- CString doesn't have a cast to LPTSTR for a reason. And blindly casting to LPTSTR is definitely not a good idea. Peter