Archive
Reading contents of a file to a vector at one go!
It’s quite easy to read the contents of a file to a vector at one go. For this we need to get the size of a file and ask vector to allocate a buffer to hold these many bytes (use vector::resize()). Here is a function which does this. Note that it’s a byte/char vector.
#include "vector" #include "fstream" void ReadFileToVector( const char* FileName, std::vector<char>& FileBuff ) { using namespace std; ifstream ifile; ifile.open( FileName, ios::in ); // Get file size ifile.seekg(0, ios_base::end); streamoff FileSize = ifile.tellg(); ifile.seekg(0, ios_base::beg); // Resize vector to file size FileBuff.resize( FileSize, 0 ); // Read in file contents to buffer ifile.read(&FileBuff[0], FileSize); }
Benefit of using a vector instead of a char pointer is that we don’t have to do memory management and also we are directly accessing this buffer so no reallocations occur internally but we’ll have to check for allocation failure after calling vector::resize since files can be of huge sizes. You can optimize this further, post a comment if you find any issue/optimization. Also note that there are other ways to achieve the same behavior for e.g. using istream_iterator and back_inserter but this does cause frequent reallocations in a vector IMO making things slower.
What’s the size limit of a vector?
Use std::vector::max_size() function.
Don’t confuse this function with std::vector::capacity() and std::vector::size() functions. vector::capacity() tells us when a vector will be reallocated and vector::size() tells us the count of elements inserted into a vector.
Source code of vector::max_size looks like this…
_SIZT max_size() const _THROW0() { // estimate maximum array size _SIZT _Count = (_SIZT)(-1) / sizeof (_Ty); return (0 < _Count ? _Count : 1); }[/sourcecode] -1 is being cast to _SIZT and then divided by the sizeof the vector type. Have a look at the following illustration... [sourcecode language='cpp']template<class T> void PrintVectorMaxSize( std::vector<t>& Obj) { const std::vector</t><t>::size_type MaxSize = Obj.max_size(); std::cout < < "Max elements that can be inserted into a vector having elements of size '" << sizeof( T ) << "' is: " << MaxSize << std::endl; } int main() { PrintVectorMaxSize( std::vector<BYTE>() ); PrintVectorMaxSize( std::vector<int>() ); PrintVectorMaxSize( std::vector<double>() ); PrintVectorMaxSize( std::vector<char *>() ); }
Here is the output for the above program…
Max elements that can be inserted into a vector having elements of size ‘1’ is: 4294967295
Max elements that can be inserted into a vector having elements of size ‘4’ is: 1073741823
Max elements that can be inserted into a vector having elements of size ‘8’ is: 536870911
Max elements that can be inserted into a vector having elements of size ‘4’ is: 1073741823
PS: Please edit those html tags inserted by code formatter before compilation.
Technorati Tags: CPlusplus, Finding out size limit of a vector, Maximum elements that can be inserted into a vector, max_size, Size limit of a vector, std::vector, VC++, vector
Dumping contents of a vector/list to cout
Is it possible to do this with just one line of code? Oh yes!
Have a look…
typedef int VT;
typedef std::vector
void Dump( VTVec& VecToPrint, std::ostream& stream, const char* lpszMsg )
{
// We will be wrapping every element within a square bracket.
// In the end output looks like this… [123] [864] [
stream << lpszMsg << "[";
// Get iterator for given stream, every element will be seperated with second
// parameter.
std::ostream_iterator Itr( stream, "] [" );
// Just one line to dump vector contents, no loops needed
std::copy( VecToPrint.begin(), VecToPrint.end(), Itr );
// Remove redundant space and bracket ( " [" ) from the end
// After this statement the series will look like [123] [864]
stream << "\b\b \b\b\n";
}// End Dump
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
VTVec VecObj( 10000, 0 );
// Fill vector with random number, see earlier post on std::generate
std::generate( VecObj.begin(), VecObj.end(), rand );
// Dump to std::cout
Dump( VecObj, std::cout, "Dumping vector of ints...\n" );
}// End _tmain[/sourcecode]
Filling out a vector using generate function
Let us suppose that you want to fill out a vector with 10000 random elements, phew. Hmm so what you would do is to write a for loop, iterate through, and fill out the elements.
Well I can do it with just one line of code. 🙂 Look
// Typedefs typedef int VtElem; typedef std::vector<vtelem> Vector; const Vector::size_type Size = 10000; Vector VecObj( Size ); // Look at the last parameter, it needs a callback function pointer/function object/functor, // we've given standard c "rand" function to fill out vector with random elements. std::generate( VecObj.begin(), VecObj.end(), rand );
So now we have a vector that has been randomly been filled out. We can replace rand with any kind of filling in method. You can even have a vector full of prime numbers using a prime functor.
There is another version of std::generate called std::generate_n, which as the name suggests generates upto n elements.
Looks like this…
// Fill just 10 elements with random numbers std::generate_n( VecObj.begin(), 10, rand );
Initializing vector elements to a particular value
There are 8 constructors for std::vector class, out of which there is this constructor that takes two parameters…
vector( size_type _Count, const Type& _Val );
First parameter is size of the vector, second is default value for all elements in the vector.
Let’s suppose you have 1000 Employees in your organization each of them has an initial salary of Rs 8000, we would like to maintain information related to them using a vector. This is how we will be declaring the vector object and initializing every Employee element in it to to have an initial salary of 8000.
class Employee { public: Employee() : m_Salary( 0 ) {} explicit Employee( const int Salary ) : m_Salary( Salary ) {} private: int m_Salary; };// End class Employee // Typedefs typedef Employee Emp; typedef std::vector<emp> EmpVector; // 1000 employees with salary member variable of every employee instance in // our vector initialized to 8000 EmpVector EmpVecObj( 1000, Employee( 8000 ));
Using std transform function
So what does std::transform function do?
“Applies a specified function object to each element in a source range or to a pair of elements from two source ranges and copies the return values of the function object into a destination range.”
Some general applications of using transform is as follows…
- For doing some kind of operation on two vectors of same type and storing the result in a third vector.
- For doing some kind of in place operations on a vector.
So simplified prototypes of this function…
template<class InputIterator, class OutputIterator, class UnaryFunction> OutputIterator transform( InputIterator _First1, InputIterator _Last1, OutputIterator _Result, UnaryFunction _Func ); template</class><class InputIterator1, class InputIterator2, class OutputIterator, class BinaryFunction> OutputIterator transform( InputIterator1 _First1, InputIterator1 _Last1, InputIterator2 _First2, OutputIterator _Result, BinaryFunction _Func );
So first prototype can take two different vectors or can be the same vector for inplace modification,while second one takes three, two source vectors (for e.g. two vector of ints and we add these two vectors and place the result in a third vector).
The applications of this function is powerful! Here are some demos
// Starts here int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { void Demo_Std_TransformInplace(); Demo_Std_TransformInplace(); void Demo_Std_Transform_Binary(); Demo_Std_Transform_Binary(); return 0; } #include <vector> // for std::vector #include <algorithm> // for std::transform // Callbacks used with std::transform, can also be functors but for ease of calling // // Unary operations. Note that I am alternating 'class' and 'typename' keywords just // to prevent code formatting errors in HTML. template<class T> T Square( const T Elem ) { return Elem * Elem; } template<typename T> T ReverseSign( const T Elem ) { return -Elem; } template<class T> T IncrementBy1( const T Elem ) { return Elem + 1; } template<typename T> T DecrementBy1( const T Elem ) { return Elem - 1; } // Binary operations template<class T> T Add( const T Elem1, const T Elem2 ) { return Elem1 + Elem2; } template<typename T> T Multiply( const T Elem1, const T Elem2 ) { return Elem1 * Elem2; } template<class T> T Divide( const T Elem1, const T Elem2 ) { return Elem1 / Elem2; } template<typename T> T Substract( const T Elem1, const T Elem2 ) { return Elem1 - Elem2; } // A typedef for ease of use typedef double VectorType; // Change this type and see the result typedef std::vector<vectortype> VTVector; // Vector typedef const VTVector::size_type Size = 1000; // Default size, increase to test performance // Randomly fills in a vector void FillInIntVector( VTVector& Vec ) { for( VTVector::size_type Index = 0; Index < Vec.size(); ++Index ) { Vec[Index] = static_cast<VectorType>( rand() ); } } // Functions for testing std::transform, Debug through and see the results // void Demo_Std_TransformInplace() { VTVector VTObj( Size ); FillInIntVector( VTObj ); // Do some in place operations std::transform( VTObj.begin(), VTObj.end(), VTObj.begin(), Square</vectortype><vectortype> ); std::transform( VTObj.begin(), VTObj.end(), VTObj.begin(), ReverseSign</vectortype><vectortype> ); std::transform( VTObj.begin(), VTObj.end(), VTObj.begin(), IncrementBy1</vectortype><vectortype> ); std::transform( VTObj.begin(), VTObj.end(), VTObj.begin(), DecrementBy1</vectortype><vectortype> ); } void Demo_Std_Transform_Binary() { // Randomly fill in first vector VTVector VTObj1( Size ); FillInIntVector( VTObj1 ); // Randomly fill in second vector VTVector VTObj2( Size ); FillInIntVector( VTObj2 ); // Added result will be placed in here VTVector Result( Size ); // Add "VTObj1" and "VTObj2" vector place the result in "Result" std::transform( VTObj1.begin(), VTObj1.end(), VTObj2.begin(), Result.begin(), Add</vectortype><vectortype> ); std::transform( VTObj1.begin(), VTObj1.end(), VTObj2.begin(), Result.begin(), Multiply</vectortype><vectortype> ); std::transform( VTObj1.begin(), VTObj1.end(), VTObj2.begin(), Result.begin(), Divide</vectortype><vectortype> ); std::transform( VTObj1.begin(), VTObj1.end(), VTObj2.begin(), Result.begin(), Substract</vectortype><vectortype> ); }