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.
dvplayltdAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

sarabandeCommented:
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


0
sarabandeCommented:
so you can omit the variable sInfo and call

StradisLogFunction(s);

where s is the CString.

Sara
0
sarabandeCommented:
the code

s="Software\\temp\\"  + LongExample + LPCTSTR_Example + bool_example + qwFrameOffset ;

is wrong.

"Software\\temp\\" is a const char* . you always should add TCHAR* by
s=_T("Software\\temp\\");

the term "Software\\temp\\"  + LongExample would add the integer LongExample to the pointer value (address) of the const char *. you can add values to a CString but not concatenate pointers and c types. also the integer must be converted to string before concatenate.

CString sn;
sn.Format(_T("%d"), LongExample);
s=CString(_T("Software\\temp\\")) + sn;

Open in new window


same way you would concatenate the other values and finally pass the CString to the StradisLogFunction.

Sara
 
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

dvplayltdAuthor Commented:
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
0
dvplayltdAuthor Commented:
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
0
sarabandeCommented:
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
0
sarabandeCommented:
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
0
sarabandeCommented:
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
0
dvplayltdAuthor Commented:
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);
0
dvplayltdAuthor Commented:
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?
0
sarabandeCommented:
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
0
sarabandeCommented:
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

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.