[c++] Prob bei Übung mit string

Icon_Master

Lt. Commander
Dabei seit
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
 

Arnd

Lieutenant
Dabei seit
Jan. 2005
Beiträge
926
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
 

Raechaer

Lt. Junior Grade
Dabei seit
Aug. 2004
Beiträge
278
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;
}
 

daemon777

Lt. Commander
Dabei seit
Dez. 2003
Beiträge
1.371
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 ?
 

Raechaer

Lt. Junior Grade
Dabei seit
Aug. 2004
Beiträge
278
Zitat von daemon777:
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).

Zitat von daemon777:
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
 

Arnd

Lieutenant
Dabei seit
Jan. 2005
Beiträge
926
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:

daemon777

Lt. Commander
Dabei seit
Dez. 2003
Beiträge
1.371
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.
 

Arnd

Lieutenant
Dabei seit
Jan. 2005
Beiträge
926
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:

daemon777

Lt. Commander
Dabei seit
Dez. 2003
Beiträge
1.371
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 )
 

Arnd

Lieutenant
Dabei seit
Jan. 2005
Beiträge
926
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:

Raechaer

Lt. Junior Grade
Dabei seit
Aug. 2004
Beiträge
278
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());
}
 

daemon777

Lt. Commander
Dabei seit
Dez. 2003
Beiträge
1.371
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:

Arnd

Lieutenant
Dabei seit
Jan. 2005
Beiträge
926
Poste doch mal den Code dazu. So kann man relativ wenig dazu sagen.
Ausser Du hast z.B. das #include vergessen.

MfG

Arnd
 

daemon777

Lt. Commander
Dabei seit
Dez. 2003
Beiträge
1.371
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.
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
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;
}
 

Arnd

Lieutenant
Dabei seit
Jan. 2005
Beiträge
926
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:

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
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:

Arnd

Lieutenant
Dabei seit
Jan. 2005
Beiträge
926
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
 

Raechaer

Lt. Junior Grade
Dabei seit
Aug. 2004
Beiträge
278
Zitat von 7H3 N4C3R:
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.

Zitat von 7H3 N4C3R:
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?
 
Top