2012-06-10 4 views
5

У меня есть программа на C++, которая должна возвращать строку, которая появляется конкретное слово, например, если мой файл выглядит следующим образом:Чтения из определенного места в файл C++

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

и I необходимо распечатать строку с «с». Вся программа получает смещение от начала файла (в этом случае 24, так как «с» составляет 24 символа от начала файла).

Как распечатать всю строку «Луна с помощью», с помощью только смещения?

Большое спасибо!

+0

Ищите подходящее вам смещение, а затем идите назад, пока не найдете новую строку. Затем читайте до следующей новой строки. Легко. –

+0

Есть ли способ прочитать целую строку сразу, не читая от одной новой строки до следующей? – Meir

+1

Чтение всей строки сразу * * считывание с одной новой строки на другую. –

ответ

2

Хорошее решение - это чтение файла с самого начала до желаемой позиции (ответ от @Chet Simpson). Если вы хотите оптимизировать (например, очень большой файл, положение где-то посередине, типичные строки довольно короткие), вы можете прочитать файл назад. Однако это работает только с файлами, открытыми в двоичном режиме (любой файл на unix-подобных платформах, открыть файл с параметром ios_base::binary в Windows).

алгоритм выглядит следующим образом:

  • Вернитесь несколько байт в файле
  • Прочитайте несколько байт
  • Если есть символ конца строки есть, остальное легко
  • в противном случае повторите

код (проверено на 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; 
} 

Редактирование: на платформах под Windows, где конец строки отмечен \r\n, так как вы должны использовать двоичный режим, выходная строка будет содержать дополнительный символ \r (если только нет конца, строка в конце файла), которую вы можете выбросить.

0

Есть функции каждого из операции Еореп - открыть файл

FSEEK - искать файл в требуемое смещение

Fread - читать количество байтов, которые вы хотите

fclose - закрыть файл

3

Вы можете сделать это, прочитав каждую строку индивидуально и записывая положение файла до и после чтения. Тогда это просто проверка, чтобы увидеть, попадает ли смещение слова в пределах этой линии.

#include <iostream> 
#include <fstream> 
#include <string> 

std::string LineFromOffset(
    const std::string &filename, 
    std::istream::pos_type targetIndex) 
{ 
    std::ifstream input(filename); 

    // Save the start position of the first line. Should be zero of course. 
    std::istream::pos_type lineStartIndex = input.tellg(); 

    while(false == input.eof()) 
    { 
     std::string line; 

     std::getline(input, line); 

     // Get the end position of the line 
     std::istream::pos_type lineEndIndex = input.tellg(); 

     // If the index of the word we're looking for in the bounds of the 
     // line, return it 
     if(targetIndex >= lineStartIndex && targetIndex < lineEndIndex) 
     { 
      return line; 
     } 

     // The end of this line is the start of the next one. Set it 
     lineStartIndex = lineEndIndex; 
    } 

    // Need a better way to indicate failure 
    return ""; 
} 

void PrintLineTest() 
{ 
    std::string str = LineFromOffset("test.txt", 24); 

    std::cout << str; 
} 
Смежные вопросы