【问题标题】:Concatenating strings of different types in C++在 C++ 中连接不同类型的字符串
【发布时间】:2015-06-03 09:42:29
【问题描述】:

如何在 C++ 中连接以下 charTCHAR 变量?

TCHAR fileName[50];

TCHAR prefix[5] = "file_";
TCHAR ext[4] = ".csv";
char *id[10];
generateId(*id);

generateId(char *s) 函数只是生成一个随机字符串。 我需要以fileName 结尾,类似于file_randomIdGoesHere.csv

我尝试过strncat(fileName, prefix, 5);,它适用于所有TCHAR 变量,但不适用于char *,因为它需要const char *,所以也许有更好的方法,不知道如何转换@987654331 @ 或 char **const char *

有什么想法吗?

strncat(fileName, id, 10) 的错误是error: cannot convert 'char**' to 'const char*'

【问题讨论】:

  • 不应该是“char id[10];” (不带星号)?
  • 在我看来,您的代码中应该有类似char id[10]; 而不是char *id[10],然后只需使用generateId(id)。为什么要使用char *id[10] 添加另一个间接级别?
  • 在我的generateId(char *s) 上,如果我删除 *,当我尝试访问 s 数组的每个元素时会出现错误
  • @matt:删除数组中的* 是否可能并且有意义,定义?即只是让它char id[10]?
  • @Mr.C64 是的,从char *id[10];generateId(*id); 中删除* 确实有效,我能够将它与strncat(fileName, id, 10); 连接起来,谢谢!

标签: c++ string char tchar


【解决方案1】:

您看到的错误是因为您的 id 数组被声明为错误的。您声明了一个指针数组而不是一个字符数组。它应该更像这样:

char id[10];
generateId(id);

话虽如此,您还将基于 char 的字符串文字分配给您的 TCHAR 数组,这意味着您没有为 Unicode 编译项目,否则此类分配将无法编译。所以你不妨把TCHAR换成char

char fileName[50] = {0};

char prefix[] = "file_";
char ext[] = ".csv";
char id[10] = {0};

generateId(id);

然后,您应该将strncat() 更改为_snprintf()

_snprintf(filename, 49, "%s%s.cvs", prefix, id);

如果你真的想使用TCHAR,那么你需要将everything更改为TCHAR,并为文字使用TEXT()宏:

TCHAR fileName[50] = {0};

TCHAR prefix[] = TEXT("file_");
TCHAR ext[] = TEXT(".csv");
TCHAR id[10] = {0};

generateId(id);
__sntprintf(filename, 49, TEXT("%s%s.cvs"), prefix, id);

如果您无法将id 更改为TCHAR,那么您将不得不执行运行时转换:

TCHAR fileName[50] = {0};

TCHAR prefix[] = TEXT("file_");
TCHAR ext[] = TEXT(".csv");
char id[10] = {0};

generateId(id);

#ifdef UNICODE
wchar_t id2[10] = {0};
MultiByteToWideChar(CP_ACP, 0, id, -1, id2, 10);
#else
char *id2 = id;
#endif

__sntprintf(filename, 49, TEXT("%s%s.cvs"), prefix, id2);

【讨论】:

  • 将“#else #define id2 id”添加到最后一个#ifdef 会更简洁一些,这样可以完全删除最后一个#ifdef。
  • 但是之后你必须记住#undef id2以避免任何可能的副作用。
  • 好的,你可以把它当作 const TCHAR* id2 = id;而不是定义来保留范围 - 或按照您更改的方式进行操作。
  • "你可以把它当作 const TCHAR* id2 = id;" - 不,你不能,因为在使用id2 的情况下,id2wchar_t[],但idchar[]。这就是 id2 存在的全部原因 - 促进从一种字符类型到另一种类型的数据转换。
  • 嗯?我说的是在 not 定义 UNICODE 时引入 id2,因此 TCHAR 和 char 是相同的(正如您自己指出的那样)。顺便说一句,您当前的代码没有问题。
【解决方案2】:

您应该做的第一件事是,由于您使用的是 C++ 而不是纯 C,因此只需使用 string class 来表示您的字符串并在比原始 C 风格的字符数组方便得多。

在 Windows C++ 编程的上下文中,CString 是一个非常方便的字符串类。
您可以使用其重载的operator+(或+=)以方便、健壮和简单的方式连接字符串。

如果您将 id 存储在 char 字符串(作为 ASCII 字符串)中,如您在问题代码中所示:

char id[10];  
generateId(id);

您可以首先围绕它创建一个 CString(这也将从 char-string 转换为 TCHAR-string,如果您使用 Unicode 构建,尤其是转换为 wchar_t-string,这是自 VS2005 以来的默认设置):

const CString strId(id);

然后,您可以构建整个文件名字符串:

//
// Build file name using this format:
//
//    file_<generatedIdGoesHere>.csv
//
CString filename(_T("file_"));
filename += strId;
filename += _T(".csv");

您也可以使用CString::Format 方法,例如:

CString filename;
filename.Format(_T("file_%s.csv"), strId.GetString());

您可以简单地将 CString 的实例传递给 Win32 API 中的 LPCTSTR 参数,因为 CString 提供了到 LPCTSTR 的隐式转换(即const TCHAR*)。

要使用CString,你可以简单地#include &lt;atlstr.h&gt;

【讨论】:

  • @JorenHeit std::string 无法存储 Win32 API 所需的 UTF-16 字符串。您应该将 UTF-8 字符串存储在 std::string 中,然后在 Win32 API 边界转换为 UTF-16。相反,CString 与 TCHAR 和 wchar_t 都可以正常工作。在这种情况下使用 std::string 会给 OP 的代码带来不必要的复杂性。
  • @Mr.C64 无论如何,你根本不应该使用 TCHAR。我怀疑 CString 是否完全尊重 unicode。
  • @rubenvb:我也同意仅在 Unicode 中构建并使用 wchar_t 等。无论如何,我发布的代码在 Unicode 构建中运行良好,因为 CString 具有从 char-string 转换为 wchar_t 的重载构造函数-细绳。 std::string 没有类似的东西。 (而且CString有方便的从资源中加载字符串的方法,很好地集成在ATL/WTL/MFC等中,在C++应用的Win32层非常棒。)
  • @Mr.C64 我必须承认我没有使用 windows api 或 UTF-16 字符串的经验(从来没有觉得有必要),但据我了解,这是 std::wstring 可以做到的用于。这是正确的还是仍然需要在 API 边界进行转换?
  • @JorenHeit:std::wstring 由 wchar_ts 组成,在 VC++ 上是 16 位单元(而在 Linux 上 wchar_ts 是 32 位单元)。所以,是的,在 VC++ 上,您可以将 wstring 用于 UTF-16。但是,您 不能 简单地从 char-string 初始化 wstring(这在 OP 的代码中很方便,CString 可以做到这一点),而且,由于平台不可知,wstring 不会'没有方便的 Win32 平台特定功能,例如从资源加载字符串等。我认为 CString 在 Win32 API 层很好。然后在代码的其他跨平台部分中,可以使用带有 UTF-8 的 std::string。
【解决方案3】:

首先,将 char 转换为 TCHAR(参见 How to convert char* to TCHAR[ ]?

然后,使用 _tcscat() 连接两个 TCHAR 字符串。

【讨论】:

    【解决方案4】:

    如果你没有使用 UNICODE 字符表。比你的 TCHAR 等同于 char。

    TCHAR prefix[6] = "file_"; //don't forget to allocate space for null terminator '\0'
    TCHAR ext[5] = ".csv"; // size is not 4, remember null terminator
    char id[10] = "random"; // no need to use char* here
    
    std::ostringstream oss;
    oss << prefix << id << ext << std::endl;
    std::cout << oss.str() << std::endl; // gives you file_random.csv as output
    

    【讨论】:

    • 如果您使用定义的UNICODE 进行编译,则TCHAR 映射到wchar_t,而不是char
    猜你喜欢
    • 2021-01-31
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多