"I think computer
viruses should count as life. I think it says
something about human nature that the only form of life
we have created so far is purely destructive.
We've created life in our own image."
- Stephen W. Hawking
Note: When I put
these tutorials together a few years ago, I used Microsoft's
Visual C++ 6.0. I attempted to keep all the console
program code in as generic a format as possible, so that you
would be learning generic C++. This way, what you learn
will be applicable to Unix/Linux and the GCC compiler, Borland's
compiler, and Microsoft's Visual Studio. Since that time,
Microsoft has changed several things with the .Net Development
Studio, and several functions have been deprecated. However, you
may still use Microsoft's Visual C++ .Net Development
Environment provided that you create an "empty .Net" project
from within the application, and you must change every line you
see that says "#include <iostream.h>" to "#include <iostream>".
You must also add the line "using namspace std;" beneath this
changed include line, else you will have to call functions and
classes using two colons such as "std::cout" and "std::cin".
Rather than change these examples, I will leave them as they are
for those using Visual C++ 6.0, Linux's gcc compiler, or other
non-.Net compilers. However, if you are using .Net, add
these to lines to each example in these tutorials to make them
compatible with .Net, replacing the single "#include <iostream.h>"
line:
#include
<iostream>
using namespace std;
// Rest of the program goes here,
// minus the old C++ 6.0
// "#include <iostream.h>".
If using VS 6.0, in order
for the getline() function to work properly without requiring an
extra "ENTER", make sure
you go to
\Program Files\Microsoft Visual
Studio\VC98\Include, find the file "string" (NOT "string.h"),
go to line 165 in notepad, and change
_I.rdbuf()->snextc();
to _I.rdbuf()->sbumpc();.
Microsoft never fixed the bug and shipped the compiler with it
broken. Instead of .Net Studio or VS 6.0 which you have to pay for, I
recommend
BloodShed 5.0, which is an
excellent compiler and completely free for you to
download. It's based on the Linux open source gcc compiler.
A. Introduction
1. Object Oriented vs. Procedural Languages C++, like Java, is object oriented, and it is just one tool
among many for today's developers. It's primary advantage
over other languages is that it can produce software with
greater power, speed, and efficiency. It gives the
developer far more control over memory management than other
languages. It's disadvantage is that it is less forgiving
and more complex than other OOP languages that manage memory
automatically. This greatly increases development time.
Many projects can be developed faster in other languages, at the
cost of efficiency in the finished application. In
choosing this language to develop in, one needs ample time and
resources.
One of the things that
sets C++ apart from C is its use of classes and structures, which
provide "encapsulation", whereas procedural languages such as
C or FORTRAN would use functions in a more linear fashion. Object
oriented languages attempt to emulate real world systems and structures
more closely that procedural programming. In the past computers weren't
as powerful and memory was very expensive. As a result, programs were
largely console or command prompt based (i.e. DOS, Unix without X
Windows). Software was written in a linear and procedural manner, to
optimize efficiency when running on slow processors and to squeeze every
available iota of usefulness out of limited, paltry and expensive
amounts of memory. Rich multimedia, power and vast capabilities weren't
as important as simply coding something that could run on a bare minimum
of hardware.
2. Moore's Law
Over time, computers exponentially increased in speed and sophistication
in fulfillment of Gordon Moore's "Law of Accelerating
Returns", theorized in 1965. Moore's Law predicts that the number
of transistors per integrated circuit doubles every 18 months. Doubling
transistors effectively means doubling the binary on/off calculations
per second in the same amount of space using the same amount of raw
material. This miniaturization and resource efficiency both increases
speed and lowers the cost of production. Each cycle of development in
technology feeds the subsequent wave, yielding an exponential increase. To illustrate this concept, look at a brief history of technology:
1822 - Charles Babbage, "The Difference Engine"
1832 - Charles Babbage, "The Analytical Engine", 1st
computer though never worked
1843 - Ada Lovelace, 1st programmer, Speculates on a
computer's ability to emulate human intelligence.
1871 - Charles Babbage dies.
1877 - William Thomson (Lord Kelvin) demonstrates
computers can be programmed
1927 - Heisenberg's uncertainty principle. 5 Years
later Quantum Mechanics by Neils Bohr and Werner
Heisenberg.
1928 - Minimax theorem, Jon Vann Neumann, used in
game programs.
1928 - 1st television
1930 - 60% all houses have radio
1931 - incompleteness theorem
1931 - electron microscope
1937 - Alan Turing, Turing Machine
1937 - Turing and Church state that all problems
that human can solve can be reduced to set of
algorithms solved by machine
1940 - "ABC", 1st electronic non-programmable PC.
1940 - "Robinson", 1st operational computer, uses
electro-mechanical relays to decode ENIGMA in WWII.
1941 - Z3, 1st programmable digital computer.
1943 - "Colossus", uses tubes 1,000 times faster
than relays in "Robinson". Decodes more German code.
1944 - "Mark I", Howard Aiken, uses tubes and punch
paper for programming, 1st programmable built by
American.
1945 - Stored program concept published.
1946 - ENIAC, 1,000 times faster than Mark I, 1st
electronic, programmable, general-purpose computer.
1946 - .02% of Americans own TV
1947 - transistor invented
1949 - EDSAC, 1st stored-program computer
1949 - George Orwell's "1984"
1950 - Alan Turing presents "Turing Test"
1950 - color TV 1st broadcast, B and W TV now
trans-Atlantic
1951 - EDVAC, 1st computer to use stored-program
concept
1952 - UNIVAC, owned by CBS television, successfully
predicts election of Eisenhower
1952 - IBM 701, 1st computer for mass production
1953 - chemical structure of DNA
1955 - William Shockley Semiconductor laboratory
founded starting silicon valley
1955 - U.S. Develops 1st design for industry robot
1955 - IPL II, 1st AI language
1956 - "The Logic Theorist", uses recursive search
techniques
1956 - FORTRAN invented
1956 - MANIAC I, 1st computer to beat a human at
chess
1956 - term "Artificial Intelligence" coined
1957 - General Problem Solver, uses recursive search
to solve problems
1958 1st integrated circuit
1958 - LISP, AI language created
1958 - CDC 1604, Seymour Cray, builds 1st full
transistor supercomputer.
1959 - computer beats humans at checkers
1959 - COBOL developed
1959 - 1st Xerox copier
1960 - 1st laser, ruby rod
1960 - 6,000 computers in operation in the US.
1956 - 72% of homes have television
1983 - 93% of homes have television
Note:
You can see that
technological advances increase exponentially and
algorithmically. Each advance increases the velocity of
subsequent advances. Since 1983 we have seen technology literally
consume, envelop and re-define the world around us. We can only assume
that as all branches of science and technology continue to build upon
the works of others, computer technology will continue to transform our
lives in ways we can't even imagine, and that these changes will occur
at an ever-increasing velocity. How many of us have experienced the
bitter sorrow of purchasing the fastest CPU or some ultimate piece of
computer hardware, only to find that before we can carry it home and
take it out of the box there's something even more powerful, compact,
faster and cheaper being advertised in the evening newspaper?
3. Event-based Programming and Input Today, most popular operating system environments employ a graphical
user interface (GUI) such as are Microsoft's "Windows" and
Linux's/Unix's window manager, "X Windows". Both of these
popular environments provide for "event based" input in a
program. Event based input is random and unpredictable input. A user no
longer has to follow a linear path of commands typed at a command prompt
to access a particular part of a program. She or he can now, randomly
and at will, access any part of a Windows or X Windows program from any
other part. Event-based input adds great power, versatility, and
functionality to a program for the user. For the programmer, it
adds its own share of problems. Unpredictable sequences of events from the user must be
foreseen and accounted for in the debugging process. Windows and X
Windows graphical user interfaces, event-based input, continuous
production of faster and more powerful computers that are less and less
expensive, and object oriented programming have all combined to make
possible the creation of software of a complexity never before imagined.
Artificial Intelligence (AI) is not
as flamboyant in reality as it has been portrayed in
science-fiction, but it is already very much a part of our
lives. One can only look with wonder at the evolution of
neural networks, global data structures and intelligent search
engines, such as
Google and
AskJeeves. AI, only a LISP fantasy thirty years
ago, is infiltrating every aspect of modern software as routines and
subroutines become more and more complex in our attempt to develop
software that is easier to use, intuitive and forgiving of our mistakes.
AI techniques are employed in our databases and in our spreadsheet and word
processing software. They are employed in modern
development environments. They are used in all of the
latest and most popular games. AI routines are largely made possible by object oriented
programming, which is well adapted to deal with the increasing complexity of
AI techniques used in large, complex pieces of software composed of hundreds of
thousands of lines of code.
If
It Interests You:
The fundamentals of AI will not be covered in this course.
However, it may spark your interest and be something you choose
to pursue on your own out of curiosity. It is a realm
of discovery and controversy that sparks moral, ethical, scientific,
and pragmatic debate among all those who pursue it.
Minds as great as the world renown physicist,
Stephen Hawking, foresee
AI as a threatening menace to humanity. Others, such as
Bill
Gates and
Ray Kurzweil, see it as the
ultimate destiny of mankind to merge with his technology.
Gates expresses his own ideas concerning this subject in the
book, "The Road Ahead". In Kurzweil's book, "The Age of Spiritual Machines" - 1999, Kurzweil defines 3 methods increasingly utilized, sometimes
simultaneously, in creating artificially intelligent software.
Lets look at these three using the example of a chess game:
1. Recursive Algorithms -
Recursion involves taking a large and complex problem and
reducing it repetitively into smaller and smaller sets of
tasks. Iterations in a recursive algorithm may take
the form of simple formulas that use the massive calculating
potential of today's CPUs and memory (brute force). A
recursive algorithm includes itself as part of its algorithm.
It is a function that invokes itself, and an object that
creates an instance of itself by its own construction.
Logistically, it says
"For my next step take my next best step. If I'm done I'm
done." You can calculate the many permutations possible in a chess game
by following simple rules: "Pick my next best move. If I win, I'm
done". Functions keep calling themselves in an ever-expanding TREE of
moves and counter-moves that, with enough raw computing power, can
fathom all possible moves on the chess board
at each step of the game. If a move results in a win, the routine picks that move. If
a winning move is unavailable,
but a tie is, then select that move. If neither a win nor a tie is
available, keep playing until the player
wins or a possibility opens for a win or tie. This technique
requires an escape mechanism (perhaps a sentinel value) telling
the program when to abandon recursive expansion and a
clear CODING of the problem.
2. Neural Net Algorithms -
Neural nets must be taught, they must learn. Neural
nets recognize patterns and relationships. They build
strong and weak associations regarding data and unexpected situations
by assigning and remembering a set of values for each
experience. These values can be complex objects or
numerical in nature. A neural net is always asking
itself, "On a scale of 1 to 10, based on the data and
history I have acquired, how likely is this pattern to
occur? How dangerous is this situation?" It then
answers itself, "7 times out of 10, this is what occurs."
These algorithms are built on the premise that, sometimes
the easiest and most efficient way to learn the right way of
doing something, is to do it the wrong way a few times.
They make associations over
time. This involves "layers" and "training" the neural
net. As with human beings, the amount of time spent learning and training directly affects
the
performance of neural net AI. It mimics a human being's sense of
intuition and wisdom, acquired through interaction and
experience with its environment. Though elementary
today, neural nets, when combined with recursion, show great
promise in the future. In our chess game, the neural
net algorithm will start off much as a child would -
helpless against the player. But after each subsequent
game it plays, it stores with flawless memory each move of
each player. It categorizes and analyzes each move
that led to a win, a tie or a loss. The moves that
lead to wins are given stronger values, the moves that lead
to losses are given weaker values. It will then select
the moves given stronger values for each subsequent game.
It thus learns from every opponent that plays it, eventually
selecting moves that allow it to win.
3. Evolutionary Algorithms - Evolutionary
algorithms create massive amounts of small
programs, functions or objects focused on a certain specified task.
They are allowed to change and adapt, in much the same way
that modern computer viruses and worms (Melissa.vbs, Lion,
Happy.exe, etc.) adapt when released. They enhance
themselves and
multiply when successful through adaptation, they eliminate themselves
when unsuccessful. These techniques utilize aspects of Chaos Theory,
recursion and fractalization. The randomness in the environment becomes fodder for change.
You can find a good deal of information on virus and
antivirus routines online at websites such as
Astalavista.com. You may watch their
evolution taking place before your eyes. A word
of caution - programmer beware! Evolutionary
algorithms can be unpredictable, especially in the form of
computer viruses, and the experimenter may get more than he
or she bargains for. Principles to follow are, "Do no
harm", and one must think in terms of containment.
What one person considers a harmless practical joke or an
experiment can be considered by others as a threat to
society or even an act of terrorism, and many careers have
been ruined by one single careless act of poor judgment.
In this third example, many chess routines of different
algorithms would be written and allowed to compete against
players and one another. They would include within
their instruction set implicit functions providing for
random adaptation to their environment. As the
routines are allowed to run, some would become successful
whereas others would fail miserably. The ones that
played most competitively would be allowed to continue and
adapt further, starting the process over. The ones
that were unsuccessful would be retired.
B. Basic Concepts
1. Pillars of object oriented development
1.Encapsulation- doing one well-defined thing completely.
This began with functions and methods, but C++ encapsulates
more completely by combining methods and data members into self-contained CLASSES.
Components should be built that have specific properties - a
developer should be able to plug them into his or her program as
needed. This treats data and procedures that act upon the data as a single
"object" - a self-contained entity with an identity and
certain characteristics of its own.
2.Data Hiding - The inner workings of classes should be hidden.
The prevailing philosophy for developing complex software is that you
don't need to know how all the library and foundation classes and precompiled code work, simply how to
use them. This enables adding complex functions and routines to code
without having to "re-invent the wheel", so to speak. It
speeds up development time through the use of encapsulated libraries of
code, functions and classes that each perform a specific task and snap
together in a "Lego-like" fashion. They are then used in
constructing larger and more complex bodies of code that incorporate
these functions and the whole becomes more than the sum of its parts. Data Hiding also provides greater security and flexibility by making it
possible to examine relevant portions of source code without seeing the
source in its entirety. Entire classes and libraries can be
utilized by parts of a program through passing arguments and
parameters to accessor methods.
3.Inheritance - Reuse, reuse, reuse! Don't reinvent the wheel. A
new type can be declared as an extension of an old type, a sub class of
an existing class, or derived types and classes from base classes.
In this way, methods and attributes can be incorporated into
derived objects without having to be repeated.
4.Polymorphism - different objects do
the right things through
function polymorphism and object polymorphism. It is multiple
inheritance, derivatives of the same object branching off
into many forms. This most closely models the "has-a"
and "is-a" relationship of the real world.
2. The Process of Compiling Source Code
compiler - produces an object file. linker - turns object file into executable program. LIBRARY = a collection of linkable files that were created,
inherent in an OS or purchased. FUNCTION = a block of code that performs a service, one or more
actions (adding 2 numbers or printing to the screen). CLASS = a collection of data and related functions. DEBUG = edit source code, recompile, re-link and rerun
Most compilers, such as Microsoft's Visual C++ Compiler combine the
functions and processes of building, compiling and linking along with a
set of standard library classes and functions into a single piece of
software. Design a program thoroughly before writing it. Begin by asking
"What problem do I need to solve?". Can this be accomplished
without writing custom software? There are many relevant libraries and
source code available for sale, many more are available for free. These
may save you countless heartache in your projects. Again, don't reinvent
the wheel. A prevailing philosophy in the Linux open source movement is
to stand on the shoulders of those who have gone before you, and allow
those who come after you to stand on your shoulders. There are large
amounts of source code on-line and libraries available that will perform
specific aspects of a program that you can simply add to your projects.
This can save lots of money and months of costly development time.
After source code is compiled an object file is produced (usually
named *.obj). Run your linker to create an executable program. C++
programs are created by linking together 1 or more object files with 1
or more library files. In Microsoft's Visual C++ 6.0, all of these
processes are integrated for you.
C. Your First C++ Program
Let's create our first C++ program. This will be a
"Console Program". We will use a simple color code in this
example. Red is for source code that is typed into the compiler and
compiled. Blue is for output rendered upon executing the compiled source
code. Since the traditional "first program" of any programming
language is one that outputs the phrase "Hello World", let's
create a short program in C++ that will render the output of "Hello
World" to the display. Follow these 14 steps:
1. Open Microsoft's Visual C++ 6.0. 2. Click "File" then "New". 3. Click "Win32 Consol Application". 4. Type "HelloWorld" in the field titled "Project
Name". Click "Ok". 5. Under "What Kind of Application Do You Want to Create?"
Check the "An Empty Project" radio button. 6. Click "Finish". A an alert box will pop up indicating your
selections. Click "OK". 7. Click "File" again and "New". 8. Make sure the "Files" tab is selected and click "C++
Source File". 9. In the field "File Name" type "HelloWorld". Click
"OK". 10. Type the following source code, exactly as shown, into the text
window:
Note: The compiler will color code what you type
by syntax as it recognizes each part of your program.
After typing in the source, we need to compile it.
So now follow these steps:
11. From the top
menu, select "Build" and then "Compile Helloworld.cpp".
Notice the display at the bottom. When the compiler is finished you
should receive the message "Compiling... HelloWorld.obj - 0 error(s),
0 warning(s)". If not, check your source code to make sure there
are no typographical errors. 12. Now that the program is compiled into object code, let's build and
link it. Do this by again selecting "Build" and then
"Build HelloWorld.exe". You should receive the message
"Linking... HelloWorld2.exe - 0 error(s), 0 warning(s)" if all
goes well. 13. Having done all this without errors, click "Build" again
and then select "Execute HelloWorld.exe". You can also click
the red exclamation mark on your tool bar as a short cut to execute your
programs. Your display should render this message:
Hello
World!
14. Congratulations! You have written your first program in C++. After
doing this, let's go over a few basic concepts of syntax and grammar.
D. Syntax and Grammar
1. #
=
This symbol triggers the preprocessor. 2. #include
= Every time it sees the # sign it modifies and inserts the source code
contained in the specified file in the <> brackets..
It is this
code that is fed to the compiler, not the actual "#include"
statement. 3. iostream.h
= a common header file provided by most compilers in the standard
library. It contains source code needed for basic
I/O (input/output)
operations. Without specifying that source code from this file be
included in the program, basic
functions like
cout
<< and
cin
>>
would not be defined or understood by the
compiler. 4. int main()
= a special function, starts automatically when program executed. Like
all functions it must state what kind of value it
will return. It will
always return int (an integer) or void. It is invoked by the
operating system to start the program. All
calls to outside source will
be contained in the main() function. 5. function - a block of code that performs one or more actions.
It is invoked or called. Functions always begin with a { and end with a
}. Opening and closing parenthesis - ( and ), are used to pass
parameters to the function from other parts of the
program. These
parameters can be hard coded values, integers, variables, array elements
or other functions. A function
must include a return type. While this
will be expanded later, in the case of "main"
function, the return type will always
either be "int"
or "void".
6. cout
= Used to output information to the display. It is contained in the
included header file "iostream.h" that we added with the
preprocessor. 7. <<
= direction of data stream. It is "<<"
for cout
when outputting data to the display. It moves the opposite direction for
user
input, becoming ">>",
when using cin. 8.
"Hello World\n";
= Whatever is placed in quotation marks is sent to the display. 9. \n
=
inserts a carriage return/end of line after displaying "Hello
World". 10. ; =
Terminates a statement, cout
<< "Hello World!\n"; is a
statement that must be terminated with a semicolon. 11.
return 0;
= ends the main() function, thus ending the program.