【问题标题】:Appending a constant cstring to my own String class object将常量 cstring 附加到我自己的 String 类对象
【发布时间】:2014-03-22 18:06:30
【问题描述】:

我正在编写自己的 String 类,但 append 函数有问题。它将一个常量 cstring 作为参数,并将其附加到调用它的 String 的末尾。

函数的原型如下:

void append(char *str );

预期工作:

String s1("John");

s1.append(" Doe");

s1.display();

结果应该是:

John Doe

我得到了什么?

John

我在做什么?

  • char * data 是我的 String 类的数据成员。

    1. data 的内容复制到 temp

    2. 重新声明 data 的大小等于 temp+CStringToBeAppended+1

    3. 现在,将 temp 的内容复制到新的 data 中。

    4. CStringToBeAppended的内容复制到新的data中,从strlen(temp)的位置开始。

这是我目前拥有的功能:

//char * data is the data member of my String class.

void append(char* str)
{

    char *temp = new char[strlen(data)+1];

    for (int i=0; data[i] != '\0'; i++)
        temp[i] = data[i];

    len = strlen(temp) + strlen(str);

    data = new char [len+1];

    for (int i=0; temp[i] != '\0'; i++)
        data[i] = temp[i];

    for (int i=strlen(temp); str[i] != '\0'; i++)
        data[i] = str[i];


    delete [] temp;
}

【问题讨论】:

  • 展示你是如何为班级中的数据分配内存的?
  • 它在那里:len = strlen(temp) + strlen(str);数据 = 新字符 [len+1];
  • 您的第一次分配毫无意义。附注:该参数应该是const char *,而不是char *
  • 为什么是 temp,为什么不分配 strlen(data) + strlen(str) + 1 并将该指针与数据交换,为什么内存泄漏?
  • @WhozCraig:临时指针在函数内部的范围受到限制。你写的是const char *

标签: c++ string class append


【解决方案1】:

我做了一些改动

  1. Null 复制数据后终止 temp
  2. 使用变量j 作为data 中的起点。用 strlen(temp) 分配 j
  3. data 的开始定位被替换为来自ij++
void stringx::appendx(char* str)
{
    int x = strlen(data);
    char *temp = new char[strlen(data)+1];

    int i;
    for ( i=0; data[i] != '\0'; i++)
        temp[i] = data[i];
    temp[i] = '\0';                             //<----Change 1

    len = strlen(temp) + strlen(str);

    data = new char [len+1];
    memset(data,0,strlen(data)+1);

    for (int i=0; temp[i] != '\0'; i++)
        data[i] = temp[i];

    int j=strlen(temp);                        //<----Change 2
    for (int i=0; str[i] != '\0'; i++)
        data[j++] = str[i];                    //<----Change 3


    delete [] temp;
}

【讨论】:

  • 仅供参考,这完全泄露了原始 data 内存分配,并且 仍然 制作了原始 data 字符串的不需要的副本。
  • @WhozCraig,是的,没错。他必须在重新分配任何东西之前删除。是的,我同意不需要临时复制..
【解决方案2】:

您的代码对传入的数据字符串进行了不必要的复制,并通过复制终止逻辑进一步增强。这就是你想要做的。

假设data 为空并且正确地以 0 结尾:

void append(const char *str)
{
    if (!(str && *str))
        return;

    char *final = new char[ strlen(str) + strlen(data) + 1 ], *dst = final;

    // copy in lhs
    const char *src = data;
    while (*src)
        *dst++ = *src++;

    // copy in rhs
    while (*str)
        *dst++ = *str++;
    *dst = 0;

    // swap pointers
    std::swap(data, final);

    // throw out prior result
    delete [] final;
}

您可以通过为您的data 成员 (data_len) 的分配大小保留一个单独的成员来使此操作相当更有效。使用std::copy()memcpy 移动数据更是如此,因为您已经知道长度。否则,您的附加信息只不过是Schlemiel the Painter 穿着华丽的课程。使用std::copy() 的修改版本如下。我将管理data_len 成员与data 留给你

void append(const char *str)
{
    if (!(str && *str))
        return;

    size_t dlen = strlen(data);
    size_t slen = strlen(str);      
    char *final = new char[ dlen + slen + 1 ];

    std::copy(data, data+dlen, final);
    std::copy(str, str+slen+1, final+dlen);
    std::swap(data,final);
    delete [] final;
}

【讨论】:

  • 你的逻辑对我来说简直太棒了。我很想投票,但我现在不能。实际上,我想接受这两个答案,但至于另一个答案,我现在接受它并从现在开始采用指针工作。谢谢
  • @FaizanSaleem Sok,不用担心,但如果您采用其他答案,您可能想要修复它的内存泄漏(除非作者修复了它,截至本文尚未发生)。您的原始代码中也存在相同的泄漏。
猜你喜欢
  • 1970-01-01
  • 2012-11-23
  • 1970-01-01
  • 2011-09-12
  • 2018-06-25
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多