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);
}