Char *组合

时间:2014-08-22 11:03:04

标签: c++ char

我更喜欢char*而不是std::string,所以我写了一个组合char指针的函数。我创建了一个新项目并进行了测试。它工作正常。但是当我尝试在一个更大的GUI项目中使用它时,我的程序崩溃了。

这是一个示例(工作)代码:

#include <Windows.h>
#include <vector>

char *StringJoin(const char *String, const char* ...)
{
    va_list ArgList;
    va_start(ArgList, String);
    std::vector<const char *> StringData;
    std::vector<unsigned int> StringLen;
    StringData.push_back(String);
    unsigned int SingleLength = strlen(String);
    StringLen.push_back(SingleLength);
    unsigned int TotalLength = SingleLength;
    while (1)
    {
        const char* Val = va_arg(ArgList, const char*);
        if (!Val)
            break;
        StringData.push_back(Val);
        SingleLength = strlen(Val);
        StringLen.push_back(SingleLength); // In larger projects it crashes here
        TotalLength += SingleLength;
    }
    va_end(ArgList);
    char *NewString = new char[TotalLength + 1];
    unsigned int VectorSize = StringData.size();
    unsigned int NewLength = 0;
    for (unsigned int Element = 0; Element < VectorSize; Element++)
    {
        memcpy(NewString + NewLength, StringData[Element], StringLen[Element]);
        NewLength += StringLen[Element];
    }
    NewString[TotalLength] = '\0';
    StringData.clear();
    StringLen.clear();
    return NewString;
}

int main(void)
{
    char* New = StringJoin("Does ", "it ", "works ", "for ", "you ", "?");
    printf("%s\n", New);
    system("PAUSE");
    return 1;
}

我的代码安全稳定吗?

2 个答案:

答案 0 :(得分:2)

您无法使用!Val条件:

const char* Val = va_arg(ArgList, const char*);
if (!Val)
    break;

使用变量参数列表时,您需要知道完全已传递了多少参数,或者(更新)何时停止处理参数,例如使用NULL / nullptr(或任何其他)sentinel.

答案 1 :(得分:0)

如果你的编译器支持它,你肯定应该使用可变参数模板。

以下非常简单的函数接受任意数量的字符串并在循环中连接它。它支持std::stringchar*参数(甚至是混合):

template<class ...Strings>
std::string StringJoin(Strings ...strings) {
    std::string joined;
    for (auto s : { strings... })
        joined += s;
    return joined;
}

Live Demo

现在,如果您希望结果为char*,则需要考虑分配内存的位置以及解除分配的位置,即您需要手动管理内存。除非你使用智能指针:

template<class ...Strings>
std::unique_ptr<char[]> StringJoin(Strings ...strings) {
    std::string joined;
    for (auto s : { strings... })
        joined += s;

    std::unique_ptr<char[]> buf(new char[joined.size() + 1]);
    memcpy(buf.get(), joined.data(), joined.size());
    buf[joined.size()] = '\0';
    return buf;
}

Live Demo