Is this String class properly implemented?
I am new to the C++ language, I implement this String class just for
practising.
I want to know what to improve to make it *qualified* to be used in
real programs, or what code should be changed to make it more
efficient...yea, I know you will recommend me to using std::string,
(-:just practising...
Here's the code:
#ifndef STRING_H_
#define STRING_H_
#include "Core.h"
class String{
private:
wchar_t* value;
int size;
public:
String();
String(const wchar_t* src);
String(const wchar_t* src, int offset, int count);
String(String& s);
String(const int& num);
String(const long& l);
String(const float& f);
String(const double& d);
String(const wchar_t& c);
operator const wchar_t* () const {
return value;
}
~String(){
size = 0;
delete [] value;
}
int length() const;
const wchar_t& wchar_tAt(int index) const;
//the length of the substring is endIndex-beginIndex
String substring(int beginIndex, int endIndex) const;
String substring(int beginIndex) const;
int indexOf(const wchar_t& c) const;
int indexOf(const wchar_t& c, int fromIndex) const;
int indexOf(const String& s) const;
int indexOf(const String& s, int fromIndex) const;
int indexOf(const wchar_t* s) const;
int indexOf(const wchar_t* s, int fromIndex) const;
int lastIndexOf(wchar_t c) const;
int lastIndexOf(wchar_t c, int fromIndex) const;
int lastIndexOf(const String& s) const;
int lastIndexOf(const String& s, int fromIndex) const;
int lastIndexOf(const wchar_t* s) const;
int lastIndexOf(const wchar_t* s, int fromIndex) const;
/*
//these two functions cannot be properly implemented using plain
pointers, an Array class is required?
String** split(const wchar_t& c) const;
String** split(const String& s) const;
*/
String toLowerCase() const;
String toUpperCase() const;
bool isEmpty() const;
bool startsWith(const String* s) const;
bool endsWith(const String* s) const;
bool startsWith(const wchar_t* s) const;
bool endsWith(const wchar_t* s) const;
bool equals(const String* s) const;
bool equals(const wchar_t* s) const;
String trim();
String trimLeft();
String trimRight();
const wchar_t* toCString() const;
String& operator+=(const String& str);
String& operator+=(const wchar_t* str);
String operator=(String& str);
String operator=(const wchar_t* str);
String operator+(const wchar_t* str) const;
bool operator==(const String* s) const;
};
String operator+(const String& str1, const String& str2);
String operator+(const wchar_t* str1, const String& str2);
#endif
#include "String.h"
String::String(){
size = 0;
value = new wchar_t[1]; //one wchar_t to store the terminating null
value[0] = '\0';
}
String::String(const int& num) {
if(num == minInteger)
String(L"-2147483648");
else{
int lenOfNumeric = num < 0 ? ::getLengthOfNumeric<int>(-num) +
1 : ::getLengthOfNumeric<int>(num);
value = new wchar_t[lenOfNumeric + 1];
::getChars(num, value, lenOfNumeric);
value[lenOfNumeric] = '\0';
size = lenOfNumeric;
}
}
String::String(const long& num) {
if(num == minInteger)
String(L"-2147483648");
else{
int lenOfNumeric = num < 0 ? ::getLengthOfNumeric<long>(-num) +
1 : ::getLengthOfNumeric<long>(num);
value = new wchar_t[lenOfNumeric + 1];
::getChars(num, value, lenOfNumeric);
value[lenOfNumeric] = '\0';
size = lenOfNumeric;
}
}
//will fail if str is null
String::String(const wchar_t* str){
size = wcslen(str);
value = new wchar_t[size + 1];
if(size > 0)
wcscpy(value, str);
else
value[0] = '\0';
}
//copy constructor
String::String(String& s){
size = s.length();
if(size == 0){
value = new wchar_t[1];
value[0] = '\0';
}else{
value = new wchar_t[size + 1];
wcscpy(value, s.value);
}
}
//will fail if str is null
String::String(const wchar_t* str, int offset, int count){
size = 0;
int len = wcslen(str);
if(len == 0 || offset >= len){
//in this case, create an empty String
value = new wchar_t[1];
value ='\0';
}else{
if(offset < 0) offset = 0;
if(count > len - offset) count = len - offset;
value = new wchar_t[count + 1];
int index = 0;
int endIndex = offset + count;
for(int i = offset; i < endIndex; ++i){
value[index] = str[i];
++index;
}
value[index] = '\0';
//only in this case will the size of the String be changed
size = count;
}
}
int String::length() const {
return size;
}
const wchar_t& String::wchar_tAt(int index) const{
if(size == 0 || index < 0 || index >= size) throw
StringIndexOutOfBoundsException(new String(L"out of bounds."));
return value[index];
}
String String::substring(int beginIndex, int endIndex) const {
if(size == 0 || beginIndex < 0 || beginIndex >= size) throw
StringIndexOutOfBoundsException(new String(L"out of bounds."));
if(endIndex > size) throw StringIndexOutOfBoundsException(new String
(L"out of bounds."));
if(beginIndex > endIndex) throw StringIndexOutOfBoundsException(new
String(L"out of bounds."));
wchar_t* temp = new wchar_t[endIndex - beginIndex + 1];
int index = 0;
for(int i = beginIndex; i < endIndex; ++i){
temp[index] = value[i];
++index;
}
temp[index] = '\0';
String s(temp);
delete [] temp;
return s;
}
String String::substring(int beginIndex) const{
if(size == 0 || beginIndex < 0 || beginIndex >= size) throw
StringIndexOutOfBoundsException(new String(L"out of bounds."));
return substring(beginIndex, size);
}
int String::indexOf(const wchar_t& c) const {
return indexOf(c, 0);
}
int String::indexOf(const wchar_t& c, int fromIndex) const {
if(fromIndex < 0) fromIndex = 0;
else if(fromIndex >= size) return -1;
for(int i = fromIndex; i < size; ++i){
if(value[i] == c)
return i;
}
return -1;
}
int String::indexOf(const String& s) const {
return indexOf(s.toCString());
}
int String::indexOf(const String& s, int fromIndex) const {
return indexOf(s.toCString(), fromIndex);
}
int String::indexOf(const wchar_t* s) const {
return indexOf(s, 0);
}
int String::indexOf(const wchar_t* s, int fromIndex) const {
if(!s || size == 0) return -1;
if(fromIndex < 0) fromIndex = 0;
else if(fromIndex >= size) return -1;
int len = wcslen(s);
if(len == 0) return -1;
if(len + fromIndex > size) return -1;
int countMatched = 0;
int firstFoundIndex = 0;
for(int i = fromIndex; i < size; ++i){
firstFoundIndex = i;
countMatched = 0;
if(value[i] == s[countMatched]){//found first letter
do{
++countMatched;
if(countMatched == len) return i; //if all chars in "s" are found
in a row, then the search is a success, return the index
++firstFoundIndex;
}while(firstFoundIndex < size && value[firstFoundIndex] == s
[countMatched]); //ensures that the loop does not step over bounds
}
}
return -1;
}
int String::lastIndexOf(wchar_t c) const {
return lastIndexOf(c, size - 1);
}
int String::lastIndexOf(wchar_t c, int fromIndex) const {
if(size == 0 || fromIndex < 0) return -1;
if(fromIndex >= size) fromIndex = size - 1;
for(int i = fromIndex; i >= 0; --i){
if(value[i] == c)
return i;
}
return -1;
}
int String::lastIndexOf(const String& s) const {
return lastIndexOf(s.toCString(), size - 1);
}
int String::lastIndexOf(const String& s, int fromIndex) const {
return lastIndexOf(s.toCString(), fromIndex);
}
int String::lastIndexOf(const wchar_t* s) const {
return lastIndexOf(s, size - 1);
}
int String::lastIndexOf(const wchar_t* s, int fromIndex) const {
if(!s || size == 0) return -1;
if(fromIndex < 0) return -1;
else if(fromIndex >= size) fromIndex = size - 1;
int len = wcslen(s);
if(len == 0) return -1;
int countMatched = 0;
int firstFoundIndex = 0;
for(int i = fromIndex; i >= 0; --i){
firstFoundIndex = i;
countMatched = 0;
if(value[i] == s[countMatched]){//found first letter
do{
++countMatched;
if(countMatched == len) return i; //if all chars in "s" are found
in a row, then the search is a success, return the index
++firstFoundIndex;
}while(firstFoundIndex < size && value[firstFoundIndex] == s
[countMatched]); //ensures that the loop does not step over bounds
}
}
return -1;
}
String String::toLowerCase() const {
if(size == 0) return String();
wchar_t* temp = new wchar_t[size + 1];
for(int i = 0; i < size; ++i){
if(value[i] >= 65 && value[i] <= 90)
temp[i] = value[i] | 0x20; //convert to lower case
else
temp[i] = value[i];
}
temp[size] = '\0';
String s(temp);
delete [] temp;
return s;
}
String String::toUpperCase() const {
if(size == 0) return String();
wchar_t* temp = new wchar_t[size + 1];
for(int i = 0; i < size; ++i){
if(value[i] >= 97 && value[i] <= 122)
temp[i] = value[i] & 0x5F; //convert to upper case
else
temp[i] = value[i];
}
temp[size] = '\0';
String s(temp);
delete [] temp;
return s;
}
bool String::isEmpty() const {
if(size > 0) return false;
return true;
}
String String::trimLeft() {
if(size == 0) return *this;
int beginIndex = 0;
if(value[beginIndex] == ' '){ //if the String starts with a space
while(++beginIndex < size)
if(value[beginIndex] != ' ')
return substring(beginIndex, size);
}
return *this;
}
String String::trimRight() {
if(size == 0) return *this;
int endIndex = size - 1;
if(value[endIndex] == ' '){ //if the String ends with a space,
which precedes the terminating '\0'
while(--endIndex >= 0)
if(value[endIndex] != ' ')
return substring(0, ++endIndex); //++endIndex is a must, since
length of the substring is endIndex-beginIndexx
}
return *this;
}
String String::trim(){
if(size == 0) return *this;
int beginIndex = 0;
int endIndex = size - 1;
if(value[beginIndex] == ' '){ //if the String starts with a space
while(++beginIndex < size)
if(value[beginIndex] != ' ')
break;
}
if(value[endIndex] == ' '){ //if the String ends with a space,
which precedes the terminating '\0'
while(--endIndex >= 0)
if(value[endIndex] != ' '){
++endIndex;
break;
}
}
if(beginIndex != 0 || endIndex != size - 1)
return substring(beginIndex, endIndex);
return *this;
}
bool String::startsWith(const String* s) const {
if(!s) return false;
if(this == s || (size == 0 && s->length() == 0)) return true;
if(size < s->length()) return false;
for(int i = 0; i < s->length(); ++i){
if(value[i] != s->value[i])
return false;
}
return true;
}
bool String::startsWith(const wchar_t* s) const {
if(!s) return false;
int len = wcslen(s);
if(size == 0 && len == 0) return true;
if(size < len) return false;
for(int i = 0; i < len; ++i){
if(value[i] != s[i])
return false;
}
return true;
}
bool String::endsWith(const String* s) const {
if(!s) return false;
if(this == s || (size == 0 && s->length() == 0)) return true;
if(size < s->length()) return false;
int oriStrIndex = size;
for(int i = s->length() - 1; i >= 0; --i){
if(value[--oriStrIndex] != s->value[i])
return false;
}
return true;
}
bool String::endsWith(const wchar_t* s) const {
if(!s) return false;
int len = wcslen(s);
if(size == 0 && len == 0) return true;
if(size < len) return false;
int oriStrIndex = size;
for(int i = len - 1; i >= 0; --i){
if(value[--oriStrIndex] != s[i])
return false;
}
return true;
}
bool String::equals(const wchar_t* s) const {
if(!s) return false;
int len = wcslen(s);
if(size == 0 && len == 0) return true;
if(size != len) return false;
for(int i = 0; i < size; ++i){
if(value[i] != s[i]) return false;
}
return true;
}
bool String::equals(const String* s) const {
if(!s) return false;
if(this == s || (size == 0 && s->length() == 0)) return true;
if(size != s->length()) return false;
for(int i = 0; i < size; ++i){
if(value[i] != s->value[i]) return false;
}
return true;
}
/*
static String valueOf(long l);
static String valueOf(float f);
static String valueOf(double d);
static String valueOf(wchar_t c);
*/
String operator +(const String& str1, const String& str2){
if(str1.length() == 0 && str2.length()) return String();
wchar_t* temp = new wchar_t[str1.length() + str2.length() + 1];
temp[0] = '\0';
if(str1.length() > 0)
wcscpy(temp, str1.toCString());
if(str2.length() > 0)
wcscat(temp, str2.toCString());
String s(temp);
delete [] temp;
return s;
}
String String::operator +(const wchar_t* str) const{
if(!str) return String(value);
int len = wcslen(str);
if(len == 0) return String(value);
wchar_t* temp = new wchar_t[size + len + 1];
temp[0] = '\0';
wcscpy(temp, value);
wcscat(temp, str);
String s(temp);
delete [] temp;
return s;
}
String operator+(const wchar_t* str1, const String& str2) {
int size = 0;
if(!str1) size = wcslen(str1);
wchar_t* temp = new wchar_t[size + str2.length() + 1];
temp[0] = '\0';
if(size > 0)
wcscpy(temp, str1);
if(str2.length() > 0)
wcscat(temp, str2.toCString());
String s(temp);
delete [] temp;
return s;
}
String& String::operator +=(const String& str) {
if(str.length() == 0) return *this;
size += str.length();
wchar_t* temp = new wchar_t[size + 1];
temp[0] = '\0';
wcscpy(temp, value);
wcscat(temp, str.toCString());
delete [] value;
value = temp;
return *this;
}
String& String::operator +=(const wchar_t* str) {
if(!str) return *this;
int len = wcslen(str);
if(len == 0) return *this;
size += len;
wchar_t* temp = new wchar_t[size + 1];
temp[0] = '\0';
wcscpy(temp, value);
wcscat(temp, str);
delete [] value;
value = temp;
return *this;
}
String String::operator =(String& str) {
return str;
}
String String::operator =(const wchar_t* str) {
if(!str) return String();
return String(str);
}
bool String::operator ==(const String* s) const{
return this == s;
}
//ensures that the returned C-style string cannot be changed
const wchar_t* String::toCString() const {
return value;
}