2009-12-13 214 views
0

我從二進制文件中獲取數據,從文件中讀取數據並寫入一個無符號字符的向量。我無法編輯它,因爲我正在使用外部庫。將矢量<unsigned char>轉換爲矢量<unsigned short>

但我是從文件中讀取的數據是一個16位的圖像,我想要把數據的無符號短

矢量也許我可以做它一投?

Rgds。

+2

所以,你要'[A,B,C,d]'變成'[BA,DC]'? – strager 2009-12-13 23:37:15

+0

也許這篇文章可以給你一些想法做什麼: http://stackoverflow.com/q/41462433/3990012 – serup 2017-02-03 07:48:11

回答

5

一個通用的方法(不防彈):

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

typedef unsigned char u8; 
typedef unsigned short u16; 

u16 combine_two_bytes(u8 a, u8 b) { 
    return a | (b << 8); 
} 

template<typename InIter, typename OutIter, typename InT, typename OutT> 
void combine_pairs(InIter in, InIter in_end, OutIter out, OutT (*func)(InT, InT)) { 
    while(1) { 
     if(in == in_end) { 
      break; 
     } 

     InT &left = *in++; 

     if(in == in_end) { 
      break; 
     } 

     InT &right = *in++; 

     *out++ = func(left, right); 
    } 
} 

int main() { 
    using namespace std; // lazy 

    u8 input[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 
    const size_t in_size = sizeof(input)/sizeof(*input); 
    u16 output[in_size/2]; 

    cout << "Original: "; 
    copy(input, input + in_size, ostream_iterator<int>(cout, " ")); 
    cout << endl; 

    combine_pairs(input, input + in_size, output, combine_two_bytes); 

    cout << "Transformed: "; 
    copy(output, output + in_size/2, ostream_iterator<int>(cout, " ")); 
    cout << endl; 

    return 0; 
} 
+2

非常好。一個小小的批評是,你的代碼僅限於隨機訪問容器,因爲for循環中的語句「i + = 2」。如果將其更改爲「std :: advance(i,2)」,則它將適用於所有容器(並且對於隨機訪問迭代器將繼續保持恆定時間)。 – 2009-12-14 07:05:36

+0

@Klatchko,謝謝你的評論。你是對的,因爲代碼僅限於隨機訪問迭代器。但是,即使使用'std :: advance',我也有一個針對'i + 1'的檢查,這是無法使用所有容器完成的。我重新編寫了代碼,希望它現在可以更好地工作(並且更安全)。 – strager 2009-12-14 09:28:37

3
vector<unsigned char> a = ...; 
vector<unsigned short> b(a.begin(), a.end()); 

但是你想要valarray s簡單的數據向量。

+0

我不知道他是否希望他的n個無符號字符的向量變成一個向量n無符號短褲,或者n/2無符號短褲。看起來他假設無符號short是2個字節,如果他想要n/2個元素的話。但是所陳述的問題還不清楚。 – 2009-12-13 23:50:38

1

假設在你的文件中的二進制數據是little-endian順序,我會變成這樣做的簡單的方法:

vector<unsigned char> a = ...; 

std::vector<unsigned short> b; 
b.reserve(a.size()/sizeof(unsigned short)); 

for(std::vector<unsigned char>::const_iterator i=a.begin(); i!=a.end(); i+=2) 
{ 
    unsigned short shortValue = *(i+1); 
    shortValue <<= 8; 
    shortValue |= *i; 
    b.push_back(shortValue); 
} 

如果您的文件中的數據是big-endian,您將需要用相反的方式組合短值。你也應該警惕在「一」不是2.

0

聲明的多個條目的數量:我沒有編譯器現在:

vector<unsigned char> vec = getVector(); 
vector<unsigned short> sv(reinterpret_cast<unsigned short*>(&vec[0]), 
          reinterpret_cast<unsigned short*>(&vec[vec.size()])); 
+0

不需要做演員。向量有一個需要兩個迭代器的構造函數。只要迭代器的值類型可轉換爲目標容器的值類型,編譯器就會執行正確的操作。 – 2009-12-14 00:42:42

+0

@Martin York:除了他不想將'char's轉換爲'short's,他希望他們重新解釋爲短褲。 – rlbond 2009-12-14 01:07:27

+0

@rlbond:這是有爭議的。這取決於你如何閱讀這個問題。由於在這個問題下的評論,它的方式偏斜了。 – 2009-12-14 02:03:48

5

如果你只是想從轉換另一種類型則使用標準構造函數。只要迭代器的值類型自動轉換爲目標向量值類型,編譯器就會在兩種類型之間進行自動轉換。只需使用標準構造函數

#include <vector> 
#include <algorithm> 
#include <iterator> 

int main() 
{ 
    std::vector<unsigned char>  a; 
    a.push_back((unsigned char)12); 
    a.push_back((unsigned char)13); 
    a.push_back((unsigned char)14); 

    std::vector<unsigned short>  b(a.begin(),a.end()); 

    // Print out the vector 
    std::copy(b.begin(),b.end(),std::ostream_iterator<unsigned short>(std::cout,"\t")); 
} 

> g++ t.cpp 
> ./a.out 
12 13 14 

如果您確實想將兩個字節轉換爲一個字節,那麼需要進行一些工作。但這取決於輸入數據是否與您所在機器的實際相同。如果你知道它是相同的endianess,你只需要投入輸入類型。

#include <vector> 
#include <algorithm> 
#include <iterator> 

int main() 
{ 
    std::vector<unsigned char>  a; 

    // Make sure that the size is correct. 
    // ie. An Odd number indicates that something is not quite correct. 
    // 
    std::vector<unsigned short>  b(static_cast<unsigned short*>(&a[0]), 
             static_cast<unsigned short*>(&a[a.size()])); 

    // Print out the vector 
    std::copy(b.begin(),b.end(),std::ostream_iterator<unsigned short>(std::cout,"\t")); 
} 

或者,如果你確實需要將兩個值組合成一個單一的值,其中字節順序是不一樣的目標架構,你可以寫一個特殊的迭代。事情是這樣的:

#include <Converter.h> 

int main() 
{ 
    std::vector<unsigned char>  a; 

    // Make sure that the size is correct. 
    // ie. An Odd number indicates that something is not quite correct. 
    // 
    std::vector<unsigned short>  b(make_Converter(a.begin()),make_Converter(a.end())); 

    // Print out the vector 
    std::copy(b.begin(),b.end(),std::ostream_iterator<unsigned short>(std::cout,"\t")); 
} 

Converter.h

#include <vector> 
#include <iostream> 
#include <iterator> 

template<typename I> 
struct Converter 
{ 
    I iterator; 

    typedef typename std::input_iterator_tag     iterator_category; 
    typedef typename std::iterator_traits<I>::value_type  value_type; 
    typedef typename std::iterator_traits<I>::difference_type difference_type; 
    typedef typename std::iterator_traits<I>::pointer   pointer; 
    typedef typename std::iterator_traits<I>::reference   reference; 

    Converter(I iter) 
     :iterator(iter) 
    {} 

    Converter& operator++() 
    { 
     iterator++; 
     return *this; 
    } 

    Converter operator++(int) 
    { 
     Converter tmp(*this); 
     this->operator++(); 

     return (tmp); 
    } 

    value_type operator*() 
    { 
     /* 
     * The actual calculation done here will depend on the underlying hardware. 
     */ 
     typename std::iterator_traits<I>::value_type val(*iterator); 
     val << 8; 
     iterator++; 
     val |= (*iterator); 

     return val; 
    } 

    bool operator!=(Converter const& rhs) 
    { 
     return iterator != rhs.iterator; 
    } 
}; 

template<typename I> 
Converter<I> make_Converter(I iter) 
{ 
    return Converter<I>(iter); 
} 
+0

+1每個人都必須在沒有理由的情況下獲得downvote :) – AraK 2009-12-14 02:25:09

相關問題