copy of an array into a vector not happening as expected - c++

I am trying to copy an array to a vector.
int A[1000]; //This array is filled by some function
vector<int> vec;
//some position from which I want to write the contents of the array into vector
int x = some_position;
vec.resize(sizeof(A)+x);
vec.insert(vec.begin()+x, A, A+sizeof(A));
The problem is that every fourth element is not copied correctly. The rest of the elements are copied correctly. i.e vec[x+3] != A[x+3]
for x=0,1,2,3....

First off, you need to check your understanding of sizeof. It returns the number of bytes needed for A as a whole, not the number of items in A, for that you would need sizeof(A)/sizeof(*A).
int A[1000];
vector<int> vec;
int x = 5;
vec.resize(x + sizeof(A) / sizeof(*A));
vec.insert(vec.begin()+x, A, A + sizeof(A) / sizeof(*A));
It's also worth noting that 'insert' may not be what you want. If your objective is to treat the vector like an array and overwrite a 1000 element long section of the vector, then you should use std::copy instead. Insert will resize the array even more, so if the resize will make the vector 1005 elements long, and them you start inserting at position 5, then the final vector will be 2005 elements long, with the contents of A going from 5 - 1004.
You could instead replace the insert line with this:
std::copy(A, A + sizeof(A) / sizeof(*A), vec.begin() + x);
This would overwrite the contents of the vector starting at position 5 and leave the vector sized at 1005.

The better way to copy array to vector:
vec.resize(1000+some_position);//if needed
std::copy(A,A+1000,vec.begin()+some_position);

It seems you believe sizeof() gives number of elements
e.g.
vec.resize(sizeof(A)+x);
but it doesn't. it gives the number of bytes.
the correct resizing should be something along the lines of
vec.resize(sizeof(A)/sizeof(int)+x);
of that follows that
vec.insert(vec.begin()+x, A, A+sizeof(A)/sizeof(int));
although I agree with Sergey that copy() is the better (more elegant) way to do it.

Your use of sizeof is wrong. sizeof is a very primitive operator,
which returns the number of bytes in the shallow image of the object
or type. This is totally useless except for very low level programming.
If you need to deal with C style arrays, there functions std::begin()
and std::end() in C++11; in earlier versions of C++, we just wrote
them ourselves. (I usually also wrote a size() function, which
basically returned the number of elements.) And std::vector works in
number of elements, not number of bytes. So your last two lines of code
should be:
vec.resize( x );
vec.insert( vec.end(), std::begin( A ), std::end( A ) );
At least, that's what I think you're trying to do, based on the
comments: create an std::vector<int> with x elements initialized to
0, followed by the contents of A.

Replace sizeof(A) with sizeof(A) / sizeof(A[0]) and it will work.
And as #Sergey pointed out, vec.resize(); in unnecessary in this case as insert() also resizes the vector.

don't copy an array into a vector. Use C++ to avoid that altogether. Instead of
void fill_array(int*, size_t);
int A[1000];
fill_array(A,1000);
std::vector<int> vec;
my_copy(vec,A);
simply do
std::vector<int> vec;
vec.resize(1000); // or whatever
fill_array(vec.data(),vec.size()); // std::vector::data() is C++11
In C++ (also pre C++11) you would actually do this more like this:
template<typename iterator> fill_data(iterator begin, iterator end);
std::vector<int> vec;
vec.resize(n); // make space (otherwise fill_data cannot fill in anything)
fill_data(vec.begin(), vec.end());
then your fill_data is generic enough to be re-used for any type of container.

Related

Is it possible to initialize a vector of strings from an array? If so, how?

So for example, on GeeksForGeeks.org, contributing user "Kartik" offers the following example for initializing a vector of integers:
// CPP program to initialize a vector from
// an array.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int arr[] = { 10, 20, 30 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vect(arr, arr + n);
for (int x : vect)
cout << x << " ";
return 0;
}
If I understand what I'm reading correctly, sizeof(arr) is some number (which I assume is the length of the array arr; i.e. 3, please correct me if I'm wrong) divided by sizeof(arr[0]) (which I assume to be 1) -- basically just being a roundabout way of saying 3/1 = 3.
At this point, vector<int> vect(arr, arr + n) appears to be a vector of size 3, with all values initialized to arr + n (which I'm assuming is a way of saying "use the 3 items from arr to instantiate; again, please correct me if I'm wrong).
Through whatever sorcery, the output is 10 20 30.
Now, regardless of whether or not any of my above rambling is coherent or even remotely correct, my main question is this: can the same technique be used to instantiate some example vector<string> stringVector such that it would iterate through strings designated by some example string stringArray[] = { "wordA", "wordB", "wordC" }? Because, as I understand it, strings have no numeric values, so I imagine it would be difficult to just say vector<string> stringVector(stringArray, stringArray + n) without encountering some funky junk. So if it is possible, how would one go about doing it?
As a rider, why, or in what type of instance, would anyone want to do this for a vector? Does instantiating it from an array (which as I understand it has constant size) defeat the purpose of the vector?
Just as a disclaimer, I'm new to C++ and a lot of the object-oriented syntax involving stuff like std::vector<_Ty, _Alloc>::vector...etc. makes absolutely no sense to me, so I may need that explained in an answer.
To whoever reads this, thank you for taking the time. I hope you're having a good day!
Clarifications:
sizeof(arr): returns the size in bytes of the array, which is 12 because it has 3 ints, and each int in most implementations has a size of 4 bytes, so 3 bytes x 4 = 12 bytes.
sizeof(arr[0]): returns the size in bytes of the first element of the array, which is 4 because it is an int array.
vector<int> vect(arr, arr + n): the vector class has multiple constructors. Here we are not using the constructor you are thinking of. We are using a constructor that takes begin and end iterators for a range of elements, making a copy of those elements. Pointers can be used as iterators, where in this case arr is the begin iterator and arr + n is the end iterator.
Note: int* + int returns int*.
Note: We should also consider that the "end" of an array is a pointer to the next space after the last item in the array, and the constructor will copy all the items except the item past the end.
Answer:
Yes, remember that here, the constructor is taking iterators, not any item of the array, so we can do it easily like this with little changes:
#include <bits/stdc++.h>
using namespace std;
int main()
{
// changed int to string and the array values
string arr[] = { "one", "two", "three" };
int n = sizeof(arr) / sizeof(arr[0]);
// changed int to string
vector<string> vect(arr, arr + n);
// changed int to string
for (string x : vect)
cout << x << " ";
return 0;
}
sizeof(arr)
sizeof gets the size of an object in bytes. The size of an object is the total number of bytes required by the object. Note that I'm using "object" in the C++ context, not the OOP context (an instance of a class).
The size of an object of a given type is always the same. A std::string containing "a" is the same size as a string containing the unabridged text of War and Peace. Any object that appears to have a variable size really contains a reference to variable length data stored elsewhere. In the case of std::string at its most basic, it is a pointer to a dynamically allocated array and an integer keeping track of how much of the dynamically allocated array is actually in use by the string. std::vector is similar, typically it's a pointer to the start of its data, a pointer to the end of its data, and a pointer to the first empty position in the data. No matter how big the vector is, sizeof(vector) will return the size of the pointers, any other book-keeping variables in the vector implementation, and any padding needed to guarantee correct memory alignment.
This means every item in an array is always the same size and thus the same distance from one another.
Through whatever sorcery...
The above means that the total size of the array divided by the size of one element in the array, sizeof(arr) / sizeof(arr[0]), will always provide the number of elements in the array. It doesn't matter what the array contains, numerical or otherwise. There are of course prettier ways like
template <class T, size_t N>
size_t getsize (const T (&array)[N])
{
return N;
}
and later
size_t n = getsize(arr);
As a rider, why, or in what type of instance, would anyone want to do this for a vector?
In the old days one could not directly construct a vector pre-loaded with data. No one wants to write some arbitrary number of lines of push_back to pound all the values in manually, It's boring as hell, a programmer almost always has better things to do, and the odds of injecting an error are too high. But you could nicely and easily format an array and feed the array into the vector, if you needed a vector at all. A lot of the time you could live off the array by itself because the contents were unchanging or at worst would only be shuffled around.
But if the number of contents could change, it could be time for a vector. If you're going to add items and you don't know the upper limit, it's time for vector. If you're calling into an API that requires a vector, it's time for a vector.
I can't speak for everybody, but I'm going to assume that like me a lot of people would have loved to have that easy-peasy array-style initialization for vectors, lists, maps, and the rest of the usual gang.
We were forced to write programs that generated the appropriate code to fill up the vector or define an array and copy the array into the vector much like the above example.
In C++11 we got our wish with std::initialzer_list and a variety of new initialization options1 that allowed
vector<string> vect{"abc","def","ghi"};
eliminating most cases where you would find yourself copying an array into a library container. And the masses rejoiced.
This coincided with a number of tools like std::size, std::begin and std::end to make converting an array into a vector a cakewalk. Assuming you don't pass the array into a function first.
1 Unfortunately the list of initialization options can get a lil' bewildering
Yes, you can do so - you just need to define something that the constructor for String will take (which is a 'const char')
const char * arr[] = { "abc","def","ghi" };
int n = sizeof(arr) / sizeof(arr[0]);
vector<string> vect(arr, arr + n);
for (string &x : vect)
cout << x << " ";
What this is effectively doing is creating the vector from two iterators (a pointer is, loosely, an iterator):
https://en.cppreference.com/w/cpp/container/vector/vector
Constructs the container with the contents of the range [first, last).
This constructor has the same effect as vector(static_cast<size_type>(first), static_cast<value_type>(last), a) if InputIt is an integral type.
And as #MartinYork pointed out, it's much more readable to use the C++ syntax:
const char * arr[] = { "abc","def","ghi" };
vector<string> vect(std::begin(arr), std::end(arr));
So if it is possible, how would one go about doing it?
Simply use vector constructor number 5, which accepts iterators to start and end of range
Constructs the container with the contents of the range [first,
last).
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::string arr[] = { "wordA", "wordB", "wordC" };
std::vector<std::string> v {std::begin(arr), std::end(arr)};
for (auto& str : v)
std::cout << str << "\n";
return 0;
}
Here's how you'd do it. Note that it's a tad awkward to get the length of the array, but that's just because arrays don't carry that information around with them (use a vector!).
#include<string>
#include<vector>
#include<iterator>
#include<iostream>
int main()
{
std::string arr[] = {"abc", "def", "ghi"};
std::vector<std::string> tmp;
std::copy(arr, arr + sizeof(arr)/sizeof(arr[0]), std::back_inserter(tmp));
for(auto str : tmp) {
std::cout<<str<<"\n";
}
}
Update: Yes good point about using std::begin and std::end for the array.

How to assign C++ array with a pointer to first element?

I apologize that I am still very new with C++, so your patience is appreciated.
As part of an un-alterable constraint in my project, I must convert a Vector to an Array. In my searching for a solution I have repeatedly come across answers like this one.
As I understand, that solution gives you a pointer to the first element in the vector -- and since a vector is guaranteed to be contiguous in memory you can then set the array to point to that memory location (or something like that).
My question is, though, how exactly do I do that in C++? The answer seems to suggest it is trivial, but I can't find how to do it.
I have tried things of this nature but they don't work....
std::vector<double> v;
double* a = &v[0];
double myArray[100];
&myArray[0] = a;
Given a pointer to the first element in a sequence, how do I then use that pointer to 'populate' an array? Furthermore, do I have to worry about size differences/going out of bounds issues? Also, could I do this in reverse as well ('populate' a vector with a pointer to the first element of an array)?
You cannot insert elements into a vector using a pointer to the vector's first element. A vector uniquely owns its contents, and therefore must allow you to change its size only using its own interface, otherwise it cannot keep track of how many elements it owns.
You can do this:
std::vector<double> v(N); // N elements initialized to 0.0
double* a = v.data();
do_something(a, N); // tell the function to write N elements
If you have a vector and an array as for example
std::vector<double> v;
double myArray[100];
and want that the array would contain elements of the vector you should copy elements of the vector in the array as for example
std::copy( v.begin(),
std::next( v.begin(), std::min<std::vector<double>::size_type>( v.size(), 100 ) ),
std::begin( myArray ) );
or
std::copy( v.begin(),
v.begin() + std::min<std::vector<double>::size_type>( v.size(), 100 ),
myArray );
If you want that the vector would have elements of the array then you can write
v.assign( std::begin( myArray ), std::end( myArray ) );
or
v.insert( v.end(), std::begin( myArray ), std::end( myArray ) );
Or you can declare the vector and initialize it at the same time (after defining and filling the array)
std::vector<double> v( std::begin( myArray ), std::end( myArray ) );
that is the same as
std::vector<double> v( myArray, myArray + 100 );
It depends on the lifetime of the array and vector, as well as how you plan on using the array.
If you merely want to access the vector as an array, you can do it as simply as you have written:
double* myArray = &v[0];
Or, using C++11 or higher:
double* myArray = v.data();
Then you may access the vector as if it were an array using myArray. Effectively, this just aliases the vector's internal memory to a separate pointer. The subscript operator [] works on pointers, thus allowing myArray to more or less function as an array.
However, there are two gotchas with this:
the above will only work correctly if the lifetime of myArray is fully encompassed by that of v. If the vector goes out of scope, is cleared, or is resized, myArray is invalidated. You are merely pointing to the internal memory of v, so anything that changes that memory will break myArray.
As written in your example, this operation is not valid to begin with, as your vector v has no size. Give it a size before taking its address.
If you want to copy the contents of the vector to an array, you can use memcpy().
double* myArray = new double[v.size()];
memcpy( myArray, &v[0], v.size() * sizeof( double ) );
This will allocate the number of elements currently in v in myArray and populate that memory with the data contained in v. However, any changes to myArray will be independent of v. You merely copied the vector into the array.
There are several other ways to accomplish the second option.
It is possible to make an array reference:
vector<double> v(100); // must size the vector first, or at least add 1 element and call reserve(100)
double (&myArray)[100] = reinterpret_cast<double(&)[100]>(v[0]);
Then you can use myArray[0], myArray[1] etc. However if you insert into the vector then myArray becomes invalid (and it is not possible to 'move' it).
Although this is possible it would be very unusual so you should not do it in any real code.

Why is std::copy throwing an error vector iterator + offset out of range and not able to copy

I was trying to copy an int array into std::vector of int and I am seeing some unusual behavior. So I have an array as defined as below.
int myarray[10] = {1,2,3,4,5,6,7,8,9,10};
and I tried copying the above array into vector using different methods as below which throws errors.
1) Using reserve
std::vector<int> vec1;
vec1.reserve(10);
std::copy(myarray, myarray+10,vec1.begin() );
This throws an error in VS 2013 which is :-
vector iterator + offset out of range
2) By defining size
std::vector<int> vec2(10);
std::copy(myarray, myarray+10,vec2.begin() );
Which successfully copies the array into the vector.
3) Just declaring the vector .
std::vector<int> vec3;
std::copy(myarray, myarray+10,vec3.begin() );
Which also throws an error
vector iterator + offset out of range
Also searching over the internet I found that std::back_inserter could be used, but I don't know what difference it would make.
Can some please explain the difference between all the three methods and whats going wrong in 1 and 3.
Instead of vec1.reserve(10); use vec1.resize(10);
std::vector::reserve would increase the capacity of vector but the size remains same. It requests that the vector capacity be at least enough to contain n elements.
On the other hand, std::vector::resize resizes the container so that it contains n elements
As #Mohit Jain's answer shows resize would help. But that initializes the vector which is not needed. For integers it might not be a problem but for big objects it's definitely a performance overhead.
reserve can help here if you use std::copy as shown below.
std::vector<int> vec2(10);
vec2.reserve(10);
std::copy(myarray, myarray+10, std::back_inserter(vec));
BTW, you can also copy the contents of the array to the vector during the construction of the vector itself.
std::vector<int> vec2 ( myarray, myarray + 10);

Is there any built in method in c++ to findout length of an array?

like array.length in java is there any built in method in c++ to findout size of an array?
I know about length(). but it only works for strings only ...
And i tried this ...
int a[10];
a[0]=1;
a[1]=2;
print(sizeof(a)/size(a[0]))
but it gives output as 10 but is there a way getting only 2 as output
If you're using C++, don't use arrays, use std::vector instead (especially if you need the count of currently held items, not the container's capacity). Then you can write:
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
printf("%d\n", vec.size());
int a[10];
declares an array of 10 ints; sure, you're only initialising the first two, but the other 8 are still there, they're just (probably) filled with junk at the moment.
To do what you want, you should use a std::vector instead. You can then do this:
std::vector<int> a;
a.push_back(1);
a.push_back(2);
std::cout << a.size() << std::endl; // prints 2
Arrays in C/C++ do not store their lengths in memory, so it is impossible to find their size purely given a pointer to an array. Any code using arrays in those languages relies on a constant known size, or a separate variable being passed around that specifies their size.
In an array of 10 ints, when it is declared, memory is allocated for 10 int values. even if you initialize just two, the rest of it contains some junk values and the memory remains allocated.
If you want the used size, your best bet is to use std::vector.
if you want to know the number of elements in an array you can do this
int array[3] = {0, 1, 2};
int arraylength = sizeof(array)/ sizeof(*array);
Sure. It's name is vector::size. It doesn't apply to C-style arrays, only to std::vector. Note that Java's Array class is also not a C-style array.

How to copy a range of data from char array into a vector?

I've read file contents into a char array, and then read some data of it into a vector.
How can i copy a range of the char array into the vector? both vector and char array is the same type (unsigned char).
Current code goes something like this:
int p = 0;
for(...){
short len = (arr[p+1] << 8) | arr[p+0];
p+=2;
...
for(...len...){
vec.push_back(arr[p]);
p++;
}
}
I would like to improve this by dropping the loop with push_back, How?
Appending something to a vector can be done using the insert() member function:
vec.insert(vec.end(), arr, arr+len);
Of course, there's also an assign(), which is probably closer to what you want to do:
vec.assign(arr, arr+len);
However, reading your question I wondered why you would first read into a C array just to copy its content into a vector, when you could read into a vector right away. A std::vector<> is required to keep its data in one contiguous block of memory, and you can access this block by taking the address of its first element. Just make sure you have enough room in the vector:
std::size_t my_read(char* buffer, std::size_t buffer_size);
vec.resize( appropriate_length );
vec.resize( my_read_func(&vec[0], vec.size()) );
Instead of &vec[0] you could also get the address of the first element by &*vec.begin(). However, note that with either method you absolutely must make sure there's at least one element in the vector. None of the two methods are required to check for it (although your implementation might do so for debug builds), and both will invoke the dreaded Undefined Behavior when you fail on this.