• No results found

Can we define new commands?

N/A
N/A
Protected

Academic year: 2022

Share "Can we define new commands?"

Copied!
40
0
0

Loading.... (view fulltext now)

Full text

(1)

An Introduction to Programming though C++

Abhiram G. Ranade Ch. 9: Functions

(2)

Can we define new commands?

• We already have many commands, e.g.

sqrt(x) evaluates to the square root of x.

forward(d) moves the turtle forward d pixels.

• Can we define new commands? e.g.

gcd(m,n) should evaluate to the GCD of m,n.

dash(d) should move the turtle forward, but draw dashes as it moves rather than a continuous line.

• Function: official name for “command”

(3)

Outline

• Example of defining and using functions

• How to define a function in general

• How a function executes

• “Contract” view of functions

• Passing parameters by reference

• Pointers

• Functions and graphics objects

(4)

A problem

Write a program that prints the GCD of 36, 24, and of 99, 47.

Using what you already know:

Make 2 copies of code to find GCD.

Use the first copy to find the GCD of 36, 24.

Use the second copy to find the GCD of 99, 47.

Duplicating code is not good.

May make mistakes in copying.

What if we need the GCD at 10 places in the program?

If we need to change later we need to remember to change in 10 places.

Inelegant: Ideally, you should not have to state anything more than once.

main_program{

int m=36, n=24;

while(m % n != 0){

int r = m%n;

m = n;

n = r;

}

cout << n << endl;

m=99; n=47;

while(m % n != 0){

int r = m%n;

m = n;

n = r;

}

cout << n << endl;

}

(5)

Using a function

Code has 2 parts: function definition + main program Main program:

“calls” or “invokes” function.

gcd(a,b) : call or invocation gcd(99,47) : another call

Call includes values whose GCD is to be calculated.

a, b in first call 99, 47 in second

Values supplied as part of a call: “arguments to the call”

Function definition:

function name

how it is to be called

what happens when function is executed.

int gcd(int m, int n) {

while(m % n != 0){

int r = m%n;

m = n;

n = r;

}

return n;

}

main_program{

int a=36,b=24;

cout << gcd(a,b) << endl;

cout << gcd(99,47)<< endl;

}

(6)

General form of function definitions

return-type name-of-function(

parameter1-type parameter1-name, parameter2-type parameter2-name, …){

function-body }

return-type : the type of the value returned by the function, e.g. int.

Some functions may not return anything, discussed later.

name-of-function: e.g. gcd

parameter : variables that will be used to hold the values of the arguments to the function. m,n in gcd.

function-body : code that will get executed.

int gcd(int m, int n) {

while(m % n != 0){

int r = m%n;

m = n;

n = r;

}

return n;

}

main_program{

int a=36,b=24;

cout << gcd(a,b) << endl;

cout << gcd(99,47)<< endl;

}

(7)

How a function executes

main_program starts execution

Control reaches gcd(a,b)

main_program suspends.

Preparations made to run “subprogram” gcd:

Area allocated in memory where gcd will have its variables. “activation frame”

Variables corresponding to parameters are created in activation frame.

Values of arguments are copied from

activation frame of main_program to that of gcd. This is termed “passing arguments by value”.

a=36, b=24 copied to m, n.

int gcd(int m, int n) {

while(m % n != 0){

int r = m%n;

m = n;

n = r;

}

return n;

}

main_program{

int a=36,b=24;

cout << gcd(a,b) << endl;

cout << gcd(99,47)<< endl;

}

(8)

Execution continued

Execution of gcd starts.

n = 12 calculated.

Execution ends when “return”

statement is encountered.

Value following the word return, 12, is copied back to the calling program

Will be used in place of the expression gcd(…,…)

Activation frame of function is destroyed, i.e. memory reserved for it is taken back.

main_program resumes, prints 12, ...

int gcd(int m, int n) {

while(m % n != 0){

int r = m%n;

m = n;

n = r;

}

return n;

}

main_program{

int a=36,b=24;

cout << gcd(a,b) << endl;

cout << gcd(99,47)<< endl;

}

(9)

Remarks

Set of variables in calling program e.g. main_program is completely disjoint from the set in called function, e.g. gcd.

Both may contain same name.

Calling program will refer to the variables in its activation frame.

Called program will refer to the variables in its activation frame.

Arguments to calls/invocations can be expressions

Evaluated, then copied to parameters of called function.

Function definition must appear before any call to it in the program file.

(10)

Remarks

• The body of a function can contain practically anything.

Can create new variables.

Can get input and produce output using cin, cout Can call other functions, defined earlier.

Main program is also a function, discussed later.

Can use graphics canvas and access turtle created using turtleSim().

Other graphics objects can also be accessed – discussed later.

(11)

Exercise: Write a program to determine whether a number is even

bool even(int n){

if(n%2 == 0)

return true;

else

return false;

}

bool even(int n){

return (n%2 == 0);

}

(12)

What we have discussed

• What is a function

• How to define a function

• How it executes

• Next: More examples and how to think of functions

🎻

(13)

Exercise: Write function to compute LCM (Least common multiple)

Use the identity LCM(m,n) = m*n/GCD(m,n).

int lcm(int m, int n){

return m*n/gcd(m,n);

}

• lcm calls gcd. So gcd definition must appear before lcm.

(14)

Program to find LCM using functions gcd, lcm

int gcd(int m, int n){

… return n }

int lcm(int m, int n){

return m*n/gcd(m,n);

}

main_program{

cout << lcm(50,75);

}

Functions and main program must appear in the given order.

(15)

Execution

int gcd(int m, int n){

… return n }

int lcm(int m, int n){

return m*n/gcd(m,n);

}

main_program{

cout << lcm(50,75);

}

main program starts executing

Call lcm(...) reached. Main program suspends.

Activation frame created for lcm.

50, 75 copied to m,n. lcm starts execution.

call to gcd encountered. lcm suspends.

Activation frame created for gcd.

50, 75 copied to m,n

Execution of gcd starts

gcd computes 25 as result.

Result copied to activation frame of lcm,

Activation frame of gcd destroyed.

lcm continues execution using result.

m*n/gcd(m,n)= 50*75/25 = 150 computed

returned to main_program

Activation frame of lcm destroyed.

main_program resumes and prints 150.

(16)

Function to draw dashes while moving

void dash(double d, int n){

repeat(n){

forward(d/2/n);

penUp();

forward(d/2/n);

penDown();

}

return;

}

main_program{

turtleSim();

repeat(4){dash(100,5);

right(90);}

getClick();

}

dash does not return a value, so its return type is void.

The statement return used in the body does not have a value after the word return.

(17)

Contract view of functions

Function : piece of code which takes the responsibility of getting something done.

Specification : what the function is supposed to do:

“If the arguments satisfy certain properties, then a certain value will be returned, or a certain action will happen.”

“certain properties” = “preconditions”

Example: gcd : If positive integers are given as arguments, then their GCD will be returned.

If preconditions are not satisfied, nothing is promised.

Before you write a function, you should write its specification as a comment

(18)

Contract view of functions (contd.)

Function = contract between the programmer who wrote the function, and programmers who use it.

Programmer who uses the function

trusts the function writer to make sure that the execution satisfies the specification.

does not otherwise care how the function executes.

Programmer who wrote the function does not care which program uses it.

Analogous to giving cloth to tailor.

Tailor promises to give you a shirt if the cloth is good.

Wearer does not care how it was stitched.

Tailor does not care who wears the shirt,

(19)

Contract view of functions (contd.)

Postcondition: What is promised about the state of the computer after the function finishes execution.

Example: After dash finishes its execution we may want it to satisfy the postcondition that the pen is up.

not true for the code given earlier.

Exercise: Modify the code of dash to ensure that the pen is up at the end.

Post conditions must also be mentioned in the specification.

Writing clear specifications is very important.

(20)

What we discussed

If you are going to execute the same code several times, possibly with different values:

Define a function that executes the code Call the function with appropriate values.

Functions can have their own variables which are created in the activation area of the function.

Names can be same in the main program and in the function

A function is like an independent program except that it gets some

values (arguments) from the calling program, and returns results to the calling program.

Next: Reference parameters

🎻

(21)

Some shortcomings

Using what we just learned, it is not possible to write functions to do the following:

• A function that exchanges the values of two variables.

• A function that produces several values as results:

Function to produce polar coordinates given Cartesian coordinates.

(22)

Exchanging the values of two variables, attempt 1

void exchange(int m, int n){

int temp = m;

m = n; n = temp;

return;

}

main_program{

int a=1, b=2;

exchange(a,b);

cout << a <<‘ ‘<<

b << endl;

}

Does not work. 1, 2 will get printed.

When exchange is called, 1, 2 are placed into m, n.

Execution of exchange exchanges values of m,n.

Change in m,n does not affect the values of a,b of main_program.

(23)

Reference parameters

void exchange(int &m, int &n){

int temp = m;

m = n; n = temp;

return;

}

main_program{

int a=1, b=2;

exchange(a,b);

cout << a <<‘ ‘<<

b << endl;

}

& before the name of the parameter:

Says: “Do not allocate space for this parameter, but

instead just use the variable from the calling program.”

When function changes m,n it is really changing a,b.

Such parameters are called reference parameters.

2 1 will be printed.

(24)

Remark

If a certain parameter is a reference parameter, then the corresponding argument is said to be “passed by

reference”.

Now we can write a program that computes polar coordinates given cartesian coordinates

We use two reference parameters.

Called function stores the polar coordinates in the reference parameters.

These changes can be seen my the main program.

There are other ways of returning 2 values – study later.

(25)

Cartesian to polar

void CtoP(double x, double y,

double &r, double &theta){

r = sqrt(x*x + y*y);

theta = atan2(y, x); //arctan return;

}

main_program{

double x=1, y=1, r, theta;

CtoP(x,y,r,theta);

cout << r <<‘ ‘<< theta << endl;

}

r, theta in CtoP are reference

parameters,

changing them in CtoP changes the value of r, theta in the main

program.

Hence sqrt(2) and pi/4 (45 degrees) will be printed.

(26)

Exercises

Write a function which takes a length in inches and returns the length in yards, feet, and inches. Note that 12 inches make a foot, and 3 feet make a yard.

As an example: 100 inches = 3 yards, 2 feet, 4 inches.

Hint: your function will have 4 parameters, one in which you will pass the given length, and the other 3 in which the function will put the the number of yards, number of feet and number of inches.

(27)

What we discussed

• If we want to return more than one result we can do so by using a reference parameter.

• If we use a reference parameter R in a function, and pass as argument a variable A, then any

change that the function makes in R will be seen by the calling program as a change in A.

• Next: Pointers, which perform a similar function.

🎻

(28)

Pointers

If the memory of a computer has N bytes, then the bytes are numbered 0..N-1.

The number of a byte (different from what is stored in the byte) is said to be its address.

A pointer is a variable that can store addresses.

Sometimes “pointer” might mean address.

What we accomplished using reference variables can also be accomplished using pointers.

This will be seen soon.

Pointers will also be useful elsewhere.

(29)

How to find the address of a variable

The operator & can be used to get the address of a variable.

The same & is used to mark reference parameters; but the meaning will be clear from the context.

int t;

cout << &t << endl;

This prints the address of the variable t, i.e. the address of the first byte that comprises the variable t.

Customarily, addresses get printed in hexadecimal radix, i.e. they will consist of a sequence of hexadecimal digits prefixed by “0x”

Note: hexadecimal digits: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F.

(30)

Variables that can store addresses

How to create a variable for storing addresses of variables of type int :

int *v; // read as “int star v”

The * is not to be read as multiplication.

Think of it as (int*) v; where int* means the type: “address of int”.

int p;

v = &p; // address of p stored in v

Since p is of type int, &p has type address of int.

Thus, it is OK to store &p in v, which is also of type address of int.

cout << v <<‘ ‘<< &p << endl; // both print same v = p; // compile time error: type mismatch

(31)

Pointers in general

In general, to create a variable w to store addresses of variables of type T, write:

T* w;

Assignment statements: types of lhs and rhs must be same

Except when both sides are numeric types; then conversion rules used.

No conversion rule between pointers of one type and pointers of other types.

No conversion rule between pointers of one type and values of any type.

(32)

The dereferencing operator *

If v contains the address of p, then we can get to p by writing *v.

int *v;

int p;

v = &p;

*v = 10; // as good as p = 10.

Think of * as the inverse of &.

&p : the address of the variable p

*v : the variable whose address is in v

int *v;

v is such that *v is an int v is an address of an int

(33)

Pointers in functions

void CtoP(double x, double y, double *pr, double *ptheta){

*pr = sqrt(x*x + y*y);

*ptheta = atan2(x,y);

return;

}

main_program{

double r, theta;

CtoP(1,1,&r,&theta);

cout << r <<‘ ‘

<< theta << endl;

}

main_program calls CtoP, supplying &r,

&theta as third and fourth arguments.

This is acceptable because corresponding parameters have type double*.

The first step of the call copies the addresses of r,theta of the

main_program into pr, ptheta of CtoP.

*pr means the variable whose address is in pr, in other words, the variable r of main_program.

Thus CtoP changes the variables of main_program.

Thus r becomes √2 = 1.41 and theta becomes π/4 = 0.79 and are printed.

(34)

Remarks

In variable definitions, * associates to the right. Example:

int *v, p;

This means int *v; and int p; i.e. defines a variable v of type int*, and variable p of type int.

For now, assume that the only operations you can perform on a variable of type T* are

dereference it,

store into it a value &v where v is of type T, store it into another variable of type T*

pass it to a function as an argument, provided corresponding parameter is of type T*

(35)

Exercise

Point out the errors in this code.

int *p, *q, w;

p = w;

q = 3;

What is the result of executing the following:

int *p, *q, w, x;

p = &w;

w = 10;

q = &x;

*q = 20;

cout << *p + x <<endl;

(36)

What we discussed

A pointer is an address or a variable containing an address.

A pointer to a variable can be created in the main program and dereferenced during a function call.

This way a function can be allowed to modify variables in the main program, or other functions.

Pointers can do the same thing as references, but the notation is clumsier.

But pointers can do other things too. (Later)

🎻

(37)

Functions and graphics objects

You can pass graphics objects to functions.

The parameter must have the same type, i.e. shape.

If you pass by value, a copy of the variable is made for use in the called function.

The copy is destroyed when the function returns.

If you pass by reference of pass a pointer, the function can operate on the original graphics object.

If you imprint an object in a call, the image will survive after the call finishes.

Incidentally, you can make a copy of an object even using assignment

Rectangle r(100,100,80,20); Rectangle s=r;

void Rev360(Rectangle &r){

  repeat(36){

    r.right(10);

    r.imprint();

    wait(0.01);

  } }

main_program{

  initCanvas();

  Rectangle r(100,100,80,20);

  Rev360(r);

  getClick();

}

(38)

Exercise

Write a function which takes a rectangle and coordinates x, y as input and decides whether the point (x,y) lies inside the rectangle.

You will need to know the following useful operations that can be performed on any rectangle R.

R.getX() : returns the x coordinate of the rectangle center

R.getY() : returns the y coordinate of the rectangle center

R.getWidth() : returns the width of the rectangle

R.getHeight() : returns the height of the rectangle

(39)

Concluding remarks

If you find that you are performing the same operation at several places in your program, consider making it into a function.

Function = “packaged software component”.

The user of the function does not need to worry what happens inside the function.

The user only expects the specification of the function to be honoured.

Arguments can be passed by value:

If corresponding parameter is modified in function, no direct effect in calling program.

Arguments can be passed by reference:

If corresponding parameter is modified in function, variable in calling program changes.

Argument is a pointer to a variable in the calling function:

Code in called function can access variable by dereferencing pointer.

(40)

Exercises

Write a function that draws an n sided regular

polygon such that each side has length s, and returns the perimeter (n*s) as the result.

Write a function that returns the cube root of a

number using Newton’s method. Have an additional parameter to the function for specifying the number of iterations you want performed.

Other exercises at the end of Chapter 9.

🎻🎻

References

Related documents

● Merge into a single floating-point image that represents the entire range of intensities.. Visual Response to

function is defined at a fixed set of sample points on the shape. Levy

Also the intensity of absorption is directly proportional to the concentration of chemical bonds in a given sample.. Note: The vibration of chemical bonds must involve a change

Use of a minimal unrolled graph can be combined with that of a dynamic slice as follows: a program P can be instrumented to obtain information concerning the program nodes visited

motivations, but must balance the multiple conflicting policies and regulations for both fossil fuels and renewables 87 ... In order to assess progress on just transition, we put

These gains in crop production are unprecedented which is why 5 million small farmers in India in 2008 elected to plant 7.6 million hectares of Bt cotton which

- Function of the Digital Logic Circuits can be represented by Logic Operations, i.e., Boolean Function(s). - From a Boolean function, a logic diagram can be constructed

Most people have unwelcome or intrusive thoughts at t imes, but for people with OCD, the importance of thes e thoughts becomes more intense or extreme. Take the example of a