Reputation: 45
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.
Upvotes: 1
Views: 5111
Reputation: 22152
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);
Upvotes: 3
Reputation: 7374
std::vector
has a constructor for this purpose:
std::vector<unsigned char> data(buffer, buffer + size);
new
ing a vector almost always should be avoided.
Upvotes: 5
Reputation: 18652
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.
Upvotes: 2