Textdatei auslesen und verarbeiten [geloest]
-
SeppJ schrieb:
xStrykex schrieb:
Quasi mit static_cast?
Nein, das wäre eine explizite Typumwandlung. Es geht ohne. Machst du wahrscheinlich standig, ohne überhaupt darüber nachzudenken.
char foo = 3; // 3 ist Integer. Nach dieser Zuweisung ist foo == '\x03' (char) double bar = foo; // Nach dieser Zuweisung ist bar == 3.0 (double)
Ne implizite Typumwandlung hätte ich jetzt nicht gedacht, dass das funktioniert aufgrund von char/string
Naja, wollte jetzt gerne meine Lösung präsentieren.
#include<iostream> #include<fstream> #include<string> #include<vector> #include<cmath> #include<limits> int main() { std::fstream Datei; std::string Dateiname; std::cin >> Dateiname; // Datei einlesen (Pfad angeben) Datei.open(Dateiname.c_str(), std::ios::binary|std::ios::in); std::vector<double> WerteL; // vector mit Messwerten double Summe = 0; double MW = 0; double SA = 0; for (double Wert; Datei >> Wert; WerteL.push_back(Wert)) { Summe +=Wert; MW = Summe / WerteL.size(); // Mittelwert aus Summe der Messwerte / Anzahl } Datei.clear(); Datei.seekg(std::ios_base::beg); std::vector<double> WerteV; for (double Wert; Datei >> Wert; WerteV.push_back(Wert-MW)) { // vector der Messwerte mit Abweichungen zum Mittelwert füllen } double Help = 0; // Hilfsvariable Help for (unsigned int i = 0; i < WerteL.size(); i++) { Help += WerteV[i]; // Summe der Abweichungen } SA = std::sqrt( (Help * Help) / WerteV.size() ); // Berechnung Standardabweichung std::cout << "\n\nMittelwert: " << MW << "\n\nStandardabweichung: " << SA; // Ausgabe std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cin.get(); return 0; }
Ich bin zufrieden und "Mentor" auch
@SeppJ: Danke für den Tipp mit dem debuggen nochmal, hat sehr geholfenDanke für die Hilfe
EDIT:Kritik und Verbesserungsvorschläge werden natürlich immer gern geseehn, aber bitte mit entsprechender Erklärung(Tipps)
-
xStrykex schrieb:
EDIT:Kritik und Verbesserungsvorschläge werden natürlich immer gern geseehn, aber bitte mit entsprechender Erklärung(Tipps)
1. Versuche Betriebsmittel immer während der Initialisierungs-Phase anzufordern, falls möglich. D.h. mach das
Datei.open
da weg und übergib die Zeichenkette dem Konstrukror vonstd::ifstream
.
2. Wie immer, benutzte NUR das, was du brauchst. Du brauchst keinstd::fstream
, du bruachst nurstd::ifstream
.
3. Ich verstehe nicht, wieso du die Datei 2x ausliest.
4. Eine for-Schleife ist auch nur eine Anweisung, die mit einem ; beendet werden kann. Eine leere Verbundanweisung ist doch etwas sinnlos.
5. Falls es sich um eine Textdatei handelt, öffnet man diese normal nicht im Binärmodus. D.h. lassstd::ios::binary
weg.
6. Ansonsten würde ich mir mal Funktionen zu nutzen machen. Ich würde eine Funktion machen, die etwas einließt. Ich würde eine Funktion machen, die etwas berechn. Ich würde eine Funktion machen, die am Ende das Programm offen hält.
-
out schrieb:
1. Versuche Betriebsmittel immer während der Initialisierungs-Phase anzufordern, falls möglich. D.h. mach das
Datei.open
da weg und übergib die Zeichenkette dem Konstrukror vonstd::ifstream
.
2. Wie immer, benutzte NUR das, was du brauchst. Du brauchst keinstd::fstream
, du bruachst nurstd::ifstream
.Ok, hoffe ist so wie du es dir gedacht hast im folgenden Code
out schrieb:
3. Ich verstehe nicht, wieso du die Datei 2x ausliest.
Ich habe mir gedacht, zweimal auslesen, da ich die Werte zweimal(einmal umgerechnet & in zwei verschiedene Vektoren schreibe) nutze?
out schrieb:
4. Eine for-Schleife ist auch nur eine Anweisung, die mit einem ; beendet werden kann. Eine leere Verbundanweisung ist doch etwas sinnlos.
5. Falls es sich um eine Textdatei handelt, öffnet man diese normal nicht im Binärmodus. D.h. lassstd::ios::binary
weg.Erledigt
out schrieb:
6. Ansonsten würde ich mir mal Funktionen zu nutzen machen. Ich würde eine Funktion machen, die etwas einließt. Ich würde eine Funktion machen, die etwas berechn. Ich würde eine Funktion machen, die am Ende das Programm offen hält.
Ich versuch mich dran, sobald die ersten fünf Punkte erledigt sind
EDIT: Code vergessen
#include<iostream> #include<fstream> #include<string> #include<vector> #include<cmath> #include<limits> int main() { std::string Dateiname; std::cin >> Dateiname; std::ifstream Datei(Dateiname.c_str(), std::ios::in); // Datei einlesen (Pfad angeben) std::vector<double> WerteL; // vector mit Messwerten double Summe = 0; double MW = 0; double SA = 0; for (double Wert; Datei >> Wert; WerteL.push_back(Wert)) { Summe +=Wert; MW = Summe / WerteL.size(); // Mittelwert aus Summe der Messwerte / Anzahl } Datei.clear(); Datei.seekg(std::ios_base::beg); std::vector<double> WerteV; for (double Wert; Datei >> Wert; WerteV.push_back(Wert-MW)); // vector der Messwerte mit Abweichungen zum Mittelwert füllen double Help = 0; // Hilfsvariable Help for (unsigned int i = 0; i < WerteL.size(); i++) { Help += WerteV[i]; // Summe der Abweichungen } SA = std::sqrt( (Help * Help) / WerteV.size() ); // Berechnung Standardabweichung std::cout << "\n\nMittelwert: " << MW << "\n\nStandardabweichung: " << SA; // Ausgabe std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cin.get(); return 0; }
-
Der Algorithmus ist noch nicht so toll:
Zeile 21: Wieso ist die in der Schleife drin? Denk mal nach, was bei jedem Durchlauf passiert und ob das wohl auch einfacher geht.
Zeile 27-28: Du hast doch die Werte alle schon in einem Container gespeichert! Selbst wenn du einen zweiten Container haben wolltest (wozu?), wieso kopierst du dann nicht den ersten Container?Stil:
Zeile 12: ios::in ist bei ifstream schon vorgegeben, kannst du weglassen. Was soll man auch anderes mit einem ifstream machen?
Zeile 30: Warum "Help"? Das ist die Summe der Abweichungsquadrate.
-
SeppJ schrieb:
Der Algorithmus ist noch nicht so toll:
Zeile 21: Wieso ist die in der Schleife drin? Denk mal nach, was bei jedem Durchlauf passiert und ob das wohl auch einfacher geht.Hab die Zeile mal aus der for-Schleife gepackt, dann kommt aber beim Mittelwert eine Ganzzahl bei raus(zumindest in der Ausgabe und die Standardabweichung wird komplett falsch berechnet. Woran liegt das, an dem "WerteL.size()"? Kann mir das grade nicht erklären
SeppJ schrieb:
Zeile 27-28: Du hast doch die Werte alle schon in einem Container gespeichert! Selbst wenn du einen zweiten Container haben wolltest (wozu?), wieso kopierst du dann nicht den ersten Container?
Stil:
Zeile 12: ios::in ist bei ifstream schon vorgegeben, kannst du weglassen. Was soll man auch anderes mit einem ifstream machen?
Zeile 30: Warum "Help"? Das ist die Summe der Abweichungsquadrate.Hast vollkommen Recht, sind unnötig und wurden entfernt
-
xStrykex schrieb:
SeppJ schrieb:
Der Algorithmus ist noch nicht so toll:
Zeile 21: Wieso ist die in der Schleife drin? Denk mal nach, was bei jedem Durchlauf passiert und ob das wohl auch einfacher geht.Hab die Zeile mal aus der for-Schleife gepackt, dann kommt aber beim Mittelwert eine Ganzzahl bei raus(zumindest in der Ausgabe und die Standardabweichung wird komplett falsch berechnet. Woran liegt das, an dem "WerteL.size()"? Kann mir das grade nicht erklären
Vermutlich weil du noch andere Sachen geändert hast. Zeig Code!
-
Eigentlich nicht großartig, wollte erstmal nur verbessern/optimieren und anschließend mich an den Funktionen (wie out erwähnte) versuchen
#include<iostream> #include<fstream> #include<string> #include<vector> #include<cmath> #include<limits> int main() { std::string Dateiname; std::cin >> Dateiname; std::ifstream Datei(Dateiname.c_str()); // Datei einlesen (Pfad angeben) std::vector<double> WerteL; // vector mit Messwerten double Summe = 0; double MW = 0; double SA = 0; for (double Wert; Datei >> Wert; WerteL.push_back(Wert)) { Summe +=Wert; } MW = Summe / WerteL.size(); // Mittelwert aus Summe der Messwerte / Anzahl , hier wuerde es jetzt stehen for (unsigned int i = 0; i < WerteL.size(); i++) { SA += WerteL[i]-MW; // Summe der Abweichungen } SA = std::sqrt( (SA * SA) / WerteL.size() ); // Berechnung Standardabweichung std::cout << "\n\nMittelwert: " << MW << "\n\nStandardabweichung: " << SA; // Ausgabe std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cin.get(); return 0; }
-
Ich kann das Problem nur teilweise nachvollziehen. Der Mittelwert ist bei mir weder eine Ganzzahl noch ist er falsch. Passt haargenau. Bist du sicher, dass überhaupt eine Datei geöffnet und gelesen wird? Oder ist der Mittelwert bei deinen Daten zufällig eine Ganzzahl? Oder sieht deine Datei eben doch anders aus als du behauptet hast (Kommas zwischen den Zahlen?) so dass nur ein Wert gelesen wird?
Insgesamt ist das mal wieder ein Fall für den Debugger oder ein paar Testausgaben.Die Standardabweichung wird weiterhin falsch berechnet. Das habe ich dir zwar schon auf Seite 1 mal gesagt und du hast richtigerweise etwas von "quadrieren" gemurmelt, aber du hast es niemals umgesetzt:
a²+b² != (a+b)²
Siebte Klasse.
-
SeppJ schrieb:
Bist du sicher, dass überhaupt eine Datei geöffnet und gelesen wird?
Ja, es wird die richtige Datei gelesen.
SeppJ schrieb:
Oder ist der Mittelwert bei deinen Daten zufällig eine Ganzzahl?
Nein, der Mittelwert ist keine Ganzzahl. Habe die Frage auch etwas ungeschickt gestellt, meinte, dass die Ausgabe eine Ganzzahl ist, obwohl sie keine ist(Debugger zeigt richtige Zahl an).Mit dem Debugger arbeite ich jetzt die ganze Zeit, seit du mir den empfohlen hast.
Habe es jetzt mit Testausgaben probiert. Und dabei stellt sich mir die Frage:
Bis zu wievielen Nachkommastellen gibt double standardmäßig aus?
Sieht mir nach 3 Nachkommastellen aus (den "Tests" zufolge). Vllt sollte ich dann einfach setprecision nehmen..SeppJ schrieb:
Oder sieht deine Datei eben doch anders aus als du behauptet hast (Kommas zwischen den Zahlen?) so dass nur ein Wert gelesen wird?
Ja, in der Datei befinden sich ausschließlich Punkte zwischen den Zahlen.
SeppJ schrieb:
a²+b² != (a+b)²
Siebte Klasse.Ja, tut mir Leid, hast wieder Recht.
Sobald die Aufgabe als korrekt abgestempelt wurde, habe ich mir darum keine Sorgen mehr gemacht.Sollte jetzt aber alles richtig sein.
#include<iostream> #include<fstream> #include<string> #include<vector> #include<cmath> #include<limits> int main() { std::string Dateiname; std::cin >> Dateiname; std::ifstream Datei(Dateiname.c_str()); // Datei einlesen (Pfad angeben) std::vector<double> WerteL; // vector mit Messwerten double Summe = 0; double MW = 0; double SA = 0; for (double Wert; Datei >> Wert; WerteL.push_back(Wert)) { Summe +=Wert; } MW = Summe / WerteL.size(); // Mittelwert aus Summe der Messwerte / Anzahl for (unsigned int i = 0; i < WerteL.size(); i++) { SA += ((WerteL[i]-MW)*(WerteL[i]-MW)); } SA = std::sqrt(SA / WerteL.size() ); std::cout << "\n\nMittelwert: " << MW << "\n\nStandardabweichung: " << SA; // Ausgabe std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cin.get(); return 0; }
Ich hoffe, es sind keine Flüchtigkeitsfehler mehr drin.
Auf jeden Fall vielen Dank für deine Mühe
EDIT: Ok, war reiner Rundungs"fehler" beim Mittelwert. Denke mal die Frage hat sich mit "standardmäßig 3 Nachkommastellen" für double erledigt
-
xStrykex schrieb:
Habe es jetzt mit Testausgaben probiert. Und dabei stellt sich mir die Frage:
Bis zu wievielen Nachkommastellen gibt double standardmäßig aus?
Sieht mir nach 3 Nachkommastellen aus (den "Tests" zufolge). Vllt sollte ich dann einfach setprecision nehmen..Standard ist eine Rundung auf 7 Stellen, wobei aber folgende Nullen abgeschnitten werden.
Das heißt, 0.3999999999 wird als 0.4 ausgegeben, sofern man nicht mit setprecision & Co. (guck dir mal fixed, scientific und andere Manipulatoren an) etwas anderes einstellt.
EDIT: Ok, war reiner Rundungs"fehler" beim Mittelwert. Denke mal die Frage hat sich mit "standardmäßig 3 Nachkommastellen" für double erledigt
Das heißt, es funktioniert? Wie gesagt ist Standard 7.
-
Also der richtige Wert war 99.99998 57896 [...]
War grade verwirrt ( mittlerweile ist Kopf ausgeschaltet, stressiger Tag noch nebenbei), aber hat sich von selbst erklärt, warum da 100 rauskam
7NachStellenMit fixed und setprecision arbeit ich ab und zu, den Rest guck ich mir auch noch an, nur net zu viel auf einmal
Nochmal Danke
-
In dem Zusammenhang könntest dir auch noch eben std::accumulate anschauen.