2012-06-10 13 views
5

ich ein Programm in C++, die eine Zeile zurückgeben muss, dass ein bestimmtes Wort in erscheint Zum Beispiel sieht, wenn meine Datei wie folgt:Lesen von einer bestimmten Stelle in einer Datei C++

the cow jumped over 
the moon with the 
green cheese in his mouth 

und ich muss die Zeile mit "mit" drucken. Das ganze Programm erhält den Offset vom Anfang der Datei (in diesem Fall 24, da "mit" 24 Zeichen vom Anfang der Datei entfernt ist).

Wie drucke ich die ganze Zeile "der Mond mit der", nur mit dem Offset?

Vielen Dank!

+0

Suchen Sie nach dem Offset, den Sie haben, und gehen Sie dann rückwärts, bis Sie einen Zeilenumbruch finden. Dann lies bis zum nächsten Zeilenumbruch. Einfach. –

+0

Gibt es eine Möglichkeit, eine ganze Zeile auf einmal zu lesen, ohne von einer Zeile zur nächsten zu lesen? – Meir

+1

Eine ganze Zeile gleichzeitig lesen * liest * von einem Zeilenende zum nächsten. –

Antwort

2

Eine gute Lösung ist das Lesen der Datei von Anfang bis zur gewünschten Position (Antwort von @Chet Simpson). Wenn Sie eine Optimierung wünschen (z. B. sehr große Datei, irgendwo in der Mitte, typische Zeilen eher kurz), können Sie die Datei rückwärts lesen. Dies funktioniert jedoch nur mit Dateien, die im Binärmodus geöffnet werden (jede Datei auf Unix-ähnlichen Plattformen; öffnen Sie die Datei mit dem Parameter ios_base::binary unter Windows).

Der Algorithmus geht wie folgt:

  • Zurück ein paar Bytes in der Datei
  • Lesen Sie den wenige Bytes
  • Wenn es eine ist End-of-line gibt, ist der Rest einfach
  • Ansonsten wiederholen

-Code (getestet unter Windows):

std::string GetSurroundingLine(std::istream& f, std::istream::pos_type start_pos) 
{ 
    std::istream::pos_type prev_pos = start_pos; 
    std::istream::pos_type pos; 
    char buffer[40]; // typical line length, so typical iteration count is 1 
    std::istream::pos_type size = sizeof(buffer); 

    // Look for the beginning of the line that includes the given position 
    while (true) 
    { 
     // Move back 40 bytes from prev_pos 
     if (prev_pos < size) 
      pos = 0; 
     else 
      pos = prev_pos - size; 
     f.seekg(pos); 

     // Read 40 bytes 
     f.read(buffer, prev_pos - pos); 
     if (!f) 
      throw; 

     // Look for a newline byte, which terminates previous line 
     int eol_pos; 
     for (eol_pos = sizeof(buffer) - 1; eol_pos >= 0; --eol_pos) 
      if (buffer[eol_pos] == '\n') 
       break; 

     // If found newline or got to beginning of file - done looking 
     if (eol_pos >= 0 || pos == (std::istream::pos_type)0) 
     { 
      pos += eol_pos + 1; 
      break; 
     } 
    } 

    // Position the read pointer 
    f.seekg(pos); 

    // Read the line 
    std::string s; 
    std::getline(f, s, '\n'); 

    return s; 
} 

Edit: Auf Windows-ähnlichen Plattformen, wo das Ende der Zeile mit \r\n markiert ist, enthält die Ausgabezeichenfolge das zusätzliche Zeichen \r (es sei denn, es gibt kein End-of-Line- Linie am Ende der Datei), die Sie wegwerfen können.

0

Es gibt Funktionen von jedem der Betrieb fopen - öffnen Sie die Datei

fseek - suchen Sie die Datei auf die

fread gewünschte Offset - lesen Sie die Menge an Bytes, die Sie

fclose wollen - Schließen Sie die Datei

3

Sie können dies tun, indem Sie jede Zeile einzeln lesen und die Dateiposition vor und nach dem Lesen aufzeichnen. Dann ist es nur eine einfache Überprüfung, ob der Offset des Wortes innerhalb der Grenzen dieser Linie liegt.

Verwandte Themen