注册 登录
编程论坛 C++教室

请问一下大家,我这段代码哪里不对呢

后卿 发布于 2023-04-17 20:05, 1541 次点击
程序代码:
#include <iostream>
class hstring
{
private:
    unsigned short usmlen;   //新建的内存长度
    char* cstr;             //字符串
    unsigned short uslen;   //字符串长度
    unsigned short getlength(const char* str) ;     //得到对象的字符串长度
    void copystr(char* dest, const char* source);   //复制内存函数
public:
    hstring(const hstring& str);
    hstring(const char* _str);
    hstring& operator= (const hstring& str);
    char* getstr()
    {
        return cstr;
    }
    hstring();
};
hstring::hstring()
{
    usmlen = 0x32;  
    uslen = 0;
    cstr = new char[usmlen];
}
unsigned short hstring::getlength(const char* str)
{
    unsigned short len{};
    for (; str[len];len++)
        return len;
}
void hstring::copystr(char* dest, const char* source)
{
    unsigned short len = getlength(source);
    if (len > usmlen)
    {
        cstr = new char[len];   //重新分配内存
        usmlen = len;
    }
    memcpy(dest, source, len);
}
hstring::hstring(const char* _str)
{
    copystr(cstr,_str);
}
hstring::hstring(const hstring& str)
{
    copystr(cstr, str.cstr);
}

hstring& hstring::operator=(const hstring& str)
{
    copystr(cstr, str.cstr);
    return *this;
}
int main()
{
    char str[]{ "1234567890aaaaa" };
    hstring hstr(str);
    hstring hstr1=hstr;
    std::cout << hstr.getstr()<<std::endl;
    std::cout <<hstr1.getstr();
    system("pause");
}

为什么我这里的代码跑起来就崩溃了呢?是哪里错了呢?清各位高手解答
11 回复
#2
apull2023-04-18 01:38
大概修改了下,供参考。
程序代码:


#include <iostream>
class hstring
{
private:
    unsigned short usmlen = 0x32;              // 新建的内存长度
    char *cstr = NULL;                         // 字符串
    unsigned short uslen = 0;                  // 字符串长度
    unsigned short getlength(const char *str); // 得到对象的字符串长度
   
//  void copystr(char *dest, const char *source); // 复制内存函数
    void copystr(const char *source); //-- dest是内部字符串,不用传递
public:
    hstring(const hstring &str);
    hstring(const char *_str);
    hstring &operator=(const hstring &str);
    char *getstr()
    {
        return cstr;
    }
    hstring();
};
hstring::hstring() //-- 在无参构造时调用,后面2个hstring声明没有使用这个构造,导致cstr空指针,memcpy时出错
{
    //-- usmlen = 0x32;
   
//-- uslen = 0;
    cstr = new char[usmlen];
}
unsigned short hstring::getlength(const char *str)
{
    unsigned short len{};
    for (; str[len]; len++)
        ; //-- 此处缺少分号,不然返回值都是0
    return len;
}

void hstring::copystr(const char *source)
{
    unsigned short len = getlength(source);
    if (len > usmlen || cstr == NULL) //--
    {
        // 先释放内存,再重新分配内存
        if (cstr)
            delete cstr;

        cstr = new char[len + 1]; // 重新分配内存,+1给末尾的'\0'留位置
        usmlen = len;
    }
    memcpy(cstr, source, len);  // memcpy(dest, source, len);  

    uslen = len; //-- 更改字符串长度
}
hstring::hstring(const char *_str)
{
    copystr(_str); //-- copystr(cstr, _str);
}
hstring::hstring(const hstring &str)
{
    copystr(str.cstr); //-- copystr(cstr, str.cstr);
}

hstring &hstring::operator=(const hstring &str)
{
    copystr(str.cstr); //-- copystr(cstr, str.cstr);
    return *this;
}
int main()
{
    char str[]{"1234567890aaaaa"};
    hstring hstr(str);
    hstring hstr1 = hstr; //-- 调用拷贝构造
    /*
    hstring hstr1;
    hstr1 = hstr; //-- hstr1已经声明的情况下调用=重载
   
*/
    std::cout << hstr.getstr() << std::endl;
    std::cout << hstr1.getstr();
    system("pause");
}



[此贴子已经被作者于2023-4-18 01:48编辑过]

#3
rjsp2023-04-18 09:42
随手瞎写的,可能有很多错误,因此仅供参考

程序代码:
#include <iostream>
#include <utility>
#include <cstring>

class hstring
{
public:
    hstring() noexcept = default;

    hstring( const char* str ) try : size_{strlen(str)}, capacity_{size_}, ptr_{new char[capacity_+1]}
    {
        memcpy( ptr_, str, size_+1 );
    }
    catch(...) { throw; }

    hstring( const hstring& str ) try : size_{str.size_}, capacity_{size_}, ptr_{new char[capacity_+1]}
    {
        memcpy( ptr_, str.ptr_, size_+1 );
    }
    catch(...) { throw; }

    hstring( hstring&& str ) noexcept : size_{str.size_}, capacity_{str.capacity_}, ptr_{str.ptr_}
    {
        str.ptr_ = nullptr;
        str.size_ = 0;
        str.capacity_ = 0;
    }

    hstring& operator=( const char* str )
    {
        size_t newsize = strlen(str);
        if( capacity_ < newsize )
        {
            delete[] ptr_;
            capacity_ = newsize;
            ptr_ = new char[capacity_+1];
        }
        size_ = newsize;
        memcpy( ptr_, str, size_+1 );
        return *this;
    }

    hstring& operator=( const hstring& str )
    {
        if( &str != this )
        {
            if( capacity_ < str.size_ )
            {
                delete[] ptr_;
                capacity_ = size_;
                ptr_ = new char[capacity_+1];
            }
            size_ = str.size_;
            memcpy( ptr_, str.ptr_, size_+1 );
        }
        return *this;
    }

    hstring& operator=( hstring&& str ) noexcept
    {
        if( &str != this )
        {
            std::swap( size_, str.size_ );
            std::swap( capacity_, str.capacity_ );
            std::swap( ptr_, str.ptr_ );
        }
        return *this;
    }

    ~hstring()
    {
        delete[] ptr_;
    }

    const char* c_str() const noexcept
    {
        return ptr_ ? ptr_ : "";
    }

    friend std::ostream& operator<<( std::ostream& os, const hstring& str )
    {
        return os << str.c_str();
    }

private:
    size_t size_ = 0;
    size_t capacity_ = 0;
    char* ptr_ = nullptr;
};

int main( void )
{
    using namespace std;

    cout << hstring() << endl;

    hstring a;
    cout << a << endl;

    hstring b = "abc";
    cout << b << endl;

    hstring c = b;
    cout << c << endl;

    c = "1234567890aaaaa";
    cout << c << endl;
}
#4
后卿2023-04-18 10:46
回复 2楼 apull
经过您的提醒,我修改了一下代码,因为原来的代码太长了,把自己绕晕了,就决定简化程序,这是简化后的版本,但还是有错误,不知道错在哪里,麻烦您指点一下
程序代码:
#include <iostream>
class hstring
{
private:
    unsigned short usmlen{};   //新建的内存长度
    char* cstr;             //字符串
    unsigned short getlength(const char* str);     //得到对象的字符串长度
    void copystr(char* &dest, const char* source);   //复制内存函数
public:
    hstring(const char* _str);
    char* getstr()
    {
        return cstr;
    }
};
unsigned short hstring::getlength(const char* str)
{
    unsigned short len{};
    for (; str[len]; len++);
        return len;
}
void hstring::copystr(char* &dest, const char* source)
{
    unsigned short len = getlength(source);
    if (len > usmlen)
    {
       dest = new char[len];   //分配内存大小为字符串长度,如果小于50,则按照50来分配
        usmlen = len;
    }
    memcpy(dest, source, usmlen);
}
hstring::hstring(const char* _str)
{
    cstr = nullptr;   //当调用构造函数时,先将cstr赋值为0
    usmlen= 0x32 ;    //当调用构造函数时,将内存设置为50字节
    copystr(cstr, _str);
}

int main()
{
    const char* str{"1234552444"};
    hstring hstr(str);

    std::cout << hstr.getstr() << std::endl;
    system("pause");
}

这么写程序还是崩溃了,不知道什么原因,按照我的理解,当传入一个cosnt cha*字符串,即12345时,调用了hstring(const char* _str),然后里面调用了copystr(),copystr先算出字符串长度,然后分配内存,复制内存,最后得到复制后的cstr

[此贴子已经被作者于2023-4-18 11:25编辑过]

#5
apull2023-04-18 12:54
if (len > usmlen)这个条件不满足的时候,dest是null
memcpy(dest, source, usmlen);出错。
#6
后卿2023-04-18 14:17
回复 5楼 apull
哇,厉害,我这样一改就对了
#7
后卿2023-04-18 15:46
回复 5楼 apull
经过您的 提醒,现在程序差不多改好了,不过还有个不理解的地方
程序代码:
#include <iostream>
class hstring
{
private:
    unsigned short usmlen{};   //新建的内存长度
    char* cstr;             //字符串
    unsigned short getlength(const char* str);     //得到对象的字符串长度
    void copystr(char*& dest, const char* source);   //复制内存函数
public:
    hstring();
    hstring(const char* _str);
    hstring(const hstring& hstr);
    hstring& operator=(const hstring& str);
    //hstring& operator= (const char* str);
    char* getstr()
    {
        return cstr;
    }
};
hstring::hstring()
{
    cstr = nullptr;     //指针初始化
    usmlen = 0x32;      //给予usmlen一个初始值,不然进入copystr函数后,无法与len进行比较
}
unsigned short hstring::getlength(const char* str)
{
    unsigned short len{};
    for (; str[len]; len++);
    return len;
}
void hstring::copystr(char*& dest, const char* source)
{
    unsigned short len = getlength(source);
    if (len > usmlen)
    {
        dest = new char[len+1];   //重新分配内存
        usmlen = len;
    }
    dest = new char[0x32];
    memcpy(dest, source, usmlen);
}
hstring::hstring(const char* _str):hstring()
{
    copystr(cstr, _str);
}
hstring::hstring(const hstring& hstr):hstring()
{
    copystr(cstr, hstr.cstr);
}
hstring& hstring::operator=(const hstring& hstr)
{
    copystr(cstr, hstr.cstr);
    return *this;
}
//hstring& hstring::operator=(const char* str)
//{
//    cstr = nullptr;
//    usmlen = 0x32;
//    copystr(cstr, str);
//    return *this;
//}
int main()
{
    char* c_str{ "1234552444" };
    char a_str[]{ "88888" };
    hstring hstr=c_str;    //调用了hstring(const char* _str)                           
    hstring hstr1=hstr;     //调用了hstring(const hstring& hstr)
    hstr1 = hstr;           //调用了hstring::operator=(const hstring& hstr)
    hstr1 = a_str;          //调用了hstring& hstring::operator=(const char* str)
    std::cout << hstr.getstr() << std::endl;
    std::cout << hstr1.getstr() << std::endl;
    system("pause");
}

//hstring& hstring::operator=(const char* str)
//{
//    cstr = nullptr;
//    usmlen = 0x32;
//    copystr(cstr, str);
//    return *this;
//}
就是这里注释的地方,有的人说可以不写,因为会发生类型转换,大意是构建了一个临时的变量,然后调用了operator=(const hstring& hstr)这个函数,但是我不是很理解,能不能帮忙解释一下
#8
后卿2023-04-18 18:15
回复 7楼 后卿
程序代码:
#include <iostream>
class hstring
{
private:
    unsigned short usmlen{};   //新建的内存长度
    char* cstr;             //字符串   
    void copystr(char*& dest, const char* source);   //复制内存函数
public:
    hstring();
    hstring(const char* _str);
    unsigned short getlength(const char* str);     //得到对象的字符串长度
    char* getstr()
    {
        return cstr;
    }
};
hstring::hstring()
{
    cstr = nullptr;     //指针初始化
    usmlen = 0x32;      //给予usmlen一个初始值,不然进入copystr函数后,无法与len进行比较
}
unsigned short hstring::getlength(const char* str)
{
    unsigned short len{};
    for (; str[len]; len++);
    return len;
}
void hstring::copystr(char*& dest, const char* source)
{
    unsigned short len = getlength(source);
    if (len > usmlen)
    {
        dest = new char[len+1];   //重新分配内存
        usmlen = len;
    }
    dest = new char[0x32];
    memcpy(dest, source, usmlen);
}
hstring::hstring(const char* _str):hstring()
{
    copystr(cstr, _str);
}
hstring& hstring::operator+ (const hstring& hstr)   //重载+,使他能够连接对象,即连接对象里的字符
{
    unsigned int hstrlen = getlength(hstr.cstr);     //得到末尾要添加的对象的字符串长度
    unsigned int sumlen  = hstrlen + getlength(cstr);  //得到总长度,即原有字符串加新对象的字符串长                                                   
                                                        
//
    cstr = new char[sumlen];                         //给原有字符串新分配一个总长度的内存
    memcpy(cstr-hstrlen+1, hstr.cstr, hstrlen);//复制新字符串到原有字符串后面,复制长度为hstrlen
    return *this;
}
int main()
{
    char* c_str{ "1234552444" };
    hstring hstr=c_str;     //调用了hstring(const char* _str)                           
    hstr+"123456";
    std::cout << hstr1.getstr() << std::endl;
    system("pause");
}

请问,为什么我这里总是不能复制出正确的值呢?打印结果总是出现乱码,另外,请问,operator+里面的cstr被重新分配内存后,它原有的值应该不会变化把?只是增加了它的内存空间。
#9
apull2023-04-19 01:11
7楼问题看2楼代码的main部分注释。
8楼问题
声明改为hstring &operator+(const char *str),参数得是字符串。
函数中 cstr = new char[sumlen];直接抹掉了以前的字符串。
cstr-hstrlen里,cstr已经指向字符串开头,再减,指针都不知道指向何处了。
#10
后卿2023-04-19 10:07
回复 9楼 apull
程序代码:
#include <iostream>
class hstring
{
private:
    unsigned short usmlen{};   //新建的内存长度
    char* cstr;             //字符串   
    void copystr(char*& dest, const char* source);   //复制内存函数
    unsigned short uslen    //字符串长度
public:
    hstring();
    hstring(const char* _str);
    unsigned short getlength(const char* str);     //得到对象的字符串长度
    hstring& operator<<(const hstring& hstr);
    char* getstr()
    {
        return cstr;
    }
};
hstring::hstring()
{
    cstr = nullptr;     //指针初始化
    usmlen = 0x32;      //给予usmlen一个初始值,不然进入copystr函数后,无法与len进行比较
}
unsigned short hstring::getlength(const char* str)
{
    unsigned short len{};
    for (; str[len]; len++);
    return len;
}
void hstring::copystr(char*& dest, const char* source)
{
    unsigned short len = getlength(source);
    if (len > usmlen)
    {
        dest = new char[len+1];   //重新分配内存
        usmlen = len;
    }
    dest = new char[0x32];
    uslen=len;
    memcpy(dest, source, usmlen);
}
hstring::hstring(const char* _str):hstring()
{
    copystr(cstr, _str);
}
hstring& hstring::operator<<(const hstring& hstr)   //重载<<
{
    unsigned short hstrlen = getlength(hstr.cstr);     //得到末尾要添加的对象的字符串长度
    unsigned int sumlen  = hstrlen + uslen;//得到总长度,即对象字符串+原有字符串长度                                                   
    if(sumlen>usmlen)
    {
        delete[] cstr;
        cstr = new char[sumlen];
        usmlen=sumlen;
    }                                                   
    memcpy(cstr+uslen-1, hstr.cstr, hstrlen);//复制新字符串到原有字符串后面,复制长度为hstrlen
    return *this;
}
int main()
{
    char* c_str{ "1234552444" };
    hstring hstr=c_str;     //调用了hstring(const char* _str)                           
    hstr<<"123456";
    std::cout << hstr1.getstr() << std::endl;
    system("pause");
}

为什么我看别人这么写,它的左移运算也成功了,我写的程序是不是少了关键的哪一步呢

[此贴子已经被作者于2023-4-19 10:23编辑过]

#11
apull2023-04-19 10:13
注意重载的参数类型。
#12
后卿2023-04-19 17:34
回复 11楼 apull
haode
1