Pages

Showing posts with label STL. Show all posts
Showing posts with label STL. Show all posts

Friday, February 19, 2010

STL. Vector. Hello, World program

Here is a simple Hello. World! program for the STL vector:
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;

const char* str = "Hello, World!";

int main()
{
vector<char> v(str, str + strlen(str));
for (unsigned int i = 0; i < v.size(); i++)
{
cout << v[i];
}
cout << endl;
return 0;
}

The firstl line in the main function:
vector<char> v(str, str + strlen(str));

converted the string (array of char) into the vector. This vector constructor can be persented as:
template <typename InputIterator>
vector(InputIterator first, InputIterator last)

vector is a sequence container - it is a collection of objects, all of the same type, into a strictly linear arrangement. vector provides random access to this sequence. The most time consuming operations with the vector are inserting and deleting at the end. The time of these operations is constant for the vector.

We are talking about the STL - Standard Template Library, so it makes sense to modify the program code listed above:
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;

const char* str = "Hello, World!";

template<typename Container>
void print(Container container)
{
for (unsigned int i = 0; i < container.size(); i++)
{
cout << container[i];
}
cout << endl;
}

int main()
{
vector<char> v(str, str + strlen(str));
print(v);
return 0;
}

Template function print was added to the program. This function will allow to print out an STL container. Method size() used in this function gives the number of elements in the container.

In the following form this function looks more atractive:
template<typename Container>
void print(Container container)
{
Container::iterator it;
for (it = container.begin(); it < container.end(); it++)
{
cout << *it;
}
cout << endl;
}
Now it works with the iterators - functions begin() and end() returns iterators declared as Container::iterator which can be derefferenced and used, for example, for the printing of the container elements.

Two other linear containers are deque and list.
In our program we can replace vector with deque:
#include <cstring>
#include <deque>
#include <iostream>
using namespace std;

const char* str = "Hello, World!";

template<typename Container>
void print(Container container)
{
Container::iterator it;
for (it = container.begin(); it < container.end(); it++)
{
cout << *it;
}
cout << endl;
}

int main()
{
deque<char> v(str, str + strlen(str));
print(v);
return 0;
}

Our function print works with this container too. All methods (begin(), end(), size()) used in this program are the same for the vector and deque (the list does not allow ++ operator).

In the same way the STL algoritms use the containers - these algorithms are the template functions (same as our print function). For example:
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

const char* str = "Hello, World!";

template<typename Container>
void print(Container container)
{
Container::iterator it;
for (it = container.begin(); it < container.end(); it++)
{
cout << *it;
}
cout << endl;
}

int main()
{
vector<char> v(str, str + strlen(str));
print(v);
vector<char>::iterator where = find(v.begin(), v.end(), 'W');
if (where != v.end())
{
vector<char> found(where, v.end());
print(found);
}
return 0;
}
This program found character 'W' in the input container, made new container from the found position and printed it out:
Or here is the reverse algorithm:
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

const char* str = "Hello, World!";

template<typename Container>
void print(Container container)
{
Container::iterator it;
for (it = container.begin(); it < container.end(); it++)
{
cout << *it;
}
cout << endl;
}

int main()
{
vector<char> v(str, str + strlen(str));
print(v);
reverse(v.begin(), v.end());
print(v);
return 0;
}
One more sample using vector:
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;

int main()
{
int x[5] = { 2, 3, 5, 7, 11 };
vector<int> v(x, x + 5);
int sum = accumulate(v.begin(), v.end(), 0);
cout << "sum = " << sum << endl;
return 0;
}
This small program above calculates the sum of 5 integers (the result is 28). Algorithm accumulate (from numeric header file) is used in this code. Integer numbers can be replaced by double:
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;

int main()
{
double x[5] = { 0.2, 0.3, 0.5, 0.7, 1.1 };
vector<double> v(x, x + 5);
double sum = accumulate(v.begin(), v.end(), 0.0);
cout << "sum = " << sum << endl;
return 0;
}
The result is 2.8. This accumulate function is also a template function that works with the iterators and may look like:
template <typename InputIterator, typename T>
T accumulate(InputIterator first, InputIterator last, T init)
{
while (first != last)
{
init = init + *first;
++first;
}
return init;
}
Here are a few articles about the basic STL:
1. A Practical Guide to STL

2. An Introduction to the Standard Template Library (STL)
3. C++ Vectors

Monday, February 15, 2010

STL. Vector. Beginning

People who knows me will not believe that I wrote even such small program with STL:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
vector<int> v;
int input;
while (cin >> input)
{
if (input == 0)
break;
v.push_back(input);
}

sort(v.begin(), v.end());
int n = v.size();
for (int i = 0; i < n; i++)
cout << "v[" << i << "] = " << v[i] << endl;

return 0;
}
Almost like Bjarne Stroustrup:
http://www2.research.att.com/~bs/bs_faq2.html

This program uses the simplest STL container vector and performs the sorting by calling sort STL function. This function works with the iterators - it gets the first iterator and increments and dereference it until it is equal to the second iterator.

Friday, October 23, 2009

I don't like STL

I don't like STL. Shame on me. I hope, all other programmers disagree with me.
I can explain why:
1. Mainly, I hate all these exception thrown from the STL classes everywhere. I don't like code protected with try...catch if this code does nothing with the hardware. I prefer to predict all mistakes on a logical level or, in the worst case detect them with a tool like IBM Purify+ or Bound Checker. Of course, I don't want the user to see any error message box.
2. I make a lot of projects running on Windows CE devices and I've met 3 of them and spent few days to make our project running there. The problem was STL. Precisely, the error exception handling. The code had #include and that was enough for the system to disregard my application.
3. The C++ code with STL sometimes looks like C#. STL is a very rich library and has a million of own classes. The code on the application level looks like a pseudo-code.
4. I don't like to support code made by someone else for me with a promise to work fine. :)

Tuesday, October 6, 2009

Шедевр

Уж не подумайте, что я такое пишу. Я увидел это по-случаю, и человек, сотворивший это, гордится таким кодом.
Вот этот макрос переводит дествительное число в строку:
#define DBL2STR(d)  ((ostringstream&)(ostringstream()<<d)).str();
И этот подход предлагается использовать и для лога:
#define LOG(s)  { ofstream ofs("path/to/errorlog", ios::app| ios::out); ofs << s; ofs.close(); }