You are on page 1of 11

1. Types, loops, subprograms CS II D.

Keil 1/03 1

Types, loops, subprograms Subtopic: Bitwise operations


(expanded review of CS I) • Operations: AND (&), OR ( | ), XOR (^),
complement (~), shift (<<, >>)
• Bitwise operators • Each operator performs a logical
operation on each bit of operand(s)
• The preprocessor
• Applications:
• Numeric and character data - Compact storage of status data
• Loops - Storage of sets
- Arithmetic at hardware level
• Subprograms
- Systems programming
David Keil 1/03 1 David Keil 1/03 2

Shift-left operator Bitwise examples


multiplies by a power of 2 C/C++
void main() Operation operator Example
{ [mult8.cpp]
cout << "Enter an integer: "; Complement ~ ~ 100000002 = 011111112
unsigned int input; OR | 11002 | 10012 = 11012
cin >> input;
cout << input << " * 8 = " AND & 11002 & 1001 2 = 10002
<< (input << 3) << endl; Left shift << 11012 << 1= 11010 2
} Right shift >> 110002 >> 2 = 1102
Sample I/O: Shift-left-3 multiplies
XOR ^ 10012 ^ 10102 = 0011 2
Enter an integer: by 8 because 2 3 = 8
6 6 * 8 = 48 David Keil 1/03 3 David Keil 1/03 4

Some bitwise problems Setting a bit to 1 with OR


Evaluate: • To set nth bit of a number, create a mask by
• 8 >> 1 = shifting a 1 left (n − 1)
times, and then bitwise-OR the number
• 3 << 2 =
with the mask.
• 7&2=
• E.g., 0001 2 OR 10102 = 10112
• 6|3=
• So to set 1st (rightmost) bit of 4-bit value
• ~15 = ten (1010 2 ), OR it with 0001:
• 9^6= cout << (10 | 1);
• a << b = Output:11 Must use parentheses here
• c >> d = David Keil 1/03 5 David Keil 1/03 6
1. Types, loops, subprograms CS II D. Keil 1/03 2

To set the nth bit of a number Clearing a bit to 0 with AND


int n,x; • To clear nth bit of a number, create a mask by
shifting a 1 left (n − 1) times and complement
cin >> n >> x; this; then bitwise-AND the number with the
int mask = 1 << (n - 1); mask
int result = x | mask; • E.g., (1) ~0001 2 = 1110 2
(2) 1110 2 AND 10112 = 1010 2
(First bit in 1011 is cleared in 1010)
The OR operation makes sure that • To clear first (from right) bit of 4 -bit value 11 10
the mask value’s single 1 bit sets to (1011 2), AND it with complement of
1 shifted left 0 places:
1 the corresponding bit in the result cout << (11 & ~(1 << 0));
David Keil 1/03 7 David Keil 1/03 8

To clear the nth bit Subtopic: The preprocessor


int n,x; • #include lets source file access library constants,
types, function declarations
cin >> n >> x;
• #define does text substitution in source:
int mask = ~(1 << (n - 1)); #define TAX 0.05
int result = x & mask; • #define x y : replaces string x with y
• #define LIB_H: adds identifier LIB_H to symbol list
• #ifdef LIB_H causes source code up to #endif to be
The AND operation makes sure that compiled only if LIB_H is #defined
the mask value’s single 0 bit clears to • #ifndef LIB_H: causes remaining source code up to
endif to be skipped if LIB_H defined
0 the corresponding bit in the result • #endif: completes ifdef or ifndef.
David Keil 1/03 9 David Keil 1/03 10

Preprocessor macros Subtopic: Standard types


• Macros with arguments eliminate function-call overhead;
but they are error prone
• Good example:
#define MIN(A,B) ((A) < (B)) ? (A):(B) • Integer
• Bad example:
#define SQUARE(N) N * N • Floating-point
Expansion of (SQUARE(2+1)):
2 + 1*2 + 1 = 5 • Character
Expansion of (8 / SQUARE(2)):
8 / 2 * 2 = 8 • String
• C++ supports inline functions; a safer option

David Keil 1/03 11 David Keil 1/03 12


1. Types, loops, subprograms CS II D. Keil 1/03 3

Small and large integer types Floating-point data


Storage Min. Max.
Type (bytes) value value
char 1 0 255
int 4 -2G +2G
unsigned int 4 0 +4G • Data types float and double represent
short int 2 -32K +32K numbers with possible fraction parts
long int 4 -2G +2G • The numeral floats because the exponent
• Type qualifiers: short, long, unsigned, const part compensates for a shift to eliminate
• Use the sizeof operator; e.g.: 0’s on the left
cout << sizeof (char); [sizeof.cpp] • double has twice the precision of float
David Keil 1/03 13 David Keil 1/03 14

C-style strings
Character data • String literals use double quotes
• A character’s data type is char • char s[20]; declares a char array (string)
• A string is a sequence of • Null character terminates a string
characters • Strings must be manipulated with libraries
such as string.h
• A standard string class is • Input: cin >> s;
evolving • Output: cout << s;
• The C-language input/output • Initialization: char s[ ] = “Foo”;
library is stdio.h • Conversions: atoi, atof (stdlib.h)
David Keil 1/03 15 David Keil 1/03 16

Some functions in string.h Using string.h functions


#include <string.h>
The standard C-style-string library: string.h [abcdef.cpp]
void main()
strlen(s): returns length of string s {
char s1[] = "abc",s2[] = "def",result[80];
strcpy(s1,s2): copies contents of s2 to s1 strcpy(result,s1);
strcat(s1,s2): concatenates s2 to end of s1 strcat(result,s2);
cout << "result = " << result << endl
strcmp(s1,s2): returns 0 if s1 and s2 are the << "strlen(" << result << ") = "
same; otherwise finds first character location << strlen(result) << endl
<< "strcmp( \"" << s1 << "\", \""
x where s1 and s2 differ and returns (s1[x]− << s2 << "\") = "
s2[x]) << strcmp(s1,s2) << endl;
}
strtok(s,ch): returns address of first substring
Output:
of s delimited by ch result = abcdef strlen(abcdef) = 6
David Keil 1/03 17 David Keil 1/03 18
strcmp("abc", "def") = -1
1. Types, loops, subprograms CS II D. Keil 1/03 4

strtok tokenizes a string Conditional expressions


void tokenize(char* s)
// Separates and displays components of <s>. int average = (n > 0 ? sum/n : 0);
{
cout << "You entered: " << endl;
char* tkn = strtok(s, " ");
• …has the same meaning as:
while (tkn) if (n > 0)
{
cout << tkn << endl; average = sum/n;
/* Subsequent calls to <strtok> using a NULL else
parameter 1 returns pointer to the character
after the token */
average = 0;
tkn = strtok(NULL," ");
}
• The conditional operator ? :
} is ternary (has 3 operands)
void main()
{ • The value of the conditional expression
cout << "Enter words separated by spaces: " << endl;
char input[80]; is operand 2 or 3, depending on the
gets(input);
[tokndemo.cpp ]
value of operand 1
tokenize(input); David Keil 1/03 19 David Keil 1/03 20
}

Subtopic: Loops and debugging Algorithm 1: What does it do, in


plain English?
• Kinds of loops: sentinel controlled, 1. a ← −1
counted, general exit tested
2. c ← 0
• C/C++ loop statements: top tested 3. b ← 0
(while), bottom tested (do…while), 4. Prompt for a
counted (for) 5. If a = 0, go to step 9
• Readability 6. If a = b then c ← 1; go to step 9
• Correctness 7. b ← a
• Debugging 8. Go to step 4
9. Display c
David Keil 1/03 21 David Keil 1/03 22

Algorithm 2 Conditions for software correctness


input ← −1 • Program eventually halts
match ← false under all conditions
previous ← 0 • Thus, values that control termination of
Loop until match is true or input is 0: a loop must converge
Prompt for input
• For all possible inputs or parameter
If input ≠ 0 and input = previous
values, a program or function must have
match ← true
previous ← input a correct result
If match = true display “Yes”; • By reasoning about the code, we can
otherwise display “No” judge correctness and find bugs
David Keil 1/03 23 David Keil 1/03 24
1. Types, loops, subprograms CS II D. Keil 1/03 5

Two kinds of comments Loop-invariant example


void main() [max.cpp]
• Narrative; tells what happens {
double input,largest;
• Assertion; tells what is true about variable cout << "Enter a number (< 0 to exit): ";
values at an instant of time during execution cin >> largest;
// Precondition: <largest> stores input
• Three useful assertions: while (input >= 0)
• Precondition: Tells what is required for the {
// Loop invariant: <largest> stores
code to be expected to work // maximum input so far
• Postcondition: Tells what is true after code cout << "Enter a number (< 0 to exit): ";
cin >> input;
runs (i.e., the spec) if (input > largest)
• Loop invariant: Tells what is true at the top of largest = input;
};
a loop cout << "Largest = " << largest << endl;
// Postcondition: program has displayed the
David Keil 1/03 25
// maximum value entered David Keil 1/03 26
}

Limits of testing Problems (loops)


• This program can hang. What is the bug and 1. Suggest C++ loop statements for:
how many tests would be expected to find it? (a) input until user enters 0
void main() (b) averaging 10 inputs
{ Standard
unsigned input1,input2; random- (c) finding logarithm of a number
srand(&time); number
cin >> input1 >> input2; functions 2. Write a program to find the second
if (rand() == input1 && largest value in a series
rand() == input2) of inputs terminated by a 0 input
while(1);
cout << input1 << “ + ” << input2 3. Write a program that finds
<< “ = “ << input1 + input2 <<
endl; for input k
} David Keil 1/03 27 David Keil 1/03 28

Errors to watch for Using assert in debugging


#include <assert.h> [div1.cpp]
• Uninitialized variables float quotient(int a,int b);
• Unused variables or parameters void main() Defines
{ macro, assert
• Poorly indented code cout << "Enter two integers: ";
• Variables, functions, or types with vague int a,b;
cin >> a >> b;
names (“value”, “process”, “data”...) cout << a << " / " << b << " = "
<< quotient (a,b);
• Loops not provably terminating }
• Loops that iterate once too many or float quotient (int a,int b)
// Returns (a/b). Terminates prog on div-by-0.
too few times { Tests precondition for
assert(b != 0); debugging purposes
• Array subscripts not provably in bounds return (float)a / b;
David Keil 1/03 29 } David Keil 1/03 30
1. Types, loops, subprograms CS II D. Keil 1/03 6

Software quality issues Subtopic: Subprograms


• User interface must be clear and Review • Defining and declaring functions
straightforward • Local variables and scope
• Robust (“bullet-proof”) • Value and reference parameters
software is ready to handle • Return values
• Recursive functions
any error condition
• Program should give correct results • C-style functions
• Static variables
(including error messages if necessary) New • Default arguments
on any input subtopics • Variable-size parameter lists
• Ensuring quality begins • Drivers and stubs
at the specification stage • Command-line arguments
David Keil 1/03 31 David Keil 1/03 32

3 C/C++ language elements When a called function is undefined


• A function prototype (declaration) • The compiler ensures that identifiers,
introduces a function name to the program e.g., function names, are declared
• A function call invokes the function before use
• A function definition spells out the
• The linker will detect function calls
function’s content
with no corresponding definition
• A function definition has a header (type; #include <iostream.h>
function ID; parameters int get_age();
in parentheses) and a body void main() Linker error message:
(compound statement) { “undefined external”
cout << get_age();
}
David Keil 1/03 33 David Keil 1/03 34

A char function parameter A double function parameter


int number_on_dial( char letter) int rounded(double n);
[round.cpp]
// Returns number corresponding to <letter>. void main()
{ {
switch (tolower(letter)) double input;
{ cout << "Enter a number: ";
case 'a': case 'b': case 'c': return 2; cin >> input;
case 'd': case 'e': case 'f': return 3; cout << input << " rounded off is "
case 'g': case 'h': case 'i': return 4; << rounded(input) << endl;
case 'j': case 'k': case 'l': return 5; }
case 'm': case 'n': case 'o': return 6;
case 'p': case 'r': case 's': return 7; int rounded(double n)
case 't': case 'u': case 'v': return 8; // Returns <n>, rounded off.
case 'w': case 'x': case 'y': return 9; {
default: return 0; return (int)(n + 0.5);
} } Sample I/O:
} Enter a number: 4.2
[telephon.cpp] David Keil 1/03 35 4.2 rounded off is 4 David Keil 1/03 36
1. Types, loops, subprograms CS II D. Keil 1/03 7

Bar-graph problem Memory allocation for local data items


void main()
• Write a function that draws a bar graph, When { This function call
pushes an activation
taking two parameters, occupancy and function int a = 2;
frame onto stack
terminates, write(5);
capacity, and displaying ten characters (X’s activation }
and underscores). The proportion of X’s to frame is
popped from void write(int b)
10 is the proportion of capacity filled by {
stack
occupancy. cout << b;
[actframe.cpp]
}
• E.g., for parameters (30,100), display:
Stack pointer
XXX___ ___ _ points here,
for (20,40), display: to top of stack
XXXXX_ ___ _
David Keil 1/03 37 David Keil 1/03 38

Activation records in memory Reference parameters: example


void add(int, int, int&);
• Each function call, at run time, causes an
activation record to be pushed on top of the void main()
{ Function add changes
stack int sum; the value of actual
add(3,4,sum ); parameter sum
• When the function terminates, the activation cout << “3 + 4 = “ << sum;
record is popped and its memory is released } Formal reference parameter
• Activation records contain local variables void add(int a, int b, int& new_sum)
and function parameters {
new_sum = a + b;
• A return statement pushes the return value }
on the stack after activation record is popped Reference
Output: operator
3 + 4 = 7
David Keil 1/03 39 David Keil 1/03 40

Reference parameters Using a reference parameter


• Reference parameters can communicate data • Factorial of n is defined
to and from a called function as the product of all natural
• Unlike a value parameter, a formal reference numbers from 1 to n (e.g., 4! = 4 × 3 × 2 × 1)
parameter is another name void factorial(int n,int& result)
for the same data location as the actual // returns n * (n-1)! as result.
parameter {
// Precondition: <n> >= 0
• Actual reference parameter must be a variable result = 1;
for (int i=1; i <= n; ++i)
new_sum is // Loop invariant: <result> = i !
result *= i;
a reference // Postcondition: <result> = n !
parameter }
David Keil 1/03 41 David Keil 1/03 42
[factiter.cpp]
1. Types, loops, subprograms CS II D. Keil 1/03 8

Displaying an address in C A string identifier is a pointer


int glo1 = 5,glo2 = 1; [intaddr.c]
char *name = “Bob”;
void main(void) Pointer type
{ specifier
Address Equivalent code:
operator
int local = 2; (a) char name[] = “Bob”;
printf("&glo1 = %p &glo2 = %p ", (b) char name[4];
&glo1,&glo2); strcpy(name,“Bob”);
printf("\n&local = %p\n",&local);
} In C++: cout << &glo1; Valid: char *p = name;
Memory addresses (in hexadecimal notation) cout << p;
Copying to who
Output: Invalid: char *p; knows where!
&glo1 = 004165F4 &glo2 = 004165F8 strcpy(p,name);
&local = 0064FDF4 David Keil 1/03 43 David Keil 1/03 44

In C, pass-by-reference A string variable is


requires pointer parameters
void factorial(int n,int* result)
a pointer to char
// Passes back n * (n-1)! as ‘result’
{
*result = 1;
for (int i=1; i <= n; ++i)
*result *= i; char name[] =
} “Bob”;
char* p = name;
Example of call: name[0] = ‘J’; p[0] = ‘J’;
int f; cout << name; cout << p;
factorial(5,&f);
printf(“5! = %i”,f); Job Job
David Keil 1/03 45 David Keil 1/03 46

String names are passed as pointers Swap problems


void martha(char s[]);
void main(void) • Write a function that swaps two integer
{ parameters.
char name[80] = "George";
Example: After int a=2,b=5, the
martha( name); statement swap(a,b) should leave
printf("name=%s\n",name);
} a with the value 5 and b with the value 2
void martha(char s[]) in the calling function.
/* Copies "Martha" to <s>. */
{ • Is it possible to write two more functions
strcpy(s,"Martha"); of the same name as above, to swap two
}
floats, two strings?
Output: [arrparm.c ]
David Keil 1/03 47 David Keil 1/03 48
name = Martha
1. Types, loops, subprograms CS II D. Keil 1/03 9

Kinds of parameters Pass streams as


Actual Formal
reference parameters
Value 5 a
Reference total sum void save(ofstream& os, char* s)
{
void main() a.r.
{
a.v. os << s << endl;
int total;
add(5, 6, total); }
cout << total; f.v. f.r.
} The stream os should be a reference
void add(int a, int b, int& because the function might change the
sum) state of the stream
{
sum = a + b;
} David Keil 1/03 49 David Keil 1/03 50

A Boolean function The recursive factorial function


bool odd(int n); int factorial(unsigned n)
[odd.cpp] {
void main()
if (n <= 1) Base case
{
cout << "Enter an integer: "; return 1;
int input; else Recursive call
cin >> input; return n * factorial(n - 1);
cout << "odd(" << input << ") = " }
<< odd(input) << endl;
} • A recursive function (a) provides a
Enter an integer: 3
bool odd(int n) odd(3) = 1 direct solution for a simple base
// Returns true if <n> odd, else false case, or (b) calls itself to reduce a
{
return (n % 2 == 1); problem to a simpler version of itself
} David Keil 1/03 51 David Keil 1/03 52

Static variables
Sum-1-to-n problems • A static variable is initialized once
• Write a function that returns • Example:
int new_ID() .
the sum of all values from // Returns a unique ID number
1 to parameter n. {
static int ID = 0;
Argument Return value ++ID;
1 1 return ID;
2 3 }
3 6 • Keyword static is a storage-class qualifier
4 10 • Storage duration of static variable is execution of
program; for automatic variable duration is
• Now, write a recursive version. execution of function
David Keil 1/03 53 David Keil 1/03 54
1. Types, loops, subprograms CS II D. Keil 1/03 10

Some features of Kernighan Default arguments (C++)


and Ritchie C (1971-1989) A function with a default argument may
• Variables have to be declared at the start of a be called without passing any parameter in call.
block in C int prompt_for_int(char prompt[] = "Enter an
integer")
• const was unavailable // Prompts for and returns int,
• Parameters were declared between header and // displaying <prompt> or default prompt.
body: {
average() cout << prompt << ": ";
int input; Sample I/O:
int a; cin >> input;
int b; Parameters return input; Enter salary: 50000
{ ANSI C: } Enter an integer: 2
return (a+b) / 2; int average(int a,int b)
} void main()
{...} {
• Default function type: int int salary = prompt_for_int("Enter salary"),
n = prompt_for_int();
David Keil 1/03 55 David Keil 1/03 56
}

Variable-sized parameter lists A function to average integers


double average(int numargs, ...)
• Ordinarily parameters in call must agree {
in number and type with prototype double total = 0;
va_list arglist;
• Using type: va_list defined in library: va_start(arglist,numargs);
*
stdarg.h, function may be called with for (int i = 1; i <= numargs; i++)
number of parameters determined by {
int next = va_arg(arglist,double);
programmer total += next;
Special macros and
• Macros defined in stdarg.h: }
type supplied by
va_end(arglist);
- void va_start(va_list,int) return total / numargs;library stdarg.h*
- <type> va_arg(va_list, <type>) }
- void va_end(va_list) cout << average(2,3,4); 3
David Keil 1/03 57
cout << average(6,4,3,3); 4 David Keil 1/03 58

A driver program tests a function


int log2(int n);
The purpose of
A driver for factorial
void main()
{
driver, main, void factorial(int n,int& result);
cout << "Enter an integer: "; is to test
int input; function log2 void main()
cin >> input; {
cout << "base-2 logarithm of " << input
<< " is " << log2(input) << endl; cout << "Enter an integer: ";
} int input,result;
int log2 (int n) cin >> input;
// Returns floor of base -2 logarithm of <n>.
{ factorial(input,result);
int count = 0; cout << input << " ! = " << result
while (n > 1)
{ << endl;
n /= 2; } [from factiter.cpp]
++count;
} Sample I/O:
return count;
} Enter an integer: 7
[log2demo.cpp]
David Keil 1/03 59
7 ! = 5040 David Keil 1/03 60
1. Types, loops, subprograms CS II D. Keil 1/03 11

void main()
Stubs test a top-down design
{
char option;
do {
A menu void add() { cout << "Calling <add>" << endl; }
cout << "1 Add" << endl
<< "2 Subtract" << endl
presents void
void
void
subtract() { cout << "Calling <subtract>" << endl; }
multiply() { cout << "Calling <multiply>" << endl; }
divide() { cout << "Calling <divide>" << endl; }
<< "3 Multiply" << endl Menu
<< "4 Divide" << endl
<< "5 Quit" << endl;
user void main()
{ Stub function definitions
cout << “Choose operation: “;
cin >> option; options char option;
do {
if (option >= '1' && option <= '4')
cout << "1 Add" << endl << "2 Subtract" << endl
{
<< "3 Multiply" << endl << "4 Divide" << endl
cout << "Enter two integers: ";
<< "5 Quit" << endl;
int input1,input2;
cin >> option;
cin >> input1 >> input2;
if (option != '5')
switch (option) {
{
case '1': cout << input1 + input2 << endl; break;
switch (option) Calls to stub
{
case '2': cout << input1 - input2 << endl; break;
case '1': add(); break; functions
case '3': cout << input1 * input2 << endl; break;
case '2': subtract(); break;
case '4': cout << input1 / input2 << endl; break; case '3': multiply(); break;
} case '4': divide(); break;
} }
} while (option != '5'); }
}
} while (option != '5');
[menu.cpp ] [stub.cpp]
David Keil 1/03 61 } David Keil 1/03 62

Command-line arguments
• argc: how many command
parameters
• argv: an array of strings
• argv[1]: the first command-line
argument
• Applications: file names, switches
void main(int argc,char **argv)
{
for (int i=0; i < argc; ++i)
cout << argv[i] << “ “;
}
Output: [The command line, verbatim] David Keil 1/03 63