在C语言中将字符数组转换为LPCTSTR

12
有人知道如何在c语言中将char数组转换为LPCTSTR吗?
编辑:
更多参考资料,我需要将一个整数添加到一个字符串中,然后将该字符串转换为CreateFile()函数的第一个参数LPCTSTR。
这是我目前正在使用的硬编码示例,但我需要能够传入任何数字作为端口号。
CreateFile(_T("\\\\.\\COM11")... //hardcoded for com port 11

以下是我尝试过的几件事情,我相信这些建议包括了本帖下两个答案的建议。不幸的是它们都不起作用。如果有人能指出我做错了什么并可能解决我的问题,我将不胜感激。

所有这些示例都假定portNum是一个已经分配了有效值的int。

1

char portName[12] = { 0 };

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

CreateFile(portName...

就我所知,我也尝试了使用 LPCSTR 进行 #1(没有什么实际价值)...

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...
8个回答

35

您可以将char数组隐式转换为LPCSTR而不需要任何强制转换:

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

一个 LPCSTR 是 Windows 定义的长指向常量字符串的指针类型。在 Win16 编程的黑暗时代,有不同类型的指针:near 指针和 far 指针,有时也称为短指针和长指针。Near 指针只能指向由 x86 段寄存器确定的 64KB 内存段。Far 指针可以指向任何东西。现在在带有虚拟内存的 Win32 中,不需要 near 指针 — 所有指针都是 long 的。
因此,LPSTR 是指向字符串的指针 char * 的 typedef。一个 LPCSTR 是它的 const 版本,即它是一个指向常量字符的指针 const char * 的 typedef。在 C 语言中,数组会衰变成指向其第一个元素的指针,所以一个 char[] 会衰变成一个 char*。最后,任何类型的 "pointer to T" (对于任何类型 T)都可以隐式转换为 "pointer to const T"。因此,结合这三个事实,我们可以将一个 char[] 隐式转换为一个 LPCSTR

针对您的编辑,我猜测您正在编译一个Unicode应用程序。如果您仔细查看CreateFile()的文档, 您会注意到文件名参数实际上是LPCTSTR,而不是LPCSTR(请注意T)。

对于几乎所有需要某些字符串类型参数(可能是间接的,即作为传递的结构体成员)的Win32函数,实际上有两个版本的该函数:一个使用8位ANSI字符串,另一个使用16位宽字符字符串。要获取实际函数名称,您需要将AW添加到函数名称的末尾。因此,CreateFile()的ANSI版本命名为CreateFileA(),宽字符版本命名为CreateFileW()。根据您是否启用了Unicode(即是否定义了预处理器符号_UNICODE),符号CreateFile将适当地#defineCreateFileACreateFileW,其他每个具有ANSI和宽字符版本的函数也是如此。

同样地,类型 TCHAR 根据是否启用 Unicode 被 typedefcharwchar_t,而 LPCTSTRtypedef 为指向 const TCHAR 的指针。

因此,为了使您的代码正确,您应该使用 TCHAR 字符串替换正在使用的字符串,并使用类型通用版本的 sprintf_s,即 _stprintf_s

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

或者,您可以明确地使用一切的 ANSI 或宽字符版本:

// 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, ...);

不幸的是,这并没有解决我的问题,尽管我添加了一个代码示例来说明我需要完成的内容--您可以在上面查看代码。 - Schuyler
你的代码似乎没有CreateFileA()函数(注意'A')。将CreateFile()替换为这个函数应该可以解决问题。 - Bojan Resnik
转换为 LPCSTR 还是 LPCTSTR?因为如果定义了 UNICODE 符号,LPCTSTR 可以是 wchar_t*。 - Cătălin Pitiș
这个答案对于像我这样刚开始学习Windows编程的人来说非常有帮助。 - Sam Tatasurya

3

你的字符数组是什么格式?

它是一个const char[]还是非常量?

LPCSTR只是微软给"Long Pointer to Constant String"取的有点混淆的名称。

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

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

如果你需要获取一个非const版本,你可以强制转换掉const属性,或者复制到一个新的数组中。我更倾向于后者。变量通常都是const有其原因的,改变它们几乎总是不好的实践。

我非常确定您不必明确地在字符串末尾放置空字符。编译器应该会自动为您完成这个操作。 - Herms
谢谢Herms,是正确的。事实上,我甚至在自己的代码中也不这样做。现在已经修复了。 - Skurmedel
能否告诉我们为什么Foredecker除了结尾的\0之外还有什么问题?仅仅说“这不好”而没有任何解释是没有建设性的。 - Skurmedel
我能想到的唯一不好的地方是它使字符串占用的内存比实际需要的多,因为编译器会在末尾添加一个空字符。 - Herms
它是非常数的——请查看我尝试使用您的示例但失败的编辑。 - Schuyler

2
尝试像这样……
TCHAR *pcCommPort = TEXT("COM1");
HANDLE h = CreateFile(pcCommPort,other arguments);

2
char* filename;
LPCTSTR ime = CA2W(filename);

这是字符串转换宏,可以在我的VS12上使用。

1

对于TCHAR,您可以使用字符串函数。例如,您可以使用接受TCHAR的stprintf_s。这样,您可以使代码“独立”于Unicode或多字节字符集。

您的代码(变体1)变为:

TCHAR portName[12] = { 0 };

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

CreateFile(portName...

"sizeof( portName )," -- 哎呀。你的回答几乎教会了提问者如何使用TCHARs,但一个缓冲区溢出可能会毁掉你整天的工作。 - Windows programmer
1
sizeof(portName) / sizeof(TCHAR) - Windows programmer

0

我不确定你最终是否解决了问题,但我遇到了同样的问题,以下方法对我很有效:

int  comPortNum = 5;
char comPortName[32];
sprintf((LPTSTR)comPortName, TEXT("\\\\.\\COM%d"), comPortNum);
HANDLE h = CreateFile(comPortName,other arguments);

0

有人知道如何在C语言中将字符数组转换为LPCSTR吗?

你其实不需要做任何操作,它会自动转换成那种类型(除了在初始化和sizeof时)。

"CreateFile(portName..."

也许您应该告诉我们VC ++在编译时给您的错误消息是什么?
也许您还应该告诉我们,当Adam Rosenfield的whcar_t版本无法为您工作时,VC ++给您了什么错误消息?

0

这是一个经典的老问题。我在UNICODE中使用它。

char *pChar = "My Caption of My application";
    WCHAR wsz[512];
    swprintf(wsz, L"%S", pChar);
    SetWindowText(hWnd,         // ウィンドウまたはコントロールのハンドル
        wsz   // タイトルまたはテキスト
    );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接