Erstellung eines Histogramms
-
Hey Leute !
Kann mir wirklich gut vorstellen, wie genervt man sein muss, wenn ständig neue Benutzer ohne vorherige Recherchen hier nach Hilfe suchen...
Ich bin leider auch einer davon, nur habe ich bereits mein Bestes (soweit es geht) gegeben und komme zu keiner Lösung
Es geht darum, ein Histogramm zu erstellen; ich lese eine Datei mit 2 Spalten ein, in der ersten steht die Zeit und in der zweiten die Ortskoordinate.
Dann Überprüfe ich ob die gewählten Intervalle getroffen wurden und lasse mir am Ende den "counter" ausgeben.
Die Sache ist, dass ich selbst bei einer "simplen" Datei mit Daten wie:
1 1
2 2
3 1
4 4
5 1
6 6
7 1
8 8
9 1am Ende in der Ausgabe totalen Schwachsinn bekomme mit Werten von:
#intervall Auftritte_Teilchen
0 -1732826976
1 32767
2 -1732826961
3 32767
4 311044592
5 32720
6 307760984
7 32720
8 -1732826912
9 32767herausbekomme. Bin ziemlich ratlos bei der Fehlersuche, weil ich mir nicht erklären kann woher solche Zahlen kommen sollen. Greife ich da vielleicht irgendwo auf falschen Speicher zu?
...also falls dies doch gegen Forumvorschriften verstößt, so ignoriert den Beitrag einfach.
Wenn nicht, dann hier der Quellcode, bin für jede Hilfe oder jeden Tipp sehr dankbar!
Wie gesagt, ich habe wenig Erfahrung bisher, mein Stil ist möglicherweise nicht der Beste
#include <iostream> #include <fstream> #include <cstdlib> #include <cstring> using namespace std; const int N=10; //Anzahl Intervalle int main(int argc, char** argv){ if(argc != 2) { cout << "Erwartet Dateiname als Parameter" << endl; return 0; } char buf[256]; ifstream fl; fl.open(argv[1]); if(!fl.is_open()) { return 1; } double max = 0; double min = 0; while(!fl.eof()) { fl.getline(buf, 255); double x; char* pch; pch = strtok(buf, " "); if(pch != NULL) x = atoi(pch); if(x > max) max = x; //Setzen der Grenzen des betrachteten Bereichs if(x < min) min = x; } double intervallgroesse = (max-min)/N; //Intervallgröße bestimmen double intervallbeginn[N]; for(int i=0; i<N; i++){ intervallbeginn[i]=intervallgroesse*(i); //Berechnung des jeweiligen Beginns eines Intervalls } fl; fl.open(argv[1]); if(!fl.is_open()) { return 1; } int counter[N]; //Zähler der Auftritte des Teilchen im Intervall i while(!fl.eof()) { fl.getline(buf, 255); double x; char* pch; pch = strtok(buf, " "); if(pch != NULL) x = atoi(pch); int i=0; if(x>intervallbeginn[i]){i++;} //Falls x größer als Intervallbeginn i, nächstes Intervall betrachten else{counter[i-1]++;} //Wenn x nicht größer als Intervallbeginn des aktuellen Intervalls, muss es im vorherigen Intervall sein } ofstream out("histogramm.txt"); out<<"#intervall"<<" "<<"Auftritte_Teilchen"<<endl; //Ausgabe for(int i=0; i<N; i++){ out<< i << " " << counter[i] <<endl; } fl.close(); out.close(); return 0; }
-
Musst du nicht atof benutzen, wenn du
double x;
verwendest?
Oder andersrum, warum deklarierst du nicht einfach
int x;
wenn scheinbar ohnehin nur integers in Frage kommen.
-
Ich übersehe da mal einiges und frage gleich: Willst du nur Ganzzahlen oder auch Kommazahlen einlesen?
-
Ich möchte auch Kommazahlen einlesen.
-
crack123 schrieb:
Ich möchte auch Kommazahlen einlesen.
Versuch mal operator >>. Du kannst von ifstreams lesen wie von std::cin:
ifstream is("file.txt"); double max; is >> max; // Eventuell Rückgabewert beachten
Hilft dir das?
(atoi() gibt im Übrigen eine Ganzzahl, genauer einern Integer zurück!)
-
Servus, ich kämpfe aktuell auch mit Histogrammen. Ohne vorher den Thread gelesen zu haben, ich bin mit den Histogrammen der GSL sehr zufrieden, siehe: http://www.gnu.org/s/gsl/manual/html_node/Histograms.html
-
Hallo crack123,
Die Hauptfehler bestehen darin, dass in den Zeilen 63,63 die Schleife fehlt, die das passende Intervall findet. Weiter ist das Array counter[] in Zeile 51 nicht initialisiert. D.h. da steht vorher irgendwas drin und das wird später ausgegeben. Daher die komischen Werte.
crack123 schrieb:
Wie gesagt, ich habe wenig Erfahrung bisher, mein Stil ist möglicherweise nicht der Beste
ok - das ist verständlich, jeder war mal Anfänger.
Aber wo hast Du denn das
crack123 schrieb:
while(!fl.eof()) { fl.getline(buf, 255);
gelernt?
Gruß
Werner@Edit benutzte den 'C/C++'-Tag statt des 'Code'-Tags um den Sourcecode darzustellen - sieht besser aus
-
Heyhey,
erstmal riesengroßes Dankeschön an all die Leute die versuchen, mir zu helfen, hätte keine so große Hilfsbereichtschaft erwartet.
Klasse Forum habt ihr hier, ich werde wohl länger bleiben@Werner Salomon: ich glaube ich verstehe was in Zeile 63 schief gelaufen ist, aber komme momentan auf keine Lösung. Ein kleiner Tipp vielleicht?
Und ehm was genau meinst Du mit "das Array ist nicht initialisiert"?
Mache ich nicht gerade das mit int counter[n]?while(!fl.eof()) { fl.getline(buf, 255);
Das habe ich irgendwo im Internet gefunden als ich mich mit dem Einlesen von Dateien beschäftigt hab, ich weiß die Quelle nicht mehr
-
Hallo,
bezogen auf die Initialisierung:
mittels "int counter[N]" wird für eine lokale Variable nur Speicher bereitgestellt (ohne die Inhalte zu verändern, d.h. dort stehen also zufällige Werte drin).
Mittelsint counter[N] = { 0 };
kannst du dies aber erzwingen (d.h. alle Array-Werte werden auf 0 gesetzt).
-
Aaaaaaaah ja stimmt, dämlich von mir.
Danke dafür!
...
Hab alles was ich brauchte, Thread kann sterben!
Vielen Dank nochmal an alle die geholfen haben!
-
crack123 schrieb:
Hab alles was ich brauchte, Thread kann sterben!
na - noch nicht ganz; ich bin Dir noch eine Antwort schuldig.
crack123 schrieb:
while(!fl.eof()) { fl.getline(buf, 255);
Das habe ich irgendwo im Internet gefunden als ich mich mit dem Einlesen von Dateien beschäftigt hab, ich weiß die Quelle nicht mehr
Du weißt, dass geschätzte 90% von dem, was man im Internet findet, Mist ist? In diesem Thread habe ich schon mal versucht auszuführen, warum ich diese while-!EOF-Konstruktion für einen Fehler halte.
In Deinem Fall kannst Du die Zahlen z.B. einfach mit ..
for( double zeit, ort; fl >> zeit >> ort; ) { if( zeit < min ) min = zeit; if( zeit > max ) max = zeit; }
.. einlesen. Wenn Du doubles haben willst, so lese doubles - so einfach ist das.
Gruß
Werner