Professional Documents
Culture Documents
php
// instr function
// checks for an occurance of a string
// within another string
function instr($string,$find,$casesensitive = false) {
$i=0;
while (strlen($string)>=$i) {
unset($substring);
if ($casesensitive) {
$find=strtolower($find);
$string=strtolower($string);
}
$substring=substr($string,$i,strlen($find));
if ($substring==$find) return true;
$i++;
}
return false;
}
?>
instr function ..
<?php
// instr function
// checks for an occurance of a string
// within another string
function instr($string,$find,$casesensitive = false) {
$i=0;
while (strlen($string)>=$i) {
unset($substring);
if ($casesensitive) {
$find=strtolower($find);
$string=strtolower($string);
}
$substring=substr($string,$i,strlen($find));
if ($substring==$find) return true;
$i++;
}
return false;
}
?>
instr function ..
disclaimer
i started looking at stl in 1995; for a long time i could compile only minimal subsets of
the hp version of the library. more recently, the compilers used by the students i teach
have been able to support more of stl, and i have been adding it to the introductory and
advanced courses i teach. now, at the beginning of 1998, i use stl in the labs for all of the
courses i teach.
i have been using c++ since 1988, and teaching c++ and object-oriented design courses in
industry since 1990. i really like the design philosophies in stl; i think that you can learn a
great deal about how generalization can simplify programming by understanding why stl
is constructed the way it is.
mark nelson's book on stl is very good if you want to understand the internal details, but
is probably overkill for many people. musser and saini have a good book on stl, but it is a
bit out-of-date.
i haven't seen very much online documentation on stl, apart from the good but rather
dense paper by stepanov and lee, i thought i would try to write something to give people a
taste of what a good library will be do for them.
another reason for getting people to start trying out stl soon is to put pressure on the
compiler-writers to get their compilers patched up enough to take the strain it puts on
them...
i would greatly appreciate comments or suggestions from anyone.
outline
stl contains five kinds of components: containers, iterators, algorithms, function objects
and allocators.
in the section example i present a simple example, introducing each of the five categories
of stl components one at a time.
in the section philosophy i explain the rationale behind the organization of stl, and give
some hints on the best ways to use it. (not yet written)
the components section goes into each category of component in more detail.
the section extending stl shows how to define your own types to satisfy the stl
requirements. (not yet written)
a first example
most of you probably use some kind of auto-allocating array-like type. stl has one called
vector. to illustrate how vector works, we will start with a simple c++ program that
reads integers, sorts them, and prints them out. we will gradually replace bits of this
program with stl calls.
let's read the elements and push them onto the end of a vector. this removes the arbitrary
limit on the number of elements that can be read.
also, instead of using qsort, we will use the stl sort routine, one of the many algorithms
provided by stl. the sort routine is generic, in that it will work on many different types of
containers. the way this is done is by having algorithms deal not with containers directly,
but with iterators.
preview of iterators
i'll go into iterators in detail later, but for now here is enough to get started.
iterators provide a way of specifying a position in a container. an iterator can be
incremented or dereferenced, and two iterators can be compared. there is a special iterator
value called "past-the-end".
you can ask a vector for an iterator that points to the first element with the message
begin. you can get a past-the-end iterator with the message end. the code
vector<int> v;
// add some integers to v
vector::iterator i1 = v.begin();
vector::iterator i2 = v.end();
will create two iterators like this:
operations like sort take two iterators to specify the source range. to get the source
elements, they increment and dereference the first iterator until it is equal to the second
iterator. note that this is a semi-open range: it includes the start but not the end.
two vector iterators compare equal if they refer to the same element of the same vector.
putting this together, here is the new program:
#include <string.h>
#include <algo.h>
#include <vector.h>
#include <stdlib.h>
#include <iostream.h>
main ()
{
vector<int> v; // create an empty vector of integers
int input;
while (cin >> input) // while not end of file
v.push_back (input); // append to vector
// sort takes two random iterators, and sorts the elements between
// them. as is always the case in stl, this includes the value
// referred to by first but not the one referred to by last; indeed,
// this is often the past-the-end value, and is therefore not
// dereferenceable.
sort(v.begin(), v.end());
int n = v.size();
for (int i = 0; i < n; i++)
cout << v[i] << "\n";
}
incidentally, this is much faster than qsort; at least a factor of 20 on the examples i tried.
this is presumably due to the fact that comparisons are done inline.
version 3: iterator adaptors
in addition to iterating through containers, iterators can iterate over streams, either to read
elements or to write them.
an input stream like cin has the right functionality for an input iterator: it provides access
to a sequence of elements. the trouble is, it has the wrong interface for an iterator:
operations that use iterators expect to be able to increment them and dereference them.
stl provides adaptors, types that transform the interface of other types. this is very much
how electrical adaptors work. one very useful adaptor is istream_iterator. this is a
template type (of course!); you parameterize it by the type of object you want to read
from the stream. in this case we want integers, so we would use an
istream_iterator<int>. istream iterators are initialized by giving them a stream, and
thereafter, dereferencing the iterator reads an element from the stream, and incrementing
the iterator has no effect. an istream iterator that is created with the default constructor
has the past-the-end value, as does an iterator whose stream has reached the end of file.
in order to read the elements into the vector from standard input, we will use the stl copy
algorithm; this takes three iterators. the first two specify the source range, and the third
specifies the destination.
the names can get pretty messy, so make good use of typedefs. iterators are actually
parameterized on two types; the second is a distance type, which i believe is really of use
only on operating systems with multiple memory models. here is a typedef for an iterator
that will read from a stream of integers:
typedef istream_iterator<int,ptrdiff_t> istream_iterator_int;
the second argument to the template should default to ptrdiff_t, but most compilers do not
understand default template arguments. some implementations of stl define
istream_iterators with only one parameter, and supply a hard-coded distance type. so
you will have to see whether your compiler understands default template arguments; if it
does, you can declare the iterator type like this:
typedef istream_iterator<int> istream_iterator_int;
so to copy from standard input into a vector, we can do this:
copy (istream_iterator_int (cin), istream_iterator_int (), v.begin());
the first iterator will be incremented and read from until it is equal to the second iterator.
the second iterator is just created with the default constructor; this gives it the past-the-
end value. the first iterator will also have this value when the end of the stream is
reached. therefore the range specified by these two iterators is from the current position
in the input stream to the end of the stream.
there is a bit of a problem with the third iterator, though: if v does not have enough space
to hold all the elements, the iterator will run off the end, and we will dereference a past-
the-end iterator (which will cause a segfault).
what we really want is an iterator that will do insertion rather than overwriting. there is an
adaptor to do this, called back_insert_iterator. this type is parameterized by the
container type you want to insert into.
vector<int> v;
istream_iterator_int start (cin);
istream_iterator_int end;
back_insert_iterator<vector<int> > dest (v);
main ()
{
vector<int> v;
istream_iterator<int,ptrdiff_t> start (cin);
istream_iterator<int,ptrdiff_t> end;
back_insert_iterator<vector<int> > dest (v);
discussion
i find the final version of the program the cleanest, because it reflects the way i think of
the computation happening: the vector is copied into memory, sorted, and copied out
again.
in general, in stl, operations are done on containers as a whole, rather than iterating
through the elements of the container explicitly in a loop. one obvious advantage of this
is that it lends itself easily to parallelization or hairy optimizations (e.g., one could be
clever about the order the elements were accessed in to help avoid thrashing).
most of the stl algorithms apply to ranges of elements in a container, rather than to the
container as a whole. while this is obviously more general than having operations always
apply to the entire container, it makes for slightly clumsy syntax. some implementations
of stl (e.g., objectspace), provide supplementary versions of the algorithms for common
cases. for example, stl has an algorithm count that counts the number of times a
particular element appears in a container:
template <class inputiterator, class t, class size>
void count (inputiterator start, inputiterator end, const t& value,
size& n);
to find how many elements have the value 42 in a vector v, you would write:
int n = 0;
count (v.begin(), v.end(), 42, n);
objectspace defines an algorithm os_count that provides a simpler interface:
int n = os_count (v, 42);
philosophy
the standard template library is designed for use with a style of programming called
generic programming. the essential idea behind generic programming is to create
components that can be composed easily without losing any performance. in some sense,
it moves the effort that is done at run-time in object-oriented programming (dynamic
binding) to compile-time, using templates.
stl components
containers
containers are objects that conceptually contain other objects. they use certain basic
properties of the objects (ability to copy, etc.) but otherwise do not depend on the type of
object they contain.
stl containers may contain pointers to objects, though in this case you will need to do a
little extra work.
vectors, lists, deques, sets, multisets, maps, multimaps, queues, stacks, and priority
queues, did i miss any? are all provided.
perhaps more importantly, built-in containers (c arrays) and user-defined containers can
also be used as stl containers; this is generally useful when applying operations to the
containers, e.g., sorting a container. using user-defined types as stl containers can be
accomplished by satisfying the requirements listed in the stl .
if this is not feasible, you can define an adaptor class that changes the interface to satisfy
the requirements.
all the types are "templated", of course, so you can have a vector of ints or windows or a
vector of vector of sets of multimaps of strings to students. sweat, compiler-writers,
sweat!
to give you a brief idea of the containers that are available, here is the hierarchy:
sequences
contiguous blocks of objects; you can insert elements at any point in the sequence, but the
performance will depend on the type of sequence and where you are inserting.
vectors
fast insertion at end, and allow random access.
lists
fast insertion anywhere, but provide only sequential access.
deques
fast insertion at either end, and allow random access. restricted types, such as stack and
queue, are built from these using adaptors.
stacks and queues
provide restricted versions of these types, in which some operations are not allowed.
associative containers
associative containers are a generalization of sequences. sequences are indexed by
integers; associative containers can be indexed by any type.
the most common type to use as a key is a string; you can have a set of strings, or a map
from strings to employees, and so forth.
it is often useful to have other types as keys; for example, if i want to keep track of the
names of all the widgets in an application, i could use a map from widgets to strings.
sets
sets allow you to add and delete elements, query for membership, and iterate through the
set.
multisets
multisets are just like sets, except that you can have several copies of the same element
(these are often called bags).
maps
maps represent a mapping from one type (the key type) to another type (the value type).
you can associate a value with a key, or find the value associated with a key, very
efficiently; you can also iterate through all the keys.
multimaps
multimaps are just like maps except that a key can be associated with several values.
should add other containers: priority queue, bit vector, queue.
vector<int> v;
for (int i = 0; i < n; i++) // append integers 0 to n-1 to
v
v.push_back (i);
unfortunately, this is not quite what we wanted -- this overwrites an existing vector,
whereas in our case, we had an empty vector, and we wanted the elements appended to it.
there are two problems here. the first is that the termination condition for the iota
function is specified by an iterator; the loop terminates when the moving iterator becomes
equal to the terminal iterator.
many algorithms in stl come in several flavors, corresponding to different terminating
conditions. for example, generate uses two iterators to specify a range; generate_n
uses one iterator and an integer to specify the range.
the iota function, unfortunately, does not have an iota_n counterpart, but it is very easy
to write:
template <class forwarditerator, class t>
void iota_n (forwarditerator first, int n, t value)
{
for (int i = 0; i < n; i++)
*first++ = value++;
}
in order to append to the vector instead of overwriting its contents, we will use an adaptor
back_inserter:
#include <iostream.h>
#include <vector.h>
#include <algo.h>
#include <iterator.h>
vector<int> v;
iota_n (v.begin(), 100, back_inserter(v));
input iterators provide access to data sources. the source may be an stl container, another
type of container, a stream, a virtual source (such as a set of permutations), etc.
output iterators
output iterators provide access to data sinks: locations to store the results of a
computation. the sink may be an stl container, a user-defined container, a stream, etc.
using input and output iterators
just input and output iterators are enough to do quite a lot, since many operations boil
down to copying objects around. for example, this function copies all the elements of a
container v to standard output. ostream_iterator is an adaptor; it is an output iterator
type. the iterator operations are defined so that in the case below, assigning through the
iterator prints to standard output, with each print followed by a newline.
copy (v.begin(), v.end(), ostream_iterator<int> (cout, "\\n"));
the first two arguments specify the source data: start an iterator that points to the
beginning of the vector v, and keep going until the iterator compares equal with v.end(),
which is called a past-the-end value. almost all stl operations have one or more pairs of
input iterators specifying the data to work with.
the third argument is an adaptor that turns an ostream like cout into an output iterator;
don't worry about the details for now.
a similar operation reads data into a vector (for now, we will assume the vector has
enough space allocated already):
copy (istream_iterator<int> (cin), istream_iterator<int> (), v.begin());
moreover, input and output iterators are necessary to do many things, since we usually
need to specify what data we want to work with, and where to put the result.
forward iterators
a forward iterator allows traversal of the sequence, reading and/or writing each element,
but no backing up. many algorithms request a forward iterator, for example
long *p = new int [1000];
fill (p, p+100, 0);
fill (p+101, p+1000, 0xdeadbeef);
fill's first two arguments specify the range the operation should take place on, and the
third specifies the value to write through the iterator at each position.
bidirectional iterators
bidirectional iterators can be moved forward or backward, and can be used to read or
write the elements of the sequence. moving an iterator from one part of the sequence to
another takes time proportional to the number of elements between the two.
containers and iterators
all the stl containers provide at least bidirectional iterators: lists, sets, maps, and so on can
be traversed forward or backward. some containers provide even more flexible indexing:
random access iterators
random access iterators can jump from any place to any other place in constant time i am
not sure that this is required, and it is certainly allowed to be amortized constant time.
every c pointer type is an stl random iterator for a c array container. if you have a
random-access container, you can perform all sorts of nifty operations on it, such as
mapping over a vector, with or without accumulation, finding and replacing elements
satisfying predicates, partitions, shuffling, and many more. the extent of this library never
ceases to amaze me given that the source code is really quite small. i think that is a
testimony to this kind of generic programming.
algorithms
the stl algorithms are template c++ functions to perform operations on containers. in
order to be able to work with many different types of containers, the algorithms do not
take containers as arguments. instead, they take iterators that specify part or all of a
container. in this way the algorithms can be used to work on entities that are not
containers; for example, the function copy can be used to copy data from standard input
into a vector.
some algorithms require only the capabilities of input iterators, while others require
random access (e.g., to sort).
the algorithms include sorting operations (sort, merge, min, max...), searching operations
(find, count, equal...), mutating operations (transform, replace, fill, rotate, shuffle...), and
generalized numeric operations (accumulate, adjacent difference...).
function objects
function objects are stl's way of representing "executable data". for example, one of the
stl algorithms is for_each. this applies a function to each object in a container. you need
to be able to specify what to do to each object in the container.
overview
function objects are objects on which at least one parenthesis operation (. . .) is
defined. they are used for three main purposes: generating data, testing data (predicates),
and applying operations.
generators
algorithms like generate walk through a range, calling a function object at each step,
and assigning the result of the function to the current element.
[picture]
for example, here is a function that always returns 0:
int zero() { return 0; }
to fill a vector with zeroes, one could use the algorithm generate with the function
object zero:
vector<int> v (100);
generate (v.begin(), v.end(), zero);
of course, it would be nice if our function were a bit more widely useful -- for example,
allowing an arbitrary arithmetic sequence. in order to do this, the function object has to
store some state indicating where in the sequence it is. there are two ways to do this. one
is to use static variables inside a global function, the other is to define a class of function
objects.
[in an aside] there are several problems with using static variables in a function to store
state. there can only be one position remembered in the sequence -- copies of the function
object will all always be positioned at the same point in the sequence. [other problems?]
here is a class iota. it provides an arithmetic sequence, starting with some initial value,
and repeatedly adding an increment to it. the function call operator returns the current
value and moves on to the next element of the sequence. the template is defined with two
types s and t. usually these will be the same, but they might be different, e.g., date and
int. it is usually a good idea to ask yourself if there is some straightforward
generalization of what you are about to do -- if it doesn't make things much more
complicated, it is probably worth it.
template <class s, class t>
class iota
{
s cur;
t inc;
public:
iota (const s& initial, const t& increment)
: cur (initial), inc (increment)
{ }
s operator()() { s tmp (cur); cur += inc; return tmp; }
};
vector v;
iterator iter = find_if (v.begin(), v.end(), greaterthanzero);
if (iter == v.end())
cout << "no elements greater than zero" << endl;
else
{
cout << "elements starting from first greater than zero: ";
copy (iter, v.end(), output (cout, " "));
}
again, it is often useful to be able to provide state in the predicate object. here is a
predicate that tests true if the element is within a specified range:
class inrange
{
const t& low;
const t& high;
public:
inrange (const t& l, const t& h) : low (l), high (h) { }
bool operator()(const t& t) { return ! (t < l) && t < h; }
};
here we find, and print, all the elements of a vector that fall within a particular range:
typedef vector<int>::iterator iterator;
typedef vector<int> vector;
typedef ostream_iterator<int> output;
vector v (100);
generate (v.begin(), v.end(), rand);
adaptors
sometimes you have a class that does the right thing, but has the wrong interface for your
purposes. adaptors are classes that sit between you and another class, and translate the
messages you want to send into the messages the other class wants to receive.
for example, the copy function expects an input iterator to get its data from. the istream
class has the right functionality: it acts as a source of data, but it has the wrong interface:
it uses << etc.
there is an adaptor called istream_iterator that provides the interface that copy
expects, translating requests into istream operations.
allocators
i confess i don't really understand stl's allocation model properly yet, so i won't say
anything about this for now. you don't need to know anything about them for now either.
extending stl
examples
iterators
the stl iterator model is somewhat different from most iterators i have seen. most
importantly, it is very flexible in regards to the type of thing iterators are ranging over.
containers are conceptually grouped by the type of access iterators can provide to them,
and iterations on any random access container (for example) is done the same way -- the
object doing the iteration does not know what kind of container it is.
the other important difference is that whereas many iterator mechanisms are mainly
intended for iteration over the entire collection, stl always deals in terms of ranges,
though of course the entire collection is just a particular range.
be careful not to confuse the past-the-end iterator value with the "null" value that other
iterator types often provide to indicate the end of the container. in particular, don't use the
past-the-end iterator to indicate an error; if you want to indicate errors, you should
provide singular iterator values; i will describe these in the section on iterators.
problem
i want a program that will let me perform arithmetic operations on streams of numbers,
with each stream coming from a different file. so as not to complicate the example with
parsing, i will use reverse polish notation, e.g., 2 cost1 * 3 cost2 * + 5 /. the
calculator has an internal stack. the expression is read left to right; if we find a number,
we push it onto the stack. if we find a name, we read a number from that file and push it
onto the stack. if we find an operator, we apply it, popping elements off the stack as
arguments. the above expression computes ((2 * cost1) + (3 * cost2))/5.
sketch of design
i will have a stack of input_iterators:
template <class t>
typedef input_iterator<t> *input_iterator_p;
appendices
lambda expressions
suppose we want to apply a function to all the elements of a vector. we can define the
function locally, since it is a type definition. it can take any context it needs in the
constructor, and store it internally.
this is not as elegant as lisp or perl's lexical scoping, but it is better than nothing.
function addoffset(vector<int>& v, int n)
{
`the question is,' said alice, `whether you can make words mean
so many different things.'
stl vector:
vector: dynamic array of variables, struct or objects. insert data at the end.
simple example of storing stl strings in a vector. this example shows three
methods of accessing the data within the vector:
#include <iostream>
#include <vector>
#include <string>
main()
{
vector<string> ss;
int ii;
for(ii=0; ii < ss.size(); ii++)
{
cout << ss[ii] << endl;
}
vector<string>::const_iterator cii;
for(cii=ss.begin(); cii!=ss.end(); cii++)
{
cout << *cii << endl;
}
vector<string>::reverse_iterator rii;
for(rii=ss.rbegin(); rii!=ss.rend(); ++rii)
{
cout << *rii << endl;
}
swap(ss[0], ss[2]);
cout << ss[2] << endl;
}
compile: g++ examplevector.cpp
run: ./a.out
output:
loop by index:
the number is 10
the number is 20
the number is 30
constant iterator:
the number is 10
the number is 20
the number is 30
reverse iterator:
the number is 30
the number is 20
the number is 10
sample output:
3
the number is 30
the number is 10
two / three / multi dimensioned arrays using vector:
a two dimensional array is a vector of vectors. the vector contructor can initialize
the length of the array and set the initial value.
example of a vector of vectors to represent a two dimensional array:
#include <iostream>
#include <vector>
main()
{
// declare size of two dimensional array and initialize.
vector< vector<int> > vi2matrix(3, vector<int>(2,0));
vi2matrix[0][0] = 0;
vi2matrix[0][1] = 1;
vi2matrix[1][0] = 10;
vi2matrix[1][1] = 11;
vi2matrix[2][0] = 20;
vi2matrix[2][1] = 21;
compile: g++ examplevector2.cpp
run: ./a.out
loop by index:
0
1
10
11
20
21
a three dimensional vector would be declared as:
#include <iostream>
#include <vector>
main()
{
// vector length of 3 initialized to 0
vector<int> vi1matrix(3,0);
...
or declare all in one statement:
#include <iostream>
#include <vector>
main()
{
vector< vector< vector<int> > > vi3matrix(2, vector< vector<int> >
(3, vector<int>(4,0)) );
using an iterator:
example of iterators used with a two dimensional vector.
#include <iostream>
#include <vector>
main()
{
vector< vector<int> > vi2matrix; // declare two dimensional array
vector<int> a, b;
vector< vector<int> >::iterator iter_ii;
vector<int>::iterator iter_jj;
a.push_back(10);
a.push_back(20);
a.push_back(30);
b.push_back(100);
b.push_back(200);
b.push_back(300);
vi2matrix.push_back(a);
vi2matrix.push_back(b);
compile: g++ examplevector2.cpp
run: ./a.out
using iterator:
10
20
30
100
200
300
constructor/declaration:
method/operator description
vector<t> v; vector declaration of data type "t".
vector<t> v(size_type n); declaration of vector containing type "t" and of
size "n" (quantity).
vector<t> v(size_type n,const t& declaration of vector containing type "t", of
t); size "n" (quantity) containing value "t".
declaration: vector(size_type n, const t&
t)
vector<t> copy of vector of data type "t" and range
v(begin_iterator,end_iterator); begin_iterator to end_iterator.
declaration: template vector(inputiterator,
inputiterator)
size methods/operators:
method/operator description
empty() returns bool (true/false). true if empty.
declaration: bool empty() const
size() number of elements of vector.
declaration: size_type size() const
resize(n, t=t()) adjust by adding or deleting elements of vector so that its size
is "n".
declaration: void resize(n, t = t())
capacity() max number of elements of vector before reallocation.
declaration: size_type capacity() const
reserve(size_t n) max number of elements of vector set to "n" before
reallocation.
declaration: void reserve(size_t)
max_size() max number of elements of vector possible.
declaration: size_type max_size() const
note: size_type is an unsigned integer.
other methods/operators:
method/operator description
erase() erase all elements of vector.
clear() declaration: void clear()
erase(iterator) erase element of vector. returns iterator to
erase(begin_iterator,end_iterator) next element.
erase element range of vector. returns
iterator to next element.
declarations:
• iterator erase(iterator pos)
iterator erase(iterator first,
iterator last)
= assign/copy entire contents of one vector
example: x=y() into another.
declaration: vector& operator=(const
vector&)
< comparison of one vector to another.
declaration: bool operator<(const
vector&, const vector&)
== returns bool. true if every element is
equal.
declaration: bool operator==(const
vector&, const vector&)
at(index) element of vector. left and right value
v[index] assignment: v.at(i)=e; and e=v.at(i);
declaration: reference
operator[](size_type n)
front() first element of vector. (left and right value
v[0] assignment.)
declaration: reference front()
back() last element of vector. (left and right value
assignment.)
declaration: reference back()
push_back(const t& value) add element to end of vector.
declaration: void push_back(const t&)
pop_back() remove element from end of vector.
declaration: void pop_back()
assign(size_type n,const t& t) assign first n elements a value "t".
assign(begin_iterator,end_iterator) replace data in range defined by iterators.
declaration:
insert(iterator, const t& t) insert at element "iterator", element of
value "t".
declaration: iterator insert(iterator
pos, const t& x)
insert(iterator pos, size_type n, const starting before element "pos", insert first n
t& x) elements of value "x".
declaration: void insert(iterator pos,
size_type n, const t& x)
insert(iterator pos, starting before element "pos", insert
begin_iterator,end_iterator) range begin_iterator to end_iterator.
declaration: void insert(iterator pos,
inputiterator f, inputiterator l)
swap(vector& v2) swap contents of two vectors.
declaration: void swap(vector&)
iterator methods/operators:
method/operator description
begin() return iterator to first element of vector.
declaration: const_iterator begin() const
end() return iterator to last element of vector.
declaration: const_iterator end() const
rbegin() return iterator to first element of vector (reverse order).
declaration: const_reverse_iterator rbegin() const
rend() return iterator to last element of vector (reverse order).
declaration: const_reverse_iterator rend() const
++ increment iterator.
decrement iterator.
vector links:
• sgi: vector detail of all vector member functions and operators available.
• also see boost ptr_vector used to hold vector of pointers.
stl list:
list: linked list of variables, struct or objects. insert/remove anywhere.
two examples are given:
1. the first stl example is for data type int
2. the second for a list of class instances.
they are used to show a simple example and a more complex real world
application.
1. lets start with a simple example of a program using stl for a linked list:
// standard template library example
#include <iostream>
#include <list>
using namespace std;
main()
{
list<int> l;
l.push_back(0); // insert a new element at the end
l.push_front(0); // insert a new element at the beginning
l.insert(++l.begin(),2); // insert "2" before position of first
argument
// (place before second argument)
l.push_back(5);
l.push_back(6);
list<int>::iterator i;
compile: g++ example1.cpp
run: ./a.out
output: 0 2 0 5 6
[potential pitfall]: in red hat linux versions 7.x one could omit the "using
namespace std;" statement. use of this statement is good programming practice
and is required in red hat 8.0.
[potential pitfall]: red hat 8.0 requires the reference to "#include <iostream>". red
hat versions 7.x used "#include <iostream.h>".
2. the stl tutorials and texts seem to give simple examples which do not apply to
the real world. the following example is for a doubly linked list. since we are using
a class and we are not using defined builtin c++ types we have included the
following:
• to make this example more complete, a copy constructor has been
included although the compiler will generate a memberwise one
automatically if needed. this has the same functionality as the assignment
operator (=).
• the assignment (=) operator must be specified so that sort routines can
assign a new order to the members of the list.
• the "less than" (<) operator must be specified so that sort routines can
determine if one class instance is "less than" another.
• the "equals to" (==) operator must be specified so that sort routines can
determine if one class instance is "equals to" another.
// standard template library example using a class.
#include <iostream>
#include <list>
using namespace std;
class aaa
{
friend ostream &operator<<(ostream &, const aaa &);
public:
int x;
int y;
float z;
aaa();
aaa(const aaa &);
~aaa(){};
aaa &operator=(const aaa &rhs);
int operator==(const aaa &rhs) const;
int operator<(const aaa &rhs) const;
};
aaa::aaa() // constructor
{
x = 0;
y = 0;
z = 0;
}
aaa::aaa(const aaa ©in) // copy constructor to handle pass by
value.
{
x = copyin.x;
y = copyin.y;
z = copyin.z;
}
// this function is required for built-in stl list functions like sort
int aaa::operator<(const aaa &rhs) const
{
if( this->x == rhs.x && this->y == rhs.y && this->z < rhs.z) return
1;
if( this->x == rhs.x && this->y < rhs.y) return 1;
if( this->x < rhs.x ) return 1;
return 0;
}
main()
{
list<aaa> l;
aaa ablob ;
ablob.x=7;
ablob.y=2;
ablob.z=4.2355;
l.push_back(ablob); // insert a new element at the end
ablob.x=5;
l.push_back(ablob); // object passed by value. uses default member-
wise
// copy constructor
ablob.z=3.2355;
l.push_back(ablob);
ablob.x=3;
ablob.y=7;
ablob.z=7.2355;
l.push_back(ablob);
list<aaa>::iterator i;
for(i=l.begin(); i != l.end(); ++i) cout << (*i).x << " "; // print
member
cout << endl;
for(i=l.begin(); i != l.end(); ++i) cout << *i << " "; // print all
cout << endl;
return 0;
}
output:
7 5 5 3
7 2 4.2355
5 2 4.2355
5 2 3.2355
3 7 7.2355
sorted:
3 7 7.2355
5 2 3.2355
5 2 4.2355
7 2 4.2355
list links:
• sgi: list detail of all "list" member functions and operators available.
• also see boost ptr_list used to hold list of pointers.
stl vector vs list function comparison:
function vector list
constructor yes yes
destructor yes yes
empty() yes yes
size() yes yes
resize() yes yes
capacity() yes no
reserve() yes no
max_size() yes yes
erase() yes yes
clear() yes yes
operator= yes yes
operator< yes yes
operator== yes yes
operator[] yes no
at() yes no
front() yes yes
back() yes yes
push_back() yes yes
pop_back() yes yes
assign() yes yes
insert() yes yes
swap() yes yes
push_front() no yes
pop_front() no yes
merge() no yes
remove() no yes
remove_if() no yes
reverse() no yes
sort() no yes
splice() no yes
unique() no yes
links/information:
• gnu string class yolinux tutorial
• "modest tutorial"
hold pointers.
• gtk api:
software and documentation available from:
• http://www.sgi.com/tech/stl/ stl home page
books:
the c++ standard library: a tutorial
reference
nicolai m. josuttis
isbn #0201379260, addison wesley
longman
this book is the only book i have seen
which covers string classes as
implemented by current linux
distributions. it also offers a fairly
complete coverage of the c++ standard
template library (stl). good reference
book.
stl for c++ programmers
leen ammeraal
isbn #0 471 97181 2, john wiley & sons
ltd.
short book which teaches c++ standard
template library (stl) by example. not as
great as a reference but is the best at
introducing all the concepts necessary to
grasp stl completely and good if you
want to learn stl quickly. this book is
easy to read and follow.
data structures with c++ using stl
william ford, willaim topp
isbn #0130858501, prentice hall
stl tutorial and reference guide: c++
programming with the standard template
library
david r. musser, gillmer j. derge, atul
saini
isbn #0201379236, addisonwesley
publications
the c++ templates: the complete guide.
david vandevoorde, nicolai josuttis
isbn #0201734842, addison wesley pub
co.
covers complex use of c++ templates.
c++ how to program
by harvey m. deitel, paul j. deitel
isbn #0131857576, prentice hall
fifth edition. the first edition of this book
(and professor sheely at uta) taught me
to program c++. it is complete and
covers all the nuances of the c++
language. it also has good code
examples. good for both learning and
reference.
dr. dobb's journal
free
subscription
free subscription to the premier resource
for professional programmers and
software developers. multilanguage and
multiplatform with program listings,
coding tips, design issue discussions
and algorithms. subscribe here!
example: boost ptr_list:
#include <boost/ptr_container/ptr_list.hpp>
#include <iostream>
class abc
{
public:
int i;
float j;
};
main()
{
boost::ptr_list<abc> intlist;
boost::ptr_list<abc>::iterator iterintlist;
a->i = 1;
b->i = 2;
c->i = 3;
intlist.push_back(a);
intlist.push_back(b);
intlist.push_back(c);
compile: g++ testboostptrlist.cpp
run: ./a.out
1
2
3
see http://www.boost.org/libs/ptr_container/doc/ptr_list.html
red hat rpm packages: boost, boost-devel newer linux releases like red hat
enterprise 5/centos 5 include boost "ptr_list". rhel4 included boost libraries but did
not include "ptr_list".
example: stl list of pointers:
// g++ -g teststlptrlist.cpp
#include <iostream>
#include <list>
class abc
{
public:
int i;
float j;
};
main()
{
list<abc*> intlist;
list<abc*>::iterator iterintlist;
a->i = 1;
b->i = 2;
c->i = 3;
intlist.push_back(a);
intlist.push_back(b);
intlist.push_back(c);
// free pointers
for (iterintlist = intlist.begin();
iterintlist != intlist.end();
iterintlist++)
{
delete *iterintlist;
}
this example shows how one must delete each pointer individually.
for more information on stl list, see the yolinux.com stl vector and stl list tutorial
gdb: pointers and memory investigation
you can test the above programs and investigate their respective memory clean
up in gdb.
using gdb:
• compile with debugging enabled: g++ -g -o teststlptrlist
teststlptrlist.cpp
• start gdb: gdb teststlptrlist
• show listing with line numbers: list
• set break point: break 30
• run program till break point: run
• find memory location of variable in gdb: print &(c->i)
(gdb) p &(c->i)
$4 = (int *) 0x503050
• dereference memory location: p (*0x503050)
(gdb) p (*0x503050)
$5 = 3
• dereference memory location after memory is freed: p (*0x503050)
(gdb) p (*0x503050)
$7 = 0
using rhel5. note older systems may give you a nonsense value.
books:
the c++ standard library: a tutorial
reference
nicolai m. josuttis
isbn #0201379260, addison wesley
longman
this book is the only book i have seen
which covers string classes as
implemented by current linux distributions.
it also offers a fairly complete coverage of
the c++ standard template library (stl).
good reference book.
stl for c++ programmers
leen ammeraal
isbn #0 471 97181 2, john wiley & sons ltd.
short book which teaches c++ standard
template library (stl) by example. not as
great as a reference but is the best at
introducing all the concepts necessary to
grasp stl completely and good if you want
to learn stl quickly. this book is easy to
read and follow.
data structures with c++ using stl
william ford, willaim topp
isbn #0130858501, prentice hall
stl tutorial and reference guide: c++
programming with the standard template
library
david r. musser, gillmer j. derge, atul saini
isbn #0201379236, addisonwesley
publications
the c++ templates: the complete guide.
david vandevoorde, nicolai josuttis
isbn #0201734842, addison wesley pub co.
covers complex use of c++ templates.
c++ how to program
by harvey m. deitel, paul j. deitel
isbn #0131857576, prentice hall
fifth edition. the first edition of this book
(and professor sheely at uta) taught me to
program c++. it is complete and covers all
the nuances of the c++ language. it also
has good code examples. good for both
learning and reference.
dr. dobb's journal
free subscription to the premier resource
for professional programmers and software
developers. multilanguage and multi
platform with program listings, coding tips,
design issue discussions and algorithms.
subscribe here!
c++ gui framework toolkits:
cross platform (linux, ms/windows, irix, solaris (gnome will be standard on solaris
10))
• gtk.org: gtk+ (cross platform)
o glade tutorial by ishan chattopadhyaya
• trolltech.com: qt used to develop kde (ms/windows, mac, linux)
o ics.com: graphpak, quics table and kd tools (qt widgets) for qt.
• wxwindows.org supports all platforms and many ide's
• fox toolkit linux, windows, most unix
• glut: toolkit and gui written in opengl. cross platform ms/win32 and x11
o api spec
o tutorial
• mozilla xpt can also use xml to define gui layout
• openoffice.org: gsl
• borland.com: clx
• winehq.com winelib libraries to support windows api (linux and bsd only.
not truly cross platform but a good porting tool)
• gnustep: gorm (objective c)
gui framework links:
c++ graphic componets and widgets:
• sl.com sherrill lubinski slgms
dynamic graphic gui components and controls for real time interfaces and
displays. common ".m1" file graphic framework for c++ and java. graphic
sources include visio, bitmaps and dxf. supports pan, zoom, drilldown and
hyperlink capability. supports input as well as displays.
• kinesix.com: sammi similar to slgms but not as good.
• genlogic.com: glg dynamic, data driven visual components.
• int.com
• ilog.com: views diagraming and data graphing capabilities.
c++ web server cgi toolkits:
• gnu c++ cgi
programming web server cgi programs with c++ and the gnu cgicc library
yolinux tutorial
• cgilib red hat
software testing tools:
• cppunit c++ port of ibm's java junit test framework. test report output is in
xml or text.
• cxxtest c++ test framework
• unit++ testing library and framework
c/c++ development environment for linux:
the following tools will provide the infrastructure for a c++ on linux development
environment:
(eclipse ide, scm and the build tools are cross platform and can be duplicated on
ms/windows and other unix environemnts)
• ide (integrated development environment): eclipse
download http://eclipse.org/downloads/ i.e. eclipse-sdk-3.1.1-linux-gtk-
x86_64.tar.gz
eclipse also requires the java installation. see yolinux java download/installation
install eclipse:
o for all on system:
mv eclipse-sdk-3.1.1-linux-gtk-x86_64.tar.gz /opt
this installs eclipse under /opt/eclipse
or
o for yourself only:
download to your home directory.
this installs eclipse under /home/your-user-id/eclipse
be sure to include the following eclipse plugins:
o cdt: c/c++ development plugin for eclipse [cdt manual]
install cdt plugin:
install from web: in eclipse select "help" from the menu bar +
"software updates" + "find and install" + "search for new
features to install" + "next" + "new remote site" to add an
update site with the url:
http://download.eclipse.org/tools/cdt/releases/eclips
e3.1
or
download and install "tar.gz" file:
http://download.eclipse.org/
download appropriate tar bundle for your platform: i.e.
org.eclipse.cdt-3.0.0-linux.x86_64.tar.gz
to the parent of the eclipse directory: i.e. /opt
tar xzf org.eclipse.cdt-3.0.0-
linux.x86_64.tar.gz
(to view contents of tar file: tar tzf
org.eclipse.cdt-3.0.0-linux.x86_64.tar.gz)
verify installation: "help" + "about eclipse sdk" + "plugin details".
"c/c++ development tools" should be listed.
note that cdt is not platform independant. you must download and
install the plugin compiled for your platform. eclipse "help" menu
will include tutorials on cdt after plugin installation. also see "help"
+ "welcome" + select "cdt tutorials".
o subclipse: subversion plugin for eclipse
installation:
download site.0.9.36.zip to eclipse directory:
/opt/eclipse
unzip file (may require installation of rpm package unzip):
unzip site.0.9.36.zip
start eclipse ide: /opt/eclipse/eclipse &
in eclipse select: "help" (from menu bar) + "software
updates" + "find and install" (wait a minute or so for it to
respond. no joke, on slow systems expect to wait over 3
min.) + "search for new features to install" + "next" + "new
local site".
browse to: /opt/eclipse/update/ + select "ok"
select the box next to "eclipse/update" + "next" + select the "i
accept the terms ..." + "next" + features to install: select
"subclipse 0.9.36" + "finish" + "install all" + "yes" to restart
eclipse.
select "window" from the menu bar + "open perspective",
select "other...", select "svn repository exploring", select "ok"
buttons on top right of eclipse window can change back and forth
from the ide to subversion browsing, or select "window" from the
menu bar + "open perspective" + "other" + "svn repository
exploring" and then click "ok".
to add a new svn repository: right click in "svn repository" exploring
pane + right click "new", "repository location". in the "add svn
repository" window enter in the "url:" space under "location" the svn
location + select "finish".
o subversive: another subversion plugin for eclipse. includes more
details for advanced subversion users. displays lots of version info.
annoying if you want a clean simple interface.
o ehep: hex file viewer plugin
o vi plug-in for those who love vi editing and cursor manipulation key
bindings.
o prc-eclipse palm os development plugin
o cca: c source code security analyzer plugin
[potential pitfall]: if eclipse is installed in /opt/eclipse/ for system wide
use, you may want to start eclipse with the following command:
eclipse -data /home/user1/workspace
[potential pitfall]: when downloading eclipse and eclipse plugins, look at
the readme files (eclipse/readme/readme_eclipse.html) to see if you
have a matching gtk+ release. if the version of eclipse and plugins are too
new for the version of gtk+ on your system then eclipse may not display
properly. for older versions of linux, you may have to install older versions
of eclipse and older plugins. i.e. the latest version of eclipse (3.1.1) on the
older red hat linux 8.0 will not operate properly. eclipse 3.1.1 requires gtk
2.2.1 while red hat 8.0 uses gtk 2.0.
[potential pitfall]: don't mix 32 bit java with 64 bit (amd64/em64t) eclipse.
choose all 32 or all 64 bit for eclipse environment.
error in ~/workspace/.metadata/.log
!session 2005-10-31 00:19:28.817 -----------------------------------------------
eclipse.buildid=m20050929-0840
java.version=1.4.2_09
java.vendor=sun microsystems inc.
bootloader constants: os=linux, arch=x86_64, ws=gtk, nl=en_us
command-line arguments: -os linux -ws gtk -arch x86_64
installing the rpm jdk-1_5_0_05-linux-amd64.rpm instead of the i586
version of java to run with the x86_64 version of eclipse fixes this problem.
notes:
o help/welcome screen is default upon startup and gives an
introduction and tutorials on eclipse . you can later return to this
menu: "help" + "welcome".
o i could not find any way to enter gdb debugger commands. the only
input accepted is through the gui. while it offers similar capability to
ms/vc++, hard core debugging is best left to ddd.
• alternate c/c++ ide: i can also recomend the anjuta ide for c/c++
development. solid, simple, intuitive, bug free ide for c/c++ development
on linux. search/indexing, edit, compile and debug.
packages:
• scm (software configuration management):
subversion is a cvs followon with new features. operates much like
old cvs.
o ibm rational clearcase:
clearcase commands
subversion.
• build systems:
o gnu gmake/make: gnu make is a build system based on the original
unix "make" build system but with more features. install rpm
package: make
gnu make manual
o scons: newer python based, cross platform build system. great for
cross platform development (i.e. ms/windows and linux/unix)
• automated nightly/continuous build and reporting systems:
system for subversion, cvs or perforce
• file compare tools:
o gtkdiff: has diff3 and merge features. written with gtk+. after gtkdiff
0.8.0, gnome required.
o fldiff: graphical file and directory diff. (cross platform)
o kdiff3: graphical directory and file diff, merge and edit. kde3/qt
based. supports drag and drop. comes with s.u.s.e. distro. (cross
platform) ms/windows download available.
o kompare: ships with kde sdk. [manual]
o meld: compare, edit and merge.
o mgdiff: [download] motifbased graphical file difference browser and
merge. comes with s.u.s.e. distro.
o tkdiff: [download]
o dirdiff: directory difference viewer.
note:
• also see javadoc like tagged comments the auto document generation facility: doxygen
yolinux tutorial
• the above environment is cross platform and can be used on ms/windows
as well.
• eclipse (and plugins) can be substituted by vi or emacs, ddd or gdb and
raw svn commands.
coding for cross platform deployment with gcc/g++:
the gcc/g++ compiler is compiled with a number of defined preprocessor
variables. the list of defined variables compiled into gcc/g++ can be viewed by
issuing the command: g++ -dumpspecs
the defined preprocessor variables can then be used to handle platform
dependencies.
platform variable: variable: variable: architecture
platform
variable name unix posix _posix_source variable
fedora core 3 linux * *
linux __gnu_linux__
linux
red hat 8 linux * * *
__gnu_linux__
linux
suse 9.2 linux *
__gnu_linux__
sun
sparc __arch64
solaris/sparc
mips
sgi irix/mips sgi * _sgi_source
host_mips
cygwin __cygwin32
* * _x86_
win/intel32 win32
example c/c++ source code 1:
#ifdef sparc
...
#endif
#ifdef linux
...
#endif
#ifdef __cygwin32
...
#endif
...
#if defined(linux) || defined(sparc)
...
#endif
...
example c/c++ source code 2:
#ifdef sgi
#ifdef sgi
return fn_sgi();
#include file_sgi.h
#elif defined(__cygwin32)
#elif defined(sparc)
return fn_win();
#include file_sparc.h
#elif defined(linux)
#elif defined(linux)
return fn_linux(); or #include file_linux.h
#else
#else
struct time ts;
#error unknown os type
return fn_time();
#endif
#endif
...
...
note use of the "#error" for error processing.
notes:
• link error solution:
if you get a similar error classname::classname[not-in-charge]
the solution is to change the order of the libraries.
i.e. if the following compile results in an error:
g++ source-file.cpp -lxxx -lyyy -lzzz -l../xxx -l../yyy -l../zzz
the solution is to change the order of the libraries:
g++ source-file.cpp -lyyy -lzzz -lxxx -l../xxx -l../yyy -l../zzz
the order of the library paths is irrellevant (l).
• architecture independent data types and pointers:
o avoid 32/64 bit cross platform issues by using pointer type:
intptr_t
use include file stdint.h. ms/windows uses int_ptr.
o avoid integer word size issues by using defined types in stdint.h
o libraries are typically found in /usr/lib and /lib. on systems which
mix 32 and 64 bit libraries look for /usr/lib64 and /lib64.
links:
• c++ references:
advanced features
o ucsd.edu: standard c
o cplusplus.com
• c++ library references:
o gnu c++ iostream library
o stl home (sgi)
• c++ api's and toolkits:
• c++ links and info:
o freshsources.com
o c++ pitfalls by cay s. horstmann
o coding standards
o cpp-home.com
o csourcesearch.net c/c++ database of searchable source code
books:
c++ how to program
by harvey m. deitel, paul j. deitel
isbn #0131857576, prentice hall
fifth edition. the first edition of this book
(and professor sheely at uta) taught me to
program c++. it is complete and covers all
the nuances of the c++ language. it also
has good code examples. good for both
learning and reference.
exceptional c++: 47 engineering puzzles,
programming problems and solutions
by herb sutter
isbn #0201615622, addisonwesley
professional
advanced c++ features and stl.
more exceptional c++
by herb sutter
isbn #020170434x, addisonwesley
professional
effective c++: 50 specific ways to improve
your programs and design (2nd edition)
by scott meyers
isbn #0201924889, addisonwesley
professional
more effective c++: 35 new ways to
improve your programs and designs
by scott meyers
isbn #020163371x, addisonwesley
professional
dr. dobb's journal
free subscription to the premier resource
for professional programmers and software
developers. multilanguage and multi
platform with program listings, coding tips,
design issue discussions and algorithms.
subscribe here!
comparison of fortran and c/c++ datatypes:
fortran
c/c++
integer*2
short int
integer
long int or int
integer iabc(2,3)
int iabc[3][2];
logical
long int or int
logical*1
bool
(c++, one byte)
real
float
real*8
double
complex
struct{float r, i;}
double complex
struct{double dr, di;}
character*6 abc
char abc[6];
parameter
#define parameter value
note:
• order of multi dimensional arrays in c/c++ is the
opposite of fortran.
• it is best not to redimension multi dimensional
arrays within a function. pass array size "n" and
declare array as x[n][];
linking fortran and c subroutines:
note: the entry point names for some fortran compilers
have an underscore appended to the name. this is also
true for common block/structure names as shown above.
fortran
c
call subra( ... )
subra_( ... )
the f77 comiler flags "-fno-underscore" and "-fno-
second-underscore" will alter the default naming in the
object code and thus affect linking. one may view the
object file with the command nm (i.e.: nm file.o).
note: the case in fortran is not preserved and is
represented in lower case in the object file. the g77
compiler option "-fsource-case-lower" is default. gnu
g77 fortran can be case sensitive with the compile option
"-fsource-case-preserve".
note: when debugging with gdb, the fortran subroutines
must be referenced with names as they appear in the
symbol table. this is the same as the "c" representation.
thus when setting a break point at the fortran subroutine
subra(), issue the comand "break subra_".
man pages:
• nm list symbols from object files
• g77/f77
function arguments:
all arguments in fortran are passed by reference and not
by value. thus c must pass fortran arguments as a
pointer.
fortran
c
call subra( i, x)
subra_( int *i, float *x)
character variables:
• linux and gnu compilers: when passing character
strings, the length must follow as separate
arguments which are passed by value.
fortran
c
call subra( string_a, string_b)
len_a = strlen(string_a);
len_b = strlen(string_a);
subra_( char *string_a, len_a, char *string_b, len_b)
• i have also seen the passing of a data structure
containing two elements, the character string and
an integer storing the length. this is common with
databases such as oracle.
• classic at&t unix:
when passing character strings, the length must
be appended as separate arguments which are
passed by value.
fortran
c
call subra( string_a, string_b)
subra_( char *string_a, char *string_b, len_a, len_b)
alternate returns:
fortran
c
call sub(a,b,c,*,*)
return 1
end
int sub_(int *a,int *b,int *c)
{
return(1)
}
note: when using alternate returns to turn on/off an
intlevel by returning a 1/0 you must use a fortran wrapper
to perform this function on the csc norwich mainframe.
this is because the c compiler is old.
• buffering output: your machine may be configured
where the output buffering defaults for fortran and c may
be configured the same or differently. c output may be
buffered buffered while fortran may not. if so, execute a
function initialization task to unbuffer c otherwise print
statements for c will be output out of order and at the
end.
#include <stdio.h>
void ersetb(void){
setbuf(stdout,null); /* set output to
unbuffered */
}
common blocks:
fortran common block and global c/c++ extern structs of
same name are equivalent. never use unnamed
common blocks! reference variables in same order, same
type and with the same name for both c and fortran.
character data is aligned on word boundaries.
fortran:
double precision x
integer a, b, c
common/abc/ x, a, b, c
c:
extern struct{
double x;
int a, b, c;
} abc_;
c++:
extern "c" {
extern struct{
double x;
int a, b, c;
} abc_;
}
note: use of extern requires that the common block be
referenced first by fortran. if referenced first by c then
drop the extern. the extern statement states that it is
trying to reference memory which has already been set
aside elsewhere.
[potential pitfall]: byte alignment can be a source of data
corruption if memory boundaries between fortran and
c/c++ are different. each language may also align
structure data differently. one must preserver the
alignment of memory between the c/c++ "struct" and
fortran "common block" by ordering the variables in the
exact same order and exactly matching the size of each
variable. it is best to order the variables from the largest
word size down to the smallest. start with "double"
followed by "float" and "int". bool and byte aligned data
should be listed last.
fortran:
integer a, b, c
double precision d, e, f
logical*1 flag
common/abc/ a, d, flag, b, e
c:
extern struct{
int a;
double d;
bool flag;
int b;
double e;
} abc_;
c++:
extern "c" {
extern struct{
int a;
double d;
bool flag;
int b;
double e;
} abc_;
}
using gdb to examine alignment:
• set a breakpoint in the c/c++ section of code which
has visibility to the struct.
• while in a c/c++ section of code:
(gdb) print &abc_.b
$3 = (int *) 0x5013e8
• set a breakpoint in the fortran section of code
which has visibility to the common block.
• while in a fortran section of code:
(gdb) print &b
$2 = (ptr to -> ( integer )) 0x5013e8
this will print the hex memory address of the variable as
c/c++ and fortran view the variable. the hex address
should be the same for both. if not, the data will be
passed improperly.
forcing alignment with compiler arguments: mixing
intel fortran compiler and gnu g++: use the following
compiler flags to force a common memory alignment and
padding to achieve a common double word alignment of
variables:
• intel c/c++: -zp8
• gnu g77: -malign-double
example:
fortran program calling a c function:
testf.f
testc.c
program test
ii = 2
jj = 3
kk = 4
ff = 9.0567
cc = 'example of a character string'
write(6,10) ii, ff
10 format('ii= ',i2,' ff= ',f10.4)
call abc(ii)
write(6,20) ii
20 format('ii= ',i2)
write(6, 40) cc
40 format(a32)
stop
end
subroutine abc(jj)
jj = jj * 2
return
end
#include <stdio.h>
extern struct
{
int ii, jj, kk;
} ijk_;
ijk_.ii *=2;
ijk_.jj *=2;
ijk_.kk *=2;
return(1);
}
compile:
• f77 -c testf.f
• gcc -c testc.c
note: if there is use of c/c++ standard libraries you may
have to include the following linking arguments: -lc or
-lstdc++
run: ./test
ii= 2 ff= 9.0567
ii= 4
ii= 4 jj= 3 kk= 4
from doubleijk: example of a character string
ii= 8 jj= 6 kk= 8
example of a character string
c++ calling a fortran function:
testc.cpp
testf.f
#include <iostream>
extern"c" {
void fortfunc_(int *ii, float *ff);
}
main()
{
int ii=5;
float ff=5.5;
fortfunc_(&ii, &ff);
return 0;
}
subroutine fortfunc(ii,ff)
integer ii
real*4 ff
write(6,100) ii, ff
100 format('ii=',i2,' ff=',f6.3)
return
end
compile:
• f77 -c testf.f
• g++ -c testc.cpp
run: ./test
ii= 5 ff= 5.500
vax extensions:
the gnu fortran compilers have only ported a small subset
of vax extensions. the vast majority will require a clever
rewrite.
vax variable format expressions:
vax expression
ported to gnu fortran
integer*4 ivar(3), nfor
nfor=3
...
vax intrinsic functions:
many are not supported in gnu fortran and require the
creation of an equivalent library written in "c".
return type
vax fortran intrinsic function
argument type
integer*4
nint(arg)
jnint(arg)
real*4
integer*4
idnint(arg)
jidnint(arg)
real*8
integer*2
inint(arg)
real*4
integer*8
knint(arg)
real*4
integer*2
iidnnt(arg)
real*8
integer*8
kidnnt(arg)
real*8
integer*2
iiqnnt(arg)
real*16
integer*4
iqnint(arg)
jiqnnt(arg)
real*16
integer*8
kiqnnt(arg)
real*16
example: inint.c
short int inint_(float *rval)
{
if(*rval < 0.0)
return (*rval - 0.5);
else
return (*rval + 0.5);
}
• gcc -c inint.c
• gcc -c idnint.c
• ...
c++:
when mixing fortran with c++, name mangling must be
prevented.
#ifdef _cplusplus
extern"c" {
#endif
.
.
place declarations here
.
.
#ifdef __cplusplus
}
#endif
the intel fortran compiler:
installation: (as root)
• mkdir /opt/intel
• cd /opt/intel
• move intel fortram compiler tar ball to this
directory.
• cd 1_fc_c_9.0.033/
• ./install.sh
1 : install
2 : provide name of an existing license file.
license file path :
/path-to-license-file/commercial_for_1_f2wc-
5fdzv87r.lic
(file copied to /opt/intel/licenses)
1 (typical installation)
type "accept" to agree to license terms.
accept default location: /opt/intel/fc/9.0
accept default location: /opt/intel/idb/9.0
x : installation done
compiler use and user configurations:
file: $home/.bashrc
..
...
#
# intel compiler
#
...
...
export ld_library_path
export path
file: makefile (snipet)
f77=/opt/intel/fc/9.0/bin/ifort
f77flags= -extend_source -fpp -f77rtl -intconstant
-ftz -pad-source -sox \
-lowercase -warn alignments -cxxlibgcc
cxx=g++
cppflags=-wpadded -wpacked
ldflags=-l/opt/intel/fc/9.0/lib -lifport -lifcore
-limf -wabi -wcast-align
debug=-g
objs=file1.o file2.o
cpp-exe: $(objs)
$(cc) $(ldflags) -o name-of-exe $(objs)
.cpp.o:
$(cxx) -c $(debug) $(cppflags) $<
.f.o:
$(f77) -c $(debug) $(f77flags) $<
intel compiler directives:
directive
description
extend_source
length of line in source file allows for greater than 72
characters.
vax
vax fortran runtime behavior. changes read behavior. i
never use this.
f77rtl
fortran 77 runtime behavior.
fpp
run preprocessor. i.e. handles #define and #ifdef
macros.
intconstant
use fortran 77 semantics to determine the kind of
parameter for integer constants.
ftz
flushes denormal results to zero.
padsource
specifies that fixedform source records shorter than the
statement field width should be padded with spacs (on
the right) to the end of the field.
lowercase
all function names are represented as lower case
symbols.
sox
store compiler options and version in the executable.
warn alignments
warning if common block records require padding for
alignment.
align all
will get rid of warning: "because of common, the
alignment of object is inconsistent with its type
[variable-name]
this requires a matching alignment for all code which links
with this, c, c++ or fortan.
use gnu g++ or intel c++ compiler to compile and link with
main():
g++ -o name-of-exe main_prog.cpp file1.o file2.o -l
/opt/intel/fc/9.0/lib -lifport -lifcore -limf -wabi
-wcast-align
using ddd as a frontend for the intel debugger:
ddd --debugger "/opt/intel/idb/9.0/bin/idb
-gdb" exe-file
[potential pitfall]: i found that i could not install the intel
fortran compiler from an nfs mounted drive. i had to copy
the intel installation files to a local drive and install from
there.
links:
• mixed language programming using c++ and fortran 77
• fortran gl api: (sgi gl library emulation for linux)
o ygl: written in x11 (2d) and opengl (3d) for c
and fortran
o repgl
books:
"introduction to programming with fortran"
with coverage of fortran 90, 95, 2003 and 77
by ian chivers, jane sleightholme
springer; 1st edition, isbn# 1846280532
"fortran 90 for scientists and engineers"
by brian hahn
butterworthheinemann, isbn# 0340600349
"introduction to fortran 90 for engineers and scientists"
by larry r. nyhoff, sanford leestma
prentice hall; 1st edition, isbn# 0135052157
dr. dobb's journal
free subscription to the premier resource for professional
programmers and software developers. multilanguage
and multiplatform with program listings, coding tips,
design issue discussions and algorithms. subscribe here!
free
subscription
return to
http://yolinux.co
m for more linux
links, information
and tutorials
return to yolinux
tutorial index
feedback form
copyright © 2001,
2005, 2006 by greg
ippolito
yolinux tutorial software
development on linux
programming linux applications
this tutorial covers
the tools available
for programming
languages
supported by linux.
java programmers,
also see the yolinux
java on linux tutorial.
c++ programmers,
also see: yolinux c++
on linux tutorial.
contents:
• #
compile
rs
• #
develop
ment
tools
• # ide:
integrat
ed
develop
ment
environ
ment
• #
memory
debuggi
ng tools
• #
softwar
e
design
• # cm:
change
/
configur
ation
manage
ment
• # build
systems
• #
autocon
f
• #
nightly /
contino
us build
and test
systems
• # bug /
change
tracking
• #
develop
ment
libraries
• #
softwar
e install
/ update
systems
• # linux
softwar
e
develop
ment
notes
• # links
• # books
return to http://yolinux.com for more linux links,
information and tutorials
return to yolinux tutorial index
feedback form
copyright © 2000, 2001, 2002, 2003, 2004, 2005, 2006 by
greg ippolito