Auslesen von komplexen Zahlen aus einer Datei



  • Und wie liest man genau den übernächsten Wert ein?

    Mit peek() lese ich ja immer den nächsten Wert, aber wie komme ich denn zum übernachsten. Konnte auch in der Referenz nichts dazu finden.



  • ...

    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 integer
    

    Und 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  +1
    
    f.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 du

    DeinIfstream.seekg(ios::cur + 1);
    

    schreibst, heißt das, du inkrementierst den get-Zeiger der, bzw. deiner Datei.
    Stattdessen könntest du auch

    DeinIfstream.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, nimm

    f.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);
        }
    

  • Mod

    😮 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!


  • Mod

    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 Funktion

    std::string::find
    

    kennst 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


Anmelden zum Antworten