跟进https://codereview.stackexchange.com/q/126242/23788。
我写了我的字符串类,根据反馈,我改变了一些东西。还有什么应该修复的吗?
+运算符不起作用,我不知道我做错了什么。当我做“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;
}
答案 0 :(得分:3)
在您的代码中
char copied[3];
t.copy(copied, 4);
cout<<copied<<endl;
&#34;复制&#34;当您尝试将4个字符复制到其中时,只有3的长度。哪会引起问题
检查以下更新的代码。使用&#34;&lt; - &#34;
阅读评论str.h
#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;
}