Auslesen von komplexen Zahlen aus einer Datei
-
Und parallel dazu, schau dir mal get() an.
-
Hacker schrieb:
Verstehe nicht wirklich was Du mir damit sagen willst?!
Du hast mir die Referenz zu "seekg" gesendet. Damit gibt man doch die Postion für den Dateizeiger an?! Nur in wie weit hilft mir das weiter? Ich weiß ja nicht in welcher Zeile ..... ich gerade bin.
Ich will doch nur auf das übernächste Zeichen zugreifen ohne das nächste und das übernächste Zeichen auszulesen.
-
Ja, du setzt also den get-Zeiger zwei(oder einen ? k.p. im moment) nach dem aktuellen stand, liest das Zeichen ein (oder peekst es) und gehst zurück. Das übernächste Zeichen so zu greifen, wie mit peek, funktioniert nicht ohne weiteres.
Edit: hättest du dir mal wenigstens etwas angesehen, hättest du ios::cur gefunden. Komm schon.
P.S.: In deinem Fall, nimm einfach ignore().
-
Hacker schrieb:
Ja, du setzt also den get-Zeiger zwei(oder einen ? k.p. im moment) nach dem aktuellen stand, liest das Zeichen ein (oder peekst es) und gehst zurück. Das übernächste Zeichen so zu greifen, wie mit peek, funktioniert nicht ohne weiteres.
Edit: hättest du dir mal wenigstens etwas angesehen, hättest du ios::cur gefunden. Komm schon.
P.S.: In deinem Fall, nimm einfach ignore().
Danke für die schnell Antwort. Jetzt hab ich es auch gesehen...Hab meinen Quellcode jetzt entsprechend angepasst. Nur leider bekomme ich jetzt den Fehler:
ISO C++ forbids comparison between pointer and integerUnd das an folgenden Stellen:
if(var == "j")
if(plus == "-")double real, imag; char plus, j, var; int a = 0; int b = 0; for(int p=0; p<7770; p++){ f>>real; f.seekg(ios::cur); var = f.peek(); if(var == "j"){ f.seekg((ios::cur)-1); f>>plus>>j>>imag; if(plus == "-"){ imag *= -1; } } else{ f.seekg((ios::cur)-1); imag = 0; } complexNumbers[p]=complex<double>(real,imag); } return complexNumbers;
-
char-Literale schreibt man in normale Quotes. ''
-
314159265358979 schrieb:
char-Literale schreibt man in normale Quotes. ''
Danke für den Tipp, jetzt funktioniert es ohne Fehlermeldungen.
Aber es muss immer noch ein Fehler in der Einleseroutine stecken, da nun 7770 Mal die gleiche Zahl gelesen wird.
Hmm...
-
Du weißt, dass
f.seekg(ios::cur);Den get-Zeiger auf die aktuelle Position setzt, also rein garnix bewirkt ?
Die Variable var ist übrigens nur ein unnötiger Platzhalter.Du kannst gleich
if(f.peek() == 'j'){ //...schreiben.
Und statt
f.seekg((ios::cur)-1); // oder +1f.unget(); // oder entsprechend get()Du kannst natürlich auch ignore() einsetzen, mit dem man auch mehrere Zeichen überspringen kann.
-
Danke für die Tipps, aber es ändert leider nichts an der Situation. Es wird immer die gleiche Zeile, Zahl eingelesen.
Vllt. hab ich ja auch nur ein Verständnisproblem damit.
Wenn f.seekg(ios::cur) jetzt auf die Stelle 0 zeigt, dann müsste es doch nach f>>xyz auf eine Stelle X zeigen oder etwa nicht?
f.seekg(ios::cur) zeigt jedoch immer auf die gleiche Stelle und ich verstehe nicht warum...
-
Javun schrieb:
Wenn f.seekg(ios::cur) jetzt auf die Stelle 0 zeigt, dann müsste es doch nach f>>xyz auf eine Stelle X zeigen oder etwa nicht?
f.seekg(ios::cur) zeigt jedoch immer auf die gleiche Stelle und ich verstehe nicht warum...
Ahh... kennst du denn keinen get-Zeiger ?
Der zeigt immer darauf wo du grad bist mit lesen.
tellg() zeigt dir an, wo er ist, mit seekg() kannst du ihn setzten.ios::cur ist einfach die aktuelle Position des get-Zeigers.
Wenn duDeinIfstream.seekg(ios::cur + 1);schreibst, heißt das, du inkrementierst den get-Zeiger der, bzw. deiner Datei.
Stattdessen könntest du auchDeinIfstream.ignore();Schreiben. Damit liest und ignorierst du 1 Zeichen (wenns mehr sein sollen, guck in der Referenz).
Die Funktion get() inkrementiert den get-Zeiger, und gibt dir den gelesenen Wert unformatiert zurück.
peek() macht dasselbe, nur das er den Zeiger nicht inkrementiert.
unget() liest ein Zeichen rückwärts, bzw. der get-Zeiger wird dekrementiert, und der eingelesene Wert wird unformatiert zurückgegeben.Der Shift-Operator nun, liest den gegebenen Wert ein, und inkrementiert den gZeiger jeweils um die Länge des Eingegebenen + 1.
Bspw: "5050aergaerg!" steht in der Datei.
Liest du einen Integer a mit
DeinFileStream>>a;ein, ist tellg() (die Position des get-Zeigers) 5 (und a 5050).
Hättest du alles in der Referenz nachlesen können.

-
Vom Prinzip her hab ich das alles Verstanden, ich versteh nur nicht ganz was das mit meinem Problem zu tun hat.
Ganz simpel gefragt, wie schaff ich es das er in die nächste Zeile sprint. Vorher hats ja auch funktioniert, dass einzige was ich jetzt ändern wollte, war die Überprüfung ob reel oder komplex. Das funktioniert ja jetzt soweit nur springt er einfach nicht in die nächste Zeile bzw. zur nächsten Zahl...
Deshalb kann ich nur meine Frage wiederholen:
Wenn f.seekg(ios::cur) jetzt auf die Stelle 0 zeigt, dann müsste es doch nach f>>xyz auf eine Stelle X zeigen oder etwa nicht?
f.seekg(ios::cur) zeigt jedoch immer auf die gleiche Stelle und ich verstehe nicht warum...
Wenn cur immer auf die gleiche Stelle zeigt, dann wäre es ja totaler Schwachsinn. Ich habe es so verstanden, dass cur immer auf die aktuelle Position zeigt.
Und wenn ich eben soetwas wie f>>xyz mache, dann muss sich diese Postion doch ändern??? Tut sie aber nicht!
-
ios::cur zeigt auch immer auf die aktuelle Position.
Die Position wird sich bei erfolgreichem Lesen auch erhöhen, wenn du den Shift-Operator nutzt. Wenn du willst, dass er in die nächste Zeile springt, nimmf.ignore(max_wert, '\n');Das dürfte dann in die nächste Zeile springen.
-
Also irgendwie drehen wir uns im Kreis. Anstatt eine Lösung zu finden treten immer mehr neue Probleme auf.
Ich mein die Problemstellung ist doch simpel.
Ich bin an einer Stelle x, will nun die Stelle x+2 überprüfen und zurückspringen zu x und dann ganz normal mit meinem vorhandenen Routine weitermachen.
Das habe ich hier versucht umzusetzen nur leider will das nicht funktionieren, da cur IMMER auf die gleiche Stelle zeigt, obwohl es das eigentlich nicht sollte...
double real, imag; char plus, j, var; int a = 0; int b = 0; for(int p=0; p<7770; p++){ f>>real; // double Zahl wird erfolgreich gelesen f.seekg((ios::cur)+1); // der Zeiger wird +1 genommen var = f.peek(); // es wird das nächste Element gelesen if(var == 'j'){ // es wird kontrolliert ob das Element ein j war f.unget(); // nun soll zurückgesprungen werden an das Ende der ausgelesenen double Zahl f>>plus>>j>>imag; // nun lesen wir den Rest der Zeile aus, beim nächsten Durchlauf soll nun auch die nächste Zahl/Zeile gelesen werden, aber cur zeigt IMMER auf die gleiche Stelle if(plus == '-'){ imag *= -1; } } else{ imag = 0; f.unget(); } complexNumbers[p]=complex<double>(real,imag); }
-
Das ist ja nicht mehr auszuhalten, wie hier der Einäugige mit den Blinden über Farbe diskutiert. Ich erbarme mich heute Abend oder morgen mal. Nur damit wir uns recht verstehen:Du suchst eine Funktion, die aus einem vorgegebenen istream einen std::vector<complex> macht? Die Zahlen können dabei in zwei Formaten vorliegen
a) realteil (plus oder minus) j imaginärteil
b) realteil
und sind jeweils durch Zeilenumbruch getrennt. Soweit richtig? Und was markiert das Ende? Wenn etwas kommt, das nicht diesem Format entspricht?
-
SeppJ schrieb:
Das ist ja nicht mehr auszuhalten, wie hier der Einäugige mit den Blinden über Farbe diskutiert. Ich erbarme mich heute Abend oder morgen mal. Nur damit wir uns recht verstehen:Du suchst eine Funktion, die aus einem vorgegebenen istream einen std::vector<complex> macht? Die Zahlen können dabei in zwei Formaten vorliegen
a) realteil (plus oder minus) j imaginärteil
b) realteil
und sind jeweils durch Zeilenumbruch getrennt. Soweit richtig? Und was markiert das Ende? Wenn etwas kommt, das nicht diesem Format entspricht?Das ist alles soweit korrekt.
Beendet wird das ganze durch "</indep>", das ist die Zeile nach der letzten Zahl. Es liegt jedoch auch die Anzahl der insgesamt auszulesenden Zahlen vor. Letztlich geht es daher nur um die for()-Schleife...
Was anderes kann nicht vorkommen, es liegt entweder eine komplexe oder eine reele Zahl vor!
-
Javun schrieb:
Beendet wird das ganze durch "</indep>", das ist die Zeile nach der letzten Zahl. Es liegt jedoch auch die Anzahl der insgesamt auszulesenden Zahlen vor.
Ahh, ok. Merkwürdiges Format, wo die Anzahl der werte drinsteht, aber das macht die Sache sogar noch einfacher.
Letztlich geht es daher nur um die for()-Schleife...
Bei diesem Monsterthread (und das ist ja schon der 2. zu diesem Thema) habe ich den Eindruck, dass fehlende Abstraktion das Problem ist. Alles hübsch in Unterprobleme eingeteilt würde alles viel einfacher und insgesamt kürzer machen. Ich erinnere mich noch mit Grauen an das Monstrum aus deinem vorherigen Thread.
Was anderes kann nicht vorkommen, es liegt entweder eine komplexe oder eine reele Zahl vor!
Ausgezeichnet. Habe gerade keine Zeit, aber morgen. Sollte schnell gehen und dürfte nicht lang werden.
-
Ersteinmal vielen Dank, dass Du Dir die Mühe machen möchtest. Aber ich würde auch schon gern erfahren, wo denn mein Fehler genau liegt.
Im Großen und Ganzen funktioniert ja soweit alles. Einziges Problem ist momentan die Unterscheidung von reelen und komplexen Zahlen. Ich habe es versucht mit den Tipps der anderen User hier zu lösen, jedoch bin ich hier zu keinem "richtigen" Ergebnis gekommen.
Für einen geübten Programmierer ist der Fehler bestimmt in weniger als einer Minute gefunden, deswegen würde ich mich sehr freuen, wenn mir jmd. evt. Heute noch einen Tipp geben könnte...
double real, imag; char plus, j, var; int a = 0; int b = 0; for(int p=0; p<7770; p++){ f>>real; // double Zahl wird erfolgreich gelesen f.seekg((ios::cur)+1); // der Zeiger wird +1 genommen var = f.peek(); // es wird das nächste Element gelesen if(var == 'j'){ // es wird kontrolliert ob das Element ein j war f.unget(); // nun soll zurückgesprungen werden an das Ende der ausgelesenen double Zahl f>>plus>>j>>imag; // nun lesen wir den Rest der Zeile aus, beim nächsten Durchlauf soll nun auch die nächste Zahl/Zeile gelesen werden, aber cur zeigt IMMER auf die gleiche Stelle if(plus == '-'){ imag *= -1; } } else{ imag = 0; f.unget(); } complexNumbers[p]=complex<double>(real,imag); }
-
Sag mal, das j kannst du genauso am Anfang und nicht mitten im Einzulesenen "String" platzieren.
Dann kannst du gleich zu Anfang sehen, ob du auch eine imaginäre Zahl einliest.Also sähen deine Zahlen so aus:
j-9.35124373769e-017-1.53956708493e-017
Probier mal sowas in der Art:
char j;// Wofür ist das ? int a = 0, b = 0;//Wofür auch immer die da sind ... for(int p=0; p<7770; p++) { double real, imag; char var= f.get(); f>>real; // double Zahl wird gelesen if(var == 'j') f>>imag; //Brauchst du hier überhaupt ein plus Char ? else imag = 0; complexNumbers.at(p)=complex<double>(real,imag); }
-
Hacker schrieb:
Sag mal, das j kannst du genauso am Anfang und nicht mitten im Einzulesenen "String" platzieren.
Dann kannst du gleich zu Anfang sehen, ob du auch eine imaginäre Zahl einliest.Also sähen deine Zahlen so aus:
j-9.35124373769e-017-1.53956708493e-017
Probier mal sowas in der Art:
char j;// Wofür ist das ? int a = 0, b = 0;//Wofür auch immer die da sind ... for(int p=0; p<7770; p++) { double real, imag; char var= f.get(); f>>real; // double Zahl wird gelesen if(var == 'j') f>>imag; //Brauchst du hier überhaupt ein plus Char ? else imag = 0; complexNumbers.at(p)=complex<double>(real,imag); }Leider auch hier immer das gleiche Ergebnis, es wird die gleiche Zeile immer und immer wieder ausgelesen...
-
Hey,
also hör mal auf SeppJ,
ansonsten solange:
A) Du kennst anfang und ende deiner Zahlenspalte
--- Dann kopier die doch in einen seperaten string
Du weißt das deine Spalte vieeeeele Zeilen hat die alle mit \n Enden?
--- Dann nutze Doch folgendes:std::string strTextWoAlleZahlenLiegen; std::vector<std::string> vecVieeeeeleZahlen; //... unsigned int zaehler=0; if(std::string::npos==zaehler=strTextWoAlleZahlenLiegen.find('\n')) { std::cout<<"ERROR"; } else vecVieeeeeleZahlen.push_back(strTextWoAlleZahlenLiegen.substr(zaehler));nun haste dann einen vector voller string's die jeweils eine Zahl beinhalten.
Was musste nun tun?
Die Funktionstd::string::findkennst Du ja mitlerweile, suche also nach einem j
(mit der annahme das das Format kontinuierlich gleich ist)
und schon weisst Du welche Zeile eine Imaginäre und welche Zeile nur einen Realteil enthält.Nun Kannst Du mit dieser Fallunterscheidung die jeweilige Zeile entsprechend Parsen...
sei gegrüßt
-
SeppJ hat völlig recht. Das kann man einfach nicht so weiter laufen lassen. Javun hat ja auch schon fest estellt, dass Ihr Euch hier im Kreis dreht.
Hallo Javun,
ich werde versuchen es Dir zu erklären. Schritt für Schritt und in mehreren Lektionen. Erstmal was grundsätzliches - versuche Dein Problem immer(!) in mehrere Teilprobleme zu zerlegen. Wenn Du also eine komplizierte Datei einlesen willst, so versuche zunächst die einzelnen Elemente - z.B. hier eine komplexe Zahl - für sich zu lesen. Lesen aus einer Datei heißt lesen aus einem std::ifstream und da dies ein std::istream ist, ist das Lesen wie von std::cin. Das macht keinen Unterschied für da Einlesen an sich.
Auch das kann man noch in kleinere Teile zerlegen. In Deinem Fall in vier: den Realteil, den Operator+/-, das 'j' und den Imaginärteil.Ich fange ganz einfach an, mit Dingen, die Du schon kennen solltest, wie ich hier gesehen habe:
// -- Lektion 1 #include <iostream> #include <complex> int main() { using namespace std; cout << "eine imaginaere Zahl bitte: z.B.: -9.351e-017-j1.539e-017 " << endl; double real, imag; char plus, imagChar; while( cin >> real >> plus >> imagChar >> imag ) cout << "gelesen: " << complex< double >( real, plus == '+'? imag: -imag ) << endl; return 0; }einfach die vier genannten Dinge als double bzw. char einlesen und eine komplexe Zahl daraus machen. Ein Test ergibt:
eine imaginaere Zahl bitte: z.B.: -9.351e-017-j1.539e-017 -9.351E-017-j1.539e-017 gelesen: (-9.351e-017,-1.539e-017) 0+j0 gelesen: (0,0) 0**2 gelesen: (0,-2)natürlich ist dem Programm das Zeichen vor dem Realteil egal und beim Operator interessiert nur ob da ein '+' kommt oder was anderes. Das ist noch suboptimal. Aber bevor ich darauf eingehe, kapsele ich diese Funktionalität und zwar mit dem Ziel, so etwas hinschreiben zu können:
complex< double > z; while( cin >> /*mal sehn*/( z ) ) cout << "gelesen: " << z << endl;weil später, da wo das benutzt wird, will ich mich nicht mehr mit dem detailliertem Format herumschlagen, sondern einfach nur eine komplexe Zahle einlesen, so wie ich ein double lese.
(gleich geht's weiter)