Text/Datenverarbeitung (Suchwort finden)



  • Hallo zusammen,

    habe eine Aufgabe bekommen aus einer Textdatei ein Suchwort zu suchen und den Zähler damit zu erhöhen.
    Randbedingung:
    - zeilenweise einlesen
    - nur das Suchwort suchen

    Beispiel:
    Suchwort: Mueller
    Jedoch soll er nicht zählen wenn da steht Muellermilch!!!!

    Nun habe ich das Programm geschrieben, aber es läuft nicht.
    Denke das an der If Anweisung was flasch ist.
    Vielleicht könnt ihr mir weiterhelfen.

    #include<string>
    #include<iostream>
    #include<fstream>
    
    using namespace std;
    
    int main()
    {
    
    string dateiname;
    fstream muellermilch_datei;
    string line;
    int counter=0 ;
    string key;
    
    cout<<"Bitte Dateiname eingegeben"<<endl;
    cin>>dateiname;
    cout<< "Key eingeben"<< endl;
    cin>> key;
    
    muellermich_datei.open(dateiname.c_str());
    
    if(!muellermilch_datei)
    	{
    		cerr<<"Kann nicht geöffnet werden"<<endl;
    		exit (-1);
    	}
    string::size_type pos=0;
    
    while(getline(muellermilch_datei, line))
    {
    
    while(1)
    {
    pos=line.find(key,pos);
    
    if(pos!=string::npos)
    {									if(pos+key.size()+1==' '||pos+key.size()+1==','||pos+key.size()+1='\n')
    	{	counter++;
    		pos=pos+key.size();
    	}	
    else
    {
    break;
    }
    
    else
    {
    break;
    }
    }
    
    cout <<"es wurden "<< counter<< "übereinstimmungen gefunden"<< endl;
    
    muellermilch_datei.close();
    }
    

    Kann es sein das ich ein Fehler in der Schleife habe?
    Ich will ja nur testen ob das Wort alleine steht, oder vor einen ,/ . sowie am ende einer zeile.

    while(1)
    {
    pos=line.find(key,pos);
    
    if(pos!=string::npos)
    {									if(pos+key.size()+1==' '||pos+key.size()+1==','||pos+key.size()+1='\n')
    	{	counter++;
    		pos=pos+key.size();
    	}
    

    Vielen Dank.



  • Das hier

    if(pos+key.size()+1==' '||pos+key.size()+1==','||pos+key.size()+1='\n')

    sollte vielleicht

    if(line[pos+key.size()+1]==' '||line[pos+key.size()+1]==','||line[pos+key.size()+1]='\n')

    so aussehen?

    Abgesehen davon vorher noch pruefen, ob du auf dieses Element ueberhaupt zugreifen kannst ( if (pos+key.size()+1 < line.size() ..... )

    Schleife ist zwar unnoetig kompliziert aufgebaut, aber sollte so funktionieren denk ich.

    Ich persoenlich wuerde es aber anders machen. Ich wuerde einfach pruefen ob nach dem Schluesselwort ein Buchstabe folgt und wenn nein den Zaehler dann hochzaehlen.



  • #include <cctype>
    #include <string>
    #include <fstream>
    #include <stdexcept>
    
    unsigned long long count_occurrences( std::string const & filename, std::string const & word )
    {
    	std::ifstream file( filename );
    
    	if( !file.good() ) {
    
    		throw std::runtime_error( "File could not be opened!\n" );
    	}
    
    	std::string line;
    	unsigned long long counter = 0;
    
    	while( std::getline( file, line ) ) {
    
    		for( std::string::size_type pos = line.find( word ); pos != std::string::npos; pos = line.find( word, pos + word.length() ) ) {
    
    			if( !( pos && std::isalpha( line[ pos - 1 ] ) ) && !( ( pos + word.length() < line.length() ) && std::isalpha( line[ pos + word.length() ] ) ) ) {
    
    				counter++;
    			}
    		}
    	};
    
    	return counter;
    }
    


  • Wie wärs damit:

    std::size_t count_word(std::istream & reader, std::string const & word)
    {
        std::string line;
        std::size_t count(0);
        while(std::getline(reader, line))
        {
            //da wir zeilenweise einlesen sollen, der Umweg übet getline und stringstream
            //eigentlich kann man da aber drauf verzichten
            std::istringstream isstr(line);
            std::string token;
            isstr >> token;
            if(word.find(word) != std::string::npos)
            {
                ++count;
            }
        }
        return count;
    }
    

    ?



  • Rob c++ schrieb:

    habe eine Aufgabe bekommen aus einer Textdatei ein Suchwort zu suchen und den Zähler damit zu erhöhen.
    Randbedingung:
    - zeilenweise einlesen

    Tachyon schrieb:

    //da wir zeilenweise einlesen sollen, der Umweg übet getline und stringstream
            //eigentlich kann man da aber drauf verzichten
    

    genau - kann mir irgendjemand sagen, warum man gerade Anfänger ständig mit 'Zeilenweise einlesen' belastet. Das führt doch bloß über getline zum String-Gefrickele 👎 . Ohne dieses 'Zeilenweise einlesen' ist die Aufgabe leicht lösen:

    #include <algorithm> // count
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <iterator> // istream_iterator
    
    int main()
    {
        using namespace std;
        string suchwort = "Mueller";
        string dateiname = "Input.txt";
        ifstream datei( dateiname.c_str() );
        if( !datei.is_open() )
        {
            cerr << "Konnte Datei '" << dateiname << "' nicht oeffnen" << endl;
            return -2;
        }
        int counter = 0;
        for( string wort; datei >> wort; )
        {
            if( wort == suchwort ) 
                ++counter;
        }
        cout << "Das Wort '" << suchwort << "' kam " << counter << "mal vor." << endl;
    }
    

    oder etwas eleganter - ab Zeile 18:

    cout << "Das Wort '" << suchwort << "' kam " 
            << count( istream_iterator< string >( datei ), istream_iterator< string >(), suchwort ) << "mal vor." << endl;
    


  • Werner_logoff schrieb:

    ...

    Das funktioniert aber nicht, wenn das Token z.B. ein Punkt enthält. Daher das "String-Gefrickel" über string::find. Man kann zwar auch den Skip-Parser im Stream anpassen, aber das find ich nun doch arg komplizert für einen Anfänger. Außerdem ist das auch deutlich mehr Code.



  • Tachyon schrieb:

    Werner_logoff schrieb:

    ...

    Das funktioniert aber nicht, wenn das Token z.B. ein Punkt enthält. Daher das "String-Gefrickel" über string::find.

    Rob c++ schrieb:

    Suchwort: Mueller
    Jedoch soll er nicht zählen wenn da steht Muellermilch!!!!

    und?

    Tachyon schrieb:

    Man kann zwar auch den Skip-Parser im Stream anpassen, aber das find ich nun doch arg komplizert für einen Anfänger. Außerdem ist das auch deutlich mehr Code.

    Das mit den Strings ist mehr Code - aber was ist daran positiv?



  • Werner_logoff schrieb:

    Tachyon schrieb:

    Werner_logoff schrieb:

    ...

    Das funktioniert aber nicht, wenn das Token z.B. ein Punkt enthält. Daher das "String-Gefrickel" über string::find.

    Rob c++ schrieb:

    Suchwort: Mueller
    Jedoch soll er nicht zählen wenn da steht Muellermilch!!!!

    und?

    Du würdest Das Mueller in "Und das war Frau Mueller." nicht mitzählen. Das soll aber mitgezählt werden.



  • Tachyon schrieb:

    Du würdest Das Mueller in "Und das war Frau Mueller." nicht mitzählen. Das soll aber mitgezählt werden.

    Ich meinte die 'Muellermilch'.

    Rob c++ schrieb:

    Suchwort: Mueller
    Jedoch soll er nicht zählen wenn da steht Muellermilch!!!!



  • Ist das dann nicht ein Feld von Line? Muss ich das nicht vorher definieren?

    Ferris schrieb:

    if(line[pos+key.size()+1]==' '||line[pos+key.size()+1]==','||line[pos+key.size()+1]='\n')

    Was meinst du mit prüfen ?

    Abgesehen davon vorher noch pruefen, ob du auf dieses Element ueberhaupt zugreifen kannst ( if (pos+key.size()+1 < line.size() ..... )

    Wie überprüfe ich den ob nach der Länge des Suchwortes ein Buchstabe ist? es könnte ja ein klein bzw ein Großbuchstabe sein!

    Ich persoenlich wuerde es aber anders machen. Ich wuerde einfach pruefen ob nach dem Schluesselwort ein Buchstabe folgt und wenn nein den Zaehler dann hochzaehlen.

    Danke



  • Achja ist die while(1) schleife eig unnötig?

    while(1)
    {
    pos=line.find(key,pos);
    

    könnte mann auch einfach sofort anfangen also:

    while (getline(muellermilch_datei, line))
    {
    pos=line.find(key,pos);
    
    if (pos== string::npos)
    {
    break;
    }
    ...
    

Anmelden zum Antworten