Link to home
Start Free TrialLog in
Avatar of dvplayltd
dvplayltdFlag for Bulgaria

asked on

Convert values to LPCTSTR with C++

Hi experts!

I’m new on MS C++ 2008, so I have a probably very easy to you question, but for me, string operation in C are really amful, no matter my 10+ experience in proffesional programming. Look my code:

      LPCTSTR sInfo; CString s;  
      long LongExample=20;LPCTSTR LPCTSTR_Example="newValue"; bool bool_example=true; __int64 qwFrameOffset = 232;
      s="Software\\temp\\"  + LongExample + LPCTSTR_Example + bool_example + qwFrameOffset ; // here I should join all values in a valiable - this
      sInfo= s;
      StradisLogFunction(sInfo);
    s="newvalue with new params";
    sInfo= s;
      StradisLogFunction(sInfo);

I need to make in a LPCTSTR a couple of params and to save it with StradisLogFunction(sInfo); which accept LPCTSTR. Could you please send me example code how to convert and add othet data types to a LPCTSTR values? If a idea to make all in CString and later to convert it to LPCTSTR is not good, please offer other. It should be able to do this many times in a procedure as I show in my code.

Note that my project is unicode. As this is simple task I do not intend to include additional libraries.
Avatar of sarabande
sarabande
Flag of Luxembourg image

the LPCTSTR translates to const TCHAR * and when using UNICODE then TCHAR is wchar_t. so you finally have const wchar_t * what is a pointer to the first wide character - actually UTF-16 - of a wchar_t array. the wchar_t array is terminated by a zero wide character which has code 0.

A CString in MFC is a string class object which has internally a TCHAR* or LPTSTR what is a non-const pointer to first element of a wchar_t array. it additional has two size parameters, one is the "string length", what means the number of characters without terminating zero and one is the allocated length, that means the number of allocated elements in memory which is at least 1 character more thna the length in order to take the terminating zero character. you can get a const pointer to the
internal buffer by doing a "cast"on the CString variable:

CString str = _T("abc");
LPCTSTR ptr = (LPCTSTR)str;

Open in new window


that works cause the CString class has an operator LPCTSTR implemented which simply returns a const pointer to its own internal array.

the problem with a LPCTSTR is that it is const. that means you cannot manipulate the string (without turning it to non-const). so a LPCTSTR from a CString is only used for input to other functions which don't need to write to the string. because of the - implicit working - cast operator you can pass a CString variable wherever a LPCTSTR is required.

CString str = _T("abc");
LPTSTR ptr = new TCHAR[str.GetLength()+1];
strcpy(ptr, str);

Open in new window


if you need to manipulate the string (value) you best do that with the CString and not with the pointer.

CString str = _T("abc");
str += _T("xyz");

Open in new window


what is much more comfortable and simple.

nevertheless CString also offers a writeable access to its internal buffer by means of the member function GetBuffer which returns a TCHAR* or LPTSTR.

you would use that when you have to use an interface which requires a non-const TCHAR* . it nevertheless should not resize the buffer nor delete the pointer. you have to call CString::ReleaseBuffer after each manipulation.

Sara


so you can omit the variable sInfo and call

StradisLogFunction(s);

where s is the CString.

Sara
ASKER CERTIFIED SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dvplayltd

ASKER

To Sara

Welcome again:-)

Ok - I will use directly CString - it is OK, I tested.
So you tell me that after I finish with CString s I should call s.ReleaseBuffer(); Is that correct? After code exit from procedure this will be call automatically or not?

And you do not answer me on primary question. Give me example please how to add to a CSting a value from different  data types. Look bellow - this produce error, I need code which join all values in a CString . Not a problem to transfer true and false to 0 or 1, this values are for debug needs and human will understand it.

      long LongExample=20;LPCTSTR LPCTSTR_Example="newValue"; bool bool_example=true; __int64 qwFrameOffset = 232;
      s="Software\\temp\\"  + LongExample + LPCTSTR_Example + bool_example + qwFrameOffset ; // here I should join all values in a valiable
Sara

Fine, it is worked. So I wait 2 small answer from you:
 1. Should I call CString s
                     s.ReleaseBuffer();

after I finish work with the valiable?

2.The function StradisLog write the a text file.  I test it, work with your example, but write all on same text line. How to add a new line charter to the end of row:

s=CString(_T("Software\\temp\\")) + sn + _T('\n');  // please correct syntacs
the ReleaseBuffer only needs to be called after a GetBuffer.

CString str = _T("abc");
// get a writeable pointer to a buffer of 20 characters
LPTSTR ptr = str.GetBuffer(20);  
wcscat(ptr, L"xyz");
str.ReleaseBuffer();

Open in new window

 

with the GetBuffer the internal buffer was resized to at least 20 characters. with the ReleaseBuffer the internal length was adjusted by looking for a terminating zero. in the sample the new length would be 6.

ReleaseBuffer rarely is necessary. you only would do it if you have to pass a wchar_t buffer of a reuired size to a function which fills that buffer and you wanted to have a proper CString from that finally.

Sara
Sara
yes your adding of a '\n' should work cause CString has an operator+ which takes a single wchar_t.

because of that the sn + _T('\n') would concatenate those operands to a new temporary CString.

so it works here cause the left operand is a CString. if you want it to work for every left operand or even if the the linefeed is the only operand simply make a CString(_T("\n"); such that the concatenation has to concatenate CString variables only.

Sara
note, _T('\n') is a single wchar_t while _T("\n") is a const wchar_t* (or LPCTSTR or LPCWSTR). you can add both to another CString and the result is the same.

Sara
10x. Used you answer I get the shorter code, here you are:

       CString sn; CString s;

       s.Format( _T( "StradisDecoder_File_Init(%s) complate with result (%d) \n" ), sInitFile, iRes);

       StradisLogFunction(s);
To Sara

If you read this, please comment. Is it bad idea to declare a variable in If operator? With sure I'll use it in If only
This is my code:

         if (mbWriteAllCmd[lCard])
      {
       CString sLog;
       sLog.Format( _T( "StradisDecoder_File_GetPlayMode() result (%d) \n" ),  lRes);
       StradisLogFunction(sLog);
      }

P.S: For bool values I should use %d, correct?
yes that works but you should be cautious with the Format function. like printf the variable arguments passed are not type-safe. if your format doesn't fit to the arguments you can cause very bad errors. also it is a potential  "door" for malicious code to inject into your program.

a more c++ way is to using stringstreams, in your case wostringstream. it is lke

wostringstream wos;
wos << L"StradisDecoder_File_Init(" << (LPCWSTR)sInitFile 
        << L") complate with result (" << iRes << L") " << std::endl;
StradisLogFunction(wos.str().c_str());

Open in new window



Sara
declaring temporaries in if block is fine. the only exception with local variables would be if the log function would run asynchronously. if that is the case (rarely) you need to pass a string which would not be destroyed when leaving the if block. you then need a static variable or member variable which lives at least as long as the call would need the buffer to write to logfile.

but don't be afraid. your log function surely is not asynchronous as that is an important information which would have been mentioned by the docs.

i don't know how to print bools. i probably would use a temporary like

CString sboolval = boolval? _T("true") : _T("false");

Open in new window


though the right term cannot be used everywhere cause it might prevent from automatic casting.

Sara