2011-01-27 6 views

답변

9

ifstream 관점에서 볼 때 줄 번호가 없습니다. 파일을 한 줄씩 읽는다면, 그 파일을 직접 추적하면됩니다.

+0

주 : 다음은 전체 예제 당신이 중 하나에 의해 통과'\ n' 문자의 수를 계산 라인으로 라인 ('표준 : getline') 또는 간단하게 읽을 수 있습니다. –

+0

@Matthieu : 각'\ n'이 플랫폼에서 개행을 의미한다고 가정합니다. – rubenvb

+0

@rubenvb : 텍스트 모드에서'\ n'은 줄 바꿈을 나타내며, 'iostream'은 로케일을 사용하여 그것을 만듭니다 (양쪽 모두의 읽기 쓰기). 물론 바이너리 모드로 읽는다면 변환은 일어나지 않습니다 ... –

4

std::getline을 사용하면 하나씩 차례대로 읽을 수 있습니다. 읽은 행의 수를 나타내는 정수를 유지하십시오 : 0으로 초기화하고 std::getline을 호출 할 때마다 성공하고 증분하십시오.

8

은 다음 std::streambuf에서 파생 된 클래스를 사용할 수 std::getline에 자신을 제한하지 당신이 경우, 어느 현재 행 번호를 추적 유지 :

class CountingStreamBuffer : public std::streambuf { /* see below */ }; 

// open file 
std::ifstream file("somefile.txt"); 

// "pipe" through counting stream buffer 
CountingStreamBuffer cntstreambuf(file.rdbuf()); 
std::istream is(&cntstreambuf); 

// sample usage 
is >> x >> y >> z; 
cout << "At line " << cntstreambuf.lineNumber(); 
std::getline(is, str); 
cout << "At line " << cntstreambuf.lineNumber(); 
여기

이입니다 CountingStreamBuffer의 샘플 구현 :

#include <streambuf> 

class CountingStreamBuffer : public std::streambuf 
{ 
public: 
    // constructor 
    CountingStreamBuffer(std::streambuf* sbuf) : 
     streamBuf_(sbuf), 
     lineNumber_(1), 
     lastLineNumber_(1), 
     column_(0), 
     prevColumn_(static_cast<unsigned int>(-1)), 
     filePos_(0) 
    { 
    } 

    // Get current line number 
    unsigned int  lineNumber() const { return lineNumber_; } 

    // Get line number of previously read character 
    unsigned int  prevLineNumber() const { return lastLineNumber_; } 

    // Get current column 
    unsigned int  column() const { return column_; } 

    // Get file position 
    std::streamsize  filepos() const { return filePos_; } 

protected: 
    CountingStreamBuffer(const CountingStreamBuffer&); 
    CountingStreamBuffer& operator=(const CountingStreamBuffer&); 

    // extract next character from stream w/o advancing read pos 
    std::streambuf::int_type underflow() 
    { 
     return streamBuf_->sgetc(); 
    } 

    // extract next character from stream 
    std::streambuf::int_type uflow() 
    { 
     int_type rc = streamBuf_->sbumpc(); 

     lastLineNumber_ = lineNumber_; 
     if (traits_type::eq_int_type(rc, traits_type::to_int_type('\n'))) 
     { 
      ++lineNumber_; 
      prevColumn_ = column_ + 1; 
      column_ = static_cast<unsigned int>(-1); 
     } 

     ++column_; 
     ++filePos_; 
     return rc; 
    } 

    // put back last character 
    std::streambuf::int_type pbackfail(std::streambuf::int_type c) 
    { 
     if (traits_type::eq_int_type(c, traits_type::to_int_type('\n'))) 
     { 
      --lineNumber_; 
      lastLineNumber_ = lineNumber_; 
      column_ = prevColumn_; 
      prevColumn_ = 0; 
     } 

     --column_; 
     --filePos_; 

     if (c != traits_type::eof()) 
      return streamBuf_->sputbackc(traits_type::to_char_type(c)); 
     else 
      return streamBuf_->sungetc(); 
    } 

    // change position by offset, according to way and mode 
    virtual std::ios::pos_type seekoff(std::ios::off_type pos, 
            std::ios_base::seekdir dir, 
            std::ios_base::openmode mode) 
    { 
     if (dir == std::ios_base::beg 
     && pos == static_cast<std::ios::off_type>(0)) 
     { 
      lastLineNumber_ = 1; 
      lineNumber_ = 1; 
      column_ = 0; 
      prevColumn_ = static_cast<unsigned int>(-1); 
      filePos_ = 0; 

      return streamBuf_->pubseekoff(pos, dir, mode); 
     } 
     else 
      return std::streambuf::seekoff(pos, dir, mode); 
    } 

    // change to specified position, according to mode 
    virtual std::ios::pos_type seekpos(std::ios::pos_type pos, 
            std::ios_base::openmode mode) 
    { 
     if (pos == static_cast<std::ios::pos_type>(0)) 
     { 
      lastLineNumber_ = 1; 
      lineNumber_ = 1; 
      column_ = 0; 
      prevColumn_ = static_cast<unsigned int>(-1); 
      filePos_ = 0; 

      return streamBuf_->pubseekpos(pos, mode); 
     } 
     else 
      return std::streambuf::seekpos(pos, mode); 
    } 


private: 
    std::streambuf*  streamBuf_;  // hosted streambuffer 
    unsigned int  lineNumber_; // current line number 
    unsigned int  lastLineNumber_;// line number of last read character 
    unsigned int  column_;  // current column 
    unsigned int  prevColumn_; // previous column 
    std::streamsize  filePos_;  // file position 
}; 
0

비효율적하지만 죽은 간단한 방법이다 스트림을 받으면 스트림의 시작 부분에서 현재 위치까지 새 줄 문자를 계산하는 함수가 있습니다. 여러 스트림 위치에 대한 행을 알고 싶다면 매번 스트림 시작부터 계산을 시작하여 여러 번 호출해야하므로 비효율적입니다. 내가 작업하고있는 일부 코드에서 유효하지 않은 입력이있는 경우 줄 번호를 알고 싶습니다.이 경우 가져 오기가 즉시 중단됩니다. 이 함수는 일단 비효율이 실제로 문제가되지 않으면 호출됩니다. 방법의

int getCurrentLine(std::istream& is) 
{ 
    int lineCount = 1; 
    is.clear();  // need to clear error bits otherwise tellg returns -1. 
    auto originalPos = is.tellg(); 
    if (originalPos < 0) 
     return -1; 
    is.seekg(0); 
    char c; 
    while ((is.tellg() < originalPos) && is.get(c)) 
    { 
     if (c == '\n') ++lineCount; 
    } 
    return lineCount; 
} 

장점 중 하나는 변경이 스트림이 구성되어 장소에 필요하지 않습니다이다

, 당신은 당신이 그것을 필요로하는 함수를 호출 할 필요가 : 여기

은 이러한 작업을 수행하기위한 내 코드입니다 .

#include <iostream> 
#include <sstream> 


int getCurrentLine(std::istream& is) 
{ 
    int lineCount = 1; 
    is.clear();  // need to clear error bits otherwise tellg returns -1. 
    auto originalPos = is.tellg(); 
    if (originalPos < 0) 
     return -1; 
    is.seekg(0); 
    char c; 
    while ((is.tellg() < originalPos) && is.get(c)) 
    { 
     if (c == '\n') ++lineCount; 
    } 
    return lineCount; 
} 

void ReadDataFromStream(std::istream& s) 
{ 
    double x, y, z; 
    while (!s.fail() && !s.eof()) 
    { 
     s >> x >> y >> z; 
     if (!s.fail()) 
      std::cout << x << "," << y << "," << z << "\n"; 
    } 

    if (s.fail()) 
     std::cout << "Error at line: " << getCurrentLine(s) << "\n"; 
    else 
     std::cout << "Read until line: " << getCurrentLine(s) << "\n"; 
} 

int main(int argc, char* argv[]) 
{ 
    std::stringstream s; 
    s << "0.0 0.0 0.0\n"; 
    s << "1.0 ??? 0.0\n"; 
    s << "0.0 1.0 0.0\n"; 
    ReadDataFromStream(s); 

    std::stringstream s2; 
    s2 << "0.0 0.0 0.0\n"; 
    s2 << "1.0 0.0 0.0\n"; 
    s2 << "0.0 1.0 0.0"; 
    ReadDataFromStream(s2); 

    return 0; 
} 
관련 문제