Получение n-й строки текстового файла в C ++ - PullRequest
7 голосов
/ 01 сентября 2011

Мне нужно прочитать n-ю строку текстового файла (например, textfile.findline(0) найдет первую строку текстового файла, загруженного с ifstream textfile). Это возможно? Мне не нужно помещать содержимое файла в массив / вектор, мне нужно просто присвоить определенную строку текстового файла переменной (в частности, int).

P.S. Я ищу простейшее решение, которое не требует от меня использования какой-либо большой внешней библиотеки (например, Boost) Заранее спасибо.

Ответы [ 5 ]

6 голосов
/ 01 сентября 2011

Как насчет этого?

std::string ReadNthLine(const std::string& filename, int N)
{
   std::ifstream in(filename.c_str());

   std::string s;
   //for performance
   s.reserve(some_reasonable_max_line_length);    

   //skip N lines
   for(int i = 0; i < N; ++i)
       std::getline(in, s);

   std::getline(in,s);
   return s; 
}
3 голосов
/ 01 сентября 2011

Если вы хотите прочитать начало n-й строки, вы можете использовать stdin :: ignore, чтобы пропустить первые n-1 строки, а затем прочитать следующую строку, чтобы присвоить переменной.

template<typename T>
void readNthLine(istream& in, int n, T& value) {
  for (int i = 0; i < n-1; ++i) {
    in.ignore(numeric_limits<streamsize>::max(), '\n');
  }
  in >> value;
}
2 голосов
/ 01 сентября 2011

Решение Армена - правильный ответ, но я подумал, что выброшу альтернативу, основанную на идее кэширования jweyrich. К лучшему или к худшему, это читает весь файл при создании, но сохраняет только позиции новой строки (не сохраняет весь файл, поэтому он хорошо работает с массивными файлами.) Затем вы можете просто вызвать ReadNthLine, и он сразу же перейти к этой строке и прочитать в той строке, которую вы хотите. С другой стороны, это оптимально, только если вы хотите получать только часть строк за раз, а номера строк не известны во время компиляции.

class TextFile {
    std::ifstream file_stream;
    std::vector<std::ifstream::streampos> linebegins;
    TextFile& operator=(TextFile& b) = delete;
public;
    TextFile(std::string filename) 
    :file_stream(filename) 
    {
        //this chunk stolen from Armen's, 
        std::string s;
        //for performance
        s.reserve(some_reasonable_max_line_length); 
        while(file_stream) {
            linebegins.push_back(file_stream.tellg());
            std::getline(file_stream, s);
        }
    }
    TextFile(TextFile&& b) 
    :file_stream(std::move(b.file_stream)), 
    :linebegins(std::move(b.linebegins))
    {}
    TextFile& operator=(TextFile&& b) 
    {
        file_stream = std::move(b.file_stream);
        linebegins = std::move(b.linebegins);
    }
    std::string ReadNthLine(int N) {
        if (N >= linebegins.size()-1)
            throw std::runtime_error("File doesn't have that many lines!");
        std::string s;
        // clear EOF and error flags
        file_stream.clear();
        file_stream.seekg(linebegins[N]);
        std::getline(file_stream, s);
        return s;
    }
};
0 голосов
/ 23 февраля 2015

Вот рабочий и аккуратный пример использования std::getline():

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

const int LENGTH = 50;
const int LINE = 4;

int main() {
std::ifstream f("FILE.txt");
std::string s;

for (int i = 1; i <= LINE; i++)
        std::getline(f, s);

std::cout << s;
return 0;
}
0 голосов
/ 01 сентября 2011

Это, конечно, возможно.Есть (n-1) символов '\ n', предшествующих n-й строке.Читайте строки, пока не дойдете до того, что ищете.Вы можете сделать это на лету, не сохраняя ничего, кроме текущей рассматриваемой строки.

...