【问题标题】:Concatenating LPTSTR with const char* (Win32 C++)连接 LPTSTR 与 const char* (Win32 C++)
【发布时间】:2016-05-12 18:42:37
【问题描述】:

我希望能够在我的 Win32 应用程序中打开文件。 我正在使用的方法是从编辑框中检索根路径,例如“C:\MyFolder”(分配给strPathToSource)。然后我想附加另一个字符串,例如"\source\Utilities\File.h" 并将连接的路径存储在新变量strPathToFile中。

所以strPathToFile 应该包含“C:\MyFolder\source\Utilities\File.h”,然后可以使用infile.open(strPathToFile) 打开。

相关代码如下:

ifstream infile;

int bufSize = 1024;
LPTSTR strPathToSource = new TCHAR[bufSize];
GetDlgItemText(hWnd, IDC_MAIN_EDIT_FILEPATH, strPathToSource, bufSize); // Get text from edit box and assign to strPathToSource

const char* strPathToFile = char(strPathToSource) + PATH_TO_FILE;
infile.open(strPathToFile);
if(!infile)
{
    log(hWnd, "File.h not found.");
    return false;
}

其中PATH_TO_FILE定义为:

const char* PATH_TO_FILE = "\\source\\Utilities\\File.h";

我的问题是它总是注销“File.h not found”。我认为问题在于连接,例如

const char* strPathToFile = char(strPathToSource) + PATH_TO_FILE;

我可以看到strPathToSourcePATH_TO_FILE 的值是它们应该的值,但是strPathToFile 中的连接结果我相信是一个NULL 值。

【问题讨论】:

  • 不要使用+ 连接指针,也不要将const char *LPTSTR 混合使用,因为它们是不同的类型。换句话说,您的代码存在两个(或更多)问题,这些问题都不相关,但都可能导致问题。
  • 还有——从不强制转换字符串类型。如果编译器抱怨指针不兼容,请not 抛弃该错误。使用正确的字符串类型。
  • 在 Windows 上,最好不要使用 std::ifstream。由于缺少构造函数,它被设计破坏了,采用了一个宽字符串。如果您仍想在 Windows 上使用 std::ifstream,请考虑使用 Microsoft 的扩展,它提供了一个接受宽字符串的 basic_ifstream c'tor

标签: c++ file winapi editbox lptstr


【解决方案1】:

添加两个字符指针不会连接字符串,它只是添加两个指针值(作为“数字”)。所以你最终得到了一个无效的指针。

此外,从 LPTSTR 类型转换为 char* 也不是一个好主意,因为 TCHAR 也可以是宽字符,具体取决于当前的构建设置。 (实际上,您将 LPTSTR 转换为 char,而不是指针,这更错误)

我认为最简单的方法是将两个字符串都转换为 std::string(或 wstring),您可以使用 '+' 运算符进行连接。

这样做的一种可能性:

const std::wstring strPathToFile = cvt2wstring(strPathToSource) + cvt2wstring(PATH_TO_FILE);

cvt2wstring 定义为:

#include <codecvt>
#include <string>

std::wstring cvt2wstring(const char * str)
{
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
    return converter.from_bytes(str);
}

std::wstring cvt2wstring(const wchar_t * str)
{
    return str;
}

根据实际类型,选择合适的重载。

对于到 std::string 的相反转换(以便您可以使用常规的 std::ifstream),您可以切换方向:

std::string cvt2string(const char * str)
{
    return str;
}

std::string cvt2string(const wchar_t * str)
{
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
    return converter.to_bytes(str);
}

对我来说,ifstream::open() 似乎可以与 wstring 一起使用(但它可能是 MSVC 扩展,因为 C++ 标准没有提供该扩展 - 无论如何,如果您使用 TCHAR 和 comp。您可能针对 Windows 和 MSVC)。

【讨论】:

  • 如果你打算使用 TCHAR(我不会。选择一个并坚持使用它 - 现在可能是 wchar_t),我强烈建议定义一个 typedef tstring,即 std::basic_string&lt;TCHAR&gt;。这样你就不必到处都有 ifdef。
  • 感谢您的回答。能否请您写下如何将两者都转换为 std::string 或 wstring?
  • 请注意,代码的另一个问题是std::ifstream 只接受基于char 的字符串。这也需要类型定义为std::ifstreamstd::wifstream,具体取决于构建类型。您应该在回答中提及这一点。
  • 感谢您扩展您的答案。我的编译器似乎无法使用 codecvt(我使用的是 VS2008)。如果您知道这些转换功能的解决方法,那就太好了!我现在接受答案。
  • 您也可以使用 mbstowcs() 将 char* 转换为 wstring,如下所述:stackoverflow.com/a/2573845/1274747
【解决方案2】:

Martin Bonner 基本上给出了正确的答案。

简而言之,最好的解决方案是完全忽略TCHAR。这是一个可以追溯到上个世纪最后十年的拐杖,当时 Unicode 对具有 4 MB RAM 的 PC 来说是个问题。今天 4 GB 很常见,是现在的一千倍。

但是,如果您还想生活在那个时代,请保持一致。不要定义

const char* PATH_TO_FILE = "\\source\\Utilities\\File.h";

但使用

const TCHAR * PATH_TO_FILE = _T("\\source\\Utilities\\File.h");

另外,学习使用字符串连接。您可以使用std::basic_string&lt;TCHAR&gt;::operator+(简单)或tcscat(习惯于缓冲区溢出)。

【讨论】:

    猜你喜欢
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多