320 likes | 437 Views
Functions. Building blocks of a C++ program Each function has a name, which is used to call the function; functions call each other You will write your own functions, e.g. main() , and also use pre-written functions from standard library. /* This program contains two functions: main()
E N D
Functions • Building blocks of a C++ program • Each function has a name, which is used to call the function; functions call each other • You will write your own functions, e.g. main(), and also use pre-written functions from standard library
/* This program contains two functions: main() and myfunc(). */ #include <iostream.h> void myfunc(); // myfunc's Protoype int main() { cout << "In main()"; myfunc(); // call myfunc() cout << "Back in main()"; return 0; } void myfunc() // myfunc’s Definition { cout << " Inside myfunc() "; }
Function Prototype void myfunc(); // myfunc's Protoype • Like variable declaration; tells the compiler about the return type of the function and the number and type of parameters it needs from the calling function: return_type functionName (parameter list); • So, place prototypes before main() • main() is predefined in C++ and does not need a prototype • Can’t the compiler look ahead and get definitions? • Prototype can be omitted if whole function placed before it is called; is that a good practice?
Returning a Value // Returning a value. #include <iostream.h> int mul(int x, int y); // mul()'s prototype int main() { int answer; answer = mul(10, 11); // assign return value cout << "The answer is " << answer; return 0; } // This function returns a value. int mul(int x, int y) { return x * y; // return product of x and y }
Library Functions • Pre-written functions in libraries that you can use • Just include the proper header file • Compiler gets prototype from the header file and searches appropriate libraries itself to get function definition • e.g. math library has mathematical functions in it #include <iostream.h> #include <math.h> //or <cmath> int main() { cout << sqrt(9.0); return 0; }
Scope Rules • Scope rules tell that a variable is visible to which parts of your program; also define variable’s lifetime • 3 types of variables: local, global, formal parameters
Scope Rules - Local Variables • A variable can be declared inside any block and is then local to that block • Block: {} int main() { {int x = 4;} cout << x; return 0; } • error C2065: 'x' : undeclared identifier • Memory storage for a local variable created when entering its block and destroyed when its block exited
Scope Rules-Local Variables • Most common block is a function #include <iostream.h> void func(); int main() { int x; // local to main() x = 10; func(); cout << x; // displays ? return 0; } void func() { int x; // local to func() x = -199; cout << x; // displays ? } • -199 10. Each variable x has a separate location in memory • Identically-named variables in inner block ‘hide’ or override those in the outer block; Avoid this practice
Scope Rules-Local Variables #include <iostream.h> int main() { int i, j; i = 10; j = 100; if(j > 0) { // start of block int i; // this i is separate from outer i i = j / 2; // outer j is known here cout << “first inner i: " << i << '\n'; } if(i < 50) { i += 10; cout << “2nd inner i: “ << i << endl; } cout << "outer i: " << i << '\n'; return 0; } 50 20 20 • Declaring within a conditional block also saves memory; see next slide
Scope Rules-Local Variables int main() { int choice; cout << "(1) add numbers or "; cout << "(2) concatenate strings?: "; cin >> choice; if(choice == 1) { int a, b; /* activate two integer vars */ cout << "Enter two numbers: "; cin >> a >> b; cout << "Sum is " << a+b << '\n'; } else { char s1[80], s2[80]; /* activate two strings */ cout << "Enter two strings: "; cin >> s1; cin >> s2; strcat(s1, s2); cout << "Concatenation is " << s1 << '\n'; } a = 10; // *** Error *** -- a not known here! return 0; }
Scope Rules-Local Variables • Variables declared in for loops are local according to current spec for C++ for(int i = 0; i<10; i++) cout << i << " "; i = 100; // *** Error *** -- i not known here! • Does not work on Visual C++ 6.0 (i.e. no error) • Can declare a variable within any conditional expression if(int x = 20) { cout << "This is x: "; cout << x; } x = 2; //*** Error *** -- x not known here! • Not a good practice
Scope Rules-Formal Parameters • Formal parameters: variables that receive values passed to a function • Scope local to the function #include <iostream.h> int mult(int, int); int main() { int a = 10, b = 20; cout << mult(a, b); //cout << x << y; // *** Error *** --unknown identifiers x, y return 0; } int mult(int x, int y)// can have different names here { return x*y; }
Scope Rules-Global Variables • Usually declared outside any function; have life as long as the program runs • Can be used by all following functions • Usually placed at the beginning of program • Initialized only at the start of the program; uninitialized default to zero • An identically named local variable masks global one
Scope Rules-Global Variables #include <iostream.h> void func(); int i = 2; // global int main() { cout << i << endl; func(); cout << i << endl; int i = 5; // local. What if i=5; cout << i << endl; func(); return 0; } void func() { cout << i << endl; int i = 3; // local cout << i << endl; } • 2 2 3 2 5 2 3 • 2 2 3 2 5 5 3ifi = 5at the indicated place
Scope Rules-global variables #include <iostream.h> #include <cstdlib> void drill(); int count; //count and num_right are global int num_right; int main() { cout << "How many practice problems: "; cin >> count; num_right = 0; do { drill(); count--; } while(count); cout << "You got " << num_right << “ right.\n"; return 0; } void drill() { int count; /* This count is local. */ int a, b, ans; // Generate two numbers between 0 and 99. a = rand() % 100; b = rand() % 100; // The user gets three tries to get it right. for(count=0; count<3; count++) { cout << "What is " << a << " + " << b << "? "; cin >> ans; if(ans==a+b) { cout << "Right\n"; num_right++; return; } } cout << "You've used up all your tries.\n"; cout << "The answer is " << a+b << '\n'; }
i 26 100 p j 100 100 Passing Pointers to Functions • No big deal. Just declare parameter as type _______ ? #include <iostream.h> void f(int *j);//or void f(int *); int main() { int i; int *p; p = &i; // p now points to i f(p); cout << i; // i is now 100 return 0; } void f(int *j) { *j = 100; // var pointed to by j is assigned 100 }
Passing Pointers to Functions i • The pointer variable not necessary. Can generate and pass the address of i as such to f() #include <iostream.h> void f(int *j); int main() { int i; f(&i); cout << i; return 0; } void f(int *j) { *j = 100; // var pointed to by j is assigned 100 } 26 100 j 100
t 5 Passing Pointers to Functions (copy) 5 #include <iostream.h> int sqr_it(int x); int main() { int t=10; cout << sqr_it(t) << ' ' << t; //output? } int sqr_it(int x) { x = x*x; return x;} • IMPORTANT: What’s the difference between the above function, and the ones on previous two slides? • Here, a copy of the value of t is passed. t remains unaltered. x is a local variable, which could have been named t • Called “Call by Value” • Previous called “Call by Reference” where the original variable (not a copy) is accessed by the called function x 5
Passing Arrays to Functions • What is an array name without index? • Address of first element passed to function. So actual array accessed, not a copy. Saves memory • 3 ways to pass this address • Declare parameter as an array of same type and size #include <iostream.h> void display(int num[10]); //or display(int [10]); int main() { int t[10],i; for(i=0; i<10; ++i) t[i]=i; display(t); // pass array t to a function cout <<endl; for(i=0; i<10; i++) cout << t[i] << ' '; //output? } // Print some numbers. void display(int num[10]) { int i; for(i=0; i<10; i++) cout << num[i] << ' '; //output? for(i=0; i<10; i++) (num[i] = num[i] + 1); }
Passing Arrays to Functions • Can also declare as display(int num[]) i.e. unsized. Same thing • Internally, compiler converts int num[10] or int num[] to int * • So, why not declare parameter as a pointer to int void display(int *num) { int i; for(i=0; i<10; i++) cout << num[i] << ' '; //or *(num+i) } • How is a single element passed? As an ordinary variable #include <iostream.h> void display(int num); //each element is of type int int main() { int t[10],i; for(i=0; i<10; ++i) t[i]=i; for(i=0; i<10; i++) display(t[i]); //only one element passed } void display(int num) { cout << num << ' ';}
Passing Arrays to Functions #include <iostream.h> void cube(int *n, int num); int main() { int i, nums[10]; for(i=0; i<10; i++) nums[i] = i+1; cout << "Original contents: "; for(i=0; i<10; i++) cout << nums[i] << ' '; cout << '\n'; cube(nums, 10); // compute cubes cout << "Altered contents: "; for(i=0; i<10; i++) cout << nums[i] << ' '; return 0; } void cube(int *n, int num) { while(num) { *n = *n * *n * *n; num--; n++; } } • Original contents: 1 2 3 4 5 6 7 8 9 10 • Altered contents: 1 8 27 64 125 216 343 512 729 1000
Passing Strings to Functions • What is a string stored as? So what should we pass? #include <iostream.h> #include <cstring> #include <cctype> void stringupper(char *str); int main() { char str[80]; strcpy(str, "this is a test"); stringupper(str); cout << str; // display uppercase string return 0; } void stringupper(char *str) { while(*str) { *str = toupper(*str); // uppercase one char str++; // move on to next char } } • Can also declare as an array of char stringupper(char[])
The return Statement • return statement can be used without a value for void functions. Must return a value for non-void functions • Control passed back to calling function when return encountered or closing curly brace of function #include <iostream.h> void power(int base, int exp); int main() { power(2, 10); return 0; } void power(int base, int exp) { int i; if(exp<0) return; i = 1; for( ; exp; exp--) i = base * i; cout << "The answer is: " << i << endl; }
The return Statement • Can have multiple return statements. Function returns as soon as the first one encountered void f() { // ... switch(c) { case 'a': return; case 'b': // ... case 'c': return; } if(count<100) return; // ... }
The return Statement • non-void functions return values to the calling function. Therefore, can call a non-void function and use that call as an operand in an expression (as it has a value) in the calling function • x = power(y); • if(max(x, y)) > 100) cout << "greater"; • switch(abs(x)) {... • Don’t necessarily have to store the returned value in a variable #include <iostream.h> #include <cstdlib> int main() { int i; i = abs(-10); // stored cout << abs(-23); // just used abs(100); // returned value discarded return 0; }
Multiple return Statements #include <iostream.h> int find_substr(char *sub, char *str); int main() { int index; index = find_substr("three", "one two three"); cout << "Index of three is " << index; // index is 8 return 0; } int find_substr(char *sub, char *str) { int t; char *p, *p2; for(t=0; str[t]; t++) { p = &str[t]; // reset pointers p2 = sub; while(*p2 && *p2==*p) { // check for substring p++; p2++; } /* If at end of p2 (i.e., substring), then a match has been found. */ if(!*p2) return t; // return index //of match } return -1; // no match found }
Returning Pointers #include <iostream.h> char *get_substr(char *sub, char *str); int main() { char *substr; substr = get_substr("three", "one two three four"); cout << "substring found: " << substr; return 0; } char *get_substr(char *sub, char *str) { int t; char *p, *p2, *start; for(t=0; str[t]; t++) { p = &str[t]; // reset pointers start = p; p2 = sub; while(*p2 && *p2==*p) { //check for substring p++; p2++; } /* If at end of p2 (i.e., substring), then a match has been found. */ if(!*p2) return start; /* return pointer to beginning of substring */ } return 0; // no match found }
Command Line Arguments • To pass info to main() from the command line • e.g. cl hellouser • Here, cl and hellouser are command line arguments • main() receives infor about these arguments in two parameters: int main( int argc, char *argv[]) • argc (argument count) parameter is an integer that holds the number of arguments on the command line. Always at least 1, as program name also counted • argv (argument variable) parameter is a null-terminated array of pointers to strings • argv[0] points to program name on command line, argv[1] points to the first argument, and so on. argv[argc]==0
Command Line Arguments #include <iostream.h> int main(int argc, char *argv[]) { if(argc!=2) { cout << "You forgot to type your name.\n"; return 1; } cout << "Hello " << argv[1] << '\n'; return 0; } • If we name this program as greeting, then after making an exe file we can type greeting Shamail at the command prompt and the program will execute and output: Hello Shamail • Spaces and tabs usually separate strings; for a longer string, use quotes e.g. greeting “Shafay Shamail” outputs Hello Shafay Shamail
Command Line Arguments • Can access individual characters in the command line strings by using a double subscript. See the program echo below #include <iostream.h> int main(int argc, char *argv[]) { int t, i; for(t=0; t<argc; ++t) {// t denotes the tth string i = 0; while(argv[t][i]) {// t[i] accesses the ith character of t cout << argv[t][i]; ++i; cout << ' '; } cout << ' '; } return 0; } • e.g. echo hi there results in e c h o h i t h e r e
Passing Numeric Command Line Arguments • Want to pass numbers to main( ), but it takes strings • Use atof(), atoi(), atol() #include <iostream.h> #include <cstdlib> int main(int argc, char *argv[]) { double a, b; a = atof(argv[1]); b = atof(argv[2]); cout << a + b; return 0; } • atoi(“2”) gives 2; atof(“-11.11”) gives -11.11
#include <iostream.h> int main(int argc, char *argv[]) { while(--argc > 0) cout << *++argv << endl; return 0; } Command Line Arguments #include <iostream.h> #include <cstdlib> int main(int argc, char *argv[]) { double a, b; a = atof(argv[1]); b = atof(argv[2]); cout << a + b; return 0; } #include <iostream.h> int main(int argc, char *argv[]) { for(int j=0; j<argc; j++) cout << argv[j] << endl; return 0; } #include <iostream.h> #include <cstdlib> int main(int argc, char *argv[]) { char **argvector = argv; double a, b; a = atof(*++argvector); b = atof(*++argvector); cout << a + b; return 0; }