2012-03-26 5 views
1

Ich versuche, Daten aus einer Textdatei in C++ einzugeben. Die Textdatei ist in diesem Format:Gibt es trotzdem einen Reset der Datei in den Ausgangszustand?

4 15 
3 516 
25 52 etc. 

Jede Zeile enthält zwei ganze Zahlen. Ich weiß nicht, die Anzahl der Zeilen in der Datei, damit ich genug Speicher binden kann und das ist, was ich in so eine Art und Weise gekommen, um das zu lösen:

ifstream filein; 
filein.open("text.txt",ios::in); 
int count=0; 

while (!filein.eof()) 
    { 
     count++; 
     filein>>temporary; 
    } 
count=count/2; // This is the number of lines in the text file. 

Mein Problem ist, dass ich nicht herausfinden können, ein Weg

FileIn

in den Anfangszustand (zum beggining der Datei, so kann ich tatsächlich eingegebenen Daten), die nicht das Schließen des Eingangsstroms und die Öffnung wieder zurückzustellen. Gibt es einen anderen Weg, das zu tun?

+1

Sie sollten seekg verwenden können (wenn ich mich richtig erinnere). Haben Sie darüber nachgedacht, nur einen Vektor zu verwenden? – Corbin

+0

Wenn Sie unter "Daten eingeben" das Zurückschreiben von Werten in diese Datei verstehen, benötigen Sie einen Ausgabestream, der trotzdem mit den entsprechenden Berechtigungen geöffnet wird. – AJG85

+0

@Corbin - 'seekg' wird' eofbit' nicht löschen. –

Antwort

5

Anstatt die Frage zu beantworten, würden wir Sie bitten, werde ich die Frage, die Sie nicht fragen beantworten, nämlich:

F: Wie kann ich mich in allen Zeilen der Datei, wenn ich don lesen Ich weiß nicht, wie viele Zeilen es gibt.

A: Verwenden Sie einen std::vector<>.

Wenn Sie alle Zahlen lesen in möchten, unabhängig von Paarung:

// all code fragments untested. typos are possible 
int i; 
std::vector<int> all_of_the_values; 
while(filein >> i) 
    all_of_the_values.push_back(i); 

Wenn Sie in alle Zahlen lesen möchten, abwechselnd Zahlen in unterschiedlichen Datenstrukturen setzen:

int i, j; 
std::vector<int> first_values; 
std::vector<int> second_values; 
while(filein >> i >> j) { 
    first_values.push_back(i); 
    second_values.push_back(j); 

Wenn Sie alle Zahlen zu lesen, in, sie in irgendeiner Art von Datenstruktur zu speichern:

int i, j; 
struct S {int i; int j;}; 
std::vector<S> values; 
while(filein >> i >> j) { 
    S s = {i, j}; 
    values.push_back(s); 
} 

Schließlich möchten, wenn Sie die Datei eine Zeile zu einem Zeitpunkt zu lesen, aus jeder Zeile die ersten beiden Zahlen zu halten, den Rest jeder Zeile zu verwerfen, und ihnen eine benutzerdefinierte Datenstruktur zu speichern:

std::vector<MyClass> v; 
std::string sline; 
while(std::getline(filein, sline)) { 
    std::istringstream isline(sline); 
    int i, j; 
    if(isline >> i >> j) { 
    values.push_back(MyClass(i, j)); 
    } 
} 


Beiseitig: Verwenden Sie niemals eof() oder good() in einer Schleife bedingt. Dies erzeugt fast immer fehlerhaften Code, wie es in Ihrem Fall wäre. Stattdessen rufen Sie lieber die Eingabefunktion in der Bedingung auf, wie ich oben getan habe.

+0

Da ich mit Vektoren nicht so erfahren bin, wie kann ich die gelesenen Werte in Arrays übertragen, ohne die Größe dieser Arrays zu kennen? Sollte ich nicht in der Lage sein, Speicher für diese Arrays zuerst zu binden? –

+0

Sie können die Werte nicht in Arrays übergeben, wenn Sie zuerst die Größe des Arrays kennen. Wenn Sie ein neuer C++ - Programmierer sind, ** verwenden Sie keine Arrays **. Arrays sollten nur für erweiterte Verwendung in Betracht gezogen werden. Beginnen Sie mit dem viel sichereren und einfacher zu verwendenden 'std :: vector'. –

+0

Vielen Dank für die Tipps und für die Hilfe. Ich werde sofort in Vektoren schauen. –

2

Die Funktion ist: filein.seekg (0, ios::beg);

hier ein Reference

ist Sie auch filein.clear() zum Zurücksetzen des eof Bit in der Datei verwenden sollten, wenn Sie es auf diese Weise tun.

Und natürlich, wenn Sie die beste Methode für das, was Sie letztlich versuchen, wollen, Robs Antwort ist viel besser, wenn auch mehr beteiligt.

+0

Aber das lässt das 'eofbit' Set. Wenn er 'seekg' verwendet, sollte er wahrscheinlich zuerst' ios :: clear() 'aufrufen. Auch wird Ihr Code (und sein) "count" einmal zu viel erhöhen, wenn die Datei mit Leerzeichen endet. –

+0

@ Robo: Meine Antwort korrigiert. –

+0

@ Robᵩ Gerade aufgefallen, wenn Sie filein >> temporary >> wc aufrufen; dann wird es kein Problem sein, die Datei zu lesen, was das Lesen zusätzlicher weißer Linien betrifft. –

2

Ich denke, @ Robᵩ hat ziemlich genau die richtige Idee - anstatt durch alle Daten zu lesen, nur um die Anzahl der Zeilen zu zählen, dann durchlesen die ganze Datei erneut, um die Daten tatsächlich zu lesen, mit etwas wie std::vector (oder std::deque), die beim Lesen der Daten nach Bedarf erweitert wird.

In einem typischen Fall werden die beiden Zahlen in einer Zeile jedoch miteinander verknüpft, und Sie möchten sie normalerweise so speichern, dass diese Verknüpfung direkt angezeigt wird. Zum Beispiel könnten sie die X- und Y-Koordinaten der Punkte sein, in welchem ​​Fall Sie lesen Punkte wollen:

class point { 
    int x, y; 
}; 

std::istream &operator>>(std::istream &is, point &p) { 
    return is >> p.x >> p.y; 
} 

std::ifstream in("myfile.txt"); 

// create the vector from the data in the file: 
std::vector<point> points((std::istream_iterator<point>(in)), 
          std::istream_iterator<point>()); 

Auf eine etwas andere Note: auch wenn Sie sich entscheiden, eine explizite Schleife verwenden möchten, bitte Verwenden Sie nicht while (!whatever.eof()), um es zu tun - das ist ziemlich garantiert zu scheitern. Sie wollen, dass das Lesen von Daten erfolgreich zu überprüfen, also (zum Beispiel) über die point Klasse verwenden, können Sie so etwas wie verwenden:

point p; 
while (infile >> p) 
    points.push_back(p); 
+1

+1 für das korrekte Idiom, um die Daten zu lesen - 'std :: iStream_iterator <>' und benutzerdefinierter 'operator >>'. –