I'm trying to make my own String class, and I have a problem with operator+.
When I use + as " s1 = s2 + s3 " it works.
But in case just use " s1 + s1 " or " s2 + s3 " does not work.
When I run it, I get 0xC0000005 error on 'init' function at delete[] str_; line.
I want to know what's wrong with my codes...
this is my string.h
class String
{
private:
int len_;
int capa_;
char* str_;
public:
String(const String& str);
String(const char* s = "");
~String();
const char* Print(bool show = true);
int size();
int length();
int capacity();
String& assign(const String& str);
String& assign(const char* s);
String& operator=(const String& str);
String& operator=(const char* s);
String& append(const String& str);
String& append(const char* s);
String& operator+=(const String& str);
String& operator+=(const char* s);
String operator+(const String& str);
String operator+(const char* s);
char& operator[](int index);
void shrink_to_fit();
friend std::ostream& operator<<(std::ostream& os, const String& str);
private:
void init(const char* s);
String plus(const char* s);
};
this is my string.cpp
void String::init(const char* s)
{
if (str_ == s) {}
else
{
delete[] str_;
}
len_ = strlen(s);
capa_ = len_ + 1;
str_ = new char[capa_];
strcpy_s(str_, capa_, s);
}
String::String(const String& str)
{
init(str.str_);
}
String::String(const char* s)
{
init(s);
}
String::~String()
{
delete[] str_;
}
int String::size()
{
return this->len_;
}
int String::length()
{
return strlen(this->str_);
}
int String::capacity()
{
return this->capa_;
}
String& String::assign(const String& str)
{
assign(str.str_);
return *this;
}
String& String::assign(const char* s)
{
init(s);
return *this;
}
String& String::operator=(const String& str)
{
assign(str.str_);
return *this;
}
String& String::operator=(const char* s)
{
assign(s);
return *this;
}
String& String::append(const String& str)
{
append(str.str_);
return *this;
}
String& String::append(const char* s)
{
len_ = this->len_ + strlen(s);
capa_ = len_ + 1;
char* temp = new char[capa_];
strcpy_s(temp, capa_, this->str_);
if (str_ == s) {}
else
{
delete[] str_;
}
strcat_s(temp, capa_, s);
str_ = new char[capa_];
strcpy_s(str_, capa_, temp);
delete[] temp;
return *this;
}
String& String::operator+=(const String& str)
{
append(str);
return *this;
}
String& String::operator+=(const char* s)
{
append(s);
return *this;
}
char& String::operator[](int index)
{
int index_;
if (index < 0)
{
index_ = 0;
}
else if (index > this->len_)
{
index_ = this->len_ - 1;
}
else
{
index_ = index;
}
return str_[index_];
}
String String::plus(const char* s)
{
int tempcapa = this->len_ + strlen(s) + 1;
char* temp = new char[tempcapa];
strcpy_s(temp, tempcapa, this->str_);
strcat_s(temp, tempcapa, s);
return temp;
}
String String::operator+(const String& str)
{
return plus(str.str_);
}
String String::operator+(const char* s)
{
return plus(s);
}
std::ostream& operator<<(std::ostream& os, const String& str)
{
os << str.str_;
return os;
}
void String::shrink_to_fit()
{
if (this->capa_ > this->len_ + 1)
{
char* temp = new char[len_ + 1];
strcpy_s(temp, len_ + 1, this->str_);
delete[] this->str_;
this->str_ = new char[len_ + 1];
strcpy_s(this->str_, len_ + 1, temp);
delete[] temp;
this->capa_ = len_ + 1;
}
}
const char* String::Print(bool show)
{
if (show == true)
std::cout << str_;
return str_;
}
Related
For this project we are suppose to cover the topic of dynamic memory allocation and deallocation. The functionality of the 'operator<<; is to output(to terminal or file depending on the type of ostream& os object passed as a parameter to it) the MyString data (the C-string representation held within m_buffer). Right after my program prints to the Terminal "Access Successful." I receive a Segmentation fault (core dumped) I am quite sure that it have something to do with the operator << but I do not know how to fix this. Hence, it fails to print "Testing Operator <<()". Any Suggestions? Thank you!
//int main
int main(){
std::cout << "Testing operator[]()" << std::endl;
MyString ms_access("Access successful (NOT)");
ms_access[17] = 0;
std::cout << "Testing operator<<()" << std::endl;
cout << ms_access << endl;
}
class MyString{
public:
MyString();
MyString(const char * str);
MyString(const MyString & other_myStr);
~MyString();
size_t size() const;
size_t length() const;
const char * c_str() const;
bool operator== (const MyString & other_myStr) const;
MyString & operator= (const MyString & other_myStr);
MyString operator+ (const MyString & other_myStr) const;
char & operator[] (size_t index);
const char & operator[] (size_t index) const;
friend std::ostream & operator<<(std::ostream & os, const MyString & myStr);
private:
void buffer_deallocate();
void buffer_allocate(size_t size);
char * m_buffer;
size_t m_size;
};
//definition
std::ostream& operator<<(std::ostream& os, const MyString& myStr){
//if(os == std::cout){
os << myStr.m_buffer << std::endl;
//}
}
//will allow by-reference accessing of a specific character at index size_tindexwithin the allocated m_bufferchar arrayof a non-constqualified object.
char& MyString::operator[](size_t index){
size_t counter = 0;
while(counter != index){
counter++;
}
return m_buffer[counter];
}
//will allow by-reference accessing of a specific character at index size_tindexwithin the allocated m_bufferchar array of a constqualified object.
const char& MyString::operator[](size_t index)const{
size_t counter = 0;
while(counter != index){
counter++;
}
return m_buffer[counter];
}
void MyString::buffer_deallocate(){
if(m_buffer != NULL){
delete [] m_buffer;
}
}
void MyString::buffer_allocate(size_t size){
if(m_buffer != NULL){
buffer_deallocate();
}
m_size = size;
m_buffer = new char[m_size];
}
MyString::MyString(){
m_size = 0;
m_buffer = NULL;
}
MyString::MyString(const char *str){
m_buffer = NULL;
m_size = strlen(str);
buffer_allocate(m_size);
strcpy(m_buffer,str);
}
MyString::MyString(const MyString &other){
m_buffer = NULL;
m_size = other.m_size;
buffer_allocate(m_size);
strcpy(m_buffer,other.m_buffer);
}
size_t MyString::size()const{
return m_size;
}
size_t MyString::length(){
return strlen(m_buffer)-1;
}
const char* MyString::c_str() const {
char *str = NULL;
str = new char[m_size];
for(size_t i = 0; i < m_size;i++){
str[i] = *(m_buffer+i);
}
return str;
delete [] str;
str = NULL;
}
bool MyString::operator==(const MyString & other)const{
if(strcmp(m_buffer,other.m_buffer) == 0){
return true;
}else if (strcmp(m_buffer,other.m_buffer) != 0){
return false;
}
}
MyString & MyString::operator=(const MyString & str1){
buffer_deallocate();
m_buffer = new char[str1.m_size];
strcpy(m_buffer,str1.m_buffer);
}
MyString MyString::operator+(const MyString & other_myStr)const{
MyString myStr(strcat(m_buffer,other_myStr.m_buffer));
return myStr;
}
I build a simple string class.
I try to make the concatenation functions which one of them is + and the other +=.
When trying to implement += I generate a Str object under that equals the 1st string and which size is s.size(). But then when I tried to append to it a new string t I need to free the old array s string and allocate new size for it. After the destructor of the temp Str object is called it stucks there when freeing the old space and I can't understand why. How can I deallocate the Str under the + member function?
class Str
{
public:
typedef size_t size_type;
typedef char* iterator;
typedef const char* const_iterator;
iterator begin(){ return p; }
iterator end() { return p + std::strlen(p); }
const_iterator begin() const { return p; }
const_iterator end() const { return p + std::strlen(p); }
size_type size() const { return data_length; }
Str() {};
Str(const Str& s):
p(new char[s.size() +1]),
data_length(s.size())
{
std::copy(s.begin(), s.end(), p);
p[data_length] = '\0';
}
Str(const char* cp) :
p(new char[std::strlen(cp) + 1 ]),
data_length(std::strlen(cp))
{
std::copy(cp, cp+ std::strlen(cp) + 1,p);//copies also the '\0' char to the last place in p
}
Str& operator=(Str& rhs)//assignment operator
{
if (&rhs != this)
{
uncreate();
create(rhs.size());
std::copy(rhs.begin(), rhs.end() + 1, p);
//p[rhs.size()] = '\0';
}
return *this;
}
Str& operator=(const char* cp)//assignment operator
{
if (cp!= p)
{
uncreate();
create(std::strlen(cp));
std::copy(cp, cp+std::strlen(cp), p);
p[data_length] = '\0';
}
return *this;
}
Str& operator+=(const Str&);
~Str()
{
delete[] p;//stucked here while returning from + member function
data_length = 0;
}
const char* c_str() const;
void copy(char* ,size_type);
private:
char* p;
size_type data_length = 0;
const_iterator ci() const { return p; }
void uncreate();
void create(size_type);
};
Str operator+(const Str& s, const Str& t)
{
Str r = s;
r += t;
return r;
}
inline Str& Str::operator+=(const Str &s)
{
//trying to allocate new space for this object
std::copy(s.begin(),s.end(),p+this->size());
p[data_length] = '\0';
return *this;
}
void Str::create(Str::size_type n)
{
p = new char[n + 1];
data_length = n;
}
void Str::uncreate()
{
delete[] p;//to check that p is allocated right
data_length = 0;
}
The main for example:
int main()
{
Str s1 = "hello";
Str s2 = "worly";
Str s3 = s1 + s2;
return 0;
}
I suppose you want something like this:
inline Str& Str::operator+=(const Str &s)
{
const int new_data_length = data_length + s.data_length;
char * temp = new char[new_data_length + 1];
memcpy(temp, p, data_length);
memcpy(temp + data_length, s.p, s.data_length);
delete [] p;
p = temp;
data_length = new_data_length;
p[data_length] = 0;
return *this;
}
Following up on https://codereview.stackexchange.com/q/126242/23788.
I wrote my string class and according to the feedback I have changed some stuff. Is there anything more that should be fixed?
+operator doesn't work and I do not know what I've done wrong. I have a segfault when I do "Str+Str".
Process finished with exit code 139
And this is my 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;
}
And example 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;
}
In your code
char copied[3];
t.copy(copied, 4);
cout<<copied<<endl;
"copied" has only length of 3 while you are trying to copy 4 characters into it. Which will cause problem
Check updated codes below. Read comments with "<--"
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;
}
and main:
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;
}
I am working on building a string class in C++. Currently I am trying to override the subscript operator so users can get and modify individual characters.
#ifndef STRING_HPP
#define STRING_HPP
#include "test.hpp"
#include <cstring>
#include <iosfwd>
struct String
{
// Defines the npos value.
static constexpr std::size_t npos = -1;
int len;
char *str;
String()
:len(0), str(0){}
String(char const * S)
:len(strlen(S)), str(new char[len + 1]){
assert(S != 0);
strcpy(str, S);
}
~String(){
delete[]str;
}
String (char *S, std::size_t const n)
:len(n), str(new char[len + 1]){
assert(S != 0);
assert(strlen(S) >= n);
strncpy(str, S, n);
str += '\0';
}
String operator +=(String const &S){
int n = len + S.len;
char * p = new char[n+1];
strcpy(p + len, S.str);
len = n;
str = p;
return *this;
}
char* data() const {
return this->str;
}
bool empty() const {
return (this->len == 0);
}
size_t size()const {
size_t temp = len;
return temp;
}
//assignment operator
String operator =(String const &s){
String temp(s);
swap(temp);
return *this;
}
void swap(String &s){
std::swap(len, s.len);
std::swap(str, s.str);
}
size_t find(const char c){
char * p = strchr(this->str, c);
if(p){
return (str - p);
}else{
return npos;
}
}
char &operator[](const size_t pos){
assert(pos >= 0);
assert(pos < this->size());
return str[pos];
//return output;
}
String substr(int index, int dist){
String output((this->str + index) ,dist);
return output;
}
};
// Output
std::ostream& operator<<(std::ostream&, String const&);
//String operator +=(String const &);
bool operator <(String const &, String const &);
bool operator >(String const &, String const &);
bool operator <=(String const &, String const &);
bool operator >=(String const &, String const &);
bool operator ==(String const &, String const &);
#endif
The portion of main that calls the subscript function is:
String s1 = "String";
s1[0] = 'a';
The error I am getting is:
error: passing 'const String' as 'this' argument of 'char& String::operator[](size_t)' discards qualifiers [-fpermissive]
Thanks!
Edit
Updated error message to be correct
turns out the answer is just to add a 'const' at the end of the function:
char &operator[](const size_t pos)const{
assert(pos >= 0);
assert(pos < this->size());
return str[pos];
//return output;
}
I am learning C++ by creating a String class for an embedded project and I have a problem with my String class' concatenation.
Here is my main method and the output
#include <iostream>
#include "string.hpp"
using namespace std;
int main() {
String s1("hello "), s2("world");
String s3 = s1 + s2;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
return 0;
}
s1=hello
s2=world
s3=hello
Rather than print out "hello world", it prints just "hello "
Here is my string.hpp class:
#pragma once
#include <cstring>
#include <iostream>
class String {
public:
String() : c_str(NULL), len(0)
{
}
String(const String& str) : c_str(new char[str.len]), len(str.len)
{
strncpy(c_str, str.c_str, len);
c_str[len] = '\0';
}
String(const char* str) : String(str, strlen(str))
{
strncpy(c_str, str, len);
c_str[len] = '\0';
}
String(const char* str, const int n) : len(n), c_str(new char[n+1])
{
strncpy(c_str, str, len);
}
~String()
{
delete[] c_str;
}
const char* get_c_str()
{
return c_str;
}
bool contains(const String &cmd, const size_t pos)
{
return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
}
size_t length()
{
return len;
}
friend std::ostream& operator<<(std::ostream& os, const String obj)
{
os << obj.c_str;
return os;
}
friend void swap(String& s1, String& s2)
{
using std::swap;
swap(s1.c_str, s2.c_str);
swap(s1.len, s2.len);
}
bool operator==(const String& str)
{
return strncmp(c_str, str.c_str, len) == 0;
}
char operator[](const size_t i)
{
return c_str[i];
}
String& operator=(const String& src)
{
String tmp(src);
swap(*this, tmp);
return *this;
}
String operator+(const String& rhs)
{
const size_t new_len = len + rhs.len;
char* new_c_arr = new char[new_len+1];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs.c_str);
printf("new_c_arr=%s\n", new_c_arr);
return String(new_c_arr, len);
}
String operator+(const char* rhs)
{
const size_t new_len = len + strlen(rhs) + 1;
char* new_c_arr = new char[new_len];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs);
return String(new_c_arr, new_len);
}
private:
char* c_str;
int len;
};
I read about "the big 3" on SO while looking for a similar question and not sure if it because of this.
This code is broken in numerous ways.
#pragma once
Actual include guards are more portable than #pragma once.
String() : c_str(NULL), len(0)
{
}
Your default constructor makes c_str null; your other functions never check for this case. Remember that even an empty C string has one character.
String(const String& str) : c_str(new char[str.len]), len(str.len)
{
strncpy(c_str, str.c_str, len);
c_str[len] = '\0';
}
You only allocated str.len characters for c_str, yet you are accessing c_str[len].
String(const char* str) : String(str, strlen(str))
{
strncpy(c_str, str, len);
c_str[len] = '\0';
}
The constructor to which you delegated already performed a copy. Why are you calling strncpy here again?
String(const char* str, const int n) : len(n), c_str(new char[n+1])
{
strncpy(c_str, str, len);
}
and here you didn't make sure that your string is null-terminated.
const char* get_c_str()
{
return c_str;
}
Should be marked const.
bool contains(const String &cmd, const size_t pos)
{
return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
}
Ditto. And you didn't check that pos is in range.
size_t length()
{
return len;
}
const.
friend std::ostream& operator<<(std::ostream& os, const String obj)
{
os << obj.c_str;
return os;
}
obj should be passed by const reference, not by value.
bool operator==(const String& str)
{
return strncmp(c_str, str.c_str, len) == 0;
}
const again, and the logic isn't even correct. By this logic, "something" == "something else" since you are only comparing the first len characters.
char operator[](const size_t i)
{
return c_str[i];
}
If you are returning a copy, then it should be const. If you want to allow users to modify the characters stored in the string, then it should return a char &. (Even better, have two separate overloads, one const and one non-const.)
String operator+(const String& rhs)
{
const size_t new_len = len + rhs.len;
char* new_c_arr = new char[new_len+1];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs.c_str);
printf("new_c_arr=%s\n", new_c_arr);
return String(new_c_arr, len);
}
You are constructing the new string with the wrong length, and also leaking new_c_arr. And this function should be const (and really should be implemented in terms of operator+=, which you don't have).
String operator+(const char* rhs)
{
const size_t new_len = len + strlen(rhs) + 1;
char* new_c_arr = new char[new_len];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs);
return String(new_c_arr, new_len);
}
Leaking new_c_arr again; also, new_len here includes the null terminator, while the version in the other operator+ doesn't. Your constructor taking a length does not appear to include the null terminator as part of the length.
This is the line of problem in the method String operator+(const String& rhs):
return String(new_c_arr, len);
You need to changed to this:
return String(new_c_arr, new_len+1);
You are initializing the returning String with a length equal to the first part only. Not the whole concatenated string.
See that the other operator is OK.
By the way you're creating a lot of new char[] in the operator+ and the constructor.
In the case of the operator+ you are creating a new char[] in every call and passing to the constructor of string (not deleting after), and in the constructor are creating a new char[] to storage the string that is deleted in the destructor, the new char[] created in the operators are leaked.