62
Chapter 1 Introduction In this course, we will be looking for general principles underlying the notion of problem solv- ing with computers. Particularly, we are inter- ested in answering the following questions: 1. What are the different ways to solve a prob- lem? How are the solutions related? 2. How do we verify the solution indeed solves that problem? 3. What solution is best for a particular prob- lem? What does that mean by “best”? 4. What problems can and can’t be solved by using a computer? The goal is to study techniques that will enable you to develop correct, and efficient, programs. Before we will do that, we will preview some essential aspects of C++, the programming language we use in this course. 1

Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

  • Upload
    others

  • View
    16

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Chapter 1Introduction

In this course, we will be looking for generalprinciples underlying the notion of problem solv-ing with computers. Particularly, we are inter-ested in answering the following questions:

1. What are the different ways to solve a prob-lem? How are the solutions related?2. How do we verify the solution indeed solvesthat problem?3. What solution is best for a particular prob-lem? What does that mean by “best”?4. What problems can and can’t be solved byusing a computer?

The goal is to study techniques that will enableyou to develop correct, and efficient, programs.

Before we will do that, we will preview someessential aspects of C++, the programminglanguage we use in this course.

1

Page 2: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Functions and parameters

The following function Abc computes the ex-pression a + b + b ∗ c + (a + b − c)/(a + b) + 4when a, b, and c are integers, and leads to aninteger type result.

#include<iostream.h>

int Abc(int a, int b, int c){

return a+b+b*c+(a+b-c)/(a+b)+4;

}

void main(void){

int x = 2, y = 3;

cout << Abc(2,x,y) << endl;

}

In the above, a, b, and c are the formal param-eters, while 2, x, and y are actual parameters.When the invocation Abc(2, x, y) is executed,a, b, and c are assigned the values of 2, x, and y,respectively. Hence, a, b, and c are called valueparameters.

2

Page 3: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

More specifically, at run time, the value of an

actual parameter is copied into the correspond-

ing formal one via a copy constructor for the

data type of the formal parameter. In case the

actual parameter and the formal one are of

different types, a type conversion will be done

first, if it is defined. For example, in the pre-

cious case, if x has a type of float, and has a

value of 3.8, then b will be assigned a value of

3.

When a function terminates, the destructor for

the data type of formal parameters will destroy

the values of the formal parameters. Hence,

the most important side effect of value pa-

rameter is when a function terminates, formal

parameter values are not copied back into the

actual ones. Therefore, you can not bring any

values back.

3

Page 4: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Template functions

Assume that we want to calculate the same

expression as computed by the previous pro-

gram. But, this time, the types of the formal

parameters are float, instead of int. A much

more general approach is to write a template

function to deal with any type of formal pa-

rameters.

template<class T>

T Abc(T a, T b, T c){

return a+b+b*c+(a+b-c)/(a+b)+4;

}

void main(void){

cout << Abc(2,3,4) << endl;

}

This mechanism eliminates the need to know

the actual type when the code is written.

4

Page 5: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Reference parameters

When using value parameters, both copy con-

structors and destructors have to be called im-

plicitly. This can become quite time consum-

ing if some “large” data type, e.g., an array of

1000 pieces, is involved.

In the following code, a, b, and c are reference

parameters, with which the actual parameters

will be bound. In other words, they refer to the

same memory locations. Hence, there will be

no need to copy over the values, and destroy

them afterwards.

template<class T>

T Abc(T& a, T& b, T& c){

return a+b+b*c+(a+b-c)/(a+b)+4;

}

5

Page 6: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Reference in review

A variable declared type & is a reference of the

given type type and must be initialized when

declared. For example,

int a;

int& ra=a;

The reference ra refers to the actual variable

a, and they can be used interchangeably.

In the above, the variable a is the initializer of

the reference ra. In general, such an initializer

must be an lvalue, i.e., something that can be

used on the lefthand side of an assignment.

6

Page 7: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Common lvalues could be variables(a), array

cells(a[i]), and dereferenced pointers(*pa). More

specifically, constants and arithmetic expres-

sions can not initialize references (?). Hence,

the following are wrong.

int& a=256;

Once initialized, a reference can’t be switched.

So, the following is wrong:

int& a=b;

...

int& a=c;

Question: What does the following do?

int& ra=a;

int c=9;

ra=c;

7

Page 8: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Reference continued

Because reference parameter refers to the same

location as actual parameters do, potentially,

the code involved can change the values of the

actual ones. For example,

template<class T>

void Abc(T& a, T& b, T& c){

a=a+b+b*c+(a+b-c)/(a+b)+4;

}

void main(void){

int x = 2, y=3, z=4;

Abc(x,y, z);

cout << x;

}

8

Page 9: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Const references

There is yet another mode of parameter pass-

ing, const reference. If a parameter is so desig-

nated, by prefixing const in the front, the code

will no longer be able to change the values of

such parameters.

For primitive parameters, we use const param-

eters to tell the calls that the function will not

change the values of such parameters. For

parameters of user-constructed types, we use

const references. (?)

9

Page 10: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Reference returned

All the functions we have seen so far make

value returns, when a value to be returned is

copied into a temporary location. If we don’t

return them, their values will be lost, since

when a function terminates, the space for the

local variables will all be freed.

We can also use reference return by suffixing &

to the return type, which will return a reference

to a variable.

For example, T& A Sample(int i, T& z) declares

a function that will return a reference to a vari-

able of type T.

10

Page 11: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

An example

#include <iostream.h>

int& maxi(int& x, int& y){

return (x > y ? x:y);

}

void main (){

int a=9, b=9;

cout << "a=" << a << "b=" << b << "\n\n" ;

maxi(a, b)=16;

cout << "a=" << a << "b=" << b << "\n\n" ;

maxi(a, b)-=10;

cout << "a=" << a << "b=" << b << "\n\n" ;

maxi(a, b)++;

cout << "a=" << a << "b=" << b << "\n\n" ;

}

11

Page 12: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

In the previous example, a reference to an lvalue

not local to the function is returned.

Question: Can we return a reference to a lo-cal variable?

For example, will the following code work?

#include <iostream.h>

int& doubtful(){

int a=1;

return a;

}

void main(){

cout << doubtful();

}

Answer: No.12

Page 13: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Homework

1.1. Write a template function Input, to bring

in a nonnegative value and verify that this value

is not negative. If it is negative, tell the user

to bring in another. Give the user three oppor-

tunities before she quits. If she does it, return

the valid value via a reference parameter.

1.2. Write a template function to determine

whether the elements in an array a are sorted.

Return true if it is; otherwise, return false.

13

Page 14: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Recursive functions

A recursive function includes at least one call

to itself, either directly or indirectly, through,

possibly, a sequence of function calls. For ex-

ample, given the following factorial function.

f(n) = 1, n ≤ 1

f(n) = 1 × 2 × · · · × n, n > 1.

We have the following iterative algorithm.

int Factorial(int n){

if(n<=1) return 1;

else {

int product=1;

for(int i=1;i<=n;i++)

product*=i;

return product;

}

}

14

Page 15: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Based on the definition of the function, we

can also rewrite it into the following recursive

version.

f(n) = 1, n ≤ 1

f(n) = n × f(n − 1), n > 1,

which leads to the following recursive function.

int RFactorial(int n){

if(n<=1) return 1;

else return(n * RFactorial(n-1);

}

This latter version is more elegant, and cap-

tures the essence of the factorial function.

15

Page 16: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Well defined recursion

A well defined recursive function must meet

the following two requirements:

1. The definition must include a base com-

ponent, in which f(n) is defined directly. For

example, f(n) = 1, n ≤ 1.

2. The parameters in the recursive component

must be smaller and/or simpler. This guaran-

tees that the more complicated recursive ex-

pressions will be eventually transformed into

the base case. For example, f(5) = 5×f(4) =

5 × 4 × f(3) = · · · = 5 × 4 × 3 × 2 × 1 = 120.

Sometimes, it is not easy to see if a function

meets the requirement. For example,

bad(0) = 0

bad(n) = bad(n/3 + 1) + n − 1

16

Page 17: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

To be or not to be?

Even though a recursive algorithm is usually

shorter in terms of lines then its non-recursive

cousin, sometimes, it can take much more time

to run, or use more space. For example, if we

compare the recursive and non-recursive algo-

rithm of the Factorial function, we will find

that the former, with n as its actual parame-

ter, uses roughly 2n units of spaces, while the

former uses only 3 units of space.

Another well-known recursive function is the

Fabinocci function, defined as the following:

f(0) = 1,

f(1) = 1,

f(n) = f(n − 1) + f(n − 2), n > 1.

17

Page 18: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

If we use the direct definition of Fabinocci

function to write up a recursive function, its

run-time will be exponential, while that of its

iterative cousin is only linear.

long Fib(int m){

if(n<=1) return 1;

else return (Fib(n-1)+Fib(n-1));

}

The reason for this behavior is lots of dupli-

cate values are calculated, which is really not

necessary. We will see later how to improve.

18

Page 19: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Homework

1.3. Write a non-recursive function to calcu-

late n!, and test its correctness.

1.4. (i) Write a recursive function to calculate

the Fibonacci function F(n). (ii) Show that

the function you just wrote calculate the same

F(i) more than once, when n ≥ 2. (iii) Write a

non-recursive function to calculate F(n), which

calculates each F(i) no more than once.

19

Page 20: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

More recursion

The following code sums up the values in an

array.

T Sum(T a[], int n){

T tsum = 0;

for (int i = 0; i < n; i++)

tsum += a[i];

return tsum;

}

It can also be put into the following recursive

function.

T Rsum(T a[], int n){

if (n > 0)

return Rsum(a, n-1) + a[n-1];

return 0;

}

20

Page 21: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Permutation

In many cases, recursion provides a powerful

problem solving tool. The generation of per-

mutation provides a demonstrating example.

The permutations of 3 items, e.g., a, b, and c

are abc, acb, bac, bca, cab, and cba.

Given n distinguishable objects: e1, e2, . . . , en,

we want to know 1) how many ways are there

to line them up, i.e., the number of permuta-

tions, and 2) how to construct all these per-

mutations.

Question: If there are 3 burgers, 4 soft drinks,

and 2 side orders, how many valued meals can

you make out of them?

21

Page 22: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Number of permutation

There are n! permutations for n distinguishable

objects.

Nonrecursively, there are n choices for the first

position, n−1 for the second, ..., and 1 for the

last. Hence, n × (n − 1) · × · 1 = n! ways.

Recursively, let M(n) be the number of permu-

tations for n distinguishable objects, we have

that

M(1) = 1

M(n) = n ∗ M(n − 1), n > 1.

Solving the above, we have that M(n) = n!.

22

Page 23: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Constructing permutations

Let E = {e1, . . . , en} denote the n objects, let

Ei be the set obtained by removing ei from E,

let perm(X) be the collection of all the permu-

tations based on X, and let eiperm(X) be all

the permutations of X ∪ {ei} obtained by pre-

fixing each and every permutation in X with

ei. For example, if E = {a, b, c}, then E1 =

{b, c}, perm(E1) = {bc, cb} and e1perm(E1) =

{abc, acb}.

When n = 1, i.e., E = {e}, the only permu-

tation is just e. Otherwise, perm(E) equals to

the union of e1perm(E1), e2perm(E2), . . . , and

enperm(En). For example, if E = {a, b, c}, then

perm(E) is aperm(E1) plus bperm(E2), and plus

perm(E3). Now the code.

23

Page 24: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

The function

If we store {e1, . . . , en} in a[n], we will call thefollowing with

Perm(a, 0, n-1);

void Perm(T list[], int k, int m){

int i;

if (k == m) {

for (i = 0; i <= m; i++)

cout << list[i];

cout << endl;

}

else for (i = k; i <= m; i++) {

Swap(list[k], list[i]);

Perm(list, k+1, m);

Swap(list[k], list[i]);

}

}

Question: What is going on?

24

Page 25: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Homework

1.5. Write a recursive function to output all

subsets of n elements.

1.6. Write a recursive function to determine

whether element x is included in the array a[0:n-1].

25

Page 26: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

This Swap or that Swap?

In the previous function, we use a Swap functionto exchange the values of two variables. Willthe following version work?

void Swap_Value(T a, T b){

T temp = a;

a = b;

b = temp;

}

Question: What will the following programprint out?

void main(void){

int x = 1, y = 2;

Swap_Value(x, y);

cout << x << y << endl;

}

Question: How could we fix it?Answer: Use reference parameter(s).

26

Page 27: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Proof by induction

When a statement is involved with a natural

number argument, n, we have infinite number

of instances to prove. Proof by mathematical

induction turns out to be an effective way to

deal with the proof of this sort of statements.

The general approach is as follows:

1.Show that some statement, with argument

n, is true for a base case, e.g., n = 1..

2. Assume that the statement is true for n,

prove that it is true for n + 1.

27

Page 28: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

An example

Given the following Fibonacci series:

F0 = 1,

F1 = 1,

Fi+1 = Fi + Fi−1, i ≥ 1.

Then, for all i ≥ 1, Fi < (53)

i.

Proof: F1(= 1) < 53. Assume that Fn < (5

3)n,

then we have

Fn+1 = Fn + Fn−1 < (5

3)n + (

5

3)n−1

= (5

3)n+1 · {

3

5+

9

25}

=24

25(5

3)n+1 < (

5

3)n+1.

28

Page 29: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Another example

∀i ≥ 1,n∑

i=1

i2 =n(n + 1)(2n + 1)

6.

Proof by induction: When n = 1, we havethat

LHS =1∑

i=1

i2 = 1 =1 · 2 · 3

6= RHS.

Now, we assume it holds for n, and try to provethat it holds for n + 1, as well:

LHS =n+1∑

i=1

i2 =n∑

i=1

i2 + (n + 1)2

=n(n + 1)(2n + 1)

6+ (n + 1)2

=(n + 1)

6[n(2n + 1) + 6(n + 1)]

=(n + 1)

6(2n2 + 7n + 6)

=(n + 1)

6(n + 2)(2n + 3) = RHS.

29

Page 30: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Watch out!

Claim: The colors of all flowers are the same.

Proof: By induction on n, the number of flow-

ers. The base case is trivial.

Assume the statement is true for n. Observe a

bouquet of n + 1 flowers. Take one, f1, out.

As there are only n flowers left, by inductive

assumption, they must be of the same color, c.

Now, take another one, f2, out of the bouquet

and put f1 back. As the bouquet still has n

flowers, those n flowers must also be of the

same color, particularly, the color of f1 must

be the same as that of those n−1 flowers, i.e.,

c. Thus, the color of all of the n + 1 flowers is

the same. 2

30

Page 31: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Question: What’s wrong?

Answer: When n = 1, n − 1 = 0. Thus, our

claim that “the color of f1 must be the same

as that of those n − 1 flowers” does not hold

up. Thus, F(1) 6⇒ F(2). Thus, the inductive

part, “ for all n ≥ 1, F(n) ⇒ F(n+1)”, doesn’t

work.

If we treat n = 2 as the base case, then, al-

though we do have the inductive statement,

for all n ≥ 2, F(n) ⇒ F(n + 1), we can’t prove

the base case, i.e., the colors of any two flow-

ers are the same. Thus, we still can’t finish

the whole proof.

Lesson: To prove something inductively, both

parts have to be checked out.

31

Page 32: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Homework

1.7. Prove by induction that the following is

true.

n∑

i=0

i2 =n(n + 1)(2n + 1)

6.

1.8. Prove by induction that

∀n ≥ 1, n! ≥ 2n−1.

1.9. Prove by induction that, if one has unlim-

ited access to five-cent and seven-cent stamps,

show that any postage value greater than or

equal to 24 cents can be exactly met.

32

Page 33: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Proof by contradiction

• General approach: To prove some state-

ment is true, assume it is false first. If

this latter assumption leads to a contradic-

tion to what has been known, or common

sense, then that assumption must be false,

i.e., the original statement must be true.

• Example: Either I am tired or sick. If I am

sick, I go home. I am not going home. So,

I am tired.

33

Page 34: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

An example

Theorem:√

2 is not a rational number.

Proof: Just suppose that√

2 is rational. Then,

there are integers m′ and n′ such that√

2 =

m′/n′. By dividing both m′ and n′ by all the fac-

tors common to both , we obtain√

2 = m/n

for some integers m and n having no com-

mon factors. Since√

2 = m/n, m = n ×√

2,

i.e.,m2 = 2n2. Therefore, m2 is even. Thus,

m must be even, (?) i.e., for some k, m = 2k.

Replace m with 2k, we have that 4k2 = 2n2.,

i.e., n2 = 2k2. By the same token, for some

j, n = 2j. Hence, both m and n has a common

factor of 2. This is a contradiction.

Hence,√

2 must not be rational. 2

34

Page 35: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Dynamic memory allocation

To dynamically assign space for an (integertype of) variable, we must declare another vari-able as a pointer first.

int * y;

When the program needs to actually use thevariable, we have to use new to ask for thespace:

y = new int;

Then, we can manipulate *y, the integer typevariable pointed by y, e.g.,

*y = 10;

These three steps can also be combined, e.g.,

int * y = new int (10);

35

Page 36: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

An example

Below shows an example on the relationship

between pointers and arrays: one of the mostimportant application of the pointer type.

#include <iostream.h>

typedef int* intPointer;

void main(){

int Array[5]={0,1,2,3,4};

intPointer p;

p=Array;

p=p+3;

cout << *p << endl;

}

Question: What will be the output?

Answer: 3.36

Page 37: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Yet another Swap?

Using the ideas of pointers, we can come up

with another example of a Swap function as fol-

lows:

void Swap_via_pointer(T* pa, T* pb){

T temp = *pa;

*pa = *pb;

*pb = temp;

}

Question: What will the following program

print out?

void main(void){

int x = 1, y = 2;

Swap_Value(&x, &y);

cout << x << y << endl;

}

37

Page 38: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Exception handling

We can also dynamically set up an array.

float * a = new float[100];

But, what happens if the computer does not

have this much space? An exception will oc-

cur. More specifically, The exception xalloc

will be thrown by new, when the latter is un-

able to assign the space. This exception can

then be caught. For example,

float *a;

try {float * a = new float[100];}

catch (xalloc){

ceer << "Out of Memory" << endl;

exit(1);

}

38

Page 39: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Set up an array

The following should be pretty familiar:

int a[2][4];

a[1][2]=12;

When dynamically declaring a 2-d array, if both

dimensions are known at the coding time, it is

piece of cake.

int* a= new char[2][4];

a[2][3]=23;

Question: What do the following do?

int *p=&a[0][0];

cout << *(p+i*4+j);

39

Page 40: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

What is going on?

The model of the memory is a linear one. Thus,

when we want to get a piece of 2-d array,

once we have secured a piece of space from

the memory, there has to be a way to map

each and every element in the 2-d array to a

location in the memory. There are basically

two ways to do that: row major and column

major.

In most of the modern languages, the row ma-

jor mechanism is used, namely, the first row is

put in first, then the second, ..., until the last

row. For each row, the first element of that

row is put in, then the second, ..., until the

last one.

40

Page 41: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Questions

Question: If the first element of a[m,n] is

mapped to the starting address start, where

is a[i,j]?

Answer: start +(i ∗ n+j).

Homework 1.10. If the first element of

a[n_1,n_2,n_3] is mapped to the starting ad-

dress start, where is a[i,j,k]? What about

the general case when a has m dimensions?

41

Page 42: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

A couple of notes

1. Dynamically assigned space should be freed,when it is no longer needed, by using delete

y, for a single variable; or delete [] a, for anarray.

2. When both dimensions of an array are known

when we write it up, it is easy to set up, e.g.,c[7][5].

3. If the number of rows is unknown, but thenumber of columns is known, it can still be

created during the compilation time as follow:

char (*c)[5];

try {

c=new char [n][5];

}

catch (xalloc) {

ceer << "out of memory" << endl;

}

42

Page 43: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

4. If we don’t know the number of columns,

we have to regard it as a collection of several

dynamically created rows, whose pointers can

then be saved in another array.

bool Make2DArray(T ** &x, int rows, int cols){

try {

x = new T * [rows];

for (int i=0; i < rows; i++)

x[i]=new int [cols];

return true;

}

catch(xalloc)

{return false;}

}

43

Page 44: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

5. The above definition reports any possi-

ble exception to the invoking function with a

Boolean value of false. Another approach is

to do nothing when there is an exception, and

let the invoking function handles it. For exam-

ple,

void Make2DArray(T ** &x, int rows, int cols){

x = new T * [rows];

for (int i=0; i < rows; i++)

x[i]=new int [cols];

}

void main(void){

try {Make2DArray(x, 4, 5);}

catch (xalloc){

ceer << "Could not create x" << endl;

exit(1);

}

}

44

Page 45: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

6. The memory assigned this way can be freed

by freeing the rows first, then freeing the space

allocated for the row pointers.

void Delete2DArray(T ** &x, int rows){

for (int i=0; i < rows; i++)

delete [] x[i];

delete [] x;

x = 0;

}

In the above code, x is assigned a NULL pointer

to prevent it being used.

45

Page 46: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Homework

1.11. Assume that a 1-d array a[0:size-1]

stores a collection of elements. If we have n

elements, and if n exceeds size, they will not

fit in a. We need to enlarge a in this case.

On the other hand, if n is less than size, we

need to reduce size to make it more efficient.

Write a function ChangeSize1D to change the

size of array a from Size to ToSize. Your func-

tion should allocate space for a new 1-d array

of size ToSize, copy the elements over, then

free the space allocated to a[0:size-1].

1.12. Write a function ChangeSize2D to change

the size of a 2-d array.

46

Page 47: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Classes

C++ only supports very few atomic data types.The most flexible way to define our own datatypes is to use the class construct. As an ex-ample, assume we need to deal with objectsof Currency type. Every instance of such atype has a sign component, a dollar compo-nent, and a cents component. For example,$4.25 and -$17.18.

We also need to provide such operations assetting values, determining values, arithmeti-cally evaluating expressions involved with cur-rencies, incrementing values, outputting val-ues, etc..

Assume that we choose to represent the sign

type as the following:

enum sign {plus, minus};

we can define the Currency type as follows:

47

Page 48: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Class Currency{

public:

Currency(sign s=plus, unsigned long d=0,

unsigned long c=0);

~Currency(){};

bool Set(sign s, unsigned long d, unsigned c);

bool Set(float a);

sign Sign()const {return sgn;}

unsigned long Dollars() const{return dollars;}

unsigned long Cents() const{return cents;}

Currency Add(const Currency& x) const;

Currency& Increment(const Currency& x);

void Output() const;

private:

sign sgn;

unsigned long dollars;

unsigned int cents;

};

48

Page 49: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Everything declared in the public section is vis-

ible to the users, while those declared in the

private section are not. Hence, we can hide

information, particularly, those implementation

details, from the users.

The function that has the same name as that

of the class is called the constructor of that

class. It will be automatically called to create

objects for that class. For example, the follow-

ing code will construct several objects of type

Currency with various initial values.

Currency f, g(plus, 3, 45), h(minus, 10);

Currency * m = new Currency(plus, 8, 12);

Similarly, ~Currency is called the destructor of

the Currency type.

The rest of the functions are used to carry out

other operations.

49

Page 50: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Class definition

All the functions have to be defined. Below

show some examples.

Currency::Currency(sign s, unsigned long d,

unsigned int c){

if (c > 99){

cerr << "Cents should be < 100" << endl;

exit(1);

}

sgn = s; dollars = d; cents = c;

}

bool Currency::Set(float a){

if (a < 0) {sgn = minus; a = -a;}

else sgn = plus;

dollars = a;

cents = (a - dollars) * 100;

return true;

}

50

Page 51: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Currency Currency::Add(const Currency& x) const{

long a1, a2, a3;

Currency ans;

a1 = dollars * 100 + cents;

if (sgn == minus) a1 = -a1;

a2 = x.dollars * 100 + x.cents;

if (x.sgn == minus) a2 = -a2;

a3 = a1 + a2;

if (a3 < 0) {ans.sgn = minus; a3 = -a3;}

else ans.sgn = plus;

ans.dollars = a3 / 100;

ans.cents = a3 - ans.dollars * 100;

return ans;

}

Since ans is a local variable, when the function

terminates, its space is destroyed. Thus, we

have to copy it back to the invoking environ-

ment via a value return.51

Page 52: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Currency& Currency::Increment(const Currency& x){

*this = Add(x);

return *this;

}

When we call the above using

g.Increment(h);

the currency object g invokes the public func-

tion Increment to get a copy of an object what

is the sum of g and h, which is assigned to

*this, namely, g itself, which is then return.

Notice that since a reference to this global vari-

able is returned, there is no need to make an

explicit copy, thus some time is saved.

52

Page 53: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

A complete program

Assume the Currency class is declared and de-

fined in currency.h file, then the following pro-

gram can be used as a driver.

void main(void)

{

Currency g, h(plus, 3, 50), i, j;

g.Set(minus, 2, 25);

i.Set(-6.45);

j = h.Add(g);

j.Output(); cout << endl;

i.Increment(h);

i.Output(); cout << endl;

j = i.Add(g).Add(h);

j.Output(); cout << endl;

j = i.Increment(g).Add(h);

j.Output(); cout << endl;

i.Output(); cout << endl;

}

53

Page 54: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Homework

1.13. (i) What are the maximum and minimumcurrency values permissible in the Currency class,assuming that an object of type long is repre-sented with 4 bytes, and that of type int withtwo bytes. (ii) Answer the same questions asin (i) if the data types of dollar and cents arechanged to int. (iii) If function Add is usedto add two currency amounts, what are theirlargest possible values so that no error wouldoccur when converting type Currency to long

int as done to variables a1 and a2?

1.14. Extend the Currency class by adding inan input function that input a currency valuefrom the keyboard and assign it to the invokingobject; a subtract function that does the op-posite as Add does; a percent(X) function thatreturns X percent of the value of the invok-ing object; and multiply(X), which returns theproduct of X and the value of the invoking ob-ject.

54

Page 55: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Operator overloading

In the definition of the Currency type, it ismore natural to use such standard operatorsas + and +=, instead of Add and Increment.

We can overload these standard operators.

class Currency {

public:

...

Currency operator+(const Currency& x) const;

...

private:

long amount;

};

Currency Currency::operator+

(const Currency& x) const

Currency y;

y.amount = amount + x.amount;

return y;

}

55

Page 56: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

A more friendly program

#include <iostream.h>

#include "currency.h"

void main(void)

{

Currency g, h(plus, 3, 50), i, j;

g.Set(minus, 2, 25);

i.Set(-6.45);

j = h + g;

cout << j << endl;

i += h;

cout << i << endl;

j = i + g + h;

cout << j << endl;

j = (i+=g) + h;

cout << j << endl;

cout << i << endl;

}

56

Page 57: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Friends and protected members

In some cases, we must give access to some

private components to other classes and func-

tions. This may be done by declaring these

classes and/or functions friends. For example,

for our Currency class, we may want to over-

load the standard output operator <<. As the

latter cannot access the private data compo-

nents, we have to declare it as a friend func-

tion. For example,

class Currency{

friend ostream& operator<<

(ostream&, const Currency&);

public:

...

}

57

Page 58: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Later we will see that a class can be derived

from another class. The former is called the

derived class, and the latter is called the base

class. In order to grant access to the derived

class to the private components of the base

class, we have to declare those components

protected. Those component will then behave

like private members, except they are accessi-

ble to the derived classes.

To reiterate, class components that are to be

accessible to user application and all the other

classes should be declared as public. Data

components should never be included in this

category. As a result, we may change the data

component later on, without touching the ap-

plication codes, since the former is transparent

from the latter’s point of view.

Homework 1.15. Redo Exercise 10 following

the more friendly approach.

58

Page 59: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Testing and debugging

By testing, we mean executing the completed

code using input data, and compare the out-

put with the expected behavior. If they don’t

match, we have a problem. On the other hand,

even if they match, we still can not rule out

the possibility that the program is incorrect,

because we can’t test the program on all the

(infinite) number of cases. However, by using

many sets of test data and verify that what

we observe do match with what we expect, we

can increase our confidence on the correctness

of the program.

59

Page 60: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

How to do it?

There are two general techniques in dealing

with designing test data, black box and white

box.

In a black box method, we consider the func-

tion, but not the actual code; while in the

white box case, we go through the code to

design test data that will cover a good por-

tion of the statements and logical paths in the

program.

Thus, we either ensure that all the statements

will be executed once, or all the conditions will

be tested once for both the true and false val-

ues.

60

Page 61: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

An example

Consider the following piece of code

template<class T>

int Max(T a[], int n){

int pos=0; \\1.

for(int i=1; i<n; i++) \\2.

if(a[pos]<a[i])\\3.

pos=i;\\4.

return pos;\\5.

}

the data set of a[0:4]=[2, 4, 6, 8, 10] pro-vides a statement coverage, but not decisioncoverage, since the only condition never be-comes false.

If we sequence the statements in their order ofexecution by a certain set of data, we get anexecution path. Execution path coverage re-quires the use of a set of test data that causesall the paths be executed, which is usually themost demanding requirement.

61

Page 62: Chapter 1 Introductionzshen/Webfiles/notes/CS316/note1.pdf · ing formal one via a copy constructor for the data type of the formal parameter. In case the actual parameter and the

Homework

1.16. Consider the Max function. When n = 1,

there is only one execution path: (1, 2, 5);

when n = 2, there are two: (1,2,3,2,5) and

(1,2,3,4,2,5), depending on if the input is al-

ready ordered. Design a test set that provide

execution path coverage when n = 4.

1.17. How many execution paths exist in the

Sum function? Design a test set that provide

execution path coverage when n = 4.

1.18. How many execution paths exist in the

RSum function? Design a test set that provide

execution path coverage when n = 4.

62