Advc 3
Advc 3
Advc 3
Science & Technology Support High Performance Computing Ohio Supercomputer Center 1224 Kinnear Road Columbus, OH 43212-1163
2
C++ Programming for Scientists
Main program consists of creation and manipulation of objects Object = data + functions which allow you to interact with the data In general, data controlled only through these interface functions: Data Encapsulation C operators can work with your objects: Operator Overloading Advanced objects can incorporate features of Simpler objects: Inheritance With the same syntax, objects can act differently in different situations: Polymorphism
3
C++ Programming for Scientists
4
C++ Programming for Scientists
Table of Contents
A Better C Object-Oriented Programming (OOP) Templates and The Standard Template Library (STL)
5
C++ Programming for Scientists
A Better C
General: End-of-line Comments Boolean Data Type Type-casting Syntax Input/Output Streams Omnipresent Variable Declaration const Keyword Memory Allocation Syntax Function-related: Improved Argument Type Checking/Strict Function Prototyping Interpretation of the void keyword Type-safe Linkage Default Arguments Function Overloading Inlined Functions Reference Declarations Operator Overloading!!
6
C++ Programming for Scientists
End-of-Line Comments
Single line form of a comment begun with the // symbol Everything from the delimiter // to the end-of-the-line is ignored Reminiscent for the Fortran 90 use of ! for one-line commenting Familiar, multi-line style of commenting still works in C++ Warning: /* */ commenting may not nest with some compilers
7
C++ Programming for Scientists
#include <stdio.h> main() { float r, theta; // polar coordinates float x,y,z; // Cartesian coordinates // only works for one line /* code might need later x=10; y=100; z=x*3+2-y/4; printf("z is %d \n",z); */ }
8
C++ Programming for Scientists
9
C++ Programming for Scientists
Type-casting Syntax
In C, override type casting was possible with the following (awkward) syntax: int i; (double) i In C++, a second (less awkward) syntax can also be used: double(i) char(3+'A') Additional usefulness of this new syntax will be seen later in the OOP Section.
10
C++ Programming for Scientists
Input/Output Streams
Probably the strangest thing you would notice when looking at a C++ for the first time Replacement of the stdio library of C with the iostream library of C++. For example the C++ version of the classic Hello World program looks as follows:
#include <iostream.h> main() { cout << "Hello World\n"; }
Notice the 3 changes: 1 Include iostream.h instead of stdio.h 2 The cout keyword indicates that the output should go to standard out. There are corresponding keywords cin and cerr which represent standard in and standard error, respectively 3 Use of the insertion operator << as opposed to the printf function. The corresponding extraction operator for input is >>
11
C++ Programming for Scientists
12
C++ Programming for Scientists
14
C++ Programming for Scientists
#include <iostream.h> #include <iomanip.h> main() { cout << "[" << setw(6) << setfill('*') << 192; cout << "]" << endl; cout << hex << "[" << setw(6); cout << setfill('^') << 192 << "]" << endl; cout << setprecision(4) << 3.14159 << endl; } [***192] [^^^^c0] 3.142
15
C++ Programming for Scientists
16
C++ Programming for Scientists
#include <iostream.h> main() { int number=34; float divisor; cout << number << " divided by 2.3 equals " << number/2.3 << endl; cout < "Please enter your own divisor: "; cin >> divisor; if (divisor==0.0) cerr << "Cannot divide by zero" << endl; else cout << " Result is " << number/divisor << endl; } (981) conan% a.out 34 divided by 2.3 equals 14.7826 Please enter your own divisor: 0.0 Cannot divide by zero (982) conan% a.out 34 divided by 2.3 equals 14.7826 Please enter your own divisor: 78.2 Result is 0.434783
17
C++ Programming for Scientists
18
C++ Programming for Scientists
19
C++ Programming for Scientists
Type Checking
In general, C++ uses very strict type checking. With respect to functions, C++ (as well as ANSI C) requires that functions be prototyped before their use. This is to insure that the compiler can check that the proper number of arguments are passed where possible and if needed, cast the actual arguments to the proper type the return type is properly used in the calling function
24
C++ Programming for Scientists
1 2 3 4 5 6 7 8 9 10 11 12
To illustrate the power of function prototyping and argument checking, the following code
#include <iostream.h> int firstchar(char *s); main() { float name=3.0; int ascii; ascii=firstchar(name); cout << "Ascii code of first char is " << ascii << endl; } int firstchar(char *s) { return(int(s[0])); }
25
C++ Programming for Scientists
1 2 3 4 5 6
and a main program in a file called tstfrk.C that uses the freak function,
#include <stdio.h> extern int freak(); main() { int x=23; printf("%d\n",freak(x)); }
when compiled with the gcc command (for example), the following compiletime error messages are produced
gcc tstfrk.C freak.C tstfrk.C: In function int main(): tstfrk.C:2: too many arguments to function int freak() tstfrk.C:5: at this point in file
1 2 3 4 5 6 7
and further consider the main source file, tstcol.c, which uses the colum function:
#include <stdio.h> extern double colum(int a, double b); main() { double a=5.5,b=6.7,c; c=colum(a,b); printf("%f\n",c); }
28
C++ Programming for Scientists
29
C++ Programming for Scientists
30
C++ Programming for Scientists
Default Arguments
In C++, the programmer can set default values for dummy arguments in function definitions. If no actual value is passed to that dummy argument, the default value is used. Useful when a certain argument almost always has the same value when the function is used. In addition, this approach can reduce the number of actual arguments in the function reference. On the other hand, should comment on why/how the default value is used.
31
C++ Programming for Scientists
32
C++ Programming for Scientists
Function Overloading
Often, a function needs to perform the same operation, but using arguments of different types. In C++, multiple versions of a function with the same name but different type arguments can be defined. In the main program, the correct version of the function is actually used by the compiler by examining the argument types. (Internally, this is done through name-mangling again). Function overloading avoids having multiple functions with slightly different baroque names which essentially perform the same work. In the following program, a swap function is overloaded to work with both integers and doubles.
33
C++ Programming for Scientists
#include <iostream.h> In the following program, a swap function is overloaded to work with both void swap(int* integers andtemp;i, int* j) { int doubles. cout << "int swap called" << endl; temp=*i; *i=*j; *j=temp; } void swap(double* x, double* y) { double temp; cout << "double swap called" << endl; temp=*x; *x=*y; *y=temp; } main() { int a=5,b=23; double r=34.5,s=1245.78; swap (&a,&b); swap (&r,&s); cout << "a is " << a << " b is " << b << endl; cout << "r is " << r << " s is " << s << endl; } int swap called double swap called a is 23 b is 5 r is 1245.78 s is 34.5 34
C++ Programming for Scientists
Inlined Functions
In C++, functions can be declared as inlined. Inlining is a general optimization technique which causes any reference to a function to be replaced by the actual code that makes up the function. The function body is input in the line where the function reference occurs. The user programs in their own style and the compiler does the inlining automatically. (Especially useful for small functions referenced often). The advantages to inlining are: Dont pay the overhead time-cost of the function call itself Unlike macros (the alternative approach), inlined functions can be prototyped and thereby type-checked Less prone to errors than macros The disadvantage of inlining (and macros) is the assembly language text bloat which will occur. In addition, the actual code must be known to the compiler, thus functions in a run-time library cannot be inlined.
35
C++ Programming for Scientists
Macros -- C Example
The following C code shows that macros can produce incorrect results due to their literal substitution of arguments:
#include <stdio.h> #define MUL(a,b) a*b main() { int x,y,z; x=10;y=100; z=MUL(x*3+2,y/4); printf("z is %d \n",z); } z is 80
The correct result we expected (10*3+2)*(100/4)=800 was not calculated because the macro substitution resulted in the expression x*3+2*y/4 which due to operator precedence gives the value 80.
36
C++ Programming for Scientists
37
C++ Programming for Scientists
Call-by-Reference
In C, the only way actual arguments are passed to dummy arguments when referencing a function is call-by-value. The value of the actual argument is passed into the dummy argument. Any changes the function makes to the dummy arguments will not affect the actual arguments. C does provide an indirect method for changing the value of the actual arguments, namely call-by-address. Addresses are passed from the actual to the dummy argument and the indirection operator * is used to change the contents of the actual argument.
38
C++ Programming for Scientists
Call-by-Address -- C Example
The following C code demonstrates the use of call-by-address
#include <stdio.h> struct item { char* name; float price; int quantity; }; void increase(struct item* p) { (*p).price=1.10*(*p).price; p->quantity=p->quantity+10; } main() { struct item chicken={"Holly Farms",5.00,20}; increase(&chicken); printf("New price is %0.2f\n",chicken.price); } New price is 5.50
39
C++ Programming for Scientists
40
C++ Programming for Scientists
41
C++ Programming for Scientists
Operator Overloading
On of the more powerful features of C++ is that programmers can define the basic C++ built-in operators -- such as +, *, [], !, for example -- to work with user-defined types. Of course, the operators continue to work as originally designed for basic types: thus the term overloading. This capability makes for sensible and more readable main programs and is similar, in spirit, to function overloading. Keep in mind also that although you can use operator overloading to define an operator to do anything you want, it is best to make the new operator definition in some way analogous to the normal use of the operator. The syntax for operator overloading looks exactly like the syntax for a function definition except that the function name is replaced by the name operator<operator symbol>
42
C++ Programming for Scientists
44
C++ Programming for Scientists
Object-Oriented Programming
Classes and Objects Constructors and Destructors Object assignment & Type Casting Operators with Objects Friend Functions Using Objects with the I/O stream Static Class Members Inheritance Virtual Functions and Polymorphism
45
C++ Programming for Scientists
C++ Classes
A class is a user-defined data type. You can think of it as an extended and improved structure data type. An object is a variable of a certain class type. It is often said that an object is an instantiation of the class. Intrinsic data-types, float for example have values they can contain (real numbers) and a set of operations (+,/,*,etc) that can be applied to variables of type float. These same concepts are carried over to class types. The values a class can contain are called its data members. The set of operations that can be applied to a certain class object are called its member functions. After a class has been declared, we will see in the rest of the course how its objects can be treated in the same manner and syntax as normal data-type variables.
46
C++ Programming for Scientists
double base; double height; public: void set(double a, double b) { base=a; height=b; member functions } void display() { cout << "base=" << base << " height=" << height << endl; } double area() {return(0.5*base*height);} }; Common Error: forget this semicolon!
47
C++ Programming for Scientists
It should be noted in this code that the same dot operator to access a member of a structure is also used to access the member of a class. Specifically, member functions are invoked with the traditional dot operator.
48
C++ Programming for Scientists
protected Accessible only to functions of same or derived classes The default access classification for classes is private. As in the class Triangle previously declared, once an access-specifier -- like public -appears, all members following the public keyword are declared public, until a different access-specifier is typed in. Thus, all three member functions of Triangle are public.
49
C++ Programming for Scientists
51
C++ Programming for Scientists
Member Functions
As we have already seen, an interesting feature of C++ classes (unlike C structures) is that they can contain functions as members. In the class examples we have shown so far the member functions have been defined within the declaration of the class itself. The actual requirement is less severe: member functions must be declared within the class declaration, that is, their prototype must appear there. They can actually be defined outside the class declaration. One advantage of defining the member function inside the class is that it will automatically be inlined. In terms of access, member functions -- wherever they are defined -- have access to all private, protected, and public class members (data & function). When the member function is defined outside the class definition the scope resolution operator -- :: -- must be used with the class name to indicate that the function belongs to that class.
52
C++ Programming for Scientists
55
C++ Programming for Scientists
Constructor Properties
Here are the basic properties of a constructor Special member function Has the same name as the class Is invoked automatically each time a new variable of its class is created (declared, dynamically-allocated, type conversion to the class) Cannot be invoked explicitly Has no return type (not even void) Typically uses its arguments (if any) to initialize the new objects data members Can have default arguments and be overloaded Default (no-op) constructor is provided by the compiler if you do not provide one. Advice: Always define your own default constructor (and destructor) -- even if they are empty -- you may need to fill them later
56
C++ Programming for Scientists
Constructor Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream.h> class Bookshelf { float width; float height; int numshelves; public: Bookshelf(float i=4.0,float j=6.0, int k=5) { width=i;height=j;numshelves=k; cout << "Another Bookshelf made: " << width << "x" << height << " with " << numshelves << " shelves" << endl;} }; main() { Bookshelf normal; Bookshelf wide(8.0); Bookshelf tall(4.0,9.0); Bookshelf* custom; custom=new Bookshelf(6.0,3.0,3); for (int i=10; i<=15; i+=5) { Bookshelf paperback(4.0,6.0,i); } } Another Another Another Another Another Another Bookshelf Bookshelf Bookshelf Bookshelf Bookshelf Bookshelf made: made: made: made: made: made: 4x6 8x6 4x9 6x3 4x6 4x6 with with with with with with 5 shelves 5 shelves 5 shelves 3 shelves 10 shelves 15 shelves
57
C++ Programming for Scientists
58
C++ Programming for Scientists
3 4 5 6 2 1
59
C++ Programming for Scientists
Allocated int: 1 Allocated int: 2 Deallocated int: Allocated int: 3 Deallocated int: Allocated int: 4 Deallocated int: Deallocated int:
2 3 4 1
Copying Objects
Is it possible to copy one object of a class into another object of a class? The answer is yes and the assignment operator "=" has been designed so that the copying is done with natural syntax. If you use an assignment statement to copy one object to another a data member by data member copy is performed. That is, each member of the object is copied in turn. The program on the following page copies objects.
61
C++ Programming for Scientists
62
C++ Programming for Scientists
63
C++ Programming for Scientists
Copy Constructor
The copy constructor is used to make a new class object safely duplicate an existing class object. The salient properties of a copy constructor are: Special type of constructor member function Has exactly one argument which is a reference to the class type Invoked with the following syntax class-name new-object-name(existing-object-name) Typically defined when the class contains pointer members and the assignment operator is inappropriate The copy constructor produces what is referred to as deep copying whereas the assignment operator performs shallow copying. The program on the following page fixes the problem just presented with our Ints class and its shallow copying. The copy constructor shown on the next page actually creates a new address for the copied classs int pointer and not the same address as the original.
65
C++ Programming for Scientists
Conversion Constructor
Yet another type of constructor enables type conversion from other types to the class type. It is, naturally, called a conversion constructor. The conversion constructor has exactly one argument of a type other than the class type. If the compiler encounters a mixed-type operation, the conversion constructor is used to make a temporary object of the class type and use this converted variable in the calculations. Note: the data members of classes involved in conversion operation often have to be made public since they will be used in non-member functions.
67
C++ Programming for Scientists
68
C++ Programming for Scientists
69
C++ Programming for Scientists
70
C++ Programming for Scientists
71
C++ Programming for Scientists
main() { English d1(6.25); English d2(3.375); d1=d1+d2; d1.display(); Metric m1(30.48); d1=d1+m1; d1.display(); } Length is 9.625 inches Length is 21.625 inches
72
C++ Programming for Scientists
F0 m = 2.512 x log F where F is the flux from the star and F0 is the flux from a zero-magnitude
star. Often astronomers will have two stars in their field of view and would like to know the magnitude of the stars combined. One simply cannot add together the magnitudes of the separate stars since it is only physically correct to add the fluxes from the stars. In the program on the next page, the + operator is overloaded to correctly work for the addition of stellar magnitudes. Again, notice how readable and sensible the statements of the main program are.
73
C++ Programming for Scientists
main() { Intarray x(20); for (register int i=0; i<20; i++); x[i]=2*i; for (register int i=0; i<=30; i+=5) cout << "At index " << i << " value is" << x[i] << endl; } At At At At At index index index index index 0: value is 0 5: value is 10 10: value is 20 15: value is 30 20: value is
77
C++ Programming for Scientists
78
C++ Programming for Scientists
main() { Metric m1(30.50); Metric m2(2.60); m1=m1+m2; m1.display(); English d(3.937); m1=m1+d; m1.display(); } Length is 33.1 cm Eng-to-Met conversion occurred Length is 43.1 cm
80
C++ Programming for Scientists
Friend Functions
In general only public members of a class are accessible to functions that are not member functions. However, a class can declare a function to be a friend function in which case the friend function has access to all members of the class (including private). Friend status is granted by the class to the function and is a feature of the class design. Friend functions are often used when a calculation needs access to the private members of two objects of the same class. To specify a friend function, declare the function in the member list of the class, preceded by the keyword friend. The function may actually be defined as a global or a member function.
81
C++ Programming for Scientists
82
C++ Programming for Scientists
83
C++ Programming for Scientists
Inheritance
When a new class is declared in C++, you can specify that it should be derived from an existing class. The new derived class inherits all data and function members from the base class, as if those class members had been declared explicitly within the new class declaration itself. The derived class modifies or extends the capabilities of the base class. It is through inheritance that C++ enables and facilitates software reuse. The reuse is even possible in cases where classes are made available to the user in the form of object libraries without accompanying member source code!
88
C++ Programming for Scientists
Public Inheritance
You may have noticed that with all the derived class declarations seen so far the access method public has been used before the name of the base class. Public inheritance is by far the most common form of class inheritance and has the following properties Public inheritance is an is-a relationship (A Pro_Golfer is a Serious_Golfer also, but more) The inherited public and protected members of the base class become public and protected members of the derived class, respectively Private members of the base class are inherited but are accessible only to member functions of the base class. If a member function of the derived class needs to directly work with a data member of the base class, make the base class data member protected. Because of the is-a nature of public inheritance, an object of the derived class may appear unambiguously in any context requiring a base class object Pointers or references of the base class type also can point or refer to derived class objects
91
C++ Programming for Scientists
#include <iostream.h> class Vehicle { int weight; public: int getweight() { return(weight); } void setweight(int i) { weight=i; } }; class Land: public Vehicle { float speed; public: float getspeed() { return(speed); } void setspeed(float x) { speed=x; } }; void check_wt(Vehicle& v) { if (v.getweight()>2000) cout << "Vehicle is too heavy\n"; } main() { Vehicle blob; blob.setweight(100); check_wt(blob); Land car; car.setweight(5000); check_wt(car); } Your vehicle is too heavy
93
C++ Programming for Scientists
94
C++ Programming for Scientists
} << "wx=" << wx << endl; } { Widget(i) { gx=j; } << "gx=" << gx << endl; }
main() { Average temp(9); temp.getdata(); temp.averagex(); temp.averagey(); temp.display(); } Average x: 5 Average y: 51.8556
98
C++ Programming for Scientists
99
C++ Programming for Scientists
100
C++ Programming for Scientists
101
C++ Programming for Scientists
102
C++ Programming for Scientists
103
C++ Programming for Scientists
#include <iostream.h> class Golfer { public: int rounds_per_mo; virtual void swing()=0; }; class Serious_Golfer: public Golfer { public: int handicap; void swing() {cout << "Ahhhh!\n";} }; class Pro_Golfer: public Serious_Golfer { public: float income; void swing() {cout << "It's in the hole!\n";} }; main() { Pro_Golfer jc;
// Golfer mike;Illegal! Cant declare variable of an abstract base class
107
C++ Programming for Scientists
Demonstration Program
#include <iostream.h> class A { int datum; public: A(int i) { datum=i; } void display() { cout << "(A)datum=" << datum << endl; } }; class B { double datum; public: B(double d) { datum=d; } void display() { cout << "(B)datum=" << datum << endl; } }; template <class T> void repeat(T tt, int n) { for (int i=1; i<=n; ++i) { tt.display(); } } void main() { A anAobject(1); B aBobject(2.5); repeat (anAobject,2); repeat (aBobject,3); } (A)datum=1 (A)datum=1 (B)datum=2.5 (B)datum=2.5 (B)datum=2.5 109
C++ Programming for Scientists
#include <iostream.h> template<class kind> kind max(kind d1, kind d2) { if (d1 > d2) return(d1); return(d2); } void main() { cout << "The max of 3.5 and 8.7 is " << max(3.5,8.7) << endl; cout << "The max of 100 and 567 is " << max(100,567) << endl; cout << "The max of 'A' and 'a' is " << max('A','a') << endl; } The max of 3.5 and 8.7 is 8.7 The max of 100 and 567 is 567 The max of 'A' and 'a' is a
110
C++ Programming for Scientists
112
C++ Programming for Scientists
Class Templates
A class template defines a family of related classes which differ only in the type of the data stored and used by them. A class template definition is preceded by the keyword template followed by an angle-bracket-enclosed list of class template arguments. These arguments consist of the keyword class followed by an identifier that will act as a dummy argument for the actual type the class will use. A class template argument can also be just a normal type name followed by an identifier. Here is an example: template<class T, int N> class Array { T array_element[N]; public: T first_element() { return array_element[0]; } }; Each class in this template can be thought of as an N-element array of Ts.
114
C++ Programming for Scientists
117
C++ Programming for Scientists
Introduction to STL
The Standard Template Library is a collection of extremely useful class templates and function templates allowing the programmer a wide variety of capabilities. There are literally hundreds of classes and functions the programmer can use with a variety of simple and derived data types. It provides many of the data structures (container classes) and algorithms useful in computer science thereby preventing the programmer from reinventing the wheel.
119
C++ Programming for Scientists
STL Features
Here are some of the salient Features of STL: It is an ANSI standard and integral part of C++ (beware competitors) STL is very efficient: container classes use no inheritance or virtual functions STL algorithms are stand-alone functions which can work on virtually all types of simple data, normal classes, and STL containers In order to accommodate machine-dependent, varying mechanisms for memory allocation and management, STL containers use special objects called allocators to control storage. This enables the portability required of an ANSI standard.
120
C++ Programming for Scientists
STL References
Because of the sheer complexity of the STL, it is difficult to list and impossible to cover all the classes and functions within it. We will attempt to teach the library material most useful to research scientists and engineers. For a complete description of the library, see these recommended Web Sites http://www.sgi.com/Technoloy/STL/ http://www.dinkumware.com/htm_cpl/
121
C++ Programming for Scientists
123
C++ Programming for Scientists
124
C++ Programming for Scientists
125
C++ Programming for Scientists
Containers: Functions
Although containers have different properties, they all share a set of common functions which do basic bookkeeping and creation/comparison/destruction tasks. Here are functions related to basic container existence (using a vector container):
Function Example Description Construct the container Destroy a container Returns true if container is empty Returns maximum number of objects the container can hold Returns the number of objects in the container
127
C++ Programming for Scientists
Constructor vector() Destructor Empty Max_size Size ~vector() bool empty() size_type max_size() size_type size()
128
C++ Programming for Scientists
129
C++ Programming for Scientists
#include <vector> #include <iostream.h> void print(vector<double>& x) { for (int i=0; i<x.size(); ++i) cout << x[i] << " "; cout << endl; } void main() { vector<double> v1; v1.push_back(12.1); v1.push_back(45.6); vector<double> v2; v2.push_back(2.893); cout << "v1="; print(v1); cout << "v2="; print(v2); v1.swap(v2); cout << "v1="; print(v1); cout << "v2="; print(v2); v2=v1; cout << "v2="; print(v2); } v1=12.1 45.6 v2=2.893 v1=2.893 v2=12.1 45.6 v2=2.893
130
C++ Programming for Scientists
131
C++ Programming for Scientists
132
C++ Programming for Scientists
Iterators
We have already been introduced to the idea of an STL iterator as a generalized pointer. Before we can explore more sophisticated containers than vector, the various types of iterators need to be discussed. Regardless of the type of iterator one thing is always true: At any point in time, an iterator is positioned at exactly one place in a container until it is repositioned. There are three major types of iterators: forward can work with object only in the forward direction bidirectional can move forwards and backwards random access can jump an arbitrary distance
133
C++ Programming for Scientists
Iterator Use
Iterators can be used with both input and output streams, as well as with containers (as we have seen). Basically the same set of basic arithmetic, logical, and de-referencing operations that can be performed with C++ pointers also work with STL iterators. Each STL container works with a certain type iterator. The vector and deque containers use random access iterators. The list, multiset, set, multimap, and map containers use bidirectional. In addition, each STL container has a set of typedefs that describe its iterators. For a container iterator there are the member functions begin and end to set the iterator to extreme positions in the container: iterator begin() -- returns an iterator positioned at the first object iterator end() -- returns an iterator positioned immediately after the last object
134
C++ Programming for Scientists
Reverse Iterators
As you might expect, a reverse iterator travels a container of objects backwards instead of forwards. As with regular iterators there are container member functions used to place the iterator at extreme positions reverse_iterator rbegin() -- returns a reverse iterator positioned at the last object reverse_iterator rend() -- returns a reverse iterator positioned immediately before the first object
135
C++ Programming for Scientists
#include <string> #include <iostream.h> #include <list> void main() { list<string> niece; niece.push_back("Madelyn"); niece.push_back("Claire"); niece.push_back("Ennis"); list<string>::reverse_iterator r; for (r=niece.rbegin(); r!=niece.rend(); ++r) cout << *r << endl; } Ennis Claire Madelyn
136
C++ Programming for Scientists
137
C++ Programming for Scientists
Algorithms
The designers of the STL wished to implement generic algorithms: those that can be applied to a variety of data structures from normal integers and doubles to advanced classes. This design was realized through the use of function templates to define the algorithm functions in the library. There are over 65 algorithms in the algorithm library, the code for which actually makes up the bulk of the entire STL. To allow the STL algorithms to work on a variety of data structures from C++ arrays to STL containers themselves, the STL algorithms only access data indirectly by using iterators. In addition, some algorithms have several implementations optimized for the kind of iterator involved. In the following pages, sample programs using several of the more popular algorithms are presented. In a separate handout, a categorized listing of the STL algorithms and a brief description of their operation is presented.
138
C++ Programming for Scientists
Min/Max Algorithm
#include <algorithm> #include <iostream.h> void main() { double x=min(444.90,6.5); cout << "minimum of 444.90 and 6.5 is " << x << endl; char c=max('=','3'); cout << "maximum (by ASCII value) of = and 3 is " << c << endl; } minimum of 444.90 and 6.5 is 6.5 maximum (by ASCII value) of = and 3 is =
139
C++ Programming for Scientists
140
C++ Programming for Scientists
#include <algorithm> // may be <numeric> on some systems #include <iostream.h> void main() { const int N=8; int a[N]={4,12,3,6,10,7,8,5 }; sum=accumulate(a,a+N,0); cout << "Sum of all elements:" << sum << endl; fun_sum=accumulate(a+2,a+5,1000); cout << "1000+a[2]+a[3]+a[4] = " << fun_sum << endl; } Sum of all elements:55 1000+a[2]+a[3]+a[4] = 1019
141
C++ Programming for Scientists
142
C++ Programming for Scientists
#include <algorithm> #include <iostream.h> void main() { int a[3]={2,20,4}; int b[3]={5,2,10}; int inprod; inprod=inner_product(a,a+3,b,0); cout << "<a,b>=" << inprod << endl; } <a,b>=90
143
C++ Programming for Scientists
Find Algorithm
#include <algorithm> #include <iostream.h> #include <vector> void main() { vector<int> v(5,8); for (int k=0; k<v.size(); ++k) cout << v[k] << " "; cout << endl; v[2]=33; vector<int>::iterator pos; pos=find(v.begin(), v.end(), 33); cout << "The value 33 was found at position " << pos-v.begin() << endl; } 8 8 8 8 8 The value 33 was found at position 2
145
C++ Programming for Scientists
#include <algorithm> #include <iostream.h> #include <vector> #include <list> void main() { vector<int> a(5); a[0]=2; a[1]=3; a[2]=8; a[3]=20; a[4]=25; int b[6]={7,9,23,28,30,33}; list<int> c(11); merge(a.begin(), a.end(), b, b+6, c.begin()); list<int>::iterator k; for (k=c.begin(); k!=c.end(); ++k) cout << *k << " "; cout << endl; } 2 3 7 8 9 20 23 25 28 30 33
146
C++ Programming for Scientists
147
C++ Programming for Scientists
#include <algorithm> #include <iostream.h> #include <vector> #include <functional> void main() { vector<int> v(6); int prod; for (int i=0; i<v.size(); ++i) v[i]=i+1; prod=accumulate(v.begin(), v.end(), 1, times<int>()); // for some compilers times has been replaced by multiplies cout << "The factorial of 6 is " << prod << endl; } The factorial of 6 is 720
149
C++ Programming for Scientists
Function Objects
A function object may be created, stored, and destroyed just like any other kind of C++ objects. On the other hand, unlike an ordinary C function, a function object can have associated data. The key requirement of a function object is that the () operator is defined so that the use of the function object can look like a normal function reference. In addition, many of function objects in the STL functional library are written as templates in order to work with a variety of data types. For example, here is the structure template definition for the times function object we just used: (obtained from the functional include file) template <class T> struct times: binary_function<T,T,T> { T operator()(const T& x, const T& y) const { return x*y; } };
150
C++ Programming for Scientists
#include <iostream.h> #include <functional> void main() { time<double> prod; // create an instance of times object cout << prod.operator()(3.4,2.0) << endl; cout << prod(3.4,2.0) << endl; } 6.8 6.8
151
C++ Programming for Scientists
152
C++ Programming for Scientists
#include <iostream.h> #include <functional> #include <algorithm> void main() { int tf[7]={1,0,0,1,1,0,1}; int n=0; count_if(tf, tf+7, logical_not<int>(), n); cout << "The count of falses was " << n << endl; } The count of falses was 3
153
C++ Programming for Scientists
#include <iostream.h> #include <functional> #include <algorithm> #include <vector> void main() { vector<int> v(3); v[0]=4; v[1]=1; v[2]=9; sort(v.begin(), v.end(), greater<int>()); vector<int>::iterator k=v.begin; while (k != v.end()) cout << *k++ << endl; } 9 4 1
154
C++ Programming for Scientists
#include <iostream.h> #include <functional> #include <algorithm> void main() { int original[6]={2,3,-8,45,9,-3}; int changed[6]; transform(original,original+6,changed,negate<int>()); for (int k=0; k<6; ++k) cout << changed[k] << " "; cout << endl; } -2 -3 8 -45 -9 3
155
C++ Programming for Scientists
Problem Set
1) Use accumulate to subtract instead of add. Output whatever is necessary to show that your program is working. 2) Write the code for a function called palindrome which takes a vector as its argument and returns a Boolean that is true only if the vector is equal to the reverse of itself. Use iterators to perform the comparison. In your main program, test your palindrome function with several vectors and output the results. 3) Use the remove algorithm to remove some objects from a vector. Does the size of the vector decrease? If not, modify your program so that it actually does remove the desired objects. TIP: Use the fill algorithm to fill up your vector to begin with.
156
C++ Programming for Scientists
157
C++ Programming for Scientists