【问题标题】:Failed to concatenation with my custom string class无法与我的自定义字符串类连接
【发布时间】:2021-05-11 15:35:52
【问题描述】:

我几乎完成了我自己的自定义字符串类的创建。但是,当程序没有返回我所期望的输出时,它似乎并不顺利。详细:

输入:

字符串 a = "你好"

字符串 b = "世界!"

预期输出:

你好世界!

!dlroWolleH

实际输出:

你好

这是我的代码:

#ifndef _STRING
#define _STRING
#include<iostream>
#include<cstring>
class string {
private:
    char* s = nullptr;
    unsigned int size = 0;
public:
    string();
    ~string() { delete s; };
    string(char* );
    string(const char* );
    string(const string&);
    friend std::ostream& operator << (std::ostream&, string&);
    friend string operator +(string, string);
    string& operator = (const string&);
    string& operator = (const char&);     
    string& inverse();
    char* inconst();
    char* output() const{
        return s;
    }
};
#endif
string::string() :s{ nullptr } {
    size = 1;
    s = new char[size];
    s[0] = '\0';
}
string::string(char* source) {
    if (source == nullptr) {
        size = 1;
        s = new char[size];
        s[0] = '\0';
    }
    else {
        size = strlen(source) + 1;
        s = new char[size];
        s[size - 1] = '\0';
        for (size_t k = 0; k < (size - 1); k++) {
            s[k] = source[k];
        }
    }
}
string::string(const char* source) {
    if (source == nullptr) {
        size = 1;
        s = new char[size];
        s[0] = '\0';
    }
    else {
        size = strlen(source) + 1;
        s = new char[size];
        s[size - 1] = '\0';
        for (size_t k = 0; k < (size - 1); k++) {
            s[k] = source[k];
        }
    }
}
string::string(const string& t) {
    size = t.size;
    s = new char[size];
    s[size - 1] = '\0';
    for (size_t k = 0; k < (size - 1); k++) {
        s[k] = t.s[k];
    }
}
string& string::operator=(const string& source) {
    delete[] s;
    size = source.size;
    s = new char[size];
    s[size - 1] = '\0';
    for (size_t k = 0; k < (size - 1); k++) {
        s[k] = source.s[k];
    }
    return *this;
}
string& string::operator=(const char&source) {
    const char* t = &source;
    if (t == nullptr) {
        size = 1;
        s = new char[size];
        s[0] = '\0';
    }
    else {
        size = strlen(t) + 1;
        s = new char[size];
        s[size - 1] = '\0';
        for (size_t k = 0; k < (size - 1); k++) {
            s[k] = t[k];
        }
    }
    return* this;
}
string operator +(string a, string b) {
    string t;
    t.size = a.size + b.size;
    t.s = new char[t.size + 1];
    strncpy_s(t.s, a.size + 1, a.s, a.size);
    strncpy_s(t.s + a.size, b.size + 1, b.s, b.size);
    return t;
}

std::ostream& operator << (std::ostream& os, string& source) {
    os << source.output();
    return os;
}

char* string::inconst() {
    char* t;
    t = new char[size + 1];
    for (size_t k = 0; k < size; k++)
    {
        t[k] = s[size - 1 - k];
    }
    t[size] = '\0';
    return t;
}
string& string::inverse() {
    this->s = this->inconst();
    return*this;
}
    int main(){
        string a = "Hello";
        string b = "World!";
        string c = a + b;
        std::cout << c << std::endl;
        std::cout << c.inverse() << std::endl;
        system("pause");
        return 0;
}

似乎我在连接部分(重载运算符 + 赋值)发现了一些错误,因为当我输出分隔变量 ab (如 std::cout &lt;&lt; b &lt;&lt; std::endl;)时我可以接收到我想要的输出,但我找不到正是我错了。请帮我修复我的代码,感谢您的帮助

【问题讨论】:

    标签: c++ arrays oop output concatenation


    【解决方案1】:

    您的string 确实将终止空字符存储在s[size - 1]

    然后在inconst 中你不考虑空字符,而是假设size 是字符串中的字符数。

    char* string::inconst() {
        char* t;
        t = new char[size + 1];               // why +1 here ?
        for (size_t k = 0; k < size; k++)     
        {
            t[k] = s[size - 1 - k];
        }
        t[size] = '\0';                      // why another \0 ?
        return t;
    }
    

    第一次迭代将s[size-1]分配给t[0],即最后存储在t中的字符串如下所示:

    t[0]  t[1]        ...   t[size] t[size+1]
    \0    s[size-2]   ...   s[0]    \0
    

    您需要确定size 是否计算空终止符,然后对此保持一致。


    大概这不会是您最后一次需要进行调试,因此我建议使用operator&lt;&lt; 来打印更多信息,而不是依赖char* 重载。编写一个逐字符打印的循环。如果我没有遗漏任何内容并且我的回答是正确的,那么您将看到上述字符串的内容。


    您的代码中还有更多问题,我发现的一个是operator= 没有正确处理自赋值。当你这样做时

    string s;
    s = s;
    

    然后您的operator= 首先删除缓冲区,然后从中复制。以防万一你不相信这是一个问题(因为谁会写s=s,这很傻,不是吗?),考虑一个函数void foo(string&amp; a, string b&amp;) { a = b; }


    在更风格的注释上,我建议您重命名该方法。 inverse 建议它会返回一个新的string,而invert 会明确表示它修改了字符串。 (而且我不知道inconst 应该是什么意思。)

    【讨论】:

    • 谢谢。看起来我在循环中发现了错误。我还会注意到命名构造函数和赋值。顺便说一句,“intconst”表示反转构造函数
    猜你喜欢
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多