2011-03-24 2 views
3

영혼과 매우 비슷한 질문이 있습니다. here. 불행히도 그 질문은 많은 반응을 촉발하지 못했습니다. 나는 대체적인 방법이 제안 될 수 있기를 희망하면서 좀 더 구체적인 질문을 할 것이라고 생각했습니다.작은 컨테이너로 반복하는 방법 (즉, 스트라이드! = 1)

std::cin (tar --to-command=./myprog)에 이진 파일을 쓰고 있습니다. 바이너리 파일은 실수로 플로트 집합이므로 데이터를 std::vector<float> (이상적으로는 C++ 방식)에 넣으려고합니다.

내가 생성 할 수 있습니다 내가 지금 std::transformfloat로 변환 (A char[2]을 수행하는 기능을 아마도하는 std::vector<float>에 내 std::vector<char> 변환 할 std::vector<char> 아주 멋지게

#include <fstream> 
#include <iostream> 
#include <iterator> 
#include <algorithm> 
#include <vector> 

int 
main (int ac, char **av) 
{ 
    std::istream& input = std::cin; 
    std::vector<char> buffer; 
    std::copy( 
     std::istreambuf_iterator<char>(input), 
      std::istreambuf_iterator<char>(), 
      std::back_inserter(buffer)); // copies all data into buffer 
} 
(감사 this answer까지) , 말하십시오). 그러나 내 std::vector<float>std::vector<char>의 절반만큼의 요소를 갖기 때문에 고군분투하고 있습니다. 2의 보폭로 반복 할 수 있다면 나는 괜찮을 것이라고 생각하지만, 이전 질문에서 나는 그렇게 할 수 없다고 (적어도 우아하게는) 할 수없는 것처럼 보인다.

+1

왜'char'에서 읽습니까? 왜'std :: string'이 아닌가? 당신이 무엇을 입력하고 싶은지, 그리고 무엇을하고 싶은지 불분명합니다. – GManNickG

+0

@Gman, std :: vector 바이너리 파일을 cin으로 입력하여 끝내고 싶습니다. 라이브러리 함수를 사용하여 std :: vector를 디코딩 할 수 있습니다. 찌르는 소리를 통해 진행하는 것이 더 쉽다면 멋지다. (나에게 cin으로 그걸하는 법은 분명하지 않다.) – Tom

+0

@Tom : 이진 파일의 형식은 무엇입니까? – GManNickG

답변

5

2 개의 문자를 읽고 부동으로 변환하는 자체 클래스를 작성합니다. G 맨으로 의견을 바탕으로

struct FloatConverter 
{ 
    // When the FloatConverter object is assigned to a float value 
    // i.e. When put into the vector<float> this method will be called 
    //  to convert the object into a float. 
    operator float() { return 1.0; /* How you convert the 2 chars */ } 

    friend std::istream& operator>>(std::istream& st, FloatConverter& fc) 
    { 
     // You were not exactly clear on what should be read in. 
     // So I went pedantic and made sure we just read 2 characters. 
     fc.data[0] = str.get(); 
     fc.data[1] = str.get(); 
     retun str; 
    } 
    char data[2]; 
}; 

:

struct FloatConverterFromBinary 
{ 
    // When the FloatConverterFromBinary object is assigned to a float value 
    // i.e. When put into the vector<float> this method will be called 
    //  to convert the object into a float. 
    operator float() { return data } 

    friend std::istream& operator>>(std::istream& st, FloatConverterFromBinary& fc) 
    { 
     // Use reinterpret_cast to emphasis how dangerous and unportable this is. 
     str.read(reinterpret_cast<char*>(&fc.data), sizeof(float)); 
     retun str; 
    } 

    float data; 
}; 

을 다음과 같이 사용 :

int main (int ac, char **av) 
{ 
    std::istream& input = std::cin; 
    std::vector<float> buffer; 

    // Note: Because the FloatConverter does not drop whitespace while reading 
    //  You can potentially use std::istream_iterator<> 
    // 
    std::copy( 
      std::istreambuf_iterator<FloatConverter>(input), 
      std::istreambuf_iterator<FloatConverter>(), 
      std::back_inserter(buffer)); 
} 
+0

+1. 그의 질문에 대한 의견을 바탕으로 대답을 완성하기 위해, endianness는 문제가 아니라고 가정하고,'sizeof (float)''char'을''float'에'reinterpret_cast'해야합니다. (만약 그렇다면,'char's를 교환하십시오.) – GManNickG

+0

아, 멋지네요, 제가 찾고있는 것을 정확하게 보입니다 - 그것을 풀어 보려합니다. – Tom

+0

@Martin, 고맙습니다. @Gman, 나는 그만 둡니다. 당신의 상상력에 C와 C++의 끔찍한 mish-mash가 당신을 대체했습니다 :) – Tom

0

가장 좋은 대답은 원하는 방식으로 파일을 구문 분석하는 자체 반복기 쌍을 작성하는 것입니다. std::vector<char>std::vector<float>으로 변경하고 동일한 streambuf 반복자를 사용할 수 있습니다. 입력 값의 범위가 하나 이상의 공백 인 경우입니다.

0

사용 부스트 범위 어댑터 :

boost::copy(istream_range(input)|stride(2),back_inserter(buffer)); 

사용자가 작성해야 할 수도 있습니다 나만의 istreambuf_iterator h는 trivial입니다.