views:

4133

answers:

4

Does anyone know how to convert a char array to a LPCTSTR in c?

Edit:

For more reference, I need to add an integer to a string then convert that string to LPCTSTR for the first parameter of the windows function CreateFile().

This is the hardcoded example which I am currently using, but I need to be able to pass in any number to use as a port number.

CreateFile(_T("\\\\.\\COM11")... //hardcoded for com port 11

and here are several things I have tried, which I believe include the following suggestions for the next 2 answers of this post. They don't work unfortunately. If anyone could point out something I've done wrong and could possibly solve my problem, I'd appreciate it.

All of these examples assume that portNum is an int that is already assigned a valid value

1

char portName[12] = { 0 };

sprintf_s( portName, sizeof( portName ), "\\\\.\\COM%i", portNum );

CreateFile(portName...

I've also tried #1 with a LPCSTR case for what it's worth...

2

LPCSTR SomeFunction(LPCSTR aString) {
    return aString;
}

main() {

char portName[12] = { 0 };
sprintf_s( portName, sizeof( portName ), "\\\\.\\COM%i", portNum );

LPCSTR lpPortName = SomeFunction(portName);

CreateFile(lpPortName...

3

const char * portName = "";
sprintf_s( portName, sizeof( portName ), "\\\\.\\COM%i", portNum );

LPCSTR lpPortName = portName;

CreateFile(lpPortName...
+3  A: 

In what format is your char array?

Is it a const char[] or a non-const?

LPCSTR is just the (somewhat) confusing Microsoft name for "Long Pointer to Constant String".

LPCSTR bar = "hello";
const char *foo = bar;

const char *evil = "hello";
LPCSTR sauron = evil;

If you need to get a non-const version, you either cast away the constness, or you copy to a new array. I would probably prefer the latter. Variables are often const for a reason, and changing them is almost always bad practice.

Skurmedel
I'm pretty sure you don't have to explicitly put the null character at the end of the string. The compiler should do that for you automatically.
Herms
Right - the code example is not good practice.
Foredecker
Thanks Herms, it is correct. In fact I don't even do that in my own code. Fixed now.
Skurmedel
Care to tell us why Foredecker, except the \0 on the end? Just saying "this is not good" without no explanation is not constructive.
Skurmedel
The only bad thing I can think of is that it makes the strings take more memory than they need to, as the compiler will stick a null character at the end.
Herms
Yeah. That I do realize :)
Skurmedel
It is nonconstant--view the edit above of how I tried to use your example and failed.
+14  A: 

You can implicitly convert a char array to an LPCSTR without any casts:

void SomeFunction(LPCSTR aString);
...
char myArray[] = "hello, world!";
SomeFunction(myArray);

An LPCSTR is a Windows typedef for a long pointer to a constant string. Back in the dark days of Win16 programming, there were different types of pointers: near pointers and far pointers, sometimes also known as short and long pointers respectively. Near pointers could only point to a 64KB segment of memory determined by one of the x86 segment registers. Far pointers could point to anything. Nowadays in Win32 with virtual memory, there is no need for near pointers -- all pointers are long.

So, an LPSTR is a typedef for a char *, or pointer to a string. An LPCSTR is the const version, i.e. it is a typedef for a const char *. In C, arrays decay into pointers to their first elements, so a char[] decays into a char*. Finally, any type of "pointer to T" (for any type T) can be implicitly converted into a "pointer to const T". Thus, combining these three facts, we see that we can implicitly convert a char[] into an LPCSTR.


In response to your edit, I'm going to guess that you're compiling a Unicode application. If you look carefully at the documentation for CreateFile(), you'll notice that the filename parameter is actually an LPCTSTR, not an LPCSTR (note the T).

For pretty much every Win32 function that takes an argument of some string type (perhaps indirectly, i.e. as a member of a structure passed as a parameter), there are actually two versions of that function: one which takes 8-bit ANSI strings, and one which takes 16-bit wide-character strings. To get the actual function names, you append an A or a W to the function name. So, the ANSI version of CreateFile() is named CreateFileA(), and the wide-character version is named CreateFileW(). Depending on whether or not you're compiling with Unicode enabled (i.e. whether the preprocessor symbol _UNICODE is defined), the symbol CreateFile is #defined to either CreateFileA or CreateFileW as appropriate, and likewise for every other function that has an ANSI and a wide-character version.

Along the same lines, the type TCHAR is typedefed to either char or wchar_t, depending on whether Unicode is enabled, and LPCTSTR is typedefed to a pointer to a const TCHAR.

Thus, to make your code correct, you should replace the strings you're using with TCHAR strings, and use the type-generic version of sprintf_s, _stprintf_s:

TCHAR portName[32];
_stprintf_s(portName, sizeof(portName)/sizeof(TCHAR), _T("\\\\.\\COM%d"), portNum);
CreateFile(portName, ...);

Alternatively, you can explicitly use the ANSI or wide-character versions of everything:

// Use ANSI
char portName[32];
sprintf_s(portName, sizeof(portName), "\\\\.\\COM%d", portNum);
CreateFileA(portName, ...);

// Use wide-characters
wchar_t portName[32];
swprintf_s(portName, sizeof(portName)/sizeof(wchar_t), L"\\\\.\\COM%d", portNum);
CreateFileW(portName, ...);
Adam Rosenfield
This is the right answer. Schuyler, you should mark this one as accepted.
Foredecker
This unfortunately hasn't solved my problem, though I added a code example of what I need done--you can view the code above.
@SchylerYou don't seem to have CreateFileA() (note the 'A') in your code. Change CreateFile() to this and it should work.
Bojan Resnik
Conversion to LPCSTR or LPCTSTR? Because LPCTSTR can be wchar_t* if UNICODE symbol is defined.
Cătălin Pitiș
A: 

"Does anyone know how to convert a char array to a LPCSTR in c?"

You don't have to do anything at all. It automatically converts to that type (except in initializers and sizeof).

"CreateFile(portName..."

Perhaps you should tell us the error message that VC++ gives you at compile time?

Perhaps you should also tell us what error message VC++ gave you when Adam Rosenfield's whcar_t version didn't work for you?

Windows programmer
+1  A: 

You have string functions for TCHAR. You can use, for example, stprintf_s accepting TCHAR. This way, you make the code "independent" of unicode or multi-byte character set.

Your code (variant 1) becomes:

TCHAR portName[12] = { 0 };

stprintf_s( portName, sizeof( portName ) / sizeof(TCHAR), _T("\\\\.\\COM%i"), portNum );

CreateFile(portName...
Cătălin Pitiș
"sizeof( portName )," -- Oops. Your answer almost taught the poster how to use TCHARs, but one buffer overflow can ruin your whole day.
Windows programmer
sizeof( portName ) / sizeof( TCHAR )
Windows programmer
Oops, you're right. My mistake.
Cătălin Pitiș