Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » Rätselecke » 47. Virtualrätsel: Java goes C++

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 < [ 3 ]
010
16.09.2003, 19:13 Uhr
0xdeadbeef
Gott
(Operator)


Nach dem Motto "Diese Aussage ist falsch", ja?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
17.09.2003, 10:00 Uhr
virtual
Sexiest Bit alive
(Operator)


Naja, scheint wohl kein rechtes interesse da zu sein:

C++:
#include <string>
#include <iostream>
#include <algorithm>
#include <stdexcept>

class StringTokenizer
{
private:
    std::string m_strText;
    std::string::size_type m_nTokenized;
    char m_cDelimiter;

public:
    StringTokenizer(
        const char* p_szText,
        char p_cDelimiter)
        :m_strText(p_szText), m_nTokenized(0), m_cDelimiter(p_cDelimiter)
    {
    }

    StringTokenizer(
        const std::string& p_strText,
        char p_cDelimiter)
        :m_strText(p_strText), m_nTokenized(0), m_cDelimiter(p_cDelimiter)
    {
    }

    bool hasMoreTokens() const
    {
        return std::string::npos!=m_strText.find(m_cDelimiter, m_nTokenized);
    }

    int countTokens() const
    {
        if (std::string::npos!=m_nTokenized)
        {
            return  std::count(m_strText.begin()+m_nTokenized,
                               m_strText.end(),
                               m_cDelimiter);
        }
        return 0;
    }

    std::string getNextToken(
        char p_cDelimiter)
    {
        if (std::string::npos==m_nTokenized)
        {
            throw std::runtime_error("No more tokens");
        }

        std::string::size_type nStart = m_nTokenized;
        m_nTokenized = m_strText.find(p_cDelimiter, m_nTokenized);

        if (std::string::npos==m_nTokenized)
        {
            return m_strText.substr(nStart);
        }
        return m_strText.substr(nStart, m_nTokenized++ - nStart);
    }

    std::string getNextToken()
    {
        return getNextToken(m_cDelimiter);
    }

};

/*** DEMO ***/
#ifdef _WIN32
# define DELIMITER ';'
#else
# define DELIMITER ':'
#endif

int main()
{
    StringTokenizer tokenizer(getenv("PATH"), DELIMITER);

    while (tokenizer.hasMoreTokens())
        std::cout<<tokenizer.getNextToken()<<std::endl;
}


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
19.09.2003, 09:39 Uhr
~wissender
Gast


Schade, wollte gerade...
Aber Object (als Basisklasse) hätte dazugehört :-)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
19.09.2003, 10:01 Uhr
~wissender
Gast


hm, kannst auch auch auf das Standardset an Delimiter reagieren, nämlich \t\n\r\f, ich glaube nicht.
Ich finde auch, das du nicht immer zählen müsstest, weil man das ja genau nur einmal machen sollte, da sich der tokenizer (wahrscheinlich) nicht verändert!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
19.09.2003, 10:19 Uhr
virtual
Sexiest Bit alive
(Operator)


@wissender
Jetzt wo Du es erwähnst: da wird von countTokens Im zweifel ein token zuwenig zurückgegeben. Rein aus Performance sicht hast Du sicherlich recht.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
19.09.2003, 17:26 Uhr
~wissender
Gast


Habe auch mal implementiert, ist etwas umfangreicher und größtenteils ungetestet , scheint aber soweit zu funktionieren


C++:
#include <string>
#include <stdexcept>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <limits>
using namespace std;

class StringTokenizer {
    public:
        //Drei Konstuktoren in einem, C++ rockt hier!
        StringTokenizer(const string str_ = "",
                        const string delim_ = "\t\n\r\f" ,
                        bool returnDelims_ = false) throw();
        
        StringTokenizer(const StringTokenizer & ) throw();
        
        StringTokenizer& operator=(const StringTokenizer & ) throw();
        bool operator==(const StringTokenizer & ) const throw();
        bool operator!=(const StringTokenizer & ) const throw();
        
        friend ostream& operator<<(ostream &, const StringTokenizer & );
        
        unsigned int countTokens() const throw();
        bool hasMoreTokens() const throw();
        string nextToken() throw (runtime_error);
        string nextToken(string &newDelimiter) throw (runtime_error);
        
    private:
        string str;
        string delim;
        vector<string> tokens;
        unsigned int pos;
        bool returnDelims;
        
    private:
        bool isDelim(char) const throw();
        void makeTokens() throw();                  
};

StringTokenizer :: StringTokenizer(const string str_,
                                   const string delim_,
                                   bool returnDelims_) throw()
                 : str(str_), delim(delim_), tokens(),
                   returnDelims(returnDelims_) {
    makeTokens();
}
                  
StringTokenizer :: StringTokenizer(const StringTokenizer &tokenizer) throw()
                 : str(tokenizer.str), delim(tokenizer.delim),
                   tokens(tokenizer.tokens), pos(tokenizer.pos),
                   returnDelims(tokenizer.returnDelims) {}
                  
StringTokenizer& StringTokenizer :: operator=(const StringTokenizer &tokenizer) throw() {
    if(this != &tokenizer) {
        str = tokenizer.str;
        delim = tokenizer.delim;
        tokens = tokenizer.tokens;
        pos = tokenizer.pos;
        returnDelims = tokenizer.returnDelims;
    }
    return *this;
}

bool StringTokenizer :: operator==(const StringTokenizer &tokenizer) const throw() {
    return str == tokenizer.str && delim == tokenizer.delim &&
           pos == tokenizer.pos && returnDelims == tokenizer.returnDelims;
}

bool StringTokenizer :: operator!=(const StringTokenizer &tokenizer) const throw() {
    return !(*this == tokenizer);
}

ostream& operator<<(ostream &out, const StringTokenizer &tokenizer) {
    if(!(tokenizer.tokens.begin() + tokenizer.pos >= tokenizer.tokens.end()))
        copy(tokenizer.tokens.begin() + tokenizer.pos, tokenizer.tokens.end(),
             ostream_iterator<string>(out, "\n"));
    return out;
}

inline
unsigned int StringTokenizer :: countTokens() const throw() {
    return tokens.size() - pos;
}

inline
bool StringTokenizer :: hasMoreTokens() const throw() {
    return pos < tokens.size();
}

string StringTokenizer :: nextToken() throw (runtime_error) {
    if(pos == tokens.size()) {
        runtime_error err("No more tokens!");
        throw err;
    }      
    return tokens[pos++];
}

string StringTokenizer :: nextToken(string &newDelimiter) throw (runtime_error) {
    if(pos == tokens.size()) {
        runtime_error err("No more tokens!");
        throw err;
    }
    
    //Wir müssen die Position im String finden, bei der der aktuelle Token mit
    //dem alten Delimiter beginnt.
    unsigned int tokencounter = 0;
    unsigned int currPosInString = 0;
    while(currPosInString < str.size() && tokencounter <= pos) {
        if(isDelim(str[currPosInString]))
            ++tokencounter;
        ++currPosInString;        
    }
      
    delim = newDelimiter;
    str = str.substr(currPosInString);
    makeTokens();
    return tokens[pos++];
}

bool StringTokenizer :: isDelim(char possDelim) const throw() {
    for(unsigned int i = 0; i < delim.size(); ++i) {
        if(possDelim == delim[i])
            return true;
    }  
    return false;
}

void StringTokenizer :: makeTokens() throw() {
    //Aufräumen
    tokens.clear();
    pos = 0;
    
    string token;
    for(unsigned int i = 0; i < str.size(); ) {      
        while(isDelim(str[i]) && i < str.size()) {            
            if(returnDelims) {
                token = str[i];
                tokens.push_back(token);
            }
            ++i;
        }
                
        token = "";
        while(!isDelim(str[i]) && i < str.size())
            token += str[i++];            
                    
        tokens.push_back(token);        
    }          
}  

int main() {
    StringTokenizer tok("hAxnhnheh-hKhazthrhihn", "hxz");
    cout << tok;
    while(tok.hasMoreTokens())
        cout << tok.nextToken();
    return 0;
}



--edit: Pablo. smilies entfernt --

Dieser Post wurde am 19.09.2003 um 17:35 Uhr von Pablo Yanez Trujillo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
19.09.2003, 18:07 Uhr
virtual
Sexiest Bit alive
(Operator)


Zwei Anmerkungen (ich muß immer nörgeln!)

1. wenn Du schon soviel wert auf Performance legst, dann solltest Du die Strings nicht by copy sondern by reference als Parameter übergeben. #

2. Copy Constructor und Zuweisungsoperator ist überflüssig: Die Vectoren und strings kopieren sich von selbst.

3. Das zerlegen bereits im ctor dürfte bei Strings mit vielen Tokens, bei denen nur einige wenige am Anfang benötigt werden, sich neg. auf die Performance auswirken.

Ansonsten schön. Meine version ist hier, mit Deinen erweiterungsvorschlägen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
19.09.2003, 23:17 Uhr
~wissender
Gast


zu1) Ja, da fehlen die Referenzen, das stimmt!

zu2) Jo, war aber gerade dabei, ist es denn so, dass C++ die Copy-Ctors
selber aufruft (von string,vector, etc)?

zu3) Ist die Frage, weil man normalerweise auch die Token braucht, ich denke im Schnitt ist es performanter.

Habe das halt auf die Schnelle gemacht, war ja halt sowieso nur zum .
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
19.09.2003, 23:53 Uhr
virtual
Sexiest Bit alive
(Operator)


zu 2)
Ja
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
20.09.2003, 09:25 Uhr
~wissender
Gast


Habe gerade festgestellt, das string die Methode find_first_of(string) unterstützt, und dabei auch alle Zeichen im Parameterstring überprüft.
Das ist ja genau das, was ich brauche, damit hätte ich ja meine Klasse *sehr* viel kürzer machen können, naja.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 < [ 3 ]     [ Rätselecke ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: