将矢量转换为矢量

问题描述:

我从二进制文件中获取数据,从文件中读取数据并写入一个无符号字符的向量。我无法编辑它,因为我正在使用外部库。将矢量<unsigned char>转换为矢量<unsigned short>

但我是从文件中读取的数据是一个16位的图像,我想要把数据的无符号短

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

Rgds。

+2

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

+0

也许这篇文章可以给你一些想法做什么: http://*.com/q/41462433/3990012 – serup 2017-02-03 07:48:11

一个通用的方法(不防弹):

#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

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

假设在你的文件中的二进制数据是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.

声明的多个条目的数量:我没有编译器现在:

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

如果你只是想从转换另一种类型则使用标准构造函数。只要迭代器的值类型自动转换为目标向量值类型,编译器就会在两种类型之间进行自动转换。只需使用标准构造函数

#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