Der beste Weg zum Spieleprogrammieren
-
Ok, nun hab ich zwei Programme zusammengebastelt:
Einmal das:
#include <iostream> #include <map> #include <limits> #include <fstream> #include <string> using namespace std; int main() { string sText; string::iterator itText; map<char, string> mText; ifstream MeineDatei ("TestDokument.txt"); if (MeineDatei.is_open()) { getline (MeineDatei, sText); int DatenGroesse = sText.size(); for (int i = 0; i != DatenGroesse; i++) { mText[i] = sText; } MeineDatei.close(); } else cout << "Fehler"; for (itText = sText.begin(); itText < sText.end(); itText++) { cout << *itText; } cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); return 0; }
und einmal das:
#include <iostream> #include <map> #include <limits> #include <fstream> #include <string> using namespace std; int main() { string sText; map<char, string> mText; ifstream MeineDatei ("TestDokument.txt"); if (MeineDatei.is_open()) { getline (MeineDatei, sText); int DatenGroesse = sText.size(); for (int i = 0; i != DatenGroesse; i++) { mText[i] = sText[i]; cout << mText[i]; } MeineDatei.close(); } else cout << "Fehler"; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); return 0; }
Beide haben den Fehler das sie nur die erste Zeile des Dokuments wiedergeben.
Wo ist da der Fehler und hab ich dieses Mal die Aufgabe erfüllt(abgesehen von dem Fehler)?
Weiterhin danke für eure Hilfe.
-Skotchy
-
Jain. Immerhin liest du jetzt aus einer Datei, so wie es vorgesehen war. Aber du hast die std::map leider noch gar nicht verstanden. Zudem würde sich bei dieser Aufgabe der operator >> zum Auslesen aus der Datei anbieten. Und es war gefordert, den "Auslesen" Teil in eine Funktion zu packen.
Aber wie gesagt, das Hauptproblem besteht einfach darin, dass du die std::map nicht verstanden hast, die solltest du dir noch mal angucken.
Du hast dich wohl etwas zu nah an diesem Beispiel gehalten, scheinbar ohne wirklich verstanden zu haben, wie die map funktioniert. Ein Tipp: Sowohl Schlüssel als auch Wert sollten hier vom Typ std::string sein!Und kleine Schönheitsfehler:
globales using namespace std;, pack das lieber in die Funktion rein oder schreibe gleich std::.
Und "Fehler" ist keine aussagekräftige Fehlermeldung.Edit:
Und nenne deine Variablen ruhig einfach text oder so, ein "Typen-Prefix", auch als Ungarische Notation bekannt, ist nicht gern gesehen.Edit2:
Und warum schließt du deine Datei innerhalb der Schleife?Warum liest du nur ein mal etwas aus?
-
Wenn dort mal eine Schleife wäre
-
Th69 schrieb:
Wenn dort mal eine Schleife wäre
LOL, irgendwie hat mein Auge da eine Schleife hingebaut.
-
cooky451 schrieb:
Th69 schrieb:
Wenn dort mal eine Schleife wäre
LOL, irgendwie hat mein Auge da eine Schleife hingebaut.
Macht man das jetzt so? Augmented Programming oder was?
-
So nun müsste es doch richtig sein:
#include <iostream> #include <map> #include <limits> #include <fstream> #include <string> void Auslesen() { using namespace std; string Text; ifstream MeineDatei; MeineDatei.open ("TestDokument.txt"); map <string, string> text; while (MeineDatei.good()) { text["meintext"] = MeineDatei.get(); cout << text["meintext"]; } MeineDatei.close(); } int main() { using namespace std; ifstream MeineDatei; MeineDatei.open ("TestDokument.txt"); if (MeineDatei.is_open()) Auslesen(); else cout << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; MeineDatei.close(); cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); }
Ich habe die Fehlermeldung aussagekräftiger gemacht,
eine Void-Funktion benutzt (zuerst dachte ich das ich alles in der main-Funktion ausgeben sollte),
den Fehler behoben bei dem ich nur die erste Zeile zu lesen bekam
und (so denke ich) habe map verstanden (ich lasse mich auch gern eines besseren belehren).Ich freue mich auch über eine Korrektur der 'Schönheitsfehler' oder auch anderen Fehlern, von denen es bestimmt genug gibt.
Weiterhin danke für eure Hilfe.
-Skotchy
-
Skotchy schrieb:
und (so denke ich) habe map verstanden (ich lasse mich auch gern eines besseren belehren).
Dann werde ich das mal machen.
Bedenke noch einmal:map<string, string> m; m[SCHLUESSEL] = WERT.
Wie sieht jetzt noch gleich die Datei aus?
Die Datei schrieb:
Schlüssel Wert Schlüssel Wert ...
So wie du es jetzt machst, änderst du immer nur den Wert des Schlüssels "meintext".
Dann noch kleine Anmerkungen:
ifstream hat einen Konstruktor, da brauchst du dann kein open mehr:ifstream datei("text.txt");
Das close am Ende kannst du hier auch sparen, das macht der Destruktor. (RAII ist schon was Tolles. :p)
Zudem sollte die Funktion (hätte ich vielleicht deutlicher machen sollen) nur auslesen, aber nichts ausgeben. Das soll dann wieder in der main() geschehen.
-
Und die nächste Version des Programms ist raus:
#include <iostream> #include <map> #include <limits> #include <fstream> #include <string> void Auslesen() { using namespace std; int i = 0; ifstream MeineDatei ("TestDokument.txt", ios::in); map <int, string> text; while(getline (MeineDatei, text[i])) i++; for (int j = 0; j != text.size() - 1; j++) cout << "Text " << j << " ist " << text[j] << endl; } int main() { using namespace std; ifstream MeineDatei ("TestDokument.txt"); if (MeineDatei.is_open()) { Auslesen(); } else cout << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); }
Allerdings habe ich immer noch ein Problem:
ich bekomme die maps nicht aus der Funktion und kann sie deswegen nich in der mein() Funktion ausgeben.
Allerdings habe ich map jetzt verstanden (oder?!).Weiterhin danke für eure Hilfe.
-Skotchy
-
Skotchy schrieb:
Allerdings habe ich immer noch ein Problem:
ich bekomme die maps nicht aus der Funktion und kann sie deswegen nich in der mein() Funktion ausgeben.Dann lies noch mal etwas über Rückgabewerte oder Referenzen oder Pointer. (Ein Pointer ist hier allerdings eher C-Stil und nicht zu bevorzugen, aber es funktioniert.)
Skotchy schrieb:
Allerdings habe ich map jetzt verstanden (oder?!).
Ich fürchte nicht. Um das noch mal klar zu machen, der Dateiaufbau:
Schlüssel Wert Schlüssel Wert ..
Beides sind Strings, du brauchst also eine std::map<std::string, std::string>!
Und getline() ist hier, wie ich bereits erwähnt hatte, nicht gerade das Optimum. Denn getline() liest, wie der Name schon vermuten lässt, eine ganze Zeile auf einmal aus. Dann musst du allerdings noch den Schlüssel von dem Wert trennen, das ist unnötig kompliziert. Guck dir noch mal operator >> an.
-
So jetzt hab ich die map aus der Funktion rausbekommen, allerdings habe ich jetzt den ganzen Text in map bzw. String.
Und wie ich den Operator>> hier anwenden soll weiß ich leider auch nicht. Ich wüsste nur wie ich den Operator>> mit cin anwenden könnte.Hier aber erstmal meine nächste Version des Programms:
#include <iostream> #include <map> #include <limits> #include <fstream> #include <string> #include <Windows.h> void Auslesen(std::string &t) { using namespace std; ifstream MeineDatei ("TestDokument.txt"); while (!MeineDatei.eof()){ t += MeineDatei.get(); // t >> MeineDatei.get(); } } int main() { using namespace std; ifstream MeineDatei ("TestDokument.txt"); if (MeineDatei.is_open()) { map <string, string> Text; Auslesen(Text["Text"]); cout << Text["Text"]; } else cout << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; cin.clear(); cin.ignore(); }
Weiterhin danke für eure Hilfe.
-Skotchy
-
Skotchy schrieb:
So jetzt hab ich die map aus der Funktion rausbekommen,
Zumindest ist das mit der Referenz ein brauchbarer Ansatz. Jetzt überlege, wie du wirklich die std::map und nicht nur einen String nutzen kannst.
Skotchy schrieb:
Und wie ich den Operator>> hier anwenden soll weiß ich leider auch nicht. Ich wüsste nur wie ich den Operator>> mit cin anwenden könnte.
Hm.. wie wäre es denn, sich mal das Beispiel anzusehen was man auf meinem Link oben betrachten kann? Ein Tipp: Die Anwendung sieht genau so aus wie bei std::cin.
Aber die std::map hast du immer noch nicht verstanden. Du liest weiterhin alles in den Schlüssel "Text" ein.
-
cooky451 schrieb:
Jetzt überlege, wie du wirklich die std::map und nicht nur einen String nutzen kannst.
also muss ich:
void Auslesen (std::map<std::string, std::string> &text)
benutzen, oder liege ich da falsch?
cooky451 schrieb:
Ein Tipp: Die Anwendung sieht genau so aus wie bei std::cin.
Also:
ifstream& >> text["test"]
oder lige ich hier(wieder) falsch? Ich habe das schon ausprobiert, aber ich bekomme immer '>>' rot unterstrichen und 'Error: Es wurde ein Bezeichner erwartet.'
Auserdem wüsste ich nicht wie ich den String "test" ändern könnte damit ich beliebig viele Wörter aus dem Dokument Auslesen kann.
Oder (so wie ich map verstanden habe): weiß ich nicht wie ich den Schlüssel("test") ändern könnte um ihnen dann die Werte(Wörter/Zeilen) zuzuordnen, weil sie im string-format vorliegen( mit int könnte ich den Schlüssel in einer for-Schleife ändern).Über weitere Tipps würde ich mich freuen und weiterhin danke für eure Hilfe.
-Skotchy
-
Skotchy schrieb:
also muss ich:
void Auslesen (std::map<std::string, std::string> &text)
benutzen, oder liege ich da falsch?
Das ist so korrekt, fehlt nur noch der Dateiname als zweiter Parameter. Du könntest die map zwar auch aus der Funktion zurückgeben (std::map<std::string, std::string> Auslesen(const char *dateiname)), aber das ist so absolut in Ordnung.
Skotchy schrieb:
Also:
ifstream& >> text["test"]
oder lige ich hier(wieder) falsch? Ich habe das schon ausprobiert, aber ich bekomme immer '>>' rot unterstrichen und 'Error: Es wurde ein Bezeichner erwartet.'
Aha, da liegt das Problem. std::cin ist eine Instanz von istream. Du schreibst ja auch nicht istream >> s. Ist der Groschen gefallen?
std::ifstream infile("test.txt"); std::string s; infile >> s;
Skotchy schrieb:
Auserdem wüsste ich nicht wie ich den String "test" ändern könnte damit ich beliebig viele Wörter aus dem Dokument Auslesen kann.
Oder (so wie ich map verstanden habe): weiß ich nicht wie ich den Schlüssel("test") ändern könnte um ihnen dann die Werte(Wörter/Zeilen) zuzuordnen, weil sie im string-format vorliegen( mit int könnte ich den Schlüssel in einer for-Schleife ändern).Wenn ich dir das jetzt einfach sage, habe ich die Aufgabe ja für dich gelöst. Aber ein Tipp: Du kannst auch eine Variable benutzen! Also Folgendes ist möglich:
std::map<std::string, std::string> m; std::string s = "Hallo, "; m[s] = "Welt!";
-
So habe ich das jetzt 'gelöst':
#include <iostream> #include <map> #include <limits> #include <fstream> #include <string> void Auslesen(std::map<std::string, std::string> &text, std::string s) { using namespace std; int i = 0; ifstream MeineDatei ("TestDokument.txt"); while (!MeineDatei.eof()){ s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i]; MeineDatei.get(); MeineDatei >> text[s]; ++i; } } int main() { using namespace std; string schluessel; map <string, string> Text; ifstream MeineDatei ("TestDokument.txt"); if (MeineDatei.is_open()) { Auslesen(Text, schluessel); for(int i = 0; i != Text.size(); ++i) { schluessel = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i]; cout << Text[schluessel]; } } else cout << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; cin.clear(); cin.ignore(); }
Und irgendwo habe ich etwas vergessen oder übersehen oder sonst etwas, denn ich habe 2 Fehler, die hoffentlich meine letzten sind bzw. in diesem Programm sein werden.
Und zwar:
1. wird der erste Buchstabe nicht ausgegeben.
2. werden keine Leerzeichen und Absätze erkannt/benutzt.Und noch eine Frage: ist die Lösung für den Schlüssel mit 'schluessel = "ABC..."[i];' eine gute bzw passend Lösung für die Namensgebung oder gibt es da bessere?
Weiterhin danke für eure Hilfe.
-Skotchy
-
Skotchy schrieb:
Und noch eine Frage: ist die Lösung für den Schlüssel mit 'schluessel = "ABC..."[i];' eine gute bzw passend Lösung für die Namensgebung oder gibt es da bessere?
Tja, du scheinst die map<> jetzt zwar irgendwie verstanden zu haben, aber scheinbar die Aufgabenstellung nicht. Du nutzt als Schlüssel wieder im Programm selbst vorgegebene Dinge. Bedenke den Aufbau der Datei!
Schlüssel Wert Schlüssel Wert ...
Für die Ausgabe in der main()-Funktion solltest du dir Iteratoren ansehen.
(Falls du lieber erstmal eine "Musterlösung" sehen möchtest, weil du das Gefühl hast so nicht weiter zu kommen sag Bescheid.)
-
Jetzt habe ich ein Programm gebastelt, das irgendwo einen Fehler hat:
#include <iostream> #include <map> #include <fstream> #include <string> void Auslesen(std::map<std::string, std::string> &text, std::string &s) { using namespace std; ifstream MeineDatei ("TestDokument.txt"); int i = 0; while (!MeineDatei.eof()) { MeineDatei.get(); MeineDatei >> s[i]; MeineDatei.get(); MeineDatei >> text[s]; i++; } } int main() { using namespace std; map <string, string> Text; ifstream MeineDatei ("TestDokument.txt"); string schluessel[5]; int i = 0; if (MeineDatei.is_open()) { Auslesen(Text, schluessel[0, 1, 2, 3, 4]); for(Text.begin(); Text.begin() != Text.end(); Text.begin()++, i++) { cout << Text[(string)schluessel[i]]; } } else cout << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; cin.clear(); cin.ignore(); }
Ich vermute das sich der Fehler in der while-Schleife versteckt hat.
cooky451 schrieb:
(Falls du lieber erstmal eine "Musterlösung" sehen möchtest, weil du das Gefühl hast so nicht weiter zu kommen sag Bescheid.)
Wenn der Fehler in meinem Programm groß genug ist, würde ich mir gern die Musterlösung ansehen
.
Weiterhin danke für eure Hilfe.
-Skotchy
-
Skotchy schrieb:
Wenn der Fehler in meinem Programm groß genug ist, würde ich mir gern die Musterlösung ansehen
.
Nja, jetzt hast du es fast.
Skotchy schrieb:
#include <iostream> #include <map> #include <fstream> #include <string> void Auslesen(std::map<std::string, std::string> &text, std::string &s) // Wozu der std::string? { using namespace std; ifstream MeineDatei ("TestDokument.txt"); // Das hier soll als Parameter übergeben werden. Entweder als "const char *", oder als "const std::string&") int i = 0; // Wozu das? while (!MeineDatei.eof()) // Tipp: http://www.cplusplus.com/reference/iostream/ios/operator_voidpt/ { MeineDatei.get(); // Wozu? MeineDatei >> s[i]; // Warum s[i]? MeineDatei.get(); // Wozu? MeineDatei >> text[s]; // Hier bist du auf dem richtigen Weg. i++; // ..? } } int main() { using namespace std; map <string, string> Text; // Korrekt ifstream MeineDatei ("TestDokument.txt"); // Hä? Du öffnest die Datei doch in der Funktion! string schluessel[5]; // Hä? int i = 0; // ?? if (MeineDatei.is_open()) { Auslesen(Text, schluessel[0, 1, 2, 3, 4]); // Was soll "schluessel"? for(Text.begin(); Text.begin() != Text.end(); Text.begin()++, i++) // Siehe Beispiel unten. :) { cout << Text[(string)schluessel[i]]; } } else cout << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; cin.clear(); cin.ignore(); }
Über einen Vektor kannst du mit Iteratoren z.B. so iterieren:
std::vector<int> v; v.push_back(5); ... for (std::vector<int>::const_iterator i = v.begin(); // i zeigt auf das erste Element des Vektors i != v.end(); ++i) // v.end() zeigt genau ein Element hinter das Letzte { std::cout << *i; }
Letzter Versuch. Du solltest dir nur im Klaren darüber sein, wenn du Spiele programmieren möchtest, sollte man die Aufgabe in ~2-3 Minuten gut lösen können.
-
So, dann ist das hier also die letzte Version meines Programms, allerdings mit ein paar Unklarheiten
#include <iostream> #include <map> #include <fstream> #include <string> #include <vector> void Auslesen(std::map<std::string, std::string> &text) { using namespace std; ifstream MeineDatei ("TestDokument.txt"); //const string &a = MeineDatei ("TestDokument.txt"); //Total falsch oder?! if ((void*)MeineDatei == 0){ cerr << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; return; } while (MeineDatei.good()) { MeineDatei >> text/*Hier müsste das erste Wort der Zeile aus der Datei als Schlüssel rein, oder?*/; //Hier müsste ich den vector v mit text[] füttern oder? } } int main() { using namespace std; vector<int> v; v.push_back (5); map <string, string> Text; Auslesen(Text); for(vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) { cout << *i; } cin.clear(); cin.ignore(); }
Ich denke mal, dass alles was mir unklar ist im code als Kommentar steht. Bin jetzt eigendlich nur noch gespannt, ob diese oder die vorherige Version näher an der Lösung bzw. an der Musterlösung ist.
Edit:
LoL warum wird der Code nicht als Code angezeigt ?!Weiterhin danke für eure Hilfe.
-Skotchy
-
Skotchy schrieb:
#include <iostream> #include <map> #include <fstream> #include <string> #include <vector> void Auslesen(std::map<std::string, std::string> &text) { using namespace std; ifstream MeineDatei ("TestDokument.txt"); //const string &a = MeineDatei ("TestDokument.txt"); //Total falsch oder?! if ((void*)MeineDatei == 0){ cerr << "Fehler beim Auslesen der Daten!" << endl << "Bitte pruefen sie ob \"TestDokument.txt\" existiert und im richtigen Ordner ist!"; return; } while (MeineDatei.good()) { MeineDatei >> text/*Hier müsste das erste Wort der Zeile aus der Datei als Schlüssel rein, oder?*/; //Hier müsste ich den vector v mit text füttern oder? } } int main() { using namespace std; vector<int> v; v.push_back (5); map <string, string> Text; Auslesen(Text); for(vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) { cout << *i; } cin.clear(); cin.ignore(); }
Der Syntaxhighlighter verträgt sich wohl nicht mit [].
Joa, schon besser.Blubb:
void readFile(std::map<std::string, std::string>& keys, const char *filename) { std::ifstream in(filename); if (in.good()) { std::string s; while (in >> s && in >> keys[s]) ; } else { std::cerr << "Could not open file: " << filename << "\n"; } } int main() { std::map<std::string, std::string> keys; readFile(keys, "keys.txt"); // auto ist hier gleichbedeutend mit: std::map<std::string, std::string>::const_iterator for (auto i = keys.begin(); i != keys.end(); ++i) std::cout << i->first << ": " << i->second << "\n"; getchar(); // Ganz böse! }
Frag, falls du irgendetwas nicht verstehst, oder wenn du noch eine Aufgabe willst.
-
Eine paar Fragen hab ich da schon zu dem Code:
1. Hätte ich gerne die while-Schleife erläutert bekommen.
2. Was ist der Unterschied zwischen 'endl' und '"\n"' ? Beide sorgen dafür das der folgende Text in der nächsten Zeile ausgegeben, richtig? Aber wo liegt der unterschied?(oder gibt es da keinen?)
3. Eine Verständnisfrage: 'i->first' Zeigt auf das erste Element aus 'i' und 'i->second' auf das zweite bzw. indem Fall auf die folgenden Elemente, richtig?
4. Warum ist 'getchar()' so böse?So, dass waren dann meine Fragen und über noch eine Aufgabe würde ich mich auch freuen
.
Weiterhin danke für eure Hilfe.
-Skotchy