C Programming 2014/2015 – Lab session #2
Davide Ceresoli,
[email protected]
Thursday March 25, 2015 – Room 310
1
Functions
Functions are the most important construct in any imperative programming language. In other lan-guages they are also called subroutines. C/C++ doesn’t make any distinction between functions and subroutines. Functions represent separate containers of specialized and generic code, and they encourage you tomodularize andreuse your code.
This is how todeclare a function, i.e. to make manifest that a function exists:
return-type name-of-function ( parameters ) ;
note the final;Functions declarations are best placed after theusing namespace std;statement. For very short programs, the function declaration is optional.
This is how todefine a function, i.e. its implementation:
return-type name-of-function ( parameters ) {
// write your code here ...
return something; // or simply: return; }
The function body must be placed after its definition, and possibly before themain.
The return-type can be any of the data-types we have already seen or it can bevoid, meaning the the function does not return any value (i.e. it’s a subroutine). The parameters list, is a comma-separated list of type and variable name, optionally, followed by a default value assignment. The function name can be a sequence of letters, digits and underscore, but it cannot begin with a digit.
Example of valid function declarations:
void clear_screen(); int max(int a, int b);
double distance(double x1, double y1, double x2, double y2); int read_integer(string msg);
Example of valid function definitions:
double distance(double x1, double y1, double x2=0.0, double y2=0.0) { ... }
int read_integer(string msg="Enter an integer> ") { ... }
• If you need to use global variables, declare them before the functions.
• By default, variables arepassed-by-value to functions, i.e. they arecopiedto the function. • As a consequence, a function cannot modify its parameters unless they are passed-by-reference.
• Functions can return only one value. If you need to return more, usepass-by-referenceparameters.
• Variables inside functions arelocalto each function invocation.
• Of course, functions can contain for, if, do, while, ... etc as well as,call other functions.
2
Variables’ scope
One fundamental rule of C/C++ is that variables live (i.e. exist) inside the {...} they are declared and are destroyed right after. Consider the following code snippet:
void func() {
int a=10;
cout << "inside func(): a=" << a << endl; }
int main() {
int a=7;
cout << "before calling func(): a=" << a << endl; func();
cout << "after calling func(): a=" << a << endl; return 0;
}
Guess what this code will print. If unsure, try it in a program.
3
Global variables
Here is an example of a using global variables: snippet:
...
using namespace std;
int a=7;
void func() {
a=10;
cout << "inside func(): a=" << a << endl; }
int main() {
cout << "before calling func(): a=" << a << endl; func();
cout << "after calling func(): a=" << a << endl; return 0;
}
4
Pass by value
Consider the following code snippet:
void twice(int a) {
// here a is the copy of a in main() a = a*2;
cout << "inside twice(): a=" << a << endl; }
int main() {
int a=7;
cout << "before calling twice(): a=" << a << endl; twice(a);
cout << "after calling twice(): a=" << a << endl; return 0;
}
Guess what this code will print. If unsure, try it in a program.
5
Pass by reference
You can pass variables by-reference (aka by-pointer or by-address) by appending&to the type of param-eters. Consider the following code snippet:
void twice(int &a) {
// here a is the same a in main() a = a*2;
cout << "inside twice(): a=" << a << endl; }
int main() {
int a=7;
cout << "before calling twice(): a=" << a << endl; twice(a);
cout << "after calling twice(): a=" << a << endl; return 0;
}
Guess what this code will print. If unsure, try it in a program.
6
An updated template C++ source file
The following is the recommended structure of the C++ source file, that will be used from now on, for the lab exercises. Please, try to follow it as close a possible.
// place here global variables
// place here functions declarations
// place here functions definitions
// main program
int main(int argc, char *argv[]) {
// write here the code return 0;
}
7
Writing and composing simple functions
Assignment #1
1. Write a program with two simple functions that convert ◦C to ◦F and vice-versa. The formulas are:
◦F = 32 +9
5
◦C ◦C =5
9(
◦F−32)
In themain, using aforloop, output the temperature in◦C and in◦F (two columns), for◦C from −20◦C to +200◦C in steps of 10◦C.
2. Add two functions that convert between ◦C and K (K = 272.15+◦C), and add a third column in output.
3. Add two function that convert between◦F and K bycomposing the four existing functions.
4. Write an interactive program that converts a temperature in input, into an other temperature scale. The typical output should look like:
you have: 100C you want: F 100C = 212F
Hint: double T; string c1; cin >> T >> c1; Try to minimize the number ofif’s.
8
Return multiple values, revisiting the quadratic equation
Assignment #2
Take your code of last week, and transform the quadratic equation into a function like this:
int quadratic_solve(double a, double b, double c, double& x1, double &x2);
that is you will providea,band cto the function, and the roots will be written intox1andx2.
Next, let’s make it more C-like (and remove allcout’s from the routine):
#define OK (0)
#define ERR_COMPLEX_ROOTS (1) #define ERR_NO_SOLUTIONS (2) #define ERR_INF_SOLUTIONS (3)
...
if (a == 0.0 && b == 0.0 && c == 0.0) return ERR_INF_SOLUTIONS; ...
... x1 = ... x2 = ... return OK; }
...
int main() {
int status; ...
status = quadratic_solve(a, b, c, x1, x2); if (status == 0)
{
cout << x1 << " " << x2 << endl; }
else {
cout << "There was an error!" << endl; }
... }
The#definestatement is a pre-processordirective which will be expanded into your code. It will help to make your code more readable. In C/C++ it is good practice that functions will return 0 if they were successful, different from zero is there was an error.
9
More difficult: passing functions to functions!
Consider the following code snippet:
double first_derivative(double (&f)(double), double x, double h=1e-6) {
return (f(x+h) - f(x))/h; }
int main() {
cout << first_derivative(sin, 0.0) << endl; return 0;
}
Note the strange syntax: double (&f)(double)stands for any functionf with one double parameter, returning a double. Note also thatsinis not a variable, but a function!
Assignment #3
10
Finding the zeros of a function
Finally, we will exercise our experience withif,for, while, and, of course, functions.
10.1
The bisection method
The bisection method is the most robust to find the zero of a function in an interval.
1. Start from the interval bound a and b, evaluate the function values f(a), f(b). Make sure that
f(a)·f(b)<0
2. Calculate the mid-point: c= (a+b)/2 and evaluatef(c).
3. Iff(a)·f(c)<0, the zero is in the [a, c] interval. Setb=cand go back to step 2.
4. Iff(b)·f(c)<0, the zero is in the [b, c] interval. Seta=c and go back to step 2.
5. If|a−b|is smaller that, say, 10−6, stop, the zero isc.
Hint #1: the modulus of a real number is given by thedouble fabs(double x)function.
Hint #2: double bisection(double (&f)(double), double a, double b, double precision=1e-6)
{...}
Assignment #4
1. Solve: exp(x2−2)−3 = 0 forx∈[0,2].
2. Using the temperature conversion functions of before, find which temperature is the same value in
Appendix: compiler and editor setup
To use the lab PCs, the username isprogc, the password ismarzo and the domain must be set toCSD. Please, download the bundle (GCC-4.8.1 & Notepad++) fromhttps://github.com/dacap/pocketcpp, the Pocket C++ 0.4 x86 (for 32 bits) version. This is a portable package, which means that it doesn’t need installation nor administrative privileges. The same file is present also on the shared drive
Z:.
The executable is a self-extracting archive. You have the option to expand it in-place (i.e. on the Desktop directory), or on a USB stick. In the former case, remember to copy you work to a USB stick before leaving the lab. In fact, the data on the laboratory PCs will be deleted automatically every night and you will have to repeat download the bundle again. The archive expands to 500 Mb!
To start the editor, double click on thePocket C++.baticon.
• To compile your code, press F9
• If there are no error, run the code by pressing Ctrl + F9
• Always remember to save changes to your code before compiling
• On the Italian keyboard the left brace {is obtained by Shift + Alt Gr + `e , the right brace}by Shift + Alt Gr + + .