250 likes | 366 Views
Lecture 16 & 17. What will I learn in this lecture?. Grasp the concept of top-down programming Identify Function Headers and Prototypes Understand when and where prototypes used Understand how arguments are passed to a function using call-by-value or call-by-reference
E N D
What will I learn in this lecture? • Grasp the concept of top-down programming • Identify Function Headers and Prototypes • Understand when and where prototypes used • Understand how arguments are passed to a function • using call-by-value or call-by-reference • Related Chapters: ABC Chapters 5.1 – 5.7
Functions - "Top Down Design" In lecture slides 2-17 and 10-15 we discussed a method for creating programs. In step three “Develop the Algorithm”, the nature of the programming problem may suggest that we use top down programming (as opposed to bottom-up programming , ...) An analogy for top-down design is the following: Suppose a general contractor was hired to construct a commercial building. The contractor would need to know where to build and what are the blue-prints. Then the contractor would hire various sub-contractors to dig foundation, install electric, plumbing, frame, roof. That is, the large job would be broken into smaller jobs, however these jobs must be performed in some sequence and not at random.
Functions - "Top Down Design" In top-down design for programming, the first function to be invoked in a program (the top function or “general contractor”) is called “main”. The programmer has the “main” function call other component functions (sub-contractors), which may in turn call functions, (sub-sub-contractors) and so on.
Example - Call-by-Value 1. Problem Definition Write a function “sinc” that computes the value of sin(x)/x . If x is zero return 1.0. 2. Refine, Generalize, Decompose the problem definition (i.e., identify sub-problems, I/O, etc.) Input = One real number of type double. Output= sin(x)/x as a double if x is not zero else 1.0. 3. Develop Algorithm Use an if statement to check for a non-zero value.
Example: Function sinc(x) = sin(x)/x #include <stdio.h> #include <math.h> double sinc (double z) /* function header */{ if (z == 0.0) return 1.0; else return sin(z) / z; /* notice that sinc calls sin */ } void main(void){ double x, y; printf("Enter a number: "); scanf("%lf", &x); y = sinc(x); /* function call */ printf("\n sinc(%lf) = %lf \n", x, y); } /* end of main */
Example: Location of user-defined functions Using gedit, user-defined functions can be typed into the same file as “main”. Functions may be typed into a separate file. For example, suppose “main” is in the file test.c and the user defined function “sinc” is entered into the file func.c then to compile both “main” and “sinc” you would type (at the Unix prompt) gcc test.c func.c -lm Note the use of the “-lm” option The -lm option is needed only if you use a math library function in “main” or “sinc”. Don’t forget that if you put the function “sinc” into a separate file, then you must still put the prototype for “sinc” in the same file as main. The prototype for “sinc” must precede the function main.
Function Definition • The function definition in C is of the form: return-type function-name(parameter-list){/* function code */return (value); /* parenthesis optional */} • The “value” can be a single variable, constant, or any C expression. • The data type of “value” should be of type “return-type”, if not then a conversion of the “value” to the “return-type” is specified by the C compiler. • If the “return-type is void then the programmer can omit the return • statement or code: return ; /* return nothing */
Function Call • A function may be called from any function (including itself) in C. • A call takes one of the following forms: function-name(argument-list); var = function-name(argument-list); • To “call” or invoke a function, you must pass the same number of arguments for which the function has parameters. The order of the arguments is important!!! • If the data types in the argument list do not match the data types in the parameter list, a conversion(or coercion) takes place. (see p. 132 in ABC)
Function Type Checking /* code fragment in main */int x = 1;float y = 2.0;float value;double z = 5.0; value = sum(x,y,z+4.0); } /* end of main *//* sum adds an integer a float and a double and returns *//* a double */double sum(int a, float b, double c){ double result; result = a + b + c; return result;} Since value has type float and sum returns a double, a conversion takes place. Data-types agree!
Function Type Checking • A function that does not return a value is declared to be of type void. e.g., void printFunction (int x , int y) • If a function takes no parameters, we specify the parameter list as void. e.g., void printPageHeading (void) It is also possible to specify an "empty" parameter list: void myFunction ( ) - argument checking is "turned off", so that anything can be passed to myFunction. Best to avoid this in C.
Function Type Checking • By default , if you omit the data type of the return value, C assumes that the function returns an int value (not void). Therefore the following function header: main(void) is equivalent to: int main(void)
Example - Average and Difference List 1. Problem Definition Redo the problem in Lecture 15 slides 12,13 using a modular approach. The problem is: Write a program that inputs a list of numbers into an array. The program then calculates the average value, and then prints a list of differences. The differences are computed by taking the original values in the list minus the average. 2. Refine, Generalize, Decompose the problem definition (i.e., identify sub-problems, I/O, etc.) Input = list of reals in a file “input.dat” . We will use Unix redirection to read values from this file. Output= The average and the list of differences.
#include <stdio.h> int read(double alias[]); /* prototype for read func */ double ave(int count,double alias[]); /* prototype for ave function */ void diff(double average, int count, double alias[]); /* prototype for diff function */ void main(void){ int counter,k; double datVal[500]; /* 500 element max */ double datAve; counter = read(datVal); /* read file into datVal */ datAve = ave(counter,datVal); /* compute, print average */ printf("The average is:%f \n", datAve); diff(datAve,counter,datVal); /* compute diff list */ for(k=0;k<counter;++k) /* print the diff list */ printf("%lf\n", datVal[k]); } /* end of main */
int read(double alias[]) { int count = 0; while (EOF != scanf("%lf", &alias[count])) { ++count; } return count; } double ave(int count,double alias[]){ int i; double sum = 0.0; for (i=0;i<count;++i) sum += alias[i]; return sum/count; } void diff(double average, int count, double alias[]){ int i; for (i = 0;i<count;++i) alias[i] -= average; }
C Problem Example - Execution 1. Use gedit to enter the above code in a file problem1.c ,and make sure to save the file. 2. Use gedit to create an input file input.dat and enter in integers into this file. Save and exit this file. 3. Compile the problem1.c code by typing gcc problem1.c 4. Run the program using Unix redirection < ./a.out < input.dat
C Problem Example - Execution Example: If the file input.dat has the values: 1.0 2.0 3.0 4.0 5.0 Then the program would execute as follows: unixprompt> ./a.out < input.dat The average is:3.000000 -2.000000 -1.000000 0.000000 1.000000 2.000000 unixprompt>
Functions - Prototypes In the latest versions of standard C ("ANSI C"), thefunction prototypeis used to define the data type to be returned by the function, the number and data type of function parameters, and the order of the function parameters. This info is used by the C compiler to validate calls to the function. A general principle in C is that you must declare or define the identifier (variable or function) before you use them.
Functions - Prototype One method to code the function “read”in C : #include <stdio.h> /* include statements */ int read(double alias[]);/* prototype for read function */ void main(void) /* definiton of the main function */ { /* C code here */ } /* end of main */ int read(double alias[]) /* function definition */ {/* more C code here */ } /* end of read */
Functions - Prototypes The actual variable or array name is not needed in the function prototype. Examples: Instead of the following prototypes int read(double alias[]); double ave(int count,double alias[]); void diff(double average, int count, double alias[]); we could have used int read(double []); double ave(int ,double []); void diff(double , int , double []);
Functions - Prototypes Another method to code the function “read ” in C without using a prototype : #include <stdio.h> /* include statements */ /* Since the definition of read occurs before it is */ /* used (called) by main, we don’t need a prototype.*/ int read(double alias[]) /* function definition */ {/* C code for read here */ } /* end of read */ void main(void) /* definiton of the main function */ { /* C code for main function here */ } /* end of main */
Passing arguments in a function call Main Memory before call • Arrays are passed as call-by-reference. 1200 datVal[0] datVal[1] datVal[2] counter = read(datVal); . . . int read(double alias[]) { int count = 0; while (EOF != scanf("%lf", &alias[count])) { ++count; } return count; } unknown . . . . . . Address Main Memory after call 1200 datVal[0] datVal[1] datVal[2] 1.0 2.0 . . . . . . Address
Passing arguments in a function call Main Memory before call • Non-arrays are passed as call-by-value. 1192 counter 5 5 . . . datAve = ave(counter,datVal);. . . double ave(int count,double alias[]) { int i; double sum = 0.0; for (i=0;i<count;++i) sum += array[i]; return sum/count; } Address while executing ave 1192 counter 5 1196 count 5 Address The value of the parameter “counter” is copied into the memory location for the variable “count”. Therefore any change to “count” would have no affect on “counter”.
Two-Dimensional Arrays as Function Parameters For two dimensional arrays, we could omit specification of the number of rows in function prototype and header. But we must include size declaration for the number of columns. (see example on next slide)
Examples of passing 2-D arrays void doSumpin(int [][5]); int main (void) { int a[10][5] = {{0}}; doSumpin (a); } void doSumpin(int b[][5]) /* array passed by reference */ {... } /* function prototype */ /* function call */