Functions 1 Example: Power, Square Root and Absolute values of a number #include <cmath> … float num; float power, squareRoot, absolute; cout << "Please input a float number: "; cin >> num; power = pow ( num , 2 ); cout << "The power is " << power << endl; if ( num > 0 ) { squareRoot = sqrt ( num ); cout << "The square root is " << squareRoot << endl; } else cout << num << " is negative. No squre root!" << endl; absolute = fabs ( num ); cout << "The absolute value is " << absolute << endl; 2 Math Functions in <cmath> Need to use #include <cmath> or #include <math.h> float pow ( float base, float exponent ); float sqrt ( float num ); float fabs ( float num ); They are functions! These are function prototypes! 3 What other functions have you learned? bool cin.eof(); int string.length(); string string.substr(); smanip setprecision(int n); smanip setw(int n); How to define and use your own function? 4 Example: MAX of 2 numbers #include <iostream> using namespace std; int Max ( int num1, int num2 ); int main() { int num1, num2, maxResult; cin >> num1 >> num2; // function prototype (function declaration) // function maxResult = Max ( num1, num2 ); cout << "The max is " << maxResult << endl; call return 0; } int Max ( int num1, int num2 ) { int result; if ( num1 > num2 ) result = num1; else result = num2; // function heading function definition return result; } 5 Review: Element of a function Return Data Type Function Body Function Name Parameter List int Max ( int num1, int num2 ) { int result; if ( num1 > num2 ) result = num1; else result = num2; return result; } 6 Function Prototype C++ programmer usually place all supporting functions after the main function. C++ rule: identifiers must be declared before use! Place a function prototype before the main function as a declaration. Two ways to declare a function: int max ( int num1, int num2 ); OR int max ( int, int ); Add a semicolon to the function heading, and you get the function prototype! 7 Function Prototype Common Practice! #include <iostream> using namespace std; #include <iostream> using namespace std; int max ( int num1, int num2 ); int max ( int num1, int num2 ) { int result; if ( num1 > num2 ) result = num1; else result = num2; int main() { … maxResult = max ( num1, num2 ) … } int max ( int num1, int num2 ) { int result; if ( num1 > num2 ) result = num1; else result = num2; return result; = return result; } int main() { … maxResult = max ( num1, num2 ) … } } 8 Review: Two Types of Functions Void Function Return data type is void Don’t need a return statement in the function Function call format: functionName(parameters); Value-Return Function Return data type is some real data type (int, float, string) Need a return statement to return a value to the caller function Function call format: var = functionName(parameters); OR use functionName(parameters)as a variable. 9 Formal parameters vs. Actual parameters (Arguments) Formal parameters appears in a function heading. int max ( int num1, int num2 ); Used in the callee function. Actually parameters (Arguments) appear in a function call. result = max ( 2, 3 ); During a function call, an argument can be a literal, variable, or expression. result = pow( 3, 2 ); result = fabs ( num ); result = sqrt ( num / 2 + 1 ); A function is not required to have arguments. eof(); Used in the caller function. 10 Void Function #include <iostream> #include <string> using namespace std; const int HEIGHT = 10; void PrintLine(int height); int main() { int height = HEIGHT; while ( height > 0 ) { PrintLine(height); height --; } return 0; } Formal parameter: height Actual parameter: height They can have the same name! void PrintLine(int height) { string spaceLine = ""; string dollarLine = ""; int count = 0; while ( count < height - 1 ) { spaceLine += " "; count ++; } count = 0; while ( count < 2 * ( HEIGHT - height ) + 1 ) { dollarLine += "$"; count ++; } cout << spaceLine << dollarLine << endl; } 11 Value-Return Function Formal parameter: payRate, hour Actual parameter: rate, hour They can have different names! #include <iostream> using namespace std; float grossPay(float payRate, float hour); int main() { float hours; float rate; float salary; cout << "Please enter your pay rate “ << “(per hour): "; cin >> rate; cout << "Please enter your working “ << “hours: "; cin >> hours; salary = GrossPay(rate, hours); cout << "Your salary is " << salary << “.” << endl; float GrossPay(float payRate, float hour) { float salary; if (hour <= 40) salary = hour * payRate; else { salary = ( hour - 40 ) * payRate * 1.5 + 40 * payRate; cout << endl << "You have " << ( hour - 40 ) << " hours overtime." << endl; } return salary; } return 0; } 12 Function Names Meaningful names Names for functions and methods with a return type of void should generally be verb phrases such as ComputePay() and PrintOrders(). Names for functions and methods with other return types should generally be nouns or noun phrases such as Average() and MonthlySalary(). Capitalize the first letter of each word! Formal and actual parameters can have the same name They are different variables in different scopes Normally they have different names 13 Activation Record There is one activation record for each function call. An activation record contains: Local variables of the function called Return address Parameters for the function called Locals Return Address Parameters Activation Record for GrossPay int main() { float hours; float rate, salary; cout << "Please enter your pay rate “ << “(per hour): "; cin >> rate; cout << "Please enter your working “ << “hours: "; cin >> hours; salary = GrossPay(rate, hours); cout << "Your salary is " << salary << “.” << endl; return 0; } hours rate Input values: ? ? salary ? 45 10 475 float GrossPay(float payRate, float hour) { float salary; if (hour <= 40) salary = hour * payRate; else { salary = ( hour - 40 ) * payRate * 1.5 + 40 * payRate; cout << endl << "You have " << ( hour - 40 ) << " hours overtime." << endl; } return salary; } 10 45 payRate 10 hour 45 salary ? 475 Scope of Variables The region of code where it is legal to reference (use) an identifier. Local Scope Global Scope Class Scope (Later in this semester.) 16 Statement Block Between a pair of matching braces e.g. The body of a function int main() { int alpha = 10; // A block for if statement if (alpha > 3) { int num; cin >> num; alpha += num; } return 0; } 17 Local Scope int main() { int alpha = 10; The scope of an // A code block if (alpha > 3) { int num; cin >> num; alpha += num; } cout << "num = “ << num; // Run time error! return 0; identifier declared inside a block extends from the point of declaration to the end of that block. } 18 Nested Local Scope local identifiers have name precedence! The scope of an identifier does not include any nested block that contains locally declared identifier of the same name! int main () { int num = 0; string name = “Kyle”; while ( num < 5 ) { string name = “Alice”; cout << name << num << endl; num ++; } cout << endl << name; return 0; } What is the output? Alice0 Alice1 Alice2 Alice3 Alice4 Kyle 19 Global Scope The scope of an identifier declared outside all functions (and classes) extends from the point of declaration to the end of the entire source file. Programming Rules: No global variables! 20 Scope of a Function Name A function name has global scope. Function definitions cannot be nested within function definitions! int main () { int num = 0; string name = “Kyle”; while ( num < 5 ) { void PrintAlice ( int count ) { string name = “Alice”; cout << name << count << endl; } num ++; } cout << endl << name; return 0; } // Can we do that? // NO! 21 Scope of Function Parameters Formal parameters Local scope Same as local variable Cannot reference it outside the function Receive values on function call Actual parameters (no global variables) Local scope Cannot reference it inside the called function 22 Example: GrossPay #include <iostream> using namespace std; formal parameters float GrossPay(float payRate, float hour); int main() { int hour; float rate; float salary; scope cout << "Please enter your pay rate “ << “(per hour): "; cin >> rate; cout << "Please enter your working “ << “hours: "; cin >> hour; actual parameters salary = GrossPay(rate, hour); cout << "Your salary is " << salary << “.” << endl; float GrossPay(float payRate, float hour) { float salary; if (hour <= 40) salary = hour * payRate; else { salary = ( hour - 40 ) * payRate * 1.5 + 40 * payRate; cout << endl << "You have " << ( hour - 40 ) << " hours overtime." << endl; } return salary; } scope return 0; } 23 Example: Using a flag float DoIt(int num, char op); int main() { int base; float result; char choice; cout << “Enter a number: ”; cin >> base; cout << “C for Cube and S for Square Root: ”; cin >> choice; // ---------------------------// Precondition: op is ‘C’ or ‘S’ // Postcondition: the cube of // num is computed when op is // ‘C’, and square root of num // is computed when op is ‘S’. // parameters: in, in // -----------------------------float DoIt(int num, char op) { if (op == ‘C’) result = pow(num, 3); else result = sqrt(num); while (choice != ‘C’ && choice != ‘S’) { cout << “C for Cube and S for Square Root: ”; cin >> choice; } result = DoIt(base, choice); return result; } cout << “The result: ” << result; return 0; } // What is wrong? // Result not declared in the // function! 24 Example: Using a flag int DoIt(int num, char op); int main() { int base; float result; char choice; cout << “Enter a number: ”; cin >> base; cout << “C for Cube and S for Square: ”; cin >> choice; while (choice != ‘C’ && choice != ‘S’) { cout << “C for Cube and S for Square: ”; cin >> choice; } result = DoIt(base, choice); cout << “The result: ” << result; return 0; } // -----------------------------// Precondition: op is ‘C’ or ‘S’ // Postcondition: the cube of // num is computed when op is // ‘C’, and square root of num // is computed when op is ‘S’. // parameters: in, in // -----------------------------float DoIt(int num, char op) { float result; if (op == ‘C’) result = pow(num, 3); else result = sqrt(num); return result; } // The two variables // result have the same // name, but different! 25 Programming Ground Rules All functions, including the main function, should be no more than 30 lines long, from the left brace to the right brace, inclusive. Every function and method, except the main function, must have a comment which describes what it does and whether the parameters are input, output, or input and output. Be sure to document the purpose of any parameter which isn't obvious from its name alone. Thus function and method headers must have the following format: //--------------------------------------------------------// A few lines describing what the function or method does. // params: (in/out/inout, ...) //--------------------------------------------------------result_type function_name(type1 param1, type2 param2, ...) 26 Function Parameters IN parameters: The value of the actual parameter is passed into the function and assigned to the formal parameter. OUT parameters: The value of formal parameter is passed out of the function and assigned to the actual parameter. InOut Both In and Out. 27 Example: IN Parameter #include <iostream> using namespace std; float GrossPay(float payRate, float hour); int main() { int hour; float rate; float salary; cout << "Please enter your pay rate “ << “(per hour): "; cin >> rate; cout << "Please enter your working “ << “hours: "; cin >> hour; salary = GrossPay(rate, hour); cout << "Your salary is " << salary << “.” << endl; The value of rate and hour in the main function is passed to payRate and hour in the grossPay function. Can we write a function to input rate and hour? How to pass the values back to the main function? return 0; } 28 Example: OUT Parameter float GrossPay(float payRate, float hour); void GetInput(float& payRate, float& hoursWorked); int main() { float hour, rate, gross; // Call function getInput() to get two values GetInput(rate, hour); // Call function grossPay to get one value gross = GrossPay(rate, hour); // display result cout << "Your salary is " << gross << endl; return 0; } 29 Function definition of GetInput // // // // // ------------------------------------------------The function inputs payRate and hoursWorked and pass both values back to the calling function. Parameters: (out, out) ------------------------------------------------- void GetInput(float& payRate, float& hoursWorked) { cout << "Enter pay rate: "; cin >> payRate; cout << "Enter hours: "; cin >> hoursWorked; } // // // // return; // in void functions, using return is optional. The function does input with prompt, but OUT parameters! How can it pass two values back? Out Parameters: & Statement return can pass only one value back! 30 Function definition of GrossPay // ------------------------------------------------// The function computes and returns the gross pay // based on the pay rate and hours. Hours over // 40 will be paid 1.5 times the regular pay rate. // Parameters: (in, in) // ------------------------------------------------float GrossPay(float payRate, float hour) { if (hour > REG_HOURS) payRate = (hour - REG_HOURS) * OVER_TIME * payRate + REG_HOURS * payRate; else payRate = hour * payRate; return payRate; } // No local variable // payRate is used to store the result 31 Reference and Value Parameters float GrossPay(float payRate, float hour); void GetInput(float& payRate, float& hoursWorked); Value parameter: No & DataType identifier, … The value of actual parameter is passed to the formal parameter Reference Parameter: With & DataType& identifier, … The address of actual parameter is passed to the formal parameter Does the actual parameter change its value when the corresponding formal parameter changes its value? Value parameter (no &): NO Reference parameter (&): YES 32 Reference and Value Parameters Function call using value parameters: gross = GrossPay(rate, hour); float main Memory rate 22.5 hour 50 GrossPay(float payRate, float hour); GrossPay payRate 22.5 hour 50 Function call using reference parameters: GetInput(rate, hour); Memory 7000 main rate 22.5 7004 50 hour void GetInput(float& payRate, float& hoursWorked); GetInput 70 &payRate 00 70 &hoursWorked 04 33 Trace Functions with OUT parameters Input: 10 45 GetInput(rate, hour); // Reference parameters gross = GrossPay(rate, hour);// Value parameters main() rate ? hour ? ? gross GetInput() 10 45 450 GrossPay() payRate &rate payRate 10 hoursWorked &hour hour 45 salary ? 450 34 Example: InOut Parameter int main() { float score, highest, lowest; int scoreCount = 0; cin >> score; while (!cin.eof()) { if (scoreCount == 0) { highest = score; lowest = score; } else { if (score > highest) highest = score; if (score < lowest) lowest = score; } scoreCount ++; cin >> score; } cout << “Highest: “ << highest << “\nLowest: “ << lowest; return 0; } // Task: Use a function to update highest and lowest. 35 Example: InOut Parameter void UpdateMaxMin ( float, float&, float& ); int main() { float score, highest, lowest; int scoreCount = 0; cin >> score; while (!cin.eof()) { if (scoreCount == 0) { highest = score; lowest = score; } else UpdateMaxMin ( score, highest, lowest ); scoreCount ++; // // // // // // -------------------------------The function uses the value of num to update the values of max and min. Parameters: ( In, InOut, InOut ) -------------------------------- void UpdateMaxMin( float num, float& max, float& min ) { if (num > max) max = num; } if (num < min) min = num; cin >> score; } cout << "Highest: " << highest << "\nLowest: " << lowest; return 0; } 36 Example: InOut Parameter Function call: UpdateMaxMin ( score, highest, lowest ); Function Definition: void UpdateMaxMin( float num, float& max, float& min ) main Memory updateMaxMin score 20 num highest 20 10 max &highest lowest 2 min &lowest 37 Trace Functions with InOut parameters Input: 45 40 50 updateMaxMin ( score, highest, lowest ); //Function call void updateMaxMin( float num, float& max, float& min ) //Function definition 38 Value Parameter and Reference Parameter What can the actual parameter be for a value parameter? A VALUE! Literal value Variable Expression (magic number) (initialized!) (with all variables initialized) What can the actual parameter be for a reference parameter? AN ADDRESS! Literal value: Expression: Variable: NO NO YES initialized or uninitialized 39 Actual Parameter Does the actual parameter change its value when the corresponding formal parameter changes its value? Value Parameter NO! Reference Parameter YES! 40 Function Calls Main function can call another function A A function can also call another function B main A B Caller Callee Caller Callee 41 Decompose the program by functions Modularity Any function or method (including the main function) can have at most 30 lines. A function should implement ONE basic functionality. Functions and methods which focus on computation should not produce output using cout statements. Check: Can I replace the loop body with a function? Can I use a function to get valid input? Can I use a function to do some particular computation? Is there any activity that is repeated multiple times in the program? 42 Design Function Interface What parameters should be passed? How? In, Out, or InOut? In: pass by value. Recommended! Out: pass by reference. InOut: pass by reference. If possible, try to avoid passing reference parameters! Because it might cause unexpected values changes of the caller’s variables. 43 Example: Bad Functions float GetRate(float rate) { cout << “Enter the rate: ”; cin >> rate; return rate; } // Bad: Why use parameter? float GetRate() { float rate; cout << “Enter the rate: ”; cin >> rate; return rate; } // Good: Use local variable! float GrossPay(float rate, float hour) { float pay = rate * hour; cout << “The pay is “ << pay; return pay; } // Bad: No output in calculation functions! void Power ( int& base, int& exponent, int& result ) { result = 1; while ( exponent > 0 ) { result = result * base; exponent --; } } // Bad: No need to use reference parameter! 44 Example: Print a chess board Pseudo Code: while height is not 8 yet if line# is odd, then print an odd row otherwise, print an even row Print an odd row: while cell height is not enough while cell width is not enough if cell# is odd print N spaces otherwise, print N ‘@’ Do we need two print row functions? Use a flag to indicate odd or even row! Print an even row: while cell height is not enough while cell width is not enough if cell# is odd print N ‘@’ otherwise, print N spaces 45 Example: Print a chess board Pseudo Code: while height is not 8 yet if row# is odd, then print an odd row otherwise, print an even row The function printRow is too long! Print a row: while cell height is not enough while cell width is not enough if cell# is odd print N spaces if row# is even, or print N ‘@’ if row# is odd otherwise, print N ‘@’ if row# is even, or print N spaces if row# is odd replace the circled code with function printLine! Further pass the flag to printLine. 46 Example: Print a chess board const const const const const int BOARD_WIDTH = 8; int CELL_WIDTH = 10; int CELL_HEIGHT = 4; char FILL = '@'; char EMPTY = ' '; int main() { int count = 0; while ( count < BOARD_WIDTH ) { printRow ( count ); count ++; } return 0; } void printRow ( int rowNum ) { int countHeight = 0; while ( countHeight < CELL_HEIGHT ) { printLine ( rowNum ); countHeight ++; } } void printLine ( int rowNum) { int countWidth = 0; int countCell = 0; while ( countWidth < BOARD_WIDTH ) { countCell = 0; if ( countWidth % 2 == 0 ) while ( countCell < CELL_WIDTH ) { if ( rowNum % 2 == 0) cout << EMPTY; else cout << FILL; countCell ++; } else while ( countCell < CELL_WIDTH ) { if ( rowNum % 2 == 0) cout << FILL; else cout << EMPTY; countCell ++; } Can it be further countWidth ++; decomposed? } cout << endl; 47 } Summary Function definition Function prototype Void functions vs. value-return functions Formal parameters vs. actual parameters Scope of variables Scope of function parameters Scope of function names Parameter passing: In, Out and InOut Value parameters vs. reference parameters Program decomposition 48 More about getting input cin.get() cin.ignore() getline(cin, string) 49 cin.get(char&) the >> operator skips any leading whitespace or new line in the input stream. What if we want to read the whitespace? char ch1, ch2, ch3; //Input: a b c cin >> ch1 >> ch2 >> ch3; //OR cin.get(ch1); cin.get(ch2); cin.get(ch3); //ch1 = ‘a’, ch2 = ‘b’, ch3=‘c’ //ch1 = ‘a’, ch2 = ‘ ’, ch3=‘c’ 50 cin.ignore() cin.ignore(200, ‘\n’): skip the next 200 input characters OR skip characters until a newline character is read whichever comes first! string str; cin.ignore(20, '\n'); cin >> str; cout << endl << str; If the input is “This is a test to see which string will be input.”, what do you think is the input? 51 getline(cin, string) How to read a complete line of input? getline(cin, string) will read everything until it reaches a newline character. 52