Prof. Clare Yu
email: cyu@moses.ps.uci.edu
phone: 949-824-6216
Office: 2168 FRH
Winter 2000
These notes draw material from the notes of Prof. Steve White, from Barton and Nackman's book Scientific and Engineering C++, and from C++ for Dummies by Stephen R. Davis.
Discuss Syllabus.
Project possibilities: Matrices of complex numbers, arbitrary precision arithmetic, data analysis, experiment control, finite elements, solve differential equations, plotting library (see web pages listed in syllabus for ideas and projects done by previous classes).
Misc: To obtain an account on Linux machines in computer lab (1002 FRH), see Tory Graziano in 480 Rowland Hall, pscsg@mail.ps.uci.edu, 824-6377. You can do the homework on any machine. If you use a Linux workstation, use the g++ compiler. Get key card to the computer lab from Jim Geier in Physics Department office. The machines are called frh1002x.ps.uci.edu where x=1,2,3,4,5. For example, frh10021.ps.uci.edu is the name of a machine. You can access them remotely using ssh; telnet will not work. Web pages:In your account, there will be a directory called WWW. Anything you put in this directory is accessible on the internet.
Simplest program: hello.cc
#include <iostream.h> int main() { cout<<"hello world"<<endl; return 0; }Or we could have written
#include <iostream.h> void main() { cout<<"hello world"<<endl; }
Here void main means nothing is returned, even though something is done.
To compile this program:
g++ hello.ccThis gives the executable a.out. If you want the executable to be hello, then type
g++ hello.cc -o hello
To get more information on g++, type man g++.
Everything in C and C++ are functions. The main program main is called like a function.
Syntax: Brackets {} group lines. Each line ends with a semicolon ``;''.
Usually there is no semicolon after brackets {} (except for a
class). In fortran each line ends when you hit <return>
and you
continue lines with a character in the 6th column. In fortran every
new line must be indented by at least 7 columns. In C and C++,
you don't have to indent lines.
#include <iostream>
means read in the file iostream here. The #
sign
indicates that the statement is a preprocessor command.
Conceptually, the preprocessor is the first step in compilation.
We will discuss preprocessor commands as they arise.
< >
means look for the file in the standard places.
cout is defined in the file iostream.h as an iostream. It represents standard output and writes to the screen. << is read as an arrow pointing out. endl means make a new line and flush the file from the buffer. return 0 means standard return when everything is fine.
Input and output of numbers:
double a,b; //or could write float cin >> a >> b; cout << "a=" << a << ", b=" << b << endl;
cin is a way of reading numbers in that have been entered from the keyboard.
Fortran C, C++
integer int (16 or 32 bits)
integer*8 (8 bytes) (1 byte=8 bits) long or long int (32 or 64 bits)
integer*4 short or short int (16 or 32 bits)
integer*2
character*1 char (8 bits)
real float (32 bits)
real*8 double (64 bits)
real*16 (not on many machines) long double (128 bits)
complex defined in library: Complex
character*20 char a[20]; or use "string" library
logical int (or 1 byte) (0 or 1)
Arrays
Real A(10) has elements float a[10]; has elements from
from A(1) to A(10) a[0] to a[9]
Real A(10,10) is 2D array float a[10][10]; // [row][col]
To initialize arrays in C:
int a[5]={0,2,18,12,5};
float b[2][4]={{23.0, 1.3, 22.2, 0.2},
{0.24, 4.1, 12.0, 9.7}};
x.lt.y x < y
x.le.y x <= y
x.eq.y x == y
x.gt.y x > y
x.ge.y x >= y
x.ne.y x != y
.false. 0
.true. nonzero, 1
.not.x !x
x.and.y x && y
x.or.y x || y (inclusive or)
Arithmetic operations: +, -, *, /
mean the same in fortran, C and C++.
But in fortran xy is written as x**y, while in C and C++,
x**y means nothing. One often uses pow(x,y) from the
math.h library.
if( ) then if(x<0)
...... { .....
endif }
Style statement: No {} are needed if there is only one statement.
if(x<0.0) x=0.0;
{} make a group of statements look like a single statement.
if( )
{...
}
else if(...)
{
}
else
{
}
if( )
{
if( )
{ }
else { }
}
As an example, let's implement the fabs() function:
float fabs(float x) //A function has () after its name. { float y; if(x<0.0) y = -x; else y = x; return y; }
Another way to write this is
float x,y; y = (x<0.0)? -x : x; return y;In y = expr1 ? expr2 : expr3, expression expr1 is evaluated first. If it is true (nonzero), y is set equal to expr2. If it is false (expr1 = 0), y = expr3.
switch (expression) { case const-expression: statements case const-expression: statements default: statements }
Each case is labeled by one or more integer-valued constants or constant expressions. If a case matches the expression value, the execution starts at that case. All case expressions must be different. The case labeled default is executed if none of the other cases are satisfied. A default is optional; if it isn't there and if none of the cases match, no action at all takes place. Cases and the default clause can occur in any order. For example
int i, j; cin >> i; switch(i) { case 1: j=i; case 2: //if i=2 or 3, then j=i+5 case 3: j=i+5; default: break; }The break statement causes an intermediate exit from the switch. After the code for one case is done, execution falls through to the next case unless you take explicit action to escape. break and return are the most common ways to leave a switch.
while(expression) statementThe expression is evaluated. If it is nonzero, statement is executed and expression is re-evaluated. This cycle continues until expression becomes zero, at which point execution resumes after statement.
do statement while (expression);The statement is executed, then the expression is evaluated. If it is true, the statement is evaluated again, and so on. When the expression becomes false, the loop terminates.
In fortran, the do loop has the form
do i=1,10 ..... enddoIn C and C++, we would write
for(i=1;i<=10;i++) // i++ is the same as i=i+1 .....(Comment follows
//
. ``//
'' is equivalent to ``!'' in Fortran or
``/*...*/
'' in C.)
The for statement is equivalent to
i=1; while(i<=10) { .... i++; // i++ means i=i+1 }
In fortran we denote a common block by
common /x/ a,b, ...
In C and C++, anything defined outside a function is global, unless declared otherwise.
int a; void func1() { a=2; } void func2() { cout << a << endl; }Here these are all the same a.
A variable defined inside a function is local to the function, and no other function can have direct access to it. Each local variable in a function comes into existence when a function is called, and disappears when the function is exited. External variables are globally accessible by all functions, and they exist permanently, rather than appearing and disappearing as functions are called and exited. Suppose our program consists of several files with some functions in filea.cc, other functions in fileb.cc, and still other functions in filec.cc. How can we have variables that are global to the functions in filea.cc and fileb.cc but not in filec.cc? That's what the extern declaration is for. Suppose we want aa to be global to filea.cc and fileb.cc. Then we would define aa outside of any function in one file, say filea.cc, and then put an extern declaration in fileb.cc. One can either put the extern declaration at the top of fileb.cc or in each function that requires it in fileb.cc. Note that a variable can only be defined once in a program but it can be declared more than once. A definition refers to the place where the variable is created or assigned storage. A declaration refers to places where the nature of the variable is stated but no storage is allocated. Our example would look something like this:
//****************************filea.cc*************************** float aa; //global definition of aa is outside of any function int func1(){ aa=2; ... } float func2(){ aa=aa*3.0; ... } //**************************fileb.cc***************************** extern float aa; // declaration of aa that indicates the // definition of aa is elsewhere. void func3(){ cout<<aa<<endl; .... } void func4(){ ... }Or if we only want func3 to know about aa, we could write
//**************************fileb.cc***************************** void func3(){ extern float aa; // declaration of aa that indicates the // definition of aa is elsewhere. } void func4(){ float aa; // here aa is local to func4() and is not the // same as the global variable aa. ... }
Enumerations
enum Color {red, pink, blue}; Color c = blue;
Each color actually denotes an integer. By default, the count starts at 0.
enum Color {red=0, pink=1, blue=2} //default
But you can specify some other numbering scheme:
enum Color {red=5, pink=7, blue} //In this case, blue=8.
It is legal to go from enum to int. int i = pink; is legal. But it is not legal to go from int to enum. Color c = blue + 1; is not legal because there are more integers than Colors.
(By the way, C and C++ are sensitive to upper and lower case, while Fortran is not case sensitive.)
There is a nice shorthand involving +=, -=, *=, /=
.
For example, a=a+b becomes a += b and
a=a*c becomes a *= c.
Increment:
i++ is the same as i=i+1
i- is the same as i=i-1.
++ and - may be used either as prefix operators (before the variable, as in ++n), or postfix operators (after the variable: n++). In both cases, the effect is to increment n by 1. But the expression ++n increments n before its value is used, while n++ increments n after its value has been used. For example,
n=5; x=n++;sets x to 5 and n to 6. But
n=5; x=++n;sets both x and n to 6. Increment and decrement operators can only be applied to variables; and an expression like (i+j)++ is illegal. Assignments using = signs return values, namely a new left side: a=(i=4)+2 sets a to 6.
Modulo i % j = modulus = remainder. For example, 5 % 3 = 2, 20 % 7 = 6, etc.
~i bit by bit "not", switches 0 to 1 and 1 to 0 i & j "AND" i ^ j exclusive "OR" 1^1 yields 0 i | j inclusive "OR" 1 | 1 yields 1 operator i j i operator j _____________________________________________________ ~ 001 110 & 011 110 010 (Both have to be 1 to get 1) ^ 011 110 101 | 011 110 111
<< left shifts bits. For example, 1 << 2 = 4 since 4 is written 100 in binary. The 2 tells how far to shift the 1 bit.
>> right shifts bits. For example, 4 >> 2 = 1.
Octal constants are preceded by 0 (zero): 030 = 24 since 3 x 8 = 24. Hexadecimal constants are a sequence of digits preceded by 0x. For example, 0x10 = 16.
Unsigned type such as unsigned int means that all the bits go into numbers, and none of the bits is used to designate a sign. This gives more bits to be used for numbers.
A single quoted letter is a constant for one character. 'a' means one character, the letter a.
char c = 'X'; //defines c and initializes it. c='y'; //reassigns c.
Special characters:
'\n' = newline '\t' = tab etc.
Literally a char is a byte-size integer. 'a' means ``ascii code for a as a byte-sized integer.''
cout << 'a' << (int)('a') << endl;yields a97 because 97 is the code for a. Here's how you can print out the ascii code for the alphabet:
for(char c = 'A'; c <= 'z'; c ++) cout << c << " " << (int)c << endl;(Try it!).
Cast In the above example (int)c
is an example of
using the cast operator. Even though c is of type char,
writing (int)c
forces a type conversion into an int.
c isn't converted into an int, but the expression
(int)c
delivers the integer value of c. In general,
a cast construction has the form
(type-name) expressionHere the value of expression is converted to the named type, even though expression itself is not actually altered.
A string is an array of chars.
char s[20];A string constant looks like this:
"A string" A s t r i n g \0 - - - - - - - - - 0 2 4 6 8The array elements occupy slots 0 through 8. The array size usually is larger than the string length. The last array element is a
\0
.
char s[]="A string"; //sets the length automatically char s[20]="A string"; //sets s to A s t r i n g \0 \0 \0 \0 ...
To copy strings, treat them like arrays. So don't say
char s[20]; char t[20]="A string"; s=t;(This makes s and t point to the same point in memory. We want to make 2 copies of the same array that will occupy 2 different places in memory.) Rather say
char s[20]; char t[20]="A string"; for(i=0;i<20;i++) s[i]=t[i];If we don't want to waste time copying all the
\0's
,
we can write
char s[20]; char t[20]="A string"; i=0; while (1) { s[i]=t[i]; i++; if(t[i]=='\0') break; }or
char s[20],t[20]; i=0; while((s[i]=t[i]) != '\0') i++;``break;'' tells the program to exit the innermost loop that it is inside of. If the program doesn't break, then it continues with the next iteration.
typedef float distance;Now distance is a synonym for float. We can write
distance d;This can make the variables in a program easier to understand. Another use for typedef is if you want to change the variable types in a program. You may want to do this to suit machine-dependent data types, since different machines can have different numbers of bytes for long, short, and int. So rather than change every line, you declare your variables with a synonym and then just change the typedef statement. For example, let's say you write
typedef long number; number a; number b; number c;Later, if you want to change all the number variables to be short, you just change the typedef statement:
typedef short number; number a; number b; number c;This is much easier to change than if you had originally written
long a; long b; long c;and then had to change each line to
short a; short b; short c;