anzahl der spalten eines strings



  • ich habe einen string aus einer datei eingelesen. dieser kann eine beliebige form besitzen.
    gibt es nun eine möglichkeit die anzahl der spalten dieses strings zu ermitteln (die spalten sind voneinander durch lehrzeichen getrennt: spalte1 spalte2 spalte3...)?



  • Anzahl Leerzeichen + 1.

    MfG, EOutOfResources



  • und wie zählt man die leerzeichen am einfachsten?



  • std::string DeinString;
    unsigned int Count = 0;
    for(unsigned int Search = 0; Search < DeinString.lenght(); Search++)
    {
      if(DeinString[Search] == ' ')
        Count++;1
    };
    

    MfG, EOutOfResouces



  • boost::tokenizer ist ne gute Idee für sowas. Der zerlegt dir nen String in Einzelteile, basierend auf einem oder mehreren vorgegebenen Zeichen.
    Oder eine Mischung aus std::string::find_first_of und std::string::substr.



  • #include <iostream> // distance, istream_iterator
    #include <iterator>
    #include <sstream>
    #include <string>
    
    int main()
    {
        using namespace std;
    
        string zeile = "das sind vier Spalten";
        istringstream buf( zeile );
        cout << "Anzahl Spalten: " << distance( istream_iterator< string >(buf), istream_iterator< string >() ) << endl;
    
        return 0;
    }
    


  • Werner_logoff schrieb:

    ...
        cout << "Anzahl Spalten: " << distance( istream_iterator< string >(buf), istream_iterator< string >() ) << endl;
    ...
    }
    

    👍 Schön, wenn die Spalten auch durch mehrere und verschiedene Leerzeichen getrennt sein können und die Zeile mit Leerzeichen anfängt oder endet. Sonst reicht auch ein
    count_if(zeile.begin(), zeile.end(), isspace)+1 oder count(zeile.begin(), zeile.end(), ' ')+1

    Sind innerhalb der Spalten auch Leerzeichen erlaubt ("Spalte Nr. 1" Spalte2 "Spalte 3") ist der boost tokenizer wohl am einfachsten.
    http://www.boost.org/doc/libs/1_46_0/libs/tokenizer/escaped_list_separator.htm



  • Ich verstehe werners Code nicht. distance ermittelt doch den Abstand zwischen zwei Iteratoren. Jetzt ist der iterator ohne Argument ein past-the-end-Iterator und der erste liest was aus dem Buffer.

    Achso, ist das, weil jede Iteration des istream_iterators einen Wert bis zu dem Leerzeichen einliest und distance über operator++ zählt? Genial.



  • ich versteh diese zeile nicht

    cout << "Anzahl Spalten: " << distance( istream_iterator< string >(buf), istream_iterator< string >() ) << endl;
    

    könnte mir das bitte jemand erklären?



  • cuba1 schrieb:

    cout << "Anzahl Spalten: " << distance( istream_iterator< string >(buf), istream_iterator< string >() ) << endl;
    

    könnte mir das bitte jemand erklären?

    .. hat sich noch keiner erbarmt. Nun denn

    Der Trick besteht darin, dass man aus der Zeile Worte heraus liest. Ein Wort ist eine Folge von Zeichen (mindestens eines) ohne Leerzeichen (genauer White Space Character). Liest man einen string vomistream (hier Variable buf ) ein, so wird das nächst folgende Wort gelesen.

    Also könnte man schreiben:

    string zeile = "das sind vier Spalten";
        istringstream buf( zeile );
        int wortZaehler = 0;
        for( string wort; buf >> wort; )
            ++wortZaehler;
        cout << "Anzahl Spalten: " << wortZaehler << endl;
    

    Der Ausdruck ' buf >> wort ' liefert den istream zurück, der in ein bool konvertiert werden kann, was angibt, ob das Einlesen gut ging. Somit zählt obige Schleife die Worte, unabhängig davon, ob vorher oder nachher noch Leerzeichen stehen oder nicht, und auch unabhängig davon wie viele oder welche Leerzeichen zwischen den Worten stehen.

    Der nächste Schritt geht dahin, einen Algorithmus zu benutzen, damit man diese Schleife nicht selbst schreiben muss. Dazu muss man das Einlesen (hier der Worte) aber erst in Iteratoren 'übersetzen', da die Algorithmen aus dem C++-Standard auf Iteratoren aufsetzen. Das erledigt istream_iterator. Schau Dir das Beispiel hinter dem Link an.
    Und distance zahlt einfach die Anzahl, die man den ersten Iterator inkrementieren muss, um den zweiten zu erreichen.

    Im Übrigen bin ich der Meinung, dass das ganze unnötig ist! Lies doch einfach die Dinge, die Du benötigst, gleich richtig aus der Datei aus. Wenn Du die Container des C++-Standards benutzt, so hast Du auch kein Problem mit dynamischen Strukturen.

    Gruß
    Werner



  • Dann war meine Vermutung richtig. Danke für die Erklärung 🙂


Anmelden zum Antworten