Vous pouvez récupérer tous les programmes en un seul tar.gz sur Telecharger String . Pour obtenir ce fichier, dans un butineur web, sauvez ce fichier en type 'texte'.
// // Auteur : Al Dev // Utilisez la classe string ou cette classe // // Pour prévenir les fuites de mémoire - une classe caractère qui gère les // variables caractères. // Préférez toujours l'utilisation de la classe string à char[] et char *. // // // Pour compiler et tester ce programme, utilisez - // g++ String.cpp #include "String.h" //#include <sys/va_list.h> pour Format() //#include <sys/varargs.h> pour Format() // Variables globales.... //String *String::_global_String = NULL; // variable globale list<String> String::explodeH; String::String() { debug_("In cstr()", "ok"); sval = (char *) my_malloc(sizeof(char)* INITIAL_SIZE); _pString = NULL; } String::String(char *bb) { unsigned long tmpii = strlen(bb); sval = (char *) my_malloc(sizeof(char)* tmpii); strncpy(sval, bb, tmpii); sval[tmpii] = '\0'; //debug_("In cstr(char *bb) bb", bb); debug_("In cstr(char *bb) sval", sval); #ifdef DEBUG //fprintf(stderr, "\nAddress of sval=%x\n", & sval); //fprintf(stderr, "\nAddress of this-pointer=%x\n", this); #endif // DEBUG _pString = NULL; } String::String(char *bb, int start, int slength) { unsigned long tmpii = strlen(bb); if (start> (int) tmpii || start < 0) { cerr << "\nString(char *, int, int) - start is out of bounds!!\n" << endl; exit(1); } sval = (char *) my_malloc(sizeof(char)* slength); strncpy(sval, & bb[start], slength); sval[slength] = '\0'; //debug_("In cstr(char *bb) bb", bb); debug_("In cstr(char *bb) sval", sval); #ifdef DEBUG //fprintf(stderr, "\nAddress of sval=%x\n", & sval); //fprintf(stderr, "\nAddress of this-pointer=%x\n", this); #endif // DEBUG _pString = NULL; } String::String(int bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // int avec 70 chiffres max sprintf(sval, "%d", bb); debug_("In cstr(int bb) sval", sval); _pString = NULL; } String::String(unsigned long bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // unsigned long avec 70 chiffres max sprintf(sval, "%lu", bb); debug_("In cstr(unsigned long bb) sval", sval); _pString = NULL; } String::String(long bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // long avec 70 chiffres max sprintf(sval, "%ld", bb); debug_("In cstr(long bb) sval", sval); _pString = NULL; } String::String(float bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // float avec 70 chiffres max sprintf(sval, "%f", bb); debug_("In cstr(float bb) sval", sval); _pString = NULL; } String::String(double bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // double avec 70 chiffres max sprintf(sval, "%f", bb); debug_("In cstr(double bb) sval", sval); _pString = NULL; } // Constructeur par recopie utilisé par l'opérateur + String::String(const String & rhs) { // Effectue une copie en profondeur à la place de la copie superficielle par défaut du compilateur debug_("In copy-cstr()", "ok"); unsigned long tmpii = strlen(rhs.sval); sval = (char *) my_malloc(sizeof(char)* tmpii); strncpy(sval, rhs.sval, tmpii); sval[tmpii] = '\0'; _pString = NULL; } // Cette fonction fournit une compatibilité avec le code Java String::String(StringBuffer sb) { debug_("In String(StringBuffer)", "ok"); unsigned long tmpii = strlen(sb.sval); sval = (char *) my_malloc(sizeof(char)* tmpii); strncpy(sval, sb.sval, tmpii); sval[tmpii] = '\0'; _pString = NULL; } // Utilisé par la classe StringBuffer. Utilise la variable dummy // pour différentes signatures. // La classe StringBuffer imite le StringBuffer de Java String::String(int size, bool dummy) { sval = (char *) my_malloc(sizeof(char)* size); debug_("In cstr(int size, bool dummy) sval", sval); #ifdef DEBUG //fprintf(stderr, "\nAddress of sval=%x\n", & sval); //fprintf(stderr, "\nAddress of this-pointer=%x\n", this); #endif // DEBUG _pString = NULL; } String::~String() { debug_("In dstr sval", sval); #ifdef DEBUG //fprintf(stderr, "\nAddress of sval=%x\n", & sval); //fprintf(stderr, "\nAddress of this-pointer=%x\n", this); #endif // DEBUG my_free(sval); //delete [] sval; sval = NULL; delete _pString; _pString = NULL; } inline void String::_allocpString() { // _pString will be deleted in destructor if (!_pString) // if (_pString == NULL) _pString = new String(this->sval); else *_pString = this->sval; } // DOIT utiliser un pointeur-sur-pointeur **aa, sinon la mémoire utilisée // par l'argument N'est PAS libérée ! /* inline void String::_free_glob(String **aa) { debug_("called _free_glob()", "ok" ); if (*aa != NULL) // (*aa != NULL) { debug_("*aa is not null", "ok"); delete *aa; *aa = NULL; } //else debug_("*aa is null", "ok"); //if (*aa == NULL) debug_("*aa set to null", "ok"); } */ // Imite le charAt de java.lang.String char String::charAt(int where) { verifyIndex(where); return (sval[where]); } // Imite la fonction getChars de java.lang.String // sourceStart spécifie l'indice du début de la sous-chaîne // et sourceEnd spécifie l'indice juste après la fin de la sous-chaîne désirée // Ainsi la sous-chaîne contient les caractères de sourceStart jusqu'à // (sourceEnd - 1). Le tableau qui va recevoir les caractères est target. // targetStart est l'indice dans target à partir duquel la copie sera effectuée. // Il convient de s'assurer que le tableau target est assez grand pour pouvoir contenir // le nombre de caractères désiré. // Par exemple getChars(3, 6, aa, 0) sur "ABCDEFGHIJK" donne aa ="DEF" void String::getChars(int sourceStart, int sourceEnd, char target[], int targetStart) { verifyIndex(sourceStart); verifyIndex(sourceEnd); if (sourceEnd>= sourceStart) { strncpy(& target[targetStart], & sval[sourceStart], sourceEnd - sourceStart); target[targetStart + (sourceEnd - sourceStart)] = 0; } else { cerr << "\ngetChars() - SourceEnd is greater than SourceStart!!\n" << endl; exit(1); } } // Imite getChars de java.lang.String // Retourne un tableau caractères contenant la chaîne entière char* String::toCharArray() { return (sval); } // Imite getBytes de java.lang.String // Retourne un tableau caractères contenant la chaîne entière char* String::getBytes() { return (sval); } // Imite equals de java.lang.String bool String::equals(String str2) // voir aussi l'opérateur == { return ( _equalto(str2.sval)); } // Imite equals de java.lang.String bool String::equals(char *str2) // voir aussi l'opérateur == { return ( _equalto(str2)); } // Imite equalsIgnoreCase de java.lang.String bool String::equalsIgnoreCase(String str2) { String aa, bb; aa = this->toLowerCase(); bb = str2.toLowerCase(); return ( aa._equalto(bb.sval) ); } // Imite regionMatches de java.lang.String // startIndex spécifie l'indice à partir duquel débute la région dans l'objet // String invoquant la méthode. La chaîne est comparée à str2. L'indice à partir // duquel la comparaison commencera dans str2 est spécifié par str2Index // La longueur de la sous-chaîne comparée est numChars. bool String::regionMatches(int startIndex, String str2, int str2StartIndex, int numChars) { verifyIndex(startIndex); str2.verifyIndex(str2StartIndex); if (strncmp(& this->sval[startIndex], & str2.sval[str2StartIndex], numChars) == 0) return true; else return false; } // Imite regionMatches de java.lang.String // Il s'agit de la version surchargée de regionMatches // Si ignoreCase vaut true, la casse des caractères est ignorée, sinon // la casse est significative (i.e. si ignoreCase vaut true alors ignore la // casse et compare) // startIndex spécifie l'indice à partir duquel débute la region dans l'objet // String invoquant la méthode. La chaîne est comparée à str2. L'indice à partir // duquel la comparaison commencera dans str2 est spécifié par str2Index // La longueur de la sous-chaîne comparée est numChars. bool String::regionMatches(bool ignoreCase, int startIndex, String str2, int str2StartIndex, int numChars) { if (ignoreCase) // if (ignoreCase == true) { verifyIndex(startIndex); str2.verifyIndex(str2StartIndex); String string1, string2; string1 = this->toLowerCase(); string2 = str2.toLowerCase(); if (strncmp(& string1.sval[startIndex], & string2.sval[str2StartIndex], numChars) == 0) return true; else return false; } else { return regionMatches(startIndex, str2, str2StartIndex, numChars); } } // Imite toLowerCase de java.lang.String // String ss("sometest"); // String egg = ss.toLowerCase(); String String::toLowerCase() { _allocpString(); for (long tmpii = strlen(_pString->sval); tmpii>= 0; tmpii--) { _pString->sval[tmpii] = tolower(_pString->sval[tmpii]); } return *_pString; // return the object now } // Imite toUpperCase de java.lang.String // String ss("sometest"); // String egg = ss.toUpperCase(); String String::toUpperCase() { _allocpString(); for (long tmpii = strlen(_pString->sval); tmpii>= 0; tmpii--) { _pString->sval[tmpii] = toupper(_pString->sval[tmpii]); } return *_pString; // return the object now } // Imite startsWith de java.lang.String bool String::startsWith(String str2) { if (!strncmp(this->sval, str2.sval, strlen(str2.sval) )) // if (strncmp() == 0) return true; else return false; } // Imite startsWith de java.lang.String // Fonction surchargée bool String::startsWith(char *str2) { int lenstr2 = strlen(str2); if (!strncmp(this->sval, str2, lenstr2)) // if (strncmp() == 0) return true; else return false; } // Imite endsWith de java.lang.String bool String::endsWith(String str2) { // str2 doit être plus courte que la chaîne courante if (strlen(str2.sval)> strlen(sval)) return false; if (!strncmp(& this->sval[strlen(sval) - strlen(str2.sval)], str2.sval, strlen(str2.sval) )) // if (strncmp() == 0) return true; else return false; } // Imite endsWith de java.lang.String bool String::endsWith(char *str2) { // str2 doit être plus courte que la chaîne courante if (strlen(str2)> strlen(sval)) return false; if (!strncmp(& this->sval[strlen(sval) - strlen(str2)], str2, strlen(str2) ) ) // if (strncmp() == 0) return true; else return false; } // Imite compareTo de java.lang.String // Pour les tris, vous devez savoir si l'un est plus petit, égal ou plus grand que l'autre. // Une chaîne est plus petite qu'une autre si elle arrive avant l'autre dans l'ordre // lexicographique. Un chaîne est plus grande qu'une autre si elle arrive après. // Négatif --> la chaîne courante est plus petite que str2 // Positif --> la chaîne courante est plus grande que str2 // Zero --> les deux chaînes sont égales int String::compareTo(String str2) { int flag = 0; // Compare les lettres dans la chaîne à chaque lettre de str2 for (int tmpii = 0, tmpjj = strlen(sval), tmpkk = strlen(str2.sval); tmpii < tmpjj; tmpii++) { if (tmpii> tmpkk) break; if (sval[tmpii] == str2.sval[tmpii]) flag = 0; else if (sval[tmpii]> str2.sval[tmpii]) { flag = 1; break; } else // if (sval[tmpii] < str2.sval[tmpii]) { flag = -1; break; } } return flag; } // Imite compareTo de java.lang.String // Fonction surchargée de compareTo int String::compareTo(char *str2) { int flag = 0; // Compare les lettres de la chaîne courante avec chaque lettre de str2 for (int tmpii = 0, tmpjj = strlen(sval), tmpkk = strlen(str2); tmpii < tmpjj; tmpii++) { if (tmpii> tmpkk) break; if (sval[tmpii] == str2[tmpii]) flag = 0; else if (sval[tmpii]> str2[tmpii]) { flag = 1; break; } else // if (sval[tmpii] < str2[tmpii]) { flag = -1; break; } } return flag; } // Imite compareToIgnoreCase de java.lang.String int String::compareToIgnoreCase(String str2) { String tmpaa = this->toLowerCase(), tmpbb = str2.toLowerCase(); return tmpaa.compareTo(tmpbb); } // Imite compareToIgnoreCase de java.lang.String // Version surchargée int String::compareToIgnoreCase(char *str2) { String tmpaa = this->toLowerCase(), tmpcc(str2), tmpbb = tmpcc.toLowerCase(); return tmpaa.compareTo(tmpbb); } // Imite indexOf de java.lang.String // Cherche la premiere occurrence d'un caractère ou d'une chaîne. // Retourne l'indice à partir duquel le caractère ou la chaîne // a été trouvé, ou -1 en cas d'échec. int String::indexOf(char ch, int startIndex = 0) { verifyIndex(startIndex); int ii = startIndex; for (; ii < (int) strlen(sval); ii++) { if (sval[ii] == ch) break; } if (ii == (int) strlen(sval)) return -1; return ii; } // Imite indexOf de java.lang.String // Version surchargée int String::indexOf(char *str2, int startIndex = 0) { verifyIndex(startIndex); char * tok; long res = -1; if ( !isNull() ) { tok = strstr(sval + startIndex, str2); if (tok == NULL) res = -1; else res = (int) (tok - sval); } return res; } // Imite indexOf de java.lang.String // Version surchargée int String::indexOf(String str2, int startIndex = 0) { verifyIndex(startIndex); char * tok; long res = -1; if ( !isNull() ) { tok = strstr(sval + startIndex, str2.sval); if (tok == NULL) res = -1; else res = (int) (tok - sval); } return res; } // Imite lastIndexOf de java.lang.String // Cherche pour la dernière occurrence d'un caractère ou d'une chaîne. // Retourne l'indice à partir duquel le caractère ou la chaîne a été trouvé // ou -1 en cas d'échec. int String::lastIndexOf(char ch, int startIndex = 0) { verifyIndex(startIndex); int ii; // Commence la recherche par le dernier caractère de la chaîne if (!startIndex) // if (startIndex == 0) ii = strlen(sval); else ii = startIndex; for (; ii> -1; ii--) { if (sval[ii] == ch) break; } if (!ii && sval[ii] != ch) // if (ii == 0) return -1; return ii; } // Imite lastIndexOf de java.lang.String // Version surchargée int String::lastIndexOf(char *str2, int startIndex = 0) { verifyIndex(startIndex); char *tok = NULL; int res = -1; register char *tmpaa = strdup(sval); // ici malloc if (!tmpaa) // tmpaa == NULL { cerr << "\nMemory alloc failed in strdup in lastIndexOf()\n" << endl; exit(-1); } if (!startIndex) // if (startIndex == 0) startIndex = strlen(sval); else tmpaa[startIndex+1] = 0; for (int ii = 0; ii <= startIndex; ii++) { tok = strstr(& tmpaa[ii], str2); if (tok == NULL) break; else { res = (int) (tok - tmpaa); debug_("res", res); ii = res; // saute vers l'endroit qui correspond (+1 dans la boucle for) } } free(tmpaa); debug_("res", res); debug_("indexOf", & sval[res]); return res; } // Imite lastIndexOf de java.lang.String // Version surchargée int String::lastIndexOf(String str2, int startIndex = 0) { verifyIndex(startIndex); char *tok = NULL; int res = -1; register char *tmpaa = strdup(sval); // ici malloc if (!tmpaa) // tmpaa == NULL { cerr << "\nMemory alloc failed in strdup in lastIndexOf()\n" << endl; exit(-1); } if (!startIndex) // if (startIndex == 0) startIndex = strlen(sval); else tmpaa[startIndex+1] = 0; for (int ii = 0; ii <= startIndex; ii++) { tok = strstr(& tmpaa[ii], str2.sval); if (tok == NULL) break; else { res = (int) (tok - tmpaa); debug_("res", res); ii = res; // saute vers l'endroit qui correspond (+1 dans la boucle for) } } free(tmpaa); debug_("res", res); debug_("indexOf", & sval[res]); return res; } // Imite substring de java.lang.String // startIndex spécifie l'indice de début, et endIndex l'indice de fin. // La chaîne retournée contient tous les caractères de l'indice de début // jusqu'à l'indice de fin, mais sans l'inclure. String String::substring(int startIndex, int endIndex = 0) { String tmpstr = String(sval); tmpstr._substring(startIndex, endIndex); return tmpstr; } // Imite concat de java.lang.String String String::concat(String str2) { return (*this + str2); } // Imite concat de java.lang.String // Version surchargée String String::concat(char *str2) { return (*this + str2); } // Imite replace de java.lang.String // Remplace toutes les occurrences de la chaîne 'original' par // 'replacement' dans 'sval' String String::replace(char original, char replacement) { // Par exemple - // replace('A', 'B') dans sval = "des AAA et AAACC" // retourne sval = "des BBB et BBBCC" //String *tmpstr = new String(sval); Utilise le constructeur de recopie par défaut String tmpstr(sval); for (int ii = 0, len = strlen(sval); ii < len; ii++) { if (tmpstr.sval[ii] == original) tmpstr.sval[ii] = replacement; } return tmpstr; // utilise le constructeur de recopie pour faire une copie } // Imite replace de java.lang.String // Version surchargée // Remplace toutes les occurrences de la chaîne 'original' par // 'replacement' dans 'sval' String String::replace(char *original, char *replacement) { char *tok = NULL, *bb; register char *aa = strdup(sval); int lenrepl = strlen(replacement); // Alloue l'espace pour bb { // portée locale int tmpii = 0; for (int ii = 0; ;ii++) { tok = strstr(& aa[ii], original); if (tok == NULL) break; else { ii = ii + (int) (tok -aa); tmpii++; } } if (!tmpii) // tmpii == 0, pas de 'original' trouvé return (String(sval)); // retourne la chaîne originale tmpii = strlen(sval) + (tmpii * lenrepl) + 20; debug_("strstr tmpii", tmpii ); bb = (char *) malloc(tmpii); memset(bb, 0, tmpii); } for (int res = -1; ;) { debug_("aa", aa); tok = strstr(aa, original); if (tok == NULL) { strcat(bb, aa); break; } else { res = (int) (tok - aa); strncat(bb, aa, res); strcat(bb, replacement); //bb[strlen(bb)] = 0; debug_("res", res ); debug_("bb", bb ); strcpy(aa, & aa[res+lenrepl]); } } debug_("bb", bb ); free(aa); String tmpstr(bb); free(bb); return tmpstr; } /* une autre méthode pour faire le remplacement mais lente... String String::replace(char *original, char *replacement) { // Par exemple - // replace("AAA", "BB") avec sval = "des AAA et AAACC" // retourne sval = "des BB et BBCC" String bb(this->before(original).sval); if (strlen(bb.sval) == 0) return String(sval); // retourne la chaîne originale bb += replacement; String tmpaa(this->sval), cc, dd; for (;;) { cc = tmpaa.after(original).sval; debug_("cc", cc.sval ); if (!strlen(cc.sval)) // if (strlen(cc.sval) == 0) break; dd = cc.before(original).sval; if (strlen(dd.sval) == 0) { bb += cc; break; } else { bb += dd; bb += replacement; } tmpaa = cc; } debug_("bb.sval", bb.sval ); return bb; } */ // Imite replace de Java - StringBuffer String String::replace (int startIndex, int endIndex, String str) { verifyIndex(startIndex); verifyIndex(endIndex); int tmpjj = strlen(str.sval); if (tmpjj == 0) return *this; int tmpii = endIndex-startIndex-1; if (tmpjj < tmpii) // la longueur de str est plus petite que les indices specifies. tmpii = tmpjj; debug_("sval", sval); debug_("str.sval", str.sval); strncpy(& sval[startIndex], str.sval, tmpii); sval[startIndex+tmpii] = 0; debug_("sval", sval); return *this; } // Imite trim de java.lang.String String String::trim() { //String *tmpstr = new String(sval); String tmpstr(sval); tmpstr._trim(); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; // utilise le constructeur par recopie pour faire une copie } // Imite insert de java.lang.String String String::insert(int index, String str2) { String tmpstr(this->insert(str2.sval, index).sval); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; } // Imite insert de java.lang.String String String::insert(int index, char ch) { char aa[2]; aa[0] = ch; aa[1] = 0; String tmpstr(this->insert(aa, index).sval); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; } // Imite deleteCharAt de java.lang.String String String::deleteCharAt(int loc) { String tmpstr(sval); tmpstr._deleteCharAt(loc); return tmpstr; } // Imite delete de java.lang.String // Note : -->le nom Java est "delete()", mais c'est un mot résérvé inutilisable en C++ // startIndex spécifie l'indice du premier caractère à enlever, // et endIndex l'indice juste après le dernier caractère à supprimer. // Ainsi, la sous-chaîne supprimée s'etend de startIndex à (endIndex - 1). String String::deleteStr(int startIndex, int endIndex) { // Par exemple - // deleteStr(3,3) avec val = 'pokemon' retourne 'poon' String tmpstr(sval); tmpstr._deleteStr(startIndex, endIndex); return tmpstr; } // Imite reverse de java.lang.String String String::reverse() { // Par exemple : // reverse() sur "12345" retourne "54321" String tmpstr(sval); tmpstr._reverse(); return tmpstr; } // Imite valueOf de java.lang.String String String::valueOf(char chars[], int startIndex, int numChars) { verifyIndex(startIndex); int ii = strlen(chars); if (startIndex> ii) { cerr << "\nvalueOf() - startIndex greater than string length of" << "string passed" << endl; exit(0); } if ( (numChars+startIndex)> ii) { cerr << "\nvalueOf() - numChars exceeds the string length of" << "string passed" << endl; exit(0); } char *aa = strdup(chars); aa[startIndex + numChars] = 0; String tmpstr(& aa[startIndex]); free(aa); return tmpstr; } // Imite ensureCapacity de java.lang.String // Utilisé par la classe StringBuffer. // Pré-alloue la place pour un certain nombre de caractères. // Utile si vous savez à l'avance que vous allez rajouter un grand nombre // de petites chaînes à un StringBuffer void String::ensureCapacity(int capacity) { sval = (char *) my_realloc(sval, capacity); sval[0] = '\0'; debug_("In ensureCapacity(int capacity) sval", sval); } // Imite setLength de java.lang.String // Utilise par la classe StringBuffer. void String::setLength(int len) { sval = (char *) my_realloc(sval, len); sval[0] = '\0'; debug_("In ensureCapacity(int len) sval", sval); } // Imite setCharAt de StringBuffer void String::setCharAt(int where, char ch) { verifyIndex(where); sval[where] = ch; debug_("in StringBuffer dstr()", "ok"); } // ---- Fin des fonctions imitant java.lang.String ----- // Version surchargée, modifie directement l'objet // La variable dummy donne une signature différente à la fonction. void String::substring(int startIndex, int endIndex, bool dummy) { this->_substring(startIndex, endIndex); } inline void String::_substring(int startIndex, int endIndex) { verifyIndex(startIndex); verifyIndex(endIndex); if (!endIndex) // endIndex == 0 strcpy(sval, & sval[startIndex] ) ; else { if (endIndex> startIndex) { strcpy(sval, & sval[startIndex] ) ; sval[endIndex -startIndex] = 0; } else { cerr << "\n_substring() - startIndex is greater than endIndex!!\n" << endl; exit(-1); } } } // Version surchargée, modifie directement l'objet String String::deleteStr(int startIndex, int endIndex, bool dummy) { this->_deleteStr(startIndex, endIndex); return *this; } inline void String::_deleteStr(int startIndex, int endIndex) { verifyIndex(startIndex); verifyIndex(endIndex); // Par exemple - // deleteStr(3,3) avec val = 'pokemon' retourne 'poon' char *tmpaa = strdup(sval); // ici malloc strcpy(& tmpaa[startIndex], & tmpaa[endIndex]); *this = tmpaa; free(tmpaa); } // Version surchargée, modifie directement l'objet String String::deleteCharAt(int loc, bool dummy) { this->_deleteCharAt(loc); return *this; } inline void String::_deleteCharAt(int loc) { char *tmpaa = strdup(sval); // ici malloc strcpy(& tmpaa[loc], & tmpaa[loc+1]); *this = tmpaa; free(tmpaa); } // Retourne la chaîne avant regx. Trouve la première occurrence de regx. String String::at(char *regx) { char *tok = NULL; tok = strstr(sval, regx); if (tok == NULL) return(String("")); else { int res = (int) (tok - sval); char *lefttok = strdup(sval); memset(lefttok, 0, strlen(sval)); strcpy(lefttok, & sval[res]); String tmpstr(lefttok); free(lefttok); return(tmpstr); } } // Retourne la chaîne avant regx. Trouve la première occurrence de regx. String String::before(char *regx) { char *tok = NULL; tok = strstr(sval, regx); if (tok == NULL) return(String("")); else { int res = (int) (tok - sval); char *lefttok = strdup(sval); lefttok[res] = 0; String tmpstr(lefttok); free(lefttok); return(tmpstr); } } // Retourne la chaîne après regx. Trouve la première occurrence de regx. String String::after(char *regx) { char *tok = NULL; tok = strstr(sval, regx); if (tok == NULL) return(String("")); else { int res = (int) (tok - sval); char *lefttok = strdup(sval); memset(lefttok, 0, strlen(sval)); strcpy(lefttok, & sval[res + strlen(regx)]); String tmpstr(lefttok); free(lefttok); return(tmpstr); } } // Divise la chaîne et retourne une liste via le pointeur de tête // de liste explodeH. // Voir aussi token(). void String::explode(char *seperator) { char *aa = NULL, *bb = NULL; aa = (char *) my_malloc(strlen(sval)); for (bb = strtok(aa, seperator); bb != NULL; bb = strtok(NULL, seperator) ) { String *tmp = new String(bb); String::explodeH.insert(String::explodeH.end(), *tmp); } my_free(aa); list<String>::iterator iter1; // voir include/g++/stl_list.h debug_("Before checking explode..", "ok"); if (String::explodeH.empty() == true ) { debug_("List is empty!!", "ok"); } for (iter1 = String::explodeH.begin(); iter1 != String::explodeH.end(); iter1++) { if (iter1 == NULL) { debug_("Iterator iter1 is NULL!!", "ok" ); break; } debug_("(*iter1).sval", (*iter1).sval); } } // Version surchargée de explode(). Retourne un tableau // de chaînes et le nombre total dans la référence strcount // Voir aussi token(). String *String::explode(int & strcount, char seperator = ' ') { String aa(sval); aa.trim(true); strcount = 0; for (int ii = 0, jj = strlen(aa.sval); ii < jj; ii++) { if (aa.sval[ii] == seperator) strcount++; } String *tmpstr = new String[strcount+1]; if (!strcount) // strcount == 0 tmpstr[0] = aa.sval; else { for (int ii = 0; ii <= strcount; ii++) tmpstr[ii] = aa.token(); } return tmpstr; } // Agrège les chaînes pointées par la tête de liste // explodeH et retourne la classe String. void String::implode(char *glue) { } // Agrège les chaînes pointées par la tête de liste // explodeH et retourne la classe String. void String::join(char *glue) { implode(glue); } // Répète la chaîne input n fois. String String::repeat(char *input, unsigned int multiplier) { // Pour exemple - // repeat("k", 4) retourne "kkkk" if (!input) // input == NULL { return (String("")); } char *aa = (char *) my_malloc(strlen(input) * multiplier); for (unsigned int tmpii = 0; tmpii < multiplier; tmpii++) { strcat(aa, input); } String tmpstr(aa); my_free(aa); return tmpstr; } // Renverse la chaîne. // Version surchargée de reverse(). Modifie directement l'objet. void String::reverse(bool dummy) { this->_reverse(); } inline void String::_reverse() { // Par exemple - // reverse() sur "12345" retourne "54321" char aa; unsigned long tot_len = strlen(sval); unsigned long midpoint = tot_len / 2; for (unsigned long tmpjj = 0; tmpjj < midpoint; tmpjj++) { aa = sval[tmpjj]; // variable temporaire de stockage sval[tmpjj] = sval[tot_len - tmpjj - 1]; // permute les valeurs sval[tot_len - tmpjj - 1] = aa; // permute les valeurs } } // Change certain caractères. // Par exemple ("abcd", "ABC") change toutes les occurrences de chaque // caractère de 'from' en le caractère correspondant dans 'to' String String::tr(char *from, char *to) { int lenfrom = strlen(from), lento = strlen(to); if (lento> lenfrom) lento = lenfrom; // choisit le min else if (lento < lenfrom) lenfrom = lento; // choisit le min debug_("lento", lento); register char *aa = strdup(sval); for (int ii = 0, jj = strlen(sval); ii < jj; ii++) // pour chaque caractère dans val { for (int kk = 0; kk < lento; kk++) // pour chaque caractère dans "from" { if (aa[ii] == from[kk]) aa[ii] = to[kk]; } } String tmpstr(aa); free(aa); return tmpstr; } // Centre le texte String String::center(int padlength, char padchar = ' ') { // Par exemple - // center(10, '*') avec sval="aa" retourne "****aa****" // center(10) avec sval="aa" retourne " aa " // Le résultat est une chaîne contenant 'padlength' caractères avec sval au milieu. int tmpii = sizeof(char) * (padlength + strlen(sval) + 10); char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); for (int jj = 0, kk = (int) padlength/2; jj < kk; jj++) { aa[jj] = padchar; } strcat(aa, sval); for (int jj = strlen(aa), kk = jj + (int) padlength/2; jj < kk; jj++) { aa[jj] = padchar; } String tmpstr(aa); free(aa); return tmpstr; } // Formate la chaîne originale en plaçant <number> caractères <padchar> // entre chaque ensemble de mots délimités par des blancs. Les blancs en début et // en fin sont toujours supprimés. Si <number> est omis ou vaut 0, alors tous les // espaces de la chaîne sont supprimés. Par défaut, <number> vaut 0 et padchar ' '. String String::space(int number, char padchar = ' ') { // Par exemple - // space(3) avec sval = "Je ne sais pas" // retournera "Je ne sais pas" // space(1, '_') avec sval = "Un lieu profondement obscur" // retournera "Un_lieu_profondement_obscur" // space() avec sval = "Je sais cela" // retournera "Jesaiscela" debug_("this->sval", this->sval ); String tmpstr = this->trim().sval; debug_("tmpstr.sval", tmpstr.sval ); // compte les espaces int spacecount = 0; for (int ii = 0, jj = strlen(tmpstr.sval); ii < jj; ii++) { if (tmpstr.sval[ii] == ' ') spacecount++; } debug_("spacecount", spacecount); char ee[2]; ee[0] = padchar; ee[1] = 0; String bb = tmpstr.repeat(ee, spacecount); int tmpii = sizeof(char) * (strlen(tmpstr.sval) + (number * spacecount) + 20); char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); for (int ii = 0, jj = strlen(tmpstr.sval); ii < jj; ii++) { if (tmpstr.sval[ii] == ' ') strcat(aa, bb.sval); else { ee[0] = sval[ii]; strcat(aa, ee); } } tmpstr = aa; free(aa); return tmpstr; } // Le résultat est une chaîne comprenant tous les caractères compris // entre <start> et <end> (inclus). String String::xrange(char start, char end) { // Par exemple - // xrange('a', 'j') retourne val = "abcdefghij" // xrange(1, 8) retourne val = "12345678" if (end < start) { cerr << "\nThe 'end' character is less than 'start' !!" << endl; return String(""); } // Note : 'end' est plus grand que 'start' ! Et ajoute +1 int tmpii = sizeof(char) * (end - start + 11); char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); debug_("xrange tmpii", tmpii); for (int ii = start, jj = 0; ii <= end; ii++, jj++) { aa[jj] = ii; debug_("xrange aa[jj]", aa[jj] ); } String tmpstr(aa); free(aa); return tmpstr; } // Supprime tous les caractères contenus dans <list>. Le caractère par défaut pour // <list> est l'espace ' '. String String::compress(char *list = " ") { // Par exemple - // compress("$,%") avec sval = "$1,934" retourne "1934" // compress() avec sval = "appelez moi alavoor vasudevan" returns "appelezmoialavoorvasudevan" int lenlist = strlen(list); register char *aa = strdup(sval); for (int ii = 0, jj = strlen(sval); ii < jj; ii++) // pour chaque caractère de sval { for (int kk = 0; kk < lenlist; kk++) // pour chaque caractère de "from" { if (aa[ii] == list[kk]) { strcpy(& aa[ii], & aa[ii+1]); } } } String tmpstr(aa); free(aa); return tmpstr; } // <newstr> est insérée dans sval à partir de <start>. <newstr> est // complétée ou tronquée à <length> caractères. <length> est par défaut la // longueur de la chaîne <newstr> String String::insert(char *newstr, int start = 0, int lengthstr = 0, char padchar = ' ') { // Par exemple - // insert("quelquechose de nouveau", 8, 30, '*') avec sval = "vieille chose" // retourne "vieille quelquechose de nouveau*******chose" int tmplen = sizeof(char) * strlen(sval) + strlen(newstr) + lengthstr + 10; char *tmpaa = (char *) malloc (tmplen); memset(tmpaa, 0, tmplen); if (!start) // start == 0 { strcpy(tmpaa, newstr); strcat(tmpaa, this->sval); } else { strncpy(tmpaa, this->sval, start); strcat(tmpaa, newstr); strcat(tmpaa, & this->sval[start]); } String tmpstr(tmpaa); free(tmpaa); return tmpstr; } // Fonction insert surchargée String String::insert(int index, String str2, bool dummy) { *this = this->insert(str2.sval, index).sval; //debug_("tmpstr.sval", tmpstr.sval); return *this; } // Fonction insert surchargée String String::insert(int index, char ch, bool dummy) { char aa[2]; aa[0] = ch; aa[1] = 0; *this = this->insert(aa, index).sval; //debug_("tmpstr.sval", tmpstr.sval); return *this; } // Le résultat est une chaîne de <length> caractères composée des caractères les plus à gauches de sval. // Méthode rapide pour justifier à gauche une chaîne. String String::left(int slength = 0, char padchar = ' ') { // Par exemple - // left(15) avec sval = "Wig" retourne "Wig " // left(4) avec sval = "Wighat" retourne "Wigh" // left() avec sval = " Wighat" retourne "Wighat " if (!slength) // slength == 0 slength = strlen(sval); debug_("left() slength", slength); int tmpii = slength + 20; char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); debug_("this->ltrim().sval ", this->ltrim().sval); strcpy(aa, this->ltrim().sval); debug_("left() aa", aa ); int currlen = strlen(aa); if (currlen < slength) { // pad the string now char ee[2]; ee[0] = padchar; ee[1] = 0; strcat(aa, this->repeat(ee, (unsigned int) (slength-currlen) ).sval); } else { aa[slength] = 0; } debug_("left() aa", aa ); String tmpstr(aa); free(aa); return tmpstr; } // Le résultat est une chaîne de <length> caractères composée des caractères les plus à droite de sval. // Méthode rapide pour justifier à droite un chaîne. String String::right(int slength = 0, char padchar = ' ') { // Par exemple - // right(10) avec sval = "never to saying " retourne " to saying" // right(4) avec sval = "Wighat" retourne "ghat" // right(8) avec sval = "4.50" retourne " 4.50" // right() avec sval = " 4.50 " retourne " 4.50" if (!slength) // slength == 0 slength = strlen(sval); debug_("right() slength", slength); int tmpii = slength + 20; char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); int currlen = strlen(this->rtrim().sval); debug_("right() currlen", currlen ); if (currlen < slength) { // pad the string now char ee[2]; ee[0] = padchar; ee[1] = 0; strcpy(aa, this->repeat(ee, (unsigned int) (slength-currlen) ).sval); strcat(aa, this->rtrim().sval); debug_("right() aa", aa ); } else { strcpy(aa, this->rtrim().sval); strcpy(aa, & aa[currlen-slength]); aa[slength] = 0; } debug_("right() aa", aa ); String tmpstr(aa); free(aa); return tmpstr; } // <newstr> est superposée à sval en commençant à <start>. <newstr> est complétée // ou tronquée à <length> caractères. Par défaut, la longueur <length> est la // longueur de la chaîne newstr. String String::overlay(char *newstr, int start = 0, int slength = 0, char padchar = ' ') { // Par exemple - // overlay("12345678", 4, 10, '*') sur sval = "oldthing is very bad" // retourne "old12345678**ery bad" // overlay("12345678", 4, 5, '*') sur sval = "oldthing is very bad" // retourne "old12345ery bad" int len_newstr = strlen(newstr); if (!slength) // slength == 0 slength = len_newstr; char *aa = (char *) malloc(slength + len_newstr + 10); aa[0] = 0; char ee[2]; ee[0] = padchar; ee[1] = 0; if (len_newstr < slength) { // remplire maintenant strcpy(aa, newstr); strcat(aa, this->repeat(ee, (slength-len_newstr)).sval ); } else { strcpy(aa, newstr); aa[slength] = 0; } // Maintenant recouvrir la chaîne String tmpstr(sval); debug_("tmpstr.sval", tmpstr.sval); for (int ii=start, jj=strlen(tmpstr.sval), kk=start+slength, mm=0; ii < jj; ii++, mm++) { if (ii == kk) break; if (mm == slength) break; tmpstr.sval[ii] = aa[mm]; } free(aa); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; } // Si la chaîne est littéralement égale à ou non égale à // Si type vaut false alors == bool String::_equalto(const String & rhs, bool type = false) { if (type == false) // test == { if (strlen(rhs.sval) == strlen(sval)) { if (!strncmp(rhs.sval, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } else // test != { if (strlen(rhs.sval) != strlen(sval)) { if (!strncmp(rhs.sval, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } } // Si la chaîne est littéralement égale à ou non égale à // Si type vaut false alors == bool String::_equalto(const char *rhs, bool type = false) { if (type == false) // test == { if (strlen(rhs) == strlen(sval)) { if (!strncmp(rhs, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } else // test != { if (strlen(rhs) != strlen(sval)) { if (!strncmp(rhs, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } } // Fonction synonyme de vacuum() void String::clear() { sval = (char *) my_realloc(sval, 10); sval[0] = '\0'; } // Supprime tous les caractères 'ch' en fin de chaîne - voir aussi chop() // Par exemple : // sval = "abcdef\n\n\n" alors chopall() = "abcdef" // sval = "abcdefffff" alors chopall('f') = "abcde" void String::chopall(char ch='\n') { unsigned long tmpii = strlen(sval) - 1 ; for (; tmpii>= 0; tmpii--) { if (sval[tmpii] == ch) sval[tmpii] = 0; else break; } } // Supprime le caractère de fin de la chaîne - voir aussi chopall() // chop() est souvent utilisé pour supprimer le caractère de fin de ligne void String::chop() { sval[strlen(sval)-1] = 0; } // Version surchargée de trim(). Modifie directement l'objet. void String::trim(bool dummy) { this->_trim(); } inline void String::_trim() { this->rtrim(true); this->ltrim(true); debug_("this->sval", this->sval); } // Version surchargée de ltrim(). Modifie directement l'objet. void String::ltrim(bool dummy) { this->_ltrim(); } inline void String::_ltrim() { // Peut causer des problèmes dans my_realloc car // l'emplacement de bb peut être détruit ! char *bb = sval; if (bb == NULL) return; while (isspace(*bb)) bb++; debug_("bb", bb); if (bb != NULL && bb != sval) { debug_("doing string copy", "done"); _str_cpy(bb); // cause des problèmes dans my_realloc et bb va être détruit ! } else debug_("Not doing string copy", "done"); } String String::ltrim() { String tmpstr(sval); tmpstr._ltrim(); return tmpstr; } // Version surchargée de rtrim(). Modifie directement l'objet. void String::rtrim(bool dummy) { this->_rtrim(); } inline void String::_rtrim() { for (long tmpii = strlen(sval) - 1 ; tmpii>= 0; tmpii--) { if ( isspace(sval[tmpii]) ) sval[tmpii] = '\0'; else break; } } String String::rtrim() { String tmpstr(sval); tmpstr._rtrim(); return tmpstr; } // Utilisé pour arrondir la partie frationnaire de réels. // Arrondit les réels avec la précision souhaitée et stocke // le résultat dans le champ sval de la chaîne. // Retourne aussi le résultat comme un char *. void String::roundf(float input_val, short precision) { float integ_flt, deci_flt; const short MAX_PREC = 4; debug_("In roundf", "ok"); if (precision> MAX_PREC) // précision maximale supportée precision = MAX_PREC; // récupère les parties entière et décimale du réel deci_flt = modff(input_val, & integ_flt); for (int tmpzz = 0; tmpzz < precision; tmpzz++) { debug_("deci_flt", deci_flt); deci_flt *= 10; } debug_("deci_flt", deci_flt); unsigned long deci_int = (unsigned long) ( rint(deci_flt) ); sval = (char *) my_malloc(NUMBER_LENGTH); // float 70 chiffres max if (deci_int> 999) // (MAX_PREC) chiffres sprintf(sval, "%lu.%lu", (unsigned long) integ_flt, deci_int); else if (deci_int> 99) // (MAX_PREC - 1) chiffres sprintf(sval, "%lu.0%lu", (unsigned long) integ_flt, deci_int); else if (deci_int> 9) // (MAX_PREC - 2) chiffres sprintf(sval, "%lu.00%lu", (unsigned long) integ_flt, deci_int); else sprintf(sval, "%lu.00000%lu", (unsigned long) integ_flt, deci_int); } void String::roundd(double input_val, short precision) { double integ_flt, deci_flt; const short MAX_PREC = 6; if (precision> MAX_PREC) // précision maximale supportée precision = MAX_PREC; debug_("In roundd", "ok"); // récupère les parties entière et décimale du réel deci_flt = modf(input_val, & integ_flt); for (int tmpzz = 0; tmpzz < precision; tmpzz++) { debug_("deci_flt", deci_flt); deci_flt *= 10; } debug_("deci_flt", deci_flt); sval = (char *) my_malloc(NUMBER_LENGTH); // double 70 chiffres max unsigned long deci_int = (unsigned long) ( rint(deci_flt) ); if (deci_int> 99999) // (MAX_PREC) chiffres sprintf(sval, "%lu.%lu", (unsigned long) integ_flt, deci_int); else if (deci_int> 9999) // (MAX_PREC - 1) chiffres sprintf(sval, "%lu.0%lu", (unsigned long) integ_flt, deci_int); else if (deci_int> 999) // (MAX_PREC - 2) chiffres sprintf(sval, "%lu.00%lu", (unsigned long) integ_flt, deci_int); else if (deci_int> 99) // (MAX_PREC - 3) chiffres sprintf(sval, "%lu.000%lu", (unsigned long) integ_flt, deci_int); else if (deci_int> 9) // (MAX_PREC - 4) chiffres sprintf(sval, "%lu.0000%lu", (unsigned long) integ_flt, deci_int); else // (MAX_PREC - 5) chiffres sprintf(sval, "%lu.00000%lu", (unsigned long) integ_flt, deci_int); } // Fournie seulement pour documenter // Vous devriez utiliser la fonction indexOf() bool String::contains(char *str2, int startIndex = 0) { // Par exemple - // if (indexOf("ohboy")> -1 ) // cout << "\nString contient 'ohboy'" << endl; // if (indexOf("ohboy") < 0 ) // cout << "\nString NE contient PAS 'ohboy'" << endl; // if (indexOf("ohboy", 4)> -1 ) // cout << "\nString contient 'ohboy'" << endl; // if (indexOf("ohboy", 4) < 0 ) // cout << "\nString NE contient PAS 'ohboy'" << endl; cerr << "\nYou must use indexOf() function instead of contains()\n" << endl; exit(-1); } // Fonction synonyme de empty() bool String::isNull() { if (sval[0] == '\0') return true; else { if (sval == NULL) return true; else return false; } } // Les caractères blancs de début et de fin sont ignorés. bool String::isInteger() { String tmpstr(sval); tmpstr.trim(true); debug_("tmpstr.sval", tmpstr.sval ); if ( strspn ( tmpstr.sval, "0123456789" ) != strlen(tmpstr.sval) ) return ( false ) ; else return ( true ) ; } // Fonction surchargée bool String::isInteger(int pos) { verifyIndex(pos); return (isdigit(sval[pos])); } // Les caractères blancs de début et de fin sont ignorés. bool String::isNumeric() { String tmpstr(sval); tmpstr.trim(true); debug_("tmpstr.sval", tmpstr.sval ); if ( strspn ( tmpstr.sval, "0123456789.+-e" ) != strlen(tmpstr.sval) ) return ( false ) ; else return ( true ) ; } // Fonction surchargée bool String::isNumeric(int pos) { verifyIndex(pos); return (isdigit(sval[pos])); } bool String::isEmpty() { if (strlen(sval) == 0) return true; else return false; } // Voir aussi explode() // Attention : l'objet String est modifié et ne contient plus le token renvoyé. // Il est conseillé de sauvegarder la chaîne originale avant d'appeler // cette fonction, comme par exemple ainsi : // String savestr = origstr; // String aa, bb, cc; // aa = origstr.token(); // bb = origstr.token(); // cc = origstr.token(); // // Cette méthode retourne le premier token non séparateur (par défaut espace) de la chaîne. String String::token(char seperator = ' ') { char ee[2]; ee[0] = seperator; ee[1] = 0; char *res = strtok(sval, ee); if (!res) // if res == NULL { debug_("token", res); debug_("sval", sval); return(String(sval)); } else { String tmpstr(res); // Utilise la longueur de la chaîne sval et pas celle de res // car strtok() a mis un NULL ('\0') sur l'emplacement et // aussi car strtok() ignore les blancs initiaux de sval strcpy(sval, & sval[strlen(sval)+1]); debug_("token", res); debug_("sval", sval); return tmpstr; } } String String::crypt(char *original, char *salt) { return String(""); } int String::toInteger() { if ( strlen(sval) == 0 ) { cerr << "Cannot convert a zero length string " << " to a numeric" << endl ; abort() ; } if ( ! isInteger() ) { cerr << "Cannot convert string [" << sval << "] to an integer numeric string" << endl ; abort() ; } return ( atoi ( sval ) ) ; } long String::parseLong() { if ( strlen(sval) == 0 ) { cerr << "Cannot convert a zero length string " << " to a numeric" << endl ; abort() ; } if ( ! isInteger() ) { cerr << "Cannot convert string [" << sval << "] to an integer numeric string" << endl ; abort() ; } return ( atol ( sval ) ) ; } double String::toDouble() { if ( strlen(sval) == 0 ) { cerr << "Cannot convert a zero length string " << " to a numeric" << endl ; abort() ; } if ( ! isNumeric() ) { cerr << "Cannot convert string [" << sval << "] to a double numeric string" << endl ; abort() ; } double d = atof ( sval ) ; return ( d ) ; } String String::getline(FILE *infp = stdin) { register char ch, *aa = NULL; register const short SZ = 100; // Valeur initiale de ii> SZ donc aa est de la mémoire allouée register int jj = 0; for (int ii = SZ+1; (ch = getc(infp)) != EOF; ii++, jj++) { if (ii> SZ) // alloue la memoire en paquets de SZ pour la performance { aa = (char *) realloc(aa, jj + ii + 15); // +15 par sécurité ii = 0; } if (ch == '\n') // lit jusqu'à rencontrer une nouvelle ligne break; aa[jj] = ch; } aa[jj] = 0; _str_cpy(aa); // met la valeur dans la chaîne free(aa); return *this; } /* void String::Format(const char *fmt, ... ) { va_list iterator; va_start(iterator, fmt ); va_end(iterator); } */ // contrôle qu'un indice se trouve dans les limites inline void String::verifyIndex(unsigned long index) const { if (index < 0 || index>= strlen(sval) ) { // throw "Index Out Of Bounds Exception"; cerr << "Index Out Of Bounds Exception at [" << index << "] in:\n" << sval << endl; exit(1); } } // contrôle qu'un indice se trouve dans les limites inline void String::verifyIndex(unsigned long index, char *aa) const { if (!aa) // aa == NULL { cerr << "\nverifyIndex(long, char *) str null value\n" << endl; exit(-1); } if (index < 0 || index>= strlen(aa) ) { cerr << "Index Out Of Bounds Exception at [" << index << "] in:\n" << aa << endl; exit(1); } } ////////////////////////////////////////////////////////// // Les fonctions privées commencent à partir d'ici... ////////////////////////////////////////////////////////// void String::_str_cpy(char bb[]) { debug_("In _str_cpy bb", bb); if (bb == NULL) { sval[0] = '\0'; return; } unsigned long tmpii = strlen(bb); if (tmpii == 0) { sval[0] = '\0'; return; } debug_("In _str_cpy tmpii", tmpii); debug_("In _str_cpy sval", sval); sval = (char *) my_realloc(sval, tmpii); //sval = new char [tmpii + SAFE_MEM_2]; debug_("In _str_cpy bb", bb); strncpy(sval, bb, tmpii); debug_("In _str_cpy sval", sval); sval[tmpii] = '\0'; debug_("In _str_cpy sval", sval); } void String::_str_cpy(int bb) { char tmpaa[100]; sprintf(tmpaa, "%d", bb); _str_cpy(tmpaa); } void String::_str_cpy(unsigned long bb) { char tmpaa[100]; sprintf(tmpaa, "%ld", bb); _str_cpy(tmpaa); } void String::_str_cpy(float bb) { char tmpaa[100]; sprintf(tmpaa, "%f", bb); _str_cpy(tmpaa); } void String::_str_cat(char bb[]) { unsigned long tmpjj = strlen(bb), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); debug_("sval in _str_cat() ", sval); strncat(sval, bb, tmpjj); } void String::_str_cat(int bb) { char tmpaa[100]; sprintf(tmpaa, "%d", bb); unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); strncat(sval, tmpaa, tmpjj); } void String::_str_cat(unsigned long bb) { char tmpaa[100]; sprintf(tmpaa, "%ld", bb); unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); strncat(sval, tmpaa, tmpjj); } void String::_str_cat(float bb) { char tmpaa[100]; sprintf(tmpaa, "%f", bb); unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); strncat(sval, tmpaa, tmpjj); } ////////////////////////////////////////////////////////// // Les opérateurs sont définis à partir d'ici... ////////////////////////////////////////////////////////// String operator+ (const String & lhs, const String & rhs) { /*******************************************************/ // Note : pour concaténer deux chaînes, transtyper d'abord // en String comme ici : //aa = (String) "alkja " + " 99djd " ; /*******************************************************/ String tmp(lhs); tmp._str_cat(rhs.sval); return(tmp); /* if (String::_global_String == NULL) { String::_global_String = new String; String::_global_String->_str_cpy(lhs.sval); String::_global_String->_str_cat(rhs.sval); //return *String::_global_String; return String(String::_global_String->val); } */ /* else if (String::_global_String1 == NULL) { debug_("1)global", "ok" ); String::_global_String1 = new String; String::_global_String1->_str_cpy(lhs.sval); String::_global_String1->_str_cat(rhs.sval); return *String::_global_String1; } */ /* else { fprintf(stderr, "\nError: cannot alloc _global_String\n"); exit(-1); } */ /* String *aa = new String; aa->_str_cpy(lhs.sval); aa->_str_cat(rhs.sval); return *aa; */ } String String::operator+ (const String & rhs) { String tmp(*this); tmp._str_cat(rhs.sval); debug_("rhs.sval in operator+", rhs.sval ); debug_("tmp.sval in operator+", tmp.sval ); return (tmp); } // L'utilisation d'une référence accélèrera l'opérateur = String& String:: operator= ( const String& rhs ) { if (& rhs == this) { debug_("Fatal Error: In operator(=). rhs is == to 'this pointer'!!", "ok" ); return *this; } this->_str_cpy(rhs.sval); debug_("rhs value", rhs.sval ); // Libere la memoire des variables globales //_free_glob(& String::_global_String); //if (String::_global_String == NULL) //fprintf(stderr, "\n_global_String is freed!\n"); //return (String(*this)); return *this; } // L'utilisation d'une référence accélèrera l'opérateur = String& String::operator+= (const String & rhs) { /*******************************************************/ // Note : pour concaténer deux chaînes, transtyper d'abord // en String comme ici : //aa = (String) "cccc " + " dddd " ; /*******************************************************/ if (& rhs == this) { debug_("Fatal error: In operator+= rhs is equals 'this' ptr", "ok"); return *this; } this->_str_cat(rhs.sval); return *this; //return (String(*this)); } bool String::operator== (const String & rhs) { return(_equalto(rhs.sval)); } bool String::operator== (const char *rhs) { return(_equalto(rhs)); } bool String::operator!= (const String & rhs) { return(_equalto(rhs.sval, true)); } bool String::operator!= (const char *rhs) { return(_equalto(rhs, true)); } char String::operator[] (unsigned long Index) const { verifyIndex(Index); return sval[Index]; } char & String::operator[] (unsigned long Index) { verifyIndex(Index); return sval[Index]; } istream & operator>> (istream & In, String & str2) { // alloue la taille max de 2048 caractères static char aa[MAX_ISTREAM_SIZE]; In>> aa; str2 = aa; // affecte aa à la référence return In; // retourne un istream } ostream & operator << (ostream & Out, const String & str2) { Out << str2.sval; return Out; } //////////////////////////////////////////////////// // Imite StringBuffer Object // MéThodes de StringBuffer //////////////////////////////////////////////////// // Imite StringBuffer ; le constructeur par défaut // (celui sans paramètre) réserve de la place pour 16 // caractères. StringBuffer::StringBuffer() :String() // appelle le constructeur de la classe de base sans paramètres { debug_("in StringBuffer cstr()", "ok"); } // Imite StringBuffer StringBuffer::StringBuffer(int size) :String(size, true) // appelle le constructeur de la classe de base sans paramètres { // String(size, true) -- ne pas l'appeler ici dans le corps de la // fonction mais durant la phase d'initialisation pour éviter un // appel supplémentaire du constructeur par défaut de la classe de // base et être plus rapide et plus efficace debug_("in StringBuffer cstr(int size)", "ok"); } // Imite StringBuffer // appelle le constructeur de la classe de base avec une chaîne en paramètre StringBuffer::StringBuffer(String str) :String(str.val()) // appelle le constructeur de la classe de base { // String(str.val()) -- ne pas l'appeler ici dans le corps de la // fonction mais durant la phase d'initialisation pour éviter un // appel supplémentaire du constructeur par défaut de la classe de // base et être plus rapide et plus efficace debug_("in StringBuffer cstr(String str)", "ok"); } // Imite StringBuffer StringBuffer::~StringBuffer() { debug_("in StringBuffer dstr()", "ok"); } // Imite la classe Float // appelle le constructeur de la classe de base avec une chaîne en paramètre Float::Float(String str) :String(str.val()) // appelle le constructeur de la classe de base { // String(str.val()) -- ne pas l'appeler ici dans le corps de la // fonction mais durant la phase d'initialisation pour éviter un // appel supplémentaire du constructeur par défaut de la classe de // base et être plus rapide et plus efficace debug_("in Float cstr(String str)", "ok"); } // Imite la classe Double // appelle le constructeur de la classe de base avec une chaîne en paramètre Double::Double(String str) :String(str.val()) // appelle le constructeur de la classe de base { // String(str.val()) -- ne pas l'appeler ici dans le corps de la // fonction mais durant la phase d'initialisation pour éviter un // appel supplémentaire du constructeur par défaut de la classe de // base et être plus rapide et plus efficace debug_("in Double cstr(String str)", "ok"); } // Imite la classe StringReader // appelle le constructeur de la classe de base avec une chaîne en paramètre StringReader::StringReader(String str) :String(str.val()) // appelle le constructeur de la classe de base { // String(str.val()) -- ne pas l'appeler ici dans le corps de la // fonction mais durant la phase d'initialisation pour éviter un // appel supplémentaire du constructeur par défaut de la classe de // base et être plus rapide et plus efficace debug_("in StringReader cstr(String str)", "ok"); _curpos = 0; _mark_pos = 0; } // Imite la méthode read de la classe StringReader int StringReader::read() { _curpos++; if (_curpos> strlen(sval) ) return -1; return sval[_curpos-1]; } // Lit des caractères dans une portion d'un tableau // cbuf est le tampon destination, offset est le décalage indiquant où écrire // les caractères, length est le nombre maximum de caractères à lire // Retourne le nombre de caractères lus ou -1 en cas de fin du flux int StringReader::read(char cbuf[], int offset, int length) { if (_curpos> strlen(sval) - 1 ) return -1; strncpy(& cbuf[offset], & sval[_curpos], length); _curpos += length; return length; } // Marque la position courante dans le flux. Les appels suivants // à reset() repositionneront le flux à ce point. // Le paramètre 'readAheadLimit' limite le nombre de caractères qui // pourraient être lus tout en préservant la marque. // Comme le flux d'entrée provient d'une chaîne, il n'y a pas de //limite actuellement, donc l'argument est ignoré. void StringReader::mark(int readAheadLimit) { _mark_pos = _curpos; } // réinitialise le flux à la marque la plus récente, ou au début de // la chaîne si aucun marque n'a été posée void StringReader::reset() { _curpos = _mark_pos; } // Passe des caractères. Cette méthode bloquera jusqu'a ce que des caractères soient // disponibles, qu'une erreur arrive ou que la fin du flux soit atteinte. // Paramètre ii : nombre de caractères à passer // Retourne : le nombre courant de caractères passés long StringReader::skip(long ii) { long tmpjj = strlen(sval) - _curpos - 1; if (ii> tmpjj) ii = tmpjj; _curpos = ii; return ii; } // Imite la classe StringWriter StringWriter::StringWriter() { debug_("in StringWriter cstr()", "ok"); char *aa = (char *) malloc(300); memset(aa, ' ', 299); // remplit avec des blancs aa[300] = 0; String((char *) aa); my_free(aa); } StringWriter::StringWriter(int bufferSize) { debug_("in StringWriter cstr(int bufferSize)", "ok"); char *aa = (char *) malloc(bufferSize); memset(aa, ' ', bufferSize-1); // remplit avec des blancs aa[bufferSize] = 0; String((char *) aa); my_free(aa); } void StringWriter::write(int bb) { _str_cat(bb); } void StringWriter::write(char *bb) { _str_cat(bb); } void StringWriter::write(String bb) { _str_cat(bb.val()); } void StringWriter::write(char *bb, int startIndex, int endIndex) { char *aa = strdup(bb); // teste le null dans verifyIndex verifyIndex(startIndex, aa); verifyIndex(endIndex, aa); aa[endIndex] = 0; _str_cat(& aa[startIndex]); } void StringWriter::write(String str, int startIndex, int endIndex) { write(str.val(), startIndex, endIndex); }