CHAPTER 20

 

POTPOURRI (MIXED BAG)

 

 

While wrapping up this book, I found there were many concepts and topics that should have been introduced in earlier chapters but did not fit into a single chapter. These topics are introduced here as a mixed bag with a variety of flavors. Also, I want to congratulate you for getting this far and covering the many chapters. Obviously you have obtained a unique and worthwhile experience. You should be proud and put into use what you have learned. In my own experience, I have found that repetition is the key to my own learning, whether learning a programming language or a natural language like Spanish or even Chinese. 

 

 

BIT-WISE OPERATIONS

 

One power of C/C++ is the ability to perform low-level operations that are done by machine languages. These operations are performed on bits. Recall, numbers and addresses are represented in binary form internally. In many applications, especially hardware, it is desirable to work with these bits. The language of C/C++ is known as a language that works closely with hardware. Because of the importance of bit-wise operations, C/C++ chooses to use one key strike for bit-wise operators (&, |) and two strikes for the logical operators (&&, ||). The following symbols are used for the C/C++ bit-wise operations.

 

|           bit-wise or operator

&         bit-wise and operator

^          bit-wise exclusive or operator

<<        shift left operator

>>        shift right operator

~          bit complement (unary operator)

 

 

BIT-WISE OPERATIONS: EXAMPLES

 

The general form of the bit-wise or operation is variable1  | variable2 where each variable of type integer is converted to binary (bits). The bit-wise or operation of two bits is zero if both corresponding bits are zero (0), otherwise the resulting bit is one (1).

 

The general form of the bit-wise and (&) is variable1 & variable2, where each variable of type integer is converted to binary. The bit-wise and operation of two bits is one if the two corresponding bits have values of 1, otherwise the resulting bit is zero.

 

The general form of the bit-wise exclusive or (^) operation is variable1 ^ variable2, where both variables and resulting variable are of type integer and are converted to binary. The exclusive or of two bits is zero if the two bits are the same, otherwise it is one. The exclusive or is different from the bit-wise or in that the exclusive or of two bits with values 1 results to zero.

 

The & operator is often used to mask off certain bits, e.g. value & 1111111. The result sets all of the bits of the value to zero except the first 8 bits (low-order).  

 

In the following program, the binary representation for 3 is 011 and 5 is 101. The resulting bit-wise or is 111 which is 7, the resulting bit-wise and is 001 which is 1, and the resulting exclusive or is 110 which is 6.

Text Box: #include <iostream>
using namespace std;
int main(){
                int x,y,z;
                x=3; y=5;
                z=x | y;
                cout<<" BITWISE | OF TWO  VALUES IS:"<<z<<endl;
                z=x & y; 
                cout<<" BITWISE & OF TWO  VALUES IS:"<<z<<endl;
                z=x ^ y;
                cout<<" BITWISE ^ OF TWO  VALUES IS:"<<z<<endl;
              return 0;   
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

   Figure 20.1a - Program to demonstrate the bit-wise operators

 

Text Box:  BITWISE | OF TWO  VALUES IS:7
 BITWISE & OF TWO  VALUES IS:1
 BITWISE ^ OF TWO  VALUES IS:6

 

 

 

 

 

 


 

   Figure 20.1b - Output of Figure 20.1a

 

 

BIT-WISE SHIFTS: SHIFT LEFT <<, SHIFT RIGHT >>

The general form of the shift left operator is variable << n, where n is the number bits to be left shifted. As the bits are shifted left, a zero bit fills the shifted position (zero left padding). After each left shift, a 0 is added next to the least-significant bit of the binary number, which makes the number twice as large (multiply by 2). Similarly, the general form of right shift is variable >> n, where n is the number of bits to be right shifted. As the bits are right shifted, the shifted position (high-order bit) is filled with zero (zero right padding). After each right shift, the binary number looses the right bit, which is the same as dividing the number by 2. As an exercise try to shift left a negative number, including –1, or use the rotate operation to perform a circular shift by moving the lost bit to the other side. In the following program the value of 4 is left shifted by 2, resulting in a value of 16 and the value of 16 is right shifted by 1, resulting in a value of 8.

 

Additionally note that the left shift and right shift operators are overloaded in C++ for input and output, and are known as extraction and insertion (cin>>   ,  cout <<).

Text Box: #include<iostream> 
using namespace std;
int main(){
                int x =4;
                x= x << 2;
                cout<<" VALUE OF X AFTER LEFT SHIFT:"<<x<<endl;
                x = x >> 1;
                cout<<" VALUE OF X AFTER RIGHT SHIFT:"<<x<<endl;
               return 0;  }//MAIN

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.2a - Program using bit-wise shift left and shift right

Text Box: VALUE OF X AFTER LEFT SHIFT:16
VALUE OF X AFTER RIGHT SHIFT:8

 

 

 

 

 


 

                                                                                                         

  Figure 20.2b - Output of Figure 20.2a

 

COMPLEMENT OPERATOR ~
Text Box: #include<iostream>
using namespace std;
int main(){
int x=1, y=~x;
cout<<"       "<<hex<<x<<endl;
cout<<hex<<y<<endl; 
cout<<hex<<x+y<<endl;
return 0;
}//MAIN
 
 
 
 
 
 
The form of the complement operator is ~variable, where a binary bit is converted to its opposite is also known as 1’s complement using the unary operator ~ ( tild ). For example, the complement of 1 is 0 and the complement of 0 is 1. A variable of type integer is converted to its binary form and complement is applied to it.

 

 

 

 

 

 

 

 

 

 

Text Box:          1
fffffffe
ffffffff
 
Text Box: Figure 20.3a – Program to demonstrate the complement operator
 

 

 

  

 

 

 

 


 

 

Text Box: Figure 20.3b – Output of Figure 20.3a
 

 

 

 

 


 

SWAP FUNCTION USING EXCLUSIVE OR

 

If you are wondering what you can do with the bit-wise operators, here is an example that uses exclusive or to swap two values without introducing a temp variable so the program uses less memory. There are other tricks that can be done using the bit-wise operations to do certain things in an unordinary way. For example: performing multiplication by using shift left, division by using shift right, and subtraction by addition of the 2’s complement. As an exercise, encrypt/decrypt a file using an exclusive or (^). You may want to exclusive or each character with a selected ASCII character.

Text Box: #include<iostream>
using namespace std;
void swap(int &x, int &y){
            y=x^y;
            x=x^y;
            y=x^y;}//SWAP
            
int main(){
            int x=5, y=6;
            cout<<"BEFORE: "<<x<<"   "<<y<<endl;
            swap(x,y);
            cout<<"AFTER:    "<<x<<"   "<<y<<endl;
            return 0;
}//MAIN
 
 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.4a – Program using exclusive or to swap two values

 

Text Box: BEFORE: 5   6
AFTER:   6   5

 

 

 

 

 

 


 

  Figure 20.4b – Output of Figure 20.4a

 

 

COMMAND LINE ARGUMENTS

 

Until now you may have wondered why in C/C++ in the main( ) we use open and close parentheses without anything inside the parentheses. Now is time to give the reason for it. One rationale for using parentheses is that the main program is a function and therefore, it can have parameters (arguments). For example, void main( ) is a function that does not take any parameters (argument-less) and returns nothing. However, a main program can have general parameters such as int main( int argc, char* argv[ ]). This main function has two special arguments, one known as argument counter (argc) which counts the number of arguments, and argument vectors (argv[ ]) which is an array of pointers to each argument. Automatically, these arguments are set and as a programmer you can use them to your advantage.

 

 

HOW THE MAIN PROGRAM IS CALLED

 

The main program is called from the operating system environment using a command prompt (DOS or UNIX prompt). The executable file name of the main program can be used to pass the parameters. For example, copy fileA fileB to fileC. The copy command calls an executable file known as copy.exe (generated from copy.cpp) with five arguments (argc is 5 including the file name). argv[0] is pointing to copy, argv[1] points to fileA, argv[2] points to fileB, argv[3] points to the word to, and argv[4] points to fileC. It is the programmer’s job to handle these arguments (words) and treat them as intended, whether they are a file or other information. You can understand how a system programmer has built the system commands by understanding the command line arguments. In fact you can make them friendlier and customize them to suit your own taste.

 

 

SYSTEM PROGRAMMING

 

One job of a system programmer is to build the commands that become the interface between the user (operating system) and the computer while carrying out the request of the user and utilizing the computer’s resources. For example, in UNIX the command           cp fileA  fileB copies the contents of fileA to fileB. Similarly, in DOS, the prompt copy fileA fileB does the same job. A system programmer can even make the above commands friendlier by inserting the word “to” between the source file and the destination file: copy fileA to fileB. If you understand the command line arguments, then you can build your own commands and customize them. You can make your own command-line calculator (e.g. add 2 + 3) or you can create generic searches (e.g. search tel Ebrahimi). The following program demonstrates a sample command line program for a copy command:

Text Box: #include<iostream>
#include<fstream>
using namespace std;
int main(int argc, char* argv[]){
        if(argc<4)
                cout<<"TOO FEW PARAMETERS";
        else{
        ifstream fin(argv[1],ios::in);
        ofstream fout(argv[3],ios::out);
        char c;
        while(fin>>c){
        fout<<c;}//WHILE
        fout.close();
        fin.close(); }//ELSE
        return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 


 

 

Figure 20.5a – Program demonstrating command-line arguments

Text Box: copy fileA to fileB

 

 

 


 

               

    Figure 20.5b – Output of Figure 20.5a

                       

 

Text Box: ABCDEF

 

Text Box: ABCDEF

 

                

 

 

 

   Figure 20.5c -  fileA                   Figure 20.5d -  fileB

           

 

 

 

This program copies the contents of one file, character by character, to another file. The above program is named copy.cpp. To create the copy command, you must compile the program with the line g++ -o copy copy.cpp; this sends the executable code to the copy command. To run this copy program, at the prompt type: copy fileA to fileB.

 

 

RUN TIME TYPE ID (RTTI)

 

In C++, the run time type information feature is supported by the typeid operator, which determines the type of a variable during run time. To use this feature you must include the header #include <typeinfo>.

 

With the use of the typeid operator, two objects can be compared to determine if they are of the same type or not. One reason to use typeid is to figure out the type of object during run time and cast (convert) it if necessary.  

Text Box: #include<typeinfo>
#include <iostream>
using namespace std;
int main(){
            double pi=3.14159;
            cout<<"TYPE OF VARIABLE IS: "<<typeid(pi).name()<<endl;
            if(typeid(pi).name() == typeid(double).name())
                        cout<<"THEY ARE SAME TYPE"<<endl;
            return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 


 

   Figure 20.6a – Program using the typeid operator

 

Text Box: TYPE OF VARIABLE IS: double
THEY ARE SAME TYPE

 

 

 

 

 


 

   Figure 20.6b – Output of Figure 20.6a

 

 

TYPE CONVERSION: CASTING, DYNAMIC CASTING, REINTERPRET

 

A type can be converted legally, implicitly or explicitly, to another type. A type can be converted implicitly through assignment, one type to another, as long as the smaller type is assigned to the larger type to avoid loss of precision. A type can be converted explicitly by the use of an operator, known as a cast operator. The general form is  (type) variable.

For example, the function sqrt( x ) takes double as its argument, therefore for an integer value, it is necessary to convert the int type to double by casting it with the following: sqrt( (double) x). Note that the value of the variable is passed as a double, but the value of variable x does not change.

 

Other than the C-style type casting, there are four more casting techniques in C++. In addition to casting the basic data types, the pointer type and user-defined types (classes) can be cast. The four different castings have a similar form:

static_cast <newtype> (expression) and are explained below.

 

reinterpret_cast: is mainly used for casting with a pointer, such as casting one pointer type to another pointer type or a pointer type to a non-pointer (e.g. int) type or vice versa.

static_cast: is like C-style casting  e.g. converting double to int.

const_cast: is for constant casting and takes away the const casting.

dynamic_cast: inspects the variable (object) type at run time and returns a valid pointer if the object is of the expected type or a null pointer if the object is not of the expected type. The dynamic _cast is mainly used in situations where the correctness of the type conversion cannot be determined during compile time.

Text Box: #include <iostream>
using namespace std;
int main(){
            int myint;
            double mydoub = 876.54;
            myint=(int)mydoub;
            cout<<"C-STYLE CASTING:"<<myint<<endl;
            myint=static_cast <int> (mydoub);
            cout<<"STATIC CASTING:"<<myint<<endl;
            return 0;           
}//MAIN

 

 

 

 

 

 

 

 


 

  Figure 20.7a – Program to illustrate C-Style and Static Casting             

Text Box: C-STYLE CASTING:876
STATIC CASTING:876

 

  Figure 20.7b – Output of Figure 20.7a

MULTIPLE FILE PROGRAM AND SEPARATE COMPILATION

A big program can be broken into separate units: functions, modules, or even header file(s). Each of these units can be written in separate files, which can be compiled separately and linked together at a later time. There are many advantages to multiple-file programs and separate compilation; some advantages are: localizing error handling at an early stage, teamwork, reusability, and better organization.  In a Linux environment, the command will compile the taxrate and overtime units:

g++ –c  taxrate.cpp overtimepay.cpp

Similarly, the following command links a set of independent files that are compiled separately: 

g++ -o  taxrate.o overtimepay.o main.cpp

 

 

 

HEADER FILES: MAKING YOUR OWN INCLUDE

 

As a program becomes larger, it is recommended to divide the program into modules and parts and keep them in separate files, rather than having them all in one file. However, these files may need to access some common variables as well as functions (prototypes) and can be saved under a name with the extension .h that can be used as a header file. One advantage is, rather than repeating the same information, we can simply include the file on top with the only difference that instead of angle brackets we use double quotations. Another advantage of header files is that any change or update in the header file is visible to others.

 

For example, for a sort program that reads data and prints the unsorted and sorted data, we can use the following common code that is saved under a file called sort.h.   

 

#define MAXSIZE  10

#include <iostream>

#include <fstream>

#include <ctype>

using namespace std;

double lst[MAXSIZE];

void printlist(double lst[]);

 

The following sort main program resides in a source file named sort.cpp and uses two header files; the header file sort.h and process.h are created for the function’s definitions.

 

#include “sort.h”

#include “process.h”

main(){

}//MAIN SORT.CPP

 

The following functions for the sort program are kept in another header file known as process.h. Remember that this header file uses the previously created header file as shown below.

#include “sort.h”

void readdatat(){       }

void printdata(){       }

int findlocmin(){       }

 

 

A const FUNCTION

 

A function can be declared as a constant (const) by providing the keyword const after the argument list (after parentheses) in the function declaration as well as in the function definition.

 

A constant function does not modify its implicit arguments. Note that the implicit arguments are those that are accessible by this pointer. An example of a const member function is the const accessor function because its job is simply to access the member data of a class and not to modify it. Defining a function as const prevents the object (variable) from accidental or deliberate change. 

Text Box: #include<iostream>
using namespace std;
class employee{
            double salary;
public:
            double getsalary() const{
                        return salary;}
            void setsalary(double amount){
                        salary=amount;}
            void printsalary() const{
                        cout<<"SALARY: "<<salary<<endl;}
};//EMPLOYEE
int main(){
            employee ebrahimi;
            ebrahimi.setsalary(1000.00);
            ebrahimi.printsalary();
            double bonus=500.00;
            cout<<"SALARY WITH BONUS: ";
            cout<<ebrahimi.getsalary()+bonus;
            return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.8a – Program utilizing a const function

Text Box: SALARY: 1000
SALARY WITH BONUS: 1500

 

 

 

 


 

  Figure 20.8b – Output of Figure 20.8a

 

In this program, the function declaration and definition are in the same place.  The format for the function declaration of a constant function is as follows:

double getsalary( ) const;.

In this program, both getsalary( ) and printsalary( ) are constant functions and hence, they do not modify the object. If you try to change salary in either one of these member functions, the compiler gives an error message. For example, adding the line: salary=salary+500; to the getsalary( ) function would cause the compiler to give the following error message:

“l-value specifies const object”.

 

 

 

 

 

ENUMERATION DATA TYPE: enum

 

The word enum stands for enumeration; this is another integral data type, like boolean. The data type enum can have more than two values, in contrast to bool which has only two values, false and true (0 and 1). For example, a weekday enum data type can have five values: mon, tue, wed, thur, and fri. Similarly, a weekend enum type can have two values: sat and sun. By using the enumerated word instead of an integer constant, the program becomes more readable. By setting an enumerator to a value, the rest of the enumerators will increase by 1. You can engage the enumerator in an equality test, assignment, or use it as a loop control variable. By default the enumerator value starts at zero.

enum wdays {mon=1, tue, wed, thur, fri, sat, sun};

wdays  weekdays, weekend;

enum colors {red, green, blue};

 

Caution: the names used in enumeration must be C++ legal names and not a literal or number, although the names can hold these values.

 

enum monthofyear {Jan=1,Feb,Mar, Apr, May, Jun, July, Aug, Sep, Oct,   Nov, Dec};

monthofyear month;

 

ENUMERATION EXAMPLE: NUMBER OF DAYS PASSED SO FAR IN YEAR

 

The following program computes the number of days passed in the year by providing the month and the day. The program uses two enumeration data types: one to determine the name of the month and one to find the number of days in each month. Two functions return enumeration types. Note that the starting value of the enumeration list is 0 and it is incremented by 1 each time. However, another initialization can be specified and the increment remains at one. Also note that enumeration values are constant and cannot be changed so they cannot be incremented and therefore cannot be used in a loop to go through a range. For example, you cannot use the enumerated type month++. However, some implementations, such as Borland Turbo C++ will run the above with warning. One solution for the loop is to cast the increment to its enumerated type.       

month=monthofyear(month+1); //or

month= (monthofyear) month+1;

 

Despite the limited capabilities of enumeration as a defined type, use of enumeration contributes to program readability; but some have reservations that it makes the program larger with redundant effort. For your own exercise, try to expand this program to consider the leap years and include a function that takes an enumeration type as a parameter.


 

 

Text Box: #include<iostream>
using namespace std;
enum months {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec, ERROR=0};
enum daysinmonth {daysinJan=31, daysinFeb=28, daysinMar=31, daysinApr=30,         daysinMay=31, daysinJun=30, daysinJul=31, daysinAug=31, daysinSep=30, daysinOct=31, daysinNov=30, daysinDec=31, DAYSERROR=0};
            months getmonth(int monthnumber){
                        switch(monthnumber){
                        case 1: return Jan; case 2: return Feb; case 3: return Mar;
                        case 4: return Apr; case 5: return May; case 6: return Jun;
                        case 7: return Jul; case 8: return Aug; case 9: return Sep;
                        case 10: return Oct; case 11: return Nov; case 12: return Dec;
                        default: return ERROR;}//SWITCH
                        }//GETMONTH
            daysinmonth getdays(int monthofyear){
            switch(monthofyear){
                        case 1: return daysinJan; case 2: return daysinFeb;
                        case 3: return daysinMar; case 4: return daysinApr;
                        case 5: return daysinMay; case 6: return daysinJun;
                        case 7: return daysinJul; case 8: return daysinAug;
                        case 9: return daysinSep; case 10: return daysinOct;
                        case 11: return daysinNov; case 12: return daysinDec;
                        default: return DAYSERROR; }//SWITCH
                        }//GETDAYS
int main(){
            months calendar; //enum TYPE
            daysinmonth daysofcurrentmonth; //enum TYPE
            int monthofyear, dayofmonth, dayspast=0;
            cout<<"ENTER AN INTEGER FOR THE MONTH: ";
            cin>>monthofyear;
            cout<<"ENTER AN INTEGER FOR THE DAY: ";
            cin>>dayofmonth;
            calendar=getmonth(monthofyear);
            daysofcurrentmonth=getdays(monthofyear);
            do{      switch(calendar){
                        case Jan: case Mar: case May:
                        case Jul: case Aug:       case Oct:
                        case Dec: dayspast+=31; break;
                        case Feb: dayspast+=28; break;
                        case Apr: case Jun: case Sep:
                        case Nov: dayspast+=30;break;     }//SWITCH
                        monthofyear--;
                        calendar=getmonth(monthofyear); }while(calendar>=Jan);
                        dayspast=dayspast-daysofcurrentmonth+dayofmonth;
                                cout<<"NUMBER OF DAYS PAST IN YEAR SO FAR: "<<dayspast;    
               return 0;
}   //MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.9a – Example of enumeration

 

 

Text Box: ENTER AN INTEGER FOR THE MONTH: 4
ENTER AN INTEGER FOR THE DAY: 16
NUMBER OF DAYS PAST IN YEAR SO FAR: 106

 

 

 

 

 

 


 

  Figure 20.9b – Output of Figure 20.a

 

 

PROGRAM NAMING CONVENTIONS AND STYLES: IDENTIFIERS

The names that are used in a program such as keywords and user-defined words are known as identifiers. C/C++ is case sensitive, which means that a lower case name is not the same as an upper case name. C/C++ is designed in favor of lower case letters with the representation of keywords and libraries in lower case letters. Besides the reserved words, it is up to you to choose any combination of styles or any convention that you like. But be consistent and not misleading by choosing improper names. Try to choose names that are related to their purpose and do not choose names that can be easily confused with each other. Try to use short names for indices. The following illustrates some naming conventions that you can use in your program. For example, the beginning of a word is capitalized, as in Counter or HourlyRate. The beginning of a first word may be lower case but the beginning of the following word is upper case as in hourlyRate. Underscores may be used between words, as in hourly_rate. Many programmers personalize words by adding the prefix my to words such as in mystack and mysalary. For example, the word delete is a reserved word and cannot be used, so you may want to use mydelete instead. To distinguish a class name from its object name, the prefix the is added before the class name in the object name. For example, with a class named stack, the object name thestack is used. For an array’s index or a loop control variable, a single letter such as i, j, k, m, or n is used. Historically, (in Fortran) these names represented integer values by default (I through N). As a result of some of the language naming restrictions, programmers adjust their programs accordingly; for example, by spelling count as kount. Interestingly, the language Basic started with one letter identifiers or one letter with one digit identifiers. Many languages limit identifiers to 4 to 6 characters, which caused a lot of problems because some compilers ignored additional characters and that also caused a new problem. Now character limit does not play a role, in fact C/C++ can have identifiers 31 characters long. Do you have an opinion? The assembly language uses mnemonic symbols such as ST for store. Blank spaces are not permitted in identifiers. Do you think it would be better to have blanks within an identifier? What would be the pros and cons of having identifiers with embedded blank spaces?

Try to not use the letter l (el) as a name since it looks like numeric 1.

 

 

PROGRAMMING CONVENTIONS USED IN THIS BOOK

 

I tried the following conventions with my novice programmers and I found better results compared to other conventions. However, you may build a convention that is even better than this. I taught programmers to stick with the convention in the beginning unless they have a reason not to. In programs I mainly use lower case letters, without even using an underscore to separate words, to avoid confusion. I left out comments on purpose so the learner can focus on the code and get to know it and not loose track, rather than hiding the code inside comments. The end of each block whether an if, loop, function, or main is commented with the word itself in capital letters (e.g. //MAIN). Display messages are in upper case (e.g. cout<<”HELLO”). In this book I stayed away from lengthy programs, and tried to fit them onto two or a maximum of three pages. I believe it is hard for learners to follow a large program when having to page back and forth.  

 

 

NAMESPACE

 

C++ is a growing language and the latest extension of the Standard Template Library (STL) makes C++ larger than ever. In a program, it is possible that you are using names for classes, variables, or functions that are the same. To solve the problem of name clashes, a new extension to the language known as the namespace feature, was created.   C++ has placed almost all the standard library names under a namespace called std and allows others to create their own namespaces. You can create your own namespaces as well or use names from other namespaces. For beginner programmers, the concept of namespace is troublesome and the reason behind it is not understood. It is one of those “wait until later” subjects. For example, in one library, the identifier find means one thing and in another library it may mean something else. A namespace is an additional feature that was added to C++ that is used to create a scope (space) for names. By having a namespace, an identifier has its own boundary. Therefore, the same name can be used in two different namespaces without any problem or confusion for the compiler or the programmer. In fact, those who worked with older compilers and are now working with new compilers realize two major changes right away; a header directive without .h, and the statement:

            using namespace std;

 

The above statement tells your program that you are using the standard namespace where most routines come from and makes std the default namespace of your program. An alternative to this statement is to mention the namespace for only names that are used in the program such as:

std::cin;          std::cout;        std::endl;

 

Some beginner programmers feel that including namespace in a program is a redundant action and the benefits of namespaces will not be realized until later. They prefer to use the old style headers without using namespaces. Let us put it this way, the use of namespace becomes necessary especially when you are using STL and strings. Note that building a string from the library <string.h> is different than building a string from the library <string > class.

 

 

 

 

 

MAKING YOUR OWN namespace

 

Creating a namespace is similar to making a class, however, several classes and functions can become members of a namespace. The general form of a namespace is shown below. Caution: do not place a semicolon after the closing brace of the namespace block; it is not needed as in a class.

namespace mynames {

//class

//template

//function

//variable declaration

}//NAMESPACE

 

By adding a directive, all those names in the namespace are available for use.

Every statement that uses a namespace component must specify the namespace such as:    mynamespace::vector; 

 

Note that the name vector is used both in STL and the above namespace but there is no name collision. Additionally, namespaces can be nested so that we can create packages or similar namespaces.

 

The following program creates two namespaces called oldproject and newproject. Note that the two namespaces are able to use the same name for values and functions.

Text Box: namespace oldproject {
class payroll {
                double basesalary;
public:
payroll (){basesalary=100000.00;}
findsalary(){return basesalary; };
 }; //CLASS PAYROLL
}//NAMESPACE
   namespace newproject {
class payroll {
double basesalary;
public:
payroll (){basesalary=100000.00;}
findsalary(){return basesalary; };
}; //CLASS PAYROLL
}//NAMESPACE
#include<iostream>
using namespace std;
int main(){
oldproject::payroll ebrahimi;
newproject::payroll johndoe;
if (ebrahimi.findsalary()== johndoe.findsalary() )
         cout<<"SAME SALARY"<<endl;
return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.10a – Program demonstrating how to create and use namespaces

Text Box: SAME SALARY

 

 

 

 

 


 

  Figure 20.10b – Output of Figure 20.10a

 

Alternatively, the main program can use one of the namespaces without specifying the prefix each time:

 

main(){

using namespace newproject;

if (findsalary()==oldproject::findsalary())

cout<<”NO PROMOTION HAS HAPPENED ”

}//MAIN

 

 

typedef

 

The keyword typedef stands for type definition and is used to create a synonym (alias) for an existing type. In fact, typedef is more like giving a nickname (shorthand) to a long and complicated type such as a type containing pointers, structures, and classes. After creating the type, you can use the synonym name given. The general form of typedef is to use the keyword typedef followed by the existing type and newname, where the existing type is a C/C++ defined type and newname is a given nickname.

            typedef existingtype newname;

 

The following illustrates using the typedef keyword by adding a new name ULI for an existing type.  The use of typedef enhances program readability.

typedef unsigned long int ULI

ULI  x;

 

A side note: the use of typedef was more common in C, especially when defining a struct with a tag name. The use of classes in C++ made typedef less popular. The following shows how typedef is used to simplify a self-referential structure double linked list (dynamic).

typedef  struct nodetag *dlistptr; 

typedef struct nodetag {

                        char info[20];

                        dlistptr  next;

                        dlistptr  prvious; } dlistnode;

 

Without the use of typedef the double linked list would be represented accordingly.

struct nodetag {

char info[20];

struct nodetag *next;

struct nodetag *previous; };

 

struct nodetag *dlistnode;

 

In a C-style struct, the tag name is used to declare a variable. In C++, the use of struct tag names is obsolete.

One last note: with the keyword typedef, do not confuse its syntax and semantics with the directive  #define.    

 

 

PREPROCESSOR DIRECTIVES

 

A preprocessor is part of a C/C++ program that processes before the compiler takes charge, as the name preprocessor suggests. There are approximately ten directives of which the #include and #define are the most popular. Other directives such as #ifndef, #else, and #undef are mainly used to compile a program in some conditional way. However, with the preprocessor, there are some tokens (names) that hold some information such as _DATE, _TIME for date and time of compilation respectively.   

 

 

#define AS LITERAL (CONSTANT) SUBSTITUTION

 

The #define directive is a macro with the following general form:

#define macroname substitution

 

#define is used to substitute a name with its character sequence. Many constant values are given a name with #define. For example, #define PI 3.14159 means that in a problem, whenever PI is encountered, PI will be substituted with the value of 3.14159. Before the keyword const was introduced in C/C++, #define was used instead. In fact, many symbolic names such as EOF and NULL are defined by #define.

#define EOF    -1

#define NULL   ‘\0’

 

There is no need to end the #define with a semicolon (;), the #define directive will end when a new line (enter key) is pressed.  When there is a need for continuation on the line, a backslash (\) is used.

Text Box: #define CHORUS  "Twinkle Twinkle Little Star, How I\
 Wonder What You Are."
#include <iostream>
using namespace std;
int main() {
cout<<"SING "<<CHORUS<<endl;
cout<<CHORUS<<endl;
return 0;
}//MAIN
 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.11a – Program using the #define directive

 

 

 

 

Text Box: SING Twinkle Twinkle Little Star, How I Wonder What You Are.
Twinkle Twinkle Little Star, How I Wonder What You Are.
 

 

 

 

 

 

 


 

 Figure 20.11b – Output of Figure 20.11a

 

MACRO AS A FUNCTION

 

With the use of #define, you will be able to define macros which are like functions, but it is done by substitutions rather than function calls. One advantage of a macro over a function is that you do not have the function overhead, such as pushing the variable onto a stack or keeping track of addresses (return address). For a small number of tasks, a macro is recommended. In assembly language, macros play a larger role. Macros are used in C; but, due to the purpose of type checking, macros are not recommended for use in C++.

For example, in the following program, a macro determines the maximum of two numbers using the directive #define. As an exercise, write a macro called SQUARE (x) to compute the square of x; then write a function to do the same. The extra parentheses are used to guarantee no mix up in substitution. 

Text Box: #define FINDMAX(x, y)    ( ( x  > y ) ? x : y )
#include <iostream>
using namespace std;
int main() {
int x = 5;
int y = 8;
cout << "THE MAXIMUM IS " << FINDMAX (x, y) <<endl;
return 0; }//main

 

 

 

 

 

 

 

 

 

 

 


 

 

Figure 20.12a – Program demonstrating the use of a macro

 

 

Text Box: THE MAXIMUM IS 8

 

 

 

 

 


 

  Figure 20.12b – Output of Figure 20.12a

 

 

CONDITIONAL DIRECTIVE

 

A conditional directive is used to prevent multiple copies and processing of the same header file. The general form for a conditional directive is shown below.

#ifndef  MYFILE_H

#define MYFILE_H

#endif

 

The above code tests if myfile.h is defined (included) previously; if not, it will be included. In other words, when #ifndef is true, the code after it is included and processed; otherwise, the code between #ifndef and #endif is ignored.

 

 

#include <ctime>  TIME AND DATE

 

The header <ctime> contains functions and types that are used to manipulate and determine the time and date. Time and date are important topics that should be integrated into every large program to keep track of events such as scheduling, appointments, time driven reports, time duration, execution time, analysis, and simulation. In fact, many computer viruses are time driven; therefore knowledge of time will help you understand how these viruses function and to some extent how to try to combat them.

In header <time.h> there are three different ways time is stored, each with a different purpose and format, as described below:

 

time_t:  a calendar time including time and date.

struct tm t:  a time and date is a structure which is broken into several members such as tm_sec, tm_min, tm_hour, tm_year, etc..

clock_t: a time value used for elapsed time (duration) which is measured in clock ticks. The function clock_t clock( ) returns the time since execution. In order to get the time in seconds you must use clock( ) / CLOCKS_PER_SEC.  

time_t and clock_t: are arithmetic types while struct tm holds each component of time and date known as calendar time.

 

We are going to divide the time functions into two divisions of time manipulation and time conversions.

As an example, the function time(NULL) is used in the function srand(time(NULL))  to seed a random number generator so that whenever the function rand( ) runs, the same series of numbers is not generated.

 

 

struct tm TIME COMPONENTS 

 

The members of struct tm hold components of time and calendar date, each of which are of type integer. The time members are: tm_sec includes seconds (0, 61?), tm_min includes minutes (0, 59), and tm_hour includes hours (0, 23). The date members are: tm_mday includes the month’s day (1, 31), tm_mon includes months (0, 11), and tm_year includes years (since 1900). Other day components are: tm_wday includes days since Sunday (0, 6) and tm_yday includes days since January 1 (0, 365). In addition, tm_isdst includes a Daylight Saving Time flag component  (0 no effect, >0  in effect, -1 not applied).

    

 

TIME IT TAKES TO RESPOND

 

The following program computes the amount of time from when the user is prompted to enter the name until the name is entered. The two variables begin and end are declared as  type time_t and their addresses are passed to the function time(&varname) so that the number of computed seconds is stored and brought back. Note that time( ) can be used to compute elapsed time for algorithm analysis. As an exercise, extend this program to limit the response time such as waiting for only 10 seconds.

Text Box: #include<iostream>
#include<ctime>
using namespace std;
int main(){
            char name[20];
            time_t begin, end;
            time(&begin);
            cout<<"NUMBER OF SECONDS ELAPSED SINCE JAN 1, 1970! "<<begin<<endl;
            cout<<"HELLO, WHAT IS YOUR NAME? "<<endl;
            cin>>name;
            time(&end);
            cout<<end<<endl;
            cout<<"TIME ELAPSED FOR "<<name<<"'S RESPONSE: "<<end-begin<<” SECONDS”<<endl;
              return 0;         
}//MAIN
 
 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.13a – Program showing uses for time.h

 

Text Box: NUMBER OF SECONDS ELAPSED SINCE JAN 1, 1970! 1024338710
HELLO, WHAT IS YOUR NAME?
Ebrahimi
1024338719
TIME ELAPSED FOR Ebrahimi'S RESPONSE: 9 SECONDS

 

 

 

 

 


 

Figure 20.13b – Output of Figure 20.13a

 

STRING TIME VERSUS STRUCTURE TIME

 

The function time( ) brings the number of seconds that have elapsed since midnight January 1, 1970 (Unix Epoch Milestone). Conversion functions are used to format the time differently. For example, the function ctime(&varname) will return a string representing the full date and time. Similarly, the function localtime(&varname) returns a structure of type tm where each member holds the appropriate time and date information such as tm_sec, tm_min, tm_hour, tm_year, etc.. ). Additionally, the function asctime(structime) converts the structure time to the same form as ctime(  ). Note that tm_year gives the number of years since 1900 (starting calendar time, January 1 is Sunday). The year 1900 is added to get the current year.

 

 

 

Text Box: #include<iostream>
#include<ctime>
using namespace std;
int main(){
            time_t timenow;
            time(&timenow);
            cout<<ctime(&timenow)<<endl;//CONVERT TIME
             struct tm *timestruct;
            timestruct=localtime(&timenow);
            cout<<timestruct->tm_wday<<" "<<timestruct->tm_mon<<" "<<timestruct->tm_mday<<" ";
            cout<<timestruct->tm_hour<<":"<<timestruct->tm_min<<":"<<timestruct->tm_sec<<" ";
            cout<<timestruct->tm_year+1900<<endl<<endl;
             cout<<asctime(timestruct);
             return 0;          
}//MAIN
 

 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.14a – Program using time( ), ctime( ), localtime( ), and asctime( )

 

Text Box: Mon Jun 17 17:55:56 2002
 
1 5 17 17:55:56 2002
 
Mon Jun 17 17:55:56 2002

 

 

 

 

 

 

 

 

 

Figure 20.14b – Output of Figure 20.14a

 

 

 

VARIABLE STORAGE SPECIFIER: auto, static, register, and extern

 

A storage class specifies where a variable (object) should be stored and determines its visibility and its duration. There are four major storage specifiers that are used for storage class: auto, extern, static, and register. Do not confuse the word storage class (categorization) with the object-oriented class. An auto (automatic) variable is a local variable in a program (or function) that comes into existence when the program is executed or when a function is called, and ceases to exist when the program is finished or the function is returned. An auto variable does not retain its value as it comes into existence once again. Automatically, a variable is of type auto storage upon its declaration. However, you can explicitly define a variable an auto by prefixing the declaration with the keyword auto as shown here:  auto int x;

 

 

 

 

 

Text Box: #include <iostream>
using namespace std;
void testauto( ); //PROTOTYPE
int main(){
auto int x=5;
cout<<x<<endl;
testauto();
              return 0;
}//MAIN
void testauto(){ 
int y=6;
y++;
cout<<y<<endl;
}//TESTAUTO

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

Text Box: 5
7

 

  Figure 20.15a – Program to test the keyword auto

 

 

  Figure 20.15b – Output of Figure 20.15a

 

An external variable is a variable that is defined outside of a main program (or any function). Other functions can access an external variable by prefixing the keyword extern in a variable declaration. External variables are globally accessible, and hence, can be used instead of parameter passing and return values when communicating with functions. I have found that beginner programmers prefer to use external variables to make the program work and then convert the program to use parameters. Note that external variables have their own side effects.

Text Box: #include <iostream>
using namespace std;
void testextern( ); //PROTOTYPE
 int x=5;   //x IS EXTERNAL  
 int main(){
cout<<x<<endl;
testextern();
return 0;
}//MAIN
void testextern(){ 
extern int x;  //OPTIONAL
x++;
cout<<x<<endl;
}//TESTEXTERN

 

 

 

 

 

 

 

 

 


 

  Figure 20.16a – Program using an external variable

Text Box: 5
6

 

 

 

 


 

  Figure 20.16b – Output of Figure 20.16a

 

Let me conclude this topic by stating that, we often talk about variable declaration but forget to mention the place (memory) where the variable is created or assigned storage.  Declaration and definition of a variable are different, in declaration no storage is allocated.

 

A static variable is a kind of variable that retains its value upon the existence of the variable. Therefore, static local variables, in contrast to auto variables, retain their values from one function call to another. One should not confuse a static variable with a static member variable of a class, and the concept of static memory allocation versus dynamic allocation. A static variable can act as a limited external variable by defining it outside the functions (visible to several functions) or it can act as an extended local variable by defining it inside the function (retaining its value).  

Text Box: #include <iostream>
using namespace std;
void teststatic( ); //PROTOTYPE
int main(){
static int x=5;
cout<<x<<endl;
teststatic();
return 0;
}//MAIN
void teststatic(){ 
static int y=6;
y++;
cout<<y<<endl;
}//TESTSTATIC

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.17a – Program using a static variable

 

Text Box: 5
7

 

 

 

 

 


 

  Figure 20.17b – Output of Figure 20.17a

 

 

 

register VARIABLES:

 

A variable can be declared as a register by prefixing the keyword register to its usual declaration. A register variable uses the computer’s register instead of regular memory. It is a good idea to declare the most frequent variables as register. The usage of a register’s variable makes the program faster and smaller, since a register resides within the CPU, but it is up to a compiler to grant the request.

 

 

 

Text Box: #include <iostream>
using namespace std;
void testregister( ); //PROTOTYPE
int main(){
register int x=5;
cout<<x<<endl;
testregister();
              return 0;
}//MAIN
void testregister(){ register int y=6;
y++;
cout<<y<<endl;
}//TESTREGISTER

 

 

 

 

 

 

 


 

Figure 20.18a – Program using a register variable

Text Box: 5
7

 

 

 

 

 


 

Figure 20.18b – Output of Figure 20.18a

 

 

mutable DATA MEMBERS VERSUS const

 

The keyword mutable allows a const member function to modify a data member. For example, by declaring a data member mutable, a const member function can change that member data. Note that a constant member function cannot change the invoking object data member. An alternative to mutable would be to cast away the const by using

const_cast <  >.

Text Box: class muty {
mutable int m;
public:
update (int x) const { m= x+1; }//UPDATE
getm( )const {return m;}//GETX
};   //CLASS MUTY    
#include <iostream>
using namespace std;
int main(){
muty  objm;
objm.update(5);
cout<<objm.getm()<<endl;
              return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.19a – Program demonstrating use of a mutable data menber

Text Box: 6

 

 

 


 

           

 

  Figure 20.19b – Output of Figure 20.19a

 

 

 

 

 

CLASS HIERARCHICAL RELATIONSHIP: Has-A VERSUS Is-A

 

A relationship between two classes can be categorized as a Has-A or Is-A Relationship.

A relationship is categorized as Has-A when a class contains (composes) one or more classes. Has-A relationship is known as composition or nested class (structure). An example to explain the Has-A relationship is if there are two classes, and one is tree and one is leaf; in this case the tree has a leaf. To describe the Is-A relationship, an apple tree is a tree (apple tree class is derived from tree class). There are other kinds of relationships such as Uses-A and others that we are not concerned with at the moment. In this program, the class date is composed in the class employee (Has-A). For simplicity, the data members of the date class are public so the main program can access them easily. As an exercise, modify the program to include constructors and set the data members to private; you can also create a separate file and an include directive. Note that hiringdate is an object of the class date.

Text Box: #include<iostream>
using namespace std;
class date{
public: int year;
            int month;
            int day; };//DATE
class employee {
private: double salary;
public: date hiringdate;
            double getsalary(){return salary;}
            void setsalary(double amount){salary=amount;}};//EMPLOYEE
int main(){
            employee ebr;
            ebr.hiringdate.year=1983;
            ebr.hiringdate.month=1;
            ebr.hiringdate.day=23;
            ebr.setsalary(99999.99);
            cout<<"SALARY: "<<ebr.getsalary()<<endl;
            cout<<"HIRING DATE: "<<ebr.hiringdate.month<<"/"<<ebr.hiringdate.day;
            cout<<"/"<<ebr.hiringdate.year<<endl;
return 0;           
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.20a – Program illustrating the Has-A relationship

Text Box: SALARY: 100000
HIRING DATE: 1/23/1983

 

 

 

 


 

  Figure 20.20b – Output of Figure 20.20a

 

IS-A RELATIONSHIP: PROGRAM

IS-A relationship is when a class is derived from another class. The following program demonstrates an Is-A relationship between two classes; person is the base class that consists of general information and the class employee is a derived class (specialized) that inherits from the person class. As an exercise, modify the program to change the data members to protected, and possibly to explore multiple inheritance instead of single inheritance. An example of multiple inheritance is if a student employee is derived from the class student and the class employee.

Text Box: #include<iostream>
#include<string>
using namespace std;
class person{
public: string firstname;
            string lastname;};//PERSON
class date{
public: int year;
            int month;
            int day; };//DATE
class employee: public person{
private: double salary;
public: date hiringdate;
            double getsalary(){return salary;}
            void setsalary(double amount){salary=amount;}};//EMPLOYEE
int main(){
            employee ebr;
            ebr.firstname="Alireza";
            ebr.lastname="Ebrahimi";
            ebr.hiringdate.year=1983;
            ebr.hiringdate.month=1;
            ebr.hiringdate.day=23;
            ebr.setsalary(99999.99);
            cout<<ebr.firstname<<" "<<ebr.lastname<<endl;
            cout<<"SALARY: "<<ebr.getsalary()<<endl;
            cout<<"HIRING DATE: "<<ebr.hiringdate.month<<"/"<<ebr.hiringdate.day;
            cout<<"/"<<ebr.hiringdate.year<<endl;
return 0;           
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.21a – Program illustrating the Is-A relationship

 

Text Box: Alireza Ebrahimi
SALARY: 100000
HIRING DATE: 1/23/1983

 

 

 

 

 

 

 


 

Figure 20.21b – Output of Figure 20.21a

 

FRIEND FUNCTION

 

A friend function can access the member functions of a class without being a member of the class.  Access to a class member is granted to a friend function as if it were a member function. You may wonder why we need a friend. One option to not having friend functions is to make the members public so that a function can access them, but making the data members public omits the idea of information hiding (abstraction). Note that the goal of OO is to separate the implementation from the interface as much as possible.  If you have too many friend functions that are accessing your class’s private members, you may want to redesign your class.

 

The use of the keyword friend in the function prototype before the function name makes the function a friend of the class, and there is no need to mention the keyword in the function definition.

 

 

A FRIEND FUNCTION: PROGRAM

 

The following program illustrates the use of a friend function addbonus( ) in the class employee. The function addbonus( ) is not a member of the employee class, but has the same access rights as a member.

Text Box: #include<iostream>
using namespace std;
class employee{
            friend void addbonus(employee &, double);
public:
            employee(double amt){salary=amt;}
            double getsalary() const{return salary;}
private:
            double salary;
            }; //EMPLOYEE
void addbonus(employee &emp, double bonus){
            emp.salary =emp.salary + bonus;}
int main(){
             employee ebrahimi(99999.00);
             cout<<"ORIGINAL SALARY: "<<ebrahimi.getsalary()<<endl;
             addbonus(ebrahimi,1000.00) ;
             cout<<"NEW SALARY: "<<ebrahimi.getsalary()<<endl;
return 0;
}//MAIN
 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.22a – Program with a friend function

 

Text Box: ORIGINAL SALARY: 99999
NEW SALARY: 100999

 

 

 

 

 


 

  Figure 20.22b – Output of Figure 20.22a

 

FRIEND FUNCTION: USED FOR OVERLOADING OPERATORS

One usage of a friend function is to use it with the overloading insertion (<<) operator. An operator overloading function must be a friend function since the object is passed to the function instead of being an invoking object. The way that operator overloading works is that the function carries two parameters, one is a reference to the stream and one

is a reference to the object. This allows you to customize a print function. For example, all the members of an object can be printed at once instead of one by one.

Text Box: #include<iostream>
#include<string.h>
using namespace std;
class person{
public: char firstname[20];
            char lastname[20];};//PERSON
class date{
public: int year;
            int month;
            int day; };//DATE
class employee: public person{
private: double salary;
public: date hiringdate;
            double getsalary(){return salary;}
            void setsalary(double amount){salary=amount;}
            friend ostream &operator<<( ostream & output, const employee &emp);
            };//EMPLOYEE
ostream &operator<<( ostream & output, const employee &emp){
            output<<emp.firstname<<" "<<emp.lastname<<endl;
            output<<"SALARY: "<<emp.salary<<endl;
            output<<"HIRING DATE: "<<emp.hiringdate.month;
            output<<"/"<<emp.hiringdate.day;
            output<<"/"<<emp.hiringdate.year<<endl;
            return output; }//<<
int main(){
             employee ebr;
             strcpy(ebr.firstname,"Alireza");
             strcpy(ebr.lastname,"Ebrahimi");
             ebr.hiringdate.year=1983;
             ebr.hiringdate.month=1;
             ebr.hiringdate.day=23;
             ebr.setsalary(99999.99);
             cout<<ebr;                    
             return 0; 
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.23a – Program with a friend function to overload the << operator

Text Box: Alireza Ebrahimi
SALARY: 100000
HIRING DATE: 1/23/1983  

 

 

 

 

 

 

 

 


 

Figure 20.23b – Output of Figure 20.23a

ARRAY OF OBJECTS

An array of objects works the same way as an array of simple variables such as an array of integers or an array of characters. The difference is that the type is a user-defined (class). The general form of an array of objects and its usages are shown below.

 

person employee[100]; //array of hundred objects of type person

employee[0]; and Employee[5]; //refer to the first and sixth objects of the array

employee[2].salary; //refers to the salary of the 3rd employee, assuming salary is public

employee[i].display(); //displays the ith employee information

 

The following program demonstrates the use of an array of objects in a payroll program with an array of five employee objects. Each employee object has its own hoursworked, hourlyrate, salary, and employeename as well as the functions: setname( ), getname( ), sethoursworked( ), computesalary( ), and getsalary( ). The constructor will set the hourlyrate to 20.00 if it is not provided.

Text Box: #include<iostream>
#include<string>
using namespace std;
class employee{
private: int hoursworked;
             double hourlyrate;
             double salary;
public: string employeename;
            employee(){hourlyrate=20.00;}
            void setname(string);
            string getname();
            void sethoursworked(double);
            void computesalary();
            double getsalary();       };//EMPLOYEE
void employee::sethoursworked(double hours){ hoursworked=hours;}
void employee::computesalary(){ salary=hourlyrate*hoursworked;}
double employee::getsalary(){ return salary;}
int main(){
            employee emp[5];
            int hours, i;      
            for(i=0; i<5; i++){ cout<<"ENTER NAME: ";
                                        cin>>emp[i].employeename;
                                        cout<<"ENTER HOURS WORKED: ";
                                        cin>>hours;
                                        emp[i].sethoursworked(hours);
                                        emp[i].computesalary();      }//FOR
            for(i=0; i<5; i++){ cout<<emp[i].employeename;
                                        cout<<": "<<emp[i].getsalary()<<endl;   }//FOR
              return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.24a – Program with an array of employee  objects

 

 

Figure 20.24a – Program with an array of employee objects

 

 

Text Box: ENTER NAME: Ebrahimi
ENTER HOURS WORKED: 55
ENTER NAME: Husain
ENTER HOURS WORKED: 44
ENTER NAME: Zainab
ENTER HOURS WORKED: 42
ENTER NAME: Zahra
ENTER HOURS WORKED: 38
ENTER NAME: Mehdi
ENTER HOURS WORKED: 40
Ebrahimi: 1100
Husain: 880
Zainab: 840
Zahra: 760
Mehdi: 800

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.24b – Output of Figure 20.24a      

 

 

POINTER TO OBJECT VERSUS this POINTER

Like pointers to simple data types, a pointer to an object works in the same way as pointers to simple data types. We can use a pointer to a class object in the same way as a pointer to an integer or to a character. But, do not confuse a pointer to an object that is explained here with the this pointer that refers to a specific calling or returning object.

Each object contains a const pointer to itself known as this pointer. Each member function carries this pointer implicitly when it is invoked. In other words, when a member function is called, there should be a way for this function to refer to other members of the object. This is done implicitly without involving this pointer because it is understood, but it could be done explicitly as this->x where x is the member data. The pointer this is used explicitly in situations where member functions need to return the address of the current object, or when a member function has several parameters of the same class type (other objects). Note that static member functions do not carry implicitly this pointer, hence, you need to use it explicitly to access the static members.

 

 

POINTER TO OBJECT OF CLASS

 

The following program builds a list of employees using a single linked list with two classes, each with a pointer to a class. For example, the node class has a pointer pointing to itself, and the employeelist class has a pointer to a node. For simplicity, we are building a new node and inserting it at the front of the list, readjusting the list upon completion, and then the entire list is displayed.

This program can be expanded to convert the payroll program to use a linked list instead of a static array to save memory. As employees are added, they are inserted to the list, and as they leave, they are deleted dynamically. As an exercise, expand the program to include other functions such as remove( ) and computesalary( ). 

Text Box: #include<iostream>
using namespace std;
class node{
public:    double salary;
                node *next;};//NODE
class employeelist{
private:
                node *firstnode;
public:
                employeelist(){ firstnode=NULL;}
                void additem(double);
                void display();        }; //EMPLOYEELIST
void employeelist::additem(double amount){
                node *p=new node;
                p->salary=amount;
                p->next=firstnode;
                firstnode=p;          }//ADDITEM
void employeelist::display(){
                node *p;
                p=firstnode;
                while(p!=NULL){
                                cout<<p->salary<<endl;
                                p=p->next;}//WHILE
}//DISPLAY
int main(){
                employeelist emplist;
                double empsalary;
                for(int i=0; i<3; i++){
                cout<<"ENTER EMPLOYEE SALARY: ";
                cin>>empsalary;
                emplist.additem(empsalary);}//FOR
                emplist.display();  
               return 0;
}//MAIN
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.25a – Program using pointers to objects of a class

 

Text Box: ENTER EMPLOYEE SALARY: 90000
ENTER EMPLOYEE SALARY: 29000
ENTER EMPLOYEE SALARY: 55000
55000
29000
90000

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.25b – Output of Figure 20.25a

this POINTER PROGRAM: WORKING WITH TWO OBJECTS

 

A common usage of this pointer is when values are returned from member functions and overloaded operators such as = and = =. The following program finds the highest paid employee. The program defines an array of employees (class), and at this time we are only dealing with id and salary. The function findhighemp( ) will compare the invoking object with the object that holds the highest salary. The function returns this pointer if the invoking object is higher, otherwise it returns the object that holds the higher salary. At the end of the loop the highest paid employee is found and the function displayemp( ) displays the information.  As an exercise, sort the objects according to the salary paid and display the information of each employee.

Text Box: #include<iostream>
using namespace std;
class employee{
public:    long int id;
double salary;
const employee & findhighemp(const employee & emp) const;
void displayemp( )const ;    };
const employee& employee:: findhighemp(const employee &highemp)const {
if (salary>highemp.salary) return *this;
else return highemp; }//FINDHIGHEMP
void employee::displayemp( ) const {
                cout<<"EMPLOYEE ID IS:"<<id<<endl;
                cout<<"EMPLOYEE SALARY IS "<<salary<<endl; }//DISPLAYEMP
void main(){
                employee emp[3];
                int i;
                for(i=0;i<3;i++){
                cout<<"ENTER ID: "; cin>>emp[i].id;
                cout<<"ENTER SALARY: "; cin>>emp[i].salary;}//FOR 
                employee highemp;
                highemp=emp[0];
                for(i=1;i<3;i++)  highemp=emp[i].findhighemp(highemp); //HIGHEST PAY
                cout<<"HIGHEST PAY EMPLOYEE:"<<endl;
                highemp.displayemp( );     
               return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.26a – Program using this pointer

Text Box: ENTER ID: 1111
ENTER SALARY: 50000
ENTER ID: 1122
ENTER SALARY: 89000
ENTER ID: 1233
ENTER SALARY: 37000
HIGHEST PAY EMPLOYEE:
EMPLOYEE ID IS:1122
EMPLOYEE SALARY IS 89000

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

Figure 20.26b – Output of Figure 20.26a
ARRAY, A POINTER TO ARRAY, AND AN ARRAY OF POINTERS

 

An array is used to store a series (contiguous) of the same (homogeneous) data type under a common name. Retrieval and storage of data is done randomly through the index (subscript). You may have seen a variety of arrays. Arrays and pointers are closely related to each other, and any operations done using array subscripts can be done using pointers. C/C++ is somewhat pointer oriented and is proud of this despite criticism from newer languages such as Java and C# that try to distance themselves from pointers, mainly due to the consequences of careless usage. After assembly language lost its popularity, C/C++ became the most popular language to manipulate pointers and memory.

 

How would you allocate 500 contiguous memory locations? The 500 memory locations can be allocated entirely by the compiler, during run time, or one by one. The following illustrates how to allocate 500 locations in different ways.

 

The most common array is an array of a data type such as integers or any other data type including user data types (class). Storage of this data type is assigned during compilation time.

 

For example, int months[12] is an array of 12 integers and employee emp[500] is an array of 500 employees. 

Note that the array name is the address of the first element of the array, emp is the same as &emp[0] and, similarly, emp[i] is the same as *(emp+i).

 

 

POINTER TO AN ARRAY: ALLOCATE ARRAY DYNAMICALLY

 

Storage is allocated dynamically (during run time) and a pointer is assigned to the first address of the array. An array can be accessed through indirection or through an index. For example, int * p=new int [500]; is a pointer to an array and will allocate an array of 500 integers. The difference between the former allocation and int p[500]; is that in the former the memory is allocated dynamically and with int p[500]; the memory is allocated statically. There are advantages and disadvantages to dynamic and static allocation, depending on the situation.

Note that the storage for the pointer is allocated during compile time and the storage for the array is allocated during run time.

 

 

AN ARRAY OF POINTERS: ALLOCATE THE MEMORY ONE BY ONE

 

An array is designated for pointers of some known data type. Storage for pointers is done during compile time and storage for its actual data type is allocated during run time one by one. An example of an array of pointers is *p[500]; where there are 500 pointers and

p[0]=new int; allocates memory.

The memory is allocated as you need it and de-allocated when you are finished with it.


 

 

Text Box: #include<iostream>
using namespace std;
int main(){
            int employeeid[5];
            double *hoursworked=new double[5];
            double *hourlyrate[5];
            double grosspay[5];
            for(int i=0; i<5; i++){
                        cout<<"ENTER ID: ";
                        cin>>employeeid[i];
                        cout<<"ENTER HOURS WORKED: ";
                        cin>>hoursworked[i]; //*(hoursworked+i)
                        cout<<"ENTER HOURLY RATE: ";
                        hourlyrate[i]=new double;
                        cin>>*hourlyrate[i];
                        grosspay[i]=hoursworked[i]*(*hourlyrate[i]);
                        delete hourlyrate[i];
                        }//FOR
            delete [] hoursworked;
            for(int n=0; n<5; n++){
                        cout<<employeeid[n]<<" "<<grosspay[n]<<endl;}//FOR
              return 0;
}//MAIN
                       

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.27a – Program using an array of pointers

Text Box: ENTER ID: 111
ENTER HOURS WORKED: 48
ENTER HOURLY RATE: 9
ENTER ID: 112
ENTER HOURS WORKED: 44
ENTER HOURLY RATE: 10
ENTER ID: 123
ENTER HOURS WORKED: 55
ENTER HOURLY RATE: 7
ENTER ID: 133
ENTER HOURS WORKED: 56
ENTER HOURLY RATE: 6
ENTER ID: 134
ENTER HOURS WORKED: 50
ENTER HOURLY RATE: 5
111 432
112 440
123 385
133 336
134 250

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.27b – Output of Figure 20.27a

C AND C++ DIFFERENCES: DYNAMIC MEMORY ALLOCATION

C language uses the malloc( ) function to allocate memory dynamically and the function  free( ) to de-allocate (free) memory. C++ uses the operator new to allocate memory and delete to de-allocate (delete) the allocated memory. The C malloc( ) function requires the number of  bytes to be allocated as a parameter. In the case where the number of bytes cannot be figured out by the programmer, the sizeof operator is used to figure out the size of a given data type. The general form of malloc( ) is:

void *malloc(sizeof(datatype))  

 

The malloc( ) function returns the beginning address of the allocated memory, however, it is a pointer of the type void. The reason for that is so that it can be converted to the type of variable that the programmer requests. In addition, in earlier version of C you must cast the return value of malloc( ) before the assignment. The following examples demonstrate the use of malloc( ) in C and new in C++.

int *myptr = (int *)malloc(sizeof(int);

int *myptr = new int;

 

You can see that C++ does some of the housekeeping for the user when using new. With the inclusion of exception handling, the new operator throws an exception when there is a problem in memory allocation (bad_alloc).

This is a C program using the malloc( ), sizeof( ), and free( ) functions.

Text Box: #include <iostream> 
#include<cstdlib >
using namespace std;
int main(){
            float *ptr;
            ptr = (float *)malloc(sizeof (float));    
            printf("HERE IS THE INPUT: ");
            scanf("%f",ptr);
            printf("HERE IS THE OUTPUT: ");
            printf("%f\n",*ptr);
            free(ptr);
            printf("%f ",*ptr);//MEMORY NOT AVAILABLE
return 0;}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.28a – Program demonstrating malloc( ), sizeof( ), and free( )

 

Text Box: HERE IS THE INPUT: 5.00
HERE IS THE OUTPUT: 5.000000
-1998397155538108400.000000

 

 

 

 

 

 


 

  Figure 20.28b – Output of Figure 20.28a

 

 

 

 

The following C++ program uses the new and delete operators.

Text Box: #include<iostream>
#include<cstdlib >
using namespace std;
int main(){
            float *ptr;
            ptr = new float;    
            cout<<"HERE IS THE INPUT: ";
            cin>>*ptr;
            cout<<"HERE IS THE OUTPUT: ";
            cout<<*ptr<<endl;
            delete ptr;
            cout<<*ptr<<endl;//MEMORY NOT AVAILABLE
             return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.29a – Program demonstrating new and delete

Text Box: HERE IS THE INPUT: 1.5
HERE IS THE OUTPUT: 1.5
-1.9984e+018

 

 

 

 

 

 

 


 

  Figure 20.29b – Output of Figure 20.29a

 

C/C++ DIFFERENCES – FILE HANDLING

In C, to access an external file, a file variable must be declared, the file has to be opened, and the file has to be accessed through an I/O routine and, finally, the file has to be closed. The form of declaring a C file pointer is:  FILE  *infile, *outfile;

 

Note, the FILE type is written in capitals and is defined in stdio.h; infile and outfile are file pointers. To open a file, the function fopen( ) associates an external filename with an access mode and returns a pointer which is assigned to the file pointer. The program uses the file pointer to access the file. The C I/O routines to handle files have a prefix of the letter f, such as fprintf( ), fputs( ), fscanf( ), and fgets( ). Note that the place of a file pointer is the first argument in fscanf( ) while it is the last in fgets( ). Opening a file using fopen( ) is shown below:

            infile=fopen(“dat.in”, “r”);

 

The following program opens a file and, if the file does not exist, it displays an error message. The content is written to the screen (stdout) as well as to an external file. To test the file copy, the copied file is opened in read mode and is displayed on the screen.

 

 

Text Box: #include<iostream>
using namespace std;
int main(){
            FILE *infile, *outfile;
            int num;
            if((infile=fopen("dat.in", "r"))==NULL)
                                    fprintf(stderr, "CANNOT OPEN %s\n", "dat.in");
            if((outfile=fopen("dat.out", "w"))==NULL)
                                    fprintf(stderr, "CANNOT OPEN %s\n", "dat.out");
            while(fscanf(infile, "%d", &num)!=EOF){
                        fprintf(outfile, "%d\n", num);
                        fprintf(stdout, "%d\n", num);
                        }//WHILE
            fclose(infile);fclose(outfile);
            if((infile=fopen("dat.out", "r"))==NULL)
                        fprintf(stderr, "CANNOT OPEN %s\n", "dat.out");
            printf("\nDISPLAY THE COPIED FILE\n");
            while(fscanf(infile, "%d", &num)!=EOF){
                                    fprintf(stdout, "%d\n", num);}//WHILE
            fclose(infile);
return 0;}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.30a – Program showing file handling in C

 

 

Text Box: 1
2
3
4
5
 
DISPLAY THE COPIED FILE
1
2
3
4
5

 

 

 

 

 


 

             

 

 

 

 

 

 

 

  Figure 20.30b – Output of Figure 20.30a

 

 

 

 

 

 

 

 

 

 

 

STATIC DATA MEMBER

 

A static data member is a variable that shares all instances (objects) of the class. In other words there is only one copy of the static data member for all of the objects. A static data member starts with the keyword static. One usage of a static data member is to count the number of processing objects. A restriction on a static member function is that it cannot access its members by this pointer.

 

 

STATIC MEMBER FUNCTION

 

A static member function does not have a this pointer and can only access the static member data. You can use a static member function without creating any object of its class. A static member function can work with a static member data to access and modify it. A static member function starts with the key word static. For example, a counter which is a static member data can be accessed by the static member function findcounter( ). The following program increments the counter as an object is created and decrements the counter as an object is deleted.

Text Box: class employee {
public:
employee () { counter++; }
~employee () {counter--;}
static int findcounter () { return counter;}//FINDCOUNTER 
private: 
static int counter;         };  // CLASS
 
int employee::counter=0;
#include <iostream>
using namespace std;
int main(){
employee  *emp1=new  employee();
cout<<"COUNTER IS:"<<employee::findcounter()<<endl;
employee  *emp2=new  employee();
cout<<"COUNTER IS:"<<employee::findcounter()<<endl;
delete emp1;
cout<<"COUNTER IS:"<<employee::findcounter()<<endl;
             return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 
 
Figure 20.31a – Program with a static member function      

Text Box: COUNTER IS:1
COUNTER IS:2
COUNTER IS:1

 

 

 

 

 

 

 

 


 

 Figure 20.31b – Output of Figure 20.31a

10 COMMANDS OF HTML:html, a, img, table, form, input, select, li, textarea, mailto

HTML stands for Hyper-Text Markup Language and it consists of numerous tags that are used to format a web page. Although it is called a language, the fact is that it is a marking (tagging) of the text that has an effect when the file is viewed in a browser, where the impact of those tags is shown. An HTML file consists of several tags inserted into a text. The HTML tags are activated when viewed with the browser. The HTML tags are enclosed in <   > (angled brackets) indicating the start of the tag; a tag preceded by a / (slash) indicates the end of the effect of the tag. Although there are more than a hundred HTML tags, I recommend that you learn the ten most important HTML tags that are needed to make a web page. The simplest way to create a web page is to start with <HTML> and type whatever you want on the page and end it here </HTML>. Make sure you save the file with the extension .html.

 

Commands can be categorized as text (bold <B>, italics <I>, font <FONT SIZE=+2>), color (<BODY BGCOLOR = red >), anchor references to other pages

(<A HREF=”www.nba.com”>) and self-referencing  anchors that search on your page

(<A NAME=List> <A HREF="#List">), images (<IMG SRC=”ebrahimi.jpg”),

form to get information from users

(<FORM METHOD=”post” ACTION=”mailto:ebrahimi@juno.com”>), input

<INPUT TYPE="text" NAME="name" SIZE=”15”>, select (<SELECT> <OPTION>), table (<TABLE><TR><TD>), and list (<UL><LI>). While the colors are defined by their names such as green, blue, and pink, they are also represented by #FFFFFF, where FF represents red, green, and blue which ranges from 00, 01 … to FF, this way you can blend your own colors. There are many other useful HTML commands such as: mailto which is used to write an e-mail to a specified address, bgsound which is used to add sound to your page, and radio buttons and check boxes that are types of input that allow the user to select from several options. The following is an example of a simple web page using the basic HTML commands.


 

 

Text Box: <HTML>
<TITLE>Dr. Ebrahimi's Webpage</TITLE>
<BODY BGCOLOR="FF0055">
<FONT SIZE="+3">Welcome to Dr. Ebrahimi's Webpage</FONT><BR><BR>
<CENTER><IMG SRC="ebrahimi.jpg"><BR><BR>
<A HREF="http://ebrahimi.cjb.net">Click here</A><BR><BR>
<A HREF="#List">Programming Languages</A><BR><BR>
<TABLE BORDER=1>
<TR>
<TD>Apple</TD>
<TD>Banana</TD>
</TR>
<TR>
<TD>Lettuce</TD>
<TD>Tomato</TD>
</TR>
</TABLE></CENTER><BR>
 
What is your favorite fruit?
<SELECT NAME="Fruit">
<OPTION>Apple
<OPTION>Banana
<OPTION>Cherry
<OPTION>Watermelon
</SELECT><BR>
 
<FORM METHOD="POST" ACTION="mailto:ebrahimi@juno.com">
Name: <INPUT TYPE="text" NAME="name" SIZE="15"><BR>
E-mail: <TEXTAREA NAME="email" ROWS=5 COLS=35></TEXTAREA>
<INPUT TYPE="submit" VALUE="send"></FORM>
 
<A NAME=List></A>
<LI>C++</LI>
<LI>Java</LI>
<LI>Perl</LI>
<LI>JavaScript</LI>
<LI>HTML</LI>
</BODY>
</HTML>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

            Figure 20.32 – Simple web page created with HTML

 

 

 

 

 

 

 

JAVASCRIPT

 

JavaScript is a language that is embedded in HTML and is executed in a browser (Internet Explorer or Netscape). Almost every web page now utilizes JavaScript. While the name is JavaScript and people think it is related to Java, it is a distinct language by itself. Dealing with the Internet (Internet programming) is a common purpose of Java and JavaScript, and both are event-driven. The way JavaScript handles input (ex. an input value has to be parsed to its numerical value) is similar to Java. JavaScript can take advantage of HTML to make the page more presentable by using loops and if statements to manipulate many fonts, colors, etc. The syntax of JavaScript is very similar to that of C++ and JavaScript’s keywords are mostly from C/C++; out of 22 keywords, 17 are used in C++, 4 keywords are used in Pascal such as var, function, with, and in, and there are some other keywords such as null and typeof. The words write and writeln (write line) to display are also used in Pascal. JavaScript is an event-driven language that, upon certain events such as clicking the mouse or pressing a key, an action takes place.

Text Box: <HTML>
<SCRIPT LANGUAGE="JavaScript">
document.write("Hello World");
</SCRIPT>
</HTML>

 

 

 

 

 

 

 

 


 

  Figure 20.33a – JavaScript code to say Hello World

Text Box: Hello World

 

 

 

 


 

  Figure 20.33b – Output of Figure 20.33a

 

The following program is a simple translator that translates english words into spanish using parallel arrays. The user enters a search key and the program performs a linear search for the english word in the english array; when the word is found, the corresponding spanish word is displayed. If the word is not found, an error message is displayed.

Text Box: <HTML><H1>Javascript search</H1>
<SCRIPT LANGUAGE="javascript">
var english=["water","house","book","university","car","computer"];
var spanish=["aqua","casa","libro","universidad","caro","computador"];
var result = 0;
var searchword = prompt("Enter english word to translate: ");
for(i=0;i<english.length;i++){
if(english[i]==searchword){
   document.writeln("Spanish word: "+spanish[i]);
   result = 1;    }//IF
   }//FOR
if(result==0)
   document.writeln("Sorry, NO MATCH for: " + searchword);
</SCRIPT> </HTML>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.34a – JavaScript translator program

 

 

 

  Figure 20.34b – Output of JavaScript program

 

WHAT IS CGI (COMMON GATEWAY INTERFACE)

CGI stands for Common Gateway Interface and is a simple protocol (standard) to establish a communication (interaction) between your Web page (located anywhere) via a browser and your program that resides on a Web server. The CGI program (e.g. C++, or Perl) processes data submitted by a form and performs requested tasks such as searching. After submitting a form, the browser uses HTTP to make a request for the URL of a CGI program. The Web server receives the request and executes the CGI program with the data that is passed. The output of the CGI program is usually in the form of a web page which is sent back through the Web server to the requesting browser. An example of CGI usage is a database program that runs on the Internet and lets individuals manipulate the database through the web.

Note that a CGI program is executable and resides in a special directory under the direct control of a Webmaster, commonly known as /cgi-bin, so that the Web server is directed to execute the CGI program rather than just display it to the browser.

 

 

WRITING A CGI IN C++

 

A CGI takes information from forms on a Web page, processes it, and sends a page back to the user. A CGI program written in C++ is nothing more than just another C++ program that accepts a string as its input and breaks down the input string into tokens (words) and identifies and processes the input based on the requested task. CGI is language independent and the languages Perl and Python or even a script language such as Unix shell can be used to write a CGI program. One caution, do not try to use Java to write a CGI; instead, use Java Servlets. The language Perl, because of its sophisticated pattern matching (regular expressions), has been the language of choice for writing CGI programs. However, you can stick to C/C++ and write a CGI, rather than using other languages.

 

In summary, in order to write a simple CGI program in C++, use the input routines of C++ cin or getline( ) to take the data as if it were on a standard input (stdin) with the understanding of how the inputs are separated from each other (e.g. by & or by ; ). After that, a CGI program is another C++ program and when all processing is done, at the end, the CGI program has to communicate to the web page or create a new one. The CGI communicates back to the web page through the standard output (stdout) such as cout with embedded HTML tags inside the quotations. Note that the CGI program takes input from the HTML form and encodes it (URL encoding) by making a single string, since URL does not allow spaces. Instead of spaces, separators (delimiters) such as & (ampersand) and = (equal sign) are used. In the following example, the string with two input data such as the first name and last name are separated with & is sent to the CGI and the program has to strip the f= and save the values correspondingly. For simplicity, we are using one letter for the name of the field.

f=John&f=Doe

 

 

C++ CGI PROGRAM

 

The following HTML file consists of a form with one input data and we want to send the input and get a response by echoing the input back. At first, an HTML file is created and, in the form tag, the action is specified by indicating the name of the executable CGI program (e.g. ebrahimi.cgi) which resides in the /cgi-bin directory. The method of sending the data to the CGI program is POST where the data is sent via the program’s standard input in contrast to the other method GET where the data is sent through a program variable name known as environment variable. For the sake of simplicity, the field’s name is chosen as one character (e.g. f ) which with the = sign makes two characters (e.g. f =). One job of the CGI is to strip off these two characters and save the rest (e.g. value). The following CGI program takes the encoded URL, strips the first two characters, and saves the rest of the string into another string (e.g. str2), which is echoed back to the user. 

 

Note that the "Content-type: text/html\n\n" in

cout<<"Content-type: text/html\n\n";

will inform the server that the CGI program is about to send data to the user in the form of an HTML page. Make sure to include the newline (\n).

 

If you need to convert the above C++ program to C language for the reason of speed, you only need to change cin to scanf(“%s”,  ) and cout to printf( “%s”, ) and make sure to include #include <stdio.h>.


 

Text Box: <html>
<form action=cgi-bin/ebrahimi.cgi method="post">
<input type=text name=f size=10>
<input type=submit value=submit>    
</form>
</html>      

 

 

 

 

 

 

 

 

 


 

   Figure 20.35a – HTML form to take in user input

Text Box: #include <iostream>
using namespace std; 
int main(){
   char str[100];
   char str2[100];
   cin>>str;
   int i=2;
   int n=0;
   for(i=2; str[i]!=0 ;i++)
   {
    str2[n]=str[i];
    n++;
   }//REMOVE FIRST TWO CHARACTERS FROM POST
   str2[n++]=0;//SET THE END OF THE STRING TO NULL
 
   cout<<"Content-type: text/html\n\n";
   cout<<str2;
              return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

                                   

 

  Figure 20.35b – CGI program to take in a string and display it

 

 

COMPILING A CGI PROGRAM

 

The following compiles a CGI program under Linux (GNU c++ compiler known as g++). However, the executable code is redirected to a file with the extension .cgi. The command chmod (change mode) makes the executable code accessible to the public (read, no write, execute), but you can have all access permissions (read, write, execute).

 

g++ -o  ebrahimi.cgi  ebrahimi.cpp

 

chmod 755  ebrahimi.cgi

 

Other operating systems may work differently than a Unix-like OS, but the concept would be the same. Note that one reason to place the CGI program in a specific directory like /cgi-bin is for security reasons and to make it easier for the system administrator to manage. 

A C++ CGI PROGRAM WITH TWO INPUT DATA

 

The following C++ CGI program uses two input with the hope that you will understand how to write a multiple input program using the same strategy. The strategy is that every data has a field name followed by =, its value, and a separator (&) before the next field’s name. The program has to skip two characters to get to the value of the first input and, after that, three characters must be skipped between values. For example: f=John&f=Doe

Note that the below program is just for you to understand the concept and you may want to generalize it so it can work with any input and any size field name.

Text Box: <html>
<form action=cgi-bin/ebrahimi.cgi method="post">
First Name: <input type=text name=f size=10><br>
Last Name: <input type=text name=f size=10><br>
<input type=submit value=submit>
</form>
</html>

 

 

 

 

 

 

 

 

 

 


 

  Figure 20.36a – HTML form to take in two inputs

Text Box: #include <iostream>
using namespace std;
int main() {
   char str[100];
   char fname[100];
   char lname[100];
   cin>>str;
   int i=2;
   int n=0;
   for(i=2;str[i]!='&';i++){
    fname[n]=str[i];
    n++;}
   fname[n++]=0;
   n=0;
   for(i+=3;str[i]!=0;i++) {
    lname[n]=str[i];
    n++;}
   lname[n++]=0;
   cout<<"Content-type: text/html\n\n";
   cout<<"<HTML><B>Your Name: </B>";
   cout<<fname<<" "<<lname;
   cout<<"</HTML>";
    return 0;}//MAIN

 

 

 

 


 

           

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  Figure 20.36b – CGI program to take in two strings and display them

 

 

Your Name: John Doe

 

  Figure 20.36c – Output as HTML page

 

 

C++ CGI DATABASE

 

The following program demonstrates how you simply can make a web application where users can interact with your program from anywhere using C++ with CGI capabilities. To make the program short, other database functions such as display, update, and deletion are omitted. The program creates a simple database with simple file handling without using other databases such as Access or SQL tools. The program follows a similar strategy of extracting the variables from the input (URL encoding). The variables need to be separated (i+=3), this extraction could be put into a function. For the sake of simplicity, each function is a separate form in HTML; you may want to try to put it into a single form. For each function, there is a separate CGI program in the cgi-bin directory. As an exercise, you can write those functions and optimize the code and even include object-oriented design.

Text Box:                 empdatabase.html
<HTML>
<BODY BGCOLOR=ffdeaa>
<CENTER><BR><B>Employee Database</B></CENTER><BR>
<HR WIDTH=65%>
<CENTER>Please select from the following choices:<BR><BR>
<FORM ACTION="insertrecord.html">
                <INPUT TYPE="submit" VALUE="1. Insert a Record          "></FORM> 
<FORM ACTION="cgi-bin/displayall.cgi">
                <INPUT TYPE="submit" VALUE="2. Display all Records  "></FORM> 
<FORM ACTION="search.html">
                <INPUT TYPE="submit" VALUE="3. Search Database      "></FORM>
<FORM ACTION="cgi-bin/update.cgi">
                <INPUT TYPE="submit" VALUE="4. Update Record          "></FORM>
<FORM ACTION="cgi-bin/delete.cgi">
        <INPUT TYPE="submit" VALUE="5. Delete a Record       "></FORM> 
</CENTER></BODY>
</HTML>

 

 

 

 

 

 

 

 

 

 

 


 

            Figure 20.37a – HTML for the database menu

                                                                                                   


 

 

Text Box: insertrecord.html
<HTML>
<BODY BGCOLOR=ffdeaa>
<CENTER>
<BR><B>Insert Record to Employee Database</B><BR><BR>
<HR WIDTH=65%><BR>
<FORM ACTION="cgi-bin/insertrec.cgi" METHOD="post">
<B>First Name: <INPUT TYPE=text NAME=f SIZE=15><BR><BR>
Last Name: <INPUT TYPE=text NAME=f SIZE=15><BR><BR>
Salary per hour: <INPUT TYPE=text NAME=f SIZE=5 value=0.00><BR><BR>
Hours worked: <INPUT TYPE=text NAME=f SIZE=5><BR><BR>
<INPUT TYPE=submit VALUE="Submit Record"></FORM>
</CENTER></BODY>
</HTML>
 
menu

Text Box:

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 


 

            Figure 20.37b – HTML for inserting a record

 

 

 

 

 

 

 

insert

Text Box:

 


 

 

Text Box:                 insertrec.cpp
#include<iostream>
#include <fstream>
#include <string.h>
using namespace std;
struct employee{                 char fname[30], lname[30];
                                double salary, hoursworked, netpay;};
int main(){
                char str[150], fnamef[20], lnamef[20], salaryf[10], hoursworkedf[10];
                cin>>str;
                int i=2, n=0;
                for(i;str[i]!='&';i++){ fnamef[n]=str[i];  n++; }//FOR
                fnamef[n++]=0; n=0;
                for(i+=3;str[i]!='&';i++){
                                lnamef[n]=str[i];
                                n++; }//FOR
                lnamef[n++]=0;  n=0;
                for(i+=3;str[i]!='&';i++){ salaryf[n]=str[i];  n++; }//FOR
                salaryf[n++]=0;  n=0;
                for(i+=3;str[i]!=0;i++){ hoursworkedf[n]=str[i];  n++; }//FOR
                hoursworkedf[n++]=0;
                ofstream record("employee.txt",ios::app);
                record<<fnamef<<" "<<lnamef<<" "<<salaryf<<" "<<hoursworkedf<<endl;
                record.close();
                cout<<"Content-type: text/html\n\n";
                i=0;  employee emp[100];
                ifstream record2( "employee.txt", ios::in);
                cout<<"<BODY BGCOLOR=ffdeaa>";
                cout<<"<BR><CENTER><B>Employee Database: Display All Records</B><BR>";
                cout<<"<BR><HR WIDTH=65%><BR>";
                cout<<"<TABLE BORDER=5><TR><TD><B>First Name</B></TD>";
        cout<<"<TD><B>Last Name</B></TD>";
        cout<<"<TD><B>Salary</B></TD>";
        cout<<"<TD><B>HrsWorked</B></TD>";
        cout<<"<TD><B>Net Pay:</B></TD>";
        cout<<"</TR>";    
while(record2>>emp[i].fname>>emp[i].lname>>emp[i].salary>>emp[i].hoursworked){
                emp[i].netpay=emp[i].salary*emp[i].hoursworked;
                cout<<"<TR><TD>"<<emp[i].fname<<"</TD><TD>";
                cout<<emp[i].lname<<"</TD><TD>"<<emp[i].salary<<"</TD><TD>";
                cout<<emp[i].hoursworked<<"</TD><TD>"<<emp[i].netpay<<"</TD></TR>";
                }//WHILE
cout<<"</TABLE><br><br>";
cout<<"</CENTER></BODY>"; 
record2.close();
              return 0;
}//MAIN

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

           

 

 

Figure 20.37c – CGI program to insert a record into the database and display all


 

OUTPUT

Text Box:                 search.html
<HTML>
<BODY BGCOLOR=ffdeaa>
<CENTER>
<BR><B>Search Employee Database</B><BR><BR>
<HR WIDTH=65%><BR>
<FORM ACTION="cgi-bin/search.cgi" METHOD="post">
<B>Enter Employee's Last Name: </B>
<INPUT TYPE=text name="f" SIZE=15>
<INPUT TYPE=submit VALUE="Search"></FORM>
</CENTER>
</BODY>
</HTML>

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

            Figure 20.37d – HTML to take in search name

 

search

Text Box:

 

 

 

 

 

 

 

 


 

 

Text Box: search.cpp
#include<iostream>
#include <fstream>
#include <string.h>
using namespace std;
struct employee{
                char fname[30], lname[30];
                double salary, hoursworked, netpay; };
int main(){
                char buff[100], buff2[100];
                cin>>buff;
                cout<<"Content-type: text/html\n\n";
                int i=2;
                while(buff[i]!=0){
                                buff2[i-2]=buff[i];
                                i++;}//WHILE
                buff2[i-2]=0;
                cout<<"<BODY BGCOLOR=ffdeaa>";
                cout<<"<CENTER><BR><B>Search results</B><BR><HR WIDTH=65%><br><br>";
                employee emp[100];
                ifstream record("employee.txt", ios::in);
                i=0;         
int k=-1;
                while(record>>emp[i].fname>>emp[i].lname>>emp[i].salary>>emp[i].hoursworked)
                {i++;}
                for(int j=0;j<i;j++){
                                if(strcmp(buff2,emp[j].lname)==0)
                                                k=j; }//FOR
                if(k!=-1){
        emp[k].netpay=emp[k].salary*emp[k].hoursworked;
        cout<<"<TABLE BORDER=5>";
                cout<<"<TR><TD>First Name:</TD><TD>"<<emp[k].fname<<"</TD></TR>";
        cout<<"<TR><TD>Last Name:</TD><TD>"<<emp[k].lname<<"</TD</TR>";
        cout<<"<TR><TD>Salary:</TD><TD>"<<emp[k].salary<<"</TD></TR>";
        cout<<"<TR><TD>Hrs Worked:</TD><TD>"<<emp[k].hoursworked<<"</TD></TR>";
        cout<<"<TR><TD>Net Pay:</TD><TD>"<<emp[k].netpay<<"</TD></TR></TABLE>";}
                else {cout<<"Record not found"<<"<br>";}
cout<<"</CENTER></BODY></HTML>";   
              return 0;
}//MAIN
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

           

 

Figure 20.37e – CGI program to search for a record and display it

search2

Text Box:

 

 

 

 

 

 

 

 

 

 

 

 

 


 

A C++  SIMPLE  DATABASE TO CONVERT TO OBJECT

 

The following program is a simple database with insertion, display, modify (update), deletion, and report functions for employee records. The program saves the employee records to a file and computes gross pay. The database has a delete file function with a password. This program uses an array of structs and each employee has its own first and last name, hourly rate, hours worked, and gross pay. At start of the program, the load function is called that uploads the records from the file to an array; similarly, when the program is exited, the store function downloads the array to the file. As an exercise, you may want to redesign the program using an object-oriented paradigm by defining a class called Dbase that has all the operations on the database and consists of the objects of all employees (e.g. 100 employees).


 

 

Text Box: #include<fstream>
#include<string>
#include<iostream>
#include<iomanip>
using namespace std;
struct employee{   string fname, lname;
                                 double hourlyrate, hoursworked, netpay; }; //employee
employee e[100];
int n=0;
void load(){
                ifstream fin("employee.txt",ios::in);
                while(fin>>e[n].fname>>e[n].lname>>e[n].hourlyrate>>e[n].hoursworked){
                e[n].netpay=e[n].hourlyrate*e[n].hoursworked;
                n++;}//WHILE
                }//LOAD
void store(){
                ofstream fout("employee.txt",ios::out);
                for(int i=0; i<n; i++){
                if(e[i].fname!=" ")
                fout<<e[i].fname<<" "<<e[i].lname<<" "<<e[i].hourlyrate<<" "<<e[i].hoursworked<<endl;
}//FOR
                }//STORE
 
void insert(){
                cout<<"Enter employee's first name: ";          cin>>e[n].fname;
                cout<<"Enter employee's last name: ";           cin>>e[n].lname;
                cout<<"Enter employee's salary per hour: "; cin>>e[n].hourlyrate;
                if(cin.fail())
                                {cout<<"Error\n"; exit(1);}
                cout<<"Enter employee's hours worked: ";
                cin>>e[n].hoursworked;
                e[n].netpay=e[n].hourlyrate*e[n].hoursworked;
                n++;        }//INSERTS THE RECORD TO ARRAY
 
void display(){
                cout<<setiosflags(ios::left)<<setw(15)<<"First Name"<<setw(15)<<"Last Name";
                cout<<setw(10)<<"Hourly Rate"<<setw(10)<<"HrsWorked"<<setw(10)<<"Net Pay";
                cout<<endl<<endl;
                cout<<setiosflags(ios::fixed|ios::showpoint|ios::left);
for(int i=0;i<n;i++){
                if(e[i].fname!=" "){                              
cout<<setiosflags(ios::left)<<setw(15)<<e[i].fname<<setw(15)<<e[i].lname;
cout<<setprecision(2)<<setiosflags(ios::left)<<setw(10)<<e[i].hourlyrate;
                cout<<setw(10)<<e[i].hoursworked<<setw(10)<<e[i].netpay;
                cout<<resetiosflags(ios::left)<<endl;}//IF
                }//FOR
}//THIS FUNCTION DISPLAYS ALL RECORDS IN ARRAY
 
int search(string s){
                for(int i=0;i<n;i++)if(s==e[i].lname)return i;//FOR
                return -1;
                }//SEARCH BY NAME,-1 NOT FOUND
 

Text Box: void update(){
                string searchn;
                cout<<"Enter the Last Name of the Employee to be modified: ";             cin>>searchn;
                int i=search(searchn); 
                if(i==-1) cout<<"EMPLOYEE NOT LISTED"<<endl;
                else{
                cout<<endl<<"Please enter the updated information."<<endl;
                cout<<"Enter employee's first name: ";          cin>>e[i].fname;
                cout<<"Enter employee's last name: ";           cin>>e[i].lname;
                cout<<"Enter employee's rate per hour: ";      cin>>e[i].hourlyrate;
                cout<<"Enter employee's hours worked: ";   cin>>e[i].hoursworked;
                e[i].netpay=(e[i].hourlyrate*e[i].hoursworked);}
                }//UPDATE
 
void deleterec(){
 string searchn;
 cout<<"Enter the Last Name of the Employee to delete: ";  cin>>searchn;
 int k=-1;
 for(int j=0; j<n;j++){
  if(searchn==e[j].lname)
     k=j;}
 if(k!=-1)
 { cout<<" Name: "<<e[k].fname<<" "<<e[k].lname<<endl;
   cout<<" Salary: "<<e[k].hourlyrate<<endl;
   cout<<" Hrs Worked: "<<e[k].hoursworked<<endl;
   cout<<" Net Pay: "<<e[k].netpay<<endl<<endl;}
                 
 char ans;
 cout<<endl<<"Do you want to delete this record? (Y/N): ";
 cin>>ans;
 if(ans=='Y'||ans=='y'){
                e[k].fname=" ";}//IF
else cout<<"EMPLOYEE NOT FOUND";     }//DELETE
 
void report(){
 int i=0;
 double totalhrs=0.00, totalpay=0.00;
 for(i=0;i<n;i++){
 totalhrs+=e[i].hoursworked;
 totalpay+=e[i].netpay; }//FOR
 cout<<"Total number of employees: " <<n<<endl<<endl;
 cout<<"Total hours worked by all employees: "<<totalhrs<<endl<<endl;
 cout<<"Total pay of all employees: "<<totalpay<<endl<<endl;   }//REPORT
 
                               

 

 

 

 

 

 

 

 

Text Box: void deletefile(){
 int pword;
 cout<<"Enter your administrative password: ";  cin>>pword;
 if(pword==5438){
 ofstream record("employee.txt", ios::out);
 record<<endl;
 load();
 record.close();}
 else cout<<"Wrong password entered."<<endl; }//DELETE FILE
 
void backupfile(){
  system("copy employee.txt backup.txt");
  cout<<endl<<"Back-up file has been made."<<endl;
}//BACKUPFILE  use cp command for UNIX
 
int main(){
                load();
                char choice;
                while (choice!='e'&&choice!='E'){
                cout<<endl<<"Payroll Database"<<endl;
                cout<<"1. Insert Employee Record and Compute Net Pay"<<endl;
                cout<<"2. Display All Records"<<endl;
                cout<<"3. Search Database"<<endl;
                cout<<"4. Update Record"<<endl;
                cout<<"5. Delete Record"<<endl;
                cout<<"6. Generate Report"<<endl;
                cout<<"7. Delete Database File"<<endl;
                cout<<"8. Back-up Database File"<<endl;
                cout<<endl<<" Type e to exit"<<endl<<endl;
                cout<<"Enter the number of your choice:";
                cin>>choice;         cout<<endl;
                switch (choice){
                 case '1': insert(); break;
                 case '2': display(); break;
                 case '3': char s[100]; int index;
                                cout<<"Enter the last name of the person you want: ";
                                cin>>s;
                                index=search(s);
                                if(index!=-1) {
                                cout<<"Name: "<<e[index].fname<<" "<<e[index].lname<<endl;
                                cout<<"Hourly Rate: "<<e[index].hourlyrate<<endl;
                                cout<<"Hrs Worked: "<<e[index].hoursworked<<endl;
                                cout<<"Net Pay: "<<e[index].netpay<<endl<<endl;}//IF
                                else cout<<"EMPLOYEE NOT FOUND"<<endl;
                                break;
                 case '4': update(); break;
                 case '5': deleterec(); break;
                 case '6': report(); break;
                 case '7': deletefile(); break;
                 case '8': backupfile(); break;
                 case 'e': store(); break; //EXIT
                 default: cout<<"Invalid Choice"<<endl; break; }//SWITCH
}//WHILE
               return 0;
}//MAIN
 
                Figure 20.38a – A simple C++ database

Text Box: Payroll Database
1. Insert Employee Record and Compute Net Pay
2. Display All Records
3. Search Database
4. Update Record
5. Delete Record
6. Generate Report
7. Delete Database File
8. Back-up Database File
 
 Type e to exit
 
Enter the number of your choice:1
 
Enter employee's first name: Alireza
Enter employee's last name: Ebrahimi
Enter employee's salary per hour: 55.00
Enter employee's hours worked: 50
 
Payroll Database
1. Insert Employee Record and Compute Net Pay
2. Display All Records
3. Search Database
4. Update Record
5. Delete Record
6. Generate Report
7. Delete Database File
8. Back-up Database File
 
 Type e to exit
 
Enter the number of your choice:2
 
First Name     Last Name      Hourly Rate     HrsWorked    Net Pay
 
John               Taylor             50.00                48.00             2400.00
Jean               Doe                 50.00                42.00             2100.00
Alireza          Ebrahimi         55.00                50.00             2750.00
 
Payroll Database
1. Insert Employee Record and Compute Net Pay
2. Display All Records
3. Search Database
4. Update Record
5. Delete Record
6. Generate Report
7. Delete Database File
8. Back-up Database File
 
 Type e to exit
 
Enter the number of your choice:e

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

               

 

 

 

 

                Figure 20.38b – Output of Figure 20.38a

 

 

JAVA DATABASE EQUIVALENT TO THE C++ DATABASE

 

The following Java database program demonstrates how your knowledge of C++ will help you to write Java applications. You will realize that the control structures are the same (while, if/else, for); however, there are differences in java file handling and user input. File handling in java is a little more complicated due to the class nature of the file. Input from the keyboard has to be parsed into the desired format. There are two stages of compiling Java programs: compilation and interpretation. The compilation of the .java file creates a .class bytecode file that can be interpreted in virtually any platform (Virtual Machine). One of the benefits of Java is its portability and its ability to create applets that can be run on browsers. Java does not have pointers and applets cannot directly access files due to security restrictions. To read input or values, StreamTokenizer is used to read either a string (sval) or a number (nval) as instance variables. The Cin class is used for input from the keyboard and once it is compiled, the class can be used in other applications as long as it is in the same directory.