1
Chapter 1: Basics For Beginners
2
4. return 0;
1.1 Software requirements (Non-zero integers, eg -1 or 1, can be returned if you
intend to exit the program while indicating that an error
You will need the following to write C++ programs:
has been encountered.)
1. a text editor which is something like a word processor
5. close bracers, }
(like your notepad),
2. a compiler which is a piece of software that checks the
source code for errors and converts it into a piece of code 1.2.2 Displaying a simple message
known as object code,
3. a linker another piece of software that takes the object It is a great morale booster if you could display something, in fact
code and uses it to join together ready-made low-level anything, on the computer screen. So for the sake of your morale,
routines to produce the executable code that will run on lets write a program that displays Hello world!.
the computer.
Let me introduce to you:
You do not have to worry about installing each piece of software std::cout sends data to the screen
separately if you install Microsoft Visual C++. All items are << known as the insertion operator and inserts anything
bundled together. This is called an integrated development that follows it into the output stream.
environment (IDE). std::endl end of line. Alternatively, may be replaced with
\n
// comments or remarks for the programmer. The C++
compiler ignores the comments.
1.2 C++ Basics
Listing 1.1
1.2.1 General layout of program My first C++
program! #include <iostream>
A += B++; s.h. A = A + B;
1.2.7 String of Characters
B = B + 1;
Use char to initialize a single character:
A += ++B; s.h. B = B + 1;
A = A + B; char a_letter = A;
1.2.6 Arrays and a string of characters well, there are two ways of doing so:
However, before you can use the strcpy command, you need to 1.2.7.2 Using a char pointer
first include the string.h header file:
The second way to initialize a string is to use a char pointer
#include <string>
variable:
If you include string, you can also make use of several helpful
char *boy = Peter;
string related functions such as
A pointer variable is recognized by the asterix * sign. So the
strcpy(girl, Jac);
variable boy is essential a pointer variable. However pointer is the
Reads as string copy.
subject of Chapter 2. Here, you will be shown how you can use a
Copies the string Jac into the variable, name.
char pointer to assign string values.
Command will overwrite previous values, if any.
strcat(girl, , Jill);
char *boy; // Declare variable first
boy = Peter; // Assign value after declaration
char str1[20];
When using char pointers to assign string values, you do not need char *str2;
to include the string.h header file. Moreover, you cannot use the str2 = Bye;
strcpy(str1, str2);
strcpy command to assign a value to the variable in the same
manner as a char array would.
Do you know you can strcat str2 with str1 but not the
other way around?
1.2.7.3 Examples
char str1[20];
char *str2;
boy deals with pointers, while girl deals with arrays, both of strcpy(str1, Hello);
which we will cover in greater detail later. As for now, just str2 = World!;
remember these two methods of assigning string values. strcat(str1, str2); // OK
strcat(str2, str1); // NOT OK!!
Listing 1.2
Be patient. You will be told the answer of this mystery when we
#include <iostream> study pointers in Chapter 2.
#include <string>
using namespace std; // to simplify std::cout 1.2.7.4 Using string
// and other std:: functions
main() {
char str1[20]; C++ provides the string class library to handle a string of
char *str2; characters elegantly. After including <string> header file, you
strcpy(str1,"Hello"); can declare a string variable and use it with little fuss, because the
str2 = " World!"; burden of memory ownership is transferred to the string class
cout << str1 << str2; rather than the programmer (i.e. you!).
return 0;
} Listing 1.3
#include <iostream>
The text Hello World! will be displayed on screen. #include <string>
Do you know you can assign str1 to str2 and vice versa? using namespace std;
#include <iostream>
Alternatively, a more efficient way to safeguard from lower-case
#include <ctype.h>
vowel inputs is to simply upper-case a_character with the using namespace std;
command toupper that is provided by the string file:
main()
switch(toupper(a_character)) {
{ float num1, num2;
case A: cout << A<< endl; char choice;
break; cout << "Welcome!\n";
... sum2numbers: // this is a label
} cout << "\n\nEnter two numbers";
cout << " and I will add them up\n";
When dealing with integers, the case conditions omit the single cin >> num1 >> num2;
quotes . cout << "The sum is " << (num1 + num2);
tryagain: // this is another label
switch(a_number) cout << "\n\nDo you want to try again?";
{ cout << "\n'Y'es or 'N'o\n";
case 1: // case 1:, not case 1: cin >> choice;
cout << Its a 1!; if (toupper(choice) == 'Y')
break; {
case 2: cout << Its a 2!; goto sum2numbers; // goto a label
break; }
... else if (toupper(choice) == 'N')
} {
cout << "\nThank you!\n";
}
else
{
1.2.11 goto labels goto tryagain; // goto a label
}
return 0;
}
Chapter 2: Simple Pointers And Functions
Pointers are often confusing to programmers of all levels, of this space. Subsequently, the integer value 9 that will be
especially beginners. Usually programmers run away (screaming) converted into binary format occupying 32 bits, i.e., 0000000
when I ask them about pointers. Such extreme response has since 00000000 0000000 00010001 is inserted into this memory
served as a constant reminder for me to very cautiously pace space.
myself when I teach pointers.
int x
32 bits (4 bytes) that carry the integer 9.
2.1 Introduction
0 0 ... 0 0 0 0 0 0 0 1 0 0 0 1
C++ gives the programmer (you) the power and flexibility to
control the way the memory of the computer is utilized as being 1st byte of x
instructed by your C++ program. In the olden days when RAM or
memory is significantly more expensive, this task of coding This 32-bit memory space has an address so that the computer may locate the
efficient programs is of utmost importance. However, careful variable x when required. For example:
memory management can be extremely tedious. Thankfully RAM 0x0012FF7C.
nowadays is much cheaper than before and we can be more relaxed The address points at the first byte of the memory space.
with memory management. However careless programming will
certainly result in disastrous consequences such as computer
hanging due to out of memory!
2.1.2 Understanding pointers
2.1.1 Understanding and managing memory Let me introduce to you
* (asterix) pointer
Lets try to understand what takes place in the context of the & (ampersand) 1) address of, or
memory of your computer when you enter the following 2) reference (depending on context)
instruction:
While you can declare and initialize an integer as in 2.1.1., you
int x = 9;
may also choose to declare a pointer variable that points to that
integer. Pointing to actually means that the pointer variable is
The declaration int x instructs the computer to find and allocate
going to store the address of the integer, which is 0x0012FF7C,
32 unused bits (NB: An int data type is allocated 4 bytes which is
and not the integer value 9. A pointer variable is declared as
32 bits; a char 8 bits; and a double 64 bits). This memory space
follows:
that is allocated to x has an address which points at the first byte
int *ptr_x; cout << *ptr_x;
Example of how it should be used: *ptr_x = 10;
int x = 9; (1) and not ptr_x = 10;! (Remember that ptr_x stores the address
int *ptr_x; (2) of x, and not the value x). You can however type
ptr_x = &x; (3)
std::cout << ptr_x;
Lets explain the codes above line by line.
Line Try it out for yourself and see what is displayed on the screen!
(1) x is declared as an integer (32-bits) and it is initialized Lastly, you should try the following codes to get a clearer picture
with a value of 9. Transparent to the programmer is the of what is happening:
allocation of 32 bits of memory space to x. The address
of this memory location is &x, read as the address of x. int x =9;
An example of &x is 0x0012FF7C. int *ptr_x = &x;
(2) An integer pointer variable ptr_x is declared. It will store
the address of an integer. cout << "Value" << "\t\t" << "Address\n";
cout << "x = " << x << "\t\t" << "&x = " <<
(3) ptr_x now stores the address of x, &x. In other words,
&x << endl << *ptr_x = " << *ptr_x <<
ptr_x points to x. "\t" << "ptr_x=" << ptr_x << endl;
What you should remember NOT to do is: This is what you will get:
int *ptr_x = 10; // Wrong!
int *ptr_x;
ptr_x = 10; // Wrong! 2.2 Arrays are Pointers?!?
which is wrong because ptr_x should have been the address of x, Yes, there is a subtle relationship between pointers and arrays. You
not the value of x. What you should do instead is to establish a might have noticed it when I introduced two methods of declaring
valid address of an integer first: a string: using a char array and using a char pointer.
int x = 9; The following instruction
int *ptr_x = &x; // Correct!
int arr[10] = {88,99,101};
Examples of accessing (retrieve or modify) x via its pointer
variable include:
declares an integer array called arr of size 10 and initializes it So what are the outcomes of the following codes? Go on, try it!
with 3 elements of type integer, leaving the remaining 7 elements
zero-initialized (yes, they are stored with 0s). cout << *arr+1;
IMPORTANT: and
Typing arr by itself actually means you are retrieving the address cout << (*arr)+1;
of the array, and not the contents of the entire array! Try it if you
do not believe me. Because both pointer variables and array variables store
addresses, you can assign one array variable to another pointer
cout << arr; variable (assignment is done using the operator =):
will produce an address which looks something like 0x0000FF24. int arr[10] = {88,99,101};
int *ptr_arr;
This address marks the beginning of the array arr, which
ptr_arr = arr;
coincidentally is also the address of the first element of the array
arr, i.e., the integer 88. Do not code ptr_arr = &arr; as in line (3) in Chapter 2.1.2
because arr here is already an address. By now, I hope you wont
Since arr is an array, the contents of its elements can be retrieved be too surprised if I told you that
using the usual index system, where first element is indexed 0:
int *arr;
cout << 1st element of arr is : << arr[0];
and
cout << \n2nd element of arr is : << arr[1];
int arr[];
...
are equivalent , as long as the array size is unknown. Yes they are!
Since arr is also an address, the contents at the address arr can be
retrieved using a pointer! Recall that *arr points to the contents of
Once initialized, the contents of an array can be modified
arr, which turns out to be the first element of the array. To select
and accessed via array index as well as pointers:
which element to retrieve, you simply add the index to the address,
arr, and prefix with the pointer, *, as shown below: cout << *(arr+1);
and
cout << 1st element of arr is : << *arr; cout << arr[1];
cout << \n2nd element of arr is : << *(arr+1);
...
(arr + 1) is the address of the second integer element in array 2.2.1 Using sizeof() to determine the number of
arr. In our example, (arr+1) would be the address 0x0000FF28 elements in an array
since arr is 0x0000FF24 (the address location is increased by 4
bytes because an integer occupies 4 bytes of memory space). C++ has a built-in operator called sizeof that gives the sizes of
data types in bytes. You can use it on both variables and data types:
int x = 9; or equivalently
cout << sizeof(x) << endl;
// variable x: 4 bytes cout << There are <<
cout << sizeof(int) << endl; sizeof(arr)/sizeof(arr[0]) << elements.;
// data type int: 4 2.2.2 Answer to Question in Chapter 1.2.7
Now it can be used to determine the number of elements in an
Iin Chapter 1.2.7, you were asked why can you only strcat str2
array. If you can correctly guess the output of the following codes,
with str1 but not the other way around?
then I am sure you will have no problems understanding how to
determine the array size: char str1[20];
char *str2;
double arr[10];
strcpy(str1, Hello);
double *ptr_arr = arr;
str2 = World!;
cout << sizeof(*arr) << endl; // 8
strcat(str1, str2); // OK
cout << sizeof(arr) << endl; // ? (1)
strcat(str2, str1); // NOT OK!!
cout << sizeof(ptr_arr) << endl; // (2)
ANS: str1 is an array with pre-allocated memory space large
In line (1), arr is used to represent the entire array although it also
enough to store 20 characters. str2 on the other hand is
holds the address of the array. Therefore sizeof(arr) will return
declared as a pointer variable and has just enough space to
80 (bytes) since a double occupies 8 bytes of space and there are
store the word World!. Appending World! behind
10 of them.
Hello is OK because of the extra space str1 has, but
appending to str2 is disallowed because str2 has just
In line (2), ptr_arr being a pointer variable, does not actually
enough space for itself.
know the size of the entire array it is pointer to. Its content is the
address of arr which occupies 4 bytes. Therefore, rather
surprisingly, line (2) yields 4 and not 80. 2.3 Functions
Thus, to determine the number of elements in an array, write:
2.3.1 What is a C++ function?
cout << There are <<
sizeof(arr)/sizeof(int) << elements.; In the context of C++, a function is a couple of lines of C++
instructions bundles together under one unique name. For example,
Since all arrays will at least have one element, you can also use the using a layman example, a series of instructions:
following codes:
Fry fish
cout << There are << Steam chicken
sizeof(arr)/sizeof(*arr) << elements.; Stir fry vegetables
Boil soup int ans = n;
Serve with rice for (int count = n 1; count>=1; count--)
{
can be bundled under the function name PrepareMeal. Thus ans = ans * count;
}
when you want a meal prepared, you only need to instruct the
kitchen to PrepareMeal instead of giving 5 sets of instructions.
It saves even more time if you PrepareMeal everyday! 2.3.4 The anatomy of a function
One way of writing the factorial function is shown below.
1. A repeating task (factorial is performed twice) The task that a function performs usually depends on a certain
2. A recognizable pattern in that task (i.e., factorial): inputs. A factorial function would compute the factorial of n, n
being the input. To be correct, n is called the input formal
// Pattern to compute n! : parameter. Note the following when writing a function:
A function can return at most one value back to the program,
Place input parameter in parentheses, ( ), behind the sometimes none. You need to determine the data type of the value
function-name. that is being returned. Write this data type in front of the function.
In factorial, the obvious return value is the resulting factorial, n!,
int factorial( <input parameter> ) which is an integer.
Specify the data type of input parameter. If there is no return value, you must indicate void.
Multiple input parameters are allowed. All parameters are 4. PLACE INSTRUCTIONS IN FUNCTION BODY
separated by commas.
int factorial(int n)
int factorial(int n, float m, char *c) {
int ans = n;
for (int count = n1; count>=1; count--)
If no input is required, either
{
leave blank within parenthesis (), or ans = ans * count;
write the word void in parenthesis, (void). }
return ans;
int factorial() }
OR
factorial(void) 5. OPTIONAL WRITE A FUNCTION PROTOTYPE
Input can have a predefined default value which will be A function prototype is just a single line of code that states the
used in case no input value is provided by the program. inputs and output of a function. It performs no action other than to
warn the compiler of what to expect later in the function definition.
int factorial(int n = 2) Prototypes are optional but are recommended so that correct type
checking for arguments (i.e., values, constants, pointers, etc) and
New variables are declared according to the input parameter return values is enabled. In other words, it is used to check if the
list. However, they only exist within the local scope of the number of arguments and their data types in the calling function
function. They will be destroyed at the end of the function. correspond to the number of parameters and their types in the
called function when the function is called. A prototype contains
the header of a function without the detailed instructions found in
3. DETERMINE ITS RETURN TYPE the function body.
I recommend writing a function prototype before the start
int factorial(int n) { ... } of the main program. They are also usually written in a separate
header .h file.
}
Example of the factorial function prototype (remember semicolon):
// main() body Program entry point
int factorial (int n=2); // Calculate {[(5! + 1)! + 2]! + 3}! + 4
main()
{
2.3.5 Using functions to simplify complex tasks int result1, result2, result3, result4;
result1 = factorial(5,1);
An example to show why using functions can really simplify result2 = factorial(result1,2);
complex tasks: result3 = factorial(result2,3);
result4 = factorial(result3,4);
Lets say your math lecturer for no reason turned evil (forgive me, cout << The answer is << result4;
Mr Koh!) and assigned you a really tough question: return(0);
}
Find {[(5! + 1)! + 2]! + 3}! + 4.
Here a repeating task is observed. The pattern is not merely a 2.3.6 Nested functions
simple factorial of n!, but it the the sum of this factorial and
another integer. The resulting pattern is therefore n!+m. The Experienced programmers will find the above program in Listing
codes to compute the above expression is given in Listing 2.1. For 2.1 a little long-winded. They prefer to write nested functions to
the sake of simplicity, I will not rename this new function that reduce usage of unnecessary variables which may confuse readers.
computes n!+m, but instead reuse the name factorial. The following program uses nested functions in a way where the
operation is identical to the previous program.
Since it is essentially an address that is being manipulated in the screen displays the contents of the first element in x, i.e., 7. If it is
function, incrementing the address by 1 simply points to the x[0] that you are passing, then the input parameter is simply an
second element of the array. The address of the second element is integer, not a pointer.
returned via a pointer variable.
struct car
Case 3: {
When passing arrays and pointers char number_plate[10];
int year_of_manufacture;
Since arrays are always passed as pointers in function calls, input float engine_cc;
parameters like int *ptr and int arr[] are not distinguishable as bool transmission;
far as the signature is concerned. The following is the example // true for auto, false for manual
};
taken from Listing 2.4.
private: main()
{
protected: Complex c_num;
}; // Note semicolon
cout << "\nAssigning new value : ";
// ==== Member functions of Complex ==== c_num.real=2;
void Complex::showNumber(void) c_num.imag=5;
c_num.showNumber(); members written under the private: can only be accessed by the
host object only, i.e., c_num only (not even objects created from
cout << "\nIts magnitude is : "; the same class, e.g., c_num2, c_num3), while members written
cout << c_num.magnitude() << endl;
under the public: section can be accessed by everybody
return(0);
}
(anywhere in the program). For now, just write every member
under public since it has the widest access.
You can use the dot notation to access public data members /*
and member functions of c_num: Static member initialization is written straight after class
{}; Dont forget to write Complex::
c_num.real=2; */
c_num.imag=5; int Complex::cnum_count = 0;
and The following program demonstrates the usefulness of a static data
member. It is similar to Listing 3.1 except with the inclusion of the
c_num.showNumber(); // Displays 2+5i tatic cnum_count has been included:
cout << c_num.magnitude() << endl;
// Calculates magnitude of 2+5i and displays
Listing 3.2 Complex class with static members
Finally, when the code return(0); is executed, C++
automatically destroys all objects created earlier. Before c_num is #include <iostream>
destroyed, the destructor function, Complex::~Complex(), is #include <math.h>
first called. This is why you get the final screen output. using namespace std;
class Complex
{
public:
double real, imag;
static int cnum_count;
Complex();
~Complex();
3.3 Static Members };
Sometimes there might be certain information that you would want int Complex::cnum_count = 0;
to retain throughout the program. For example, you may want to
Complex::Complex()
keep count of the total number of existing complex number objects
{
in your program. In such a case, you need to declare the integer cnum_count++;
static within the class. For example: // At object creation, cnum_count is incremented
real = 0;
class Complex imag = 0;
{ cout << There is(are) now <<
public: cnum_count << complex number(s).\n;
double real, imag; }
Complex::~Complex()
{
cnum_count--;
// At object destruction, cnum_count is
// decremented
cout << cnum_count;
cout << complex number(s) left.\n;
}
Complex::Complex(Name& n):c_name(n) Even though you may survive without a destructor, good
{ programming practice encourages destructors be written. It is
// ... because when an object is created, the amount of available
}
memory decreases. Therefore when the object is destroyed, the
destructor should release the memory appropriately. Failure to do
You have a data member which is declared const but has no so will result in memory leak.
value yet.
class Complex
{
private: 3.4.4 A small task
const int max_count;
// ... By the way, for the sake of beautifying the output as good
}; programmers like to do, can you rewrite the showNumber()
function so that for negative imaginary numbers, instead of
Complex::Complex():max_count(99)
{ displaying, say, 5+-2i, it will display 5-2i?
// ...
} Sample Solution (give it a try first before peeking at answer):
void Complex::showNumber(void)
{
cout << real << (imag<0 ? "-" : "+")
3.4.3 Destructors << (imag<0 ? imag*-1 : imag) << "i";
}
Destructor functions are called when the object is being destroyed
or deleted from the computers memory. For example at the end of
the program when return 0; is executed. The purpose of the 3.5 Can I Have Pointers For Objects Too?
destructor is to allow the termination of an object in an orderly
fashion. It is declared in the same fashion as the constructor except
YES! There...
double x, y;
Complex c_num(4,5); x = c1->getReal() - c2->getReal();
Complex *p = &c_num; y = c1->getImag() - c2->getImag();
return sqrt(x*x + y*y);
}
3.5.1 Accessing Members
And this is how you access the members of c_num via its
pointer: 3.5.2 Object Arrays
p->showNumber(); Remember that an array is essential a pointer too (because an array
(*p).showNumber(); is represented by an address, just like pointers)! Let me show you
one way of finding the distance between two complex numbers
They are both equivalent. C++ provides the member accessor which are now stored in an array. Remember that this is just one of
operator -> for pointers so that you do not have to type * in order many ways to get the job done!
to retrieve the contents of c_num. Check out the following
example program that calculate the distance between two complex main()
numbers: {
Complex c_arr[2];
Listing 3.4 Complex class with pointers Complex c_num1(1,1), c_num2(4,5);
c_arr[0] = c_num1;
c_arr[1] = c_num2;
cout << "Distance is ";
// adopting the codes from Listing 3.3
cout << c_num1.calcDist(c_arr);
// An address is passed into calcDist
main()
return 0;
{
}
Complex c_num1, c_num2;
Complex *p1, *p2;
double Complex::calcDist(Complex *c_arr)
p1 = &c_num1;
{
p2 = &c_num2;
Complex c_dist( (*c_arr).getReal()
p1->setValue(1,1);
(*(c_arr+1)).getReal() ,
p2->setValue(4,5);
(*c_arr).getImag()
cout << "Distance is ";
(*(c_arr+1)).getImag() );
cout << c_num1.calcDist(p1, p2);
return 0;
Complex *c_ptr = &c_dist;
}
return c_ptr->magnitude();
double Complex::calcDist(Complex *c1, Complex *c2)
}
{