1.45k likes | 1.59k Views
HKUST Summer Programming Course 2008. Function ~ Modular Programming. Overview. Introduction to Functions Standard Libraries (cmath, cctype, cstring, ctime, cstdlib) User-defined function Pass-by-value and Pass-by-reference Local and Global scope Identifiers Name Resolution
E N D
HKUST SummerProgramming Course 2008 Function ~ Modular Programming
Overview • Introduction to Functions • Standard Libraries (cmath, cctype, cstring, ctime, cstdlib) • User-defined function • Pass-by-value and Pass-by-reference • Local and Global scope • Identifiers Name Resolution • Function Definition and Declaration • Function Overloading and Default Parameter • Separate Compilation (Function Level) • Header Files • g++ and Makefile • Function Execution in Runtime • Static Variables in Function Definition • Inline Function and its Compilation Model
Function Introduction to Functions
Introduction to Functions • So far, the code we learnt were completely specified within main() • This was possible because the code is simple and easy. • However, a large software application requires hundreds of thousands, or even millions lines of code. • Impractical to write a single piece of code for such a large application. • Therefore, modular design principal is introduced, to put a small, but meaningful, piece of code together. • Other parts of program can use this piece of code once (or several times code reuse). • A principal part of all such schemes is the use of functions.
Function Standard Libraries (cmath, cctype, cstring, ctime, cstdlib)
Standard Libraries (cmath, cctype, cstring, ctime, cstdlib) • Before learning how to write a function, let’s see some standard libraries defined by C++ • cmath (Math functions) • cctype (Character functions) • cstring (Character string functions) • ctime (time-related functions) • cstdlib (commonly-used functions) • To use cmath, you have to include the library by #include <cmath> using namespace std; • You can include other libraries similarly. • Good reference: http://www.cplusplus.com/ref/.
Standard Libraries (cmath) • double ceil(double x) • Smallest integer greater than or equal to x. • ceil(3.2) = 4, ceil(3.7) = 4, ceil(-3.2) = -3, ceil(-3.7) = -3 • double floor(double x) • Largest integer less than or equal to x. • floor(3.2) = 3, floor(3.7) = 3, floor(-3.2) = -4, floor(-3.7) = -4 • Other rounding methods • Cast as integer • Truncate the floating-point part (int)(3.2) = 3, (int)(3.7) = 3, (int)(-3.2) = -3, (int)(-3.7) = -3 • Round to nearest integer (no default function). • round(3.2) = 3, round(3.7) = 4, round(-3.2) = -3, round(-3.7) = -4
Standard Libraries (cmath) • int abs(int x) • Absolute value of x (integer version). • double fabs(double x) • Absolute value of x (floating-point version). • Common errors double x = -3.2; double absX = abs(x); • C++ will convert x into int and then apply abs. result = 3, but not 3.2 • Use fabs instead.
Standard Libraries (cmath) • double exp(double x) • ex • double pow(double x, double y) • xy • double sqrt(double x) • Square root of x • double log(double x) • Natural log of x • double log10(double x) • Log base 10 of x
Standard Libraries (cmath) • double sin(double x) • Sine of angle x (in radian). • double asin(double x) • Angle (in radian) whose sine is x. • double cos(double x) • Cosine of angle x (in radian). • double acos(double x) • Angle (in radian) whose cosine is x. • double tan(double x) • Tangent of angle x (in radian). • double atan(double x) • Angle (in radian) whose tangent is x.
Standard Libraries (cctype) • int isalpha(char c) • true if c is a letter. • Non-zero value means true • int isdigit(char c) • true if c is a digit. • int isalnum(char c) • true if c is a letter or digit. • int isblank(char c) • true if c is a blank or tab. • int isspace(char c) • true if c is whitespace character. • space, tab, vertical tab, formfeed, carriage return, or newline.
Standard Libraries (cctype) • int islower(char c) • true if c is a lowercase letter. • int isupper(char c) • true if c is an uppercase letter. • int tolower(char c) • returns lowercase version of c if there is one, otherwise it returns the character unchanged. • We can cast the return value back to char. • int toupper(char c) • returns uppercase version of c if there is one, otherwise it returns the character unchanged.
Standard Libraries (cstring) • size_t strlen(const char* str) • Return str’s length. • typedefunsignedint size_t; • char* strcat(char* dest, const char* src) • Appends src string to dest string. • char* strcpy(char* dest, const char* src) • Copies src to dest. • int strcmp(const char* str1, const char* str2) • Compares str1 to str2 character by character. • Returns 0 if str1 is equal to str2. • Returns >0 if str1 is greater than str2. • Returns <0 if str1 is less than str2.
Standard Libraries (cstring) • char* strtok(char* str, const char* delimiters) • Sequentially truncate string if delimiter is found. • Useful in parsing input, for example: char input[100]; strcpy( input, "Name=Desmond;Mark1=100;Mark2=99"); char* pch = strtok(input, “="); int fieldID = 0; while ( pch != NULL ) { cout << pch << endl; if ( fieldID % 2 == 0 ) pch = strtok(NULL, “;"); // continue to use, use NULL else pch = strtok(NULL, “="); ++fieldID; } • More on this when we are talking about static variable. Output: Name Desmond Mark1 100 Mark2 99
Standard Libraries (ctime) • time_t time ( time_t * timer ) • Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock. • typedef long clock_t; • This will overflow in the year 2038, if 32-bit long is used !! • char* ctime( const time_t* timer ) • Converts timer to a string containing time and date adjusted to local time zone in the format Www Mmm dd hh:mm:ss yyyy. • clock_t clock () • Returns the number of clock ticks elapsed. • Useful in measuring time for an expensive job. clock_t start = clock( ); // expensive job clock_t end = clock( ); cout << “Elapsed seconds = “ << (end-start)*CLK_TCK;
Standard Libraries (cstdlib) • double atof( const char* string ) • Convert string to double. • int atoi( const char* string ) • Convert string to int. • void qsort( void* base, size_t num, size_t width, int (*fncompare)(const void *, const void *) ) • Sort the array with quick-sort algorithm. • More about this when we are talking function pointer.
Standard Libraries (cstdlib) • void exit( int status ); • Terminate calling process, return status to OS. • char* getenv( const char* varname ) • Get system environment variable. char* buffer = getenv ("PATH"); if (buffer != NULL) cout << "Current path is” << buffer << endl; • Linux separates PATH with semicolon, you can use strtok to separate the path from the long string. • int system( const char* command ) • Execute command. int status = system(“ls"); if (status == -1) cout << "Error executing ls\n”;
Standard Libraries (cstdlib) • int rand() • Generate a pseudo-random number in the range from 0 to RAND_MAX. • RAND_MAX is also defined in <cstdlib> • void srand( unsigned int seed ) • Initialize the random seed once at the beginning of main( ). • Eg.: srand( time(NULL) ); • Random generator depends on two parameters. • Seed (initialized with srand) • Number of rand() called • Detail can be found in lab manual (lab03).
Standard Libraries • Guarantee: • If it is necessary to use any standard functions in exam, a brief description of that function will be given. • Say, function prototype and function description. • No memorization is needed!!
Function User-defined Function
User-defined function • Function Definition • Syntax <return-type> <function name>(<parameter list>){ // function body } • Function call • Syntax • <function name>( <variable list> )
Function Name • <function name> can be any valid C++ identifier. • It is a good practice to use a meaningful function name. • To describe the tasks that the function performs.
Parameter List • The parameter listis a comma-separated list of variables (with their types) that receive values of the arguments when the function is called. • If no parameters is needed, the parameter list is empty. • However, even if there are no parameters, parentheses are required. • Syntax <return-type> <function name>(<type1> <name1>, <type2> <name2>, …, <typeN><nameN>){ // function body } int func(int i, int k, int j){ ... } // correct int func(int i, k, int j){ ... } // incorrect int func( ){ ... } // correct • It is a good practice to select meaningful identifiers for the parameters.
Parameter List • In old C, it is not allowed to use <return-type> <function name>( )to define a function. • Instead, it will use <return-type> <function name>( void ), where void is a reserved word that specify there is no argument in this function. • In ANSI C/C++, these two forms are equivalent. • C++ is backward compatible with C!!
Function Calling - Variable List • Syntax • <function name> (<variable list>); • <variable list> is a comma-separated list of variables • The type of the variable must be the same as the type specified in <parameter list>. • Or auto-convertible to the type specified in <parameter list>. • For example, int a; double b, c; func(a, b, c); // function call, b is converted to int • for the function int func(int i, int k, double j){ ... }
Terminology • Function header VS function body int func(int a, int b, int c){ // function body } • The first line is called function header: <return-type> <function name>(<parameter list>) • The code inside the curly-brace is called function body. • The whole piece of code is called function definition.
Terminology • Formal Parameters VS Actual Parameters int func(int i, int k, int j){ ... }// function definition func(a, b, c); // function call • The parameters in the function header is called formal parameters, or parameters ONLY. • Here, i, k, j are formal parameters. • The variables used in the function call is called actual parameters, or arguments. • Here, a, b, c are actual parameters.
Return Value • <return-type>: specifies the type of data that the function returns. • A function may return any type of data EXCEPT an array. • A function can either return a single result or return nothing. • To return nothing, we can put void in the <return-type>. • The return value may either • Signals whether an operation is successful or not. • Result of computation. • …… • If multiple parameters need to be returned, use passing by reference (will be covered in a minute).
Return Value • The function caller may ignore the returned value • But this is not a good practice. • Some compilers even flag this as a warning. • Non-void return-typed function should have one or more return statements:return <expression>; • The value passed back by return should have the same type as the <return-type> of the function. • Or a type that can be converted to <return-type> automatically. • Return statement also indicates the end of the function. • Therefore, void function can also have a statement likes: return;
Function Body • function body defines how the function do. • Note the function body is enclosed by braces { } • It can include any number of statements. • Even if there is only one statement, you cannot omit the braces { } • This is different from the if-statement and iterative statements.
Example of user-defined function (1) int add(int val1, int val2) { return val1 + val2; } int main() { cout << "Enter two integers: "; int v1, v2; cin >> v1 >> v2; cout << "The sum is " << add(v1,v2) << endl; return 0; }
Example of user-defined function (2) • We can implement the tolower (defined in cctype) ourselves. // Convert an upper-case letter to lower case // Keep it unchanged if it is not an upper-case letter int tolower(char c) { if ( c >= ‘A’ && c <= ‘Z’ ) return ( c – ‘A’ + ‘a’ ); else return c; } • No need to memorize the ASCII table!!
Example of user-defined function (3) • Now, try to implement a round function ourselves. int round( double x ) { if ( x >= 0 ) return (x + 0.5); else return (x - 0.5); } • C++ will convert the returned value to the desired type. • (x+0.5) is a double, but it will cast back to int automatically.
Example of user-defined function (3) // here is definition of the function: round int main( ) { double x1 = 3.2, x2 = 3.7, x3 = -3.2, x4 = -3.7; cout << ceil(x1) << “ “ << ceil(x2) << “ “ << ceil(x3) << “ “ << ceil(x4) << endl; cout << floor(x1) << “ “ << floor(x2) << “ “ << floor(x3) << “ “ << floor(x4) << endl; cout << (int)(x1) << “ “ << (int)(x2) << “ “ << (int)(x3) << “ “ << (int)(x4) << endl; cout << round(x1) << “ “ << round(x2) << “ “<< round(x3) << “ “ << round(x4) << endl; return 0; }
Example of user-defined function (4) void formattedOutput(char* name, int mark1, int mark2){ cout << “Name: “ << name << endl; cout << “Midterm mark: “ << mark1 << endl; cout << “Final Exam mark: “ << mark2 << endl; } int main( ) { char* name = “Desmond”; int midtermMark = 100; int finalExamMark = 90; formattedOutput(name, midtermMark, finalExamMark); return 0; }
Example of user-defined function (5) • These two function definitions are equivalent void printWelcome(void) { cout << “Hello World” << endl; } void printWelcome() { cout << “Hello World” << endl; }
Documentation for functions • It is a good practice to document the functions (ie. add sufficient comment to the function). • Describe the task that the function performs. • Describe the meaning of each parameter. • Describe the meaning of the returned value. • For example, • /* Convert the character c to lowercase letter if c is a uppercase letterOtherwise, keep the character c unchanged */int tolower(char c) { … } • /* Round x into nearest integerInput: x, any real numberOutput: nearest integer of x */int round( double x ) { … }
Function Pass-by-value and Pass-by-reference
Pass-by-value and Pass-by-reference • In C++, there are two ways that the arguments can be passed to a function: • Pass-by-value • Pass-by-reference
Pass-by-value • Pass-by-value copies the value of an actual parameter into the formal parameters of the function. • Changes made to the formal parameter have no effect on the actual parameter.
Examples int sum(int a, int b) { a = a + b; return a; } int main() { int x = 3, y = 5; int z= sum(x,y); return 0; } • What’s the value of x, y, z after the function call sum? • Ans: 3, 5, 8
Examples • Reasons: • The value of the original variable is copied to the parameter. changes to the value of the parameter do not affect the original variable. Even though the value of parameter a is changed, the corresponding value in variable x does not change. • In fact, all information in local variables declared within the function will be lost when the function terminates. • The only information saved from a pass by value function is the return value.
Pass-by-reference • Pass-by-reference does not copy the value of the actual parameters. • Instead, the formal parameters refer the actual parameters by some mechanism. • More about this later, when we are talking about reference variable. • Any modification of the formal parameters directly changes the value of the actual parameters. • To pass the parameters by reference, we have to add a symbol & after the type of the formal parameters.
Examples void swap(int& a, int& b) { int temp = a; a = b; b = temp; } int main() { int x = 10, y = 20; swap(x, y); cout << “(x, y) = “ << x << ", " << y ; return 0; } • What’s the output? • (x,y) = 20, 10
Examples • Explanation: • Note that two formal parameters are pass-by-reference. • The formal parameter a refers to the actual parameter x. • The formal parameter b refers to the actual parameter y. • The value of a and b are changed inside the function. • This is equivalent to modify the actual parameters x and y directly.
Examples void swap(int a, int b) { int temp = a; a = b; b = temp; } int main() { int x = 10, y = 20; swap(x, y); cout << “(x, y) = “ << x << ", " << y ; return 0; } • What’s the output? • (x, y) = 10, 20 (unchanged!!)
Final Note on Pass-by-value and Pass-by-reference • A function can contain multiple parameters. • Some may be pass-by-value, while other may be pass-by-reference. • No restriction on the order of pass-by-value and pass-by-reference. • If a function has multiple return values, we may use pass-by-reference. • void largestTwoElements(const int* array, int size, int& largest, int& secondLargest) • Sometimes, when the object is large, we may use pass-by-reference to avoid copying even if we don’t want to change the actual parameters. • Use constant reference (add const before the type). • More on this when we are talking about class.
Function Local and Global scope
Scope • Scope is a region of code. • We can define a scope by enclosing a piece of code within curly-braces. • It is possible to declare the same identifier name in different scopes. • Because an identifier is both identified by its name and the scope where it is defined. • Identifiers defined in different scopes are treated as different identifiers, even if their name are the same. • But an identifier should have unique name inside a scope. • The outermost scope is called global scope. • All other scopes (may be called local scope) are inner scopes of global scope. • More about this when we are talking about namespace.
Global and Local Declaration • Declaration inside global scope is called global declaration. • It is valid inside all other scopes (or in the whole program). • Declaration inside local scope is called local declaration. • It is valid inside that local scope or other inner scopes . • Of course, it is only valid after its declaration inside that scope.