C For Engineers Handout
C For Engineers Handout
2 20 22 24 24 26 26 27 28 28 30 32 32 33 34 35 38 40 40 41 42 43 43 44 44 46 47 48 48 49 50 51 52 53 53 54 57
2006 February
Outline
Expressions 6.1 Arithmetic Expressions . . . . . . . . 6.2 Arithmetic Operators and Precedence 6.3 All Operators and their Precedence . . 6.4 Relational Expressions . . . . . . . . 6.5 Logical Expressions . . . . . . . . . . 6.6 Assignment Expressions . . . . . . . 6.7 Increment, Decrement Operators . . . 6.8 Comma Operator . . . . . . . . . . . 6.9 Arithmetic if Expressions . . . . . . . 6.10 Bitwise Operators . . . . . . . . . . . 6.11 Casts . . . . . . . . . . . . . . . . . .
Contents
1 2 Who am I? Who are You? Overview 2.1 Quick Tour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Standard Input, Standard Output . . . . . . . . . . . . . . . . . . . . . . . 2.3 Redirecting Output and Input . . . . . . . . . . . . . . . . . . . . . . . . . C++ and iostreamlibrary 3.1 An overview of the iostream library . . . . . . . . . . . . . . . . . . . . Continuing our tour 4.1 hello.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Basic Syntax . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Input characters without skipping whitespace . . . . . . . . 4.4 I/O of other data to standard output and from standard input . 4.5 Reading into strings . . . . . . . . . . . . . . . . . . . . . . 4.6 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.7 Reading till the end of le . . . . . . . . . . . . . . . . . . 4.8 Innite Loop while reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 4 4 5 6 7 7 9 9 9 10 11 12 13 13 14 14 16 18
Statements 7.1 Simple Statements . . . . . . . . . . . . . . . . . . 7.2 Compound Statements . . . . . . . . . . . . . . . . 7.3 Scope . . . . . . . . . . . . . . . . . . . . . . . . . 7.4 Looping Statements . . . . . . . . . . . . . . . . . . 7.5 while Statement . . . . . . . . . . . . . . . . . . . 7.6 do statement . . . . . . . . . . . . . . . . . . . . . 7.7 Avoid Confusing == with = . . . . . . . . . . . . . . 7.8 Using a constant or single variable as a test condition 7.9 while and the null statement . . . . . . . . . . . . . 7.10 for Statement . . . . . . . . . . . . . . . . . . . . . 7.11 Comparing while and for . . . . . . . . . . . . . . 7.12 if and switch Statements . . . . . . . . . . . . . . . 7.13 break, continue, goto . . . . . . . . . . . . . . . 7.14 Exercises . . . . . . . . . . . . . . . . . . . . . . . Functions 8.1 Dening Functions . . . . . . . . . 8.2 Calling Functions . . . . . . . . . . 8.3 Using return Value from Functions 8.4 Function Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
1. Who am I? Who are You? 9 Arrays 9.1 Dening Arrays . 9.2 Arrays and Loops 9.3 Exercise . . . . . 9.4 Strings . . . . . .
3 58 58 60 61 61 63 64 65 65 68 68 68 71 72 73 74 76 77 77 77 78 79 80 81 82 82 83 84 86
2. Overview Call me Nick My email address is [email protected] The notes for this class are always available at http://nicku.org/c-for-engineers/ I taught in Hong Kong for ten years I taught in Macau one year before that Before that I wrote software in C++ to collect data for medical experiments How we will work in these classes We will learn by doing I will explain something for a short time you will then try it out for a short time Next week: I will print the notes out for you, now that I know what you need I will give you more information about this course
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
10 Pointers 10.1 Pointers as Function Parameters . . . . . . . . . . . . . . . . . . . . . . . 11 Arrays and Pointers 11.1 Strong relationship between arrays and pointers . . . . . . . . . . . . . . . 12 Multidimensional Arrays and arrays of pointers 12.1 Arrays of pointers . . . . . . . . . . . . . . . 12.2 Memory Allocation . . . . . . . . . . . . . . 12.3 Multidimensional Arrays . . . . . . . . . . . 12.4 Command Line Arguments: argc, argv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13 Structures 13.1 Passing Structures to Functions . . . . . . . . . . . . . . . . . . . . . . . . 13.2 typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Reading and Writing Files 14.1 fstream: le input and output . . . . 14.2 Error Handling . . . . . . . . . . . . . 14.3 Binary les . . . . . . . . . . . . . . . 14.4 Character I/O . . . . . . . . . . . . . . 14.5 Reading a Line at a time: getline() 14.6 I/O of other data to/from Text Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
This is always available from http://nicku.org/; click on the link on the left C for Engineers. I will publish all the teaching material also on http://gonzo.org.au/, and Ill explain to you how to use it
Overview
15 Guidelines 15.1 Style Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.2 Program Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.3 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Some Things to Read
Welcome!
Although C matches the capabilities of many computers, it is independent of any particular machine architecture. it is not difcult to write portable programs that can be run without change on a variety of hardware the standard makes portability issues explicit, and prescribes a set of constants that characterize the machine on which the program is run. See limits.h C quick tour (continued) The standard library is a suite of ready-written commonly used functions header les declare the library functions, and any symbolic constants required. The (obsolete) header le for the iostream library is included into your program le with:
#include <iostream>
Header les tell the compiler about the library functions and about the type of the parameters and return types linker automatically links in the required functions at compile-time. C programs make use of functions from the standard library; e.g., all input and output operations are usually performed using standard library functions.
normally
command >
with redirection
output (file)
Input Redirection < redirects standard input from a le, e.g., C:\STUDENT> analyse < numbers.txt
These are normally connected to the keyboard and your command prompt window
3. C++ and iostream library analyse now take the contents of the le numbers.txt as its input
3.1 An overview of the iostream library std::cin pronounced see-in an istream class object representing standard input std::cout pronounced see-out an ostream class object representing standard output std::cerr pronounced see-err an ostream class object representing standard error Input and Output operators
numbers.txt (file)
<
st di n
analyse
stdo ut
Output is done using the left shift operator < < Input is done using the right shift operator > >
#include <iostream> int main( void ) { char name[ 1000 ]; std::cout < "what is your name? "; < std::cin > name; > if ( name[ 0 ] == \0 ) std::cerr < "error: name is empty!\n"; < else std::cout < "hello, " < name < "!\n"; < < < }
3
C++
How do I remember? A way of remembering which operator is which: each operator points in the direction the data moves, e.g.,
> x >
gets data out from x Why is this better than printf() and scanf()? std::cin, std::cout and std::cerr know the type of data they are working with, so there is no need for you to remember which format string is needed for which data type; it all just works
If you are using a very old C++ compiler, put this instead: #include <iostream.h> The library denes three standard stream objects:
4.3 Input characters without skipping whitespace Variable declarations Variables are declared and dened with a data type and a name. The name is also called an identier.
10
4.1 hello.cpp
First example Program hello.cpp:
// A rst program in C++ #include <iostream> int main( void ) { std::cout < "Hello World\n"; < }
First character of a variable must be letter or underscore (_). Special characters (e.g., $ and #) are illegal. Some people (including me!) recommend using lowercase letters and underscores only.
Output for Program hello.cpp: Hello World Good programming practice Indentation can improves clarity and readability. It can be enhanced by placing braces or blank lines. Use variable and function names that explain themselves Functions should be shorter than one A4 page and should be simple to understand Every long or complicated function should be preceded by a comment describing the purpose of the function. Aim: make the program as easy for a human to understand as possible Saves money: less time to change/update program = less money.
Note that by default, std::cin > letter ; will skip over whitespace, such as spaces, > tabs and newlines You can use the iostream member function std::cin.get() to input characters one at a time, including whitespace:
#include <iostream> int main( void ) { char letter ; std::cin.get( letter ); std::cout < letter ; < }
4.4 I/O of other data to standard output and from standard input Data Types Three of the most commonly used data types: int double char integer oating point number character
11 4.5 Reading into strings Output of program celcius.cpp: 212 deg F => 100 deg C Using std::cin for input std::cin object performs the opposite operation. reads text from standard input and assigns to variables automatically converts the input text data to appropriate types Program cin-cout-2.cpp:
#include <iostream> int main( void ) { int num; oat cost; std::cout < "Enter number: "; < std::cin > num; > std::cout < "Enter cost: "; < std::cin > cost; > std::cout < "Num = " < num < ", cost = " < < < < cost < \n; < < }
12
Program vars.cpp:
#include <iostream> int main( void ) { int num = 5; oat cost = 9.5; std::cout < "Hello: num = " < num < < < " cost = " < cost < < < \n; < }
The std::endl manipulator The iostream libraries support manipulators A manipulator changes the state of a stream The std::endl manipulator: prints a newline \n, and sends any remaining characters stored ready for output, to the output We say that this ushes the buffer
4.4 I/O of other data to standard output and from standard input
Input and output with iostream Simple input and output operations using iostream library objects std::cout and std::cin Program celcius.cpp:
#include <iostream> int main( void ) { double fahr = 212, cel; cel = ( 5.0 / 9.0 ) * ( fahr 32 ); std::cout < fahr < " deg F => " < < < cel < " deg C\n"; < < }
13
14
If you execute the code std::cin > name; after reaching end of le, the result is > false. That means you can write code like this:
if ( std::cin > name ) { > // do something with name }
You can also write a loop that automatically terminates when there is no more to read:
oat num; while ( std::cin > num ) { > // Now we know that num is a valid oat, // so do something with it }
4.6 Loops
Loops A loop will cause statements to be executed repeatedly until a test condition proves false Program while-1.cpp:
#include <iostream> int main( void ) { int j = 0; while ( j < 5 ) { std::cout < "j has the value " < j < \n; < < < j = j + 1; } }
After this loop is nished, either we have reached end of le, or the next input is not a valid oat
if you enter something that is not a valid oat, you get an innite loop. Use the method I described in the last slide.
Data Types
Data Types
5. Data Types
15
5.1 Integer Types Integer and oating point data types Types of integer data (each has an unsigned counterpart): character
16
Data is represented in memory by a sequence of bits, arranged into bytes, eight bits to a byte These bits could represent strings or characters integers oating point values memory addresses binary values representing music or video ... Each item of data has a data type The data type determines how the program will interpret the data Declaration & data types A variable declaration consists of a data type and an identier, followed by a semicolon: Data Type Example: int count; Variable Name semicolon
integer short integer long integer long long integer Types of oating point values: single precision (oat) double precision (double) long double precision (long double) The range of values that can be held are machine dependent. The ranges of integer types are in limits.h The ranges of oating types are in float.h
Basic data types character signed character unsigned character integer unsigned integer long integer unsigned long integer long long integer unsigned long long integer short integer oating point
Keywords char signed char unsigned char int int long unsigned long long long unsigned long long short oat or double or long double
Signed Integers: int size: range: use: standard integer system dependent, usually size of a word. INT_MIN to INT_MAX, dened in limits.h. For 4 byte word, 231 1 to 231 , i.e., 2147483648 to 2147483647 int num; 1000
17
5.2 Characters
18
unsigned int long size: range: example declaration: example constant: short size: range: declaration: constants: long long long long size: range: example declaration: example constant: unsigned long long size: range: example declaration: example constant: Unsigned integers 1 use: very large numbers usually 8 bytes. for 8 bytes, 263 to 263 1, i.e., 9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 long long lnum; 5212000LL use: very large positive numbers usually 8 bytes. for 8 bytes, 0 to 264 1, i.e., 0 to 18,446,744,073,709,551,615 unsigned long long lnum; 5212000LL char size: range: example declaration: example constant: usually 8 bits; CHAR_BIT in limits.h CHAR_MIN to CHAR_MAX. For 1 byte, could be 27 to 27 1, i.e., 127 to 128 or 0 to 255 char ch; a use: large numbers size: usually 4 bytes. LONG_MIN to LONG_MAX. For 4 bytes, 2 2147483648 to 2147483647 long lnum; 5212000L Unsigned integers 2
unsigned long size: range: example declaration: example constant: unsigned short size: range: example declaration: example constant: usually 2 bytes; always same size as short int 0 to USHRT_MAX. For 2 bytes, 0 to 65536 unsigned short usnum; 34000u usually 4 bytes; always same size as long 0 to UINT_MAX. For 4 byte, 0 to 232 1 = 4294967295 unsigned long ulnum; 76212000uL
31
system dependent; always same size as int 0 to UINT_MAX. For 4 byte word, 0 to 232 1, i.e., 4294967295 unsigned int unum; or unsigned unum; 5530u
range: to 2
31
1, i.e.,
declaration: constants:
use: smaller numbers 2 bytes or same size as integer SHRT_MIN to SHRT_MAX. For 2 bytes, 215 to 215 1, i.e., 32768 to 32767 short snum; 120
5.2 Characters
Characters When working with characters, use the type char. Note that the type char can be signed or unsigned, depending on the compiler.
5.2 Characters
19
20
Characters: signed, unsigned specify the type as signed or unsigned only if you care.
#include <iostream> int main( void { char letter int num char ch1 char ch2 ) = A; = letter ; = b; = B; // A is character constant // ASCII code = 98 // ASCII code = 66
signed char size: range: example declaration: example constant: unsigned char usually 8 bits; CHAR_BIT in limits.h SCHAR_MIN to SCHAR_MAX. For 1 byte, 27 to 27 1, i.e., 127 to 128 signed char ch; a
std::cout < "letter = " < letter < < < ", num = " < num < \n; < < < std::cout < "letter + 1 = " < letter + 1 < < < ", num = " < num < \n; < < < std::cout < ch1 < " - " < ch2 < < < < " = " < ch1 ch2 < std::endl; < < < }
Output for Program princhar.cpp: size: range: example declaration: Character types Characters are represented in C with integer values. The correspondence between a given character and an integer value is determined by an agreed-upon character set, such as the ASCII character set. Examples of declarations:
char letter ; signed char sletter ; unsigned char uletter ;
usually 8 bits; CHAR_BIT in limits.h 0 to UCHAR_MAX. For 1 byte, 0 to 28 1 = 255 unsigned char ch; letter = A, num = 65 letter + 1 = 66, num = 65 b - B = 32
Program princhar.cpp
The long integer qualier L can also used with the octal and hexadecimal Example of octal constant: 0553000L Example of hexadecimal constant: 0x2f6c7a333L
21
22
std::dec Changes the state of the ostream to displaying all integer type numbers in decimal std::showbase a state that displays octal with leading 0, hexadecimal with leading 0x
Floating point data types oat double size: range: example declaration: example constants: twice the size of oat, usually eight bytes DBL MIN to DBL MAX dened in float.h double dnum; oating point notation: 3.4567 exponential notation: 4.788e+5, 3e1
Output for Program printvar.cpp num (dec) = 77, (oct) = 0115, (hex) = 0x4d small (oct) = 0173, little (hex) = 0x7b big (dec) = 88000, large (dec) = -43000 unum = 45000, ubig = 330000000 small (dec) = 123, little (dec) = 123 We need to include iomanip here for the manipulators: std::oct Changes the state of the ostream to displaying all integer type numbers in octal. All numbers printed while in this state are in octal. std::hex Changes the state of the ostream to displaying all integer type numbers in hexadecimal
Floating point data types long double long double size: range: example declaration: example constants: bigger than the size of double. LDBL MIN to LDBL MAX dened in float.h long double ldnum; 3.4567L exponential notation: 4.788e+5L
23
24
Output for Program float.cpp float min: 1.17549e-38 float max: 3.40282e+38 double min: 2.22507e-308 double max: 1.79769e+308 long double min: 3.3621e-4932 long double max: 1.18973e+4932 float epsilon: 1.19209e-07 double epsilon: 2.22045e-16 long double epsilon: 1.0842e-19 A long double constant: 478800
Output for Program float-io.cpp cost = 15.92, total = 360000 value = 35.7 debt = 1.2e+15 decrease = 5e-06 Program float.cppshowing limits of oating values
#include <oat.h> #include <iostream> int main() { std::cout < < std::cout < < std::cout < < std::cout < < std::cout < < std::cout < < std::cout < < std::cout < < std::cout < < std::cout < < return 0; }
"float min: " < FLT MIN < \n; < < "float max: " < FLT MAX < \n; < < "double min: " < DBL MIN < \n; < < < "double max: " < DBL MAX < \n; < "long double min: " < LDBL MIN < \n; < < "long double max: " < LDBL MAX < \n; < < < "float epsilon: " < FLT EPSILON < \n; < "double epsilon: " < DBL EPSILON < \n; < < "long double epsilon: " < LDBL EPSILON < \n; < < "A long double constant: " < 4.788e+5L < \n; < <
25
26
#include <iostream>
30 5 255 1
int main( void ) { const oat rate = 1.5; oat cost = rate * 8;
// with ;
Expressions
Expressions dene the tasks to be performed in a program do calculations perform function calls and assignment operations Arithmetic expressions perform the standard arithmetic operations. Arithmetic operator is a symbol or a binary operator, i.e. acts upon 1 or more operands or values. Operand - may be constant, variable, or function.
Expressions
std::cout < "cost = " < cost < < < ", rate = " < rate < \n; < < < }
Program enum-2.cpp:
#include <iostream> enum weather { clouds, rain, sunny, storm }; int main( void ) { weather today = sunny ; std::cout < clouds < < rain < < < < < < sunny < < storm < \n; < < < < std::cout < "today: " < today < \n; < < < }
operator
8 + x
operands
Enumerated types 2 Program enum-3.cpp:
#include <iostream> enum weather { clouds = 30, rain = 5, sunny = 255, storm = 1 }; enum boolean { TRUE = 1, FALSE = 0 }; int main( void ) { weather today = rain; std::cout < clouds < < rain < < < < < < sunny < < storm < \n; < < < < std::cout < "today: " < today < \n; < < < }
6.2 Arithmetic Operators and Precedence Arithmetic operators binary Additive operators: + addition subtraction
total = 8 + 5 2; sum = num 3;
27
28
Arithmetic Precedence and Associativity (cont) If the operators share the same operand, the priority of one operator over the other will be determined by its associativity. Associativity describes how an operator associates its operands. Arithmetic operators associate left to right, whereas assignment operators associate right to left. Example:
2 + 10 5
If there are no parentheses, precedence determines the order of evaluation All operators are ranked according to their precedence. Operators with greater precedence are evaluated rst.
6.4 Relational Expressions Level 15L Operator >, . [] () sizeof ++, ! +, *, & () *, /, % +, < > <, > <, <=, >, >= ==, != & ^ | && || ?: = *=, /=, %= +=, =, < <= > >=, &=, |=, ^= , Function structure member selectors array index function call size in bytes increment, decrement bitwise NOT logical NOT unary plus, minus dereference, address-of type conversion (cast) multiply, divide, modulus arithmetic operators bitwise shift relational operators equality, inequality bitwise AND bitwise XOR bitwise OR logical AND logical OR arithmetic if assignment operator compound assignment operators
29
6.5 Logical Expressions Relational expressions 1 Relational expressions can be combined with other expressions. Example:
num = 3; abc = ( num < 5 );
30
14R
As 8 > 5, the value of abc is 5 + 0 = 5. Relational expressions 2 The equality operators test a relationship between two operands result is 1 or 0. == equal, != not equal equality operator is a double equal sign == assignment operation is a single equals sign = e.g while ( test == 1 ) // comparison operation for equality test = 1; // assignment operation
1L
comma operator
Table 1: Table of C operators and their precedence A relational operator compares two operands and determines whether one is greater or less than the other. < > <= >= less than greater than less than or equal greater than or equal
6.5 Logical Expressions Logical expressions 2 Here is the truth table for the logical AND operation: expr1 T T F F non-zero non-zero 0 0 T F T F expr2 non-zero 0 non-zero 0-zero (expr1) && (expr2) T F F F 1 0 0 0
31
32
Truth table for the logical OR operation: expr1 T T F F non-zero non-zero 0 0 T F T F expr2 non-zero 0 non-zero 0-zero (expr1) || (expr2) T T T F 1 1 1 0
Parentheses can be left out since assignment evaluate from right to left.
total = num = 4 + 2;
which is identical to
total = 4 + 2; num = 4 + 2;
Truth table for the logical NOT operation: expr T F non-zero 0 !(expr) F T 0 1
Arithmetic assignment operators provide a shorthand applying an arithmetic operation to a variable j += 3; is equivalent to j = j + 3;
Program countdig.cpp
/* Counts only the numeric characters 0 - 9 read from standard input */ #include <iostream> int main( void ) { int n = 0; char c; while ( std::cin > c ) { > if ( c >= 0 && c <= 9 ) n = n + 1; } std::cout < "Count of digits = " < n < \n; < < < }
j *= 3; is equivalent to j = j * 3; List of arithmetic assignment operators: += = *= /= %= add and then assign subtract and then assign multiply and then assign divide and then assign modulo; assign remainder
33
34
The increment or decrement operator can operate in two ways: Prex places the increment or decrement operator before its operand. Postx places the increment or decrement operator after its operand. Example:
x = 32; y = ++x;
The result is the value of the last expression in its list i.e.,
r = num = 5
equivalent to
if ( a > b ) max = a; else max = b;
35
36
The bitwise exclusive OR operator, ^, results in 1 if the corresponding two bits are different: bit m 0 0 1 1 Shift Operators There are two shift operators: < left shift operator < > right shift operator > useful for accessing individual parts of a bit pattern shift the bits of the left operand some number of positions to the left or right.
unsigned char bits = 1; bits = bits < 1; < bits = bits < 2; < bits = bits > 3; > // // // // 0000 0000 0000 0000 0001 0010 1000 0001
bit m 0 1 0 1
m ^ n 0 1 1 0
Right Shift Operator the right shift operator will ll negative signed numbers with 1s from the left, but will shift 0 into the MSb (most signicant bit) of unsigned numbers. Program shiftright-demo.cpp
Bitwise operators 3 The ones complement operator, , is a unary operator. The resulting value is set to the opposite of that of the operands bit. bit m 0 1 m 1 0
37
6.11 Casts so the signed value 0xfffffff0 (16) shifted right two places is 0xfffffffc Use of bitwise operators Use the AND operator & to clear individual bits, leaving the others unchanged For example,
x = x & 0xf;
38
Use the OR operator | to set individual bits, leaving the others unchanged For example,
y = y | 0xf ;
will set all bits except for the least signicant four bits of y Use the Exlusive OR operator ^ to toggle (ip) individual bits, leaving the others unchanged For example, Right Shift Operator: example output output of program shiftright-demo.cpp (folded to t): dec n: -16; n >> 2: -4 hex n: 0xfffffff0; n >> 2: 0xfffffffc dec u: 4294967280; u >> 2: 1073741820 hex u: 0xfffffff0; u >> 2: 0x3ffffffc dec n: 16; n >> 2: 4 hex n: 0x10; n >> 2: 0x4 dec u: 16; u >> 2: 4 hex u: 0x10; u >> 2: 0x4 dec n: -1; n >> 2: -1 hex n: 0xffffffff; n >> 2: 0xffffffff dec u: 4294967295; u >> 2: 1073741823 hex u: 0xffffffff; u >> 2: 0x3fffffff dec n: 1; n >> 2: 0 hex n: 0x1; n >> 2: 0 dec u: 1; u >> 2: 0 hex u: 0x1; u >> 2: 0 Notice that when shifted right: unsigned values have the upper two bits zero so the unsigned value 0xfffffff0 shifted right by two is 0x3ffffffc signed values have the upper two bits the same as the previous value of the MSb (most signicant bit)
z = z ^ 0xf;
6.11 Casts
Cast expressions The cast operation returns the value of an expression, converting it to the type in the brackets Example:
( oat ) 7
This converts the integer 7 to a oating point value, 7.00. The operand may be any expression Examples:
( int ) ( 5.8 * 2.7 ) ( double ) ( k = 10 ) ( oat ) num
6.11 Casts If a oating point value is cast to an integer, the oating point fraction is lost. Example:
( int ) 3.75
39
7. Statements
40
Statements
A C program is a sequence of declarations and statements. We have seen: how to declare variables, and how to create expressions using operators examples of putting this all together. Now lets look at statements.
Statements: an introduction
resulting value is 3 Casts overide the compilers concept of correctness use rarely Conversions Expressions can include operands of different number types Example: An integer can be multiplied by a oat. C handled operands of different types by converting one of them into the same type as that of the other operand. Conversion determines which operand to convert by a process of promotion and demotion. Conversions: promotion In expressions with two different types of operands, the operand with the smaller type is always promoted to that of the largest type. Example:
int num = 6; oat cost; cost = num * 5;
Statements: intro 2 We can turn an expression such as x = 0 or std::cout < "a" into a statement simply < by putting a semicolon at the end:
x = 0; std::cout < "a"; <
We can join these into a compound statement by putting braces { } around them. There are some which are used to create loops and make decisions. These are sometimes called control-ow statements.
The expression num * 5 results in the integer 30 and will be promoted to a oat, 30.0 before assigned into the cost variable. Conversions: demotion Demotion from a oating point type to an integer type results in the loss of the oating points fraction. Example:
int num; oat cost = 62.65; num = cost;
However, the expression could just as easily be an arithmetic expression or relational expression. Example:
4 + 5; // nothing done with the result, 9. ( n < 3 );
The fraction will be cut off, leaving just the integer, 62. The value 62 is then assigned to the variable num.
41
7.3 Scope
42
If there is no expression in the expression statement, nothing happens. This is called as the null statement. Example:
#include <iostream> int main( void ) { int num = 10; oat cost = 100.0; { oat cost = 50.0; num = 5; std::cout < "Inside: " < cost < < < ", " < num < \n; < < < } std::cout < "Outside: " < cost < < < ", " < num < \n; < < < }
7.3 Scope
Scope A new scope is created in each block the compiler searches for an identier dened in the innermost scope rst then searches the scopes that the enclose current scope. . . . . . until it reaches global scope global scope is outside of any block
Blocks 1 Variables can be declared at the beginning of compound statement. A compound statement with variable declarations is referred to as a block. The body of a function is a compound statement itself, and is often referred to as the function block. Program blocks.cpp
identiers dened in an inner scope hide identiers dened in an outer scope For example, in program blocks.cpp, there are two variables called cost in different nested scopes The inner output statement prints the value of the cost variable dened in the inner scope The outer output statement prints the cost dened in the outer scope.
43
7.6 do statement
44
7.6 do statement
Iteration Statements do loop The do statement is a variation on the while statement. Instead of the test occurring at the beginning of the loop, it occurs at the end, Example:
i = 0; do { std::cout < "abc\n"; < ++i; // loop counter } while ( i < 4 );
Program square-1.cpp
#include <iostream>
This program has a major problem. What happens if we input a character that is not part of an integer?
7.7 Avoid Confusing == with = assignment operation simple primary expression consisting of a variable or a constant A zero result evaluated is considered to be false while any non-zero result is true. Traps with = and == Dont confuse comparison with assignment in a test expression. while ( i = k ) { ... } If k equals 0, the test will always be false If k is not equal to zero, the test will always be true. Examples of incorrect test expressions: while ( n = 0 ) { while ( n = 3 ) {
/* always false */
45
46
#include <iostream> /* This program shows problems that come from confusing assignment with comparison */ int main( void ) { int quit = 0, num = 1, square; while ( quit = 0 ) // Oh dear; always false { // the loop body will never be executed square = num * num; std::cout < "Square of " < num < < < " = " < square < \n; < < < if ( num = 10 ) // Oh dear; always true quit = 1; num++; } }
... } ... }
The correct way to write these test expressions is: while ( n == 0 ) { ... } while ( n == 3 ) { ... } Program quit-1.cpp
Program square-2.cpp
47
48
The for Statement The for statement consists of three expressions followed by a statement. for ( expression 1 ; expression 2 ; expression 3 ) statement ; expression 1 is executed once, before loop begins. It is often used to initialize variables used in the test expression. expression 2 is the test expression for the loop. When it evaluates as false, the loop stops. expression 3 update expression. It is executed within the loop and is usually used to update variables used in the test expression. Example of for loop
for ( int i = 1; i < 3; ++i ) { std::cout < "OK\n"; < }
Three actions take place in the above example: function call to the istream member function get() std::cin.get( ch ) will return false if reach end of input le; inequality operation in which character value obtained by std::cin.get() is tested against a newline constant. End result is that we wait till we get a newline character, or end of le example:
for ( int i = 0; i < 3; ++i ) std::cout < "loop " < i < < < \n; <
7.12 if and switch Statements Nested loops loop within a loop The inner loop executes fully within each iteration of the outer loop Example:
for ( int k = 0, i = 0; i < 3; ++i ) { for ( int j = 0; j < 3; ++j ) { ++k ; std::cout < k < ; < < } std::cout < \n; < }
49
7.13 break, continue, goto Only one action is performed the rst that matches is done. The switch statement 1
50
The switch statement provides a convenient way to choose among several alternatives. It is a conditional statement (selection) switch ( integer expression ) { case integer : statements ; break; case integer : statements ; break; default: statements ; break; } The switch statement 2 The switch compares an integer value against a set of integer constants. The execution will continue unless a break is encountered.
7.14 Exercises Example of use of continue Kernighan and Ritchie provide this example of using continue:
51
8. Functions
52
2. Save your source to a different le name, but replace all the ifs (except the rst) to else ifs. 3. Run your two programs and compare the output.
for ( i = 0; i < n; ++n ) { if ( a[ i ] < 0 ) // skip negative elements continue; // do positive elements }
4. Write a program contianing a while loop and a for loop that both output data and do the same thing.
Functions
A big program may be too complex to hold in your head. I need a way to break a big problem into many small, easy-to-understand problems. One way to break a problem into small problems is to divide a problem into small parts that can be written as functions. A function is a number of statements that: Perform one easily-understood job are given a single name. A function is a little bit like a simple IC, with input pins and output pins.
See also my example program cat.cpp goto: use it seldom goto and label statements allow the program to jump to any statement. Using goto can cause the program to become very hard to understand Use it only when you really have to An example is to break out of a nested loop from the inner loop
for ( i = small; i < big; ++i ) for ( j = small2; j < bigger ; ++j ) if ( i == j ) goto equal; equal:
Functions 1
7.14 Exercises
1. Write a program using the following code fragment as a guide:
int i = 10; if ( i > 0 ) std::cout if ( i > 1 ) std::cout if ( i > 2 ) std::cout // . . . if ( i > 10 ) std::cout else std::cout
sin()
< "i > 0\n"; < < "i > 1\n"; < < "i > 2\n"; <
The inputs go in the parentheses: () The output of the function can be assigned, as above.
8.1 Dening Functions Functions 3 To write and use functions in your program, there are two things to consider:
53
54
// Program to call a function #include <iostream> // function denition: void calc( void ) { std::cout < "Now in Calc\n"; < } int main( void ) { std::cout < "Hello World\n"; < calc(); std::cout < "Now in Main\n"; < }
When you dene the function, you write the statements that the function will perform when it is called. When you want to use the function, we say we call the function.
8.3 Using return Value from Functions return statement and function return value
55
56
The return statement consists of the keyword return, an expression, and a semicolon. Syntax: return expression ; The expression is called the return expression. return statement will: end the processing of a function make execution continue from where the function was called, and specify the functions return value. Function return value: example Program calc-3.cpp
#include <iostream> // Example of a function that takes // parameters oat calc( int num, oat calc rate ) { return calc rate * num; } int main( void ) { oat rate = 2.0; oat res = calc( 5, rate ); std::cout < "res = " < res < \n; < < < }
Return inconsistencies Return value inconsistencies: occur when the return expression has a type different from the functions return type. The return expression is what comes between the keyword return and the semicolon. The return type is what is written before the name of the function in a function denition.
int main( void ) { oat res1; res1 = calc(); printf ( "%f\n", res1 ); }
57
58
the value of x is copied to a, the value 4.5 is copied into b. The type of the parameter in the function call matches the type of the parameter in the same position in the function denition. This is like pins on an IC plugging into the holes in the IC socket.
Arrays
An array is a collection of objects, all of the same data type. Any one data type can be used in an array. an array of integers an arrary of characters an array of structures an array of pointers The declaration of an array reserves memory, which is then managed by pointers (to be discussed in next section). Array objects themselves are actually referenced through pointer indirection.
Arrays
An array declaration consists of 4 parts the data type array name, square brackets around the. . . . . . number of objects in the array
9.1 Dening Arrays Arrays 2 The declaration below declares an array of 5 integers. The array name is mynums
int mynums[ 5 ];
59
60
Once an array has been declared, its objects can be referenced and used in expressions. The array name, together with the position of an object in the array is used to reference an object. The objects in an array are arranged in sequence, starting from zero. The number of an objects place in that sequence is referred to as either the objects index or subscript. In the example above, we can see
mynums[ mynums[ mynums[ mynums[ mynums[ 0 1 2 3 4 ] ] ] ] ] = = = = = 3; 4; 5; 6; 7; // // // // // rst object second object third object fourth object fth object
Many different kinds of arrays may be declared, each having its own data type and number objects. int total[10]; char name[40]; an array of ten integers (i.e. total[0], total[1], . . . total[9]) an array of forty characters (i.e. name[0], name[1], . . . name[39])
Array initialisation When a variable is dened it can be initialised with a value. In the declaration:
char mychar = E;
the variable mychar is initialised with the character E. The elements of an array can also be initialised in an array declaration. The initalisation values are listed within curly braces and separated by commas:
int mynums[ 5 ] = { 3, 4, 5, 6, 7, };
Array Length When using standard C, the initialization part of the array declaration can be used be left out of the array declarations. The number is, instead, determined by the number of values in the initialisation block. Program array-1.cpp
#include <iostream> int main( void ) { char letters[ ] = { A, B, C, }; int totals[ ] = { 23, 8, 11, 31, }; std::cout < letters[ 1 ] < ; < < std::cout < totals[ 3 ] < \n; < < }
Array Management and Loops 2 A common rule of thumb is that the test for the end of an array is the less than operator, <, tested against the number of objects declared in the array.
9.3 Exercise Example: this for loop prints each number in the array:
int nums[ 4 ] = { 42, 1000, 7, 103 }; for ( int i = 0; i < 4; ++i ) std::cout < "this num is " < nums[ i ] < \n; < < <
61
9.4 Strings Note that the string denitions str and letters are equivalent.
62
Note that a string is automatically ended with a special character called the null character, \0 Arrays of characters: strings 2 Because the string has the extra \0 character at the end, the array of characters must be long enough to hold it. Example:
char string2[ ] = "string";
Using constants for array size In the listing below, the same symbolic constant, max, is used in both the array declaration and the test for the last array object in the for statement.
#include <iostream> const int max = 4; int main( void ) { int mynums[ max ] = { 23, 8, 11, 31 }; for ( int i = 0; i < max; ++i ) std::cout < mynums[ i ] < ; < < std::cout < \n; < }
9.3 Exercise
Write a program that: 1. Reads up to 20 numbers into an array; 2. After reading those numbers, the program calculates and prints the sum of the numbers in the array. 3. Note that your program should stop attempting to read numbers when there are no more numbers to read, i.e., because you have reached end of le, or a character is in the input that cannot be part of a number.
Careful: strings cf. characters A common mistake is to confuse a string with a character. Example:
char c; // Wrong! c = "A"; A character has single quotes: A
9.4 Strings
Arrays of characters: strings A string is an array of characters. Here are examples of denitions of strings:
char name[ 20 ]; char string[ ] = "This is a string"; char str [ 10 ] = "string"; char letters[ 10 ] = { s, t, r, i, n, g, \0 };
The string "A" is actually two characters: A then \0. One nal note: do not assign strings!
char str [ 100 ]; str = "this is a string"; /* Oh no, a mistake! Use strcpy () library function instead. */ strcpy ( str, "this is a string" ); // OK
63
10.1 Pointers as Function Parameters There are 3 elements involved in this referencing process: a pointer variable an address and another variable Pointer holds address A pointer variable holds the address of another variable of a particular type Program pointer-1.cpp
64
The standard C++ strings library is the best choice for simplicity, but the Borland 3.1 compiler does not seem to support it The standard library that comes with (nearly) every C compiler provides lots of functions for working with strings. To use them, put:
#include <string.h>
at the top of your program. Here are some: strlen() give the length of a string strcpy () copy one string to another string strcmp() compare two strings strcat() join one string onto the end of another Working with strings 2 Example using strlen():
int len; len = strlen( "a string" ); // len = 8 #include <iostream> int main( void ) { int num = 12; int *nptr ; nptr = # std::cout < "num holds " < num < < < " and nptr points to " < *nptr < \n; < < < std::cout < "The address held in nptr is " < nptr < < < \n; < }
Output of program pointer-1.cpp: num holds 12 and nptr points to 12 The address held in nptr is 0xbfafade8
10 Pointers
Pointers Any object dened in a program can be referenced through its address. A pointer is a variable that has as its value the address of an object. A pointer is used as a referencing mechanism. A pointer provides a way to reference an object using that objects address.
and call it like this: swap( a, b );, the values of a and b are copied by value, so the nal values are not changed.
65
11.1 Strong relationship between arrays and pointers C Arrays and pointers
66
The right way is to pass the address of a and b like this: swap( &a, &b ); and dene the function like this:
void swap( int *x, int *y ) { int temp = *x; *x = *y ; *y = temp; }
The name of an array is the same as the location of the rst element, so these two statements are equivalent:
pa = &a[ 0 ]; pa = a;
An expression made of an array and index has an equivalent expression made with a pointer and offset. Important: we can do
++pa; // okay; now pa points to a[ 1 ]
. . . but not:
++a; // compiler error
. . . because an array name is a constant, but an ordinary pointer is not. Passing arrays to functions
If a parameter is an array name, inside the function it is a pointer to the rst element of the array If you nd the size of an array with sizeof, you are given the number of elements the size of one element Inside a function, the size of an array parameter is the size of a pointer. See program array-parameter.cpp. Note that the sizeof operator gives the number of characters in either a type or an expression: sizeof( T ) gives the number of characters in the type T sizeof expression gives the number of characters in the expression expression.
then the value of *pa is the same as is stored in a[ 0 ]. The pointer pa + 1 points to the value of a[ 1 ], so this statement is true: *( pa + 1 ) == a[ 1 ] If we add 1 to a pointer, we point to the address just after the value stored at that pointer. If sizeof( int ) is 4, and if addresses each hold one character, then the address pa + 1 is 4 address locations higher than the address pa. The type of the pointer determines what address you get when you increment a pointer. similarly *( pa + i ) == a[ i ] is true.
67
68
If the length of the array passed to mean() is 100, then that number must be passed as a separate parameter.
Output of array-parameter.cpp sizeof( a ) = 4 sizeof( ar ) = 40 sizeof( ar ) = 40 number of elements in ar[] is 10 Passing arrays to functions 3 To work properly, you need to pass the length of an array as a separate parameter together with the array. Example:
double mean( int nums[ ], int len ) { int sum = 0; for ( int i = 0; i < len; ++i ) { sum += nums[ i ]; } if ( len == 0 ) return 0; return ( double ) sum / len; }
We must make sure that we allocate memory using the new operator for this as we read lines.
Note that it makes no difference to write the parameter as int nums[ 100 ], since that length information will not be passed to the function as part of the int nums[ 100 ] parameter
12.2 Memory Allocation and free the memory like this: delete [] pointer ; the result from new is a null pointer if the memory cannot be allocated. Always check the return value of new Example use of new: Program new-1.cpp Program new-1.cpp does the following: dynamically allocate an array of ten integers terminate if allocation doesnt succeed put a value into each element of the array print each value free up the memory
#include <iostream> #include <stdlib.h> int main( void ) { const int maxn = 10; int *a = new int[ maxn ]; if ( a == NULL ) { std::cerr < "Out of memory!\n"; < exit( 1 ); } for ( int i = 0; i < maxn; ++i ) a[ i ] = i + 1; for ( int i = 0; i < maxn; ++i ) std::cout < "a[ " < i < " ] = " < < < < a[ i ] < \n; < < delete [ ] a; }
69
70
#include <iostream> #include <string.h> // Read all of input into memory. // at a time, as we read it. Normally we would process one line
// Read each line into a string // allocate memory for the string and copy the string into that memory // add the newly allocated string to an array of pointers int read lines( char *lines[ ], int maxnlines ) { const int maxlinelen = 8000; char line[ maxlinelen ]; int nlines = 0; while ( std::cin.getline( line, maxlinelen ) ) { int len = std::cin.gcount(); // includes space for \0 char *p; if ( nlines >= maxnlines | | ( p = new char[ len ] ) == NULL ) { return 1; } else { strcpy ( p, line ); lines[ nlines++ ] = p; } } return nlines; }
Program new.cpp 2
Program new.cpp 1
71
12.4 Command Line Arguments: argc, argv Note that this is wrong, and just uses the comma operator:
72
void write lines( char *lines[ ], int nlines ) { while ( nlines > 0 ) std::cout < *lines++ < \n; < < } void free lines( char *lines[ ], int nlines ) { while ( nlines > 0 ) delete [ ] *lines++; } int main( void ) { const int maxlines = 10000; char *line[ maxlines ]; int nlines = read lines( line, maxlines ); if ( nlines >= 0 ) { write lines( line, nlines ); free lines( line, nlines ); } else { std::cerr < "Input is too big to read\n"; < } }
parameter argc is the number of arguments on the command line including the program name parameter argv is a pointer to an array of command line arguments if the program echo is called like this: echo this is a test then argc is 5, argv [ 0 ] is "echo", argv [ 1 ] is "this", argv [ 2 ] is "is", argv [ 3 ] is "a", argv [ 4 ] is "test" and nally argv [ 5 ] is the null pointer. Program echo.cpp
denes a rectangular matrix. We can access the entry with the value 30 with
int entry = matrix[ 1 ][ 2 ];
prints its parameters, like the echo command in the Windows CMD.EXE shell, or like the echo command built into the bash shell that is popular with Linux.
13. Structures
73
13.1 Passing Structures to Functions We could initialise our struct employee like this:
struct employee person = { 8, 80000 };
74
13 Structures
Structures 1 A structure consists of a set of data objects that can be referenced as one object. struct tag name { list of declarations }; A tag can be used to label a structure type declaration. In the structure type declaration, the keyword struct may be followed with a tag placed before the opening brace of the declaration list, Example:
struct employee { int id; oat salary ; };
After this, person will contain the same values as in the next slide. Structures: Program struct.cpp
#include <iostream> int main( void ) { struct employee { int id; oat salary ; }; struct employee person; person.id = 8; person.salary = 80000; std::cout < "ID = " < person.id < \n; < < < std::cout < "Salary = $" < person.salary < \n; < < < }
Dening struct variables We can dene a variable person of the type struct employee like this:
We can now refer to the two values in the variable person as person.id and person.salary Initialising struct variables We can initialise a structure when it is dened by putting a list of values in braces, as we do for arrays The rst item in that list initialises the rst element of the structure, the second item initialises the second element of the structure, ...
we could access the members with the arrow operator > like this:
p>id = 8; p>salary = 80000; std::cout < "ID = " < p>id < \n; < < < std::cout < "Salary = $" < p>salary < \n; < < <
75
13.2 typedef
76
There is nothing magic about the > operator; it is just a shorthand used, because we often access members of structures through pointers Note that p>id is equivalent to (*p).id , and p>salary is equivalent to (*p).salary . Passing Structures to Functions Unlike arrays, structures are passed to functions by value That means that your function only gets a copy of the structure. If you want to modify the original structure, you need to either: return the modied structure, or pass a pointer to the structure. Passing Structures: example Here we use the struct employee dened previously. Passing structure by value
struct employee raise salary ( struct employee p, oat raise ) { p.salary += raise; return p; } // in another function: struct employee manager = { 50, 100000 }; manager = raise salary ( manager, 20000 );
#include <iostream> struct complex { int re; int im; }; complex cadd( complex z1, complex z2 ) { complex zt; zt.re = z1.re + z2.re; zt.im = z1.im + z2.im; return zt; } int main( void ) { complex za; za.re = 1; za.im = 2; complex zb = za; complex zc = cadd( za, zb ); std::cout < "zc.re = " < zc.re < < < ", zc.im = " < zc.im < \n; < < < }
13.2 typedef
typedef A typedef is used to allow the programmer to give another name to a type. typedef type NAME ;
denes NAME as a new name for the existing type type Example:
Often typedef is used with struct variables to avoid needing to type the word struct
77
78
#include <iostream> #include <fstream> // . . . std::ifstream n( "data.in" ); if ( ! n ) { std::cerr < "error: unable to open file " < < "data.in for reading\n"; < exit( 1 ); } std::ofstream fout( "data.out" ); if ( ! fout ) { std::cerr < "error: unable to open file " < < "data.out for writing\n"; < exit( 1 ); }
Appending to les To append to a le, use the extra parameter std::ios::app when dening the ofstream object:
#include <iostream> #include <fstream> // . . . std::ofstream fout( "data.out", std::ios::app ); if ( ! fout ) { std::cerr < "error: unable to open file " < < "data.out for appending\n"; < exit( 1 ); }
There are a number of other parameters available. OR them together with the bitwise OR operator |
79
80
#include <iostream> #include <fstream> // . . . std::ofstream fout( "data.out", std::ios::app | std::ios::binary ); if ( ! fout ) { std::cerr < "error: unable to open binary file " < < "data.out for appending\n"; < exit( 1 ); }
#include <iostream> #include <fstream> #include <stdlib.h> int main( void ) { char ch; std::ifstream n( "abc.txt" ); if ( ! n ) { std::cerr < "Cannot open file abc.txt\n"; < exit( 1 ); } // skips whitespace. // while ( n > ch ) > // std::cout < ch; < while ( n.get( ch ) ) std::cout.put( ch ); }
#include <iostream> #include <fstream> // . . . std::ofstream fout( "data.out", std::ios::out | std::ios::binary ); if ( ! fout ) { std::cerr < "error: unable to open binary file " < < "data.out for writing\n"; < exit( 1 ); }
14.6 I/O of other data to/from Text Files We often want to work with one line of a text le at a time
81
82
the istream member function getline() reads from a le and places it in a string or character array, without the ending newline.
std::cin.getline( string or character array , maximum length );
We can read formatted text from text les just as we can from standard input with std::cin Program filein.cpp:
#include <iostream> #include <fstream> #include <stdlib.h> int main( void ) { int num; std::ifstream n( "abc.txt" ); if ( ! n ) { std::cerr < "Cannot open abc.txt\n"; < exit( 1 ); } n > num; > std::cout < "we got " < num < < < " from abc.txt\n"; < }
15 Guidelines
15.1 Style Guidelines
Program layout: rules of thumb
not
printf ("%d",i);
and
x = x + 3;
not
x=x+3;
15.2 Program Design I suggest you put your main() function last.
83
15.3 Modules Program design: top-down Top-down design looks at the big picture rst, forgetting the details.
84
avoids the need to put function prototypes that need unnecessary extra maintainance Use modern books about C, not very old ones. Indent your program to make it easy to follow. Indent the body of loops and if statements.
Write pseudocode including only these important, big steps, leaving out small steps at rst. This is like your main() function. Write more pseudocode for each of these big steps, giving more detail, but not the smallest details. These are written rather like function denitions. For each step, write out more pseudocode like more function denitions, until you have enough detail to begin writing your source code. Check your design carefully before you move on.
15.3 Modules
Making an application from many modules Most useful C or C++ programs are written in separate modules Each module corresponds to: one .c, .C, .cc, .cpp, or .cxx le (lets call this the source le), and one .h, .H, .hh, or .hpp le (we call this the header le). Each header le lists the publicly exported names: type denitions, global variables, and function prototypes Avoid dening variables or functions in header les It makes this set of names as small as possible to reduce the interaction between modules All non-public functions dened in the source les are dened with the keyword static so that they cannot be linked to from other modules. Modules silly example main.cpp:
15.3 Modules
85
86
#include <iostream> #include "calc.h" #include "main.h" int glob; int main( void ) { glob = 10; int sum = calc( 15 ); std::cout < "sum = " < sum < \n; < < < }
A variable dened with the keyword static is visible only within its le, and does not conict with a variable with the same name dened in another le the static keyword can (and should) be used with functions that are to be used only within one le The static keyword can be used inside functions and blocks It is initialised once, and its value remains even between function calls. See Program static.cpp:
main.h:
#ifndef MAIN H #dene MAIN H extern int glob; #endif
#include <iostream> void show times called( void ) { static int called = 0; std::cout < "called " < ++called < " times\n"; < < < } int main( void ) { for ( int i = 0; i < 5; ++i ) show times called(); }
output of static.cpp: called called called called called 1 2 3 4 5 times times times times times
calc.h:
#ifndef CALC H #dene CALC H extern int calc( int n ); #endif
References
87
[2] Bjarne Stroustrup. The C++ Programming Language (Special 3rd Edition). AddisonWesley, 2004, ISBN 0201889544. [3] Tom Adamson and James L. Antonakos and Kenneth C. Manseld Jr. Structured C for Engineering and Technology, Third Edition. Prentice Hall, 1998. [4] Steve Oualline. Practical C Programming. OReilly 1993. [5] Paul Davies. The Indispensable Guide to C With Engineering Applications. AddisonWesley 1995. [6] H. M. Deitel and P. J. Deitel.C How to Program, Second Edition. Prentice Hall 1994. [7] Vincent Kassab.Technical C Programming. Prentice Hall 1989. [8] Marshall Cline. C++ FAQ LITE. http://www.parashift.com/c++-faq-lite/ [9] Bjarne Stroustrup. A Tour of the Standard Library. Chapter 3 of The C++ Programming Language. http://public.research.att.com/~bs/3rd_tour2.pdf License covering this document Copyright c 2006 Nick Urbanik <[email protected]> You can redistribute modied or unmodied copies of this document provided that this copyright notice and this permission notice are preserved on all copies under the terms of the GNU General Public License as published by the Free Software Foundation either version 2 of the License or (at your option) any later version.