Getting array from std:vector - c++

What is the easiest way of getting a char array from a vector?
The way I am doing is getting a string initialized using vector begin and end iterators, and then getting .c_str() from this string. Are there other efficient methods?

This was discussed in Scott Meyers' Effective STL, that you can do &vec[0] to get the address of the first element of an std::vector, and since the standard constrains vectors to having contiguous memory, you can do stuff like this.
// some function
void doSomething(char *cptr, int n)
{
}
// in your code
std::vector<char> chars;
if (!chars.empty())
{
doSomething(&chars[0], chars.size());
}
edit: From the comments (thanks casablanca)
be wary about holding pointers to this data, as the pointer can be invalidated if the vector is modified.

std::vector<char> chars;
char* char_arr = chars.data(); // &chars[0]

Related

How to "delete" a part of an array and keep the rest without running through it?

I am trying to implement an algorithm in C++.
In the pseudocode, there is this: w ←w[0..e], where w is an array of characters and e is an integer. Basically I want to keep a part of the array and discard the rest.
Just to make the program working, I have used a for loop, where I scan through the original array up to e and I copy the values in a new array.
char newArray[sizeIAlreadyKnow];
for (int i=0;i<e;i++)
newArray[i] = w[i];
I know this is not efficient; is there a way to avoid iterating through the original array?
Also I am not very familiar with vectors. Do they have a functionality for this?
Thank you in advance
You can use std::string::resize. The basic idea is to use std::string instead of raw arrays of char. Correspondingly, things also become much easier and safer by using std::vector<T> instead of raw arrays of T.
You're right, you should really use vectors !
A lot of documentation is available here, there are also a lot of good tutorials on c++ and std containers (ask google for some of those)
Conserning your question, what vectors can do is (create a copy)
std::vector<char> myArray;
// fill your array, do watherver work you want with it
std::vector<char> newArray(&myArray[start], &myArray[end]);
or in you case (resize)
std::vector<char> myArray;
// fill your array, do watherver work you want with it
myArray.resize(e);
Each and every one of the methods on vector listed in here come with exemple. Reading those might help you a lot with the implementation of your algorithm.
If you ever need, more can be done (like sorting) using the algorithm section on vector (or any other std container)
What you're asking is not possible with C++ builtin arrays or std::vector out of the box.
In the D programming language, it's is possible. If you scroll down to the section labelled Introducing Slices in the link below, you'll find an explanation about how it's possible. In short, it can't be done without garbage collection. You can't free an array in C++ by calling delete on a pointer to the middle of it. So if you tried to slice the middle out of an array, then ditched the old pointer, you would have no way to free the memory, and your program would leak.
http://dlang.org/d-array-article.html
Now, while it's not possible using a language construct, it is possible in a number of other ways.
Of course, there is the obvious, as stated by Amxx: You can simply copy the segment of the array you want into a new array or vector. However, if you're concerned about performance, this is not the best way.The vector constructor Amxx is using will still loop over all the elements and copy them, even though you can't see it.
For a more efficient solution, there are C++ iterators. If you have a function that you want to work on a subset of an array, you can make your function accept iterators instead of an array or a vector.
For example:
int sumElements(vector<int>::iterator first, vector<int>::iterator last)
{
int sum = 0;
for( ; first != last; ++first)
sum += *first;
return sum;
}
vector<int> numbers;
for(int i = 0; i < 100; ++i)
numbers.push_back(i);
int sum = sumElements(numbers.begin() + 10, numbers.begin() + 20);
There are also things like a string_view:
http://en.cppreference.com/w/cpp/experimental/basic_string_view
string_view is a non-owning reference to a slice of a string, but instead of having to deal with a pair of iterators, you can just treat it like the object that it is a slice of. Internally, it just stores pointers to the original string. The caveat though, is that since string_view is a non-owning reference, the original string's lifetime must outlast that of any string_view pointing at it.
The same thing could also be done with a vector, but there is nothing in the standard library for this yet(even string_view is still experimental).
I suppose you could do something like this:
template<class T>
class vector_view
{
vector<T>::iterator first;
vector<T>::iterator last;
public:
vector_view(vector<T>::iterator first, vector<T>::iterator last)
: first(first), last(last) { }
const T& operator[](size_t i) const {
assert(first + i < last);
return *(first + i)
}
size_t size() const {
return last - first;
}
};
vector<int> numbers;
// ... init numbers with 100 numbers
vector_view<int> vv(numbers.begin() + 5, numbers.begin() + 32);
int number = vv[10];
I would probably just stick to vectors and iterators to keep things simple, but there you have it.
edit: similar ideas to the one above are discussed in this proposal for C++ ranges:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4128.html

constructing char*const* from string

I am trying to convert a string to a const*char* in order to be able to call a library function. My code is as follows:
// myVec is simply a vector<string>
vector<string> myVec;
/* stuff added to myVec
* it is a vector of words that were seperated by whitespace
* for example myVec[0]=="Hey"; myVec[1]=="Buck"; myVec[2]=="Rogers"; etc...
*/
char*const* myT = new char*[500]; //I believe my problem stems from here
for(int z=0; z<myVec.size(); z++) {
string temp=myVec[z]+=" ";
myT[z]=temp.c_str();
}
//execv call here
I am constructing this for the second parameter of execv().
Compiler always throws various errors, and when I fix one another one pops up (seems rather circular from the solutions/google-fu I have employed).
The signature of execv expects the array of arguments to point to modifyable C style strings. So contrary to what the other answers suggest, c_str() is not such a good idea.
While not guaranteed in C++03, the fact is that all implementations of std::string that I know of store the data in a contiguous NULL terminated block of memory (this is guaranteed in C++11), so you can use that to your advantage: Create a vector of pointers to modifiable character arrays, initialize the values with the buffers for the strings in your input vector and pass the address of that block of data to execv:
std::vector<char*> args;
args.reserve(myVec.size()+1);
for (std::vector<std::string>::iterator it=myVec.begin(); it != myVec.end(); ++it) {
args.push_back(&((*it)[0]);
}
args.push_back(0); // remember the null termination:
execv("prog", &args[0]);
There are two fundamental problems which need addressing. The
first is a compiler error: the pointers in the array pointed to
by myT are const, so you cannot assign to them. Make myT
char const** myT;. The second problem is that what you are
assigning to them is a pointer into a local variable, which
will be destructed when it goes out of scope, so the pointers
will dangle.
Does the function you are calling really need the extra white
space at the end? (You mentioned execv somewhere, I think.
If that's the function, the extra whitespace will do more harm
than good.) If not, all you have to do is:
std::vector<char const*> myT( myVec.size() + 1 );
std::transform( myVec.begin(), myVec.end(), myT.begin(),
[]( std::string const& arg ) { return arg.c_str(); } );
execv( programPath, &myT[0] );
If you can't count on C++11 (which is still usually the case),
you can probably do something similar with boost::bind;
otherwise, just write the loop yourself.
If you do need to transform the strings in myVec in some way,
the best solution is still to copy them into a second
std::vector<std::string>, with the transformation, and use
this.
(BTW: do you really want to modify the contents of myVec, by
using += on each element in the loop?)

Copying an array into a std::vector

I was searching about this topic and I found many ways to convert an array[] to an std::vector, like using:
assign(a, a + n)
or, direct in the constructor:
std::vector<unsigned char> v ( a, a + n );
Those solve my problem, but I am wondering if it is possible (and correct) to do:
myvet.resize( 10 );
memcpy( &myvet[0], buffer, 10 );
I am wondering this because I have the following code:
IDiskAccess::ERetRead nsDisks::DiskAccess::Read( std::vector< uint8_t >& bufferRead, int32_t totalToRead )
{
uint8_t* data = new uint8_t[totalToRead];
DWORD totalRead;
ReadFile( mhFile, data, totalToRead, &totalRead, NULL );
bufferRead.resize( totalRead );
bufferRead.assign( data, data + totalRead );
delete[] data;
return IDiskAccess::READ_OK;
}
And I would like to do:
IDiskAccess::ERetRead nsDisks::DiskAccess::Read( std::vector< uint8_t >& bufferRead, int32_t totalToRead )
{
bufferRead.resize( totalToRead );
DWORD totalRead;
ReadFile( mhFile, &bufferRead[0], totalToRead, &totalRead, NULL );
bufferRead.resize( totalRead );
return IDiskAccess::READ_OK;
}
(I have removed the error treatment of the ReadFile function to simplify the post).
It is working, but I am affraid that it is not safe. I believe it is ok, as the memory used by the vector is continuous, but I've never seen someone using vectors this way.
Is it correct to use vectors like this? Is there any other better option?
Yes it is safe with std::vector C++ standard guarantees that the elements will be stored at contiguous memory locations.
C++11 Standard:
23.3.6.1 Class templatevector overview [vector.overview]
A vector is a sequence container that supports random access iterators. In addition,itsupports(amortized) constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage management is handled automatically, though hints can be given to improve efficiency. The elements of a vector are stored contiguously, meaning that ifv is avector whereT is some type other than bool, then it obeys the identity&v[n] == &v[0] + n for all0 <= n < v.size().
Yes, it is fine to do that. You might want to do myvet.data() instead of &myvet[0] if it looks better to you, but they both have the same effect. Also, if circumstances permit, you can use std::copy instead and have more type-safety and all those other C++ standard library goodies.
The storage that a vector uses is guaranteed to be contiguous, which makes it suitable for use as a buffer or with other functions.
Make sure that you don't modify the vector (such as calling push_back on it, etc) while you are using the pointer you get from data or &v[0] because the vector could resize its buffer on one of those operations and invalidate the pointer.
That approach is correct, it only depends on the vector having contiguous memory which is required by the standard. I believe that in c++11 there is a new data() member function in vectors that returns a pointer to the buffer. Also note that in the case of `memcpy you need to pass the size in bytes not e size of the array
The memory in vector is guaranteed to be allocated contiguously, and unsigned char is POD, therefore it is totally safe to memcpy into it (assuming you don't copy more than you have allocated, of course).
Do your resize first, and it should work fine.
vector<int> v;
v.resize(100);
memcpy(&v[0], someArrayOfSize100, 100 * sizeof(int));
Yes, the solution using memcpy is correct; the buffer held by a vector is contiguous. But it's not quite type-safe, so prefer assign or std::copy.

std::list<char> list_type to (char * data, int lenght)

I have some
std::list<char> list_type
Now I have to supply contents of the list as (char *data, int length). Is there convenient way to present list contents as pointer and length? Does <vector> has such interface?
Thank you in advance.
You can do it with a vector, because its data is stored contiguously:
std::vector<char> vec;
char* data = &vec[0];
int length = static_cast<int>(vec.size());
For list, you have to copy the data to an array. Luckily, that too is fairly easy:
std::list<char> list:
int length = static_cast<int>(list.size());
char* data = new char[length]; // create the output array
std::copy(list.begin(), list.end(), data); // copy the contents of the list to the output array
Of course, you're then left with a dynamically allocated array you have to free again.
You can do this with vector, not with list. A vector is guaranteed to be a contigous chunk of memory so you can say:
char *data = &list_type[0];
std::vector<char>::size_type length = list_type.size();
I don't know about std::list, but std::vector does:
std::vector<char> list_type;
...
foo(&list_type[0], list_type.size())
std::string can do the job too, but you probably already know it.
You cannot do this with a list, as a list saves its data in list nodes. However, you can do this with a vector, which is guaranteed to store its data in a contiguous piece of memory. You can use either &v[0] or &*v.begin() to get a pointer to its first element:
void f(std::list<char>& list)
{
std::vector<char> vec(list.begin(),list.end());
assert(!vec.empty());
c_api_function(&vec[0],vec.size());
// assuming you need the result of the call to replace the list's content
list.assign(vec.begin(),vec.end());
}
Note that the vector will automatically free its memory when the function returns.
There are (at least) two more noteworthy things:
The vector must not be empty. You are not allowed to access v[0] of an empty vector. (Neither are you allowed to dereference v.begin().)
Since dynamic allocation is involved, converting back and forth between std::list and std::vector can be a real performance killer. Consider switching to std::vector altogether.
list is a linked list data structure. There's no way you could do that (theoretically) without conversion.
You'll be able to access (C++0x Draft 23.2.6.3) the backing store of a vector with .data() in C++0x. Currently, your best bet is to treat it as an array by taking the address of the initial element.

Best Replacement for a Character Array

we have a data structure
struct MyData
{
int length ;
char package[MAX_SIZE];
};
where MAX_SIZE is a fixed value . Now we want to change it so as to support
"unlimited" package length greater than MAX_SIZE . one of the proposed solution
is to replace the static array with a pointer and then dynamically allocating
the size as we require For EX
struct MyData
{
int length ;
char* package;
};
and then
package = (char*)malloc(SOME_RUNTIME_SIZE) ;
Now my question is that is this the most efficient way to cater to the requirement OR is there any other method .. maybe using STL data structures like growable arrays etc etc .
we want a solution where most of the code that works for the static char array should work for the new structure too ..
Much, much better/safer:
struct my_struct
{
std::vector<char>package;
};
To resize it:
my_struct s;
s.package.resize(100);
To look at how big it is:
my_struct s;
int size = s.package.size();
You can even put the functions in the struct to make it nicer:
struct my_struct
{
std::vector<char>package;
void resize(int n) {
package.resize(n);
}
int size() const {
return package.size();
}
};
my_struct s;
s.resize(100);
int z = s.size();
And before you know it, you're writing good code...
using STL data structures like growable arrays
The STL provides you with a host of containers. Unfortunately, the choice depends on your requirements. How often do you add to the container? How many times do you delete? Where do you delete from/add to? Do you need random access? What performance gurantees do you need? Once you have a sufficiently clear idea about such things look up vector, deque, list, set etc.
If you can provide some more detail, we can surely help pick a proper one.
I would also wrap a vector:
// wraps a vector. provides convenience conversion constructors
// and assign functions.
struct bytebuf {
explicit bytebuf(size_t size):c(size) { }
template<size_t size>
bytebuf(char const(&v)[size]) { assign(v); }
template<size_t size>
void assign(char const(&v)[size]) {
c.assign(v, v+size);
}
// provide access to wrapped vector
std::vector<char> & buf() {
return c;
}
private:
std::vector<char> c;
};
int main() {
bytebuf b("data");
process(&b.buf()[0], b.buf().size()); // process 5 byte
std::string str(&b.buf()[0]);
std::cout << str; // outputs "data"
bytebuf c(100);
read(&c.buf()[0], c.buf().size()); // read 100 byte
// ...
}
There is no need to add many more functions to it, i think. You can always get the vector using buf() and operate on it directly. Since a vectors' storage is contiguous, you can use it like a C array, but it is still resizable:
c.buf().resize(42)
The template conversion constructor and assign function allows you to initialize or assign from a C array directly. If you like, you can add more constructors that can initialize from a set of two iterators or a pointer and a length. But i would try keeping the amount of added functionality low, so it keeps being a tight, transparent vector wrapping struct.
If this is C:
Don't cast the return value of malloc().
Use size_t to represent the size of the allocated "package", not int.
If you're using the character array as an array of characters, use a std::vector<char> as that's what vectors are for. If you're using the character array as a string, use a std::string which will store its data in pretty much the same way as a std::vector<char>, but will communicate its purpose more clearly.
Yep, I would use an STL vector for this:
struct
{
std::vector<char> package;
// not sure if you have anything else in here ?
};
but your struct length member just becomes package.size ().
You can index characters in the vector as you would in your original char array (package[index]).
use a deque. sure a vector will work and be fine, but a deque will use fragmented memory and be almost as fast.
How are you using your structure?
Is it like an array or like a string?
I would just typedef one of the C++ containers:
typedef std::string MyData; // or std::vector<char> if that is more appropriate
What you have written can work and is probably the best thing to do if you do not need to resize on the fly. If you find that you need to expand your array, you can run
package = (char*)realloc((void*)package, SOME_RUNTIME_SIZE) ;
You can use an STL vector
include <vector>
std::vector<char> myVec(); //optionally myVec(SOME_RUNTIME_SIZE)
that you can then resize using myVec.resize(newSize) or by using functions such as push_back that add to the vector and automatically resize. The good thing about the vector solution is that it takes away many memory management issues -- if the vector is stack-allocated, its destructor will be called when it goes out of scope and the dynamically-allocated array underlying it will be deleted. However, if you pass the vector around, the data will get copied that can be slow, so you may need to pass pointers to vectors instead.