Sunteți pe pagina 1din 12

Laboratory Module 4

Using Functions

Purpose:
To understand functions returning non-integers and static/external variables
To understand the usage of call by value / call by reference functions

1 Preparation Before Lab

1.1 Theoretical aspects

1.1.1 The C Function
Functions are a basic component of the C language. A function is a discrete group of program
statements containing code that acts as an independent program. The function can create new data, or it can
use and modify the program's original data. A function can provide a user interface or perform behind-the-
scenes activities.
Functions enable you to create structured and modular code. Such structured, modular code lets
you create programs that are easy to read and to interpret, portable from one platform to another, and easily
updated and modified
A function must be defined. As it must be done with variables, functions must be declared
statement called the function prototype. The basic statement for defining a function prototype takes the
form:
function_type function_name(argument_type argument_name);

The function_type represents the value that is to be returned by the function.
The function_name is the actual name that is given to the function in the program and will be used
to call the function.
There might be one or more arguments, which are data, sent to the function for processing. If your
function will accept arguments, you must include a type definition and name for each of those arguments in
the function prototype. The name you specify for a parameter in the function prototype is the name by
which you can access the value within the function.
Finally, the function prototype is terminated with the semi-colon.
Then, it must be defined the actual code that makes up the function with the function definition
statements.

/* first, the prototype statement */
void hello(int x);

/* then, the definition statements */
void hello(int x) {
printf("The number of the day is %d", x);
}

1.1.2 Structure and Modularity through Functions / The Scope and Attributes of a Function
A program that contains all of its program statements in a single block (as in the following code) is
cumbersome, difficult to read, and almost impossible to modify without affecting the other code.
With functions, modular blocks of code can be created, avoiding repetitious programming and
creating code that can be used numerous times without modification. A function may even be used in other,
separate C programs, though that application of functions isn't covered in this lesson.
All C functions have a common scope and certain attributes that apply to them, including:
1) Each function is a discrete program unit; its code is private and can be accessed only by a valid
function call.
2) All functions reside at the same level. A function cannot be defined within another function (as in other
languages like Pascal) or be subordinate to another function.
3) The first program statement in the function main() begins the execution of a program.
4) Any function can call any other function, including a call to the function main().

1.1.3 The ANSI Standard C Function
Three components make up the ANSI standard C function:
1) The function prototype (or declaration) is used to declare the function, and is analogous to declaring a
variable.
2) The function code (or definition) contains the actual C statements that perform the actions of the
function.
3) The function call puts the function to work by initiating the function's actions and providing the
function with any data (arguments) it requires to perform its actions.
The Function Prototype
According to the ANSI standard, you must declare each function with a function prototype. The
function prototype is similar to the declaration used to create variables. When you declare a function, you
specify a type, such as int, char, or float, depending on the value that the function returns. If your function
won't return data, you can declare it as type void.
Types of Functions
A function can pass (or return) a value back to the calling function (such as main()). The type of
value that will be passed back by the function is the data type you specified in the function prototype. You
can declare functions to be of any valid C data types.
The only requirement is that the prototype should occur prior to the first function call. The
placement of the prototype affects the scope of the function. It is advisable that the function prototypes will
be located before the function main().
The Function Code or Definition
The function definition contains the actual program statements that performs the function's action.
The function definition is located after the function main().
The opening definition includes the function type, followed by the function name and, enclosed in
parentheses, any arguments passed to the function. As with the function main(), program statements are
enclosed in braces. A variable that is declared within the parenthesized list of a function definition
statement is called a parameter, though you will probably see it most often called an argument. Technically,
parameter and argument have different meanings. Arguments are the data passed to a function. Parameters
are the variables defined to hold that data.
The Function Call
To use a function that has been declared and defined, use a function call. You can call a function,
from main() or another function. The function call includes the function's name and, enclosed in
parentheses, any arguments passed to the function. The function call, when used as a stand-alone program
statement, is terminated with a semi-colon.
Creating Local Variables Within a Function
If the functions that you create will handle data, such as input from a user, and pass that data back
to the calling function, then you will need to define a storage location for the data.
To handle such a need, C functions can use local variables. As with the program statements in a
function, these variables are private to the function and aren't usable by program statements outside of the
function. Local variables are created when the function is called and are destroyed on the completion of the
function's actions.
The formats for declaring local variables in a function are the same as those you use to define
variables outside of functions. You should declare local variables immediately following the opening brace
in the function definition.
The scope of a variable is the extent to which it is known within a function or a program. The
variables declared in the example shown above are limited to the function in which they're declared. It is
possible to modify (increase or decrease) the scope of a variable, though details of how to do so are not
covered in this lesson.



Returning a Value from a Function
In the function prototype, you declare a function to be of any valid C type. The reason you do so is
to specify what type of data the function will return once it has finished executing. A function is said to
return data when it sends a value back to the function that called it.
To pass a value back to the calling function, use the return keyword. You put the return statement
after the point in the code where the function has finished its processing and is ready to pass back a result.

1.1.4 Passing Data to Functions

Passing Variables as Arguments
So far, it was shown how to create and use functions in your programs. The values that were used
in the functions were created, assigned, and used entirely in the function, or they were obtained from the
user as input from the keyboard. There is a third method of providing functions with data. Data, whether
constant or variable, can be passed as an argument to the function. Data is passed to a function for two
purposes:
1) To use the data as it is passed, without altering the original values.
2) To alter the value that is passed and its value in memory.
Passing Data Values
Passing data values provides a function with information from outside of the function. When you
pass a value, a copy of the original value is created for use within the function. The original value is not
altered by the function.
In the function definition, the arguments create new variables. These new variables are initialized
to the values passed in the function call. These copies of the original data are then used within the function.
Modifying Variable Values From Within a Function
Passing data values provides a function with outside information, but not the ability to modify the
original information. You can allow a function to modify the original values of the data passed to it. This is
analogous to the "pass by reference" notation of other programming languages, but it isn't a true "pass by
reference".
To alter the original value in memory, the address, not the value of the variable, is passed to the
function. This provides the function with the ability to access the value's memory location and alter the
value stored at that location.
Passing an Address to Modify a Value in Memory
Previously, it was presented how to pass values of variables to a function, use those values for
processing, and then return a value to the calling function. The return statement is limited in that, regardless
of the number of values passed to a function, you can have only a single return. By passing variable
addresses, you can work with and modify more than one value per function call.
The C language uses a unique, and sometimes confusing, method to change the values of variables
passed to functions. Instead of the value being passed to the function, as with pass-by-value, the address in
memory of the location where the value is stored is passed. A new type of variable, known as a pointer, is
then used by the function to point to the contents of the memory location, which is the value to be modified.
The unary operators involved in setting up the pass-by reference are the address (&) operator and the
indirection (*) operator.

1.1.5 The C Standard Library Functions

Organization of the C Standard Library
Typically much of the code used in a program isn't contained within your source file, but resides in
other files. You put this concept to use when you used input and output functions that were not part of your
program's code. The I/O functions were referred to by the statement: #include <stdio.h>
The program accessed the I/O constants, macros, and functions in the standard input/output header
file. In keeping with the philosophy of C, much (and in some cases most) of the code that you use in your C
programs won't be written by you. In fact, it isn't really part of the C language; it is code that accompanies
and supports your implementation of C, and is known as the C standard library. The files that comprise the
standard library usually reside in two locations: a directory containing the header files and a directory
containing the library files.

The Header Files
The header files might contain the following statements:
1) Defined (symbolic) constants.
2) Macro functions.
3) Prototypes, or declarations for functions in the standard library.
When you refer to a header file in your program, you can access any or all of the constructs in the
header file. Examples of typical statements in header files are described below: A defined constant might
appear as follows:
#define BUFSIZE 512
This constant (from the stdio.h file) defines the default buffer size. A macro function might be
defined as follows:
#define TO_INCHES(X) (X / 25.4)
The macro TO_INCHES(X) converts millimeters to inches.
A function prototype; might appear as follows:
int _Cdecl scanf( const char * format, ...);
This statement is the prototype for the scanf() function. It is from the stdio.h file. The code for the
standard-library functions resides in the library files.
The Library Files
The library files contain the compiled code for the functions prototyped in the header files. They
are often located in a directory named library, lib, or a similar name. The files usually end with the .lib
extension.
There is a difference between a compiled object file and a library file.
1) When an object file is linked to your program, the entire compiled code is added to the program.
2) The library files behave just as their names indicate, as a library. When a library function is used in
your program, the code for that function is looked up in the library file and only that function's code is
added to the executable version of your program. The remaining contents of the library file are ignored.

Organization of the standard library
Examining and Comparing the header and library Files
1) Move to the directory that contains the library files for your compiler. This will probably be named lib
or library and will be located in the parent directory of your compiler. You can determine the location
of the library and header files by consulting your reference manual that accompanies your compiler.
2) List and examine the names of the files that end with .lib. These library files contain the code for the
standard-library functions.
3) Move to the directory that contains the header files. This will probably be named include and will be
located in the parent directory of your compiler.
4) List and examine the names of the files that end with .h. These header files contain the function
declarations for the standard-library functions. Header files are included in their entirety in your code,
even if you need only a small part of their functionality. Just the needed functions of a library are
added to your executable code, making for a smaller and potentially more efficient program.
The ANSI C Standard Library
Before the ANSI standard was developed, the contents of the library that accompanied your
compiler were not specified. The original C library was based upon the UNIX implementation of the
language. The version of C that you would have used probably contained the stdio.h, math.h, and some of
the other common files, but this was not guaranteed. The names of the files could also differ. The ANSI C
standard specifies the following files: assert.h, ctype.h, errno.h, float.h, limits.h, locale.h, math.h, setjmp.h,
signal.h, stdarg.h, stddef.h, stdio.h, stdlib.h, string.h, time.h.
ctype.h
The ctype.h file contains functions for testing characters. The functions returns non-zero if the test
is true and zero if the test is false. Some representative functions in ctype.h are presented in table below.
This file also includes functions that convert characters to upper or lowercase.






Name Test
isalpha(char) For upper- or lowercase characters
isdigit(char) For decimal digit
isupper(char) For uppercase characters
islower(char) For lowercase characters
isspace(char) For spaces, new lines, tabs, and so forth

limits.h
The limits.h file contains defined constants that specify the minimum sizes of the primary integer
data types on your system. Examples of these are:

Name Test
INT_MAX Maximum value of an int
INT_MIN Minimum value of an int
SHRT_MIN Minimum value of a short
SHRT_MAX Maximum value of a short

The float.h file performs a similar function for floating-point numbers. It defines the length and
precision that can be expected for the float and double types.
math.h

The math.h file contains mathematical functions and macro definitions. Trigonometric, square, and
square-root functions are in math.h. In the following examples, x indicates a numeric argument:
Name Test
double sin(x) Sine of a value
double tan(x) Tangent of a value
double exp(x) Exponential value
double pow(x,y) Value of x to the y power
double sqrt(x) Square root of a value

The arguments x and y are type double. The trigonometric function results are type double, but
they represent radians, not degrees.

stdio.h
The stdio.h file contains the input and output functions and macros. The stdio.h file typically is the
largest of the header files. It can occupy as much as a third of the total size of the header files. You're
probably familiar with some of the input and output operations provided by stdio.h from earlier topics in
this course. The categories of I/O provided include the following:
1) Formatted input and output.
2) Character input and output.
3) File operations.
4) File-positioning functions.

The stdlib.h (or standard library file) file is also known as the utility file. It contains a number of functions
that deal with numeric conversions, memory allocation, and program status. Some stdlib.h functions appear
as though they belong in the math.h file. You should be aware of their location in stdlib.h. The stdlib.h
functions include:
Name Test
double atof(str) Converts characters to float
int atoi(str) Converts characters to int
long atol(str) Converts characters to long
int abs(int x) Returns the absolute value of x
int rand(void) Returns a random number
exit(int x) Ends the program with a status flag

Name Test
double atof(str) Converts characters to float
int atoi(str) Converts characters to int
long atol(str) Converts characters to long
int abs(int x) Returns the absolute value of x
int rand(void) Returns a random number
exit(int x) Ends the program with a status flag

string.h
The string.h file (or string header file) file contains functions that are used to manage character
strings. Some of the operations the functions perform include:
1) Copying a string.
2) Concatenating strings.
3) Comparing strings.

Using the Standard Library Programs
There are several ways to include and use the information in the standard library. How to best
accomplish this will depend on your compiler. Three methods of accessing the library files are:
1) Your compiler might provide automatic access to the standard library. This method depends on your
compiler; to determine whether or not this option is provided, refer to your compiler documentation.
2) Include in your program's code the #include statement and the names of the files you want to refer to.
This method is relatively simple and has the added advantage of improving the readability and
portability of your program. You should consider using this method even if your compiler
automatically includes the standard library.
3) Include in your code a function declaration for the library function, similar to your regular function
prototypes. This method can be difficult because it requires you to determine the correct function
prototype and include it in your source code.

Personal Header Files

You can create personal header files that contain information that you use frequently and that you
want to avoid entering in every program that you develop. The formats for including a file that resides in
your current directory, or a directory that you specify, are shown next, respectively.

#include "filename.h" and #include "\path\filename.h"

For example, there may be defined the following symbolic constants and placed in a header file
named check.h:

/* check.h */
#define MAX_CHECK 1000
#define MAX_WITHDRAWAL 1500

If check.h file is left in your current directory, you would use the following format for your
#include statement:

#include "check.h"
The #include "check.h" statement tells the compiler to look for the file in the current directory.
Using angle braces and double quotes around your header file will work for any compiler. With some
compilers, you might be able to include a path and drive name to specify a location for header files:
#include "\headers\check.h"
#include "c:\headers\check.h"


2 Examples
Example 1. Edit sample program example1.c
/* converts string s to double */
#include <stdio.h>
#include <ctype.h>
#define MAXLINE 100
int getline(char line[], int max);
double string_to_double(char s[]);
void main(void){
double sum;
char line[MAXLINE];
getline(line, MAXLINE);
printf("d = %g", string_to_double(line));
getchar();
}

/* getline: get line into s, return length */
int getline(char s[], int lim){
int c, i;
i = 0;
while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
/* string_to_double: convert string s to double */
double string_to_double(char s[]){
double val, power;
int i, sign;
for (i = 0; isspace(s[i]); i++); /* skip white space */
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s[i] - '0');
power *= 10;
}
return sign * val / power;
}

Example 2. Edit sample program example2.c
/* reverse Polish notation computing*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
#define MAXVAL 100 /* maximum depth of val stack */
#define BUFSIZE 100
int getop(char []);
void push(double);
double pop(void);
int getch(void);
int getch(void);
void ungetch(int);
int sp = 0; /* next free stack position */
double val[MAXVAL]; /* value stack */
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */

/* reverse Polish calculator */
void main(void){
int type;
double op2;
char s[MAXOP];
while ((type = getop(s)) != EOF) {
switch (type) {
case NUMBER:
push(atof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command %s\n", s);
break;
}//end switch
}//endwhile
return 0;
}
/* push: push f onto value stack */
void push(double f){
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}
/* pop: pop and return top value from stack */
double pop(void){
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
/* getop: get next character or numeric operand */
int getop(char s[]){
int i, c;

while ((s[0] = c = getch()) == ' ' || c == '\t');
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c; /* not a number */
i = 0;
if (isdigit(c)) /* collect integer part */
while (isdigit(s[++i] = c = getch()));
if (c == '.') /* collect fraction part */
while (isdigit(s[++i] = c = getch()));
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
/* get a (possibly pushed-back) character */
int getch(void){
return (bufp > 0) ? buf[--bufp] : getchar();
}
/* push character back on input */
void ungetch(int c){
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}

Example 3. Edit sample program example3.c
/* using static variables*/
#include <stdio.h>
#define MAX 5
void sum(void);
void main (void){
for (int i=0; i < MAX; i++)
sum();
}
void sum(void){
static int SUM = 0;
int n;
printf("\n Enter a number: ");
scanf("%d", &n);
SUM += n;
printf("\n Total = %d", SUM);
}

Example 4. Edit sample program example3.c
/* sample call by value and by reference*/
#include <stdio.h>
void add(int *i);
void add(int i);
void main(void){
int i=4; /* variable declaration*/
int *ptr; /* int pointer*/
ptr = &i; /* 'ptr' now contains the address of 'i'*/
printf("\n i = %d.\n", i);
add(ptr);/*call by reference*/
printf("\n After call by reference: i = %d.\n", i);
add(i);/*call by value*/
printf("\n After call by value: i = %d.\n", i);
}
void add(int *ptr){
++*ptr; /* Add 1 to the value pointed too by 'ptr' */
return;
}
void add(int i){
++i; /* Add 1 to i */
return;
}

3 Assignments

I.
1) In example 2, add the modulus (%) operator and provisions for negative numbers.
2) In example 2, add access to library functions like sin, exp, and pow. (See <math.h>)
3)
a. Write a program in C which incorporates a function using parameter passing and performs the
addition of three numbers. The main section of the program is to print the result.
b. Write a program in C which incorporates a function using parameter passing and performs the
product of three numbers. The main section of the program is to print the result.
c. Write a program in C which incorporates a function using parameter passing and performs the
average of three numbers. The main section of the program is to print the result.
4) Write a C function that interchanges two integers. The call must be made by reference.
5)
a. Write a program that prints 2, 4, 6, 8, 60. Use a for loop.
b. Same, but use a while loop.
c. Same, but use a do-while loop.
6) Write a program that asks for two sides of a triangle and then calculates the hypotenuse. Use two
hypotenuse functions to do the calculation: one which calls the attributes by value and returns the
result and one that obtains the result as a parameter called by reference..
II.
1) In example 2, add commands for handling variables.
2) The following should be written as one program.
a. Write a program that prints the value y of the equation
y = ax
2n
+ bx
2
+ cx + d
b. The user should be asked to provide the integer value for n and the decimal values of a, b, c,
d, and x.
c. Using the same values of a, b, c, and x, have the same program then print the value y for
y = ax
2
+ bx + cos(c)
d. The code for each of these polynomials should be placed in its own function.
3) Write a program that asks the user for the high and low temperatures for each day in the month of
January. Ask the user to enter all of the temperatures.
a. Store these temperatures in a two-dimensional array.
b. Pass the array to a function that calculates and returns the average high and low temperatures
for the month.
c. Pass the array to another function that finds and returns the highest and lowest temperatures
for the month.
d. Print out the average high and average low temperatures and the maximum and minimum
temperature.
4) Write a complete program with one function called FindMinMax. This one function will return both
the minimum and the maximum values from an array of values. The FindMinMax function has three
arguments: array with 10 random numbers between 1 and 100 and two pointers: one pointer to min
value and one pointer to max value.
5) Write a program that transforms a number from base p to base q.
6) It is given a positive integer n. Write a program that displays all positive integers that may be obtained
using its digits.
7) Using the random function, show how to store a random number into the variable number that satisfies
each of the following descriptions:
a. A random floating point value in [0,15).
b. A random floating point value in [15,40).
c. A random integer from the set {0, 1, 2, ... , 12}.
d. A random integer from the set {12, 15, 18, 21, 24, 27, 30}.

8) We wish to simulate the roll of two standard six-sided die using a random number generator. When
you roll two standard six-sided die, the total you can roll is between 2 and 12, inclusive. Alice wants to
implement the roll of the pair of dice this way:
srand ( time(NULL) );
int roll1 = rand() % 5 +1;//1-6
srand ( time(NULL) );
int roll2 = rand() % 5 +1;
int total = roll1 + roll2;
printf("\n You rolled a total of %d ",total);

Bob, on the other hand, wants to implement the roll of the pair of dice this way:
srand ( time(NULL) );
total = rand() % 10 +2;
printf("\n You rolled a total of %d", total);

(a) Explain why Alice's code will generate a random number between 2 and 12.
(b) Explain why Bob's code will also generate a random number between 2 and 2.
(c) Which technique, Alice's or Bob's, simulates the rolling of two die correctly? Why?

III.
1) In order to improve readability of example2, split it up into multiple files Every file encapsulates
one part of the program:
calc.h: declarations for all files
main.c: main program
getop.c: getop function
stack.c: stack handling
getch.c: getch and ungetch functions
Decide what variables need to be declared static in these files. Reminder: external (or global) static
variables are private inside one file, whereas internal (or local) static variables provide private, permanent
storage for one function. For this exercise, only external static variables are required.
Make sure your program compiles and executes properly when split up into different files. The
program can be compiled as follows:
% gcc -o calculator main.c getop.c stack.c getch.c
2) Write a program that computes the equivalent resistance of a general circuit. The rules are:
a. R defines a circuit with one resistor
b. (R1 R2)S defines a circuit with resistors R1 and R2 connected in series.
c. (R1 R2)P - defines a circuit with resistors R1 and R2 connected in parallel.
ex: ((R1 R2)S (R3 R4)S)P defines a circuit with resistors R1 and R2 connected in series, resistors
R3 and R4 connected in series and (R1 R2)S and (R3 R4)S connected in parallel.
3) On a chessboard (say 8x8), 1 piece (horse) is placed on a random cell. From then on the horse
should move around the chessboard. The horse should never ends twice on the same cell. The aim
is to have the horse visit ALL cells without visiting a cell twice.
4) It is given a rectangular piece of iron plate with length L and width H. On its surface, there are n
holes at given integer coordinates. It is required to be found the largest area without holes. The
surface is bounded only by vertical and horizontal edges.

S-ar putea să vă placă și