将矢量转换为矢量
我从二进制文件中获取数据,从文件中读取数据并写入一个无符号字符的向量。我无法编辑它,因为我正在使用外部库。将矢量<unsigned char>转换为矢量<unsigned short>
但我是从文件中读取的数据是一个16位的图像,我想要把数据的无符号短
矢量也许我可以做它一投?
Rgds。
一个通用的方法(不防弹):
#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;
}
非常好。一个小小的批评是,你的代码仅限于随机访问容器,因为for循环中的语句“i + = 2”。如果将其更改为“std :: advance(i,2)”,则它将适用于所有容器(并且对于随机访问迭代器将继续保持恒定时间)。 – 2009-12-14 07:05:36
@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简单的数据向量。
我不知道他是否希望他的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()]));
不需要做演员。向量有一个需要两个迭代器的构造函数。只要迭代器的值类型可转换为目标容器的值类型,编译器就会执行正确的操作。 – 2009-12-14 00:42:42
@Martin York:除了他不想将'char's转换为'short's,他希望他们重新解释为短裤。 – rlbond 2009-12-14 01:07:27
@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);
}
+1每个人都必须在没有理由的情况下获得downvote :) – AraK 2009-12-14 02:25:09
所以,你要'[A,B,C,d]'变成'[BA,DC]'? – strager 2009-12-13 23:37:15
也许这篇文章可以给你一些想法做什么: http://stackoverflow.com/q/41462433/3990012 – serup 2017-02-03 07:48:11