2017-02-24 3 views
1

나는 일반화 된 파서 결합 자 라이브러리를 작성 중이다. 이 라이브러리 (호출하면) 문자열을 입력 받아 파서 않은 경우 목록이 비어있는 ParseResult가C++ : std :: cin의 여러 복사본을 사용하고 있습니까?

template <typename A> using ParseResult = std::pair<A, std::string> 입니다 출력, 같은 ParseResults의 목록을 반환 많은 작은 함수 객체라는 파서를 포함 의미 일치하지 않으면 단일 결과를 포함하고 여러 (모호한) f}으로 일치하는 특정 파서가 더 많은 결과를 리턴 할 수 있습니다.

그러나 지금은 많은 문자열 복사가 진행되고 있음을 의미합니다. 또한 처음에는 마지막으로 생성 된 파서를 문자열로 호출해야하므로 std::cin (또는 파일의 coompete 내용)이 모두 문자열로 복사됩니다.

파서가 현재 문자열 앞의 첫 번째 문자 만보고 있기 때문에 더 나은 아이디어 인 것 같습니다. 표준 입력에서 현재 위치를 추적하는 것입니다. 흐름. 그리고 이것은 정확하게 std::istream이 무엇을 믿습니다. 그러나, istreams는 복사 할 수 없습니다. 내 문제는 어떻게 해결 될 수 있습니까? 원본이 가리키는 곳을지나 몇 문자를 가리키는 istream 사본을 반환하는 방법이 있습니까? 아니면이 문제를 해결할 수있는 또 다른, 깨끗한 방법이 있습니까?

+3

C++의 참조가 무엇인지 알고 있습니까? – PiotrNycz

답변

1

질문은 다음과 같이 바꿔 쓸 수 있습니다. 과도한 복사를 피하고 입력 스트리밍을 허용하는 방식으로 입력의 해석되지 않은 부분을 어떻게 나타 냅니까?

가장 유연한 방법은 iterator로 표현하는 것입니다. 파서가 역 추적을 수행하는 경우 ForwardIterator이어야하며, 그렇지 않으면 InputIterator이면 충분합니다. 즉 을 std::cin 또는 std::ifstream 초 이상 사용하거나 메모리 내에있는 std::strings 또는 char 어레이를 구문 분석 할 수 있습니다. 역 추적을 통한 스트리밍은 좀 더 복잡하므로 InputIterator을 과 같이 ForwardIterator으로 변환하거나 역 추적해야 할 때 std::ifstream을 직접 래핑하고 반복 코드를 으로 작성하는 버퍼링 반복기 어댑터를 작성해야합니다.

또 다른 옵션으로는 복사하지 않고 분석하기 쉬운 인터페이스가있는 C++ 17의 std::string_view을 사용하는 것입니다. 이렇게해도 스트리밍은 해결되지 않지만 전체 파일을 먼저 읽어야합니다.

+0

이 위대한 답변에 감사드립니다! 추가 연구에 따르면'.seekg()'는 stdin에서 제대로 작동하지 않는다는 것을 의미합니다. 즉, 모든 것을 메모리로 읽어들이는 것 (그리고 나서'std :: istringstream' 또는'std :: string_view'를 사용하는 것이 가장 좋습니다. 잘 했어. – Qqwy

관련 문제