Design Frage
-
DerDesigner schrieb:
Wenn alles korrekt sein soll würde ich sagen das der Ablauf so aussehen muss:
- Prüfen ob die Datei existiert
- Datei auslesen
- Daten verarbeitenJa genau, jetzt hast du aber wohl den wichtigsten Punkt vergessen, nämlich das Prüfen, ob das Auslesen erfolgreich war:
- Prüfen ob die Datei existiert
- Daten auslesen
- Prüfen, ob das Auslesen erfolgreich war.
- Daten verarbeiten
-
DerDesigner schrieb:
SeppJ schrieb:
- Prüfen, Lesen, Verarbeiten ist logisch falsch. Du willst Lesen, Prüfen, Verarbeiten
Das versteh ich nicht.
Wenn alles korrekt sein soll würde ich sagen das der Ablauf so aussehen muss:
- Prüfen ob die Datei existiert
- Datei auslesen
- Daten verarbeitenIch meinte auf der Ebene darunter. Du machst:
-Prüfen ob letzte Aktion erfolgreich
-Leseaktion
-Ausgabe des Gelesenen
Das heißt du bekommst im Fehlerfall (Dateiende) irgendwelchen Müll (hier: Das letzte Wort doppelt).Und was endl genau macht:
http://www.cplusplus.com/reference/iostream/manipulators/endl/ Inserts a new-line character. Additionally, for buffered streams, [b]endl flushes the buffer (i.e. writes all unwritten characters in the buffer to the output sequence, see ostream::flush).[/b]Ich weiss noch immer nicht wo da das Problem ist.
Willst du das fett markierte wirklich? Ist dir genau klar, was das das bedeutet bzw. was passieren würde, wenn du stattdessen einfach nur '\n' benutzen würdest?
-
DerDesigner schrieb:
Wenn ich die Datei Zeile für Zeile mit getline auslese und die Ausgabe auch Zeile für Zeile sehen will dann komm ich doch um das endl nicht herum oder?
Und was endl genau macht:
http://www.cplusplus.com/reference/iostream/manipulators/endl/ Inserts a new-line character. Additionally, for buffered streams, endl flushes the buffer (i.e. writes all unwritten characters in the buffer to the output sequence, see ostream::flush).Ich weiss noch immer nicht wo da das Problem ist.
Das Problem ist, dass du
endl(bzw. das Flushen) nicht willst. Was du willst, ist einfach nur eine neue Zeile, sprich'\n', und nichtendl. (endl='\n'+flush)
-
Achso jetzt versteh ich das wieso endl in meinem Fall nicht so toll ist.^^
Aber was genau bedeutet das? Schreibt alle ungeschriebenen Zeichen in den Buffer der Ausgabe Sequenz.
Was sind den ungeschriebene Zeichen? Was soll man sich darunter vorstellen?
Ich hab sonst immer für einen Zeilenumbruch endl verwendet unser Lehrer meinte immer "das nimmt man wenn man einen Zeilenumbruch" machen will er meinte in C benutzt man immer '\n' und in C++ endl. Aber \n ist anscheind wohl irgendwie angebrachter.
Und ja stimmt ich hab gar nicht geprüft ob die Aktionen erfolgreich waren aber dafür muss ich mich erst mal mit dem this* Pointer auseinander setzen.^^
-
DerDesigner schrieb:
Ich hab sonst immer für einen Zeilenumbruch endl verwendet unser Lehrer meinte immer "das nimmt man wenn man einen Zeilenumbruch" machen will er meinte in C benutzt man immer '\n' und in C++ endl. Aber \n ist anscheind wohl irgendwie angebrachter.
Dann hinterfrag in Zukunft alles was dein Lehrer dir beibringen will. Nun ja, das sollte man sowieso immer bei jedem Lehrer tun
. Also: Hinterfrag alles doppelt, was er dir beibringen will
. Du kannst ihn ja mal fragen, was fflush in C macht, ich wette er weiß es nicht (aber vielleicht denkt er sich spontan etwas aus).Oftmals werden Ausgaben zwischengespeichert um dann später effizient alles in großen Blöcken auf das eigentliche Ausgabegerät zu schreiben. Ein flush (direkt oder ein indirektes flush durch endl) erzwingt, dass der Zwischenspeicher sofort geschrieben wird. Bei einer Konsolenausgabe merkt man das meistens nicht, da die meisten Konsolen bei einem Zeilenumbruch ebenfalls den Zwischenspeicher leeren. Auf vielen Konsolen wird aber ein Programm wie dieses hier eine verspätete Ausgabe erzeugen, weil der Zwischenspeicher erst nach der Wartescheife geschrieben wird:
#include <iostream> int main() { using namespace std; cout << "Hallo Welt!"; for (volatile int i = 0; i < 999999999; ++i); cout << flush; }(Funktioniert mit Linuxkonsolen, sollte auch in Windows funktionieren: Bitte Rückmeldung falls nicht.)
Wirklich wichtig wird das aber bei Ausgabe in Dateien. Da wird nämlich aus gutem Grund nicht bei jedem Zeilenumbruch geflusht, sondern erst wenn es sich richtig lohnt. Denn das Schreiben von kleinen Datenpaketen auf die Festplatte ist sehr, sehr ineffizient. Wenn man da nach jeder Zeile ein leeren des Zwischenpuffers erzwingt wird das entsprechend lahm. Ganz schlimm auf Mehrbenutzersystemen, da man dadurch auch leicht so viel I/O-Last erzeugen kann, dass das ganze System in die Knie geht und andere Nutzer auch betroffen sind. Daher gleich richtig angewöhnen, '\n' schreiben wo man einen Zeilenumbruch möchte und endl wo man wirklich auch eine Ausgabe erzwingen möchte (das kann in manchen Fällen sinnvoll sein, zum Beispiel Logausgaben).
-
DerDesigner schrieb:
Aber was genau bedeutet das? Schreibt alle ungeschriebenen Zeichen in den Buffer der Ausgabe Sequenz.
Der stream besitzt einen Datenpuffer. Es werden erst Daten in die Datei geschrieben, wenn genug Daten in diesem Puffer sind. Dies verhindert, dass sehr viele unnötige Schreiboperationen durchgeführt werden, die man auch einfacher zusammen fassen könnte, was schneller ist. Durch exzessive Benutzung von std::endl umgehst du diesen Mechanismus, weil du den Puffer explizit leerst(=flush)
Dies ist aber nur bei Dateien wirklich sinnvoll, bei std::cout will man oft Dinge sofort ausgeben, und muss daher std::flush oder std::endl verwenden. Sonst denkt der Benutzer, dass ein Programm gar nichts tut, dabei war nur der Ausgabepuffer von cout nicht voll ;).
In vielen kleinen Anwendungsfällen und auch Übungsprogrammen ist der Unterschied zwischen \n und std::endl nicht messbar und als Anfänger hat man in C++ eh 1000 verschiedene Dinge auf die man achten soll, da kann ich gut verstehen, dass man sich nicht auch damit herum plagen will. Und das ist auch, unabhängig von dem kleinen Kreuzzug gegen std::endl in diesem Forum, okay so. Mach es erst mal so, wie es dir einfacher erscheint, oder bis es wirklich mal lange dauert...
-
SeppJ schrieb:
Auf vielen Konsolen wird aber ein Programm wie dieses hier eine verspätete Ausgabe erzeugen, weil der Zwischenspeicher erst nach der Wartescheife geschrieben wird:
#include <iostream> int main() { using namespace std; cout << "Hallo Welt!"; for (volatile int i = 0; i < 999999999; ++i); cout << flush; }(Funktioniert mit Linuxkonsolen, sollte auch in Windows funktionieren: Bitte Rückmeldung falls nicht.)
Nope es wird sofort geschrieben. (Win7 Prof. 64-bit)
-
Bei mir wird es auch sofort geschrieben.
WinXP Pro SP3Aber zu erst kommt doch auch der cout Befehl damit gibt man doch den Text aus.
otze schrieb:
Dies ist aber nur bei Dateien wirklich sinnvoll, bei std::cout will man oft Dinge sofort ausgeben, und muss daher std::flush oder std::endl verwenden. Sonst denkt der Benutzer, dass ein Programm gar nichts tut, dabei war nur der Ausgabepuffer von cout nicht voll
Kann man das auf Windows auch irgendwie nachstellen?
-
DerDesigner schrieb:
Bei mir wird es auch sofort geschrieben.
WinXP Pro SP3Aber zu erst kommt doch auch der cout Befehl damit gibt man doch den Text aus.
Deine Resistanz ist echt bewundernswert :D. Die Ausgabe, die du mit coutmachst, findet gepuffert statt. Alles, das du mitcoutausgibst, landet in einem Datenpuffer. Erst irgendwann später wird der Inhalt vom Datenpuffer auf den Bildschirm gepfeffert; wann das passiert, kann manchmal sofort sein und manchmal übermorgen.otze schrieb:
Dies ist aber nur bei Dateien wirklich sinnvoll, bei std::cout will man oft Dinge sofort ausgeben, und muss daher std::flush oder std::endl verwenden. Sonst denkt der Benutzer, dass ein Programm gar nichts tut, dabei war nur der Ausgabepuffer von cout nicht voll
Dann gibts da aber auch noch
cerr.
-
DerDesigner schrieb:
Kann man das auf Windows auch irgendwie nachstellen?
#include <iostream> int main() { using namespace std; char buffer[512]; std::cout.rdbuf()->pubsetbuf(buffer, 512); cout << "Hallo Welt!"; for (volatile int i = 0; i < 999999999; ++i); cout << flush; }
-
Ok ty @ all jetzt hab ich es auch kapiert.
