520 likes | 634 Views
Chapter 7-8. Functions. 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 );
E N D
Chapter 7-8 Functions
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;
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!
What other functions have you learned? • bool cin.eof(); • int string.length(); • string string.substr(); • smanipsetprecision(int n); • smanipsetw(int n); How to define and use your own function?
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; maxResult = Max ( num1, num2 ); cout << "The max is " << maxResult << endl; return 0; } int Max ( int num1, int num2 ) { int result; if ( num1 > num2 ) result = num1; else result = num2; return result; } // function prototype (function declaration) // function call // function heading function definition
Review: Element of a function Return Data Type Function Name Parameter List int Max ( int num1, int num2 ) { int result; if ( num1 > num2 ) result = num1; else result = num2; return result; } Function Body
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!
Function Prototype Common Practice! #include <iostream> using namespace std; int max ( int num1, int num2 ) { int result; if ( num1 > num2 ) result = num1; else result = num2; return result; } int main() { … maxResult = max ( num1, num2 ) … } #include <iostream> using namespace std; int max ( int num1, int 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; } =
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.
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.
Void Function Formal parameter: height Actual parameter: height They can have the same name! #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; } 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; }
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; return 0; } 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; }
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
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; } 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; } Input values: 10 45 ? hours 45 payRate 10 rate hour ? 10 45 ? salary salary 475 ? 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.)
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; }
Local Scope int main() { int alpha = 10; // A code block if (alpha > 3) { int num; cin >> num; alpha += num; } cout << "num = “ << num; // Run time error! return 0; } • The scope of an identifier declared inside a block extends from the point of declaration to the end of that block.
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
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!
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!
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
Example: GrossPay #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; return 0; } formal parameters 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 actual parameters scope
Example: Using a flag // ---------------------------- // 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); return result; } // What is wrong? // Result not declared in the // function! 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; while (choice != ‘C’ && choice != ‘S’) { cout << “C for Cube and S for Square Root: ”; cin >> choice; } result = DoIt(base, choice); cout << “The result: ” << result; return 0; }
Example: Using a flag // ------------------------------ // 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! 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; }
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_typefunction_name(type1 param1, type2 param2, ...)
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.
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; return 0; } 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?
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; }
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!
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
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
Reference and Value Parameters • Function call using value parameters: gross = GrossPay(rate, hour); • Function call using reference parameters: GetInput(rate, hour); float GrossPay(float payRate, float hour); main GrossPay Memory Memory rate 22.5 payRate 22.5 50 hour hour 50 void GetInput(float& payRate, float& hoursWorked); main GetInput 7000 rate 22.5 &payRate 7000 7004 50 &hoursWorked 7004 hour
Trace Functions with OUT parameters Input: 10 45 GetInput(rate, hour); // Reference parameters gross = GrossPay(rate, hour);// Value parameters main() GetInput() GrossPay() rate ? 10 payRate 10 &rate payRate hour hoursWorked ? 45 &hour hour 45 ? gross 450 salary ? 450
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.
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 ++; cin >> score; } cout << "Highest: " << highest << "\nLowest: " << lowest; return 0; } // -------------------------------- // 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; }
Example: InOut Parameter • Function call: UpdateMaxMin ( score, highest, lowest ); • Function Definition: void UpdateMaxMin( float num, float& max, float& min ) Memory main updateMaxMin 20 score 20 num highest 20 10 max &highest lowest 2 min &lowest
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
Value Parameter and Reference Parameter • What can the actual parameter be for a value parameter? A VALUE! Literal value (magic number) Variable (initialized!) Expression (with all variables initialized) • What can the actual parameter be for a reference parameter? AN ADDRESS! Literal value: NO Expression: NO Variable: YES initialized or uninitialized
Actual Parameter • Does the actual parameter change its value when the corresponding formal parameter changes its value? Value Parameter NO! Reference Parameter YES!
Function Calls • Main function can call another function A • A function can also call another function B main A B Caller Callee Caller Callee
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?
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.
Example: Bad Functions 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! 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!
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 ‘@’ 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 Do we need two print row functions? Use a flag to indicate odd or even row!
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 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 The function printRow is too long! replace the circled code with function printLine! Further pass the flag to printLine.
Example: Print a chess board 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 ++; } countWidth ++; } cout << endl; } const int BOARD_WIDTH = 8; const int CELL_WIDTH = 10; const int CELL_HEIGHT = 4; const char FILL = '@'; const 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 ++; } } Can it be further decomposed?
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
More about getting input • cin.get() • cin.ignore() • getline(cin, string)
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; cin >> ch1 >> ch2 >> ch3; //OR cin.get(ch1); cin.get(ch2); cin.get(ch3); //Input: a b c //ch1 = ‘a’, ch2 = ‘b’, ch3=‘c’ //ch1 = ‘a’, ch2 = ‘ ’, ch3=‘c’