Functions are used to break up the code in modules. Typically a function should perform one type of action on a data. Other actions should be handled by other functions. Under the ANSI C standard all functions must be prototyped. This can take place in the program itself or in a header file.
The function prototype is a copy of the function declaration line terminated with a semicolon.
A typical function declaration :
return_type function_name(argument_type, argument_name, [ argument_type, argument_name, .... ]);
The function prototype is usually included at the start of the program. It is used by the compiler for type checking. The actual function with the declaration and body of code appears after the main function.
The ANSI C recommends each function be prototyped in a seperate header file. For small programs this is not necessary
Calling by value is the default method in C++. This means that the value in the calling program is unchanged. Only a copy of the variable is passed.
Calling by reference passes the address of the variable instead of the actual value.
/*
// function prototype, functions
// argument passing
*/
#include <iostream.h>
int addInteger(int a, int b); // function prototype
int paddInteger(int* pa, int *pb);
// function prototype for call by reference
// expects to be passed pointers to the values
int raddInteger(int &ra, int &rb);
// this is special to C++
// it uses a reference type operator
// however in the call statement there is no
// deferencing operator
// it avoids the use of pointers
int main()
{ int ia = 5;
int ib = 7;
int ic;
int icp;
int icr;
cout << "Value of ic: " << ic << endl;
// see what happens if data is not initialized
ic = addInteger(ia,ib);
cout << " The sum is - pass by value: " << ic << endl;
icp = paddInteger(&ia, &ib);
cout << "\n The sum is - pass by reference: " << icp << endl;
icr = raddInteger(ia,ib);
cout << "\n The sum is - pass by reference C++ only: " << icr << endl;
return(0);
}
int addInteger(int a, int b)
{ return(a + b);
}
int paddInteger(int *pa, int* pb)
{ return(*pa + *pb);
}
int raddInteger(int &ra, int &rb)
{ return(ra + rb);
}
When calling arrays only the array name need to be specified. For example if there is a function prototype
int addArray(int iarray[ ]);
and if the code had an array called intarray[ ] then the function is called addArray(intarray)
By default arrays are called by reference
An array will hold homogenous data. While you can have an array of anything, all elements of the array have the same properties as they are of the same type. Enter structures. Structures allow you to a have a group of variables which can be of different types called members. As you can guess, Structures are the precursors of the Classes which you saw in Java ( and in C++ too) The syntax for a Structure definition:
Definition
struct name_of_structure {
type member1;
type member2;
...........................
type member n;
};
struct bez_Curve {
int order;
char description[40];
double xVert[7];
double yVert[7]
double xyData[50][50]
};
.Once the structure is defined it can be used like the type statement for the basic variables.
struct bez_Curve curve1; // you can also append curve1 after the closing braces and before the semicolon in the definition of the structure above.
If the name_of_structure is missing, it is called an anonymous structure. Variables can only be associated with the structure when it is defined
In C++ the keyword struct can be omitted and the variable of type bez_Curve can be defined as:
bez_Curve curve1;.
Accessing Members
To access the members of a structure:
curve1.order will yield the order of the curve
curve1.xVert[3] will access the fourth x - vertex
Passing Structures
Structure variables can be passed to a function using the variable name. It is passed by value. The prototype/function declaration must identify the variable as a stucture of the appropriate type.
process_data(curve1); and
void process_data(bez_Curve curve);
// here the entire structure is passed to the function
// it is possible to pass selected members
// of the structure by value
Array of Structures
A powerful way to use structures , especially with data base design, is to use an arroy of structures. For example:
#define MAX_STUDENTS 4
#define MAX_NAME 60
#define NUM_HW 8
struct EMEM899 {
char name[MAX_NAME];
double HW[NUM_HW];
double Project;
double Total;
char Grade;
};
................................
int main(void)
{ int ivar;
EMEM899 student[MAX_STUDENTS]
..........
....
}
The time has arrived for us to generate our Bezier curve. In this application we should
use a structure
use function prototypes and functions
example of a recursive function
read the order of the curve from console
read the appropriate number of vertices
generate the coefficient matrix
HW: Extend the project to
save the vertices to a file
save the xy data to another file
write a script file in Matlab to read and plot the vertex and curve
/*
// BezierCurve.cpp
//
// Bezier curve of arbitrary order
//
*/
#include <iostream.h>
#include <stdlib.h>
#include <math.h> // all functions in the library use double type
#define MAX_ORDER 6 // constants
#define MAX_POINTS 50
// the curve is defined as a structure
// the arrays have to be dimensioned so
// that the compiler needs to know
// how much memory to allot to the program
struct bez_Curve {
int order;
double xVert[MAX_ORDER + 1];
double yVert[MAX_ORDER + 1];
double xyData [MAX_POINTS][MAX_POINTS];
};
// function prototypes
double combination(double value1, double value2);
double factorial (double value);
// scope; same idea as before. Anything outside
// main has global scope
int main(int argc, char *argv[])
{ // this allows you to read comma
// seperated strings from the command line - remember
// our first program in Java
// argc is an integer giving the number
// of command line arguments + 1.
// The first is the name of the program
// *argv[] represents a pointer to
// an array of string pointers
void calcCoeff(int n, \
double A[MAX_ORDER + 1][MAX_ORDER + 1]);
// scope within main()
bez_Curve Curve1; // C++ definition of structure variable
int ivar;
double coeff[MAX_ORDER + 1][MAX_ORDER + 1];
if (argc != 2)
{ cout << "Enter an integer greater than 2 and less than 7 on the command line. \n";
exit(1);
}
// the prompt will appear and program will exit if you
// do not provide the order of the curve after typing *.exe file
// at the console
Curve1.order = atoi(argv[1]);
// the atoi() library function converts a
// string into an integer
cout << "Order of the Bezier Curve: " << Curve1.order << endl;
for (ivar = 0; ivar < Curve1.order + 1; ivar++)
{ cout << "Read vertex number " << ivar+1 << " Vertices(x,y): ";
cin >> Curve1.xVert[ivar] >> Curve1.yVert[ivar];
}
// check if it reads the information
/*for (ivar = 0; ivar < Curve1.order + 1; ivar++)
cout << Curve1.xVert[ivar] << " " << Curve1.yVert[ivar] << endl; */
calcCoeff(Curve1.order, coeff);
// prints 4 columns of coefficients for confirmaion
for (ivar = 0; ivar < Curve1.order + 1; ivar++)
cout << coeff[ivar][0] << " " << coeff[ivar][1] << " " << \
coeff[ivar][2] << " " << coeff[ivar][3] << endl;
return(0);
}
void calcCoeff(int n, double A[MAX_ORDER + 1][MAX_ORDER + 1])
{ // calculates coefficient matrix
// using combination
// remember all math functions use parameters
// of type double and return value of type double
int i, j;
for (i = 0; i <= n; i++)
for (j = 0; j <= n; j++)
A[i][j] = 0.0;
for( i = 0; i <=n; i++)
for (j = 0; j <= n - i; j++)
A[i][j] = combination((double)n, (double)j)* \
combination((double)(n - j), (double)(n - i - j)) * \
pow((double)(-1), (double)(n - i - j));
return;
}
double combination(double value1, double value2)
{ // calculates the combination of value1
// taken value2 at a time
double answer;
answer = factorial(value1)/(factorial(value2)* \
factorial(value1-value2));
return (answer);
// we could have returned tha calculation
// instead of defining a dummy variable answer
}
double factorial (double value)
{
if (value <= 1.0)
return(1.0);
else
return(value * factorial(value - 1.0));
// notice the recursive use of function
// and no dummy variables used
}
A screen shot of the application
Classes
The concept of class in C++ is the same as the one in Java. It appears that Class is a feature of OOP Languages rather than a part of any particular implementation of the paradigm. The definitionof Class in C++ has evolved from the Structure we saw in the previous section. There the Structure included different variable types. This is valid in C/C++.
In C++, Structures can also defined by including procedures. These can be accessed using the variable name with the access (::) operator. By definition all elements of the structure are public. The next stop in the evolution was to restrict access to the information in the structure. Thus a Class was born. We take a look at the class definition and there is a similarity with Java
Syntax:
/*
// A class describing a mechanical
// engineering graduate student
// The parent class keeps general data
// the derived classes keep information on courses
// in the solid option
*/
#include <iostream.h>
#include <string.h>
char newline;
class Grad_Student { //name of class
char name[60],
street[60], // member variables private by default
city[20], // public/private meaning is same
state[20], // as the one in Java
zip[10];
public:
void print_info(void); // these are only prototypes
void read_info(void); // usually functions are public
// they are usually defined outside class
// unlike Java
};
void Grad_Student::print_info( ) // notice if parameter list is empty
// void is still necessary
{
cout << "\n\n\n" ;
cout << " Name: " << name << endl;
cout << " Street:" << street << endl;
cout << " City: " << city << endl;
cout << " State: " << state << " " << zip << endl;
}
void Grad_Student::read_info( ) // defining member function outside class body
{
cout << " Enter Graduate Student Name: ";
cin.get(name,59,'\n');
cin.get(newline); // flush carriage return
cout << " Enter Street Address: ";
cin.get(street,59,'\n');
cin.get(newline);
cout << " Enter City Name: ";
cin.get(city,19,'\n');
cin.get(newline);
cout << " Enter State Name: " ;
cin.get(state, 19, '\n');
cin.get(newline);
cout << " Enter Zip Code: ";
cin.get(zip, 9, '\n');
cin.get(newline);
}
// the Solids_Option derives from Grad_Student class
class Solids_Option: public Grad_Student {
char course_1[60]; // private member variables in this class
char grade_1;
float marks_1;
public:
void enter_grade(); // member functions of Solids_Option
void display_grade();
};
void Solids_Option::enter_grade()
{
read_info(); // calling the method of parent
cout << " Enter Course Name: ";
cin.get(course_1,59,'\n');
cin.get(newline);
cout << " Enter Letter Grade for Course: ";
cin.get(grade_1);
//cin.get(newline);
cout << " Enter Course Marks : ";
cin >> marks_1;
}
void Solids_Option::display_grade()
{
print_info(); // parent method
cout << " \n\nCourse Name : " << course_1 << endl;
cout << " Letter Grade: " << grade_1 << endl;
cout << " Marks : " << marks_1 << endl;
}
int main() // the nedded main method
{
Solids_Option so; // Object so of type Solids_Option
so.enter_grade();
so.display_grade();
return(0);
}
A screen shot of the complete application:
We will now attempt to learn and use the Windows API - for using window resources. This is not easy in C++. You will appreciate Visual Basic for doing the same at the end of this segment of the course