2013-12-15 1 views
4

각각의 문자를 읽고 콘솔로 출력하기 위해 outer while 루프가 있다고 가정 해 보겠습니다. 또한 단어가 발견되면 플래그를 지정하고 peek 메서드를 사용하여 단어의 첫 번째 인스턴스를 찾을 수 있습니다. 앞으로 여러 장소를 들여다 볼 수있는 방법이 있습니까? 예를 들어, 내가 "월급 날"이라는 단어를 찾고 있다면. 이 문자열을 입력하고 문자열을 검색 할 수 있지만 이진 모드에서 파일을 읽고 싶어하고 외부 루프의 값을 제거하지 않으려 고합니다. 만약 내가 read 메소드로 내부 루프를 가지고 있다면, 그 값들은 외부 루프를 통해 표시되지 않습니다. 당신은 IStream을 내 주위를 뛰어 seekg 방법을 사용할 수 있습니다peek() 여러 지역 정보

감사

int main() 

ifstream strm; 
char *chr = new char; 

strm.open("mytext.txt",ios::out | ios::binary); 

while (strm.read(chr,1) 
{ 
    if (strm.peek() == 'p'; 
    { 
    cout << "found a word beginning with 'p'" << endl; 
    //what if I want to read multiple characters ahead. Peek will read only one. 
    } 

} 
+0

왜 동적 할당을 사용하고 있습니까? – Shoe

답변

5

.

파일을 이진 모드로 열면 tellg 메서드를 사용하여 이동할 위치를 표시 할 수 있습니다.

그러나 파일을 텍스트 모드로 열면 newline과 같은 멀티 바이트 문자가 tellg 및 seekg에 의해 계산되는 방식 때문에 오프셋 대신 점프하는 것이 좋습니다 (예 : strm.seekg (offset, strm.cur)). 텍스트 모드에서. 따라서 다음 문자가 "p"가 될 것을 감지하면 다음 n 문자를 읽은 다음 원하는 문자가 아닌 경우 다시 n 문자로 건너 뛸 수 있습니다.

+0

감사합니다. 어느 솔루션이든 여기서 작동하지만 실제로 Seekg를 사용 해본 적이 없으며 이제는 내가 찾은 것, 정확히 내가 필요한 것을 수행합니다. 매우 감사합니다. – domonica

+0

@domonica : 올바른 오류 처리, 공백 변경에 대한 견고성 및 안전한 이스케이프로 적절한 구문 분석을 수행하면 구문 분석 작업이 매우 빠르게 복잡해질 수 있으므로 적절한 파서를 사용하는 것이 일반적으로 더 나은 솔루션이라는 점에 유의하십시오. 심지어 더 좋은 방법은 자신의 형식을 정의하는 대신 xml이나 json 또는 csv와 같은 잘 설정된 형식을 사용하고 잘 디버깅 된 라이브러리를 사용하여 작성하고로드하는 것입니다. –

4

이것을 달성하는 방법은 여러 가지가 있지만, 기존 파일과 "사용자"기능 사이에 하나 이상의 레이어를 추가하기 만하면됩니다. 예를 들어

, 무제한 버퍼링과 렉서 :

class Lexer { 
public: 
    Lexer(std::istream& s): source(s) { this->read(); } 

    explicit operator bool() const { 
     return not queue.empty(); 
    } 

    Lexer& operator>>(std::string& s) { 
     assert(*this and "Test for readiness before calling this method"); 

     s = queue.front(); 
     queue.pop_front(); 

     if (queue.empty()) { this->read(); } 
     return *this; 
    } 

    std::string const* peek(size_t const i) { 
     while (source and queue.size() < i) { this->read(); } 
     return queue.size() >= i ? &queue[i] : nullptr; 
    } 

private: 
    void read() { 
     queue.emplace_back(); 
     if (not (source >> queue.back())) { queue.pop_back(); } 
    } 

    std::istream& source; 
    std::deque<std::string> queue; 
}; // class Lexer 

참고 : 분명히, 당신은 완벽하게 렉서의 버퍼링을 제한 할 수 있습니다, 또는 주 ...는 등의 말보다 다른 것을, 버퍼 만들기 사용자 정의 클래스의 장점은 입니다.의 의미를 지정하십시오!