schnelles Regex-Cleaning



  • Hallo

    Ich suche nach dem schnellsten und elegantesten Weg einen String nach Sonderzeichen zu durchsuchen deren ASCII Wert unter 32 oder über 127 liegt.
    Aus ANSI C kenne ich es das man dazu eine kleine Funktion benutz, die jedes einzelne Zeichen durchläuft und prüft.
    Wie mache ich das in C++? Weiß das es in Boost so etwas gibt aber dazu habe ich gerade keine Bücher hier....
    Arbeite mit gcc 4.1.2 unter Debian Linux und suche nach einer kleine eleganten Lösung die möglichst schnell sein sollte.

    Danke Magier



  • wie in C: eine schleife die alle buchstaben betrachtet. uU mit for_each statt einer schleife, aber warum sollte man es komplett anders lösen?

    regex gehen natürlich in c++ genauso wie in c auch...



  • Jo, weiß das in C++ auch altes C funzt, dachte nur es gäbe etwas kürzeres... irgendwas schon vorgeschrieben... will nicht immer das Rad neu erfinden und meine eigenen Fehler suchen gehen.. 😃



  • Ich würds wahrscheinlich so in etwa anstellen:

    #include <cstdlib>
    using std::size_t;
    
    template <typename T>
    class CountEvil
    {
    public:
     typedef size_t size_type;
     typedef T value_type;
    
    private:
     T lower;
     T upper;
    
     size_type count; 
    public:
     CountEvil(T _lower, T _upper) : lower(_lower), upper(_upper), count(0) {}
     void operator () (T val) {if ((val > upper) || (val < lower)) ++count;}
    
     size_type Get() const {return count;}
    };
    
    #include <algorithm>
    #include <string>
    #include <iostream>
    
    int main()
    {
     std::string in;
     std::getline (std::cin, in);
    
     CountEvil <std::string::value_type> evilchars('a', 'Z');
    
     std::for_each(in.begin(), in.end(), evilchars);
    
     std::cout << evilchars.Get() << std::endl;
    }
    

    bb


  • Administrator

    @unskilled,
    Dein Programm funktioniert nicht. An std::for_each wird eine Kopie übergeben 😉

    Für Regex gibt es:
    http://www.boost.org/doc/libs/1_38_0/libs/regex/doc/html/index.html
    http://www.boost.org/doc/libs/1_38_0/doc/html/xpressive.html

    Aber hier empfiehlt es sich den genau gleichen Weg einzuschlagen, wie in C auch, dürfte wohl das schnellste und einfchste sein. Ich würde aber nicht std::for_each nehmen, sondern zum zählen z.B. std::count_if :
    http://www.cplusplus.com/reference/algorithm/count_if/

    Oder zum löschen, std::remove_if :
    http://www.cplusplus.com/reference/algorithm/remove_if/

    Grüssli



  • Dravere schrieb:

    Oder zum löschen, std::remove_if :
    http://www.cplusplus.com/reference/algorithm/remove_if/

    ACK 🙂



  • japp, count_if wär auch ne idee gewesen - verdammt 😉

    btw:

    int main()
    {
     std::string in;
     std::getline (std::cin, in);
    
     const CountEvil <std::string::value_type> evilchars = std::for_each(in.begin(), in.end(), CountEvil <std::string::value_type> ('a', 'Z'));
    
     std::cout << evilchars.Get() << std::endl;
    }
    


  • Bei std::remove_if() sollte man noch beachten, dass zuerst mal nichts gelöscht, sondern nur die Iterator-Range so umgeordnet wird, dass man einen zusammenhängenden Bereich am Schluss der Range mittels erase() wirklich löschen kann.



  • Ich würds wahrscheinlich so in etwa anstellen:

    #include <cstdlib>
    using std::size_t;

    template <typename T>
    class CountEvil
    {
    public:
    typedef size_t size_type;
    typedef T value_type;

    private:
    T lower;
    T upper;

    size_type count;
    public:
    CountEvil(T _lower, T _upper) : lower(_lower), upper(_upper), count(0) {}
    void operator () (T val) {if ((val > upper) || (val < lower)) ++count;}

    size_type Get() const {return count;}
    };

    #include <algorithm>
    #include <string>
    #include <iostream>

    int main()
    {
    std::string in;
    std::getline (std::cin, in);

    CountEvil std::string::value_type evilchars('a', 'Z');

    std::for_each(in.begin(), in.end(), evilchars);

    std::cout << evilchars.Get() << std::endl;
    }

    oder einfach

    #include <string> 
    #include <iostream> 
    using namespace std;
    int main() 
    { 
     std::string in; 
     std::getline (std::cin, in); 
    
     int count=0;
     for(string::iterator i=in.begin();i!=in.end();++i)
       if('a'<=*i && *i<='z')
         ++count;
     cout << count << '\n'; 
    }
    


  • volkard schrieb:

    Ich würds wahrscheinlich so in etwa anstellen:

    #include <cstdlib>
    using std::size_t;

    template <typename T>
    class CountEvil
    {
    public:
    typedef size_t size_type;
    typedef T value_type;

    private:
    T lower;
    T upper;

    size_type count;
    public:
    CountEvil(T _lower, T _upper) : lower(_lower), upper(_upper), count(0) {}
    void operator () (T val) {if ((val > upper) || (val < lower)) ++count;}

    size_type Get() const {return count;}
    };

    #include <algorithm>
    #include <string>
    #include <iostream>

    int main()
    {
    std::string in;
    std::getline (std::cin, in);

    CountEvil std::string::value_type evilchars('a', 'Z');

    std::for_each(in.begin(), in.end(), evilchars);

    std::cout << evilchars.Get() << std::endl;
    }

    oder einfach

    #include <string> 
    #include <iostream> 
    using namespace std;
    int main() 
    { 
     std::string in; 
     std::getline (std::cin, in); 
    
     int count=0;
     for(string::iterator i=in.begin();i!=in.end();++i)
       if('a'<=*i && *i<='z')
         ++count;
     cout << count << '\n'; 
    }
    

    Gott! 👍



  • Danke für alle eure Beiträge.. habe mir das hier zusammen geschrieben....

    int F_Clean(string& str_in)
    {
        string str_temp;
        int int_now, int_count, int_re = 0;
        char chr_t;
        str_temp.clear();
        for (int_count = 0; int_count < str_in.size() ; int_count++)
        {
            int_now = str_in[int_count];
            if ((int_now > 31) && (int_now < 127))
            {
                chr_t = int_now;
                str_temp=str_temp + chr_t;
            }
            else
            {
                int_re++;
            }
        }
        str_in = str_temp;
        return int_re;
    }
    

    Nicht schön aber es funzt 🕶

    BEDANKT!!!!!!!!!!!



  • ein paar ideen, die mir da einfallen

    int F_Clean(string& str_in)
    {
        string str_temp;
        for (string::itearator i=str_in.begin();i!=str.end();++i)
            if ((*i > 31)/* && (*i < 127)*/)//signed char?!
                str_temp+=*i;
        swap(str_in,str_temp);
        return str_tmp.size()-str_in.size();
    }
    

    /*remove_if tönt sehr lecker, das würde ich aber vertahen bis lamda-dinge da sind. ;)*/


Anmelden zum Antworten