2017-01-05 2 views
0
istream& operator>>(istream& s, vector<Order>& ord) { 

    string c{}; 
    bool got_customer = false; 
    Customer temp_customer{}; 
    vector<Purchase>vec_purchase{}; 
    while (s >> c) { 
     cout << "Erstes Wort der Zeile: "<<c << endl; 

     if (!got_customer) { //c[0] == '#' 
      c.erase(c.begin()); //löscht erstes Element vom string 
      int k_nummer{}; 
      string k_vname{}; 
      string k_nname{}; 
      string k_plz{}; 
      string k_stadt{}; 
      k_nummer = stoi(c); //string to int 
      s >> k_vname >> k_nname >> k_plz>>k_stadt; 
      k_vname += " " + k_nname; 
      temp_customer = Customer(k_nummer, k_vname, k_plz, k_stadt); 
      got_customer = true; 
     } else { 
      string p_name{}; 
      double p_preis{}; 
      int p_menge{}; 
      p_name = c; 
      s >> p_preis>>p_menge; 
      cout << p_name << " " << p_preis << " " << p_menge << endl; 
      vec_purchase.push_back(Purchase{p_name, p_preis, p_menge}); 
     } 

     cout<<s.peek()<<endl; 
     if (s.peek() == '#') { 
      ord.push_back(Order{temp_customer, vec_purchase}); 
      temp_customer = Customer{}; 
      vec_purchase.clear(); 
      got_customer = false; 
     } 
    } 
} 

Dies ist die txt-Datei:C++ lesen TXT-Datei, und kopieren Sie in zwei Klassen istream :: peek()

#725454 Schenker Rudolf DE-30159 Hannover 
Shirt 135.95 1 
Tie 89.59 1 
#987654 Orbison Roy US-TN37075 Hendersonville 
Mug 1.49 3 
T-Shirt 14.90 1 
#123456 Petty Tom US-FL32641 Gainesville 
Flashlight 12.95 2 
#246802 Hite Bob US-CA90291 Venice 
CannedBeans 0.89 10 
CannedTomatoes 1.79 6 
#246802 Hite Bob US-CA90291 Venice 
CanOpener 0.48 1 
Spoon 1.49 4 
Needle 0.05 100 

Die Linien mit '#' beginnen, sind Kunden Objekte. Die anderen Zeilen sind Kaufobjekte.

Ich versuche einen Blick in den kommenden Char zu werfen, aber ich bekomme immer wieder den gleichen Char. In diesem Fall erhalte ich immer '13' als Ausgabe von s.peek().

€ dit: Danke @Mark Ransom. Hier ist der Arbeitscode, wenn jemand das gleiche Problem hat. :)

istream& operator>>(istream& s, vector<Order>& ord) { 
    string c{}; 
    bool got_customer = false; 
    Customer temp_customer{}; 
    vector<Purchase>vec_purchase{}; 

    while (s >> c) { 
     if (!got_customer) { 
      c.erase(c.begin()); //deletes first char of string 
      int k_nummer{}; 
      string k_vname{}; 
      string k_nname{}; 
      string k_plz{}; 
      string k_stadt{}; 
      k_nummer = stoi(c); //string to int 
      s >> k_vname >> k_nname >> k_plz>>k_stadt>>ws; 
      k_vname += " " + k_nname; 
      temp_customer = Customer(k_nummer, k_vname, k_plz, k_stadt); 
      got_customer = true; 
     } else { 
      string p_name{}; 
      double p_preis{}; 
      int p_menge{}; 
      p_name = c; 
      s >> p_preis>>p_menge>>ws; 
      vec_purchase.push_back(Purchase{p_name, p_preis, p_menge}); 
     } 

     if (s.peek() == 35||s.peek() == -1) { //35 (in ascii) -> # , -1 -> end of txt file 
      ord.push_back(Order{temp_customer, vec_purchase}); 
      temp_customer = Customer{}; 
      vec_purchase.clear(); 
      got_customer = false; 
     } 
    } 
} 

Antwort

0
s >> p_preis>>p_menge; 

Dies soll mit einem Datensatz, der die letzten beiden Felder auf einer Linie lesen. Unmittelbar danach:

if (s.peek() == '#') { 

Ihre offensichtliche Absicht hier ist das erste Zeichen in der nächsten Zeile zu spähen, um zu überprüfen, ob die nächste Zeile mit # beginnt, oder nicht.

Nun, das wird nicht passieren, wie das ...

Das Problem ist, dass die >> Betreiber nicht das Ende der Zeile Zeichen nach dem verarbeiteten Eingang verbrauchen. peek() Hier erhalten Sie stattdessen den Newline-Charakter. Überraschung.

eine Probeneingangsleitung Gegeben:

Tie 89.59 1 

Der "1" wird durch einen Teil >>p_menge gelesen werden und in menge gespeichert. Das nächste Zeichen nach 1 wird das Newline-Zeichen, und das wird peek() Ihnen gerne geben.

Dies ist völlig der falsche Ansatz für diese Aufgabe. Es gibt nur eine richtige Ansatz Dateien mit Textzeilen zu lesen:

std::getline()

Das ist es. std::getline(), und sonst nichts. Erfahren Sie, wie Sie es verwenden. Ich werde dein Leben viel einfacher machen.

Sie können sicherlich den Operator >> verwenden, um Zeilen aus Ihrer Eingabedatei Stück für Stück zu lesen, aber wie Sie festgestellt haben, ist dies ein fehleranfälliger und fragiler Prozess. Zu viele Minenfelder und Fallgruben.

Nun, natürlich ist es möglich, dies richtig mit dem >>-Operator zu tun, aber es ist nicht immer offensichtlich, wie es geht, und man muss alle Nuancen von formatierten Eingabeoperationen vollständig verstehen.

Es ist bedauerlich, dass zu viele einführende C++ - Bücher auf Anhieb mit Beispielen beginnen, die den Operator >> verwenden, um Eingaben zu lesen, die aus Textzeilen bestehen. Dies verwirrt nur die meisten Anfänger und führt zu Problemen und Missverständnissen wie diesen.

Sie müssen Ihr Programm neu schreiben, um std::getline() zu verwenden, um eine Textzeile gleichzeitig zu lesen. Ende der Geschichte.

Sobald Sie die gesamte Textzeile in einem std::string gelesen haben, und überprüft, ob es mit dem # Zeichen beginnt: Wenn Sie es sich wie dann Sie die ganze Zeile in eine std::istringstream stopfen und dann den Operator >> in einer kontrollierten Umgebung verwenden.

+0

Während ich zustimme, dass "getline" das Leben leichter machen wird, kann ich diese Einstellung nicht als die * einzige * Antwort dulden. –

+0

Hallo vielen Dank fürs Beantworten :) Natürlich weiß ich über std :: getline, aber ich muss mit istream_iterators arbeiten es ist ein Schulprojekt –

+0

'' '' ist kein iStream Iterator. Außerdem, wenn Sie den letzten Absatz in meiner Antwort langsam gelesen haben, habe ich erklärt, wie Sie es richtig verwenden können. –

1

Wenn Sie aus einem Stream lesen, stoppt die Eingabe beim ersten Leerzeichen. Das Zeichen mit einem Dezimalcode von 13 ist die ASCII CR, die am Ende jeder Zeile in Windows kommt; es wird als Leerzeichen betrachtet. Sie müssen das Leerzeichen überspringen, um das nächste signifikante Zeichen zu finden. Sie tun dies mit std::ws.

s >> k_vname >> k_nname >> k_plz >> k_stadt >> std::ws; 

s >> p_preis >> p_menge >> std::ws; 
Verwandte Themen