无法与我的自定义字符串连接 class

Failed to concatenation with my custom string class

我几乎完成了我自己的自定义字符串的创建 class。但是,当程序没有 return 我预期的输出时,似乎进展不顺利。详细:

Input:

string a = "Hello"

string b = "World!"

Expected output:

HelloWorld!

!dlroWolleH

Actual output:

Hello

这是我的代码:

#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] = '[=11=]';
}
string::string(char* source) {
    if (source == nullptr) {
        size = 1;
        s = new char[size];
        s[0] = '[=11=]';
    }
    else {
        size = strlen(source) + 1;
        s = new char[size];
        s[size - 1] = '[=11=]';
        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] = '[=11=]';
    }
    else {
        size = strlen(source) + 1;
        s = new char[size];
        s[size - 1] = '[=11=]';
        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] = '[=11=]';
    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] = '[=11=]';
    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] = '[=11=]';
    }
    else {
        size = strlen(t) + 1;
        s = new char[size];
        s[size - 1] = '[=11=]';
        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] = '[=11=]';
    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 << b << std::endl; 但我无法确切地找出我错了什么。请帮助我修复我的代码,感谢你帮助我

您的 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] = '[=10=]';                      // why another [=10=] ?
    return t;
}

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

t[0]  t[1]        ...   t[size] t[size+1]
[=11=]    s[size-2]   ...   s[0]    [=11=]

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


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


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

string s;
s = s;

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


从更文体的角度来看,我建议您重命名该方法。 inverse 表明它会 return 一个新的 string,而 invert 会明确表示它修改了字符串。 (我不知道 inconst 是什么意思。)