<?

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; }

// a similar function, returns the number of occurances function instrcount($string,$find,$casesensitive = false) { $i=0; $x=0;
while (strlen($string)>=$i) { unset($substring); if ($casesensitive) {

$find=strtolower($find); $string=strtolower($string); } $substring=substr($string,$i,strlen($find));
if ($substring==$find) $x++;

$i++; } return $x; }

// another similar function, this will return the position of // the string. returns -1 if the string does not exist function instrpos($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 $i;

$i++; } return -1; }

?>

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; }

// a similar function, returns the number of occurances function instrcount($string,$find,$casesensitive = false) { $i=0; $x=0;
while (strlen($string)>=$i) { unset($substring); if ($casesensitive) {

$find=strtolower($find); $string=strtolower($string); } $substring=substr($string,$i,strlen($find));
if ($substring==$find) $x++;

$i++; } return $x; }

// another similar function, this will return the position of // the string. returns -1 if the string does not exist function instrpos($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 $i;

$i++; } return -1; }

?>

instr function

..

a modest stl tutorial
i am using a software tool called hyperlatex to create this document. the tutorial is also available in gzip-compressed postscript form or zip-compressed postscript form. for those wanting to install a copy of these pages on their system, they may be freely copied providing they are not modified in any significant way (other than, say, locale changes). the file tut.tar.z contains a tarred distribution of the pages. please note that i will be making modifications to this document in the coming months, so you may want to occasionally check for changes. i will start putting in version numbers, and if i can manage to, changebars.

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.

version 1: standard c++
here is a standard c++ program to read a list of integers, sort them and print them:
#include <stdlib.h> #include <iostream.h>

// a and b point to integers. cmp returns -1 if a is less than b, // 0 if they are equal, and 1 if a is greater than b. inline int cmp (const void *a, const void *b) { int aa = *(int *)a; int bb = *(int *)b; return (aa < bb) ? -1 : (aa > bb) ? 1 : 0; } // read a list of integers from stdin // sort (c library qsort) // print the list main (int argc, char *argv[]) { const int size = 1000; // array of 1000 integers int array [size]; int n = 0; // read an integer into the n+1 th element of array while (cin >> array[n++]); n--; // it got incremented once too many times qsort (array, n, sizeof(int), cmp); for (int i = 0; i < n; i++) cout << array[i] << "\n"; }

version 2: containers, iterators, algorithms
stl provides a number of container types, representing objects that contain other objects. one of these containers is a class called vector that behaves like an array, but can grow itself as necessary. one of the operations on vector is push_back, which pushes an element onto the end of the vector (growing it by one). a vector contains a block of contiguous initialized elements -- if element index k has been initialized, then so have all the ones with indices less than k. a vector can be presized, supplying the size at construction, and you can ask a vector how many elements it has with size. this is the logical number of elements -- the number of elements up to the highest-indexed one you have used. there is a also a notion of capacity -- the number of elements the vector can hold before reallocating.

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 #include #include #include #include <string.h> <algo.h> <vector.h> <stdlib.h> <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-theend 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 pastthe-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.

so input is done like this:

typedef istream_iterator<int,ptrdiff_t> istream_iterator_int; vector<int> v; istream_iterator_int start (cin); istream_iterator_int end;

back_insert_iterator<vector<int> > dest (v); copy (start, end, dest);

similarly, to print out the values after sorting, we use copy:

copy (v.begin(), v.end(), ostream_iterator<int> (cout, "\n")); ostream_iterator is another adaptor; it provides output iterator functionality: assigning to the dereferenced iterator will write the data out. the ostream_iterator constructor

takes two arguments: the stream to use and the separator. it prints the separator between elements.

putting this all together,
#include #include #include #include #include <string.h> <algo.h> <vector.h> <stdlib.h> <iostream.h>

main () { vector<int> v; istream_iterator<int,ptrdiff_t> start (cin); istream_iterator<int,ptrdiff_t> end; back_insert_iterator<vector<int> > dest (v); copy (start, end, dest); sort(v.begin(), v.end()); copy (v.begin(), v.end(), ostream_iterator<int>(cout, "\n"));

}

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.

examples using containers
here is a program that generates a random permutation of the first n integers, where n is specified on the command line.
#include #include #include #include <iostream.h> <vector.h> <algo.h> <iterator.h>

main (int argc, char *argv[]) { int n = atoi (argv[1]); // argument checking removed for clarity vector<int> v; for (int i = 0; i < n; i++) // append integers 0 to n-1 to

v

v.push_back (i); random_shuffle (v.begin(), v.end()); // shuffle copy (v.begin(), v.end(), ostream_iterator<int> (cout, "\n")); // print } this program creates an empty vector and fills it with the integers from 0 to n. it then

shuffles the vector and prints it out. it is quite common to want a sequence of elements with arithmetically increasing values; common enough that there is an algorithm that does something like this for us. it is called iota:
template <class forwarditerator, class t> void iota (forwarditerator first, forwarditerator last, t value);

this function allows us to fill a range of a container with increasing values, starting with some initial value:
vector<int> a(100); // initial size 100 iota (a.begin(), a.end(), 0); this call will fill the array a with the values

0, 1, 2...

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 #include #include #include <iostream.h> <vector.h> <algo.h> <iterator.h>

main (int argc, char *argv[]) { int n = atoi (argv[1]); // argument checking removed for clarity vector<int> v; iota_n (v.begin(), 100, back_inserter(v)); random_shuffle (v.begin(), v.end()); // shuffle copy (v.begin(), v.end(), ostream_iterator<int> (cout, "\n")); // print } back_inserter is a function that takes a container as an argument, and returns an

iterator. the iterator is defined in such a way that writing a value through it and incrementing it will cause the value to be appended to the container.

iterators
iterators are like location specifiers for containers or streams of data, in the same way that an int* can be used as a location specifier for an array of integers, or an ifstream can be used as a location specifier for a file. stl provides a variety of iterators for its different collection types and for streams. input iterators

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; } };

requirements: if a is an instance of the type s, and b is an instance of the type t, the following expressions must be valid:
s a (b) a += b

this template class can be used with any types s and t that satisfy the requirements; for example, if both s and t are int, the requirements are satisfied:
vector<int> v (365); generate (v.begin(), v.end(), iota<int,int> (0, 1)); cout << v << endl;

it is a bit tedious to have to keep specifying the types of the arguments; you might hope that the compiler could figure them out from the expressions provided. unfortunately, you can't create an instance of a template class without providing the types, but you <em>can</em> use a function to help out, and get the same effect:
template <class s, class t> iota<s, t> makeiota (const s& s, const t& t) { return iota<s, t> (s, t); }

and now the user code becomes:
vector<int> v (365); generate (v.begin(), v.end(), makeiota (0, 1)); cout << v << endl;

here, the function object is storing some state between calls; it is what is called a <em>closure</em> in some languages. anything needed to initialize the data is provided in the construction of the function object. predicates the second type of function object is used to test things; the parenthesis operator will be defined to return something that can be tested for truth. uses a function object to test each element of a range, returning an iterator pointing to the first element that satisfies the test. in this case, the function object takes an argument, the element of the range, and returns a boolean:
find_if bool greaterthanzero (int i) return i > 0;

this could be used to move to the first strictly positive element of a range:
typedef vector<int>::iterator iterator; typedef vector<int> vector; typedef ostream_iterator<int> output; 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; } }; typedef vector<int>::iterator iterator; typedef vector<int> vector; typedef ostream_iterator<int> output; vector v (100); generate (v.begin(), v.end(), rand); iterator iter (v); while (iter != v.end()) { iter = find (v.begin(), v.end(), inrange (0, 10000)); cout << *iter << endl; }

here we find, and print, all the elements of a vector that fall within a particular range:

it is possible to simulate lexical scoping. there are many pre-defined (templated, of course) function objects that can be used -many algorithms expect a function as an argument. example

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. other adaptors provide backward-moving iterators from forward-moving iterators, and queues from lists, for example. adaptors are very useful, but you don't have to understand them to use stl; treat them as black magic for now.

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.

example 2: finding scheduling conflicts
there is just a sketch of the problem and solution here. students are associated with a list of courses, and courses with a list of timeslots. we want to know which students have different courses with same timeslot. uses:
• • • •

algorithms: copy, find iterators: istream_iterator, ostream_iterator adaptors: istream_iterator, ostream_iterator containers: multiset, set

problem i have a file of information about students, of the form:
name [course...] ...

and a file of information about courses, of the form:
course [timeslot...] ...

the names, courses and timeslots are arbitrary strings, but for simplicity we will assume that each token is one word (e.g., we write student names like jak_kirman. the program must print out the names of students who have collisions in their course schedules, along with the courses causing the collisions. repetitions in the lists of courses or lists of timeslots should be ignored.

example 3: stream calculator
there is just a sketch of the problem and solution here. i want to give my program command-line expressions in reverse polish notation, like a b + to mean (a+b). the elements of expressions can be constants or filenames. the program should repeatedly evaluate the expression, replacing any occurrence of a file name with the next number read from that file. as an added bonus, the types we define will allow us to combine arbitrary streams of input with arbitrary operations.
• • • • •

algorithms: copy, find iterators: input_iterator, istream_iterator, ostream_iterator functions: binary_function, unary_function adaptors: istream_iterator, ostream_iterator containers: stack, vector

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; template <class t>

typedef stack<vector<input_iterator_p<t> > > input_stack;

as each token is read from the command line, we create an iterator, using the stack as the source of any arguments. at the end, the stack should have a single iterator, which we can then copy to the output stream. the only tricky part here is the "dynamic inheritance". i will have a kind of input_iterator called constant_source, for which
• •

increment does nothing dereference returns the constant

template <class t, class distance> // default distance = ptrdiff_t class constant_source : public input_iterator<t,distance> { private: const t& value; bool bad; public: friend bool operator==(const number_source<t, distance>& x, const number_source<t, distance>& y) { return x.bad == y.bad; } number_source() : bad (true) {} number_source (const t& t) : value (t), bad (false){} number_source<t,distance>& operator++(int = 0) { return *this; } const t& operator*() const { return value; } }; a combiner input iterator is created from two input iterators s1 and s2, and a function object func of type binary_function<t,t,t>.

increment increments s1 and s2 dereference dereferences s1 and s2, applies func and returns the result
template <class t, class distance> // default distance = ptrdiff_t class combiner : public input_iterator<t,distance> { protected: void read() { ++source1; ++source2; value = func (*source1, *source2); } friend bool operator==(const combiner<t, distance>& x, const combiner<t, distance>& y) { return (x.source1 == source1) && (y.source1 == source2); } combiner() : source1(), source2() {} combiner (input_iterator<t,distance>& s1, input_iterator<t,distance>& s2, binary_function<t,t,t> f) : source1 (s1), source2 (s2), func (f) combiner<t,distance>& operator++() { read(); return *this; } combiner<t,distance>& operator++(int) { combiner<t,distance>& tmp = *this; read(); return tmp; const t& operator*() const { return value; } }; now, for example, to read pairs from file1 and file2 and print their sums: main (int argc, char *argv[]) {

combiner<double> adder (istream_iterator<double>(ifstream (argv[1])), istream_iterator<double>(ifstream (argv[2])), plus<double>); } copy (adder, combiner<double>(), ostream_iterator<double>(cout));

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) { // we want to add n to each element of v struct addn : public unary_function<int> { addn(int n) : _n (n) {}; int operator() (const int& k) { return k + n; } }; transform (v.begin(), v.end(), v.begin(), addn(n));

}

null iterator values
why doesn't stl have null iterator values? stl iterators are supposed to be generalized pointers, right? that phrase has been bandied about a great deal, but it is very misleading. stl iterators are generalizations of array pointers, that is, a pointer set to point into an array, and then incremented or decremented. it does not make sense to talk about such a pointer having a null value. in c and c++, null pointers are used to indicate errors, or abnormal conditions. when you have a c++ iterator type, there is normally only one kind of error value it will return: one indicating "i fell off the end of the list". it is natural, therefore, for most iterator classes to use null as the "past-the-end" value. if you find yourself wanting a null stl iterator, you probably want the past-the-end value.

alice vs humpty const
in "alice through the looking glass", alice meets humpty dumpty, and they have a discussion during which humpty uses a word to mean something completely different from its usual meaning. alice protests that that was not what the word meant; words mean what the dictionary says. humpty says that words mean what he wants them to mean; he pays them enough. courtesy of eric anderson and j coleman, here is the section, taken from <a

href="http://www.cs.indiana.edu/metastuff/looking/looking.txt.gz">the text at indiana university</a>:
`when _i_ use a word,' humpty dumpty said in rather a scornful tone, `it means just what i choose it to mean -- neither more nor less.' `the question is,' said alice, `whether you can make words mean so many different things.' `the question is,' said humpty dumpty, `which is to be master - that's all.'

alice const is the "dictionary" const, or language definition const, which says that a member function is constant if and only if the member function does not modify any of the data members. humpty const is the "conceptual" const, or design const, which says that the object has the same appearance to the user after the operation as before, and that it is ok to apply the operation to objects that must not be modified. in a string class,
class string { private: char *_data; mutable int _len; public: string (const char *data) : _data (data), _len (-1) { } void capitalize() { char *p = _data; while (*p) *p = toupper(*p++); } int length() const { if (_len == -1) _len = strlen (_data); return _len; } };

capitalize is alice const (the value of the pointer doesn't change), but not humpty const -to the user it seems like a mutating function, and it should not be applied to objects that are constant. length is humpty const (the user thinks of it as an operation that does not modify the string, and it can be applied to constant strings), but not alice const, since _len changes. the keyword mutable allows you to change a variable so specified in a const member function. jak@cs.brown.edu

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> using namespace std; main() { vector<string> ss; ss.push_back("the number is 10"); ss.push_back("the number is 20"); ss.push_back("the number is 30"); cout << "loop by index:" << endl; int ii; for(ii=0; ii < ss.size(); ii++) { cout << ss[ii] << endl; } cout << endl << "constant iterator:" << endl; vector<string>::const_iterator cii; for(cii=ss.begin(); cii!=ss.end(); cii++) { cout << *cii << endl; } cout << endl << "reverse iterator:" << endl; vector<string>::reverse_iterator rii; for(rii=ss.rbegin(); rii!=ss.rend(); ++rii) { cout << *rii << endl; } cout << endl << "sample output:" << endl; cout << ss.size() << endl; cout << ss[2] << 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> using namespace std; main() { // declare size of two dimensional array and initialize. vector< vector<int> > vi2matrix(3, vector<int>(2,0)); vi2matrix[0][0] vi2matrix[0][1] vi2matrix[1][0] vi2matrix[1][1] vi2matrix[2][0] vi2matrix[2][1] = = = = = = 0; 1; 10; 11; 20; 21;

cout << "loop by index:" << endl; int ii, jj; for(ii=0; ii < 3; ii++) { for(jj=0; jj < 2; jj++) { cout << vi2matrix[ii][jj] << endl; } } }

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> using namespace std; main() { vector<int> vi1matrix(3,0); another // vector length of 4 initialized to hold

// vector length of 3 initialized to 0

// vector vi1matrix which has been initialized to 0 vector< vector<int> > vi2matrix(4, vi1matrix); // vector of length 5 containing two dimensional vectors vector< vector< vector<int> > > vi3matrix(5, vi2matrix); ...

or declare all in one statement: 
#include <iostream> #include <vector> using namespace std; main() { vector< vector< vector<int> > > vi3matrix(2, vector< vector<int> > (3, vector<int>(4,0)) ); for(int kk=0; kk<4; kk++) { for(int jj=0; jj<3; jj++) { for(int ii=0; ii<2; ii++) { cout << vi3matrix[ii][jj][kk] << endl; } } }

}

using an iterator: 

example of iterators used with a two dimensional vector. 
#include <iostream> #include <vector> using namespace std; 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); cout << endl << "using iterator:" << endl; for(iter_ii=vi2matrix.begin(); iter_ii!=vi2matrix.end(); iter_ii++) { for(iter_jj=(*iter_ii).begin(); iter_jj!=(*iter_ii).end(); iter_jj++) { cout << *iter_jj << endl; } } }

compile: g++ examplevector2.cpp  run: ./a.out 
using iterator: 10 20 30 100 200 300

constructor/declaration:  method/operator vector<t> v; vector<t> v(size_type n); description vector declaration of data type "t". declaration of vector containing type "t" and of  size "n" (quantity).

vector<t> v(size_type n,const t&  t);

declaration of vector containing type "t", of  size "n" (quantity) containing value "t". declaration: vector(size_type n, const t&
t)

vector<t>  v(begin_iterator,end_iterator);

copy of vector of data type "t" and range  begin_iterator to end_iterator. declaration: template vector(inputiterator,
inputiterator)

size methods/operators:  method/operator empty() size() resize(n, t=t()) description returns bool (true/false). true if empty. declaration: bool empty() const number of elements of vector. declaration: size_type size() const adjust by adding or deleting elements of vector so that its size  is "n". declaration: void resize(n, t = t()) max number of elements of vector before reallocation. declaration: size_type capacity() const max number of elements of vector set to "n" before  reallocation. declaration: void reserve(size_t) max number of elements of vector possible. declaration: size_type max_size() const

capacity() reserve(size_t n)

max_size()

note: size_type is an unsigned integer.  other methods/operators:  method/operator erase() clear() erase(iterator) erase(begin_iterator,end_iterator) description erase all elements of vector. declaration: void clear() erase element of vector. returns iterator to  next element. erase element range of vector. returns 

iterator to next element. declarations: 
• iterator erase(iterator pos)  iterator erase(iterator first, iterator last) 

= example: x=y()

assign/copy entire contents of one vector  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) v[index]

element of vector. left and right value  assignment: v.at(i)=e; and e=v.at(i); declaration: reference
operator[](size_type n)

front() v[0] back()

first element of vector. (left and right value  assignment.) declaration: reference front() last element of vector. (left and right value  assignment.) declaration: reference back() add element to end of vector. declaration: void push_back(const t&) remove element from end of vector. declaration: void pop_back() assign first n elements a value "t". replace data in range defined by iterators. declaration:  insert at element "iterator", element of 

push_back(const t& value) pop_back() assign(size_type n,const t& t) assign(begin_iterator,end_iterator) insert(iterator, const t& t)

value "t". declaration: iterator insert(iterator
pos, const t& x)

insert(iterator pos, size_type n, const  t& x)

starting before element "pos", insert first n  elements of value "x". declaration: void insert(iterator pos,
size_type n, const t& x)

insert(iterator pos,  begin_iterator,end_iterator)

starting before element "pos", insert  range begin_iterator to end_iterator. declaration: void insert(iterator pos,
inputiterator f, inputiterator l)

swap(vector& v2) iterator methods/operators:  method/operator begin() end() rbegin() rend() ++ ­­ vector links: 
• •

swap contents of two vectors. declaration: void swap(vector&) description return iterator to first element of vector. declaration: const_iterator begin() const return iterator to last element of vector. declaration: const_iterator end() const return iterator to first element of vector (reverse order). declaration: const_reverse_iterator rbegin() const return iterator to last element of vector (reverse order). declaration: const_reverse_iterator rend() const increment iterator. decrement iterator.

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; // simple example uses type int main() { list<int> l; l.push_back(0); l.push_front(0); l.insert(++l.begin(),2); argument l.push_back(5); l.push_back(6); list<int>::iterator i; for(i=l.begin(); i != l.end(); ++i) cout << *i << " "; cout << endl; return 0; }

// insert a new element at the end // insert a new element at the beginning // insert "2" before position of first // (place before second argument)

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 built­in 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 member­wise 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; // the list stl template requires overloading operators =, == and <. 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; // constructor

};

aaa::aaa() { x = 0; y = 0; z = 0; }

aaa::aaa(const aaa &copyin) value. { x = copyin.x; y = copyin.y; z = copyin.z; }

// copy constructor to handle pass by

ostream &operator<<(ostream &output, const aaa &aaa) { output << aaa.x << ' ' << aaa.y << ' ' << aaa.z << endl; return output; } aaa& aaa::operator=(const aaa &rhs) { this->x = rhs.x; this->y = rhs.y; this->z = rhs.z; return *this; } int aaa::operator==(const aaa &rhs) const { if( this->x != rhs.x) return 0; if( this->y != rhs.y) return 0; if( this->z != rhs.z) return 0; return 1; } // 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); ablob.x=5; l.push_back(ablob); wise ablob.z=3.2355; l.push_back(ablob);

// insert a new element at the end // object passed by value. uses default member// copy constructor

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; cout << "sorted: " << endl; l.sort(); 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.  boost ptr_list and stl list of pointers ­ yolinux tutorial 

also see boost ptr_list ­ used to hold list of pointers. 

stl vector vs list function comparison:
function destructor empty() vector list yes yes yes yes yes constructor yes

size() resize() capacity() reserve() erase() clear() operator= operator< operator== operator[] at() front() back()

yes yes yes yes yes yes yes yes yes yes yes yes yes

yes yes no no yes yes yes yes yes yes no no yes yes yes yes yes yes yes yes yes yes yes yes yes yes yes yes

max_size() yes

push_back() yes pop_back() yes assign() insert() swap() yes yes yes

push_front() no pop_front() no merge() remove() reverse() sort() splice() unique() no no no no no no

remove_if() no

links/information:

gnu string class ­ yolinux tutorial 

• • •

"modest tutorial"  technical university vienna tutorial  boost pointer container library ­ containter libraries (vectors,lists,maps,...) to 

hold pointers. 
• •
an old fashioned linked list with pointers (old homework problem) 

gtk api: 
o o
singly linked list api  doubly linked list 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, addison­wesley  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. multi­language and  multi­platform with program listings,  coding tips, design issue discussions  and algorithms. subscribe here! 
free subscription 

example: boost ptr_list:
#include <boost/ptr_container/ptr_list.hpp> #include <iostream> using namespace std; class abc { public: int i; float j; }; main() { boost::ptr_list<abc> intlist; boost::ptr_list<abc>::iterator iterintlist; abc *a= new abc; abc *b= new abc;

abc *c= new abc; a->i = 1; b->i = 2; c->i = 3; intlist.push_back(a); intlist.push_back(b); intlist.push_back(c); for (iterintlist = intlist.begin(); iterintlist != intlist.end(); iterintlist++) { cout << iterintlist->i << endl; } intlist.clear(); // all pointers held in list are deleted. }

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".  ubuntu installation: apt-get install libboost-dev libboost-doc 

example: stl list of pointers:
// g++ -g teststlptrlist.cpp #include <iostream> #include <list> using namespace std; class abc { public: int i; float j; }; main() {

list<abc*> intlist; list<abc*>::iterator iterintlist; abc *a= new abc; abc *b= new abc; abc *c= new abc; a->i = 1; b->i = 2; c->i = 3; intlist.push_back(a); intlist.push_back(b); intlist.push_back(c); for (iterintlist = intlist.begin(); iterintlist != intlist.end(); iterintlist++) { cout << (*iterintlist)->i << endl; } // free pointers for (iterintlist = intlist.begin(); iterintlist != intlist.end(); iterintlist++) { delete *iterintlist; } intlist.clear(); // list is deleted. }

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.  see the yolinux.com gdb tutorial.  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, addison­wesley  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. multi­language 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 o o o •

yolinux tutorial: gtk+ tips and tricks ­ building a gui using gtk+  linux magazine: gui building with gtk+  glade home page ­ gtk+ gui builder.  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 o • •

api spec  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: 
• • •
ibm developer site: gui components and vendors ­ slightly out of date  list of cross platform gui libraries  another list of cross platform gui libraries 

c++ graphic componets and widgets:

sl.com ­ sherrill ­ lubinski sl­gms 

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, drill­down and  hyperlink capability. supports input as well as displays. 
• • • •
kinesix.com: sammi ­ similar to sl­gms 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  yacgi: yet another c/c++ library for cgi programming  c++ cgi for sql/oracle 

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-gtkx86_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  tar xzf eclipse-sdk-3.1.1-linux-gtk-x86_64.tar.gz 

this installs eclipse under /opt/eclipse  or 
o

for yourself only: 
 

download to your home directory. 
tar xzf eclipse-sdk-3.1.1-linux-gtk-x86_64.tar.gz 

this installs eclipse under /home/your-user-id/eclipse  be sure to include the following eclipse plug­ins: 
o
cdt: c/c++ development plug­in for eclipse ­ [cdt manual] 

install cdt plug­in: 

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.0linux.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" + "plug­in details".  "c/c++ development tools" should be listed.  note that cdt is not platform independant. you must download and  install the plug­in compiled for your platform. eclipse "help" menu  will include tutorials on cdt after plug­in installation. also see "help"  + "welcome" + select "cdt tutorials". 
o
subclipse: subversion plug­in 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 plug­in for eclipse. includes more 

details for advanced subversion users. displays lots of version info.  annoying if you want a clean simple interface. 
o o
ehep: hex file viewer plug­in  vi plug-in ­ for those who love vi editing and cursor manipulation key 

bindings. 
o o
prc-eclipse ­ palm os development plug­in  cca: c source code security analyzer plug­in 

[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 plug­ins, 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 plug­ins 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 plug­ins. 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

!entry org.eclipse.osgi 2005-10-31 00:19:29.787 !message application error !stack 1 java.lang.unsatisfiedlinkerror: /opt/eclipse/configuration/org.eclipse.osgi/bundles/24/1/.cp/libswt-pi-gtk-3139.so ...xxxxxxxxxxx...: cannot open shared object file: such file or directory at java.lang.classloader$nativelibrary.load(native method) at java.lang.classloader.loadlibrary0(classloader.java:1586) at java.lang.classloader.loadlibrary(classloader.java:1495) at java.lang.runtime.loadlibrary0(runtime.java:788) at java.lang.system.loadlibrary(system.java:834) at org.eclipse.swt.internal.library.loadlibrary(library.java:123) at org.eclipse.swt.internal.gtk.os.(os.java:19) at org.eclipse.swt.internal.converter.wcstombcs(converter.java:63) at org.eclipse.swt.internal.converter.wcstombcs(converter.java:54) at org.eclipse.swt.widgets.display.(display.java:122) at org.eclipse.ui.internal.workbench.createdisplay(workbench.java:381) at org.eclipse.ui.platformui.createdisplay(platformui.java:155) at org.eclipse.ui.internal.ide.ideapplication.createdisplay(ideapplication.java:128) at org.eclipse.ui.internal.ide.ideapplication.run(ideapplication.java:79) at org.eclipse.core.internal.runtime.platformactivator$1.run(platformactivator.java:2 at org.eclipse.core.runtime.adaptor.eclipsestarter.run(eclipsestarter.java:376) at org.eclipse.core.runtime.adaptor.eclipsestarter.run(eclipsestarter.java:163) at sun.reflect.nativemethodaccessorimpl.invoke0(native method) at sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl.java:39) at sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java: at java.lang.reflect.method.invoke(method.java:324) at org.eclipse.core.launcher.main.invokeframework(main.java:334) at org.eclipse.core.launcher.main.basicrun(main.java:278) at org.eclipse.core.launcher.main.run(main.java:973) at org.eclipse.core.launcher.main.main(main.java:948)

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 start­up and gives an  introduction and tutorials on eclipse . you can later return to this  menu: "help" + "welcome".  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. 

o

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: 
o o o

yum: yum install anjuta  rpms available from dag wieers: anjuta.  ubuntu/debian: apt-get install anjuta (requires: anjuta-common,
libgtk2.0-dev libgtkmm2.0-dev libgnome2-dev libgnomemm2.0dev devhelp-books glade-2 glade-gnome-2 cvs automake autogen indent ctags devhelp gnome-devel libtool) 

scm (software configuration management): 
o
subversion cm server and trac bug tracking server ­ version control ­ 

subversion is a cvs follow­on with new features. operates much like  old cvs. 
 o
yolinux subversion user tutorial 

ibm rational clearcase: 
  
clearcase client installation  clearcase server installation  clearcase commands 

o

yolinux cm tools links 

bug / issue tracking: 
o
trac bug tracking server ­ installation, configuration and integration with 

subversion. 
o •

see yolinux bug tracking systems links 

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: 
o
yolinux tutorial - cabie installation/configuration: multi­platform build 

system for subversion, cvs or perforce 
o •
yolinux.com: list of continuous and nightly build / test systems 

file compare tools: 
o
gtkdiff: has diff3 and merge features. written with gtk+. after gtkdiff­

0.8.0, gnome required. 
o o
fldiff: graphical file and directory diff. (cross platform)  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. 
    

difference: kdiff file1 file2  difference: kdiff file1 file2 file3  difference of two files: kdiff directory1/file directory2  difference: kdiff directory1 directory2  merge: kdiff directory1 directory2 -o dest-directory 

  o o o

merge: kdiff file1 file2 -m  merge: kdiff file1 file2 -o output-file 

kompare: ships with kde sdk. [manual]  meld: compare, edit and merge.  mgdiff: [download] motif­based graphical file difference browser and 

merge. comes with s.u.s.e. distro. 
o o o •
tkdiff: [download]  gvim and gvimdiff  dirdiff: directory difference viewer. 

compiler: install rpm packages for gnu compiler gcc, gcc-c++, binutils (linker), glibc, glibc-devel, gdb 

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 plug­ins) 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 fedora core 3  platform  variable name linux variable:  variable:  unix
posix _posix_source

variable: 

architecture  variable

*

*

linux red hat 8 linux suse 9.2 linux sun  solaris/sparc sgi irix/mips cygwin  win/intel­32

__gnu_linux__ linux * __gnu_linux__ linux * __gnu_linux__ sparc sgi __cygwin32 win32 * * _sgi_source * __arch64 mips host_mips _x86_ * *

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 return fn_sgi(); #elif defined(__cygwin32) return fn_win(); #elif defined(linux) return fn_linux(); #else struct time ts; return fn_time(); #endif ... #ifdef sgi #include file_sgi.h #elif defined(sparc) #include file_sparc.h #elif defined(linux) #include file_linux.h #else #error unknown os type #endif ...

or 

note use of the "#error" for error processing.  also see yolinux gnu makefile cross platform tips 

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:  the solution is to change the order of the libraries:  the order of the library paths is irrellevant (­l). 

g++ source-file.cpp -lxxx -lyyy -lzzz -l../xxx -l../yyy -l../zzz  g++ source-file.cpp -lyyy -lzzz -lxxx -l../xxx -l../yyy -l../zzz 

c++ link error: "undefined reference to `vtable for classname-goeshere`"  my fix was to define a destructor. the virtual base class and destructor  required the derived class to define a destructor.  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.  avoid integer word size issues by using defined types in stdint.h  libraries are typically found in /usr/lib and /lib. on systems which  mix 32 and 64 bit libraries look for /usr/lib64 and /lib64. 

o o

links:

c++ references: 
o o
gnu c++ library user's guide  sun's c++ 5.0 compiler programming guide ­ very good coverage of 

advanced features 
o o o o •
c++ programming language tutorials  ucsd.edu: standard c  cplusplus.com  informit.com: c++ reference guide 

c++ library references: 

o o o o o o •

gnu c++ iostream library  stl ­ home (sgi)  c++ data structures source code  list of c++ libraries  c++ library reference  c++ standard library - a tutorial and reference ­ nicolai josuttis 

c++ api's and toolkits: 
o o o o
c++ motif toolkit  object oriented programming ­ c++ gui and c++ frameworks  ace c++ framework ­ schmidt  c++ boost libraries 

c++ links and info: 
o o o o o o o o o o
c/c++ users journal ­ magazine articles  freshsources.com  c++ pitfalls ­ by cay s. horstmann  programmersheaven.com: c++ links  us chapter of the association of c/c++ users  the comp.lang.c++ faq  coding standards  c-c++ beautifier how-to  cpp-home.com  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, addison­wesley  professional  advanced c++ features and stl.  more exceptional c++  by herb sutter  isbn #020170434x, addison­wesley  professional 

effective c++: 50 specific ways to improve  your programs and design (2nd edition)  by scott meyers  isbn #0201924889, addison­wesley  professional 

more effective c++: 35 new ways to  improve your programs and designs  by scott meyers  isbn #020163371x, addison­wesley  professional  dr. dobb's journal  free subscription to the premier resource  for professional programmers and software  developers. multi­language 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 re­dimension 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 "-fnosecond-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) } goto(1, 2, 3), sub() if( sub() ) goto errs;

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 un­named  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 

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. 

$2 = (ptr to -> ( integer )) 0x5013e8 

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 fortran: -warn alignments -align all -align rec8byte  intel c/c++: -zp8  gnu g++: -wpadded -wpacked -malign-double -mpreferred-stack-boundary=8  example warning: warning: padding struct size to alignment boundary  gnu g77: -malign-double 

• •

example:
fortran program calling a c function:  testf.f testc.c
program test integer ii, jj, kk common/ijk/ ii, jj, kk real*8 ff character*32 cc ii jj kk ff cc 10 = = = = = 2 3 4 9.0567 'example of a character string'

write(6,10) ii, ff format('ii= ',i2,' ff= ',f10.4) call abc(ii)

20

write(6,20) ii format('ii= ',i2) write(6,30) ii, jj, kk

call doubleijk(cc) 30 40 write(6,30) ii, jj, kk format('ii= ',i2,' jj= ', i2, ' kk= ', i2) write(6, 40) cc format(a32) stop end subroutine abc(jj) jj = jj * 2 return end #include <stdio.h> extern struct { int ii, jj, kk; } ijk_; int doubleijk_(char *cc, int ll) { printf("from doubleijk: %s\n",cc); ijk_.ii *=2; ijk_.jj *=2; ijk_.kk *=2; } return(1);

compile: 
• • • f77 -c testf.f  gcc -c testc.c  f77 -o test testf.o testc.o 

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> using namespace std; 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 100 write(6,100) ii, ff format('ii=',i2,' ff=',f6.3) return end

compile: 
• • • f77 -c testf.f  g++ -c testc.cpp  g++ -o test testf.o testc.o -lg2c 

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  re­write. 

vax variable format expressions: vax expression ported to gnu fortran
integer*4 ivar(3), nfor nfor=3 ... write(6,100) (ivar(i), i=1,nfor) 100 format(<nfor>i3) do 20 i=1,nfor write(6,200) ivar(i) 200 format(i3,$) !! supress carriage return 20 continue write(6,400) 400 format() !! write carriage return

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 

...  create library: ar -cvq libvax.a inint.o idnint.o ... 

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:
the intel fortran compiler has become a popular fortran  compiler for linux as it supports many of the fortran  extensions supported by the compaq (old dec vax) and  sgi fortran compilers. (i.e. "structure", "record", "external",  "encode", "decode", "find", "virtual", "pointer", "union",  various intr8insic functions, i/o directives, ...) it links with  object code generated by gnu gcc/g++ compilers as well  as their own intel c/c++ compilers.  installation: (as root) 
• • • mkdir /opt/intel  cd /opt/intel 

move intel fortram compiler tar ball to this  directory. 
tar xzf 1_fc_c_9.0.033_ia32.tar.gz  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_f2wc5fdzv87r.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 #

# flexlm license server export intel_license_file=28518@license-server # support for intel fortran compiler if [ -f /opt/intel/fc/9.0/bin/ifortvars.sh ]; then source /opt/intel/fc/9.0/bin/ifortvars.sh fi # support for intel c/c++ compiler if [ -f /opt/intel/cc/9.0/bin/iccvars.sh ]; then source /opt/intel/cc/9.0/bin/iccvars.sh fi # support for intel debugger if [ -f /opt/intel/cc/9.0/bin/idbvars.sh ]; then source /opt/intel/cc/9.0/bin/idbvars.sh fi ... ... 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.

­pad­source specifies that fixed­form 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 front­end 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  butterworth­heinemann, 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. multi­language  and multi­platform 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 

Sign up to vote on this title
UsefulNot useful