It seems to be a general consensus that C arrays are bad and that using the smarter alternatives, like vectors or C++ strings is the way to 开发者_StackOverflow中文版go. No problem here.
Having said that, why does the read()
member of ifstream
input data to a char*
...
The question is: can I input to a vector of bytes somehow using the STL alone?
A related bonus question: do you often check for ios::badbit
and ios::failbit
especially if you work with a dynamically allocated C string within that scope? Do you do deallocation of the C string in the catch()
's?
Thank you for reading.
You can read directly into an allocated vector (I have no ability to compile this from here so there might be typos or transposed parameters etc...) but the idea is correct.
vector<char> data;
data.resize(100);
// Read 100 characters into the storage of data
thing.read(&data[0], 100);
Having said that, why does the read() member of ifstream input data to a char*...
It was a design choice. Not necessarily the smartest one.
The question is: can I input to a vector of bytes somehow
The underlying storage for a std::vector<char>
is guaranteed to be contiguous (i.e., a single block of memory), so yes. To use ifstream::read
, you must (a) ensure that the vector's size is big enough (using .resize()
- not .reserve()
! This is because the vector has no way of knowing about the data you're reading in to its unused capacity
and updating its size
), and then (b) obtain a pointer to the beginning element of the vector (e.g. with &v.front()
or &(v[0])
).
If you don't want to pre-size the vector, then there are more advanced techniques you can use that involve iterator types and standard library algorithms. These have the advantage that you can easily read an entire file into a vector without having to check the file length first (and the standard tricks for checking a file's length might not be as reliable as you think!).
It looks something like:
#include <iterator>
#include <algorithm> // in addition to what you already have.
// ...
std::ifstream ifs;
std::vector v;
// ...
std::istreambuf_iterator<char> begin(ifs), end;
std::copy(begin, end, std::back_inserter(v));
A vector of bytes is not a string, of course. But you can do the exact same thing with std::string
- the std::back_inserter
function is smart enough to create the appropriate iterator type for any supplied type that provides a .push_back()
, which both string
and vector
do. That's the magic of templates. :)
using the STL alone?
I'm confused. I thought we were talking about the C++ standard library. What is this STL of which you speak?
A related bonus question: do you often check for ios::badbit and ios::failbit
No; I usually write code in such a way that I can just check the result of the reading operation directly. See http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.4 for an example/discussion.
especially if you work with a dynamically allocated C string within that scope?
This is a bad idea in general.
Do you do deallocation of the C string in the catch()'s?
And having to deal with this sort of thing is one of the main reasons why. This is not easy to get right. But I hope you realize that catching an exception and checking for ios::bits are two totally different things. Although you can configure the stream object to throw exceptions instead of just setting the flag bits :)
精彩评论