/* This class defnes a class to hold a chain of characters with operators and functions to easily handle the strings. Note: some assignment operators/methods allocate new memory, others just use the reference passed in parameter. */ #define USE_MAC_BOOL #ifndef __StringClass__header__ #define __StringClass__header__ #pragma once #include #include #include #include #ifdef USE_MAC_BOOL #include #endif //#define NON_MEMBER //#define COPY_CONSTRUCT /* Does not work typedef char StringClass[15]; */ class StringClass { char *itsString; int itsLength; // number of chars without ending null int itsSize; // allocated size (may be 0 if constructor with const char* called) public: static const size_t npos; // Definition of iterator typedef char* iterator; public: StringClass() { itsString = NULL; itsLength = 0; itsSize = 0; cout << "Const no param" << endl; } StringClass(int size) { itsString = new char[size]; itsLength = 0; itsSize = size; itsString[0] = 0; cout << "Const 1i param" << endl; } StringClass(const char* value) { itsString = (char*)value; itsLength = strlen(value); itsSize = 0; cout << "Const 1c param " << itsLength << endl; } StringClass(int length, char muster) { itsString = new char[length+1]; itsLength = length; itsSize = length+1; for (int idx=0; idxitsLength; itsSize = original->itsLength+1; itsString = new char[itsSize]; strcpy(itsString, original->itsString); cout << "Const* copy " << endl; } ~StringClass() { if (itsSize > 0) delete itsString; cout << "Dest" << endl; } StringClass* clone(); /* Operator overloading All operators can be overloaded except . / .* / :: / ?: / sizeof / ->* / , / (T.B.C) !!!*/ // A) Operators () / [] / -> / = must be declared as member char operator[] (int idx); const char operator[] (int idx) const; // for constant strings const StringClass* operator=(const char* value); // enables writing StringClass variable=""; StringClass* operator=(char* value); // enables writing StringClass variable= buffer; (allocated on the heap) /* Lors de la déclaration des variables, le constructeur avec un paramètre de type entier est appelé ex : StringClass test(5) dans le code, cet opérateu est applé ex : StringClass test2 ... Test2(4); */ void operator()(const int allocSize) { // Free potential already allocated memory if (itsSize > 0) delete itsString; // Allocate new size itsString = new char[allocSize]; itsLength = 0; itsSize = allocSize; cout << "Op ()" << endl; } // B) operators having a left operant of type StringClass can be defined as member or non-member routines. #ifndef NON_MEMBER #ifdef USE_MAC_BOOL Boolean operator== (const StringClass* nomDroit) const; Boolean operator== (const StringClass& nomDroit) const; // Boolean operator== (StringClass* nomDroit); // Boolean operator== (StringClass& nomDroit); Boolean operator!= (const StringClass* nomDroit) const; #else bool operator== (const StringClass* nomDroit) const; bool operator== (const StringClass& nomDroit) const; // bool operator== (StringClass* nomDroit); // bool operator== (StringClass& nomDroit); bool operator!= (const StringClass* nomDroit) const; #endif StringClass operator+ (const StringClass* nomDroit) const; StringClass operator+ (const char* nomDroit) const; StringClass& operator+= (const char* nomDroit); StringClass operator+ (const StringClass nomDroit) const; #ifdef USE_MAC_BOOL Boolean operator< (const StringClass* nomDroit) const; Boolean operator< (const StringClass nomDroit) const; #else bool operator< (const StringClass* nomDroit) const; bool operator< (const StringClass nomDroit) const; #endif #else #ifdef USE_MAC_BOOL friend Boolean operator== (const StringClass& nomGche, const StringClass* nomDroit); friend Boolean operator== (const StringClass& nomGche, const StringClass& nomDroit); // friend Boolean operator== (StringClass& nomGche, StringClass* nomDroit); // friend Boolean operator== (StringClass& nomGche, StringClass& nomDroit); friend Boolean operator!= (const StringClass& nomGche, const StringClass& nomDroit); #else #endif friend StringClass operator+ (const StringClass& nomGche, const StringClass* nomDroit); friend StringClass operator+ (const StringClass& nomGche, const char* nomDroit); friend StringClass& operator+= (StringClass& nomGche, const char* nomDroit); friend StringClass operator+ (const StringClass& nomGche, const StringClass nomDroit); #ifdef USE_MAC_BOOL friend Boolean operator< (const StringClass& nomGche, const StringClass& nomDroit); #else friend bool operator< (const StringClass& nomGche, const StringClass& nomDroit); #endif #endif // C) Other operators must be non-members // Stream extraction and insertion operators must be non-members friend istream& operator >> (istream& is, StringClass *s); // enables reading in from a stream is >> variable friend ostream& operator << (ostream& os, const StringClass* s); // enables writing in into a stream is << variable // This << overload takes an object itself as parameter (former << version takes a reference friend ostream& operator << (ostream& os, const StringClass s); // enables writing in into a stream is << variable friend StringClass operator+ (const char* nomGche, const StringClass& nomDroit); // friend StringClass& operator+= (StringClass& nomGche, const char* nomDroit); // Access methods char *String() const { return itsString; } int getLength() const { return itsLength; } void SetString(char* value); /* Standard C++ string methods */ void assign(const char* value); void swap(StringClass *str2); friend void swap(StringClass *str1, StringClass *str2); StringClass *append(StringClass *add); int size() const { return itsSize; } int length() const { return itsLength; } char *c_str() const { return itsString; } int find_first_of(const char* pattern, int start); StringClass* substr(int start); StringClass* substr(int start, int length); // Definition of iterator char* begin() { return itsString; } char* end() { return (itsString+itsLength); } }; StringClass* StringClass::clone() { StringClass *copy = new StringClass(*this); if (this->itsSize > 0) { // Also make a copy of the string buffer copy->itsString = new char[this->itsSize]; strcpy(copy->itsString, this->itsString); } return copy; } const size_t StringClass::npos = -1; /* Operators definitions ==================*/ char StringClass::operator[] (int idx) { // assert(idx>0 && idx=0 && idx0 && idx=0 && idx 0) delete itsString; itsString = (char*)value; itsLength = strlen(value); itsSize = 0; return this; } StringClass* StringClass::operator=(char* value) { itsString = value; itsLength = strlen(value); itsSize = itsLength+1; return this; } #ifndef NON_MEMBER #ifdef USE_MAC_BOOL Boolean StringClass::operator == (const StringClass* nomDroit) const { return !strcmp(itsString, nomDroit->itsString); } Boolean StringClass::operator == (const StringClass& nomDroit) const { return !strcmp(itsString, nomDroit.itsString); } /* Boolean StringClass::operator == (StringClass* nomDroit) { return !strcmp(itsString, nomDroit->itsString); } Boolean StringClass::operator == (StringClass& nomDroit) { return !strcmp(itsString, nomDroit.itsString); } */ Boolean StringClass::operator != (const StringClass* nomDroit) const { return strcmp(itsString, nomDroit->itsString); } #else bool StringClass::operator == (const StringClass* nomDroit) const { return !strcmp(itsString, nomDroit->itsString); } bool StringClass::operator == (const StringClass& nomDroit) const { return !strcmp(itsString, nomDroit.itsString); } /* bool StringClass::operator == (StringClass* nomDroit) { return !strcmp(itsString, nomDroit->itsString); } bool StringClass::operator == (StringClass& nomDroit) { return !strcmp(itsString, nomDroit.itsString); } */ bool StringClass::operator != (const StringClass* nomDroit) const { return strcmp(itsString, nomDroit->itsString); } #endif StringClass StringClass::operator+ (const StringClass* nomDroit) const { StringClass temp; temp.itsLength = this->itsLength + nomDroit->itsLength; temp.itsString = new char[temp.itsLength +1]; temp.itsSize = temp.itsLength +1; strncpy(temp.itsString, itsString, itsLength); strcpy(temp.itsString+itsLength, nomDroit->itsString); return temp; } StringClass StringClass::operator+ (const char* nomDroit) const { StringClass temp; temp.itsLength = this->itsLength + strlen(nomDroit); temp.itsString = new char[temp.itsLength +1]; temp.itsSize = temp.itsLength +1; strncpy(temp.itsString, itsString, itsLength); strcpy(temp.itsString+itsLength, nomDroit); return temp; } StringClass& StringClass::operator+= (const char* nomDroit) { char *temp; int addLgth = strlen(nomDroit); // Check if allocated memory is sufficient if (itsSize >= itsLength+addLgth+1) { strcpy(itsString+itsLength, nomDroit); itsLength += addLgth; } else { // Reallocate memory temp = new char[itsLength+addLgth+1]; strcpy(temp, itsString); strcpy(temp+itsLength, nomDroit); itsLength += addLgth; itsSize = itsLength+addLgth+1; delete itsString; itsString = temp; } return *this; } StringClass StringClass::operator+ (const StringClass nomDroit) const { StringClass temp; temp.itsLength = this->itsLength + nomDroit.itsLength; temp.itsString = new char[temp.itsLength +1]; temp.itsSize = temp.itsLength +1; strncpy(temp.itsString, this->itsString, itsLength); strcpy(temp.itsString+itsLength, nomDroit.itsString); return temp; } #ifdef USE_MAC_BOOL Boolean StringClass::operator < (const StringClass* nomDroit) const { return (strcmp(itsString, nomDroit->itsString) < 0); } Boolean StringClass::operator < (const StringClass nomDroit) const { return (strcmp(itsString, nomDroit.itsString) < 0); } #else bool StringClass::operator < (const StringClass* nomDroit) const { return (strcmp(itsString, nomDroit->itsString) < 0); } bool StringClass::operator < (const StringClass nomDroit) const { return (strcmp(itsString, nomDroit.itsString) < 0); } #endif #else #ifdef USE_MAC_BOOL Boolean operator == (const StringClass& nomGche, const StringClass* nomDroit) { return !strcmp(nomGche.String(), nomDroit->String()); } Boolean operator == (const StringClass& nomGche, const StringClass& nomDroit) { return !strcmp(nomGche.String(), nomDroit.String()); } /* Boolean operator == (StringClass& nomGche, StringClass* nomDroit) { return !strcmp(nomGche.String(), nomDroit->String()); * provoque :File ³StringClass.h²; Line 335; While compiling ³Converter.cpp² Error: can't pass const/volatile object to non-const/volatile member function Had: const StringClass * and: char *"C++"() Pb: String doit être déclarée const * * int strcmp(const char *s1, const char *s2) { char c1, c2, dif; for (;;) { if (!(c1 = *s1++)) return *s2 ? -1 : 0; if (!(c2 = *s2++)) return 1; if (!(dif = (c1 - c2))) continue; if (dif < 0) return -1; else return 1; } return 0; } * * if (nomGche.getLength() != nomDroit->getLength()) { return false; } else { char *gche, *drte, c1, c2, dif; gche = nomGche.String(); drte = nomDroit->String(); for (;;) { if (!(c1 = *gche++)) return *drte ? 0 : 1; if (!(c2 = *drte++)) return 0; if (!(dif = (c1 - c2))) continue; if (dif < 0) return 0; else return 0; } } * *} Boolean operator == (StringClass& nomGche, StringClass& nomDroit) { return !strcmp(nomGche.String(), nomDroit.String()); } */ Boolean operator != (StringClass& nomGche, StringClass& nomDroit) { // return strcmp(nomGche.String(), nomDroit.String()); if (nomGche.getLength() != nomDroit.getLength()) { return true; } else { char *gche, *drte, c1, c2, dif; gche = nomGche.String(); drte = nomDroit.String(); for (;;) { if (!(c1 = *gche++)) return *drte ? -1 : 0; if (!(c2 = *drte++)) return 1; if (!(dif = (c1 - c2))) continue; if (dif < 0) return -1; else return 1; } } } #else bool operator == (const StringClass& nomGche, const StringClass* nomDroit) { return !strcmp(nomGche.String(), nomDroit->String()); } bool operator == (const StringClass& nomGche, const StringClass& nomDroit) { return !strcmp(nomGche.String(), nomDroit.String()); } /* bool operator == (StringClass& nomGche, StringClass* nomDroit) { return !strcmp(nomGche.String(), nomDroit->String()); * provoque :File ³StringClass.h²; Line 335; While compiling ³Converter.cpp² Error: can't pass const/volatile object to non-const/volatile member function Had: const StringClass * and: char *"C++"() Pb: String doit être déclarée const * * int strcmp(const char *s1, const char *s2) { char c1, c2, dif; for (;;) { if (!(c1 = *s1++)) return *s2 ? -1 : 0; if (!(c2 = *s2++)) return 1; if (!(dif = (c1 - c2))) continue; if (dif < 0) return -1; else return 1; } return 0; } * * if (nomGche.getLength() != nomDroit->getLength()) { return false; } else { char *gche, *drte, c1, c2, dif; gche = nomGche.String(); drte = nomDroit->String(); for (;;) { if (!(c1 = *gche++)) return *drte ? 0 : 1; if (!(c2 = *drte++)) return 0; if (!(dif = (c1 - c2))) continue; if (dif < 0) return 0; else return 0; } } * *} bool operator == (StringClass& nomGche, StringClass& nomDroit) { return !strcmp(nomGche.String(), nomDroit.String()); } */ bool operator != (StringClass& nomGche, StringClass& nomDroit) { // return strcmp(nomGche.String(), nomDroit.String()); if (nomGche.getLength() != nomDroit.getLength()) { return true; } else { char *gche, *drte, c1, c2, dif; gche = nomGche.String(); drte = nomDroit.String(); for (;;) { if (!(c1 = *gche++)) return *drte ? -1 : 0; if (!(c2 = *drte++)) return 1; if (!(dif = (c1 - c2))) continue; if (dif < 0) return -1; else return 1; } } } #endif StringClass operator+ (const StringClass& nomGche, const StringClass* nomDroit) { StringClass temp; temp.itsLength = nomGche.itsLength + nomDroit->itsLength; temp.itsString = new char[temp.itsLength +1]; temp.itsSize = temp.itsLength +1; strncpy(temp.itsString, nomGche.itsString, nomGche.itsLength); strcpy(temp.itsString+nomGche.itsLength, nomDroit->itsString); return temp; } StringClass operator+ (const StringClass& nomGche, const char* nomDroit) { StringClass temp; temp.itsLength = nomGche.itsLength + strlen(nomDroit); temp.itsString = new char[temp.itsLength +1]; temp.itsSize = temp.itsLength +1; strncpy(temp.itsString, nomGche.itsString, nomGche.itsLength); strcpy(temp.itsString+nomGche.itsLength, nomDroit); return temp; } StringClass& operator+= (StringClass& nomGche, const char* nomDroit) { char *temp; int addLgth = strlen(nomDroit); // Check if allocated memory is sufficient if (nomGche.itsSize >= nomGche.itsLength+addLgth+1) { strcpy(nomGche.itsString+nomGche.itsLength, nomDroit); nomGche.itsLength += addLgth; } else { // Reallocate memory temp = new char[nomGche.itsLength+addLgth+1]; strcpy(temp, nomGche.itsString); strcpy(temp+nomGche.itsLength, nomDroit); nomGche.itsLength += addLgth; nomGche.itsSize = nomGche.itsLength+addLgth+1; delete nomGche.itsString; nomGche.itsString = temp; } return nomGche; } StringClass operator+ (const StringClass& nomGche, const StringClass nomDroit) { StringClass temp; temp.itsLength = nomGche.itsLength + nomDroit.itsLength; temp.itsString = new char[temp.itsLength +1]; temp.itsSize = temp.itsLength + 1; strncpy(temp.itsString,nomGche.itsString,nomGche.itsLength); strcpy(temp.itsString+nomGche.itsLength,nomDroit.itsString); return temp; } Boolean operator < (const StringClass& nomGche, const StringClass& nomDroit) { return (strcmp(nomGche.String(), nomDroit.String()) < 0); } #endif istream& operator >> (istream& is, StringClass *s) { #ifdef DEBUG if (s->itsSize == 0) cout << "StringClass >> with non allocated param" << endl; #endif is >> s->itsString; // Also set length & size return is; } ostream& operator << (ostream& os, const StringClass* s) { if (0 != s->itsLength) os << s->itsString; return os; } // Test with object itself ostream& operator << (ostream& os, const StringClass s) { if (0 != s.itsLength) os << s.itsString; return os; } StringClass operator+ (const char* nomGche, const StringClass& nomDroit) { StringClass temp; temp.itsSize = strlen(nomGche) + nomDroit.itsLength +1; temp.itsString = new char[temp.itsSize]; temp.itsLength = strlen(nomGche) + nomDroit.itsLength; return temp; } /* Methods definitions ================*/ /* * This routine only resuses the passed pointer whithout allocating any memory */ void StringClass::SetString(char* value) { // Deallocate memory if necessary if (itsSize > 0) delete itsString; itsLength = strlen(value); itsString = value; } /* Standard C++ string routines */ /* * This routine makes a copy of the passed string, allocating new memory if necessary */ void StringClass::assign(const char* value) { int size = strlen(value)+1; if (itsSize >= size) { // No reallocation necessary strcpy(itsString, value); } else { if (0 !=itsSize) delete itsString; itsString = new char[size]; strcpy(itsString, value); itsSize = size; } itsLength = size-1; } void StringClass::swap(StringClass *str2) { char *temp; int tmpsz,tmplg; temp = this->itsString; tmpsz = this->itsSize; tmplg = this->itsLength; // Transfer str2 into str1 this->itsString = str2->itsString; this->itsSize = str2->itsSize; this->itsLength = str2->itsLength; // and temp into str2 str2->itsString = temp; str2->itsSize = tmpsz; str2->itsLength = tmplg; /* // Optimised in // str1 = str1 xor str2 1 = 1 xor 2 (long)(str1->itsString) ^= (long)(str2->itsString); this->itsSize ^= str2->itsSize; this->itsLength ^= str2->itsLength; // str1 xor str2 = original str1 stored into str2 2 = ( 1 xor 2) xor 1 str2->itsString ^= this->itsString; str2->itsSize ^= this->itsSize; str2->itsLength ^= this->itsLength; // str1 xor str2(original str1) = original str2 stored into str1 1 = ( 1 xor 2) xor 2 this->itsString ^= str2->itsString; this->itsSize ^= str2->itsSize; this->itsLength ^= str2->itsLength; */ } void swap(StringClass *str1, StringClass *str2) { char *temp; int tmpsz,tmplg; temp = str1->itsString; tmpsz = str1->itsSize; tmplg = str1->itsLength; // Transfer str2 into str1 str1->itsString = str2->itsString; str1->itsSize = str2->itsSize; str1->itsLength = str2->itsLength; // and temp into str2 str2->itsString = temp; str2->itsSize = tmpsz; str2->itsLength = tmplg; /* // Optimised in // str1 = str1 xor str2 1 = 1 xor 2 (long)(str1->itsString) ^= (long)(str2->itsString); str1->itsSize ^= str2->itsSize; str1->itsLength ^= str2->itsLength; // str1 xor str2 = original str1 stored into str2 2 = ( 1 xor 2) xor 1 str2->itsString ^= str1->itsString; str2->itsSize ^= str1->itsSize; str2->itsLength ^= str1->itsLength; // str1 xor str2(original str1) = original str2 stored into str1 1 = ( 1 xor 2) xor 2 str1->itsString ^= str2->itsString; str1->itsSize ^= str2->itsSize; str1->itsLength ^= str2->itsLength; */ } StringClass *StringClass::append(StringClass *add) { char *buf; if ((itsSize-itsLength-1) < add->itsLength) { // a reallocation is necessary buf = new char[itsLength+add->itsLength+1]; itsSize = itsLength+add->itsLength+1; strcpy(buf, itsString); strcpy(buf+itsLength, add->itsString); delete itsString; itsString = buf; } else { strcpy(itsString+itsLength, add->itsString); } itsLength += add->itsLength; return this; } int StringClass::find_first_of(const char* pattern, int start) { char *index; int firstpos; #ifdef USE_MAC_BOOL Boolean found = false; #else bool found = false; #endif firstpos = strlen(itsString); for (int idx=0; idxitsLength = itsLength-start+1; strcpy(result->itsString, itsString+start); #ifdef DEBUG if (0 != *(result->itsString+itsLength-start)) { cout << "Strcpy did not 0 term!" << endl; } #endif *(result->itsString+itsLength-start) = 0; return result; } /* Generates an new instance of string and sets its value to source[start .. start+length] */ StringClass* StringClass::substr(int start, int length) { StringClass *result; result = new StringClass(length+1); result->itsLength = length; strncpy(result->itsString, itsString+start, length); #ifdef DEBUG if (0 != *(result->itsString+length)) { cout << "Strncpy did not 0 term!" << endl; } #endif *(result->itsString+length) = 0; return result; } #include //#define DEBUG StringClass itos(int value) { StringClass temp; int length, denom; double logval,dummy; div_t digit; // use ldiv_t for long values char *buf; // Determine string length logval = log10(value); length = ceil(logval); if (0 == modf(logval, &dummy)) { // value is multiple of 10 ++length; } #ifdef DEBUG cout << "itos : log lgth: " << logval << " " << length << "/"; #endif buf = new char[length+1]; // Perform conversion denom = pow(10,length-1); for (int idx=0; idx