[c++] Prob bei Übung mit string

Icon_Master

Lt. Commander
Registriert
März 2003
Beiträge
1.228
hey,

bin seit kurzen angefangen mein wissen über c++ nen bissl aufzubessern und da bin ich vor ner woche auf strings "gestoßen" und da ich mir immer ne kleine übungsaufgabe zu den einzelnen themen mache. hab ich mir überlegt, dass ich doch nen kleines prog schreiben könnt, was die anzahl der wörter in nem string ausgibt. aber irgendwie hab ich da noch nen kleinen denkfehler drin ... :( vllt. könntet ihr mir ja eben auf die sprünge helfen...
schon mal danke im vorraus

Code:
int iWoerter(string satz)
{
    int a(0),
        c(0);
        
    do
    {
        a = satz.find(' ');
        if(satz.find(' ')==-1) break;
        else
        {
             if(satz.find(' ') != a+1)
             {
             c++;
             }
             satz.erase(0,a+1);
            
        }
    }while(satz.empty()==false);
    
    
    return c;
}

cyA ICon
 
Hallo,

Das hier if(satz.find(' ') != a+1)
findet im Endeffekt ja immer das selbe Space wie vorher bereits gesucht wurde.
Daher wird das ganze wohl ins leere laufen und c immer 0 liefern?

Ich würde im in dem else Zweig einfach solange den String um das nächste Space kürzen, solange dieses um a+1 weiter liegt. Wenn die Entfernung > 1 ist, kommt ein neues Wort, oder der Satz ist zu Ende.

Also nicht hinterher löschen sondern vorher.

MfG

Arnd
 
Den String beim Bestimmen der Anzahl der Wörter zu verändern halte ich für keine gute Idee, denn das verschlechtert die Performance doch erheblich. Als kleine Anregung wie man das besser machen könnte: Schau dir doch mal den zweiten Parameter von find an.

Ganz einfach könnte man das übrigens auch so machen:

PHP:
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
	string test = "Das ist ein Test";
	cout << "Anzahl der Woerter in \"" << test << "\": " <<  count(test.begin(),test.end(),' ')+1 << endl;
}
 
Das bringt mich gerade auf die Idee dass man mal einlesen könnte wie viele Buchstaben einer art in einem Satz vokommen. Das könnte man ja auch damit mache. Allerdingswähre dass über diese Möglihckeit recht Umständlich. Man müsste schließlich 26 Zeilen schreiben um alle Buchstaben zu suchen. Kann man das irgendwie über eine Schleife machen ? Diese Tabelle dürfte einem doch da helfen oder ? ANSCII oder wie die heißt.

Und wie war noch mal die Syntax von getline() ? Ich habe dein Programm mal übernommen und wollte mit cin etwas einlesen allerdings funktioniert das logischerweise nicht. Kann mir jemand veraten wie die Syntax von getline() war ?
 
daemon777 schrieb:
Das bringt mich gerade auf die Idee dass man mal einlesen könnte wie viele Buchstaben einer art in einem Satz vokommen. Das könnte man ja auch damit mache. Allerdingswähre dass über diese Möglihckeit recht Umständlich. Man müsste schließlich 26 Zeilen schreiben um alle Buchstaben zu suchen. Kann man das irgendwie über eine Schleife machen ? Diese Tabelle dürfte einem doch da helfen oder ? ANSCII oder wie die heißt.
Klar kannst du das mit einer Schleife machen, z.B. so:
PHP:
for (char i='a'; i <= 'z'; ++i)
		cout << i << ": " << count(test.begin(),test.end(),i) << endl;
Allerdings ist das natürlich schrecklich ineffizient da du ja 26 mal über den ganzen string iterierst. Besser wäre in diesem Fall wohl for_each anstatt count (damit brauchst du dann nur einen Durchlauf).

daemon777 schrieb:
Und wie war noch mal die Syntax von getline() ? Ich habe dein Programm mal übernommen und wollte mit cin etwas einlesen allerdings funktioniert das logischerweise nicht. Kann mir jemand veraten wie die Syntax von getline() war ?
http://msdn.microsoft.com/library/d.../vcstdlib/html/vclrf_string_getline_class.asp
 
Hallo,

also die Variante mit count ist schön kurz und knapp. Nur gelernt ist dabei nicht viel.

Den String dynamisch zu verkürzen ist sicher nicht effizient. Besser ist es den String nicht zu verändern. Nur bedingt das dann eben mehr Logik im Code.

Das wäre dann die nächste Version des Wortzählers :-).

Den Buchstabenzähler würde ich mit einem 26 Einträge grossen Array realisieren.
Ein Durchgang durch den Satz und bei jedem Buchstaben den entsprechenden Arraywert um eins erhöhen.
Es gibt aber noch Gross und Kleinschreibung, sowie Sonderzeichen von daher sollte das Array wohl eher 255 Einträge haben.

MfG

Arnd
 
Zuletzt bearbeitet:
Ich will ja nur wissen wie viele 'e' s zB in einem Text sind. Also brauche ich nur 26.

Dass das mit chars geht einfach hoch zu zählen wusste ich nicht :D

Danke euch allen.
 
Und was ist mit dem grossen 'E'? Wenn Dir Gross Kleinschreibung egal ist, solltest vorher in Upper oder Lowercase konvertieren.

Zur Verdeutlichung:

long gAsciiArray[ 255 ];

void charCount( char* apText )
{
long lCount = 0;

if( apText )
{

memset( gAsciiArray, 0, sizeof gAsciiArray );
while( apText[lCount] )
{
gAsciiArray[ (unsigned char) apText[ lCount ] ]++;
lCount++;
}

}

}

MfG

Arnd
 
Zuletzt bearbeitet:
Was ist denn Mset ? Mit diesem ganzen ASCII Zeugs kenne ich mich leider überhaupt nicht aus. Wie würde denn ein komplettes Programm aussehen bei dem man erst einen satz oder ganzen Text einliest und dann die Buchstaben zählt ? ( Das Thema beginnt interressant zu werden :D )
 
Hallo daemon777,

memset = setze memory auf den übergebenen Wert
D.h initialisiert in diesem Fall das Array mit dem Wert 0. Ist hier notwendig damit das ++ (hochzählen um 1) auch korrekt bei 0 anfängt.

Code:
// charcount.cpp : Definiert den Einsprungpunkt für die Konsolenanwendung.
//

#include <stdio.h>
#include <string.h>

long gAsciiArray[ 255 ];

// Buchstaben zählen in einem String
void charCount( char* apText )
{
	long lCount = 0;

	while( apText && apText[lCount] )
	{	
		gAsciiArray[ (unsigned char) apText[ lCount ] ]++;
		lCount++;
	}
}

int main(int argc, char* argv[])
{
	// Wenn Parameter übergeben
	if( argc > 1 )
	{
		// Datei öffnen
		FILE* fpFile = fopen( argv[1], "r" );

		// Wenn Datei geöffnet werden konnte
		if( fpFile )
		{
			// lokale Variablen
			char lData[ 256 ];
			long lCount = 0;

			// Ascii Array initialisieren
			memset( gAsciiArray, 0, sizeof gAsciiArray );

			// Datei auslesen
			while(!feof( fpFile ) )
			{
				// Zeile auf 0 initialisieren
				memset( lData, 0, sizeof lData );
				// Zeile aus Datei lesen
				fgets( lData, sizeof lData - 1, fpFile );

				// Wenn kein Fehler aufgetreten
				if( !feof( fpFile ) )
				{
					// Buchstaben zählen
					charCount( lData );
				}
			}
			// Datei schliessen
			fclose( fpFile );

			// Ausgabe der gefundenen Buchstaben
			lCount = 0;
			while( lCount < sizeof gAsciiArray / sizeof( long) )
			{
				// Wenn Buchstabe gefunden wurde
				if( gAsciiArray[ lCount ] > 0 )
				{
					// Diesen ausgeben mit Asciicode, Klartext und Anzahl 
					printf( "%d %c: %d\n", (unsigned char) lCount, (char) lCount, gAsciiArray[ lCount ] );
				}
				lCount++;
			}
		}

	} else
	{
		printf( "missing parameter: charcount <filename>" );
	}

	return 0;
}

Das ganze ist jetzt natürlich mehr ein C Programm. Das eine globale Variable verwendet wird ist auch nicht so schön. Hat dafür aber auch nicht so lange gedauert :-).

Mit Templates könnte man das ganze sicher noch kürzer formulieren. Aber etwas wesentlich anderes machen die Templates auch nicht.

MfG

Arnd
 
Zuletzt bearbeitet:
Und das Ganze auch noch als C++:

PHP:
#include <string>
#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

class CountChars
{
private:
	map<char, unsigned int> m;
	
public:
	void operator() (char zeichen)
	{
		m[zeichen]++;
	}

	operator map<char, unsigned int> ()
	{
		return m;
	}
};

ostream& operator<< (ostream& stream, const map<char, unsigned int>& v)
{
	for (map<char, unsigned int>::const_iterator iter = v.begin(); iter != v.end(); ++iter)
		cout << iter->first <<": " << iter->second << endl;

	return stream;
}

           
int main(int argc, char* argv[])
{
	string text;
	cout << "Bitte Satz eingeben:" << endl;
	getline(cin,text);
	
	cout << for_each(text.begin(), text.end(), CountChars());
}
 
Irgendwie habe ich gerade ein Problem mit strings. Es scheint so als könnte ich die strings bei Methoden nicht übergeben. Kann man strings nicht als Parameter benutzen ?

EDIT: So wies aussieht kann ich gar keine Variabeln als String deklarieren. Woher kommt das ?
 
Zuletzt bearbeitet:
Poste doch mal den Code dazu. So kann man relativ wenig dazu sagen.
Ausser Du hast z.B. das #include vergessen.

MfG

Arnd
 
ich hab jetzt einfach nochmal ein neues kleines Programm gemacht wo (aus meiner Sicht) wirklich nichts ist was irgendwie Fehler erzeugen könnte aber dennoch funktioniert es nicht.

Code:
#include <iostream.h>
#include <string.h>
#include <windows.h>

using namespace std;

int main()
{
	string moin;
	cout<<"Hallo !"<<endl;
	cin>>moin;
	cout<<moin<<" ?"<<endl;
	Sleep(2000);
	return 1;
}

Den alten Code habe ich leider nicht mehr aber hier dürfte mein Problem deutlich werden.

Übrigens wird auch namespace nicht mehr richtig erkannt sobald ich die string bib einbinden will.
 
Code:
#include <iostream>
#include <string>
#include <windows.h>

using namespace std;

int main()
{
	string moin;
	cout<<"Hallo !"<<endl;
	cin>>moin;
	cout<<moin<<" ?"<<endl;
	Sleep(2000);
	return 0;
}
 
Hallo,

also das cin hat bei mir nicht funktioniert. Daher:

Code:
#include <iostream>
#include <string>
#include <windows.h>

using namespace std;

int main()
{
	string moin;
	cout<<"Hallo !"<<endl;
	getline(cin,moin, ' ');
	cout<<moin<<" ?"<<endl;
	Sleep(2000);
	return 1;
}

Noch als Anmerkung. Exakt das Programm hättest Du auch in der Online Hilfe vom Visual C++ gefunden. Wenn man mal von dem Sleep absieht.

MfG

Arnd
 
Zuletzt bearbeitet:
An der Stelle sei dann aber vielleicht mal der getline Bug vom VS C++ 6.0 erwähnt, bei dem getline u.U. zuviele Zeichen einliest. cin arbeitet übrigens prima mit dem std::string zusammen. Solche Schreibweisen wie cin >> string waren u.A. ein Designziel der STL (weg von hässlichen char*-Arrays)

@Code von Raechaer: Warum eine Map? Ein Vektor wär wesentlich effizientier. Und für den Cast-Operator gehört Dir auch was auf die Finger gehauen *gg*
 
Zuletzt bearbeitet:
Hallo,

also bei meinem VC++ 6.0 ist auch im Header für string kein operator >> definiert.
Gewundert hat es mich mich aber auch das es nicht geht.
In VS2003 habe ich es nicht probiert.

MfG

Arnd
 
7H3 N4C3R schrieb:
Warum eine Map? Ein Vektor wär wesentlich effizientier.
Weil ich mit einem Schlüssel (dem jeweiligem Buchstaben) auf einen Wert zugreifen will. Und das mache ich im Normalfall eher mit einer Map als mit einem Vektor. Und je nach Implementierung der Map is ein Vektor nicht umbedingt effizienter was die Laufzeit betrifft.
Und da das ganze ja eine Übung ist ging's mir mehr um schönen Code bei dem man vielleicht auch etwas lernen kann (map kennt/benutzt fast niemand) als um maximale Performance.

7H3 N4C3R schrieb:
Und für den Cast-Operator gehört Dir auch was auf die Finger gehauen *gg*
Begründung? Wie hättest du es denn gemacht?
 

Ähnliche Themen

Zurück
Oben