home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / XSTRING.ZIP / XString.Cpp next >
Encoding:
C/C++ Source or Header  |  1998-05-05  |  26.8 KB  |  787 lines

  1. /*******************************************************************************
  2.  *
  3.  * Autor:            Joachim Raidl
  4.  * Adresse:            Joachim.Raidl@iname.com
  5.  * Klasse:            XString
  6.  * Files:            XString.cpp, XString.h
  7.  * Beschreibung:    Die Klasse XString stellt eine Erweiterung der Klasse
  8.  *                    CString dar. Neben den Standardfunktionen werden zusΣtzlich
  9.  *                    Funktionen fⁿr Element-Strings zur Verfⁿgung gestellt.
  10.  *                    Elementstrings zeichnen sich dadurch aus, da▀ sie mehrere
  11.  *                    Werte durch einen Separator getrennt enthalten. So kann zum
  12.  *                    Beispiel aus dem Elementstring "012|345|678|901" jedes
  13.  *                    Element fⁿr sich gelesen und ⁿberschrieben werden.
  14.  * Operatoren:        operator char*, operator const char*, operator CString,
  15.  *                    operator--, operator!
  16.  * Funktionen:        Double(), Int(), Remove(), RemoveAll(), Insert(), Replace(),
  17.  *                    ReplaceAll(), Reverse(), Trim(), Lower(), Upper(), Fill(),
  18.  *                    ReplaceTabs(), Count(), FindIndex(), ReplaceText(),
  19.  *                    NCFind(), NCReplace(), NCReplaceAll(), NCRemove(),
  20.  *                    NCRemoveAll(),
  21.  * Element-Fkt.:    SetSeparator(), RestoreSeparator(), Element(), operator(),
  22.  *                    Elements(), GetString(), GetDouble(), GetInt(), GetChar(),
  23.  *                    Get(), SetElement(), ElementIndex(), ElementSortString(),
  24.  *                    ElementSortDouble(), ElementSortChar(), ElementSortInt(),
  25.  *                    ElementSort(), SerializeElements(),
  26.  * Friends:            itoa(), utoa(), dtoa(), Repeat(), Concat(),
  27.  *                    GetStringTableEntry(), GetDoubleFormatString(),
  28.  *
  29.  ******************************************************************************/
  30.  
  31. #include "StdAfx.H"
  32. #include "XString.H"
  33. #include <CType.H>
  34.  
  35. #ifdef _DEBUG
  36. #define new DEBUG_NEW
  37. #include "NoDump.h"
  38. #undef THIS_FILE
  39. static char THIS_FILE[] = __FILE__;
  40. #endif
  41.  
  42. volatile static char jrrcid[] = "%J%";
  43.  
  44. char    XString::SEP    = '|';            // Trennzeichen fⁿr Element-Strings
  45. char    XString::OLDSEP    = '|';            // Trennzeichen fⁿr Element-Strings
  46. XString STRERROR = ">>> ERROR <<<";        // Fehlerstring fⁿr alle Klassen
  47.  
  48. /*****************************************************************************
  49.  * Klasse:        XString
  50.  * Funktion:    NCFind
  51.  * Parameter:    s        Suchstring
  52.  *                c        Suchzeichen
  53.  * Return:        int        Erste gefundene Position des Suchtextes
  54.  * Beispiel:    XString("Test TEST").Find("E")        ==> 6
  55.  *                XString("Test TEST").NCFind("E")    ==> 1
  56.  *
  57.  * Die Funktion NCFind arbeitet wie alle nachfolgenden NC-Funktion im
  58.  * Case-Unsensitiven Fall, da▀ hei▀t, sie berⁿcksichtigt keine Gro▀-/Klein-
  59.  * schreibung. Ansonsten arbeitet die Funktion genau wie Find.
  60.  ****************************************************************************/
  61. int XString::NCFind(const XString& s) const
  62. {
  63.     XString copy = this->Upper();
  64.  
  65.     return copy.Find(s.Upper());
  66. }
  67.  
  68. int XString::NCFind(char c) const
  69. {
  70.     XString copy = this->Upper();
  71.  
  72.     return copy.Find((char) toupper(c));
  73. }
  74.  
  75. /*****************************************************************************
  76.  * Klasse:        XString
  77.  * Funktion:    Remove, NCRemove
  78.  * Parameter:    von, bis        L÷schbereich
  79.  *                s                L÷schstring
  80.  *                c                L÷schzeichen
  81.  * Return:        Ergebnisstring
  82.  * Beispiel:    XString("0123456789").Remove(1, 3)        ==> "0456789"
  83.  *                XString("0123456789").Remove("345")        ==> "0126789"
  84.  *                XString("0123456789").Remove('4')        ==> "012356789"
  85.  *                XString("Test  Test").NCRemove("E")        ==> "Tst  Test"
  86.  *
  87.  * L÷scht einen bestimmten Teil aus dem String. Hierbei kann wahlweise ein
  88.  * Bereich (von, bi), ein String (s) oder ein einzelnes Zeichen (c) gel÷scht
  89.  * werden.
  90.  ****************************************************************************/
  91. XString XString::Remove(int von, int bis) const
  92. {
  93.     if (bis < 0)                    bis = von;
  94.  
  95.     if ((von < 0) || (bis < von))    return *this;
  96.     else                            return Left(von) + Mid(bis);
  97. }
  98.  
  99. XString XString::Remove(const XString& s) const
  100. {
  101.     int i = Find(s);
  102.  
  103.     if (i >= 0)    return Left(i) + Mid(i + s.GetLength());
  104.     else        return *this;
  105. }
  106.  
  107. XString XString::Remove(char c) const
  108. {
  109.     int i = Find(c);
  110.  
  111.     if (i >= 0)    return Left(i) + Mid(i+1);
  112.     else        return *this;
  113. }
  114.  
  115. XString    XString::NCRemove(const XString& s) const
  116. {
  117.     int i = NCFind(s);
  118.  
  119.     if (i >= 0)    return Left(i) + Mid(i + s.GetLength());
  120.     else        return *this;
  121. }
  122.  
  123. XString    XString::NCRemove(char c) const
  124. {
  125.     int i = NCFind(c);
  126.  
  127.     if (i >= 0)    return Left(i) + Mid(i+1);
  128.     else        return *this;
  129. }
  130.  
  131. /*****************************************************************************
  132.  * Klasse:        XString
  133.  * Funktion:    RemoveAll, NCRemoveAll
  134.  * Parameter:    s                L÷schstring
  135.  *                c                L÷schzeichen
  136.  * Return:        Ergebnisstring
  137.  * Beispiel:    XString("01234567890123456789").RemoveAll("34567")
  138.  *                    ==> "0128901289"
  139.  *                XString("Test TEST").NCRemoveAll("e")    ==> "Tst TST"
  140.  *
  141.  * L÷scht jedes Auftreten einse String (s) oder eines Zeichens (c) as einem
  142.  * String.
  143.  ****************************************************************************/
  144. XString XString::RemoveAll(const XString& s) const
  145. {
  146.     XString hilf = *this;
  147.  
  148.     while (hilf.Find(s) >= 0)    hilf = hilf.Remove(s);
  149.     return hilf;
  150. }
  151.  
  152. XString XString::RemoveAll(char c) const
  153. {
  154.     XString hilf = *this;
  155.  
  156.     while (hilf.Find(c) >= 0)    hilf = hilf.Remove(c);
  157.     return hilf;
  158. }
  159.  
  160. XString XString::NCRemoveAll(const XString& s) const
  161. {
  162.     XString hilf = *this;
  163.  
  164.     while (hilf.NCFind(s) >= 0)    hilf = hilf.NCRemove(s);
  165.     return hilf;
  166. }
  167.  
  168. XString XString::NCRemoveAll(char c) const
  169. {
  170.     XString hilf = *this;
  171.  
  172.     while (hilf.NCFind(c) >= 0)    hilf = hilf.NCRemove(c);
  173.     return hilf;
  174. }
  175.  
  176. /*****************************************************************************
  177.  * Klasse:        XString
  178.  * Funktion:    Insert
  179.  * Parameter:    s                Einfⁿgestring
  180.  *                at                Einfⁿgeposition
  181.  *                c                L÷schzeichen
  182.  * Return:        Ergebnisstring
  183.  * Beispiel:    XString("0123456789").Insert("xx", 3)    ==> "012xx3456789"
  184.  *
  185.  * Fⁿgt einen String in den aktellen String ein.
  186.  ****************************************************************************/
  187. XString XString::Insert(const XString& s, int at) const
  188. {
  189.     if ((at <= GetLength()) && (at >= 0))    return Left(at) + s + Mid(at);
  190.     else                                    return *this;
  191. }
  192.  
  193. /*****************************************************************************
  194.  * Klasse:        XString
  195.  * Funktion:    Replace, NCReplace
  196.  * Parameter:    s                Ersatzstring
  197.  *                search            Suchstring
  198.  *                von, bis        Ersatzbereich
  199.  * Return:        Ergebnisstring
  200.  * Beispiel:    XString("0123456789").Replace("xx", "345")    ==> "012xx6789"
  201.  *                XString("0123456789").Replace("xx", 1, 6)    ==> "0xx789"
  202.  *                XString("List LIST").NCReplace("I", "a")    ==> "Last LIST"
  203.  *
  204.  * Ersetzt einen Teil-String (search) oder ein Bereich (von, bis) durch
  205.  * einen neuen String.
  206.  ****************************************************************************/
  207. XString XString::Replace(const XString& s, const XString& search) const
  208. {
  209.     int i = Find(search);
  210.     return Remove(search).Insert(s, i);
  211. }
  212.  
  213. XString    XString::Replace(const XString& s, int von, int bis) const
  214. {
  215.     return Remove(von, bis).Insert(s, von);
  216. }
  217.  
  218. XString XString::NCReplace(const XString& s, const XString& search) const
  219. {
  220.     int i = NCFind(search);
  221.     return NCRemove(search).Insert(s, i);
  222. }
  223.  
  224. /*****************************************************************************
  225.  * Klasse:        XString
  226.  * Funktion:    ReplaceAll, NCReplaceAll
  227.  * Parameter:    s                Ersatzstring
  228.  *                search            Suchstring
  229.  * Return:        Anzahl der Ersetzungen
  230.  * Beispiel:    XString("0123401234").Replace("xx", "34")    ==> "012xx012xx"
  231.  *                XString("List LIST").NCReplaceAll("I", "a")    ==> "Last LaST"
  232.  *
  233.  * Ersetzt einen jedes Auftreten des Suchstrings durch den Ersatzstring. Bei
  234.  * der NC-Version werden nicht die entsprechenden NC-Funktionen von Find und
  235.  * Replace benutzt, da dies zu viele Konversionen nach sich ziehen wⁿrde.
  236.  * Statt dessen wird der String als Kopie nur einmal konvertiert und dann
  237.  * der Originalstring und die Gro▀-Kopie parallel gehandelt.
  238.  ****************************************************************************/
  239. int XString::ReplaceAll(const XString& s, const XString& search)
  240. {
  241.     XString aktString = *this;
  242.     this->Empty();
  243.  
  244.     int len = search.GetLength();
  245.     for (int pos = aktString.Find(search), i = 0; pos >= 0; pos = aktString.Find(search))
  246.     {
  247.         *this        += aktString.Left(pos) + s;
  248.         aktString    = aktString.Mid(pos + len);
  249.         i++;
  250.     }
  251.  
  252.     *this += aktString;
  253.  
  254.     return i;
  255. }
  256.  
  257. int XString::NCReplaceAll(const XString& s, const XString& search)
  258. {
  259.     XString aktString = *this;
  260.     this->Empty();
  261.  
  262.     XString AktString    = aktString.Upper();    // Gro▀-Version von aktString
  263.     XString Search        = search.Upper();        // Gro▀-Version von search
  264.  
  265.     int len = Search.GetLength();
  266.     for (int pos = AktString.Find(Search), i = 0; pos >= 0; pos = AktString.Find(Search))
  267.     {
  268.         *this        += aktString.Left(pos) + s;
  269.         aktString    = aktString.Mid(pos + len);
  270.         AktString    = AktString.Mid(pos + len);
  271.         i++;
  272.     }
  273.  
  274.     *this += aktString;
  275.  
  276.     return i;
  277. }
  278.  
  279. /*****************************************************************************
  280.  * Klasse:        XString
  281.  * Funktion:    ReplaceText
  282.  * Parameter:    replace            Ersatz-Element-String
  283.  * Return:        Ergebnisstring
  284.  * Beipsiel:    XString("Das File * ist * Byte lang").ReplaceText("Test|100")
  285.  *                ==> "Das File Test ist 100 Byte lang"
  286.  *
  287.  * Ersetzt alle '*' durch die ⁿbergebenen Werte des Elementstrings 'replace'.
  288.  * Die einzelnen Ersatzstring sind durch '|' voneinander zu trennen.
  289.  ****************************************************************************/
  290. XString XString::ReplaceText(const XString& replace) const
  291. {
  292.     XString erg = *this;
  293.     XString rep;
  294.     for (int i = 0; !!(rep = replace.GetString(i)); i++)
  295.         if (erg.Find("*") >= 0)
  296.             erg = erg.Replace(rep, "*");
  297.  
  298.     erg.ReplaceAll("*", "º");
  299.  
  300.     return erg;
  301. }
  302.  
  303. /*****************************************************************************
  304.  * Klasse:        XString
  305.  * Funktion:    Count
  306.  * Parameter:    c            ZΣhlzeichen
  307.  *                str            ZΣhlstring
  308.  * Return:        Anzahl der Zeichen im String
  309.  * Beipsiel:    XString("123412341234").Count('1')    ==> 3
  310.  *                XString("123412341234").Count("41")    ==> 2
  311.  *
  312.  * ZΣhlt das Auftreten von c im String.
  313.  ****************************************************************************/
  314. int XString::Count(char c) const
  315. {
  316.     int anz = 0;
  317.     for (int i = 0, l = GetLength(); i < l; i++)
  318.         if (m_pchData[i] == c) anz++;
  319.  
  320.     return anz;
  321. }
  322.  
  323. int XString::Count(const XString& str) const
  324. {
  325.     int anz = 0, p, l = str.GetLength();
  326.     XString copy = *this;
  327.     while ((p = copy.Find(str)) >= 0)
  328.     {
  329.         anz++;
  330.         copy = copy.Mid(p + l);
  331.     }
  332.  
  333.     return anz;
  334. }
  335.  
  336. /*****************************************************************************
  337.  * Klasse:        XString
  338.  * Funktion:    Fill
  339.  * Parameter:    n            Neue LΣnge
  340.  * Return:        Ergebnisstring
  341.  * Beipsiel:    XString("12345").Fill(10)    ==> "12345     "
  342.  *
  343.  * Fⁿllt den String mit Leerzeichen auf, soda▀ er aus n Zeichen besteht.
  344.  ****************************************************************************/
  345. XString XString::Fill(int n) const
  346. {
  347.     XString erg = *this;
  348.     for (int i = GetLength(); i < n; i++) erg += ' ';
  349.  
  350.     return erg;
  351. }
  352.  
  353. /*****************************************************************************
  354.  * Klasse:        XString
  355.  * Funktion:    ReplaceTabs
  356.  * Parameter:    abstand            Tablatorabstand
  357.  * Return:        String ohne Tabulatorzeichen
  358.  * Beispiel:    str = "Blank\tEinfⁿgen";
  359.  *                ReplaceTabs(str, 4)        ==>    "Blank   einfⁿgen"
  360.  *
  361.  * Ersetzt alle Tabulatoren innerhalb des Strings durch entsprechend viele
  362.  * Leerzeichen und gibt diesen dann zurⁿck. Hierbei werden die Leerzeichen
  363.  * so eingefⁿgt, da▀ die Position des darauffolgenden Textes mit der
  364.  * vorherigen ⁿbereinstimmt. Bei einem Tabulatorabstand von 4 kann ein Text,
  365.  * der einem Tabulatorzeichen folgt immer nur bei der Position 4, 8, 12, ...
  366.  * erscheinen.
  367.  ****************************************************************************/
  368. XString XString::ReplaceTabs(int abstand) const
  369. {
  370.     XString erg = *this;
  371.     int i;
  372.     while ((i = erg.Find('\t')) >= 0)
  373.         erg = erg.Left(i) + Repeat(' ', abstand - i % abstand) + erg.Mid(i + 1);
  374.  
  375.     return erg;
  376. }
  377.  
  378. /*****************************************************************************
  379.  * Klasse:        XString
  380.  * Funktion:    FindIndex
  381.  * Parameter:    c            Suchzeichen
  382.  *                pos            Suchposition
  383.  * Return:        Position des i-ten Auftauchens von c wenn es existiert,
  384.  *                -1 sonst
  385.  * Beipsiel:    XString("0|1|2|3|4|5|6").FindIndex('|', 5)    ==> 9
  386.  *                                  ^
  387.  *                XString("0|1|2|3|4|5|6").FindIndex('|', 11)    ==> -1
  388.  *
  389.  * Gibt den Index des i-ten Auftauchens des Zeichens c zurⁿck.
  390.  ****************************************************************************/
  391. int XString::FindIndex(char c, int pos) const
  392. {
  393.     if (!pos)    return 0;
  394.  
  395.     for (int i=0, l=GetLength(); (i < l) && pos; i++)
  396.         if (m_pchData[i] == c) pos--;
  397.  
  398.     int erg;
  399.     if (!pos)    erg = i-1;
  400.     else        erg = -1;
  401.  
  402.     return erg;
  403. }
  404.  
  405. /*****************************************************************************
  406.  * Klasse:        XString
  407.  * Funktion:    operator(), Element, Elements
  408.  * Parameter:    i            Position
  409.  *                von, bis    Bereich
  410.  *                sep            Separator
  411.  * Return:        i-tes Element bzw. (von-bis)-Elemente des Strings
  412.  * Beispiele:    XString str    = "0|1|2|3"
  413.  *                 str(1)            = str.Element(1)    ==> "1"
  414.  *                str(5)            = str.GetString(5)    ==> ""
  415.  *                str.GetDouble(1)                    ==> 1.0
  416.  *                str.GetInt(0)                        ==> 0
  417.  *                str.GetChar(3)                        ==> '3'
  418.  *                 str(1, 2)        = str.Elements(1,2)    ==> "1|2"
  419.  *                str(2, -1)        = str.Elements(2)    ==> "2|3"
  420.  *                XString("0, 1, 2, 3).Element(2,',')    ==> "2"
  421.  *
  422.  * Der Funktions-Operator '()' gibt ein Element eines Element-Strings zurⁿck.
  423.  * Ein Element-String ist ein String mit mehreren durch ein Separator getrennte
  424.  * Elemente. Je nach ▄bergabeparameter kann ein einzelnes Element oder eine
  425.  * Teil-Elementstring zurⁿckgegeben werden. Es existieren mehrere Overloads fⁿr
  426.  * diese Funktion:
  427.  *
  428.  *        (i)                i-tes Element als String
  429.  *        Element(i)        i-tes Element als String
  430.  *        Element(i, c)    i-tes Element. Als Trenner wird c benutzt
  431.  *        (i, j)            Elementstring mit den Elementen i bis j
  432.  *        Elements(i, j)    Elementstring mit den Elementen i bis j
  433.  *        (i, -1)            Elementstring mit allen Elementen ab dem i-ten Element
  434.  *        Elements(i, -1)    Elementstring mit allen Elementen ab dem i-ten Element
  435.  *
  436.  *        String(i)        i-tes Element als String
  437.  *        Double(i)        i-tes Element als Double
  438.  *        Int(i)            i-tes Element als Int
  439.  *        Char(i)            i-tes Element als Char
  440.  ****************************************************************************/
  441. XString XString::Element(int i, char sep) const
  442. {
  443.     char tempSep = SEP;
  444.     SEP = sep;
  445.     XString erg = Elements(i, i);
  446.     SEP = tempSep;
  447.  
  448.     return erg;
  449. }
  450.  
  451. XString XString::Elements(int von, int bis) const
  452. {
  453.     if (bis < 0) bis = Count(SEP);    // Rest ab von
  454.     bis += 1 - von;                    // bis = bis - von + 1
  455.  
  456.     if (von <  0) return "";        // Falscher Parameter von
  457.     if (bis <  0) return "";        // Falscher Parameter bis < von 
  458.  
  459.     int    len = GetLength();            // LΣnge des aktuellen Strings
  460.     XString copy = *this;            // Copy des aktuellen Strings
  461.  
  462.     for (int v = 0;    (v < len) && von; v++) if (copy[v] == SEP) von--;
  463.     for (int b = v;    (b < len) && bis; b++) if (copy[b] == SEP) bis--;
  464.     if ((b > 0) && !((b == len) && bis)) b--;
  465.  
  466.     XString erg;
  467.     if (v >= len)        erg = Repeat(SEP, --bis);
  468.     else if (b == 0)    erg = "";
  469.     else if (b < len)    erg = copy.Mid(v, b - v); 
  470.     else                erg = copy.Mid(v) + Repeat(SEP, --bis);
  471.  
  472.     return erg;
  473. }
  474.  
  475. XString XString::Elements(int von, int bis, char sep) const
  476. {
  477.     char tempSep = SEP;
  478.     SEP = sep;
  479.     XString erg = Elements(von, bis);
  480.     SEP = tempSep;
  481.  
  482.     return erg;
  483. }
  484.  
  485. /*****************************************************************************
  486.  * Klasse:        XString
  487.  * Funktion:    SetElement
  488.  * Parameter:    pos            Suchposition
  489.  *                rep            Ersatzstring, -int, -double
  490.  * Return:        String mit ersetzem Wert
  491.  * Beipsiel:    str = "1|2|3"
  492.  *                str.SetElement(1, "99")    ==> "1|99|3"
  493.  *                str.SetElement(5, "99")    ==> "1|2|3|||99"
  494.  *                str.SetElement(1)        ==> "1||3"
  495.  *                str.SetElement(2, 75)    ==> "1|2|75"
  496.  *                str.SetElement(1, 1.23)    ==> "1|1.23|3"
  497.  *
  498.  * Ersetzt in einem Elemente-String den i-ten Eintrag. Wenn der Eintrag nicht
  499.  * existiert, wird er automatisch generiert. DefaultmΣ▀ig wird der Replace-
  500.  * String durch "" repΣsentiert, was einem L÷schen des i-ten Elements ent-
  501.  * spricht. Alternativ kann auch ein double- oder int-Wert ⁿbergeben werden.
  502.  ****************************************************************************/
  503. XString XString::SetElement(int pos, const XString& rep) const
  504. {
  505.     if (pos < 0)    return *this;
  506.  
  507.     int n = GetLength();
  508.     int s = Count(SEP);
  509.  
  510.     if (s < pos) return (*this + Repeat(SEP, pos - s) + rep);
  511.  
  512.     for (int von = 0;    pos;     von++)    if (m_pchData[von] == SEP) pos--;
  513.     for (int bis = von; bis < n; bis++)    if (m_pchData[bis] == SEP) break;
  514.  
  515.     if (bis < von)    return Insert(rep, von);
  516.     else            return Replace(rep, von, bis);
  517. }
  518.  
  519. /*****************************************************************************
  520.  * Klasse:        XString
  521.  * Funktion:    ElementIndex
  522.  * Parameter:    such        Suchstring
  523.  * Return:        Elementposition des Suchstrings, wenn er gefunden wurde,
  524.  *                -1 sonst
  525.  * Beipsiel:    str = "0|1|2|3"
  526.  *                 str.ElementIndex("2")    ==> 2
  527.  *                str.ElementIndex("5")    ==> -1
  528.  *                str.ElementIndex(1.0)    ==> 1
  529.  *                str.ElementIndex(3)        ==> 3
  530.  *
  531.  * Liefert den Index eines Eintrags in einer Element-Liste zurⁿck. Bei der
  532.  * ▄bergabe von int- oder double-Werten, werden die Werte ⁿberprⁿft und nicht
  533.  * die Strings. So wird der Eintrag "3.0" auch dann gefunden, wenn nach 3
  534.  * gesucht wird.
  535.  ****************************************************************************/
  536. int XString::ElementIndex(const XString& such) const
  537. {
  538.     for (int j=0; j<=Count(SEP); j++) if (GetString(j) == such) return j;
  539.     return -1;
  540. }
  541.  
  542. int XString::ElementIndex(double such) const
  543. {
  544.     for (int j=0; j<=Count(SEP); j++) if (GetDouble(j) == such) return j;
  545.     return -1;
  546. }
  547.  
  548. int XString::ElementIndex(int such) const
  549. {
  550.     for (int j=0; j<=Count(SEP); j++) if (GetInt(j) == such) return j;
  551.     return -1;
  552. }
  553.  
  554. int XString::ElementIndex(char such) const
  555. {
  556.     for (int j=0; j<=Count(SEP); j++) if (GetChar(j) == such) return j;
  557.     return -1;
  558. }
  559.  
  560. int XString::ElementIndex(bool such) const
  561. {
  562.     for (int j=0; j<=Count(SEP); j++) if (GetBool(j) == such) return j;
  563.     return -1;
  564. }
  565.  
  566. /*****************************************************************************
  567.  * Klasse:        XString
  568.  * Funktion:    ElementSortString, ElementSortDouble, ElementSortInt,
  569.  *                ElementSortChar
  570.  *                (template<>Sort, compString, compDouble, compInt, compChar)
  571.  * Parameter:    -
  572.  * Return:        Sortierter Element-String
  573.  * Beipsiel:    XString("9|3|1").ElementSortString()        ==>    "1|3|9"
  574.  *                XString("4|4.3|3.9").ElementSortDouble()    ==>    "3.9|4|4.3"
  575.  *
  576.  * Sortiert die Elemente eines Element-Strings nach dem angegebenen Typ in
  577.  * aufsteigender Reihenfolge. Hierzu wird das Template 'Sort' definiert, da▀
  578.  * nurstatisch in diesem File definiert ist.
  579.  *
  580.  * Zum Sortieren des Strings werden zuerst die Elemente in ein Array ⁿbertragen
  581.  * und dann mittels der Library-Funktion 'qsort' sortiert. Fⁿr jeden Typ steht
  582.  * hierfⁿr eine spezielle Vergleichsfunktion 'compTyp' zur Verfⁿgung, die
  583.  * ebenfalls nur statisch in diesem File definiert ist.
  584.  ****************************************************************************/
  585. int compString(XString *a, XString *b)    { return a->Compare(*b); }
  586. int compDouble(double *a, double *b)    { return ((*a == *b) ? 0 : ((*a > *b) ? 1 : -1)); }
  587. int compChar(char *a, char *b)            { return ((*a == *b) ? 0 : ((*a > *b) ? 1 : -1)); }
  588. int compInt(int *a, int *b)                { return ((*a == *b) ? 0 : ((*a > *b) ? 1 : -1)); }
  589.  
  590. template<class Typ> XString Sort(Typ, const XString& str, int (*comp)(const void *a, const void *b))
  591. {
  592.     const int anz = str.Count(XString::SEP) + 1;    // Anzahl der Elemente
  593.     Typ *ar = new Typ[anz];                            // Array fⁿr die Elemente
  594.  
  595.     for (int i=0; i<anz; i++)    str.Get(ar[i], i);    // Array erzeugen
  596.     qsort(ar, anz, sizeof(ar[0]), comp);            // Array sortieren
  597.  
  598.     XString ret = ar[0];                            // Rⁿckgabewert
  599.     for (i=1; i<anz; i++) ret = Concat(ret, ar[i]);    // Elementstring aufbauen
  600.  
  601.     delete [] ar;                                    // Array l÷schen
  602.     return ret;
  603. }
  604.  
  605. #define CAST    int (*)(const void*, const void*)
  606. XString XString::ElementSortString() const    { return Sort((XString)0,    *this, (CAST)compString); }
  607. XString XString::ElementSortDouble() const    { return Sort((double)0,    *this, (CAST)compDouble); }
  608. XString XString::ElementSortChar() const    { return Sort((char)0,        *this, (CAST)compChar); }
  609. XString XString::ElementSortInt() const        { return Sort((int)0,        *this, (CAST)compInt); }
  610. #undef CAST
  611.  
  612. /*****************************************************************************
  613.  * Klasse:        XString
  614.  * Funktion:    GetDoubleFormatString
  615.  * Parameter:    -
  616.  * Return:        Formatstring im C++-Format
  617.  * Beipsiel:    XString("###.##").GetDoubleFormatString()    ==>    "%6.2lf"
  618.  *                XString("*****").GetDoubleFormatString()    ==> "%5.0lf"
  619.  *                GetDoubleFormatString("###.##")                ==> "%6.2lf"
  620.  *
  621.  * Erzeugt einen C++-Formatstring (der in printf()- oder Format()-Funktionen
  622.  * benutzt werden kann) aus einem Formatstring in Direkteingabe (also
  623.  * Angabe der Stellen). ZusΣtzlich existiert noch eine friend-Version die
  624.  * direkt den Formatstring als Parameter erhΣlt.
  625.  ****************************************************************************/
  626. XString XString::GetDoubleFormatString() const
  627. {
  628.     int punktPosition = Find('.') + 1;
  629.     int laenge = GetLength();
  630.     if (punktPosition == 0) punktPosition = laenge;
  631.  
  632.     XString ret;
  633.     ret.Format("%%%d.%dlf", laenge, laenge - punktPosition);
  634.  
  635.     return ret;
  636. }
  637.  
  638. XString GetDoubleFormatString(const XString& str)
  639. {
  640.     return str.GetDoubleFormatString();
  641. }
  642.  
  643. /*****************************************************************************
  644.  * Klasse:        - (friend XString)
  645.  * Funktion:    GetStringTableEntry
  646.  * Parameter:    id        ID des Strings in der String-Table
  647.  * Return:        Eintrag in der String-Table
  648.  *
  649.  * Mit dieser Funktion wird ein Eintrag aus der String-Table gelesen und
  650.  * zurⁿckgegeben
  651.  ****************************************************************************/
  652. XString GetStringTableEntry(UINT id)
  653. {
  654.     XString ret;
  655.     ret.LoadString(id);
  656.     return ret;
  657. }
  658.  
  659. /*****************************************************************************
  660.  * Klasse:        - (friend XString)
  661.  * Funktion:    itoa, utoa, dtoa
  662.  * Parameter:    i, u, d        Zahlenwert im jeweiligen Format
  663.  *                n            Anzahl der Nachkommastellen
  664.  * Return:        Formatierter XString
  665.  * Beipsiel:    itoa(5)            ==> "5"
  666.  *                dtoa(3.72)        ==> "3.72"
  667.  *                dtoa(3.72, 1)    ==> "3.7"
  668.  *
  669.  * Wandelt eine Zahl vom Typ int, unsigned oder double in einen XString um
  670.  ****************************************************************************/
  671. XString itoa(int i)                { XString h; h.Format("%d", i); return h; }
  672. XString utoa(UINT u)            { XString h; h.Format("%u", u); return h; }
  673. XString dtoa(double d)            { XString h; h.Format("%g", d); return h; }
  674. XString dtoa(double d, int n)    { XString h; h.Format("%.*f", n, d); return h; }
  675.  
  676. /*****************************************************************************
  677.  * Klasse:        - (friend XString)
  678.  * Funktion:    Repeat
  679.  * Parameter:    c        Zu wiederholendes Zeichen
  680.  *                str        Zu wiederholende Zeichenkette
  681.  *                n        Anzahl der Wiederholungen
  682.  * Return:        Formatierter String
  683.  * Beipsiel:    Repeat('*', 5)    ==> "*****"
  684.  *                Repeat('#', 0)    ==> ""
  685.  *                Repeat("01", 5)    ==> "0101010101"
  686.  *
  687.  * Erzeugt einen String aus mehreren Wiederholungen eines Zeichens oder
  688.  * eines Strings.
  689.  ****************************************************************************/
  690. XString Repeat(char c, int n)
  691. {
  692.     XString erg(c, n);
  693.  
  694.     return erg;
  695. }
  696.  
  697. XString Repeat(const XString& str, int n)
  698. {
  699.     for (XString ret; n > 0; n--)
  700.         ret += str;
  701.  
  702.     return ret;
  703. }
  704.  
  705. /*****************************************************************************
  706.  * Klasse:        - (friend XString)
  707.  * Funktion:    Concat
  708.  * Parameter:    a, b, .., h
  709.  * Return:        Zusammengesetzter Element-String
  710.  * Beipsiel:    Concat("alpha", "beta", "gamma")    ==> "alpha|beta|gamma"
  711.  *
  712.  * Verbindet Strings zu einem durch '|' getrennten Elemente-String. Die
  713.  * Funktion kann mit bis zu 8 Elementen aufgerufen werden. Eine beliebige
  714.  * Anzahl an Parametern mittels "..." ist nicht m÷glich, da XString kein
  715.  * skalarer Typ ist. Dies wΣre nur mit char* m÷glich, dann mⁿssten aber alle
  716.  * Parameter explizit gecastet werden.
  717.  ****************************************************************************/
  718. #define S    XString::SEP
  719.  
  720. XString Concat(XS& a,XS& b)
  721.     { return (a+S+b); }
  722.  
  723. XString Concat(XS& a,XS& b,XS& c)
  724.     { return (a+S+b+S+c); }
  725.  
  726. XString Concat(XS& a,XS& b,XS& c,XS& d)
  727.     { return (a+S+b+S+c+S+d); }
  728.  
  729. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e)
  730.     { return (a+S+b+S+c+S+d+S+e); }
  731.  
  732. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f)
  733.     { return (a+S+b+S+c+S+d+S+e+S+f); }
  734.  
  735. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g)
  736.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g); }
  737.  
  738. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h)
  739.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h); }
  740.  
  741. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i)
  742.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i); }
  743.  
  744. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i,XS& j)
  745.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i+S+j); }
  746.  
  747. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i,XS& j,XS& k)
  748.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i+S+j+S+k); }
  749.  
  750. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i,XS& j,XS& k,XS& l)
  751.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i+S+j+S+k+S+l); }
  752.  
  753. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i,XS& j,XS& k,XS& l,XS& m)
  754.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i+S+j+S+k+S+l+S+m); }
  755.  
  756. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i,XS& j,XS& k,XS& l,XS& m,XS& n)
  757.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i+S+j+S+k+S+l+S+m+S+n); }
  758.  
  759. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i,XS& j,XS& k,XS& l,XS& m,XS& n,XS& o)
  760.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i+S+j+S+k+S+l+S+m+S+n+S+o); }
  761.  
  762. XString Concat(XS& a,XS& b,XS& c,XS& d,XS& e,XS& f,XS& g,XS& h,XS& i,XS& j,XS& k,XS& l,XS& m,XS& n,XS& o,XS& p)
  763.     { return (a+S+b+S+c+S+d+S+e+S+f+S+g+S+h+S+i+S+j+S+k+S+l+S+m+S+n+S+o+S+p); }
  764.  
  765. #undef S
  766.  
  767. /****************************************************************************
  768.  * Klasse:        -
  769.  * Funktion:    SerializeElements
  770.  * Parameter:    ar            Archiv, in das, bzw. von dem serialisiert wird
  771.  *                pElements    Pointer auf ein oder mehrere Elemente
  772.  *                nCount        Anzahl der zu serialisierenden Elemente
  773.  * Return:        -
  774.  *
  775.  * Diese Funktion wird ben÷tigt, wenn eine Template-Klasse serialisiert wird.
  776.  * Fⁿr CMap-, CList- und CArray-Instatiierungen mit XString wird diese
  777.  * Funktion aus der Serialize-Funktion der Template-Klasse heraus aufgerufen.
  778.  ****************************************************************************/
  779. void AFXAPI SerializeElements(CArchive& ar, XString* pElements, int nCount)
  780. {
  781.     ASSERT(nCount == 0 || AfxIsValidAddress(pElements, nCount * sizeof(XString)));
  782.  
  783.     if (ar.IsStoring())    for (; nCount--; ++pElements) ar << *pElements;
  784.     else                for (; nCount--; ++pElements) ar >> *pElements;
  785. }
  786.  
  787.