我從二進制文件中獲取數據,從文件中讀取數據並寫入一個無符號字符的向量。我無法編輯它,因爲我正在使用外部庫。將矢量<unsigned char>轉換爲矢量<unsigned short>
但我是從文件中讀取的數據是一個16位的圖像,我想要把數據的無符號短
矢量也許我可以做它一投?
Rgds。
我從二進制文件中獲取數據,從文件中讀取數據並寫入一個無符號字符的向量。我無法編輯它,因爲我正在使用外部庫。將矢量<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