Anfängerfragen zu einem Projekt mit Klassen
-
Hast du denn inzwischen mal versucht die Datei Zeilenweise einzulesen und einzelne Wörte herauszufiltern? Genug Tipps hast du ja eigentlich bekommen

-
relax, relax, ja ich muss char benutzen...
nachdem ich ja gestern es geschafft hatte die Anzahl von r zu ermitteln und auf der Konsole auszugeben wollte ich heute alles ein wenig schicker gestalten.
Also ich probiere etwas rum, da muss man schon etwas flexibel mit mir sein.
Ist ja klar das man als Anfänger erstmal hin und her macht...void Ctext_analyse::datei_suchen(void) { int i; int z=0; for(i=0; i<lang; i++) { if('r'==text[i]) { z=z+1; } } cout << "Anzahl: "<<z<< endl; }Also aktuell will ich ein Wort suchen das auf der Konsole augegeben wird und mir die Anzahl angezeigt wird.
Ich wollte alles in einer Schleife packen, ist das o.k.? oder besser mehrere Schleifen, hm.....hab da ne Denkblockade grade
gruß
Venta
-
Hier mal n paar Denkansätze:
- überlege dir, wie du die Wörter brauchst
-> musst du beim Speichern beachten
- mit was willst du das eingelesene Vergleichen/oder Zählen
-> geeigneten Container finden, der die Anzahl pro Wort speichert
- sieh' dir nochmal alle geposteten Sachen an und überlege ob die Ratschläge dir helfen könnenDu darfst gerne Fragen stellen, aber bitte so, dass es jeder versteht und du am besten schon ein bisschen Code von deinen Ansätzen zeigst ...
... es ist nicht schlimm, wenn du dein Programm erweitern willst, aber du bist mit deimen Code immer noch so weit wie zu Anfang (wartest du etwa auf eine Musterlösung?) ...
-
void Ctext_analyse::datei_suchen(void) { FILE *fp; int i; char text[255]; char suchwort[2][20]={"wert","so"}; int AnzahlSuchwoerter=2; char* ptr; fp = fopen ("collection.txt","rt"); if (fp==NULL) { printf("Fehlen von diso_b_text.ini\r\n"); } else { i=0; while ( feof( fp ) != EOF ) { fgets(text,255, fp); for(int i =0;i<AnzahlSuchwoerter;i++) { ptr = strstr (text,suchwort[i]); if ( ptr != NULL ) { printf("%s ",suchwort[i]); //printf("%s\r\n",text); } } } } }
-
wie bekomme ich es jetzt Ordentlich ausgegeben, also die Anzahl von ... beträgt ...
-
Hallo ventilatores, ich hab mal zum Spass dir eine Klasse geschrieben die Dir die Wörter aus deiner Datei auflistet, zählt und sortiert, so wie du es im letzten Post gerne gehabt hättest. Viel Spass

Dauer 3Std 45min.
Datei wc.hpp
#ifndef WC_HPP_INCLUDED #define WC_HPP_INCLUDED #include <string> #include <fstream> #include <vector> #include <map> struct Wort { std::string Name; int Anzahl; }; class CWortCount { private: std::vector<Wort> m_Worte; // enthält die Worte : Anzahl für die Ausgabe std::ifstream* m_pfs; // zeiger auf file handle void ZaehleWorte(std::ifstream* fs); // zerlegt die Datei in Worte void WortZurMap(std::string& strWort, std::map<std::string, int>& mapWorte); // fügt neue Worte ein, erhöht den Zähler void KopiereMapZuVektor(std::vector<Wort>& vecWorte, std::map<std::string,int>& mapWorte);// kopiert die Worte in einen vektor für den // besseren Zugriff public: void SortCount(bool asc = true); // sortieren nach Anzahl void SortWord(bool asc = true); // lexikalisch sortieren bool OeffneDatei(std::string& Datei); // Oeffnet die Datei zu lesen Wort& operator[](const long idx); // liefert alle Wörter und deren Anzahl long WortAnzahl() { return m_Worte.size(); } // Anzahl der gefunden Woerter }; #endif // WC_HPP_INCLUDEDDatei: wc.cpp
#include "wc.hpp" #include <iostream> #include <map> using namespace std; bool CWortCount::OeffneDatei(string& Datei) { m_pfs = new ifstream(Datei.c_str()); if (!m_pfs->is_open()) { delete m_pfs; return false; } ZaehleWorte(m_pfs); // aufräumen brauchen wir nicht mehr // close wird automaisch aufgerufen delete m_pfs; return true; } void CWortCount::ZaehleWorte(ifstream* fs) { // Zerlegen des input streams in worte char c; string wort; map<string, int> mapWorte; // enthält die gefundenen (Worte:Anzahl) while (fs->get(c)) { switch (c) { case ',': case '.': case ' ': case '\n': case ';': // worttrenner gefunden if (wort.length() > 0) { WortZurMap(wort, mapWorte); wort.clear(); } break; default: wort.push_back(c); // addiere Zeichen zum Wort; break; } } if (!fs->eof()) cout << "DBGM: Filestream nicht leer !!" << endl; KopiereMapZuVektor(m_Worte, mapWorte); } void CWortCount::WortZurMap(string& strWort, map<string, int>& mapWorte) { pair<map<string,int>::iterator,bool> cmp; // versuche das wort einzufügen cmp = mapWorte.insert (pair<string,int>(strWort,1) ); // wort ist schon vorhanden erhöhe den Zähler; if (cmp.second == false) (*cmp.first).second++; } Wort& CWortCount::operator[](const long idx) { return m_Worte.at(idx); } void CWortCount::KopiereMapZuVektor(vector<Wort>& vecWorte, map<string,int>& mapWorte ) { map<string,int>::iterator it; for (it = mapWorte.begin(); it != mapWorte.end(); it++) { Wort w = { (*it).first, (*it).second }; vecWorte.push_back(w); // erzeugt eine Kopie und wird owner } } void CWortCount::SortCount(bool asc) { // ganz billige sortierung! for(size_t i = 0; i < m_Worte.size()-1; i++) { for(size_t j = i+1 ; j < m_Worte.size(); j++) if ((m_Worte.at(i).Anzahl > m_Worte.at(j).Anzahl) == asc) { Wort temp = m_Worte.at(j); m_Worte.at(j) = m_Worte.at(i); m_Worte.at(i) = temp; // kleinstes element speichern } } } void CWortCount::SortWord(bool asc) { // ganz billige sortierung! for(size_t i = 0; i < m_Worte.size()-1; i++) { for(size_t j = i+1 ; j < m_Worte.size(); j++) if ((m_Worte.at(i).Name > m_Worte.at(j).Name) == asc) { Wort temp = m_Worte.at(j); m_Worte.at(j) = m_Worte.at(i); m_Worte.at(i) = temp; // kleinstes element speichern } } }Datei: main.cpp
#include <iostream> #include "wc.hpp" using namespace std; int main() { string datei = "meine.dat"; CWortCount wc; // Ich hatte keine Lust den operator! zu überladen um zu prüfen // ob der Vorgang erfolgreich war, daher ist die Initialsierung // im Konstruktor noch nicht möglich if (!wc.OeffneDatei(datei)) cout << "Kann die Datei nicht oeffnen : " << datei << endl; wc.SortWord(); cout << "Alle gefunden Wörter in: " << datei << endl; for(int i = 0; i < wc.WortAnzahl(); i++) cout << "Anzahl von : " << wc[i].Name << " beträgt : " << wc[i].Anzahl << endl; return 0; }Eine mögliche Ausgabe könnte so aussehen:
Alle gefunden Wörter in: meine.dat Anzahl von : Aenean beträgt : 5 Anzahl von : Aliquam beträgt : 3 Anzahl von : Curabitur beträgt : 5 Anzahl von : Curae beträgt : 2 Anzahl von : Donec beträgt : 5 Anzahl von : Duis beträgt : 3 Anzahl von : Etiam beträgt : 3 Anzahl von : Fusce beträgt : 6 Anzahl von : In beträgt : 1 Anzahl von : Integer beträgt : 5 Anzahl von : Lorem beträgt : 1 Anzahl von : Maecenas beträgt : 4 Anzahl von : Mauris beträgt : 1 Anzahl von : Morbi beträgt : 2 Anzahl von : Nulla beträgt : 4 Anzahl von : Nullam beträgt : 2 Anzahl von : Nunc beträgt : 3 Anzahl von : Pellentesque beträgt : 3 Anzahl von : Phasellus beträgt : 3 Anzahl von : Praesent beträgt : 1 Anzahl von : Proin beträgt : 2 Anzahl von : Quisque beträgt : 4 Anzahl von : Sed beträgt : 5 Anzahl von : Suspendisse beträgt : 5 Anzahl von : Ut beträgt : 3 Anzahl von : Vestibulum beträgt : 3 Anzahl von : Vivamus beträgt : 3Grüssle DC!
-
Und jetzt mal bissl eleganter:
string filetxt = ""; ifstream fileIn("..."); copy(istreambuf_iterator<char>(fileIn), istreambuf_iterator<char>(), back_inserter(filetxt)); // 1. Methode: Bustaben zählen: map<char, size_t> charCount; for (size_t i = 0; i < filetxt.size(); ++i) ++charCount[filetxt[i]]; cout << "Anzahl r's :" << charCount['r'] << "\nAnzahl a's :" << charCount['a'] << endl; // 2. Methode: Wörter zählen: boost::tokenizer<> toki(filetxt); map<string, size_t> wordCount; for (boost::tokenizer<>::iterator it=toki.begin(); it!=toki.end(); ++it) ++wordCount[*it]; cout << "Anzahl bla's :" << wordCount["bla"] << "\nAnzahl blub's :" << wordCount["blub"] << endl;Dauer: 2min 45s

-
@KasF Deinen Tipp finde ich gut, aber was daran eleganter sein sollte, weiß ich noch nicht, der Klassenansatz gefällt mir persönlich besser (von boost war ja noch nicht die Rede :)), da man das Konstrukt ('we can load anything, weapons, equipment and training simulations'
) erweitern kann.Allerdings hast du recht das der Tokenizer die gleiche Arbeit wie meine Funktion ZaehleWorte() eleganter erledigt, nur kann ich dort eben nicht mehr in den Code eingreifen und komplexe Bedingungen für die Wortgrenze zu definieren.
Auch istreambuf_iterator war mir in den Sinn gekommen, habe ihn aber wieder verworfen da ich nur den Teil im Speicher haben wollte den ich tatsächlich auch benötige und den Rest einfach verwerfe.
Ansonsten hätte ich auch so gemacht

So long and thank's for all the fish! (HG)
Grüssle DC!
-
@DeepCopy hey hey, thanx für die wirklich tolle Arbeit von dir, jetzt habe ich wenigstens mal ein Beispiel und kann alles genau analysieren und mein Lehrer freut sich auch, der hatte mich schon auf dem Kicker.
@KasF puh, das ist mir noch zu hoch
Trotzdem, tausend Dank an euch beiden!

Venti

-
Könnten wir die Ausgabe jetzt noch ein wenig, mit DeepCopy's Code, etwas edler machen?
z.Bsp.:
--------------------------------------------------------------------------------
Welches Wort suchen Sie?...eingabe Wort.....Die Anzahl Ihres gesuchten Wortes beträgt: .......Anzahl Wort....
--------------------------------------------------------------------------------
-
DeepCopy schrieb:
@KasF Deinen Tipp finde ich gut, aber was daran eleganter sein sollte, weiß ich noch nicht, der Klassenansatz gefällt mir persönlich besser
Das waren auch nur Codeschnipsel
das kann man immernoch schön verpacken.DeepCopy schrieb:
Allerdings hast du recht das der Tokenizer die gleiche Arbeit wie meine Funktion ZaehleWorte() eleganter erledigt, nur kann ich dort eben nicht mehr in den Code eingreifen und komplexe Bedingungen für die Wortgrenze zu definieren.
Meinst du die Wortgrenzen bei boost::Tokenizer ? Das Trennzeichen kann man dort auch definieren.
DeepCopy schrieb:
Auch istreambuf_iterator war mir in den Sinn gekommen, habe ihn aber wieder verworfen da ich nur den Teil im Speicher haben wollte den ich tatsächlich auch benötige und den Rest einfach verwerfe.
Benötigte ? Rest ? im Speicher ? Wo, wie was ?

Noch ein paar kleine Verbesserungsvorschläge zu deinem Code:
1.) Wieso ist der Stream aufm Heap und nicht aufm Stack ?
2.) Wieso reichst du deinen Member m_pfs in der Klasse rum ? Falls das Absicht ist, damit ZaehleWorte() auch mit anderen Quellen benutzt werden kann, stimmt hier was mit der Kohärenz nicht ?
3.) Dein ZaehleWorte() ist nicht unbedingt performant mit den ganzen Stream-Zugriffen.
4.) WortZurMap kann ein Einzeiler sein, siehe mein Code und die Referenz deiner Wahl.
5.) Für die Container-Kopieroperationen gibts es schöne Konstruktoren und std::copy.Und für *Nicht-Boost-Haben-Woller*
:class SimpleTokenizer { private: vector<string> toki; public: typedef vector<string>::const_iterator TokiIt; SimpleTokenizer(const string& str) { string blub = ""; stringstream sstr(str); while(sstr>>blub) toki.push_back(blub); } vector<string>::const_iterator begin() const { return toki.begin(); } vector<string>::const_iterator end() const { return toki.end(); } }; // 2. Methode: Wörter zählen: SimpleTokenizer toki(filetxt); map<string, size_t> wordCount; for (SimpleTokenizer::TokiIt it=toki.begin(); it!=toki.end(); ++it) ++wordCount[*it]; cout << "Anzahl bla's :" << wordCount["bla"] << "\nAnzahl blub's :" << wordCount["blub"] << endl;
-
ventilatores schrieb:
Könnten wir die Ausgabe jetzt noch ein wenig, mit DeepCopy's Code, etwas edler machen?
z.Bsp.:
--------------------------------------------------------------------------------
Welches Wort suchen Sie?...eingabe Wort.....Die Anzahl Ihres gesuchten Wortes beträgt: .......Anzahl Wort....
--------------------------------------------------------------------------------
Wenn du das nicht alleine schaffst, dann brauchst du auch gar nicht DC's Code zu benutzen.

-
***BlaBliBlub schrieb:
Wenn du das nicht alleine schaffst, dann brauchst du auch gar nicht DC's Code zu benutzen.
Äh wat?, ich benutz den schon und der läuft 1 A!
Ich habe doch mit meinen Projekt ganz anders Angefangen als DeepCopy und für mich
als super Anfänger ist das echt nicht leicht, dieses wie-was-wozu u.s.w.ein kleiner tipp und ne Erklärung wärn da super, nennt man neues modernes Lernen

gruß
Venti
-
So!, jetzt hast du dich bei 95% der registrierten User hier disqualifiziert
[Grund: mangelnde Eigeninitiative]
In deinem ersten Beitrag schien es noch danach auszusehen, dass du C++ lernen willst. Mit diesem Beitrag hier aber nicht mehr:ventilatores schrieb:
Könnten wir die Ausgabe jetzt noch ein wenig, mit DeepCopy's Code, etwas edler machen?
z.Bsp.:
--------------------------------------------------------------------------------
Welches Wort suchen Sie?...eingabe Wort.....Die Anzahl Ihres gesuchten Wortes beträgt: .......Anzahl Wort....
--------------------------------------------------------------------------------
[Newbie] Das ist cin und cout und bissl if und so, das steht in Kapitel 1 vieler Bücher [/Newbie]
Jetzt mal ernst, das sind wirklich Grund-Grundlagen. Ließ dir ein paar Tutorial dazu durch und versuchs selber. Copy&Paste bringt dir 5% Lerneffekt.
-
ja, is ja jut

muss das halt bis Freitag fertig haben und hab ja schon in der Zwischenzeit selber dran rum gebastelt also, passt schon

venti
p.s. 95% an Kumpels verloren die mir nich mehr helfen wollen, puhhh...fett
naja hoffe Deep Copy gehört zu den restlichen 5% die mir nochmal helfen
-
@ ventilatores:
KasF hat völlig Recht, mangelnde Eigeninitiative ist hier wirklich nicht gern gesehen. Es ist auch eine ziemliche Ausnahme, dass sich überhaupt jemand so viel Zeit wie DeepCopy nimmt. Von daher solltest du eher dankbar sein statt weitere Forderungen zu stellen.Wenn du dich etwas mit der Materie auseinandersetzt und versuchst, DeepCopys Code zu verstehen, solltest du auch relativ schnell in der Lage sein, das Programm selbstständig zu erweitern. Aber dazu ist halt C++-Theorie unumgänglich - du kannst schliesslich nicht für jedes kleine Problem im Forum nachfragen.
Nichts für ungut, aber ich hoffe, dir ist das nun etwas verständlicher geworden.

-
KasF schrieb:
1.) Wieso ist der Stream aufm Heap und nicht aufm Stack ?
2.) Wieso reichst du deinen Member m_pfs in der Klasse rum ? Falls das Absicht ist, damit ZaehleWorte() auch mit anderen Quellen benutzt werden kann, stimmt hier was mit der Kohärenz nicht ?
3.) Dein ZaehleWorte() ist nicht unbedingt performant mit den ganzen Stream-Zugriffen.
4.) WortZurMap kann ein Einzeiler sein, siehe mein Code und die Referenz deiner Wahl.
5.) Für die Container-Kopieroperationen gibts es schöne Konstruktoren und std::copy.zu 1)
Ich möchte das Objekt erst initialisieren/instanzieren wenn der Benutzer das Objekt tatsächlich braucht.zu 2)
Das hängt mit der von mir gewählten Richtline für Funktionssignaturen zusammen, ich erarbeite mir gerade eine neue Strategie für die Übergabe vom Elementdaten um Seiteneffekte zu minimieren.zu 3)
Kann ich nicht nachvollziehen, ich möchte nur den Speicher verbrauchen den ich auch benötige, dann bleibt mir nur die Möglichkeit immer das nächste Token aus dem Stream zu holen.zu 4)
Habe ich gesehen, über den operator[] das hat Vorteile und Nachteile. Vorteil die Map legt das Objekt in die Map wenn der Schlüssel nicht vorhanden ist und erhöht den integer, oder einfach nur den integer, dieses Konzept versagt aber bei komplexen Datentypen da es zwar eine Default-Initialisierung gibt aber ich komme so nicht an die "inneren Objekte", und der Code sollte als Anschauungsmaterial dienen wie man auch bei komplexen Datentypen arbeitet.zu 5)
Daran werde ich diese Woche noch arbeiten um das zu verbessern... danke für den Tip

@ventilatores
Vielen dank für Blumen, vielen Dank, wie lieb von Dir!
ventilatores schrieb:
Ich habe doch mit meinen Projekt ganz anders Angefangen als DeepCopy und für mich
als super Anfänger ist das echt nicht leicht, dieses wie-was-wozu u.s.w.
...
p.s. 95% an Kumpels verloren die mir nich mehr helfen wollen, puhhh...fett
naja hoffe Deep Copy gehört zu den restlichen 5% die mir nochmal helfen
Soweit es meine Zeit zulässt werde ich dir gerne Helfen, wenn du fragen zum Code hast stell sie einfach ich habe mir leider nicht die Mühe gemacht den Code zu Dokumentieren.

Für dein restliches Problem solltest du eigentlich nur absolute Grundlagen benötigen, so wie ventilatores und Nexus es gesagt haben, wirklich. Ist nicht mehr als ein paar If's und ein bisschen cin und cout. Versuche den Code von mir oder KasF zu verstehen, dann solltest du dein Prob. mit links hinkriegen. Und wenn du nich weiter kommst, dein Stück fehlerhaften Code posten und hoffen das einer hilft.

Grüssle DC!
-
hi,
warum wird nach dem zugelassenen Zugang die Schleife nicht weiter geführt und die Datei nicht durchsucht?
Habe jetzt einiges probiert und komme nicht weiter.greetz
Venti#include <iostream> #include "wc.hpp" using namespace std; int pnummer, code; int personalnummer = 1999; int geheimcode = 1212; int main() { string datei = "collection.txt"; CWortCount wc; cout << "Geben Sie Ihre Personalnummer ein: "; cin >> pnummer; cout << "\nGeben Sie Ihren Zugangscode ein: "; cin >> code; if (!wc.OeffneDatei(datei), (pnummer == personalnummer) && (code == geheimcode)) { cout << "\nZutritt gewaehrt!\n"; return 0; } if ((pnummer == personalnummer) && !(code == geheimcode)) { cout << "\nFalscher Zugangscode!\n"; return 0; } if (!(pnummer == personalnummer) && (code == geheimcode)) { cout << "\nFalsche Personalnummer!\n"; return 0; } if (!(pnummer == personalnummer) && !(code == geheimcode)) { cout << "\nFalsche Zugangsdaten!\n"; return 0; } cout << "Kann die Datei nicht oeffnen : " << datei << endl; cout << "Bitte Warten, analysiere die Datei " << endl; wc.SortWord(); cout << "Alle gefunden Wörter in: " << datei << endl; for(int i = 0; i < wc.WortAnzahl(); i++) cout << "Anzahl von " << wc[i].Name << " betraegt : " << wc[i].Anzahl << endl; return 0; }
-
if (!wc.OeffneDatei(datei), (pnummer == personalnummer) && (code == geheimcode)) // <- hier darf kein , stehen { cout << "\nZutritt gewaehrt!\n"; return 0; <- damit wird dein Programm beendet! Das ist falsch }Diese Anweisung macht nicht viel Sinn, du must das Öffnen separat ausführen und überprüfen!
Besser:
if (!wc.OeffneDatei(datei)) { cout << "Kann die Datei nicht oeffnen : " << datei << endl; return 0; } // ab hier alle if (...) aber ohne !wc.OeffneDatei(datei) if (!(pnummer == personalnummer) && (code == geheimcode)) { cout << "\nFalscher Zugangscode!\n"; return 0; // <-- Beenden ok, die personalnummer war falsch } // ... usw. // diese zeile ganz nach oben... // cout << "Kann die Datei nicht oeffnen : " << datei << endl; cout << "Bitte Warten, analysiere die Datei " << endl; // ab hier weiter wie bisher.. wc.SortWord(); cout << "Alle gefunden Wörter in: " << datei << endl; // ... usw.
-
ahhh, alles klar thanx DC gut erklärt.
ups... palim palim, da is'n ERROR!
--->jetzt geht die PW Abfrage nicht mehr,
also man kommt auch mit falsche Zugangsdaten rein.um gottes Willen!

gruß
Venti