C ++的基本自定义字符串类

时间:2010-04-09 16:41:34

标签: c++ string class object

编辑:我不想删除这篇文章,因为我很快就从中学到了很多东西,并且可能会让其他人感觉良好,但是没有其他人花时间回答或查看这个问题。这些问题出现在我的编程基础中,而这些问题在快速响应中无法解决。对于所有发帖的人,感谢您的帮助,非常谦卑!

嘿所有,我正在构建具有非常基本功能的自己的字符串类。我很难理解我所定义的基本类正在发生什么,并且相信在处理范围时会出现某种错误。当我尝试查看我创建的对象时,所有字段都被描述为(显然是错误的指针)。此外,如果我公开数据字段或构建一个访问器方法,程序崩溃。由于某种原因,对象的指针是0xccccccccc,它指向no where 我怎么能解决这个问题?非常感谢任何帮助/评论。

    //This is a custom string class, so far the only functions are 
    //constructing and appending

#include<iostream>
using namespace std;

class MyString1
{
public:
    MyString1()     
    {   

        //no arg constructor
        char *string;
        string = new char[0];
        string[0] ='\0';
        std::cout << string;
        size = 1;
    }
    //constructor receives pointer to character array
    MyString1(char* chars)
    {
        int index = 0;
        //Determine the length of the array
        while (chars[index] != NULL)
            index++;
        //Allocate dynamic memory on the heap
        char *string;
        string = new char[index+1];
        //Copy the contents of the array pointed by chars into string, the char array of the object
        for (int ii = 0; ii < index; ii++)
            string[ii] = chars[ii];
        string[index+1] = '\0';
        size = index+1;
    }
    MyString1 append(MyString1 s)
    { 
        //determine new size of the appended array and allocate memory
        int newsize = s.size + size;
        MyString1 MyString2;
        char *newstring;
        newstring = new char[newsize+1];

        int index = 0;
        //load the first string into the array
        for (int ii = 0; ii < size; ii++)
        {
            newstring[ii] = string[ii];
            index++;
        }

        for(int jj = 0; jj < s.size; jj++, ii++)
        {
            newstring[ii] = s.string[jj++];
            index++;
        }
        //null terminate
        newstring[newsize+1] = '\0';

        delete string;
        //generate the object for return
        MyString2.string=newstring;
        MyString2.size=newsize;

        return MyString2;
    }
private:
    char *string;
    int size;
};



int main()
{
    MyString1 string1;
    MyString1 string2("Hello There");
    MyString1 string3("Buddy");
    string2.append(string3);
    return 0;
}

编辑: 到目前为止,感谢大家回应并处理我对此主题缺乏了解的问题。我将开始处理所有的答案,但再次感谢您的回复,对不起,我的问题很模糊,但实际上没有特定的错误,但更多的是缺乏对数组和类的理解。

3 个答案:

答案 0 :(得分:3)

这只是第一个构造函数的错误。

    MyString1()     
    {   

//no arg constructor
        char *string;         //defines local variable that hides the member by that name
        string = new char[0]; //sort of meaningless
        string[0] ='\0';      //not enough room for that (out-of-bounds)
        std::cout << string;
        size = 1;             //I don't think you should count null as part of the string
    }

其他地方也有类似的错误。

此外,您应该更仔细地传递参数。

MyString1(const char* source); //note const

MyString1 append(const MyString1& what); //note const and reference

如果后者是正确的,还取决于它应该做什么。基于std::string,预期结果将是:

MyString1 a("Hello "), b("world");
a.append(b);
assert(a == "Hello world");

答案 1 :(得分:2)

对您的代码的一些评论:

    MyString1()     
    {   

//no arg constructor

也许你的指示需要它,但总的来说这是一种比无用更糟糕的评论。从第一眼看代码时,评论应该告诉读者不是的事情。

        char *string;
        string = new char[0];
        string[0] ='\0';

这会调用未定义的行为。允许使用零元素调用new,但是您不能取消引用它返回的内容(它可能返回空指针,或者它可能返回不引用任何存储的非空指针)。在大多数情况下,最好只将指针设置为NULL。

        std::cout << string;

写出空字符串有什么意义?

        size = 1;

字符串为空,因此通过正常计算,大小为零。

//constructor receives pointer to character array

仍然没用。

    MyString1(char* chars)

由于您没有(或者不应该)计划修改输入数据,因此该参数应为char const *

    {
        int index = 0;
//Determine the length of the array
        while (chars[index] != NULL)
            index++;

虽然这有效,但“NULL”应该保留用作指针,至少是IMO。我写的是:

while (chars[index] != '\0')
    ++index;

除非您使用之前的值,否则更喜欢预增量到后增量。

//Allocate dynamic memory on the heap

与在堆上分配静态内存相反?

    MyString1 MyString2;

对类型和变量使用相同的命名约定令人困惑。

    while (string[index] != NULL)

以前适用于NULL的相同评论。

MyString1 append(MyString1 s)

IMO,这个函数的整个想法是完全错误的 - 如果你有一个字符串,并要求它在你的字符串中添加一些内容,它销毁你的原始字符串,并且(更糟)使它处于不可用的状态 - 当你开始添加一个释放字符串所拥有的内存的析构函数时,它将导致双重删除字符串的存储,该字符串是{{受害者?)的{{ 1}}呼吁它。

我会考虑编写一个私有的“复制”功能,并在你在这里展示的一些(大多数?)的实现中使用它。

作为一个更一般的建议,我会考虑更多的可能性:首先,我不会总是精确分配字符串所需的空间量,而是考虑将分配四舍五入到(例如)a两个人的力量。其次,如果您希望字符串类能够正常工作,您可以考虑实现“短字符串优化”。这包括在字符串对象本身的主体中为短字符串(例如20个字符)分配空间。由于许多字符串往往相对较短,因此如果字符串很短,可以通过避免执行堆分配来显着提高速度(并减少堆碎片等)。

答案 2 :(得分:1)

index在追加函数的第二个while循环中不会从0开始。您可能应该使用for循环。哦,你正在使用错误的delete形式。您应该使用delete[] string,因为string是一个数组。

还有很多其他风格问题和彻头彻尾的错误,但我首先提到的是您遇到的基本错误。

我会用这种方式编写append函数:

void append(MyString1 s)
{ 
           //determine new size of the appended array and allocate memory
    int newsize = s.size + size;
    char *newstring = new char[newsize+1];

    int destindex = 0;
    for (int index = 0; index < size; ++index) {
       newstring[destindex++] = string[index];
    }
    for (int index = 0; index < s.size; ++index) {
       newstring[destindex++] = s.string[index];
    }
    newstring[destindex] = '\0';

    delete[] string;
    string = newstring;
}