Last active
December 31, 2015 06:19
-
-
Save dongguosheng/7946826 to your computer and use it in GitHub Desktop.
A string class implemented to practice C++.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "MyString.h" | |
using namespace std; | |
void testMyString(const char *, const MyString &); | |
int main(int argc, char* argv[]) | |
{ | |
const char *s = "const char *"; | |
char str[] = "char array str"; | |
//Test constructors | |
MyString str1; | |
MyString str2(s); | |
MyString str3(str, strlen(str)); | |
cout << "Test constructors" << endl; | |
cout << "-----------------------------" << endl; | |
testMyString("str1", str1); | |
testMyString("str2", str2); | |
testMyString("str3", str3); | |
//Test copy constructor | |
MyString str4(str3); | |
cout << "Test copy constructor" << endl; | |
cout << "-----------------------------" << endl; | |
testMyString("str4", str4); | |
//Test append | |
str1.append(str2); | |
str2.append(str3, 2, 2); | |
str3.append(5, 'o'); | |
cout << "Test append" << endl; | |
cout << "-----------------------------" << endl; | |
testMyString("str1", str1); | |
testMyString("str2", str2); | |
testMyString("str3", str3); | |
// //Test assign | |
str1.assign("test assign const char *"); | |
str2.assign(str3, 1, 2); | |
str3.assign("test assign const char * & n", 6); | |
str4.assign(4, 'c'); | |
cout << "Test assign" << endl; | |
cout << "-----------------------------" << endl; | |
testMyString("str1", str1); | |
testMyString("str2", str2); | |
testMyString("str3", str3); | |
testMyString("str4", str4); | |
// //Test erase | |
str3.erase(); | |
cout << "Test erase" << endl; | |
cout << "-----------------------------" << endl; | |
testMyString("str3", str3); | |
return 0; | |
} | |
void testMyString(const char * str, const MyString &myString){ | |
cout << str << " capacity: " << myString.getCapacity() << " length: " << myString.length() | |
<< " value: " << myString.data() << endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "MyString.h" | |
MyString::MyString(void) : capacity(INITIAL_CAPACITY), size(0) | |
{ | |
s_ptr = new char[INITIAL_CAPACITY]; | |
*s_ptr = '\0'; | |
} | |
MyString::~MyString(void) | |
{ | |
delete [] s_ptr; | |
s_ptr = NULL; | |
} | |
MyString::MyString(const char *str) | |
{ | |
uint_t len = strlen(str); | |
capacity = INITIAL_CAPACITY; | |
while(len + 1 > capacity){ | |
capacity *= 2; | |
} | |
s_ptr = new char[capacity]; | |
memcpy(s_ptr, str, len + 1); | |
size = len; | |
} | |
MyString::MyString(const char str[], uint_t n) : size(n) | |
{ | |
capacity = INITIAL_CAPACITY; | |
while(n + 1 > capacity){ | |
capacity *= 2; | |
} | |
s_ptr = new char[capacity]; | |
memcpy(s_ptr, str, n); | |
s_ptr[n] = '\0'; | |
} | |
MyString::MyString(const MyString& myString) : capacity(myString.capacity), size(myString.size) | |
{ | |
s_ptr = new char[capacity]; | |
memcpy(s_ptr, myString.s_ptr, myString.size + 1); | |
} | |
// append 退出时会调用MyString析构函数,所以,虽然str是copy,delete str中的char *s_ptr将会影响传入的参数; | |
// 由于返回类型的设置,导致函数返回后调用了析构函数,同上,会出现不可预料的结果(返回引用,不会发生对象拷贝,自然也不会调用析构函数) | |
MyString& MyString::append(const MyString &str) | |
{ | |
uint_t last_capacity = capacity; | |
setNewCapacity(size + str.size + 1); | |
if(capacity > last_capacity){ | |
char *result_str = new char[capacity]; | |
memcpy(result_str, s_ptr, size - 1); | |
delete[] s_ptr; | |
memcpy(result_str + size, str.s_ptr, str.size + 1); | |
s_ptr = result_str; | |
}else { | |
memcpy(s_ptr + size, str.s_ptr, str.size + 1); | |
} | |
size += str.size; | |
return *this; | |
} | |
MyString& MyString::append(const MyString &str, uint_t index, uint_t n) | |
{ | |
uint_t len_copy = index + n > str.size ? str.size - index : n; | |
uint_t last_capacity = capacity; | |
setNewCapacity(size + len_copy + 1); | |
if(capacity > last_capacity){ | |
char *result_str = new char[capacity]; | |
memcpy(result_str, s_ptr, size); | |
delete[] s_ptr; | |
memcpy(result_str + size, str.s_ptr + index, len_copy); | |
size += len_copy; | |
s_ptr = result_str; | |
}else { | |
memcpy(s_ptr + size, str.s_ptr + index, len_copy); | |
size += len_copy; | |
} | |
s_ptr[size] = '\0'; | |
return *this; | |
} | |
MyString& MyString::append(uint_t n, char ch) | |
{ | |
uint_t last_capacity = capacity; | |
setNewCapacity(size + n + 1); | |
if(capacity > last_capacity){ | |
char *result_str = new char[capacity]; | |
memcpy(result_str, s_ptr, size); | |
delete[] s_ptr; | |
memset(result_str + size, ch, n); | |
s_ptr = result_str; | |
}else { | |
memset(s_ptr + size, ch, n); | |
} | |
size += n; | |
s_ptr[size] = '\0'; | |
return *this; | |
} | |
MyString& MyString::assign(const char *chars) | |
{ | |
uint_t chars_len = strlen(chars); | |
uint_t last_capacity = capacity; | |
setNewCapacity(chars_len + 1); | |
if(capacity > last_capacity){ | |
delete [] s_ptr; | |
s_ptr = new char[capacity]; | |
} | |
memcpy(s_ptr, chars, chars_len + 1); | |
size = chars_len; | |
return *this; | |
} | |
MyString& MyString::assign(const MyString& str, uint_t index, uint_t n) | |
{ | |
uint_t len_copy = index + n > str.size ? str.size - index : n; | |
uint_t last_capacity = capacity; | |
setNewCapacity(len_copy + 1); | |
if(capacity > last_capacity){ | |
delete[] s_ptr; | |
s_ptr = new char[capacity]; | |
} | |
memcpy(s_ptr, str.s_ptr + index, len_copy); | |
size = len_copy; | |
s_ptr[size] = '\0'; | |
return *this; | |
} | |
MyString& MyString::assign(const char *chars, uint_t n) | |
{ | |
uint_t last_capacity = capacity; | |
setNewCapacity(n + 1); | |
if(capacity > last_capacity){ | |
delete[] s_ptr; | |
s_ptr = new char[capacity]; | |
} | |
memcpy(s_ptr, chars, n); | |
size = n; | |
s_ptr[size] = '\0'; | |
return *this; | |
} | |
MyString& MyString::assign(uint_t n, char ch) | |
{ | |
uint_t last_capacity = capacity; | |
setNewCapacity(n + 1); | |
if(capacity > last_capacity){ | |
delete[] s_ptr; | |
s_ptr = new char[capacity]; | |
} | |
memset(s_ptr, ch, n); | |
size = n; | |
s_ptr[size] = '\0'; | |
return *this; | |
} | |
MyString& MyString::erase(uint_t index, uint_t n) | |
{ | |
if(index >= size){ | |
cout << "Index out of range." << endl; | |
return *this; | |
} | |
if(index == 0 && n == -1){ | |
clear(); | |
} | |
else if(index + n > size){ | |
*(s_ptr + index) = '\0'; | |
size = index + 1; | |
} | |
else { | |
for(uint_t i = 0; i < n; i++){ | |
*(s_ptr + index + i) = *(s_ptr + index + n + i); | |
} | |
*(s_ptr + index + n) = '\0'; | |
size -= n; | |
} | |
return *this; | |
} | |
int MyString::compare(const MyString &str) const | |
{ | |
char *p = s_ptr; | |
const char *q = str.data(); | |
while(*p != '\0' && *q != '\0'){ | |
if(*p != *q){ | |
return *p - *q; | |
} | |
else { | |
p++; | |
q++; | |
} | |
} | |
return *p - *q; | |
} | |
int MyString::compare(uint_t index, uint_t n, const MyString &str, uint_t index_str, uint_t n_str) const | |
{ | |
if (index >= size || index_str >= str.size){ | |
cout << "Index out of range." << endl; | |
return 0; | |
} | |
else { | |
char *p = s_ptr + index; | |
const char *q = str.data() + index_str; | |
int i = 0; | |
int min_n = n > n_str? n_str: n; | |
while(*p != '\0' && *q != '\0' && i < min_n){ | |
if(*p != *q){ | |
return *p - *q; | |
} | |
else { | |
p++; q++; | |
i++; | |
} | |
} | |
return *p - *q; | |
} | |
} | |
MyString::uint_t MyString::copy(char *s, uint_t index, uint_t n) const | |
{ | |
char *p = s_ptr; | |
if(index + n > size){ | |
while(*p != '\0'){ | |
*s++ = *p++; | |
} | |
return size - index; | |
} | |
else { | |
for(uint_t i = 0; i < n; i++){ | |
s[i] = p[index + i]; | |
} | |
return n; | |
} | |
} | |
MyString MyString::substr(uint_t index, uint_t n) const | |
{ | |
if(index >= size){ | |
cout << "Index out of memory." << endl; | |
return *this; | |
} | |
if(index + n > size){ | |
return MyString(s_ptr + index); | |
}else { | |
return MyString(s_ptr + index, n); | |
} | |
} | |
MyString::uint_t MyString::find(char ch, uint_t index) const | |
{ | |
if(index >= size){ | |
cout << "Index out of range." << endl; | |
} | |
char *p = s_ptr + index; | |
uint_t i = 0; | |
while(p[i] != '\0'){ | |
if(ch == p[i]){ | |
return i + index; | |
}else { | |
i ++; | |
} | |
} | |
return -1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef MYSTRING_H | |
#define MYSTRING_H | |
#include <iostream> | |
#include <cstring> | |
using namespace std; | |
class MyString | |
{ | |
public: | |
typedef unsigned int uint_t; | |
static const uint_t INITIAL_CAPACITY = 20; | |
/* | |
* Constructs an empty string, with a length of zero characters | |
*/ | |
MyString(void); | |
~MyString(void); | |
MyString(const char *str); | |
MyString(const char chars[], uint_t size); | |
/* | |
* Copy constructor | |
*/ | |
MyString(const MyString& myString); | |
/* | |
* Extends the string by appending additional characters at the end of its current value | |
*/ | |
MyString& append(const MyString &str); | |
MyString& append(const MyString &str, uint_t index, uint_t n); | |
MyString& append(uint_t n, char ch); | |
/* | |
* Assigns a new value to the string, replacing its current contents | |
*/ | |
MyString& assign(const char *chars); | |
MyString& assign(const MyString &str, uint_t index, uint_t n); | |
/* | |
* Copies the first n characters from the array of characters pointed by s. | |
*/ | |
MyString& assign(const char *chars, uint_t n); | |
/* | |
* Replaces the current value by n consecutive copies of character c. | |
*/ | |
MyString& assign(uint_t n, char ch); | |
inline char& at(uint_t index); | |
inline const char& at(uint_t index) const; | |
inline uint_t length() const; | |
/* | |
* Erases the contents of the string, which becomes an empty string (with a length of 0 characters) | |
*/ | |
inline void clear(); | |
/* | |
* Erases part of the string, reducing its length, use default arguments | |
*/ | |
MyString& erase(uint_t index = 0, uint_t n = -1); | |
inline bool empty() const; | |
/* | |
* Compares the value of the string object | |
*/ | |
int compare(const MyString &s) const; | |
/* | |
* compare the substring of string(from index span n) to str's substring(from index_str span n_str) | |
*/ | |
int compare(uint_t index, uint_t n, const MyString &str, uint_t index_str, uint_t n_str) const; | |
/* | |
* Copies a substring of the current value of the string object into the array pointed by s. This substring contains the len characters that start at position pos. | |
* The function does not append a null character at the end of the copied content. | |
*/ | |
uint_t copy(char *s, uint_t index, uint_t n = 0) const; | |
inline const char *data() const; | |
inline uint_t getCapacity() const; | |
/* | |
* Returns a newly constructed string object with its value initialized to a copy of a substring of this object. | |
* The substring is the portion of the object that starts at character position pos and spans len characters (or until the end of the string, whichever comes first). | |
*/ | |
MyString substr(uint_t index, uint_t n) const; | |
MyString substr(uint_t index) const; | |
/* | |
* Exchanges the content of the container by the content of str, which is another string object. Lengths may differ | |
*/ | |
inline void swap(MyString &str); | |
/* | |
* Searches the string for the first occurrence of the sequence specified by its arguments. | |
*/ | |
uint_t find(char ch, uint_t index = 0) const; | |
private: | |
char *s_ptr; | |
uint_t capacity; //memory string owns | |
uint_t size; //string size | |
inline void setNewCapacity(uint_t size); | |
}; | |
inline MyString::uint_t MyString::length() const{ | |
return size; | |
} | |
inline const char* MyString::data() const { | |
return s_ptr; | |
} | |
inline char& MyString::at(uint_t index){ | |
if(size > index){ | |
return *(s_ptr + index); | |
} | |
else { | |
cout << "Index out of range." << endl; | |
} | |
} | |
inline const char& MyString::at(uint_t index) const{ | |
return this->at(index); | |
} | |
inline void MyString::clear(){ | |
if(size != 0){ | |
*s_ptr = '\0'; | |
} | |
size = 0; | |
} | |
inline bool MyString::empty() const{ | |
return size == 0 ? true : false; | |
} | |
inline void MyString::swap(MyString &str){ | |
char *temp = s_ptr; | |
s_ptr = str.s_ptr; | |
str.s_ptr = temp; | |
uint_t temp_size = size; | |
size = str.size; | |
str.size = temp_size; | |
temp_size = capacity; | |
capacity = str.capacity; | |
str.capacity = temp_size; | |
} | |
inline MyString::uint_t MyString::getCapacity() const{ | |
return capacity; | |
} | |
inline void MyString::setNewCapacity(uint_t n){ | |
while(n > capacity){ | |
capacity *= 2; | |
} | |
} | |
#endif /* MYSTRING_H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment