c++ - 复制在我的 string::copy 实现中不起作用

标签 c++ string class oop

跟进 https://codereview.stackexchange.com/q/126242/23788 .

我编写了我的字符串类,并根据反馈更改了一些内容。还有什么需要解决的吗?

+operator 不起作用,我不知道我做错了什么。当我执行“Str+Str”时出现段错误。

Process finished with exit code 139

这是我的 Str.h

class Str {

    friend std::istream &operator>>(std::istream &, Str &);

    friend void swap(Str &s, Str &t) {
        std::swap(s.data, t.data);
        std::swap(s.length, t.length);
        std::swap(s.alloc, t.alloc);
    }


public:
    typedef char *iterator;
    typedef size_t size_type;

    Str() : data(nullptr), length(0), capacity(0) { }

    Str(size_type length, char char_to_fill) : Str() { create(length, char_to_fill); }

    Str(const char *s) : Str() { create(s); }

    template<class In>
    Str(In b, In e) : Str() { create(b, e); }

    ~Str() {
        if (data) alloc.deallocate(data, capacity);
        data = nullptr;
    }

    Str(const Str &s) {
        *this = s;
    }

    // move constructor?
    Str(Str &&other)
            : Str() {// initialize via default constructor, C++11 only
        swap(*this, other);
    }

    Str &operator+=(const Str &s) {
        size_type new_length = length + s.length - 1; //remove 1 because of 2 nulls
        if (new_length > capacity) {
            reallocate(new_length);
            strcpy(data + length - 1, s.data); //overwrite null from s
            length = new_length;
        }
        else {//if there was already enough space
            strcpy(data + length - 1, s.data);
        }
        return *this;
    }

    Str &operator=(Str rhs) {
        swap(*this, rhs);
        return *this;
    }

    char &operator[](size_type i) { return data[i]; };

    const char &operator[](size_type i) const { return data[i]; };

    size_type size() { return length; }

    const size_type size() const { return length; }

    const char *c_str() const {
        return data;
    }

    void copy(char *dest, size_type n) {
        if (n > length)
            throw std::out_of_range("Out of range");
        std::copy(data, data + n, dest);
    }

    char *begin() { return data; };

    char *end() { return data + length; };

    void push_back(char c) {
        if (length == capacity) {
            reallocate(capacity == 0 ? DEFAULT_CAPACITY : 2 * capacity);
        }
        data[length++] = c;
    }

private:
    char *data;
    std::allocator<char> alloc;
    size_type length;
    size_type capacity;
    static const size_type DEFAULT_CAPACITY = 20;

    void create(size_type n, char character_to_fill) {
        capacity = length = n + 1;
        data = alloc.allocate(capacity);
        std::uninitialized_fill(data, data + length - 1, character_to_fill);
        //alloc.construct(data + length - 1, '\0'); //is it needed to be constructed?
        data[length - 1] = '\0';
    }

    void create(const char *s) {
        capacity = length = strlen(s) + 1;
        data = alloc.allocate(capacity);
        strcpy(data, s);
        //alloc.construct(data + length - 1, '\0');
        data[length - 1] = '\0';
    }

    template<class In>
    void create(In b, In e) {
        capacity = e - b + 1;
        data = alloc.allocate(capacity);
        while (b != e) {
            data[length++] = *(b++);
        }
        //alloc.construct(data + length -1, '\0');
        data[length++] = '\0';
    }

    void reallocate(size_t new_capacity) {
        char *new_data = alloc.allocate(new_capacity);
        std::copy(data, data + length, new_data);
        alloc.deallocate(data, length);
        data = new_data;
        capacity = new_capacity;
    }
};

std::istream &operator>>(std::istream &is, Str &s) {
    std::vector<char> buf;
    char actual_character;
    while (is.get(actual_character) && isspace(actual_character)) { ;
    }
    if (is) { //is it correct to check "is" ?
        do buf.push_back(actual_character);
        while (is.get(actual_character) && !isspace(actual_character));
        if (is)
            is.unget();
    }
    s.create(buf.begin(), buf.end());
    return is;
}

std::ostream &operator<<(std::ostream &os, const Str &s) {
    os << s.c_str();
    return os;
}

Str operator+(Str lhs, const Str &rhs) {
    lhs += rhs;
    return lhs;
}

和示例 main.cpp

#include <iostream>
#include <vector>
#include "Str.h"

using std::cout;
using std::endl;

int main() {
    Str s("Siema");
    cout<<s.c_str()<<endl;

    s = "Hello";
    cout<<s<<endl;

    s.push_back('a');
    cout<<s<<endl;

    Str t = "World";
    //cout<<s+t<<endl; //THIS DOESNT WORK

    s+=t;
    cout<<s<<endl;

    cout<<s[3]<<s[5]<<s[11]<<endl;

    cout<<s.size()<<endl;
    cout<<Str(s.begin()+3, s.end()-2)<<endl;
    for(Str::iterator i = s.begin(); i<s.end() ; i+=2){
        cout<<i<<endl;
    }

    char copied[3];
    t.copy(copied, 4);
    cout<<copied<<endl;

    return 0;
}

最佳答案

在你的代码中

char copied[3];
t.copy(copied, 4);
cout<<copied<<endl;

“copied”的长度只有 3,而您正试图将 4 个字符复制到其中。这会导致问题

检查下面的更新代码。使用“<--”阅读评论

海峡

#include <iostream>
#include <memory>
#include <vector>
class Str {

friend std::istream &operator >> (std::istream &, Str &);

 void swap(Str &s, Str &t) {
    std::swap(s.data, t.data);
    std::swap(s.length, t.length);
    std::swap(s.alloc, t.alloc);
}


public:
typedef char *iterator;
typedef size_t size_type;

Str() : data(nullptr), length(0), capacity(0) { }

Str(size_type length, char char_to_fill) : Str() { create(length, char_to_fill); }

Str(const char *s) : Str() { create(s); }

template<class In>
Str(In b, In e) : Str() { create(b, e); }

~Str() {
    if (data) alloc.deallocate(data, capacity);
    data = nullptr;
}

Str(const Str &s) {
    *this = s;
}

// move constructor?
Str(Str &&other)
    : Str() {// initialize via default constructor, C++11 only
    swap(*this, other);
}

Str &operator+=(const Str &s) {
    size_type new_length = length + s.length - 1; //remove 1 because of 2 nulls
    if (new_length > capacity) {
        reallocate(new_length);
        strcpy(data + length - 1, s.data); //overwrite null from s
        //length = new_length;  //<-- You need to update the length anyay. Move it to before return
    }
    else {//if there was already enough space
        strcpy(data + length - 1, s.data);
    }
    length = new_length; //<-- update the length
    return *this;
}

Str &operator=(Str rhs) {
    swap(*this, rhs);
    return *this;
}

char &operator[](size_type i) { return data[i]; };

const char &operator[](size_type i) const { return data[i]; };

size_type size() { return length; }

const size_type size() const { return length; }

const char *c_str() const {
    return data;
}

void copy(char *dest, size_type n) {
    if (n > length)
        throw std::out_of_range("Out of range");
    std::copy(data, data + n, dest);  // <--forgot about '\0'?
    dest[n] = '\0';                   // <-- add '\0'
}

char *begin() { return data; };

char *end() { return data + length; };

void push_back(char c) {
    if (length == capacity) {
        reallocate(capacity == 0 ? DEFAULT_CAPACITY : 2 * capacity);
    }
    data[length++ - 1] = c;  //<-- length - 1 is the last position, because length here includes '\0'
    data[length - 1] = 0;    //<-- don't forget to add '\0'. It's better if you fill the unused spaces to '\0' after allocate them.
}

private:
char *data;
std::allocator<char> alloc;
size_type length;
size_type capacity;
static const size_type DEFAULT_CAPACITY = 20;

void create(size_type n, char character_to_fill) {
    capacity = length = n + 1;
    data = alloc.allocate(capacity);
    std::uninitialized_fill(data, data + length - 1, character_to_fill);
    //alloc.construct(data + length - 1, '\0'); //is it needed to be constructed?
    data[length - 1] = '\0';
}

void create(const char *s) {
    capacity = length = strlen(s) + 1;
    data = alloc.allocate(capacity);
    strcpy(data, s);
    //alloc.construct(data + length - 1, '\0');
    data[length - 1] = '\0';
}

template<class In>
void create(In b, In e) {
    capacity = e - b + 1;
    data = alloc.allocate(capacity);
    while (b != e) {
        data[length++] = *(b++);
    }
    //alloc.construct(data + length -1, '\0');
    data[length++] = '\0';
}

void reallocate(size_t new_capacity) {
    char *new_data = alloc.allocate(new_capacity);
    std::copy(data, data + length, new_data);
    alloc.deallocate(data, length);
    data = new_data;
    capacity = new_capacity;
}
};

std::istream &operator >> (std::istream &is, Str &s) {
std::vector<char> buf;
char actual_character;
while (is.get(actual_character) && isspace(actual_character)) {
    ;
}
if (is) { //is it correct to check "is" ?
    do buf.push_back(actual_character);
    while (is.get(actual_character) && !isspace(actual_character));
    if (is)
        is.unget();
}
s.create(buf.begin(), buf.end());
return is;
}

std::ostream &operator<<(std::ostream &os, const Str &s) {
os << s.c_str();
return os;
}

Str operator+(Str lhs, const Str &rhs) {
lhs += rhs;
return lhs;
}

和主要:

int main() {
Str s("Siema");
cout << s.c_str() << endl;

s = "Hello";
cout << s << endl;

s.push_back('a');
cout << s << endl;

Str t = "World";
//cout<<s+t<<endl; //THIS DOESNT WORK

s += t;
cout << s << endl;

cout << s[3] << s[5] << s[11] << endl;

cout << s.size() << endl;
cout << Str(s.begin() + 3, s.end() - 2) << endl;
for (Str::iterator i = s.begin(); i<s.end(); i += 2) {
    cout << i << endl;
}

char copied[5];  //<-- was 3, not enough space
t.copy(copied, 4);
cout << copied << endl;

return 0;
}

关于c++ - 复制在我的 string::copy 实现中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36778183/

相关文章:

android - 显示图像的透明按钮

c++ - 作为类成员的引用初始化

java - 如何将 "[]"的字符串转换为整数数组

php - 为什么PHP在访问对象属性时不需要$?

javascript - 单击同级时从导航中删除类

r - 根据obj2的结构改变obj1的内部结构

c++ - 创建 Matlab MEX 函数时,是否将 mexFunction 放在 C++ 头文件或源文件中?

c++ - 避免迭代器在 vector 迭代期间失效

string - Perl 范围字符串 ID

java - java中重复字符串中的特定字符