2012-06-10 19 views
5

Ho un programma in C++ che ha bisogno di restituire una linea che una parola specifica appare in Per esempio, se il mio file è simile al seguente:leggere da un punto specifico in un file C++

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

ed io bisogno di stampare la linea che ha "con". Tutto il programma ottiene è l'offset dall'inizio del file (in questo caso 24, poiché "con" è di 24 caratteri dall'inizio del file).

Come si stampa l'intera linea "la luna con il", con solo l'offset?

Grazie mille!

+0

Cercare l'offset che si ha e quindi andare indietro finché non si trova una nuova riga. Quindi leggi fino alla prossima nuova riga. Facile. –

+0

C'è un modo per leggere un'intera riga in una sola volta, senza leggere da una nuova riga alla successiva? – Meir

+1

Leggere un'intera riga contemporaneamente * è * la lettura da una nuova riga alla successiva. –

risposta

2

Una buona soluzione è leggere il file dall'inizio fino alla posizione desiderata (risposta di @Chet Simpson). Se si desidera l'ottimizzazione (ad esempio file di grandi dimensioni, posizione da qualche parte nel mezzo, linee tipiche piuttosto brevi), è possibile leggere il file all'indietro. Tuttavia, questo funziona solo con i file aperti in modalità binaria (qualsiasi file su piattaforme unix-like, aprire il file con il parametro ios_base::binary su Windows).

L'algoritmo è la seguente:

  • Torna pochi byte nel file
  • Leggere i pochi byte
  • Se c'è una linea di fine lì, il resto è facile
  • in caso contrario, ripetere

Codice (testato su 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: Sulle piattaforme Windows-like, in cui end-of-line è caratterizzata da \r\n, poiché è necessario utilizzare la modalità binaria, stringa di output conterrà il carattere aggiuntivo \r (a meno che non c'è fine-di- linea alla fine del file), che puoi buttare via.

0

ci sono funzioni di ogni dell'operazione fopen - aprire il file

fseek - cercare il file nella offset desiderato

fread - leggere la quantità di byte che si desidera

fclose - chiudi il file

3

Puoi farlo leggendo ogni riga individualmente e registrando la posizione del file prima e dopo la lettura. Quindi è solo un semplice controllo per vedere se l'offset della parola rientra nei limiti di quella linea.

Problemi correlati