?
Solved

Convert values to LPCTSTR with C++

Posted on 2011-10-06
12
Medium Priority
?
1,550 Views
Last Modified: 2012-05-12
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.
0
Comment
Question by:dvplayltd
  • 8
  • 4
12 Comments
 
LVL 35

Expert Comment

by:sarabande
ID: 36929100
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
 
LVL 35

Expert Comment

by:sarabande
ID: 36929106
so you can omit the variable sInfo and call

StradisLogFunction(s);

where s is the CString.

Sara
0
 
LVL 35

Accepted Solution

by:
sarabande earned 2000 total points
ID: 36929165
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:dvplayltd
ID: 36929190
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
 

Author Comment

by:dvplayltd
ID: 36929220
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
 
LVL 35

Expert Comment

by:sarabande
ID: 36929290
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
 
LVL 35

Expert Comment

by:sarabande
ID: 36929420
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
 
LVL 35

Expert Comment

by:sarabande
ID: 36929465
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
 

Author Closing Comment

by:dvplayltd
ID: 36929630
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
 

Author Comment

by:dvplayltd
ID: 36929659
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
 
LVL 35

Expert Comment

by:sarabande
ID: 36929672
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
 
LVL 35

Expert Comment

by:sarabande
ID: 36929767
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

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

580 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question