I have following in my code:
static unsigned char* table;
...
table = something here;
Now I have to assign this table to variable of type std::vector<unsigned char> and I am unable to do so. I am doing:
unsigned char* buffer = (unsigned char*) table;
std::vector<unsigned char>::size_type size = strlen((const char*)buffer);
std::vector<unsigned char>static rawTable(buffer, buffer + size);
for(ByteBuffer::iterator it=rawTable.begin();it!=rawTable.end();++it)
std::cout << "Raw Table: "<<*it<< std::endl;
I am able to compile the code, but no value is there inside rawTable. Please help!
I have verified that variable table has value. I appreciate any help on this. Thanks.
strlen gives you the length of a string, not the size of an arbitrary memory region. If your table has a '\0' anywhere inside, strlen will find it and stop counting.
Also, by making rawTable a static variable, it will not update its value if buffer or size ever change. static variables are constructed only once.
Also, if this is supposed to be a table of numeric data, you should cast to a numeric non-character type. Otherwise cout may interpret it as ASCII codes.
You have a pointer of type unsigned char* pointing to an array.
Then you want to push every element of the array into a std::vector<unsigned char>, right?
If so, the key is to know the size of the array. You need to know the size beforehand. There's no way to determine the size of the array in the general case with some keyword or function if all that is visible to you is a pointer of type unsigned char*. You need to pass that information along with the pointer somehow.
In the case when the pointer of type unsigned char* points to an array of characters which is null-terminated (e.g. {'f', 'o', 'o', '\0'}), then you can use the C-string function strlen to count the number of characters in the array using only the pointer. However if the array is not null-terminated this will result in undefined behaviour.
When you have the size it's a simple matter to populate the std::vector with the arrays elements:
std::vector<unsigned char> v(arr, arr + size); // arr = pointer to array.
This is why you should use the containers in the standard library instead of raw arrays, as these containers internally keep track of the size and you can always access it with the size() function.
For constant size arrays use std::array. Example:
std::array<unsigned char, 3> arr{'f', 'o', 'o'}; // arr.size() == 3
// Print its contents.
for (auto c : arr) {
std::cout << c << std::endl;
}
Related
I'm trying to fill a vector with integers from an array I have but when I check the contents of the vector all the values are zero.
I'm using vector.push_back() to try and fill the vector so it will be in the same order as the array as I needed it ordered in a specific way.
unsigned char* buffer = new unsigned char[size];
std::vector<unsigned char> *data = new std::vector<unsigned char>(size);
fread(buffer, sizeof(unsigned char), size, f);
for(int transfer = 0; transfer < size; transfer += 1){
std::cout << buffer[transfer];
data->push_back(buffer[transfer]);
std::cout << int(data->at(transfer));
}
fclose(f);
When I print the output I can see that the values aren't zero when they're coming from the buffer array but they are when I read from the data vector. Here is some example output φ0$0.
std::vector has a constructor for this purpose:
std::vector<unsigned char> data(buffer, buffer + size);
newing a vector almost always should be avoided.
Live
The overload of the constructor of std::vector that you are using takes the number of elements to initialize the vector with and initializes these (to 0 in this case).
After the line
std::vector<unsigned char> *data = new std::vector<unsigned char>(size);
*data therefore contains already size elements set to zero.
Then with data->push_back(...) you are adding additional elements after these size elements. You are not overwriting the previous ones.
Either use
std::vector<unsigned char> *data = new std::vector<unsigned char>();
to default-initialize an empty vector, or use
(*data)[transfer] = ...
to set the elements at the given location.
Furthermore your program has undefined behavior if the fread reads less than size bytes into the array. You need to check the number of bytes read from its return value and you are not allowed to access any elements beyond that in data, because you never initialized it.
You can initialize it to zero with:
unsigned char* buffer = new unsigned char[size]{};
If you want to write C++, don't use C library functions like fread, use the facilities provided by <fstream>, i.e. std::ifstream and std::ofstream instead.
Similarly there is no need for dynamic memory allocation here. Declare variables with automatic storage:
unsigned char buffer[size]{};
std::vector<unsigned char> data(size);
and the rest of the syntax also simplifies:
data[transfer] = ...
Finally, as mentioned in the other answer, there is a constructor for std::vector that will perform the whole copy loop for you. Note however that my argument about undefined behavior still applies when using that.
Defining data as automatic array as in
unsigned char buffer[size]{};
works only if size is a compile-time constant. If it is not, then this part of my advice does not apply. However there is no real need to use arrays at all in any case. You can initialize a std::vector of proper size (compile-time constant or not) and provide that as buffer via its .data() method, which returns a pointer to the underlying (continuous) storage:
std::vector<unsigned char> buffer(size);
fread(buffer.data(), sizeof(unsigned char), buffer.size(), f);
You don't need a separate buffer or any dynamic allocation in your code. You can create the std::vector with the desired size and then read from the file directly into the vector. The std::vector::data member function returns a pointer to the vector's underlying array that you can pass to the fread() function
std::vector<unsigned char> vec(size);
fread(vec.data(), sizeof(unsigned char), size, f);
Ideally you'll also check the return value from fread() to know how many elements were read.
I want to convert size_t to vector of unsigned chars. This vector is defined as 4 bytes.
Could anybody suggest a suitable way to do that?
Once you've reconciled yourself to the fact that your std::vector is probably going to have to be bigger than that - it will need to have sizeof(size_t) elements - one well-defined way is to access the data buffer of such an appropriately sized vector and use ::memcpy:
size_t bar = 0; /*initialise this else the copy code behaviour is undefined*/
std::vector<uint8_t> foo(sizeof(bar)); /*space must be allocated at this point*/
::memcpy(foo.data(), &bar, sizeof(bar));
There is an overload of data() that returns a non-const pointer to the data buffer. I'm exploiting this here. Accessing the data buffer in this way is unusual but other tricks (using unions etc.) often lead to code whose behaviour is, in general, undefined.
By "convert", I'll assume you mean "copy", since vector will allocate and own its memory. You can't just give it a pointer and expect to use your own memory.
An efficient way to do so which avoids two-stage construction (that causes initialization of the array with zero) is to do this:
auto ptr = reinterpret_cast<uint8_t*>(&the_size);
vector<uint8_t> vec{ptr, ptr + sizeof(size_t)};
Note that sizeof(size_t) is not required to be 4. So you shouldn't write your code assuming that it is.
You could write a generic converter using std::bitset
template <typename T>
std::vector<unsigned char> Type_To_Bit_Vector(T type, char true_char, char false_char){
//convert type to bitset
std::bitset<sizeof(type)*8> bset(type);
//convert bitset to vector<unsigned char>
std::vector<char> vec;
for(int i = 0 ; i < bset.size() ; i++){
if (bset[i]){
vec.push_back(true_char);
}else{
vec.push_back(false_char);
}
}
return vec;
}
You could then get a desired vector representation like so:
auto vec = Type_To_Bit_Vector(size_t(123),'1','0');
I have two vectors.
One is
std::vector<unsigned char> one_v;
and the other is
std::vector<bool> outputValuesInBits;
I pushed values to both one_v and outputValuesInBits.
Both vectors have two bytes.
one_v[0] and [1] are filled with data which would be 2 bytes.
outputValuesInBits[0] to [15] are filled with data which would be 2 bytes.
Now, I would like to copy(memcpy) data to char array.
I can successfully copy data from one_v vector as following.
unsigned char* output = new unsigned char[one_v.size()]();
memcpy(&output, one_v.data(), 2);
But I cannot copy data from outputValuesInBits.
If I do as follow,
unsigned char* output = new unsigned char[outputValuesInBits.size()/8+1]();
memcpy(&output, outputValuesInBits.data(), 2);
It gives me an error
error: invalid use of void expression
memcpy(&output, outputValuesInBits.data(), 2);
Can anyone please tell me how I can copy the bool vector to char array?
Thank you in advance!
I'm afraid you cannot in a portable way. Cplusplus page on vector says: The specialization has the same member functions as the unspecialized vector, except data, emplace, and emplace_back, that are not present in this specialization. That means that data in not defined what explains the error when you try to use it.
If portability is not an option, there will be no solution because The storage is not necessarily an array of bool values, but the library implementation may optimize storage so that each value is stored in a single bit. (emphasize mine). My understanding of the may is that you cannot even be sure that the 16 boolean are stored in 2 consecutive bytes: the implementation must only provide you a way to use them (almost) as if they were stored in 16 different booleans.
If you can forget partability, you will have to find the source for you current implementation to know where and how the byte array is stored... but it is not that easy...
std::vector<bool> doesn't have a data member function
At least in g++ compiler you can use the _M_p member of the vector::iterator, which is the pointer to the data.
Example:
std::vector<bool> vBool(16, false);
vBool[0] = true;
vBool[2] = true;
vBool[13] = true;
std::vector<unsigned char> vChar(2);
unsigned short *ptrUS = reinterpret_cast<unsigned short *>( &(vChar[0]) );
*ptrUS = *reinterpret_cast<unsigned short *>(vBool.begin()._M_p);
std::cout << (unsigned int)vChar[0] << " " << (unsigned int)vChar[1] << "\n";
gives in output '5 32', which corresponds to the numbers with 1st and 3rd bit (5) and with the 6th bit (32).
How would I get the size of this:
char* stringit[4] = {"H","H","UH","i"};
I tried:
sizeof(stringit);
and it outputed 32.
I tried to make a for loop:
for (i= 0; check != 0; ++i){
check = stringit[i];
}
and that did not work either. Is there anyway to do this without having to pass in the size of the array?
make it a NULL terminated array of pointers
char* stringit[] = {"H","H","UH","i" , NULL };
Then just count the pointers until you find a null pointer.
The right way to get the number of elements of an array is to divide its actual size (in bytes) by the size of an element:
sizeof(stringit) / sizeof(stringit[0])
But unless you have extremely specific requirements, you should use a standard container like vector (and string too instead of char* C strings):
std::vector<std::string> stringit = {"H","H","UH","i"};
std::cout << stringit.size();
As #KonradRudolph mentioned, vector is nice if your number of elements is variable. If the number of elements is known at compile time and will never change you could instead use array:
std::array<std::string, 4> stringit = {"H","H","UH","i"};
std::cout << stringit.size();
As long as you have access to the array itself, i.e. as long as you have not converted it to a pointer, the number of elements can be calculated as
sizeof stringit / sizeof *stringit
which will evaluate to a compile-time constant 4 in your case.
Whether this is what you are looking for or not depends on some additional details, which you did not provide in your question. You mention "having to pass in the size of the array". Pass where?
32 is the right size. The variable stringit is an array of 4 char pointers, and each pointer is 8 bytes.
What is it that you are trying to do?
char* stringit[4] = {"H","H","UH","i"};
is an array of 4 strings, i.e. array of 4 char* (pointer holds an address, 64bit address = 8 bytes). That's why you get 32. To retrieve the number of elements, you could do:
int count = sizeof(stringit) / sizeof(stringit[0]);
which will give you 4. But note that this kind of approach isn't much flexible and I'd rather use some STL container, i.e. std::vector<char*> or yet even better, get rid of C-style strings as well and use std::vector<std::string> instead.
The sizeof works for static arrays. It's giving you the size of the construct in bytes.
If you want length, do sizeof(stringit) / sizeof(char*).
For a more flexible solution that is probably the ``Right way" to do things in C++ (which works for dynamic arrays), just use std::array, or std::vector/std::list, if you need more dynamic allocation.
http://www.cplusplus.com/reference/array/array/
http://www.cplusplus.com/reference/vector/vector/
http://www.cplusplus.com/reference/list/list/
With this construct, you can simply use a size() member.
Remember to pass by reference when necessary to avoid needless copying.
I'm reading multiple reports from a HID device into an unsigned char, then trying to copy the data to a std::vector. I'm also writing the data out to a file for hex analysis, whose content appears to be correct when I view it. However, the std::vector doesn't appear to contain the correct data when I dump it to the console.
This is the code:
typedef vector<unsigned char> buffer_t;
buffer_t sendCommand (hid_device *devh, const unsigned char cmd[], int reports) {
unsigned char outbuf[0x40];
buffer_t retbuf(0x40 * reports);
hid_write(devh, cmd, 0x41);
int i;
FILE *file = fopen("test.out", "w+b");
while (i++ < reports) {
hid_read(devh, outbuf, 0x40);
fwrite(outbuf, 1, sizeof(outbuf), file);
retbuf.push_back(*outbuf);
}
fclose(file);
cout << &retbuf[0];
return retbuf;
}
I have a feeling I'm way off the mark here; I'm fairly new to C/C++, and I've been stuck with this for a while now. Can anyone tell me what I'm doing wrong, or point me in a better direction?
You want to add multiple unsigned char objects to your vector, but push_back only adds one.
So, replace retbuf.push_back(*outbuf); with either:
for (size_t i = 0; i < sizeof(outbuf); ++i) {
retbuf.push_back(outbuf[i]);
}
or
std::copy(outbuf, outbuf+sizeof(outbuf), std::back_inserter(retbuf));
or
retbuf.insert(retbuf.end(), outbuf, outbuf+sizeof(outbuf));
which all do the same thing.
You create your vector with a certain size:
buffer_t retbuf(0x40 * reports);
but push_back increases the size of the vector by adding an element at the end. You should create it empty:
buffer_t retbuf;
Optionally, you could arrange for the vector to have enough space allocated, ready for the elements you're going to add:
retbuf.reserve(0x40 * reports);
This is purely a performance issue, but sometimes it's a significant issue for large vectors, or vectors of types that (unlike unsigned char) are expensive to copy/move when the vector runs out of internal space and has to allocate more.
A note on style: you repeat the literal value 0x40 a few times, and also use sizeof(outbuf). It's often best to define a constant, and use the name throughout:
const int report_size = 0x40;
This is partly in case the number changes in future, but also it's about the readability of your code -- if someone sees 0x40 they may or may not immediately understand why that is the correct value. If someone sees report_size then they don't know what value that actually is until they look it up, but they do know why you're using that value.
The problem is in this line: buffer_t retbuf(0x40 * reports); It means that you create vector with 0x40 * reports elements filled with default value for unsigned char (zero). Then push_back() just adds new elements to the end of vector and doesn't affect existing elements.
You need to rewrite it this way:
buffer_t retbuf; // Empty vector
retbuf.reserve(0x40 * reports); // Preallocate memory for known element count
This way push_back() will work as expected and add elements to empty vector from beginning.
And of course you shall push_back() all elements of outbuf, not only first one (*outbuf).
To push back multiple values use std::vector's function assign. For example:
std::vector<char>vec1;
char array[3] = {'a', 'b', 'c'};
vec1.assign(array, array+3);
I am currently working on a project were I had to do this.
Your vector is of a type unsigned char, which means every element of it is of this type. Your outbuf is an array of unsigned chars.
The push_back() only appends one item to the end of the vector, so push_back(*outbuf) will only add the first element of the outbuf to the vector, not all of them.
To put all the data into the vector, you will need to push_back them one-by-one, or use std::copy.
Note that since outbuf is a char array, then *outbuf will be the first element of the char array because of the array/pointer duality.
I think you probably wanted to do:
typedef vector<string> buffer_t; // alternatively vector<unsigned char*>
...
retbuf.push_back(outbuf);
...
Or
typedef vector<unsigned char> buffer_t;
...
for (size_t i = 0; i < sizeof(outbuf); i++)
retbuf.push_back(outbuf);
...